From bfaa5e1902a2ce23874aa696a485df10b63116bb Mon Sep 17 00:00:00 2001 From: Starkku Date: Wed, 6 Apr 2022 20:34:03 +0300 Subject: [PATCH] Laser fixes & improvements - IsSingleColor can be set on laser weapon to draw a single-color laser akin to IsHouseColor using only LaserInnerColor - Fixed laser glow falloff of single-color lasers to match that of vanilla game --- CREDITS.md | 1 + docs/Fixed-or-Improved-Logics.md | 10 ++++++++++ docs/Whats-New.md | 2 ++ src/Ext/Techno/Hooks.cpp | 14 ++++++++++++++ src/Ext/WeaponType/Body.cpp | 2 ++ src/Ext/WeaponType/Body.h | 4 +++- src/Misc/Hooks.LaserDraw.cpp | 12 +++++++----- src/Utilities/GeneralUtils.cpp | 14 ++++++++++++++ src/Utilities/GeneralUtils.h | 2 +- 9 files changed, 54 insertions(+), 7 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index 923790eba6..2ba4299504 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -136,6 +136,7 @@ This page lists all the individual contributions to the project by their author. - Weapon owner detachment - Feedback weapon - TerrainType & ore minimap color customization + - Laser fixes & improvements - **Morton (MortonPL)**: - `XDrawOffset` - Shield passthrough & absorption diff --git a/docs/Fixed-or-Improved-Logics.md b/docs/Fixed-or-Improved-Logics.md index 418664b87c..5b65c97a8f 100644 --- a/docs/Fixed-or-Improved-Logics.md +++ b/docs/Fixed-or-Improved-Logics.md @@ -351,6 +351,16 @@ In `rulesmd.ini`: DetachedFromOwner=false ; boolean ``` +### Single-color lasers + +- You can now set laser to draw using only `LaserInnerColor` by setting `IsSingleColor`, in same manner as `IsHouseColor` lasers do using player's team color. These lasers respect laser thickness. + +In `rulesmd.ini`: +```ini +[SOMEWEAPON] ; WeaponType +IsSingleColor=false ; boolean +``` + ### Toggle-able ElectricBolt visuals - You can now specify individual ElectricBolt bolts you want to disable. Note that this is only a visual change. diff --git a/docs/Whats-New.md b/docs/Whats-New.md index d349b86edf..fdee4315f0 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -291,6 +291,7 @@ New: - Weapon owner detachment (by Starkku) - Feedback weapon (by Starkku) - TerrainType & ore minimap color customization (by Starkku) +- Single-color weapon lasers (by Starkku) Vanilla fixes: - Fixed laser drawing code to allow for thicker lasers in house color draw mode (by Kerbiter, ChrisLv_CN) @@ -314,6 +315,7 @@ Phobos fixes: - Fixed shielded objects not decloaking if shield takes damage (by Starkku) - Fixed critical hit animation playing even if no critical hits were dealt due to `Crit.Affects` or `ImmuneToCrit` settings (by Starkku) - Fixed `RemoveDisguise` not working on `PermaDisguise` infantry (by Starkku) +- Fixed single-color laser (IsHouseColor, IsSingleColor, LaserTrails) glow falloff to match the vanilla appearance (by Starkku) diff --git a/src/Ext/Techno/Hooks.cpp b/src/Ext/Techno/Hooks.cpp index c77498c97c..daa9e6dfd1 100644 --- a/src/Ext/Techno/Hooks.cpp +++ b/src/Ext/Techno/Hooks.cpp @@ -445,3 +445,17 @@ DEFINE_HOOK(0x6FF43F, TechnoClass_FireAt_FeedbackWeapon, 0x6) return 0; } + +DEFINE_HOOK(0x6FD446, TechnoClass_FireLaser_IsSingleColor, 0x7) +{ + GET(WeaponTypeClass* const, pWeapon, ECX); + GET(LaserDrawClass* const, pLaser, EAX); + + if (auto const pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon)) + { + if (!pLaser->IsHouseColor && pWeaponExt->Laser_IsSingleColor) + pLaser->IsHouseColor = true; + } + + return 0; +} diff --git a/src/Ext/WeaponType/Body.cpp b/src/Ext/WeaponType/Body.cpp index 16fc6badcb..af7e167142 100644 --- a/src/Ext/WeaponType/Body.cpp +++ b/src/Ext/WeaponType/Body.cpp @@ -46,6 +46,7 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->AreaFire_Target.Read(exINI, pSection, "AreaFire.Target"); this->DetachedFromOwner.Read(exINI, pSection, "DetachedFromOwner"); this->FeedbackWeapon.Read(exINI, pSection, "FeedbackWeapon", true); + this->Laser_IsSingleColor.Read(exINI, pSection, "IsSingleColor"); } template @@ -67,6 +68,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm) .Process(this->AreaFire_Target) .Process(this->DetachedFromOwner) .Process(this->FeedbackWeapon) + .Process(this->Laser_IsSingleColor) ; }; diff --git a/src/Ext/WeaponType/Body.h b/src/Ext/WeaponType/Body.h index 6fc683f0d2..f197708979 100644 --- a/src/Ext/WeaponType/Body.h +++ b/src/Ext/WeaponType/Body.h @@ -32,7 +32,8 @@ class WeaponTypeExt Valueable AreaFire_Target; Valueable DetachedFromOwner; Nullable FeedbackWeapon; - + Valueable Laser_IsSingleColor; + ExtData(WeaponTypeClass* OwnerObject) : Extension(OwnerObject) , DiskLaser_Radius { 38.2 } , DiskLaser_Circumference { 240 } @@ -49,6 +50,7 @@ class WeaponTypeExt , AreaFire_Target { AreaFireTarget::Base } , DetachedFromOwner { false } , FeedbackWeapon {} + , Laser_IsSingleColor { false } { } virtual ~ExtData() = default; diff --git a/src/Misc/Hooks.LaserDraw.cpp b/src/Misc/Hooks.LaserDraw.cpp index bb20fb054a..461838fe8c 100644 --- a/src/Misc/Hooks.LaserDraw.cpp +++ b/src/Misc/Hooks.LaserDraw.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace LaserDrawTemp { @@ -26,13 +27,14 @@ DEFINE_HOOK(0x550F47, LaserDrawClass_DrawInHouseColor_BetterDrawing, 0x0) GET(LaserDrawClass*, pThis, EBX); GET_STACK(int, currentThickness, 0x5C) - // Map value from range of [1, Thickness] to [0, pi/2] - double x = 0; + double mult = 1.0; if (pThis->Thickness > 1) - x = Math::HalfPi * (currentThickness - 1) / (pThis->Thickness - 1); + { + double falloffStep = 1.0 / pThis->Thickness; + double falloffMult = GeneralUtils::FastPow(1.0 - falloffStep, currentThickness); + mult = (1.0 - falloffStep * currentThickness) * falloffMult; + } - // Cosine function for falloff - double mult = Math::cos(x); unsigned int r = (unsigned int)(mult * LaserDrawTemp::maxColor.R); unsigned int g = (unsigned int)(mult * LaserDrawTemp::maxColor.G); unsigned int b = (unsigned int)(mult * LaserDrawTemp::maxColor.B); diff --git a/src/Utilities/GeneralUtils.cpp b/src/Utilities/GeneralUtils.cpp index d2fb0e5565..57e52b7b3c 100644 --- a/src/Utilities/GeneralUtils.cpp +++ b/src/Utilities/GeneralUtils.cpp @@ -81,3 +81,17 @@ int GeneralUtils::ChooseOneWeighted(const double dice, const std::vector* w return -1; } + +// Direct multiplication pow +double GeneralUtils::FastPow(double x, double n) +{ + double r = 1.0; + + while (n > 0) + { + r *= x; + --n; + } + + return r; +} \ No newline at end of file diff --git a/src/Utilities/GeneralUtils.h b/src/Utilities/GeneralUtils.h index 13e16226b4..4721f38b51 100644 --- a/src/Utilities/GeneralUtils.h +++ b/src/Utilities/GeneralUtils.h @@ -24,6 +24,6 @@ class GeneralUtils static std::vector AdjacentCellsInRange(unsigned int range); static const int GetRangedRandomOrSingleValue(Point2D range); static const double GetWarheadVersusArmor(WarheadTypeClass* pWH, Armor ArmorType); - static int ChooseOneWeighted(const double dice, const std::vector* weights); + static double FastPow(double x, double n); };