From 3fdecfbcf41824d4ebca5eb9821d1606af76f14b Mon Sep 17 00:00:00 2001 From: Flugente Date: Mon, 17 Sep 2012 20:42:38 +0000 Subject: [PATCH] - fixed an error that could cause clothes to spwan that were not worn - upon shooting/stabbing someone, their vest/pants will get unusable. It can be taken off, but no item will appear. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5572 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Tactical/Item Types.h | 6 ++- Tactical/Rotting Corpses.cpp | 59 ++++++++++++++++---------- Tactical/Rotting Corpses.h | 3 +- Tactical/Soldier Control.cpp | 72 +++++++++++++++++++------------- Tactical/Soldier Control.h | 6 +-- TileEngine/Explosion Control.cpp | 10 ++--- 6 files changed, 94 insertions(+), 62 deletions(-) diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index afef3f4c..f53433b4 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -805,8 +805,10 @@ extern OBJECTTYPE gTempObject; #define CORPSE_PANTS_BLUE 0x10000000 //268435456 #define CORPSE_PANTS_BEIGE 0x20000000 //536870912 -#define CORPSE_STRIPPED 0x40000000 //1073741824 -#define TRIPWIRE_ACTIVATED 0x80000000 //2147483648 // for tripwire activation (gets set and unset when activating tripwire) +#define CORPSE_NO_VEST 0x40000000 //1073741824 // corpse has no vest item (it has been either taken or been destroyed) +#define CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED 0x80000000 //2147483648 // corpse has no pants item/for tripwire activation (gets set and unset when activating tripwire) + +// Flugente TODO 2012-09-17: next time we break savegame compatibility, extend the flagmasks from UINT32 to UINT64. I didn't do it this time (see double-used flag above), as we try to minimise those breaks. But it is needed. // ---------------------------------------------------------------- // -------- added by Flugente: flags for action items -------- diff --git a/Tactical/Rotting Corpses.cpp b/Tactical/Rotting Corpses.cpp index 7154a9bb..7dd4ebe2 100644 --- a/Tactical/Rotting Corpses.cpp +++ b/Tactical/Rotting Corpses.cpp @@ -899,8 +899,11 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE #endif // if this soldier's uniform was damaged (gunfire, blade attacks, explosions) then don't allow to take the uniform. We can't stay hidden if we're covered in blood :-) - if ( pSoldier->bSoldierFlagMask &SOLDIER_DAMAGED_UNIFORM ) - Corpse.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN; + if ( pSoldier->bSoldierFlagMask & SOLDIER_DAMAGED_VEST ) + Corpse.usFlags |= ROTTING_CORPSE_NO_VEST; + + if ( pSoldier->bSoldierFlagMask & SOLDIER_DAMAGED_PANTS ) + Corpse.usFlags |= ROTTING_CORPSE_NO_PANTS; // Determine corpse type! ubType = (UINT8)gubAnimSurfaceCorpseID[ pSoldier->ubBodyType][ pSoldier->usAnimState ]; @@ -1951,7 +1954,7 @@ void GutCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel ) // Flugente: can clothes be taken off of this corpse? BOOLEAN IsValidStripCorpse( ROTTING_CORPSE *pCorpse ) { - if ( pCorpse->def.ubType == ROTTING_STAGE2 || (pCorpse->def.usFlags & ROTTING_CORPSE_CLOTHES_TAKEN) ) + if ( pCorpse->def.ubType == ROTTING_STAGE2 || ((pCorpse->def.usFlags & ROTTING_CORPSE_NO_VEST) && (pCorpse->def.usFlags & ROTTING_CORPSE_NO_PANTS)) ) return( FALSE ); return( CorpseOkToDress(pCorpse) ); @@ -1970,28 +1973,34 @@ void StripCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel ) if ( IsValidStripCorpse( pCorpse ) ) { // determine which clothes to spawn - UINT16 vestitem = 0; - if ( GetFirstClothesItemWithSpecificData(&vestitem, pCorpse->def.VestPal, "blank") ) + if ( !(pCorpse->def.usFlags & ROTTING_CORPSE_NO_VEST) ) { - CreateItem( vestitem, 100, &gTempObject ); - if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) - AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); + UINT16 vestitem = 0; + if ( GetFirstClothesItemWithSpecificData(&vestitem, pCorpse->def.VestPal, "blank") ) + { + CreateItem( vestitem, 100, &gTempObject ); + if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) + AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); } - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); - UINT16 pantsitem = 0; - if ( GetFirstClothesItemWithSpecificData(&pantsitem, "blank", pCorpse->def.PantsPal) ) + if ( !(pCorpse->def.usFlags & ROTTING_CORPSE_NO_PANTS) ) { - CreateItem( pantsitem, 100, &gTempObject ); - if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) - AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); + UINT16 pantsitem = 0; + if ( GetFirstClothesItemWithSpecificData(&pantsitem, "blank", pCorpse->def.PantsPal) ) + { + CreateItem( pantsitem, 100, &gTempObject ); + if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) ) + AddItemToPool( pSoldier->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); } - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); // we took the clothes, mark this - pCorpse->def.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN; + pCorpse->def.usFlags |= (ROTTING_CORPSE_NO_VEST|ROTTING_CORPSE_NO_PANTS); } else ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCorpseTextStr[STR_CORPSE_NO_CLOTHESFOUND] ); @@ -2038,8 +2047,11 @@ void TakeCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel ) if ( pCorpse->def.usFlags & ROTTING_CORPSE_HEAD_TAKEN ) gTempObject[0]->data.sObjectFlag |= CORPSE_NO_HEAD; - if ( pCorpse->def.usFlags & ROTTING_CORPSE_CLOTHES_TAKEN ) - gTempObject[0]->data.sObjectFlag |= CORPSE_STRIPPED; + if ( pCorpse->def.usFlags & ROTTING_CORPSE_NO_VEST ) + gTempObject[0]->data.sObjectFlag |= CORPSE_NO_VEST; + + if ( pCorpse->def.usFlags & ROTTING_CORPSE_NO_PANTS ) + gTempObject[0]->data.sObjectFlag |= CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED; #ifdef ENABLE_ZOMBIES if ( pCorpse->def.usFlags & ROTTING_CORPSE_NEVER_RISE_AGAIN ) @@ -2297,8 +2309,11 @@ BOOLEAN AddCorpseFromObject(OBJECTTYPE* pObj, INT32 sGridNo, INT8 bLevel ) if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_HEAD ) gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_HEAD_TAKEN; - if ( (*pObj)[0]->data.sObjectFlag & CORPSE_STRIPPED ) - gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_CLOTHES_TAKEN; + if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_VEST ) + gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_NO_VEST; + + if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED ) + gRottingCorpse[ iCorpseID ].def.usFlags |= ROTTING_CORPSE_NO_PANTS; #ifdef ENABLE_ZOMBIES if ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_ZOMBIE_RISE ) diff --git a/Tactical/Rotting Corpses.h b/Tactical/Rotting Corpses.h index edc66917..6a2955d4 100644 --- a/Tactical/Rotting Corpses.h +++ b/Tactical/Rotting Corpses.h @@ -92,7 +92,8 @@ enum RottingCorpseDefines // Flugente: corpses can now be gutted after they have been decapitated. Atm there is no corpse that can be both gutted and decapitated (to be done later) #define ROTTING_CORPSE_HEAD_TAKEN 0x00001000 // head has been taken off #define ROTTING_CORPSE_GUTTED 0x00002000 // corpse has been gutted -#define ROTTING_CORPSE_CLOTHES_TAKEN 0x00004000 // corpse is without clothes (atm not visually) +#define ROTTING_CORPSE_NO_VEST 0x00004000 // corpse has no vest (atm not visually) +#define ROTTING_CORPSE_NO_PANTS 0x00008000 // corpse has no vest (atm not visually) typedef struct { diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index f410c48c..646f2fef 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -6315,9 +6315,11 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD } } - // Flugente: if hit in legs or torso, blood will be on our uniform - this unifrom can't be used to disguise someone anymore - if ( ubHitLocation == AIM_SHOT_TORSO || ubHitLocation == AIM_SHOT_LEGS ) - pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_UNIFORM; + // Flugente: if hit in legs or torso, blood will be on our uniform - parts of the clothes cannot be worn anymore + if ( ubHitLocation == AIM_SHOT_TORSO ) + pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_VEST; + else if ( ubHitLocation == AIM_SHOT_LEGS ) + pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_PANTS; // IF HERE AND GUY IS DEAD, RETURN! if ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) @@ -6365,9 +6367,11 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD void SoldierGotHitExplosion( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation ) { - // Flugente: if hit in legs or torso, blood will be on our uniform - this unifrom can't be used to disguise someone anymore - if ( ubHitLocation == AIM_SHOT_TORSO || ubHitLocation == AIM_SHOT_LEGS ) - pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_UNIFORM; + // Flugente: if hit in legs or torso, blood will be on our uniform - parts of the clothes cannot be worn anymore + if ( ubHitLocation == AIM_SHOT_TORSO ) + pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_VEST; + else if ( ubHitLocation == AIM_SHOT_LEGS ) + pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_PANTS; INT32 sNewGridNo; @@ -6537,9 +6541,11 @@ void SoldierGotHitExplosion( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 void SoldierGotHitBlade( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sDamage, UINT16 bDirection, UINT16 sRange, UINT8 ubAttackerID, UINT8 ubSpecial, UINT8 ubHitLocation ) { - // Flugente: if hit in legs or torso, blood will be on our uniform - this unifrom can't be used to disguise someone anymore - if ( ubHitLocation == AIM_SHOT_TORSO || ubHitLocation == AIM_SHOT_LEGS ) - pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_UNIFORM; + // Flugente: if hit in legs or torso, blood will be on our uniform - parts of the clothes cannot be worn anymore + if ( ubHitLocation == AIM_SHOT_TORSO ) + pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_VEST; + else if ( ubHitLocation == AIM_SHOT_LEGS ) + pSoldier->bSoldierFlagMask |= SOLDIER_DAMAGED_PANTS; // IF HERE AND GUY IS DEAD, RETURN! if ( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) @@ -15086,29 +15092,37 @@ void SOLDIERTYPE::Strip() // if already not covert, take off clothes else if ( this->bSoldierFlagMask & (SOLDIER_NEW_VEST|SOLDIER_NEW_PANTS) ) { + // if having a new vest that is undamaged, take it off + if ( (this->bSoldierFlagMask & SOLDIER_NEW_VEST) && !(this->bSoldierFlagMask & SOLDIER_DAMAGED_VEST) ) + { + UINT16 vestitem = 0; + if ( GetFirstClothesItemWithSpecificData(&vestitem, this->VestPal, "blank") ) + { + CreateItem( vestitem, 100, &gTempObject ); + if ( !AutoPlaceObject( this, &gTempObject, FALSE ) ) + AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + } + + // if having new pants that are undamaged, take them off + if ( (this->bSoldierFlagMask & SOLDIER_NEW_PANTS) && !(this->bSoldierFlagMask & SOLDIER_DAMAGED_PANTS) ) + { + UINT16 pantsitem = 0; + if ( GetFirstClothesItemWithSpecificData(&pantsitem, "blank", this->PantsPal) ) + { + CreateItem( pantsitem, 100, &gTempObject ); + if ( !AutoPlaceObject( this, &gTempObject, FALSE ) ) + AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 ); + } + else + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); + } + // loose any clothes flags this->bSoldierFlagMask &= ~(SOLDIER_NEW_VEST|SOLDIER_NEW_PANTS); - UINT16 vestitem = 0; - if ( GetFirstClothesItemWithSpecificData(&vestitem, this->VestPal, "blank") ) - { - CreateItem( vestitem, 100, &gTempObject ); - if ( !AutoPlaceObject( this, &gTempObject, FALSE ) ) - AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 ); - } - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); - - UINT16 pantsitem = 0; - if ( GetFirstClothesItemWithSpecificData(&pantsitem, "blank", this->PantsPal) ) - { - CreateItem( pantsitem, 100, &gTempObject ); - if ( !AutoPlaceObject( this, &gTempObject, FALSE ) ) - AddItemToPool( this->sGridNo, &gTempObject, 1, 0, 0, -1 ); - } - else - ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CLOTHES_ITEM] ); - // show our true colours UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( this, this->usAnimState ); diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 7b9abcf3..dc7dee4c 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -348,13 +348,13 @@ enum #define SOLDIER_COVERT_CIV 0x00000004 //4 // Soldier is currently disguised as a civilian #define SOLDIER_COVERT_SOLDIER 0x00000008 //8 // Soldier is currently disguised as an enemy soldier -#define SOLDIER_DAMAGED_UNIFORM 0x00000010 //16 // Soldier's uniform is damged (and thus can't be taken off of his corpse) +#define SOLDIER_DAMAGED_VEST 0x00000010 //16 // Soldier's vest is damaged (and thus can't be taken off) #define SOLDIER_COVERT_NPC_SPECIAL 0x00000020 //32 // Special flag for NPCs when recruited (used for covert stuff) #define SOLDIER_NEW_VEST 0x00000040 //64 // Soldier is wearing new vest. if having both vest and pants, he can disguise #define SOLDIER_NEW_PANTS 0x00000080 //128 // Soldier is wearing new pants -/*#define WH40K_ROSARIUS 0x00000100 //256 -#define WH40K_SEAL 0x00000200 //512 +#define SOLDIER_DAMAGED_PANTS 0x00000100 //256 // Soldier's vest is damaged (and thus can't be taken off) +/*#define WH40K_SEAL 0x00000200 //512 #define WH40K_POWER_WEAPON 0x00000400 //1024 #define ENEMY_NET_4_LVL_3 0x00000800 //2048 diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 4c730948..b4ae2540 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -3690,7 +3690,7 @@ BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel, UIN if ( Item[usBombItem].tripwire == 1 ) { // this is important - we have to check wether the wire has already been activated - if ( ( (*pObj)[0]->data.sObjectFlag & TRIPWIRE_ACTIVATED ) == 0 ) + if ( ( (*pObj)[0]->data.sObjectFlag & CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED ) == 0 ) { // determine this tripwire's flag UINT32 ubWireNetworkFlag = (*pObj)[0]->data.ubWireNetworkFlag; @@ -3740,7 +3740,7 @@ BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel, UIN // Flugente hack: the tripwire will get removed in HandleExplosionQueue (it is still needed in there until the bomb gets called). // Because of this, ActivateSurroundingTripwire would normally find this wire again, thus a loop would occur. // So we mark the wire with this flag - (*pObj)[0]->data.sObjectFlag |= TRIPWIRE_ACTIVATED; + (*pObj)[0]->data.sObjectFlag |= CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED; // activate surrounding tripwires, unless tripwire is too much damaged and we are unlucky.. if ( (*pObj)[0]->data.objectStatus > (INT16)Random(50) ) @@ -3910,7 +3910,7 @@ void HandleExplosionQueue( void ) } // delete the flag, otherwise wire will only work once - (newtripwireObject)[0]->data.sObjectFlag &= ~TRIPWIRE_ACTIVATED; + (newtripwireObject)[0]->data.sObjectFlag &= ~CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED; // now add a tripwire item to the floor, simulating that activating tripwire deactivates it AddItemToPool( sGridNo, &newtripwireObject, 1, ubLevel, 0, -1 ); @@ -3941,7 +3941,7 @@ void HandleExplosionQueue( void ) } // delete the flag, otherwise wire will only work once - (newtripwireObject)[0]->data.sObjectFlag &= ~TRIPWIRE_ACTIVATED; + (newtripwireObject)[0]->data.sObjectFlag &= ~CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED; // now add a tripwire item to the floor, simulating that activating tripwire deactivates it AddItemToPool( sGridNo, &newtripwireObject, 1, ubLevel, 0, -1 ); @@ -4425,7 +4425,7 @@ BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8 // Flugente hack: the tripwire will get removed in HandleExplosionQueue (it is still needed in there until the bomb gets called). // Because of this, ActivateSurroundingTripwire would normally find this wire again, thus a loop would occur. // So we mark the wire with this flag - (*pObj)[0]->data.sObjectFlag |= TRIPWIRE_ACTIVATED; + (*pObj)[0]->data.sObjectFlag |= CORPSE_NO_PANTS_AND_TRIPWIRE_ACTIVATED; // activate surrounding tripwires and tripwire-activated mines, unless tripwire is too much damaged and we are unlucky.. if ( (*pObj)[0]->data.objectStatus > (INT16)Random(50) )