Skip to content

Commit 258f711

Browse files
committed
Allow using <Player @ X> as trigger owner in skirmish/MP
1 parent 53f6aab commit 258f711

7 files changed

Lines changed: 100 additions & 2 deletions

File tree

CREDITS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ This page lists all the individual contributions to the project by their author.
272272
- Build area customizations
273273
- `Scorch` / `Flamer` fire animation customization
274274
- EM Pulse cannon logic improvements
275-
- `<Player @ X>` as owner for pre-placed objects
275+
- `<Player @ X>` as owner for pre-placed objects and triggers
276276
- Custom exit cell for infantry factory
277277
- Vehicles keeping target on move command
278278
- `IsSonic` wave drawing crash fix

docs/AI-Scripting-and-Mapping.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This page describes all AI scripting and mapping related additions and changes i
44

55
## Bugfixes and Miscellanous
66

7+
- `<Player @ X>` can now be used as owner for pre-placed objects as well as owner for triggers on skirmish and multiplayer maps. Triggers with owners that are not present in the game are destroyed and never sprung.
78
- Script action `Move to cell` now obeys YR cell calculation now. Using `1000 * Y + X` as its cell value. (was `128 * Y + X` as it's a RA1 leftover)
89
- The game now can reads waypoints ranges in [0, 2147483647]. (was [0,701])
910
- Map trigger action `41 Play Animation At...` can now create 'non-inert' animations which can play sounds, deal damage and apply `TiberiumChainReaction` if a parameter is set (needs [following changes to `fadata.ini`](Whats-New.md#for-map-editor-final-alert-2)).

docs/Fixed-or-Improved-Logics.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
164164
- Certain global tileset indices (`ShorePieces`, `WaterSet`, `CliffSet`, `WaterCliffs`, `WaterBridge`, `BridgeSet` and `WoodBridgeSet`) can now be toggled to be parsed for lunar theater by setting `[General] -> ApplyLunarFixes` to true in `lunarmd.ini`. Do note that enabling this without fixing f.ex `WoodBridgeTileSet` pointing to a tileset with `TilesInSet=0` will cause issues in-game.
165165
- Fixed infantry `SecondaryFire` / `SecondaryProne` sequences being displayed in water instead of `WetAttack`.
166166
- Fixed objects with ally target and `AttackFriendlies=true` having their target reset every frame, particularly AI-owned buildings.
167-
- `<Player @ X>` can now be used as owner for pre-placed objects on skirmish and multiplayer maps.
168167
- Follower vehicle index for preplaced vehicles in maps is now explicitly constrained to `[Units]` list in map files and is no longer thrown off by vehicles that could not be created or created vehicles having other vehicles as initial passengers.
169168
- Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix
170169
- Stop command (`[S]` by default) behavior is now more correct:

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ New:
562562
- [Allow customize jumpjet properties on warhead](Fixed-or-Improved-Logics.md#customizing-locomotor-warhead) (by NetsuNegi)
563563
- Customize effects range of power plant enhancer (by NetsuNegi)
564564
- Allow each side to customize the color when the proportion of working miners is higher than `HarvesterCounter.ConditionYellow` (by Noble_Fish)
565+
- `<Player @ X>` can now be used as owner for triggers on skirmish and multiplayer maps (by Starkku)
565566
566567
Vanilla fixes:
567568
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)

src/Ext/Scenario/Body.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ void ScenarioExt::ExtData::Serialize(T& Stm)
174174
.Process(this->DefaultLS800BkgdName)
175175
.Process(this->DefaultLS800BkgdPal)
176176
.Process(this->LimboLaunchers)
177+
.Process(this->TriggerTypePlayerAtXOwners)
177178
.Process(this->UndergroundTracker)
178179
.Process(this->SpecialTracker)
179180
.Process(this->FallingDownTracker)
@@ -204,6 +205,7 @@ DEFINE_HOOK(0x683549, ScenarioClass_CTOR, 0x9)
204205
ScenarioExt::Global()->Waypoints.clear();
205206
ScenarioExt::Global()->Variables[0].clear();
206207
ScenarioExt::Global()->Variables[1].clear();
208+
ScenarioExt::Global()->TriggerTypePlayerAtXOwners.clear();
207209

208210
return 0;
209211
}

src/Ext/Scenario/Body.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class ScenarioExt
4444

4545
std::vector<TechnoExt::ExtData*> LimboLaunchers;
4646

47+
std::map<int, int> TriggerTypePlayerAtXOwners; // TriggerTypeClass ArrayIndex -> Player slot index
48+
4749
DynamicVectorClass<TechnoClass*> UndergroundTracker; // Technos that are underground.
4850
DynamicVectorClass<TechnoClass*> SpecialTracker; // For special purposes, like tracking technos that are forced moving. Currently unused.
4951
DynamicVectorClass<TechnoClass*> FallingDownTracker; // Technos that are falling down, parachutes and land technos falling from bridge.
@@ -62,6 +64,7 @@ class ScenarioExt
6264
, DefaultLS800BkgdName {}
6365
, DefaultLS800BkgdPal {}
6466
, LimboLaunchers {}
67+
, TriggerTypePlayerAtXOwners {}
6568
, UndergroundTracker {}
6669
, SpecialTracker {}
6770
, FallingDownTracker {}

src/Ext/Trigger/Hooks.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <TriggerTypeClass.h>
2+
#include <Ext/Scenario/Body.h>
13
#include <Ext/TEvent/Body.h>
24

35
DEFINE_HOOK(0x727064, TriggerTypeClass_HasLocalSetOrClearedEvent, 0x5)
@@ -23,3 +25,93 @@ DEFINE_HOOK(0x727024, TriggerTypeClass_HasGlobalSetOrClearedEvent, 0x5)
2325
? 0x72702E
2426
: 0x727029;
2527
}
28+
29+
#pragma region PlayerAtX
30+
31+
// Store player slot index for trigger type if such value is used in scenario INI.
32+
DEFINE_HOOK(0x727292, TriggerTypeClass_ReadINI_PlayerAtX, 0x5)
33+
{
34+
GET(TriggerTypeClass*, pThis, EBP);
35+
GET(const char*, pID, ESI);
36+
37+
// Bail out early in campaign mode or if the name does not start with <
38+
if (SessionClass::IsCampaign() || *pID != '<')
39+
return 0;
40+
41+
const int playerAtIndex = HouseClass::GetPlayerAtFromString(pID);
42+
43+
if (playerAtIndex != -1)
44+
{
45+
ScenarioExt::Global()->TriggerTypePlayerAtXOwners.emplace(pThis->ArrayIndex, playerAtIndex);
46+
47+
// Override the name to prevent Ares whining about non-existing HouseType names.
48+
R->ESI(NONE_STR);
49+
}
50+
51+
return 0;
52+
}
53+
54+
// Handle mapping player slot index for trigger to HouseClass pointer in logic.
55+
DEFINE_HOOK_AGAIN(0x7265F7, TriggerClass_Logic_PlayerAtX, 0x6)
56+
DEFINE_HOOK(0x72652D, TriggerClass_Logic_PlayerAtX, 0x6)
57+
{
58+
enum { SkipGameCode1 = 0x726538, SkipGameCode2 = 0x726602};
59+
60+
GET(TriggerTypeClass*, pType, EDX);
61+
62+
if (SessionClass::IsCampaign())
63+
return 0;
64+
65+
auto const& triggerOwners = ScenarioExt::Global()->TriggerTypePlayerAtXOwners;
66+
auto it = triggerOwners.find(pType->ArrayIndex);
67+
68+
if (it != triggerOwners.end())
69+
{
70+
if (auto const pHouse = HouseClass::FindByPlayerAt(it->second))
71+
{
72+
R->EAX(pHouse);
73+
return R->Origin() == 0x72652D ? SkipGameCode1 : SkipGameCode2;
74+
}
75+
}
76+
77+
return 0;
78+
}
79+
80+
// Destroy triggers with Player @ X owners if they are not present in scenario.
81+
DEFINE_HOOK(0x725FC7, TriggerClass_CTOR_PlayerAtX, 0x7)
82+
{
83+
GET(TriggerClass*, pThis, ESI);
84+
85+
if (SessionClass::IsCampaign())
86+
return 0;
87+
88+
auto& triggerOwners = ScenarioExt::Global()->TriggerTypePlayerAtXOwners;
89+
auto it = triggerOwners.find(pThis->Type->ArrayIndex);
90+
91+
if (it != triggerOwners.end())
92+
{
93+
if (!HouseClass::FindByPlayerAt(it->second))
94+
pThis->Destroy();
95+
}
96+
97+
return 0;
98+
}
99+
100+
// Remove destroyed triggers from the map.
101+
DEFINE_HOOK(0x726727, TriggerClass_Destroy_PlayerAtX, 0x5)
102+
{
103+
GET(TriggerClass*, pThis, ESI);
104+
105+
if (SessionClass::IsCampaign())
106+
return 0;
107+
108+
auto& triggerOwners = ScenarioExt::Global()->TriggerTypePlayerAtXOwners;
109+
auto it = triggerOwners.find(pThis->Type->ArrayIndex);
110+
111+
if (it != triggerOwners.end())
112+
triggerOwners.erase(it);
113+
114+
return 0;
115+
}
116+
117+
#pragma endregion

0 commit comments

Comments
 (0)