From 346e7890f54b9233215642a00b63e92932b4ddfd Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sat, 9 Oct 2021 13:26:02 +0200 Subject: [PATCH 01/19] Script actions 99-109 All the remaining from PR 296. --- README.md | 2 +- docs/New-or-Enhanced-Logics.md | 30 ++++- docs/Whats-New.md | 6 +- src/Ext/Rules/Body.cpp | 2 +- src/Ext/Script/Body.cpp | 229 ++++++++++++++++++++++++++++++++- src/Ext/Script/Body.h | 4 + 6 files changed, 263 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b551bed9b0..411bb6d3cb 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ Credits - **secsome (SEC-SOME)** - debug info dump hotkey, refactoring & porting of Ares helper code, introducing more Ares-derived stuff, disguise removal warhead, Mind Control removal warhead, Mind Control enhancement, shields, AnimList.PickRandom, MoveToCell fix, unlimited waypoints, Build At trigger action buildup anim fix, Undeploy building into a unit plays `EVA_NewRallyPointEstablished` fix, custom ore gathering anim, TemporaryClass related crash, Retry dialog on mission failure, Default disguise for individual InfantryTypes, PowerPlant Enhancer - **Otamaa (Fahroni, BoredEXE)** - help with CellSpread, ported and fixed custom RadType code, togglable ElectricBolt bolts, customizable Chrono Locomotor properties per TechnoClass, DebrisMaximums fixes, Anim-to-Unit, NotHuman anim sequences improvements, Customizable OpenTopped Properties, hooks for ScriptType Actions 92 & 93 - **E1 Elite** - TileSet 255 and above bridge repair fix -- **FS-21** - Dump Object Info enhancements, Powered.KillSpawns, Spawner.LimitRange, ScriptType Actions 71, 72, 73, 74 to 81, 92, 93, 94, 95 to 98, 112, MC deployer fixes, help with docs, Automatic Passenger Deletion +- **FS-21** - Dump Object Info enhancements, Powered.KillSpawns, Spawner.LimitRange, ScriptType Actions 71 to 109, 112, MC deployer fixes, help with docs, Automatic Passenger Deletion - **AutoGavy** - interceptor logic, warhead critical damage system - **ChrisLv_CN** - interceptor logic, LaserTrails, laser fixes, general assistance (work relicensed under [following permission](images/ChrisLv-relicense.png)) - **Xkein** - general assistance, YRpp edits diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index efd8c41ed2..bc923515b6 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -631,16 +631,16 @@ In `aimd.ini`: x=83,n ``` -### `84-91` `AITargetTypes` Attack Action +### `84-91`, `104-105` `AITargetTypes` Attack Action -- These Actions instruct the TeamType to use the TaskForce to approach and attack the target specified by the second parameter which is an index of a modder-defined group from `AITargetTypess`. Look at the tables below for the possible Actions (first parameter value) and Arguments (the second parameter value). +- These Actions instruct the TeamType to use the TaskForce to approach and attack the target specified by the second parameter which is an index of a modder-defined group from `AITargetTypes`. - For threat-based attack actions `TargetSpecialThreatCoefficientDefault` and `EnemyHouseThreatBonus` tags from `rulesmd.ini` are accounted. - All Aircrafts that attack other air units will end the script. This behavior is intentional because without it aircrafts had some bugs that weren't fixable at the time of developing the feature. In `aimd.ini`: ```ini [SOMESCRIPTTYPE] ; ScriptType -x=i,n ; where 84 <= i <= 91 +x=i,n ; where 84 <= i <= 91 or 104 <= i <= 105 ``` | *Action* | *Argument* | *Repeats* | *Target Priority* | *Description* | @@ -653,6 +653,8 @@ x=i,n ; where 84 <= i <= 91 89 | `AITargetTypes` index# | No | Farther, higher threat | Ends when a team member kill the designated target | 90 | `AITargetTypes` index# | No | Closer | Ends when a team member kill the designated target | 91 | `AITargetTypes` index# | No | Farther | Ends when a team member kill the designated target | +104 | `AITargetTypes` index# | Yes | Closer | Picks 1 random target from the list | +105 | `AITargetTypes` index# | Yes | Farther | Picks 1 random target from the list | - The second parameter with a 0-based index for the `AITargetTypes` section specifies the list of possible `VehicleTypes`, `AircraftTypes`, `InfantryTypes` and `BuildingTypes` that can be evaluated. The new `AITargetTypes` section must be declared in `rulesmd.ini` for making this script work: @@ -704,14 +706,14 @@ In `rulesmd.ini`: ; ... ``` -### `95-98` Moving Team to techno location +### `95-98`, `106-109` Moving Team to techno location - These Actions instructs the TeamType to use the TaskForce to approach the target specified by the second parameter. Look at the tables below for the possible Actions (first parameter value). In `aimd.ini`: ```ini [SOMESCRIPTTYPE] ; ScriptType -x=i,n ; where 95 <= i <= 98 +x=i,n ; where 95 <= i <= 98 or 106 <= i <= 109 ``` | *Action* | *Argument* | Target Owner | *Target Priority* | *Description* | @@ -720,6 +722,24 @@ x=i,n ; where 95 <= i <= 98 96 | Target Type# | Enemy | Farther, higher threat | | 97 | Target Type# | Friendly | Closer | | 98 | Target Type# | Friendly | Farther | | +99 | [AITargetType] index# | Enemy | Closer, higher threat | | +100 | [AITargetType] index# | Enemy | Farther, higher threat | | +101 | [AITargetType] index# | Friendly | Closer | | +102 | [AITargetType] index# | Friendly | Farther | | +106 | [AITargetType] index# | Enemy | Closer | Picks 1 random target from the selected list | +107 | [AITargetType] index# | Enemy | Farther | Picks 1 random target from the selected list | +108 | [AITargetType] index# | Friendly | Closer | Picks 1 random target from the selected list | +109 | [AITargetType] index# | Friendly | Farther | Picks 1 random target from the selected list | + +### `103` Modify Target Distance + +- By default Movement actions `95-102` & `106-109` ends when the Team Leader reaches a distance declared in rulesmd.ini called CloseEnough. When this action is executed before the Movement actions `95-102` overwrites CloseEnough value. This action works only the first time and CloseEnough will be used again the next Movement action. + +In `aimd.ini`: +```ini +[SOMESCRIPTTYPE] ; ScriptType +x=103,n +``` ### `112` Regroup temporarily around the Team Leader diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 6f20ab68a9..34d0932dbc 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -52,13 +52,15 @@ New: - XDrawOffset for animations (by Morton) - Customizable OpenTopped properties (by Otamaa) - Automatic Passenger Deletion (by FS-21) -- Script Action 74 to 81 and 84 to 91 for new AI attacks (by FS-21) +- Script Action 74 to 81, 84 to 91 and 104 to 105 for new AI attacks (by FS-21) - Script Actions 82 & 83 for modifying AI Trigger Current Weight (by FS-21) - Script Action 92 for waiting & repeat the same new AI attack if no target was found (by FS-21) - Script Action 93 that modifies the Team's Trigger Weight when ends the new attack action (by FS-21) - Script Action 94 for picking a random script from a list (by FS-21) +- Script Action 95 to 102 and 106 to 109 for new AI movements towards certain objects (by FS-21) +- Script Action 103 that Modify Target Distance in the new move actions (by FS-21) - Script Action 112 to regroup temporarily around the Team Leader (by FS-21) -- Script Action 95 to 98 for new AI movements towards certain objects (by FS-21) + - ObjectInfo now shows, current Target and AI Trigger data (by FS-21) Vanilla fixes: diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 8f2ce0062b..9938945b8e 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -72,7 +72,7 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->Pips_Shield_Buildings.Read(exINI, "AudioVisual", "Pips.Shield.Building"); this->MissingCameo.Read(pINI, "AudioVisual", "MissingCameo"); - // Section AITargetType + // Section AITargetTypes int itemsCount = pINI->GetKeyCount(sectionAITargetTypes); for (int i = 0; i < itemsCount; ++i) { diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 2f2003c7e5..c83aef63c4 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -118,6 +118,8 @@ void ScriptExt::ProcessAction(TeamClass* pTeam) case 93: ScriptExt::TeamWeightReward(pTeam, 0); break; + case 94: + ScriptExt::PickRandomScript(pTeam, -1); case 95: // Move to the closest enemy target ScriptExt::Mission_Move(pTeam, 2, false, -1, -1); @@ -134,6 +136,49 @@ void ScriptExt::ProcessAction(TeamClass* pTeam) // Move to the farther friendly target ScriptExt::Mission_Move(pTeam, 3, true, -1, -1); break; + case 99: + // Move to the closest specific enemy target + ScriptExt::Mission_Move_List(pTeam, 2, false, -1); + break; + case 100: + // Move to the farther specific enemy target + ScriptExt::Mission_Move_List(pTeam, 3, false, -1); + case 101: + // Move to the closest specific friendly target + ScriptExt::Mission_Move_List(pTeam, 2, true, -1); + break; + case 102: + // Move to the farther specific friendly target + ScriptExt::Mission_Move_List(pTeam, 3, true, -1); + break; + case 103: + // AISafeDistance equivalent for Mission_Move() + ScriptExt::SetCloseEnoughDistance(pTeam, -1); + break; + case 104: + // Pick 1 closer random objective from specific list for attacking it + ScriptExt::Mission_Attack_List1Random(pTeam, true, 2, -1); + break; + case 105: + // Pick 1 farther random objective from specific list for attacking it + ScriptExt::Mission_Attack_List1Random(pTeam, true, 3, -1); + break; + case 106: + // Pick 1 closer enemy random objective from specific list for moving to it + ScriptExt::Mission_Move_List1Random(pTeam, 2, false, -1, -1); + break; + case 107: + // Pick 1 farther enemy random objective from specific list for moving to it + ScriptExt::Mission_Move_List1Random(pTeam, 3, false, -1, -1); + break; + case 108: + // Pick 1 closer friendly random objective from specific list for moving to it + ScriptExt::Mission_Move_List1Random(pTeam, 2, true, -1, -1); + break; + case 109: + // Pick 1 farther friendly random objective from specific list for moving to it + ScriptExt::Mission_Move_List1Random(pTeam, 3, true, -1, -1); + break; case 112: ScriptExt::Mission_Gather_NearTheLeader(pTeam, -1); break; @@ -1174,7 +1219,7 @@ bool ScriptExt::EvaluateObjectWithMask(TechnoClass *pTechno, int mask, int attac double distanceToTarget = 0; TechnoClass* pTarget = nullptr; - // Special case: validate target if is part of a technos list in [AITargetType] section + // Special case: validate target if is part of a technos list in [AITargetTypes] section if (attackAITargetType >= 0 && RulesExt::Global()->AITargetTypesLists.Count > 0) { DynamicVectorClass objectsList = RulesExt::Global()->AITargetTypesLists.GetItem(attackAITargetType); @@ -2317,3 +2362,185 @@ TechnoClass* ScriptExt::FindBestObject(TechnoClass *pTechno, int method, int cal return bestObject; } + +void ScriptExt::Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, int calcThreatMode, int attackAITargetType) +{ + bool selected = false; + int idxSelectedObject = -1; + + auto pTeamData = TeamExt::ExtMap.Find(pTeam); + if (pTeamData && pTeamData->IdxSelectedObjectFromAIList >= 0) + { + idxSelectedObject = pTeamData->IdxSelectedObjectFromAIList; + selected = true; + } + + if (attackAITargetType < 0) + attackAITargetType = pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Argument; + + if (attackAITargetType >= 0 + && attackAITargetType < RulesExt::Global()->AITargetTypesLists.Count) + { + DynamicVectorClass objectsList = RulesExt::Global()->AITargetTypesLists.GetItem(attackAITargetType); + + if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) + { + DynamicVectorClass validIndexes; + + // Finding the objects from the list that actually exists in the map + for (int i = 0; i < TechnoClass::Array->Count; i++) + { + auto itemFromTechnoList = TechnoClass::Array->GetItem(i); + auto itemTypeFromTechnoList = TechnoClass::Array->GetItem(i)->GetTechnoType(); + bool found = false; + + for (int j = 0; j < objectsList.Count && !found; j++) + { + auto objectFromList = objectsList.GetItem(j); + + if (itemTypeFromTechnoList == objectFromList + && itemFromTechnoList->IsAlive + && !itemFromTechnoList->InLimbo + && itemFromTechnoList->IsOnMap + && !itemFromTechnoList->Absorbed + && (!pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList) + || (pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList) + && itemFromTechnoList->IsMindControlled() + && !pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList->MindControlledBy)))) + { + validIndexes.AddItem(j); + found = true; + } + } + } + + if (validIndexes.Count > 0) + { + idxSelectedObject = validIndexes.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validIndexes.Count - 1)); + selected = true; + Debug::Log("DEBUG: [%s] [%s] Picked a random Techno from the list index [AITargetTypes][%d][%d] = %s\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, idxSelectedObject, objectsList.GetItem(idxSelectedObject)->ID); + } + } + + if (selected) + pTeamData->IdxSelectedObjectFromAIList = idxSelectedObject; + + Mission_Attack(pTeam, repeatAction, calcThreatMode, attackAITargetType, idxSelectedObject); + } + + // This action finished + if (!selected) + { + pTeam->StepCompleted = true; + Debug::Log("DEBUG: [%s] [%s] Failed to pick a random Techno from the list index [AITargetTypes][%d]!\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType); + } +} + +void ScriptExt::Mission_Move_List(TeamClass *pTeam, int calcThreatMode, bool pickAllies, int attackAITargetType) +{ + auto pTeamData = TeamExt::ExtMap.Find(pTeam); + if (pTeamData) + pTeamData->IdxSelectedObjectFromAIList = -1; + + if (attackAITargetType < 0) + attackAITargetType = pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Argument; + + if (RulesExt::Global()->AITargetTypesLists.Count > 0 + && RulesExt::Global()->AITargetTypesLists.GetItem(attackAITargetType).Count > 0) + { + Mission_Move(pTeam, calcThreatMode, pickAllies, attackAITargetType, -1); + } +} + +void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, bool pickAllies, int attackAITargetType, int idxAITargetTypeItem = -1) +{ + bool selected = false; + int idxSelectedObject = -1; + + auto pTeamData = TeamExt::ExtMap.Find(pTeam); + if (pTeamData && pTeamData->IdxSelectedObjectFromAIList >= 0) + { + idxSelectedObject = pTeamData->IdxSelectedObjectFromAIList; + selected = true; + } + + if (attackAITargetType < 0) + attackAITargetType = pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Argument; + + if (attackAITargetType >= 0 + && attackAITargetType < RulesExt::Global()->AITargetTypesLists.Count) + { + DynamicVectorClass objectsList = RulesExt::Global()->AITargetTypesLists.GetItem(attackAITargetType); + + // Still no random target selected + if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) + { + DynamicVectorClass validIndexes; + + // Finding the objects from the list that actually exists in the map + for (int i = 0; i < TechnoClass::Array->Count; i++) + { + auto itemFromTechnoList = TechnoClass::Array->GetItem(i); + auto itemTypeFromTechnoList = TechnoClass::Array->GetItem(i)->GetTechnoType(); + bool found = false; + + for (int j = 0; j < objectsList.Count && !found; j++) + { + auto objectFromList = objectsList.GetItem(j); + + if (itemTypeFromTechnoList == objectFromList + && itemFromTechnoList->IsAlive + && !itemFromTechnoList->InLimbo + && itemFromTechnoList->IsOnMap + && !itemFromTechnoList->Absorbed + && ((pickAllies + && pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList)) + || (!pickAllies + && !pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList)))) + { + validIndexes.AddItem(j); + found = true; + } + } + } + + if (validIndexes.Count > 0) + { + idxSelectedObject = validIndexes.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validIndexes.Count - 1)); + selected = true; + Debug::Log("DEBUG: [%s] [%s] Picked a random Techno from the list index [AITargetTypes][%d][%d] = %s\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, idxSelectedObject, objectsList.GetItem(idxSelectedObject)->ID); + } + } + + if (selected) + pTeamData->IdxSelectedObjectFromAIList = idxSelectedObject; + + Mission_Move(pTeam, calcThreatMode, pickAllies, attackAITargetType, idxSelectedObject); + } + + // This action finished + if (!selected) + { + pTeam->StepCompleted = true; + Debug::Log("DEBUG: [%s] [%s] Failed to pick a random Techno from the list index [AITargetTypes][%d]!\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType); + } +} + +void ScriptExt::SetCloseEnoughDistance(TeamClass *pTeam, double distance = -1) +{ + // This passive method replaces the CloseEnough value from rulesmd.ini by a custom one. Used by Mission_Move() + if (distance <= 0) + distance = pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Argument; + + auto pTeamData = TeamExt::ExtMap.Find(pTeam); + if (pTeamData) + { + if (distance > 0) + pTeamData->CloseEnough = distance; + } + + // This action finished + pTeam->StepCompleted = true; + + return; +} diff --git a/src/Ext/Script/Body.h b/src/Ext/Script/Body.h index 6f34fefa20..b76a8da196 100644 --- a/src/Ext/Script/Body.h +++ b/src/Ext/Script/Body.h @@ -64,6 +64,10 @@ class ScriptExt static TechnoClass* FindBestObject(TechnoClass *pTechno, int method, int calcThreatMode, bool pickAllies, int attackAITargetType, int idxAITargetTypeItem); static void Mission_Attack_List(TeamClass *pTeam, bool repeatAction, int calcThreatMode, int attackAITargetType); + static void Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, int calcThreatMode, int attackAITargetType); + static void Mission_Move_List(TeamClass *pTeam, int calcThreatMode, bool pickAllies, int attackAITargetType); + static void Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, bool pickAllies, int attackAITargetType, int idxAITargetTypeItem); + static void SetCloseEnoughDistance(TeamClass *pTeam, double distance); static ExtContainer ExtMap; From 9e2435e5629bf05097b6973390031bf3950cbdc3 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sat, 9 Oct 2021 14:15:13 +0200 Subject: [PATCH 02/19] small fix --- docs/New-or-Enhanced-Logics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index bc923515b6..257a594742 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -633,7 +633,7 @@ x=83,n ### `84-91`, `104-105` `AITargetTypes` Attack Action -- These Actions instruct the TeamType to use the TaskForce to approach and attack the target specified by the second parameter which is an index of a modder-defined group from `AITargetTypes`. +- These Actions instruct the TeamType to use the TaskForce to approach and attack the target specified by the second parameter which is an index of a modder-defined group from `AITargetTypess`. Look at the tables below for the possible Actions (first parameter value) and Arguments (the second parameter value). - For threat-based attack actions `TargetSpecialThreatCoefficientDefault` and `EnemyHouseThreatBonus` tags from `rulesmd.ini` are accounted. - All Aircrafts that attack other air units will end the script. This behavior is intentional because without it aircrafts had some bugs that weren't fixable at the time of developing the feature. From 4d68d9aba14c7a2eb7e32206168040bae3a3355c Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sat, 9 Oct 2021 16:29:04 +0200 Subject: [PATCH 03/19] Changes suggested by the last review --- src/Ext/Script/Body.cpp | 72 +++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index c83aef63c4..8a00662ac5 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -2385,38 +2385,36 @@ void ScriptExt::Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) { - DynamicVectorClass validIndexes; + DynamicVectorClass validItems; // Finding the objects from the list that actually exists in the map - for (int i = 0; i < TechnoClass::Array->Count; i++) + for (const auto& pTechno : *TechnoClass::Array) { - auto itemFromTechnoList = TechnoClass::Array->GetItem(i); - auto itemTypeFromTechnoList = TechnoClass::Array->GetItem(i)->GetTechnoType(); + auto pTechnoType = pTechno->GetTechnoType(); bool found = false; - for (int j = 0; j < objectsList.Count && !found; j++) + for (const auto& pObject : objectsList) { - auto objectFromList = objectsList.GetItem(j); - - if (itemTypeFromTechnoList == objectFromList - && itemFromTechnoList->IsAlive - && !itemFromTechnoList->InLimbo - && itemFromTechnoList->IsOnMap - && !itemFromTechnoList->Absorbed - && (!pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList) - || (pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList) - && itemFromTechnoList->IsMindControlled() - && !pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList->MindControlledBy)))) + if (pTechnoType == pObject + && pTechno->IsAlive + && !pTechno->InLimbo + && pTechno->IsOnMap + && !pTechno->Absorbed + && (!pTeam->FirstUnit->Owner->IsAlliedWith(pTechno) + || (pTeam->FirstUnit->Owner->IsAlliedWith(pTechno) + && pTechno->IsMindControlled() + && !pTeam->FirstUnit->Owner->IsAlliedWith(pTechno->MindControlledBy)))) { - validIndexes.AddItem(j); + validItems.AddItem(pTechno); found = true; } } } - if (validIndexes.Count > 0) + if (validItems.Count > 0) { - idxSelectedObject = validIndexes.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validIndexes.Count - 1)); + auto selectedObject = validItems.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validItems.Count - 1)); + idxSelectedObject = validItems.GetItemIndex(&selectedObject); selected = true; Debug::Log("DEBUG: [%s] [%s] Picked a random Techno from the list index [AITargetTypes][%d][%d] = %s\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, idxSelectedObject, objectsList.GetItem(idxSelectedObject)->ID); } @@ -2475,38 +2473,36 @@ void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, b // Still no random target selected if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) { - DynamicVectorClass validIndexes; + DynamicVectorClass validItems; // Finding the objects from the list that actually exists in the map - for (int i = 0; i < TechnoClass::Array->Count; i++) + for (const auto& pTechno : *TechnoClass::Array) { - auto itemFromTechnoList = TechnoClass::Array->GetItem(i); - auto itemTypeFromTechnoList = TechnoClass::Array->GetItem(i)->GetTechnoType(); + auto pTechnoType = pTechno->GetTechnoType(); bool found = false; - for (int j = 0; j < objectsList.Count && !found; j++) + for (const auto& pObject : objectsList) { - auto objectFromList = objectsList.GetItem(j); - - if (itemTypeFromTechnoList == objectFromList - && itemFromTechnoList->IsAlive - && !itemFromTechnoList->InLimbo - && itemFromTechnoList->IsOnMap - && !itemFromTechnoList->Absorbed - && ((pickAllies - && pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList)) - || (!pickAllies - && !pTeam->FirstUnit->Owner->IsAlliedWith(itemFromTechnoList)))) + if (pTechnoType == pObject + && pTechno->IsAlive + && !pTechno->InLimbo + && pTechno->IsOnMap + && !pTechno->Absorbed + && (!pTeam->FirstUnit->Owner->IsAlliedWith(pTechno) + || (pTeam->FirstUnit->Owner->IsAlliedWith(pTechno) + && pTechno->IsMindControlled() + && !pTeam->FirstUnit->Owner->IsAlliedWith(pTechno->MindControlledBy)))) { - validIndexes.AddItem(j); + validItems.AddItem(pTechno); found = true; } } } - if (validIndexes.Count > 0) + if (validItems.Count > 0) { - idxSelectedObject = validIndexes.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validIndexes.Count - 1)); + auto selectedObject = validItems.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validItems.Count - 1)); + idxSelectedObject = validItems.GetItemIndex(&selectedObject); selected = true; Debug::Log("DEBUG: [%s] [%s] Picked a random Techno from the list index [AITargetTypes][%d][%d] = %s\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, idxSelectedObject, objectsList.GetItem(idxSelectedObject)->ID); } From 875fe9714dfabcf6f4285ecab8c2d6dfca13f5ea Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sat, 9 Oct 2021 20:21:34 +0200 Subject: [PATCH 04/19] Reverted some code that make crashes --- src/Ext/Script/Body.cpp | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 8a00662ac5..907f921846 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -2385,17 +2385,20 @@ void ScriptExt::Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) { - DynamicVectorClass validItems; + DynamicVectorClass validIndexes; // Finding the objects from the list that actually exists in the map - for (const auto& pTechno : *TechnoClass::Array) + for (int i = 0; i < TechnoClass::Array->Count; i++) { - auto pTechnoType = pTechno->GetTechnoType(); + auto pTechno = TechnoClass::Array->GetItem(i); + auto pTechnoType = TechnoClass::Array->GetItem(i)->GetTechnoType(); bool found = false; - for (const auto& pObject : objectsList) + for (int j = 0; j < objectsList.Count && !found; j++) { - if (pTechnoType == pObject + auto objectFromList = objectsList.GetItem(j); + + if (pTechnoType == objectFromList && pTechno->IsAlive && !pTechno->InLimbo && pTechno->IsOnMap @@ -2405,16 +2408,15 @@ void ScriptExt::Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, && pTechno->IsMindControlled() && !pTeam->FirstUnit->Owner->IsAlliedWith(pTechno->MindControlledBy)))) { - validItems.AddItem(pTechno); + validIndexes.AddItem(j); found = true; } } } - if (validItems.Count > 0) + if (validIndexes.Count > 0) { - auto selectedObject = validItems.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validItems.Count - 1)); - idxSelectedObject = validItems.GetItemIndex(&selectedObject); + idxSelectedObject = validIndexes.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validIndexes.Count - 1)); selected = true; Debug::Log("DEBUG: [%s] [%s] Picked a random Techno from the list index [AITargetTypes][%d][%d] = %s\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, idxSelectedObject, objectsList.GetItem(idxSelectedObject)->ID); } @@ -2473,17 +2475,20 @@ void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, b // Still no random target selected if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) { - DynamicVectorClass validItems; + DynamicVectorClass validIndexes; // Finding the objects from the list that actually exists in the map - for (const auto& pTechno : *TechnoClass::Array) + for (int i = 0; i < TechnoClass::Array->Count; i++) { - auto pTechnoType = pTechno->GetTechnoType(); + auto pTechno = TechnoClass::Array->GetItem(i); + auto pTechnoType = TechnoClass::Array->GetItem(i)->GetTechnoType(); bool found = false; - for (const auto& pObject : objectsList) + for (int j = 0; j < objectsList.Count && !found; j++) { - if (pTechnoType == pObject + auto objectFromList = objectsList.GetItem(j); + + if (pTechnoType == objectFromList && pTechno->IsAlive && !pTechno->InLimbo && pTechno->IsOnMap @@ -2493,16 +2498,15 @@ void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, b && pTechno->IsMindControlled() && !pTeam->FirstUnit->Owner->IsAlliedWith(pTechno->MindControlledBy)))) { - validItems.AddItem(pTechno); + validIndexes.AddItem(j); found = true; } } } - if (validItems.Count > 0) + if (validIndexes.Count > 0) { - auto selectedObject = validItems.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validItems.Count - 1)); - idxSelectedObject = validItems.GetItemIndex(&selectedObject); + idxSelectedObject = validIndexes.GetItem(ScenarioClass::Instance->Random.RandomRanged(0, validIndexes.Count - 1)); selected = true; Debug::Log("DEBUG: [%s] [%s] Picked a random Techno from the list index [AITargetTypes][%d][%d] = %s\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, idxSelectedObject, objectsList.GetItem(idxSelectedObject)->ID); } From 9b9db387d9df7ac0f583001c11d51b95534472fc Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sun, 10 Oct 2021 14:24:43 +0200 Subject: [PATCH 05/19] Fix small mistakes When restoring code I though those code blocks were the same. Added a possible bugfix that could interrumpt the attack script in very rare cases. --- src/Ext/Script/Body.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 907f921846..27bd5b2966 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -785,6 +785,10 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } } + auto pLeaderTarget = abstract_cast(pLeaderUnit->Target); + if (!pLeaderTarget && pTeam->Focus) + pTeam->Focus = nullptr; + pFocus = abstract_cast(pTeam->Focus); if (!pFocus && !bAircraftsWithoutAmmo) { @@ -2367,6 +2371,7 @@ void ScriptExt::Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, { bool selected = false; int idxSelectedObject = -1; + DynamicVectorClass validIndexes; auto pTeamData = TeamExt::ExtMap.Find(pTeam); if (pTeamData && pTeamData->IdxSelectedObjectFromAIList >= 0) @@ -2385,8 +2390,6 @@ void ScriptExt::Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) { - DynamicVectorClass validIndexes; - // Finding the objects from the list that actually exists in the map for (int i = 0; i < TechnoClass::Array->Count; i++) { @@ -2432,7 +2435,7 @@ void ScriptExt::Mission_Attack_List1Random(TeamClass *pTeam, bool repeatAction, if (!selected) { pTeam->StepCompleted = true; - Debug::Log("DEBUG: [%s] [%s] Failed to pick a random Techno from the list index [AITargetTypes][%d]!\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType); + Debug::Log("DEBUG: [%s] [%s] Failed to pick a random Techno from the list index [AITargetTypes][%d]! Valid Technos in the list: %d\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, validIndexes.Count); } } @@ -2456,6 +2459,7 @@ void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, b { bool selected = false; int idxSelectedObject = -1; + DynamicVectorClass validIndexes; auto pTeamData = TeamExt::ExtMap.Find(pTeam); if (pTeamData && pTeamData->IdxSelectedObjectFromAIList >= 0) @@ -2475,8 +2479,6 @@ void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, b // Still no random target selected if (idxSelectedObject < 0 && objectsList.Count > 0 && !selected) { - DynamicVectorClass validIndexes; - // Finding the objects from the list that actually exists in the map for (int i = 0; i < TechnoClass::Array->Count; i++) { @@ -2493,10 +2495,10 @@ void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, b && !pTechno->InLimbo && pTechno->IsOnMap && !pTechno->Absorbed - && (!pTeam->FirstUnit->Owner->IsAlliedWith(pTechno) - || (pTeam->FirstUnit->Owner->IsAlliedWith(pTechno) - && pTechno->IsMindControlled() - && !pTeam->FirstUnit->Owner->IsAlliedWith(pTechno->MindControlledBy)))) + && ((pickAllies + && pTeam->FirstUnit->Owner->IsAlliedWith(pTechno)) + || (!pickAllies + && !pTeam->FirstUnit->Owner->IsAlliedWith(pTechno)))) { validIndexes.AddItem(j); found = true; @@ -2522,7 +2524,7 @@ void ScriptExt::Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, b if (!selected) { pTeam->StepCompleted = true; - Debug::Log("DEBUG: [%s] [%s] Failed to pick a random Techno from the list index [AITargetTypes][%d]!\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType); + Debug::Log("DEBUG: [%s] [%s] Failed to pick a random Techno from the list index [AITargetTypes][%d]! Valid Technos in the list: %d\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, attackAITargetType, validIndexes.Count); } } From 5e8906a38d296df9637c517f438dccbce3c41a9e Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sun, 10 Oct 2021 15:53:42 +0200 Subject: [PATCH 06/19] restore missing hook 1 hook for saving the Team kills was lost during the merges. --- src/Ext/Script/Body.cpp | 8 ++++---- src/Ext/Techno/Hooks.cpp | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 27bd5b2966..6506361678 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -575,7 +575,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (!pTeam) { pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No team members alive)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument); + Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No team members alive)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -704,7 +704,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c // This action finished pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No Leader found | Exists Aircrafts without ammo | Team members have no weapons)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument); + Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No Leader found | Exists Aircrafts without ammo | Team members have no weapons)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -2017,7 +2017,7 @@ void ScriptExt::Mission_Move(TeamClass *pTeam, int calcThreatMode = 0, bool pick // This action finished pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No team members alive)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument); + Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No team members alive)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -2062,7 +2062,7 @@ void ScriptExt::Mission_Move(TeamClass *pTeam, int calcThreatMode = 0, bool pick // This action finished pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reasons: No Leader | Aircrafts without ammo)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument); + Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reasons: No Leader | Aircrafts without ammo)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 9556cf8b29..eccf814b9c 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -36,6 +36,17 @@ DEFINE_HOOK(0x6F42F7, TechnoClass_Init_SetLaserTrails, 0x2) return 0; } +DEFINE_HOOK(0x702E4E, TechnoClass_Save_Killer_Techno, 0x6) +{ + GET(TechnoClass*, pKiller, EDI); + GET(TechnoClass*, pVictim, ECX); + + if (pKiller && pVictim) + TechnoExt::ObjectKilledBy(pVictim, pKiller); + + return 0; +} + DEFINE_HOOK_AGAIN(0x7355C0, TechnoClass_Init_InitialStrength, 0x6) // UnitClass_Init DEFINE_HOOK_AGAIN(0x517D69, TechnoClass_Init_InitialStrength, 0x6) // InfantryClass_Init DEFINE_HOOK_AGAIN(0x442C7B, TechnoClass_Init_InitialStrength, 0x6) // BuildingClass_Init From f56995adb1a2007afec18af4d71a180be58ced98 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sun, 10 Oct 2021 23:25:05 +0200 Subject: [PATCH 07/19] post-merge fix in Readme file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 411bb6d3cb..993e46ace4 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ Credits - **secsome (SEC-SOME)** - debug info dump hotkey, refactoring & porting of Ares helper code, introducing more Ares-derived stuff, disguise removal warhead, Mind Control removal warhead, Mind Control enhancement, shields, AnimList.PickRandom, MoveToCell fix, unlimited waypoints, Build At trigger action buildup anim fix, Undeploy building into a unit plays `EVA_NewRallyPointEstablished` fix, custom ore gathering anim, TemporaryClass related crash, Retry dialog on mission failure, Default disguise for individual InfantryTypes, PowerPlant Enhancer - **Otamaa (Fahroni, BoredEXE)** - help with CellSpread, ported and fixed custom RadType code, togglable ElectricBolt bolts, customizable Chrono Locomotor properties per TechnoClass, DebrisMaximums fixes, Anim-to-Unit, NotHuman anim sequences improvements, Customizable OpenTopped Properties, hooks for ScriptType Actions 92 & 93 - **E1 Elite** - TileSet 255 and above bridge repair fix -- **FS-21** - Dump Object Info enhancements, Powered.KillSpawns, Spawner.LimitRange, ScriptType Actions 71 to 109, 112, MC deployer fixes, help with docs, Automatic Passenger Deletion +- **FS-21** - Dump Object Info enhancements, Powered.KillSpawns, Spawner.LimitRange, ScriptType Actions 71 to 109, 111, 112, MC deployer fixes, help with docs, Automatic Passenger Deletion - **AutoGavy** - interceptor logic, warhead critical damage system - **ChrisLv_CN** - interceptor logic, LaserTrails, laser fixes, general assistance (work relicensed under [following permission](images/ChrisLv-relicense.png)) - **Xkein** - general assistance, YRpp edits From a5f58fb339e92415e70ebdf733706a0f56d4c2cb Mon Sep 17 00:00:00 2001 From: FS-21 Date: Mon, 11 Oct 2021 18:26:03 +0200 Subject: [PATCH 08/19] Added the last Action 110 --- README.md | 2 +- docs/New-or-Enhanced-Logics.md | 18 ++++ docs/Whats-New.md | 1 + src/Ext/Script/Body.cpp | 183 ++++++++++++++++++++++++++------- src/Ext/Script/Body.h | 2 + src/Ext/Team/Body.cpp | 1 + src/Ext/Team/Body.h | 2 + 7 files changed, 173 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 993e46ace4..92ba60da97 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ Credits - **secsome (SEC-SOME)** - debug info dump hotkey, refactoring & porting of Ares helper code, introducing more Ares-derived stuff, disguise removal warhead, Mind Control removal warhead, Mind Control enhancement, shields, AnimList.PickRandom, MoveToCell fix, unlimited waypoints, Build At trigger action buildup anim fix, Undeploy building into a unit plays `EVA_NewRallyPointEstablished` fix, custom ore gathering anim, TemporaryClass related crash, Retry dialog on mission failure, Default disguise for individual InfantryTypes, PowerPlant Enhancer - **Otamaa (Fahroni, BoredEXE)** - help with CellSpread, ported and fixed custom RadType code, togglable ElectricBolt bolts, customizable Chrono Locomotor properties per TechnoClass, DebrisMaximums fixes, Anim-to-Unit, NotHuman anim sequences improvements, Customizable OpenTopped Properties, hooks for ScriptType Actions 92 & 93 - **E1 Elite** - TileSet 255 and above bridge repair fix -- **FS-21** - Dump Object Info enhancements, Powered.KillSpawns, Spawner.LimitRange, ScriptType Actions 71 to 109, 111, 112, MC deployer fixes, help with docs, Automatic Passenger Deletion +- **FS-21** - Dump Object Info enhancements, Powered.KillSpawns, Spawner.LimitRange, ScriptType Actions 71 to 112, MC deployer fixes, help with docs, Automatic Passenger Deletion - **AutoGavy** - interceptor logic, warhead critical damage system - **ChrisLv_CN** - interceptor logic, LaserTrails, laser fixes, general assistance (work relicensed under [following permission](images/ChrisLv-relicense.png)) - **Xkein** - general assistance, YRpp edits diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 183a952ad9..ce2d1b5a76 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -741,6 +741,24 @@ In `aimd.ini`: x=103,n ``` +### `110` Set Move Action End Mode + +- Sets how the Movement actions ends and jumps to the next line. This action works only the first time and CloseEnough will be used again the next Movement action. + +In `aimd.ini`: +```ini +[SOMESCRIPTTYPE] ; ScriptType +x=110,n +``` + +- The possible argument values are: + +| *Argument* | *Action ends when...* | +| :------: | :-------------------------------------------: | +0 | Team Leader reaches the minimum distance | +1 | One unit reaches the minimum distance | +2 | All team members reached the minimum distance | + ### `111` Un-register Team success - Is just the opposite effect of the script action `49,0`. Like if the Team failed. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index aeb7eee4d4..1cc88bca24 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -59,6 +59,7 @@ New: - Script Action 94 for picking a random script from a list (by FS-21) - Script Action 95 to 102 and 106 to 109 for new AI movements towards certain objects (by FS-21) - Script Action 103 that Modify Target Distance in the new move actions (by FS-21) +- Script Action 110 that Modify how ends the new move actions (by FS-21) - Script Action 111 that un-register Team success, is just the opposite effect of Action 49 (by FS-21) - Script Action 112 to regroup temporarily around the Team Leader (by FS-21) - ObjectInfo now shows current Target and AI Trigger data (by FS-21) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 5190d39c9d..8014794c1f 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -179,6 +179,10 @@ void ScriptExt::ProcessAction(TeamClass* pTeam) // Pick 1 farther friendly random objective from specific list for moving to it ScriptExt::Mission_Move_List1Random(pTeam, 3, true, -1, -1); break; + case 110: + // Set the condition for ending the Mission_Move Actions. + ScriptExt::SetMoveMissionEndMode(pTeam, -1); + break; case 111: // Un-register success for AITrigger weight adjustment (this is the opposite of 49,0) ScriptExt::UnregisterGreatSuccess(pTeam); @@ -2158,50 +2162,21 @@ void ScriptExt::Mission_Move(TeamClass *pTeam, int calcThreatMode = 0, bool pick } else { - double closeEnough = RulesClass::Instance->CloseEnough / 256.0; + int moveDestinationMode = 0; auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData && pTeamData->CloseEnough > 0) - closeEnough = pTeamData->CloseEnough; - - bool bForceNextAction = true; - - // Team already have a focused target - for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) + if (pTeamData) { - if (pUnit - && pUnit->IsAlive - && !pUnit->InLimbo) - { - if (!pUnit->Locomotor->Is_Moving_Now()) - pUnit->SetDestination(pFocus, false); - - if (pUnit->DistanceFrom(pUnit->Destination) / 256.0 > closeEnough) - { - bForceNextAction = false; - - if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo > 0) - pUnit->QueueMission(Mission::Move, false); - - continue; - } - else - { - if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo <= 0) - { - pUnit->QueueMission(Mission::Return, false); - pUnit->Mission_Enter(); - - continue; - } - } - } + moveDestinationMode = pTeamData->MoveMissionEndMode; } + bool bForceNextAction = ScriptExt::MoveMissionEndStatus(pTeam, pFocus, pLeaderUnit, moveDestinationMode); + if (bForceNextAction) { if (pTeamData) { + pTeamData->MoveMissionEndMode = 0; pTeamData->IdxSelectedObjectFromAIList = -1; if (pTeamData->CloseEnough >= 0) @@ -2556,3 +2531,141 @@ void ScriptExt::UnregisterGreatSuccess(TeamClass* pTeam) pTeam->AchievedGreatSuccess = false; pTeam->StepCompleted = true; // This action finished - FS-21 } + +void ScriptExt::SetMoveMissionEndMode(TeamClass* pTeam, int mode = 0) +{ + // This passive method replaces the CloseEnough value from rulesmd.ini by a custom one. Used by Mission_Move() + if (mode < 0 || mode > 2) + mode = pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Argument; + + auto pTeamData = TeamExt::ExtMap.Find(pTeam); + if (pTeamData) + { + if (mode >= 0 && mode <= 2) + pTeamData->MoveMissionEndMode = mode; + } + + // This action finished + pTeam->StepCompleted = true; + + return; +} + +bool ScriptExt::MoveMissionEndStatus(TeamClass* pTeam, TechnoClass* pFocus, FootClass* pLeader = nullptr, int mode = 0) +{ + if (!pTeam || !pFocus || mode < 0) + return false; + + if (mode != 2 && mode != 1 && !pLeader) + return false; + + double closeEnough = RulesClass::Instance->CloseEnough / 256.0; + + auto pTeamData = TeamExt::ExtMap.Find(pTeam); + if (pTeamData && pTeamData->CloseEnough > 0) + closeEnough = pTeamData->CloseEnough; + + bool bForceNextAction; + + if (mode == 2) + bForceNextAction = true; + else + bForceNextAction = false; + + // Team already have a focused target + for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) + { + if (pUnit + && pUnit->IsAlive + && !pUnit->InLimbo + && !pUnit->TemporalTargetingMe + && !pUnit->BeingWarpedOut) + { + if (!pUnit->Locomotor->Is_Moving_Now()) + pUnit->SetDestination(pFocus, false); + + if (mode == 2) + { + // Default mode: all members in range + if (pUnit->DistanceFrom(pUnit->Destination) / 256.0 > closeEnough) + { + bForceNextAction = false; + + if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo > 0) + pUnit->QueueMission(Mission::Move, false); + + continue; + } + else + { + if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo <= 0) + { + pUnit->QueueMission(Mission::Return, false); + pUnit->Mission_Enter(); + + continue; + } + } + } + else + { + if (mode == 1) + { + // Any member in range + if (pUnit->DistanceFrom(pUnit->Destination) / 256.0 > closeEnough) + { + if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo > 0) + pUnit->QueueMission(Mission::Move, false); + + continue; + } + else + { + bForceNextAction = true; + + if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo <= 0) + { + pUnit->QueueMission(Mission::Return, false); + pUnit->Mission_Enter(); + + continue; + } + } + } + else + { + // All other cases: Team Leader mode in range + if (pLeader) + { + if (pUnit->DistanceFrom(pUnit->Destination) / 256.0 > closeEnough) + { + if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo > 0) + pUnit->QueueMission(Mission::Move, false); + + continue; + } + else + { + if (pUnit == pLeader) + bForceNextAction = true; + + if (pUnit->GetTechnoType()->WhatAmI() == AbstractType::AircraftType && pUnit->Ammo <= 0) + { + pUnit->QueueMission(Mission::Return, false); + pUnit->Mission_Enter(); + + continue; + } + } + } + else + { + break; + } + } + } + } + } + + return bForceNextAction; +} diff --git a/src/Ext/Script/Body.h b/src/Ext/Script/Body.h index c5554d784d..57f3ad2749 100644 --- a/src/Ext/Script/Body.h +++ b/src/Ext/Script/Body.h @@ -69,9 +69,11 @@ class ScriptExt static void Mission_Move_List(TeamClass *pTeam, int calcThreatMode, bool pickAllies, int attackAITargetType); static void Mission_Move_List1Random(TeamClass *pTeam, int calcThreatMode, bool pickAllies, int attackAITargetType, int idxAITargetTypeItem); static void SetCloseEnoughDistance(TeamClass *pTeam, double distance); + static void SetMoveMissionEndMode(TeamClass* pTeam, int mode); static ExtContainer ExtMap; private: static void ModifyCurrentTriggerWeight(TeamClass* pTeam, bool forceJumpLine, double modifier); + static bool MoveMissionEndStatus(TeamClass* pTeam, TechnoClass* pFocus, FootClass* pLeader, int mode); }; diff --git a/src/Ext/Team/Body.cpp b/src/Ext/Team/Body.cpp index 690b026248..60640c5fd8 100644 --- a/src/Ext/Team/Body.cpp +++ b/src/Ext/Team/Body.cpp @@ -15,6 +15,7 @@ void TeamExt::ExtData::Serialize(T& Stm) .Process(this->IdxSelectedObjectFromAIList) .Process(this->CloseEnough) .Process(this->Countdown_RegroupAtLeader) + .Process(this->MoveMissionEndMode) ; } diff --git a/src/Ext/Team/Body.h b/src/Ext/Team/Body.h index 471c9f4213..e26b87da13 100644 --- a/src/Ext/Team/Body.h +++ b/src/Ext/Team/Body.h @@ -20,6 +20,7 @@ class TeamExt int IdxSelectedObjectFromAIList; double CloseEnough; int Countdown_RegroupAtLeader; + int MoveMissionEndMode; ExtData(TeamClass* OwnerObject) : Extension(OwnerObject) , WaitNoTargetAttempts(0) @@ -27,6 +28,7 @@ class TeamExt , IdxSelectedObjectFromAIList(-1) , CloseEnough(-1) , Countdown_RegroupAtLeader(-1) + , MoveMissionEndMode(0) { } virtual ~ExtData() = default; From 642dfaa723e4edadd3a7657aed94bdb5eec1cf5b Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sat, 16 Oct 2021 13:02:36 +0200 Subject: [PATCH 09/19] Fixed bug in Action Argument 20 & new argument 35 Argument 35 is the old Argument 20 that covers Land vehicle factory and Naval factory. Now Argument 20 ignores Naval factories --- src/Ext/Script/Body.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 8014794c1f..747649b0ca 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -1578,10 +1578,11 @@ bool ScriptExt::EvaluateObjectWithMask(TechnoClass *pTechno, int mask, int attac case 20: pTypeBuilding = abstract_cast(pTechnoType); - // Vehicle Factory + // Land Vehicle Factory if (!pTechno->Owner->IsNeutral() && pTechnoType->WhatAmI() == AbstractType::BuildingType - && pTypeBuilding->Factory == AbstractType::UnitType) + && pTypeBuilding->Factory == AbstractType::UnitType + && !pTypeBuilding->Naval) { return true; } @@ -1794,6 +1795,19 @@ bool ScriptExt::EvaluateObjectWithMask(TechnoClass *pTechno, int mask, int attac break; + case 35: + pTypeBuilding = abstract_cast(pTechnoType); + + // Land Vehicle Factory & Naval Factory + if (!pTechno->Owner->IsNeutral() + && pTechnoType->WhatAmI() == AbstractType::BuildingType + && pTypeBuilding->Factory == AbstractType::UnitType) + { + return true; + } + + break; + default: break; } From 4ba9b384df691e66d893263e006aa76e55d8d9f6 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Wed, 27 Oct 2021 15:17:38 +0200 Subject: [PATCH 10/19] Fixes and small improvements --- YRpp | 2 +- src/Ext/Script/Body.cpp | 137 ++++++++++++++++++++++------------------ 2 files changed, 77 insertions(+), 62 deletions(-) diff --git a/YRpp b/YRpp index a83c410285..310d5c6ec8 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit a83c410285d7194ff131a96fffe5a18f720c2a96 +Subproject commit 310d5c6ec8d78ea4bb416a2e0d9dbe24b945222f diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 747649b0ca..e13a69e33b 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -192,7 +192,12 @@ void ScriptExt::ProcessAction(TeamClass* pTeam) break; default: // Do nothing because or it is a wrong Action number or it is an Ares/YR action... - //Debug::Log("[%s] [%s] %d = %d,%d\n", pTeam->Type->ID, pScriptType->ID, pScript->idxCurrentLine, currentLineAction->Action, currentLineAction->Argument); + if (action > 70) + { + // Unknown new action. This action finished + pTeam->StepCompleted = true; + Debug::Log("[%s] [%s] (Line %d): Unknown Script Action: %d\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, pTeam->CurrentScript->idxCurrentLine, pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Action); + } break; } } @@ -556,6 +561,15 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c TechnoClass* pFocus = nullptr; bool agentMode = false; bool pacifistTeam = true; + auto pTeamData = TeamExt::ExtMap.Find(pTeam); + + if (!pTeamData) + { + pTeam->StepCompleted = true; + Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: ExtData found)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); + + return; + } // When the new target wasn't found it sleeps some few frames before the new attempt. This can save cycles and cycles of unnecessary executed lines. if (pTeam->GuardAreaTimer.TimeLeft != 0 || pTeam->GuardAreaTimer.InProgress()) @@ -566,12 +580,8 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c pTeam->GuardAreaTimer.Stop(); // Needed noWaitLoop = true; - auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) - { - if (pTeamData->WaitNoTargetAttempts > 0) - pTeamData->WaitNoTargetAttempts--; - } + if (pTeamData->WaitNoTargetAttempts > 0) + pTeamData->WaitNoTargetAttempts--; } else { @@ -588,20 +598,29 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c return; } + pFocus = abstract_cast(pTeam->Focus); + if (pFocus && pFocus->IsAlive + && !pFocus->InLimbo + && !pFocus->GetTechnoType()->Immune + && pFocus->IsOnMap + && !pFocus->Absorbed) + { } + else + { + pTeam->Focus = nullptr; + pFocus = nullptr; + } + for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) { auto pKillerTechnoData = TechnoExt::ExtMap.Find(pUnit); if (pKillerTechnoData && pKillerTechnoData->LastKillWasTeamTarget) { // Time for Team award check! (if set any) - auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) + if (pTeamData->NextSuccessWeightAward > 0) { - if (pTeamData->NextSuccessWeightAward > 0) - { - IncreaseCurrentTriggerWeight(pTeam, false, pTeamData->NextSuccessWeightAward); - pTeamData->NextSuccessWeightAward = 0; - } + IncreaseCurrentTriggerWeight(pTeam, false, pTeamData->NextSuccessWeightAward); + pTeamData->NextSuccessWeightAward = 0; } // Let's clean the Killer mess @@ -628,9 +647,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } } - //auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) - pTeamData->IdxSelectedObjectFromAIList = -1; + pTeamData->IdxSelectedObjectFromAIList = -1; // This action finished pTeam->StepCompleted = true; @@ -643,7 +660,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) { - if (pUnit && pUnit->IsAlive && pUnit->Health > 0 && !pUnit->InLimbo) + if (pUnit && pUnit->IsAlive && !pUnit->InLimbo) { auto pUnitType = pUnit->GetTechnoType(); if (pUnitType) @@ -678,20 +695,18 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } // Any Team member (infantry) is a special agent? If yes ignore some checks based on Weapons. - bool isAgent = false; if (pUnitType->WhatAmI() == AbstractType::InfantryType) { auto pTypeInf = abstract_cast(pUnitType); - if (pTypeInf->Agent || pTypeInf->Infiltrate || pTypeInf->Engineer) + if ((pTypeInf->Agent && pTypeInf->Infiltrate) || pTypeInf->Engineer) { agentMode = true; - isAgent = true; } } // The team leader will be used for selecting targets, if there are living Team Members then always exists 1 Leader. int unitLeadershipRating = pUnitType->LeadershipRating; - if (unitLeadershipRating > bestUnitLeadershipValue && (!pacifistUnit || isAgent)) + if (unitLeadershipRating > bestUnitLeadershipValue && (!pacifistUnit || agentMode)) { pLeaderUnit = pUnit; bestUnitLeadershipValue = unitLeadershipRating; @@ -700,15 +715,11 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } } - if (!pLeaderUnit || bAircraftsWithoutAmmo || pacifistTeam) + if (!pLeaderUnit || bAircraftsWithoutAmmo || (pacifistTeam && !agentMode)) { - auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) - { - pTeamData->IdxSelectedObjectFromAIList = -1; - if (pTeamData->WaitNoTargetAttempts != 0) - pTeamData->WaitNoTargetAttempts = 0; - } + pTeamData->IdxSelectedObjectFromAIList = -1; + if (pTeamData->WaitNoTargetAttempts != 0) + pTeamData->WaitNoTargetAttempts = 0; // This action finished pTeam->StepCompleted = true; @@ -793,11 +804,6 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } } - auto pLeaderTarget = abstract_cast(pLeaderUnit->Target); - if (!pLeaderTarget && pTeam->Focus) - pTeam->Focus = nullptr; - - pFocus = abstract_cast(pTeam->Focus); if (!pFocus && !bAircraftsWithoutAmmo) { // Favorite Enemy House case. If set, AI will focus against that House @@ -811,14 +817,11 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c { Debug::Log("DEBUG: [%s] [%s](line: %d = %d,%d): Leader [%s] selected [%s] as target.\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument, pLeaderUnit->GetTechnoType()->get_ID(), selectedTarget->GetTechnoType()->get_ID()); pTeam->Focus = selectedTarget; - - auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) - pTeamData->WaitNoTargetAttempts = 0; // Disable Script Waits if there are any because a new target was selected + pTeamData->WaitNoTargetAttempts = 0; // Disable Script Waits if there are any because a new target was selected for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) { - if (pUnit->IsAlive && pUnit->Health > 0 && !pUnit->InLimbo) + if (pUnit->IsAlive && !pUnit->InLimbo) { auto pUnitType = pUnit->GetTechnoType(); if (pUnitType && pUnit != selectedTarget && pUnit->Target != selectedTarget) @@ -868,6 +871,19 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } } + // Spy case + if (pUnitType->WhatAmI() == AbstractType::InfantryType) + { + auto pInfantryType = abstract_cast(pUnitType); + + if (pInfantryType && pInfantryType->Infiltrate && pInfantryType->Agent) + { + // Check if target is an structure and see if spiable + if (pUnit->GetCurrentMission() != Mission::Enter) + pUnit->Mission_Enter(); + } + } + // Tanya / Commando C4 case if ((pUnitType->WhatAmI() == AbstractType::InfantryType && (abstract_cast(pUnitType)->C4 || pUnit->HasAbility(Ability::C4))) && pUnit->GetCurrentMission() != Mission::Sabotage) { @@ -889,17 +905,13 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (!noWaitLoop) pTeam->GuardAreaTimer.Start(16); - auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) - { - if (pTeamData->IdxSelectedObjectFromAIList >= 0) - pTeamData->IdxSelectedObjectFromAIList = -1; + if (pTeamData->IdxSelectedObjectFromAIList >= 0) + pTeamData->IdxSelectedObjectFromAIList = -1; - if (pTeamData->WaitNoTargetAttempts != 0) - { - pTeam->GuardAreaTimer.Start(16); // No target? let's wait some frames - return; - } + if (pTeamData->WaitNoTargetAttempts != 0) + { + pTeam->GuardAreaTimer.Start(16); // No target? let's wait some frames + return; } // This action finished @@ -943,7 +955,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c && (pUnitType->WhatAmI() == AbstractType::AircraftType && abstract_cast(pUnitType)->AirportBound) && pUnit->Ammo > 0 - && (pUnit->Target != pTeam->Focus && !pUnit->InAir)) + && (pUnit->Target != pFocus && !pUnit->InAir)) { pUnit->SetTarget(pFocus); } @@ -972,7 +984,10 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (pUnit->Ammo > 0) { pUnit->QueueMission(Mission::Attack, true); - pUnit->ClickedAction(Action::Attack, pFocus, false); + + if (pFocus) + pUnit->ClickedAction(Action::Attack, pFocus, false); + pUnit->Mission_Attack(); } else @@ -1018,7 +1033,9 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c pTeam->Focus = nullptr; pTeam->QueuedFocus = nullptr; - pUnit->ClickedAction(Action::Attack, pFocus, false); + if (pFocus) + pUnit->ClickedAction(Action::Attack, pFocus, false); + pUnit->CurrentTargets.Clear(); pUnit->SetTarget(nullptr); pUnit->SetFocus(nullptr); @@ -1033,9 +1050,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (bForceNextAction) { - auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) - pTeamData->IdxSelectedObjectFromAIList = -1; + pTeamData->IdxSelectedObjectFromAIList = -1; pTeam->StepCompleted = true; Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: Naval is unable to target ground)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); @@ -1420,7 +1435,7 @@ bool ScriptExt::EvaluateObjectWithMask(TechnoClass *pTechno, int mask, int attac for (int i = 0; i < NeutralTechBuildings.Count; i++) { auto pTechObject = NeutralTechBuildings.GetItem(i); - if (pTechObject->ID == pTechno->get_ID()) + if (_stricmp(pTechObject->ID, pTechno->get_ID()) == 0) return true; } } @@ -1626,7 +1641,7 @@ bool ScriptExt::EvaluateObjectWithMask(TechnoClass *pTechno, int mask, int attac for (int i = 0; i < BuildTech.Count; i++) { auto pTechObject = BuildTech.GetItem(i); - if (pTechObject->ID == pTechno->get_ID()) + if (_stricmp(pTechObject->ID, pTechno->get_ID()) == 0) return true; } } @@ -1684,7 +1699,7 @@ bool ScriptExt::EvaluateObjectWithMask(TechnoClass *pTechno, int mask, int attac for (int i = 0; i < BaseUnit.Count; i++) { auto pMCVObject = BaseUnit.GetItem(i); - if (pMCVObject->ID == pTechno->get_ID()) + if (_stricmp(pMCVObject->ID, pTechno->get_ID()) == 0) return true; } } @@ -2046,7 +2061,7 @@ void ScriptExt::Mission_Move(TeamClass *pTeam, int calcThreatMode = 0, bool pick for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) { - if (pUnit && pUnit->IsAlive && pUnit->Health > 0 && !pUnit->InLimbo) + if (pUnit && pUnit->IsAlive && !pUnit->InLimbo) { auto pUnitType = pUnit->GetTechnoType(); if (pUnitType) @@ -2107,7 +2122,7 @@ void ScriptExt::Mission_Move(TeamClass *pTeam, int calcThreatMode = 0, bool pick for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) { - if (pUnit->IsAlive && pUnit->Health > 0 && !pUnit->InLimbo) + if (pUnit->IsAlive && pUnit->IsOnMap && !pUnit->InLimbo) { auto pUnitType = pUnit->GetTechnoType(); From c2e917fb16f26d74ac85414e506eeefc15ec4108 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Wed, 27 Oct 2021 15:23:23 +0200 Subject: [PATCH 11/19] Changed the 103,0 behavior due to feedback Gallback to CloseEnough value in Rulesmd.ini --- src/Ext/Script/Body.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index e13a69e33b..79d5e426b9 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -2549,6 +2549,9 @@ void ScriptExt::SetCloseEnoughDistance(TeamClass *pTeam, double distance = -1) pTeamData->CloseEnough = distance; } + if (distance <= 0) + pTeamData->CloseEnough = RulesClass::Instance->CloseEnough / 256.0; + // This action finished pTeam->StepCompleted = true; From 7fce07ec5212952b2b6939646545d01259d34b33 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Mon, 15 Nov 2021 00:38:55 +0100 Subject: [PATCH 12/19] Point to latest YRpp --- YRpp | 2 +- src/Ext/Script/Body.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/YRpp b/YRpp index 310d5c6ec8..155dc5ac0f 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit 310d5c6ec8d78ea4bb416a2e0d9dbe24b945222f +Subproject commit 155dc5ac0fc330ca03961fc9f68595dd7bef0cc6 diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 196371a545..8395e285fd 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -2897,4 +2897,4 @@ void ScriptExt::VariableBinaryOperationHandler(TeamClass* pTeam, int nVariable, VariableOperationHandler(pTeam, nVariable, itr->second.Value); pTeam->StepCompleted = true; -} \ No newline at end of file +} From 51373f4d7bfea0c6ab4bf240fee0db0fac755b28 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Mon, 15 Nov 2021 06:20:00 +0100 Subject: [PATCH 13/19] Changes in how is stored the selected target --- src/Ext/Script/Body.cpp | 19 ++++++++++--------- src/Ext/Team/Body.cpp | 1 + src/Ext/Team/Body.h | 2 ++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 8395e285fd..25c3939c96 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -603,7 +603,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c return; } - pFocus = abstract_cast(pTeam->Focus); + pFocus = pTeamData->SelectedTarget; if (pFocus && pFocus->IsAlive && !pFocus->InLimbo && !pFocus->GetTechnoType()->Immune @@ -612,7 +612,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c { } else { - pTeam->Focus = nullptr; + pTeamData->SelectedTarget = nullptr; pFocus = nullptr; } @@ -629,9 +629,9 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } // Let's clean the Killer mess - pTeam->QueuedFocus = nullptr; - pTeam->Focus = nullptr; + selectedTarget = nullptr; pKillerTechnoData->LastKillWasTeamTarget = false; + pTeamData->SelectedTarget = nullptr; if (!repeatAction) { @@ -821,7 +821,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (selectedTarget) { Debug::Log("DEBUG: [%s] [%s](line: %d = %d,%d): Leader [%s] selected [%s] as target.\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument, pLeaderUnit->GetTechnoType()->get_ID(), selectedTarget->GetTechnoType()->get_ID()); - pTeam->Focus = selectedTarget; + pTeamData->SelectedTarget = selectedTarget; pTeamData->WaitNoTargetAttempts = 0; // Disable Script Waits if there are any because a new target was selected for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) @@ -1009,7 +1009,10 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (pUnit->Ammo > 0) { pUnit->QueueMission(Mission::Attack, true); - pUnit->ClickedAction(Action::Attack, pFocus, false); + + if (pFocus) + pUnit->ClickedAction(Action::Attack, pFocus, false); + pUnit->Mission_Attack(); } else @@ -1035,8 +1038,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c } else { - pTeam->Focus = nullptr; - pTeam->QueuedFocus = nullptr; + pTeamData->SelectedTarget = nullptr; if (pFocus) pUnit->ClickedAction(Action::Attack, pFocus, false); @@ -1056,7 +1058,6 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (bForceNextAction) { pTeamData->IdxSelectedObjectFromAIList = -1; - pTeam->StepCompleted = true; Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: Naval is unable to target ground)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); diff --git a/src/Ext/Team/Body.cpp b/src/Ext/Team/Body.cpp index 60640c5fd8..fb568a0bd7 100644 --- a/src/Ext/Team/Body.cpp +++ b/src/Ext/Team/Body.cpp @@ -16,6 +16,7 @@ void TeamExt::ExtData::Serialize(T& Stm) .Process(this->CloseEnough) .Process(this->Countdown_RegroupAtLeader) .Process(this->MoveMissionEndMode) + .Process(this->SelectedTarget) ; } diff --git a/src/Ext/Team/Body.h b/src/Ext/Team/Body.h index e26b87da13..2a790a4c0f 100644 --- a/src/Ext/Team/Body.h +++ b/src/Ext/Team/Body.h @@ -21,6 +21,7 @@ class TeamExt double CloseEnough; int Countdown_RegroupAtLeader; int MoveMissionEndMode; + TechnoClass* SelectedTarget; ExtData(TeamClass* OwnerObject) : Extension(OwnerObject) , WaitNoTargetAttempts(0) @@ -29,6 +30,7 @@ class TeamExt , CloseEnough(-1) , Countdown_RegroupAtLeader(-1) , MoveMissionEndMode(0) + , SelectedTarget(nullptr) { } virtual ~ExtData() = default; From 137259ac559904e132c95663ad61d18b2d04ce2b Mon Sep 17 00:00:00 2001 From: FS-21 Date: Mon, 15 Nov 2021 18:45:39 +0100 Subject: [PATCH 14/19] Added function for finding the Team Leader helper function --- src/Ext/Script/Body.cpp | 115 ++++++++++++++++++++-------------------- src/Ext/Script/Body.h | 1 + 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 25c3939c96..81000cde69 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -357,12 +357,12 @@ void ScriptExt::WaitUntilFullAmmoAction(TeamClass* pTeam) void ScriptExt::Mission_Gather_NearTheLeader(TeamClass *pTeam, int countdown = -1) { FootClass *pLeaderUnit = nullptr; - int bestUnitLeadershipValue = -1; int initialCountdown = pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Argument; bool gatherUnits = false; + auto pTeamData = TeamExt::ExtMap.Find(pTeam); // This team has no units! END - if (!pTeam) + if (!pTeam || !pTeamData) { // This action finished pTeam->StepCompleted = true; @@ -370,19 +370,8 @@ void ScriptExt::Mission_Gather_NearTheLeader(TeamClass *pTeam, int countdown = - } // Load countdown - auto pTeamData = TeamExt::ExtMap.Find(pTeam); - if (pTeamData) - { - if (pTeamData->Countdown_RegroupAtLeader >= 0) - countdown = pTeamData->Countdown_RegroupAtLeader; - } - else - { - // Looks like an error... - // This action finished - pTeam->StepCompleted = true; - return; - } + if (pTeamData->Countdown_RegroupAtLeader >= 0) + countdown = pTeamData->Countdown_RegroupAtLeader; // Gather permanently until all the team members are near of the Leader if (initialCountdown == 0) @@ -427,30 +416,9 @@ void ScriptExt::Mission_Gather_NearTheLeader(TeamClass *pTeam, int countdown = - int nTogether = 0; int nUnits = -1; // Leader counts here double closeEnough; - - // Find the leader - for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) - { - if (pUnit && pUnit->IsAlive - && pUnit->Health > 0 - && !pUnit->InLimbo - && pUnit->IsOnMap - && !pUnit->Absorbed) - { - auto pUnitType = pUnit->GetTechnoType(); - - if (pUnitType) - { - // The team leader will be used for selecting targets, if there are living Team Members then always exists 1 Leader. - int unitLeadershipRating = pUnitType->LeadershipRating; - if (unitLeadershipRating > bestUnitLeadershipValue) - { - pLeaderUnit = pUnit; - bestUnitLeadershipValue = unitLeadershipRating; - } - } - } - } + + // Find the Leader + pLeaderUnit = FindTheTeamLeader(pTeam); if (!pLeaderUnit) { @@ -561,7 +529,6 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c bool noWaitLoop = false; FootClass *pLeaderUnit = nullptr; TechnoTypeClass* pLeaderUnitType = nullptr; - int bestUnitLeadershipValue = -1; bool bAircraftsWithoutAmmo = false; TechnoClass* pFocus = nullptr; bool agentMode = false; @@ -708,18 +675,13 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c agentMode = true; } } - - // The team leader will be used for selecting targets, if there are living Team Members then always exists 1 Leader. - int unitLeadershipRating = pUnitType->LeadershipRating; - if (unitLeadershipRating > bestUnitLeadershipValue && (!pacifistUnit || agentMode)) - { - pLeaderUnit = pUnit; - bestUnitLeadershipValue = unitLeadershipRating; - } } } } + // Find the Leader + pLeaderUnit = FindTheTeamLeader(pTeam); + if (!pLeaderUnit || bAircraftsWithoutAmmo || (pacifistTeam && !agentMode)) { pTeamData->IdxSelectedObjectFromAIList = -1; @@ -2022,7 +1984,6 @@ void ScriptExt::Mission_Move(TeamClass *pTeam, int calcThreatMode = 0, bool pick bool noWaitLoop = false; FootClass *pLeaderUnit = nullptr; TechnoTypeClass* pLeaderUnitType = nullptr; - int bestUnitLeadershipValue = -1; bool bAircraftsWithoutAmmo = false; TechnoClass* pFocus = nullptr; @@ -2080,18 +2041,13 @@ void ScriptExt::Mission_Move(TeamClass *pTeam, int calcThreatMode = 0, bool pick bAircraftsWithoutAmmo = true; pUnit->CurrentTargets.Clear(); } - - // The Team Leader will be used for selecting targets, if there are living Team Members then always exists 1 Leader. - int unitLeadershipRating = pUnitType->LeadershipRating; - if (unitLeadershipRating > bestUnitLeadershipValue) - { - pLeaderUnit = pUnit; - bestUnitLeadershipValue = unitLeadershipRating; - } } } } + // Find the Leader + pLeaderUnit = FindTheTeamLeader(pTeam); + if (!pLeaderUnit || bAircraftsWithoutAmmo) { auto pTeamData = TeamExt::ExtMap.Find(pTeam); @@ -2899,3 +2855,48 @@ void ScriptExt::VariableBinaryOperationHandler(TeamClass* pTeam, int nVariable, pTeam->StepCompleted = true; } + +FootClass* ScriptExt::FindTheTeamLeader(TeamClass* pTeam) +{ + FootClass* pLeaderUnit = nullptr; + int bestUnitLeadershipValue = -1; + + if (!pTeam) + { + return pLeaderUnit; + } + + // Find the Leader or promote a new one + for (auto pUnit = pTeam->FirstUnit; pUnit; pUnit = pUnit->NextTeamMember) + { + if (pUnit && pUnit->IsAlive + && !pUnit->InLimbo + && pUnit->IsOnMap + && !pUnit->Absorbed) + { + if (pUnit->IsTeamLeader) + { + pLeaderUnit = pUnit; + break; + } + + auto pUnitType = pUnit->GetTechnoType(); + + if (pUnitType) + { + // The team Leader will be used for selecting targets, if there are living Team Members then always exists 1 Leader. + int unitLeadershipRating = pUnitType->LeadershipRating; + if (unitLeadershipRating > bestUnitLeadershipValue) + { + pLeaderUnit = pUnit; + bestUnitLeadershipValue = unitLeadershipRating; + } + } + } + } + + if (pLeaderUnit) + pLeaderUnit->IsTeamLeader = true; + + return pLeaderUnit; +} diff --git a/src/Ext/Script/Body.h b/src/Ext/Script/Body.h index e5b207609a..695fe9dc40 100644 --- a/src/Ext/Script/Body.h +++ b/src/Ext/Script/Body.h @@ -153,6 +153,7 @@ class ScriptExt static void VariableOperationHandler(TeamClass* pTeam, int nVariable, int Number); template static void VariableBinaryOperationHandler(TeamClass* pTeam, int nVariable, int nVarToOperate); + static FootClass* FindTheTeamLeader(TeamClass* pTeam); static void LocalVariableAdd(TeamClass* pTeam, int nVariable, int Number); static void LocalVariableMultiply(TeamClass* pTeam, int nVariable, int Number); From a8ced1a039eb25f3b1c43a80f8c11d1eb5e784bd Mon Sep 17 00:00:00 2001 From: FS-21 Date: Tue, 16 Nov 2021 09:49:06 +0100 Subject: [PATCH 15/19] Fix a potential crash --- src/Ext/Script/Body.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 81000cde69..9c93813f24 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -573,7 +573,6 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c pFocus = pTeamData->SelectedTarget; if (pFocus && pFocus->IsAlive && !pFocus->InLimbo - && !pFocus->GetTechnoType()->Immune && pFocus->IsOnMap && !pFocus->Absorbed) { } From 4fae22d49cb2829fe59b108d28dcd6cda538f944 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Tue, 16 Nov 2021 22:44:33 +0100 Subject: [PATCH 16/19] fix missing break statement --- src/Ext/Script/Body.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 9c93813f24..4e9a2ba0dc 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -122,6 +122,7 @@ void ScriptExt::ProcessAction(TeamClass* pTeam) break; case 94: ScriptExt::PickRandomScript(pTeam, -1); + break; case 95: // Move to the closest enemy target ScriptExt::Mission_Move(pTeam, 2, false, -1, -1); From 479295c10fb03b6eb5bc91900be739fe8802203e Mon Sep 17 00:00:00 2001 From: FS-21 Date: Sun, 28 Nov 2021 16:15:36 +0100 Subject: [PATCH 17/19] =?UTF-8?q?=C2=B7=20Fixed=20bug=20that=20made=20AI?= =?UTF-8?q?=20pick=20dead=20units=20as=20targets.=20=C2=B7=20Replaced=20Ar?= =?UTF-8?q?mor=20comparison=20when=20selecting=20possible=20new=20targets?= =?UTF-8?q?=20by=20a=20new=20comparison=20based=20on=20total=20damage=20pr?= =?UTF-8?q?oduced=20by=20the=20selected=20weapon.=20=C2=B7=20Fixed=20"Case?= =?UTF-8?q?=2033"=20in=20EvaluateObjectWithMask(...)=20=C2=B7=20Small=20tw?= =?UTF-8?q?eaks=20in=20Debug=20lines.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Ext/Script/Body.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 4e9a2ba0dc..307a678b62 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -539,7 +539,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (!pTeamData) { pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: ExtData found)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); + Debug::Log("DEBUG: [%s] [%s] (line: %d) Jump to next line: %d = %d,%d -> (Reason: ExtData found)\n", pTeam->Type->ID, pScript->idxCurrentLine, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -566,7 +566,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (!pTeam) { pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No team members alive)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); + Debug::Log("DEBUG: [%s] [%s] (line: %d) Jump to next line: %d = %d,%d -> (Reason: No team members alive)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -623,7 +623,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c // This action finished pTeam->StepCompleted = true; - Debug::Log("DEBUG: [%s] [%s]: Force the jump to NEXT line: %d = %d,%d (No repeatAction set)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); + Debug::Log("DEBUG: [%s] [%s] (line: %d) Force the jump to next line: %d = %d,%d (This action wont repeat)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -690,7 +690,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c // This action finished pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: No Leader found | Exists Aircrafts without ammo | Team members have no weapons)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); + Debug::Log("DEBUG: [%s] [%s] (line: %d) Jump to next line: %d = %d,%d -> (Reason: No Leader found | Exists Aircrafts without ammo | Team members have no weapons)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -782,7 +782,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (selectedTarget) { - Debug::Log("DEBUG: [%s] [%s](line: %d = %d,%d): Leader [%s] selected [%s] as target.\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument, pLeaderUnit->GetTechnoType()->get_ID(), selectedTarget->GetTechnoType()->get_ID()); + Debug::Log("DEBUG: [%s] [%s] (line: %d = %d,%d) Leader [%s] (UID: %lu) selected [%s] (UID: %lu) as target.\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->Type->ScriptActions[pScript->idxCurrentLine].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine].Argument, pLeaderUnit->GetTechnoType()->get_ID(), pLeaderUnit->UniqueID, selectedTarget->GetTechnoType()->get_ID(), selectedTarget->UniqueID); pTeamData->SelectedTarget = selectedTarget; pTeamData->WaitNoTargetAttempts = 0; // Disable Script Waits if there are any because a new target was selected @@ -883,7 +883,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c // This action finished pTeam->StepCompleted = true; - Debug::Log("DEBUG: Next script action line for [%s] (%s) will be: %d = %d,%d (Reason: New target NOT FOUND)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); + Debug::Log("DEBUG: [%s] [%s] (line: %d) Jump to next line: %d = %d,%d (new target NOT FOUND)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -918,6 +918,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c if (auto pUnitType = pUnit->GetTechnoType()) { if (pUnit->IsAlive + && !pUnit->Health > 0 && !pUnit->InLimbo && (pUnitType->WhatAmI() == AbstractType::AircraftType && abstract_cast(pUnitType)->AirportBound) @@ -1021,7 +1022,7 @@ void ScriptExt::Mission_Attack(TeamClass *pTeam, bool repeatAction = true, int c { pTeamData->IdxSelectedObjectFromAIList = -1; pTeam->StepCompleted = true; - Debug::Log("DEBUG: ScripType: [%s] [%s] Jump to NEXT line: %d = %d,%d -> (Reason: Naval is unable to target ground)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); + Debug::Log("DEBUG: [%s] [%s] (line: %d) Jump to NEXT line: %d = %d,%d (Naval is unable to target ground)\n", pTeam->Type->ID, pScript->Type->ID, pScript->idxCurrentLine, pScript->idxCurrentLine + 1, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Action, pScript->Type->ScriptActions[pScript->idxCurrentLine + 1].Argument); return; } @@ -1055,8 +1056,18 @@ TechnoClass* ScriptExt::GreatestThreat(TechnoClass *pTechno, int method, int cal if ((weaponType && weaponType->Projectile->AG) || agentMode) unitWeaponsHaveAG = true; + int weaponDamage = 0; + + if (weaponType) + { + if (weaponType->AmbientDamage > 0) + weaponDamage = MapClass::GetTotalDamage(weaponType->AmbientDamage, weaponType->Warhead, objectType->Armor, 0) + MapClass::GetTotalDamage(weaponType->Damage, weaponType->Warhead, objectType->Armor, 0); + else + weaponDamage = MapClass::GetTotalDamage(weaponType->Damage, weaponType->Warhead, objectType->Armor, 0); + } + // If the target can't be damaged then isn't a valid target - if (weaponType && GeneralUtils::GetWarheadVersusArmor(weaponType->Warhead, objectType->Armor) == 0.0 && !agentMode) + if (weaponType && weaponDamage <= 0 && !agentMode) continue; if (!agentMode) @@ -1098,6 +1109,7 @@ TechnoClass* ScriptExt::GreatestThreat(TechnoClass *pTechno, int method, int cal if (object != pTechno && object->IsAlive + && !object->Health > 0 && !object->InLimbo && !objectType->Immune && !object->Transporter @@ -1752,10 +1764,10 @@ bool ScriptExt::EvaluateObjectWithMask(TechnoClass *pTechno, int mask, int attac pTypeBuilding = abstract_cast(pTechnoType); // Capturable Structure or Repair Hut - if (pTechnoType->WhatAmI() == AbstractType::BuildingType - && pTypeBuilding->Capturable - || (pTypeBuilding->BridgeRepairHut - && pTypeBuilding->Repairable)) + if (pTypeBuilding + && (pTypeBuilding->Capturable + || (pTypeBuilding->BridgeRepairHut + && pTypeBuilding->Repairable))) { return true; } From 924d2e79ab3ff976a2701cf1e9ef216d29260783 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Tue, 30 Nov 2021 12:32:58 +0100 Subject: [PATCH 18/19] improvement for unknown actions --- src/Ext/Script/Body.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp index 307a678b62..057cbdc305 100644 --- a/src/Ext/Script/Body.cpp +++ b/src/Ext/Script/Body.cpp @@ -195,11 +195,11 @@ void ScriptExt::ProcessAction(TeamClass* pTeam) break; default: // Do nothing because or it is a wrong Action number or it is an Ares/YR action... - if (action > 70) + if (action > 70 && !(action >= PhobosScripts::LocalVariableAdd && action <= PhobosScripts::GlobalVariableAndByGlobal)) { // Unknown new action. This action finished pTeam->StepCompleted = true; - Debug::Log("[%s] [%s] (Line %d): Unknown Script Action: %d\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, pTeam->CurrentScript->idxCurrentLine, pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Action); + Debug::Log("[%s] [%s] (line %d): Unknown Script Action: %d\n", pTeam->Type->ID, pTeam->CurrentScript->Type->ID, pTeam->CurrentScript->idxCurrentLine, pTeam->CurrentScript->Type->ScriptActions[pTeam->CurrentScript->idxCurrentLine].Action); } break; } From 5be6b396ed54b673aa3fda5ffc92e5b649eebd93 Mon Sep 17 00:00:00 2001 From: FS-21 Date: Mon, 27 Dec 2021 19:41:38 +0100 Subject: [PATCH 19/19] small change --- src/Ext/Team/Body.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ext/Team/Body.h b/src/Ext/Team/Body.h index 51abed9b86..648ff1f6b2 100644 --- a/src/Ext/Team/Body.h +++ b/src/Ext/Team/Body.h @@ -29,8 +29,8 @@ class TeamExt , IdxSelectedObjectFromAIList { -1 } , CloseEnough { -1 } , Countdown_RegroupAtLeader { -1 } - , MoveMissionEndMode(0) - , SelectedTarget(nullptr) + , MoveMissionEndMode { 0 } + , SelectedTarget { nullptr } { } virtual ~ExtData() = default;