Skip to content

Commit c51b21b

Browse files
committed
Allow using <Player @ X> as trigger owner in skirmish/MP
1 parent 0b8c4db commit c51b21b

File tree

8 files changed

+100
-3
lines changed

8 files changed

+100
-3
lines changed

CREDITS.md

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

YRpp

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
@@ -166,7 +166,6 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
166166
- 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.
167167
- Fixed infantry `SecondaryFire` / `SecondaryProne` sequences being displayed in water instead of `WetAttack`.
168168
- Fixed objects with ally target and `AttackFriendlies=true` having their target reset every frame, particularly AI-owned buildings.
169-
- `<Player @ X>` can now be used as owner for pre-placed objects on skirmish and multiplayer maps.
170169
- 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.
171170
- Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix
172171
- 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
@@ -443,6 +443,7 @@ New:
443443
- [Ammo-based deploy customizations for vehicles expanded to non-IsSimpleDeployer deploy functions](New-or-Enhanced-Logics.md#automatic-deploy-and-blocking-deploying-based-on-ammo) (by Starkku)
444444
- Randomized anims for several behaviors (by Ollerus)
445445
- Shield respawn animation and weapon (by Ollerus)
446+
- `<Player @ X>` can now be used as owner for triggers on skirmish and multiplayer maps (by Starkku)
446447
447448
Vanilla fixes:
448449
- 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
@@ -167,6 +167,7 @@ void ScenarioExt::ExtData::Serialize(T& Stm)
167167
.Process(this->DefaultLS800BkgdName)
168168
.Process(this->DefaultLS800BkgdPal)
169169
.Process(this->MasterDetonationBullet)
170+
.Process(this->TriggerTypePlayerAtXOwners)
170171
// .Process(this->NewMessageList); // Should not S/L
171172
;
172173
}
@@ -195,6 +196,7 @@ DEFINE_HOOK(0x683549, ScenarioClass_CTOR, 0x9)
195196
ScenarioExt::Global()->Waypoints.clear();
196197
ScenarioExt::Global()->Variables[0].clear();
197198
ScenarioExt::Global()->Variables[1].clear();
199+
ScenarioExt::Global()->TriggerTypePlayerAtXOwners.clear();
198200

199201
return 0;
200202
}

src/Ext/Scenario/Body.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class ScenarioExt
4747
PhobosFixedString<64u> DefaultLS800BkgdPal;
4848

4949
BulletClass* MasterDetonationBullet; // Used to do warhead/weapon detonations on spot without having to create new BulletClass instance every time.
50+
std::map<int, int> TriggerTypePlayerAtXOwners; // TriggerTypeClass ArrayIndex -> Player slot index
5051

5152
ExtData(ScenarioClass* OwnerObject) : Extension<ScenarioClass>(OwnerObject)
5253
, ShowBriefing { false }
@@ -62,6 +63,7 @@ class ScenarioExt
6263
, DefaultLS800BkgdName {}
6364
, DefaultLS800BkgdPal {}
6465
, MasterDetonationBullet {}
66+
, TriggerTypePlayerAtXOwners {}
6567
{ }
6668

6769
void SetVariableToByID(bool bIsGlobal, int nIndex, char bState);

src/Ext/Trigger/Hooks.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include <TriggerClass.h>
2+
#include <TriggerTypeClass.h>
23

34
#include <Helpers/Macro.h>
45

6+
#include <Ext/Scenario/Body.h>
57
#include <Ext/TEvent/Body.h>
68

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

0 commit comments

Comments
 (0)