diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 68baab04..6d9e6aa1 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -9039,9 +9039,10 @@ void SOLDIERTYPE::BeginSoldierClimbWindow( void ) this->usPendingAnimation = JUMPWINDOWS; } + // Flugente: should be fixed now, re-enable if not // Flugente: if an AI guy, end turn (weird endless clock syndrome) - if ( this->bTeam != OUR_TEAM ) - EndAIGuysTurn( this); + //if ( this->bTeam != OUR_TEAM ) + //EndAIGuysTurn( this); // Flugente: if we are jumping through an intact window, smash it during our animation if ( gGameExternalOptions.fCanJumpThroughClosedWindows ) @@ -15550,6 +15551,38 @@ UINT32 SOLDIERTYPE::GetSurrenderStrength() return value; } +// used for an enemy liberating fellow prisoners +BOOLEAN SOLDIERTYPE::FreePrisoner() +{ + // we can only free people we are facing + INT32 nextGridNoinSight = NewGridNo( this->sGridNo, DirectionInc( this->ubDirection ) ); + + UINT8 target = WhoIsThere2( nextGridNoinSight, this->pathing.bLevel ); + + // is there somebody? + if ( target != NOBODY ) + { + SOLDIERTYPE* pSoldier = MercPtrs[target]; + + // if he is captured, free him! + // note that this would also work for prisoner civs that we spawn in our prisons. All needed would be commanding the AI to get there + if ( pSoldier->bSoldierFlagMask & (SOLDIER_POW|SOLDIER_POW_PRISON) ) + { + pSoldier->bSoldierFlagMask &= ~(SOLDIER_POW|SOLDIER_POW_PRISON); + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_X_FREES_Y], this->GetName(), pSoldier->GetName() ); + + // alert both soldiers + this->aiData.bAlertStatus = min(this->aiData.bAlertStatus, STATUS_RED); + pSoldier->aiData.bAlertStatus = min(pSoldier->aiData.bAlertStatus, STATUS_RED); + + return TRUE; + } + } + + return FALSE; +} + // Flugente: scuba gear BOOLEAN SOLDIERTYPE::UsesScubaGear() { diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index febc5cf2..6f0b1599 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -1539,6 +1539,7 @@ public: // Flugente: prisoner system BOOLEAN CanProcessPrisoners(); UINT32 GetSurrenderStrength(); + BOOLEAN FreePrisoner(); // used for an enemy liberating fellow prisoners // Flugente: scuba gear BOOLEAN UsesScubaGear(); diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 357159ce..76fa37f3 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -2271,9 +2271,17 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) case AI_ACTION_JUMP_WINDOW: { pSoldier->BeginSoldierClimbWindow(); + ActionDone( pSoldier ); } break; + case AI_ACTION_FREE_PRISONER: + { + pSoldier->FreePrisoner(); + 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 5d3a41fe..651bbf9d 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -585,6 +585,10 @@ BOOLEAN IsActionAffordable(SOLDIERTYPE *pSoldier) break; + case AI_ACTION_FREE_PRISONER: + bMinPointsNeeded = APBPConstants[AP_HANDCUFF]; + break; + default: #ifdef BETAVERSION //NumMessage("AffordableAction - Illegal action type = ",pSoldier->aiData.bAction); diff --git a/TacticalAI/DecideAction.cpp b/TacticalAI/DecideAction.cpp index 72a84e0d..0829ff7f 100644 --- a/TacticalAI/DecideAction.cpp +++ b/TacticalAI/DecideAction.cpp @@ -914,13 +914,20 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier) } } + //////////////////////////////////////////////////////////////////////////// + // IF YOU SEE CAPTURED FRIENDS, FREE THEM! + //////////////////////////////////////////////////////////////////////////// + // Flugente: if we see one of our buddies in handcuffs, its a clear sign of enemy activity! - if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM ) + if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM && !gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition ) { - UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 10, ENEMY_TEAM, SOLDIER_POW ); + UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW ); if ( ubPerson != NOBODY ) + { + // raise alarm! return( AI_ACTION_RED_ALERT ); + } } } //ddd} @@ -1514,13 +1521,56 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier) return(AI_ACTION_NONE); } - // Flugente: if we see one of our buddies in handcuffs, its a clear sign of enemy activity! - if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM ) + if( gGameExternalOptions.bNewTacticalAIBehavior ) { - UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 10, ENEMY_TEAM, SOLDIER_POW ); + //////////////////////////////////////////////////////////////////////////// + // IF YOU SEE CAPTURED FRIENDS, FREE THEM! + //////////////////////////////////////////////////////////////////////////// - if ( ubPerson != NOBODY ) - return( AI_ACTION_RED_ALERT ); + // Flugente: if we see one of our buddies in handcuffs, its a clear sign of enemy activity! + // Flugente: if we see one of our buddies captured, it is a clear sign of enemy activity! + if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM ) + { + UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW ); + + if ( ubPerson != NOBODY ) + { + // if we are close, we can release this guy + // possible only if not handcuffed (binders can be opened, handcuffs not) + if ( !HasItemFlag( (&(MercPtrs[ubPerson]->inv[HANDPOS]))->usItem, HANDCUFFS ) ) + { + if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 ) + { + // see if we are facing this person + UINT8 ubDesiredMercDir = atan8(CenterX(pSoldier->sGridNo),CenterY(pSoldier->sGridNo),CenterX(MercPtrs[ubPerson]->sGridNo),CenterY(MercPtrs[ubPerson]->sGridNo)); + + // if not already facing in that direction, + if ( pSoldier->ubDirection != ubDesiredMercDir ) + { + pSoldier->aiData.usActionData = ubDesiredMercDir; + + return( AI_ACTION_CHANGE_FACING ); + } + + return(AI_ACTION_FREE_PRISONER); + } + else + { + pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0); + + if (!TileIsOutOfBounds(pSoldier->aiData.usActionData)) + { + return(AI_ACTION_SEEK_FRIEND); + } + } + } + else if ( !gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition ) + { + // raise alarm! + return( AI_ACTION_RED_ALERT ); + } + } + } } //////////////////////////////////////////////////////////////////////////// @@ -2724,6 +2774,52 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK) } */ + if( gGameExternalOptions.bNewTacticalAIBehavior ) + { + //////////////////////////////////////////////////////////////////////////// + // IF YOU SEE CAPTURED FRIENDS, FREE THEM! + //////////////////////////////////////////////////////////////////////////// + + // Flugente: if we see one of our buddies captured, it is a clear sign of enemy activity! + if ( gGameExternalOptions.fAllowPrisonerSystem && pSoldier->bTeam == ENEMY_TEAM ) + { + UINT8 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 20, ENEMY_TEAM, SOLDIER_POW ); + + if ( ubPerson != NOBODY ) + { + // if we are close, we can release this guy + // possible only if not handcuffed (binders can be opened, handcuffs not) + if ( !HasItemFlag( (&(MercPtrs[ubPerson]->inv[HANDPOS]))->usItem, HANDCUFFS ) ) + { + if ( PythSpacesAway(pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo) < 2 ) + { + // see if we are facing this person + UINT8 ubDesiredMercDir = atan8(CenterX(pSoldier->sGridNo),CenterY(pSoldier->sGridNo),CenterX(MercPtrs[ubPerson]->sGridNo),CenterY(MercPtrs[ubPerson]->sGridNo)); + + // if not already facing in that direction, + if ( pSoldier->ubDirection != ubDesiredMercDir ) + { + pSoldier->aiData.usActionData = ubDesiredMercDir; + + return( AI_ACTION_CHANGE_FACING ); + } + + return(AI_ACTION_FREE_PRISONER); + } + else + { + pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards(pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0); + + if (!TileIsOutOfBounds(pSoldier->aiData.usActionData)) + { + return(AI_ACTION_SEEK_FRIEND); + } + } + } + } + } + } + //////////////////////////////////////////////////////////////////////////// // WHEN IN THE LIGHT, GET OUT OF THERE! //////////////////////////////////////////////////////////////////////////// diff --git a/TacticalAI/ai.h b/TacticalAI/ai.h index e7252ad3..8cc8b111 100644 --- a/TacticalAI/ai.h +++ b/TacticalAI/ai.h @@ -101,7 +101,8 @@ typedef enum AI_ACTION_RELOAD_GUN, - AI_ACTION_JUMP_WINDOW, // added by Flugente: jump through a window + AI_ACTION_JUMP_WINDOW, // added by Flugente: jump through a window + AI_ACTION_FREE_PRISONER, // added by Flugente: free a prisoner } ActionType; diff --git a/Utils/Text.h b/Utils/Text.h index 7f34c3f5..ced012be 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -750,6 +750,7 @@ enum STR_PRISONER_REFUSE_SURRENDER, STR_PRISONER_REFUSE_TAKE_PRISONERS, SRT_PRISONER_INI_SETTING_OFF, + STR_PRISONER_X_FREES_Y, TEXT_NUM_PRISONER_STR }; diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index aa633493..142a12c3 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -7568,6 +7568,7 @@ STR16 szPrisonerTextStr[]= L"这敌人丫宁死不从!",//L"The enemy refuses to surrender!", L"敌人不肯拿你当囚犯 - 他们宁愿你死!", //L"The enemy refuses to take you as prisoners - they prefer you dead!", L"这些可以在 INI 设置关闭。", // L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 58803f63..e134a042 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -7567,6 +7567,7 @@ STR16 szPrisonerTextStr[]= L"The enemy refuses to surrender!", L"The enemy refuses to take you as prisoners - they prefer you dead!", // TODO.Translate L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= // TODO.Translate diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index b66b88fe..73e0df3f 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -7554,6 +7554,7 @@ STR16 szPrisonerTextStr[]= L"The enemy refuses to surrender!", L"The enemy refuses to take you as prisoners - they prefer you dead!", L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 651a5d44..5a88167d 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -7551,6 +7551,7 @@ STR16 szPrisonerTextStr[]= L"The enemy refuses to surrender!", L"The enemy refuses to take you as prisoners - they prefer you dead!", // TODO.Translate L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= // TODO.Translate diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 2b17bf4a..e9f38774 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -7377,6 +7377,7 @@ STR16 szPrisonerTextStr[]= L"Der Gegner weigert sich aufzugeben!", L"Der Feind weigert sich, Sie als Gefangenen zu nehmen - Er möchte Sie tod sehen!", L"Dieses Verhalten ist ausgeschaltet in der ja2_options.ini Datei.", + L"%s hat %s befreit!", }; STR16 szMTATextStr[]= diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index b5288b09..959ea633 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -7553,6 +7553,7 @@ STR16 szPrisonerTextStr[]= L"The enemy refuses to surrender!", L"The enemy refuses to take you as prisoners - they prefer you dead!", // TODO.Translate L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= // TODO.Translate diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 0a21e111..e4ea6533 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -7573,6 +7573,7 @@ STR16 szPrisonerTextStr[]= L"The enemy refuses to surrender!", L"The enemy refuses to take you as prisoners - they prefer you dead!", // TODO.Translate L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= // TODO.Translate diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 0c6082bf..917db79e 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -7553,6 +7553,7 @@ STR16 szPrisonerTextStr[]= // TODO.Translate L"The enemy refuses to surrender!", L"The enemy refuses to take you as prisoners - they prefer you dead!", L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= // TODO.Translate diff --git a/Utils/_TaiwaneseText.cpp b/Utils/_TaiwaneseText.cpp index 8b445492..e1d8d0f5 100644 --- a/Utils/_TaiwaneseText.cpp +++ b/Utils/_TaiwaneseText.cpp @@ -7571,6 +7571,7 @@ STR16 szPrisonerTextStr[]= L"The enemy refuses to surrender!", L"The enemy refuses to take you as prisoners - they prefer you dead!", // TODO.Translate L"This behaviour is set OFF in your ini settings.", + L"%s has freed %s!", }; STR16 szMTATextStr[]= // TODO.Translate