From 9e1b5338a67843b2b0c0c9f19bde7fe60f0ef8a8 Mon Sep 17 00:00:00 2001 From: Sevenfm Date: Sun, 8 Mar 2020 22:39:21 +0000 Subject: [PATCH] More AI logging information. PanicAI: use correct movement and stealth mode when determining AP needed. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8768 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Strategic/LuaInitNPCs.cpp | 1 + Tactical/Boxing.cpp | 2 + Tactical/Handle Doors.cpp | 1 + Tactical/Handle Items.cpp | 1 + Tactical/Handle UI.cpp | 1 + Tactical/Overhead.cpp | 4 ++ Tactical/Soldier Ani.cpp | 2 + Tactical/Soldier Control.cpp | 36 +++++++++++++----- Tactical/Soldier Control.h | 5 ++- Tactical/opplist.cpp | 5 ++- TacticalAI/AIMain.cpp | 34 +++++++++++++++-- TacticalAI/DecideAction.cpp | 2 +- TacticalAI/FindLocations.cpp | 60 +++++++++++++++++++++++++++--- TacticalAI/Knowledge.cpp | 1 + TacticalAI/Medical.cpp | 1 + TacticalAI/Movement.cpp | 8 ++++ TacticalAI/NPC.cpp | 1 + TacticalAI/PanicButtons.cpp | 72 +++++++++++++++++++++++------------- 18 files changed, 190 insertions(+), 47 deletions(-) diff --git a/Strategic/LuaInitNPCs.cpp b/Strategic/LuaInitNPCs.cpp index b36accf0..8a1e33b9 100644 --- a/Strategic/LuaInitNPCs.cpp +++ b/Strategic/LuaInitNPCs.cpp @@ -6463,6 +6463,7 @@ SOLDIERTYPE * pSoldier; pSoldier = FindSoldierByProfileID( ID, FALSE ); if (pSoldier) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: lua cancel action")); CancelAIAction( pSoldier, TRUE ); } } diff --git a/Tactical/Boxing.cpp b/Tactical/Boxing.cpp index fccce6ff..f961b3f1 100644 --- a/Tactical/Boxing.cpp +++ b/Tactical/Boxing.cpp @@ -82,6 +82,7 @@ void ExitBoxing( void ) SetSoldierNeutral( pSoldier ); RecalculateOppCntsDueToBecomingNeutral( pSoldier ); } + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: exit boxing")); CancelAIAction( pSoldier, TRUE ); pSoldier->aiData.bAlertStatus = STATUS_GREEN; pSoldier->aiData.bUnderFire = 0; @@ -396,6 +397,7 @@ BOOLEAN PickABoxer( void ) pBoxer->flags.uiStatusFlags |= SOLDIER_BOXER; SetSoldierNonNeutral( pBoxer ); RecalculateOppCntsDueToNoLongerNeutral( pBoxer ); + DebugAI(AI_MSG_INFO, pBoxer, String("CancelAIAction: pick a boxer")); CancelAIAction( pBoxer, TRUE ); RESETTIMECOUNTER( pBoxer->timeCounters.AICounter, 0 ); gfBoxerFought[ uiLoop ] = TRUE; diff --git a/Tactical/Handle Doors.cpp b/Tactical/Handle Doors.cpp index 7658f0f9..455caeeb 100644 --- a/Tactical/Handle Doors.cpp +++ b/Tactical/Handle Doors.cpp @@ -468,6 +468,7 @@ void ProcessImplicationsOfPCMessingWithDoor( SOLDIERTYPE * pSoldier ) // alert her if she hasn't been alerted pGoon->aiData.bAlertStatus = STATUS_RED; CheckForChangingOrders( pGoon ); + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: tixa door")); CancelAIAction( pGoon, TRUE ); } } diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index a60297d1..0c1bcb0d 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -6604,6 +6604,7 @@ void RemoveBlueFlag( INT32 sGridNo, INT8 bLevel ) void MakeNPCGrumpyForMinorOffense( SOLDIERTYPE * pSoldier, SOLDIERTYPE *pOffendingSoldier ) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: MakeNPCGrumpyForMinorOffense")); CancelAIAction( pSoldier, TRUE ); switch( pSoldier->ubProfile ) diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index b1584826..724cab53 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -2722,6 +2722,7 @@ void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, IN if ( NPCFirstDraw( pSoldier, pTargetSoldier ) ) { // go into turnbased for that person + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: UIHandleMercAttack")); CancelAIAction( pTargetSoldier, TRUE ); AddToShouldBecomeHostileOrSayQuoteList( pTargetSoldier->ubID ); //MakeCivHostile( pTargetSoldier, 2 ); diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index b1d1450e..90648b96 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -3510,6 +3510,7 @@ void HandlePlayerTeamMemberDeath( SOLDIERTYPE *pSoldier ) { if ( pSoldier->ubAutoBandagingMedic != NOBODY ) { + DebugAI(AI_MSG_INFO, MercPtrs[pSoldier->ubAutoBandagingMedic], String("CancelAIAction: stop autobandaging in HandlePlayerTeamMemberDeath")); CancelAIAction( MercPtrs[ pSoldier->ubAutoBandagingMedic ], TRUE ); } } @@ -6073,6 +6074,7 @@ void CommonEnterCombatModeCode( ) pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); // END AI actions + DebugAI(AI_MSG_INFO, MercPtrs[pSoldier->ubAutoBandagingMedic], String("CancelAIAction: enter combat mode")); CancelAIAction( pSoldier, TRUE ); // turn off AI controlled flag @@ -8812,6 +8814,7 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker ) // AI people will have to have their actions canceled if (!(pSoldier->flags.uiStatusFlags & SOLDIER_PC)) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: suppression: change stance/cower")); CancelAIAction( pSoldier, TRUE ); #if 0 pSoldier->aiData.bAction = AI_ACTION_CHANGE_STANCE; @@ -9768,6 +9771,7 @@ void CencelAllActionsForTimeCompression( ) if ( pSoldier->bInSector ) { // Hault! + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: time compression")); pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); // END AI actions diff --git a/Tactical/Soldier Ani.cpp b/Tactical/Soldier Ani.cpp index e6d823d9..99acb2ac 100644 --- a/Tactical/Soldier Ani.cpp +++ b/Tactical/Soldier Ani.cpp @@ -1987,6 +1987,7 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier ) if ( pTSoldier->bTeam != gbPlayerNum ) { + DebugAI(AI_MSG_INFO, pTSoldier, String("CancelAIAction: dodge")); CancelAIAction( pTSoldier, TRUE ); } @@ -2493,6 +2494,7 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier ) { if (!TileIsOutOfBounds(pSoldier->sAbsoluteFinalDestination)) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: end door open code")); CancelAIAction( pSoldier, FORCE ); } } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index f710bf2b..2aba1b5b 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -12649,6 +12649,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginBladeAttack( INT32 sGridNo, UINT8 ubDirectio if ( pTSoldier->bTeam != gbPlayerNum ) { + DebugAI(AI_MSG_INFO, pTSoldier, String("CancelAIAction: begin blade attack")); CancelAIAction( pTSoldier, TRUE ); } @@ -12984,6 +12985,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginPunchAttack( INT32 sGridNo, UINT8 ubDirectio if ( pTSoldier->bTeam != gbPlayerNum ) { + DebugAI(AI_MSG_INFO, pTSoldier, String("CancelAIAction: begin blade attack")); CancelAIAction( pTSoldier, TRUE ); } @@ -16522,16 +16524,6 @@ BOOLEAN SOLDIERTYPE::IsAssassin( ) return FALSE; } -BOOLEAN SOLDIERTYPE::CheckInitialAP(void) -{ - if (this->bActionPoints < this->bInitialActionPoints || this->usSoldierFlagMask2 & SOLDIER_SPENT_AP) - { - return FALSE; - } - - return TRUE; -} - UINT8 SOLDIERTYPE::GetMultiTurnAction( ) { return usMultiTurnAction; @@ -22171,6 +22163,7 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid { // Start combat etc DeleteTalkingMenu( ); + DebugAI(AI_MSG_INFO, pTSoldier, String("CancelAIAction: assasin: start talking")); CancelAIAction( pTSoldier, TRUE ); AddToShouldBecomeHostileOrSayQuoteList( pTSoldier->ubID ); } @@ -24789,3 +24782,26 @@ BOOLEAN ApplyConsumable( SOLDIERTYPE* pSoldier, OBJECTTYPE *pObj, BOOLEAN fForce return FALSE; } + +// sevenfm: service functions +BOOLEAN SOLDIERTYPE::CheckInitialAP(void) +{ + if (this->bActionPoints < this->bInitialActionPoints || this->usSoldierFlagMask2 & SOLDIER_SPENT_AP) + { + return FALSE; + } + + return TRUE; +} + +BOOLEAN SOLDIERTYPE::IsFlanking(void) +{ + if (this->aiData.bAlertStatus < STATUS_YELLOW || + this->numFlanks == 0 || + this->numFlanks >= MAX_FLANKS_RED) + { + return FALSE; + } + + return TRUE; +} diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 144fd173..1cd6fb5b 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -1840,9 +1840,12 @@ public: // lose disguise or take off any clothes item and switch back to original clothes void Strip(); - // check wether our disguise is any good + // check whether our disguise is any good void SpySelfTest(); + // sevenfm: service functions + BOOLEAN IsFlanking(void); + // Flugente: prisoner system BOOLEAN CanProcessPrisoners(); UINT32 GetSurrenderStrength(); diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index acabfbce..9a1f9f48 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -1843,7 +1843,7 @@ void HandleManNoLongerSeen( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pOpponent, INT { // unauthorized! // make guard run to block guard room - CancelAIAction( pSoldier, TRUE ); + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: make guard run to block guard room")); CancelAIAction( pSoldier, TRUE ); RESETTIMECOUNTER( pSoldier->timeCounters.AICounter, 0 ); pSoldier->aiData.bNextAction = AI_ACTION_RUN; pSoldier->aiData.usNextActionData = 13250; @@ -2298,6 +2298,7 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo, if ( pSoldier->aiData.bOppCnt == 0 ) { // didn't see anyone before! + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: NPC with profile: change orders, reset action")); CancelAIAction( pSoldier, TRUE ); SetNewSituation( pSoldier ); } @@ -2314,6 +2315,7 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo, } else if ( ( CheckFact( FACT_ANGEL_LEFT_DEED, ANGEL ) == TRUE ) && ( CheckFact( FACT_ANGEL_MENTIONED_DEED, ANGEL ) == FALSE ) ) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: NPC: Angel code")); CancelAIAction( pSoldier, TRUE ); pSoldier->sAbsoluteFinalDestination = NOWHERE; pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection ); @@ -2389,6 +2391,7 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo, if ( pSoldier->aiData.bOppCnt == 0 ) { // didn't see anyone before! + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: assasin: didn't see anyone before!")); CancelAIAction( pSoldier, TRUE ); SetNewSituation( pSoldier ); } diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 66c7800b..0b4cf85f 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -81,6 +81,9 @@ extern BOOLEAN gfWaitingForTriggerTimer; UINT8 gubAICounter; +extern STR16 gStrAction[]; +extern STR szAction[]; + // // Commented out/ to fix: // lots of other stuff, I think @@ -572,6 +575,7 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named #endif // stunned/collapsed! + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: collapsed")); CancelAIAction( pSoldier, FORCE ); EndAIGuysTurn( pSoldier ); return; @@ -612,6 +616,7 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named { // don't force, don't want escorted mercs reacting to new opponents, etc. // now we don't have AI controlled escorted mercs though - CJC + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: escorted merc")); CancelAIAction( pSoldier, FORCE ); // zap any next action too if ( pSoldier->aiData.bAction != AI_ACTION_END_COWER_AND_MOVE ) @@ -645,8 +650,6 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named Start of new overall AI system ********/ - - if (gfTurnBasedAI) { if ( ( GetJA2Clock() - gTacticalStatus.uiTimeSinceMercAIStart ) > ( (UINT32)gGameExternalOptions.gubDeadLockDelay * 1000 ) && !gfUIInDeadlock ) @@ -654,6 +657,9 @@ void HandleSoldierAI( SOLDIERTYPE *pSoldier ) // FIXME - this function is named // ATE: Display message that deadlock occured... LiveMessage( "Breaking Deadlock" ); + //ScreenMsg(FONT_MCOLOR_LTRED, MSG_INTERFACE, L"Aborting AI deadlock for [%d] %s data %d", pSoldier->ubID, gStrAction[pSoldier->aiData.bAction], pSoldier->aiData.usActionData); + DebugAI(String("Aborting AI deadlock for [%d] %s data %d", pSoldier->ubID, szAction[pSoldier->aiData.bAction], pSoldier->aiData.usActionData)); + #ifdef JA2TESTVERSION // display deadlock message gfUIInDeadlock = TRUE; @@ -923,6 +929,12 @@ void EndAIDeadlock(void) DebugAI( String("Ending turn for %d because breaking deadlock", pSoldier->ubID ) ); } #endif + // sevenfm: abort flanking + if (pSoldier->IsFlanking()) + { + pSoldier->numFlanks = MAX_FLANKS_RED + 1; + DebugAI(AI_MSG_INFO, pSoldier, String("abort flanking, numFlanks = %d", pSoldier->numFlanks)); + } DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Number of bullets in the air is %ld", guiNumBullets ) ); @@ -936,7 +948,6 @@ void EndAIDeadlock(void) } } - if (!bFound) { StartPlayerTeamTurn( TRUE, FALSE ); @@ -1428,6 +1439,8 @@ void CancelAIAction(SOLDIERTYPE *pSoldier, UINT8 ubForce) } #endif + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction")); + // re-enable cover checking, something is new or something strange happened if ( gGameExternalOptions.fEnemyTanksCanMoveInTactical || !ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 SkipCoverCheck = FALSE; @@ -1708,9 +1721,15 @@ void RefreshAI(SOLDIERTYPE *pSoldier) DecideAlertStatus(pSoldier); if (pSoldier->aiData.bAlertStatus == STATUS_YELLOW) + { SkipCoverCheck = FALSE; - if ( !gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE( pSoldier ) )//dnl ch64 290813 tanks don't have move animations + DebugAI(AI_MSG_INFO, pSoldier, String("RefreshAI: disable SkipCoverCheck in yellow AI")); + } + if (!gGameExternalOptions.fEnemyTanksCanMoveInTactical && ARMED_VEHICLE(pSoldier))//dnl ch64 290813 tanks don't have move animations + { SkipCoverCheck = TRUE; + DebugAI(AI_MSG_INFO, pSoldier, String("RefreshAI: enable SkipCoverCheck for armed vehicle")); + } // if he's in battle or knows opponents are here if (gfTurnBasedAI) @@ -2064,12 +2083,14 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) if (!pSoldier->pathing.bPathStored) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: no path stored, could not find path")); CancelAIAction(pSoldier,FORCE); return(FALSE); // nothing is in progress } } else { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: no path stored")); CancelAIAction(pSoldier,FORCE); return(FALSE); // nothing is in progress } @@ -2124,6 +2145,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) pSoldier->pathing.sBlackList = (INT16) pSoldier->aiData.usActionData; DebugAI( String( "Setting blacklist for %d to %d", pSoldier->ubID, pSoldier->pathing.sBlackList ) ); + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: sFinalDestination != usActionData")); CancelAIAction(pSoldier,FORCE); return(FALSE); // nothing is in progress @@ -2214,6 +2236,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) DebugAI( String( "AI %d got error code %ld from HandleItem, doing action %d, has %d APs... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction, pSoldier->bActionPoints ) ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"AI %d got error code %ld from HandleItem, doing action %d... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction ); } + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: !ITEM_HANDLE_OK")); CancelAIAction( pSoldier, FORCE); #ifdef TESTAICONTROL if (gfTurnBasedAI) @@ -2391,6 +2414,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) iRetCode = HandleItem( pSoldier, pSoldier->aiData.usActionData, 0, pSoldier->inv[HANDPOS].usItem, FALSE ); if ( iRetCode != ITEM_HANDLE_OK) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: AI_ACTION_GIVE_AID: !ITEM_HANDLE_OK")); #ifdef JA2BETAVERSION ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %d got error code %ld from HandleItem, doing action %d... aborting deadlock!", pSoldier->ubID, iRetCode, pSoldier->aiData.bAction ); #endif @@ -2429,6 +2453,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) #ifdef JA2TESTVERSION ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_ERROR, L"AI %d tried to open door it could not then find in %d", pSoldier->ubID, sDoorGridNo ); #endif + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: door: cannot find structure")); CancelAIAction( pSoldier, FORCE); #ifdef TESTAICONTROL if (gfTurnBasedAI) @@ -2459,6 +2484,7 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) //if ( pSoldier->aiData.bOrders == SNIPER && pSoldier->aiData.bLastAction == AI_ACTION_RAISE_GUN) if ( pSoldier->aiData.bLastAction == AI_ACTION_RAISE_GUN) { + DebugAI(AI_MSG_INFO, pSoldier, String("sniper deadlock fix !!! repeated AI_ACTION_RAISE_GUN, set next action to AI_ACTION_END_TURN")); pSoldier->aiData.bNextAction = AI_ACTION_END_TURN; } diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index fdc37650..49773fe3 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -3729,7 +3729,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier) } // sevenfm: possibly start RED flanking - if ( ( pSoldier->aiData.bAttitude == CUNNINGAID || pSoldier->aiData.bAttitude == CUNNINGSOLO || + if (( pSoldier->aiData.bAttitude == CUNNINGAID || pSoldier->aiData.bAttitude == CUNNINGSOLO || ( pSoldier->aiData.bAttitude == BRAVESOLO || pSoldier->aiData.bAttitude == BRAVEAID ) && fOvercrowded ) && pSoldier->bTeam == ENEMY_TEAM && gAnimControl[ pSoldier->usAnimState ].ubHeight != ANIM_PRONE && diff --git a/TacticalAI/FindLocations.cpp b/TacticalAI/FindLocations.cpp index 078a20c7..1a64249a 100644 --- a/TacticalAI/FindLocations.cpp +++ b/TacticalAI/FindLocations.cpp @@ -1897,6 +1897,7 @@ INT32 FindNearbyDarkerSpot(SOLDIERTYPE *pSoldier) INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) { DebugMsg(TOPIC_JA2AI,DBG_LEVEL_3,String("SearchForItems")); + DebugAI(AI_MSG_INFO, pSoldier, String("SearchForItems [%d] bReason %d usItem %d", pSoldier->ubID, bReason, usItem)); INT32 iSearchRange; INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset; @@ -1915,20 +1916,24 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) // No fair picking up weapons while boxing! if (gTacticalStatus.bBoxingState == BOXING) { + DebugAI(AI_MSG_INFO, pSoldier, String("no picking up items for boxers!")); return AI_ACTION_NONE; } if (pSoldier->bActionPoints < GetBasicAPsToPickupItem( pSoldier )) { + DebugAI(AI_MSG_INFO, pSoldier, String("not enough AP!")); return( AI_ACTION_NONE ); } if ( !IS_MERC_BODY_TYPE( pSoldier ) ) { + DebugAI(AI_MSG_INFO, pSoldier, String("not merc bodytype!")); return( AI_ACTION_NONE ); } iSearchRange = gbDiff[DIFF_MAX_COVER_RANGE][ SoldierDifficultyLevel( pSoldier ) ]; + DebugAI(AI_MSG_INFO, pSoldier, String("use search range %d", iSearchRange)); switch (pSoldier->aiData.bAttitude) { @@ -1995,8 +2000,11 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) FindBestPath( pSoldier, GRIDSIZE, pSoldier->pathing.bLevel, DetermineMovementMode( pSoldier, AI_ACTION_PICKUP_ITEM ), COPYREACHABLE, 0 );//dnl ch50 071009 // Flugente: if the soldier is 'dumb enough', he may pick up certain items... which can be used to lure the AI into traps - if ( pSoldier->stats.bWisdom < 70 ) + if (pSoldier->stats.bWisdom < 70) + { + DebugAI(AI_MSG_INFO, pSoldier, String("dumb enough to pick up items")); fDumbEnoughtoPickup = TRUE; + } // SET UP DOUBLE-LOOP TO STEP THROUGH POTENTIAL GRID #s for (sYOffset = -sMaxUp; sYOffset <= sMaxDown; sYOffset++) @@ -2030,16 +2038,21 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) continue; } + DebugAI(AI_MSG_INFO, pSoldier, String("check spot %d, found items", sGridNo)); + iValue = 0; GetItemPool( sGridNo, &pItemPool, pSoldier->pathing.bLevel ); switch( bReason ) { case SEARCH_AMMO: // we are looking for ammo to match the gun in usItem + DebugAI(AI_MSG_INFO, pSoldier, String("SEARCH_AMMO")); while( pItemPool ) { pObj = &(gWorldItems[ pItemPool->iItemIndex ].object); pItem = &(Item[pObj->usItem]); + DebugAI(AI_MSG_INFO, pSoldier, String("check item %d at %d status %d", pObj->usItem, sGridNo, (*pObj)[0]->data.objectStatus)); + if ( pItem->usItemClass == IC_GUN && (*pObj)[0]->data.objectStatus >= MINIMUM_REQUIRED_STATUS ) { // maybe this gun has ammo (adjust for whether it is better than ours!) @@ -2054,14 +2067,19 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) } else if (ValidAmmoType( usItem, pObj->usItem ) ) { + DebugAI(AI_MSG_INFO, pSoldier, String("good ammo")); iTempValue = TotalPoints( pObj ); } else { + DebugAI(AI_MSG_INFO, pSoldier, String("not gun, not ammo - skip")); iTempValue = 0; } + DebugAI(AI_MSG_INFO, pSoldier, String("iTempValue %d", iTempValue)); + if (iTempValue > iValue ) { + DebugAI(AI_MSG_INFO, pSoldier, String("select this ammo")); iValue = iTempValue; iItemIndex = pItemPool->iItemIndex; } @@ -2069,19 +2087,25 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) } break; case SEARCH_WEAPONS: + DebugAI(AI_MSG_INFO, pSoldier, String("SEARCH_WEAPONS")); while( pItemPool ) { pObj = &(gWorldItems[ pItemPool->iItemIndex ].object); pItem = &(Item[pObj->usItem]); + DebugAI(AI_MSG_INFO, pSoldier, String("check item %d at %d status %d", pObj->usItem, sGridNo, (*pObj)[0]->data.objectStatus)); + if (pItem->usItemClass & IC_WEAPON && (*pObj)[0]->data.objectStatus >= MINIMUM_REQUIRED_STATUS ) { + DebugAI(AI_MSG_INFO, pSoldier, String("weapon has good status")); if ( (pItem->usItemClass & IC_GUN) && ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (( Item[pObj->usItem].fingerprintid ) && (*pObj)[0]->data.ubImprintID != NOBODY && (*pObj)[0]->data.ubImprintID != pSoldier->ubID) ) ) { // jammed or out of ammo, skip it! + DebugAI(AI_MSG_INFO, pSoldier, String("jammed or out of ammo, skip it!")); iTempValue = 0; } else if ( Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON ) { + DebugAI(AI_MSG_INFO, pSoldier, String("compare with gun in hand")); if (Weapon[pObj->usItem].ubDeadliness > Weapon[pSoldier->inv[HANDPOS].usItem].ubDeadliness) { iTempValue = 100 * Weapon[pObj->usItem].ubDeadliness / Weapon[pSoldier->inv[HANDPOS].usItem].ubDeadliness; @@ -2098,10 +2122,14 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) } else { + DebugAI(AI_MSG_INFO, pSoldier, String("not weapon or bad status")); iTempValue = 0; } + DebugAI(AI_MSG_INFO, pSoldier, String("iTempValue %d", iTempValue)); + if (iTempValue > iValue ) { + DebugAI(AI_MSG_INFO, pSoldier, String("select this weapon")); iValue = iTempValue; iItemIndex = pItemPool->iItemIndex; } @@ -2109,19 +2137,26 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) } break; default: + DebugAI(AI_MSG_INFO, pSoldier, String("search items")); + while( pItemPool ) { pObj = &(gWorldItems[ pItemPool->iItemIndex ].object); pItem = &(Item[pObj->usItem]); + DebugAI(AI_MSG_INFO, pSoldier, String("check item %d at %d status %d", pObj->usItem, sGridNo, (*pObj)[0]->data.objectStatus)); + if ( pItem->usItemClass & IC_WEAPON && (*pObj)[0]->data.objectStatus >= MINIMUM_REQUIRED_STATUS ) { + DebugAI(AI_MSG_INFO, pSoldier, String("gun has good status")); if ( (pItem->usItemClass & IC_GUN) && ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || (*pObj)[0]->data.gun.ubGunShotsLeft == 0 || (( Item[pObj->usItem].fingerprintid ) && (*pObj)[0]->data.ubImprintID != NOBODY && (*pObj)[0]->data.ubImprintID != pSoldier->ubID) ) ) { // jammed or out of ammo, skip it! + DebugAI(AI_MSG_INFO, pSoldier, String("jammed or out of ammo, skip it!")); iTempValue = 0; } - else if ( (Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON) ) + else if (pSoldier->inv[HANDPOS].exists() && (Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_WEAPON)) { + DebugAI(AI_MSG_INFO, pSoldier, String("compare with weapon in hand")); if (Weapon[pObj->usItem].ubDeadliness > Weapon[pSoldier->inv[HANDPOS].usItem].ubDeadliness) { if ((Weapon[pSoldier->inv[HANDPOS].usItem].ubDeadliness != NULL) && (Weapon[pSoldier->inv[HANDPOS].usItem].ubDeadliness > 0)) @@ -2142,14 +2177,17 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) { iTempValue = 200 + Weapon[pObj->usItem].ubDeadliness; } + DebugAI(AI_MSG_INFO, pSoldier, String("iTempValue %d", iTempValue)); } else if (pItem->usItemClass == IC_ARMOUR && (*pObj)[0]->data.objectStatus >= MINIMUM_REQUIRED_STATUS ) { + DebugAI(AI_MSG_INFO, pSoldier, String("armour has good status")); iTempValue = 0; switch( Armour[pItem->ubClassIndex].ubArmourClass ) { case ARMOURCLASS_HELMET: + DebugAI(AI_MSG_INFO, pSoldier, String("ARMOURCLASS_HELMET")); if (pSoldier->inv[HELMETPOS].exists() == false) { iTempValue = 200 + EffectiveArmour( pObj ); @@ -2158,8 +2196,10 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) { iTempValue = 100 * EffectiveArmour( pObj ) / (EffectiveArmour( &(pSoldier->inv[HELMETPOS]) ) + 1); } + DebugAI(AI_MSG_INFO, pSoldier, String("iTempValue %d", iTempValue)); break; case ARMOURCLASS_VEST: + DebugAI(AI_MSG_INFO, pSoldier, String("ARMOURCLASS_VEST")); if (pSoldier->inv[VESTPOS].exists() == false) { iTempValue = 200 + EffectiveArmour( pObj ); @@ -2168,8 +2208,10 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) { iTempValue = 100 * EffectiveArmour( pObj ) / (EffectiveArmour( &(pSoldier->inv[VESTPOS]) ) + 1); } + DebugAI(AI_MSG_INFO, pSoldier, String("iTempValue %d", iTempValue)); break; case ARMOURCLASS_LEGGINGS: + DebugAI(AI_MSG_INFO, pSoldier, String("ARMOURCLASS_LEGGINGS")); if (pSoldier->inv[LEGPOS].exists() == false) { iTempValue = 200 + EffectiveArmour( pObj ); @@ -2178,6 +2220,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) { iTempValue = 100 * EffectiveArmour( pObj ) / (EffectiveArmour( &(pSoldier->inv[LEGPOS]) ) + 1); } + DebugAI(AI_MSG_INFO, pSoldier, String("iTempValue %d", iTempValue)); break; default: { @@ -2188,6 +2231,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) // Flugente: if the soldier is 'dumb enough', he may pick up 'interesting items'. This can be used to lure him into traps (a certain scene in FMJ comes to mind) else if ( fDumbEnoughtoPickup && pItem->usItemClass == IC_MISC && HasItemFlag(pObj->usItem, ATTENTION_ITEM) ) { + DebugAI(AI_MSG_INFO, pSoldier, String("dumb soldier picks up item!")); // oooh... shiny! iTempValue = 1000; } @@ -2195,9 +2239,11 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) { iTempValue = 0; } + DebugAI(AI_MSG_INFO, pSoldier, String("iTempValue %d", iTempValue)); if (iTempValue > iValue ) { + DebugAI(AI_MSG_INFO, pSoldier, String("select item")); iValue = iTempValue; iItemIndex = pItemPool->iItemIndex; } @@ -2206,8 +2252,12 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) break; } iValue = (3 * iValue) / (3 + PythSpacesAway( sGridNo, pSoldier->sGridNo )); + DebugAI(AI_MSG_INFO, pSoldier, String("iBestValue %d", iBestValue)); + DebugAI(AI_MSG_INFO, pSoldier, String("value modified by distance %d", iValue)); + if (iValue > iBestValue ) { + DebugAI(AI_MSG_INFO, pSoldier, String("select item at %d", sGridNo)); sBestSpot = sGridNo; iBestValue = iValue; iBestItemIndex = iItemIndex; @@ -2218,7 +2268,7 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) if (!TileIsOutOfBounds(sBestSpot)) { - DebugAI( String( "%d decides to pick up %S", pSoldier->ubID, ItemNames[ gWorldItems[ iBestItemIndex ].object.usItem ] ) ); + DebugAI(AI_MSG_INFO, pSoldier, String("%d decides to pick up %S", pSoldier->ubID, ItemNames[gWorldItems[iBestItemIndex].object.usItem])); if (Item[gWorldItems[ iBestItemIndex ].object.usItem].usItemClass == IC_GUN) { //CHRISL: This is the line from ADB's code but I removed it, for now, to match what 0verhaul has been working on @@ -2232,14 +2282,14 @@ INT8 SearchForItems( SOLDIERTYPE * pSoldier, INT8 bReason, UINT16 usItem ) if (pSoldier->inv[HANDPOS].fFlags & OBJECT_UNDROPPABLE) { // destroy this item! - DebugAI( String( "%d decides he must drop %S first so destroys it", pSoldier->ubID, ItemNames[ pSoldier->inv[HANDPOS].usItem ] ) ); + DebugAI(AI_MSG_INFO, pSoldier, String("%d decides he must drop %S first so destroys it", pSoldier->ubID, ItemNames[pSoldier->inv[HANDPOS].usItem])); DeleteObj( &(pSoldier->inv[HANDPOS]) ); DeductPoints( pSoldier, GetBasicAPsToPickupItem( pSoldier ), 0, AFTERACTION_INTERRUPT ); } else { // we want to drop this item! - DebugAI( String( "%d decides he must drop %S first", pSoldier->ubID, ItemNames[ pSoldier->inv[HANDPOS].usItem ] ) ); + DebugAI(AI_MSG_INFO, pSoldier, String("%d decides he must drop %S first", pSoldier->ubID, ItemNames[pSoldier->inv[HANDPOS].usItem])); pSoldier->aiData.bNextAction = AI_ACTION_PICKUP_ITEM; pSoldier->aiData.usNextActionData = sBestSpot; diff --git a/TacticalAI/Knowledge.cpp b/TacticalAI/Knowledge.cpp index be6f1a14..f6c34fa5 100644 --- a/TacticalAI/Knowledge.cpp +++ b/TacticalAI/Knowledge.cpp @@ -108,6 +108,7 @@ void CallEldinTo( INT32 sGridNo ) pSoldier->aiData.bAlertStatus = STATUS_RED; if ( (pSoldier->aiData.bAction != AI_ACTION_GET_CLOSER) || CheckFact( FACT_MUSEUM_ALARM_WENT_OFF, 0 ) == FALSE ) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: CallEldinTo")); CancelAIAction( pSoldier, TRUE ); pSoldier->aiData.bNextAction = AI_ACTION_GET_CLOSER; pSoldier->aiData.usNextActionData = sGridNo; diff --git a/TacticalAI/Medical.cpp b/TacticalAI/Medical.cpp index 216c2f5d..86bf9eb8 100644 --- a/TacticalAI/Medical.cpp +++ b/TacticalAI/Medical.cpp @@ -382,6 +382,7 @@ INT8 FindBestPatient( SOLDIERTYPE * pSoldier, BOOLEAN * pfDoClimb ) if (pBestPatient->ubAutoBandagingMedic != NOBODY) { // cancel that medic + DebugAI(AI_MSG_INFO, MercPtrs[pBestPatient->ubAutoBandagingMedic], String("CancelAIAction: medic: find patient")); CancelAIAction( MercPtrs[ pBestPatient->ubAutoBandagingMedic ], TRUE ); } pBestPatient->ubAutoBandagingMedic = pSoldier->ubID; diff --git a/TacticalAI/Movement.cpp b/TacticalAI/Movement.cpp index b2fe766c..aeb2bbfe 100644 --- a/TacticalAI/Movement.cpp +++ b/TacticalAI/Movement.cpp @@ -163,6 +163,7 @@ int TryToResumeMovement(SOLDIERTYPE *pSoldier, INT32 sGridNo) #endif // must work even for escorted civs, can't just set the flag + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: could not resume movement")); CancelAIAction(pSoldier,FORCE); } @@ -188,6 +189,7 @@ int TryToResumeMovement(SOLDIERTYPE *pSoldier, INT32 sGridNo) if (!pSoldier->aiData.bUnderEscort) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: not under escort")); CancelAIAction(pSoldier,DONTFORCE); // no need to force this } else @@ -222,6 +224,7 @@ int TryToResumeMovement(SOLDIERTYPE *pSoldier, INT32 sGridNo) if (ubGottaCancel) { // can't get close, gotta abort the movement! + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: can't get close, abort movement")); CancelAIAction(pSoldier,FORCE); // tell the player doing the escorting that civilian has stopped @@ -754,18 +757,21 @@ void SoldierTriesToContinueAlongPath(SOLDIERTYPE *pSoldier) if (pSoldier->aiData.bNewSituation == IS_NEW_SITUATION) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: IS_NEW_SITUATION")); CancelAIAction(pSoldier,DONTFORCE); return; } if (TileIsOutOfBounds(pSoldier->aiData.usActionData)) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: bad usActionData")); CancelAIAction(pSoldier,DONTFORCE); return; } if (!NewOKDestination( pSoldier,pSoldier->aiData.usActionData, TRUE, pSoldier->pathing.bLevel )) { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: !NewOKDestination")); CancelAIAction(pSoldier,DONTFORCE); return; } @@ -801,6 +807,7 @@ void SoldierTriesToContinueAlongPath(SOLDIERTYPE *pSoldier) } else { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: !IsActionAffordable")); CancelAIAction(pSoldier,DONTFORCE); #ifdef TESTAI DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, @@ -826,6 +833,7 @@ void SoldierTriesToContinueAlongPath(SOLDIERTYPE *pSoldier) } else { + DebugAI(AI_MSG_INFO, pSoldier, String("CancelAIAction: not enough AP")); CancelAIAction(pSoldier,DONTFORCE); #ifdef TESTAI DebugMsg( TOPIC_JA2AI, DBG_LEVEL_3, diff --git a/TacticalAI/NPC.cpp b/TacticalAI/NPC.cpp index e890ed5c..b90ee115 100644 --- a/TacticalAI/NPC.cpp +++ b/TacticalAI/NPC.cpp @@ -2240,6 +2240,7 @@ void Converse( UINT8 ubNPC, UINT8 ubMerc, INT8 bApproach, UINT32 uiApproachData case OLGA: case TYRONE: // Start combat etc + DebugAI(AI_MSG_INFO, pNPC, String("CancelAIAction: NPC coverse")); CancelAIAction( pNPC, TRUE ); AddToShouldBecomeHostileOrSayQuoteList( pNPC->ubID ); default: diff --git a/TacticalAI/PanicButtons.cpp b/TacticalAI/PanicButtons.cpp index 008993c8..970879b9 100644 --- a/TacticalAI/PanicButtons.cpp +++ b/TacticalAI/PanicButtons.cpp @@ -249,14 +249,17 @@ void PossiblyMakeThisEnemyChosenOne( SOLDIERTYPE * pSoldier ) INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) { - BOOLEAN fFoundRoute = FALSE; - INT8 bSlot; - INT32 iPathCost; - INT8 bPanicTrigger; - INT32 sPanicTriggerGridNo; - #ifdef DEBUGDECISIONS - STR16 tempstr; - #endif + BOOLEAN fFoundRoute = FALSE; + INT8 bSlot; + INT32 iPathCost; + INT8 bPanicTrigger; + INT32 sPanicTriggerGridNo; + UINT16 usMovementMode; +#ifdef DEBUGDECISIONS + STR16 tempstr; +#endif + + DebugAI(AI_MSG_TOPIC, pSoldier, String("[Panic AI]")); // if there are panic bombs here if (gTacticalStatus.fPanicFlags & PANIC_BOMBS_HERE) @@ -265,6 +268,7 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) bSlot = FindTrigger( pSoldier ); if (bSlot != NO_SLOT) { + DebugAI(AI_MSG_TOPIC, pSoldier, String("found trigger, slot %d", bSlot)); ////////////////////////////////////////////////////////////////////// // ACTIVATE DETONATOR: blow up sector's panic bombs ////////////////////////////////////////////////////////////////////// @@ -277,11 +281,13 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) PopMessage(tempstr); #endif // blow up all the PANIC bombs! + DebugAI(AI_MSG_TOPIC, pSoldier, String("blow up panic bomb")); return(AI_ACTION_USE_DETONATOR); } else // otherwise, wait a turn { pSoldier->aiData.usActionData = NOWHERE; + DebugAI(AI_MSG_TOPIC, pSoldier, String("wait a turn")); return(AI_ACTION_NONE); } } @@ -292,54 +298,66 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) // if there's a panic trigger here (DOESN'T MATTER IF ANY PANIC BOMBS EXIST!) if ( gTacticalStatus.fPanicFlags & PANIC_TRIGGERS_HERE ) { + DebugAI(AI_MSG_TOPIC, pSoldier, String("found panic trigger")); + usMovementMode = DetermineMovementMode(pSoldier, AI_ACTION_GET_CLOSER); + DebugAI(AI_MSG_TOPIC, pSoldier, String("movement mode %d", usMovementMode)); + // Have WE been chosen to go after the trigger? if (pSoldier->ubID == gTacticalStatus.ubTheChosenOne) { bPanicTrigger = ClosestPanicTrigger( pSoldier ); + if (bPanicTrigger == -1) { // augh! return( -1 ); } + sPanicTriggerGridNo = gTacticalStatus.sPanicTriggerGridNo[ bPanicTrigger ]; + DebugAI(AI_MSG_TOPIC, pSoldier, String("closest panic trigger %d, spot %d", bPanicTrigger, sPanicTriggerGridNo)); // if not standing on the panic trigger if (pSoldier->sGridNo != sPanicTriggerGridNo) { // determine whether we can still get there - iPathCost = PlotPath( pSoldier, sPanicTriggerGridNo, FALSE, FALSE, FALSE, RUNNING, FALSE, FALSE, 0); + //iPathCost = PlotPath( pSoldier, sPanicTriggerGridNo, FALSE, FALSE, FALSE, RUNNING, FALSE, FALSE, 0); + iPathCost = PlotPath(pSoldier, sPanicTriggerGridNo, FALSE, FALSE, FALSE, usMovementMode, pSoldier->bStealthMode, FALSE, 0); + if (iPathCost != 0) { + DebugAI(AI_MSG_TOPIC, pSoldier, String("found route to panic trigger, path cost %d", iPathCost)); fFoundRoute = TRUE; } } else { + DebugAI(AI_MSG_TOPIC, pSoldier, String("standing at panic trigger spot")); fFoundRoute = TRUE; } // if we managed to find an adjacent spot if (fFoundRoute) { + DebugAI(AI_MSG_TOPIC, pSoldier, String("have good route to panic triger")); + /* + *** COMMENTED OUT BECAUSE WE DON'T HAVE SUPPORT ROUTINES YET -/* - *** COMMENTED OUT BECAUSE WE DON'T HAVE SUPPORT ROUTINES YET + // make sure it's not in water (those triggers can't be pulled) + if (Water(Terrain(gTacticalStatus.sHandGrid),Structure(gTacticalStatus.sHandGrid))) + { + #ifdef BETAVERSION + PopMessage("BAD SCENARIO DESIGN: Enemies can't use this panic trigger!"); + #endif + gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status + // don't bother replacing him either, the next won't have more luck! + return(-1); + } + */ - // make sure it's not in water (those triggers can't be pulled) - if (Water(Terrain(gTacticalStatus.sHandGrid),Structure(gTacticalStatus.sHandGrid))) - { -#ifdef BETAVERSION - PopMessage("BAD SCENARIO DESIGN: Enemies can't use this panic trigger!"); -#endif - gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status - // don't bother replacing him either, the next won't have more luck! - return(-1); - } - - */ // if we are at that spot now if (pSoldier->sGridNo == sPanicTriggerGridNo) { + DebugAI(AI_MSG_TOPIC, pSoldier, String("we are at the spot, activate the trigger!")); //////////////////////////////////////////////////////////////// // PULL THE PANIC TRIGGER! //////////////////////////////////////////////////////////////// @@ -355,11 +373,12 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) pSoldier->name,pSoldier->aiData.usActionData); PopMessage(tempstr); #endif - + DebugAI(AI_MSG_TOPIC, pSoldier, String("enough AP, activate trigger!")); return(AI_ACTION_PULL_TRIGGER); } else // otherwise, wait a turn { + DebugAI(AI_MSG_TOPIC, pSoldier, String("wait a turn, not enough AP")); pSoldier->aiData.usActionData = NOWHERE; return(AI_ACTION_NONE); } @@ -380,7 +399,7 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) sprintf(tempstr,"%s - GETTING CLOSER to PANIC TRIGGER at grid %d (Trigger at %d)", pSoldier->name,pSoldier->aiData.usActionData,sPanicTriggerGridNo); AIPopMessage(tempstr); #endif - + DebugAI(AI_MSG_TOPIC, pSoldier, String("move closet to panic trigger %d", sPanicTriggerGridNo)); return(AI_ACTION_GET_CLOSER); } else // Oh oh, the chosen one can't get to the trigger! @@ -388,12 +407,14 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) #ifdef TESTVERSION PopMessage("TEST MSG: Oh oh! !legalDest - ChosenOne can't get to the trigger!"); #endif + DebugAI(AI_MSG_TOPIC, pSoldier, String("cannot move to the trigger, find another chosen one")); gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status MakeClosestEnemyChosenOne(); // and replace him! } } else // can't move, wait 1 turn { + DebugAI(AI_MSG_TOPIC, pSoldier, String("cannot move, wait one turn")); pSoldier->aiData.usActionData = NOWHERE; return(AI_ACTION_NONE); } @@ -404,6 +425,7 @@ INT8 PanicAI(SOLDIERTYPE *pSoldier, UINT8 ubCanMove) #ifdef TESTVERSION PopMessage("TEST MSG: Oh oh! !adjacentFound - ChosenOne can't get to the trigger!"); #endif + DebugAI(AI_MSG_TOPIC, pSoldier, String("cannot find route to the trigger, find another chosen one")); gTacticalStatus.ubTheChosenOne = NOBODY; // strip him of his Chosen One status MakeClosestEnemyChosenOne(); // and replace him! }