From 2b599508800ac1ffd7c8a7b3998573a92535d857 Mon Sep 17 00:00:00 2001 From: SpaceViking Date: Fri, 15 Jun 2007 03:00:15 +0000 Subject: [PATCH] Update inventory arrays to be vectors. Add class for inventory. Change some structs that use inventories to classes to provide constructors, destructors, etc. Note that with this update all file operations should still be compatible with previous files. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@971 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Tactical/Air Raid.cpp | 4 +- Tactical/Enemy Soldier Save.cpp | 78 +++-- Tactical/Handle Items.cpp | 13 +- Tactical/Handle Items.h | 11 +- Tactical/Interface Items.cpp | 6 +- Tactical/Items.h | 2 + Tactical/PATHAI.cpp | 16 +- Tactical/Real Time Input.cpp | 2 + Tactical/Rotting Corpses.cpp | 8 +- Tactical/ShopKeeper Interface.cpp | 4 +- Tactical/Soldier Add.cpp | 24 +- Tactical/Soldier Control.cpp | 492 ++++++++++++++++++++++++++++++ Tactical/Soldier Control.h | 132 +++++++- Tactical/Soldier Create.cpp | 157 ++++++++-- Tactical/Soldier Create.h | 53 +++- Tactical/Soldier Init List.cpp | 19 +- Tactical/Soldier Profile.cpp | 17 +- Tactical/Turn Based Input.cpp | 3 +- Tactical/Vehicles.h | 4 +- Tactical/World Items.h | 5 +- Tactical/soldier profile type.h | 61 +++- 21 files changed, 1006 insertions(+), 105 deletions(-) diff --git a/Tactical/Air Raid.cpp b/Tactical/Air Raid.cpp index 1ca63ce9..4c2c8df5 100644 --- a/Tactical/Air Raid.cpp +++ b/Tactical/Air Raid.cpp @@ -288,7 +288,9 @@ BOOLEAN BeginAirRaid( ) gfAirRaidHasHadTurn = FALSE; gpRaidSoldier = MercPtrs[ MAX_NUM_SOLDIERS - 1 ]; - memset( gpRaidSoldier, 0, sizeof( SOLDIERTYPE ) ); + // WDS - Clean up inventory handling + //memset( gpRaidSoldier, 0, SIZEOF_SOLDIERTYPE ); + gpRaidSoldier->initialize(); gpRaidSoldier->bLevel = 0; gpRaidSoldier->bTeam = 1; gpRaidSoldier->bSide = 1; diff --git a/Tactical/Enemy Soldier Save.cpp b/Tactical/Enemy Soldier Save.cpp index feb32caa..4e59e380 100644 --- a/Tactical/Enemy Soldier Save.cpp +++ b/Tactical/Enemy Soldier Save.cpp @@ -259,14 +259,17 @@ BOOLEAN LoadEnemySoldiersFromTempFile() for( i = 0; i < slots; i++ ) { - FileRead( hfile, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ), &uiNumBytesRead ); - if( uiNumBytesRead != sizeof( SOLDIERCREATE_STRUCT ) ) + // WDS - Clean up inventory handling + FileRead( hfile, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD, &uiNumBytesRead ); + if( uiNumBytesRead != SIZEOF_SOLDIERCREATE_STRUCT_POD) { #ifdef JA2TESTVERSION sprintf( zReason, "EnemySoldier -- EOF while reading tempDetailedPlacment %d. KM", i ); #endif goto FAIL_LOAD; } + tempDetailedPlacement.CopyOldInventoryToNew(); + curr = gSoldierInitHead; while( curr ) { @@ -279,10 +282,11 @@ BOOLEAN LoadEnemySoldiersFromTempFile() curr->pBasicPlacement->fPriorityExistance = TRUE; if( !curr->pDetailedPlacement ) { //need to upgrade the placement to detailed placement - curr->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); + curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT ); } //now replace the map pristine placement info with the temp map file version.. - memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ) ); + //memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT ); + *curr->pDetailedPlacement = tempDetailedPlacement; curr->pBasicPlacement->fPriorityExistance = TRUE; curr->pBasicPlacement->bDirection = curr->pDetailedPlacement->bDirection; @@ -470,8 +474,10 @@ BOOLEAN SaveEnemySoldiersToTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSecto if( !curr->pDetailedPlacement ) { //need to upgrade the placement to detailed placement curr->pBasicPlacement->fDetailedPlacement = TRUE; - curr->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); - memset( curr->pDetailedPlacement, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT ); + //memset( curr->pDetailedPlacement, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + curr->pDetailedPlacement->initialize(); } //Copy over the data of the soldier. @@ -542,7 +548,9 @@ BOOLEAN SaveEnemySoldiersToTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSecto sprintf( curr->pDetailedPlacement->MiscPal, pSoldier->MiscPal ); //copy soldier's inventory - memcpy( curr->pDetailedPlacement->Inv, pSoldier->inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); + // WDS - Clean up inventory handling + //memcpy( curr->pDetailedPlacement->Inv, pSoldier->inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); + curr->pDetailedPlacement->Inv = pSoldier->inv; } //DONE, now increment the counter, so we know how many there are. @@ -693,8 +701,10 @@ BOOLEAN SaveEnemySoldiersToTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSecto } if( curr && curr->pSoldier == pSoldier && pSoldier->ubProfile == NO_PROFILE ) { //found a match. - FileWrite( hfile, curr->pDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ), &uiNumBytesWritten ); - if( uiNumBytesWritten != sizeof( SOLDIERCREATE_STRUCT ) ) + // WDS - Clean up inventory handling + curr->pDetailedPlacement->CopyNewInventoryToOld(); + FileWrite( hfile, curr->pDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD, &uiNumBytesWritten ); + if( uiNumBytesWritten != SIZEOF_SOLDIERCREATE_STRUCT_POD) { goto FAIL_SAVE; } @@ -979,14 +989,16 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() for( i = 0; i < slots; i++ ) { - FileRead( hfile, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ), &uiNumBytesRead ); - if( uiNumBytesRead != sizeof( SOLDIERCREATE_STRUCT ) ) + // WDS - Clean up inventory handling + FileRead( hfile, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD, &uiNumBytesRead ); + if( uiNumBytesRead != SIZEOF_SOLDIERCREATE_STRUCT_POD) { #ifdef JA2TESTVERSION sprintf( zReason, "EnemySoldier -- EOF while reading tempDetailedPlacment %d. KM", i ); #endif goto FAIL_LOAD; } + tempDetailedPlacement.CopyOldInventoryToNew(); curr = gSoldierInitHead; while( curr ) { @@ -997,10 +1009,11 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile() curr->pBasicPlacement->fPriorityExistance = TRUE; if( !curr->pDetailedPlacement ) { //need to upgrade the placement to detailed placement - curr->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); + curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; //(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT ); } //now replace the map pristine placement info with the temp map file version.. - memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ) ); + //memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT ); + *curr->pDetailedPlacement = tempDetailedPlacement; curr->pBasicPlacement->fPriorityExistance = TRUE; curr->pBasicPlacement->bDirection = curr->pDetailedPlacement->bDirection; @@ -1332,14 +1345,16 @@ BOOLEAN NewWayOfLoadingCiviliansFromTempFile() for( i = 0; i < slots; i++ ) { - FileRead( hfile, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ), &uiNumBytesRead ); - if( uiNumBytesRead != sizeof( SOLDIERCREATE_STRUCT ) ) + // WDS - Clean up inventory handling + FileRead( hfile, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD, &uiNumBytesRead ); + if( uiNumBytesRead != SIZEOF_SOLDIERCREATE_STRUCT_POD) { #ifdef JA2TESTVERSION sprintf( zReason, "Civilian -- EOF while reading tempDetailedPlacment %d. KM", i ); #endif goto FAIL_LOAD; } + tempDetailedPlacement.CopyOldInventoryToNew(); curr = gSoldierInitHead; while( curr ) { @@ -1354,10 +1369,11 @@ BOOLEAN NewWayOfLoadingCiviliansFromTempFile() if( !curr->pDetailedPlacement ) { //need to upgrade the placement to detailed placement - curr->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); + curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; } //now replace the map pristine placement info with the temp map file version.. - memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ) ); + //memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT ); + *curr->pDetailedPlacement = tempDetailedPlacement; curr->pBasicPlacement->fPriorityExistance = TRUE; curr->pBasicPlacement->bDirection = curr->pDetailedPlacement->bDirection; @@ -1565,8 +1581,10 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY if( !curr->pDetailedPlacement ) { //need to upgrade the placement to detailed placement curr->pBasicPlacement->fDetailedPlacement = TRUE; - curr->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); - memset( curr->pDetailedPlacement, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; + curr->pDetailedPlacement->initialize(); + //memset( curr->pDetailedPlacement, 0, SIZEOF_SOLDIERCREATE_STRUCT ); } //Copy over the data of the soldier. @@ -1625,7 +1643,9 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY sprintf( curr->pDetailedPlacement->MiscPal, pSoldier->MiscPal ); //copy soldier's inventory - memcpy( curr->pDetailedPlacement->Inv, pSoldier->inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); + // WDS - Clean up inventory handling + //memcpy( curr->pDetailedPlacement->Inv, pSoldier->inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); + curr->pDetailedPlacement->Inv = pSoldier->inv; } } @@ -1759,8 +1779,10 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY if( curr && curr->pSoldier == pSoldier && pSoldier->ubProfile == NO_PROFILE ) { //found a match. - FileWrite( hfile, curr->pDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ), &uiNumBytesWritten ); - if( uiNumBytesWritten != sizeof( SOLDIERCREATE_STRUCT ) ) + // WDS - Clean up inventory handling + curr->pDetailedPlacement->CopyNewInventoryToOld(); + FileWrite( hfile, curr->pDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD, &uiNumBytesWritten ); + if( uiNumBytesWritten != SIZEOF_SOLDIERCREATE_STRUCT_POD ) { goto FAIL_SAVE; } @@ -1996,14 +2018,16 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( for( i = 0; i < slots; i++ ) { - FileRead( hfile, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ), &uiNumBytesRead ); - if( uiNumBytesRead != sizeof( SOLDIERCREATE_STRUCT ) ) + // WDS - Clean up inventory handling + FileRead( hfile, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD, &uiNumBytesRead ); + if( uiNumBytesRead != SIZEOF_SOLDIERCREATE_STRUCT_POD) { #ifdef JA2TESTVERSION sprintf( zReason, "Check EnemySoldier -- EOF while reading tempDetailedPlacment %d. KM", i ); #endif goto FAIL_LOAD; } + tempDetailedPlacement.CopyOldInventoryToNew(); //increment the current type of soldier switch( tempDetailedPlacement.ubSoldierClass ) @@ -2038,13 +2062,15 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( { if( curr->pBasicPlacement->bTeam == tempDetailedPlacement.bTeam ) { + // WDS - Clean up inventory handling curr->pBasicPlacement->fPriorityExistance = TRUE; if( !curr->pDetailedPlacement ) { //need to upgrade the placement to detailed placement - curr->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); + curr->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT; } //now replace the map pristine placement info with the temp map file version.. - memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ) ); +// memcpy( curr->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT ); + *curr->pDetailedPlacement = tempDetailedPlacement; curr->pBasicPlacement->fPriorityExistance = TRUE; curr->pBasicPlacement->bDirection = curr->pDetailedPlacement->bDirection; diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index a374fba4..2e5cacc3 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -5243,7 +5243,9 @@ INT16 FindNearestAvailableGridNoForItem( INT16 sSweetGridNo, INT8 ubRadius ) //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + // WDS - Clean up inventory handling + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; @@ -5359,7 +5361,8 @@ UINT8 StealItems(SOLDIERTYPE* pSoldier,SOLDIERTYPE* pOpponent, UINT8* ubIndexRet { fStealItem = FALSE; - pObject=pOpponent->inv+i; + // WDS - Clean up inventory handling + pObject=&pOpponent->inv[i]; if (pObject->usItem!=0) { // Is the enemy collapsed @@ -5473,8 +5476,10 @@ void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, cnt++; if ( fPickup ) { + // WDS - Clean up inventory handling // Make copy of item - memcpy( &Object, pOpponent->inv+pTempItemPool->iItemIndex, sizeof( OBJECTTYPE ) ); +// memcpy( &Object, pOpponent->inv+pTempItemPool->iItemIndex, sizeof( OBJECTTYPE ) ); + Object = pOpponent->inv[pTempItemPool->iItemIndex]; if ( ItemIsCool( &Object ) ) { fShouldSayCoolQuote = TRUE; @@ -5483,7 +5488,7 @@ void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, { AddItemToPool( pSoldier->sGridNo, &Object, 1, pSoldier->bLevel, 0, -1 ); } - DeleteObj(pOpponent->inv+pTempItemPool->iItemIndex); + DeleteObj(&pOpponent->inv[pTempItemPool->iItemIndex]); } pTempItemPool = pTempItemPool->pNext; } diff --git a/Tactical/Handle Items.h b/Tactical/Handle Items.h index 29a24551..2846b314 100644 --- a/Tactical/Handle Items.h +++ b/Tactical/Handle Items.h @@ -1,9 +1,9 @@ #ifndef __HANDLE_ITEMS_H #define __HANDLE_ITEMS_H -#include "Soldier Control.h" #include "World Items.h" #include "structure.h" +#include "Soldier Control.h" #define ITEM_HANDLE_OK 1 #define ITEM_HANDLE_RELOADING -1 @@ -46,6 +46,10 @@ typedef void ( *ITEM_POOL_LOCATOR_HOOK )( void ); +// WDS - Clean up inventory handling +struct WORLDITEM; +struct LEVELNODE; + typedef struct TAG_ITEM_POOL { struct TAG_ITEM_POOL *pNext; @@ -59,7 +63,7 @@ typedef struct TAG_ITEM_POOL UINT8 ubLevel; UINT16 usFlags; INT8 bRenderZHeightAboveLevel; - struct TAG_level_node *pLevelNode; + LEVELNODE *pLevelNode; } ITEM_POOL; @@ -76,7 +80,8 @@ typedef struct } ITEM_POOL_LOCATOR; - +// WDS - Clean up inventory handling +class SOLDIERTYPE; INT32 HandleItem( SOLDIERTYPE *pSoldier, UINT16 usGridNo, INT8 bLevel, UINT16 usHandItem, BOOLEAN fFromUI ); void SoldierPickupItem( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT16 sGridNo, INT8 bZLevel ); void HandleSoldierPickupItem( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT16 sGridNo, INT8 bZLevel ); diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index 44b7b009..ef760831 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -6502,7 +6502,8 @@ void SetupPickupPage( INT8 bPage ) { gItemPickupMenu.ItemPoolSlots[ cnt - iStart ] = pTempItemPool; - pObject = (gfStealing)? gpOpponent->inv+pTempItemPool->iItemIndex + // WDS - Clean up inventory handling + pObject = (gfStealing)? &gpOpponent->inv[pTempItemPool->iItemIndex] :&(gWorldItems[ pTempItemPool->iItemIndex ].o ); sValue = pObject->bStatus[ 0 ]; @@ -6679,7 +6680,8 @@ void RenderItemPickupMenu( ) if ( gItemPickupMenu.ItemPoolSlots[ cnt ] != NULL ) { // Get item to render - pObject = (gfStealing)? gpOpponent->inv+ gItemPickupMenu.ItemPoolSlots[ cnt ]->iItemIndex + // WDS - Clean up inventory handling + pObject = (gfStealing)? &gpOpponent->inv[gItemPickupMenu.ItemPoolSlots[ cnt ]->iItemIndex] :&(gWorldItems[ gItemPickupMenu.ItemPoolSlots[ cnt ]->iItemIndex ].o ); pItem = &( Item[ pObject->usItem ] ); diff --git a/Tactical/Items.h b/Tactical/Items.h index 799d7cb8..15dcaf20 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -12,6 +12,8 @@ extern UINT8 SlotToPocket[7]; +// WDS - Clean up inventory handling +class SOLDIERTYPE; extern BOOLEAN WeaponInHand( SOLDIERTYPE * pSoldier ); extern INT8 FindObj( SOLDIERTYPE * pSoldier, UINT16 usItem ); diff --git a/Tactical/PATHAI.cpp b/Tactical/PATHAI.cpp index c56c163b..dc0e0a45 100644 --- a/Tactical/PATHAI.cpp +++ b/Tactical/PATHAI.cpp @@ -2050,7 +2050,9 @@ void GlobalReachableTest( INT16 sStartGridNo ) SOLDIERTYPE s; INT32 iCurrentGridNo =0; - memset( &s, 0, sizeof( SOLDIERTYPE ) ); + // WDS - Clean up inventory handling + //memset( &s, 0, SIZEOF_SOLDIERTYPE ); + s.initialize(); s.sGridNo = sStartGridNo; s.bLevel = 0; s.bTeam = 1; @@ -2072,7 +2074,9 @@ void LocalReachableTest( INT16 sStartGridNo, INT8 bRadius ) INT32 iCurrentGridNo = 0; INT32 iX, iY; - memset( &s, 0, sizeof( SOLDIERTYPE ) ); + // WDS - Clean up inventory handling + //memset( &s, 0, SIZEOF_SOLDIERTYPE ); + s.initialize(); s.sGridNo = sStartGridNo; //if we are moving on the gorund level @@ -2113,7 +2117,9 @@ void GlobalItemsReachableTest( INT16 sStartGridNo1, INT16 sStartGridNo2 ) SOLDIERTYPE s; INT32 iCurrentGridNo =0; - memset( &s, 0, sizeof( SOLDIERTYPE ) ); + // WDS - Clean up inventory handling + //memset( &s, 0, SIZEOF_SOLDIERTYPE ); + s.initialize(); s.sGridNo = sStartGridNo1; s.bLevel = 0; s.bTeam = 1; @@ -2139,7 +2145,9 @@ void RoofReachableTest( INT16 sStartGridNo, UINT8 ubBuildingID ) SOLDIERTYPE s; INT16 sGridNo; - memset( &s, 0, sizeof( SOLDIERTYPE ) ); + // WDS - Clean up inventory handling + //memset( &s, 0, SIZEOF_SOLDIERTYPE ); + s.initialize(); s.sGridNo = sStartGridNo; s.bLevel = 1; s.bTeam = 1; diff --git a/Tactical/Real Time Input.cpp b/Tactical/Real Time Input.cpp index 434a0d38..79a47e48 100644 --- a/Tactical/Real Time Input.cpp +++ b/Tactical/Real Time Input.cpp @@ -62,6 +62,8 @@ #include "soldier macros.h" #include "render dirty.h" #include "Militia Control.h" +#include "render dirty.h" +#include "Militia Control.h" #endif diff --git a/Tactical/Rotting Corpses.cpp b/Tactical/Rotting Corpses.cpp index e966a6ad..e5fcfdd2 100644 --- a/Tactical/Rotting Corpses.cpp +++ b/Tactical/Rotting Corpses.cpp @@ -1068,8 +1068,10 @@ void AddCrowToCorpse( ROTTING_CORPSE *pCorpse ) return; } + // WDS - Clean up inventory handling // Put him flying over corpse pisition - memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) ); +// memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) ); + MercCreateStruct.initialize(); MercCreateStruct.ubProfile = NO_PROFILE; MercCreateStruct.sSectorX = gWorldSectorX; MercCreateStruct.sSectorY = gWorldSectorY; @@ -1612,9 +1614,11 @@ INT16 FindNearestAvailableGridNoForCorpse( ROTTING_CORPSE_DEFINITION *pDef, INT8 gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; + // WDS - Clean up inventory handling //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; diff --git a/Tactical/ShopKeeper Interface.cpp b/Tactical/ShopKeeper Interface.cpp index f6ed5ecc..057e4cf7 100644 --- a/Tactical/ShopKeeper Interface.cpp +++ b/Tactical/ShopKeeper Interface.cpp @@ -2897,12 +2897,12 @@ BOOLEAN DetermineArmsDealersSellingInventory( ) if ( ArmsDealerInfo[ gbSelectedArmsDealerID ].ubTypeOfArmsDealer == ARMS_DEALER_REPAIRS ) { // sort this list by object category, and by ascending price within each category - qsort( gpTempDealersInventory, guiNextFreeInvSlot, sizeof( INVENTORY_IN_SLOT ), RepairmanItemQsortCompare ); + qsort( (void*)gpTempDealersInventory, (size_t)guiNextFreeInvSlot, sizeof( INVENTORY_IN_SLOT ), RepairmanItemQsortCompare ); } else { // sort this list by object category, and by ascending price within each category - qsort( gpTempDealersInventory, guiNextFreeInvSlot, sizeof( INVENTORY_IN_SLOT ), ArmsDealerItemQsortCompare ); + qsort( (void*)gpTempDealersInventory, (size_t)guiNextFreeInvSlot, sizeof( INVENTORY_IN_SLOT ), ArmsDealerItemQsortCompare ); } } diff --git a/Tactical/Soldier Add.cpp b/Tactical/Soldier Add.cpp index ab57cdad..91e059a2 100644 --- a/Tactical/Soldier Add.cpp +++ b/Tactical/Soldier Add.cpp @@ -72,9 +72,11 @@ UINT16 FindGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; + // WDS - Clean up inventory handling //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bLevel = 0; soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; @@ -174,9 +176,11 @@ UINT16 FindGridNoFromSweetSpotThroughPeople( SOLDIERTYPE *pSoldier, INT16 sSweet gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; + // WDS - Clean up inventory handling //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bLevel = 0; soldier.bTeam = pSoldier->bTeam; soldier.sGridNo = sSweetGridNo; @@ -275,9 +279,11 @@ UINT16 FindGridNoFromSweetSpotWithStructData( SOLDIERTYPE *pSoldier, UINT16 usAn gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; + // WDS - Clean up inventory handling //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bLevel = 0; soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; @@ -438,9 +444,11 @@ UINT16 FindGridNoFromSweetSpotWithStructDataUsingGivenDirectionFirst( SOLDIERTYP gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; + // WDS - Clean up inventory handling //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bLevel = 0; soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; @@ -617,9 +625,11 @@ UINT16 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; + // WDS - Clean up inventory handling //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bLevel = 0; soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; @@ -948,9 +958,11 @@ UINT16 FindRandomGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, gubNPCAPBudget = 0; gubNPCDistLimit = ubRadius; + // WDS - Clean up inventory handling //create dummy soldier, and use the pathing to determine which nearby slots are //reachable. - memset( &soldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( &soldier, 0, SIZEOF_SOLDIERTYPE ); + soldier.initialize(); soldier.bLevel = 0; soldier.bTeam = 1; soldier.sGridNo = sSweetGridNo; diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index bf52190b..da6fe843 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -226,6 +226,498 @@ BATTLESNDS_STRUCT gBattleSndsData[] = "enem", 0, 1, 1, 1, 0, }; +// WDS - Clean up inventory handling +// ---------------------------------------- +// New inventory handling code. +// ---------------------------------------- + +Inventory::Inventory() { + slotCnt = NUM_INV_SLOTS; + inv.reserve(slotCnt); + for (int idx=0; idx < slotCnt; ++idx) { + OBJECTTYPE *filler = new OBJECTTYPE; // Use MEMALLOC? + inv.push_back(*filler); + } + clear(); + Assert (inv.size() == slotCnt); +}; + +Inventory::Inventory(int slotCount) { + slotCnt = slotCount; + inv.reserve(slotCnt); + for (int idx=0; idx < slotCnt; ++idx) { + OBJECTTYPE *filler = new OBJECTTYPE; // Use MEMALLOC? + inv.push_back(*filler); + } + clear(); + Assert (inv.size() == slotCnt); +}; + +Inventory::Inventory(const Inventory& src) { + inv.reserve(slotCnt); + Assert (src.inv.size() == slotCnt); + inv = src.inv; + Assert (inv.size() == slotCnt); +} + +int Inventory::size() const { + Assert (inv.size() == slotCnt); + return slotCnt; +} + + +// Assignment operator +Inventory& Inventory::operator=(const Inventory& src) +{ + // This IF is just for setting breakpoints when trying to figure out inventory item problems. Remove it later + if ((src.inv.size() != slotCnt) || + (inv.size() != slotCnt)) { + int i = 0; // Set BP here if following asserts throw + } + Assert (src.inv.size() == slotCnt); + Assert (inv.size() == slotCnt); + if (this != &src) { + if (inv.size() == 0) { + inv.reserve(slotCnt); + for (int idx=0; idx < slotCnt; ++idx) { + inv.push_back(src.inv[idx]); + } + } else { + clear(); + for (int idx=0; idx < slotCnt; ++idx) { + inv[idx] = src.inv[idx]; + } + } + } + return *this; +} + +Inventory::~Inventory() { +}; + + +OBJECTTYPE& Inventory::operator [] (int idx) { + // This IF is just from setting breakpoints when trying to figure out inventory item problems. Remove it later + if ((idx < 0) || + (idx >= slotCnt) || + (inv.size() != slotCnt)) { + int i = inv.size(); // Set BP here if following asserts throw + } + Assert(idx >= 0); + Assert(idx < slotCnt); + Assert(inv.size() == slotCnt); + return inv[idx]; +}; + +void Inventory::clear() { + Assert (inv.size() == slotCnt); + for (int idx=0; idx < slotCnt; ++idx) { + memset(&inv[idx], 0, sizeof(OBJECTTYPE)); + } +}; + +// ---------------------------------------- + +SOLDIERTYPE::SOLDIERTYPE() { + bNewItemCount.reserve(inv.size()); + bNewItemCycleCount.reserve(inv.size()); + for (int idx=0; idx < (int)inv.size(); ++idx) { + bNewItemCount.push_back(0); + bNewItemCycleCount.push_back(0); + } + initialize(); + + Assert(bNewItemCount.size() == inv.size()); + Assert(bNewItemCycleCount.size() == inv.size()); + + // The following are based on the "old" SOLDIERTYPE struct + // Remove these later + Assert(SIZEOF_SOLDIERTYPE_POD == 2344); + Assert(offsetof( SOLDIERTYPE, bFiller ) == 2305); +} + +// Copy Constructor +SOLDIERTYPE::SOLDIERTYPE(const SOLDIERTYPE& src) { + memcpy(this, &src, SIZEOF_SOLDIERTYPE_POD); + inv = src.inv; + bNewItemCount = src.bNewItemCount; + bNewItemCycleCount = src.bNewItemCycleCount; + + Assert(bNewItemCount.size() == inv.size()); + Assert(bNewItemCycleCount.size() == inv.size()); +} + +// Assignment operator +SOLDIERTYPE& SOLDIERTYPE::operator=(const SOLDIERTYPE& src) +{ + if (this != &src) { + memcpy(this, &src, SIZEOF_SOLDIERTYPE_POD); + inv = src.inv; + bNewItemCount = src.bNewItemCount; + bNewItemCycleCount = src.bNewItemCycleCount; + } + return *this; +} + +// Destructor +SOLDIERTYPE::~SOLDIERTYPE() { +} + +// Initialize the soldier. +// Use this instead of the old method of calling memset! +// Note that the constructor does this automatically. +void SOLDIERTYPE::initialize() { + memset( this, 0, SIZEOF_SOLDIERTYPE_POD); + inv.clear(); + for (int idx=0; idx < (int)inv.size(); ++idx) { + bNewItemCount[idx] = 0; + bNewItemCycleCount[idx] = 0; + } + + Assert(bNewItemCount.size() == inv.size()); + Assert(bNewItemCycleCount.size() == inv.size()); +} + + +// Ugly temporary solution +// +// These two functions map the "old" style inventory (fixed array of ) to the new (a flexibly sized vector). +// If you change names or eliminate some positions or such you need to change these. +// Eventually the need for these functions will disappear. + +void SOLDIERTYPE::CopyOldInventoryToNew() { + // Do not use a loop in case the new inventory slots are arranged differently than the old + inv[HELMETPOS] = DO_NOT_USE_Inv[OldInventory::HELMETPOS]; + inv[VESTPOS] = DO_NOT_USE_Inv[OldInventory::VESTPOS]; + inv[LEGPOS] = DO_NOT_USE_Inv[OldInventory::LEGPOS]; + inv[HEAD1POS] = DO_NOT_USE_Inv[OldInventory::HEAD1POS]; + inv[HEAD2POS] = DO_NOT_USE_Inv[OldInventory::HEAD2POS]; + inv[HANDPOS] = DO_NOT_USE_Inv[OldInventory::HANDPOS]; + inv[SECONDHANDPOS] = DO_NOT_USE_Inv[OldInventory::SECONDHANDPOS]; + inv[BIGPOCK1POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK1POS]; + inv[BIGPOCK2POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK2POS]; + inv[BIGPOCK3POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK3POS]; + inv[BIGPOCK4POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK4POS]; + inv[SMALLPOCK1POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK1POS]; + inv[SMALLPOCK2POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK2POS]; + inv[SMALLPOCK3POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK3POS]; + inv[SMALLPOCK4POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK4POS]; + inv[SMALLPOCK5POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK5POS]; + inv[SMALLPOCK6POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK6POS]; + inv[SMALLPOCK7POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK7POS]; + inv[SMALLPOCK8POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK8POS]; + + bNewItemCount[OldInventory::HELMETPOS] = DO_NOT_USE_bNewItemCount[HELMETPOS]; + bNewItemCount[OldInventory::VESTPOS] = DO_NOT_USE_bNewItemCount[VESTPOS]; + bNewItemCount[OldInventory::LEGPOS] = DO_NOT_USE_bNewItemCount[LEGPOS]; + bNewItemCount[OldInventory::HEAD1POS] = DO_NOT_USE_bNewItemCount[HEAD1POS]; + bNewItemCount[OldInventory::HEAD2POS] = DO_NOT_USE_bNewItemCount[HEAD2POS]; + bNewItemCount[OldInventory::HANDPOS] = DO_NOT_USE_bNewItemCount[HANDPOS]; + bNewItemCount[OldInventory::SECONDHANDPOS] = DO_NOT_USE_bNewItemCount[SECONDHANDPOS]; + bNewItemCount[OldInventory::BIGPOCK1POS] = DO_NOT_USE_bNewItemCount[BIGPOCK1POS]; + bNewItemCount[OldInventory::BIGPOCK2POS] = DO_NOT_USE_bNewItemCount[BIGPOCK2POS]; + bNewItemCount[OldInventory::BIGPOCK3POS] = DO_NOT_USE_bNewItemCount[BIGPOCK3POS]; + bNewItemCount[OldInventory::BIGPOCK4POS] = DO_NOT_USE_bNewItemCount[BIGPOCK4POS]; + bNewItemCount[OldInventory::SMALLPOCK1POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK1POS]; + bNewItemCount[OldInventory::SMALLPOCK2POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK2POS]; + bNewItemCount[OldInventory::SMALLPOCK3POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK3POS]; + bNewItemCount[OldInventory::SMALLPOCK4POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK4POS]; + bNewItemCount[OldInventory::SMALLPOCK5POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK5POS]; + bNewItemCount[OldInventory::SMALLPOCK6POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK6POS]; + bNewItemCount[OldInventory::SMALLPOCK7POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK7POS]; + bNewItemCount[OldInventory::SMALLPOCK8POS] = DO_NOT_USE_bNewItemCount[SMALLPOCK8POS]; + + bNewItemCycleCount[OldInventory::HELMETPOS] = DO_NOT_USE_bNewItemCycleCount[HELMETPOS]; + bNewItemCycleCount[OldInventory::VESTPOS] = DO_NOT_USE_bNewItemCycleCount[VESTPOS]; + bNewItemCycleCount[OldInventory::LEGPOS] = DO_NOT_USE_bNewItemCycleCount[LEGPOS]; + bNewItemCycleCount[OldInventory::HEAD1POS] = DO_NOT_USE_bNewItemCycleCount[HEAD1POS]; + bNewItemCycleCount[OldInventory::HEAD2POS] = DO_NOT_USE_bNewItemCycleCount[HEAD2POS]; + bNewItemCycleCount[OldInventory::HANDPOS] = DO_NOT_USE_bNewItemCycleCount[HANDPOS]; + bNewItemCycleCount[OldInventory::SECONDHANDPOS] = DO_NOT_USE_bNewItemCycleCount[SECONDHANDPOS]; + bNewItemCycleCount[OldInventory::BIGPOCK1POS] = DO_NOT_USE_bNewItemCycleCount[BIGPOCK1POS]; + bNewItemCycleCount[OldInventory::BIGPOCK2POS] = DO_NOT_USE_bNewItemCycleCount[BIGPOCK2POS]; + bNewItemCycleCount[OldInventory::BIGPOCK3POS] = DO_NOT_USE_bNewItemCycleCount[BIGPOCK3POS]; + bNewItemCycleCount[OldInventory::BIGPOCK4POS] = DO_NOT_USE_bNewItemCycleCount[BIGPOCK4POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK1POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK1POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK2POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK2POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK3POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK3POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK4POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK4POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK5POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK5POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK6POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK6POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK7POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK7POS]; + bNewItemCycleCount[OldInventory::SMALLPOCK8POS] = DO_NOT_USE_bNewItemCycleCount[SMALLPOCK8POS]; +} +void SOLDIERTYPE::CopyNewInventoryToOld() { + // Do not use a loop in case the new inventory slots are arranged differently than the old + DO_NOT_USE_Inv[OldInventory::HELMETPOS] = inv[HELMETPOS]; + DO_NOT_USE_Inv[OldInventory::VESTPOS] = inv[VESTPOS]; + DO_NOT_USE_Inv[OldInventory::LEGPOS] = inv[LEGPOS]; + DO_NOT_USE_Inv[OldInventory::HEAD1POS] = inv[HEAD1POS]; + DO_NOT_USE_Inv[OldInventory::HEAD2POS] = inv[HEAD2POS]; + DO_NOT_USE_Inv[OldInventory::HANDPOS] = inv[HANDPOS]; + DO_NOT_USE_Inv[OldInventory::SECONDHANDPOS] = inv[SECONDHANDPOS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK1POS] = inv[BIGPOCK1POS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK2POS] = inv[BIGPOCK2POS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK3POS] = inv[BIGPOCK3POS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK4POS] = inv[BIGPOCK4POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK1POS] = inv[SMALLPOCK1POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK2POS] = inv[SMALLPOCK2POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK3POS] = inv[SMALLPOCK3POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK4POS] = inv[SMALLPOCK4POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK5POS] = inv[SMALLPOCK5POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK6POS] = inv[SMALLPOCK6POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK7POS] = inv[SMALLPOCK7POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK8POS] = inv[SMALLPOCK8POS]; + + DO_NOT_USE_bNewItemCount[OldInventory::HELMETPOS] = bNewItemCount[HELMETPOS]; + DO_NOT_USE_bNewItemCount[OldInventory::VESTPOS] = bNewItemCount[VESTPOS]; + DO_NOT_USE_bNewItemCount[OldInventory::LEGPOS] = bNewItemCount[LEGPOS]; + DO_NOT_USE_bNewItemCount[OldInventory::HEAD1POS] = bNewItemCount[HEAD1POS]; + DO_NOT_USE_bNewItemCount[OldInventory::HEAD2POS] = bNewItemCount[HEAD2POS]; + DO_NOT_USE_bNewItemCount[OldInventory::HANDPOS] = bNewItemCount[HANDPOS]; + DO_NOT_USE_bNewItemCount[OldInventory::SECONDHANDPOS] = bNewItemCount[SECONDHANDPOS]; + DO_NOT_USE_bNewItemCount[OldInventory::BIGPOCK1POS] = bNewItemCount[BIGPOCK1POS]; + DO_NOT_USE_bNewItemCount[OldInventory::BIGPOCK2POS] = bNewItemCount[BIGPOCK2POS]; + DO_NOT_USE_bNewItemCount[OldInventory::BIGPOCK3POS] = bNewItemCount[BIGPOCK3POS]; + DO_NOT_USE_bNewItemCount[OldInventory::BIGPOCK4POS] = bNewItemCount[BIGPOCK4POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK1POS] = bNewItemCount[SMALLPOCK1POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK2POS] = bNewItemCount[SMALLPOCK2POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK3POS] = bNewItemCount[SMALLPOCK3POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK4POS] = bNewItemCount[SMALLPOCK4POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK5POS] = bNewItemCount[SMALLPOCK5POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK6POS] = bNewItemCount[SMALLPOCK6POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK7POS] = bNewItemCount[SMALLPOCK7POS]; + DO_NOT_USE_bNewItemCount[OldInventory::SMALLPOCK8POS] = bNewItemCount[SMALLPOCK8POS]; + + DO_NOT_USE_bNewItemCycleCount[OldInventory::HELMETPOS] = bNewItemCycleCount[HELMETPOS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::VESTPOS] = bNewItemCycleCount[VESTPOS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::LEGPOS] = bNewItemCycleCount[LEGPOS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::HEAD1POS] = bNewItemCycleCount[HEAD1POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::HEAD2POS] = bNewItemCycleCount[HEAD2POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::HANDPOS] = bNewItemCycleCount[HANDPOS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SECONDHANDPOS] = bNewItemCycleCount[SECONDHANDPOS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::BIGPOCK1POS] = bNewItemCycleCount[BIGPOCK1POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::BIGPOCK2POS] = bNewItemCycleCount[BIGPOCK2POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::BIGPOCK3POS] = bNewItemCycleCount[BIGPOCK3POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::BIGPOCK4POS] = bNewItemCycleCount[BIGPOCK4POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK1POS] = bNewItemCycleCount[SMALLPOCK1POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK2POS] = bNewItemCycleCount[SMALLPOCK2POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK3POS] = bNewItemCycleCount[SMALLPOCK3POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK4POS] = bNewItemCycleCount[SMALLPOCK4POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK5POS] = bNewItemCycleCount[SMALLPOCK5POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK6POS] = bNewItemCycleCount[SMALLPOCK6POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK7POS] = bNewItemCycleCount[SMALLPOCK7POS]; + DO_NOT_USE_bNewItemCycleCount[OldInventory::SMALLPOCK8POS] = bNewItemCycleCount[SMALLPOCK8POS]; +} + +// ---------------------------------------- + +MERCPROFILESTRUCT::MERCPROFILESTRUCT() { + inv.reserve(NUM_INV_SLOTS); + bInvStatus.reserve(NUM_INV_SLOTS); + bInvNumber.reserve(NUM_INV_SLOTS); + for (int idx=0; idx < NUM_INV_SLOTS; ++idx) { + inv.push_back(0); + bInvStatus.push_back(0); + bInvNumber.push_back(0); + } + initialize(); + + Assert(inv.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); + + // The following are based on the "old" MERCPROFILESTRUCT struct + // Remove these later + Assert(SIZEOF_MERCPROFILESTRUCT_POD == 0x2cc); //sizeof(OLD_MERCPROFILESTRUCT)); +} + +// Copy Constructor +MERCPROFILESTRUCT::MERCPROFILESTRUCT(const MERCPROFILESTRUCT& src) { + memcpy(this, &src, SIZEOF_MERCPROFILESTRUCT_POD); + inv = src.inv; + bInvStatus = src.bInvStatus; + bInvNumber = src.bInvNumber; + + Assert(inv.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); +} + +// Assignment operator +MERCPROFILESTRUCT& MERCPROFILESTRUCT::operator=(const MERCPROFILESTRUCT& src) +{ + if (this != &src) { + memcpy(this, &src, SIZEOF_MERCPROFILESTRUCT_POD); + inv = src.inv; + bInvStatus = src.bInvStatus; + bInvNumber = src.bInvNumber; + } + Assert(inv.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); + return *this; +} + +// Destructor +MERCPROFILESTRUCT::~MERCPROFILESTRUCT() { +} + +// Initialize the soldier. +// Use this instead of the old method of calling memset! +// Note that the constructor does this automatically. +void MERCPROFILESTRUCT::initialize() { + memset( this, 0, SIZEOF_MERCPROFILESTRUCT_POD); + clearInventory(); + Assert(inv.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); +} + +// Initialize the soldier. +// Use this instead of the old method of calling memset! +// Note that the constructor does this automatically. +void MERCPROFILESTRUCT::clearInventory() { + for (int idx=0; idx < (int)inv.size(); ++idx) { + inv[idx] = 0; + bInvStatus[idx] = 0; + bInvNumber[idx] = 0; + } + Assert(inv.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); + Assert(bInvStatus.size() == NUM_INV_SLOTS); +} + +// Ugly temporary solution +// +// These two functions map the "old" style inventory (fixed array of ) to the new (a flexibly sized vector). +// If you change names or eliminate some positions or such you need to change these. +// Eventually the need for these functions will disappear. + +void MERCPROFILESTRUCT::CopyOldInventoryToNew() { + // Do not use a loop in case the new inventory slots are arranged differently than the old + inv[HELMETPOS] = DO_NOT_USE_inv[OldInventory::HELMETPOS]; + inv[VESTPOS] = DO_NOT_USE_inv[OldInventory::VESTPOS]; + inv[LEGPOS] = DO_NOT_USE_inv[OldInventory::LEGPOS]; + inv[HEAD1POS] = DO_NOT_USE_inv[OldInventory::HEAD1POS]; + inv[HEAD2POS] = DO_NOT_USE_inv[OldInventory::HEAD2POS]; + inv[HANDPOS] = DO_NOT_USE_inv[OldInventory::HANDPOS]; + inv[SECONDHANDPOS] = DO_NOT_USE_inv[OldInventory::SECONDHANDPOS]; + inv[BIGPOCK1POS] = DO_NOT_USE_inv[OldInventory::BIGPOCK1POS]; + inv[BIGPOCK2POS] = DO_NOT_USE_inv[OldInventory::BIGPOCK2POS]; + inv[BIGPOCK3POS] = DO_NOT_USE_inv[OldInventory::BIGPOCK3POS]; + inv[BIGPOCK4POS] = DO_NOT_USE_inv[OldInventory::BIGPOCK4POS]; + inv[SMALLPOCK1POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK1POS]; + inv[SMALLPOCK2POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK2POS]; + inv[SMALLPOCK3POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK3POS]; + inv[SMALLPOCK4POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK4POS]; + inv[SMALLPOCK5POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK5POS]; + inv[SMALLPOCK6POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK6POS]; + inv[SMALLPOCK7POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK7POS]; + inv[SMALLPOCK8POS] = DO_NOT_USE_inv[OldInventory::SMALLPOCK8POS]; + + bInvStatus[OldInventory::HELMETPOS] = DO_NOT_USE_bInvStatus[HELMETPOS]; + bInvStatus[OldInventory::VESTPOS] = DO_NOT_USE_bInvStatus[VESTPOS]; + bInvStatus[OldInventory::LEGPOS] = DO_NOT_USE_bInvStatus[LEGPOS]; + bInvStatus[OldInventory::HEAD1POS] = DO_NOT_USE_bInvStatus[HEAD1POS]; + bInvStatus[OldInventory::HEAD2POS] = DO_NOT_USE_bInvStatus[HEAD2POS]; + bInvStatus[OldInventory::HANDPOS] = DO_NOT_USE_bInvStatus[HANDPOS]; + bInvStatus[OldInventory::SECONDHANDPOS] = DO_NOT_USE_bInvStatus[SECONDHANDPOS]; + bInvStatus[OldInventory::BIGPOCK1POS] = DO_NOT_USE_bInvStatus[BIGPOCK1POS]; + bInvStatus[OldInventory::BIGPOCK2POS] = DO_NOT_USE_bInvStatus[BIGPOCK2POS]; + bInvStatus[OldInventory::BIGPOCK3POS] = DO_NOT_USE_bInvStatus[BIGPOCK3POS]; + bInvStatus[OldInventory::BIGPOCK4POS] = DO_NOT_USE_bInvStatus[BIGPOCK4POS]; + bInvStatus[OldInventory::SMALLPOCK1POS] = DO_NOT_USE_bInvStatus[SMALLPOCK1POS]; + bInvStatus[OldInventory::SMALLPOCK2POS] = DO_NOT_USE_bInvStatus[SMALLPOCK2POS]; + bInvStatus[OldInventory::SMALLPOCK3POS] = DO_NOT_USE_bInvStatus[SMALLPOCK3POS]; + bInvStatus[OldInventory::SMALLPOCK4POS] = DO_NOT_USE_bInvStatus[SMALLPOCK4POS]; + bInvStatus[OldInventory::SMALLPOCK5POS] = DO_NOT_USE_bInvStatus[SMALLPOCK5POS]; + bInvStatus[OldInventory::SMALLPOCK6POS] = DO_NOT_USE_bInvStatus[SMALLPOCK6POS]; + bInvStatus[OldInventory::SMALLPOCK7POS] = DO_NOT_USE_bInvStatus[SMALLPOCK7POS]; + bInvStatus[OldInventory::SMALLPOCK8POS] = DO_NOT_USE_bInvStatus[SMALLPOCK8POS]; + + bInvNumber[OldInventory::HELMETPOS] = DO_NOT_USE_bInvNumber[HELMETPOS]; + bInvNumber[OldInventory::VESTPOS] = DO_NOT_USE_bInvNumber[VESTPOS]; + bInvNumber[OldInventory::LEGPOS] = DO_NOT_USE_bInvNumber[LEGPOS]; + bInvNumber[OldInventory::HEAD1POS] = DO_NOT_USE_bInvNumber[HEAD1POS]; + bInvNumber[OldInventory::HEAD2POS] = DO_NOT_USE_bInvNumber[HEAD2POS]; + bInvNumber[OldInventory::HANDPOS] = DO_NOT_USE_bInvNumber[HANDPOS]; + bInvNumber[OldInventory::SECONDHANDPOS] = DO_NOT_USE_bInvNumber[SECONDHANDPOS]; + bInvNumber[OldInventory::BIGPOCK1POS] = DO_NOT_USE_bInvNumber[BIGPOCK1POS]; + bInvNumber[OldInventory::BIGPOCK2POS] = DO_NOT_USE_bInvNumber[BIGPOCK2POS]; + bInvNumber[OldInventory::BIGPOCK3POS] = DO_NOT_USE_bInvNumber[BIGPOCK3POS]; + bInvNumber[OldInventory::BIGPOCK4POS] = DO_NOT_USE_bInvNumber[BIGPOCK4POS]; + bInvNumber[OldInventory::SMALLPOCK1POS] = DO_NOT_USE_bInvNumber[SMALLPOCK1POS]; + bInvNumber[OldInventory::SMALLPOCK2POS] = DO_NOT_USE_bInvNumber[SMALLPOCK2POS]; + bInvNumber[OldInventory::SMALLPOCK3POS] = DO_NOT_USE_bInvNumber[SMALLPOCK3POS]; + bInvNumber[OldInventory::SMALLPOCK4POS] = DO_NOT_USE_bInvNumber[SMALLPOCK4POS]; + bInvNumber[OldInventory::SMALLPOCK5POS] = DO_NOT_USE_bInvNumber[SMALLPOCK5POS]; + bInvNumber[OldInventory::SMALLPOCK6POS] = DO_NOT_USE_bInvNumber[SMALLPOCK6POS]; + bInvNumber[OldInventory::SMALLPOCK7POS] = DO_NOT_USE_bInvNumber[SMALLPOCK7POS]; + bInvNumber[OldInventory::SMALLPOCK8POS] = DO_NOT_USE_bInvNumber[SMALLPOCK8POS]; +} +void MERCPROFILESTRUCT::CopyNewInventoryToOld() { + // Do not use a loop in case the new inventory slots are arranged differently than the old + DO_NOT_USE_inv[OldInventory::HELMETPOS] = inv[HELMETPOS]; + DO_NOT_USE_inv[OldInventory::VESTPOS] = inv[VESTPOS]; + DO_NOT_USE_inv[OldInventory::LEGPOS] = inv[LEGPOS]; + DO_NOT_USE_inv[OldInventory::HEAD1POS] = inv[HEAD1POS]; + DO_NOT_USE_inv[OldInventory::HEAD2POS] = inv[HEAD2POS]; + DO_NOT_USE_inv[OldInventory::HANDPOS] = inv[HANDPOS]; + DO_NOT_USE_inv[OldInventory::SECONDHANDPOS] = inv[SECONDHANDPOS]; + DO_NOT_USE_inv[OldInventory::BIGPOCK1POS] = inv[BIGPOCK1POS]; + DO_NOT_USE_inv[OldInventory::BIGPOCK2POS] = inv[BIGPOCK2POS]; + DO_NOT_USE_inv[OldInventory::BIGPOCK3POS] = inv[BIGPOCK3POS]; + DO_NOT_USE_inv[OldInventory::BIGPOCK4POS] = inv[BIGPOCK4POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK1POS] = inv[SMALLPOCK1POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK2POS] = inv[SMALLPOCK2POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK3POS] = inv[SMALLPOCK3POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK4POS] = inv[SMALLPOCK4POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK5POS] = inv[SMALLPOCK5POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK6POS] = inv[SMALLPOCK6POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK7POS] = inv[SMALLPOCK7POS]; + DO_NOT_USE_inv[OldInventory::SMALLPOCK8POS] = inv[SMALLPOCK8POS]; + + DO_NOT_USE_bInvStatus[OldInventory::HELMETPOS] = bInvStatus[HELMETPOS]; + DO_NOT_USE_bInvStatus[OldInventory::VESTPOS] = bInvStatus[VESTPOS]; + DO_NOT_USE_bInvStatus[OldInventory::LEGPOS] = bInvStatus[LEGPOS]; + DO_NOT_USE_bInvStatus[OldInventory::HEAD1POS] = bInvStatus[HEAD1POS]; + DO_NOT_USE_bInvStatus[OldInventory::HEAD2POS] = bInvStatus[HEAD2POS]; + DO_NOT_USE_bInvStatus[OldInventory::HANDPOS] = bInvStatus[HANDPOS]; + DO_NOT_USE_bInvStatus[OldInventory::SECONDHANDPOS] = bInvStatus[SECONDHANDPOS]; + DO_NOT_USE_bInvStatus[OldInventory::BIGPOCK1POS] = bInvStatus[BIGPOCK1POS]; + DO_NOT_USE_bInvStatus[OldInventory::BIGPOCK2POS] = bInvStatus[BIGPOCK2POS]; + DO_NOT_USE_bInvStatus[OldInventory::BIGPOCK3POS] = bInvStatus[BIGPOCK3POS]; + DO_NOT_USE_bInvStatus[OldInventory::BIGPOCK4POS] = bInvStatus[BIGPOCK4POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK1POS] = bInvStatus[SMALLPOCK1POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK2POS] = bInvStatus[SMALLPOCK2POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK3POS] = bInvStatus[SMALLPOCK3POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK4POS] = bInvStatus[SMALLPOCK4POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK5POS] = bInvStatus[SMALLPOCK5POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK6POS] = bInvStatus[SMALLPOCK6POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK7POS] = bInvStatus[SMALLPOCK7POS]; + DO_NOT_USE_bInvStatus[OldInventory::SMALLPOCK8POS] = bInvStatus[SMALLPOCK8POS]; + + DO_NOT_USE_bInvNumber[OldInventory::HELMETPOS] = bInvNumber[HELMETPOS]; + DO_NOT_USE_bInvNumber[OldInventory::VESTPOS] = bInvNumber[VESTPOS]; + DO_NOT_USE_bInvNumber[OldInventory::LEGPOS] = bInvNumber[LEGPOS]; + DO_NOT_USE_bInvNumber[OldInventory::HEAD1POS] = bInvNumber[HEAD1POS]; + DO_NOT_USE_bInvNumber[OldInventory::HEAD2POS] = bInvNumber[HEAD2POS]; + DO_NOT_USE_bInvNumber[OldInventory::HANDPOS] = bInvNumber[HANDPOS]; + DO_NOT_USE_bInvNumber[OldInventory::SECONDHANDPOS] = bInvNumber[SECONDHANDPOS]; + DO_NOT_USE_bInvNumber[OldInventory::BIGPOCK1POS] = bInvNumber[BIGPOCK1POS]; + DO_NOT_USE_bInvNumber[OldInventory::BIGPOCK2POS] = bInvNumber[BIGPOCK2POS]; + DO_NOT_USE_bInvNumber[OldInventory::BIGPOCK3POS] = bInvNumber[BIGPOCK3POS]; + DO_NOT_USE_bInvNumber[OldInventory::BIGPOCK4POS] = bInvNumber[BIGPOCK4POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK1POS] = bInvNumber[SMALLPOCK1POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK2POS] = bInvNumber[SMALLPOCK2POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK3POS] = bInvNumber[SMALLPOCK3POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK4POS] = bInvNumber[SMALLPOCK4POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK5POS] = bInvNumber[SMALLPOCK5POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK6POS] = bInvNumber[SMALLPOCK6POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK7POS] = bInvNumber[SMALLPOCK7POS]; + DO_NOT_USE_bInvNumber[OldInventory::SMALLPOCK8POS] = bInvNumber[SMALLPOCK8POS]; +} BOOLEAN IsValidSecondHandShot( SOLDIERTYPE *pSoldier ); diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 6a07960e..0d8f24e3 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -11,6 +11,13 @@ #include "vobject.h" #include "Overhead Types.h" #include "Item Types.h" +#include "worlddef.h" + +// WDS - Clean up inventory handling +#include +#include + +using namespace std; // TEMP VALUES FOR NAMES @@ -274,6 +281,35 @@ enum { NUM_INV_SLOTS, }; +// WDS - Clean up inventory handling +// NOTE NOTE NOTE! Leave this alone until it is no longer needed. It must match the +// original definition so old files can be read. +namespace OldInventory { +enum { + HELMETPOS = 0, + VESTPOS, + LEGPOS, + HEAD1POS, + HEAD2POS, + HANDPOS, + SECONDHANDPOS, + BIGPOCK1POS, + BIGPOCK2POS, + BIGPOCK3POS, + BIGPOCK4POS, + SMALLPOCK1POS, + SMALLPOCK2POS, + SMALLPOCK3POS, + SMALLPOCK4POS, + SMALLPOCK5POS, + SMALLPOCK6POS, + SMALLPOCK7POS, + SMALLPOCK8POS, // = 18, so 19 pockets needed + + NUM_INV_SLOTS, +}; +}; + //used for color codes, but also shows the enemy type for debugging purposes enum { @@ -335,8 +371,66 @@ enum }; -typedef struct +// WDS - Clean up inventory handling +struct LEVELNODE; + +class Inventory { +public: + // Constructors + // Create an inventory with a fixed maximum number of slots + Inventory(); // Uses NUM_INV_SLOTS for slotCount + Inventory(int slotCount); + + // Copy Constructor + Inventory(const Inventory&); + + // Assignment operator + Inventory& operator=(const Inventory&); + + // Destructor + ~Inventory(); + + // Index operator + OBJECTTYPE& operator [] (int idx); + + // Removes all items from the inventory + void clear(); + + // How any slots are there in this inventory? + int size() const; + +private: + vector inv; + int slotCnt; +}; + +//typedef struct +class SOLDIERTYPE { +public: + // Constructor + SOLDIERTYPE(); + // Copy Constructor + SOLDIERTYPE(const SOLDIERTYPE&); + // Assignment operator + SOLDIERTYPE& operator=(const SOLDIERTYPE&); + // Destructor + ~SOLDIERTYPE(); + + // Initialize the soldier. + // Use this instead of the old method of calling memset. + // Note that the constructor does this automatically. + void initialize(); + + // Ugly temporary solution + void CopyOldInventoryToNew(); + void CopyNewInventoryToOld(); + + // Note: Place all non-POD items at the end (after endOfPOD) + // The format of this structure affects what is written into and read from various + // files (maps, save files, etc.). If you change it then that code will not work + // properly until it is all fixed and the files updated. +public: // ID UINT8 ubID; UINT8 bReserved1; @@ -348,7 +442,9 @@ typedef struct UINT32 uiStatusFlags; - OBJECTTYPE inv[ NUM_INV_SLOTS ]; +private: + OBJECTTYPE DO_NOT_USE_Inv[ OldInventory::NUM_INV_SLOTS ]; +public: OBJECTTYPE *pTempObject; KEY_ON_RING *pKeyRing; @@ -536,9 +632,9 @@ typedef struct THROW_PARAMS *pThrowParams; BOOLEAN fTurningFromPronePosition; INT8 bReverse; - struct TAG_level_node *pLevelNode; - struct TAG_level_node *pExternShadowLevelNode; - struct TAG_level_node *pRoofUILevelNode; + LEVELNODE *pLevelNode; + LEVELNODE *pExternShadowLevelNode; + LEVELNODE *pRoofUILevelNode; // WALKING STUFF INT8 bDesiredDirection; @@ -793,10 +889,12 @@ typedef struct UINT32 uiChangeMechanicalTime; UINT32 uiUniqueSoldierIdValue; // the unique value every instance of a soldier gets - 1 is the first valid value - INT8 bBeingAttackedCount; // Being attacked counter is obsolete and can be renamed and used as something else + INT8 UNUSED1; // This is unused at present and can be used for something else - INT8 bNewItemCount[ NUM_INV_SLOTS ]; - INT8 bNewItemCycleCount[ NUM_INV_SLOTS ]; +private: + INT8 DO_NOT_USE_bNewItemCount[ OldInventory::NUM_INV_SLOTS ]; + INT8 DO_NOT_USE_bNewItemCycleCount[ OldInventory::NUM_INV_SLOTS ]; +public: BOOLEAN fCheckForNewlyAddedItems; INT8 bEndDoorOpenCode; @@ -953,10 +1051,24 @@ typedef struct INT8 snowCamo; INT8 wornSnowCamo; - + UINT8 bFiller[ 36 ]; -} SOLDIERTYPE; + // + // New and OO stuff goes after here. Above this point any changes will goof up reading from files. + // + char ef1,ef2,ef3; // Extra filler to get "offsetof(endOfPOD)" to match SIZEOF(oldstruct) + + char endOfPOD; // marker for end of POD (plain old data) + + Inventory inv; + + vector bNewItemCount; + vector bNewItemCycleCount; +}; // SOLDIERTYPE; + +#define SIZEOF_SOLDIERTYPE_POD offsetof( SOLDIERTYPE, endOfPOD ) +#define SIZEOF_SOLDIERTYPE sizeof( SOLDIERTYPE ) #define HEALTH_INCREASE 0x0001 #define STRENGTH_INCREASE 0x0002 diff --git a/Tactical/Soldier Create.cpp b/Tactical/Soldier Create.cpp index 41af7145..ef68f4ee 100644 --- a/Tactical/Soldier Create.cpp +++ b/Tactical/Soldier Create.cpp @@ -65,6 +65,92 @@ #define MAX_PALACE_DISTANCE 20 +// WDS - Clean up inventory handling +SOLDIERCREATE_STRUCT::SOLDIERCREATE_STRUCT() { + initialize(); +} + +// Copy Constructor +SOLDIERCREATE_STRUCT::SOLDIERCREATE_STRUCT(const SOLDIERCREATE_STRUCT& src) { + memcpy(this, &src, SIZEOF_SOLDIERCREATE_STRUCT_POD); + this->Inv = src.Inv; +} + +// Assignment operator +SOLDIERCREATE_STRUCT& SOLDIERCREATE_STRUCT::operator=(const SOLDIERCREATE_STRUCT& src) +{ + if (this != &src) { + memcpy(this, &src, SIZEOF_SOLDIERCREATE_STRUCT_POD); + this->Inv = src.Inv; + } + return *this; +} + +// Destructor +SOLDIERCREATE_STRUCT::~SOLDIERCREATE_STRUCT() { +} + +// Initialize the soldier. +// Use this instead of the old method of calling memset! +// Note that the constructor does this automatically. +void SOLDIERCREATE_STRUCT::initialize() { + memset( this, 0, SIZEOF_SOLDIERCREATE_STRUCT_POD); + Inv.clear(); +} + + +// Ugly temporary solution +// +// These two functions map the "old" style inventory (fixed array of ) to the new (a flexibly sized vector). +// If you change names or eliminate some positions or such you need to change these. +// Eventually the need for these functions will disappear. + +void SOLDIERCREATE_STRUCT::CopyOldInventoryToNew() { + // Do not use a loop in case the new inventory slots are arranged differently than the old + Inv[HELMETPOS] = DO_NOT_USE_Inv[OldInventory::HELMETPOS]; + Inv[VESTPOS] = DO_NOT_USE_Inv[OldInventory::VESTPOS]; + Inv[LEGPOS] = DO_NOT_USE_Inv[OldInventory::LEGPOS]; + Inv[HEAD1POS] = DO_NOT_USE_Inv[OldInventory::HEAD1POS]; + Inv[HEAD2POS] = DO_NOT_USE_Inv[OldInventory::HEAD2POS]; + Inv[HANDPOS] = DO_NOT_USE_Inv[OldInventory::HANDPOS]; + Inv[SECONDHANDPOS] = DO_NOT_USE_Inv[OldInventory::SECONDHANDPOS]; + Inv[BIGPOCK1POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK1POS]; + Inv[BIGPOCK2POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK2POS]; + Inv[BIGPOCK3POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK3POS]; + Inv[BIGPOCK4POS] = DO_NOT_USE_Inv[OldInventory::BIGPOCK4POS]; + Inv[SMALLPOCK1POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK1POS]; + Inv[SMALLPOCK2POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK2POS]; + Inv[SMALLPOCK3POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK3POS]; + Inv[SMALLPOCK4POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK4POS]; + Inv[SMALLPOCK5POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK5POS]; + Inv[SMALLPOCK6POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK6POS]; + Inv[SMALLPOCK7POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK7POS]; + Inv[SMALLPOCK8POS] = DO_NOT_USE_Inv[OldInventory::SMALLPOCK8POS]; +} +void SOLDIERCREATE_STRUCT::CopyNewInventoryToOld() { + // Do not use a loop in case the new inventory slots are arranged differently than the old + DO_NOT_USE_Inv[OldInventory::HELMETPOS] = Inv[HELMETPOS]; + DO_NOT_USE_Inv[OldInventory::VESTPOS] = Inv[VESTPOS]; + DO_NOT_USE_Inv[OldInventory::LEGPOS] = Inv[LEGPOS]; + DO_NOT_USE_Inv[OldInventory::HEAD1POS] = Inv[HEAD1POS]; + DO_NOT_USE_Inv[OldInventory::HEAD2POS] = Inv[HEAD2POS]; + DO_NOT_USE_Inv[OldInventory::HANDPOS] = Inv[HANDPOS]; + DO_NOT_USE_Inv[OldInventory::SECONDHANDPOS] = Inv[SECONDHANDPOS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK1POS] = Inv[BIGPOCK1POS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK2POS] = Inv[BIGPOCK2POS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK3POS] = Inv[BIGPOCK3POS]; + DO_NOT_USE_Inv[OldInventory::BIGPOCK4POS] = Inv[BIGPOCK4POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK1POS] = Inv[SMALLPOCK1POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK2POS] = Inv[SMALLPOCK2POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK3POS] = Inv[SMALLPOCK3POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK4POS] = Inv[SMALLPOCK4POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK5POS] = Inv[SMALLPOCK5POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK6POS] = Inv[SMALLPOCK6POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK7POS] = Inv[SMALLPOCK7POS]; + DO_NOT_USE_Inv[OldInventory::SMALLPOCK8POS] = Inv[SMALLPOCK8POS]; +} + + //Private functions used within TacticalCreateStruct() void InitSoldierStruct( SOLDIERTYPE *pSoldier ); BOOLEAN TacticalCopySoldierFromProfile( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCreateStruct ); @@ -591,8 +677,10 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * if( guiCurrentScreen != AUTORESOLVE_SCREEN ) { + // WDS - Clean up inventory handling // Copy into merc struct - memcpy( MercPtrs[ Soldier.ubID ], &Soldier, sizeof( SOLDIERTYPE ) ); + //memcpy( MercPtrs[ Soldier.ubID ], &Soldier, SIZEOF_SOLDIERTYPE ); + *MercPtrs[ Soldier.ubID ] = Soldier; // Alrighty then, we are set to create the merc, stuff after here can fail! CHECKF( CreateSoldierCommon( Soldier.ubBodyType, MercPtrs[ Soldier.ubID ], Soldier.ubID, STANDING ) != FALSE ); } @@ -615,8 +703,10 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * Soldier.bNeutral = TRUE; } + // WDS - Clean up inventory handling // Copy into merc struct - memcpy( MercPtrs[ Soldier.ubID ], &Soldier, sizeof( SOLDIERTYPE ) ); + //memcpy( MercPtrs[ Soldier.ubID ], &Soldier, SIZEOF_SOLDIERTYPE ); + *MercPtrs[ Soldier.ubID ] = Soldier; // Alrighty then, we are set to create the merc, stuff after here can fail! CHECKF( CreateSoldierCommon( Soldier.ubBodyType, MercPtrs[ Soldier.ubID ], Soldier.ubID, Menptr[ Soldier.ubID ].usAnimState ) != FALSE ); @@ -660,10 +750,12 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 * SOLDIERTYPE *pSoldier; UINT8 ubSectorID; ubSectorID = GetAutoResolveSectorID(); - pSoldier = (SOLDIERTYPE*)MemAlloc( sizeof( SOLDIERTYPE ) ); + // WDS - Clean up inventory handling + pSoldier = new (MemAlloc( SIZEOF_SOLDIERTYPE )) SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE ); if( !pSoldier ) return NULL; - memcpy( pSoldier, &Soldier, sizeof( SOLDIERTYPE ) ); + //memcpy( pSoldier, &Soldier, SIZEOF_SOLDIERTYPE ); + *pSoldier = Soldier; pSoldier->ubID = 255; pSoldier->sSectorX = (INT16)SECTORX( ubSectorID ); pSoldier->sSectorY = (INT16)SECTORY( ubSectorID ); @@ -1176,8 +1268,10 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT //Generate colors for soldier based on the body type. GeneratePaletteForSoldier( pSoldier, pCreateStruct->ubSoldierClass ); + // WDS - Clean up inventory handling // Copy item info over - memcpy( pSoldier->inv, pCreateStruct->Inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); +// memcpy( pSoldier->inv, pCreateStruct->Inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); + pSoldier->inv = pCreateStruct->Inv; return( TRUE ); } @@ -1185,8 +1279,10 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT void InitSoldierStruct( SOLDIERTYPE *pSoldier ) { + // WDS - Clean up inventory handling // Memset values - memset( pSoldier, 0, sizeof( SOLDIERTYPE ) ); + //memset( pSoldier, 0, SIZEOF_SOLDIERTYPE ); + pSoldier->initialize(); // Set default values pSoldier->bVisible = -1; @@ -1743,7 +1839,9 @@ void CreateStaticDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT INT32 i; if( !spp || !bp ) return; - memset( spp, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + //memset( spp, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + spp->initialize(); spp->fStatic = TRUE; spp->ubProfile = NO_PROFILE; spp->sInsertionGridNo = bp->usStartingGridNo; @@ -1817,7 +1915,9 @@ void CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo( DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo")); - memset( pp, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + //memset( pp, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + pp->initialize(); pp->fOnRoof = spp->fOnRoof = bp->fOnRoof; pp->fStatic = FALSE; pp->ubSoldierClass = bp->ubSoldierClass; @@ -1968,8 +2068,10 @@ void UpdateSoldierWithStaticDetailedInformation( SOLDIERTYPE *s, SOLDIERCREATE_S s->ubScheduleID = spp->ubScheduleID; + // WDS - Clean up inventory handling //Copy over the current inventory list. - memcpy( s->inv, spp->Inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); +// memcpy( s->inv, spp->Inv, sizeof( OBJECTTYPE ) * NUM_INV_SLOTS ); + s->inv = spp->Inv; } //In the case of setting a profile ID in order to extract a soldier from the profile array, we @@ -2100,11 +2202,13 @@ SOLDIERTYPE* ReserveTacticalSoldierForAutoresolve( UINT8 ubSoldierClass ) //reserve this soldier MercPtrs[ i ]->sGridNo = NOWHERE; + // WDS - Clean up inventory handling //Allocate and copy the soldier - pSoldier = (SOLDIERTYPE*)MemAlloc( sizeof( SOLDIERTYPE ) ); + pSoldier = new (MemAlloc( SIZEOF_SOLDIERTYPE )) SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE ); if( !pSoldier ) return NULL; - memcpy( pSoldier, MercPtrs[ i ], sizeof( SOLDIERTYPE ) ); +// memcpy( pSoldier, MercPtrs[ i ], SIZEOF_SOLDIERTYPE ); + *pSoldier = *MercPtrs[i]; //Assign a bogus ID, then return it pSoldier->ubID = 255; @@ -2130,7 +2234,9 @@ SOLDIERTYPE* TacticalCreateAdministrator() } memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) ); - memset( &pp, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + //memset( &pp, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + pp.initialize(); RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ADMINISTRATOR ); RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ADMINISTRATOR ); bp.bTeam = ENEMY_TEAM; @@ -2164,7 +2270,9 @@ SOLDIERTYPE* TacticalCreateArmyTroop() } memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) ); - memset( &pp, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + //memset( &pp, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + pp.initialize(); RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ARMY ); RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ARMY ); bp.bTeam = ENEMY_TEAM; @@ -2199,7 +2307,9 @@ SOLDIERTYPE* TacticalCreateEliteEnemy() } memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) ); - memset( &pp, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + //memset( &pp, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + pp.initialize(); RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ELITE ); RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ELITE ); @@ -2247,11 +2357,13 @@ SOLDIERTYPE* ReserveTacticalMilitiaSoldierForAutoresolve( UINT8 ubSoldierClass ) //reserve this soldier MercPtrs[ i ]->sGridNo = NOWHERE; + // WDS - Clean up inventory handling //Allocate and copy the soldier - pSoldier = (SOLDIERTYPE*)MemAlloc( sizeof( SOLDIERTYPE ) ); + pSoldier = new (MemAlloc( SIZEOF_SOLDIERTYPE )) SOLDIERTYPE; //(SOLDIERTYPE*)MemAlloc( SIZEOF_SOLDIERTYPE ); if( !pSoldier ) return NULL; - memcpy( pSoldier, MercPtrs[ i ], sizeof( SOLDIERTYPE ) ); +// memcpy( pSoldier, MercPtrs[ i ], SIZEOF_SOLDIERTYPE ); + *pSoldier = *MercPtrs[i]; //Assign a bogus ID, then return it pSoldier->ubID = 255; @@ -2277,7 +2389,10 @@ SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass ) } memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) ); - memset( &pp, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + //memset( &pp, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + pp.initialize(); + RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), ubMilitiaClass ); RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), ubMilitiaClass ); bp.bTeam = MILITIA_TEAM; @@ -2306,7 +2421,10 @@ SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType ) } memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) ); - memset( &pp, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + // WDS - Clean up inventory handling + //memset( &pp, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + pp.initialize(); + RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_CREATURE ); RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_CREATURE ); bp.bTeam = CREATURE_TEAM; @@ -2472,7 +2590,8 @@ void CopyProfileItems( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCreateStruc { // do some special coding to put stuff in the profile in better-looking // spots - memset( pSoldier->inv, 0, NUM_INV_SLOTS * sizeof( OBJECTTYPE ) ); + // WDS - Clean up inventory handling +// memset( pSoldier->inv, 0, NUM_INV_SLOTS * sizeof( OBJECTTYPE ) ); for ( cnt = 0; cnt < NUM_INV_SLOTS; cnt++ ) { if ( pProfile->inv[ cnt ] != NOTHING ) diff --git a/Tactical/Soldier Create.h b/Tactical/Soldier Create.h index 4b8975da..4161c1d9 100644 --- a/Tactical/Soldier Create.h +++ b/Tactical/Soldier Create.h @@ -8,6 +8,12 @@ #include "Item Types.h" #include "soldier control.h" +// WDS - Clean up inventory handling +#include +#include + +using namespace std; + #define SOLDIER_CREATE_AUTO_TEAM -1 //Kris: @@ -51,8 +57,37 @@ typedef struct INT8 PADDINGSLOTS[ 14 ]; } BASIC_SOLDIERCREATE_STRUCT; //50 bytes -typedef struct +// WDS - Clean up inventory handling +//typedef struct +class SOLDIERCREATE_STRUCT { +public: + // Constructor + SOLDIERCREATE_STRUCT(); + // Copy Constructor + SOLDIERCREATE_STRUCT(const SOLDIERCREATE_STRUCT&); + // Assignment operator + SOLDIERCREATE_STRUCT& operator=(const SOLDIERCREATE_STRUCT&); + // Destructor + ~SOLDIERCREATE_STRUCT(); + + // Initialize the soldier. + // Use this instead of the old method of calling memset! + // Note that the constructor does this automatically. + void initialize(); + + // Ugly temporary solution + // + // Note! These two functions should ONLY be used either just before saving to a + // file (NewToOld) or after loading a file (OldToNew). + void CopyOldInventoryToNew(); + void CopyNewInventoryToOld(); + + // Note: Place all non-POD items at the end (after endOfPOD) + // The format of this structure affects what is written into and read from various + // files (maps, save files, etc.). If you change it then that code will not work + // properly until it is all fixed and the files updated. +public: //Bulletproofing so static detailed placements aren't used to tactically create soldiers. //Used by editor for validation purposes. BOOLEAN fStatic; @@ -93,8 +128,10 @@ typedef struct INT8 bMorale; INT8 bAIMorale; +private: //Inventory - OBJECTTYPE Inv[ NUM_INV_SLOTS ]; + OBJECTTYPE DO_NOT_USE_Inv[ OldInventory::NUM_INV_SLOTS ]; +public: //Palette information for soldiers. PaletteRepID HeadPal; @@ -130,8 +167,18 @@ typedef struct INT8 bPadding[115]; + // + // New and OO stuff goes after here. Above this point any changes will goof up reading from files. + // + char ef1,ef2; // Extra filler to get "offsetof(endOfPOD)" to match SIZEOF(oldstruct) -} SOLDIERCREATE_STRUCT; + char endOfPOD; // marker for end of POD (plain old data) + + Inventory Inv; +}; // SOLDIERCREATE_STRUCT; + +#define SIZEOF_SOLDIERCREATE_STRUCT_POD offsetof( SOLDIERCREATE_STRUCT, endOfPOD ) +#define SIZEOF_SOLDIERCREATE_STRUCT sizeof( SOLDIERCREATE_STRUCT ) //Original functions currently used throughout the game. diff --git a/Tactical/Soldier Init List.cpp b/Tactical/Soldier Init List.cpp index 437162aa..324586ec 100644 --- a/Tactical/Soldier Init List.cpp +++ b/Tactical/Soldier Init List.cpp @@ -236,8 +236,9 @@ BOOLEAN SaveSoldiersToMap( HWFILE fp ) { if( !curr->pDetailedPlacement ) return FALSE; - FileWrite( fp, curr->pDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ), &uiBytesWritten ); - + // WDS - Clean up inventory handling + curr->pDetailedPlacement->CopyNewInventoryToOld(); + FileWrite( fp, curr->pDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT_POD /*SIZEOF_SOLDIERCREATE_STRUCT*/, &uiBytesWritten ); } curr = curr->next; } @@ -293,17 +294,21 @@ BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer ) } if( tempBasicPlacement.fDetailedPlacement ) { //Add the static detailed placement information in the same newly created node as the basic placement. + // WDS - Clean up inventory handling + tempDetailedPlacement.initialize(); //read static detailed placement from file - LOADDATA( &tempDetailedPlacement, *hBuffer, sizeof( SOLDIERCREATE_STRUCT ) ); + LOADDATA( &tempDetailedPlacement, *hBuffer, SIZEOF_SOLDIERCREATE_STRUCT_POD ); + tempDetailedPlacement.CopyOldInventoryToNew(); //allocate memory for new static detailed placement - pNode->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); + pNode->pDetailedPlacement = new (MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT )) SOLDIERCREATE_STRUCT;//(SOLDIERCREATE_STRUCT*)MemAlloc( SIZEOF_SOLDIERCREATE_STRUCT ); if( !pNode->pDetailedPlacement ) { AssertMsg( 0, "Failed to allocate memory for new detailed placement in LoadSoldiersFromMap." ); return FALSE; } //copy the file information from temp var to node in list. - memcpy( pNode->pDetailedPlacement, &tempDetailedPlacement, sizeof( SOLDIERCREATE_STRUCT ) ); + //memcpy( pNode->pDetailedPlacement, &tempDetailedPlacement, SIZEOF_SOLDIERCREATE_STRUCT ); + *pNode->pDetailedPlacement = tempDetailedPlacement; if( tempDetailedPlacement.ubProfile != NO_PROFILE ) { @@ -527,8 +532,10 @@ BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *curr ) DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AddPlacementToWorld")); // First check if this guy has a profile and if so check his location such that it matches! + // WDS - Clean up inventory handling // Get profile from placement info - memset( &tempDetailedPlacement, 0, sizeof( SOLDIERCREATE_STRUCT ) ); + //memset( &tempDetailedPlacement, 0, SIZEOF_SOLDIERCREATE_STRUCT ); + tempDetailedPlacement.initialize(); DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AddPlacementToWorld: decide on placement")); if( curr->pDetailedPlacement ) diff --git a/Tactical/Soldier Profile.cpp b/Tactical/Soldier Profile.cpp index 05660ab3..4d032f5f 100644 --- a/Tactical/Soldier Profile.cpp +++ b/Tactical/Soldier Profile.cpp @@ -275,13 +275,14 @@ BOOLEAN LoadMercProfiles(void) for(uiLoop=0; uiLoop< NUM_PROFILES; uiLoop++) { - if( JA2EncryptedFileRead( fptr, &gMercProfiles[uiLoop], sizeof( MERCPROFILESTRUCT ), &uiNumBytesRead ) != 1) + // WDS - Clean up inventory handling + if( JA2EncryptedFileRead( fptr, &gMercProfiles[uiLoop], SIZEOF_MERCPROFILESTRUCT_POD, &uiNumBytesRead ) != 1) { DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("FAILED to Read Merc Profiles from File %d %s",uiLoop, pFileName) ); FileClose( fptr ); return(FALSE); } - + gMercProfiles[ uiLoop ].CopyOldInventoryToNew(); //if the Dialogue exists for the merc, allow the merc to be hired if( DialogueDataFileExistsForProfile( (UINT8)uiLoop, 0, FALSE, NULL ) ) @@ -904,8 +905,9 @@ SOLDIERTYPE *ChangeSoldierTeam( SOLDIERTYPE *pSoldier, UINT8 ubTeam ) // Remove him from the game! InternalTacticalRemoveSoldier( ubID, FALSE ); + // WDS - Clean up inventory handling // Create a new one! - memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) ); + MercCreateStruct.initialize(); MercCreateStruct.bTeam = ubTeam; MercCreateStruct.ubProfile = pSoldier->ubProfile; MercCreateStruct.bBodyType = pSoldier->ubBodyType; @@ -1463,9 +1465,10 @@ SOLDIERTYPE * SwapLarrysProfiles( SOLDIERTYPE * pSoldier ) pNewProfile->bExplosivesDelta = gMercProfiles[ ubSrcProfile ].bExplosivesDelta; */ - memcpy( pNewProfile->bInvStatus, gMercProfiles[ ubSrcProfile ].bInvStatus , sizeof( UINT8) * 19 ); - memcpy( pNewProfile->bInvNumber, gMercProfiles[ ubSrcProfile ].bInvNumber , sizeof( UINT8) * 19 ); - memcpy( pNewProfile->inv , gMercProfiles[ ubSrcProfile ].inv , sizeof( UINT16 ) * 19 ); + // WDS - Clean up inventory handling + pNewProfile->bInvStatus = gMercProfiles[ ubSrcProfile ].bInvStatus; + pNewProfile->bInvNumber = gMercProfiles[ ubSrcProfile ].bInvNumber; + pNewProfile->inv = gMercProfiles[ ubSrcProfile ].inv; memcpy( pNewProfile->bMercTownReputation , gMercProfiles[ ubSrcProfile ].bMercTownReputation , sizeof( UINT8 ) * 20 ); // remove face @@ -1551,4 +1554,4 @@ BOOLEAN IsProfileIdAnAimOrMERCMerc( UINT8 ubProfileID ) } return( FALSE ); -} \ No newline at end of file +} diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 1cd2971d..a168ae31 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -4683,7 +4683,8 @@ void CreatePlayerControlledMonster() SOLDIERCREATE_STRUCT MercCreateStruct; INT8 iNewIndex; - memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) ); + // WDS - Clean up inventory handling + MercCreateStruct.initialize(); MercCreateStruct.ubProfile = NO_PROFILE; MercCreateStruct.sSectorX = gWorldSectorX; MercCreateStruct.sSectorY = gWorldSectorY; diff --git a/Tactical/Vehicles.h b/Tactical/Vehicles.h index 0dfaa467..0a156281 100644 --- a/Tactical/Vehicles.h +++ b/Tactical/Vehicles.h @@ -49,6 +49,8 @@ enum{ extern INT16 sVehicleOrigArmorValues[ NUMBER_OF_TYPES_OF_VEHICLES][ NUMBER_OF_INTERNAL_HIT_LOCATIONS_IN_VEHICLE]; +// WDS - Clean up inventory handling +#define MAXPASSENGERS 10 // struct for vehicles typedef struct { @@ -60,7 +62,7 @@ typedef struct INT16 sSectorZ; BOOLEAN fBetweenSectors; // between sectors? INT16 sGridNo; // location in tactical - SOLDIERTYPE *pPassengers[ 10 ]; + SOLDIERTYPE *pPassengers[ MAXPASSENGERS ]; UINT8 ubDriver; INT16 sInternalHitLocations[ NUMBER_OF_EXTERNAL_HIT_LOCATIONS_ON_VEHICLE ]; INT16 sArmourType; diff --git a/Tactical/World Items.h b/Tactical/World Items.h index 5440ff92..244f7ad5 100644 --- a/Tactical/World Items.h +++ b/Tactical/World Items.h @@ -15,7 +15,8 @@ //Kaiden: This constant is to flag items that an enemy drops when they die. #define WORLD_ITEM_DROPPED_FROM_ENEMY 0x0800 -typedef struct +//typedef struct +struct WORLDITEM { BOOLEAN fExists; INT16 sGridNo; @@ -33,7 +34,7 @@ typedef struct //This check is only performed the first time a map is loaded. Later, it is entirely skipped. UINT8 ubNonExistChance; -} WORLDITEM; +}; // WORLDITEM; extern WORLDITEM *gWorldItems; extern UINT32 guiNumWorldItems; diff --git a/Tactical/soldier profile type.h b/Tactical/soldier profile type.h index c28a3fe6..9d85541b 100644 --- a/Tactical/soldier profile type.h +++ b/Tactical/soldier profile type.h @@ -2,6 +2,7 @@ #define __SOLDER_PROFILE_TYPE_H #include "overhead types.h" +#include "Soldier Control.h" #define NUM_PROFILES 170 #define FIRST_RPC 57 @@ -160,8 +161,38 @@ typedef enum{ #define BUDDY_OPINION +25 #define HATED_OPINION -25 -typedef struct -{ +// WDS - Clean up inventory handling +//typedef struct +class MERCPROFILESTRUCT { +public: + // Constructor + MERCPROFILESTRUCT(); + // Copy Constructor + MERCPROFILESTRUCT(const MERCPROFILESTRUCT&); + // Assignment operator + MERCPROFILESTRUCT& operator=(const MERCPROFILESTRUCT&); + // Destructor + ~MERCPROFILESTRUCT(); + + // Initialize the mercenary profile. + // Use this instead of the old method of calling memset. + // Note that the constructor does this automatically. + void initialize(); + + // Clear out the mercenary profile's invetory + // Use this instead of the old method of calling memset. + // Note that the constructor does this automatically. + void clearInventory(); + + // Ugly temporary solution + void CopyOldInventoryToNew(); + void CopyNewInventoryToOld(); + + // Note: Place all non-POD items at the end (after endOfPOD) + // The format of this structure affects what is written into and read from various + // files (maps, save files, etc.). If you change it then that code will not work + // properly until it is all fixed and the files updated. +public: CHAR16 zName[ NAME_LENGTH ]; CHAR16 zNickname[ NICKNAME_LENGTH ]; UINT32 uiAttnSound; @@ -268,8 +299,10 @@ typedef struct UINT8 bResigned; UINT8 bActive; - UINT8 bInvStatus[19]; - UINT8 bInvNumber[19]; +private: + UINT8 DO_NOT_USE_bInvStatus[OldInventory::NUM_INV_SLOTS]; + UINT8 DO_NOT_USE_bInvNumber[OldInventory::NUM_INV_SLOTS]; +public: UINT16 usApproachFactor[4]; INT8 bMainGunAttractiveness; @@ -282,7 +315,9 @@ typedef struct UINT8 ubInvUndroppable; UINT8 ubRoomRangeStart[2]; - UINT16 inv[19]; +private: + UINT16 DO_NOT_USE_inv[OldInventory::NUM_INV_SLOTS]; +public: INT8 bMercTownReputation[ 20 ]; UINT16 usStatChangeChances[ 12 ]; // used strictly for balancing, never shown! @@ -358,7 +393,21 @@ typedef struct UINT32 uiTotalCostToDate; // The total amount of money that has been paid to the merc for their salary UINT8 ubBuffer[4]; -} MERCPROFILESTRUCT; + + // + // New and OO stuff goes after here. Above this point any changes will goof up reading from files. + // + //char ef1; // Extra filler to get "offsetof(endOfPOD)" to match SIZEOF(oldstruct) + + char endOfPOD; // marker for end of POD (plain old data) + + vector inv; + vector bInvStatus; + vector bInvNumber; +}; // MERCPROFILESTRUCT; + +#define SIZEOF_MERCPROFILESTRUCT_POD offsetof( MERCPROFILESTRUCT, endOfPOD ) +#define SIZEOF_MERCPROFILESTRUCT sizeof( MERCPROFILESTRUCT ) #define TIME_BETWEEN_HATED_COMPLAINTS 24