New Feature: gear templates allow us to save and load a merc's equipment, thereby speeding up the equipment process.

For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23462&goto=350497&#msg_350497

Requires GameDir >= r2384

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8440 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2017-08-06 21:06:49 +00:00
parent 35cdd64a92
commit f7423782db
15 changed files with 1345 additions and 108 deletions
+9 -9
View File
@@ -15,9 +15,9 @@
#ifdef JA2EDITOR
#ifdef JA2UB
CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.8440 (Development Build)" };
#else
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.8440 (Development Build)" };
#endif
// ------------------------------
@@ -27,11 +27,11 @@
//DEBUG BUILD VERSION
#ifdef JA2UB
CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.8440 (Development Build)" };
#elif defined (JA113DEMO)
CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.8440 (Development Build)" };
#else
CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Debug: v1.13.8440 (Development Build)" };
#endif
#elif defined CRIPPLED_VERSION
@@ -46,16 +46,16 @@
//RELEASE BUILD VERSION
#ifdef JA2UB
CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.8440 (Development Build)" };
#elif defined (JA113DEMO)
CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.8440 (Development Build)" };
#else
CHAR16 zVersionLabel[256] = { L"Release v1.13.8434 (Development Build)" };
CHAR16 zVersionLabel[256] = { L"Release v1.13.8440 (Development Build)" };
#endif
#endif
CHAR8 czVersionNumber[16] = { "Build 17.07.29" }; //YY.MM.DD
CHAR8 czVersionNumber[16] = { "Build 17.08.06" }; //YY.MM.DD
CHAR16 zTrackingNumber[16] = { L"Z" };
// SAVE_GAME_VERSION is defined in header, change it there
+240 -29
View File
@@ -199,7 +199,7 @@ UINT32 guiMapInvenSortButton[4];
UINT32 guiMapInvenFilterButtonImage[MAP_INVENTORY_FILTER_BUTTONS];
UINT32 guiMapInvenFilterButton[MAP_INVENTORY_FILTER_BUTTONS];
BOOLEAN guiMapInvenFilterButtonDefined[MAP_INVENTORY_FILTER_BUTTONS];
BOOLEAN gfCheckForCursorOverMapSectorInventoryItem = FALSE;
@@ -286,6 +286,11 @@ void MapInventoryPoolEjectAmmoBtn( GUI_BUTTON *btn, INT32 reason );
// HEADROCK HAM 5: Preliminary Filter Button
void MapInventoryPoolFilterBtn( GUI_BUTTON *btn, INT32 reason );
void MapInventoryPoolFilterBtnMoveItemDisplay( GUI_BUTTON *btn, INT32 reason ); // Flugente
// Flugente: gear templates
void MapInventoryWriteEquipmentTemplate(GUI_BUTTON *btn, INT32 reason);
void MapInventoryReadEquipmentTemplate(GUI_BUTTON *btn, INT32 reason);
void DisplayCurrentSector( void );
void ResizeInventoryList( void );
#ifdef INVFIX_Moa//dnl ch85 050214
@@ -821,7 +826,8 @@ void UpdateHelpTextForInvnentoryStashSlots( void )
return;
}
// Flugente:
extern void EquipmentListMenuCancel( );
// create and remove buttons for inventory
void CreateDestroyMapInventoryPoolButtons( BOOLEAN fExitFromMapScreen )
@@ -1861,6 +1867,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 0 ] ]->UserData[1] = IC_MAPFILTER_ALL;
ButtonList[ guiMapInvenFilterButton[ 0 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 0 ] ]->UserData[3] = 0;
guiMapInvenFilterButtonDefined[0] = TRUE;
guiMapInvenFilterButtonImage[ 1 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 20, 20, -1, 21, -1 );
guiMapInvenFilterButton[ 1 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 1 ], INVEN_POOL_X+214 + xResOffset, INVEN_POOL_Y + 10 + yResOffset,
@@ -1872,6 +1879,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 1 ] ]->UserData[1] = IC_MAPFILTER_GUN;
ButtonList[ guiMapInvenFilterButton[ 1 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 1 ] ]->UserData[3] = IC_MAPFILTER_GUN;
guiMapInvenFilterButtonDefined[1] = TRUE;
guiMapInvenFilterButtonImage[ 2 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 22, 22, -1, 23, -1 );
guiMapInvenFilterButton[ 2 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 2 ], INVEN_POOL_X+214 + xResOffset, INVEN_POOL_Y + 24 + yResOffset,
@@ -1883,6 +1891,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 2 ] ]->UserData[1] = IC_MAPFILTER_AMMO;
ButtonList[ guiMapInvenFilterButton[ 2 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 2 ] ]->UserData[3] = IC_MAPFILTER_AMMO;
guiMapInvenFilterButtonDefined[2] = TRUE;
guiMapInvenFilterButtonImage[ 3 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 24, 24, -1, 25, -1 );
guiMapInvenFilterButton[ 3 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 3 ], INVEN_POOL_X+243 + xResOffset, INVEN_POOL_Y + 10 + yResOffset,
@@ -1894,6 +1903,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 3 ] ]->UserData[1] = IC_MAPFILTER_EXPLOSV;
ButtonList[ guiMapInvenFilterButton[ 3 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 3 ] ]->UserData[3] = IC_MAPFILTER_EXPLOSV;
guiMapInvenFilterButtonDefined[3] = TRUE;
guiMapInvenFilterButtonImage[ 4 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 26, 26, -1, 27, -1 );
guiMapInvenFilterButton[ 4 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 4 ], INVEN_POOL_X+243 + xResOffset, INVEN_POOL_Y + 24 + yResOffset,
@@ -1905,6 +1915,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 4 ] ]->UserData[1] = IC_MAPFILTER_MELEE;
ButtonList[ guiMapInvenFilterButton[ 4 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 4 ] ]->UserData[3] = IC_MAPFILTER_MELEE;
guiMapInvenFilterButtonDefined[4] = TRUE;
guiMapInvenFilterButtonImage[ 5 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 28, 28, -1, 29, -1 );
guiMapInvenFilterButton[ 5 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 5 ], INVEN_POOL_X+272 + xResOffset, INVEN_POOL_Y + 10 + yResOffset,
@@ -1916,6 +1927,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 5 ] ]->UserData[1] = IC_MAPFILTER_ARMOR;
ButtonList[ guiMapInvenFilterButton[ 5 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 5 ] ]->UserData[3] = IC_MAPFILTER_ARMOR;
guiMapInvenFilterButtonDefined[5] = TRUE;
guiMapInvenFilterButtonImage[ 6 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 30, 30, -1, 31, -1 );
guiMapInvenFilterButton[ 6 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 6 ], INVEN_POOL_X+272 + xResOffset, INVEN_POOL_Y + 24 + yResOffset,
@@ -1927,6 +1939,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 6 ] ]->UserData[1] = IC_MAPFILTER_LBE;
ButtonList[ guiMapInvenFilterButton[ 6 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 6 ] ]->UserData[3] = IC_MAPFILTER_LBE;
guiMapInvenFilterButtonDefined[6] = TRUE;
guiMapInvenFilterButtonImage[ 7 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 32, 32, -1, 33, -1 );
guiMapInvenFilterButton[ 7 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 7 ], INVEN_POOL_X+301 + xResOffset, INVEN_POOL_Y + 10 + yResOffset,
@@ -1938,6 +1951,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 7 ] ]->UserData[1] = IC_MAPFILTER_KIT;
ButtonList[ guiMapInvenFilterButton[ 7 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 7 ] ]->UserData[3] = IC_MAPFILTER_KIT;
guiMapInvenFilterButtonDefined[7] = TRUE;
guiMapInvenFilterButtonImage[ 8 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 34, 34, -1, 35, -1 );
guiMapInvenFilterButton[ 8 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 8 ], INVEN_POOL_X+301 + xResOffset, INVEN_POOL_Y + 24 + yResOffset,
@@ -1949,6 +1963,7 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 8 ] ]->UserData[1] = IC_MAPFILTER_MISC;
ButtonList[ guiMapInvenFilterButton[ 8 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 8 ] ]->UserData[3] = IC_MAPFILTER_MISC;
guiMapInvenFilterButtonDefined[8] = TRUE;
// Flugente: toggle button for move item display
guiMapInvenFilterButtonImage[ 9 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 36, 36, -1, 37, -1 );
@@ -1963,24 +1978,33 @@ void CreateMapInventoryButtons( void )
ButtonList[ guiMapInvenFilterButton[ 9 ] ]->UserData[1] = IC_MAPFILTER_MISC;
ButtonList[ guiMapInvenFilterButton[ 9 ] ]->UserData[2] = 0;
ButtonList[ guiMapInvenFilterButton[ 9 ] ]->UserData[3] = IC_MAPFILTER_MISC;
guiMapInvenFilterButtonDefined[9] = TRUE;
/*
guiMapInvenFilterButtonImage[ 9 ]= LoadButtonImage( "INTERFACE\\sector_inventory_buttons.sti" , 19, 17, -1, 18, -1 );
guiMapInvenFilterButton[ 9 ] = QuickCreateButton( guiMapInvenFilterButtonImage[ 9 ], INVEN_POOL_X+340 + xResOffset, INVEN_POOL_Y + 10 + yResOffset,
// as no space is left, further buttons require better resolutions
if ( iResolution > _640x480 )
{
// Flugente: gear templates
guiMapInvenFilterButtonImage[10] = LoadButtonImage("INTERFACE\\sector_inventory_buttons.sti", 40, 40, -1, 40, -1);
guiMapInvenFilterButton[10] = QuickCreateButton(guiMapInvenFilterButtonImage[10], INVEN_POOL_X + 371 + xResOffset, INVEN_POOL_Y + 10 + yResOffset,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST,
NULL, (GUI_CALLBACK)MapInventoryPoolFilterBtn );
NULL, (GUI_CALLBACK)MapInventoryWriteEquipmentTemplate);
SetButtonFastHelpText( guiMapInvenFilterButton[ 9 ], pMapScreenInvenButtonHelpText[ 17 ] );
ButtonList[ guiMapInvenFilterButton[ 9 ] ]->UserData[0] = 0;
ButtonList[ guiMapInvenFilterButton[ 9 ] ]->UserData[1] = 0;
*/
SetButtonFastHelpText(guiMapInvenFilterButton[10], pMapScreenInvenButtonHelpText[18]);
guiMapInvenFilterButtonDefined[10] = TRUE;
guiMapInvenFilterButtonImage[11] = LoadButtonImage("INTERFACE\\sector_inventory_buttons.sti", 42, 42, -1, 42, -1);
guiMapInvenFilterButton[11] = QuickCreateButton(guiMapInvenFilterButtonImage[11], INVEN_POOL_X + 406 + xResOffset, INVEN_POOL_Y + 10 + yResOffset,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST,
NULL, (GUI_CALLBACK)MapInventoryReadEquipmentTemplate);
SetButtonFastHelpText(guiMapInvenFilterButton[11], pMapScreenInvenButtonHelpText[19]);
guiMapInvenFilterButtonDefined[11] = TRUE;
}
//reset the current inventory page to be the first page
iCurrentInventoryPoolPage = 0;
HandleSetFilterButtons();
return;
}
@@ -2010,11 +2034,18 @@ void DestroyMapInventoryButtons( void )
UnloadButtonImage( guiMapInvenSortButtonImage[ 3 ] );
// HEADROCK HAM 5: Filter button
for (INT32 iCounter = 0; iCounter < MAP_INVENTORY_FILTER_BUTTONS; iCounter++)
for (INT32 iCounter = 0; iCounter < MAP_INVENTORY_FILTER_BUTTONS; ++iCounter)
{
if ( guiMapInvenFilterButtonDefined[ iCounter ] )
{
RemoveButton( guiMapInvenFilterButton[ iCounter ] );
UnloadButtonImage( guiMapInvenFilterButtonImage[ iCounter ] );
guiMapInvenFilterButtonDefined[ iCounter ] = FALSE;
}
}
// Flugente: destroy gear template selection, in case that thing is still open
EquipmentListMenuCancel( );
/*
// Destroy the popup.
@@ -2023,8 +2054,6 @@ void DestroyMapInventoryButtons( void )
gfMapInventoryFilterPopupInitialized = FALSE;
gfMapInventoryFilterPopupVisible = FALSE;
*/
return;
}
////////////////////////////
@@ -2937,28 +2966,99 @@ void MapInventoryPoolFilterBtnMoveItemDisplay( GUI_BUTTON *btn, INT32 reason )
// The refresh function moves the necessary items from the Seen to the Unseen inventories, and vice versa.
RefreshSeenAndUnseenPools();
BlitInventoryPoolGraphic( );
BlitInventoryPoolGraphic();
HandleSetFilterButtons();
}
}
/*if (reason & MSYS_CALLBACK_REASON_RBUTTON_UP)
}
// Flugente: gear templates
extern void WriteEquipmentTemplate(SOLDIERTYPE* pSoldier, STR16 name);
extern void EquipmentListMenu( );
void TemplateNameInputCallBack(UINT8 ubResult)
{
if (ubResult == MSG_BOX_RETURN_OK && wcscmp(gszMsgBoxInputString, L"") > 0)
{
if (btn->uiFlags & (BUTTON_CLICKED_ON))
SOLDIERTYPE* pSoldier = &Menptr[gCharactersList[bSelectedInfoChar].usSolID];
if (pSoldier)
{
if (btn->UserData[2] == 0)
WriteEquipmentTemplate(pSoldier, gszMsgBoxInputString);
// The refresh function moves the necessary items from the Seen to the Unseen inventories, and vice versa.
RefreshSeenAndUnseenPools();
BlitInventoryPoolGraphic();
HandleSetFilterButtons();
}
}
memset(gszMsgBoxInputString, 0, sizeof(gszMsgBoxInputString));
}
void MapInventoryWriteEquipmentTemplate(GUI_BUTTON *btn, INT32 reason)
{
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ||
reason & MSYS_CALLBACK_REASON_RBUTTON_DWN )
{
MapInventoryFilterSet( btn->UserData[3] );
if ( !(btn->uiFlags & (BUTTON_CLICKED_ON)) )
{
// Set as "clicked on", but do nothing until the mouse is released.
btn->uiFlags |= (BUTTON_CLICKED_ON);
}
}
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
if ( btn->uiFlags & (BUTTON_CLICKED_ON) )
{
SOLDIERTYPE* pSoldier = &Menptr[gCharactersList[bSelectedInfoChar].usSolID];
if ( pSoldier )
{
DoMessageBox( MSG_BOX_BASIC_SMALL_BUTTONS, szGearTemplateText[0], guiCurrentScreen, MSG_BOX_FLAG_INPUTBOX, TemplateNameInputCallBack, NULL );
}
}
}
}
void MapInventoryReadEquipmentTemplate(GUI_BUTTON *btn, INT32 reason)
{
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ||
reason & MSYS_CALLBACK_REASON_RBUTTON_DWN )
{
if ( !(btn->uiFlags & (BUTTON_CLICKED_ON)) )
{
// Set as "clicked on", but do nothing until the mouse is released.
btn->uiFlags |= (BUTTON_CLICKED_ON);
}
}
if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
if ( btn->uiFlags & (BUTTON_CLICKED_ON) )
{
SOLDIERTYPE* pSoldier = &Menptr[gCharactersList[bSelectedInfoChar].usSolID];
if ( pSoldier &&
pSoldier->sSectorX == sSelMapX && pSoldier->sSectorY == sSelMapY && pSoldier->bSectorZ == iCurrentMapSectorZ &&
!pSoldier->flags.fBetweenSectors )
{
if ( (gTacticalStatus.uiFlags & INCOMBAT || gTacticalStatus.fEnemyInSector) )
{
DoScreenIndependantMessageBox( szGearTemplateText[1], MSG_BOX_FLAG_OK, NULL );
}
else
{
MapInventoryFilterToggle( btn->UserData[3] );
// open the menu
EquipmentListMenu( );
}
}
else
{
DoScreenIndependantMessageBox( szGearTemplateText[2], MSG_BOX_FLAG_OK, NULL );
}
}
// HEADROCK HAM 5: Disabled for now, as we've got buttons for this.
//CreateMapInventoryFilterMenu( );
}
}*/
}
// HEADROCK HAM 5: Zoom button.
@@ -5138,7 +5238,11 @@ void SortSectorInventorySeparateAttachments()
while ((size = pInventoryItem->object[x]->attachments.size()) != cnt)
{
OBJECTTYPE * pNewObj = new OBJECTTYPE();
gpTempObject = pInventoryItem->object[x]->GetAttachmentAtIndex(size - 1 - cnt);
// Flugente: prevent an underflow
UINT8 attindex = size > cnt ? size - 1 - cnt : 0;
gpTempObject = pInventoryItem->object[x]->GetAttachmentAtIndex( attindex );
//WarmSteel - This actually still works with NAS, be it by accident
if (gpTempObject != NULL && pInventoryItem->object.RemoveAttachment(gpTempObject, pNewObj, x))
@@ -5153,13 +5257,13 @@ void SortSectorInventorySeparateAttachments()
}
else
{
cnt++;
++cnt;
}
uiLoopCnt++;
++uiLoopCnt;
// Failsafe
if (uiLoopCnt > 100)
if (uiLoopCnt > 50)
{
break;
}
@@ -5262,6 +5366,83 @@ void SortSectorInventoryStackAndMerge(bool ammoOnly )
fMapPanelDirty = TRUE;
}
// Flugente: on a key press, we loop over each team members' inventory and exchange it with world items that have a higher status
// however, we ignore items that have inseparable attachments
// the goal is to simulate the player manually changing items, as that is rather tedious
BOOL GetBetterObject_InventoryPool(UINT16 usItem, INT16 status, UINT32& arLoop, UINT8& arIndex)
{
OBJECTTYPE* pBestObj = NULL;
INT16 beststatus = status;
BOOLEAN found = FALSE;
for (UINT32 uiLoop = 0; uiLoop < pInventoryPoolList.size(); ++uiLoop) // ... for all items in the world ...
{
if (pInventoryPoolList[uiLoop].object.exists() &&
pInventoryPoolList[uiLoop].usFlags & WORLD_ITEM_REACHABLE &&
!(pInventoryPoolList[uiLoop].usFlags & WORLD_ITEM_ARMED_BOMB) &&
pInventoryPoolList[uiLoop].bVisible == VISIBLE &&
pInventoryPoolList[uiLoop].object.usItem == usItem)
{
OBJECTTYPE* pObj = &(pInventoryPoolList[uiLoop].object);
if (pObj != NULL )
{
for (UINT8 i = 0; i < pObj->ubNumberOfObjects; ++i)
{
if ((*pObj)[i]->data.objectStatus > beststatus)
{
// ignore if there are inseparable attachments - we wouldn't be able to change those by hand
attachmentList::iterator iterend = (*pObj)[i]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter)
{
if (iter->exists() && Item[iter->usItem].inseparable)
{
continue;
}
}
beststatus = (*pObj)[i]->data.objectStatus;
arLoop = uiLoop;
arIndex = i;
found = TRUE;
}
}
}
}
}
return found;
}
// Flugente: tell us the position of the first inventory item with a fitting calibre and ammotype
BOOL GetFittingAmmo_InventoryPool( UINT8 usCalibre, UINT8 usAmmoType, UINT32& arLoop )
{
for ( UINT32 uiLoop = 0; uiLoop < pInventoryPoolList.size( ); ++uiLoop )
{
if ( pInventoryPoolList[uiLoop].object.exists( ) &&
pInventoryPoolList[uiLoop].usFlags & WORLD_ITEM_REACHABLE &&
!(pInventoryPoolList[uiLoop].usFlags & WORLD_ITEM_ARMED_BOMB) &&
pInventoryPoolList[uiLoop].bVisible == VISIBLE &&
(Item[pInventoryPoolList[uiLoop].object.usItem].usItemClass & IC_AMMO) )
{
UINT16 usMagIndex = Item[pInventoryPoolList[uiLoop].object.usItem].ubClassIndex;
if ( usCalibre == Magazine[usMagIndex].ubCalibre )
{
if ( usAmmoType == Magazine[usMagIndex].ubAmmoType )
{
arLoop = uiLoop;
return TRUE;
}
}
}
}
return FALSE;
}
// HEADROCK HAM 5: This is a helper function that puts together all seen and unseen items from the two
// sector-inventory pools, and then rebuilds the pool. By changing the flags used by the function that tests
// whether an item should appear in the "SEEN" list, we can create filters to show or hide specific items.
@@ -5767,9 +5948,14 @@ void MapInventoryFilterSet( UINT32 uiFlags )
void HandleSetFilterButtons()
{
// Show/Hide All button always off.
if ( guiMapInvenFilterButtonDefined[0] )
{
ButtonList[guiMapInvenFilterButton[ 0 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
// Guns
if ( guiMapInvenFilterButtonDefined[1] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_GUN)
{
ButtonList[guiMapInvenFilterButton[ 1 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5778,8 +5964,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 1 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// Ammo
if ( guiMapInvenFilterButtonDefined[2] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_AMMO)
{
ButtonList[guiMapInvenFilterButton[ 2 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5788,8 +5977,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 2 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// Explosives
if ( guiMapInvenFilterButtonDefined[3] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_EXPLOSV)
{
ButtonList[guiMapInvenFilterButton[ 3 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5798,8 +5990,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 3 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// Melee Weapons
if ( guiMapInvenFilterButtonDefined[4] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_MELEE)
{
ButtonList[guiMapInvenFilterButton[ 4 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5808,8 +6003,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 4 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// Armor
if ( guiMapInvenFilterButtonDefined[5] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_ARMOR)
{
ButtonList[guiMapInvenFilterButton[ 5 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5818,8 +6016,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 5 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// LBEs
if ( guiMapInvenFilterButtonDefined[6] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_LBE)
{
ButtonList[guiMapInvenFilterButton[ 6 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5828,8 +6029,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 6 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// Kits
if ( guiMapInvenFilterButtonDefined[7] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_KIT)
{
ButtonList[guiMapInvenFilterButton[ 7 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5838,8 +6042,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 7 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// Misc. Items
if ( guiMapInvenFilterButtonDefined[8] )
{
if (guiMapInventoryFilter & IC_MAPFILTER_MISC)
{
ButtonList[guiMapInvenFilterButton[ 8 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5848,8 +6055,11 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 8 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
// Flugente: move item display
if ( guiMapInvenFilterButtonDefined[9] )
{
if ( IsShowMoveItem() )
{
ButtonList[guiMapInvenFilterButton[ 9 ]]->uiFlags |= (BUTTON_CLICKED_ON);
@@ -5858,6 +6068,7 @@ void HandleSetFilterButtons()
{
ButtonList[guiMapInvenFilterButton[ 9 ]]->uiFlags &=~ (BUTTON_CLICKED_ON);
}
}
}
//Moa:moved code to CreateDestroyMapInventoryPoolButtons() and EnterSector() to decrease loading time
@@ -8,7 +8,7 @@
#define MAX_DISTANCE_TO_PICKUP_ITEM 5
// Flugente: number of map inventory filter buttons
#define MAP_INVENTORY_FILTER_BUTTONS 10 // Flugente: 9 -> 10
#define MAP_INVENTORY_FILTER_BUTTONS 12 // Flugente: 9 -> 12
// number of inventory slots
//#define MAP_INVENTORY_POOL_SLOT_COUNT 84 //45 //45
+781
View File
@@ -78,6 +78,9 @@
#include "Game Clock.h" // added by Flugente
#include <vfs/Core/vfs_file_raii.h> // added by Flugente for vfs-stuff
#include "DynamicDialogue.h" // added by Flugente for SoldierRelation()
#include "MessageBoxScreen.h" // added by Flugente
#include "Map Screen Interface.h" // added by Flugente
#include "Map Screen Interface Map.h" // added by Flugente
#endif
#ifdef JA2UB
@@ -92,6 +95,18 @@
// directory for fortification plans (located in Profiles sub-folder)
#define FORTIFICATIONPLAN_DIRECTORY "FortificationPlan\\"
#define EQUIPMENTTEMPLATE_DIRECTORY "GearTemplate\\"
extern BOOL GetBetterObject_InventoryPool( UINT16 usItem, INT16 status, UINT32& arLoop, UINT8& arIndex );
extern BOOL GetFittingAmmo_InventoryPool( UINT8 usCalibre, UINT8 usAmmoType, UINT32& arLoop );
extern BOOLEAN HandleNailsVestFetish( SOLDIERTYPE *pSoldier, UINT32 uiHandPos, UINT16 usReplaceItem );
extern std::vector<WORLDITEM> pInventoryPoolList;
extern INT32 GetAttachmentInfoIndex( UINT16 usItem );
extern INT32 giItemDescAmmoButton;
ITEM_POOL_LOCATOR FlashItemSlots[ NUM_ITEM_FLASH_SLOTS ];
UINT32 guiNumFlashItemSlots = 0;
// sevenfm: remember network settings for last planted tripwire
@@ -8970,3 +8985,769 @@ BOOLEAN SpendMoney( SOLDIERTYPE *pSoldier, UINT32 aAmount )
return (aAmount == 0);
}
// Flugente: gear templates
extern std::vector<std::string> gTemplateVector;
// this class is used to store our gear templates
class GEAR_NODE
{
public:
GEAR_NODE(INT8 a, UINT16 b, UINT16 c) :
slot( a ), item( b ), ammoitem(c){}
GEAR_NODE() :
slot( NOWHERE ), item( 0 ), ammoitem(0) {}
void swap(GEAR_NODE& other)
{
std::swap( slot, other.slot );
std::swap( item, other.item );
std::swap( ammoitem, other.ammoitem );
std::vector<UINT16> tmp = other.attachments;
other.attachments = attachments;
attachments = tmp;
}
INT8 slot;
UINT16 item;
UINT16 ammoitem;
std::vector<UINT16> attachments;
};
std::ostream& operator<<(std::ostream& stream, GEAR_NODE const& data)
{
stream << (int)(data.slot) << " " << (UINT16)(data.item) << " " << (UINT16)(data.ammoitem);
std::vector<UINT16> tmp = data.attachments;
for ( std::vector<UINT16>::iterator it = tmp.begin( ); it != tmp.end( ); ++it )
stream << " " << (*it);
stream << std::endl;
return stream;
}
std::vector<GEAR_NODE> LoadEquipmentTemplate( std::string aName )
{
CHAR8 filename[MAX_PATH];
sprintf(filename, "%s%s", EQUIPMENTTEMPLATE_DIRECTORY, aName.c_str());
// get full path to save file
vfs::Path vfsPath;
vfs::COpenWriteFile rfile( filename, true );
rfile->_getRealPath(vfsPath);
std::string str = vfsPath.to_string();
const char* filenamewithpath = str.c_str();
// Read data
std::ifstream file;
file.open(filenamewithpath, std::ios::in);
std::vector<GEAR_NODE> vec;
std::string line;
while ( std::getline( file >> std::ws, line ) )
{
if ( line[0] != '#' && line[0] != '/' )
{
std::istringstream iss( line );
GEAR_NODE node;
int num;
if ( iss >> num && iss >> (UINT16)node.item )
{
node.slot = num;
// additional data is optional
if ( iss >> (UINT16)node.ammoitem )
{
while ( iss >> num )
{
node.attachments.push_back( num );
}
}
vec.push_back(node);
}
}
}
file.close();
return vec;
}
void SaveEquipmentTemplate(std::vector<GEAR_NODE> aVec, STR16 aName)
{
CHAR8 filename[MAX_PATH];
sprintf(filename, "%s%S.txt", EQUIPMENTTEMPLATE_DIRECTORY, aName);
// get full path to save file
// what we are doing here might seem rather odd. If the file does not exist, we are creating a new file via vfs... and then create a fresh binary file afterwards.
// I found this to be the easiest solution for using both vfs pathing and being able to use a std::fstream
// If you don't like it, fix it yourself, or make vfs not such a pain to use
vfs::Path vfsPath;
vfs::COpenWriteFile rfile(filename, true);
rfile->_getRealPath(vfsPath);
std::string str = vfsPath.to_string();
const char* filenamewithpath = str.c_str();
// write
std::fstream binary_file(filenamewithpath, std::ios::out);
for (std::vector<GEAR_NODE>::iterator it = aVec.begin(); it != aVec.end(); ++it)
{
GEAR_NODE node = (*it);
binary_file << node;
}
binary_file.close();
}
void WriteEquipmentTemplate(SOLDIERTYPE* pSoldier, STR16 name)
{
if (pSoldier)
{
std::vector<GEAR_NODE> vec;
INT8 invsize = (INT8)pSoldier->inv.size(); // remember inventorysize, so we don't call size() repeatedly
for (INT8 bLoop = 0; bLoop < invsize; ++bLoop) // ... for all items in our inventory ...
{
if (pSoldier->inv[bLoop].exists())
{
// if this item is a gun, note what magazine is currently loaded
UINT16 ammoitem = 0;
if ( Item[(pSoldier->inv[bLoop]).usItem].usItemClass & IC_GUN )
ammoitem = (pSoldier->inv[bLoop])[0]->data.gun.usGunAmmoItem;
GEAR_NODE node( bLoop, (pSoldier->inv[bLoop]).usItem, ammoitem );
// add all attachments
attachmentList::iterator iterend = (pSoldier->inv[bLoop])[0]->attachments.end( );
for ( attachmentList::iterator iter = (pSoldier->inv[bLoop])[0]->attachments.begin( ); iter != iterend; ++iter )
{
if ( iter->exists( ) )
node.attachments.push_back( iter->usItem );
}
vec.push_back(node);
}
}
SaveEquipmentTemplate(vec, name);
}
}
std::vector<std::string> get_all_files_names_within_folder(std::string folder)
{
std::vector<std::string> names;
std::string search_path = folder + "/*.*";
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
names.push_back(fd.cFileName);
}
}
while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
// get a vector of all tilesets that are allowed to be built in this sector (the above filtered by structure construct/deconstruct basically)
void GetEquipmentTemplates()
{
CHAR8 filename[MAX_PATH];
sprintf(filename, "%sUpdate Gear.txt", EQUIPMENTTEMPLATE_DIRECTORY);
// get full path to save file
// what we are doing here might seem rather odd. If the file does not exist, we are creating a new empty file via vfs
// in this case, this is rather useful, as the above file simply updates our gear, which is already neat
// I found this to be the easiest solution for using both vfs pathing and being able to use a std::fstream
// If you don't like it, fix it yourself, or make vfs not such a pain to use
vfs::Path vfsPath;
vfs::COpenWriteFile rfile( filename, true );
rfile->_getRealPath(vfsPath);
vfs::Path dir, file;
vfsPath.splitLast(dir, file);
std::string str = dir.to_string();
const char* filenamewithpath = str.c_str();
gTemplateVector = get_all_files_names_within_folder( filenamewithpath );
}
void ReadEquipmentTable( SOLDIERTYPE* pSoldier, std::string name )
{
// make sure the merc is actually in this sector
if ( pSoldier )
{
UINT16 color = FONT_MCOLOR_WHITE;
// for safety, test again
if ( pSoldier->sSectorX != sSelMapX ||
pSoldier->sSectorY != sSelMapY ||
pSoldier->bSectorZ != iCurrentMapSectorZ )
{
ScreenMsg( color, MSG_INTERFACE, szGearTemplateText[3], pSoldier->GetName( ) );
return;
}
if ( (gTacticalStatus.uiFlags & INCOMBAT || gTacticalStatus.fEnemyInSector) )
{
ScreenMsg( color, MSG_INTERFACE, szGearTemplateText[1] );
return;
}
std::vector<GEAR_NODE> vec = LoadEquipmentTemplate(name);
UINT16 usReloadSound = 0;
BOOLEAN attachmentsound = FALSE;
// 1. loop over the gear we should pick up and remove mismatching items if we can find a fitting one in the sector
for (std::vector<GEAR_NODE>::iterator it = vec.begin(); it != vec.end(); ++it)
{
GEAR_NODE node = (*it);
if ( node.slot >= 0 && node.slot < NUM_INV_SLOTS && node.item != NOTHING )
{
// is there already an item here?
if (pSoldier->inv[node.slot].exists())
{
if ( (pSoldier->inv[node.slot]).usItem != node.item )
{
// can we get the requested item in the first place?
UINT32 poolslot = 0;
UINT8 index = 0;
if ( GetBetterObject_InventoryPool( node.item, 0, poolslot, index ) )
{
// We have to check whether we have any LBE equipped that isn't in the template
// in that case we have to dump it and it's contents, otherwise it can block slots that are used in the template
if ( node.slot >= VESTPOCKPOS && node.slot <= BPACKPOCKPOS )
{
std::vector<INT8> pocketKey;
GetLBESlots( node.slot, pocketKey );
// remove everything inside LBE
for ( std::vector<INT8>::iterator lbeslotit = pocketKey.begin( ); lbeslotit != pocketKey.end( ); ++lbeslotit )
{
if ( pSoldier->inv[(*lbeslotit)].exists( ) )
{
AutoPlaceObjectInInventoryStash( &pSoldier->inv[(*lbeslotit)], pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &pSoldier->inv[(*lbeslotit)] );
}
}
}
// if we want to equip a two-handed item in our first hand, also drop whatever we have in the second hand
else if ( node.slot == HANDPOS && Item[node.item].twohanded && pSoldier->inv[SECONDHANDPOS].exists( ) )
{
AutoPlaceObjectInInventoryStash( &pSoldier->inv[SECONDHANDPOS], pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &pSoldier->inv[SECONDHANDPOS] );
}
// if we are Nails and are ordered to drop our vest, refuse and complain!
else if ( node.slot == VESTPOS && HandleNailsVestFetish( pSoldier, node.slot, NOTHING ) )
continue;
// drop item
AutoPlaceObjectInInventoryStash( &pSoldier->inv[node.slot], pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &pSoldier->inv[node.slot] );
}
}
}
}
}
// 2. loop over the gear again and pick up what fits
for ( std::vector<GEAR_NODE>::iterator it = vec.begin( ); it != vec.end( ); ++it )
{
GEAR_NODE node = (*it);
if ( node.slot >= 0 && node.slot < NUM_INV_SLOTS )
{
// only if slot is still empty...
if ( !pSoldier->inv[node.slot].exists( ) && node.item != NOTHING )
{
// see if we can find a better object in this sector and put it into our slot
UINT32 poolslot = 0;
UINT8 index = 0;
if ( GetBetterObject_InventoryPool( node.item, 0, poolslot, index ) )
{
(pInventoryPoolList[poolslot].object).RemoveObjectAtIndex( index, &gItemPointer );
if ( !PlaceObject( pSoldier, node.slot, &gItemPointer ) )
{
ScreenMsg( color, MSG_INTERFACE, szGearTemplateText[4], pSoldier->GetName( ), Item[node.item].szItemName );
AutoPlaceObjectInInventoryStash( &gItemPointer, pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &gItemPointer );
}
}
else
{
// if this is ammo, we might still be able to create a mag from different-sized mags
if ( Item[node.item].usItemClass & IC_AMMO )
{
UINT16 usMagIndex = Item[node.item].ubClassIndex;
UINT16 neededammo = Magazine[usMagIndex].ubMagSize;
if ( neededammo > 0 )
{
UINT32 poolslot = 0;
if ( GetFittingAmmo_InventoryPool( Magazine[usMagIndex].ubCalibre, Magazine[usMagIndex].ubAmmoType, poolslot ) )
{
UINT32 takeammo = min( neededammo, pInventoryPoolList[poolslot].object[pInventoryPoolList[poolslot].object.ubNumberOfObjects - 1]->data.ubShotsLeft );
pInventoryPoolList[poolslot].object[pInventoryPoolList[poolslot].object.ubNumberOfObjects - 1]->data.ubShotsLeft -= takeammo;
if ( !pInventoryPoolList[poolslot].object[pInventoryPoolList[poolslot].object.ubNumberOfObjects - 1]->data.ubShotsLeft )
{
pInventoryPoolList[poolslot].object.RemoveObjectAtIndex( pInventoryPoolList[poolslot].object.ubNumberOfObjects - 1 );
}
CreateAmmo( node.item, &gItemPointer, takeammo );
if ( !PlaceObject( pSoldier, node.slot, &gItemPointer ) )
{
ScreenMsg( color, MSG_INTERFACE, szGearTemplateText[4], pSoldier->GetName( ), Item[node.item].szItemName );
AutoPlaceObjectInInventoryStash( &gItemPointer, pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &gItemPointer );
}
}
}
}
//if ( !pSoldier->inv[node.slot].exists( ) )
//ScreenMsg( color, MSG_INTERFACE, L"%s found no %s to equip.", pSoldier->GetName( ), Item[node.item].szItemName );
}
}
// if this slot is a LBE slot, we need to add attachments here. Otherwise we add the attachments after we fail to pick up other items as their LBE slots won't exist
if ( pSoldier->inv[node.slot].exists() && node.slot >= VESTPOCKPOS && node.slot <= BPACKPOCKPOS )
{
// try to add attachments if nod entry fits the item, or if the node item is NOTHING (essentially a wildcard for this)
if ( !node.attachments.empty( ) && (pSoldier->inv[node.slot]).usItem == node.item || NOTHING == node.item )
{
OBJECTTYPE* pObj = &(pSoldier->inv[node.slot]);
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
{
for ( std::vector<UINT16>::iterator attit = node.attachments.begin( ); attit != node.attachments.end( ); ++attit )
{
UINT16 item_attachment = (*attit);
// only apply attachments if they don't require any checks!
INT32 bAttachInfoIndex = GetAttachmentInfoIndex( item_attachment );
if ( bAttachInfoIndex < 0 || AttachmentInfo[bAttachInfoIndex].bAttachmentSkillCheck == NO_CHECK )
{
UINT32 poolslot = 0;
UINT8 index = 0;
if ( GetBetterObject_InventoryPool( item_attachment, 0, poolslot, index ) )
{
(pInventoryPoolList[poolslot].object).RemoveObjectAtIndex( index, &gItemPointer );
BOOLEAN isAttachedNow = pObj->AttachObject( pSoldier, &gItemPointer, FALSE, i ); //do the actual attaching
if ( !isAttachedNow )
{
attachmentsound = TRUE;
//ScreenMsg( color, MSG_INTERFACE, L"%s could not attach %s to %s", pSoldier->GetName( ), Item[item_attachment].szItemName, Item[pObj->usItem].szItemName );
AutoPlaceObjectInInventoryStash( &gItemPointer, pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &gItemPointer );
}
}
}
}
}
}
}
}
}
// 3. loop over all slots (not just those of the gear vector), improve, merge and fill stacks
for ( int slot = HELMETPOS; slot < NUM_INV_SLOTS; ++slot )
{
if (pSoldier->inv[slot].exists())
{
OBJECTTYPE* pObj = &(pSoldier->inv[slot]);
if ( Item[pObj->usItem].usItemClass & (IC_KIT | IC_MEDKIT) && pObj->ubNumberOfObjects > 1 )
{
CleanUpStack( pObj, pObj );
}
// if this is ammo, try merging mags first before replacing them, the not-full mag being the visible one
// by doing this we won't have so many used magazines lying around
if ( (Item[pObj->usItem].usItemClass & IC_AMMO) && pObj->ubNumberOfObjects > 1 )
{
UINT16 usMagIndex = Item[pObj->usItem].ubClassIndex;
UINT16 magsize = Magazine[usMagIndex].ubMagSize;
if ( magsize )
{
UINT32 ammocount = 0;
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
ammocount += (*pObj)[i]->data.ubShotsLeft;
UINT8 fullmags = ammocount / magsize;
UINT16 leftover = ammocount - fullmags * magsize;
UINT8 totalmags = fullmags + (leftover > 0 ? 1 : 0);
if ( totalmags < pObj->ubNumberOfObjects )
pObj->RemoveObjectsFromStack( pObj->ubNumberOfObjects - totalmags );
for ( INT16 i = 0; i < totalmags; ++i )
(*pObj)[i]->data.ubShotsLeft = magsize;
if ( leftover > 0 )
(*pObj)[0]->data.ubShotsLeft = leftover;
}
}
// for every object in the stack, try to find a better improvement
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
{
// see if we can find a better object in this sector and put it into our slot
UINT32 poolslot = 0;
UINT8 index = 0;
if ( (*pObj)[i]->data.objectStatus < 100 && GetBetterObject_InventoryPool( pObj->usItem, (*pObj)[i]->data.objectStatus, poolslot, index ) )
{
// WARNING! The correct way of doing this would be to exchange both objects
// we are not doing this here on purpose, as we want to save time
// instead, we switch status and a few other properties
// Only do this if you know what you are doing - in the wrong location, we could do odd things to global pointers. Consider yourself warned!
// tmp data
INT16 objectStatus = (*pObj)[i]->data.objectStatus;
INT8 bTrap = (*pObj)[i]->data.bTrap;
UINT8 fUsed = (*pObj)[i]->data.fUsed;
UINT8 ubImprintID = (*pObj)[i]->data.ubImprintID;
FLOAT bTemperature = (*pObj)[i]->data.bTemperature;
UINT8 ubDirection = (*pObj)[i]->data.ubDirection;
UINT32 ubWireNetworkFlag = (*pObj)[i]->data.ubWireNetworkFlag;
INT8 bDefuseFrequency = (*pObj)[i]->data.bDefuseFrequency;
INT16 sRepairThreshold = (*pObj)[i]->data.sRepairThreshold;
UINT64 sObjectFlag = (*pObj)[i]->data.sObjectFlag;
// set data on our object
(*pObj)[i]->data.objectStatus = (pInventoryPoolList[poolslot].object)[index]->data.objectStatus;
(*pObj)[i]->data.bTrap = (pInventoryPoolList[poolslot].object)[index]->data.bTrap;
(*pObj)[i]->data.fUsed = (pInventoryPoolList[poolslot].object)[index]->data.fUsed;
(*pObj)[i]->data.ubImprintID = (pInventoryPoolList[poolslot].object)[index]->data.ubImprintID;
(*pObj)[i]->data.bTemperature = (pInventoryPoolList[poolslot].object)[index]->data.bTemperature;
(*pObj)[i]->data.ubDirection = (pInventoryPoolList[poolslot].object)[index]->data.ubDirection;
(*pObj)[i]->data.ubWireNetworkFlag = (pInventoryPoolList[poolslot].object)[index]->data.ubWireNetworkFlag;
(*pObj)[i]->data.bDefuseFrequency = (pInventoryPoolList[poolslot].object)[index]->data.bDefuseFrequency;
(*pObj)[i]->data.sRepairThreshold = (pInventoryPoolList[poolslot].object)[index]->data.sRepairThreshold;
(*pObj)[i]->data.sObjectFlag = (pInventoryPoolList[poolslot].object)[index]->data.sObjectFlag;
// set data on world object
(pInventoryPoolList[poolslot].object)[index]->data.objectStatus = objectStatus;
(pInventoryPoolList[poolslot].object)[index]->data.bTrap = bTrap;
(pInventoryPoolList[poolslot].object)[index]->data.fUsed = fUsed;
(pInventoryPoolList[poolslot].object)[index]->data.ubImprintID = ubImprintID;
(pInventoryPoolList[poolslot].object)[index]->data.bTemperature = bTemperature;
(pInventoryPoolList[poolslot].object)[index]->data.ubDirection = ubDirection;
(pInventoryPoolList[poolslot].object)[index]->data.ubWireNetworkFlag = ubWireNetworkFlag;
(pInventoryPoolList[poolslot].object)[index]->data.bDefuseFrequency = bDefuseFrequency;
(pInventoryPoolList[poolslot].object)[index]->data.sRepairThreshold = sRepairThreshold;
(pInventoryPoolList[poolslot].object)[index]->data.sObjectFlag = sObjectFlag;
}
}
// pick up new items from the sector and put them on the stack
UINT8 ubSlotLimit = ItemSlotLimit(pObj, slot, pSoldier, FALSE);
while (pObj->ubNumberOfObjects < ubSlotLimit)
{
UINT32 poolslot = 0;
UINT8 index = 0;
if ( GetBetterObject_InventoryPool( pObj->usItem, 0, poolslot, index ) )
{
(pInventoryPoolList[poolslot].object).RemoveObjectAtIndex( index, &gItemPointer );
if ( !TryToStackInSlot( pSoldier, &gItemPointer, slot ) )
break;
}
else
{
break;
}
}
// try to improve attachments, too
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
{
for ( attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != (*pObj)[i]->attachments.end(); ++iter )
{
if ( iter->exists() )
{
// see if we can find a better object in this sector and put it into our slot
UINT32 poolslot = 0;
UINT8 index = 0;
if ( (*iter)[0]->data.objectStatus < 100 && GetBetterObject_InventoryPool( iter->usItem, (*iter)[0]->data.objectStatus, poolslot, index ) )
{
// WARNING! The correct way of doing this would be to exchange both objects
// we are not doing this here on purpose, as we want to save time
// instead, we switch status and a few other properties
// Only do this if you know what you are doing - in the wrong location, we could do odd things to global pointers. Consider yourself warned!
// tmp data
INT16 objectStatus = (*iter)[0]->data.objectStatus;
INT8 bTrap = (*iter)[0]->data.bTrap;
UINT8 fUsed = (*iter)[0]->data.fUsed;
UINT8 ubImprintID = (*iter)[0]->data.ubImprintID;
FLOAT bTemperature = (*iter)[0]->data.bTemperature;
UINT8 ubDirection = (*iter)[0]->data.ubDirection;
UINT32 ubWireNetworkFlag = (*iter)[0]->data.ubWireNetworkFlag;
INT8 bDefuseFrequency = (*iter)[0]->data.bDefuseFrequency;
INT16 sRepairThreshold = (*iter)[0]->data.sRepairThreshold;
UINT64 sObjectFlag = (*iter)[0]->data.sObjectFlag;
// set data on our object
(*iter)[0]->data.objectStatus = (pInventoryPoolList[poolslot].object)[index]->data.objectStatus;
(*iter)[0]->data.bTrap = (pInventoryPoolList[poolslot].object)[index]->data.bTrap;
(*iter)[0]->data.fUsed = (pInventoryPoolList[poolslot].object)[index]->data.fUsed;
(*iter)[0]->data.ubImprintID = (pInventoryPoolList[poolslot].object)[index]->data.ubImprintID;
(*iter)[0]->data.bTemperature = (pInventoryPoolList[poolslot].object)[index]->data.bTemperature;
(*iter)[0]->data.ubDirection = (pInventoryPoolList[poolslot].object)[index]->data.ubDirection;
(*iter)[0]->data.ubWireNetworkFlag = (pInventoryPoolList[poolslot].object)[index]->data.ubWireNetworkFlag;
(*iter)[0]->data.bDefuseFrequency = (pInventoryPoolList[poolslot].object)[index]->data.bDefuseFrequency;
(*iter)[0]->data.sRepairThreshold = (pInventoryPoolList[poolslot].object)[index]->data.sRepairThreshold;
(*iter)[0]->data.sObjectFlag = (pInventoryPoolList[poolslot].object)[index]->data.sObjectFlag;
// set data on world object
(pInventoryPoolList[poolslot].object)[index]->data.objectStatus = objectStatus;
(pInventoryPoolList[poolslot].object)[index]->data.bTrap = bTrap;
(pInventoryPoolList[poolslot].object)[index]->data.fUsed = fUsed;
(pInventoryPoolList[poolslot].object)[index]->data.ubImprintID = ubImprintID;
(pInventoryPoolList[poolslot].object)[index]->data.bTemperature = bTemperature;
(pInventoryPoolList[poolslot].object)[index]->data.ubDirection = ubDirection;
(pInventoryPoolList[poolslot].object)[index]->data.ubWireNetworkFlag = ubWireNetworkFlag;
(pInventoryPoolList[poolslot].object)[index]->data.bDefuseFrequency = bDefuseFrequency;
(pInventoryPoolList[poolslot].object)[index]->data.sRepairThreshold = sRepairThreshold;
(pInventoryPoolList[poolslot].object)[index]->data.sObjectFlag = sObjectFlag;
}
}
}
}
}
}
// 4. add attachments. If an attachment cannot be attached - for example because a different one is blocking it - tell us so
for ( std::vector<GEAR_NODE>::iterator it = vec.begin( ); it != vec.end( ); ++it )
{
GEAR_NODE node = (*it);
// try to add attachments if nod entry fits the item, or if the node item is NOTHING (essentially a wildcard for this)
if ( node.slot >= 0 && node.slot < NUM_INV_SLOTS &&
(node.slot < VESTPOCKPOS || node.slot > BPACKPOCKPOS) && // we already did that for LBE slots though, no need to repeat
!node.attachments.empty( ) && pSoldier->inv[node.slot].exists( ) &&
((pSoldier->inv[node.slot]).usItem == node.item || NOTHING == node.item) )
{
OBJECTTYPE* pObj = &(pSoldier->inv[node.slot]);
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
{
for ( std::vector<UINT16>::iterator attit = node.attachments.begin( ); attit != node.attachments.end( ); ++attit )
{
UINT16 item_attachment = (*attit);
// only apply attachments if they don't require any checks!
INT32 bAttachInfoIndex = GetAttachmentInfoIndex( item_attachment );
if ( bAttachInfoIndex < 0 || AttachmentInfo[bAttachInfoIndex].bAttachmentSkillCheck == NO_CHECK )
{
UINT32 poolslot = 0;
UINT8 index = 0;
if ( GetBetterObject_InventoryPool( item_attachment, 0, poolslot, index ) )
{
(pInventoryPoolList[poolslot].object).RemoveObjectAtIndex( index, &gItemPointer );
BOOLEAN isAttachedNow = pObj->AttachObject( pSoldier, &gItemPointer, FALSE, i ); //do the actual attaching
if ( !isAttachedNow )
{
attachmentsound = TRUE;
//ScreenMsg( color, MSG_INTERFACE, L"%s could not attach %s to %s", pSoldier->GetName( ), Item[item_attachment].szItemName, Item[pObj->usItem].szItemName );
AutoPlaceObjectInInventoryStash( &gItemPointer, pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &gItemPointer );
}
}
}
}
}
}
}
// 5. reload guns, fill mags
for ( int slot = HELMETPOS; slot < NUM_INV_SLOTS; ++slot )
{
if ( pSoldier->inv[slot].exists( ) )
{
if ( Item[(pSoldier->inv[slot]).usItem].usItemClass & (IC_KIT | IC_MEDKIT) )
{
UINT32 poolslot = 0;
UINT8 index = 0;
if ( GetBetterObject_InventoryPool( (pSoldier->inv[slot]).usItem, 0, poolslot, index ) )
{
DistributeStatus( &(pInventoryPoolList[poolslot].object), &(pSoldier->inv[slot]), 100);
}
}
if ( (Item[(pSoldier->inv[slot]).usItem].usItemClass & (IC_GUN | IC_AMMO)))
{
OBJECTTYPE* pObj = &(pSoldier->inv[slot]);
for ( INT16 i = 0; i < pObj->ubNumberOfObjects; ++i )
{
UINT16 ammoitem = (pSoldier->inv[slot]).usItem;
if ( (Item[(pSoldier->inv[slot]).usItem].usItemClass & IC_GUN) )
{
UINT8 calibre = Weapon[pObj->usItem].ubCalibre;
UINT16 magsize = GetMagSize( pObj, i );
ammoitem = (*pObj)[i]->data.gun.usGunAmmoItem;
for ( std::vector<GEAR_NODE>::iterator it = vec.begin( ); it != vec.end( ); ++it )
{
if ( (*it).slot == slot && (*it).item == pObj->usItem )
{
ammoitem = (*it).ammoitem;
break;
}
}
// if we somehow don't have a valid ammoitem (for example, if the gun was empty), find one
if ( !ammoitem )
ammoitem = DefaultMagazine( pObj->usItem );
UINT16 usMagIndex = Item[ammoitem].ubClassIndex;
// safety check: if the calibre or mag size doesn't fit, get a better mag
if ( calibre != Magazine[usMagIndex].ubCalibre || magsize != Magazine[usMagIndex].ubMagSize )
{
ammoitem = FindReplacementMagazine( calibre, magsize, Magazine[usMagIndex].ubAmmoType );
usMagIndex = Item[ammoitem].ubClassIndex;
}
// if the requested ammo isn't the only currently loaded, take that one out
if ( (*pObj)[i]->data.gun.usGunAmmoItem != ammoitem && (*pObj)[i]->data.gun.usGunAmmoItem != NOTHING && ammoitem != NOTHING )
{
CreateAmmo( (*pObj)[i]->data.gun.usGunAmmoItem, &gItemPointer, (*pObj)[i]->data.gun.ubGunShotsLeft );
AutoPlaceObjectInInventoryStash( &gItemPointer, pSoldier->sGridNo, pSoldier->pathing.bLevel );
DeleteObj( &gItemPointer );
(*pObj)[i]->data.gun.usGunAmmoItem = NOTHING;
(*pObj)[i]->data.gun.ubGunShotsLeft = 0;
(*pObj)[i]->data.gun.ubGunAmmoType = 0;
}
}
UINT16 usMagIndex = Item[ammoitem].ubClassIndex;
UINT16 neededammo = Magazine[usMagIndex].ubMagSize - (*pObj)[i]->data.ubShotsLeft;
if ( (Item[(pSoldier->inv[slot]).usItem].usItemClass & IC_GUN) )
neededammo = Magazine[usMagIndex].ubMagSize - (*pObj)[i]->data.gun.ubGunShotsLeft;
while ( neededammo > 0 )
{
UINT32 poolslot = 0;
if ( GetFittingAmmo_InventoryPool( Magazine[usMagIndex].ubCalibre, Magazine[usMagIndex].ubAmmoType, poolslot ) )
{
for ( INT16 j = pInventoryPoolList[poolslot].object.ubNumberOfObjects - 1; j >= 0; --j )
{
UINT32 takeammo = min( neededammo, pInventoryPoolList[poolslot].object[j]->data.ubShotsLeft );
neededammo -= takeammo;
pInventoryPoolList[poolslot].object[j]->data.ubShotsLeft -= takeammo;
if ( (Item[(pSoldier->inv[slot]).usItem].usItemClass & IC_GUN) )
{
(*pObj)[i]->data.gun.usGunAmmoItem = ammoitem;
(*pObj)[i]->data.gun.ubGunAmmoType = Magazine[usMagIndex].ubAmmoType;
(*pObj)[i]->data.gun.ubGunShotsLeft += takeammo;
usReloadSound = Weapon[pObj->usItem].sReloadSound;
}
else
{
(*pObj)[i]->data.ubShotsLeft += takeammo;
}
if ( !pInventoryPoolList[poolslot].object[j]->data.ubShotsLeft )
{
pInventoryPoolList[poolslot].object.RemoveObjectAtIndex( j );
}
if ( !neededammo )
break;
}
}
else
{
break;
}
if ( (Item[(pSoldier->inv[slot]).usItem].usItemClass & IC_GUN) )
neededammo = Magazine[usMagIndex].ubMagSize - (*pObj)[i]->data.gun.ubGunShotsLeft;
else
neededammo = Magazine[usMagIndex].ubMagSize - (*pObj)[i]->data.ubShotsLeft;
}
}
}
}
}
// Immersion, let's play a reload sound
if ( usReloadSound != 0 )
PlayJA2Sample( usReloadSound, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
else if ( attachmentsound )
PlayJA2Sample( ATTACH_TO_GUN, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
// 6. redraw inventory
fTeamPanelDirty = TRUE;
fMapPanelDirty = TRUE;
fInterfacePanelDirty = DIRTYLEVEL2;
fCharacterInfoPanelDirty = TRUE;
// refresh ammo button in description box if it exists
if ( giItemDescAmmoButton > -1 )
MarkAButtonDirty( giItemDescAmmoButton ); // Required for tactical screen
}
}
+147
View File
@@ -12,6 +12,15 @@
#include "worldman.h"
#include "Queen Command.h"
#include "strategicmap.h"
#include "Map Screen Interface.h"
extern void GetEquipmentTemplates( );
std::vector<std::string> gTemplateVector;
extern void ReadEquipmentTable( SOLDIERTYPE* pSoldier, std::string name );
extern INT8 bSelectedInfoChar;
// sevenfm: need this for correct calculation of traits menu position
extern INT16 gsInterfaceLevel;
@@ -740,3 +749,141 @@ void TraitsMenu( INT32 usMapPos )
gTraitSelection.Setup(0);
}
/////////////////////////////// Trait Selection ////////////////////////////////////////////
EquipmentSelection gEquipmentSelection;
void Wrapper_Function_EquipmentSelection(UINT32 aVal) { gEquipmentSelection.Functions(aVal); }
void Wrapper_Setup_EquipmentSelection(UINT32 aVal) { gEquipmentSelection.Setup(aVal); }
void Wrapper_Cancel_EquipmentSelection(UINT32 aVal) { gEquipmentSelection.Cancel(); }
/////////////////////////////// Trait Selection ////////////////////////////////////////////
/////////////////////////////// Trait Selection ////////////////////////////////////////////
UINT32 gEquipmentSelectionFirstEntryShown = 0;
UINT32 gEquipmentSelectionLastEntryShown = 0;
UINT32 gEquipmentSelectionMaxEntriesShown = 0;
void
EquipmentSelection::Setup(UINT32 aVal)
{
Destroy();
SetupPopup("EquipmentSelection");
INT16 sX = 261 + 406 + xResOffset + 30;
INT16 sY = 0 + 10 + yResOffset + 30;
if ( sX < 0 ) sX = 0;
if ( sY < 0 ) sY = 0;
usTraitMenuPosX = sX + 30;
usTraitMenuPosY = sY;
if ( (usTraitMenuPosX + 400) > SCREEN_WIDTH )
usTraitMenuPosX = SCREEN_WIDTH - 400;
if ( (usTraitMenuPosY + 130) > SCREEN_HEIGHT )
usTraitMenuPosY = SCREEN_HEIGHT - 190;
POPUP_OPTION *pOption;
CHAR16 pStr[300];
// create entries for the sub-menus for each trait
GetEquipmentTemplates();
// we limit the maximum number of entries shown at once - too many entries could theoretically cause the button system to freak out
gEquipmentSelectionMaxEntriesShown = min(40, max( 0, (SCREEN_HEIGHT - 150 - usTraitMenuPosY) / 12 ) );
gEquipmentSelectionLastEntryShown = min( gEquipmentSelectionFirstEntryShown + gEquipmentSelectionMaxEntriesShown, gTemplateVector.size( ) );
if ( gEquipmentSelectionLastEntryShown < gEquipmentSelectionMaxEntriesShown )
gEquipmentSelectionFirstEntryShown = 0;
else
gEquipmentSelectionFirstEntryShown = gEquipmentSelectionLastEntryShown - gEquipmentSelectionMaxEntriesShown;
UINT32 cnt = gEquipmentSelectionFirstEntryShown;
for ( UINT32 i = gEquipmentSelectionFirstEntryShown; i < gEquipmentSelectionLastEntryShown; ++i )
{
//std::string str8 = (*it);
std::string str8 = gTemplateVector[i];
std::size_t found = str8.find_last_of( "." );
std::string str82 = str8.substr( 0, found );
const char* coca = str82.c_str( );
CHAR16 tmpchar[256];
int nChars = MultiByteToWideChar( CP_ACP, 0, coca, -1, NULL, 0 );
MultiByteToWideChar( CP_UTF8, 0, coca, -1, tmpchar, nChars );
pOption = new POPUP_OPTION( &std::wstring( tmpchar ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_EquipmentSelection, i ) );
pOption->color_foreground = FONT_GREEN;
GetPopup()->addOption(*pOption);
}
// 'more' option (moves down list)
if ( gEquipmentSelectionMaxEntriesShown < gTemplateVector.size( ) )
{
swprintf( pStr, pSkillMenuStrings[SKILLMENU_MORE] );
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_EquipmentSelection, 99999 ) );
GetPopup( )->addOption( *pOption );
}
// cancel option
swprintf(pStr, pSkillMenuStrings[SKILLMENU_CANCEL]);
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_EquipmentSelection, 99998 ) );
GetPopup()->addOption(*pOption);
SetPos(usTraitMenuPosX, usTraitMenuPosY);
}
void
EquipmentSelection::Functions(UINT32 aVal)
{
// this special value allows to 'scroll down'
if ( aVal == 99999 )
{
gEquipmentSelectionFirstEntryShown += gEquipmentSelectionMaxEntriesShown;
if ( gEquipmentSelectionFirstEntryShown >= gTemplateVector.size( ) )
gEquipmentSelectionFirstEntryShown = 0;
Cancel( );
EquipmentListMenu();
}
else if ( aVal == 99998 )
{
gEquipmentSelectionFirstEntryShown = 0;
Cancel( );
}
else if ( aVal < gTemplateVector.size( ) )
{
SOLDIERTYPE* pSoldier = &Menptr[gCharactersList[bSelectedInfoChar].usSolID];
if ( pSoldier )
{
std::string name = gTemplateVector[aVal];
ReadEquipmentTable( pSoldier, name );
}
// Note that we don't close menu - this way we don't have to open it every time we want to apply a template
}
}
/////////////////////////////// Trait Selection ////////////////////////////////////////////
void EquipmentListMenu()
{
gEquipmentSelection.Setup(0);
}
void EquipmentListMenuCancel()
{
gEquipmentSelection.Cancel();
}
+15 -1
View File
@@ -10,7 +10,7 @@
/**
* @brief A basic class for popup menus
* Use this to create mensu calling other menus, each having various sub-options
* Use this to create menus calling other menus, each having various sub-options
* I tried to make this as orderly as possible. It's ugly, but much more clean than the first solution, which was a hardcoded mess.
* You will, however, still need wrapper functions (we use callbacks on member functions), see Implementation.
*/
@@ -162,4 +162,18 @@ private:
*/
void TraitsMenu( INT32 usMapPos );
// C17
// not skill-related, but while we're here...
class EquipmentSelection : public SkillMenuItem
{
public:
EquipmentSelection() {}
void Setup(UINT32 aVal);
void Functions(UINT32 aVal);
};
void EquipmentListMenu();
void EquipmentListMenuCancel();
#endif
+4
View File
@@ -167,6 +167,7 @@ enum
SKILLMENU_CANCEL,
SKILLMENU_X_MILITIA,
SKILLMENU_ALL_MILITIA,
SKILLMENU_MORE,
};
extern STR16 pSkillMenuStrings[]; //Flugente
@@ -2992,6 +2993,9 @@ extern STR16 szInteractiveActionText[];
extern STR16 szLaptopStatText[];
// Flugente: gear templates
extern STR16 szGearTemplateText[];
#define TACTICAL_INVENTORY_DIALOG_NUM 16
#define TACTICAL_COVER_DIALOG_NUM 16
+11 -1
View File
@@ -2837,8 +2837,9 @@ STR16 pSkillMenuStrings[] =
L"其他队伍",
L"取消",
L"%d 民兵",
L"所有民兵",
L"More",
};
STR16 pSnitchMenuStrings[] =
@@ -11251,6 +11252,15 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Recruit approach",
};
STR16 szGearTemplateText[] = // TODO.Translate
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
// WANNE: Some Chinese specific strings that needs to be in unicode!
STR16 ChineseSpecString1 = L"%"; //defined in _ChineseText.cpp as this file is already unicode
STR16 ChineseSpecString2 = L"*%3d%%%"; //defined in _ChineseText.cpp as this file is already unicode
+11 -1
View File
@@ -2836,8 +2836,9 @@ STR16 pSkillMenuStrings[] = // TODO.Translate
L"Other Squads",
L"Cancel",
L"%d Militia",
L"All Militia",
L"More",
};
// TODO.Translate
@@ -11269,4 +11270,13 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Recruit approach",
};
STR16 szGearTemplateText[] = // TODO.Translate
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
#endif //DUTCH
+11 -1
View File
@@ -2833,8 +2833,9 @@ STR16 pSkillMenuStrings[] =
L"Other Squads",
L"Cancel",
L"%d Militia",
L"All Militia",
L"More",
};
STR16 pSnitchMenuStrings[] =
@@ -11250,4 +11251,13 @@ STR16 szLaptopStatText[] =
L"Recruit approach",
};
STR16 szGearTemplateText[] =
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
#endif //ENGLISH
+12 -2
View File
@@ -2839,14 +2839,15 @@ STR16 pTraitSkillsDenialStrings[] =
L" - aimed gun\n",
};
STR16 pSkillMenuStrings[] = // TODO.Translate
STR16 pSkillMenuStrings[] =
{
L"Milice",
L"Autre escouade",
L"Annuler",
L"%d miliciens",
L"Tous",
L"More", // TODO.Translate
};
STR16 pSnitchMenuStrings[] =
@@ -11251,4 +11252,13 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Recruit approach",
};
STR16 szGearTemplateText[] = // TODO.Translate
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
#endif //FRENCH
+11 -1
View File
@@ -2840,8 +2840,9 @@ STR16 pSkillMenuStrings[] = // TODO.Translate
L"Other Squads",
L"Cancel",
L"%d Militia",
L"All Militia",
L"More", // TODO.Translate
};
// TODO.Translate
@@ -11081,4 +11082,13 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Recruit approach",
};
STR16 szGearTemplateText[] = // TODO.Translate
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
#endif //GERMAN
+11 -1
View File
@@ -2831,8 +2831,9 @@ STR16 pSkillMenuStrings[] = // TODO.Translate
L"Other Squads",
L"Cancel",
L"%d Militia",
L"All Militia",
L"More", // TODO.Translate
};
// TODO.Translate
@@ -11260,4 +11261,13 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Recruit approach",
};
STR16 szGearTemplateText[] = // TODO.Translate
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
#endif //ITALIAN
+11 -1
View File
@@ -2843,8 +2843,9 @@ STR16 pSkillMenuStrings[] = // TODO.Translate
L"Other Squads",
L"Cancel",
L"%d Militia",
L"All Militia",
L"More", // TODO.Translate
};
STR16 pSnitchMenuStrings[] =
@@ -11273,4 +11274,13 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Recruit approach",
};
STR16 szGearTemplateText[] = // TODO.Translate
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
#endif //POLISH
+11 -1
View File
@@ -2837,8 +2837,9 @@ STR16 pSkillMenuStrings[] =
L"Другие отряды",
L"Отмена",
L"%d ополченцев",
L"Все ополченцы",
L"More", // TODO.Translate
};
STR16 pSnitchMenuStrings[] =
@@ -11254,4 +11255,13 @@ STR16 szLaptopStatText[] = // TODO.Translate
L"Recruit approach",
};
STR16 szGearTemplateText[] = // TODO.Translate
{
L"Enter Template Name",
L"Not possible during combat.",
L"Selected mercenary is not in this sector.",
L"%s is not in that sector.",
L"%s could not equip %s.",
};
#endif //RUSSIAN