diff --git a/CREDITS.md b/CREDITS.md index 5e57da4eb6..f3b359298d 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -446,6 +446,7 @@ This page lists all the individual contributions to the project by their author. - SkipMapSelect Enhancement - Add a global default value for `KeepAlive` - Customized transport plane for teams + - Fix the bug where *Customizable crew type per country* overrides the pre-techno settings - **NetsuNegi**: - Forbidding parallel AI queues by type - Jumpjet crash speed fix when crashing onto building @@ -764,6 +765,7 @@ This page lists all the individual contributions to the project by their author. - Customizable infantry sequence rates - Country-specific veteran buildings - Fix the Spotlight-transport interaction bug caused by the incorrect reference removal fix + - Fix the issue that *Customizable crew type per country* not considering parsing order caused game parsing failure and a warning in the log - **Ollerus**: - Build limit group enhancement - Customizable rocker amplitude diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 9854ffb58a..2cf117e54f 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -442,7 +442,7 @@ HideShakeEffects=false ; boolean - [Draw offset rules for AttachEffect animations](New-or-Enhanced-Logics.md#attached-effects) (by Starkku) - [Allowed customize that whether `Temporal=yes` warhead will cause target building animation poweroff](Fixed-or-Improved-Logics.md#allow-customize-that-whether-temporal-yes-warhead-will-cause-target-building-animation-poweroff) (by NetsuNegi) - Country-based attached effects (by Ollerus) -- [Customizable crew type per country](Fixed-or-Improved-Logics.md#customizable-crew-type-per-country) (by Sovietianqi) +- [Customizable crew type per country](Fixed-or-Improved-Logics.md#customizable-crew-type-per-country) (by Sovietianqi, FlyStar, Noble_Fish) - [Country-specific veteran buildings](Fixed-or-Improved-Logics.md#country-specific-veteran-buildings) (by Noble_Fish) #### Vanilla fixes: diff --git a/src/Ext/HouseType/Body.cpp b/src/Ext/HouseType/Body.cpp index 4b175dc4dc..5ed6681480 100644 --- a/src/Ext/HouseType/Body.cpp +++ b/src/Ext/HouseType/Body.cpp @@ -22,7 +22,7 @@ void HouseTypeExt::LoadFromINIFile(CCINIClass* pINI) this->AttachEffects.LoadFromINI(pINI, pSection); this->AttachEffects_AttachOnOwnerChange.Read(exINI, pSection, "AttachEffect.AttachOnOwnerChange"); - this->Crew.Read(exINI, pSection, "Crew"); + this->Crew.Read(exINI, pSection, "Crew"); this->VeteranBuildings.Read(exINI, pSection, "VeteranBuildings"); this->VeteranDefenses.Read(exINI, pSection, "VeteranDefenses"); diff --git a/src/Ext/HouseType/Hooks.cpp b/src/Ext/HouseType/Hooks.cpp index 46e1c86f9c..9a19756e02 100644 --- a/src/Ext/HouseType/Hooks.cpp +++ b/src/Ext/HouseType/Hooks.cpp @@ -36,22 +36,20 @@ DEFINE_HOOK(0x68AD0C, ScenarioClass_ReadMap_SetEVAIndex, 0x7) return 0; } -DEFINE_HOOK(0x707DCF, TechnoClass_GetCrew_NationalOverride, 0x5) +// Ares has taken over TechnoClass_GetCrew, so usually it won't work. +DEFINE_HOOK(0x707D40, TechnoClass_GetCrew_NationalOverride, 0x6) { - GET(TechnoClass*, pThis, ECX); + enum { SkipGameCode = 0x707D81 }; - if (!pThis) - return 0; - - HouseClass* pHouse = pThis->Owner; - - if (!pHouse) - return 0; + GET(HouseClass* const, pHouse, ECX); auto const pHouseTypeExt = HouseTypeExt::Fetch(pHouse->Type); if (pHouseTypeExt->Crew.isset()) - R->EAX(pHouseTypeExt->Crew.Get()); + { + R->ESI(pHouseTypeExt->Crew.Get()); + return SkipGameCode; + } return 0; } diff --git a/src/Misc/Hooks.Ares.cpp b/src/Misc/Hooks.Ares.cpp index 031a5f10ec..90d6e63a4c 100644 --- a/src/Misc/Hooks.Ares.cpp +++ b/src/Misc/Hooks.Ares.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -245,6 +246,20 @@ static bool __fastcall AresHouseExt_UpdateKeepAlive(AresHouseExt* pExt_Ares, voi #pragma endregion +#pragma region AresGetCrew + +static InfantryTypeClass* __fastcall AresHouseExt_GetCrew(HouseClass** pExt_Ares, void*) +{ + auto const pTypeExt = HouseTypeExt::Fetch((*pExt_Ares)->Type); + + if (pTypeExt->Crew.isset()) + return pTypeExt->Crew.Get(); + + return AresFunctions::GetCrew(pExt_Ares); +} + +#pragma endregion + DEFINE_HOOK(0x440580, BuildingClass_Unlimbo_UnitDeliveryFix, 0x5) { if (UnitDeliveryTemp::Placing) @@ -383,6 +398,9 @@ void Apply_Ares3_0_Patches() // Ares' `KeepAlive` adds global tags. Patch::Apply_LJMP(AresHelper::AresBaseAddress + 0x21F70, GET_OFFSET(AresHouseExt_UpdateKeepAlive)); + + // Add a new custom crew for a country. + Patch::Apply_CALL(AresHelper::AresBaseAddress + 0x4C836, GET_OFFSET(AresHouseExt_GetCrew)); } void Apply_Ares3_0p1_Patches() @@ -504,4 +522,7 @@ void Apply_Ares3_0p1_Patches() // Ares' `KeepAlive` adds global tags. Patch::Apply_LJMP(AresHelper::AresBaseAddress + 0x229F0, GET_OFFSET(AresHouseExt_UpdateKeepAlive)); + + // Add a new custom crew for a country. + Patch::Apply_CALL(AresHelper::AresBaseAddress + 0x4D496, GET_OFFSET(AresHouseExt_GetCrew)); } diff --git a/src/Utilities/AresAddressInit.cpp b/src/Utilities/AresAddressInit.cpp index 08576b92b8..bbc56e475c 100644 --- a/src/Utilities/AresAddressInit.cpp +++ b/src/Utilities/AresAddressInit.cpp @@ -7,7 +7,6 @@ decltype(AresFunctions::ConvertTypeTo) AresFunctions::ConvertTypeTo = nullptr; decltype(AresFunctions::CreateAresEBolt) AresFunctions::CreateAresEBolt = nullptr; decltype(AresFunctions::SpawnSurvivors) AresFunctions::SpawnSurvivors = nullptr; -decltype(AresFunctions::ReverseEngineer) AresFunctions::ReverseEngineer = nullptr; decltype(AresFunctions::IsTargetConstraintsEligible) AresFunctions::IsTargetConstraintsEligible = nullptr; decltype(AresFunctions::UnitDeliveryStateMachine_Update) AresFunctions::UnitDeliveryStateMachine_Update = nullptr; decltype(AresFunctions::SetSpotlight) AresFunctions::SetSpotlight = nullptr; @@ -21,6 +20,9 @@ PhobosMap* AresFunctions::BombExtMap = nullptr; decltype(AresFunctions::GetTunnel) AresFunctions::GetTunnel = nullptr; decltype(AresFunctions::AddPassengerFromTunnel) AresFunctions::AddPassengerFromTunnel = nullptr; +decltype(AresFunctions::ReverseEngineer) AresFunctions::ReverseEngineer = nullptr; +decltype(AresFunctions::GetCrew) AresFunctions::GetCrew = nullptr; + decltype(AresFunctions::FindEVAIndex) AresFunctions::FindEVAIndex = nullptr; void* AresFunctions::_SWTypeExtMap = nullptr; @@ -46,8 +48,6 @@ void AresFunctions::InitAres3_0() NOTE_ARES_FUN(SpawnSurvivors, 0x464C0); } - NOTE_ARES_FUN(ReverseEngineer, 0x022360); - NOTE_ARES_FUN(IsTargetConstraintsEligible, 0x032110); NOTE_ARES_FUN(UnitDeliveryStateMachine_Update, 0x075DE0); @@ -71,6 +71,10 @@ void AresFunctions::InitAres3_0() NOTE_ARES_FUN(AresFunctions::GetTunnel, 0x0D740); NOTE_ARES_FUN(AresFunctions::AddPassengerFromTunnel, 0x09000); + // HouseExt + NOTE_ARES_FUN(ReverseEngineer, 0x022360); + NOTE_ARES_FUN(GetCrew, 0x021230); + // VoxClass NOTE_ARES_FUN(AresFunctions::FindEVAIndex, 0x063560); @@ -96,8 +100,6 @@ void AresFunctions::InitAres3_0p1() NOTE_ARES_FUN(SpawnSurvivors, 0x47030); } - NOTE_ARES_FUN(ReverseEngineer, 0x022DE0); - NOTE_ARES_FUN(IsTargetConstraintsEligible, 0x032AF0); NOTE_ARES_FUN(UnitDeliveryStateMachine_Update, 0x076E90); @@ -121,6 +123,10 @@ void AresFunctions::InitAres3_0p1() NOTE_ARES_FUN(AresFunctions::GetTunnel, 0x0DA30); NOTE_ARES_FUN(AresFunctions::AddPassengerFromTunnel, 0x09040); + // HouseExt + NOTE_ARES_FUN(ReverseEngineer, 0x022DE0); + NOTE_ARES_FUN(GetCrew, 0x021CB0); + // VoxClass NOTE_ARES_FUN(AresFunctions::FindEVAIndex, 0x0642B0); diff --git a/src/Utilities/AresFunctions.h b/src/Utilities/AresFunctions.h index 41b09b148f..0a3eb40c49 100644 --- a/src/Utilities/AresFunctions.h +++ b/src/Utilities/AresFunctions.h @@ -33,8 +33,6 @@ class AresFunctions static void(__stdcall* SpawnSurvivors)(FootClass* pThis, TechnoClass* pKiller, bool Select, bool PreventEscape); - static bool(__thiscall* ReverseEngineer)(void* pAresHouseExt, TechnoTypeClass* pType); - static bool(__thiscall* IsTargetConstraintsEligible)(void*, HouseClass*, bool); static void(__thiscall* UnitDeliveryStateMachine_Update)(void*); @@ -57,6 +55,10 @@ class AresFunctions static void* (__thiscall* GetTunnel)(void*, HouseClass*); static void(__thiscall* AddPassengerFromTunnel)(void*, BuildingClass*, FootClass*); + // HouseExt + static bool(__thiscall* ReverseEngineer)(void*, TechnoTypeClass* pType); + static InfantryTypeClass* (__thiscall* GetCrew)(void*); + // VoxClass static int(__stdcall* FindEVAIndex)(const char* buffer); private: