diff --git a/CREDITS.md b/CREDITS.md index 3497c053a7..9c4195e714 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -685,6 +685,7 @@ This page lists all the individual contributions to the project by their author. - Allow customizing whether the creation of shrapnel weapon is controlled by the new target check on the warhead of the parent weapon - Customize `Tiled` drawing interval and centering - Customize whether technos with `Locomotor=Fly` wobble + - Customize the landing animation of technos that have `Locomotor=Fly` - **Ollerus**: - Build limit group enhancement - Customizable rocker amplitude diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index f075411878..ac8586ffcc 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -1749,6 +1749,21 @@ FallingDownDamage.Water= ; integer / percentage FallingDownDamage.AllowEMP=true ; boolean ``` +### Customize the landing animation of technos that have `Locomotor=Fly` + +- In vanilla, if a techno has `Locomotor=Fly` and `IsDropship=true`, it plays the `[DROPLAND]` animation when landing; if `IsDropship=false` but it is an aircraft with `Carryall=true`, it will play the `[CARYLAND]` animation when landing. Now you can customize this logic. + +In `rulesmd.ini`: +```ini +[AudioVisual] +DefaultLandingAnim= ; AnimationType +DefaultLandingAnim.Dropship=DROPLAND ; AnimationType +DefaultLandingAnim.Carryall=CARYLAND ; AnimationType + +[SOMETECHNO] ; TechnoType +LandingAnim= ; AnimationType, defaults to the global default (none, DROPLAND, or CARYLAND) based on unit's IsDropship/Carryall flags +``` + ### Customize whether technos with `Locomotor=Fly` wobble - In vanilla, if technos use `Locomotor=Fly` and do not have `IsDropship=true`, they will have a hardcoded wobble effect. However, using `IsDropship=true` also introduces a series of hardcoded behaviors associated with it. Now, you can customize whether to disable this behavior, and it can also be used to enable this behavior for technos with `IsDropship=true`. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 0b297249f0..aae141bdc5 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -592,6 +592,7 @@ HideShakeEffects=false ; boolean - [Animation transparency customization settings](New-or-Enhanced-Logics.md#customizable-animation-transparency-settings) (by Starkku) - [Customize `Tiled` drawing interval and centering](Fixed-or-Improved-Logics.md#customize-the-drawing-interval-for-tiled) (by Noble_Fish) - [Customize whether technos with `Locomotor=Fly` wobble](Fixed-or-Improved-Logics.md#customize-whether-technos-with-locomotor-fly-wobble) (by Noble_Fish) +- [Customize the landing animation of technos that have `Locomotor=Fly`](Fixed-or-Improved-Logics.md#customize-the-landing-animation-of-technos-that-have-locomotor-fly) (by Noble_Fish) #### 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/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 5c9d173b92..5ddb243507 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -428,6 +428,10 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->FlyNoWobbles.Read(exINI, GameStrings::AudioVisual, "FlyNoWobbles"); + this->DefaultLandingAnim.Read(exINI, GameStrings::AudioVisual, "DefaultLandingAnim"); + this->DefaultLandingAnim_Dropship.Read(exINI, GameStrings::AudioVisual, "DefaultLandingAnim.Dropship"); + this->DefaultLandingAnim_Carryall.Read(exINI, GameStrings::AudioVisual, "DefaultLandingAnim.Carryall"); + this->TeamDelays_DynamicType.Read(exINI, GameStrings::General, "TeamDelays.DynamicType"); char tempBuffer[40]; @@ -775,6 +779,9 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->RemoveMindControl_Silent) .Process(this->MindControl_Permanent_ReplaceSilent) .Process(this->FlyNoWobbles) + .Process(this->DefaultLandingAnim) + .Process(this->DefaultLandingAnim_Dropship) + .Process(this->DefaultLandingAnim_Carryall) .Process(this->TeamDelays_DynamicType) .Process(this->TeamDelays_Count) ; diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index 4530b67e6d..97198c0bcb 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -365,6 +365,10 @@ class RulesExt Valueable MindControl_Permanent_ReplaceSilent; Nullable FlyNoWobbles; + Valueable DefaultLandingAnim; + Nullable DefaultLandingAnim_Dropship; + Nullable DefaultLandingAnim_Carryall; + Valueable TeamDelays_DynamicType; Valueable> TeamDelays_Count[8]; @@ -672,6 +676,10 @@ class RulesExt , FlyNoWobbles {} + , DefaultLandingAnim { nullptr } + , DefaultLandingAnim_Dropship {} + , DefaultLandingAnim_Carryall {} + , TeamDelays_DynamicType { DynamicTeamDelayType::StartingPoint } , TeamDelays_Count {} { } diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index c5c73e95bf..8275a6bf4e 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -2065,6 +2065,58 @@ DEFINE_HOOK(0x70AFEF, TechnoClass_UpdateSight_DynamicSight2, 0x6) #pragma endregion +static AnimTypeClass* GetLandingAnim(TechnoClass* pTechno) +{ + auto const pType = pTechno->GetTechnoType(); + auto const pTypeExt = TechnoTypeExt::ExtMap.Find(pType); + + if (pTypeExt->LandingAnim.isset()) + return pTypeExt->LandingAnim.Get(); + + if (pType->IsDropship) + { + if (RulesExt::Global()->DefaultLandingAnim_Dropship.isset()) + return RulesExt::Global()->DefaultLandingAnim_Dropship.Get(); + return AnimTypeClass::Find("DROPLAND"); + } + + auto const pAircraft = abstract_cast(pTechno); + if (pAircraft && pAircraft->Type->Carryall) + { + if (RulesExt::Global()->DefaultLandingAnim_Carryall.isset()) + return RulesExt::Global()->DefaultLandingAnim_Carryall.Get(); + return AnimTypeClass::Find("CARYLAND"); + } + + return RulesExt::Global()->DefaultLandingAnim; +} + +DEFINE_HOOK(0x4CEB59, FlyLocomotionClass_ProcessLanding_ForceDropship, 0x6) +{ + GET(FlyLocomotionClass*, pLoco, ESI); + auto const pType = pLoco->LinkedTo->GetTechnoType(); + bool force = TechnoTypeExt::ExtMap.Find(pType)->LandingAnim.isset() || RulesExt::Global()->DefaultLandingAnim != nullptr; + + R->CL(force || pType->IsDropship); + return 0x4CEB5F; +} + +DEFINE_HOOK(0x4CEB7E, FlyLocomotionClass_ProcessLanding_DropshipAnim, 0x5) +{ + GET(FlyLocomotionClass*, pLoco, ESI); + auto const pAnim = GetLandingAnim(pLoco->LinkedTo); + R->EAX(pAnim ? pAnim->ArrayIndex : -1); + return 0x4CEB88; +} + +DEFINE_HOOK(0x4CEC31, FlyLocomotionClass_ProcessLanding_CarryallAnim, 0x5) +{ + GET(FlyLocomotionClass*, pLoco, ESI); + auto const pAnim = GetLandingAnim(pLoco->LinkedTo); + R->EAX(pAnim ? pAnim->ArrayIndex : -1); + return 0x4CEC3B; +} + DEFINE_HOOK(0x4CF8B1, FlyLocomotionClass_Draw_Point_NoWobbles, 0x6) { enum { Continue = 0x4CF8B7 }; diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 55a153f919..c3f8c2a32c 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -1201,6 +1201,8 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->FlyNoWobbles.Read(exINI, pSection, "FlyNoWobbles"); + this->LandingAnim.Read(exINI, pSection, "LandingAnim"); + // Ares 0.2 this->RadarJamRadius.Read(exINI, pSection, "RadarJamRadius"); @@ -1945,6 +1947,8 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->Parasite_AllowWaterExit) .Process(this->FlyNoWobbles) + + .Process(this->LandingAnim) ; } void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 0571b99caf..8c972465da 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -514,6 +514,8 @@ class TechnoTypeExt Nullable FlyNoWobbles; + Nullable LandingAnim; + ExtData(TechnoTypeClass* OwnerObject) : Extension(OwnerObject) , HealthBar_Hide { false } , HealthBar_HidePips { false } @@ -980,6 +982,8 @@ class TechnoTypeExt , Parasite_AllowWaterExit {} , FlyNoWobbles {} + + , LandingAnim {} { } virtual ~ExtData() = default;