Skip to content

Commit 56a9f18

Browse files
Fly-Star-himDeathFishAtEaseCoronia
authored
Country-specific EVAType (#2195)
- You can now set the `EVA.Tag` for a specific country. > 现在可以自定义指定国家的`EVA.Tag`。 - `EVAIndex` now supports saving and loading game states. > `EVAIndex` 支持存读档。 --------- Co-authored-by: Fly-Star <100747645+a851903106@users.noreply.github.com> Co-authored-by: Noble_Fish <1065703286@qq.com> Co-authored-by: Coronia <2217891145@qq.com>
1 parent 32e02b4 commit 56a9f18

13 files changed

Lines changed: 283 additions & 0 deletions

File tree

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ This page lists all the individual contributions to the project by their author.
421421
- Custom hover vehicles shutdown drowning death
422422
- SHP turret vehicles support the use of `*tur.shp` files
423423
- Fix a bug where game will crash after loading if a techno with `AlphaImage` converts to a type without it, or an anim with `AlphaImage` changes to a type without it through `Next`
424+
- `EVA.Tag` already supports being set for specific countries, and `EVAIndex` is no longer reset after load game
424425
- **NetsuNegi**:
425426
- Forbidding parallel AI queues by type
426427
- Jumpjet crash speed fix when crashing onto building

Phobos.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
<ClCompile Include="src\Commands\DeselectObject.cpp" />
2323
<ClCompile Include="src\Ext\Cell\Hooks.cpp" />
2424
<ClCompile Include="src\Ext\Event\Body.cpp" />
25+
<ClCompile Include="src\Ext\HouseType\Body.cpp" />
26+
<ClCompile Include="src\Ext\HouseType\Hooks.cpp" />
2527
<ClCompile Include="src\Ext\Infantry\Hooks.cpp" />
2628
<ClCompile Include="src\Ext\Infantry\Hooks.Firing.cpp" />
2729
<ClCompile Include="src\Ext\TechnoType\Hooks.MultiWeapon.cpp" />
@@ -225,6 +227,7 @@
225227
<ClInclude Include="src\Commands\DeselectObject.h" />
226228
<ClInclude Include="src\Ext\EBolt\Body.h" />
227229
<ClInclude Include="src\Ext\Event\Body.h" />
230+
<ClInclude Include="src\Ext\HouseType\Body.h" />
228231
<ClInclude Include="src\New\Entity\Ares\RadarJammerClass.h" />
229232
<ClInclude Include="src\New\Type\Affiliated\CreateUnitTypeClass.h" />
230233
<ClInclude Include="src\Blowfish\blowfish.h" />
@@ -275,6 +278,7 @@
275278
<ClInclude Include="src\New\Type\Affiliated\TypeConvertGroup.h" />
276279
<ClInclude Include="src\New\Type\Affiliated\DroppodTypeClass.h" />
277280
<ClInclude Include="src\New\Type\DigitalDisplayTypeClass.h" />
281+
<ClInclude Include="src\New\Type\EVATypeClass.h" />
278282
<ClInclude Include="src\New\Type\InsigniaTypeClass.h" />
279283
<ClInclude Include="src\New\Type\RadTypeClass.h" />
280284
<ClInclude Include="src\New\Type\SelectBoxTypeClass.h" />

docs/Fixed-or-Improved-Logics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
373373
- Fixed a bug where passengers created by the InitialPayload logic or TeamType with `Full=true` would fail to fire when the transport unit with `OpenTopped=yes` moved to an area that the passengers' `MovementZone` cannot move into.
374374
- Fixed a bug where game will crash after loading if a techno with `AlphaImage` converts to a type without it, or an anim with `AlphaImage` changes to a type without it through `Next`.
375375
- Fixed the issue that `BombSight` not being updated correctly in techno conversion.
376+
- `EVA.Tag` already supports being set for specific countries, and `EVAIndex` is no longer reset after load game.
376377

377378
## Newly added global settings
378379

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ Fixes / interactions with other extensions:
720720
- Fixed a bug where passengers created by the InitialPayload logic or TeamType with `Full=true` would fail to fire when the transport unit with `OpenTopped=yes` moved to an area that the passengers' `MovementZone` cannot move into (by NetsuNegi)
721721
- Fixed a bug where game will crash after loading if a techno with `AlphaImage` converts to a type without it, or an anim with `AlphaImage` changes to a type without it through `Next` (by NetsuNegi & FlyStar)
722722
- Fixed the issue that `BombSight` not being updated correctly in techno conversion (by TaranDahl)
723+
- `EVA.Tag` already supports being set for specific countries, and `EVAIndex` is no longer reset after load game (by FlyStar)
723724
```
724725

725726
### 0.4.0.3

src/Ext/HouseType/Body.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#include "Body.h"
2+
3+
#include <Ext/Side/Body.h>
4+
#include <Utilities/GeneralUtils.h>
5+
6+
HouseTypeExt::ExtContainer HouseTypeExt::ExtMap;
7+
8+
void HouseTypeExt::ExtData::Initialize() { }
9+
10+
void HouseTypeExt::ExtData::LoadFromINIFile(CCINIClass* pINI)
11+
{
12+
auto pThis = this->OwnerObject();
13+
const char* pSection = pThis->ID;
14+
15+
if (!pINI->GetSection(pSection))
16+
return;
17+
18+
INI_EX exINI(pINI);
19+
20+
this->EVATag.Read(pINI, pSection, "EVA.Tag");
21+
}
22+
23+
template <typename T>
24+
void HouseTypeExt::ExtData::Serialize(T& Stm)
25+
{
26+
Stm
27+
.Process(this->EVATag)
28+
;
29+
}
30+
31+
void HouseTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
32+
{
33+
Extension<HouseTypeClass>::LoadFromStream(Stm);
34+
this->Serialize(Stm);
35+
}
36+
37+
void HouseTypeExt::ExtData::SaveToStream(PhobosStreamWriter& Stm)
38+
{
39+
Extension<HouseTypeClass>::SaveToStream(Stm);
40+
this->Serialize(Stm);
41+
}
42+
43+
bool HouseTypeExt::LoadGlobals(PhobosStreamReader& Stm)
44+
{
45+
return Stm
46+
.Success();
47+
}
48+
49+
bool HouseTypeExt::SaveGlobals(PhobosStreamWriter& Stm)
50+
{
51+
return Stm
52+
.Success();
53+
}
54+
55+
// =============================
56+
// container
57+
58+
HouseTypeExt::ExtContainer::ExtContainer() : Container("HouseTypeClass") { }
59+
HouseTypeExt::ExtContainer::~ExtContainer() = default;
60+
61+
// =============================
62+
// container hooks
63+
64+
DEFINE_HOOK(0x511635, HouseTypeClass_CTOR_1, 0x5)
65+
{
66+
GET(HouseTypeClass*, pItem, EAX);
67+
68+
HouseTypeExt::ExtMap.TryAllocate(pItem);
69+
return 0;
70+
}
71+
72+
DEFINE_HOOK(0x511643, HouseTypeClass_CTOR_2, 0x5)
73+
{
74+
GET(HouseTypeClass*, pItem, EAX);
75+
76+
HouseTypeExt::ExtMap.TryAllocate(pItem);
77+
return 0;
78+
}
79+
80+
DEFINE_HOOK(0x5127CF, HouseTypeClass_DTOR, 0x6)
81+
{
82+
GET(HouseTypeClass*, pItem, ESI);
83+
84+
HouseTypeExt::ExtMap.Remove(pItem);
85+
return 0;
86+
}
87+
88+
DEFINE_HOOK_AGAIN(0x512480, HouseTypeClass_SaveLoad_Prefix, 0x5)
89+
DEFINE_HOOK(0x512290, HouseTypeClass_SaveLoad_Prefix, 0x5)
90+
{
91+
GET_STACK(HouseTypeClass*, pItem, 0x4);
92+
GET_STACK(IStream*, pStm, 0x8);
93+
94+
HouseTypeExt::ExtMap.PrepareStream(pItem, pStm);
95+
96+
return 0;
97+
}
98+
99+
DEFINE_HOOK(0x51246D, HouseTypeClass_Load_Suffix, 0x5)
100+
{
101+
102+
HouseTypeExt::ExtMap.LoadStatic();
103+
return 0;
104+
}
105+
106+
DEFINE_HOOK(0x51255C, HouseTypeClass_Save_Suffix, 0x5)
107+
{
108+
HouseTypeExt::ExtMap.SaveStatic();
109+
return 0;
110+
}
111+
112+
DEFINE_HOOK_AGAIN(0x51215A, HouseTypeClass_LoadFromINI, 0x5)
113+
DEFINE_HOOK(0x51214F, HouseTypeClass_LoadFromINI, 0x5)
114+
{
115+
GET(HouseTypeClass*, pItem, EBX);
116+
GET_BASE(CCINIClass*, pINI, 0x8);
117+
118+
HouseTypeExt::ExtMap.LoadFromINI(pItem, pINI);
119+
return 0;
120+
}

src/Ext/HouseType/Body.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#pragma once
2+
3+
#include <HouseTypeClass.h>
4+
5+
#include <Utilities/Container.h>
6+
#include <Utilities/TemplateDef.h>
7+
8+
#include <New/Type/EVATypeClass.h>
9+
10+
class HouseTypeExt
11+
{
12+
public:
13+
using base_type = HouseTypeClass;
14+
15+
static constexpr DWORD Canary = 0xAFFEAFFE;
16+
static constexpr size_t ExtPointerOffset = 0x1AC;
17+
18+
class ExtData final : public Extension<HouseTypeClass>
19+
{
20+
public:
21+
EVAType EVATag;
22+
23+
ExtData(HouseTypeClass* OwnerObject) : Extension<HouseTypeClass>(OwnerObject)
24+
, EVATag { -2 }
25+
{ }
26+
27+
virtual ~ExtData() = default;
28+
29+
virtual void LoadFromINIFile(CCINIClass* pINI) override;
30+
virtual void Initialize() override;
31+
virtual void InvalidatePointer(void* ptr, bool bRemoved) override { }
32+
33+
virtual void LoadFromStream(PhobosStreamReader& Stm) override;
34+
virtual void SaveToStream(PhobosStreamWriter& Stm) override;
35+
36+
private:
37+
template <typename T>
38+
void Serialize(T& Stm);
39+
};
40+
41+
class ExtContainer final : public Container<HouseTypeExt>
42+
{
43+
public:
44+
ExtContainer();
45+
~ExtContainer();
46+
};
47+
48+
static bool LoadGlobals(PhobosStreamReader& Stm);
49+
static bool SaveGlobals(PhobosStreamWriter& Stm);
50+
51+
static ExtContainer ExtMap;
52+
};

src/Ext/HouseType/Hooks.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "Body.h"
2+
3+
#include <Ext/Scenario/Body.h>
4+
5+
DEFINE_HOOK(0x535005, ScenarioClass_LoadSide_SetEVAIndex, 0x6)
6+
{
7+
if (ScenarioExt::Global()->EVAIndex != -2)
8+
{
9+
VoxClass::EVAIndex = ScenarioExt::Global()->EVAIndex;
10+
}
11+
// I don't know why, but if you don't do it this way, it might not work.
12+
else if (SessionClass::Instance.IsCampaign())
13+
{
14+
if (const auto pHouse = HouseClass::CurrentPlayer)
15+
{
16+
const int EVAIndex = HouseTypeExt::ExtMap.Find(pHouse->Type)->EVATag;
17+
18+
if (EVAIndex != -2)
19+
VoxClass::EVAIndex = EVAIndex;
20+
}
21+
}
22+
23+
return 0;
24+
}
25+
26+
DEFINE_HOOK(0x68AD0C, ScenarioClass_ReadMap_SetEVAIndex, 0x7)
27+
{
28+
if (const auto pHouse = HouseClass::CurrentPlayer)
29+
{
30+
const int EVAIndex = HouseTypeExt::ExtMap.Find(pHouse->Type)->EVATag;
31+
32+
if (EVAIndex != -2)
33+
VoxClass::EVAIndex = EVAIndex;
34+
}
35+
36+
return 0;
37+
}

src/Ext/Scenario/Body.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ void ScenarioExt::ExtData::Serialize(T& Stm)
177177
.Process(this->UndergroundTracker)
178178
.Process(this->SpecialTracker)
179179
.Process(this->FallingDownTracker)
180+
.Process(this->EVAIndex)
180181
;
181182
}
182183

@@ -188,6 +189,8 @@ void ScenarioExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
188189

189190
void ScenarioExt::ExtData::SaveToStream(PhobosStreamWriter& Stm)
190191
{
192+
Global()->EVAIndex = VoxClass::EVAIndex;
193+
191194
Extension<ScenarioClass>::SaveToStream(Stm);
192195
this->Serialize(Stm);
193196
}

src/Ext/Scenario/Body.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class ScenarioExt
4848
DynamicVectorClass<TechnoClass*> SpecialTracker; // For special purposes, like tracking technos that are forced moving. Currently unused.
4949
DynamicVectorClass<TechnoClass*> FallingDownTracker; // Technos that are falling down, parachutes and land technos falling from bridge.
5050

51+
int EVAIndex;
52+
5153
ExtData(ScenarioClass* OwnerObject) : Extension<ScenarioClass>(OwnerObject)
5254
, ShowBriefing { false }
5355
, BriefingTheme { -1 }
@@ -65,6 +67,7 @@ class ScenarioExt
6567
, UndergroundTracker {}
6668
, SpecialTracker {}
6769
, FallingDownTracker {}
70+
, EVAIndex { -2 }
6871
{ }
6972

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

src/New/Type/EVATypeClass.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#pragma once
2+
3+
#include <Utilities/Enumerable.h>
4+
#include <Utilities/TemplateDef.h>
5+
#include <Utilities/AresFunctions.h>
6+
#include <Utilities/AresHelper.h>
7+
8+
class EVAType : public Valueable<int>
9+
{
10+
public:
11+
template <typename T>
12+
EVAType(T value)
13+
{
14+
this->Value = (int)std::move(value);
15+
}
16+
17+
template <typename T>
18+
EVAType& operator = (T value)
19+
{
20+
this->Value = std::move(value);
21+
return *this;
22+
}
23+
24+
bool Read(CCINIClass* pINI, const char* pSection, const char* pKey)
25+
{
26+
int buffer = this->Value;
27+
28+
if (pINI->ReadString(pSection, pKey, "", Phobos::readBuffer))
29+
{
30+
if (AresHelper::CanUseAres)
31+
buffer = AresFunctions::FindEVAIndex(Phobos::readBuffer);
32+
else if (!strcmp(Phobos::readBuffer, "Allied"))
33+
buffer = 0;
34+
else if (!strcmp(Phobos::readBuffer, "Russian"))
35+
buffer = 1;
36+
else if (!strcmp(Phobos::readBuffer, "Yuri"))
37+
buffer = 2;
38+
}
39+
40+
if (buffer >= 0 || INIClass::IsBlank(Phobos::readBuffer))
41+
{
42+
this->Value = buffer;
43+
return true;
44+
}
45+
46+
return false;
47+
}
48+
};

0 commit comments

Comments
 (0)