From b60a94afc53057bc0faf00787e615a533f50dbc2 Mon Sep 17 00:00:00 2001 From: TheBob Date: Fri, 19 May 2017 13:40:34 +0000 Subject: [PATCH] Added: Ctrl+Shift+E now fill LBE items in sector with other items and places them in vehicles first. Added: Right-Click on remove attachments button on sector inventory screen will not empty LBE items in sector Changed: SLAY_STAYS_FOREVER disables Slay's hourly chance to leave when unattended Added: SLAY_HOURLY_CHANCE_TO_LEAVE setting to Ja2_Options.ini Fixed: a bunch of array index out of bounds bugs Fixed: a bunch of typos in if contitions Fixed: BuildListFile() function loading items from index 1 instead 0 Added translation: Polish text for some map inventory screen items Added translation: English texts for new functionality for other language files Cleaned up some old TODOs git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8404 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 2 + GameSettings.h | 2 + Laptop/BobbyRGuns.cpp | 2 +- Laptop/BriefingRoom_Data.cpp | 6 +- Laptop/BriefingRoom_Data.h | 2 +- Laptop/IMP Background.cpp | 2 +- Laptop/finances.cpp | 2 +- Strategic/Assignments.cpp | 4 +- Strategic/Hourly Update.cpp | 4 +- Strategic/LuaInitNPCs.cpp | 16 +- .../Map Screen Interface Map Inventory.cpp | 180 +++++++++++++--- Strategic/mapscreen.cpp | 200 +++++++++++++++--- Strategic/strategicmap.cpp | 4 +- Tactical/Civ Quotes.cpp | 6 +- Tactical/Interface Enhanced.cpp | 10 +- Tactical/Item Types.cpp | 26 ++- Tactical/Item Types.h | 4 +- Tactical/Items.cpp | 71 ++++++- Tactical/LOS.cpp | 17 +- Tactical/Turn Based Input.cpp | 15 ++ Tactical/Vehicles.cpp | 4 +- Tactical/XML_Clothes.cpp | 2 +- Tactical/XML_MercStartingGear.cpp | 12 +- Tactical/XML_Vehicles.cpp | 4 +- Tactical/opplist.cpp | 6 + Tactical/soldier profile type.h | 7 +- TacticalAI/NPC.cpp | 2 +- TileEngine/Buildings.cpp | 2 +- TileEngine/tiledef.cpp | 5 +- Utils/_ChineseText.cpp | 9 +- Utils/_DutchText.cpp | 9 +- Utils/_EnglishText.cpp | 11 +- Utils/_FrenchText.cpp | 9 +- Utils/_GermanText.cpp | 9 +- Utils/_ItalianText.cpp | 9 +- Utils/_PolishText.cpp | 17 +- Utils/_RussianText.cpp | 9 +- aniviewscreen.cpp | 8 +- ext/libpng/pngget.c | 2 +- 39 files changed, 565 insertions(+), 146 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index f9b9881b..46744ea9 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -864,6 +864,8 @@ void LoadGameExternalOptions() // CHRISL: New setting to allow Slay to remain as a hired PC gGameExternalOptions.fEnableSlayForever = iniReader.ReadBoolean("Recruitment Settings", "SLAY_STAYS_FOREVER", FALSE); + // Bob: externalized Slay's chance to leave + gGameExternalOptions.ubHourlyChanceSlayWillLeave = iniReader.ReadInteger("Recruitment Settings", "SLAY_HOURLY_CHANCE_TO_LEAVE", 15, 0, 100); // anv: playable Speck gGameExternalOptions.fEnableRecruitableSpeck = iniReader.ReadBoolean("Recruitment Settings", "RECRUITABLE_SPECK", TRUE); diff --git a/GameSettings.h b/GameSettings.h index 16542fb7..d9fbf8ef 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -807,6 +807,8 @@ typedef struct // CHRISL: option to allow Slay to remain as a hired PC BOOLEAN fEnableSlayForever; + // Bob: % chance Slay will leave every hour if left alone in sector + UINT16 ubHourlyChanceSlayWillLeave; // anv: playable Speck BOOLEAN fEnableRecruitableSpeck; diff --git a/Laptop/BobbyRGuns.cpp b/Laptop/BobbyRGuns.cpp index e0a4008e..5983fbb2 100644 --- a/Laptop/BobbyRGuns.cpp +++ b/Laptop/BobbyRGuns.cpp @@ -2309,7 +2309,7 @@ UINT16 DisplayProtection(UINT16 usPosY, UINT16 usIndex, UINT16 usFontHeight) break; } - swprintf(sTemp, L"%d", iProtection, Armour[ Item[ usIndex ].ubClassIndex ].ubProtection); // FIXME: param4 is unused + swprintf(sTemp, L"%d", iProtection); wcscat( sTemp, L"%%" ); swprintf( sTemp2, L"(%d)", Armour[ Item[ usIndex ].ubClassIndex ].ubProtection ); wcscat( sTemp, sTemp2 ); diff --git a/Laptop/BriefingRoom_Data.cpp b/Laptop/BriefingRoom_Data.cpp index 3fe739a9..d1c19c3d 100644 --- a/Laptop/BriefingRoom_Data.cpp +++ b/Laptop/BriefingRoom_Data.cpp @@ -212,8 +212,8 @@ void ResetTemp() for(i=0; i IMP_BACKGROUND_DISPLAYED_CHOICES ) + if( uiSkillPressed >= IMP_BACKGROUND_DISPLAYED_CHOICES ) { Assert( 0 ); return; diff --git a/Laptop/finances.cpp b/Laptop/finances.cpp index 27f62cba..3f4a22ac 100644 --- a/Laptop/finances.cpp +++ b/Laptop/finances.cpp @@ -1478,7 +1478,7 @@ void ProcessTransactionString(STR16 pString, FinanceUnitPtr pFinance) break; case PAY_SPECK_FOR_MERC: - swprintf(pString, L"%s", pTransactionText[ PAY_SPECK_FOR_MERC ], gMercProfiles[pFinance->ubSecondCode].zName); // FIXME: param4 unused + swprintf(pString, L"%s", pTransactionText[ PAY_SPECK_FOR_MERC ]); break; case MEDICAL_DEPOSIT: diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index 146efe4a..83043111 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -4833,7 +4833,7 @@ BOOLEAN CleanObject( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOwner, OBJECTTYPE * BOOLEAN bFullyCleaned = FALSE; // no gun? We shouldn't be here... - if ( !Item[pObj->usItem].usItemClass & IC_GUN ) + if ( !(Item[pObj->usItem].usItemClass & IC_GUN) ) Assert(0); ubItemsInPocket = pObj->ubNumberOfObjects; @@ -5033,7 +5033,7 @@ void HandleRepairBySoldier( SOLDIERTYPE *pSoldier ) // we spent some time cleaning so adjust repair points accordingly if ( ubRepairPtsLeft > 0 && ubInitialCleaningPts > ubCleaningPtsLeft ) { - ubRepairPtsLeft = UINT8()(ubRepairPtsLeft * ubCleaningPtsLeft / ubInitialCleaningPts); + ubRepairPtsLeft = (UINT8)(ubRepairPtsLeft * ubCleaningPtsLeft / ubInitialCleaningPts); } } diff --git a/Strategic/Hourly Update.cpp b/Strategic/Hourly Update.cpp index e0734b9b..6e192ce0 100644 --- a/Strategic/Hourly Update.cpp +++ b/Strategic/Hourly Update.cpp @@ -811,6 +811,8 @@ void HourlyStealUpdate() #else void HourlyCheckIfSlayAloneSoHeCanLeave() { + if (gGameExternalOptions.fEnableSlayForever || gGameExternalOptions.ubHourlyChanceSlayWillLeave < 1) return; + SOLDIERTYPE *pSoldier; pSoldier = FindSoldierByProfileID( SLAY, TRUE ); if( !pSoldier ) @@ -827,7 +829,7 @@ void HourlyCheckIfSlayAloneSoHeCanLeave() } if( PlayerMercsInSector( (UINT8)pSoldier->sSectorX, (UINT8)pSoldier->sSectorY, pSoldier->bSectorZ ) == 1 ) { - if( Chance( 15 ) ) + if( Chance( gGameExternalOptions.ubHourlyChanceSlayWillLeave ) ) { pSoldier->ubLeaveHistoryCode = HISTORY_SLAY_MYSTERIOUSLY_LEFT; TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING_NO_ASK_EQUIP, 0, 0 ); diff --git a/Strategic/LuaInitNPCs.cpp b/Strategic/LuaInitNPCs.cpp index f4a443fd..610ee07a 100644 --- a/Strategic/LuaInitNPCs.cpp +++ b/Strategic/LuaInitNPCs.cpp @@ -2925,7 +2925,7 @@ SOLDIERTYPE * FindSoldierByProfileID2( UINT8 ubProfileID, BOOLEAN fPlayerMercsOn BOOLEAN FindSoldier( SOLDIERTYPE **ppSoldier, UINT16 usSoldierIndex, BOOLEAN fPlayerMercsOnly) { - SOLDIERTYPE Menptr[ TOTAL_SOLDIERS ]; + //SOLDIERTYPE Menptr[ TOTAL_SOLDIERS ]; *ppSoldier = NULL; @@ -12009,11 +12009,15 @@ static int l_SetStartMission(lua_State *L) if ( idMission != -1 ) { - if ( gBriefingRoomData[idMission].CheckMission != MISSIONSTART || gBriefingRoomData[idMission].CheckMission != MISSIONEND || gBriefingRoomData[idMission].CheckMission == MISSIONNOSTARTED ) - { - gBriefingRoomData[idMission].CheckMission = MISSIONSTART; //set start mission - gBriefingRoomData[idMission].Hidden = TRUE; // set next mission - } + if ( + (gBriefingRoomData[idMission].CheckMission != MISSIONSTART) + || (gBriefingRoomData[idMission].CheckMission != MISSIONEND) + || (gBriefingRoomData[idMission].CheckMission == MISSIONNOSTARTED) + ) + { + gBriefingRoomData[idMission].CheckMission = MISSIONSTART; //set start mission + gBriefingRoomData[idMission].Hidden = TRUE; // set next mission + } } return 0; diff --git a/Strategic/Map Screen Interface Map Inventory.cpp b/Strategic/Map Screen Interface Map Inventory.cpp index 11aa6967..1e574220 100644 --- a/Strategic/Map Screen Interface Map Inventory.cpp +++ b/Strategic/Map Screen Interface Map Inventory.cpp @@ -337,6 +337,7 @@ void AnimateZoomInventory ( UINT16 iLocationInPool, UINT16 iCounter, INT32 iStar // the currently-opened sector inventory ammo. void SortSectorInventoryAmmo(bool useBoxes); void SortSectorInventoryEjectAmmo(); +void SortSectorInventoryEmptyLBE(); // Bob: added option to empty LBE items in sector void SortSectorInventorySeparateAttachments(); void SortSectorInventoryStackAndMerge(bool ammoOnly); // HEADROCK HAM 5: A quick function to rebuilt the Seen and Unseen item pools without saving the inventory. @@ -2244,15 +2245,22 @@ void BuildStashForSelectedSector( INT16 sMapX, INT16 sMapY, INT16 sMapZ ) { uiTotalNumberOfItems = guiNumWorldItems; uiNumOfSlots = (uiTotalNumberOfItems / MAP_INVENTORY_POOL_SLOT_COUNT + 1) * MAP_INVENTORY_POOL_SLOT_COUNT; - if(pInventoryPoolList.size() < uiNumOfSlots) + + if (pInventoryPoolList.size() < uiNumOfSlots) { pInventoryPoolList.resize(uiNumOfSlots); - if(pUnSeenItems.size() < uiNumOfSlots) + } + + if (pUnSeenItems.size() < uiNumOfSlots) { pUnSeenItems.resize(uiNumOfSlots); + } + uiNumberOfSeenItems = 0; uiNumberOfUnSeenItems = 0; + pwi = &gWorldItems.front(); pipl = &pInventoryPoolList.front(); pusi = &pUnSeenItems.front(); + for(i=0; iuiFlags & (BUTTON_CLICKED_ON))) { btn->uiFlags |= (BUTTON_CLICKED_ON); } } + if (reason & MSYS_CALLBACK_REASON_RBUTTON_UP) + { + if (btn->uiFlags & (BUTTON_CLICKED_ON)) + { + SortSectorInventoryEmptyLBE(); + btn->uiFlags &= ~(BUTTON_CLICKED_ON); + } + } if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP) { if (btn->uiFlags & (BUTTON_CLICKED_ON)) @@ -2829,6 +2845,7 @@ void MapInventoryPoolSortAttachmentsBtn( GUI_BUTTON *btn, INT32 reason ) btn->uiFlags &=~ (BUTTON_CLICKED_ON); } } + } // HEADROCK HAM 5: Eject Ammo button callback @@ -4002,21 +4019,27 @@ BOOLEAN SortInventoryPoolQ(void) BOOLEAN SwitchToInventoryPoolQ(UINT8 newidx)//dnl ch75 021113 { UINT8 curidx = gInventoryPoolIndex & 0x0F; + if(curidx >= INVPOOLLISTNUM) + return(FALSE); + newidx &= 0x0F; + if(curidx == newidx) return(FALSE); + MapInventoryFilterSet(IC_MAPFILTER_ALL); -#if 0 - pInventoryPoolListQ[curidx] = pInventoryPoolList; -#else + UINT32 uiNumOfSlots = (iLastInventoryPoolPage + 1) * MAP_INVENTORY_POOL_SLOT_COUNT; + if(pInventoryPoolListQ[curidx].size() != uiNumOfSlots) pInventoryPoolListQ[curidx].resize(uiNumOfSlots); + WORLDITEM *pwiQ1 = &pInventoryPoolListQ[curidx].front(); WORLDITEM *pwiQ2 = &pInventoryPoolListQ[curidx].back(); WORLDITEM *pwi1 = &pInventoryPoolList.front(); WORLDITEM *pwi2 = &pInventoryPoolList.back(); int cnt = 0; + while(pwi1 <= pwi2) { if(pwi1->fExists) @@ -4027,22 +4050,23 @@ BOOLEAN SwitchToInventoryPoolQ(UINT8 newidx)//dnl ch75 021113 pwi1++; cnt++; } + while(pwiQ1 <= pwiQ2) { pwiQ1->fExists = FALSE; pwiQ1->object.ubNumberOfObjects = 0; pwiQ1++; } -#endif + iCurrentInventoryPoolPageQ[curidx] = iCurrentInventoryPoolPage; iLastInventoryPoolPageQ[curidx] = iLastInventoryPoolPage; + if(pInventoryPoolListQ[newidx].empty() == true) pInventoryPoolListQ[newidx].resize(MAP_INVENTORY_POOL_SLOT_COUNT); -#if 0 - pInventoryPoolList = pInventoryPoolListQ[newidx]; -#else + if(pInventoryPoolList.size() < pInventoryPoolListQ[newidx].size()) pInventoryPoolList.resize(pInventoryPoolListQ[newidx].size()); + pwiQ1 = &pInventoryPoolListQ[newidx].front(); pwiQ2 = &pInventoryPoolListQ[newidx].back(); pwi1 = &pInventoryPoolList.front(); @@ -4064,11 +4088,12 @@ BOOLEAN SwitchToInventoryPoolQ(UINT8 newidx)//dnl ch75 021113 pwi1->object.ubNumberOfObjects = 0; pwi1++; } -#endif + iCurrentInventoryPoolPage = iCurrentInventoryPoolPageQ[newidx]; iLastInventoryPoolPage = iLastInventoryPoolPageQ[newidx]; gInventoryPoolIndex = newidx | 0x30; fMapPanelDirty = TRUE; + return(TRUE); } @@ -5011,23 +5036,98 @@ void SortSectorInventoryEjectAmmo() fMapPanelDirty=TRUE; } +void SortSectorInventoryEmptyLBE() { + // current item + WORLDITEM * pInventoryItem = NULL; + + SOLDIERTYPE * pSoldier = &(Menptr[gCharactersList[bSelectedInfoChar].usSolID]); + + for (UINT32 uiLoop = 0; uiLoop < pInventoryPoolList.size(); uiLoop++) //for all items in sector + { + pInventoryItem = &(pInventoryPoolList[uiLoop]); + + if (pInventoryItem->bVisible == TRUE && // Visible + pInventoryItem->object.exists() == true && // Exists + pInventoryItem->usFlags & WORLD_ITEM_REACHABLE && // Reachable + !(pInventoryItem->usFlags & WORLD_ITEM_ARMED_BOMB)) // Not booby-trapped! + { + // Iterate through stacks + for (int x = 0; x < pInventoryItem->object.ubNumberOfObjects; ++x) + { + UINT8 size = 0, cnt = 0, uiLoopCnt = 0; + // Bob: empty LBE items in sector inventory + if (pInventoryItem->object.IsActiveLBE(x)) { + LBENODE * lbePtr = pInventoryItem->object.GetLBEPointer(x); + INVTYPE & LBEType = Item[pInventoryItem->object.usItem]; + + if (lbePtr != NULL) { + int dropCnt = 0; + + for (auto lbeInvIter = lbePtr->inv.begin(); lbeInvIter != lbePtr->inv.end(); lbeInvIter++) { + OBJECTTYPE * LBEStack = lbeInvIter._Ptr; + dropCnt += LBEStack->ubNumberOfObjects; + + AutoPlaceObjectToWorld(pSoldier, LBEStack, true); + if (LBEStack != NULL) + { + DeleteObj(lbeInvIter._Ptr); + } + } + + if (dropCnt > 0) { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzMapInventorySortingMessage[5], dropCnt, LBEType.szItemName); + } + else { + ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, gzMapInventorySortingMessage[6], LBEType.szItemName); + } + + if (DestroyLBEIfEmpty(&(pInventoryItem->object), x)) { + ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, gzMapInventorySortingMessage[7], LBEType.szItemName); + } + else { + ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, gzMapInventorySortingMessage[8], LBEType.szItemName); + } + } + else { // can't get LBE pointer, something is wrong + ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, gzMapInventorySortingMessage[9], LBEType.szItemName); + } + } // IsActiveLBE + } // Iterate through stacks + } // pInventoryPoolList loop + } + + // "FINISHED" + CHAR16 pStr[500]; + swprintf(pStr, gzMapInventorySortingMessage[4], 'A' + sSelMapY - 1, sSelMapX); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pStr); + + // Dirty! + fMapPanelDirty = TRUE; +} + void SortSectorInventorySeparateAttachments() { - + // attachment ref and pointer OBJECTTYPE gTempObject; - - SOLDIERTYPE * pSoldier = &(Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ]); + OBJECTTYPE * gpTempObject = NULL; - for ( UINT32 uiLoop = 0; uiLoop < pInventoryPoolList.size(); uiLoop++ ) //for all items in sector + // current item + WORLDITEM * pInventoryItem = NULL; + + + SOLDIERTYPE * pSoldier = &(Menptr[gCharactersList[bSelectedInfoChar].usSolID]); + + for (UINT32 uiLoop = 0; uiLoop < pInventoryPoolList.size(); uiLoop++) //for all items in sector { - if ( pInventoryPoolList[uiLoop].bVisible == TRUE && // Visible - pInventoryPoolList[uiLoop].object.exists() == true && // Exists - pInventoryPoolList[uiLoop].usFlags & WORLD_ITEM_REACHABLE && // Reachable - !(pInventoryPoolList[uiLoop].usFlags & WORLD_ITEM_ARMED_BOMB) ) // Not booby-trapped! - { + pInventoryItem = &(pInventoryPoolList[uiLoop]); + if (pInventoryItem->bVisible == TRUE && // Visible + pInventoryItem->object.exists() == true && // Exists + pInventoryItem->usFlags & WORLD_ITEM_REACHABLE && // Reachable + !(pInventoryItem->usFlags & WORLD_ITEM_ARMED_BOMB)) // Not booby-trapped! + { // Iterate through stacks - for (int x = 0; x < pInventoryPoolList[uiLoop].object.ubNumberOfObjects; ++x) + for (int x = 0; x < pInventoryItem->object.ubNumberOfObjects; ++x) { UINT8 size = 0, cnt = 0, uiLoopCnt = 0; @@ -5035,17 +5135,28 @@ void SortSectorInventorySeparateAttachments() // launchers before detaching the launchers (and their grenade slots) themselves. // Since the size of the attachmentList remains constant under NAS but decrements by one // under OAS, recheck the list size every iteration in order to calculate an rindex. - while((size = pInventoryPoolList[uiLoop].object[x]->attachments.size()) != cnt) + while ((size = pInventoryItem->object[x]->attachments.size()) != cnt) { - gTempObject = *(pInventoryPoolList[uiLoop].object[x]->GetAttachmentAtIndex(size - 1 - cnt)); + OBJECTTYPE * pNewObj = new OBJECTTYPE(); + gpTempObject = pInventoryItem->object[x]->GetAttachmentAtIndex(size - 1 - cnt); //WarmSteel - This actually still works with NAS, be it by accident - if (pInventoryPoolList[uiLoop].object.RemoveAttachment(&gTempObject,0,x)) + if (gpTempObject != NULL && pInventoryItem->object.RemoveAttachment(gpTempObject, pNewObj, x)) { - AutoPlaceObjectToWorld( pSoldier, &gTempObject, true ); - if (&gTempObject != NULL) + // Bob: sanity check! I think RemoveAttachment shouldn't be used like it was here. + if (gpTempObject->usItem > 0 && (gpTempObject->ubNumberOfObjects != 1 || gpTempObject->usItem > MAXITEMS || gpTempObject->ubMission != 0)) { + gpTempObject = pNewObj; + } + + // Bob: not sure why was this a ref instead of a pointer, + // I'll leave it here so it gets cleaned up when going out of scope + // since DeleteObj() doesn't free all the memory + gTempObject = *gpTempObject; + + AutoPlaceObjectToWorld(pSoldier, gpTempObject, true); + if (gpTempObject != NULL) { - DeleteObj( &gTempObject ); + DeleteObj(gpTempObject); } } else @@ -5053,24 +5164,25 @@ void SortSectorInventorySeparateAttachments() cnt++; } - uiLoopCnt ++; + uiLoopCnt++; // Failsafe - if(uiLoopCnt > 100) + if (uiLoopCnt > 100) { break; } } - } - } + } // Iterate through stacks + } // pInventoryPoolList loop } + // "FINISHED" CHAR16 pStr[500]; - swprintf( pStr, gzMapInventorySortingMessage[ 1 ], 'A' + sSelMapY - 1, sSelMapX ); - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pStr ); + swprintf(pStr, gzMapInventorySortingMessage[1], 'A' + sSelMapY - 1, sSelMapX); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pStr); // Dirty! - fMapPanelDirty=TRUE; + fMapPanelDirty = TRUE; } // HEADROCK HAM 5: This function sorts all inventory items into stacks. It is similar to a hotkey-driven diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index c29a6873..5af7e8ac 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -1035,6 +1035,14 @@ void ChangeCharacterListSortMethod( INT32 iValue ); void MapscreenMarkButtonsDirty(); +// Bob: functions for packing vehicles with filled LBE items +void moveSectorInventoryToVehicle(SOLDIERTYPE *pSoldier); +void fillCurrentSectorLBEItems(SOLDIERTYPE *pSoldier); +void fillLBEWithSectorItems(OBJECTTYPE * LBEObject); +void moveCurrentSectorItemsToVehicle(SOLDIERTYPE *pSoldier); +bool placeItemInVehicle(SOLDIERTYPE *pSoldier, WORLDITEM &worldItem); +bool placeItemInVehicle(SOLDIERTYPE *pSoldier, OBJECTTYPE &item); + extern BOOLEAN CanRedistributeMilitiaInSector( INT16 sClickedSectorX, INT16 sClickedSectorY, INT8 bClickedTownId ); extern INT32 GetNumberOfMercsInUpdateList( void ); @@ -7671,34 +7679,7 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) { if (gGameExternalOptions.fVehicleInventory) { - for (unsigned int i = 0; i < pInventoryPoolList.size(); i++) - { - if (pInventoryPoolList[i].fExists == TRUE && (pInventoryPoolList[i].usFlags & WORLD_ITEM_REACHABLE)) - { - for (int x = 0; x < NUM_INV_SLOTS; x++) - { - if (vehicleInv[x] == FALSE) - continue; - if (pSoldier->inv[x].exists() == true) - { - if (pSoldier->inv[x].usItem != pInventoryPoolList[i].object.usItem) - continue; - else - pInventoryPoolList[i].object.AddObjectsToStack(pSoldier->inv[x], -1, pSoldier, x); - } - else - pInventoryPoolList[i].object.MoveThisObjectTo(pSoldier->inv[x], -1, pSoldier, x); - if (pInventoryPoolList[i].object.ubNumberOfObjects < 0) - { - //RemoveItemFromWorld(i); - break; - } - } - } - fTeamPanelDirty = TRUE; - fMapPanelDirty = TRUE; - fInterfacePanelDirty = DIRTYLEVEL2; - } + moveSectorInventoryToVehicle(pSoldier); } } // Flugente: also allow mercs to qickly pick up items this way (but not EPCs) @@ -16973,3 +16954,166 @@ void RetreatBandageCallback( UINT8 ubResult ) { HandleRetreatBandaging( ); } + +// Bob: moved here to expand what CHRISL did +// try to move all items in sector into the vehicle inventory. Try to use LBE items in sector to store as much stuff as possible +void moveSectorInventoryToVehicle(SOLDIERTYPE *pSoldier) { + + fillCurrentSectorLBEItems(pSoldier); // puts LBE items in vehicle + // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"---------------------------------------------"); + // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Moving remaining sector items into the car..."); + moveCurrentSectorItemsToVehicle(pSoldier); // puts remaining items in vehicle + + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fInterfacePanelDirty = DIRTYLEVEL2; +} + +// fills all empty LBE items in currebt sector with other sector items then tries to place all LBE items in the vehicle (pSoldier) +void fillCurrentSectorLBEItems(SOLDIERTYPE *pSoldier) { + std::vector LBEObjects; // list of LBE objects found in sector + + // build a list of LBE objects in sector. Stacks are split into separate items. + for (unsigned int i = 0; i < pInventoryPoolList.size(); i++) + { + WORLDITEM & stack = pInventoryPoolList[i]; + OBJECTTYPE & stackContents = pInventoryPoolList[i].object; + INVTYPE & stackContentType = Item[stackContents.usItem]; + + if ( stack.fExists == TRUE + && stack.usFlags & WORLD_ITEM_REACHABLE + && stackContentType.usItemClass == IC_LBEGEAR + ) { + for (int j = 0; j< stackContents.ubNumberOfObjects; j++) { + OBJECTTYPE * LBEObject = new OBJECTTYPE(); + + stackContents.MoveThisObjectTo(*LBEObject, 1); + LBEObjects.push_back(LBEObject); + } + } + } + + // fill the LBE items in the list with items from current sector then try to put them in the vehicle + for (std::vector::iterator LBEItemIter = LBEObjects.begin(); LBEItemIter != LBEObjects.end(); LBEItemIter++) { + OBJECTTYPE* LBEItem = *LBEItemIter; + INVTYPE LBEItemType = Item[LBEItem->usItem]; + LBETYPE LBEType = LoadBearingEquipment[LBEItemType.ubClassIndex]; + + //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"==================================="); + //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Filling: %s", LBEItemType.szItemName); + + if ( LBEItem->IsActiveLBE(0) == FALSE ) { + // init LBE data + CreateLBE(LBEItem, pSoldier->ubID, LBEType.lbePocketIndex.size()); + // stuff it full of sector items + fillLBEWithSectorItems(LBEItem); + } + + // try to put the LBE item in the vehicle, if we fail then drop it. + if (placeItemInVehicle(pSoldier, *LBEItem) == false) { + // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Dropped %s on the ground", LBEItemType.szItemName); + AutoPlaceObjectToWorld(pSoldier, LBEItem); + } else { + // ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Moved %s into the car", LBEItemType.szItemName); + } + + } +} + +// fills LBEObject with items from currently loaded sector. Assumes that LBEObject contains only one item +void fillLBEWithSectorItems(OBJECTTYPE * LBEObject) { + LBENODE* pLBE = LBEObject->GetLBEPointer(0); + + INVTYPE LBEItemType = Item[LBEObject->usItem]; + LBETYPE LBEType = LoadBearingEquipment[LBEItemType.ubClassIndex]; + + int movedItemsTotal = 0; + + for (int i = 0; i < LBEType.lbePocketIndex.size(); i++) { + INT16 lbePocket = LBEType.lbePocketIndex[i]; + if (lbePocket == 0) continue; + + POCKETTYPE lbePocketType = LBEPocketType[lbePocket]; + + for (auto itemIterator = pInventoryPoolList.begin(); itemIterator != pInventoryPoolList.end(); itemIterator++) { + WORLDITEM * sectorItemStack = &(*itemIterator); + OBJECTTYPE * sectorItemObject = &(itemIterator->object); + INVTYPE sectorItemType = Item[sectorItemObject->usItem]; + + if (sectorItemStack->fExists && sectorItemStack->usFlags & WORLD_ITEM_REACHABLE && sectorItemType.usItemClass != IC_LBEGEAR && sectorItemObject->usItem > 0) { + int pocketCapacity = lbePocketType.ItemCapacityPerSize[sectorItemType.ItemSize]; + + if (pocketCapacity > 0) { + OBJECTTYPE * pocketItemObject = new OBJECTTYPE(); + + int movedItems = (sectorItemObject->ubNumberOfObjects > pocketCapacity) ? pocketCapacity : sectorItemObject->ubNumberOfObjects; + + int remainingItems = sectorItemObject->MoveThisObjectTo(*pocketItemObject, movedItems); + + //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Moved %s * %i (%i remaining) into %s (%s)", sectorItemType.szItemName, movedItems, remainingItems, LBEItemType.szItemName, lbePocketType.pName); + + pLBE->inv[i] = (*pocketItemObject); + + movedItemsTotal += movedItems; + + break; + } + } + } + } + + if (movedItemsTotal == 0) { + DestroyLBE(LBEObject); + } +} + +void moveCurrentSectorItemsToVehicle(SOLDIERTYPE *pSoldier) { + for (unsigned int i = 0; i < pInventoryPoolList.size(); i++) + { + if (pInventoryPoolList[i].fExists == TRUE && (pInventoryPoolList[i].usFlags & WORLD_ITEM_REACHABLE)) + { + placeItemInVehicle(pSoldier, pInventoryPoolList[i]); + } + } +} + +bool placeItemInVehicle(SOLDIERTYPE *pSoldier, WORLDITEM &worldItem) { + return placeItemInVehicle(pSoldier, worldItem.object); +} + +bool placeItemInVehicle(SOLDIERTYPE *pSoldier, OBJECTTYPE &item) { + if (item.usItem < 1) return false; + + INVTYPE sectorItemType = Item[item.usItem]; + + for (int x = 0; x < NUM_INV_SLOTS && item.ubNumberOfObjects > 0; x++) + { + if (vehicleInv[x] == FALSE) + continue; + + if (pSoldier->inv[x].exists() == true) + { + if (pSoldier->inv[x].usItem != item.usItem) + { + continue; + } + else + { + //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Stacking %s * %i in car slot %i", sectorItemType.szItemName, item.ubNumberOfObjects, x); + pSoldier->inv[x].AddObjectsToStack(item, -1, pSoldier, x); + } + } + else + { + //ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Placing %s * %i in car slot %i", sectorItemType.szItemName, item.ubNumberOfObjects, x); + int result = item.MoveThisObjectTo(pSoldier->inv[x], -1, pSoldier, x); + } + + if (item.ubNumberOfObjects < 0) + { + break; + } + } + + return (item.ubNumberOfObjects == 0); +} diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index a260d141..75596e84 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -676,7 +676,7 @@ samsiteEndElementHandle( void *userData, const XML_Char *name ) pData->curElement = SAMSITE_ELEMENT_SAM; pData->curSamInfo.samOrientation = (INT8)atol( pData->szCharData ); - if ( pData->curSamInfo.samOrientation != 3 || pData->curSamInfo.samOrientation != 4 ) + if ( pData->curSamInfo.samOrientation != 3 && pData->curSamInfo.samOrientation != 4 ) { pData->curSamInfo.samOrientation = 3; } @@ -2045,7 +2045,7 @@ void GetMapFileName( INT16 sMapX, INT16 sMapY, INT8 bSectorZ, STR8 bString, BOOL // Debug str DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Map does not exist for %s, using default.", bTestString ) ); // Set to a string we know! - sprintf( bString, "H10.DAT", pVertStrings[sMapY], pHortStrings[sMapX] ); + sprintf( bString, "H10.DAT"); ScreenMsg( FONT_YELLOW, MSG_DEBUG, L"Using PLACEHOLDER map!" ); } return; diff --git a/Tactical/Civ Quotes.cpp b/Tactical/Civ Quotes.cpp index 80404484..bb7e5e39 100644 --- a/Tactical/Civ Quotes.cpp +++ b/Tactical/Civ Quotes.cpp @@ -589,8 +589,10 @@ UINT16 DetermineCivQuoteEntry( SOLDIERTYPE *pCiv, UINT16 *pubCivHintToUse, BOOLE // Determine what type of quote to say... // Are are we going to attack? - if ( pCiv->aiData.bAction == AI_ACTION_TOSS_PROJECTILE || pCiv->aiData.bAction == AI_ACTION_FIRE_GUN || - pCiv->aiData.bAction == AI_ACTION_FIRE_GUN || pCiv->aiData.bAction == AI_ACTION_KNIFE_MOVE ) + if ( pCiv->aiData.bAction == AI_ACTION_TOSS_PROJECTILE + || pCiv->aiData.bAction == AI_ACTION_FIRE_GUN + || pCiv->aiData.bAction == AI_ACTION_THROW_KNIFE + || pCiv->aiData.bAction == AI_ACTION_KNIFE_MOVE ) { return( CIV_QUOTE_ENEMY_THREAT ); } diff --git a/Tactical/Interface Enhanced.cpp b/Tactical/Interface Enhanced.cpp index 16935752..a7da8015 100644 --- a/Tactical/Interface Enhanced.cpp +++ b/Tactical/Interface Enhanced.cpp @@ -11002,7 +11002,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject ) else { SetFontForeground( 5 ); - swprintf( pStr, L"=", iFloatModifier[cnt2] ); + swprintf( pStr, L"=" ); } FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY); } @@ -12016,25 +12016,25 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject ) if (iModifier[cnt2]) { SetFontForeground( 5 ); - swprintf( pStr, L"=", iModifier[cnt2] ); + swprintf( pStr, L"=" ); } else { SetFontForeground( ITEMDESC_FONTPOSITIVE ); - swprintf( pStr, L"Y", iModifier[cnt2] ); + swprintf( pStr, L"Y" ); } FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY); } else if ( fComparisonMode && !iComparedModifier[0] ) { SetFontForeground( ITEMDESC_FONTNEGATIVE ); - swprintf( pStr, L"N", iModifier[cnt2] ); + swprintf( pStr, L"N" ); FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY); } else if (iModifier[cnt2]) { SetFontForeground( ITEMDESC_FONTPOSITIVE ); - swprintf( pStr, L"Y", iModifier[cnt2] ); // FIXME: unused param + swprintf( pStr, L"Y" ); FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY); } else diff --git a/Tactical/Item Types.cpp b/Tactical/Item Types.cpp index 581fc948..5ac11c28 100644 --- a/Tactical/Item Types.cpp +++ b/Tactical/Item Types.cpp @@ -156,10 +156,10 @@ void CreateLBE (OBJECTTYPE* pObj, UINT8 ubID, int numSubPockets) (*pObj)[0]->data.lbe.uniqueID = uniqueID; } -bool DestroyLBEIfEmpty(OBJECTTYPE* pObj) +bool DestroyLBEIfEmpty(OBJECTTYPE* pObj, int stackIndex) { - if (pObj->IsActiveLBE(0) == true) { - LBENODE* pLBE = pObj->GetLBEPointer(0); + if (pObj->IsActiveLBE(stackIndex) == true) { + LBENODE* pLBE = pObj->GetLBEPointer(stackIndex); if (pLBE) { UINT16 plbesize = pLBE->inv.size(); @@ -174,19 +174,19 @@ bool DestroyLBEIfEmpty(OBJECTTYPE* pObj) break; } } - (*pObj)[0]->data.lbe.uniqueID = 0; - (*pObj)[0]->data.lbe.bLBE = 0; + (*pObj)[stackIndex]->data.lbe.uniqueID = 0; + (*pObj)[stackIndex]->data.lbe.bLBE = 0; return true; } } return false; } -void DestroyLBE(OBJECTTYPE* pObj) +void DestroyLBE(OBJECTTYPE* pObj, int stackIndex) { - if(pObj->IsActiveLBE(0) == true) + if(pObj->IsActiveLBE(stackIndex) == true) { - LBENODE* pLBE = pObj->GetLBEPointer(0); + LBENODE* pLBE = pObj->GetLBEPointer(stackIndex); if(pLBE) { UINT16 plbesize = pLBE->inv.size(); @@ -206,8 +206,8 @@ void DestroyLBE(OBJECTTYPE* pObj) } } - (*pObj)[0]->data.lbe.uniqueID = 0; - (*pObj)[0]->data.lbe.bLBE = 0; + (*pObj)[stackIndex]->data.lbe.uniqueID = 0; + (*pObj)[stackIndex]->data.lbe.bLBE = 0; return; } } @@ -1009,7 +1009,11 @@ OBJECTTYPE* StackedObjectData::GetAttachmentAtIndex(UINT8 index) } if (iter != attachments.end()) { - return &(*iter); + OBJECTTYPE * attachment = &(*iter); + if (attachment->usItem > 0 && (attachment->ubNumberOfObjects != 1 || attachment->usItem > MAXITEMS || attachment->ubMission != 0) ) { + __debugbreak(); + } + return attachment; } return 0; } diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 86b8de8b..1acd0734 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -257,8 +257,8 @@ public: bool checkLBEArrayIntegrity(bool verbose=false); // BOB: checks all worldItems for missing LBE info void CreateLBE(OBJECTTYPE* pObj, UINT8 ubID, int numSubPockets); -bool DestroyLBEIfEmpty(OBJECTTYPE* pObj); -void DestroyLBE(OBJECTTYPE* pObj); +bool DestroyLBEIfEmpty(OBJECTTYPE* pObj, int stackIndex = 0); +void DestroyLBE(OBJECTTYPE* pObj, int stackIndex = 0); void GetLBESlots(UINT32 LBEType, std::vector& LBESlots); void MoveItemsInSlotsToLBE( SOLDIERTYPE *pSoldier, std::vector& LBESlots, LBENODE* pLBE, OBJECTTYPE* pObj); diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index c8e36d7d..138a0697 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -8248,7 +8248,8 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting ) return( TRUE ); } -BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNewObj, UINT8 subObject, SOLDIERTYPE * pSoldier, BOOLEAN fForceInseperable, BOOLEAN fRemoveProhibited ) +// pAttachment will be filled with garbage data, pass a new OBJECTTYPE as pNewObj to get the removed attachment or pass NULL to indicate the attachment is to be deleted +BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNewObj, UINT8 subObject, SOLDIERTYPE * pSoldier, BOOLEAN fForceInseperable, BOOLEAN fRemoveProhibited ) { BOOLEAN objDeleted = FALSE; std::vector usAttachmentSlotIndexVector; @@ -8280,20 +8281,31 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew //This is so that you can click to remove an attachment and it will take off THAT attachment and not the first one that just "looks" like it. for (std::list::iterator iter = (*this)[subObject]->attachments.begin(); iter != (*this)[subObject]->attachments.end(); ++iter){ - //Compare the adress - if(&(*iter) == pAttachment) - { - removedAttachment = *pAttachment; - iter = (*this)[subObject]->RemoveAttachmentAtIter(iter); - pAttachment = NULL; - objDeleted = TRUE; - break; - } + + // Bob: sanity check! + if (pAttachment != NULL && pAttachment->usItem > 0 && (pAttachment->ubNumberOfObjects != 1 || pAttachment->usItem > MAXITEMS || pAttachment->ubMission != 0)) { + __debugbreak(); + } + + //Compare the adress + if(&(*iter) == pAttachment) + { + removedAttachment = *pAttachment; + iter = (*this)[subObject]->RemoveAttachmentAtIter(iter); + pAttachment = NULL; + objDeleted = TRUE; + break; + } } //It is possible that the previous loop did not find the EXACT attachment we wanted to delete, look if there is one that is at least equal in data. if(!objDeleted){ for (std::list::iterator iter = (*this)[subObject]->attachments.begin(); iter != (*this)[subObject]->attachments.end(); ++iter){ + // Bob: sanity check! + if (pAttachment != NULL && pAttachment->usItem > 0 && (pAttachment->ubNumberOfObjects != 1 || pAttachment->usItem > MAXITEMS || pAttachment->ubMission != 0)) { + __debugbreak(); + } + //This compares the internal data of the objects. if(*iter == *pAttachment) { @@ -8305,9 +8317,20 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew } } } + + // Bob: sanity check! + if (pAttachment != NULL && pAttachment->usItem > 0 && (pAttachment->ubNumberOfObjects != 1 || pAttachment->usItem > MAXITEMS || pAttachment->ubMission != 0)) { + __debugbreak(); + } + if(!objDeleted) return( FALSE ); + // Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data + if (pAttachment != NULL) { + __debugbreak(); + } + //After removing an attachment, the ammo capacity might have changed. if ( Item[this->usItem].usItemClass == IC_GUN && (*this)[subObject]->data.gun.usGunAmmoItem != NONE && (*this)[subObject]->data.gun.ubGunShotsLeft > 0 && oldMagSize != GetMagSize(this, subObject) ) { @@ -8399,8 +8422,23 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew RemoveProhibitedAttachments(pSoldier, &removedAttachment, removedAttachment.usItem); RemoveProhibitedAttachments(pSoldier, this, this->usItem); } - if(pNewObj != NULL) + + // Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data + if (pAttachment != NULL) { + __debugbreak(); + } + + if (pNewObj != NULL) { *pNewObj = removedAttachment; + } + else { + *pAttachment = removedAttachment; + } + + // Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data + if (pAttachment != NULL) { + __debugbreak(); + } // Why is this here? By now, the object, pAttachment had been pointing to, has already been deconstructed via RemoveAttachmentAtIter. @@ -8425,11 +8463,22 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew pNewObj->AttachObject(NULL, &tmp, FALSE, 0, -1, 0); } } + + // Bob: this function tends to leave this pointer in a messed up state, leading other code to deal with bogus item data + if (pAttachment != NULL) { + __debugbreak(); + } + //Removing an attachment can alter slots, check them. if(UsingNewAttachmentSystem()==true && fRemoveProhibited){ RemoveProhibitedAttachments(pSoldier, this, this->usItem); } + // Bob: this function tends to leave this pointer in a messed up state, leading to other code to deal with bogus item data + if (pAttachment != NULL) { + __debugbreak(); + } + //ADB ubWeight has been removed, see comments in OBJECTTYPE //this->ubWeight = CalculateObjectWeight( this ); return( TRUE ); diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index ed6024a8..b44a7b3d 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -2201,7 +2201,15 @@ BOOLEAN CalculateSoldierZPos( SOLDIERTYPE * pSoldier, UINT8 ubPosType, FLOAT * p *pdZPos = ( WALL_HEIGHT_UNITS * 2 ) - 1; } - *pdZPos += CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[pSoldier->sGridNo].sHeight ); + // Bob: check if sGridNo is set, otherwise bail out to avoid access violation + INT32 grid = pSoldier->sGridNo; + if (grid > 0) { + *pdZPos += CONVERT_PIXELS_TO_HEIGHTUNITS(gpWorldLevelData[grid].sHeight); + } + else { + // ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"CalculateSoldierZPos: Caught bad LOS height check!"); + } + return( TRUE ); } @@ -2505,6 +2513,13 @@ INT32 LocationToLocationLineOfSightTest( INT32 sStartGridNo, INT8 bStartLevel, I { FLOAT dStartZPos, dEndZPos; INT16 sStartXPos, sStartYPos, sEndXPos, sEndYPos; + + // Bob: prevent access violation + if (sStartGridNo < 0) { + // ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"LocationToLocationLineOfSightTest: Caught bad LOS check!"); + return 0; + } + // UINT8 ubStartID; // sevenfm: always use standing heights diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 5f329ff1..e1cdc7cb 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -6703,6 +6703,21 @@ void SeperateItems() break; } } + + // Bob: also empty out LBE items in sector inventory + if (gWorldItems[uiLoop].object.IsActiveLBE(x)) { + LBENODE * lbePtr = gWorldItems[uiLoop].object.GetLBEPointer(x); + + for (auto lbeInvIter = lbePtr->inv.begin(); lbeInvIter != lbePtr->inv.end(); lbeInvIter++) { + OBJECTTYPE * LBEStack = lbeInvIter._Ptr; + + if (LBEStack->usItem != 0 && LBEStack->exists()) { + AddItemToPool(gWorldItems[uiLoop].sGridNo, LBEStack, 1, gWorldItems[uiLoop].ubLevel, WORLD_ITEM_REACHABLE, -1); + } + } + DestroyLBE(&(gWorldItems[uiLoop].object), x); + } + } } } diff --git a/Tactical/Vehicles.cpp b/Tactical/Vehicles.cpp index 3d125235..9a119245 100644 --- a/Tactical/Vehicles.cpp +++ b/Tactical/Vehicles.cpp @@ -2449,7 +2449,7 @@ BOOLEAN LoadVehicleInformationFromSavedGameFile( HWFILE hFile, UINT32 uiSavedGam { // ! The id of the soldier was saved in the passenger pointer. The passenger pointer is converted back // ! to a UINT8 so we can get the REAL pointer to the soldier. - pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)pVehicleList[cnt].pPassengers[ ubPassengerCnt ], FALSE ); + pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)(pVehicleList[cnt].pPassengers[ ubPassengerCnt ]), FALSE ); } } else @@ -2458,7 +2458,7 @@ BOOLEAN LoadVehicleInformationFromSavedGameFile( HWFILE hFile, UINT32 uiSavedGam { // ! The id of the soldier was saved in the passenger pointer. The passenger pointer is converted back // ! to a UINT8 so we can get the REAL pointer to the soldier. - pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)pVehicleList[cnt].pPassengers[ ubPassengerCnt ], FALSE ); + pVehicleList[cnt].pPassengers[ubPassengerCnt] = FindSoldierByProfileID( (UINT8)(pVehicleList[cnt].pPassengers[ ubPassengerCnt ]), FALSE ); } else { diff --git a/Tactical/XML_Clothes.cpp b/Tactical/XML_Clothes.cpp index 31c80927..b051effc 100644 --- a/Tactical/XML_Clothes.cpp +++ b/Tactical/XML_Clothes.cpp @@ -210,7 +210,7 @@ BOOLEAN WriteClothesStats() UINT32 cnt; FilePrintf(hFile,"\r\n"); - for(cnt = 0; cnt < MAXITEMS; ++cnt) + for(cnt = 0; cnt < CLOTHES_MAX; ++cnt) { FilePrintf(hFile,"\t\r\n"); diff --git a/Tactical/XML_MercStartingGear.cpp b/Tactical/XML_MercStartingGear.cpp index e7c6c9c3..2d9cba89 100644 --- a/Tactical/XML_MercStartingGear.cpp +++ b/Tactical/XML_MercStartingGear.cpp @@ -188,14 +188,16 @@ MercStartingGearEndElementHandle(void *userData, const XML_Char *name) else if(strcmp(name, "mName") == 0) { pData->curElement = ELEMENT; - if(MAX_CHAR_DATA_LENGTH >= strlen(pData->szCharData)) - strcpy(pData->curMercStartingGear.mName,pData->szCharData); + if (strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH ) { + strncpy(pData->curMercStartingGear.mName, pData->szCharData, mNameLength); + } else { - strncpy(pData->curMercStartingGear.mName,pData->szCharData,MAX_CHAR_DATA_LENGTH); - pData->curMercStartingGear.mName[MAX_CHAR_DATA_LENGTH] = '\0'; + strncpy(pData->curMercStartingGear.mName,pData->szCharData, mNameLength); + pData->curMercStartingGear.mName[mNameLength-1] = '\0'; } - for(int i=0;iszCharData),MAX_CHAR_DATA_LENGTH);i++) + + for(int i=0;iszCharData), mNameLength);i++) { temp = pData->szCharData[i]; pData->curMercStartingGear.mName[i] = temp; diff --git a/Tactical/XML_Vehicles.cpp b/Tactical/XML_Vehicles.cpp index fd4b4127..dff98eee 100644 --- a/Tactical/XML_Vehicles.cpp +++ b/Tactical/XML_Vehicles.cpp @@ -230,10 +230,10 @@ newCarEndElementHandle(void *userData, const XML_Char *name) else { strncpy(pData->curNewCar.szIconFace,pData->szCharData,MAX_MAIN_VEHICLE_CHARS); - pData->curNewCar.szIconFace[MAX_MAIN_VEHICLE_CHARS] = '\0'; + pData->curNewCar.szIconFace[MAX_MAIN_VEHICLE_CHARS-1] = '\0'; } - for(int i=0;iszCharData),MAX_MAIN_VEHICLE_CHARS);i++) + for(int i=0;iszCharData),MAX_MAIN_VEHICLE_CHARS-1);i++) { temp = pData->szCharData[i]; pData->curNewCar.szIconFace[i] = temp; diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index 73b379c0..e4182839 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -1218,6 +1218,12 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir, return( 0 ); } + // Bob: if gridNo isn't set, this would cause a access violation later on + if (pSoldier->sGridNo < 0) { + // ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"DistanceVisible(): Caught bad LOS distance check!"); + return(0); + } + // anv: some places in vehicle don't give passenger any view outside INT8 bSeatIndex = GetSeatIndexFromSoldier( pSoldier ); if( bSeatIndex != (-1) ) diff --git a/Tactical/soldier profile type.h b/Tactical/soldier profile type.h index 815e88af..8c2b2307 100644 --- a/Tactical/soldier profile type.h +++ b/Tactical/soldier profile type.h @@ -453,6 +453,9 @@ public: }; // RECORDS ////////////////////////////////////////////////////////////////////////////// +#define mNameLength 80 +#define mGearKitNameLength 80 + // CHRISL: Class to handle profile equipment from XML_MercStartingGear class MERCPROFILEGEAR { public: @@ -472,8 +475,8 @@ public: UINT16 mIndex; INT16 PriceModifier; INT16 AbsolutePrice; - CHAR16 mGearKitName[80]; - CHAR8 mName[80]; + CHAR16 mGearKitName[mGearKitNameLength]; + CHAR8 mName[mNameLength]; char endOfPOD; // marker for end of POD (plain old data) std::vector inv; std::vector iStatus; diff --git a/TacticalAI/NPC.cpp b/TacticalAI/NPC.cpp index 574bbe33..0dbb0367 100644 --- a/TacticalAI/NPC.cpp +++ b/TacticalAI/NPC.cpp @@ -258,7 +258,7 @@ NPCQuoteInfo * LoadQuoteFile( UINT8 ubNPC ) //new profiles by Jazz else if ( gProfilesIMP[ubNPC].ProfilId == ubNPC || gProfilesAIM[ubNPC].ProfilId == ubNPC || gProfilesMERC[ubNPC].ProfilId == ubNPC || ( gProfilesRPC[ubNPC].ProfilId == ubNPC && gMercProfiles[ ubNPC ].ubMiscFlags & PROFILE_MISC_FLAG_RECRUITED ) ) { - sprintf( zFileName, "NPCData\\000.npc", ubNPC ); // FIXME: extra/unused argument + sprintf( zFileName, "NPCData\\000.npc" ); } else { diff --git a/TileEngine/Buildings.cpp b/TileEngine/Buildings.cpp index f54509c8..c300e1ec 100644 --- a/TileEngine/Buildings.cpp +++ b/TileEngine/Buildings.cpp @@ -254,7 +254,7 @@ INT32 FindClosestClimbPoint( SOLDIERTYPE *pSoldier, INT32 sStartGridNo, INT32 sD BUILDING * CreateNewBuilding( UINT8 * pubBuilding ) { - if (gubNumberOfBuildings >= MAX_BUILDINGS) + if (gubNumberOfBuildings >= MAX_BUILDINGS-1) { return( NULL ); } diff --git a/TileEngine/tiledef.cpp b/TileEngine/tiledef.cpp index 1d51d327..ba8f722e 100644 --- a/TileEngine/tiledef.cpp +++ b/TileEngine/tiledef.cpp @@ -759,12 +759,11 @@ void CreateTileDatabase( INT32 iTilesetID ) } */ + Assert(gusNumAnimatedTiles < MAX_ANIMATED_TILES); // set into animation controller array gusAnimatedTiles[ gusNumAnimatedTiles ] = gTileDatabaseSize; - gusNumAnimatedTiles++; - - Assert( gusNumAnimatedTiles <= MAX_ANIMATED_TILES ); + gusNumAnimatedTiles++; TileElement.uiFlags |= ANIMATED_TILE; } diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 2317a521..d825d362 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -4323,7 +4323,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"合并堆叠同类的物品", // HEADROCK HAM 5: Stack and Merge L"|鼠|标|左|击: 将子弹分类装入弹箱 \n|鼠|标|右|击: 将子弹分类装入纸盒 ", //L"|L|e|f|t |C|l|i|c|k: 将子弹分类装入弹箱\n|R|i|g|h|t |C|l|i|c|k: 将子弹分类装入纸盒", HEADROCK HAM 5: Sort ammo // 6 - 10 - L"移除所有物品的附件", // HEADROCK HAM 5: Separate Attachments + L"|鼠|标|左|击: 移除所有物品的附件\n|鼠|标|右|击: empty LBE in sector", // HEADROCK HAM 5: Separate Attachments L"退出所有武器的子弹", //HEADROCK HAM 5: Eject Ammo L"|鼠|标|左|击: 显示全部物品 \n|鼠|标|右|击: 隐藏全部物品 ", // HEADROCK HAM 5: Filter Button L"|鼠|标|左|击: 切换显示武器 \n|鼠|标|右|击: 只显示武器 ", // HEADROCK HAM 5: Filter Button @@ -8637,6 +8637,13 @@ STR16 gzMapInventorySortingMessage[] = L"已完成 移除所有物品上的附件 在区域 %c%d.", L"已完成 退出所有武器里的子弹 在区域 %c%d.", L"已完成 合并后堆叠了所有物品 在区域 %c%d.", + // Bob: new strings for emptying LBE items + L"Finished emptying LBE items in sector %c%d.", + L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s + L"No droppable items in %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"%s is now empty.", // LBE item %s contained stuff and was emptied + L"Cannot empty %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"%s contents lost!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index fb2d2197..c213c7ef 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -4328,7 +4328,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"Stack and merge items", // HEADROCK HAM 5: Stack and Merge L"|L|e|f|t |C|l|i|c|k: Sort ammo into crates\n|R|i|g|h|t |C|l|i|c|k: Sort ammo into boxes", // HEADROCK HAM 5: Sort ammo // 6 - 10 - L"Remove all item attachments", // HEADROCK HAM 5: Separate Attachments + L"|L|e|f|t |C|l|i|c|k: Remove all item attachments\n|R|i|g|h|t |C|l|i|c|k: empty LBE in sector", // HEADROCK HAM 5: Separate Attachments; Bob: empty LBE items L"Eject ammo from all weapons", //HEADROCK HAM 5: Eject Ammo L"|L|e|f|t |C|l|i|c|k: Show all items\n|R|i|g|h|t |C|l|i|c|k: Hide all items", // HEADROCK HAM 5: Filter Button L"|L|e|f|t |C|l|i|c|k: Toggle Guns\n|R|i|g|h|t |C|l|i|c|k|: Show only Guns", // HEADROCK HAM 5: Filter Button @@ -8655,6 +8655,13 @@ STR16 gzMapInventorySortingMessage[] = L"Finished removing attachments from items in sector %c%d.", L"Finished ejecting ammo from weapons in sector %c%d.", L"Finished stacking and merging all items in sector %c%d.", + // Bob: new strings for emptying LBE items + L"Finished emptying LBE items in sector %c%d.", + L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s + L"No droppable items in %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"%s is now empty.", // LBE item %s contained stuff and was emptied + L"Cannot empty %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"%s contents lost!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index fe51a45f..233d3907 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -4324,7 +4324,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"Stack and merge items", // HEADROCK HAM 5: Stack and Merge L"|L|e|f|t |C|l|i|c|k: Sort ammo into crates\n|R|i|g|h|t |C|l|i|c|k: Sort ammo into boxes", // HEADROCK HAM 5: Sort ammo // 6 - 10 - L"Remove all item attachments", // HEADROCK HAM 5: Separate Attachments + L"|L|e|f|t |C|l|i|c|k: Remove all item attachments\n|R|i|g|h|t |C|l|i|c|k: empty LBE in sector", // HEADROCK HAM 5: Separate Attachments; Bob: empty LBE items L"Eject ammo from all weapons", //HEADROCK HAM 5: Eject Ammo L"|L|e|f|t |C|l|i|c|k: Show all items\n|R|i|g|h|t |C|l|i|c|k: Hide all items", // HEADROCK HAM 5: Filter Button L"|L|e|f|t |C|l|i|c|k: Toggle Guns\n|R|i|g|h|t |C|l|i|c|k|: Show only Guns", // HEADROCK HAM 5: Filter Button @@ -8638,7 +8638,14 @@ STR16 gzMapInventorySortingMessage[] = L"Finished sorting ammo into crates in sector %c%d.", L"Finished removing attachments from items in sector %c%d.", L"Finished ejecting ammo from weapons in sector %c%d.", - L"Finished stacking and merging all items in sector %c%d.", + L"Finished stacking and merging all items in sector %c%d.", + // Bob: new strings for emptying LBE items + L"Finished emptying LBE items in sector %c%d.", + L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s + L"No droppable items in %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"%s is now empty.", // LBE item %s contained stuff and was emptied + L"Cannot empty %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"%s contents lost!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 80eb7348..3fa0fce6 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -4331,7 +4331,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"Empiler les mêmes objets", // HEADROCK HAM 5: Stack and Merge L"|C|l|i|c |G|. : Trier munitions par caisse\n|C|l|i|c |D|. : Trier munitions par boîte", // HEADROCK HAM 5: Sort ammo // 6 - 10 - L"Ôter tous les accessoires des objets", // HEADROCK HAM 5: Separate Attachments + L"|C|l|i|c |G|. : Ôter tous les accessoires des objets\n|C|l|i|c |D|. : empty LBE in sector", // HEADROCK HAM 5: Separate Attachments L"Décharger toutes les armes", //HEADROCK HAM 5: Eject Ammo L"|C|l|i|c |G|. : Voir tous les objets\n|C|l|i|c |D|. : Cacher tous les objets", // HEADROCK HAM 5: Filter Button L"|C|l|i|c |G|. : Avec/sans armes\n|C|l|i|c |D|. : Voir que les armes", // HEADROCK HAM 5: Filter Button @@ -8640,6 +8640,13 @@ STR16 gzMapInventorySortingMessage[] = L"Fin du démontage de tous les accessoires au secteur %c%d.", L"Fin du déchargement des armes au secteur %c%d.", L"Fin du classement et de l'empilage par type au secteur %c%d.", + // Bob: new strings for emptying LBE items + L"Finished emptying LBE items in sector %c%d.", + L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s + L"No droppable items in %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"%s is now empty.", // LBE item %s contained stuff and was emptied + L"Cannot empty %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"%s contents lost!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 198fb903..be946c6d 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -4317,7 +4317,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"Gegenstände stapeln und verbinden", // HEADROCK HAM 5: Stack and Merge L"|L|i|n|k|e|r |K|l|i|c|k: Munition in Kisten sortieren\n|R|e|c|h|t|e|r |K|l|i|c|k: Munition in Boxen sortieren", // HEADROCK HAM 5: Sort ammo // 6 - 10 - L"Alle Gegenstandsanbauten entfernen", // HEADROCK HAM 5: Separate Attachments + L"|L|i|n|k|e|r |K|l|i|c|k: Alle Gegenstandsanbauten entfernen\n|R|e|c|h|t|e|r |K|l|i|c|k: empty LBE in sector", // HEADROCK HAM 5: Separate Attachments L"Munition aus allen Waffen entfernen", //HEADROCK HAM 5: Eject Ammo L"|L|i|n|k|e|r |K|l|i|c|k: Alle Gegenstände anzeigen\n|R|e|c|h|t|e|r |K|l|i|c|k: Alle Gegenstände ausblenden", // HEADROCK HAM 5: Filter Button L"|L|i|n|k|e|r |K|l|i|c|k: Ein-/Ausblenden von Waffen\n|R|e|c|h|t|e|r |K|l|i|c|k: Nur Waffen anzeigen", // HEADROCK HAM 5: Filter Button @@ -8470,6 +8470,13 @@ STR16 gzMapInventorySortingMessage[] = L"Das Entfernen von Gegenstandsanbauten im Sektor %c%d wurde fertiggestellt.", L"Das Entfernen von Munition der Waffen im Sektor %c%d wurde fertiggestellt.", L"Das Stapeln und Zusammenführen von Gegenständen im Sektor %c%d wurde fertiggestellt.", + // Bob: new strings for emptying LBE items + L"Finished emptying LBE items in sector %c%d.", + L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s + L"No droppable items in %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"%s is now empty.", // LBE item %s contained stuff and was emptied + L"Cannot empty %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"%s contents lost!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 50de71bb..aa47a0c5 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -4322,7 +4322,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"Stack and merge items", // HEADROCK HAM 5: Stack and Merge L"|L|e|f|t |C|l|i|c|k: Sort ammo into crates\n|R|i|g|h|t |C|l|i|c|k: Sort ammo into boxes", // HEADROCK HAM 5: Sort ammo // 6 - 10 - L"Remove all item attachments", // HEADROCK HAM 5: Separate Attachments + L"|L|e|f|t |C|l|i|c|k: Remove all item attachments\n|R|i|g|h|t |C|l|i|c|k: empty LBE in sector", // HEADROCK HAM 5: Separate Attachments; Bob: empty LBE items L"Eject ammo from all weapons", //HEADROCK HAM 5: Eject Ammo L"|L|e|f|t |C|l|i|c|k: Show all items\n|R|i|g|h|t |C|l|i|c|k: Hide all items", // HEADROCK HAM 5: Filter Button L"|L|e|f|t |C|l|i|c|k: Toggle Guns\n|R|i|g|h|t |C|l|i|c|k|: Show only Guns", // HEADROCK HAM 5: Filter Button @@ -8645,6 +8645,13 @@ STR16 gzMapInventorySortingMessage[] = L"Finished removing attachments from items in sector %c%d.", L"Finished ejecting ammo from weapons in sector %c%d.", L"Finished stacking and merging all items in sector %c%d.", + // Bob: new strings for emptying LBE items + L"Finished emptying LBE items in sector %c%d.", + L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s + L"No droppable items in %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"%s is now empty.", // LBE item %s contained stuff and was emptied + L"Cannot empty %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"%s contents lost!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index b8b69f9f..f6605213 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -4333,7 +4333,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"Stack and merge items", // HEADROCK HAM 5: Stack and Merge L"|L|e|f|t |C|l|i|c|k: Sort ammo into crates\n|R|i|g|h|t |C|l|i|c|k: Sort ammo into boxes", // HEADROCK HAM 5: Sort ammo // 6 - 10 - L"Remove all item attachments", // HEADROCK HAM 5: Separate Attachments + L"|L|e|f|t |C|l|i|c|k: Remove all item attachments\n|R|i|g|h|t |C|l|i|c|k: empty LBE in sector", // HEADROCK HAM 5: Separate Attachments; Bob: empty LBE items L"Eject ammo from all weapons", //HEADROCK HAM 5: Eject Ammo L"|L|e|f|t |C|l|i|c|k: Show all items\n|R|i|g|h|t |C|l|i|c|k: Hide all items", // HEADROCK HAM 5: Filter Button L"|L|e|f|t |C|l|i|c|k: Toggle Guns\n|R|i|g|h|t |C|l|i|c|k|: Show only Guns", // HEADROCK HAM 5: Filter Button @@ -8653,10 +8653,17 @@ STR16 gzNCTHlabels[]= // HEADROCK HAM 5: Screen messages for sector inventory sorting reports. STR16 gzMapInventorySortingMessage[] = { - L"Finished sorting ammo into crates in sector %c%d.", - L"Finished removing attachments from items in sector %c%d.", - L"Finished ejecting ammo from weapons in sector %c%d.", - L"Finished stacking and merging all items in sector %c%d.", + L"Spakowano amunicję do skrzyń w sektorze %c%d.", + L"Usunięto dodatki z przedmiotów w sektorze %c%d.", + L"Rozładowano amunicję z broni w sektorze %c%d.", + L"Poukładano i scalono przedmioty w sektorze %c%d.", + // Bob: new strings for emptying LBE items + L"Rozładowano LBE w sektorze %c%d.", + L"Wyrzucono %i przedmiot(ów) z %s", // Bunch of stuff removed from LBE item %s + L"Nie można nic wyjąć z %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"Rozładowano %s.", // LBE item %s contained stuff and was emptied + L"Nie udało się rozładować %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"Utracona zawartość %s!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index b114cfd2..3232d0b2 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -4324,7 +4324,7 @@ STR16 pMapScreenInvenButtonHelpText[] = L"Сложить и объединить предметы", // HEADROCK HAM 5: Stack and Merge L"|Л|е|в|ы|й| |щ|е|л|ч|о|к|: Собрать патроны в ящики\n|П|р|а|в|ы|й| |щ|е|л|ч|о|к|: Собрать патроны в коробки", // HEADROCK HAM 5: Sort ammo // 6 - 10 - L"Снять всю навеску \nс предметов", // HEADROCK HAM 5: Separate Attachments + L"|Л|е|в|ы|й| |щ|е|л|ч|о|к|: Снять всю навеску \nс предметов\n|П|р|а|в|ы|й| |щ|е|л|ч|о|к|: empty LBE in sector", // HEADROCK HAM 5: Separate Attachments L"Разрядить всё оружие", //HEADROCK HAM 5: Eject Ammo L"|Л|е|в|ы|й| |щ|е|л|ч|о|к|: Показать все предметы\n|П|р|а|в|ы|й| |щ|е|л|ч|о|к|: Скрыть все предметы", // HEADROCK HAM 5: Filter Button L"|Л|е|в|ы|й| |щ|е|л|ч|о|к|: Скрыть оружие\n|П|р|а|в|ы|й| |щ|е|л|ч|о|к|: Показать оружие", // HEADROCK HAM 5: Filter Button @@ -8639,6 +8639,13 @@ STR16 gzMapInventorySortingMessage[] = L"С предметов в секторе %c%d снята вся навеска.", L"В секторе %c%d всё оружие разряжено.", L"В секторе %c%d все вещи сгруппированы и объединены.", + // Bob: new strings for emptying LBE items + L"Finished emptying LBE items in sector %c%d.", + L"Dropped %i item(s) from %s", // Bunch of stuff removed from LBE item %s + L"No droppable items in %s!", // LBE item %s had a LBENode assigned but it contained no items (error!) + L"%s is now empty.", // LBE item %s contained stuff and was emptied + L"Cannot empty %s!", // Removed everything we could from LBE item %s but it's still not marked as empty (error!) + L"%s contents lost!", // LBE item %s not marked as empty but LBENode not found (error!!!) }; STR16 gzMapInventoryFilterOptions[] = diff --git a/aniviewscreen.cpp b/aniviewscreen.cpp index 44bc71f2..63ce7309 100644 --- a/aniviewscreen.cpp +++ b/aniviewscreen.cpp @@ -372,7 +372,7 @@ void BuildListFile( ) fOKFiles = TRUE; cnt = 0; - while( !feof( infoFile ) ) + while( !feof( infoFile ) && cnt < numEntries ) { fgets( currFilename, 128, infoFile ); @@ -384,9 +384,11 @@ void BuildListFile( ) if ( usState != 5555 ) { + // Bob: swapped places, there's numEntries things to be put in pusStates, I'm guessing supposed to start at 0 + pusStates[cnt] = usState; cnt++; - ubNumStates = (UINT8)cnt; - pusStates[ cnt ] = usState; + ubNumStates = (UINT8)cnt; + // pusStates[ cnt ] = usState; } else { diff --git a/ext/libpng/pngget.c b/ext/libpng/pngget.c index f3145c72..4951b02f 100644 --- a/ext/libpng/pngget.c +++ b/ext/libpng/pngget.c @@ -893,7 +893,7 @@ png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_fcTL) && width != NULL && height != NULL && - x_offset != NULL && x_offset != NULL && + x_offset != NULL && y_offset != NULL && delay_num != NULL && delay_den != NULL && dispose_op != NULL && blend_op != NULL) {