diff --git a/CREDITS.md b/CREDITS.md index 9b4105fd33..44c87160fb 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -521,6 +521,7 @@ This page lists all the individual contributions to the project by their author. - Allow the use of more precise calculation of repair costs - Fix the initial direction of building placed by Ares's UnitDelivery superweapon - Customize default mirage disguises per vehicletypes + - Allow customize jumpjet properties on warhead - **Apollo** - Translucent SHP drawing patches - **ststl**: - Customizable `ShowTimer` priority of superweapons diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 703e91301c..6c2070cb3b 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -2497,6 +2497,24 @@ In `rulesmd.ini`: DecloakDamagedTargets=true ; boolean ``` +### Customizing locomotor warhead + +- Now you can customize jumpjet properties on warhead. + +In `rulesmd.ini`: +```ini +[SOMEWARHEAD] ; WarheadType with IsLocomotor and Locomotor=Jumpjet +JumpjetTurnRate= ; Integer, default to [TechnoType] -> JumpjetTurnRate +JumpjetSpeed= ; Integer, default to [TechnoType] -> JumpjetSpeed +JumpjetClimb= ; floating point value, default to [TechnoType] -> JumpjetClimb +JumpjetCrash= ; floating point value, default to [TechnoType] -> JumpjetCrash +JumpjetHeight= ; Integer, default to [TechnoType] -> JumpjetHeight +JumpjetAccel= ; floating point value, default to [TechnoType] -> JumpjetAccel +JumpjetWobbles= ; floating point value, default to [TechnoType] -> JumpjetWobbles +JumpjetNoWobbles= ; boolean, default to [TechnoType] -> JumpjetNoWobbles +JumpjetDeviation= ; Integer, default to [TechnoType] -> JumpjetDeviation +``` + ### Customizing parasite - Now you can specify which targets the parasite will culling them. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 077ec39649..3109a5d109 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -559,6 +559,7 @@ New: - Add toggle of whether shield use ArmorMultiplier or not (by NetsuNegi) - Allow the [use of more precise calculation of repair costs](Fixed-or-Improved-Logics.md#use-more-precise-calculation-of-repair-costs) (by NetsuNegi) - [Customize default mirage disguises per vehicletypes](New-or-Enhanced-Logics.md#default-mirage-disguise-for-individual-vehicletypes) (by NetsuNegi) +- [Allow customize jumpjet properties on warhead](Fixed-or-Improved-Logics.md#customizing-locomotor-warhead) (by NetsuNegi) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) diff --git a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po index 6e3ca5d7a0..44b1407bc6 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po +++ b/docs/locale/zh_CN/LC_MESSAGES/CREDITS.po @@ -1710,6 +1710,11 @@ msgid "" msgstr "" "为每个载具类型单独定义默认的幻影伪装类型" +msgid "" +"Allow customize jumpjet properties on warhead" +msgstr "" +"允许在弹头上自定义 Jumpjet 属性" + msgid "**Apollo** - Translucent SHP drawing patches" msgstr "**Apollo** - 半透明 SHP 绘制补丁" diff --git a/docs/locale/zh_CN/LC_MESSAGES/Fixed-or-Improved-Logics.po b/docs/locale/zh_CN/LC_MESSAGES/Fixed-or-Improved-Logics.po index 65f4e83eb3..59a2bc576d 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/Fixed-or-Improved-Logics.po +++ b/docs/locale/zh_CN/LC_MESSAGES/Fixed-or-Improved-Logics.po @@ -5181,6 +5181,12 @@ msgid "" "damaged by the warhead." msgstr "现在你可以指定被这个弹头杀伤的对象是否解除隐形。" +msgid "Customizing locomotor warhead" +msgstr "自定义运动模式弹头" + +msgid "Now you can customize jumpjet properties on warhead." +msgstr "现在你可以在弹头上指定 Jumpjet 属性了。" + msgid "Customizing parasite" msgstr "自定义寄生" diff --git a/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po b/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po index be6e85ae83..7f591e154b 100644 --- a/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po +++ b/docs/locale/zh_CN/LC_MESSAGES/Whats-New.po @@ -1786,6 +1786,13 @@ msgstr "" "[为每个载具类型单独定义默认的幻影伪装类型](New-or-Enhanced-Logics.md#" "default-mirage-disguise-for-individual-vehicletypes)(by NetsuNegi)" +msgid "" +"[Allow customize jumpjet properties on warhead](Fixed-or-Improved-" +"Logics.md#customizing-locomotor-warhead) (by NetsuNegi)" +msgstr "" +"[允许在弹头上自定义 Jumpjet 属性](Fixed-or-Improved-" +"Logics.md#customizing-locomotor-warhead)(by NetsuNegi)" + msgid "Vanilla fixes:" msgstr "原版问题修复:" diff --git a/src/Ext/Techno/Body.cpp b/src/Ext/Techno/Body.cpp index dfc6d58c79..9ed28305bf 100644 --- a/src/Ext/Techno/Body.cpp +++ b/src/Ext/Techno/Body.cpp @@ -1014,6 +1014,7 @@ void TechnoExt::ExtData::Serialize(T& Stm) .Process(this->PassengerDeletionTimer) .Process(this->CurrentShieldType) .Process(this->LastWarpDistance) + .Process(this->JumpjetSpeed) .Process(this->ChargeTurretTimer) .Process(this->AutoDeathTimer) .Process(this->MindControlRingAnimType) diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index 57d9f650dd..7cceb902fb 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -36,6 +36,7 @@ class TechnoExt CDTimerClass PassengerDeletionTimer; ShieldTypeClass* CurrentShieldType; int LastWarpDistance; + int JumpjetSpeed; CDTimerClass ChargeTurretTimer; // Used for charge turrets instead of RearmTimer if weapon has ChargeTurret.Delays set. CDTimerClass AutoDeathTimer; AnimTypeClass* MindControlRingAnimType; @@ -119,6 +120,7 @@ class TechnoExt , PassengerDeletionTimer {} , CurrentShieldType { nullptr } , LastWarpDistance {} + , JumpjetSpeed { 14 } // 0x7115B8 , ChargeTurretTimer {} , AutoDeathTimer {} , MindControlRingAnimType { nullptr } diff --git a/src/Ext/Unit/Hooks.Jumpjet.cpp b/src/Ext/Unit/Hooks.Jumpjet.cpp index 280a9082ca..dd50e3324f 100644 --- a/src/Ext/Unit/Hooks.Jumpjet.cpp +++ b/src/Ext/Unit/Hooks.Jumpjet.cpp @@ -2,6 +2,7 @@ #include #include +#include // Misc jumpjet facing, turning, drawing fix -- Author: Trsdy // Jumpjets stuck at FireError::FACING because Jumpjet has its own facing just for JumpjetTurnRate @@ -180,13 +181,14 @@ DEFINE_FUNCTION_JUMP(VTABLE, 0x7ECDF4, JumpjetLocomotionClass_Can_Fire); DEFINE_HOOK(0x54DAC4, JumpjetLocomotionClass_EndPiggyback_Blyat, 0x6) { GET(FootClass*, pLinkedTo, EAX); - auto const* pType = pLinkedTo->GetTechnoType(); + const auto pType = pLinkedTo->GetTechnoType(); + const auto pExt = TechnoExt::ExtMap.Find(pLinkedTo); + pExt->JumpjetSpeed = pType->JumpjetSpeed; pLinkedTo->PrimaryFacing.SetROT(pType->ROT); if (pType->SensorsSight) { - const auto pExt = TechnoExt::ExtMap.Find(pLinkedTo); pLinkedTo->RemoveSensorsAt(pExt->LastSensorsMapCoords); pLinkedTo->AddSensorsAt(CellStruct::Empty); } @@ -454,3 +456,42 @@ DEFINE_HOOK(0x54D859, JumpjetLocomotionClass_GetFloorZ_IgnoreBuilding, 0x9) } #pragma endregion + +DEFINE_HOOK(0x54AD41, JumpjetLocomotionClass_Link_To_Object_LocomotorWarhead, 0x8) +{ + enum { SkipGameCode = 0x54ADF8 }; + + GET(ILocomotion*, pThis, EBP); + GET(FootClass*, pLinkedTo, EBX); + const auto pLoco = static_cast(pThis); + const auto pLinkedToExt = TechnoExt::ExtMap.Find(pLinkedTo); + const auto pType = pLinkedTo->GetTechnoType(); + + if (const auto pLocomotorWarhead = WarheadTypeExt::LocomotorWarhead) + { + const auto pWHExt = WarheadTypeExt::ExtMap.Find(pLocomotorWarhead); + pLoco->TurnRate = pWHExt->JumpjetTurnRate.Get(pType->JumpjetTurnRate); + pLoco->Speed = pLinkedToExt->JumpjetSpeed = pWHExt->JumpjetSpeed.Get(pType->JumpjetSpeed); + pLoco->Climb = pWHExt->JumpjetClimb.Get(pType->JumpjetClimb); + pLoco->Crash = pWHExt->JumpjetCrash.Get(pType->JumpjetCrash); + pLoco->Height = std::max(pWHExt->JumpjetHeight.Get(pType->JumpjetHeight), Unsorted::CellHeight); + pLoco->Accel = pWHExt->JumpjetAccel.Get(pType->JumpjetAccel); + pLoco->Wobbles = pWHExt->JumpjetWobbles.Get(pType->JumpjetWobbles); + pLoco->Deviation = pWHExt->JumpjetDeviation.Get(pType->JumpjetDeviation); + pLoco->NoWobbles = pWHExt->JumpjetNoWobbles.Get(pType->JumpjetNoWobbles); + } + else + { + pLoco->TurnRate = pType->JumpjetTurnRate; + pLoco->Speed = pLinkedToExt->JumpjetSpeed = pType->JumpjetSpeed; + pLoco->Climb = pType->JumpjetClimb; + pLoco->Crash = pType->JumpjetCrash; + pLoco->Height = std::max(pType->JumpjetHeight, Unsorted::CellHeight); + pLoco->Accel = pType->JumpjetAccel; + pLoco->Wobbles = pType->JumpjetWobbles; + pLoco->Deviation = pType->JumpjetDeviation; + pLoco->NoWobbles = pType->JumpjetNoWobbles; + } + + return SkipGameCode; +} diff --git a/src/Ext/WarheadType/Body.cpp b/src/Ext/WarheadType/Body.cpp index 3124129d53..cccf621672 100644 --- a/src/Ext/WarheadType/Body.cpp +++ b/src/Ext/WarheadType/Body.cpp @@ -4,6 +4,8 @@ WarheadTypeExt::ExtContainer WarheadTypeExt::ExtMap; +WarheadTypeClass* WarheadTypeExt::LocomotorWarhead = nullptr; + bool WarheadTypeExt::ExtData::CanTargetHouse(HouseClass* pHouse, TechnoClass* pTarget) const { if (pHouse && pTarget) @@ -291,6 +293,16 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->Parasite_CullingTarget.Read(exINI, pSection, "Parasite.CullingTarget"); this->Parasite_GrappleAnim.Read(exINI, pSection, "Parasite.GrappleAnim"); + this->JumpjetTurnRate.Read(exINI, pSection, "JumpjetTurnRate"); + this->JumpjetSpeed.Read(exINI, pSection, "JumpjetSpeed"); + this->JumpjetClimb.Read(exINI, pSection, "JumpjetClimb"); + this->JumpjetCrash.Read(exINI, pSection, "JumpjetCrash"); + this->JumpjetHeight.Read(exINI, pSection, "JumpjetHeight"); + this->JumpjetAccel.Read(exINI, pSection, "JumpjetAccel"); + this->JumpjetWobbles.Read(exINI, pSection, "JumpjetWobbles"); + this->JumpjetNoWobbles.Read(exINI, pSection, "JumpjetNoWobbles"); + this->JumpjetDeviation.Read(exINI, pSection, "JumpjetDeviation"); + this->Nonprovocative.Read(exINI, pSection, "Nonprovocative"); this->MergeBuildingDamage.Read(exINI, pSection, "MergeBuildingDamage"); @@ -666,6 +678,16 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm) .Process(this->Parasite_DisableParticleSystem) .Process(this->Parasite_CullingTarget) .Process(this->Parasite_GrappleAnim) + + .Process(this->JumpjetTurnRate) + .Process(this->JumpjetSpeed) + .Process(this->JumpjetClimb) + .Process(this->JumpjetCrash) + .Process(this->JumpjetHeight) + .Process(this->JumpjetAccel) + .Process(this->JumpjetWobbles) + .Process(this->JumpjetNoWobbles) + .Process(this->JumpjetDeviation) .Process(this->Nonprovocative) diff --git a/src/Ext/WarheadType/Body.h b/src/Ext/WarheadType/Body.h index 22715ea821..639641011f 100644 --- a/src/Ext/WarheadType/Body.h +++ b/src/Ext/WarheadType/Body.h @@ -159,6 +159,16 @@ class WarheadTypeExt Valueable Parasite_CullingTarget; NullableIdx Parasite_GrappleAnim; + Nullable JumpjetTurnRate; + Nullable JumpjetSpeed; + Nullable JumpjetClimb; + Nullable JumpjetCrash; + Nullable JumpjetHeight; + Nullable JumpjetAccel; + Nullable JumpjetWobbles; + Nullable JumpjetNoWobbles; + Nullable JumpjetDeviation; + Valueable Nonprovocative; Nullable MergeBuildingDamage; @@ -405,6 +415,16 @@ class WarheadTypeExt , Parasite_CullingTarget { AffectedTarget::Infantry } , Parasite_GrappleAnim {} + , JumpjetTurnRate {} + , JumpjetSpeed {} + , JumpjetClimb {} + , JumpjetCrash {} + , JumpjetHeight {} + , JumpjetAccel {} + , JumpjetWobbles {} + , JumpjetNoWobbles {} + , JumpjetDeviation {} + , Nonprovocative { false } , MergeBuildingDamage {} @@ -553,6 +573,8 @@ class WarheadTypeExt static bool LoadGlobals(PhobosStreamReader& Stm); static bool SaveGlobals(PhobosStreamWriter& Stm); + static WarheadTypeClass* LocomotorWarhead; + static void DetonateAt(WarheadTypeClass* pThis, AbstractClass* pTarget, TechnoClass* pOwner, int damage, HouseClass* pFiringHouse = nullptr); static void DetonateAt(WarheadTypeClass* pThis, const CoordStruct& coords, TechnoClass* pOwner, int damage, HouseClass* pFiringHouse = nullptr, AbstractClass* pTarget = nullptr); }; diff --git a/src/Ext/WarheadType/Hooks.cpp b/src/Ext/WarheadType/Hooks.cpp index a706148224..2b59d709ac 100644 --- a/src/Ext/WarheadType/Hooks.cpp +++ b/src/Ext/WarheadType/Hooks.cpp @@ -21,6 +21,21 @@ DEFINE_HOOK(0x46920B, BulletClass_Detonate, 0x6) return 0; } +// Customize Jumpjet properties on warhead +DEFINE_HOOK(0x4696CE, BulletClass_Detonate_ImbueLocomotor, 0x6) +{ + enum { SkipGameCode = 0x469AA4 }; + + GET(BulletClass* const, pBullet, ESI); + GET(FootClass* const, pTarget, EDI); + const auto pWH = pBullet->WH; + + WarheadTypeExt::LocomotorWarhead = pWH; + pBullet->Owner->ImbueLocomotor(pTarget, pWH->Locomotor); + WarheadTypeExt::LocomotorWarhead = nullptr; + return SkipGameCode; +} + DEFINE_HOOK(0x489286, MapClass_DamageArea, 0x6) { GET_BASE(const WarheadTypeClass*, pWH, 0xC); diff --git a/src/Misc/Hooks.BugFixes.cpp b/src/Misc/Hooks.BugFixes.cpp index e9ee83fd62..63873b28c9 100644 --- a/src/Misc/Hooks.BugFixes.cpp +++ b/src/Misc/Hooks.BugFixes.cpp @@ -443,7 +443,7 @@ DEFINE_HOOK(0x54D138, JumpjetLocomotionClass_Movement_AI_SpeedModifiers, 0x6) GET(JumpjetLocomotionClass*, pThis, ESI); const double multiplier = TechnoExt::GetCurrentSpeedMultiplier(pThis->LinkedTo); - pThis->Speed = (int)(pThis->LinkedTo->GetTechnoType()->JumpjetSpeed * multiplier); + pThis->Speed = static_cast(TechnoExt::ExtMap.Find(pThis->LinkedTo)->JumpjetSpeed * multiplier); return 0; }