diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index d7d16839..db876662 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -3422,6 +3422,11 @@ void EquipArmouredVehicle( SOLDIERCREATE_STRUCT *pp, BOOLEAN fTank ) CreateItems( MINIMI, (INT8)(80 + Random( 21 )), 1, &gTempObject ); gTempObject.fFlags |= OBJECT_UNDROPPABLE; PlaceObjectInSoldierCreateStruct( pp, &gTempObject ); + + // smoke grenade + CreateItems( SMOKE_GRENADE, (INT8)(80 + Random( 21 )), 1, &gTempObject ); + gTempObject.fFlags |= OBJECT_UNDROPPABLE; + PlaceObjectInSoldierCreateStruct( pp, &gTempObject ); } else { diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 9c9b43d5..6b6b282b 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -7604,6 +7604,9 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou // UnderFire now starts at 2 for "under fire this turn", // down to 1 for "under fire last turn", to 0. this->aiData.bUnderFire--; + + if ( !this->aiData.bUnderFire ) + this->usSoldierFlagMask2 &= ~SOLDIER_TAKEN_LARGE_HIT; } // Flugente: reset extra stats. Currently they only depend on drug effects, and those are reset every turn @@ -9888,6 +9891,9 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr } } } + + if ( sLifeDeduct > 30 ) + this->usSoldierFlagMask2 |= SOLDIER_TAKEN_LARGE_HIT; VehicleTakeDamage( this->bVehicleID, ubReason, sLifeDeduct, this->sGridNo, ubAttacker ); HandleTakeDamageDeath( this, bOldLife, ubReason ); @@ -18989,6 +18995,41 @@ FLOAT SOLDIERTYPE::GetConstructionPoints( ) return dval; } +BOOLEAN SOLDIERTYPE::HasItem(UINT16 usItem) +{ + INT8 invsize = (INT8)inv.size( ); + for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) + { + if ( inv[bLoop].exists( ) == true && inv[bLoop].usItem == usItem ) + return TRUE; + } + + return FALSE; +} + +// AI-only: heal self. Do NOT, repeat, NOT use this with mercs! +BOOLEAN SOLDIERTYPE::SelfDetonate( ) +{ + if ( !(this->flags.uiStatusFlags & SOLDIER_UNDERAICONTROL) ) + return FALSE; + + INT8 invsize = (INT8)inv.size( ); + for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) + { + if ( inv[bLoop].exists( ) == true && inv[bLoop].usItem == this->aiData.usActionData ) + { + IgniteExplosion( this->ubID, this->sX, this->sY, (INT16)(gpWorldLevelData[this->sGridNo].sHeight), this->sGridNo, inv[bLoop].usItem, this->pathing.bLevel, this->ubDirection ); + + // Remove item! + DeleteObj( &(this->inv[bLoop]) ); + + return TRUE; + } + } + + return FALSE; +} + INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) { INT8 bBandaged; //,savedOurTurn; diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 5cca015d..24ada5c0 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -411,6 +411,7 @@ enum #define SOLDIER_INTERROGATE_CIVILIAN 0x00000100 //256 // interrogate civilian #define SOLDIER_POTENTIAL_VOLUNTEER 0x00000200 //512 // this civilian _might_ join us as a volunteer if conditions are right #define SOLDIER_HUNGOVER 0x00000400 //1024 // we drank alcohol recently, and are now hungover +#define SOLDIER_TAKEN_LARGE_HIT 0x00000800 // we recently received a lot of damage in a single hit #define SOLDIER_INTERROGATE_ALL 0x000001F8 // all interrogation flags // ---------------------------------------------------------------- @@ -1918,6 +1919,10 @@ public: // Flugente: fortification FLOAT GetConstructionPoints( ); + + // Flugente: do we have a specific item in our inventory? + BOOLEAN HasItem( UINT16 usItem ); + BOOLEAN SelfDetonate(); // AI-only: blow up explosive in own inventory. Do NOT, repeat, NOT use this with mercs! ////////////////////////////////////////////////////////////////////////////// }; // SOLDIERTYPE; diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 27ec9830..2aaa19a5 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -2307,6 +2307,13 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) } break; + case AI_ACTION_SELFDETONATE: + { + pSoldier->SelfDetonate( ); + ActionDone( pSoldier ); + } + break; + default: #ifdef BETAVERSION NumMessage("ExecuteAction - Illegal action type = ",pSoldier->aiData.bAction); diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index b6345397..c1ab7242 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -615,6 +615,10 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier, INT8 bAction) bMinPointsNeeded = 20; // TODO break; + case AI_ACTION_SELFDETONATE: + bMinPointsNeeded = 20; // TODO + break; + default: #ifdef BETAVERSION //NumMessage("AffordableAction - Illegal action type = ",pSoldier->aiData.bAction); diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index aaa269fc..1843aae8 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -9847,7 +9847,6 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK ) if ( OKFallDirection( pSoldier, sCheckGridNo, pSoldier->pathing.bLevel, ubOpponentDir, pSoldier->usAnimState ) ) { - // then do it! The functions have already made sure that we have a // pair of worthy opponents, etc., so we're not just wasting our time @@ -10711,6 +10710,14 @@ INT8 ArmedVehicleDecideActionRed( SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK ) // if we're currently under fire (presumably, attacker is hidden) if ( pSoldier->aiData.bUnderFire ) { + // Flugente: see if we are equipped with a smoke screen. If so, use it do hide us + if ( (pSoldier->usSoldierFlagMask2 & SOLDIER_TAKEN_LARGE_HIT) && pSoldier->HasItem( SMOKE_GRENADE ) && IsActionAffordable( pSoldier, AI_ACTION_SELFDETONATE ) ) + { + pSoldier->aiData.usActionData = SMOKE_GRENADE; + + return AI_ACTION_SELFDETONATE; + } + // only try to run if we've actually been hit recently & noticably so // otherwise, presumably our current cover is pretty good & sufficient // HEADROCK HAM B2.6: New value here helps us change the ratio of running away due to shock. This diff --git a/TacticalAI/ai.h b/TacticalAI/ai.h index 7f719bee..217cf079 100644 --- a/TacticalAI/ai.h +++ b/TacticalAI/ai.h @@ -107,6 +107,7 @@ typedef enum AI_ACTION_USE_SKILL, // added by Flugente: perform a skill, which one is stored in usAISkillUse AI_ACTION_DOCTOR, // added by Flugente: AI-ONLY! bandage/surgery on fellow AI. DO NOT USE THIS FOR MERCS!!! AI_ACTION_DOCTOR_SELF, // added by Flugente: AI-ONLY! bandage/surgery on self. DO NOT USE THIS FOR MERCS!!! + AI_ACTION_SELFDETONATE, // added by Flugente: blow up an explosive in own inventory } ActionType;