Repository navigation
Expand file tree
/
Copy pathSimpleScript.cs
More file actions
350 lines (314 loc) · 14.6 KB
/
Copy pathSimpleScript.cs
File metadata and controls
350 lines (314 loc) · 14.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
using System;
using System.Numerics;
using System.Reflection.Metadata;
using System.Threading.Tasks;
using System.Windows.Forms;
using Dalamud.Utility.Numerics;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using KodakkuAssist.Extensions;
using KodakkuAssist.Module.Draw;
using KodakkuAssist.Module.GameEvent;
using KodakkuAssist.Module.GameEvent.Struct;
using KodakkuAssist.Script;
using static FFXIVClientStructs.FFXIV.Component.GUI.AtkTimer.Delegates;
namespace MyScriptNamespace
{
/// <summary>
/// name and version affect the script name and version number displayed in the user interface.
/// territorys specifies the regions where this trigger is effective. If left empty, it will be effective in all regions.
/// Classes with the same GUID will be considered the same trigger. Please ensure your GUID is unique and does not conflict with others.
/// </summary>
[ScriptType(name: "SimpleScript", territorys: [179, 979], guid: "d3b6a9b4-1e0e-4e0c-b7c7-ff1fce0e6cf2", version: "0.0.0.3", author: "Karlin", note: noteStr, updateInfo: updateInfoStr)]
public class SimpleScript : IDisposable
{
const string noteStr =
"""
这是一个提示文本.
他有多行显示.
请在这里放置你的提示文本
""";
const string updateInfoStr =
"""
这里是更新信息.
他有多行显示.
请在这里放置你的更新信息
""";
/// <summary>
/// note will be displayed to the user as a tooltip.
/// </summary>
[UserSetting(note: "This is a test Property")]
public int prop1 { get; set; } = 1;
[UserSetting("Another Test Property")]
public bool prop2 { get; set; } = false;
[UserSetting("UserColorSetting")]
public ScriptColor color { get; set; } = new();
[UserSetting("EnumSetting")]
public TestEnum enumSetting { get; set; }
int n = 0;
public enum TestEnum
{
First,
Second
}
/// <summary>
/// 时间轴范例,战斗中随事件同步推进
/// </summary>
[ScriptTimeline("时间轴范例")]
const string SampleTimeline = """
# ───────── 最小时间轴范例 ─────────
# 格式:<时间> <类型> <参数...>
# 时间 10.0 绝对秒 | +2.0 相对上一条
# 类型 info 提示 | sync 同步 | event 触发脚本 | jump 跳转
# info 裸文本即正文;带参数用 text=、level=、duration=、tts=
# sync eventName 必填,其余键是事件条件,window/timeout 单位秒
# event 参数会塞进事件属性,供 ScriptMethod 用 eventCondition 匹配
# jump targetTime 单位秒,写事件条件则为条件跳转
# 正文里的等号要写成 \=
0.0 info 时间轴开始
3.0 info level=important duration=5 tts=true 死刑,注意减伤
+2.0 info text=分散站位
10.0 sync eventName=StartCasting ActionId=133 window=2.5 timeout=2.5
12.0 event kind=adds
30.0 jump targetTime=0
""";
/// <summary>
/// 简体中文翻译,同时作为其它语言的对照原文
/// </summary>
[ScriptTimelineI18n(ScriptTimelineLang.ChineseSimplified)]
static readonly Dictionary<string, string> SampleTimelineI18n = new()
{
["时间轴开始"] = "时间轴开始",
["死刑,注意减伤"] = "死刑,注意减伤",
["分散站位"] = "分散站位",
};
[ScriptTimelineI18n(ScriptTimelineLang.ChineseTraditional)]
static readonly Dictionary<string, string> SampleTimelineI18n_ChineseTraditional = new()
{
["时间轴开始"] = "時間軸開始",
["死刑,注意减伤"] = "死刑,注意減傷",
["分散站位"] = "分散站位",
};
[ScriptTimelineI18n(ScriptTimelineLang.English)]
static readonly Dictionary<string, string> SampleTimelineI18n_English = new()
{
["时间轴开始"] = "Timeline start",
["死刑,注意减伤"] = "Tank buster, use mitigation",
["分散站位"] = "Spread out",
};
[ScriptTimelineI18n(ScriptTimelineLang.Japanese)]
static readonly Dictionary<string, string> SampleTimelineI18n_Japanese = new()
{
["时间轴开始"] = "タイムライン開始",
["死刑,注意减伤"] = "死刑、軽減を準備",
["分散站位"] = "散開",
};
/// <summary>
/// 时间轴 event 行触发的脚本方法
/// </summary>
[ScriptMethod(name: "时间轴事件", eventType: EventTypeEnum.TimeLineEvent, eventCondition: ["kind:adds"])]
public void OnTimelineEvent(Event @event, ScriptAccessory accessory)
{
accessory.Method.TTS($"时间轴事件 {@event["kind"]}");
}
/// <summary>
/// This method is called at the start of each battle reset.
/// If this method is not defined, the program will execute an empty method.
/// </summary>
public void Init(ScriptAccessory accessory)
{
n = 0;
}
/// <summary>
/// name is the name of the method as presented to the user.
/// eventType is the type of event that triggers this method.
/// eventCondition is an array of strings specifying the properties that the event must have,
/// in the format name:value,For specific details, please refer to the GameEvent of the plugin.
/// userControl set to false will make the method not be shown to the user
/// and cannot be disabled by the user.
/// Please note, the method will be executed asynchronously.
/// </summary>
/// <param name="event">The event instance that triggers this method.</param>
/// <param name="accessory">Pass the instances of methods and data that might be needed.</param>
[ScriptMethod(name: "Test StartCasting", eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:133"])]
public void PrintInfo(Event @event, ScriptAccessory accessory)
{
n++;
accessory.Method.SendChat($"/e {@event["SourceId"]} {n}-th use the Medica II");
accessory.Log.Debug($"Prop2 is {prop2}");
accessory.Log.Debug($"enum is {enumSetting}");
}
[ScriptMethod(eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:124"])]
public void DrawCircle(Event @event, ScriptAccessory accessory)
{
var sid = @event.SourceId;
var prop = accessory.Data.GetDefaultDrawProperties();
prop.Owner = accessory.Data.Me;
prop.DestoryAt = 10000;
prop.Color = accessory.Data.DefaultDangerColor;
prop.Scale = new(5);
prop.InnerScale = new(3);
var start = DateTime.Now;
var n = 0;
//accessory.Method.SendDraw(DrawModeEnum.Default, DrawTypeEnum.Donut, prop);
accessory.Method.SendDraw(DrawModeEnum.Default, DrawTypeEnum.Donut, prop, (dpc) =>
{
var elapsedSeconds = (float)(DateTime.Now - start).TotalSeconds;
float hue = (elapsedSeconds * 0.5f) % 1f;
dpc.Color = HueToRGB(hue);
if (elapsedSeconds > 2)
{
start = DateTime.Now;
n++;
dpc.Radian = MathF.PI / 4 * n;
}
dpc.Scale = new(3 + hue * 3);
});
}
[ScriptMethod(eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:999999"])]
public void TestTTS(Event @event, ScriptAccessory accessory)
{
accessory.Method.TTS($"黏黏{DateTime.Now:T}");
}
[ScriptMethod(name: "Test Suppress", eventType: EventTypeEnum.Waymark)]
public void TestSuppress(Event @event, ScriptAccessory accessory)
{
n++;
accessory.Log.Debug($"WayMark {n} {@event.EventTriggerSource}");
uint id = 0x40000001;
if (accessory.Data.EnmityList.TryGetValue(id, out var objs))
{
var firstId = objs[0];
}
}
[ScriptMethod(name: "Test Action", eventType: EventTypeEnum.Waymark)]
public void TestAction(Event @event, ScriptAccessory accessory)
{
accessory.Method.UseAction(accessory.Data.Me, 37010);
}
[ScriptMethod(name: "Test ActionLocation", eventType: EventTypeEnum.Waymark)]
public void TestActionLocation(Event @event, ScriptAccessory accessory)
{
//accessory.Method.UseActionLocation(new System.Numerics.Vector3(-750, -30, -560), 3569, 1);
}
[ScriptMethod(name: "Unconfigurable Method", eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:124"], userControl: false)]
public void UnconfigurableMethod(Event @event, ScriptAccessory accessory)
{
accessory.Log.Debug($"The unconfigurable method has been triggered.");
}
string guid = "";
[ScriptMethod(eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:37010"])]
public void TestRunOnFrame(Event @event, ScriptAccessory accessory)
{
guid = accessory.Method.RegistFrameworkUpdateAction(() =>
{
var a = 123;
});
}
[ScriptMethod(eventType: EventTypeEnum.StartCasting, eventCondition: ["ActionId:124"])]
public void TestRunOnFrame2(Event @event, ScriptAccessory accessory)
{
accessory.Method.RegistFrameworkUpdateAction(TestRunOnFrame22);
}
[ScriptMethod(eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:124"])]
public void TestFadeOut(Event @event, ScriptAccessory accessory)
{
var dp = accessory.Data.GetDefaultDrawProperties();
dp.Name = $"TestFadeOut";
dp.Scale = new(5);
dp.Color = accessory.Data.DefaultDangerColor;
dp.Owner = 0x400003B8;
dp.FadeCentreObject = 0x400003B8;
dp.FadeDistance = 5;
dp.FadeMode = FadeMode.OmenCentre;
dp.DestoryAt = 15000;
accessory.Method.SendDraw(DrawModeEnum.Vfx, DrawTypeEnum.Circle, dp);
}
[ScriptMethod(eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:99999"])]
public void TestCreateLockOn(Event @event, ScriptAccessory accessory)
{
var objHandle = accessory.Method.ObjectMethod.CreateEmptyChara(0x40001234);
Task.Delay(50).ContinueWith(t =>
{
var start = DateTime.Now;
var handle = accessory.Method.VfxMethod.CreateLockOn(1, 0x40001234, new Vector4(1, 0, 0, 1), 10000,
(ref Vector4 color, ref Vector4 pos, ref Vector3 scale) =>
{
var elapsedSeconds = (float)(DateTime.Now - start).TotalSeconds;
float hue = (elapsedSeconds * 0.5f) % 1f;
scale = new(hue * 1 + 0.5f);
color = HueToRGB(hue);
//pos = new(hue);
unsafe
{
var obj = (BattleChara*)objHandle;
obj->Position = new(hue);
}
});
});
Task.Delay(5000).ContinueWith(t => { accessory.Method.ObjectMethod.DestoryChara(objHandle); });
}
[ScriptMethod(eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:99999"])]
public void TestCreateOmen(Event @event, ScriptAccessory accessory)
{
var start = DateTime.Now;
var pos = accessory.Data.MyObject.Position;
var handle = accessory.Method.VfxMethod.CreateOmen(3, new(3), accessory.Data.MyObject.Position, 0, new Vector4(1, 0, 0, 1), 10000,
(ref Vector4 color, ref Vector4 pos, ref Vector3 scale) =>
{
var elapsedSeconds = (float)(DateTime.Now - start).TotalSeconds;
float hue = (elapsedSeconds * 0.5f) % 1f;
color = HueToRGB(hue);//算一个rgb跑马灯颜色并赋值给颜色
pos = new(accessory.Data.MyObject.Position, pos.W + MathF.PI / 100);//追踪游戏人物的坐标
scale = new(2 + hue * 3);//随时间大小变化
});
}
[ScriptMethod(eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:99999"])]
public void TestMark(Event @event, ScriptAccessory accessory)
{
accessory.Method.Mark(accessory.Data.Me, KodakkuAssist.Module.GameOperate.MarkType.Attack1);
accessory.Method.Mark((uint)accessory.Data.MyObject.TargetObjectId, KodakkuAssist.Module.GameOperate.MarkType.Attack2, true);
}
[ScriptMethod(eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:99999"])]
public void TestClearMark(Event @event, ScriptAccessory accessory)
{
accessory.Method.MarkClear();
}
System.Threading.Timer t;
[ScriptMethod(eventType: EventTypeEnum.ActionEffect, eventCondition: ["ActionId:99999"])]
public void TestVarDestory(Event @event, ScriptAccessory accessory)
{
t = new(_ =>
{
accessory.Log.Debug($"来自版本F的timer,每5秒钟提示一次");
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));
}
public void TestRunOnFrame22()
{
var a = 111;
}
private static Vector4 HueToRGB(float hue)
{
float r = 0, g = 0, b = 0;
float h = hue * 6f;
int segment = (int)h;
float f = h - segment;
float p = 0f;
float q = 0.5f * (1f - f);
float t = 0.5f * f;
switch (segment)
{
case 0: r = 1; g = t; b = p; break;
case 1: r = q; g = 1; b = p; break;
case 2: r = p; g = 1; b = t; break;
case 3: r = p; g = q; b = 1; break;
case 4: r = t; g = p; b = 1; break;
case 5: r = 1; g = p; b = q; break;
}
return new Vector4(r, g, b, 1f);
}
public void Dispose()
{
t.Dispose();
}
}
}