From 5507c64c0a996c9e205ea76b4b0fec91e9ddbde2 Mon Sep 17 00:00:00 2001 From: dh381-1 <2575903651@qq.com> Date: Wed, 9 Sep 2026 15:17:49 +0800 Subject: [PATCH 1/5] initial --- CREDITS.md | 2 + Phobos.vcxproj | 1 + docs/New-or-Enhanced-Logics.md | 20 +++ docs/Whats-New.md | 1 + src/Ext/House/Body.cpp | 1 + src/Ext/House/Body.h | 3 + src/Ext/HouseType/Body.cpp | 8 ++ src/Ext/HouseType/Body.h | 7 ++ src/Ext/HouseType/Hooks.InitialElite.cpp | 150 +++++++++++++++++++++++ src/Ext/TechnoType/Body.cpp | 6 + src/Ext/TechnoType/Body.h | 8 ++ 11 files changed, 207 insertions(+) create mode 100644 src/Ext/HouseType/Hooks.InitialElite.cpp diff --git a/CREDITS.md b/CREDITS.md index a01c6e0585..98e5d9d97a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -956,3 +956,5 @@ This page lists all the individual contributions to the project by their author. - **obsidianus** - Automatic conversion based on health - **Nuke** - Reload speed adjustment on promotion - **frg2089 (舰队的偶像-岛风酱!)** - Fix `Slaved.OwnerWhenMasterKilled` not being respected when the master is sold or self-destructed +- **dh381-1(dh381)** + - Add country initial elite unit lists diff --git a/Phobos.vcxproj b/Phobos.vcxproj index 67dc28e6ee..a172ae1b7b 100644 --- a/Phobos.vcxproj +++ b/Phobos.vcxproj @@ -108,6 +108,7 @@ + diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index aae20369cb..3037acdcde 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -2639,6 +2639,26 @@ WarpInWeapon.UseDistanceAsDamage=false ; boolean WarpOutWeapon= ; WeaponType ``` +### Set country initial elite + +- Now you can add `TechnoTypes` in the three lists. They will appear at an elite initial level when produced, and cloned infantry will also be affected by this effect. + +In `rulesmd.ini`: +```ini +[SOMECOUNTRYIES] ; Countries +EliteInfantry= ; List of InfantryTypes +EliteUnits= ; List of UnitTypes +EliteAircraft= ; List of AircraftTypes +``` + +- For each `TechnoType`, you can define `SpareCameo` to specify the elite‑level icon. When a `TechnoType` is added to the initial elite list, it will preferentially use the SpareCameo as its icon. Supports `SHP`/`PCX` formats. + +In `artmd.ini`: +```ini +[SOMETECHNO] ; TechnoTypes +SpareCameo= ; filename +``` + ## Terrain ### Destroy animation & sound diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 54de7231a8..948abd34f6 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -720,6 +720,7 @@ HideShakeEffects=false ; boolean - [Disable AlphaImage during Buildup](Fixed-or-Improved-Logics.md#disable-alphaimage-during-buildup) (by Noble_Fish) - [Reload speed adjustment on promotion](New-or-Enhanced-Logics.md#reload-speed-adjustment-on-promotion) (by Nuke) - Allowed `(Pre)ProductionAnim` animations to use `Powered` & `PoweredLight/Effect/Special` keys (by Noble_Fish) +- [Set country initial elite](New-or-Enhanced-Logics.md#set-country-initial-elite) (by dh381) #### 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/House/Body.cpp b/src/Ext/House/Body.cpp index e53d1d2ad9..cc78b14fc9 100644 --- a/src/Ext/House/Body.cpp +++ b/src/Ext/House/Body.cpp @@ -713,6 +713,7 @@ void HouseExt::Serialize(T& Stm) .Process(this->ForceRadar) .Process(this->PlayerAutoRepair) //.Process(this->BeaconsPlacedOrder) beacon is not saved, so this follows it. + .Process(this->TechnoPCX_IsLoad) ; } diff --git a/src/Ext/House/Body.h b/src/Ext/House/Body.h index df5ba629b6..ba6ac3737a 100644 --- a/src/Ext/House/Body.h +++ b/src/Ext/House/Body.h @@ -81,6 +81,8 @@ class HouseExt final : public AbstractExt, public Detach::Listener BeaconsPlacedOrder; + ValueableVector TechnoPCX_IsLoad; + HouseExt(HouseClass* OwnerObject) : AbstractExt(OwnerObject) , PowerPlantEnhancers {} , OwnedLimboDeliveredBuildings {} @@ -116,6 +118,7 @@ class HouseExt final : public AbstractExt, public Detach::ListenerEVATag.Read(pINI, pSection, "EVA.Tag"); + + this->EliteInfantry.Read(exINI, pSection, "EliteInfantry"); + this->EliteUnits.Read(exINI, pSection, "EliteUnits"); + this->EliteAircraft.Read(exINI, pSection, "EliteAircraft"); } template @@ -25,6 +29,10 @@ void HouseTypeExt::Serialize(T& Stm) { Stm .Process(this->EVATag) + + .Process(this->EliteInfantry) + .Process(this->EliteUnits) + .Process(this->EliteAircraft) ; } diff --git a/src/Ext/HouseType/Body.h b/src/Ext/HouseType/Body.h index c843286266..796963c3b4 100644 --- a/src/Ext/HouseType/Body.h +++ b/src/Ext/HouseType/Body.h @@ -27,8 +27,15 @@ class HouseTypeExt final : public AbstractTypeExt EVAType EVATag; + ValueableVector EliteInfantry; + ValueableVector EliteUnits; + ValueableVector EliteAircraft; + HouseTypeExt(HouseTypeClass* OwnerObject) : AbstractTypeExt(OwnerObject) , EVATag { -2 } + , EliteInfantry {} + , EliteUnits {} + , EliteAircraft {} { } virtual ~HouseTypeExt() = default; diff --git a/src/Ext/HouseType/Hooks.InitialElite.cpp b/src/Ext/HouseType/Hooks.InitialElite.cpp new file mode 100644 index 0000000000..3ea970f4fe --- /dev/null +++ b/src/Ext/HouseType/Hooks.InitialElite.cpp @@ -0,0 +1,150 @@ +#include "Body.h" + +#include +#include + +static SHPStruct* LoadSHPCameo(TechnoTypeClass* pType) +{ + auto pTypeExt = TechnoTypeExt::Fetch(pType); + + if(pTypeExt->SpareCameo_IsLoad) + return pTypeExt->SpareCameo; + + char pFileName[0x20]; + + strcpy_s(pFileName, pTypeExt->SpareCameoFile.data()); + _strlwr_s(pFileName); + + if(!_stricmp(pFileName, pTypeExt->SpareCameoFile.data()) + && strstr(pFileName, ".shp")) + { + SHPStruct* pSHP = FileSystem::LoadSHPFile(pFileName); + pTypeExt->SpareCameo_IsLoad = true; + pTypeExt->SpareCameo = pSHP; + return pSHP; + } + return nullptr; +} + +static bool DrawPCXCameo(TechnoTypeClass* pType, const int destX, const int destY) +{ + auto pTypeExt = TechnoTypeExt::Fetch(pType); + char pFileName[0x20]; + + strcpy_s(pFileName, pTypeExt->SpareCameoFile.data()); + _strlwr_s(pFileName); + + if(!_stricmp(pFileName, pTypeExt->SpareCameoFile.data()) + && strstr(pFileName, ".pcx")) + { + PCX::Instance.LoadFile(pFileName); + if (const auto pCameoPCX = PCX::Instance.GetSurface(pFileName)) + { + RectangleStruct bounds = { destX, destY, 60, 48 }; + return PCX::Instance.BlitToSurface(&bounds, DSurface::Sidebar, pCameoPCX); + } + } + return false; +} + +DEFINE_HOOK(0x6A980A, StripClass_Draw_DrawSHPCameo, 0x8) +{ + GET(TechnoTypeClass*, pType, EBX); + + auto pHouseExt = HouseExt::Fetch(HouseClass::CurrentPlayer); + auto pHouseTypeExt = HouseTypeExt::Fetch(HouseClass::CurrentPlayer->Type); + + SHPStruct* pSHP = nullptr; + + switch(pType->WhatAmI()) + { + case AbstractType::InfantryType: + { + if(pHouseTypeExt->EliteInfantry.Contains(pType)) + { + pHouseExt->TechnoPCX_IsLoad.push_back(pType); + pSHP = LoadSHPCameo(pType); + } + break; + } + case AbstractType::UnitType: + { + if(pHouseTypeExt->EliteUnits.Contains(pType)) + { + pHouseExt->TechnoPCX_IsLoad.push_back(pType); + pSHP = LoadSHPCameo(pType); + } + break; + } + case AbstractType::AircraftType: + { + if(pHouseTypeExt->EliteAircraft.Contains(pType)) + { + pHouseExt->TechnoPCX_IsLoad.push_back(pType); + pSHP = LoadSHPCameo(pType); + } + break; + } + default: + break; + } + + if(pSHP) + R->EAX(pSHP); + + return 0; +} + +DEFINE_HOOK(0x6A99E7, StripClass_Draw_DrawPCXCameo, 0x6) +{ + enum { SkipDrawSHP = 0x6A9A43 }; + + GET(const int, destX, ESI); + GET(const int, destY, EBP); + GET_STACK(SHPStruct*, pSHP, STACK_OFFSET(0x48C, -0x444)); + + auto pHouseExt = HouseExt::Fetch(HouseClass::CurrentPlayer); + + for(auto pType : pHouseExt->TechnoPCX_IsLoad) + { + if(pSHP == pType->Cameo || pSHP == pType->AltCameo) + { + if(DrawPCXCameo(pType, destX, destY)) + return SkipDrawSHP; + } + } + return 0; +} + +DEFINE_HOOK(0x443C71, BuildingClass_ExitObject_CountryInitialElite, 0x6) +{ + GET(TechnoClass*, pTechno, EDI); + + const auto pHouseTypeExt = HouseTypeExt::Fetch(pTechno->Owner->Type); + + switch(pTechno->WhatAmI()) + { + case AbstractType::Infantry: + { + if(pHouseTypeExt->EliteInfantry.Contains(pTechno->GetTechnoType())) + pTechno->Veterancy.SetElite(); + break; + } + case AbstractType::Unit: + { + if(pHouseTypeExt->EliteUnits.Contains(pTechno->GetTechnoType())) + pTechno->Veterancy.SetElite(); + break; + } + case AbstractType::Aircraft: + { + if(pHouseTypeExt->EliteAircraft.Contains(pTechno->GetTechnoType())) + pTechno->Veterancy.SetElite(); + break; + } + default: + break; + } + + return 0; +} diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index ae05a36241..e5bfab881a 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -1436,6 +1436,8 @@ void TechnoTypeExt::LoadFromINIFile(CCINIClass* const pINI) // VoiceIFVRepair from Ares 0.2 this->VoiceIFVRepair.Read(exINI, pSection, "VoiceIFVRepair"); this->ParseVoiceWeaponAttacks(exINI, pSection, this->VoiceWeaponAttacks, this->VoiceEliteWeaponAttacks); + + this->SpareCameoFile.Read(pArtINI, pArtSection, "SpareCameo"); } template @@ -1831,6 +1833,10 @@ void TechnoTypeExt::Serialize(T& Stm) .Process(this->DecloakAnims) .Process(this->Cloak_KickOutParasite) + .Process(this->SpareCameoFile) + .Process(this->SpareCameo) + .Process(this->SpareCameo_IsLoad) + // Ares 0.2 .Process(this->RadarJamRadius) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index c7c2ba9ed6..329be0a190 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -461,6 +461,10 @@ class TechnoTypeExt : public ObjectTypeExt Nullable Unsellable; Nullable KeepAlive; + PhobosFixedString<0x20> SpareCameoFile; + SHPStruct* SpareCameo; + bool SpareCameo_IsLoad; + TechnoTypeExt(TechnoTypeClass* OwnerObject) : ObjectTypeExt(OwnerObject) , HealthBar_Hide { false } , HealthBar_HidePips { false } @@ -851,6 +855,10 @@ class TechnoTypeExt : public ObjectTypeExt , DecloakAnims {} , Cloak_KickOutParasite {} + , SpareCameoFile { NONE_STR } + , SpareCameo { nullptr } + , SpareCameo_IsLoad { false } + // Ares 0.2 , RadarJamRadius { 0 } From dbc20deb580b0bf9085638ac6cdac24b6a9e7e24 Mon Sep 17 00:00:00 2001 From: Noble_Fish <1065703286@qq.com> Date: Wed, 9 Sep 2026 15:37:29 +0800 Subject: [PATCH 2/5] fix docs & correct the order of variables --- docs/New-or-Enhanced-Logics.md | 8 +++++--- docs/Whats-New.md | 2 +- src/Ext/HouseType/Body.cpp | 14 ++++++++------ src/Ext/HouseType/Body.h | 6 +++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 9ef39379cd..565a445fec 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -823,6 +823,8 @@ SpyEffect.VictimSuperWeapon= ; SuperWeaponType SpyEffect.InfiltratorSuperWeapon= ; SuperWeaponType ``` +## Countries + ## Infantry ### Allow infantry to perform type conversion when deploying and undeploying @@ -2705,7 +2707,7 @@ WarpOutWeapon= ; WeaponType In `rulesmd.ini`: ```ini -[SOMECOUNTRYIES] ; Countries +[SOMECOUNTRY] ; Country EliteInfantry= ; List of InfantryTypes EliteUnits= ; List of UnitTypes EliteAircraft= ; List of AircraftTypes @@ -2715,8 +2717,8 @@ EliteAircraft= ; List of AircraftTypes In `artmd.ini`: ```ini -[SOMETECHNO] ; TechnoTypes -SpareCameo= ; filename +[SOMETECHNO] ; TechnoType +SpareCameo= ; filename - including the .shp/.pcx extension ``` ## Terrain diff --git a/docs/Whats-New.md b/docs/Whats-New.md index de389e0e0f..942e2eccaa 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -443,6 +443,7 @@ HideShakeEffects=false ; boolean - [Allowed customize that whether `Temporal=yes` warhead will cause target building animation poweroff](Fixed-or-Improved-Logics.md#allow-customize-that-whether-temporal-yes-warhead-will-cause-target-building-animation-poweroff) (by NetsuNegi) - Country-based attached effects (by Ollerus) - [Customizable crew type per country](Fixed-or-Improved-Logics.md#customizable-crew-type-per-country) (by Sovietianqi) +- [Set country initial elite](New-or-Enhanced-Logics.md#set-country-initial-elite) (by dh381) #### Vanilla fixes: - Fixed the bug where a building with `Factory=BuildingType` owned by the AI did not play `ProductionAnim` when placing a produced building (by Noble_Fish) @@ -730,7 +731,6 @@ HideShakeEffects=false ; boolean - [Disable AlphaImage during Buildup](Fixed-or-Improved-Logics.md#disable-alphaimage-during-buildup) (by Noble_Fish) - [Reload speed adjustment on promotion](New-or-Enhanced-Logics.md#reload-speed-adjustment-on-promotion) (by Nuke) - Allowed `(Pre)ProductionAnim` animations to use `Powered` & `PoweredLight/Effect/Special` keys (by Noble_Fish) -- [Set country initial elite](New-or-Enhanced-Logics.md#set-country-initial-elite) (by dh381) #### 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/HouseType/Body.cpp b/src/Ext/HouseType/Body.cpp index d27def6330..474cd5abec 100644 --- a/src/Ext/HouseType/Body.cpp +++ b/src/Ext/HouseType/Body.cpp @@ -19,13 +19,14 @@ void HouseTypeExt::LoadFromINIFile(CCINIClass* pINI) this->EVATag.Read(pINI, pSection, "EVA.Tag"); - this->EliteInfantry.Read(exINI, pSection, "EliteInfantry"); - this->EliteUnits.Read(exINI, pSection, "EliteUnits"); - this->EliteAircraft.Read(exINI, pSection, "EliteAircraft"); this->AttachEffects.LoadFromINI(pINI, pSection); this->AttachEffects_AttachOnOwnerChange.Read(exINI, pSection, "AttachEffect.AttachOnOwnerChange"); this->Crew.Read(exINI, pSection, "Crew"); + + this->EliteInfantry.Read(exINI, pSection, "EliteInfantry"); + this->EliteUnits.Read(exINI, pSection, "EliteUnits"); + this->EliteAircraft.Read(exINI, pSection, "EliteAircraft"); } template @@ -34,12 +35,13 @@ void HouseTypeExt::Serialize(T& Stm) Stm .Process(this->EVATag) - .Process(this->EliteInfantry) - .Process(this->EliteUnits) - .Process(this->EliteAircraft) .Process(this->AttachEffects) .Process(this->AttachEffects_AttachOnOwnerChange) .Process(this->Crew) + + .Process(this->EliteInfantry) + .Process(this->EliteUnits) + .Process(this->EliteAircraft) ; } diff --git a/src/Ext/HouseType/Body.h b/src/Ext/HouseType/Body.h index a9e8a842a4..d610091bd3 100644 --- a/src/Ext/HouseType/Body.h +++ b/src/Ext/HouseType/Body.h @@ -38,12 +38,12 @@ class HouseTypeExt final : public AbstractTypeExt HouseTypeExt(HouseTypeClass* OwnerObject) : AbstractTypeExt(OwnerObject) , EVATag { -2 } - , EliteInfantry {} - , EliteUnits {} - , EliteAircraft {} , AttachEffects {} , AttachEffects_AttachOnOwnerChange {} , Crew {} + , EliteInfantry {} + , EliteUnits {} + , EliteAircraft {} { } virtual ~HouseTypeExt() = default; From c72f7e596ce97a16b9c1a740010c1f0a55a6fdf0 Mon Sep 17 00:00:00 2001 From: Noble_Fish <1065703286@qq.com> Date: Wed, 9 Sep 2026 15:43:48 +0800 Subject: [PATCH 3/5] [doc] Move to the countries section --- docs/New-or-Enhanced-Logics.md | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 565a445fec..2ce01b5958 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -825,6 +825,26 @@ SpyEffect.InfiltratorSuperWeapon= ; SuperWeaponType ## Countries +### Set country initial elite + +- Now you can add `TechnoTypes` in the three lists. They will appear at an elite initial level when produced, and cloned infantry will also be affected by this effect. + +In `rulesmd.ini`: +```ini +[SOMECOUNTRY] ; Country +EliteInfantry= ; List of InfantryTypes +EliteUnits= ; List of UnitTypes +EliteAircraft= ; List of AircraftTypes +``` + +- For each `TechnoType`, you can define `SpareCameo` to specify the elite‑level icon. When a `TechnoType` is added to the initial elite list, it will preferentially use the SpareCameo as its icon. Supports `SHP`/`PCX` formats. + +In `artmd.ini`: +```ini +[SOMETECHNO] ; TechnoType +SpareCameo= ; filename - including the .shp/.pcx extension +``` + ## Infantry ### Allow infantry to perform type conversion when deploying and undeploying @@ -2701,26 +2721,6 @@ WarpInWeapon.UseDistanceAsDamage=false ; boolean WarpOutWeapon= ; WeaponType ``` -### Set country initial elite - -- Now you can add `TechnoTypes` in the three lists. They will appear at an elite initial level when produced, and cloned infantry will also be affected by this effect. - -In `rulesmd.ini`: -```ini -[SOMECOUNTRY] ; Country -EliteInfantry= ; List of InfantryTypes -EliteUnits= ; List of UnitTypes -EliteAircraft= ; List of AircraftTypes -``` - -- For each `TechnoType`, you can define `SpareCameo` to specify the elite‑level icon. When a `TechnoType` is added to the initial elite list, it will preferentially use the SpareCameo as its icon. Supports `SHP`/`PCX` formats. - -In `artmd.ini`: -```ini -[SOMETECHNO] ; TechnoType -SpareCameo= ; filename - including the .shp/.pcx extension -``` - ## Terrain ### Destroy animation & sound From 3fcb41c277e5e75e805c7f1f7dd3ae6167179a66 Mon Sep 17 00:00:00 2001 From: dh381-1 <2575903651@qq.com> Date: Thu, 10 Sep 2026 12:11:40 +0800 Subject: [PATCH 4/5] add SpareCameoPCX to load pcx file --- src/Ext/HouseType/Hooks.InitialElite.cpp | 14 ++++++++------ src/Ext/TechnoType/Body.cpp | 4 +++- src/Ext/TechnoType/Body.h | 7 +++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Ext/HouseType/Hooks.InitialElite.cpp b/src/Ext/HouseType/Hooks.InitialElite.cpp index 3ea970f4fe..107b55eda4 100644 --- a/src/Ext/HouseType/Hooks.InitialElite.cpp +++ b/src/Ext/HouseType/Hooks.InitialElite.cpp @@ -7,7 +7,7 @@ static SHPStruct* LoadSHPCameo(TechnoTypeClass* pType) { auto pTypeExt = TechnoTypeExt::Fetch(pType); - if(pTypeExt->SpareCameo_IsLoad) + if(pTypeExt->SHPCameo_IsLoad) return pTypeExt->SpareCameo; char pFileName[0x20]; @@ -16,10 +16,12 @@ static SHPStruct* LoadSHPCameo(TechnoTypeClass* pType) _strlwr_s(pFileName); if(!_stricmp(pFileName, pTypeExt->SpareCameoFile.data()) - && strstr(pFileName, ".shp")) + && !strstr(pFileName, ".pcx")) { - SHPStruct* pSHP = FileSystem::LoadSHPFile(pFileName); - pTypeExt->SpareCameo_IsLoad = true; + std::string Filename(pFileName); + Filename += ".shp"; + SHPStruct* pSHP = FileSystem::LoadSHPFile(Filename.c_str()); + pTypeExt->SHPCameo_IsLoad = true; pTypeExt->SpareCameo = pSHP; return pSHP; } @@ -31,10 +33,10 @@ static bool DrawPCXCameo(TechnoTypeClass* pType, const int destX, const int dest auto pTypeExt = TechnoTypeExt::Fetch(pType); char pFileName[0x20]; - strcpy_s(pFileName, pTypeExt->SpareCameoFile.data()); + strcpy_s(pFileName, pTypeExt->SpareCameoPCX.GetFilename()); _strlwr_s(pFileName); - if(!_stricmp(pFileName, pTypeExt->SpareCameoFile.data()) + if(!_stricmp(pFileName, pTypeExt->SpareCameoPCX.GetFilename()) && strstr(pFileName, ".pcx")) { PCX::Instance.LoadFile(pFileName); diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index e5bfab881a..c52afd71a4 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -1438,6 +1438,7 @@ void TechnoTypeExt::LoadFromINIFile(CCINIClass* const pINI) this->ParseVoiceWeaponAttacks(exINI, pSection, this->VoiceWeaponAttacks, this->VoiceEliteWeaponAttacks); this->SpareCameoFile.Read(pArtINI, pArtSection, "SpareCameo"); + this->SpareCameoPCX.Read(pArtINI, pArtSection, "SpareCameoPCX"); } template @@ -1835,7 +1836,8 @@ void TechnoTypeExt::Serialize(T& Stm) .Process(this->SpareCameoFile) .Process(this->SpareCameo) - .Process(this->SpareCameo_IsLoad) + .Process(this->SHPCameo_IsLoad) + .Process(this->SpareCameoPCX) // Ares 0.2 .Process(this->RadarJamRadius) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 329be0a190..b6e0a3fcd4 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -463,7 +463,9 @@ class TechnoTypeExt : public ObjectTypeExt PhobosFixedString<0x20> SpareCameoFile; SHPStruct* SpareCameo; - bool SpareCameo_IsLoad; + bool SHPCameo_IsLoad; + PhobosPCXFile SpareCameoPCX; + TechnoTypeExt(TechnoTypeClass* OwnerObject) : ObjectTypeExt(OwnerObject) , HealthBar_Hide { false } @@ -857,7 +859,8 @@ class TechnoTypeExt : public ObjectTypeExt , SpareCameoFile { NONE_STR } , SpareCameo { nullptr } - , SpareCameo_IsLoad { false } + , SHPCameo_IsLoad { false } + , SpareCameoPCX {} // Ares 0.2 , RadarJamRadius { 0 } From d0855265a6b6cac7f443f8383c2c798b03f59e5b Mon Sep 17 00:00:00 2001 From: dh381-1 <2575903651@qq.com> Date: Thu, 10 Sep 2026 12:17:18 +0800 Subject: [PATCH 5/5] Merge branch 'new/CountryInitialElite' of https://github.com/dh381-1/Phobos into new/CountryInitialElite --- docs/New-or-Enhanced-Logics.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 2ce01b5958..36de23268b 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -837,12 +837,13 @@ EliteUnits= ; List of UnitTypes EliteAircraft= ; List of AircraftTypes ``` -- For each `TechnoType`, you can define `SpareCameo` to specify the elite‑level icon. When a `TechnoType` is added to the initial elite list, it will preferentially use the SpareCameo as its icon. Supports `SHP`/`PCX` formats. +- For each `TechnoType`, you can define `SpareCameo` and `SpareCameoPCX` to specify the elite‑level icon. When a `TechnoType` is added to the initial elite list, it will preferentially use the SpareCameo as its icon. In `artmd.ini`: ```ini [SOMETECHNO] ; TechnoType -SpareCameo= ; filename - including the .shp/.pcx extension +SpareCameo= ; filename +SpareCameoPCX= ; filename - include ".pcx" extension ``` ## Infantry