From 3c4da04532b92615475f0c10d8efc2255a2a40a5 Mon Sep 17 00:00:00 2001 From: TheBob Date: Mon, 12 Jun 2017 17:09:25 +0000 Subject: [PATCH] Cleaned up attachment removal code Fixed rare issue with squads and movement groups not being defined at game start. Fixed wrong type declarations in header files git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8407 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- .../Map Screen Interface Map Inventory.cpp | 12 +---- Strategic/Map Screen Interface Map.cpp | 10 ++-- Strategic/strategicmap.cpp | 36 ++++++++++++- Strategic/strategicmap.h | 3 ++ Tactical/Item Types.cpp | 3 -- Tactical/Items.cpp | 54 +------------------ Tactical/Soldier Create.h | 2 +- Tactical/Soldier Init List.h | 2 +- Tactical/Squads.cpp | 11 +++- TileEngine/overhead map.cpp | 6 ++- 10 files changed, 65 insertions(+), 74 deletions(-) diff --git a/Strategic/Map Screen Interface Map Inventory.cpp b/Strategic/Map Screen Interface Map Inventory.cpp index 1e574220..31b4e351 100644 --- a/Strategic/Map Screen Interface Map Inventory.cpp +++ b/Strategic/Map Screen Interface Map Inventory.cpp @@ -5108,7 +5108,7 @@ void SortSectorInventoryEmptyLBE() { void SortSectorInventorySeparateAttachments() { // attachment ref and pointer - OBJECTTYPE gTempObject; + //OBJECTTYPE gTempObject; OBJECTTYPE * gpTempObject = NULL; // current item @@ -5143,15 +5143,7 @@ void SortSectorInventorySeparateAttachments() //WarmSteel - This actually still works with NAS, be it by accident if (gpTempObject != NULL && pInventoryItem->object.RemoveAttachment(gpTempObject, pNewObj, x)) { - // 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; + gpTempObject = pNewObj; AutoPlaceObjectToWorld(pSoldier, gpTempObject, true); if (gpTempObject != NULL) diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index f9ed56d6..ece282ac 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -1754,14 +1754,18 @@ void PlotATemporaryPathForCharacter( SOLDIERTYPE *pCharacter, INT16 sX, INT16 sY return; } + // Bob: make sure we have a valid movement group + UINT8 soldierGroupId = GetSoldierGroupId(pCharacter); + if (soldierGroupId == 0) { + soldierGroupId = tryToRecoverSquadsAndMovementGroups(pCharacter); + } + // build path - pTempCharacterPath = BuildAStrategicPath( pTempCharacterPath, GetLastSectorIdInCharactersPath( pCharacter ) , ( INT16 )( sX + sY*( MAP_WORLD_X ) ), GetSoldierGroupId( pCharacter ), FALSE /*, TRUE */ ); + pTempCharacterPath = BuildAStrategicPath( pTempCharacterPath, GetLastSectorIdInCharactersPath( pCharacter ) , ( INT16 )( sX + sY*( MAP_WORLD_X ) ), soldierGroupId, FALSE /*, TRUE */ ); return; } - - // clear out character path list, after and including this sector UINT32 ClearPathAfterThisSectorForCharacter( SOLDIERTYPE *pCharacter, INT16 sX, INT16 sY ) { diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index 75596e84..5eeb93f3 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -4939,9 +4939,16 @@ BOOLEAN OKForSectorExit( INT8 bExitDirection, INT32 usAdditionalData, UINT32 *pu // ATE: Dont's assume exit grids here... if ( bExitDirection != -1 ) { + // Bob: make sure we have a valid movement group + UINT8 soldierGroupId = GetSoldierGroupId(pValidSoldier); + if (soldierGroupId == 0) { + soldierGroupId = tryToRecoverSquadsAndMovementGroups(pValidSoldier); + } + //Now, determine if this is a valid path. - pGroup = GetGroup( pValidSoldier->ubGroupID ); + pGroup = GetGroup(soldierGroupId); AssertMsg( pGroup, String( "%S is not in a valid group (pSoldier->ubGroupID is %d)", pValidSoldier->name, pValidSoldier->ubGroupID ) ); + if ( !gbWorldSectorZ ) { *puiTraverseTimeInMinutes = GetSectorMvtTimeForGroup( (UINT8)SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ), bExitDirection, pGroup ); @@ -7862,3 +7869,30 @@ BOOLEAN CanRequestMilitiaReinforcements( INT16 sMapX, INT16 sMapY, INT16 sSrcMap return FALSE; } + +// Bob: this function will check if the merc is in a valid squad and if there are other mercs assigned to that squad who lack a mvt group. +// Will attempt to fix this by assigning everyone to a proper squad and forcing squads to reevaluate movement groups. +// returns the movement group the character was reassigned to or zero if we failed. +UINT8 tryToRecoverSquadsAndMovementGroups(SOLDIERTYPE* pCharacter) { + // check if the char we're trying to move is in a valid squad! + if (SquadCharacterIsIn(pCharacter) == -1) { + + if (pCharacter->bAssignment < ON_DUTY && SquadIsEmpty(pCharacter->bAssignment)) + { // assignment says we're in a squad but that squad is empty! + int squadWeThinkWeAreIn = pCharacter->bAssignment; + + for (int i = 0; i < MAXMERCS; i++) { + if (Menptr[i].bActive && Menptr[i].bTeam == pCharacter->bTeam && Menptr[i].bAssignment == squadWeThinkWeAreIn) + { // reassign everyone who's supposed to be in the bogus squad + AddCharacterToAnySquad(&Menptr[i]); + } + } + } + else + { // that squad seems fine, it's just the merc that got confused + AddCharacterToAnySquad(pCharacter); + } + } + CheckSquadMovementGroups(); + return GetSoldierGroupId(pCharacter); +} \ No newline at end of file diff --git a/Strategic/strategicmap.h b/Strategic/strategicmap.h index 24c706fa..c6011711 100644 --- a/Strategic/strategicmap.h +++ b/Strategic/strategicmap.h @@ -225,4 +225,7 @@ void HandleEmailBeingSentWhenEnteringSector( INT16 sMapX, INT16 sMapY, INT8 bMap // Flugente: militia movement: can we order militia reinforcements from( sSrcMapX, sSrcMapY ) to( sMapX, sMapY ) ? BOOLEAN CanRequestMilitiaReinforcements( INT16 sMapX, INT16 sMapY, INT16 sSrcMapX, INT16 sSrcMapY ); +// Bob: check and try to fix issues with squad and group assignment +UINT8 tryToRecoverSquadsAndMovementGroups(SOLDIERTYPE* pCharacter); + #endif \ No newline at end of file diff --git a/Tactical/Item Types.cpp b/Tactical/Item Types.cpp index 5ac11c28..36cc5cc7 100644 --- a/Tactical/Item Types.cpp +++ b/Tactical/Item Types.cpp @@ -1010,9 +1010,6 @@ OBJECTTYPE* StackedObjectData::GetAttachmentAtIndex(UINT8 index) if (iter != attachments.end()) { 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/Items.cpp b/Tactical/Items.cpp index 138a0697..484104a5 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -8282,11 +8282,6 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNe 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(); - } - //Compare the adress if(&(*iter) == pAttachment) { @@ -8297,14 +8292,11 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNe 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) @@ -8318,19 +8310,9 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNe } } - // 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) ) { @@ -8423,28 +8405,9 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNe 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(); - } - 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. - // (Commenting out the following two lines) - //if(pAttachment->exists() && (pAttachment->usItem == 0 || pAttachment->usItem == removedAttachment.usItem )) - // *pAttachment = removedAttachment; if (pNewObj->exists() && Item[pNewObj->usItem].grenadelauncher )//UNDER_GLAUNCHER) { @@ -8453,9 +8416,6 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNe OBJECTTYPE* pGrenade = FindAttachmentByClass( this, IC_GRENADE ); if (pGrenade->exists()) { - //ADB ubWeight has been removed, see comments in OBJECTTYPE - //pNewObj->ubWeight = CalculateObjectWeight( pNewObj ); - // we might have to do it in this order, because if we attach first, // the object is pretty much gone and RemoveAttachment won't work (returns right away) OBJECTTYPE tmp; @@ -8464,23 +8424,11 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE * pAttachment, OBJECTTYPE * pNe } } - // 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/Soldier Create.h b/Tactical/Soldier Create.h index d92bbcf1..3a569629 100644 --- a/Tactical/Soldier Create.h +++ b/Tactical/Soldier Create.h @@ -273,7 +273,7 @@ public: void initialize(); BOOLEAN Load(HWFILE hFile, int versionToLoad, bool loadChecksum); - BOOLEAN Load(INT8 **hBuffer, float dMajorMapVersion, UINT8 ubMinorMapVersion); + BOOLEAN Load(INT8 **hBuffer, FLOAT dMajorMapVersion, UINT8 ubMinorMapVersion); BOOLEAN Save(HWFILE hFile, bool fSavingMap, FLOAT dMajorMapVersion=MAJOR_MAP_VERSION, UINT8 ubMinorMapVersion=MINOR_MAP_VERSION);//dnl ch42 250909 public: diff --git a/Tactical/Soldier Init List.h b/Tactical/Soldier Init List.h index 81a9fb11..832a9816 100644 --- a/Tactical/Soldier Init List.h +++ b/Tactical/Soldier Init List.h @@ -21,7 +21,7 @@ extern SOLDIERINITNODE *gSoldierInitTail; //These serialization functions are assuming the passing of a valid file //pointer to the beginning of the save/load area, at the correct part of the //map file. -BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer, float dMajorMapVersion, UINT8 ubMinorMapVersion ); +BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer, FLOAT dMajorMapVersion, UINT8 ubMinorMapVersion ); BOOLEAN SaveSoldiersToMap(HWFILE fp, FLOAT dMajorMapVersion, UINT8 ubMinorMapVersion);//dnl ch33 150909 //For the purpose of keeping track of which soldier belongs to which placement within the game, diff --git a/Tactical/Squads.cpp b/Tactical/Squads.cpp index 29199c9b..bf462d6a 100644 --- a/Tactical/Squads.cpp +++ b/Tactical/Squads.cpp @@ -1655,7 +1655,8 @@ BOOLEAN DoesVehicleExistInSquad( INT8 bSquadValue ) void CheckSquadMovementGroups( void ) { - INT32 iSquad; + INT32 iSquad; + INT8 iSoldier; GROUP * pGroup; for( iSquad = 0; iSquad < NUMBER_OF_SQUADS; iSquad++ ) @@ -1671,5 +1672,13 @@ void CheckSquadMovementGroups( void ) Assert( pGroup ); pGroup->fPersistant = TRUE; } + + // Bob: propagate the group id to the squad members + for (INT8 iSoldier = 0; iSoldier < NUMBER_OF_SOLDIERS_PER_SQUAD; iSoldier++) { + if (Squad[iSquad][iSoldier] != NULL) + { + Squad[iSquad][iSoldier]->ubGroupID = pGroup->ubGroupID; + } + } } } diff --git a/TileEngine/overhead map.cpp b/TileEngine/overhead map.cpp index 3ee7b0f3..735087a5 100644 --- a/TileEngine/overhead map.cpp +++ b/TileEngine/overhead map.cpp @@ -2038,7 +2038,11 @@ BOOLEAN GetOverheadMouseGridNo( INT32 *psGridNo ) GetFromAbsoluteScreenXYWorldXY( (INT32 *)&uiCellX, (INT32 *)&uiCellY, sWorldScreenX, sWorldScreenY ); // Get gridNo - (*psGridNo ) = MAPROWCOLTOPOS( ( uiCellY / CELL_Y_SIZE ), ( uiCellX / CELL_X_SIZE ) ); + (*psGridNo) = MAPROWCOLTOPOS( ( uiCellY / CELL_Y_SIZE ), ( uiCellX / CELL_X_SIZE ) ); + + if ((*psGridNo) == -1) { + return(FALSE); + } // Adjust for height..... sWorldScreenY = sWorldScreenY + gpWorldLevelData[ (*psGridNo) ].sHeight;