diff --git a/src/Endwalker/P12S Limit Cut 女神的护佑 麻将.cs b/src/Endwalker/P12S Limit Cut 女神的护佑 麻将.cs new file mode 100644 index 0000000..4cd3bd0 --- /dev/null +++ b/src/Endwalker/P12S Limit Cut 女神的护佑 麻将.cs @@ -0,0 +1,164 @@ +using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Interface.Colors; +using ECommons; +using ECommons.DalamudServices; +using ECommons.Hooks; +using ECommons.Hooks.ActionEffectTypes; +using ECommons.ImGuiMethods; +using ECommons.Logging; +using Splatoon; +using Splatoon.Memory; +using Splatoon.SplatoonScripting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SplatoonScriptsOfficial.Duties.Endwalker +{ + public class P12S_Limit_Cut_女神的护佑_麻将 : SplatoonScript + { + public override HashSet ValidTerritories => new() { 1154 }; + public override Metadata? Metadata => new(1, "NightmareXIV -by Errer CN版本"); + const uint Puddle = 33527; + const uint Laser = 33520; + bool mechanicActive = false; + int puddleNum = 0; + int laserNum = 0; + + Element EPuddle = null!; + Element ELaser = null!; + + public override void OnSetup() + { + EPuddle = Controller.RegisterElementFromCode("Puddle", "{\"Name\":\"Puddle\",\"type\":1,\"Enabled\":false,\"radius\":4.5,\"Donut\":0.5,\"overlayBGColor\":4278190335,\"overlayTextColor\":4294967295,\"overlayVOffset\":1.5,\"thicc\":3.0,\"overlayText\":\"贴边分摊!\",\"refActorType\":1}"); + ELaser = Controller.RegisterElementFromCode("Laser", "{\"Name\":\"Laser\",\"type\":1,\"Enabled\":false,\"overlayBGColor\":4278252031,\"overlayTextColor\":4278190080,\"overlayFScale\":2.0,\"thicc\":0.0,\"overlayText\":\"引导激光\",\"refActorType\":1}"); + } + + public override void OnEnable() + { + ActionEffect.ActionEffectEvent += ActionEffect_ActionEffectEvent; + } + + public override void OnDisable() + { + ActionEffect.ActionEffectEvent -= ActionEffect_ActionEffectEvent; + } + + public override void OnVFXSpawn(uint target, string vfxPath) + { + if (vfxPath.StartsWith("vfx/lockon/eff/sph_lockon2_num0")) + { + mechanicActive = true; + puddleNum = 0; + laserNum = 0; + //DuoLog.Information($"Mechanic starts"); + } + } + + public override void OnUpdate() + { + EPuddle.Enabled = false; + ELaser.Enabled = false; + if (mechanicActive) + { + var myNum = GetMyNumber(); + if (myNum.EqualsAny(1, 2, 3, 4)) + { + if (puddleNum < 4) + { + //take puddle + EPuddle.Enabled = true; + } + else + { + //puddle complete + } + } + else + { + if (puddleNum >= 4) + { + //take puddle + EPuddle.Enabled = true; + } + else + { + //puddle not yet started + } + } + //57681324 + if (myNum.EqualsAny(5, 7) && laserNum == 0) + { + //laser + ELaser.Enabled = true; + } + if (myNum.EqualsAny(6, 8) && laserNum == 2) + { + //laser + ELaser.Enabled = true; + } + if (myNum.EqualsAny(1, 3) && laserNum == 4) + { + //laser + ELaser.Enabled = true; + } + if (myNum.EqualsAny(2, 4) && laserNum == 6) + { + //laser + ELaser.Enabled = true; + } + if (ELaser.Enabled) + { + ELaser.overlayBGColor = GradientColor.Get(ImGuiColors.DalamudRed, ImGuiColors.DalamudYellow).ToUint(); + } + if ((puddleNum >= 8 && laserNum >= 8)) + { + mechanicActive = false; + //DuoLog.Information($"Mechanic ends {puddleNum} {laserNum}"); + } + } + } + + public override void OnDirectorUpdate(DirectorUpdateCategory category) + { + if (category.EqualsAny(DirectorUpdateCategory.Wipe, DirectorUpdateCategory.Recommence)) + { + mechanicActive = false; + } + } + + int GetMyNumber() + { + if (AttachedInfo.VFXInfos.TryGetValue(Svc.ClientState.LocalPlayer.Address, out var info)) + { + if (info.OrderBy(x => x.Value.Age).TryGetFirst(x => x.Key.StartsWith("vfx/lockon/eff/sph_lockon2_num0"), out var effect)) + { + return int.Parse(effect.Key.Replace("vfx/lockon/eff/sph_lockon2_num0", "")[0].ToString()); + } + } + return 0; + } + + private void ActionEffect_ActionEffectEvent(ActionEffectSet set) + { + if (!mechanicActive) return; + if (set.Source?.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) + { + if (set.Action.RowId == Puddle) + { + //DuoLog.Information($"Puddle on {set.Target?.Name}"); + puddleNum++; + } + if (set.Action.RowId == Laser) + { + //DuoLog.Information($"Laser"); + laserNum++; + } + //DuoLog.Information($"Cast: {set.Action.RowId} {set.Action.Name} on {set.Target}"); + } + } + } +} diff --git a/src/Endwalker/P12S Superchain 超链理论.cs b/src/Endwalker/P12S Superchain 超链理论.cs new file mode 100644 index 0000000..b6d2c1e --- /dev/null +++ b/src/Endwalker/P12S Superchain 超链理论.cs @@ -0,0 +1,291 @@ +using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Interface.Colors; +using ECommons; +using ECommons.Configuration; +using ECommons.DalamudServices; +using ECommons.GameFunctions; +using ECommons.ImGuiMethods; +using ImGuiNET; +using Lumina.Data.Parsing.Tex.Buffers; +using Splatoon.SplatoonScripting; +using Splatoon.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace SplatoonScriptsOfficial.Duties.Endwalker +{ + public class P12S_Superchain_超链理论 : SplatoonScript + { + public override HashSet ValidTerritories => new() { 1154 }; + public override Metadata? Metadata => new(6, "NightmareXIV, RedAsteroid 修改+调色"); + + enum Spheres : uint + { + Mastersphere = 16176, + AOEBall = 16177, + Protean = 16179, + Donut = 16178, + Pairs = 16180, + } + + const uint AOEDebuff = 3578; + + public override void OnSetup() + { + var donut = "{\"Name\":\"Donut\",\"type\":1,\"radius\":6.0,\"Donut\":30.0,\"thicc\":4.0,\"refActorObjectID\":0,\"FillStep\":0.2,\"refActorComparisonType\":2}"; + var donut1 = "{\"Name\":\"Donut1\",\"type\":1,\"radius\":6.0,\"Donut\":30.0,\"color\":4294967295,\"thicc\":5.0,\"refActorObjectID\":0,\"FillStep\":999.0,\"refActorComparisonType\":2}"; + var donut2 = "{\"Name\":\"Donut2\",\"type\":1,\"radius\":6.0,\"Donut\":30.0,\"color\":4294906112,\"thicc\":2.0,\"refActorObjectID\":0,\"FillStep\":999.0,\"refActorComparisonType\":2}"; + + Controller.RegisterElementFromCode("Donut1", donut); + Controller.RegisterElementFromCode("Donut11", donut1); + Controller.RegisterElementFromCode("Donut12", donut2); + Controller.RegisterElementFromCode("Donut2", donut); + Controller.RegisterElementFromCode("Donut21", donut1); + Controller.RegisterElementFromCode("Donut22", donut2); + + + var AOE = "{\"Name\":\"AOE\",\"type\":1,\"radius\":7.0,\"color\":1275012352,\"thicc\":3.0,\"refActorObjectID\":0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"Filled\":true}"; + var AOE1 = "{\"Name\":\"AOE1\",\"type\":1,\"radius\":7.0,\"color\":4294967295,\"thicc\":5.0,\"refActorObjectID\":0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"Filled\":false}"; + var AOE2 = "{\"Name\":\"AOE2\",\"type\":1,\"radius\":7.0,\"color\":4294901769,\"thicc\":2.0,\"refActorObjectID\":0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"Filled\":false}"; + Controller.RegisterElementFromCode("AOEBall1", AOE); + Controller.RegisterElementFromCode("AOEBall11", AOE1); + Controller.RegisterElementFromCode("AOEBall12", AOE2); + Controller.RegisterElementFromCode("AOEBall2", AOE); + Controller.RegisterElementFromCode("AOEBall21", AOE1); + Controller.RegisterElementFromCode("AOEBall22", AOE2); + + Controller.TryRegisterLayoutFromCode("Protean", "~Lv2~{\"Name\":\"P12S Protean\",\"Group\":\"P12S\",\"ZoneLockH\":[1154],\"ElementsL\":[{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"Filled\":true},{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":0.7853982,\"Filled\":true},{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":1.5707964,\"Filled\":true},{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":2.3561945,\"Filled\":true},{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":3.1415927,\"Filled\":true},{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":3.7524579,\"Filled\":true},{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":4.7996554,\"Filled\":true},{\"Name\":\"Protean\",\"type\":3,\"refY\":7.16,\"radius\":0.0,\"color\":1275002882,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":5.497787,\"Filled\":true},{\"Name\":\"Hint\",\"type\":1,\"offX\":-0.5,\"radius\":0.0,\"color\":16711931,\"overlayBGColor\":2936012800,\"overlayTextColor\":4294967295,\"overlayVOffset\":0.8,\"overlayFScale\":2.0,\"thicc\":0.0,\"overlayText\":\"8人分散\",\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true}]}", out _); + + Controller.TryRegisterLayoutFromCode("Pairs", "~Lv2~{\"Name\":\"P12S Pairs\",\"Group\":\"P12S\",\"ZoneLockH\":[1154],\"ElementsL\":[{\"Name\":\"Pair\",\"type\":3,\"refX\":-0.5,\"refY\":7.16,\"offX\":-0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"Filled\":true},{\"Name\":\"Pair\",\"type\":3,\"refX\":0.5,\"refY\":7.16,\"offX\":0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"Filled\":true},{\"Name\":\"Pair\",\"type\":3,\"refX\":-0.5,\"refY\":7.16,\"offX\":-0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":1.5707964,\"Filled\":true},{\"Name\":\"Pair\",\"type\":3,\"refX\":0.5,\"refY\":7.16,\"offX\":0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":1.5707964,\"Filled\":true},{\"Name\":\"Pair\",\"type\":3,\"refX\":0.5,\"refY\":7.16,\"offX\":0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":3.1415927,\"Filled\":true},{\"Name\":\"Pair\",\"type\":3,\"refX\":-0.5,\"refY\":7.16,\"offX\":-0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":3.1415927,\"Filled\":true},{\"Name\":\"Pair\",\"type\":3,\"refX\":0.5,\"refY\":7.16,\"offX\":0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":4.712389,\"Filled\":true},{\"Name\":\"Pair\",\"type\":3,\"refX\":-0.5,\"refY\":7.16,\"offX\":-0.5,\"radius\":0.0,\"color\":2113863931,\"thicc\":7.0,\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true,\"AdditionalRotation\":4.712389,\"Filled\":true},{\"Name\":\"Hint\",\"type\":1,\"offX\":-0.5,\"radius\":0.0,\"color\":16711931,\"overlayBGColor\":2936012800,\"overlayTextColor\":4278255571,\"overlayVOffset\":0.8,\"overlayFScale\":2.0,\"thicc\":0.0,\"overlayText\":\"2人分摊\",\"FillStep\":0.25,\"refActorComparisonType\":2,\"includeRotation\":true}]}", out _); + + Controller.TryRegisterLayoutFromCode("DebuffAOESelf", "~Lv2~{\"Enabled\":false,\"Name\":\"P12S Spread AOE\",\"Group\":\"P12S\",\"ZoneLockH\":[1154],\"ElementsL\":[{\"Name\":\"self1\",\"type\":1,\"radius\":7.0,\"color\":603914262,\"refActorType\":1,\"Filled\":true},{\"Name\":\"self2\",\"type\":1,\"radius\":7.0,\"color\":4294967295,\"thicc\":5.0,\"refActorType\":1},{\"Name\":\"self3\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"refActorType\":1},{\"Name\":\"self 3s\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayVOffset\":0.8,\"overlayText\":\"3秒\",\"refActorUseCastTime\":true,\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMin\":2.0,\"refActorBuffTimeMax\":3.0,\"refActorType\":1},{\"Name\":\"self 2s\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayVOffset\":0.8,\"overlayText\":\"2秒\",\"refActorUseCastTime\":true,\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMin\":1.0,\"refActorBuffTimeMax\":2.0,\"refActorType\":1},{\"Name\":\"self 1s\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayVOffset\":0.8,\"overlayText\":\"1秒\",\"refActorUseCastTime\":true,\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMax\":1.0,\"refActorType\":1},{\"Name\":\"party1\",\"type\":1,\"radius\":7.0,\"color\":603914262,\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorComparisonType\":5},{\"Name\":\"party2\",\"type\":1,\"radius\":7.0,\"color\":4294967295,\"thicc\":5.0,\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorComparisonType\":5},{\"Name\":\"party3\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorComparisonType\":5},{\"Name\":\"party 3s\",\"type\":1,\"radius\":7.0,\"color\":603914262,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayText\":\"3秒\",\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMin\":2.0,\"refActorBuffTimeMax\":3.0,\"refActorComparisonType\":5},{\"Name\":\"party 2s\",\"type\":1,\"radius\":7.0,\"color\":603914262,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayText\":\"2秒\",\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMin\":1.0,\"refActorBuffTimeMax\":2.0,\"refActorComparisonType\":5},{\"Name\":\"party 1s\",\"type\":1,\"radius\":7.0,\"color\":603914262,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayText\":\"1秒\",\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMax\":1.0,\"refActorComparisonType\":5}]}", out _); + + Controller.TryRegisterLayoutFromCode("DebuffAOEOther", "~Lv2~{\"Enabled\":false,\"Name\":\"P12S Spread AOE other\",\"Group\":\"P12S\",\"ZoneLockH\":[1154],\"ElementsL\":[{\"Name\":\"party1\",\"type\":1,\"radius\":7.0,\"color\":603914262,\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMax\":3.0,\"refActorComparisonType\":5},{\"Name\":\"party2\",\"type\":1,\"radius\":7.0,\"color\":4294967295,\"thicc\":5.0,\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMax\":3.0,\"refActorComparisonType\":5},{\"Name\":\"party3\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMax\":3.0,\"refActorComparisonType\":5},{\"Name\":\"party 3s\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayText\":\"3秒\",\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMin\":2.0,\"refActorBuffTimeMax\":3.0,\"refActorComparisonType\":5},{\"Name\":\"party 2s\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayText\":\"2秒\",\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMin\":1.0,\"refActorBuffTimeMax\":2.0,\"refActorComparisonType\":5},{\"Name\":\"party 1s\",\"type\":1,\"radius\":7.0,\"color\":4294919424,\"overlayBGColor\":4278190080,\"overlayTextColor\":4294967295,\"overlayText\":\"1秒\",\"refActorPlaceholder\":[\"<2>\",\"<3>\",\"<4>\",\"<5>\",\"<6>\",\"<7>\",\"<8>\"],\"refActorRequireBuff\":true,\"refActorBuffId\":[3578],\"refActorUseBuffTime\":true,\"refActorBuffTimeMax\":1.0,\"refActorComparisonType\":5}]}", out _); + } + + Dictionary> Attachments = new(); + + public override void OnTetherCreate(uint source, uint target, uint data2, uint data3, uint data5) + { + if (!Attachments.ContainsKey(target)) Attachments.Add(target, new()); + //DuoLog.Information($"Attached {source} to {target}"); + Attachments[target].Add(source); + } + + public override void OnUpdate() + { + var list = FindNextMechanic().ToList(); + list.RemoveAll(x => x.dist < 0.1f); + if(list.Count > 0) + { + var toDisplay = list.Where(x => Math.Abs(x.dist - list[0].dist) < 0.5f).Select(x => (x.type, x.obj, x.dist)).ToList(); + if(list.TryGetFirst(x => x.type.EqualsAny(Spheres.Pairs, Spheres.Protean), out var l)) + { + toDisplay.Add((l.type, l.obj, l.dist)); + } + Display(toDisplay); + } + else + { + Display(); + } + if(Controller.TryGetLayoutByName("DebuffAOESelf", out var self) && Controller.TryGetLayoutByName("DebuffAOEOther", out var other)) + { + if (C.EnableAOEChecking) + { + if (Svc.ClientState.LocalPlayer.StatusList.Any(x => x.StatusId == AOEDebuff && x.RemainingTime < 3.5f)) + { + self.Enabled = true; + other.Enabled = false; + } + else + { + self.Enabled = false; + other.Enabled = true; + } + } + else + { + self.Enabled = false; + other.Enabled = false; + } + } + } + + void Display(IEnumerable<(Spheres type, BattleNpc obj, float dist)>? values = null) + { + int aoe = 0; + int donut = 0; + Controller.GetRegisteredElements().Each(x => x.Value.Enabled = false); + Controller.GetRegisteredLayouts().Each(x => x.Value.Enabled = false); + if (values != null) + { + foreach (var x in values) + { + if (x.type == Spheres.AOEBall) + { + aoe++; + if (Controller.TryGetElementByName($"AOEBall{aoe}", out var e)) + { + e.Enabled = true; + e.refActorObjectID = x.obj.ObjectId; + //e.color = TransformColorBasedOnDistance(e.color, x.dist); + e.color = C.AoeColor.ToUint(); + } + if (Controller.TryGetElementByName($"AOEBall{aoe}1", out var e1)) + { + e1.Enabled = true; + e1.refActorObjectID = x.obj.ObjectId; + //e1.color = TransformColorBasedOnDistance(e.color, x.dist); + //e1.color = C.AoeColor.ToUint(); + } + if (Controller.TryGetElementByName($"AOEBall{aoe}2", out var e2)) + { + e2.Enabled = true; + e2.refActorObjectID = x.obj.ObjectId; + //e2.color = TransformColorBasedOnDistance(e.color, x.dist); + //e2.color = C.AoeColor.ToUint(); + } + } + else if (x.type == Spheres.Donut) + { + donut++; + if (Controller.TryGetElementByName($"Donut{donut}", out var e)) + { + e.Enabled = true; + e.refActorObjectID = x.obj.ObjectId; + e.Donut = C.DonutRadius; + e.color = C.DonutColor.ToUint(); + //e.color = TransformColorBasedOnDistance(e.color, x.dist); + } + if (Controller.TryGetElementByName($"Donut{donut}1", out var e1)) + { + e1.Enabled = true; + e1.refActorObjectID = x.obj.ObjectId; + e1.Donut = C.DonutRadius; + //e1.color = C.DonutColor.ToUint(); + //e.color = TransformColorBasedOnDistance(e.color, x.dist); + } + if (Controller.TryGetElementByName($"Donut{donut}2", out var e2)) + { + e2.Enabled = true; + e2.refActorObjectID = x.obj.ObjectId; + e2.Donut = C.DonutRadius; + //e2.color = C.DonutColor.ToUint(); + //e.color = TransformColorBasedOnDistance(e.color, x.dist); + } + } + else + { + if (Controller.TryGetLayoutByName($"{x.type}", out var e)) + { + e.Enabled = true; + e.ElementsL.Each(z => z.refActorObjectID = x.obj.ObjectId); + if (x.type == Spheres.Protean) e.ElementsL.Each(z => z.color = C.ProteanLineColor.ToUint()); + if (x.type == Spheres.Pairs) e.ElementsL.Each(z => z.color = C.PairLineColor.ToUint()); + //e.ElementsL.Each(z => z.color = TransformColorBasedOnDistance(z.color, x.dist)); + } + } + } + } + } + + uint TransformColorBasedOnDistance(uint col, float distance) + { + distance.ValidateRange(2, 20); + distance -= 2f; + var alpha = (1 - distance / 18) * 0.3f + 0.5f; + return (col.ToVector4() with { W = alpha }).ToUint(); + } + + IEnumerable<(BattleNpc obj, Spheres type, float dist)> FindNextMechanic() + { + List<(BattleNpc obj, Spheres type, float dist)> objs = new(); + foreach(var x in Svc.Objects.Where(z => z is BattleNpc b && b.IsCharacterVisible()).Cast()) + { + if(Enum.GetValues().Contains((Spheres)x.DataId) && x.DataId != (uint)Spheres.Mastersphere) + { + var master = GetMasterSphereForObject(x); + if(master != null) + { + objs.Add((master, (Spheres)x.DataId, Vector3.Distance(master.Position, x.Position))); + } + } + } + return objs.OrderBy(x => x.dist); + } + + BattleNpc? GetMasterSphereForObject(BattleNpc obj) + { + foreach(var x in Attachments) + { + if (x.Value.Contains(obj.ObjectId) && x.Key.GetObject() is BattleNpc b && b.IsCharacterVisible()) + { + return b; + } + } + return null; + } + + public override void OnMessage(string Message) + { + if (Message.ContainsAny("(12377>33498)", "(12377>34554)", "(12377>34555)")) + { + Attachments.Clear(); + } + } + + public unsafe static Vector4 Vector4FromABGR(uint col) + { + byte* bytes = (byte*)&col; + return new Vector4((float)bytes[0] / 255f, (float)bytes[1] / 255f, (float)bytes[2] / 255f, (float)bytes[3] / 255f); + } + + public class Config : IEzConfig + { + public float DonutRadius = 25.0f; + public bool EnableAOEChecking = true; + public Vector4 ProteanLineColor = Vector4FromABGR(1275002882); + public Vector4 PairLineColor = Vector4FromABGR(2113863931); + public Vector4 AoeColor = Vector4FromABGR(1275012352); + public Vector4 DonutColor = Vector4FromABGR(1107248384); + //public Vector4 AssistColorSelf = Vector4FromABGR(1258356223); + //public Vector4 AssistColorOther = Vector4FromABGR(3355508706); + } + + Config C => Controller.GetConfig(); + + public override void OnSettingsDraw() + { + ImGuiEx.TextV("月环半径:"); // Dount radius: + ImGui.SameLine(); + ImGui.SetNextItemWidth(150f); + ImGui.DragFloat("", ref C.DonutRadius.ValidateRange(5f, 50f), 0.1f, 5f, 30f); + ImGui.ColorEdit4("月环 颜色", ref C.DonutColor, ImGuiColorEditFlags.NoInputs); // Dount color + ImGui.ColorEdit4("AOE 颜色", ref C.AoeColor, ImGuiColorEditFlags.NoInputs); // AOE color + ImGui.ColorEdit4("22分摊 颜色", ref C.PairLineColor, ImGuiColorEditFlags.NoInputs); // Pair line color + ImGui.ColorEdit4("8人分散 颜色", ref C.ProteanLineColor, ImGuiColorEditFlags.NoInputs); // Protean line color + ImGui.Checkbox($"启用 天火刻印 debuff 提示", ref C.EnableAOEChecking); // Enable AOE debuff assist + /*ImGuiEx.Text($" "); + ImGui.SameLine(); + ImGui.ColorEdit4("Self color (filled)", ref C.AssistColorSelf, ImGuiColorEditFlags.NoInputs); + ImGui.SameLine(); + ImGui.ColorEdit4("Others (radius)", ref C.AssistColorOther, ImGuiColorEditFlags.NoInputs);*/ + + if (ImGui.CollapsingHeader("Debug")) + { + foreach(var x in Attachments) + { + ImGuiEx.Text($"{x.Key}({x.Key.GetObject()}) <- {x.Value.Select(z => $"{z}({z.GetObject()})").Print()}"); + } + ImGui.Separator(); + foreach (var x in FindNextMechanic()) + { + ImGuiEx.Text($"{x.type} = {x.dist}"); + } + } + } + } +} diff --git a/src/Endwalker/P12S Tethers 小怪连线机制.cs b/src/Endwalker/P12S Tethers 小怪连线机制.cs new file mode 100644 index 0000000..a30e7b7 --- /dev/null +++ b/src/Endwalker/P12S Tethers 小怪连线机制.cs @@ -0,0 +1,179 @@ +using ECommons; +using ECommons.Configuration; +using ECommons.DalamudServices; +using ECommons.MathHelpers; +using ImGuiNET; +using Splatoon.SplatoonScripting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace SplatoonScriptsOfficial.Duties.Endwalker +{ + public class P12S_Tethers_小怪连线机制 : SplatoonScript + { + public override HashSet ValidTerritories => new() { 1154 }; + public override Metadata? Metadata => new(2, "Zeffuro, RedAsteroid 修改+调色"); + + List _tethers = new(); + + public class TetherData + { + public uint Source {get;set;} + public uint Target {get;set;} + public uint Data3 {get;set;} // 233 / 250 = Light, 234 / 251 = Dark + } + + public override void OnSetup() + { + Controller.RegisterElementFromCode("T1", "{\"Name\":\"\",\"type\":3,\"Enabled\":false,\"refY\":45.0,\"radius\":3,\"color\":687668992,\"thicc\":3.0,\"refActorObjectID\":0,\"FillStep\":0.2,\"refActorComparisonType\":2,\"includeRotation\":true}"); + Controller.RegisterElementFromCode("T2", "{\"Name\":\"\",\"type\":3,\"Enabled\":false,\"refY\":45.0,\"radius\":3,\"color\":687668992,\"thicc\":3.0,\"refActorObjectID\":0,\"FillStep\":0.2,\"refActorComparisonType\":2,\"includeRotation\":true}"); + Controller.RegisterElementFromCode("T3", "{\"Name\":\"\",\"type\":3,\"Enabled\":false,\"refY\":45.0,\"radius\":3,\"color\":687668992,\"thicc\":3.0,\"refActorObjectID\":0,\"FillStep\":0.2,\"refActorComparisonType\":2,\"includeRotation\":true}"); + Controller.RegisterElementFromCode("T4", "{\"Name\":\"\",\"type\":3,\"Enabled\":false,\"refY\":45.0,\"radius\":3,\"color\":687668992,\"thicc\":3.0,\"refActorObjectID\":0,\"FillStep\":0.2,\"refActorComparisonType\":2,\"includeRotation\":true}"); + } + + public override void OnUpdate() + { + ToggleLayouts(false); + if (_tethers.Count() == 0) return; + ToggleLayouts(true); + var i = 1; + foreach (var tether in _tethers) + { + if(tether.Source.TryGetObject(out var source) && tether.Target.TryGetObject(out var target) && Controller.TryGetElementByName($"T{i++}", out var e)) + { + e.color = GetConfigTetherColor(tether.Data3, i); + e.refActorObjectID = tether.Source; + e.AdditionalRotation = GetRelativeAngle(source.Position.ToVector2(), target.Position.ToVector2()) + source.Rotation; + } + } + } + + public override void OnTetherCreate(uint source, uint target, uint data2, uint data3, uint data5) + { + if(Svc.Objects.Any(x => x.DataId == 16172)) + { + if(source.TryGetObject(out var sourceObject)){ + + //PluginLog.Information($"{sourceObject.DataId} Data2: {data2} Data3: {data3} Data5:{data5}"); + if(sourceObject.DataId != 16172) return; + if(_tethers.Exists(tether => tether.Target == target)){ + _tethers = _tethers.Where(tether => tether.Target != target).ToList(); + } + _tethers.Add(new TetherData{Source = source, Target = target, Data3 = data3}); + } + } + } + + public override void OnTetherRemoval(uint source, uint data2, uint data3, uint data5) + { + //PluginLog.Information($"{source} Data2: {data2} Data3: {data3} Data5:{data5}"); + _tethers = _tethers.Where(tether => tether.Source != source).ToList(); + } + + static float GetRelativeAngle(Vector2 origin, Vector2 target) + { + var vector2 = target - origin; + var vector1 = new Vector2(0, 1); + return MathF.Atan2(vector2.Y, vector2.X) - MathF.Atan2(vector1.Y, vector1.X); + } + + public uint GetConfigTetherColor(uint data3, int i) + { + switch(C.ColorMode){ + case 0: // Dark and Light + return (data3 == 233 || data3 == 250) ? C.LightTetherColor.ToUint() : C.DarkTetherColor.ToUint(); + break; + case 1: // Dark and Light + Stretched + if(data3 == 233 || data3 == 234) + { + return data3 == 233 ? C.LightTetherColor.ToUint() : C.DarkTetherColor.ToUint(); + break; + }else{ + return data3 == 250 ? C.LightTetherStretchedColor.ToUint() : C.DarkTetherStretchedColor.ToUint(); + break; + } + break; + case 2: // Four different tether colors + if(i == 1) return C.T1Color.ToUint(); + if(i == 2) return C.T2Color.ToUint(); + if(i == 3) return C.T3Color.ToUint(); + if(i == 4) return C.T4Color.ToUint(); + break; + default: + return C.LightTetherColor.ToUint(); + } + return C.LightTetherColor.ToUint(); + } + + + void ToggleLayouts(bool enabled) + { + Controller.GetRegisteredElements().Each(x => x.Value.Enabled = enabled); + Controller.GetRegisteredLayouts().Each(x => x.Value.Enabled = enabled); + } + + public unsafe static Vector4 Vector4FromABGR(uint col) + { + byte* bytes = (byte*)&col; + return new Vector4((float)bytes[0] / 255f, (float)bytes[1] / 255f, (float)bytes[2] / 255f, (float)bytes[3] / 255f); + } + + public class Config : IEzConfig + { + public int ColorMode = 0; + + public Vector4 LightTetherColor = Vector4FromABGR(598867950); + public Vector4 DarkTetherColor = Vector4FromABGR(603933696); + + public Vector4 LightTetherStretchedColor = Vector4FromABGR(599982066); + public Vector4 DarkTetherStretchedColor = Vector4FromABGR(603933696); + + public Vector4 T1Color = Vector4FromABGR(0xC6FF0000); + public Vector4 T2Color = Vector4FromABGR(0xC600FF00); + public Vector4 T3Color = Vector4FromABGR(0xC60000FF); + public Vector4 T4Color = Vector4FromABGR(0xC6FFFFFF); + } + + Config C => Controller.GetConfig(); + + public override void OnSettingsDraw() + { + ImGui.SetNextItemWidth(150f); + ImGui.Combo("颜色模式##Color Mode", ref C.ColorMode, new string[] {"光/暗", "光/暗, 是否拉直", "4 种不同颜色的线"}, 3); + + if(C.ColorMode < 2){ + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("暗连线 颜色", ref C.DarkTetherColor, ImGuiColorEditFlags.NoInputs); // Dark tether color + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("光连线 颜色", ref C.LightTetherColor, ImGuiColorEditFlags.NoInputs); // Light tether color + } + + if(C.ColorMode == 1){ + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("暗连线(拉直) 颜色", ref C.DarkTetherStretchedColor, ImGuiColorEditFlags.NoInputs); // Dark tether stretched color + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("光连线(拉直) 颜色", ref C.LightTetherStretchedColor, ImGuiColorEditFlags.NoInputs); // Light tether stretched color + } + + if(C.ColorMode == 2){ + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("1 号线 颜色", ref C.T1Color, ImGuiColorEditFlags.NoInputs); // Tether 1 color + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("2 号线 颜色", ref C.T2Color, ImGuiColorEditFlags.NoInputs); // Tether 2 color + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("3 号线 颜色", ref C.T3Color, ImGuiColorEditFlags.NoInputs); // Tether 3 color + ImGui.SetNextItemWidth(150f); + ImGui.ColorEdit4("4 号线 颜色", ref C.T4Color, ImGuiColorEditFlags.NoInputs); // Tether 4 color + } + /* + if (ImGui.CollapsingHeader("Debug")) + { + ImGui.Text($"{Tethers.Count()}"); + + } + */ + } + } +} \ No newline at end of file diff --git a/src/Endwalker/P12S Wing Cleaves 三魂一体半场刀.cs b/src/Endwalker/P12S Wing Cleaves 三魂一体半场刀.cs new file mode 100644 index 0000000..f4bb649 --- /dev/null +++ b/src/Endwalker/P12S Wing Cleaves 三魂一体半场刀.cs @@ -0,0 +1,196 @@ +using Dalamud.Game.ClientState.Objects.Types; +using ECommons; +using ECommons.Configuration; +using ECommons.DalamudServices; +using ECommons.GameFunctions; +using ECommons.Hooks; +using ECommons.Hooks.ActionEffectTypes; +using ECommons.ImGuiMethods; +using ECommons.MathHelpers; +using ImGuiNET; +using Splatoon; +using Splatoon.SplatoonScripting; +using Splatoon.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; + +namespace SplatoonScriptsOfficial.Duties.Endwalker +{ + public class P12S_Wing_Cleaves_三魂一体半场刀 : SplatoonScript + { + public override HashSet ValidTerritories => new() { 1153, 1154 }; + public override Metadata? Metadata => new(5, "NightmareXIV, RedAsteroid 修改+调色"); + Queue Cleaves = new(); + bool isSpin = false; + Vector3 firstPos; + float BaseRotation = 0; + + const uint AthenaNameId = 12377; + readonly uint[] Casts = new uint[] { 33473, 33474, 33475, 33476, 33477, 33478, 33505, 33506, 33507, 33508, 33509, 33510, 33511, 33512, 33513, 33514, 33515, 33516 }; + + BattleNpc? Athena => Svc.Objects.FirstOrDefault(x => x is BattleNpc b && b.NameId == AthenaNameId && b.IsTargetable()) as BattleNpc; + Vector2 Center = new(100, 100); + bool IsSavage => Svc.ClientState.TerritoryType == 1154; + + public override void OnSetup() + { + Controller.RegisterElementFromCode("Indicator", "{\"Name\":\"Indicator\",\"type\":5,\"Enabled\":false,\"refX\":100.0,\"refY\":100.0,\"radius\":30.0,\"coneAngleMax\":180,\"refActorComparisonType\":3,\"includeRotation\":true,\"Filled\":true}"); + Controller.RegisterElementFromCode("Line", "{\"Name\":\"\",\"type\":2,\"radius\":0.0,\"thicc\":6.0}"); + } + + public override void OnEnable() + { + ActionEffect.ActionEffectEvent += ActionEffect_ActionEffectEvent; + } + + private void ActionEffect_ActionEffectEvent(ActionEffectSet set) + { + if (set.Action == null) return; + if (Casts.Contains(set.Action.RowId)) + { + ////DuoLog.Information($"Cast"); + GenericHelpers.Safe(() => + { + Cleaves.Dequeue(); + Hide(); + if (Cleaves.Count > 0) + { + Process(Cleaves.Peek()); + //DuoLog.Information($"-> {Cleaves.Peek()}"); + } + }); + } + } + + public override void OnDisable() + { + ActionEffect.ActionEffectEvent -= ActionEffect_ActionEffectEvent; + } + + public override void OnVFXSpawn(uint target, string vfxPath) + { + var obj = target.GetObject(); + if(obj?.DataId == 16229 && vfxPath.Contains("vfx/lockon/eff/m0829")) + { + if (Cleaves.Count == 0) + { + firstPos = obj.Position; + BaseRotation = 360 - Athena.Rotation.RadToDeg(); + //DuoLog.Information($"Athena's rotation: {BaseRotation}"); + } + var angle = (MathHelper.GetRelativeAngle(obj.Position, Athena.Position) + 360f - BaseRotation) % 360f; + //DuoLog.Information($"Angle: {angle}"); + if (angle.InRange(180, 360)) + { + if (Cleaves.Count == 1 && firstPos.Y < obj.Position.Y && IsSavage) + { + Cleaves.Enqueue("Right"); + } + else + { + Cleaves.Enqueue("Left"); + } + } + else + { + if (Cleaves.Count == 1 && firstPos.Y < obj.Position.Y) + { + Cleaves.Enqueue("Left"); + } + else + { + Cleaves.Enqueue("Right"); + } + } + if(Cleaves.Count == 1) + { + //DuoLog.Information($"{Cleaves.Peek()}"); + Hide(); + Process(Cleaves.Peek()); + } + } + } + + void Hide() + { + Controller.GetElementByName("Indicator").Enabled = false; + Controller.GetElementByName("Line").Enabled = false; + } + + void Process(string dir) + { + if(Controller.TryGetElementByName("Indicator", out var e) && Controller.TryGetElementByName("Line", out var l)) + { + var apos = Athena.Position; + var arot = Athena.Rotation; + e.SetRefPosition(apos); + e.Enabled = true; + if(dir == "Left") + { + e.coneAngleMin = (int)(BaseRotation - 180f) + 1; + e.coneAngleMax = (int)BaseRotation - 1; + } + else + { + e.coneAngleMin = (int)BaseRotation + 1; + e.coneAngleMax = (int)(BaseRotation + 180) - 1; + } + l.Enabled = true; + var fpos = Static.GetPositionXZY(Athena); + SetPos(l, Static.RotatePoint(fpos.X, fpos.Y, -arot, fpos with { Y = fpos.Y + 30 }), Static.RotatePoint(fpos.X, fpos.Y, -arot + 180f.DegreesToRadians(), fpos with { Y = fpos.Y + 30 })); + } + } + + void SetPos(Element e, Vector3 RefPosition, Vector3 OffPosition) + { + e.refX = RefPosition.X; + e.refY = RefPosition.Y; + e.refZ = RefPosition.Z; + e.offX = OffPosition.X; + e.offY = OffPosition.Y; + e.offZ = OffPosition.Z; + } + + public override void OnUpdate() + { + if (Cleaves.Count > 0) + { + var wings = Svc.Objects.Where(x => x.DataId == 16229); + if (!wings.Any()) + { + Cleaves.Clear(); + Hide(); + } + else + { + if(Controller.TryGetElementByName("Line", out var e) && Controller.TryGetElementByName("Indicator", out var i)) + { + e.color = GradientColor.Get(C.Col1, C.Col2).ToUint(); + i.color = e.color; + } + } + } + } + + Config C => Controller.GetConfig(); + public class Config: IEzConfig + { + public Vector4 Col1 = Vector4FromRGBA(0x0073FFAF); + public Vector4 Col2 = Vector4FromRGBA(0x0004FF64); + } + + public override void OnSettingsDraw() + { + ImGui.ColorEdit4("颜色 1", ref C.Col1, ImGuiColorEditFlags.NoInputs); // Color 1 + ImGui.ColorEdit4("颜色 2", ref C.Col2, ImGuiColorEditFlags.NoInputs); // Color 2 + } + + public unsafe static Vector4 Vector4FromRGBA(uint col) + { + byte* bytes = (byte*)&col; + return new Vector4((float)bytes[3] / 255f, (float)bytes[2] / 255f, (float)bytes[1] / 255f, (float)bytes[0] / 255f); + } + } +}