diff --git a/CREDITS.md b/CREDITS.md index e486b4e375..d4aac761e8 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -260,6 +260,7 @@ This page lists all the individual contributions to the project by their author. - Vehicles keeping target on move command - `IsSonic` wave drawing crash fix - Customizable electric bolt duration and electric bolt-related fixes + - Airstrike flare visual customizations - **Morton (MortonPL)**: - `XDrawOffset` for animations - Shield passthrough & absorption diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 505fe59779..fa9f72fe2b 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -223,6 +223,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho - Fixed the bug that `AllowAirstrike=no` cannot completely prevent air strikes from being launched against it. - Fixed the issue where computer players did not search for new enemies after defeating them or forming alliances with them. - Fixed the bug that infantry ignored `Passengers` and `SizeLimit` when entering buildings. +- Fixed an issue where airstrike flare line drawn to target at lower elevation would clip. ## Fixes / interactions with other extensions @@ -702,6 +703,22 @@ BallisticScatter.Max= ; floating point value, distance in cells ## Technos +### Airstrike flare customizations + +- It is now possible to customize color of airstrike flare tint on target on the TechnoType calling in the airstrike as well as customize the color of the line drawn to target. + - `LaserTargetColor` can be used to set the index of color from `[ColorAdd]` defaults to `[AudioVisual]` -> `LaserTargetColor`. + - `AirstrikeLineColor` sets the color of the line and dot drawn from firer to target, defaults to `[AudioVisual]` -> `AirstrikeLineColor`. + +In `rulesmd.ini`: +```ini +[AudioVisual] +AirstrikeLineColor=255,0,0 ; integer - Red,Green,Blue + +[SOMETECHNO] ; TechnoType +LaserTargetColor= ; integer - [ColorAdd] index +AirstrikeLineColor= ; integer - Red,Green,Blue +``` + ### Airstrike target eligibility - By default whether or not a building can be targeted by airstrikes depends on value of `CanC4`, which also affects other things. This can now be changed independently by setting `AllowAirstrike`. If not set, defaults to value of `CanC4`. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index e2e835e8f7..64eadffaed 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -374,6 +374,7 @@ New: - [Make harvesters do addtional scan after unload](Fixed-or-Improved-Logics.md#make-harvesters-do-addtional-scan-after-unload) (by TaranDahl) - [Passenger-based insignias](Fixed-or-Improved-Logics.md#customizable-veterancy-insignias) (by Ollerus) - [Use `InsigniaType` to set the properties of insignia in a batch](Miscellanous.md#insignia-type) (by Ollerus) +- [Customizable airstrike flare colors](Fixed-or-Improved-Logics.md#airstrike-flare-customizations) (by Starkku) Vanilla fixes: - Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya) @@ -393,6 +394,7 @@ Vanilla fixes: - Fixed the bug that buildings will always be tinted as airstrike owner (by NetsuNegi) - Fixed the issue where computer players did not search for new enemies after defeating them or forming alliances with them (by FlyStar) - Fixed the bug that infantry ignored `Passengers` and `SizeLimit` when entering buildings (by NetsuNegi) +- Fixed an issue where airstrike flare line drawn to target at lower elevation would clip (by Starkku) Phobos fixes: - Fixed the bug that `AllowAirstrike=no` cannot completely prevent air strikes from being launched against it (by NetsuNegi) diff --git a/src/Ext/Rules/Body.cpp b/src/Ext/Rules/Body.cpp index 42c12fa691..8199b1cb29 100644 --- a/src/Ext/Rules/Body.cpp +++ b/src/Ext/Rules/Body.cpp @@ -171,6 +171,7 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI) this->IronCurtain_ExtraTintIntensity.Read(exINI, GameStrings::AudioVisual, "IronCurtain.ExtraTintIntensity"); this->ForceShield_ExtraTintIntensity.Read(exINI, GameStrings::AudioVisual, "ForceShield.ExtraTintIntensity"); this->ColorAddUse8BitRGB.Read(exINI, GameStrings::AudioVisual, "ColorAddUse8BitRGB"); + this->AirstrikeLineColor.Read(exINI, GameStrings::AudioVisual, "AirstrikeLineColor"); this->CrateOnlyOnLand.Read(exINI, GameStrings::CrateRules, "CrateOnlyOnLand"); this->UnitCrateVehicleCap.Read(exINI, GameStrings::CrateRules, "UnitCrateVehicleCap"); @@ -413,6 +414,7 @@ void RulesExt::ExtData::Serialize(T& Stm) .Process(this->ForceShield_ExtraTintIntensity) .Process(this->AllowWeaponSelectAgainstWalls) .Process(this->ColorAddUse8BitRGB) + .Process(this->AirstrikeLineColor) .Process(this->ROF_RandomDelay) .Process(this->ToolTip_Background_Color) .Process(this->ToolTip_Background_Opacity) diff --git a/src/Ext/Rules/Body.h b/src/Ext/Rules/Body.h index a564bcdd3b..9f6d2d8b3e 100644 --- a/src/Ext/Rules/Body.h +++ b/src/Ext/Rules/Body.h @@ -127,6 +127,7 @@ class RulesExt Valueable IronCurtain_ExtraTintIntensity; Valueable ForceShield_ExtraTintIntensity; Valueable ColorAddUse8BitRGB; + Valueable AirstrikeLineColor; Valueable> ROF_RandomDelay; Valueable ToolTip_Background_Color; @@ -306,6 +307,7 @@ class RulesExt , ForceShield_ExtraTintIntensity { 0.0 } , AllowWeaponSelectAgainstWalls { false } , ColorAddUse8BitRGB { false } + , AirstrikeLineColor { { 255, 0, 0 } } , ROF_RandomDelay { { 0 ,2 } } , ToolTip_Background_Color { { 0, 0, 0 } } , ToolTip_Background_Opacity { 100 } diff --git a/src/Ext/Techno/Body.Internal.cpp b/src/Ext/Techno/Body.Internal.cpp index 120cb1f8c8..05c7e25aee 100644 --- a/src/Ext/Techno/Body.Internal.cpp +++ b/src/Ext/Techno/Body.Internal.cpp @@ -164,11 +164,22 @@ int TechnoExt::GetTintColor(TechnoClass* pThis, bool invulnerability, bool airst if (pThis) { if (invulnerability && pThis->IsIronCurtained()) + { tintColor |= GeneralUtils::GetColorFromColorAdd(pThis->ForceShielded ? RulesClass::Instance->ForceShieldColor : RulesClass::Instance->IronCurtainColor); - if (airstrike && TechnoExt::ExtMap.Find(pThis)->AirstrikeTargetingMe) - tintColor |= GeneralUtils::GetColorFromColorAdd(RulesClass::Instance->LaserTargetColor); + } + if (airstrike) + { + if (auto const pAirstrike = TechnoExt::ExtMap.Find(pThis)->AirstrikeTargetingMe) + { + auto const pTypeExt = TechnoTypeExt::ExtMap.Find(pAirstrike->Owner->GetTechnoType()); + auto index = pTypeExt->LaserTargetColor.Get(RulesClass::Instance->LaserTargetColor); + tintColor |= GeneralUtils::GetColorFromColorAdd(index); + } + } if (berserk && pThis->Berzerk) + { tintColor |= GeneralUtils::GetColorFromColorAdd(RulesClass::Instance->BerserkColor); + } } return tintColor; diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index 80f4fa2460..d8de9ae0a4 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -781,4 +781,50 @@ DEFINE_HOOK(0x655DDD, RadarClass_ProcessPoint_RadarInvisible, 0x6) return GoOtherChecks; } -#pragma endregion \ No newline at end of file +#pragma endregion + +#pragma region DrawAirstrikeFlare + +namespace DrawAirstrikeFlareTemp +{ + TechnoClass* pTechno = nullptr; +} + +DEFINE_HOOK(0x705860, TechnoClass_DrawAirstrikeFlare_SetContext, 0x8) +{ + GET(TechnoClass*, pThis, ECX); + + // This is not used in vanilla function so ECX gets overwritten later. + DrawAirstrikeFlareTemp::pTechno = pThis; + + return 0; +} + +DEFINE_HOOK(0x7058F6, TechnoClass_DrawAirstrikeFlare, 0x5) +{ + enum { SkipGameCode = 0x705976 }; + + GET(int, zSrc, EBP); + GET(int, zDest, EBX); + REF_STACK(ColorStruct, color, STACK_OFFSET(0x70, -0x60)); + + // Fix depth buffer value. + int zValue = Math::min(zSrc, zDest); + R->EBP(zValue); + R->EBX(zValue); + + // Allow custom colors. + auto const pThis = DrawAirstrikeFlareTemp::pTechno; + auto const baseColor = TechnoTypeExt::ExtMap.Find(pThis->GetTechnoType())->AirstrikeLineColor.Get(RulesExt::Global()->AirstrikeLineColor); + double percentage = Randomizer::Global.RandomRanged(745, 1000) / 1000.0; + color = { (BYTE)(baseColor.R * percentage), (BYTE)(baseColor.G * percentage), (BYTE)(baseColor.B * percentage) }; + R->ESI(Drawing::RGB_To_Int(baseColor)); + + return SkipGameCode; +} + +// Skip setting color for the dot, it is already done in previous hook. +DEFINE_JUMP(LJMP, 0x705986, 0x7059C7); + +#pragma endregion + diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index b51f10e558..9383449686 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -299,6 +299,10 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->ReloadInTransport.Read(exINI, pSection, "ReloadInTransport"); this->ForbidParallelAIQueues.Read(exINI, pSection, "ForbidParallelAIQueues"); + + this->LaserTargetColor.Read(exINI, pSection, "LaserTargetColor"); + this->AirstrikeLineColor.Read(exINI, pSection, "AirstrikeLineColor"); + this->ShieldType.Read(exINI, pSection, "ShieldType"); this->HarvesterDumpAmount.Read(exINI, pSection, "HarvesterDumpAmount"); @@ -818,6 +822,8 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->InitialStrength) .Process(this->ReloadInTransport) .Process(this->ForbidParallelAIQueues) + .Process(this->LaserTargetColor) + .Process(this->AirstrikeLineColor) .Process(this->ShieldType) .Process(this->PassengerDeletionType) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index e0ed681ce4..6571b088f0 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -58,6 +58,8 @@ class TechnoTypeExt Nullable InitialStrength; Valueable ReloadInTransport; Valueable ForbidParallelAIQueues; + Nullable LaserTargetColor; + Nullable AirstrikeLineColor; Valueable ShieldType; std::unique_ptr PassengerDeletionType; @@ -382,6 +384,8 @@ class TechnoTypeExt , InitialStrength {} , ReloadInTransport { false } , ForbidParallelAIQueues { false } + , LaserTargetColor {} + , AirstrikeLineColor {} , ShieldType {} , PassengerDeletionType { nullptr }