diff --git a/Phobos.vcxproj b/Phobos.vcxproj index 819c7037b0..87ee4f3c6a 100644 --- a/Phobos.vcxproj +++ b/Phobos.vcxproj @@ -32,6 +32,7 @@ + diff --git a/README.md b/README.md index 327226c265..169229e17b 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Credits - wiktorderelf - overhauled Unicode font - Thrifinesma (Uranusian) - Mind Control enhancement, custom warhead splash list, harvesters counter, promoted spawns, shields, overhauled Unicode font, help with docs - SEC-SOME (secsome) - debug info dump hotkey, refactoring & porting of Ares helper code, introducing more Ares-derived stuff, disguise removal warhead, Mind Control removal warhead, Mind Control enhancement, shields -- Otamaa (BoredEXE) - help with CellSpread, ported and fixed custom RadType code , Disable spesific ElectricBolt bolt +- Otamaa (BoredEXE) - help with CellSpread, ported and fixed custom RadType code, togglable ElectricBolt bolts, customizable Chrono Locomotor properties per TechnoClass - E1 Elite - TileSet 255 and above bridge repair fix - FS-21 - Dump Object Info enhancements, Powered.KillSpawns, Spawner.LimitRange, ScriptType Actions 71, 72 & 73, MC deployer fixes, help with docs - AutoGavy - interceptor logic, warhead critical damage system diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 415ff0cc4a..ff71d7d8e4 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -57,6 +57,30 @@ SpawnsTiberium.Range=1 ; integer, radius in cells SpawnsTiberium.GrowthStage=3 ; single int / comma-sep. range ``` +## TechnoType + +### Customizable Teleport/Chrono Locomotor settings per TechnoType + +![image](_static/images/cust-Chrono.gif) +*Chrono Legionere and Ronco (hero) from [YR:New War] (https://www.moddb.com/mods/yuris-revenge-new-war)* + +- You can now specify Teleport/Chrono Locomotor settings per TechnoType to override default rules values. Unfilled values default to values in `[General]`. +- Only applicable to Techno that have Teleport/Chrono Locomotor attached. + +In `rulesmd.ini`: +```ini +[SOMETECHNO] ; TechnoType +WarpOut= ; Anim (played when Techno warping out) +WarpIn= ; Anim (played when Techno warping in) +WarpAway= ; Anim (played when Techno chronowarped by chronosphere) +ChronoTrigger= ; boolean, if yes then delay varies by distance, if no it is a constant +ChronoDistanceFactor= ; integer, amount to divide the distance to destination by to get the warped out delay +ChronoMinimumDelay= ; integer, the minimum delay for teleporting, no matter how short the distance +ChronoRangeMinimum= ; integer, can be used to set a small range within which the delay is constant +ChronoDelay= ; integer, delay after teleport for chronosphere + +``` + ## Weapons ### Togglable ElectricBolt visuals diff --git a/docs/_static/images/cust-Chrono.gif b/docs/_static/images/cust-Chrono.gif new file mode 100644 index 0000000000..68ba3dff56 Binary files /dev/null and b/docs/_static/images/cust-Chrono.gif differ diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index b373d0e066..0f8b58eb87 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -117,6 +117,17 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->Shield_HitAnim.Read(exINI, pSection, "Shield.HitAnim"); this->Shield_BracketDelta.Read(exINI, pSection, "Shield.BracketDelta"); + // + this->WarpOut.Read(exINI, pSection, "WarpOut"); + this->WarpIn.Read(exINI, pSection, "WarpIn"); + this->WarpAway.Read(exINI, pSection, "WarpAway"); + this->ChronoTrigger.Read(exINI, pSection, "ChronoTrigger"); + this->ChronoDistanceFactor.Read(exINI, pSection, "ChronoDistanceFactor"); + this->ChronoMinimumDelay.Read(exINI, pSection, "ChronoMinimumDelay"); + this->ChronoRangeMinimum.Read(exINI, pSection, "ChronoRangeMinimum"); + this->ChronoDelay.Read(exINI, pSection, "ChronoDelay"); + + // Ares 0.A this->GroupAs.Read(pINI, pSection, "GroupAs"); @@ -158,6 +169,14 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->Shield_BreakAnim) .Process(this->Shield_RespawnAnim) .Process(this->Shield_HitAnim) + .Process(this->WarpOut) + .Process(this->WarpIn) + .Process(this->WarpAway) + .Process(this->ChronoTrigger) + .Process(this->ChronoDistanceFactor) + .Process(this->ChronoMinimumDelay) + .Process(this->ChronoRangeMinimum) + .Process(this->ChronoDelay) ; } void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 0731acfb2d..a6386ba53a 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -45,6 +45,15 @@ class TechnoTypeExt Nullable Shield_RespawnAnim; Nullable Shield_HitAnim; + Nullable WarpOut; + Nullable WarpIn; + Nullable WarpAway; + Nullable ChronoTrigger; + Nullable ChronoDistanceFactor; + Nullable ChronoMinimumDelay; + Nullable ChronoRangeMinimum; + Nullable ChronoDelay; + ExtData(TechnoTypeClass* OwnerObject) : Extension(OwnerObject), HealthBar_Hide(false), UIDescription(), @@ -74,7 +83,15 @@ class TechnoTypeExt Shield_IdleAnim(), Shield_BreakAnim(), Shield_RespawnAnim(), - Shield_HitAnim() + Shield_HitAnim(), + WarpOut(), + WarpIn(), + WarpAway(), + ChronoTrigger(), + ChronoDistanceFactor(), + ChronoMinimumDelay(), + ChronoRangeMinimum(), + ChronoDelay() { } virtual ~ExtData() = default; diff --git a/src/Ext/TechnoType/Hooks.Teleport.cpp b/src/Ext/TechnoType/Hooks.Teleport.cpp new file mode 100644 index 0000000000..09cd876caf --- /dev/null +++ b/src/Ext/TechnoType/Hooks.Teleport.cpp @@ -0,0 +1,99 @@ +#include "Body.h" +#include +#include + +#define GET_LOCO(reg_Loco) \ + GET(ILocomotion *, Loco, reg_Loco); \ + TeleportLocomotionClass *pLocomotor = static_cast(Loco); \ + TechnoTypeClass *pType = pLocomotor->LinkedTo->GetTechnoType(); \ + TechnoTypeExt::ExtData *pExt = TechnoTypeExt::ExtMap.Find(pType); + +DEFINE_HOOK(719439, TeleportLocomotionClass_ILocomotion_Process_WarpoutAnim, 6) +{ + GET_LOCO(ESI); + + R->EDX(pExt->WarpOut.Get(RulesClass::Instance->WarpOut)); + + return 0x71943F; +} + +DEFINE_HOOK(719788, TeleportLocomotionClass_ILocomotion_Process_WarpInAnim, 6) +{ + GET_LOCO(ESI); + + R->EDX(pExt->WarpIn.Get(RulesClass::Instance->WarpOut)); + + return 0x71978E; +} + +DEFINE_HOOK(71986A, TeleportLocomotionClass_ILocomotion_Process_WarpAway, 6) +{ + GET_LOCO(ESI); + + R->ECX(pExt->WarpAway.Get(RulesClass::Instance->WarpOut)); + + return 0x719870; +} + +DEFINE_HOOK(7194D0, TeleportLocomotionClass_ILocomotion_Process_ChronoTrigger, 6) +{ + GET_LOCO(ESI); + + R->AL(pExt->ChronoTrigger.Get(RulesClass::Instance->ChronoTrigger)); + + return 0x7194D6; +} + +DEFINE_HOOK(7194E3, TeleportLocomotionClass_ILocomotion_Process_ChronoDistanceFactor, 6) +{ + GET_LOCO(ESI); + GET(int, val, EAX); + + auto factor = pExt->ChronoDistanceFactor.Get(RulesClass::Instance->ChronoDistanceFactor); + factor = factor == 0 ? 1 : factor; //fix factor 0 crash by force it to 1 (Vanilla bug) + + //IDIV + R->EAX(val / factor); + R->EDX(val % factor); + + return 0x7194E9; +} + +DEFINE_HOOK(719519, TeleportLocomotionClass_ILocomotion_Process_ChronoMinimumDelay, 6) +{ + GET_LOCO(ESI); + + R->EBX(pExt->ChronoMinimumDelay.Get(RulesClass::Instance->ChronoMinimumDelay)); + + return 0x71951F; +} + +DEFINE_HOOK(719562, TeleportLocomotionClass_ILocomotion_Process_ChronoMinimumDelay2, 6) +{ + GET_LOCO(ESI); + + R->ECX(pExt->ChronoMinimumDelay.Get(RulesClass::Instance->ChronoMinimumDelay)); + + return 0x719568; +} + +DEFINE_HOOK(719555, TeleportLocomotionClass_ILocomotion_Process_ChronoRangeMinimum, 6) +{ + GET_LOCO(ESI); + GET(int, comparator, EDX); + + auto factor = pExt->ChronoRangeMinimum.Get(RulesClass::Instance->ChronoRangeMinimum); + + return comparator < factor ? 0x71955D : 0x719576; +} + +DEFINE_HOOK(71997B, TeleportLocomotionClass_ILocomotion_Process_ChronoDelay, 6) +{ + GET_LOCO(ESI); + + R->ECX(pExt->ChronoDelay.Get(RulesClass::Instance->ChronoDelay)); + + return 0x719981; +} + +#undef GET_LOCO \ No newline at end of file