From eb17281a4f0680f00dbc09453302d2fdc2398f97 Mon Sep 17 00:00:00 2001 From: sourpuh <150582765+sourpuh@users.noreply.github.com> Date: Sat, 27 Jul 2024 12:56:16 -0700 Subject: [PATCH 1/3] Cast Animations Add option for DX11 renderer to choose one of three cast animations --- .../Gui/Layouts/Elements/LayoutDrawElement.cs | 65 ++++++++- .../DirectX11/DirectX11DisplayObjects.cs | 16 ++- .../DirectX11/DirectX11Renderer.cs | 33 +++-- .../RenderEngines/DirectX11/DirectX11Scene.cs | 125 +++++++++++++----- Splatoon/Serializables/CastAnimationKind.cs | 33 +++++ Splatoon/Serializables/DisplayStyle.cs | 47 ++++--- Splatoon/Serializables/Element.cs | 38 +++++- Splatoon/Utility/Colors.cs | 8 ++ Splatoon/Utility/ElementExtensions.cs | 55 +++++++- Splatoon/Utility/LayoutUtils.cs | 29 ++++ 10 files changed, 364 insertions(+), 85 deletions(-) create mode 100644 Splatoon/Serializables/CastAnimationKind.cs diff --git a/Splatoon/Gui/Layouts/Elements/LayoutDrawElement.cs b/Splatoon/Gui/Layouts/Elements/LayoutDrawElement.cs index fa24689e..dec8c218 100644 --- a/Splatoon/Gui/Layouts/Elements/LayoutDrawElement.cs +++ b/Splatoon/Gui/Layouts/Elements/LayoutDrawElement.cs @@ -1,14 +1,12 @@ -using Dalamud; -using Dalamud.Game; +using Dalamud.Game; using Dalamud.Interface.Components; +using Dalamud.Interface.Utility.Raii; using ECommons.GameFunctions; -using ECommons.ImGuiMethods; using ECommons.LanguageHelpers; using Lumina.Excel.GeneratedSheets; using Newtonsoft.Json; +using Splatoon.RenderEngines; using Splatoon.Serializables; -using Splatoon.Utility; -using System; namespace Splatoon; @@ -805,7 +803,62 @@ internal void LayoutDrawElement(Layout l, Element el, bool forceEnable = false) { el.SetDisplayStyle(style); } + using (ImRaii.Disabled(!el.Filled)) + { + if (el.type.EqualsAny(1, 3, 4) && el.Filled) + { + bool canSetCastAnimation = el.refActorRequireCast && el.ConfiguredRenderEngineKind() == RenderEngineKind.DirectX11; + using (ImRaii.Disabled(!canSetCastAnimation)) + { + ImGuiUtils.SizedText("Cast Animation:".Loc(), WidthElement); + ImGui.SameLine(); + } + ImGuiEx.HelpMarker("Choose a cast animation for this element. Requires 'While Casting' checked.\nUnsupported in ImGui Legacy renderer"); + ImGui.SameLine(); + using (ImRaii.Disabled(!canSetCastAnimation)) + { + ImGui.SetNextItemWidth(WidthElement); + ImGuiUtils.EnumCombo("##castanimation" + i + k, ref el.castAnimation, CastAnimations.Names, CastAnimations.Tooltips); + using (ImRaii.Disabled(el.castAnimation is CastAnimationKind.Unspecified)) + { + ImGui.SameLine(); + ImGuiEx.Text("Color:".Loc()); + ImGui.SameLine(); + var v4 = ImGui.ColorConvertU32ToFloat4(el.animationColor); + if (ImGui.ColorEdit4("##animationcolorbutton" + i + k, ref v4, ImGuiColorEditFlags.NoInputs)) + { + el.animationColor = ImGui.ColorConvertFloat4ToU32(v4); + } + ImGui.SameLine(); + if (ImGui.Button("Copy".Loc() + "##copyfromstroke" + i + k)) + { + el.animationColor = style.strokeColor; + } + if (ImGui.IsItemHovered()) + { + ImGui.SetTooltip("Copy Stroke Color".Loc()); + } + if (el.castAnimation is CastAnimationKind.Pulse) + { + ImGuiUtils.SizedText("Pulse:".Loc(), WidthElement); + ImGui.SameLine(); + + ImGuiEx.Text("Size:".Loc()); + ImGui.SameLine(); + ImGui.SetNextItemWidth(60f); + el.pulseSize = MathF.Min(el.pulseSize, el.EffectiveLength()); + ImGui.DragFloat("##animationsize" + i + k, ref el.pulseSize, 0.01f, 0.1f, el.EffectiveLength()); + ImGui.SameLine(); + ImGuiEx.Text("Frequency (s):".Loc()); + ImGui.SameLine(); + ImGui.SetNextItemWidth(60f); + ImGui.DragFloat("##animationfreq" + i + k, ref el.pulseFrequency, 0.01f, 1, 10); + } + } + } + } + } if ((el.type != 3) || el.includeRotation) { if (!(el.type == 3 && !el.includeRotation)) @@ -971,7 +1024,7 @@ internal void LayoutDrawElement(Layout l, Element el, bool forceEnable = false) ImGuiEx.HelpMarker("Choose a mechanic type that best represents this element.\n" + "This is used for automatically setting default colors.\nOnly for DirectX11 renderer."); ImGui.SameLine(); - ImGui.SetNextItemWidth(WidthCombo); + ImGui.SetNextItemWidth(WidthElement); ImGuiUtils.EnumCombo("##mechtype" + i + k, ref el.mechanicType, MechanicTypes.Names, MechanicTypes.Tooltips); if ((el.type.EqualsAny(0, 1) && el.Donut > 0) || el.type == 4 || (el.type.EqualsAny(2, 3) && (el.radius > 0 || el.includeHitbox || el.includeOwnHitbox))) diff --git a/Splatoon/RenderEngines/DirectX11/DirectX11DisplayObjects.cs b/Splatoon/RenderEngines/DirectX11/DirectX11DisplayObjects.cs index 5f9eb71e..89fd4101 100644 --- a/Splatoon/RenderEngines/DirectX11/DirectX11DisplayObjects.cs +++ b/Splatoon/RenderEngines/DirectX11/DirectX11DisplayObjects.cs @@ -77,7 +77,13 @@ public DisplayObjectLine(float ax, float ay, float az, float bx, float by, float this.startStyle = startStyle; this.endStyle = endStyle; } - + public float Length + { + get + { + return (stop - start).Length(); + } + } public Vector3 Direction { get @@ -107,10 +113,10 @@ public Vector2[] Bounds { return [ (start - PerpendicularRadius).ToVector2(), - (start + PerpendicularRadius).ToVector2(), - (stop - PerpendicularRadius).ToVector2(), - (stop + PerpendicularRadius).ToVector2(), - ]; + (start + PerpendicularRadius).ToVector2(), + (stop - PerpendicularRadius).ToVector2(), + (stop + PerpendicularRadius).ToVector2(), + ]; } } } diff --git a/Splatoon/RenderEngines/DirectX11/DirectX11Renderer.cs b/Splatoon/RenderEngines/DirectX11/DirectX11Renderer.cs index ccc51303..e6cb1fd0 100644 --- a/Splatoon/RenderEngines/DirectX11/DirectX11Renderer.cs +++ b/Splatoon/RenderEngines/DirectX11/DirectX11Renderer.cs @@ -55,19 +55,18 @@ internal void DrawCircle(Element e, float x, float y, float z, float r, float an { if (e.Donut > 0) { - DisplayObjects.Add(new DisplayObjectDonut(new(cx, z + e.offZ, cy), r, e.Donut, e.GetDisplayStyleWithOverride())); + DisplayObjects.Add(new DisplayObjectDonut(new(cx, z + e.offZ, cy), r, e.Donut, e.GetDisplayStyleWithOverride(go))); } else { - var style = e.GetDisplayStyleWithOverride(); - DisplayObjects.Add(new DisplayObjectCircle(new(cx, z + e.offZ, cy), r, style)); + DisplayObjects.Add(new DisplayObjectCircle(new(cx, z + e.offZ, cy), r, e.GetDisplayStyleWithOverride(go))); } } else { DisplayObjects.Add(new DisplayObjectDot(cx, z + e.offZ, cy, e.thicc, e.color)); } - if (e.overlayText.Length > 0) + if (e.overlayPlaceholders && e.overlayText.Length > 0) { var text = e.overlayText; if (go != null) @@ -78,7 +77,7 @@ internal void DrawCircle(Element e, float x, float y, float z, float r, float an } } - internal void DrawCone(Element e, Vector3 origin, float? radius = null, float baseAngle = 0f) + internal void DrawCone(Element e, Vector3 origin, float? radius = null, float baseAngle = 0f, IGameObject go = null) { if (e.coneAngleMax > e.coneAngleMin) { @@ -108,11 +107,11 @@ internal void DrawCone(Element e, Vector3 origin, float? radius = null, float ba } DisplayObjects.Add(new DisplayObjectLine(center, end, 0, e.GetDisplayStyleWithOverride(), e.LineEndA, e.LineEndB)); } - DisplayObjects.Add(new DisplayObjectFan(center, innerRadius, outerRadius, angleMin, angleMax, e.GetDisplayStyleWithOverride())); + DisplayObjects.Add(new DisplayObjectFan(center, innerRadius, outerRadius, angleMin, angleMax, e.GetDisplayStyleWithOverride(go))); } } - internal void AddRotatedLine(Vector3 tPos, float angle, Element e, float aradius, float hitboxRadius) + internal void AddRotatedLine(Vector3 tPos, float angle, Element e, float aradius, float hitboxRadius, IGameObject go = null) { if (e.includeRotation) { @@ -136,7 +135,7 @@ internal void AddRotatedLine(Vector3 tPos, float angle, Element e, float aradius tPos.Y + e.offY, tPos.Z + e.offZ)); - var line = new DisplayObjectLine(Utils.XZY(start), Utils.XZY(stop), aradius, e.GetDisplayStyleWithOverride(), e.LineEndA, e.LineEndB); + var line = new DisplayObjectLine(Utils.XZY(start), Utils.XZY(stop), aradius, e.GetDisplayStyleWithOverride(go), e.LineEndA, e.LineEndB); DisplayObjects.Add(line); } } @@ -170,15 +169,15 @@ internal override void ProcessElement(Element e, Layout i = null, bool forceEnab { var pointPos = Utils.GetPlayerPositionXZY(); DrawCircle(e, pointPos.X, pointPos.Y, pointPos.Z, radius, e.includeRotation ? Svc.ClientState.LocalPlayer.Rotation : 0f, - e.overlayPlaceholders ? Svc.ClientState.LocalPlayer : null); + Svc.ClientState.LocalPlayer); } else if (e.type == 3) { - AddRotatedLine(Utils.GetPlayerPositionXZY(), Svc.ClientState.LocalPlayer.Rotation, e, radius, 0f); + AddRotatedLine(Utils.GetPlayerPositionXZY(), Svc.ClientState.LocalPlayer.Rotation, e, radius, 0f, Svc.ClientState.LocalPlayer); } else if (e.type == 4) { - DrawCone(e, Utils.GetPlayerPositionXZY(), radius, Svc.ClientState.LocalPlayer.Rotation); + DrawCone(e, Utils.GetPlayerPositionXZY(), radius, Svc.ClientState.LocalPlayer.Rotation, Svc.ClientState.LocalPlayer); } } else if (e.refActorType == 2 && Svc.Targets.Target != null @@ -191,19 +190,19 @@ internal override void ProcessElement(Element e, Layout i = null, bool forceEnab { DrawCircle(e, Svc.Targets.Target.GetPositionXZY().X, Svc.Targets.Target.GetPositionXZY().Y, Svc.Targets.Target.GetPositionXZY().Z, radius, e.includeRotation ? Svc.Targets.Target.Rotation : 0f, - e.overlayPlaceholders ? Svc.Targets.Target : null); + Svc.Targets.Target); } else if (e.type == 3) { var angle = e.FaceMe ? (180 - (MathHelper.GetRelativeAngle(Svc.Targets.Target.Position.ToVector2(), Marking.GetPlayer(e.faceplayer).Position.ToVector2()))).DegreesToRadians() : Svc.Targets.Target.Rotation; - AddRotatedLine(Svc.Targets.Target.GetPositionXZY(), angle, e, radius, Svc.Targets.Target.HitboxRadius); + AddRotatedLine(Svc.Targets.Target.GetPositionXZY(), angle, e, radius, Svc.Targets.Target.HitboxRadius, Svc.Targets.Target); } else if (e.type == 4) { var baseAngle = e.FaceMe ? (180 - (MathHelper.GetRelativeAngle(Svc.Targets.Target.Position.ToVector2(), Marking.GetPlayer(e.faceplayer).Position.ToVector2()))).DegreesToRadians() : Svc.Targets.Target.Rotation; - DrawCone(e, Svc.Targets.Target.GetPositionXZY(), radius, baseAngle); + DrawCone(e, Svc.Targets.Target.GetPositionXZY(), radius, baseAngle, Svc.Targets.Target); } } } @@ -228,21 +227,21 @@ internal override void ProcessElement(Element e, Layout i = null, bool forceEnab { DrawCircle(e, a.GetPositionXZY().X, a.GetPositionXZY().Y, a.GetPositionXZY().Z, aradius, e.includeRotation ? a.Rotation : 0f, - e.overlayPlaceholders ? a : null); + a); } else if (e.type == 3) { var angle = e.FaceMe ? (180 - (MathHelper.GetRelativeAngle(a.Position.ToVector2(), Marking.GetPlayer(e.faceplayer).Position.ToVector2()))).DegreesToRadians() : a.Rotation; - AddRotatedLine(a.GetPositionXZY(), angle, e, aradius, a.HitboxRadius); + AddRotatedLine(a.GetPositionXZY(), angle, e, aradius, a.HitboxRadius, a); } else if (e.type == 4) { var baseAngle = e.FaceMe ? (180 - (MathHelper.GetRelativeAngle(a.Position.ToVector2(), Marking.GetPlayer(e.faceplayer).Position.ToVector2()))).DegreesToRadians() : (a.Rotation); - DrawCone(e, a.GetPositionXZY(), aradius, baseAngle); + DrawCone(e, a.GetPositionXZY(), aradius, baseAngle, a); } } } diff --git a/Splatoon/RenderEngines/DirectX11/DirectX11Scene.cs b/Splatoon/RenderEngines/DirectX11/DirectX11Scene.cs index cc476bdf..0419e26c 100644 --- a/Splatoon/RenderEngines/DirectX11/DirectX11Scene.cs +++ b/Splatoon/RenderEngines/DirectX11/DirectX11Scene.cs @@ -119,40 +119,11 @@ void Draw() { if (element is DisplayObjectFan elementFan) { - if (elementFan.style.filled) - drawList.AddFanFilled( - elementFan.origin, - elementFan.innerRadius, - elementFan.outerRadius, - elementFan.angleMin, - elementFan.angleMax, - elementFan.style.originFillColor, - elementFan.style.endFillColor); - if (elementFan.style.IsStrokeVisible()) - drawList.AddFan( - elementFan.origin, - elementFan.innerRadius, - elementFan.outerRadius, - elementFan.angleMin, - elementFan.angleMax, - elementFan.style.strokeColor, - thickness: elementFan.style.strokeThickness); + DrawFan(elementFan, drawList); } else if (element is DisplayObjectLine elementLine) { - if (elementLine.style.filled) - drawList.AddLineFilled( - elementLine.start, - elementLine.stop, - elementLine.radius, - elementLine.style.originFillColor, - elementLine.style.endFillColor); - if (elementLine.style.IsStrokeVisible()) - drawList.AddLine( - elementLine.start, - elementLine.stop, - elementLine.radius, - elementLine.style.strokeColor); + DrawLine(elementLine, drawList); } } foreach (var zone in P.Config.ClipZones) @@ -180,6 +151,98 @@ void Draw() return texture; } + public void DrawFan(DisplayObjectFan fan, PctDrawList drawList) + { + if (fan.style.filled) + drawList.AddFanFilled( + fan.origin, + fan.innerRadius, + fan.outerRadius, + fan.angleMin, + fan.angleMax, + fan.style.originFillColor, + fan.style.endFillColor); + if (fan.style.IsStrokeVisible()) + drawList.AddFan( + fan.origin, + fan.innerRadius, + fan.outerRadius, + fan.angleMin, + fan.angleMax, + fan.style.strokeColor, + thickness: fan.style.strokeThickness); + if (fan.style.castFraction > 0) + { + if (fan.style.animation.kind is Serializables.CastAnimationKind.Pulse) + { + var size = fan.style.animation.size + fan.outerRadius - fan.innerRadius; + var pulsePosition = size * (float)((DateTime.Now - DateTime.MinValue).TotalMilliseconds / 1000f % fan.style.animation.frequency) / fan.style.animation.frequency; + drawList.AddFanFilled( + fan.origin, + MathF.Max(fan.innerRadius, fan.innerRadius + pulsePosition - fan.style.animation.size), + MathF.Min(fan.outerRadius, fan.innerRadius + pulsePosition), + fan.angleMin, + fan.angleMax, + fan.style.animation.color & 0x00FFFFFF, + fan.style.animation.color); + } + else if (fan.style.animation.kind is Serializables.CastAnimationKind.Fill) + { + var size = fan.outerRadius - fan.innerRadius; + var castRadius = size * fan.style.castFraction; + drawList.AddFanFilled( + fan.origin, + fan.innerRadius, + fan.innerRadius + castRadius, + fan.angleMin, + fan.angleMax, + fan.style.animation.color, + fan.style.animation.color); + } + } + } + + public void DrawLine(DisplayObjectLine line, PctDrawList drawList) + { + if (line.style.filled) + drawList.AddLineFilled( + line.start, + line.stop, + line.radius, + line.style.originFillColor, + line.style.endFillColor); + if (line.style.IsStrokeVisible()) + drawList.AddLine( + line.start, + line.stop, + line.radius, + line.style.strokeColor); + if (line.style.castFraction > 0) + { + if (line.style.animation.kind is Serializables.CastAnimationKind.Pulse) + { + var length = line.style.animation.size + line.Length; + var pulsePosition = length * (float)((DateTime.Now - DateTime.MinValue).TotalMilliseconds / 1000f % line.style.animation.frequency) / line.style.animation.frequency; + drawList.AddLineFilled( + line.start + line.Direction * MathF.Max(0, pulsePosition - line.style.animation.size), + line.start + line.Direction * MathF.Min(pulsePosition, line.Length), + line.radius, + line.style.animation.color & 0x00FFFFFF, + line.style.animation.color); + } + else if (line.style.animation.kind is Serializables.CastAnimationKind.Fill) + { + var castLength = line.style.castFraction * line.Length; + drawList.AddLineFilled( + line.start, + line.start + line.Direction * castLength, + line.radius, + line.style.animation.color, + line.style.animation.color); + } + } + } + public void DrawTextWorld(DisplayObjectText e) { if (Svc.GameGui.WorldToScreen( diff --git a/Splatoon/Serializables/CastAnimationKind.cs b/Splatoon/Serializables/CastAnimationKind.cs new file mode 100644 index 00000000..d47f4b4c --- /dev/null +++ b/Splatoon/Serializables/CastAnimationKind.cs @@ -0,0 +1,33 @@ +using ECommons.LanguageHelpers; + +namespace Splatoon.Serializables; + +public enum CastAnimationKind +{ + // These names can be changed. + // These number values are used for serialization and must not be changed. + Unspecified = 0, + Pulse = 1, + ColorShift = 2, + Fill = 3, +} + + +public static class CastAnimations +{ + public static readonly string[] Names = + [ + "Unspecified".Loc(), + "Pulse".Loc(), + "ColorShift".Loc(), + "Fill".Loc(), + ]; + + public static readonly string[] Tooltips = + [ + "The default type for new elements. No cast animation is specified.".Loc(), + "Pulse with some frequency. This looks similar to the game's default VFX.".Loc(), + "Change the element's color based on the cast progress.".Loc(), + "Fill the element from start to end based on the cast progress.".Loc(), + ]; +} diff --git a/Splatoon/Serializables/DisplayStyle.cs b/Splatoon/Serializables/DisplayStyle.cs index 4ff20e03..585ce368 100644 --- a/Splatoon/Serializables/DisplayStyle.cs +++ b/Splatoon/Serializables/DisplayStyle.cs @@ -1,20 +1,31 @@ -namespace Splatoon.Serializables +namespace Splatoon.Serializables; + +public struct DisplayStyle( + uint strokeColor, + float strokeThickness, + float fillIntensity, + uint originFillColor, + uint endFillColor, + bool filled = true, + bool overrideFillColor = false, + float castFraction = 0, + AnimationStyle animation = default) { - public struct DisplayStyle( - uint strokeColor, - float strokeThickness, - float fillIntensity, - uint originFillColor, - uint endFillColor, - bool filled = true, - bool overrideFillColor = false) - { - public uint strokeColor = strokeColor; - public float strokeThickness = strokeThickness; - public float fillIntensity = fillIntensity; - public uint originFillColor = originFillColor; - public uint endFillColor = endFillColor; - public bool filled = filled; - public bool overrideFillColor = overrideFillColor; - } + public uint strokeColor = strokeColor; + public float strokeThickness = strokeThickness; + public float fillIntensity = fillIntensity; + public uint originFillColor = originFillColor; + public uint endFillColor = endFillColor; + public bool filled = filled; + public bool overrideFillColor = overrideFillColor; + public float castFraction = castFraction; + public AnimationStyle animation = animation; +} + +public struct AnimationStyle(CastAnimationKind kind, uint color, float size, float frequency) +{ + public CastAnimationKind kind = kind; + public uint color = color; + public float size = size; + public float frequency = frequency; } diff --git a/Splatoon/Serializables/Element.cs b/Splatoon/Serializables/Element.cs index 5092da8f..12b65a05 100644 --- a/Splatoon/Serializables/Element.cs +++ b/Splatoon/Serializables/Element.cs @@ -1,9 +1,7 @@ using ECommons.LanguageHelpers; using Splatoon.RenderEngines; using Splatoon.Serializables; -using Splatoon.Utility; using System.ComponentModel; -using System.Runtime.Serialization; namespace Splatoon; @@ -87,6 +85,10 @@ public Element(int t) [DefaultValue(null)] public uint? endFillColor = null; [DefaultValue(0x70000000)] public uint overlayBGColor = 0x70000000; [DefaultValue(0xC8FFFFFF)] public uint overlayTextColor = 0xC8FFFFFF; + [DefaultValue(CastAnimationKind.Unspecified)] public CastAnimationKind castAnimation = CastAnimationKind.Unspecified; + [DefaultValue(0xc80000ff)] public uint animationColor = 0xc80000ff; + [DefaultValue(0.5f)] public float pulseSize = 0.5f; + [DefaultValue(1.5f)] public float pulseFrequency = 1.5f; [DefaultValue(0f)] public float overlayVOffset = 0f; [DefaultValue(1f)] public float overlayFScale = 1f; [DefaultValue(false)] public bool overlayPlaceholders = false; @@ -337,4 +339,36 @@ public bool ShouldSerializeDonut() { return type.EqualsAny(0, 1) && Donut > 0; } + public bool ShouldSerializefillIntensity() + { + return Filled && !overrideFillColor; + } + public bool ShouldSerializeoverrideFillColor() + { + return Filled && overrideFillColor; + } + public bool ShouldSerializeoriginFillColor() + { + return ShouldSerializeoverrideFillColor(); + } + public bool ShouldSerializeendFillColor() + { + return ShouldSerializeoverrideFillColor(); + } + public bool ShouldSerializecastAnimation() + { + return refActorRequireCast && castAnimation is not CastAnimationKind.Unspecified; + } + public bool ShouldSerializeanimationColor() + { + return ShouldSerializecastAnimation(); + } + public bool ShouldSerializepulseSize() + { + return ShouldSerializecastAnimation() && castAnimation is CastAnimationKind.Pulse; + } + public bool ShouldSerializepulseFrequency() + { + return ShouldSerializecastAnimation() && castAnimation is CastAnimationKind.Pulse; + } } diff --git a/Splatoon/Utility/Colors.cs b/Splatoon/Utility/Colors.cs index 0601a77d..e2a414c5 100644 --- a/Splatoon/Utility/Colors.cs +++ b/Splatoon/Utility/Colors.cs @@ -18,4 +18,12 @@ public static uint MultiplyAlpha(uint color, float amount) alpha = Math.Clamp(alpha, 0x00, 0xFF); return color & 0x00FFFFFF | (alpha << 24); } + + // Linear interpolation between 1-byte components of uint32 + // Intended for interpolating colors + public static uint Lerp(uint v1, uint v2, float amount) + { + if (v1 == v2) return v1; + return Vector4.Lerp(v1.ToVector4(), v2.ToVector4(), amount).ToUint(); + } } diff --git a/Splatoon/Utility/ElementExtensions.cs b/Splatoon/Utility/ElementExtensions.cs index 931ec0d3..00339a7c 100644 --- a/Splatoon/Utility/ElementExtensions.cs +++ b/Splatoon/Utility/ElementExtensions.cs @@ -1,4 +1,5 @@ -using Splatoon.Serializables; +using Splatoon.RenderEngines; +using Splatoon.Serializables; namespace Splatoon.Utility; public static class ElementExtensions @@ -62,11 +63,11 @@ public static DisplayStyle GetDisplayStyle(this Element e) uint originFillColor = e.originFillColor ?? Colors.MultiplyAlpha(e.color, fillIntensity); uint endFillColor = e.endFillColor ?? Colors.MultiplyAlpha(e.color, fillIntensity); - return new DisplayStyle(e.color, e.thicc, fillIntensity, originFillColor, endFillColor, e.Filled, e.overrideFillColor); + return new DisplayStyle(e.color, e.thicc, fillIntensity, originFillColor, endFillColor, e.Filled, e.overrideFillColor, 0, e.GetAnimationStyle()); } - public static DisplayStyle GetDisplayStyleWithOverride(this Element e) + public static DisplayStyle GetDisplayStyleWithOverride(this Element e, IGameObject go = null) { DisplayStyle style = e.GetDisplayStyle(); @@ -84,9 +85,18 @@ public static DisplayStyle GetDisplayStyleWithOverride(this Element e) style.originFillColor = defaultColor; style.endFillColor = defaultColor; } - - style.originFillColor = P.Config.ClampFillColorAlpha(style.originFillColor); - style.endFillColor = P.Config.ClampFillColorAlpha(style.endFillColor); + style.animation = e.GetAnimationStyle(); + style.castFraction = e.refActorRequireCast ? LayoutUtils.CastFraction(e, go) : 0f; + if (style.animation.kind is CastAnimationKind.ColorShift) + { + style.originFillColor = P.Config.ClampFillColorAlpha(Colors.Lerp(style.originFillColor, style.animation.color, style.castFraction)); + style.endFillColor = P.Config.ClampFillColorAlpha(Colors.Lerp(style.endFillColor, style.animation.color, style.castFraction)); + } + else + { + style.originFillColor = P.Config.ClampFillColorAlpha(style.originFillColor); + style.endFillColor = P.Config.ClampFillColorAlpha(style.endFillColor); + } return style; } @@ -99,4 +109,37 @@ public static bool IsDangerous(this Element e) { return e.mechanicType == MechanicType.Danger; } + + public static AnimationStyle GetAnimationStyle(this Element e) + { + return new(e.castAnimation, e.animationColor, e.pulseSize, e.pulseFrequency); + } + + public static float EffectiveLength(this Element e) + { + if (e.type.EqualsAny(0, 1)) + { + if (e.Donut > 0) + return e.Donut; + return e.radius; + } + if (e.type.EqualsAny(2, 3)) + { + return (new Vector3(e.refX, e.refY, e.refZ) - new Vector3(e.offX, e.offY, e.offZ)).Length(); + } + if (e.type.EqualsAny(4, 5)) + { + return e.radius; + } + return 0; + } + + public static RenderEngineKind ConfiguredRenderEngineKind(this Element e) + { + if (e.RenderEngineKind != RenderEngineKind.Unspecified) + return e.RenderEngineKind; + if (P.Config.RenderEngineKind != RenderEngineKind.Unspecified) + return P.Config.RenderEngineKind; + return RenderEngineKind.DirectX11; + } } diff --git a/Splatoon/Utility/LayoutUtils.cs b/Splatoon/Utility/LayoutUtils.cs index e8dac623..e28ab122 100644 --- a/Splatoon/Utility/LayoutUtils.cs +++ b/Splatoon/Utility/LayoutUtils.cs @@ -158,6 +158,35 @@ public static bool IsCastingMatches(Element e, IBattleChara chr) } } + public static float CastFraction(Element e, IGameObject go) + { + if (go is IBattleChara chr) + { + float castTime = -1; + float totalCastTime = 1; + if (chr.IsCasting(e.refActorCastId)) + { + castTime = chr.CurrentCastTime; + totalCastTime = chr.TotalCastTime; + } + else if (!(e.refActorUseOvercast && AttachedInfo.TryGetCastTime(chr.Address, e.refActorCastId, out castTime))) + { + return 0; + } + + if (e.refActorUseCastTime) + { + castTime -= e.refActorCastTimeMin; + totalCastTime = e.refActorCastTimeMax - e.refActorCastTimeMin; + } + if (castTime <= 0 || totalCastTime <= 0) return 0; + if (castTime > totalCastTime) return 1; + + return castTime / totalCastTime; + } + return 0; + } + public static bool CheckEffect(Element e, IBattleChara c) { if (e.refActorRequireAllBuffs) From 3648750b2ca98633336ed0febe867457a2d706df Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 27 Jul 2024 19:57:26 +0000 Subject: [PATCH 2/3] Update SplatoonScripts/update.csv --- SplatoonScripts/update.csv | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/SplatoonScripts/update.csv b/SplatoonScripts/update.csv index 53bb0308..c433c619 100644 --- a/SplatoonScripts/update.csv +++ b/SplatoonScripts/update.csv @@ -1,45 +1,45 @@ -SplatoonScriptsOfficial.Generic@AutoFateSync,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/AutoFateSync.cs -SplatoonScriptsOfficial.Generic@ZoneNameToast,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/ZoneNameToast.cs -SplatoonScriptsOfficial.Generic@ShowTooltipOnKey,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/ShowTooltipOnKey.cs +SplatoonScriptsOfficial.Tests@DMParser,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Tests/DMParser.cs SplatoonScriptsOfficial.Generic@ShowEmote,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/ShowEmote.cs SplatoonScriptsOfficial.Generic@QuestHighlighter,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/QuestHighlighter.cs -SplatoonScriptsOfficial.Generic@PluginInstallerWindowCollapsible,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/PluginInstallerWindowCollapsible.cs +SplatoonScriptsOfficial.Generic@ZoneNameToast,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/ZoneNameToast.cs +SplatoonScriptsOfficial.Generic@ShowTooltipOnKey,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/ShowTooltipOnKey.cs +SplatoonScriptsOfficial.Generic@AutoFateSync,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/AutoFateSync.cs SplatoonScriptsOfficial.Generic@ActReminder,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/ActReminder.cs -SplatoonScriptsOfficial.Tests@DMParser,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Tests/DMParser.cs +SplatoonScriptsOfficial.Generic@PluginInstallerWindowCollapsible,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Generic/PluginInstallerWindowCollapsible.cs +SplatoonScriptsOfficial.Duties.Shadowbringers@TEA_P2_Transition,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Shadowbringers/TEA_P2_Transition.cs SplatoonScriptsOfficial.Duties.Dawntrail@EX2_Projection_of_Triumph,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Dawntrail/EX2 Projection of Triumph.cs -SplatoonScriptsOfficial.Duties.Endwalker@DSR_Wrath,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR Wrath.cs -SplatoonScriptsOfficial.Duties.Endwalker@Aloalo_Bombs,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/Aloalo Bombs.cs +SplatoonScriptsOfficial.Duties.Endwalker@P12S_Superchain,7,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Superchain.cs SplatoonScriptsOfficial.Duties.Endwalker@P10S_Debuffs,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P10S Debuffs.cs -SplatoonScriptsOfficial.Duties.Endwalker@DSR_Dooms,5,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR Dooms.cs +SplatoonScriptsOfficial.Duties.Endwalker@DSR_Wrath,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR Wrath.cs SplatoonScriptsOfficial.Duties.Endwalker@P10S_Tethers,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P10S Tethers.cs -SplatoonScriptsOfficial.Duties.Endwalker@P12S_Classical_Concepts,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Classical Concepts.cs -SplatoonScriptsOfficial.Duties.Endwalker@P12S_Wing_Cleaves,6,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Wing Cleaves.cs -SplatoonScriptsOfficial.Duties.Endwalker@P12S_Superchain,7,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Superchain.cs -SplatoonScriptsOfficial.Duties.Endwalker@P12S_Caloric_Theory,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Caloric Theory.cs +SplatoonScriptsOfficial.Duties.Endwalker@DSR_Towers,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR Towers.cs SplatoonScriptsOfficial.Duties.Endwalker@P12S_Limit_Cut,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Limit Cut.cs -SplatoonScriptsOfficial.Duties.Endwalker@P12S_Pangenesis,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Pangenesis.cs -SplatoonScriptsOfficial.Duties.Endwalker@P8S2_Limitless_Desolation,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P8S2 Limitless Desolation.cs -SplatoonScriptsOfficial.Duties.Endwalker@P8S2_Dancer_HC_Step,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P8S2 Dancer HC Step.cs -SplatoonScriptsOfficial.Duties.Endwalker@P12S_Tethers,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Tethers.cs +SplatoonScriptsOfficial.Duties.Endwalker@Aloalo_Bombs,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/Aloalo Bombs.cs SplatoonScriptsOfficial.Duties.Endwalker@P11S_Multiscript,4,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P11S Multiscript.cs -SplatoonScriptsOfficial.Duties.Endwalker@DSR_P6_Cauterize_Unsafe,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR_P6_Cauterize_Unsafe.cs -SplatoonScriptsOfficial.Duties.Endwalker@P8S2_Dominion,8,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P8S2 Dominion.cs -SplatoonScriptsOfficial.Duties.Endwalker@DSR_Towers,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR Towers.cs +SplatoonScriptsOfficial.Duties.Endwalker@P12S_Caloric_Theory,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Caloric Theory.cs SplatoonScriptsOfficial.Duties.Endwalker@P9S_JP_LC_Strat,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P9S JP LC Strat.cs +SplatoonScriptsOfficial.Duties.Endwalker@P12S_Tethers,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Tethers.cs +SplatoonScriptsOfficial.Duties.Endwalker@P8S2_Dominion,8,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P8S2 Dominion.cs +SplatoonScriptsOfficial.Duties.Endwalker@P8S2_Dancer_HC_Step,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P8S2 Dancer HC Step.cs SplatoonScriptsOfficial.Duties.Endwalker@P9S_Dualspell_InOut,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P9S Dualspell InOut.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Dynamis_Sigma,7,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Dynamis Sigma.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@MF_Target_Enforcer,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/MF Target Enforcer.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Dynamis_Delta,9,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Dynamis Delta.cs +SplatoonScriptsOfficial.Duties.Endwalker@DSR_Dooms,5,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR Dooms.cs +SplatoonScriptsOfficial.Duties.Endwalker@P8S2_Limitless_Desolation,1,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P8S2 Limitless Desolation.cs +SplatoonScriptsOfficial.Duties.Endwalker@P12S_Pangenesis,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Pangenesis.cs +SplatoonScriptsOfficial.Duties.Endwalker@P12S_Classical_Concepts,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Classical Concepts.cs +SplatoonScriptsOfficial.Duties.Endwalker@DSR_P6_Cauterize_Unsafe,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/DSR_P6_Cauterize_Unsafe.cs +SplatoonScriptsOfficial.Duties.Endwalker@P12S_Wing_Cleaves,6,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/P12S Wing Cleaves.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Program_Loop,4,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Program Loop.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Limitless_Synergy,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Limitless Synergy.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Party_Synergy,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Party Synergy.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Hello_Near_Far_World,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Hello Near Far World.cs SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Hello_World,9,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Hello World.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Exasquares,5,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Exasquares.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Dynamis_Delta,9,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Dynamis Delta.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@MF_Target_Enforcer,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/MF Target Enforcer.cs +SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Dynamis_Sigma,7,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Dynamis Sigma.cs SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Pantokrator,4,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Pantokrator.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Program_Loop,4,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Program Loop.cs SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Beyond_Defense,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Beyond Defense.cs SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Oversampled_Wave_Cannon,5,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Oversampled Wave Cannon.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Exasquares,5,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Exasquares.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Party_Synergy,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Party Synergy.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Limitless_Synergy,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Limitless Synergy.cs -SplatoonScriptsOfficial.Duties.Endwalker.The_Omega_Protocol@Hello_Near_Far_World,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Endwalker/The Omega Protocol/Hello Near Far World.cs -SplatoonScriptsOfficial.Duties.Shadowbringers@TEA_P2_Transition,2,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Shadowbringers/TEA_P2_Transition.cs -SplatoonScriptsOfficial.Duties.Stormblood@UCOB_dragon_baits,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Stormblood/UCOB dragon baits.cs +SplatoonScriptsOfficial.Duties.Stormblood@UCOB_Heavensfall_Trio_Towers,6,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Stormblood/UCOB Heavensfall Trio Towers.cs SplatoonScriptsOfficial.Duties.Stormblood@UCOB_Tethers,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Stormblood/UCOB Tethers.cs -SplatoonScriptsOfficial.Duties.Stormblood@UCOB_Heavensfall_Trio_Towers,6,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Stormblood/UCOB Heavensfall Trio Towers.cs \ No newline at end of file +SplatoonScriptsOfficial.Duties.Stormblood@UCOB_dragon_baits,3,https://github.com/PunishXIV/Splatoon/raw/main/SplatoonScripts/Duties/Stormblood/UCOB dragon baits.cs \ No newline at end of file From 29b903064a7a198dd806120311998fd97b7de92c Mon Sep 17 00:00:00 2001 From: Limiana <5073202+Limiana@users.noreply.github.com> Date: Sat, 27 Jul 2024 23:34:21 +0300 Subject: [PATCH 3/3] Update version --- Splatoon/Splatoon.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Splatoon/Splatoon.csproj b/Splatoon/Splatoon.csproj index c2bb07a1..d78e3118 100644 --- a/Splatoon/Splatoon.csproj +++ b/Splatoon/Splatoon.csproj @@ -2,7 +2,7 @@ NightmareXIV - 3.6.0.3 + 3.7.0.0