From 73629dabc859fba99e35e0f42f43347d21b17e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B2=A2=E5=93=8D=E4=B9=9F?= <72963826+Hibiya615@users.noreply.github.com> Date: Sun, 3 Aug 2025 04:31:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=B8=80=E7=82=B9=E7=BB=9D?= =?UTF-8?q?=E4=BC=8A=E7=94=B8=E5=B0=8F=E5=B7=A5=E5=85=B7=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 07-Dawntrail/FRU_DLC.cs | 384 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 07-Dawntrail/FRU_DLC.cs diff --git a/07-Dawntrail/FRU_DLC.cs b/07-Dawntrail/FRU_DLC.cs new file mode 100644 index 0000000..3cb0def --- /dev/null +++ b/07-Dawntrail/FRU_DLC.cs @@ -0,0 +1,384 @@ +using System; +using System.ComponentModel; +using System.Linq; +using System.Numerics; +using System.Collections.Generic; +// using Dalamud.Game.ClientState.Objects.Subkinds; +// using Dalamud.Game.ClientState.Objects.Types; +using Newtonsoft.Json; +using Dalamud.Utility.Numerics; +using KodakkuAssist.Script; +using KodakkuAssist.Module.GameEvent; +using KodakkuAssist.Module.Draw; +using KodakkuAssist.Data; +using KodakkuAssist.Extensions; +using ECommons; +using ECommons.DalamudServices; +using ECommons.GameFunctions; +using ECommons.MathHelpers; +using System.Threading.Tasks; + +namespace FRU_DLC; + +[ScriptType(guid: "981e39b5-ea99-4b85-a4b1-0e698d4c4036", name: "FRU_DLC [光暗未来绝境战_额外补充]", territorys: [1238], + version: "0.0.0.1", author: "Tetora", note: noteStr)] + +public class FRU_DLC +{ + const string noteStr = + """ + v0.0.0.1: + 光暗未来绝境战 额外补充部分 + 可以与灵视的与连桑的Patch同时使用,并无冲突部分 + """; + + #region 基础控制 + + [UserSetting("TTS开关(TTS请二选一开启)")] + public bool isTTS { get; set; } = false; + + [UserSetting("EdgeTTS开关(TTS请二选一开启)")] + public bool isEdgeTTS { get; set; } = true; + + [UserSetting("弹窗文本提示开关")] + public bool isText { get; set; } = true; + + [UserSetting("P4二运自动防击退 [Y字击退打法]")] + public bool isAutoAntiKnockback { get; set; } = false; + + [UserSetting("龙骑开荒小提示")] + public bool isDRG { get; set; } = false; + + [UserSetting("[龙骑] 光暴自动提前猛枪(踩塔前)")] + public bool isAutoLanceCharge { get; set; } = false; + + [UserSetting("开发者模式")] + public bool isDeveloper { get; set; } = false; + + #endregion + + #region 记录与转换 + + public enum FRU_Phase + { + Init, // 初始 + Fatebreaker, // P1 + FallOfFaith, // P1 罪壤断(雷火线) + UsurperOfFrost, // P2 + LightRampant, // P2 光之失控 + OracleOfDarkness, // P3 + Les, // P4 + DarklitDragonsong, // P4一运 光与暗的龙诗 + CrystallizeTime, // P4二运 时间结晶 + Pandora, // P5 + } + + FRU_Phase phase = FRU_Phase.Init; + + // uint BurnishedGlory=0; + + public void Init(ScriptAccessory accessory) { + phase = FRU_Phase.Init; + } + + [ScriptMethod(name: "P1 开场转换(记录暴风破)", userControl: false, eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:regex:^4014[48]$"])] + public void P1开场转换(Event @event, ScriptAccessory accessory) + { + phase = phase switch + { + FRU_Phase.Init => FRU_Phase.Fatebreaker, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至开场"); + } + + [ScriptMethod(name: "P1 阶段转换 - 罪壤断", userControl: false, eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:40140"])] + public void P1罪壤断转换(Event @event, ScriptAccessory accessory) + { + phase = phase switch + { + FRU_Phase.Fatebreaker => FRU_Phase.FallOfFaith, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至雷火线"); + } + + [ScriptMethod(name: "P2 开场转换", userControl: false, eventType: EventTypeEnum.AddCombatant, eventCondition: ["DataId:17823"])] + public void P2开场转换(Event @event, ScriptAccessory accessory) + { + phase = phase switch + { + FRU_Phase.FallOfFaith => FRU_Phase.UsurperOfFrost, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至P2"); + } + + [ScriptMethod(name: "P2 阶段转换 - 光之失控", userControl: false, eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:40212"])] + public void P2光之失控转换(Event @event, ScriptAccessory accessory) + { + phase = phase switch + { + FRU_Phase.UsurperOfFrost => FRU_Phase.LightRampant, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至光暴"); + } + + [ScriptMethod(name: "P3 开场转换", userControl: false, eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:40226"])] + public void P3开场转换(Event @event, ScriptAccessory accessory) + { + phase = phase switch + { + FRU_Phase.LightRampant => FRU_Phase.OracleOfDarkness, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至P3"); + } + + [ScriptMethod(name: "P4 开场转换", userControl: false, eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:40246"])] + public void P4开场转换(Event @event, ScriptAccessory accessory) + { + // 注:P4的 [希瓦·米特隆] DataId为 [17833] 且圣龙出现时会再次生成一个 ,[暗之巫女] 为 [17835] ; [圣龙] [17834] [琳的幻影] [17844] [盖娅的幻影] [17845] + phase = phase switch + { + FRU_Phase.OracleOfDarkness => FRU_Phase.Les, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至P4"); + } + + [ScriptMethod(name: "P4 阶段转换 - 一运 [光与暗的龙诗]", userControl: false, eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:40301"])] + public void P4光暗龙诗转换(Event @event, ScriptAccessory accessory) + { + phase = phase switch + { + FRU_Phase.Les => FRU_Phase.DarklitDragonsong, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至P4一运[光与暗的龙诗]"); + } + + [ScriptMethod(name: "P4 阶段转换 - 二运 [时间结晶]", userControl: false, eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:40298"])] + public void P4时间结晶转换(Event @event, ScriptAccessory accessory) + { + phase = phase switch + { + FRU_Phase.DarklitDragonsong => FRU_Phase.CrystallizeTime, + }; + if(isDeveloper) accessory.Method.SendChat($"/e [虎のDebug]:阶段成功转换至P4二运[时间结晶]"); + } + + #endregion + + [ScriptMethod(name: "P2.5 严冬风暴(大圈)判定时间绘制", eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:40256"])] + public void 严冬风暴(Event @event, ScriptAccessory accessory) + { + var dp = accessory.Data.GetDefaultDrawProperties(); + dp.Name = $"严冬风暴{@event.SourceId()}"; + dp.Color = accessory.Data.DefaultDangerColor; + dp.Position = @event.EffectPosition(); + dp.Scale = new Vector2(7f); + dp.DestoryAt = 3000; + dp.ScaleMode = ScaleMode.ByTime; + accessory.Method.SendDraw(DrawModeEnum.Default, DrawTypeEnum.Circle, dp); + } + + [ScriptMethod(name: "严冬风暴销毁", eventType: EventTypeEnum.CancelAction, eventCondition: ["ActionId:40256"],userControl: false)] + public void 严冬风暴销毁(Event @event, ScriptAccessory accessory) + { + accessory.Method.RemoveDraw($"严冬风暴{@event.SourceId()}"); + } + + [ScriptMethod(name: "P4 盖娅出现横幅倒计时", eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:40186"])] + public async void P4AddGaia(Event @event, ScriptAccessory accessory) + { + if (isText)accessory.Method.TextInfo("盖娅即将出现,注意团辅时机", duration: 5300, true); + if (isTTS)accessory.Method.TTS("盖娅即将出现"); + if (isEdgeTTS)accessory.Method.EdgeTTS("盖娅即将出现"); + } + + #region 龙骑妙妙小工具 + + [ScriptMethod(name: "————龙骑妙妙小工具(此选项并无实际意义)————", eventType: EventTypeEnum.StartCasting, eventCondition: ["DataId:1"])] + public void 龙骑妙妙小工具(Event @event, ScriptAccessory accessory) { } + + [ScriptMethod(name: "P1 开场提示", eventType: EventTypeEnum.Chat, eventCondition: ["Message:距离战斗开始还有5秒!"])] + public async void FatebreakerStart(Event @event, ScriptAccessory accessory) + { + if (!isDRG) return; + await Task.Delay(3000); + if (isText)accessory.Method.TextInfo("1G高跳,2G连祷猛枪", duration: 7000, false); + if (isTTS)accessory.Method.TTS("1G高跳,2G连祷猛枪"); + if (isEdgeTTS)accessory.Method.EdgeTTS("1G高跳,2G连祷猛枪"); + } + + [ScriptMethod(name: "P1 雾龙上天前提示", eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:40168"])] + public void UtopianSkyEarly(Event @event, ScriptAccessory accessory) + { + if (!isDRG) return; + if (phase != FRU_Phase.Fatebreaker) return; + if (isText)accessory.Method.TextInfo("提前后跳,强化标枪代替龙4收尾", duration: 10000, false); + if (isTTS)accessory.Method.TTS("提前后跳,标枪收尾"); + if (isEdgeTTS)accessory.Method.EdgeTTS("提前后跳,标枪收尾"); + } + + [ScriptMethod(name: "P1 雾龙落地提示", eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:40167"])] + public void FatebreakerTargetable(Event @event, ScriptAccessory accessory) + { + if (!isDRG) return; + if (isText)accessory.Method.TextInfo("1G后牵制,2G高跳,延后猛枪蓝炮,打完身位排队", duration: 6000, true); + if (isTTS)accessory.Method.TTS("1G牵制,延后爆发"); + if (isEdgeTTS)accessory.Method.EdgeTTS("1G牵制,延后爆发"); + } + + [ScriptMethod(name: "P2 光之暴走 踩塔前猛枪提示(与自动猛枪)", eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:regex:^4022[01]$"])] + public void P2LanceCharge(Event @event, ScriptAccessory accessory) + { + if (!isDRG) return; + if (phase != FRU_Phase.LightRampant) return; + if (isText)accessory.Method.TextInfo("提前猛枪", duration: 5000, true); + if (isTTS)accessory.Method.TTS("提前猛枪"); + if (isEdgeTTS)accessory.Method.EdgeTTS("提前猛枪"); + if (isAutoLanceCharge) accessory.Method.SendChat($"/ac 猛枪"); + if (isAutoLanceCharge) accessory.Method.SendChat($"/e [DEBUG] 龙骑小工具:已尝试自动使用猛枪"); + } + + [ScriptMethod(name: "P2.5 龙骑时间轴小抄", eventType: EventTypeEnum.AddCombatant, eventCondition: ["DataId:17829"])] + public async void P25DRGTimeLine(Event @event, ScriptAccessory accessory) + { + if (!isDRG) return; + if (isText)accessory.Method.TextInfo("[1G] 连祷爆发药 [2G] 高跳 [3G] 疾跑猛枪 \n [4G] 龙炎冲龙剑 [5G] 后撤放大圈 [6G] 蓝炮好了单插 \n [7G] 幻象冲+坠星冲 ", duration: 17500, false); + + await Task.Delay(8200); + if (isTTS)accessory.Method.TTS("后撤引导大圈"); + if (isEdgeTTS)accessory.Method.EdgeTTS("后撤引导大圈"); + } + + [ScriptMethod(name: "P4 开场提示", eventType: EventTypeEnum.AddCombatant, eventCondition: ["DataId:17841"])] + public async void P4AddFragmentOfFate(Event @event, ScriptAccessory accessory) + { + if (!isDRG) return; + if (isText)accessory.Method.TextInfo("躲完天光轮回1G后,爆发药+猛枪 \n 盖娅出现开团辅", duration: 6000, false); + if (isTTS)accessory.Method.TTS("注意爆发时机"); + if (isEdgeTTS)accessory.Method.EdgeTTS("注意爆发时机"); + } + + [ScriptMethod(name: "P4 天光轮回猛枪提示", eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:40237"])] + public async void P4AkhRhai(Event @event, ScriptAccessory accessory) + { + if (!isDRG) return; + if (isTTS)accessory.Method.TTS("爆发药加猛枪"); + if (isEdgeTTS)accessory.Method.EdgeTTS("爆发药加猛枪"); + } + + #endregion + +} + +public static class EventExtensions +{ + private static bool ParseHexId(string? idStr, out uint id) + { + id = 0; + if (string.IsNullOrEmpty(idStr)) return false; + try + { + var idStr2 = idStr.Replace("0x", ""); + id = uint.Parse(idStr2, System.Globalization.NumberStyles.HexNumber); + return true; + } + catch (Exception) + { + return false; + } + } + + public static uint ActionId(this Event @event) + { + return JsonConvert.DeserializeObject(@event["ActionId"]); + } + + public static uint SourceId(this Event @event) + { + return ParseHexId(@event["SourceId"], out var id) ? id : 0; + } + + public static uint SourceDataId(this Event @event) + { + return JsonConvert.DeserializeObject(@event["SourceDataId"]); + } + + public static uint Command(this Event @event) + { + return ParseHexId(@event["Command"], out var cid) ? cid : 0; + } + + public static uint DurationMilliseconds(this Event @event) + { + return JsonConvert.DeserializeObject(@event["DurationMilliseconds"]); + } + + public static float SourceRotation(this Event @event) + { + return JsonConvert.DeserializeObject(@event["SourceRotation"]); + } + + public static float TargetRotation(this Event @event) + { + return JsonConvert.DeserializeObject(@event["TargetRotation"]); + } + + public static byte Index(this Event @event) + { + return (byte)(ParseHexId(@event["Index"], out var index) ? index : 0); + } + + public static uint State(this Event @event) + { + return ParseHexId(@event["State"], out var state) ? state : 0; + } + + public static string SourceName(this Event @event) + { + return @event["SourceName"]; + } + + public static string TargetName(this Event @event) + { + return @event["TargetName"]; + } + + public static uint TargetId(this Event @event) + { + return ParseHexId(@event["TargetId"], out var id) ? id : 0; + } + + public static Vector3 SourcePosition(this Event @event) + { + return JsonConvert.DeserializeObject(@event["SourcePosition"]); + } + + public static Vector3 TargetPosition(this Event @event) + { + return JsonConvert.DeserializeObject(@event["TargetPosition"]); + } + + public static Vector3 EffectPosition(this Event @event) + { + return JsonConvert.DeserializeObject(@event["EffectPosition"]); + } + + public static uint DirectorId(this Event @event) + { + return ParseHexId(@event["DirectorId"], out var id) ? id : 0; + } + + public static uint StatusId(this Event @event) + { + return JsonConvert.DeserializeObject(@event["StatusId"]); + } + + public static uint StackCount(this Event @event) + { + return JsonConvert.DeserializeObject(@event["StackCount"]); + } + + public static uint Param(this Event @event) + { + return JsonConvert.DeserializeObject(@event["Param"]); + } +} \ No newline at end of file