diff --git a/CREDITS.md b/CREDITS.md index f977b2a3ed..d3c0883bb4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -365,6 +365,7 @@ This page lists all the individual contributions to the project by their author. - Auto-deploy/Deploy block on ammo change - Flashing Technos on selecting - Promotion animation + - Damaged unit image changes - **ZivDero** - Re-enable the Veinhole Monster and Weeds from TS - Recreate the weed-charging of SWs like the TS Chemical Missile diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index b789131486..bf37a63ef0 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -1366,6 +1366,24 @@ Convert.HumanToComputer = ; TechnoType Convert.ComputerToHuman = ; TechnoType ``` +### Damaged unit image changes + +- When a unit is damaged (health points percentage is lower than `ConditionYellow` percentage), it now may use different image set by `DamagedImage.ConditionYellow` UnitType. Similar, `DamagedImage.ConditionRed` is used as image if unit health points percentage is lower than `ConditionRed` percentage. +- It is also works on water by setting `WaterDamagedImage.ConditionYellow` and `WaterDamagedImage.ConditionRed` UnitType, similar to Ares' `WaterImage`. + +In `rulesmd.ini`: +```ini +[SOMEUNIT] ; UnitType +DamagedImage.ConditionYellow= ; UnitType entry +DamagedImage.ConditionRed= ; UnitType entry +WaterDamagedImage.ConditionYellow= ; UnitType entry +WaterDamagedImage.ConditionRed= ; UnitType entry +``` + +```{warning} +Note that the UnitTypes had to be defined under [VehicleTypes] and use same image type (SHP/VXL) for vanilla/damaged states. +``` + ## Terrain ### Destroy animation & sound diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 4d770168e5..cbff25bd45 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -469,6 +469,7 @@ New: - `` can now be used as owner for pre-placed objects on skirmish and multiplayer maps (by Starkku) - Allow customizing charge turret delays per burst on a weapon (by Starkku) - Unit `Speed` setting now accepts floating point values (by Starkku) +- Damaged unit image changes (by Fryone) Vanilla fixes: - Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy) diff --git a/src/Ext/Techno/Body.cpp b/src/Ext/Techno/Body.cpp index 0d5c6ccf02..4954af6290 100644 --- a/src/Ext/Techno/Body.cpp +++ b/src/Ext/Techno/Body.cpp @@ -466,6 +466,20 @@ int TechnoExt::ExtData::GetAttachedEffectCumulativeCount(AttachEffectTypeClass* return foundCount; } +UnitTypeClass* TechnoExt::ExtData::GetUnitTypeExtra(bool isRedHP) const { + if (auto pUnit = abstract_cast(this->OwnerObject())) + { + auto pData = TechnoTypeExt::ExtMap.Find(pUnit->Type); + + if (!pUnit->OnBridge && pUnit->GetCell()->LandType == LandType::Water && (pData->WaterDamagedImage_ConditionRed || pData->WaterDamagedImage_ConditionYellow)) + return (isRedHP && pData->WaterDamagedImage_ConditionRed) ? pData->WaterDamagedImage_ConditionRed : pData->WaterDamagedImage_ConditionYellow; + else if (pData->DamagedImage_ConditionRed || pData->DamagedImage_ConditionYellow) + return (isRedHP && pData->DamagedImage_ConditionRed) ? pData->DamagedImage_ConditionRed : pData->DamagedImage_ConditionYellow; + + } + return nullptr; +} + // ============================= // load / save diff --git a/src/Ext/Techno/Body.h b/src/Ext/Techno/Body.h index dd958380bd..b6fd8023bf 100644 --- a/src/Ext/Techno/Body.h +++ b/src/Ext/Techno/Body.h @@ -116,6 +116,8 @@ class TechnoExt bool HasAttachedEffects(std::vector attachEffectTypes, bool requireAll, bool ignoreSameSource, TechnoClass* pInvoker, AbstractClass* pSource, std::vector const* minCounts, std::vector const* maxCounts) const; int GetAttachedEffectCumulativeCount(AttachEffectTypeClass* pAttachEffectType, bool ignoreSameSource = false, TechnoClass* pInvoker = nullptr, AbstractClass* pSource = nullptr) const; + UnitTypeClass* GetUnitTypeExtra(bool isRedHP) const; + virtual ~ExtData() override; virtual void InvalidatePointer(void* ptr, bool bRemoved) override { } virtual void LoadFromStream(PhobosStreamReader& Stm) override; diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 88e9183347..0c8d796c7c 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -543,3 +543,43 @@ DEFINE_HOOK(0x70EFE0, TechnoClass_GetMaxSpeed, 0x6) return SkipGameCode; } +DEFINE_HOOK(0x73B4DA, UnitClass_DrawVXL_WaterType_Extra, 0x6) +{ + enum { Continue = 0x73B4E0 }; + + GET(UnitClass*, pThis, EBP); + TechnoExt::ExtData *pData = TechnoExt::ExtMap.Find(pThis); + + if (pThis->IsClearlyVisibleTo(HouseClass::CurrentPlayer) && !pThis->Deployed && (pThis->IsYellowHP() || pThis->IsRedHP())) + { + if (UnitTypeClass* pCustomType = pData->GetUnitTypeExtra(pThis->IsRedHP())) + { + ObjectTypeClass* Image = pCustomType; + R->EBX(Image); + } + } + + R->EAX(pThis->WalkedFramesSoFar); + return Continue; +} + +DEFINE_HOOK(0x73C602, UnitClass_DrawSHP_WaterType_Extra, 0x6) +{ + enum { Continue = 0x73C608 }; + + GET(UnitClass*, pThis, EBP); + TechnoExt::ExtData *pData = TechnoExt::ExtMap.Find(pThis); + + if(pThis->IsYellowHP() || pThis->IsRedHP()) + { + if(UnitTypeClass* pCustomType = pData->GetUnitTypeExtra(pThis->IsRedHP())) + { + SHPStruct* Image = pCustomType->GetImage(); + if(Image) + R->EAX(Image); + } + } + + R->ECX(pThis->GetType()); + return Continue; +} diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 0091ceb22e..36d72579dc 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -458,6 +458,11 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->Wake_Grapple.Read(exINI, pSection, "Wake.Grapple"); this->Wake_Sinking.Read(exINI, pSection, "Wake.Sinking"); + this->DamagedImage_ConditionYellow.Read(exINI, pSection, "DamagedImage.ConditionYellow"); + this->DamagedImage_ConditionRed.Read(exINI, pSection, "DamagedImage.ConditionRed"); + this->WaterDamagedImage_ConditionYellow.Read(exINI, pSection, "WaterDamagedImage.ConditionYellow"); + this->WaterDamagedImage_ConditionRed.Read(exINI, pSection, "WaterDamagedImage.ConditionRed"); + // Ares 0.2 this->RadarJamRadius.Read(exINI, pSection, "RadarJamRadius"); @@ -828,6 +833,11 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->Wake) .Process(this->Wake_Grapple) .Process(this->Wake_Sinking) + + .Process(this->DamagedImage_ConditionYellow) + .Process(this->DamagedImage_ConditionRed) + .Process(this->WaterDamagedImage_ConditionYellow) + .Process(this->WaterDamagedImage_ConditionRed) ; } void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index f6caad6729..3081f32031 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -230,6 +230,11 @@ class TechnoTypeExt Nullable Wake_Grapple; Nullable Wake_Sinking; + Nullable DamagedImage_ConditionYellow; + Nullable DamagedImage_ConditionRed; + Nullable WaterDamagedImage_ConditionYellow; + Nullable WaterDamagedImage_ConditionRed; + struct LaserTrailDataEntry { ValueableIdx idxType; @@ -452,6 +457,11 @@ class TechnoTypeExt , Wake { } , Wake_Grapple { } , Wake_Sinking { } + + , DamagedImage_ConditionYellow { } + , DamagedImage_ConditionRed { } + , WaterDamagedImage_ConditionYellow { } + , WaterDamagedImage_ConditionRed { } { } virtual ~ExtData() = default;