diff --git a/CREDITS.md b/CREDITS.md index f92cc6854e..817a722983 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -921,4 +921,6 @@ This page lists all the individual contributions to the project by their author. - **Chang_zhi**: - Interop export interface for accessing scenario local/global variables - Add `ClampToScreen` tag for `BannerType` to control whether banner position is clamped to the visible area -- **obsidianus** - Automatic conversion based on health +- **obsidianus**: + - Automatic conversion based on health + - Unit image changes in various theater types diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 00e3c041e4..e39a8cf1ba 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2573,6 +2573,26 @@ WaterImage.ConditionRed= ; VehicleType entry Note that the VehicleTypes had to be defined under [VehicleTypes] and use same image type (SHP/VXL) for vanilla/damaged states. ``` +### Unit image changes in various theater types + +- Units on maps of different theater types can now change their models to the corresponding theater-specific models. +- The INI tags are shown below. + +In `rulesmd.ini`: +```ini +[SOMEVEHICLE] ; VehicleType +Image.Temperate= ; VehicleType entry +Image.Snow= ; VehicleType entry +Image.Urban= ; VehicleType entry +Image.Desert= ; VehicleType entry +Image.NewUrban= ; VehicleType entry +Image.Lunar= ; VehicleType entry +``` + +```{warning} +Note that the VehicleTypes had to be defined under [VehicleTypes] and use same image type (SHP/VXL) for vanilla/damaged states. +``` + ### Default mirage disguise for individual VehicleTypes - Vehicle can now have its `DefaultMirageDisguises` overridden per-type. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index e40e61b614..9ab924414f 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -654,6 +654,7 @@ HideShakeEffects=false ; boolean - [DeployFire supports buildings](New-or-Enhanced-Logics.md#deployfire-supports) (By FlyStar) - `OmniFire` supports buildings with `Turret=yes` (by FlyStar) - [Automatic conversion based on heallth](New-or-Enhanced-Logics.md#automatic-conversion-based-on-heallth) (by obsidianus) +- [Unit image changes in various theater types](New-or-Enhanced-Logics.md#unit-image-changes-in-various-theater-types) (by obsidianus) #### 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/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 52c290d1cf..5bc3dcfcb5 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -796,10 +796,19 @@ DEFINE_HOOK(0x73B4DA, UnitClass_DrawVXL_WaterType_Extra, 0x6) const auto pTypeExt = UnitTypeExt::Fetch(pThis->Type); - if (pTypeExt->NeedDamagedImage && pThis->IsClearlyVisibleTo(HouseClass::CurrentPlayer) && !pThis->Deployed) + if (pThis->IsClearlyVisibleTo(HouseClass::CurrentPlayer) && !pThis->Deployed) { - if (const auto pCustomType = UnitExt::GetUnitTypeExtra(pThis, pTypeExt)) + if (const auto pCustomType = UnitExt::GetUnitType(pThis, pTypeExt)) + { R->EBX(pCustomType); + } + if (pTypeExt->NeedDamagedImage) + { + if (const auto pCustomType = UnitExt::GetUnitTypeExtra(pThis, pTypeExt)) + { + R->EBX(pCustomType); + } + } } return 0; @@ -814,12 +823,24 @@ DEFINE_HOOK(0x73C602, UnitClass_DrawSHP_WaterType_Extra, 0x6) const auto pType = pThis->Type; const auto pTypeExt = UnitTypeExt::Fetch(pType); - if (pTypeExt->NeedDamagedImage && pThis->IsClearlyVisibleTo(HouseClass::CurrentPlayer) && !pThis->Deployed) + if (pThis->IsClearlyVisibleTo(HouseClass::CurrentPlayer) && !pThis->Deployed) { - if (const auto pCustomType = UnitExt::GetUnitTypeExtra(pThis, pTypeExt)) + if (const auto pCustomType = UnitExt::GetUnitType(pThis, pTypeExt)) { if (const auto Image = pCustomType->GetImage()) + { R->EAX(Image); + } + } + if (pTypeExt->NeedDamagedImage) + { + if (const auto pCustomType = UnitExt::GetUnitTypeExtra(pThis, pTypeExt)) + { + if (const auto Image = pCustomType->GetImage()) + { + R->EAX(Image); + } + } } } diff --git a/src/Ext/Unit/Body.cpp b/src/Ext/Unit/Body.cpp index baac35745d..a3a9b1d08c 100644 --- a/src/Ext/Unit/Body.cpp +++ b/src/Ext/Unit/Body.cpp @@ -342,6 +342,52 @@ bool UnitExt::CanDeployIntoBuilding(UnitClass* pThis, bool noDeploysIntoDefaultV return canDeploy; } +UnitTypeClass* UnitExt::GetUnitType(UnitClass* pUnit, UnitTypeExt* pData) +{ + switch (ScenarioClass::Instance->Theater) + { + case TheaterType::Temperate: + if (const auto image = pData->Image_Temperate) + { + return image; + } + break; + case TheaterType::Snow: + if (const auto image = pData->Image_Snow) + { + return image; + } + break; + case TheaterType::Urban: + if (const auto image = pData->Image_Urban) + { + return image; + } + break; + case TheaterType::Desert: + if (const auto image = pData->Image_Desert) + { + return image; + } + break; + case TheaterType::NewUrban: + if (const auto image = pData->Image_NewUrban) + { + return image; + } + break; + case TheaterType::Lunar: + if (const auto image = pData->Image_Lunar) + { + return image; + } + break; + default: + break; + } + return nullptr; +} + UnitTypeClass* UnitExt::GetUnitTypeExtra(UnitClass* pUnit, UnitTypeExt* pData) { if (pUnit->IsGreenHP()) diff --git a/src/Ext/Unit/Body.h b/src/Ext/Unit/Body.h index f314b6ef7b..b513a2af37 100644 --- a/src/Ext/Unit/Body.h +++ b/src/Ext/Unit/Body.h @@ -58,6 +58,7 @@ class UnitExt final : public FootExt static bool SimpleDeployerAllowedToDeploy(UnitClass* pThis, bool defaultValue, bool alwaysCheckLandTypes); static bool CanDeployIntoBuilding(UnitClass* pThis, bool noDeploysIntoDefaultValue = false); static UnitTypeClass* GetUnitTypeExtra(UnitClass* pUnit, UnitTypeExt* pData); + static UnitTypeClass* GetUnitType(UnitClass* pUnit, UnitTypeExt* pData); UnitClass* OwnerObject() const { diff --git a/src/Ext/UnitType/Body.cpp b/src/Ext/UnitType/Body.cpp index 5f6cd33986..fb1f6d66d6 100644 --- a/src/Ext/UnitType/Body.cpp +++ b/src/Ext/UnitType/Body.cpp @@ -88,6 +88,13 @@ void UnitTypeExt::LoadFromINIFile(CCINIClass* const pINI) this->Deploy_NoTiberium.Read(exINI, pSection, "Deploy.NoTiberium"); this->HoverDrownable.Read(exINI, pSection, "HoverDrownable"); + this->Image_Temperate.Read(exINI, pSection, "Image.Temperate"); + this->Image_Snow.Read(exINI, pSection, "Image.Snow"); + this->Image_Urban.Read(exINI, pSection, "Image.Urban"); + this->Image_Desert.Read(exINI, pSection, "Image.Desert"); + this->Image_NewUrban.Read(exINI, pSection, "Image.NewUrban"); + this->Image_Lunar.Read(exINI, pSection, "Image.Lunar"); + const auto pArtINI = &CCINIClass::INI_Art; INI_EX exArtINI(pArtINI); auto pArtSection = pThis->ImageFile; @@ -192,6 +199,12 @@ void UnitTypeExt::Serialize(T& Stm) .Process(this->Deploy_NoPassenger) .Process(this->Deploy_NoTiberium) .Process(this->HoverDrownable) + .Process(this->Image_Temperate) + .Process(this->Image_Snow) + .Process(this->Image_Urban) + .Process(this->Image_Desert) + .Process(this->Image_NewUrban) + .Process(this->Image_Lunar) .Process(this->TurretShape) .Process(this->BarrelOverTurret) .Process(this->BarrelOffset) diff --git a/src/Ext/UnitType/Body.h b/src/Ext/UnitType/Body.h index f232759a20..b8f8cabe96 100644 --- a/src/Ext/UnitType/Body.h +++ b/src/Ext/UnitType/Body.h @@ -83,6 +83,13 @@ class UnitTypeExt final : public TechnoTypeExt std::vector ExtraTurretOffsets; Valueable BurstPerTurret; + Nullable Image_Temperate; + Nullable Image_Snow; + Nullable Image_Urban; + Nullable Image_Desert; + Nullable Image_NewUrban; + Nullable Image_Lunar; + explicit UnitTypeExt(UnitTypeClass* const OwnerObject) : TechnoTypeExt(OwnerObject) , SinkSpeed {} , Sinkable {} @@ -143,6 +150,12 @@ class UnitTypeExt final : public TechnoTypeExt , ExtraTurretCount { 0 } , ExtraTurretOffsets { } , BurstPerTurret { 0 } + , Image_Temperate {} + , Image_Snow {} + , Image_Urban {} + , Image_Desert {} + , Image_NewUrban {} + , Image_Lunar {} { } UnitTypeClass* OwnerObject() const