diff --git a/CREDITS.md b/CREDITS.md
index d486713e9d..e503538c13 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -134,10 +134,9 @@ This page lists all the individual contributions to the project by their author.
- Power plant damage factor
- **FS-21**:
- Dump Object Info enhancements
- - `Powered.KillSpawns`
- - `Spawner.LimitRange`
- Majority of ScriptType actions
- ScriptType Action 14004: Force Global `OnlyTargetHouseEnemy` value in Teams
+ - Script actions for managing AI Triggers
- MC deployer fixes
- Help with docs
- Automatic Passenger Deletion logic
diff --git a/Phobos.vcxproj b/Phobos.vcxproj
index 67dc28e6ee..37deaf25f5 100644
--- a/Phobos.vcxproj
+++ b/Phobos.vcxproj
@@ -132,6 +132,7 @@
+
diff --git a/docs/AI-Scripting-and-Mapping.md b/docs/AI-Scripting-and-Mapping.md
index 074d3917e2..8b2f9d0ee2 100644
--- a/docs/AI-Scripting-and-Mapping.md
+++ b/docs/AI-Scripting-and-Mapping.md
@@ -508,6 +508,87 @@ In `aimd.ini`:
x=16005,0
```
+### `16006` Set House Index For Managing AI Triggers
+
+- Set the house index for enabling and disabling triggers. The indexes aren't the ones used in [Countries], these are internal in-game House indexes.
+
+In `aimd.ini`:
+```ini
+[SOMESCRIPTTYPE] ; ScriptType
+x=16006,n ; integer
+```
+
+- The possible argument values are:
+
+| *Argument* | *Description* |
+| :--------: | :-------------------------------------------: |
+| 4475-4482 | Multiplayer start location indexes |
+| 8997 | Special case that returns the house index of the Team object |
+| >= 0 | House index. Neutral houses can be used |
+| -1 | Random non-neutral House |
+| -2 | Find the first Neutral house available |
+| -3 | Random Human Player alive |
+
+### `16007` Enable Or Disable All AI Triggers
+
+- All AI triggers will be enabled or disabled.
+You must set the affected side with action `16012` and house with action `16006`.
+
+In `aimd.ini`:
+```ini
+[SOMESCRIPTTYPE] ; ScriptType
+x=16007,n ; integer, 1 == enable, 0 == disable
+```
+
+### `16008` Enable AI Triggers From List
+
+- When executed this action enable all AI trigger types from the selected list in `AITriggersList`. The second parameter is a 0-based index from the new section `AITriggersList` explained below.
+
+In `aimd.ini`:
+```ini
+[SOMESCRIPTTYPE] ; ScriptType
+x=16008,n
+```
+
+The second parameter is a 0-based index for the `AITriggersList` section that specifies the list of possible `AITriggerTypes` that can be evaluated. The new `AITriggersList` section must be declared in `rulesmd.ini` for making this script work:
+
+In `rulesmd.ini`:
+```ini
+[AITriggersList] ; List of AITriggerTypes lists
+0=SOMEAITRIGGERTYPE,SOMEOTHERAITRIGGERTYPE,SAMPLETRIGGERTYPE
+1=ANOTHERTRIGGERTYPE,YETANOTHERTRIGGERTYPE
+; ...
+```
+
+### `16009` Disable AI Triggers From List
+
+- Works silimar to the Action `16008`. When executed this action disable all AI trigger types from the selected list in `AITriggersList`. The second parameter is a 0-based index from the new section `AITriggersList`.
+
+### `16010` Disable AI Triggers If Contains Any Objects From the List
+
+- Works silimar to the Action `16011`. When executed this action all AI Trigger Types that contains any unit of the selected list in `AITargetTypes` will be disabled. The second parameter is a 0-based index from the new section `AITargetTypes`.
+
+### `16011` Enable AI Triggers If Contains Any Objects From the List
+
+- When executed this action all AI trigger types that contains any unit of the selected list in `AITargetTypes` will be enabled. The second parameter is a 0-based index from the new section `AITargetTypes`.
+
+In `aimd.ini`:
+```ini
+[SOMESCRIPTTYPE] ; ScriptType
+x=16011,n
+```
+
+### `16012` Set Side Index For Managing AI Triggers
+
+- Set the side index for enabling and disabling triggers.
+0 means any side.
+
+In `aimd.ini`:
+```ini
+[SOMESCRIPTTYPE] ; ScriptType
+x=16012,n ; integer, where 0 > n, default -1
+```
+
### `18000-18999` Variable Manipulation
#### `18000-18023` Edit Variable
diff --git a/docs/Whats-New.md b/docs/Whats-New.md
index 8225c1eaa0..121af88f39 100644
--- a/docs/Whats-New.md
+++ b/docs/Whats-New.md
@@ -328,6 +328,13 @@ HideShakeEffects=false ; boolean
10103=Load Onto Transports,0,0,1,[LONG DESC]
10104=Chronoshift to Enemy Base,20,0,1,[LONG DESC]
14004=Force Global OnlyTargetHouseEnemy value in Teams,20,0,1,[LONG DESC]
+ 16006=Set House Index For Managing AI Triggers,20,0,1,[LONG DESC]
+ 16007=Enable Or Disable All AI Triggers,21,0,1,[LONG DESC]
+ 16008=Enable AI Triggers From List,28,0,1,[LONG DESC]
+ 16009=Disable AI Triggers From List,28,0,1,[LONG DESC]
+ 16010=Disable AI Triggers If Contains Any Objects From the List,29,0,1,[LONG DESC]
+ 16011=Enable AI Triggers If Contains Any Objects From the List,29,0,1,[LONG DESC]
+ 16012=Set Side Index For Managing AI Triggers,20,0,1,[LONG DESC]
18000=Local variable set,22,0,1,[LONG DESC]
18001=Local variable add,22,0,1,[LONG DESC]
18002=Local variable minus,22,0,1,[LONG DESC]
@@ -408,6 +415,12 @@ HideShakeEffects=false ; boolean
25=Local variables,-4
26=Global variables,-5
27=Global variables,-6
+ 28=AI Scripts List, -7
+ 29=AI Target Type,-8
+
+ [ScriptParamTypes]
+ 7=AIScriptsList,1,1,0
+ 8=AITargetTypes,1,1,0
```
````
@@ -421,6 +434,7 @@ HideShakeEffects=false ; boolean
#### New:
- [Customized transport plane for teams](AI-Scripting-and-Mapping.md#customized-transport-plane-for-teams) (by FlyStar)
- [Modify ammo on impact](New-or-Enhanced-Logics.md#modify-ammo-on-impact) (by FS-21)
+- [Script actions for managing AI Triggers](AI-Scripting-and-Mapping.md#script-actions-for-managing-ai-triggers) (by FS-21)
#### Vanilla fixes:
- Fixed the bug where a building with `Factory=BuildingType` owned by the AI did not play `ProductionAnim` when placing a produced building (by Noble_Fish)
@@ -951,6 +965,7 @@ HideShakeEffects=false ; boolean
- Building airstrike target eligibility customization (by Starkku)
- IvanBomb detonation & image display optionally centered on buildings (by Starkku)
- Forcing specific weapon against cloaked or disguised targets (by Starkku)
+- Script action for enabling & disabling AI Triggers (by FS-21)
- Customizable ROF random delay (by Starkku)
- Animation with `Tiled=yes` now supports `CustomPalette` (by ststl)
- Toggleable `DieSound` when grinding (by Trsdy)
diff --git a/src/Ext/House/Body.cpp b/src/Ext/House/Body.cpp
index e53d1d2ad9..f638c21bc8 100644
--- a/src/Ext/House/Body.cpp
+++ b/src/Ext/House/Body.cpp
@@ -586,6 +586,73 @@ float HouseExt::GetRestrictedFactoryPlantMult(TechnoTypeClass* pTechnoType) cons
return 1.0f - ((1.0f - mult) * pTechnoTypeExt->FactoryPlant_Multiplier);
}
+int HouseExt::GetHouseIndex(int param, TeamClass* pTeam, TActionClass* pTAction)
+{
+ if ((pTeam && pTAction) || (param == 8997 && !pTeam && !pTAction))
+ return -1;
+
+ int houseIdx = -1;
+ std::vector housesListIdx;
+
+ // Check special cases
+ if (param < 0)
+ {
+ if (param < -3)
+ return -1;
+
+ for (auto pHouse : HouseClass::Array)
+ {
+ if (param == -2 && pHouse->IsNeutral())
+ {
+ houseIdx = pHouse->ArrayIndex;
+ break;
+ }
+ else if (!pHouse->Defeated && !pHouse->IsObserver())
+ {
+ if ((param == -1 && !pHouse->Type->MultiplayPassive) // Random non-neutral player
+ || (param == -3 && !pHouse->IsObserver())) // Random human player
+ {
+ housesListIdx.push_back(pHouse->ArrayIndex);
+ }
+
+ if (housesListIdx.size() > 0)
+ houseIdx = housesListIdx.at(ScenarioClass::Instance->Random.RandomRanged(0, housesListIdx.size() - 1));
+ else
+ return -1;
+ }
+ }
+
+ return houseIdx;
+ }
+
+ // Check a specific house of the map
+ if (param >= HouseClass::PlayerAtA && param <= HouseClass::PlayerAtH)
+ {
+ // Is a multiplayer house index (Player@A - Player@H) ?
+ houseIdx = param - HouseClass::PlayerAtA;
+ }
+ else if (param == 8997)
+ {
+ // Is the owner of the trigger ?
+ houseIdx = pTeam ? pTeam->Owner->ArrayIndex : pTAction->TeamType->Owner->ArrayIndex;
+ }
+ else if (param > 8997 || HouseClass::Array.Count <= param)
+ {
+ // Is a invalid index value
+ if (pTAction)
+ Debug::Log(__FUNCTION__": Invalid house index '%d'. This action could be skipped.\n", (int)pTAction->ActionKind, param);
+
+ return -1;
+ }
+
+ HouseClass* pHouse = HouseClass::Array.GetItem(houseIdx);
+
+ if (!pHouse->Defeated && !pHouse->IsObserver())
+ return houseIdx;
+
+ return -1;
+}
+
void HouseExt::SetForceOnlyTargetHouseEnemy(HouseClass* pThis, int mode)
{
const auto pHouseExt = HouseExt::Fetch(pThis);
diff --git a/src/Ext/House/Body.h b/src/Ext/House/Body.h
index df5ba629b6..597ba4bd0d 100644
--- a/src/Ext/House/Body.h
+++ b/src/Ext/House/Body.h
@@ -1,5 +1,6 @@
#pragma once
#include
+#include
#include
@@ -171,6 +172,7 @@ class HouseExt final : public AbstractExt, public Detach::ListenerAIScriptsLists.emplace_back(std::move(objectsList));
}
+
+ // Section AITriggersList
+ int triggerItemsCount = pINI->GetKeyCount("AITriggersList");
+ for (int i = 0; i < triggerItemsCount; ++i)
+ {
+ std::vector objectsList;
+
+ char* context = nullptr;
+ pINI->ReadString("AITriggersList", pINI->GetKeyName("AITriggersList", i), "", Phobos::readBuffer);
+
+ for (char *cur = strtok_s(Phobos::readBuffer, Phobos::readDelims, &context); cur; cur = strtok_s(nullptr, Phobos::readDelims, &context))
+ {
+ AITriggerTypeClass* pNewTrigger = GameCreate(cur); // Note: Don't use ::FindOrAllocate(cur) here...
+ objectsList.emplace_back(pNewTrigger);
+ }
+
+ this->AITriggersLists.emplace_back(std::move(objectsList));
+ }
}
// this should load everything that TypeData is not dependant on
@@ -695,6 +713,7 @@ void RulesExt::ExtData::Serialize(T& Stm)
Stm
.Process(this->AITargetTypesLists)
.Process(this->AIScriptsLists)
+ .Process(this->AITriggersLists)
.Process(this->Storage_TiberiumIndex)
.Process(this->HarvesterDumpAmount)
.Process(this->InfantryGainSelfHealCap)
diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h
index 2de689e591..933c030d24 100644
--- a/src/Ext/Rules/Body.h
+++ b/src/Ext/Rules/Body.h
@@ -1,5 +1,6 @@
#pragma once
+#include
#include
#include
@@ -24,6 +25,7 @@ class RulesExt
public:
std::vector> AITargetTypesLists;
std::vector> AIScriptsLists;
+ std::vector> AITriggersLists;
Valueable Storage_TiberiumIndex;
Valueable HarvesterDumpAmount;
diff --git a/src/Ext/Script/Body.ManageAITriggers.cpp b/src/Ext/Script/Body.ManageAITriggers.cpp
new file mode 100644
index 0000000000..16993f2c74
--- /dev/null
+++ b/src/Ext/Script/Body.ManageAITriggers.cpp
@@ -0,0 +1,186 @@
+#include "Body.h"
+#include
+
+void ScriptExt::ManageTriggersFromList(TeamClass* pTeam, int idxAITriggerType = -1, bool isEnabled = false)
+{
+ auto pScript = pTeam->CurrentScript;
+
+ if (idxAITriggerType < 0)
+ idxAITriggerType = pScript->Type->ScriptActions[pScript->CurrentMission].Argument;
+
+ if (idxAITriggerType < 0 || RulesExt::Global()->AITriggersLists.size() <= 0)
+ {
+ pTeam->StepCompleted = true;
+ ScriptExt::Log("AI Scripts - ManageTriggersFromList: [%s] [%s] (line: %d = %d,%d) Aborting script action because the [AITriggersLists] index %d is invalid.\n",
+ pTeam->Type->ID,
+ pScript->Type->ID,
+ pScript->CurrentMission,
+ pScript->Type->ScriptActions[pScript->CurrentMission].Action,
+ pScript->Type->ScriptActions[pScript->CurrentMission].Argument,
+ idxAITriggerType);
+
+ return;
+ }
+
+ DynamicVectorClass objectsList;
+ for (auto obj : RulesExt::Global()->AITriggersLists[idxAITriggerType])
+ objectsList.AddUnique(obj);
+
+ for (auto pTrigger : AITriggerTypeClass::Array)
+ {
+ if (objectsList.FindItemIndex(pTrigger) >= 0)
+ pTrigger->IsEnabled = isEnabled;
+ }
+
+ // This action finished
+ pTeam->StepCompleted = true;
+}
+
+void ScriptExt::ManageAllTriggersFromHouse(TeamClass* pTeam, HouseClass* pHouse = nullptr, int sideIdx = -1, int houseIdx = -1, bool isEnabled = true)
+{
+ // if pHouse is set then it overwrites any argument
+ if (pHouse)
+ {
+ houseIdx = pHouse->ArrayIndex;
+ sideIdx = pHouse->SideIndex;
+ }
+
+ if (sideIdx < 0)
+ return;
+
+ for (auto pTrigger : AITriggerTypeClass::Array)
+ {
+ if ((houseIdx == -1 || houseIdx == pTrigger->HouseIndex) && (sideIdx == 0 || sideIdx == pTrigger->SideIndex))
+ pTrigger->IsEnabled = isEnabled;
+ }
+
+ // This action finished
+ pTeam->StepCompleted = true;
+}
+
+void ScriptExt::SetSideIdxForManagingTriggers(TeamClass* pTeam, int sideIdx = -1)
+{
+ auto pScript = pTeam->CurrentScript;
+
+ if (sideIdx < 0)
+ sideIdx = pScript->Type->ScriptActions[pScript->CurrentMission].Argument;
+
+ // Any negative value will mark it as "Any side"
+ if (sideIdx < 0)
+ sideIdx = -1;
+
+ if (auto pTeamData = TeamExt::Fetch(pTeam))
+ pTeamData->TriggersSideIdx = sideIdx;
+
+ // This action finished
+ pTeam->StepCompleted = true;
+}
+
+void ScriptExt::SetHouseIdxForManagingTriggers(TeamClass* pTeam, int houseIdx = 2147483647)
+{
+ auto pScript = pTeam->CurrentScript;
+
+ // Note: this magic number is a default index value the game will never be able to use due to technical limitations
+ if (houseIdx == 2147483647)
+ houseIdx = pScript->Type->ScriptActions[pScript->CurrentMission].Argument;
+
+ houseIdx = HouseExt::GetHouseIndex(houseIdx, pTeam, nullptr);
+
+ if (auto pTeamData = TeamExt::Fetch(pTeam))
+ pTeamData->TriggersHouseIdx = houseIdx;
+
+ // This action finished
+ pTeam->StepCompleted = true;
+}
+
+void ScriptExt::ManageAITriggers(TeamClass* pTeam, int enabled = -1)
+{
+ auto pTeamData = TeamExt::Fetch(pTeam);
+ if (!pTeamData)
+ {
+ // This action finished
+ pTeam->StepCompleted = true;
+ return;
+ }
+
+ int sideIdx = pTeamData->TriggersSideIdx;
+ int houseIdx = pTeamData->TriggersHouseIdx;
+ pTeamData->TriggersSideIdx = -1;
+ pTeamData->TriggersHouseIdx = -1;
+ auto pScript = pTeam->CurrentScript;
+ bool isEnabled = false;
+
+ if (enabled < 0)
+ enabled = pScript->Type->ScriptActions[pScript->CurrentMission].Argument;
+ else
+ isEnabled = true;
+
+ ScriptExt::ManageAllTriggersFromHouse(pTeam, nullptr, sideIdx, houseIdx, isEnabled);
+
+ // This action finished
+ pTeam->StepCompleted = true;
+}
+
+void ScriptExt::ManageTriggersWithObjects(TeamClass* pTeam, int idxAITargetType = -1, bool isEnabled = false)
+{
+ auto pScript = pTeam->CurrentScript;
+
+ if (idxAITargetType < 0)
+ idxAITargetType = pScript->Type->ScriptActions[pScript->CurrentMission].Argument;
+
+ if (idxAITargetType < 0 || RulesExt::Global()->AITargetTypesLists.size() <= 0)
+ {
+ pTeam->StepCompleted = true;
+ ScriptExt::Log("AI Scripts - ManageTriggersWithObjects: [%s] [%s] (line: %d = %d,%d) Aborting script action because the [AITargetTypes] index %d is invalid.\n",
+ pTeam->Type->ID,
+ pScript->Type->ID,
+ pScript->CurrentMission,
+ pScript->Type->ScriptActions[pScript->CurrentMission].Action,
+ pScript->Type->ScriptActions[pScript->CurrentMission].Argument,
+ idxAITargetType);
+
+ return;
+ }
+
+ DynamicVectorClass objectsList;
+ for (auto obj : RulesExt::Global()->AITargetTypesLists[idxAITargetType])
+ objectsList.AddUnique(obj);
+
+ if (objectsList.Count == 0)
+ {
+ pTeam->StepCompleted = true;
+ return;
+ }
+
+ auto AddTechnosFromTeam = [&](DynamicVectorClass& entriesList, TeamTypeClass* pTeam)
+ {
+ if (pTeam)
+ {
+ for (auto entry : pTeam->TaskForce->Entries)
+ {
+ if (entry.Amount > 0)
+ entriesList.AddItem(entry.Type);
+ }
+ }
+ };
+
+ for (auto pTrigger : AITriggerTypeClass::Array)
+ {
+ DynamicVectorClass entriesList;
+
+ AddTechnosFromTeam(entriesList, pTrigger->Team1);
+ AddTechnosFromTeam(entriesList, pTrigger->Team2);
+
+ for (auto entry : entriesList)
+ {
+ if (objectsList.FindItemIndex(entry) >= 0)
+ {
+ pTrigger->IsEnabled = isEnabled;
+ break;
+ }
+ }
+ }
+
+ // This action finished
+ pTeam->StepCompleted = true;
+}
diff --git a/src/Ext/Script/Body.cpp b/src/Ext/Script/Body.cpp
index 8380de3b5b..0294cf60a7 100644
--- a/src/Ext/Script/Body.cpp
+++ b/src/Ext/Script/Body.cpp
@@ -216,6 +216,27 @@ void ScriptExt::ProcessAction(TeamClass* pTeam)
// Chronoshift to enemy base, argument is additional distance modifier
ScriptExt::ChronoshiftToEnemyBase(pTeam, argument);
break;
+ case PhobosScripts::SetSideIdxForManagingTriggers:
+ ScriptExt::SetSideIdxForManagingTriggers(pTeam, -1);
+ break;
+ case PhobosScripts::SetHouseIdxForManagingTriggers:
+ ScriptExt::SetHouseIdxForManagingTriggers(pTeam, 2147483647);
+ break;
+ case PhobosScripts::ManageAllAITriggers:
+ ScriptExt::ManageAITriggers(pTeam, -1);
+ break;
+ case PhobosScripts::EnableTriggersFromList:
+ ScriptExt::ManageTriggersFromList(pTeam, -1, true);
+ break;
+ case PhobosScripts::DisableTriggersFromList:
+ ScriptExt::ManageTriggersFromList(pTeam, -1, false);
+ break;
+ case PhobosScripts::EnableTriggersWithObjects:
+ ScriptExt::ManageTriggersWithObjects(pTeam, -1, true);
+ break;
+ case PhobosScripts::DisableTriggersWithObjects:
+ ScriptExt::ManageTriggersWithObjects(pTeam, -1, false);
+ break;
case PhobosScripts::ForceGlobalOnlyTargetHouseEnemy:
ScriptExt::ForceGlobalOnlyTargetHouseEnemy(pTeam, -1);
break;
diff --git a/src/Ext/Script/Body.h b/src/Ext/Script/Body.h
index f1ce860587..88bb1055bc 100644
--- a/src/Ext/Script/Body.h
+++ b/src/Ext/Script/Body.h
@@ -2,6 +2,7 @@
#include
#include
+#include
#include
#include
#include
@@ -70,6 +71,13 @@ enum class PhobosScripts : unsigned int
RandomSkipNextAction = 16003,
PickRandomScript = 16004,
JumpBackToPreviousScript = 16005,
+ SetHouseIdxForManagingTriggers = 16006,
+ ManageAllAITriggers = 16007,
+ EnableTriggersFromList = 16008,
+ DisableTriggersFromList = 16009,
+ DisableTriggersWithObjects = 16010,
+ EnableTriggersWithObjects = 16011,
+ SetSideIdxForManagingTriggers = 16012,
// Range 18000-18999 are variable actions
LocalVariableSet = 18000,
@@ -219,6 +227,8 @@ class ScriptExt final : public AbstractExt
static void Stop_ForceJump_Countdown(TeamClass* pTeam);
static void JumpBackToPreviousScript(TeamClass* pTeam);
static void ChronoshiftToEnemyBase(TeamClass* pTeam, int extraDistance);
+ static void ManageTriggersFromList(TeamClass* pTeam, int idxAITriggerType, bool isEnabled);
+ static void ManageAllTriggersFromHouse(TeamClass* pTeam, HouseClass* pHouse, int sideIdx, int houseIdx, bool isEnabled);
static void ForceGlobalOnlyTargetHouseEnemy(TeamClass* pTeam, int mode);
@@ -229,6 +239,10 @@ class ScriptExt final : public AbstractExt
template
static void VariableBinaryOperationHandler(TeamClass* pTeam, int nVariable, int nVarToOperate);
static bool IsUnitAvailable(TechnoClass* pTechno, bool checkIfInTransportOrAbsorbed);
+ static void SetSideIdxForManagingTriggers(TeamClass* pTeam, int sideIdx);
+ static void SetHouseIdxForManagingTriggers(TeamClass* pTeam, int houseIdx);
+ static void ManageAITriggers(TeamClass* pTeam, int enabled);
+ static void ManageTriggersWithObjects(TeamClass* pTeam, int idxAITargetType, bool isEnabled);
static void Log(const char* pFormat, ...);
static void PlaySpeech(TeamClass* pTeam);
diff --git a/src/Ext/Team/Body.cpp b/src/Ext/Team/Body.cpp
index 1d8be2bc29..bc12bd3b52 100644
--- a/src/Ext/Team/Body.cpp
+++ b/src/Ext/Team/Body.cpp
@@ -22,6 +22,8 @@ void TeamExt::Serialize(T& Stm)
.Process(this->ForceJump_RepeatMode)
.Process(this->TeamLeader)
.Process(this->PreviousScriptList)
+ .Process(this->TriggersSideIdx)
+ .Process(this->TriggersHouseIdx)
;
}
diff --git a/src/Ext/Team/Body.h b/src/Ext/Team/Body.h
index 5d6b9916b5..a2fc28538f 100644
--- a/src/Ext/Team/Body.h
+++ b/src/Ext/Team/Body.h
@@ -37,6 +37,8 @@ class TeamExt final : public AbstractExt, public Detach::Listener
bool ForceJump_RepeatMode;
FootClass* TeamLeader;
std::vector PreviousScriptList;
+ int TriggersSideIdx;
+ int TriggersHouseIdx;
TeamExt(TeamClass* OwnerObject) : AbstractExt(OwnerObject)
, WaitNoTargetAttempts { 0 }
@@ -52,6 +54,8 @@ class TeamExt final : public AbstractExt, public Detach::Listener
, ForceJump_RepeatMode { false }
, TeamLeader { nullptr }
, PreviousScriptList { }
+ , TriggersSideIdx { -1 }
+ , TriggersHouseIdx { -1 }
{ }
virtual ~TeamExt() = default;