diff --git a/.gitignore b/.gitignore
index 86a6c2eb1..f90f34245 100644
--- a/.gitignore
+++ b/.gitignore
@@ -375,3 +375,4 @@ FodyWeavers.xsd
/Maple2.File.Ingest/Navmeshes/*.navmesh
.idea/.idea.Maple2/.idea/sqldialects.xml
.idea/.idea.Maple2/.idea/dataSources.xml
+/Maple2.Server.Game/DebugTriggers
diff --git a/.gitmodules b/.gitmodules
index c59ee16a0..9c1743ce7 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "Maple2.Server.Game/Scripting/Scripts"]
- path = Maple2.Server.Game/Scripting/Scripts
- url = https://github.com/AngeloTadeucci/maple2-scripts.git
[submodule "Maple2.Server.Game/Navmeshes"]
path = Maple2.Server.Game/Navmeshes
url = https://github.com/AngeloTadeucci/Maple2.Navmeshes
diff --git a/.idea/.idea.Maple2/.idea/scopes/Ignore_all_bin__obj__debugtrigger_folders.xml b/.idea/.idea.Maple2/.idea/scopes/Ignore_all_bin__obj__debugtrigger_folders.xml
new file mode 100644
index 000000000..18011e8cc
--- /dev/null
+++ b/.idea/.idea.Maple2/.idea/scopes/Ignore_all_bin__obj__debugtrigger_folders.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Maple2/.idea/scopes/Ignore_all_bin_and_obj_folders.xml b/.idea/.idea.Maple2/.idea/scopes/Ignore_all_bin_and_obj_folders.xml
deleted file mode 100644
index bf3e5155d..000000000
--- a/.idea/.idea.Maple2/.idea/scopes/Ignore_all_bin_and_obj_folders.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/.idea.Maple2/.idea/vcs.xml b/.idea/.idea.Maple2/.idea/vcs.xml
index 2f986640b..7e72f8d8d 100644
--- a/.idea/.idea.Maple2/.idea/vcs.xml
+++ b/.idea/.idea.Maple2/.idea/vcs.xml
@@ -3,6 +3,5 @@
-
\ No newline at end of file
diff --git a/Maple2.Database/Context/MetadataContext.cs b/Maple2.Database/Context/MetadataContext.cs
index 0367e3fbf..6090ed5ed 100644
--- a/Maple2.Database/Context/MetadataContext.cs
+++ b/Maple2.Database/Context/MetadataContext.cs
@@ -31,6 +31,7 @@ public sealed class MetadataContext(DbContextOptions options) : DbContext(option
public DbSet NXSMeshMetadata { get; set; } = null!;
public DbSet FunctionCubeMetadata { get; set; } = null!;
public DbSet MapDataMetadata { get; set; } = null!;
+ public DbSet TriggerMetadata { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
@@ -57,6 +58,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Entity(ConfigureNifMetadata);
modelBuilder.Entity(ConfigureNXSMeshMetadata);
modelBuilder.Entity(ConfigureFunctionCubeMetadata);
+ modelBuilder.Entity(ConfigureTriggerMetadata);
}
private static void ConfigureAdditionalEffectMetadata(EntityTypeBuilder builder) {
@@ -250,4 +252,12 @@ private static void ConfigureFunctionCubeMetadata(EntityTypeBuilder cube.AutoStateChange).HasJsonConversion();
builder.Property(cube => cube.Nurturing).HasJsonConversion();
}
+
+ private static void ConfigureTriggerMetadata(EntityTypeBuilder builder) {
+ builder.ToTable("trigger");
+ builder.HasKey(trigger => new {
+ trigger.MapXBlock,
+ trigger.Name,
+ });
+ }
}
diff --git a/Maple2.Database/Storage/Game/GameStorage.User.cs b/Maple2.Database/Storage/Game/GameStorage.User.cs
index 03e68ac66..046582bd9 100644
--- a/Maple2.Database/Storage/Game/GameStorage.User.cs
+++ b/Maple2.Database/Storage/Game/GameStorage.User.cs
@@ -1,4 +1,5 @@
-using Maple2.Database.Extensions;
+using System.Text.Json;
+using Maple2.Database.Extensions;
using Maple2.Database.Model;
using Maple2.Model.Enum;
using Maple2.Model.Game;
@@ -396,13 +397,11 @@ public bool SaveCharacterConfig(
attribute => attribute,
attribute => allocation[attribute]);
config.StatPoints = statSources.Points;
- config.SkillPoint = skillPoint.Points.SelectMany(
- point => point.Value.Ranks.Select(
- rankPoint => new Model.SkillPoint {
- Source = point.Key,
- Rank = rankPoint.Key,
- Points = rankPoint.Value,
- }))
+ config.SkillPoint = skillPoint.Points.SelectMany(point => point.Value.Ranks.Select(rankPoint => new Model.SkillPoint {
+ Source = point.Key,
+ Rank = rankPoint.Key,
+ Points = rankPoint.Value,
+ }))
.ToList();
config.GatheringCounts = gatheringCounts;
config.GuideRecords = guideRecords;
diff --git a/Maple2.Database/Storage/Metadata/TriggerScriptMetadata.cs b/Maple2.Database/Storage/Metadata/TriggerScriptMetadata.cs
new file mode 100644
index 000000000..2075161bb
--- /dev/null
+++ b/Maple2.Database/Storage/Metadata/TriggerScriptMetadata.cs
@@ -0,0 +1,33 @@
+using System.Diagnostics.CodeAnalysis;
+using Maple2.Database.Context;
+using Maple2.Model.Metadata;
+
+namespace Maple2.Database.Storage;
+
+public class TriggerScriptMetadata(MetadataContext context) : MetadataStorage<(string, string), TriggerMetadata>(context, CACHE_SIZE) {
+ private const int CACHE_SIZE = 5000; // ~5k total triggers
+
+ public bool TryGet(string mapXBlock, string triggerName, [NotNullWhen(true)] out TriggerMetadata? trigger) {
+ if (Cache.TryGet((mapXBlock, triggerName), out trigger)) {
+ return true;
+ }
+
+ lock (Context) {
+ // Double-checked locking
+ if (Cache.TryGet((mapXBlock, triggerName), out trigger)) {
+ return true;
+ }
+
+ trigger = Context.TriggerMetadata.Find(mapXBlock, triggerName);
+
+ if (trigger == null) {
+ return false;
+ }
+
+ Cache.AddReplace((mapXBlock, triggerName), trigger);
+ }
+
+ return true;
+ }
+
+}
diff --git a/Maple2.File.Ingest/Generator/TriggerGenerator.cs b/Maple2.File.Ingest/Generator/TriggerGenerator.cs
deleted file mode 100644
index e6b99a724..000000000
--- a/Maple2.File.Ingest/Generator/TriggerGenerator.cs
+++ /dev/null
@@ -1,688 +0,0 @@
-using System.CodeDom.Compiler;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Xml;
-using M2dXmlGenerator;
-using Maple2.File.Ingest.Utils;
-using Maple2.File.Ingest.Utils.Trigger;
-using Maple2.File.IO;
-using Maple2.File.IO.Crypto.Common;
-using Maple2.Tools;
-using static System.Char;
-
-namespace Maple2.File.Ingest.Generator;
-
-public class TriggerGenerator {
- private readonly M2dReader reader;
- private readonly Dictionary checkUserCountStates = new();
- private readonly Dictionary checkUser10States = new();
-
- private static readonly HashSet<(string, bool, bool, bool)> ProcessedStrings = [];
- private static readonly SortedDictionary KoreanStrings = new();
- private static readonly TriggerApiScript ApiScript = new();
-
- public TriggerGenerator(M2dReader xmlReader) {
- reader = xmlReader;
-
- XmlDocument checkUserCountDocument = reader.GetXmlDocument(reader.Files.First(entry =>
- entry.Name.StartsWith("trigger/dungeon_common/checkusercount.xml")));
- foreach (XmlNode stateNode in checkUserCountDocument.SelectNodes("ms2/state")!) {
- string stateName = stateNode.Attributes["name"].Value;
- checkUserCountStates.Add(stateName, stateName);
- }
-
- XmlDocument guildCheckUserDocument = reader.GetXmlDocument(reader.Files.First(entry =>
- entry.Name.StartsWith("trigger/dungeon_common/checkuser10_guildraid.xml")));
- foreach (XmlNode stateNode in guildCheckUserDocument.SelectNodes("ms2/state")!) {
- string stateName = stateNode.Attributes["name"].Value;
- checkUser10States.Add(stateName, stateName);
- }
- }
-
- public void Generate() {
- foreach (PackFileEntry entry in reader.Files.Where(file => file.Name.StartsWith("trigger/"))) {
- XmlDocument document = reader.GetXmlDocument(entry);
- XmlNodeList stateNodeList = document.SelectNodes("ms2/state")!;
- if (stateNodeList.Count == 0) {
- Console.WriteLine($"Empty script: {entry.Name}");
- continue;
- }
-
- string scriptDir = entry.Name.Split('/', StringSplitOptions.RemoveEmptyEntries)[1];
- string scriptName = Path.GetFileNameWithoutExtension(entry.Name);
-
- Directory.CreateDirectory(Path.Combine(Paths.GAME_SCRIPTS_DIR, scriptDir));
- string pyName = Path.Combine(Paths.GAME_SCRIPTS_DIR, scriptDir, $"{scriptName}.py");
- using var stream = new StreamWriter(pyName);
- using var writer = new IndentedTextWriter(stream, " ");
- writer.WriteLine(@$""""""" {entry.Name} """"""");
-
- var script = new TriggerScript {
- Shared = scriptDir == "dungeon_common",
- };
-
- try {
- Dictionary stateIndex = [];
- foreach (XmlNode importNode in document.SelectNodes("ms2/import")!) {
- string path = importNode.Attributes["path"].Value.ToLower();
- string importModule = Directory.GetParent(path).Name;
- string importName = Path.GetFileNameWithoutExtension(path);
-
- script.Imports.Add($"{importModule}.{importName}");
- switch (importName) {
- case "checkusercount":
- foreach (KeyValuePair state in checkUserCountStates) {
- stateIndex.Add(state.Key, state.Value);
- }
- break;
- case "checkuser10_guildraid":
- foreach (KeyValuePair state in checkUser10States) {
- stateIndex.Add(state.Key, state.Value);
- }
- break;
- default:
- throw new InvalidOperationException($"Unknown import: {importModule}/{importName}");
- }
- }
- stateIndex.Add("DungeonStart", "DungeonStart");
-
- // Copy node list so that we can remove duplicate states
- List stateNodes = stateNodeList.Cast().ToList();
- foreach (XmlNode stateNode in stateNodes.ToList()) {
- if (stateNode.Attributes["feature"] != null && !FeatureLocaleFilter.FeatureEnabled(stateNode.Attributes["feature"].Value)) {
- continue;
- }
- string name = stateNode.Attributes["name"].Value;
- if (name == "DungeonStart") continue; // Special case
-
- name = FixClassName(name);
- if (stateIndex.ContainsKey(name)) {
- // Console.WriteLine($"Duplicate state in {entry.Name} ignored and removed: {name}");
- stateNodes.Remove(stateNode);
- } else {
- stateIndex.Add(name, name);
- }
- }
-
- foreach (XmlNode stateNode in stateNodes) {
- if (stateNode.Attributes["feature"] != null && !FeatureLocaleFilter.FeatureEnabled(stateNode.Attributes["feature"].Value)) {
- continue;
- }
- TriggerScript.State scriptState = ParseState(stateNode, stateIndex, entry.Name);
-
- IList comments = SiblingComments(stateNode);
- // Join all comments and attempt to parse as XML
- if (TryParseXml(string.Join("\n", comments).Trim(), "state", out List commentNodes)) {
- foreach (XmlNode commentNode in commentNodes) {
- switch (commentNode.Name) {
- case "state":
- script.States.Add(new CommentWrapper(ParseState(commentNode, stateIndex, entry.Name)));
- break;
- default:
- Debug.Assert(commentNode.Value != null);
- script.States.Add(new Comment(commentNode.Value));
- break;
- }
- }
- } else {
- // If unable to parse full block comment, attempt individual blocks
- foreach (string comment in comments) {
- if (TryParseXml(comment, "state", out commentNodes)) {
- foreach (XmlNode commentNode in commentNodes) {
- switch (commentNode.Name) {
- case "state":
- script.States.Add(new CommentWrapper(ParseState(commentNode, stateIndex, entry.Name)));
- break;
- default:
- Debug.Assert(commentNode.Value != null);
- script.States.Add(new Comment(commentNode.Value));
- break;
- }
- }
- continue;
- }
-
- // Anything unparsed is added back as a comment
- scriptState.Comments.Add(comment);
- }
- }
-
- script.States.Add(scriptState);
- }
-
- script.WriteTo(writer);
- //Console.WriteLine($"Generated {pyName}...");
- } catch (Exception ex) {
- Console.WriteLine($"Failed to parse file: {entry.Name} - {ex.Message}");
- Console.WriteLine(ex.StackTrace);
- }
- }
-
- // Create module for dungeon_common
- System.IO.File.Create(Path.Combine(Paths.GAME_SCRIPTS_DIR, "dungeon_common", "__init__.py"));
- using var apiStream = new StreamWriter(Path.Combine(Paths.GAME_SCRIPTS_DIR, "trigger_api.py"));
- using var apiWriter = new IndentedTextWriter(apiStream, " ");
- ApiScript.WriteTo(apiWriter);
-
- using var csStream = new StreamWriter(Path.Combine(Paths.TRIGGER_CONTEXT_DIR, "TriggerContext.cs"));
- using var csWriter = new IndentedTextWriter(csStream, " ");
- ApiScript.WriteInterface(csWriter);
-
- using var csEnumStream = new StreamWriter(Path.Combine(Paths.TRIGGER_CONTEXT_DIR, "TriggerEnums.cs"));
- using var csEnumWriter = new IndentedTextWriter(csEnumStream, " ");
- ApiScript.WriteEnums(csEnumWriter);
- }
-
- private static TriggerScript.State ParseState(XmlNode node, Dictionary stateIndex, string filePath) {
- string name = FixClassName(node.Attributes["name"].Value);
- // IndexStrings(name, isState: true);
-
- List onEnter = [];
- TriggerScript.Transition? onEnterTransition = null;
- XmlNode? onEnterNode = node.SelectSingleNode("onEnter");
- if (onEnterNode != null) {
- IEnumerator it = onEnterNode.ChildNodes.Cast().GetEnumerator();
- while (it.MoveNext()) {
- switch (it.Current.Name) {
- case "action":
- onEnter.Add(ParseAction(it, stateIndex));
- break;
- case "transition":
- onEnterTransition = ParseTransition(it, stateIndex);
- break;
- case "#comment":
- if (it.Current.Value == null) {
- break;
- }
- if (TryParseXml(it.Current.Value, "action", out List commentActionNodes)) {
- foreach (XmlNode commentNode in commentActionNodes) {
- switch (commentNode.Name) {
- case "action":
- onEnter.Add(new CommentWrapper(ParseAction(commentNode, stateIndex)));
- break;
- default:
- Debug.Assert(commentNode.Value != null);
- AppendCommentOrAdd(onEnter, commentNode);
- break;
- }
- }
- } else {
- AppendCommentOrAdd(onEnter, it.Current);
- }
- break;
- case "#text":
- if (!string.IsNullOrWhiteSpace(node.Value)) {
- Console.WriteLine($"Unexpected text: {node.Value}");
- }
- break;
- default:
- throw new ArgumentException($"[{filePath}] Unexpected node <{it.Current.Name}>: {onEnterNode.InnerXml}");
- }
- }
- }
-
- List conditions = [];
- foreach (XmlNode conditionNode in node.SelectNodes("condition")!) {
- TriggerScript.Condition condition = ParseCondition(conditionNode, stateIndex, filePath);
- if (conditionNode.NextSibling is XmlComment comment) {
- if (TryParseXml(comment.Value, "condition", out List commentNodes, allowComments: false)) {
- foreach (TriggerScript.Condition commentedCondition in commentNodes.Select(commentNode => ParseCondition(commentNode, stateIndex, filePath))) {
- conditions.Add(new CommentWrapper(commentedCondition));
- }
- } else {
- condition.LineComment = comment.Value;
- }
- }
- conditions.Add(condition);
- }
-
- List onExit = [];
- XmlNode? onExitNode = node.SelectSingleNode("onExit");
- if (onExitNode != null) {
- foreach (XmlNode child in onExitNode.ChildNodes) {
- switch (child.Name) {
- case "action":
- onExit.Add(ParseAction(child, stateIndex));
- break;
- case "condition":
- Console.WriteLine($"[{filePath}] Moving onExit to onTick");
- conditions.Add(ParseCondition(child, stateIndex, filePath));
- break;
- case "#comment":
- if (child.Value == null) {
- break;
- }
- if (TryParseXml(child.Value, "action", out List commentNodes)) {
- foreach (TriggerScript.Action commentedAction in commentNodes.Select(commentNode => ParseAction(commentNode, stateIndex))) {
- onExit.Add(new CommentWrapper(commentedAction));
- }
- } else {
- AppendCommentOrAdd(onExit, child);
- }
- break;
- default:
- throw new ArgumentException($"Unexpected node in onExit: {child.Name}\n{child.OuterXml}");
- }
- }
- }
-
- return new TriggerScript.State(name) {
- OnEnter = onEnter,
- OnEnterTransition = onEnterTransition,
- Conditions = conditions,
- OnExit = onExit,
- };
- }
-
- private static TriggerScript.Action ParseAction(IEnumerator it, Dictionary stateIndex) {
- TriggerScript.Action action = ParseAction(it.Current, stateIndex);
- if (it.Current.NextSibling is XmlComment { Value: not null } lineComment) {
- string trimmed = lineComment.Value.Trim();
- if (trimmed.StartsWith('<') || trimmed.StartsWith("action name=")) {
- return action;
- }
-
- if (action.LineComment != null) {
- action.LineComment += ", " + lineComment.Value;
- } else {
- action.LineComment = lineComment.Value;
- }
-
- it.MoveNext(); // Advance iterator
- }
-
- return action;
- }
-
- private static TriggerScript.Action ParseAction(XmlNode node, Dictionary stateIndex) {
- Debug.Assert(node.Name == "action", $"ParseAction(node) where node is not : {node.OuterXml}");
-
- List<(string, string)> strArgs = [];
- string? origName = null;
- foreach (XmlAttribute attribute in node.Attributes) {
- if (attribute.Name == "name") {
- origName = attribute.Value;
- continue;
- }
- strArgs.Add((attribute.Name, attribute.Value));
- }
- Debug.Assert(origName != null, "Unable to find name param");
-
- // IndexStrings(name, isAction: true);
- string name = Translate(origName, TriggerTranslate.TranslateAction);
- string? extraDescription = null;
- string? splitArgValue = null;
- string? splitName = null;
- if (TriggerDefinitionOverride.ActionOverride.TryGetValue(name, out TriggerDefinitionOverride? @override) && @override.FunctionSplitter != null) {
- string? splitArgName;
- if (strArgs.Any(e => e.Item1 == @override.FunctionSplitter)) {
- (splitArgName, splitArgValue) = strArgs.Single(e => e.Item1 == @override.FunctionSplitter);
- } else {
- splitArgName = @override.FunctionSplitter;
- splitArgValue = @override.Types[@override.FunctionSplitter].Default!;
- }
-
- Debug.Assert(@override.FunctionLookup.ContainsKey(splitArgValue), $"Unknown function split in {name} for {splitArgValue}");
- splitName = @override.FunctionLookup[splitArgValue].Name;
- extraDescription = $"{splitArgName}={splitArgValue}";
- }
-
- if (!ApiScript.Actions.TryGetValue((name, splitName), out TriggerApiScript.Function? function)) {
- function = new TriggerApiScript.Function(name, splitArgValue, false) {
- Description = extraDescription != null ? $"{origName}: {extraDescription}" : origName,
- };
- ApiScript.Actions.Add((name, splitName), function);
- }
-
- List args = [];
- foreach ((string argName, string argValue) in strArgs) {
- if (name == "reset_camera" && argValue == "interpolationTime") {
- continue;
- }
-
- (ScriptType Type, string Name) param = function.AddParameter(ScriptType.Str, argName);
- if (param.Type != ScriptType.None) {
- args.Add(new PyParameter(param.Type, param.Name, argValue));
- }
- }
-
- var action = new TriggerScript.Action(name, splitArgValue) {
- Args = args,
- };
-
- // Fix state names referenced in args
- if (name is "set_skip" or "set_scene_skip") {
- PyParameter? result = action.Args.FirstOrDefault(arg => arg.Name == "state");
- if (result != null) {
- string? fixedName = FixClassName(result.Value);
- if (fixedName != null && stateIndex.ContainsKey(fixedName)) {
- result.Value = fixedName;
- } else {
- if (!string.IsNullOrWhiteSpace(fixedName)) {
- action.LineComment = $"Missing State: {fixedName}";
- }
- result.Value = null;
- }
- }
- }
-
- return action;
- }
-
- private static TriggerScript.Transition ParseTransition(IEnumerator it, Dictionary stateIndex) {
- string? transition = FixClassName(it.Current.Attributes?["state"]?.Value);
- bool isValid = false;
- if (transition != null) {
- isValid = stateIndex.ContainsKey(transition);
- // if (!isValid) {
- // Console.WriteLine($"Script {filePath} Missing transition: {transition}");
- // Console.WriteLine($"- {string.Join(",", stateIndex.Keys)}");
- // }
- }
- string? transitionComment = null;
- if (it.Current.NextSibling is XmlComment { Value: not null } comment) {
- if (!comment.Value.StartsWith('<') && !comment.Value.StartsWith("action name=")) {
- transitionComment = comment.Value;
- it.MoveNext(); // Advance iterator
- }
- }
-
- return new TriggerScript.Transition(transition, isValid, transitionComment);
- }
-
- private static TriggerScript.Condition ParseCondition(XmlNode node, Dictionary stateIndex, string filePath) {
- List<(string, string)> strArgs = [];
- string? origName = null;
- foreach (XmlAttribute attribute in node.Attributes) {
- if (attribute.Name == "name") {
- origName = attribute.Value;
- continue;
- }
- strArgs.Add((attribute.Name, attribute.Value));
- }
- Debug.Assert(origName != null, "Unable to find name param");
-
- bool negated = origName.StartsWith('!');
- origName = origName.TrimStart('!');
- // IndexStrings(name, isCondition: true);
- string name = Translate(origName, TriggerTranslate.TranslateCondition);
- if (!ApiScript.Conditions.TryGetValue(name, out TriggerApiScript.Function? function)) {
- function = new TriggerApiScript.Function(name, null, true) {
- Description = origName,
- };
- ApiScript.Conditions.Add(name, function);
- }
-
- List args = [];
- foreach ((string argName, string argValue) in strArgs) {
- (ScriptType Type, string Name) param = function.AddParameter(ScriptType.Str, argName);
- if (param.Type != ScriptType.None) {
- args.Add(new PyParameter(param.Type, param.Name, argValue));
- }
- }
- // Negative boxId matching
- if (name is "user_detected") {
- PyParameter? result = args.Find(arg => arg.Name == "box_ids");
- if (result != null && result.Value?.StartsWith("!") == true) {
- result.Value = result.Value.TrimStart('!');
- negated = !negated;
- }
- }
-
- var condition = new TriggerScript.Condition(name) {
- Negated = negated,
- Args = args,
- };
- IEnumerator it = node.ChildNodes.Cast().GetEnumerator();
- while (it.MoveNext()) {
- switch (it.Current.Name) {
- case "action":
- condition.Actions.Add(ParseAction(it, stateIndex));
- break;
- case "transition":
- condition.Transition = ParseTransition(it, stateIndex);
- break;
- case "group":
- foreach (XmlNode child in it.Current.ChildNodes) {
- switch (child.Name) {
- case "condition":
- condition.Group.Add(ParseCondition(child, stateIndex, filePath));
- break;
- case "#comment":
- condition.Comments.Add($"{name}: {child.Value}");
- break;
- default:
- Console.WriteLine($"[{filePath}] Unknown : {child.OuterXml}");
- break;
- }
- }
- break;
- case "#comment":
- if (it.Current.Value == null) {
- break;
- }
- if (TryParseXml(it.Current.Value, "action", out List commentNodes)) {
- foreach (XmlNode commentNode in commentNodes) {
- switch (commentNode.Name) {
- case "action":
- condition.Actions.Add(new CommentWrapper(ParseAction(commentNode, stateIndex)));
- break;
- default:
- Debug.Assert(commentNode.Value != null);
- AppendCommentOrAdd(condition.Actions, commentNode);
- break;
- }
- }
- } else {
- AppendCommentOrAdd(condition.Actions, it.Current);
- }
- break;
- case "#text":
- if (!string.IsNullOrWhiteSpace(it.Current.Value) && it.Current.Value != ">") {
- if (condition.LineComment == null) {
- condition.LineComment = it.Current.Value.Trim();
- } else {
- Console.WriteLine($"Unexpected text: {it.Current.Value}");
- }
- }
- break;
- default:
- Console.WriteLine($"[{filePath}] Unknown : {it.Current.OuterXml}");
- break;
- }
- }
-
- return condition;
- }
-
- private static readonly Dictionary SubStart = new() {
- { "1st", "First" },
- { "2nd", "Second" },
- { "3rd", "Third" },
- { "4th", "Fourth" },
- { "5th", "Fifth" },
- { "6th", "Sixth" },
- { "7th", "Seventh" },
- };
-
- [return: NotNullIfNotNull(nameof(name))]
- private static string? FixClassName(string? name) {
- if (name == null) {
- return null;
- }
- if (string.IsNullOrWhiteSpace(name)) {
- return "State";
- }
-
- // Reserved Keywords
- switch (name) {
- case "None":
- return "StateNone";
- case "True":
- return "StateTrue";
- case "False":
- return "StateFalse";
- case "del":
- return "StateDelete";
- }
-
- name = name.Replace("-", "To").Replace(" ", "_").Replace(".", "_");
- foreach ((string key, string value) in SubStart) {
- if (name.StartsWith(key)) {
- name = name.Replace(key, value);
- break;
- }
- }
-
- string prefix = "";
- while (name.Length > 0 && !IsLetter(name[0])) {
- if (name[0] != '_') {
- prefix += name[0];
- }
- name = name[1..];
- }
-
- // name is already valid
- if (prefix.Length == 0) {
- return name;
- }
- if (name.Length == 0) {
- return $"State{prefix}";
- }
-
- return !IsLetter(name[^1]) ? $"{name}_{prefix}" : $"{name}{prefix}";
- }
-
- [return: NotNullIfNotNull(nameof(name))]
- private static string? Translate(string? name, Func translator) {
- if (name == null) {
- return null;
- }
-
- var builder = new StringBuilder();
- foreach (string split in name.Split('_', ' ')) {
- builder.Append(translator(split));
- }
-
- return TriggerTranslate.ToSnakeCase(builder.ToString());
- }
-
- private static void IndexStrings(string? text, bool isState = false, bool isAction = false, bool isCondition = false) {
- if (text == null || ProcessedStrings.Contains((text, isState, isAction, isCondition))) {
- return;
- }
-
- var builder = new StringBuilder();
- foreach (string split in text.Split('_', ' ', 'U')) {
- string korean = Regex.Replace(split, "[0-9a-zA-Z]+", "");
- if (korean.Length == 0) {
- continue;
- }
-
- builder.Append($"{korean},");
-
- KoreanStrings.TryGetValue(korean, out (bool IsState, bool IsAction, bool IsCondition) value);
- value.IsState |= isState;
- value.IsAction |= isAction;
- value.IsCondition |= isCondition;
- KoreanStrings[korean] = value;
- }
-
- ProcessedStrings.Add((text, isState, isAction, isCondition));
- if (builder.Length > 0) {
- //Console.WriteLine($"{text} => {builder}");
- }
- }
-
- private static IList SiblingComments(XmlNode? node, bool before = true, bool after = false) {
- List comments = [];
- if (node == null) {
- return comments;
- }
-
- XmlNode? sibling = node.PreviousSibling;
- while (before && sibling is XmlComment { Value: not null } comment) {
- comments.Insert(0, comment.Value);
- sibling = sibling.PreviousSibling;
- }
-
- List afterComments = [];
- sibling = node.NextSibling;
- while (after && sibling is XmlComment { Value: not null } comment) {
- afterComments.Add(comment.Value);
- sibling = sibling.NextSibling;
- }
-
- if (comments.Count > 0 && afterComments.Count > 0) {
- comments.Add(""); // Linebreak between comment groups
- }
- comments.AddRange(afterComments);
-
- return comments;
- }
-
- private static bool TryParseXml(string? xml, string name, out List nodes, bool allowComments = true) {
- if (xml == null || !Regex.Match(xml, $"{name} +name=").Success) {
- nodes = [];
- return false;
- }
- // Attempt to close some unclosed xml elements
- xml = xml.Trim();
- if (!xml.Contains("\n")) {
- if (xml.Contains($"<{name}") && !xml.Contains("/>")) {
- xml = xml.Replace(">", "/>");
- }
- }
-
- // Always first try without allowing comments
- if (allowComments && TryParseXml(xml, name, out nodes, false)) {
- return true;
- }
-
- // Many cases of valid xml missing first and last <>
- foreach (string tryXml in new[] {
- xml,
- $"<{xml.Trim()}>",
- $"<{xml.Trim()}/>",
- }) {
- try {
- var stateDocument = new XmlDocument();
- stateDocument.LoadXml($"{tryXml}");
- if (stateDocument.DocumentElement != null) {
- List children = stateDocument.DocumentElement.ChildNodes.Cast().ToList();
- if (children.All(node => node.Name == name || (allowComments && node.Name is "#comment" or "#text"))) {
- nodes = children.ToList();
- return true;
- }
- }
- } catch (XmlException) { /* ignored */
- }
- }
-
- nodes = [];
- return false;
- }
-
- // Appends a LineComment to the previous Action block if possible
- // otherwise, just adds a separate Comment block
- private static void AppendCommentOrAdd(IList list, XmlNode comment) {
- Debug.Assert(comment is XmlComment or XmlText && comment.Value != null);
- if (list.Count == 0) {
- list.Add(new Comment(comment.Value));
- return;
- }
-
- IScriptBlock prevBlock = list[^1];
- if (prevBlock is CommentWrapper wrapper) {
- prevBlock = wrapper.Child;
- }
-
- if (prevBlock is TriggerScript.Action { LineComment: null } prevAction) {
- prevAction.LineComment = comment.Value;
- } else {
- list.Add(new Comment(comment.Value));
- }
- }
-}
diff --git a/Maple2.File.Ingest/Mapper/TriggerMapper.cs b/Maple2.File.Ingest/Mapper/TriggerMapper.cs
new file mode 100644
index 000000000..88625654c
--- /dev/null
+++ b/Maple2.File.Ingest/Mapper/TriggerMapper.cs
@@ -0,0 +1,229 @@
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+using System.Xml;
+using Maple2.File.Ingest.Utils;
+using Maple2.File.IO;
+using Maple2.File.IO.Crypto.Common;
+using Maple2.Model.Metadata;
+using Maple2.Tools;
+using static System.Char;
+
+
+namespace Maple2.File.Ingest.Mapper;
+
+public class TriggerMapper : TypeMapper {
+ private readonly M2dReader reader;
+
+ public TriggerMapper(M2dReader reader) {
+ this.reader = reader;
+ }
+
+ protected override IEnumerable Map() {
+ IEnumerable triggers = reader.Files.Where(file => file.Name.StartsWith("trigger/"));
+ foreach (PackFileEntry file in triggers) {
+ // get the folder name from the file path after "trigger/"
+ string[] filePath = file.Name["trigger/".Length..].Split('/');
+ string folderName = filePath[0];
+ string triggerName = filePath[1].Split(".")[0]; // remove the file extension
+ string xml = NormalizeTriggerXmlNames(reader.GetXmlDocument(file));
+
+ var trigger = new TriggerMetadata(folderName, triggerName, xml);
+
+ if (Constant.DebugTriggers) { // for debugging purposes
+ string filePathName = Path.Combine(Paths.DEBUG_TRIGGERS_DIR, folderName, $"{triggerName}.xml");
+ Directory.CreateDirectory(Path.GetDirectoryName(filePathName)!);
+
+ var formattedXml = new XmlDocument();
+ formattedXml.LoadXml(xml);
+ var settings = new XmlWriterSettings {
+ Indent = true,
+ NewLineOnAttributes = false,
+ OmitXmlDeclaration = true,
+ };
+
+ using var writer = XmlWriter.Create(filePathName, settings);
+ formattedXml.Save(writer);
+ }
+ yield return trigger;
+ }
+ }
+
+ private static readonly Dictionary SubStart = new() {
+ { "1st", "First" },
+ { "2nd", "Second" },
+ { "3rd", "Third" },
+ { "4th", "Fourth" },
+ { "5th", "Fifth" },
+ { "6th", "Sixth" },
+ { "7th", "Seventh" },
+ };
+
+ public static string NormalizeTriggerXmlNames(XmlDocument xml) {
+ foreach (XmlNode node in xml.SelectNodes("//state")!) {
+ XmlAttribute? attr = node.Attributes?["name"];
+ Debug.Assert(attr?.Value != null, "Unable to find name param");
+ attr.Value = FixClassName(attr.Value);
+ }
+
+ foreach (XmlNode node in xml.SelectNodes("//transition")!) {
+ XmlAttribute? attr = node.Attributes?["state"];
+ Debug.Assert(attr?.Value != null, "Unable to find state param");
+ attr.Value = FixClassName(attr.Value);
+ }
+
+ foreach (XmlNode node in xml.SelectNodes("//action")!) {
+ string actionName = string.Empty;
+ List nodeParams = [];
+ foreach (XmlAttribute? attribute in node.Attributes!) {
+ if (attribute is null) continue;
+ if (attribute.Name is "name") {
+ attribute.Value = Translate(attribute.Value, TriggerTranslate.TranslateAction);
+ actionName = attribute.Value;
+ continue;
+ }
+
+ nodeParams.Add(attribute);
+ }
+
+ if (!TriggerDefinitionOverride.ActionOverride.TryGetValue(actionName, out TriggerDefinitionOverride? overrideValue)) continue;
+
+ if (overrideValue.FunctionSplitter is not null) {
+ XmlAttribute? attributeSplitter = nodeParams.FirstOrDefault(x => x.Name == overrideValue.FunctionSplitter);
+ if (attributeSplitter is not null) {
+ overrideValue.FunctionLookup.TryGetValue(attributeSplitter.Value, out overrideValue);
+ Debug.Assert(overrideValue is not null, $"Unable to find override for {attributeSplitter.Value}");
+ } else {
+ string? valueDefault = overrideValue.Types.FirstOrDefault().Value;
+ Debug.Assert(valueDefault is not null, $"Unable to find default value for {overrideValue.Name}");
+ overrideValue.FunctionLookup.TryGetValue(valueDefault, out overrideValue);
+ Debug.Assert(overrideValue is not null, $"Unable to find override for {valueDefault}");
+ }
+ node.Attributes["name"]!.Value = overrideValue.Name;
+ }
+
+ foreach (XmlAttribute xmlAttribute in nodeParams) {
+ overrideValue.Names.TryGetValue(TriggerTranslate.ToSnakeCase(xmlAttribute.Name), out string? newName);
+ if (newName is null) {
+ if (xmlAttribute.Name != TriggerTranslate.ToSnakeCase(xmlAttribute.Name)) {
+ newName = TriggerTranslate.ToSnakeCase(xmlAttribute.Name);
+ } else {
+ continue;
+ }
+ }
+
+ node.Attributes.Remove(xmlAttribute);
+ XmlAttribute newAttribute = xml.CreateAttribute(newName);
+ newAttribute.Value = xmlAttribute.Value;
+ node.Attributes.Append(newAttribute);
+ }
+ }
+
+ foreach (XmlNode node in xml.SelectNodes("//condition")!) {
+ string conditionName = string.Empty;
+ List nodeParams = [];
+ foreach (XmlAttribute? attribute in node.Attributes!) {
+ if (attribute is null) continue;
+ if (attribute.Name is "name") {
+ conditionName = attribute.Value;
+ continue;
+ }
+
+ nodeParams.Add(attribute);
+ }
+
+ if (conditionName.StartsWith('!')) {
+ XmlAttribute negateAttribute = xml.CreateAttribute("negate");
+ negateAttribute.Value = "true";
+ node.Attributes.Append(negateAttribute);
+ }
+
+ conditionName = conditionName.TrimStart('!');
+ node.Attributes["name"]!.Value = Translate(conditionName, TriggerTranslate.TranslateCondition);
+
+ if (!TriggerDefinitionOverride.ConditionOverride.TryGetValue(node.Attributes["name"]!.Value, out TriggerDefinitionOverride? overrideValue)) continue;
+ if (overrideValue.Name != node.Attributes["name"]!.Value) {
+ node.Attributes["name"]!.Value = overrideValue.Name;
+ }
+ foreach (XmlAttribute xmlAttribute in nodeParams) {
+ overrideValue.Names.TryGetValue(TriggerTranslate.ToSnakeCase(xmlAttribute.Name), out string? newName);
+ if (newName is null) {
+ if (xmlAttribute.Name != TriggerTranslate.ToSnakeCase(xmlAttribute.Name)) {
+ newName = TriggerTranslate.ToSnakeCase(xmlAttribute.Name);
+ } else {
+ continue;
+ }
+ }
+
+ node.Attributes.Remove(xmlAttribute);
+ XmlAttribute newAttribute = xml.CreateAttribute(newName);
+ newAttribute.Value = xmlAttribute.Value;
+ node.Attributes.Append(newAttribute);
+ }
+ }
+
+ return xml.OuterXml;
+ }
+
+ [return: NotNullIfNotNull(nameof(name))]
+ private static string? FixClassName(string? name) {
+ if (name == null) {
+ return null;
+ }
+ if (string.IsNullOrWhiteSpace(name)) {
+ return "State";
+ }
+
+ // Reserved Keywords
+ switch (name) {
+ case "None":
+ return "StateNone";
+ case "True":
+ return "StateTrue";
+ case "False":
+ return "StateFalse";
+ case "del":
+ return "StateDelete";
+ }
+
+ name = name.Replace("-", "To").Replace(" ", "_").Replace(".", "_");
+ foreach ((string key, string value) in SubStart) {
+ if (name.StartsWith(key)) {
+ name = name.Replace(key, value);
+ break;
+ }
+ }
+
+ string prefix = "";
+ while (name.Length > 0 && !IsLetter(name[0])) {
+ if (name[0] != '_') {
+ prefix += name[0];
+ }
+ name = name[1..];
+ }
+
+ // name is already valid
+ if (prefix.Length == 0) {
+ return name;
+ }
+ if (name.Length == 0) {
+ return $"State{prefix}";
+ }
+
+ return !IsLetter(name[^1]) ? $"{name}_{prefix}" : $"{name}{prefix}";
+ }
+
+ [return: NotNullIfNotNull(nameof(name))]
+ private static string? Translate(string? name, Func translator) {
+ if (name == null) {
+ return null;
+ }
+
+ var builder = new StringBuilder();
+ foreach (string split in name.Split('_', ' ')) {
+ builder.Append(translator(split));
+ }
+
+ return TriggerTranslate.ToSnakeCase(builder.ToString());
+ }
+}
diff --git a/Maple2.File.Ingest/Program.cs b/Maple2.File.Ingest/Program.cs
index 16acec5bd..a5e396fb1 100644
--- a/Maple2.File.Ingest/Program.cs
+++ b/Maple2.File.Ingest/Program.cs
@@ -186,6 +186,8 @@
new("/model/textures/", Path.Combine(ms2Root, "Resource/Model/Textures.m2d")),
};
+UpdateDatabase(metadataContext, new TriggerMapper(xmlReader));
+
UpdateDatabase(metadataContext, new ServerTableMapper(serverReader));
UpdateDatabase(metadataContext, new AiMapper(serverReader));
diff --git a/Maple2.File.Ingest/Utils/Recast.cs b/Maple2.File.Ingest/Utils/DotRecast.cs
similarity index 100%
rename from Maple2.File.Ingest/Utils/Recast.cs
rename to Maple2.File.Ingest/Utils/DotRecast.cs
diff --git a/Maple2.File.Ingest/Utils/PyParameter.cs b/Maple2.File.Ingest/Utils/PyParameter.cs
deleted file mode 100644
index 23443bf25..000000000
--- a/Maple2.File.Ingest/Utils/PyParameter.cs
+++ /dev/null
@@ -1,251 +0,0 @@
-using System.Diagnostics;
-using System.Globalization;
-
-namespace Maple2.File.Ingest.Utils;
-
-internal enum ScriptType {
- None = 0, Str, Int, Float, IntList, StrList, StateList, Vector3, Bool, State,
- EnumAlign, EnumFieldGame, EnumLocale, EnumWeather, EnumBannerType
-}
-
-internal record PyParameter(ScriptType Type, string Name) {
- public string? Value;
-
- public PyParameter(ScriptType type, string name, string? value) : this(type, name) {
- Value = value;
- }
-
- public string? Import() {
- return Type switch {
- ScriptType.Vector3 => "Vector3",
- ScriptType.EnumAlign => "Align",
- ScriptType.EnumFieldGame => "FieldGame",
- ScriptType.EnumLocale => "Locale",
- ScriptType.EnumWeather => "Weather",
- ScriptType.EnumBannerType => "BannerType",
- _ => null,
- };
- }
-
- public bool IsDefault(string? defaultOverride) {
- if (string.IsNullOrWhiteSpace(Value)) {
- return true;
- }
- if (defaultOverride == "") {
- return false;
- }
-
- string valueStr = FormatValue();
- // Alternative format that's also equivalent to default.
- if (Type == ScriptType.Vector3 && valueStr == "Vector3(0,0,0)") {
- valueStr = "Vector3()";
- }
-
- return valueStr == (defaultOverride ?? DefaultStr());
- }
-
- public string TypeStr() {
- return TypeStr(Type);
- }
-
- public static string TypeStr(ScriptType type) {
- return type switch {
- ScriptType.None => "None",
- ScriptType.Str => "str",
- ScriptType.Int => "int",
- ScriptType.Float => "float",
- ScriptType.IntList => "List[int]",
- ScriptType.StrList => "List[str]",
- ScriptType.StateList => "List['Trigger']",
- ScriptType.Vector3 => "Vector3",
- ScriptType.Bool => "bool",
- ScriptType.State => "'Trigger'",
- // Enums
- ScriptType.EnumAlign => "Align",
- ScriptType.EnumFieldGame => "FieldGame",
- ScriptType.EnumLocale => "Locale",
- ScriptType.EnumWeather => "Weather",
- ScriptType.EnumBannerType => "BannerType",
- _ => throw new ArgumentException($"Invalid parameter type: {type}"),
- };
- }
-
- public string DefaultStr() {
- return Type switch {
- ScriptType.Str => "''",
- ScriptType.Int => "0",
- ScriptType.Float => "0.0",
- ScriptType.IntList => "[]",
- ScriptType.StrList => "[]",
- ScriptType.StateList => "[]",
- ScriptType.Vector3 => "Vector3()",
- ScriptType.Bool => "False",
- ScriptType.State => "None",
- // Enums
- ScriptType.EnumAlign => "Align.center",
- ScriptType.EnumLocale => "Locale.ALL",
- ScriptType.EnumWeather => "Weather.Clear",
- ScriptType.EnumBannerType => "BannerType.Lose",
- _ => throw new ArgumentException($"Invalid parameter type: {Type}"),
- };
- }
-
- public string FormatValue(bool validate = true) {
- if (validate) ValidateValue();
-
- try {
- return FormatValue(Type, Value) ?? DefaultStr();
- } catch (Exception) {
- if (validate) {
- throw;
- }
- return Value ?? "None";
- }
- }
-
- private static string? FormatValue(ScriptType type, string? value) {
- return type switch {
- ScriptType.Str => string.IsNullOrWhiteSpace(value) ? null : $"'{value.Replace(@"\", @"\\").Replace("'", @"\'")}'",
- ScriptType.Int => string.IsNullOrWhiteSpace(value) ? null : long.Parse(value).ToString(),
- ScriptType.Float => string.IsNullOrWhiteSpace(value) ? null : float.Parse(value).ToString("0.0###", CultureInfo.InvariantCulture),
- ScriptType.IntList => string.IsNullOrWhiteSpace(value) ? null
- : $"[{string.Join(",", GetIntList(value).Select(int.Parse))}]",
- ScriptType.StrList => string.IsNullOrWhiteSpace(value) ? null
- : $"[{string.Join(",", value.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(str => $"'{str.Replace(@"\", @"\\").Replace("'", @"\'")}'"))}]",
- ScriptType.StateList => string.IsNullOrWhiteSpace(value) ? null
- : $"[{string.Join(",", value.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries))}]",
- ScriptType.Vector3 => string.IsNullOrWhiteSpace(value) ? null
- : $"Vector3({string.Join(",", value.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries))})",
- ScriptType.Bool => string.IsNullOrWhiteSpace(value) ? null : value.ToLower() == "true" || value == "1" ? "True" : "False",
- ScriptType.State => string.IsNullOrWhiteSpace(value) ? null : value,
- // Enums
- ScriptType.EnumAlign => string.IsNullOrWhiteSpace(value) ? null : value.ToLower() switch {
- "center" => "Align.center",
- "left" => "Align.left",
- "right" => "Align.right",
- "topcenter" => "Align.topCenter",
- "centerleft" => "Align.centerLeft",
- "centerright" => "Align.centerRight",
- "bottomleft" => "Align.bottomLeft",
- "bottomright" => "Align.bottomRight",
- _ => throw new ArgumentException($"Unexpected Align: {value}"),
- },
- ScriptType.EnumFieldGame => string.IsNullOrWhiteSpace(value) ? null : $"FieldGame.{value}",
- ScriptType.EnumLocale => string.IsNullOrWhiteSpace(value) ? null : $"Locale.{value.ToUpper()}",
- ScriptType.EnumWeather => string.IsNullOrWhiteSpace(value) ? null : value switch {
- "None" => "Weather.Clear",
- _ => $"Weather.{TriggerTranslate.ToPascalCase(value)}",
- },
- ScriptType.EnumBannerType => string.IsNullOrWhiteSpace(value) ? null : value switch {
- // The type values intentionally do not match the BannerType enum values.
- //"0" => "",
- "1" => "BannerType.Text",
- //"2" => "",
- "3" => "BannerType.Winner",
- "4" => "BannerType.Lose",
- "5" => "BannerType.GameOver",
- "6" => "BannerType.Bonus",
- "7" => "BannerType.Success",
- _ => throw new ArgumentException($"Unexpected BannerType: {value}"),
- },
- _ => throw new ArgumentException($"Unexpected Type: {type} for {value}"),
- };
- }
-
- private void ValidateValue() {
- if (string.IsNullOrWhiteSpace(Value) || Type == ScriptType.None) {
- return;
- }
-
- switch (Type) {
- case ScriptType.Str:
- Debug.Assert(Value != null, $"Invalid: {this}");
- return;
- case ScriptType.Int:
- if (!long.TryParse(Value, out _)) {
- Value = "-1";
- }
- return;
- case ScriptType.Float:
- Debug.Assert(double.TryParse(Value, out _), $"Invalid: {this}");
- return;
- case ScriptType.IntList:
- // Handle destroy_monster(all)
- if (Value.Equals("all", StringComparison.OrdinalIgnoreCase)) {
- Value = "-1";
- }
- foreach (string value in GetIntList(Value)) {
- Debug.Assert(long.TryParse(value, out _), $"Invalid({value}): {this}");
- }
- return;
- case ScriptType.StrList:
- return;
- case ScriptType.StateList:
- return;
- case ScriptType.Vector3:
- string[] values = Value.Split(",", StringSplitOptions.RemoveEmptyEntries);
- Debug.Assert(values.Length == 3, $"Invalid: {this}");
- foreach (string value in values) {
- Debug.Assert(double.TryParse(value, out _), $"Invalid: {this}");
- }
- return;
- case ScriptType.Bool:
- if (Name == "return_view" && Value == "11000032") {
- Value = "1";
- }
- string boolValue = Value.ToLower();
- Debug.Assert(boolValue is "true" or "false" or "1" or "0", $"Invalid: {this}");
- return;
- case ScriptType.State:
- return;
- case ScriptType.EnumAlign:
- if (Value == "Reft") {
- Value = "Left";
- }
- string alignValue = Value.ToLower();
- Debug.Assert(alignValue is "top" or "center" or "bottom" or "left" or "right" or "topcenter"
- or "centerleft" or "centerright" or "bottomleft" or "bottomright", $"Invalid: {this}");
- return;
- case ScriptType.EnumFieldGame:
- if (Value == "MapleSurvive") {
- Value = "MapleSurvival";
- }
- Debug.Assert(Value is "HideAndSeek" or "GuildVsGame" or "MapleSurvival" or "MapleSurvivalTeam" or "WaterGunBattle", $"Invalid: {this}");
- break;
- case ScriptType.EnumLocale:
- string localeValue = Value.ToUpper();
- Debug.Assert(localeValue is "KR" or "CN" or "NA" or "JP" or "TH" or "TW", $"Invalid: {this}");
- break;
- case ScriptType.EnumWeather:
- string weatherValue = Value.ToLower();
- Debug.Assert(weatherValue is "none" or "snow" or "heavysnow" or "rain" or "heavyrain" or "sandstorm" or "cherryblossom" or "leaffall", $"Invalid: {this}");
- return;
- case ScriptType.EnumBannerType:
- if (!byte.TryParse(Value, out byte bannerTypeValue)) {
- bannerTypeValue = byte.MaxValue;
- }
- Debug.Assert(bannerTypeValue is >= 0 and < 9, $"Invalid: {this}");
- return;
- default:
- throw new ArgumentException($"Unexpected Type: {Type} for {Name}");
- }
- }
-
- private static IList GetIntList(string value) {
- string[] splits = value.Split(new[] { ',', '.', ' ' }, StringSplitOptions.RemoveEmptyEntries);
- List result = [];
- foreach (string split in splits) {
- string[] range = split.Split("-");
- if (range.Length == 2 && long.TryParse(range[0], out long min) && long.TryParse(range[1], out long max)) {
- for (long i = min; i <= max; i++) {
- result.Add("" + i);
- }
- } else {
- result.Add(split);
- }
- }
-
- return result;
- }
-}
diff --git a/Maple2.File.Ingest/Utils/TextWriterExtensions.cs b/Maple2.File.Ingest/Utils/TextWriterExtensions.cs
deleted file mode 100644
index 22c38d440..000000000
--- a/Maple2.File.Ingest/Utils/TextWriterExtensions.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.CodeDom.Compiler;
-
-namespace Maple2.File.Ingest.Utils;
-
-public static class TextWriterExtensions {
- public static void WriteBlankLine(this IndentedTextWriter writer) {
- int indent = writer.Indent;
- writer.Indent = 0;
- writer.WriteLine();
- writer.Indent = indent;
- }
-
- public static void WriteLineCommentString(this IndentedTextWriter writer, string str, bool sameLine = true) {
- if (str.Contains('\n')) {
- writer.WriteComments(new[] { str.Trim() });
- } else {
- writer.WriteLine(sameLine ? $" # {str.Trim()}" : $"# {str.Trim()}");
- }
- }
-
- public static void WriteComments(this IndentedTextWriter writer, ICollection comments) {
- if (comments.Count > 0) {
- if (comments.SelectMany(c => c.Split("\n")).Count() > 1) {
- writer.WriteLine("\"\"\"");
- foreach (string comment in comments) {
- writer.WriteLine(comment.Replace("\t", " ").Trim());
- }
- writer.WriteLine("\"\"\"");
- } else {
- writer.WriteLine($"# {comments.First().Trim()}");
- }
- }
- }
-}
diff --git a/Maple2.File.Ingest/Utils/Trigger/IScriptBlock.cs b/Maple2.File.Ingest/Utils/Trigger/IScriptBlock.cs
deleted file mode 100644
index 79d0c1f28..000000000
--- a/Maple2.File.Ingest/Utils/Trigger/IScriptBlock.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System.CodeDom.Compiler;
-
-namespace Maple2.File.Ingest.Utils.Trigger;
-
-internal interface IScriptBlock {
- public bool SingleLine { get; }
- public bool IsCode => true;
-
- public void WriteTo(IndentedTextWriter writer, bool isCommented = false);
-
- public ISet Imports();
-}
-
-internal class Comment : IScriptBlock {
- public bool SingleLine => !Value.Contains('\n');
- public bool IsCode => false;
-
- public readonly string Value;
-
- public Comment(string value) {
- Value = value.Trim();
- }
-
- public void WriteTo(IndentedTextWriter writer, bool isCommented = true) {
- if (Value.Contains('\n')) {
- writer.WriteLine("\"\"\"");
- // TODO: preserve tabbing instead of trimming all
- // str = str.Replace("\t", " ");
- foreach (string line in Value.Split(["\n", "\r\n"], StringSplitOptions.TrimEntries)) {
- writer.WriteLine(line);
- }
- writer.WriteLine("\"\"\"");
- } else {
- writer.WriteLine($"# {Value}");
- }
- }
-
- public ISet Imports() => new HashSet();
-}
-
-internal class CommentWrapper : IScriptBlock {
- public bool SingleLine => Child.SingleLine;
- public bool IsCode => false;
-
- public readonly IScriptBlock Child;
-
- public CommentWrapper(IScriptBlock child) {
- Child = child;
- }
-
- public void WriteTo(IndentedTextWriter writer, bool isCommented = true) {
- if (Child.SingleLine) {
- writer.Write("# ");
- Child.WriteTo(writer, true);
- } else {
- writer.WriteLine("\"\"\""); // Start block comment
- Child.WriteTo(writer, true);
- writer.WriteLine("\"\"\""); // End block comment
- }
- }
-
- public ISet Imports() => new HashSet();
-}
diff --git a/Maple2.File.Ingest/Utils/Trigger/TriggerApiScript.cs b/Maple2.File.Ingest/Utils/Trigger/TriggerApiScript.cs
deleted file mode 100644
index 27309544b..000000000
--- a/Maple2.File.Ingest/Utils/Trigger/TriggerApiScript.cs
+++ /dev/null
@@ -1,308 +0,0 @@
-using System.CodeDom.Compiler;
-using System.Diagnostics;
-
-namespace Maple2.File.Ingest.Utils.Trigger;
-
-internal class TriggerApiScript {
- public readonly SortedDictionary<(string, string?), Function> Actions = new();
- public readonly SortedDictionary Conditions = new();
-
- public void WriteTo(IndentedTextWriter writer) {
- writer.WriteLine("import clr");
- writer.WriteLine("clr.AddReference(\"System.Numerics\")");
- writer.WriteLine("clr.AddReference(\"Maple2.Server.Game\")");
- writer.WriteBlankLine();
- writer.WriteLine("from typing import List");
- writer.WriteLine("from System import Array, Int32, String, Object");
- writer.WriteLine("from System.Numerics import Vector3");
- writer.WriteLine("from Maple2.Server.Game.Scripting.Trigger import Align, FieldGame, Locale, Weather, BannerType");
- writer.WriteBlankLine();
-
- writer.WriteBlankLine();
- writer.WriteLine("class Trigger:");
- writer.Indent++;
- writer.WriteLine("def __init__(self, ctx: ...):");
- writer.Indent++;
- writer.WriteLine("self.ctx = ctx");
- writer.Indent--;
- writer.WriteBlankLine();
- writer.WriteLine("def on_enter(self) -> 'Trigger':");
- writer.Indent++;
- writer.WriteLine(@"""""""Invoked after transitioning to this state.""""""");
- writer.WriteLine("pass");
- writer.Indent--;
- writer.WriteBlankLine();
- writer.WriteLine("def on_tick(self) -> 'Trigger':");
- writer.Indent++;
- writer.WriteLine(@"""""""Periodically invoked while in this state.""""""");
- writer.WriteLine("pass");
- writer.Indent--;
- writer.WriteBlankLine();
- writer.WriteLine("def on_exit(self) -> None:");
- writer.Indent++;
- writer.WriteLine(@"""""""Invoked before transitioning to another state.""""""");
- writer.WriteLine("pass");
- writer.Indent--;
-
- writer.WriteBlankLine();
- writer.WriteLine(@""""""" Actions """"""");
- foreach (Function action in Actions.Values) {
- action.WriteTo(writer);
- writer.WriteBlankLine();
- }
-
- writer.WriteBlankLine();
- writer.WriteLine(@""""""" Conditions """"""");
- foreach (Function condition in Conditions.Values) {
- // These conditions are handled used "and"/"or"
- if (condition.Name is "true" or "always" or "all_of" or "any_one") {
- continue;
- }
-
- condition.WriteTo(writer);
- writer.WriteBlankLine();
- }
-
- writer.Indent--;
- }
-
- public void WriteInterface(IndentedTextWriter writer) {
- writer.WriteLine("using System.Numerics;");
- writer.WriteBlankLine();
- writer.WriteLine("namespace Maple2.Server.Game.Scripting.Trigger;");
- writer.WriteBlankLine();
- writer.WriteLine("public interface ITriggerContext {");
- writer.Indent++;
- writer.WriteLine("// Actions");
- foreach (Function action in Actions.Values) {
- action.WriteInterface(writer);
- writer.WriteBlankLine();
- }
- writer.WriteBlankLine();
- writer.WriteLine("// Conditions");
- foreach (Function condition in Conditions.Values) {
- // These conditions are handled using "and"/"or"
- if (condition.Name is "true" or "always" or "all_of" or "any_one") {
- continue;
- }
-
- condition.WriteInterface(writer);
- writer.WriteBlankLine();
- }
- writer.Indent--;
- writer.WriteLine("}");
- writer.WriteBlankLine();
- }
-
- public void WriteEnums(IndentedTextWriter writer) {
- writer.WriteLine("namespace Maple2.Server.Game.Scripting.Trigger;");
- writer.WriteBlankLine();
- writer.WriteLine("// ReSharper disable InconsistentNaming");
- writer.WriteLine("public enum Align { center = 0, left = 1, right = 2, bottomLeft = 3, bottomRight = 4, topCenter = 5, centerLeft = 6, centerRight = 7 }");
- writer.WriteLine("// ReSharper restore All");
- writer.WriteBlankLine();
- writer.WriteLine("public enum FieldGame { Unknown, HideAndSeek, GuildVsGame, MapleSurvival, MapleSurvivalTeam, WaterGunBattle }");
- writer.WriteBlankLine();
- writer.WriteLine("// ReSharper disable InconsistentNaming");
- writer.WriteLine("public enum Locale { ALL, KR, CN, NA, JP, TH, TW }");
- writer.WriteLine("// ReSharper restore All");
- writer.WriteBlankLine();
- writer.WriteLine("public enum Weather { Clear = 0, Snow = 1, HeavySnow = 2, Rain = 3, HeavyRain = 4, SandStorm = 5, CherryBlossom = 6, LeafFall = 7 }");
- writer.WriteBlankLine();
- writer.WriteLine("public enum BannerType : byte { Lose = 0, GameOver = 1, Winner = 2, Bonus = 3, Draw = 4, Success = 5, Text = 6, Fail = 7, Countdown = 8, }");
- writer.WriteBlankLine();
- writer.WriteLine("public enum SideNpcTalkType : byte { Default = 0, Movie = 1, CutIn = 2, TalkBottom = 3, Invasion = 4, Wedding = 5 }");
- }
-
- internal class Function : IComparable {
- public readonly string Name;
-
- public string? Description = null;
- public ScriptType ReturnType { get; }
- private readonly List parameters = new();
-
- private readonly TriggerDefinitionOverride overrides;
-
- public Function(string name, string? splitArgValue, bool isCondition) {
- Name = name;
-
- if (isCondition) {
- overrides = TriggerDefinitionOverride.ConditionOverride.GetValueOrDefault(name)!;
- Debug.Assert(overrides != null, $"no overrides for {name}");
- ReturnType = ScriptType.Bool;
- if (overrides.Compare.Type != ScriptType.None) {
- ReturnType = overrides.Compare.Type;
- }
- } else {
- overrides = TriggerDefinitionOverride.ActionOverride.GetValueOrDefault(name)!;
- if (splitArgValue != null) {
- overrides = overrides.FunctionLookup[splitArgValue];
- }
- Debug.Assert(overrides != null, $"no overrides for {name}");
- }
- }
-
- public int CompareTo(Function? other) {
- if (ReferenceEquals(this, other)) return 0;
- if (ReferenceEquals(null, other)) return 1;
-
- int nameComparison = string.Compare(Name, other.Name, StringComparison.Ordinal);
- if (nameComparison != 0) return nameComparison;
-
- return ReturnType.CompareTo(other.ReturnType);
- }
-
- // Returns normalized parameter name
- public (ScriptType, string) AddParameter(ScriptType type, string name, string? defaultValue = null) {
- name = TriggerTranslate.ToSnakeCase(name);
- if (overrides.Names.ContainsKey(name)) {
- name = overrides.Names[name];
- }
-
- PyParameter? existing = parameters.FirstOrDefault(param => param.Name == name);
- if (existing != null) {
- return (existing.Type, existing.Name);
- }
-
- if (overrides.Types.ContainsKey(name)) {
- (ScriptType Type, string? Default) typeOverride = overrides.Types[name];
- type = typeOverride.Type;
- defaultValue = typeOverride.Default;
- }
-
- parameters.Add(new PyParameter(type, name, defaultValue));
- return (type, name);
- }
-
- public void WriteTo(IndentedTextWriter writer) {
- writer.Write($"def {overrides.Name}(self");
- PyParameter[] filteredParameters = parameters.Where(p => p.Type != ScriptType.None && !SkipParameter(p)).ToArray();
- PyParameter[] requiredParameters = filteredParameters.Where(p => p.Value == "").ToArray();
- PyParameter[] optionalParameters = filteredParameters.Where(p => p.Value != "").ToArray();
- // Must write required parameters first in function def.
- foreach (PyParameter parameter in requiredParameters) {
- writer.Write(", ");
- writer.Write($"{parameter.Name}: ");
- writer.Write(parameter.TypeStr());
- }
- foreach (PyParameter parameter in optionalParameters) {
- writer.Write(", ");
- writer.Write($"{parameter.Name}: ");
- writer.Write(parameter.TypeStr());
- writer.Write($"={parameter.FormatValue()}"); // Default value
- }
-
- writer.Write(")");
- string returnTypeStr = PyParameter.TypeStr(ReturnType);
- if (!string.IsNullOrWhiteSpace(returnTypeStr)) {
- writer.Write($" -> {returnTypeStr}");
- }
- writer.WriteLine(":");
- writer.Indent++;
-
- // Write docstring
- if (parameters.Count == 0 && string.IsNullOrWhiteSpace(overrides.Description) && string.IsNullOrWhiteSpace(returnTypeStr)) {
- writer.WriteLine($@"""""""{Description}"""""""); // Single-line
- } else {
- writer.WriteLine($@"""""""{Description}");
- if (!string.IsNullOrWhiteSpace(overrides.Description)) {
- writer.WriteBlankLine();
- foreach (string line in overrides.Description.Split(["\n", "\r\n"], StringSplitOptions.None)) {
- writer.WriteLine(line);
- }
- }
- if (parameters.Any(p => !SkipParameter(p))) {
- writer.WriteBlankLine();
- writer.WriteLine("Args:");
- writer.Indent++;
- // Must write required parameters first in function def.
- foreach (PyParameter parameter in requiredParameters) {
- writer.WriteLine($"{parameter.Name} ({parameter.TypeStr()}): _description_.");
- }
- foreach (PyParameter parameter in optionalParameters) {
- writer.WriteLine($"{parameter.Name} ({parameter.TypeStr()}): _description_. Defaults to {parameter.FormatValue()}.");
- }
- writer.Indent--;
- }
- if (!string.IsNullOrWhiteSpace(returnTypeStr)) {
- writer.WriteBlankLine();
- if (overrides.Compare.Type == ScriptType.None) {
- writer.WriteLine("Returns: None");
- } else {
- writer.WriteLine("Returns:");
- writer.Indent++;
- writer.WriteLine($"{returnTypeStr}: {overrides.Compare.Field}");
- writer.Indent--;
- }
- }
- writer.WriteLine(@"""""""");
- }
-
- string pascalName = TriggerTranslate.ToPascalCase(overrides.Name);
- string argString = string.Join(", ", parameters.Where(p => !SkipParameter(p)).Select(p => {
- return p.Type switch {
- ScriptType.IntList => $"Array[Int32]({p.Name})",
- ScriptType.StrList => $"Array[String]({p.Name})",
- ScriptType.StateList => $"Array[Object]({p.Name})",
- _ => p.Name,
- };
- }));
- if (ReturnType != ScriptType.None) {
- writer.WriteLine($"return self.ctx.{pascalName}({argString})");
- } else {
- writer.WriteLine($"self.ctx.{pascalName}({argString})");
- }
- writer.Indent--;
- }
-
- // Skip parameter because it's used for comparison override OR function splitting.
- private bool SkipParameter(PyParameter parameter) {
- if (overrides.FunctionSplitter == parameter.Name) {
- return true;
- }
- if (overrides.Compare.Type == ScriptType.None) {
- return false;
- }
-
- return parameter.Name == overrides.Compare.Field || parameter.Name == overrides.Compare.Op;
- }
-
- private readonly HashSet csReserved = new() { "operator", "event", "string" };
- public void WriteInterface(IndentedTextWriter writer) {
- string pascalName = TriggerTranslate.ToPascalCase(overrides.Name);
- IEnumerable paramList = parameters.Where(p => !SkipParameter(p))
- .Select(p => {
- string paramName = $"{TriggerTranslate.ToCamelName(p.Name)}";
- if (csReserved.Contains(paramName)) {
- paramName = $"@{paramName}";
- }
- return $"{TypeString(p.Type)} {paramName}";
- });
-
- writer.Write($"public {TypeString(ReturnType)} {pascalName}({string.Join(", ", paramList)});");
- return;
-
- string TypeString(ScriptType scriptType) {
- return scriptType switch {
- ScriptType.None => "void",
- ScriptType.Bool => "bool",
- ScriptType.Str => "string",
- ScriptType.Int => "int",
- ScriptType.Float => "float",
- ScriptType.IntList => "int[]",
- ScriptType.StrList => "string[]",
- ScriptType.StateList => "dynamic[]",
- ScriptType.Vector3 => "Vector3",
- ScriptType.State => "dynamic",
- // Enums
- ScriptType.EnumAlign => "Align",
- ScriptType.EnumFieldGame => "FieldGame",
- ScriptType.EnumLocale => "Locale",
- ScriptType.EnumWeather => "Weather",
- ScriptType.EnumBannerType => "BannerType",
- _ => throw new ArgumentOutOfRangeException($"Invalid parameter type: {scriptType}"),
- };
- }
- }
- }
-}
diff --git a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Action.cs b/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Action.cs
deleted file mode 100644
index ed07e6152..000000000
--- a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Action.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System.CodeDom.Compiler;
-using System.Diagnostics;
-using Maple2.Tools.Extensions;
-
-namespace Maple2.File.Ingest.Utils.Trigger;
-
-internal partial class TriggerScript {
- public class Action : IScriptBlock {
- public bool SingleLine => true;
-
- private readonly string? splitName;
- public IList Args = [];
- public string? LineComment;
-
- private readonly TriggerDefinitionOverride? overrides;
-
- public Action(string? name, string? splitArgValue) {
- if (name != null) {
- overrides = TriggerDefinitionOverride.ActionOverride.GetValueOrDefault(name);
- if (splitArgValue != null) {
- overrides = overrides?.FunctionLookup[splitArgValue];
- }
- }
- if (splitArgValue != null) {
- splitName = overrides?.Name;
- }
- }
-
- public virtual void WriteTo(IndentedTextWriter writer, bool isCommented) {
- if (overrides != null) {
- if (LineComment != null && (LineComment.Contains('\n') || LineComment.Length > LineCommentMax)) {
- writer.WriteLineCommentString(LineComment, sameLine: false);
-
- // Set null to avoid writing twice.
- LineComment = null;
- }
-
- foreach ((string? name, _) in overrides.Types.Where(o => o.Value.Default == "")) {
- Debug.Assert(Args.Any(arg => arg.Name == name), $"Action {overrides.Name} is missing required arg: {name}");
- }
-
- IEnumerable args = Args
- .Where(arg => arg.Name != overrides.Compare.Field && arg.Name != overrides.FunctionSplitter)
- .Where(arg => !arg.IsDefault(overrides.Types.GetValueOrDefault(arg.Name).Default))
- .Select(arg => $"{arg.Name}={arg.FormatValue()}");
- writer.Write($"self.{overrides.Name}({string.Join(", ", args)})");
- if (LineComment != null) {
- writer.WriteLineCommentString(LineComment);
- } else {
- writer.WriteBlankLine();
- }
- } else if (LineComment != null) {
- writer.WriteLineCommentString(LineComment, false);
- }
- }
-
- public ISet Imports() {
- return Args.Select(a => a.Import())
- .WhereNotNull()
- .ToHashSet();
- }
- }
-}
diff --git a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Condition.cs b/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Condition.cs
deleted file mode 100644
index b38854ddd..000000000
--- a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Condition.cs
+++ /dev/null
@@ -1,167 +0,0 @@
-using System.CodeDom.Compiler;
-using System.Diagnostics;
-using System.Text.RegularExpressions;
-using Maple2.Tools.Extensions;
-
-namespace Maple2.File.Ingest.Utils.Trigger;
-
-internal partial class TriggerScript {
- public class Condition : IScriptBlock {
- public bool SingleLine => false;
-
- public readonly string Name;
- public readonly List Comments = [];
- public string? LineComment;
-
- public bool Negated;
- public IList Args = [];
- public readonly IList Actions = [];
- public readonly IList Group = [];
- public Transition? Transition;
-
- private readonly TriggerDefinitionOverride overrides;
-
- public Condition(string name) {
- Name = name;
- overrides = TriggerDefinitionOverride.ConditionOverride.GetValueOrDefault(name)!;
- }
-
- public void WriteTo(IndentedTextWriter writer, bool isCommented) {
- writer.WriteComments(Comments);
- if (LineComment != null && (LineComment.Contains('\n') || LineComment.Length > LineCommentMax)) {
- writer.WriteLineCommentString(LineComment, sameLine: false);
-
- // Set null to avoid writing twice.
- LineComment = null;
- }
-
- foreach ((string? argName, _) in overrides.Types.Where(o => o.Value.Default == "")) {
- Debug.Assert(Args.Any(arg => arg.Name == argName), $"Condition {overrides.Name} is missing required arg: {argName}");
- }
-
- bool unconditional = overrides.Name is "true" or "always";
- if (unconditional) {
- if (LineComment != null) {
- writer.WriteLineCommentString(LineComment, sameLine: false);
- }
- } else {
- writer.Write($"if {ConditionString()}:");
- if (LineComment != null) {
- writer.WriteLineCommentString(LineComment);
- } else {
- writer.WriteBlankLine();
- }
- }
-
- if (!unconditional) writer.Indent++;
- {
- bool hasBody = false;
- foreach (IScriptBlock action in Actions) {
- action.WriteTo(writer, isCommented);
- hasBody |= action.IsCode;
- }
- if (Transition != null) {
- Transition.WriteTo(writer, isCommented);
- hasBody = true;
- }
- if (!hasBody) {
- writer.WriteLine("pass");
- }
- }
- if (!unconditional) writer.Indent--;
- }
-
- public ISet Imports() {
- return Actions.SelectMany(a => a.Imports())
- .Concat(Args.Select(a => a.Import()).WhereNotNull())
- .Concat(Group.SelectMany(g => g.Imports()))
- .ToHashSet();
- }
-
- private string ConditionString() {
- // Comparison is overridden.
- if (overrides.Compare.Type != ScriptType.None) {
- string? compareOp;
- if ((compareOp = Args.SingleOrDefault(arg => arg.Name == overrides.Compare.Op)?.Value) == null) {
- if (overrides.Types.TryGetValue(overrides.Compare.Op, out (ScriptType type, string? @default) compare) && compare.@default != null) {
- compareOp = compare.@default;
- } else {
- compareOp = overrides.Compare.Default;
- }
- }
- string? compareValue;
- if ((compareValue = Args.SingleOrDefault(arg => arg.Name == overrides.Compare.Field)?.FormatValue()) == null) {
- if (overrides.Types.TryGetValue(overrides.Compare.Field, out (ScriptType type, string? @default) compare) && compare.@default != null) {
- compareValue = compare.@default;
- } else {
- Debug.Assert(overrides.Compare.Type == ScriptType.Int);
- compareValue = "0";
- }
- }
-
- // We need special parsing here
- if (Name == "widget_condition") {
- (compareOp, compareValue) = NormalizedWidgetCondition(compareOp, compareValue);
- }
- string op = compareOp switch {
- "Equal" or "=" => Negated ? "!=" : "==",
- "Less" or "lower" or "<" => Negated ? ">=" : "<",
- "LessEqual" or "lowerEqual" or "<=" => Negated ? ">" : "<=",
- "Greater" or "higher" or ">" => Negated ? "<=" : ">",
- "GreaterEqual" or "higherEqual" or ">=" => Negated ? "<" : ">=",
- "in" => Negated ? "not in" : "in",
- _ => throw new ArgumentException($"Unexpected comparison operation: {compareOp}"),
- };
-
- foreach ((string? argName, _) in overrides.Types.Where(o => o.Value.Default == "")) {
- Debug.Assert(Args.Any(arg => arg.Name == argName), $"Condition {overrides.Name} is missing required arg: {argName}");
- }
-
- IEnumerable args = Args.Where(arg => arg.Name != overrides.Compare.Field && arg.Name != overrides.Compare.Op)
- .Where(arg => !arg.IsDefault(overrides.Types.GetValueOrDefault(arg.Name).Default))
- .Select(arg => $"{arg.Name}={arg.FormatValue()}");
- if (overrides.Compare.Type == ScriptType.Bool) {
- return compareValue switch {
- "True" => $"self.{overrides.Name}({string.Join(", ", args)})",
- "False" => $"not self.{overrides.Name}({string.Join(", ", args)})",
- _ => throw new ArgumentException($"Invalid bool value for comparison operation: {compareValue}")
- };
- }
- return $"self.{overrides.Name}({string.Join(", ", args)}) {op} {compareValue}";
- }
-
- return Name switch {
- "all_of" => string.Join(" and ", Group.Select(condition => condition.ConditionString())),
- "any_one" => string.Join(" or ", Group.Select(condition => condition.ConditionString())),
- "always" => "True",
- "true" => "True",
- _ => $"{(Negated ? "not " : "")}self.{overrides.Name}({string.Join(", ", Args.Select(arg => $"{arg.Name}={arg.FormatValue()}"))})",
- };
- }
-
- private static (string, string) NormalizedWidgetCondition(string compareOp, string compareValue) {
- if (Regex.Match(compareOp, @"\d+-\d+").Success) {
- compareValue = new PyParameter(ScriptType.IntList, "") {
- Value = compareValue[1..^1],
- }.FormatValue();
- compareOp = "in";
- } else if (int.TryParse(compareOp, out int resultValue)) {
- compareValue = resultValue.ToString();
- compareOp = "=";
- } else if (Regex.Match(compareOp, @"= \d+").Success) {
- compareValue = compareOp.Replace("= ", "");
- compareOp = "=";
- } else if (Regex.Match(compareOp, @"\D\D?,\d+").Success) {
- compareValue = int.Parse(compareOp.Split(",")[1]).ToString();
- compareOp = compareOp.Split(",")[0];
- } else if (compareOp == "") {
- compareValue = "1"; // Use 1 as True
- compareOp = "=";
- } else {
- throw new ArgumentException($"Unknown compare for widget_condition: <{compareOp}>");
- }
-
- return (compareOp, compareValue);
- }
- }
-}
diff --git a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.State.cs b/Maple2.File.Ingest/Utils/Trigger/TriggerScript.State.cs
deleted file mode 100644
index 13faa9d3b..000000000
--- a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.State.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-using System.CodeDom.Compiler;
-
-namespace Maple2.File.Ingest.Utils.Trigger;
-
-internal partial class TriggerScript {
- public class State : IScriptBlock {
- public bool SingleLine => false;
-
- public readonly string Name;
- public readonly List Comments = [];
- public IList OnEnter = [];
- public Transition? OnEnterTransition;
- public IList Conditions = [];
- public IList OnExit = [];
-
- public State(string name) {
- Name = name;
- }
-
- public void WriteTo(IndentedTextWriter writer, bool isCommented) {
- writer.WriteComments(Comments);
- writer.WriteLine($"class {Name}(trigger_api.Trigger):");
- bool hasBody = false;
- writer.Indent++;
- if (OnEnter.Count > 0 || OnEnterTransition != null) {
- bool hasOnEnterBody = false;
- writer.WriteLine("def on_enter(self) -> 'trigger_api.Trigger':");
- writer.Indent++;
- foreach (IScriptBlock action in OnEnter) {
- action.WriteTo(writer, isCommented);
- hasOnEnterBody |= action.IsCode;
- }
- OnEnterTransition?.WriteTo(writer, isCommented);
- hasOnEnterBody |= OnEnterTransition != null;
- if (!hasOnEnterBody) {
- writer.WriteLine("pass");
- }
- writer.Indent--;
- if (Conditions.Count > 0 || OnExit.Count > 0) {
- writer.WriteBlankLine();
- }
- hasBody = true;
- }
- if (Conditions.Count > 0) {
- writer.WriteLine("def on_tick(self) -> trigger_api.Trigger:");
- writer.Indent++;
- foreach (IScriptBlock condition in Conditions) {
- condition.WriteTo(writer, isCommented);
- }
- writer.Indent--;
- if (OnExit.Count > 0) {
- writer.WriteBlankLine();
- }
- hasBody = true;
- }
- if (OnExit.Count > 0) {
- bool hasOnExitBody = false;
- writer.WriteLine("def on_exit(self) -> None:");
- writer.Indent++;
- foreach (IScriptBlock action in OnExit) {
- action.WriteTo(writer, isCommented);
- hasOnExitBody |= action.IsCode;
- }
- if (!hasOnExitBody) {
- writer.WriteLine("pass");
- }
- writer.Indent--;
- hasBody = true;
- }
-
- if (!hasBody) {
- writer.WriteLine("pass");
- }
- writer.Indent--;
- }
-
- public ISet Imports() {
- return Conditions.SelectMany(c => c.Imports())
- .Concat(OnEnter.SelectMany(o => o.Imports()))
- .Concat(OnExit.SelectMany(o => o.Imports()))
- .ToHashSet();
- }
- }
-}
diff --git a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Transition.cs b/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Transition.cs
deleted file mode 100644
index 83d3a0de9..000000000
--- a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.Transition.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.CodeDom.Compiler;
-using System.Diagnostics;
-
-namespace Maple2.File.Ingest.Utils.Trigger;
-
-internal partial class TriggerScript {
- public class Transition(string? state, bool isValid, string? lineComment) {
- public void WriteTo(IndentedTextWriter writer, bool isCommented = false) {
- if (state == null) {
- writer.WriteLine("return None");
- return;
- }
-
- if (lineComment != null && (lineComment.Contains('\n') || lineComment.Length > LineCommentMax || !isValid)) {
- Debug.Assert(!lineComment.StartsWith('<'), lineComment);
- writer.WriteLineCommentString(lineComment, sameLine: false);
-
- // Set null to avoid writing twice.
- lineComment = null;
- }
-
- if (isValid || isCommented) {
- writer.Write($"return {state}(self.ctx)");
- if (lineComment != null) {
- Debug.Assert(!lineComment.StartsWith('<'), lineComment);
- writer.Write($" # {lineComment.Trim()}");
- }
- writer.WriteBlankLine();
- } else {
- writer.WriteLine($"return None # Missing State: {state}");
- }
- }
- }
-}
diff --git a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.cs b/Maple2.File.Ingest/Utils/Trigger/TriggerScript.cs
deleted file mode 100644
index 907554c68..000000000
--- a/Maple2.File.Ingest/Utils/Trigger/TriggerScript.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System.CodeDom.Compiler;
-
-namespace Maple2.File.Ingest.Utils.Trigger;
-
-internal partial class TriggerScript {
- private const int LineCommentMax = 25;
-
- public readonly IList Imports = [];
- public readonly IList States = [];
- public bool Shared { get; init; }
-
- public void WriteTo(IndentedTextWriter writer) {
- writer.WriteLine("import trigger_api");
-
- List enumImports = [];
- foreach (string import in States.SelectMany(s => s.Imports()).Distinct()) {
- switch (import) {
- case "Vector3":
- writer.WriteLine("from System.Numerics import Vector3");
- break;
- case "Align" or "FieldGame" or "Weather" or "Locale" or "BannerType":
- enumImports.Add(import);
- break;
- default:
- throw new ArgumentException($"Unexpected import: {import}");
- }
- }
- if (enumImports.Count > 0) {
- writer.WriteLine($"from Maple2.Server.Game.Scripting.Trigger import {string.Join(", ", enumImports)}");
- }
-
- if (Imports.Count > 0) {
- writer.WriteBlankLine();
- foreach (string import in Imports) {
- writer.WriteLine($"#include {import.Replace('.', '/')}.py");
- writer.WriteLine($"from {import} import *");
- }
- }
- writer.WriteBlankLine();
- writer.WriteBlankLine();
-
- foreach (IScriptBlock state in States) {
- state.WriteTo(writer);
- // Extra line only if this is actual code
- if (state.IsCode) {
- writer.WriteBlankLine();
- }
- writer.WriteBlankLine();
- }
-
- // No initialization for dungeon_common
- if (!Shared) {
- IScriptBlock? block = States.FirstOrDefault(stateEntry => stateEntry is not CommentWrapper);
- if (block is not State) {
- throw new InvalidOperationException("No initial_state found");
- }
-
- var state = (State) block;
-
- writer.WriteLine($"initial_state = {state.Name}");
- }
- }
-}
diff --git a/Maple2.File.Ingest/Utils/TriggerDefinitionOverride.cs b/Maple2.File.Ingest/Utils/TriggerDefinitionOverride.cs
index 91eedf23c..dde5581ea 100644
--- a/Maple2.File.Ingest/Utils/TriggerDefinitionOverride.cs
+++ b/Maple2.File.Ingest/Utils/TriggerDefinitionOverride.cs
@@ -1,5 +1,4 @@
using System.Diagnostics;
-using static Maple2.File.Ingest.Utils.ScriptType;
namespace Maple2.File.Ingest.Utils;
@@ -15,10 +14,10 @@ internal class TriggerDefinitionOverride {
public Dictionary Names { get; init; } = null!;
// Parameter Types
- public Dictionary Types { get; init; } = null!;
+ public Dictionary Types { get; init; } = null!;
// Comparison Operation (Only for Conditions)
- public (ScriptType Type, string Field, string Op, string Default) Compare { get; init; }
+ public (string Field, string Op, string Default) Compare { get; init; }
public string? FunctionSplitter { get; init; }
public Dictionary FunctionLookup { get; init; } = null!;
@@ -28,187 +27,187 @@ private TriggerDefinitionOverride(string name, string? splitter = null) {
FunctionSplitter = splitter;
}
- public static readonly Dictionary ActionOverride = new();
- public static readonly Dictionary ConditionOverride = new();
+ public static readonly Dictionary ActionOverride = new Dictionary();
+ public static readonly Dictionary ConditionOverride = new Dictionary();
static TriggerDefinitionOverride() {
// Action Override
ActionOverride["add_balloon_talk"] = new TriggerDefinitionOverride("add_balloon_talk") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, null), ("duration", Int, null), ("delayTick", Int, null), ("npcID", Int, null)),
+ Types = BuildTypeOverride(("spawnId", null), ("duration", null), ("delayTick", null), ("npcID", null)),
};
ActionOverride["add_buff"] = new TriggerDefinitionOverride("add_buff") {
Names = BuildNameOverride(("arg1", "boxIds"), ("arg2", "skillId"), ("arg3", "level"), ("arg4", "ignorePlayer"), ("arg5", "isSkillSet")),
- Types = BuildTypeOverride(("boxIds", IntList, Required), ("skillId", Int, Required), ("level", Int, Required), ("ignorePlayer", Bool, "True"), ("isSkillSet", Bool, "True")),
+ Types = BuildTypeOverride(("boxIds", Required), ("skillId", Required), ("level", Required), ("ignorePlayer", "True"), ("isSkillSet", "True")),
};
ActionOverride["add_cinematic_talk"] = new TriggerDefinitionOverride("add_cinematic_talk") {
Names = BuildNameOverride(("npcID", "npcId"), ("illustID", "illustId"), ("illust", "illustId"), ("delay", "delayTick")),
- Types = BuildTypeOverride(("npcId", Int, Required), ("duration", Int, null), ("align", EnumAlign, null), ("delayTick", Int, null)),
+ Types = BuildTypeOverride(("npcId", Required), ("duration", null), ("align", null), ("delayTick", null)),
};
ActionOverride["add_effect_nif"] = new TriggerDefinitionOverride("add_effect_nif") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("isOutline", Bool, null), ("scale", Float, null), ("rotateZ", Int, null)),
+ Types = BuildTypeOverride(("spawnId", Required), ("isOutline", null), ("scale", null), ("rotateZ", null)),
};
ActionOverride["add_user_value"] = new TriggerDefinitionOverride("add_user_value") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("value", Int, Required)),
+ Types = BuildTypeOverride(("value", Required)),
};
ActionOverride["allocate_battlefield_points"] = new TriggerDefinitionOverride("allocate_battlefield_points") {
Names = BuildNameOverride(("arg1", "boxId"), ("arg2", "points")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("points", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("points", Required)),
};
ActionOverride["announce"] = new TriggerDefinitionOverride("announce") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "content")),
- Types = BuildTypeOverride(("type", Int, null), ("content", Str, Required), ("arg3", Bool, null)),
+ Types = BuildTypeOverride(("type", null), ("content", Required), ("arg3", null)),
};
ActionOverride["arcade_boom_boom_ocean"] = new TriggerDefinitionOverride(string.Empty) {
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["StartGame"] = new("arcade_boom_boom_ocean_start_game", splitter: "type") {
+ ["StartGame"] = new TriggerDefinitionOverride("arcade_boom_boom_ocean_start_game", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("lifeCount", Int, Required)),
+ Types = BuildTypeOverride(("lifeCount", Required)),
},
- ["EndGame"] = new("arcade_boom_boom_ocean_end_game", splitter: "type") {
+ ["EndGame"] = new TriggerDefinitionOverride("arcade_boom_boom_ocean_end_game", splitter: "type") {
Names = BuildNameOverride(),
Types = BuildTypeOverride(),
},
- ["SetSkillScore"] = new("arcade_boom_boom_ocean_set_skill_score", splitter: "type") {
+ ["SetSkillScore"] = new TriggerDefinitionOverride("arcade_boom_boom_ocean_set_skill_score", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("type", Str, Required), ("id", Int, Required), ("score", Int, Required)),
+ Types = BuildTypeOverride(("type", Required), ("id", Required), ("score", Required)),
},
- ["StartRound"] = new("arcade_boom_boom_ocean_start_round", splitter: "type") {
+ ["StartRound"] = new TriggerDefinitionOverride("arcade_boom_boom_ocean_start_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("type", Str, Required), ("round", Int, Required), ("roundDuration", Int, Required), ("timeScoreRate", Int, Required)),
+ Types = BuildTypeOverride(("type", Required), ("round", Required), ("roundDuration", Required), ("timeScoreRate", Required)),
},
- ["ClearRound"] = new("arcade_boom_boom_ocean_clear_round", splitter: "type") {
+ ["ClearRound"] = new TriggerDefinitionOverride("arcade_boom_boom_ocean_clear_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("type", Str, Required), ("round", Int, Required)),
+ Types = BuildTypeOverride(("type", Required), ("round", Required)),
},
},
};
ActionOverride["arcade_spring_farm"] = new TriggerDefinitionOverride("") {
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["StartGame"] = new("arcade_spring_farm_start_game", splitter: "type") {
+ ["StartGame"] = new TriggerDefinitionOverride("arcade_spring_farm_start_game", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("lifeCount", Int, Required)),
+ Types = BuildTypeOverride(("lifeCount", Required)),
},
- ["EndGame"] = new("arcade_spring_farm_end_game", splitter: "type") {
+ ["EndGame"] = new TriggerDefinitionOverride("arcade_spring_farm_end_game", splitter: "type") {
Names = BuildNameOverride(),
Types = BuildTypeOverride(),
},
- ["SetInteractScore"] = new("arcade_spring_farm_set_interact_score", splitter: "type") {
+ ["SetInteractScore"] = new TriggerDefinitionOverride("arcade_spring_farm_set_interact_score", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("id", Int, Required), ("score", Int, Required)),
+ Types = BuildTypeOverride(("id", Required), ("score", Required)),
},
- ["SpawnMonster"] = new("arcade_spring_farm_spawn_monster", splitter: "type") {
+ ["SpawnMonster"] = new TriggerDefinitionOverride("arcade_spring_farm_spawn_monster", splitter: "type") {
Names = BuildNameOverride(("spawnID", "spawnIds")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required), ("score", Int, Required)),
+ Types = BuildTypeOverride(("spawnIds", Required), ("score", Required)),
},
- ["StartRound"] = new("arcade_spring_farm_start_round", splitter: "type") {
+ ["StartRound"] = new TriggerDefinitionOverride("arcade_spring_farm_start_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("uiDuration", Int, Required), ("round", Int, Required), ("roundDuration", Int, Required), ("timeScoreType", Str, Required), ("timeScoreRate", Int, Required)),
+ Types = BuildTypeOverride(("uiDuration", Required), ("round", Required), ("roundDuration", Required), ("timeScoreType", Required), ("timeScoreRate", Required)),
},
- ["ClearRound"] = new("arcade_spring_farm_clear_round", splitter: "type") {
+ ["ClearRound"] = new TriggerDefinitionOverride("arcade_spring_farm_clear_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
},
};
ActionOverride["arcade_three_two_one"] = new TriggerDefinitionOverride("") {
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["StartGame"] = new("arcade_three_two_one_start_game", splitter: "type") {
+ ["StartGame"] = new TriggerDefinitionOverride("arcade_three_two_one_start_game", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("lifeCount", Int, Required), ("initScore", Int, Required)),
+ Types = BuildTypeOverride(("lifeCount", Required), ("initScore", Required)),
},
- ["EndGame"] = new("arcade_three_two_one_end_game", splitter: "type") {
+ ["EndGame"] = new TriggerDefinitionOverride("arcade_three_two_one_end_game", splitter: "type") {
Names = BuildNameOverride(),
Types = BuildTypeOverride(),
},
- ["StartRound"] = new("arcade_three_two_one_start_round", splitter: "type") {
+ ["StartRound"] = new TriggerDefinitionOverride("arcade_three_two_one_start_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("uiDuration", Int, Required), ("round", Int, Required)),
+ Types = BuildTypeOverride(("uiDuration", Required), ("round", Required)),
},
- ["ResultRound"] = new("arcade_three_two_one_result_round", splitter: "type") {
+ ["ResultRound"] = new TriggerDefinitionOverride("arcade_three_two_one_result_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("resultDirection", Int, Required)),
+ Types = BuildTypeOverride(("resultDirection", Required)),
},
- ["ResultRound2"] = new("arcade_three_two_one_result_round2", splitter: "type") {
+ ["ResultRound2"] = new TriggerDefinitionOverride("arcade_three_two_one_result_round2", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
- ["ClearRound"] = new("arcade_three_two_one_clear_round", splitter: "type") {
+ ["ClearRound"] = new TriggerDefinitionOverride("arcade_three_two_one_clear_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
},
};
ActionOverride["arcade_three_two_one2"] = new TriggerDefinitionOverride("") {
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["StartGame"] = new("arcade_three_two_one2_start_game", splitter: "type") {
+ ["StartGame"] = new TriggerDefinitionOverride("arcade_three_two_one2_start_game", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("lifeCount", Int, Required), ("initScore", Int, Required)),
+ Types = BuildTypeOverride(("lifeCount", Required), ("initScore", Required)),
},
- ["EndGame"] = new("arcade_three_two_one2_end_game", splitter: "type") {
+ ["EndGame"] = new TriggerDefinitionOverride("arcade_three_two_one2_end_game", splitter: "type") {
Names = BuildNameOverride(),
Types = BuildTypeOverride(),
},
- ["StartRound"] = new("arcade_three_two_one2_start_round", splitter: "type") {
+ ["StartRound"] = new TriggerDefinitionOverride("arcade_three_two_one2_start_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("uiDuration", Int, Required), ("round", Int, Required)),
+ Types = BuildTypeOverride(("uiDuration", Required), ("round", Required)),
},
- ["ResultRound"] = new("arcade_three_two_one2_result_round", splitter: "type") {
+ ["ResultRound"] = new TriggerDefinitionOverride("arcade_three_two_one2_result_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("resultDirection", Int, Required)),
+ Types = BuildTypeOverride(("resultDirection", Required)),
},
- ["ResultRound2"] = new("arcade_three_two_one2_result_round2", splitter: "type") {
+ ["ResultRound2"] = new TriggerDefinitionOverride("arcade_three_two_one2_result_round2", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
- ["ClearRound"] = new("arcade_three_two_one2_clear_round", splitter: "type") {
+ ["ClearRound"] = new TriggerDefinitionOverride("arcade_three_two_one2_clear_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
},
};
ActionOverride["arcade_three_two_one3"] = new TriggerDefinitionOverride("") {
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["StartGame"] = new("arcade_three_two_one3_start_game", splitter: "type") {
+ ["StartGame"] = new TriggerDefinitionOverride("arcade_three_two_one3_start_game", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("lifeCount", Int, Required), ("initScore", Int, Required)),
+ Types = BuildTypeOverride(("lifeCount", Required), ("initScore", Required)),
},
- ["EndGame"] = new("arcade_three_two_one3_end_game", splitter: "type") {
+ ["EndGame"] = new TriggerDefinitionOverride("arcade_three_two_one3_end_game", splitter: "type") {
Names = BuildNameOverride(),
Types = BuildTypeOverride(),
},
- ["StartRound"] = new("arcade_three_two_one3_start_round", splitter: "type") {
+ ["StartRound"] = new TriggerDefinitionOverride("arcade_three_two_one3_start_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("uiDuration", Int, Required), ("round", Int, Required)),
+ Types = BuildTypeOverride(("uiDuration", Required), ("round", Required)),
},
- ["ResultRound"] = new("arcade_three_two_one3_result_round", splitter: "type") {
+ ["ResultRound"] = new TriggerDefinitionOverride("arcade_three_two_one3_result_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("resultDirection", Int, Required)),
+ Types = BuildTypeOverride(("resultDirection", Required)),
},
- ["ResultRound2"] = new("arcade_three_two_one3_result_round2", splitter: "type") {
+ ["ResultRound2"] = new TriggerDefinitionOverride("arcade_three_two_one3_result_round2", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
- ["ClearRound"] = new("arcade_three_two_one3_clear_round", splitter: "type") {
+ ["ClearRound"] = new TriggerDefinitionOverride("arcade_three_two_one3_clear_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
},
};
ActionOverride["change_background"] = new TriggerDefinitionOverride("change_background") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("dds", Str, Required)),
+ Types = BuildTypeOverride(("dds", Required)),
};
ActionOverride["change_monster"] = new TriggerDefinitionOverride("change_monster") {
Names = BuildNameOverride(("arg1", "fromSpawnId"), ("arg2", "toSpawnId")),
- Types = BuildTypeOverride(("fromSpawnId", Int, Required), ("toSpawnId", Int, Required)),
+ Types = BuildTypeOverride(("fromSpawnId", Required), ("toSpawnId", Required)),
};
ActionOverride["close_cinematic"] = new TriggerDefinitionOverride("close_cinematic") {
Names = BuildNameOverride(),
@@ -216,56 +215,56 @@ static TriggerDefinitionOverride() {
};
ActionOverride["create_field_game"] = new TriggerDefinitionOverride("create_field_game") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("type", EnumFieldGame, Required), ("reset", Bool, null)),
+ Types = BuildTypeOverride(("type", Required), ("reset", null)),
};
ActionOverride["create_item"] = new TriggerDefinitionOverride("create_item") {
Names = BuildNameOverride(("arg1", "spawnIds"), ("arg2", "triggerId"), ("arg3", "itemId")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required), ("triggerId", Int, null), ("itemId", Int, null), ("arg5", Int, null)),
+ Types = BuildTypeOverride(("spawnIds", Required), ("triggerId", null), ("itemId", null), ("arg5", null)),
};
ActionOverride["spawn_monster"] = new TriggerDefinitionOverride("spawn_monster") {
Names = BuildNameOverride(("arg1", "spawnIds"), ("arg2", "autoTarget"), ("agr2", "autoTarget"), ("arg", "autoTarget"), ("arg3", "delay")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required), ("autoTarget", Bool, "True"), ("delay", Int, null)),
+ Types = BuildTypeOverride(("spawnIds", Required), ("autoTarget", "True"), ("delay", null)),
};
ActionOverride["create_widget"] = new TriggerDefinitionOverride("create_widget") {
Names = BuildNameOverride(("arg1", "type")),
- Types = BuildTypeOverride(("type", Str, Required)),
+ Types = BuildTypeOverride(("type", Required)),
};
ActionOverride["dark_stream"] = new TriggerDefinitionOverride("dark_stream") {
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["StartGame"] = new("dark_stream_start_game", splitter: "type") {
+ ["StartGame"] = new TriggerDefinitionOverride("dark_stream_start_game", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
- ["SpawnMonster"] = new("dark_stream_spawn_monster", splitter: "type") {
+ ["SpawnMonster"] = new TriggerDefinitionOverride("dark_stream_spawn_monster", splitter: "type") {
Names = BuildNameOverride(("spawnID", "spawnIds")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required), ("score", Int, Required)),
+ Types = BuildTypeOverride(("spawnIds", Required), ("score", Required)),
},
- ["StartRound"] = new("dark_stream_start_round", splitter: "type") {
+ ["StartRound"] = new TriggerDefinitionOverride("dark_stream_start_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("uiDuration", Int, Required), ("round", Int, Required), ("damagePenalty", Int, Required)),
+ Types = BuildTypeOverride(("uiDuration", Required), ("round", Required), ("damagePenalty", Required)),
},
- ["ClearRound"] = new("dark_stream_clear_round", splitter: "type") {
+ ["ClearRound"] = new TriggerDefinitionOverride("dark_stream_clear_round", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
},
},
};
ActionOverride["debug_string"] = new TriggerDefinitionOverride("debug_string") {
Names = BuildNameOverride(("arg1", "value"), ("string", "value")),
- Types = BuildTypeOverride(("value", Str, Required)),
+ Types = BuildTypeOverride(("value", Required)),
};
ActionOverride["destroy_monster"] = new TriggerDefinitionOverride("destroy_monster") {
Names = BuildNameOverride(("arg1", "spawnIds"), ("agr2", "arg2")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required), ("arg2", Bool, "True")),
+ Types = BuildTypeOverride(("spawnIds", Required), ("arg2", "True")),
};
ActionOverride["dungeon_clear"] = new TriggerDefinitionOverride("dungeon_clear") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("uiType", Str, null)),
+ Types = BuildTypeOverride(("uiType", null)),
};
ActionOverride["dungeon_clear_round"] = new TriggerDefinitionOverride("dungeon_clear_round") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
+ Types = BuildTypeOverride(("round", Required)),
};
ActionOverride["dungeon_close_timer"] = new TriggerDefinitionOverride("dungeon_close_timer") {
@@ -280,7 +279,7 @@ static TriggerDefinitionOverride() {
ActionOverride["dungeon_enable_give_up"] = new TriggerDefinitionOverride("dungeon_enable_give_up") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("isEnable", Bool, null)),
+ Types = BuildTypeOverride(("isEnable", null)),
};
ActionOverride["dungeon_fail"] = new TriggerDefinitionOverride("dungeon_fail") {
@@ -290,17 +289,17 @@ static TriggerDefinitionOverride() {
ActionOverride["dungeon_mission_complete"] = new TriggerDefinitionOverride("dungeon_mission_complete") {
Names = BuildNameOverride(("missionID", "missionId")),
- Types = BuildTypeOverride(("missionId", Int, Required)),
+ Types = BuildTypeOverride(("missionId", Required)),
};
ActionOverride["dungeon_move_lap_time_to_now"] = new TriggerDefinitionOverride("dungeon_move_lap_time_to_now") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("id", Int, Required)),
+ Types = BuildTypeOverride(("id", Required)),
};
ActionOverride["dungeon_reset_time"] = new TriggerDefinitionOverride("dungeon_reset_time") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("seconds", Int, Required)),
+ Types = BuildTypeOverride(("seconds", Required)),
};
ActionOverride["dungeon_set_end_time"] = new TriggerDefinitionOverride("dungeon_set_end_time") {
@@ -310,7 +309,7 @@ static TriggerDefinitionOverride() {
ActionOverride["dungeon_set_lap_time"] = new TriggerDefinitionOverride("dungeon_set_lap_time") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("id", Int, Required), ("lapTime", Int, null)),
+ Types = BuildTypeOverride(("id", Required), ("lapTime", null)),
};
ActionOverride["dungeon_stop_timer"] = new TriggerDefinitionOverride("dungeon_stop_timer") {
@@ -319,55 +318,55 @@ static TriggerDefinitionOverride() {
};
ActionOverride["dungeon_variable"] = new TriggerDefinitionOverride("set_dungeon_variable") {
Names = BuildNameOverride(("varID", "varId")),
- Types = BuildTypeOverride(("varId", Int, Required), ("value", Int, Required)),
+ Types = BuildTypeOverride(("varId", Required), ("value", Required)),
};
ActionOverride["enable_local_camera"] = new TriggerDefinitionOverride("enable_local_camera") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("isEnable", Bool, null)),
+ Types = BuildTypeOverride(("isEnable", null)),
};
ActionOverride["enable_spawn_point_pc"] = new TriggerDefinitionOverride("enable_spawn_point_pc") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("isEnable", Bool, null)),
+ Types = BuildTypeOverride(("spawnId", Required), ("isEnable", null)),
};
ActionOverride["end_mini_game"] = new TriggerDefinitionOverride("end_mini_game") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("winnerBoxId", Int, null), ("isEnable", Bool, null), ("isOnlyWinner", Bool, null)),
+ Types = BuildTypeOverride(("winnerBoxId", null), ("isEnable", null), ("isOnlyWinner", null)),
};
ActionOverride["end_mini_game_round"] = new TriggerDefinitionOverride("end_mini_game_round") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("winnerBoxId", Int, Required), ("expRate", Float, null), ("meso", Float, null), ("isOnlyWinner", Bool, null), ("isGainLoserBonus", Bool, null)),
+ Types = BuildTypeOverride(("winnerBoxId", Required), ("expRate", null), ("meso", null), ("isOnlyWinner", null), ("isGainLoserBonus", null)),
};
ActionOverride["face_emotion"] = new TriggerDefinitionOverride("face_emotion") {
Names = BuildNameOverride(("spawnPointID", "spawnId"), ("spwnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, null)),
+ Types = BuildTypeOverride(("spawnId", null)),
};
ActionOverride["field_game_constant"] = new TriggerDefinitionOverride("field_game_constant") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("key", Str, Required), ("value", Str, Required), ("locale", EnumLocale, null)),
+ Types = BuildTypeOverride(("key", Required), ("value", Required), ("locale", null)),
};
ActionOverride["field_game_message"] = new TriggerDefinitionOverride("field_game_message") {
Names = BuildNameOverride(("arg2", "script"), ("arg3", "duration")),
- Types = BuildTypeOverride(("custom", Int, null), ("type", Str, Required), ("duration", Int, null), ("arg1", Bool, null), ("script", Str, Required)),
+ Types = BuildTypeOverride(("custom", null), ("type", Required), ("duration", null), ("arg1", null), ("script", Required)),
};
ActionOverride["field_war_end"] = new TriggerDefinitionOverride("field_war_end") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("isClear", Bool, null)),
+ Types = BuildTypeOverride(("isClear", null)),
};
ActionOverride["give_exp"] = new TriggerDefinitionOverride("give_exp") {
Names = BuildNameOverride(("arg1", "boxId"), ("arg2", "rate")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("rate", Float, "1.0"), ("arg3", Bool, null)),
+ Types = BuildTypeOverride(("boxId", Required), ("rate", "1.0"), ("arg3", null)),
};
ActionOverride["give_guild_exp"] = new TriggerDefinitionOverride("give_guild_exp") {
Names = BuildNameOverride(("boxID", "boxId")),
- Types = BuildTypeOverride(("boxId", Int, null), ("type", Int, Required)),
+ Types = BuildTypeOverride(("boxId", null), ("type", Required)),
};
ActionOverride["give_reward_content"] = new TriggerDefinitionOverride("give_reward_content") {
Names = BuildNameOverride(("rewardID", "rewardId")),
- Types = BuildTypeOverride(("rewardId", Int, Required)),
+ Types = BuildTypeOverride(("rewardId", Required)),
};
ActionOverride["guide_event"] = new TriggerDefinitionOverride("guide_event") {
Names = BuildNameOverride(("eventID", "eventId")),
- Types = BuildTypeOverride(("eventId", Int, Required)),
+ Types = BuildTypeOverride(("eventId", Required)),
};
ActionOverride["guild_vs_game_end_game"] = new TriggerDefinitionOverride("guild_vs_game_end_game") {
Names = BuildNameOverride(),
@@ -375,11 +374,11 @@ static TriggerDefinitionOverride() {
};
ActionOverride["guild_vs_game_give_contribution"] = new TriggerDefinitionOverride("guild_vs_game_give_contribution") {
Names = BuildNameOverride(("teamID", "teamId")),
- Types = BuildTypeOverride(("teamId", Int, Required), ("isWin", Bool, null)),
+ Types = BuildTypeOverride(("teamId", Required), ("isWin", null)),
};
ActionOverride["guild_vs_game_give_reward"] = new TriggerDefinitionOverride("guild_vs_game_give_reward") {
Names = BuildNameOverride(("teamID", "teamId")),
- Types = BuildTypeOverride(("teamId", Int, Required), ("isWin", Bool, null)),
+ Types = BuildTypeOverride(("teamId", Required), ("isWin", null)),
};
ActionOverride["guild_vs_game_log_result"] = new TriggerDefinitionOverride("guild_vs_game_log_result") {
Names = BuildNameOverride(),
@@ -387,7 +386,7 @@ static TriggerDefinitionOverride() {
};
ActionOverride["guild_vs_game_log_won_by_default"] = new TriggerDefinitionOverride("guild_vs_game_log_won_by_default") {
Names = BuildNameOverride(("teamID", "teamId")),
- Types = BuildTypeOverride(("teamId", Int, Required)),
+ Types = BuildTypeOverride(("teamId", Required)),
};
ActionOverride["guild_vs_game_result"] = new TriggerDefinitionOverride("guild_vs_game_result") {
Names = BuildNameOverride(),
@@ -395,111 +394,111 @@ static TriggerDefinitionOverride() {
};
ActionOverride["guild_vs_game_score_by_user"] = new TriggerDefinitionOverride("guild_vs_game_score_by_user") {
Names = BuildNameOverride(("triggerBoxID", "boxId")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("score", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("score", Required)),
};
ActionOverride["hide_guide_summary"] = new TriggerDefinitionOverride("hide_guide_summary") {
Names = BuildNameOverride(("entityID", "entityId"), ("textID", "textId")),
- Types = BuildTypeOverride(("entityId", Int, Required), ("textId", Int, null)),
+ Types = BuildTypeOverride(("entityId", Required), ("textId", null)),
};
ActionOverride["init_npc_rotation"] = new TriggerDefinitionOverride("init_npc_rotation") {
Names = BuildNameOverride(("arg1", "spawnIds")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required)),
+ Types = BuildTypeOverride(("spawnIds", Required)),
};
ActionOverride["kick_music_audience"] = new TriggerDefinitionOverride("kick_music_audience") {
Names = BuildNameOverride(("targetBoxID", "boxId"), ("targetPortalID", "portalId")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("portalId", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("portalId", Required)),
};
ActionOverride["limit_spawn_npc_count"] = new TriggerDefinitionOverride("limit_spawn_npc_count") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("limitCount", Int, Required)),
+ Types = BuildTypeOverride(("limitCount", Required)),
};
ActionOverride["lock_my_pc"] = new TriggerDefinitionOverride("lock_my_pc") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("isLock", Bool, null)),
+ Types = BuildTypeOverride(("isLock", null)),
};
ActionOverride["mini_game_camera_direction"] = new TriggerDefinitionOverride("mini_game_camera_direction") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("boxId", Int, Required), ("cameraId", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("cameraId", Required)),
};
ActionOverride["mini_game_give_exp"] = new TriggerDefinitionOverride("mini_game_give_exp") {
Names = BuildNameOverride(("isOutSide", "isOutside")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("expRate", Float, "1.0"), ("isOutside", Bool, null)),
+ Types = BuildTypeOverride(("boxId", Required), ("expRate", "1.0"), ("isOutside", null)),
};
ActionOverride["mini_game_give_reward"] = new TriggerDefinitionOverride("mini_game_give_reward") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("winnerBoxId", Int, Required), ("contentType", Str, Required)),
+ Types = BuildTypeOverride(("winnerBoxId", Required), ("contentType", Required)),
};
ActionOverride["move_npc"] = new TriggerDefinitionOverride("move_npc") {
Names = BuildNameOverride(("arg1", "spawnId"), ("arg2", "patrolName")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("patrolName", Str, Required)),
+ Types = BuildTypeOverride(("spawnId", Required), ("patrolName", Required)),
};
ActionOverride["move_npc_to_pos"] = new TriggerDefinitionOverride("move_npc_to_pos") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("pos", Vector3, Required), ("rot", Vector3, Required)),
+ Types = BuildTypeOverride(("spawnId", Required), ("pos", Required), ("rot", Required)),
};
ActionOverride["move_random_user"] = new TriggerDefinitionOverride("move_random_user") {
Names = BuildNameOverride(("arg1", "mapId"), ("arg2", "portalId"), ("arg3", "boxId"), ("arg4", "count")),
- Types = BuildTypeOverride(("mapId", Int, Required), ("portalId", Int, Required), ("boxId", Int, Required), ("count", Int, Required)),
+ Types = BuildTypeOverride(("mapId", Required), ("portalId", Required), ("boxId", Required), ("count", Required)),
};
ActionOverride["move_to_portal"] = new TriggerDefinitionOverride("move_to_portal") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("userTagId", Int, null), ("portalId", Int, null), ("boxId", Int, null)),
+ Types = BuildTypeOverride(("userTagId", null), ("portalId", null), ("boxId", null)),
};
ActionOverride["move_user"] = new TriggerDefinitionOverride("move_user") {
Names = BuildNameOverride(("arg1", "mapId"), ("arg2", "portalId"), ("arg3", "boxId")),
- Types = BuildTypeOverride(("mapId", Int, null), ("portalId", Int, null), ("boxId", Int, null)),
+ Types = BuildTypeOverride(("mapId", null), ("portalId", null), ("boxId", null)),
};
ActionOverride["move_user_path"] = new TriggerDefinitionOverride("move_user_path") {
Names = BuildNameOverride(("arg1", "patrolName")),
- Types = BuildTypeOverride(("patrolName", Str, Required)),
+ Types = BuildTypeOverride(("patrolName", Required)),
};
ActionOverride["move_user_to_box"] = new TriggerDefinitionOverride("move_user_to_box") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("boxId", Int, Required), ("portalId", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("portalId", Required)),
};
ActionOverride["move_user_to_pos"] = new TriggerDefinitionOverride("move_user_to_pos") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("pos", Vector3, Required), ("rot", Vector3, null)),
+ Types = BuildTypeOverride(("pos", Required), ("rot", null)),
};
ActionOverride["notice"] = new TriggerDefinitionOverride("notice") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script")),
- Types = BuildTypeOverride(("type", Int, null), ("script", Str, Required), ("arg3", Bool, null)),
+ Types = BuildTypeOverride(("type", null), ("script", Required), ("arg3", null)),
};
ActionOverride["npc_remove_additional_effect"] = new TriggerDefinitionOverride("npc_remove_additional_effect") {
Names = BuildNameOverride(("spawnPointID", "spawnId"), ("additionalEffectID", "additionalEffectId")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("additionalEffectId", Int, Required)),
+ Types = BuildTypeOverride(("spawnId", Required), ("additionalEffectId", Required)),
};
ActionOverride["npc_to_patrol_in_box"] = new TriggerDefinitionOverride("npc_to_patrol_in_box") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("boxId", Int, Required), ("npcId", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("npcId", Required)),
};
ActionOverride["patrol_condition_user"] = new TriggerDefinitionOverride("patrol_condition_user") {
Names = BuildNameOverride(("additionalEffectID", "additionalEffectId")),
- Types = BuildTypeOverride(("patrolIndex", Int, Required), ("additionalEffectId", Int, Required)),
+ Types = BuildTypeOverride(("patrolIndex", Required), ("additionalEffectId", Required)),
};
ActionOverride["play_scene_movie"] = new TriggerDefinitionOverride("play_scene_movie") {
Names = BuildNameOverride(("movieID", "movieId")),
- Types = BuildTypeOverride(("movieId", Int, null)),
+ Types = BuildTypeOverride(("movieId", null)),
};
ActionOverride["play_system_sound_by_user_tag"] = new TriggerDefinitionOverride("play_system_sound_by_user_tag") {
Names = BuildNameOverride(("userTagID", "userTagId")),
- Types = BuildTypeOverride(("userTagId", Int, Required), ("soundKey", Str, Required)),
+ Types = BuildTypeOverride(("userTagId", Required), ("soundKey", Required)),
};
ActionOverride["play_system_sound_in_box"] = new TriggerDefinitionOverride("play_system_sound_in_box") {
Names = BuildNameOverride(("arg1", "boxIds"), ("arg2", "sound")),
- Types = BuildTypeOverride(("boxIds", IntList, null), ("sound", Str, Required)),
+ Types = BuildTypeOverride(("boxIds", null), ("sound", Required)),
};
ActionOverride["random_additional_effect"] = new TriggerDefinitionOverride("random_additional_effect") {
Names = BuildNameOverride(("Target", "target"), ("triggerBoxID", "boxId"), ("spawnPointID", "spawnId"), ("arg1", "boxIds"), ("additionalEffectID", "additionalEffectId")),
- Types = BuildTypeOverride(("boxId", Int, null), ("spawnId", Int, null), ("targetCount", Int, null), ("tick", Int, null), ("waitTick", Int, null), ("additionalEffectId", Int, null)),
+ Types = BuildTypeOverride(("boxId", null), ("spawnId", null), ("targetCount", null), ("tick", null), ("waitTick", null), ("additionalEffectId", null)),
};
ActionOverride["remove_balloon_talk"] = new TriggerDefinitionOverride("remove_balloon_talk") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, null)),
+ Types = BuildTypeOverride(("spawnId", null)),
};
ActionOverride["remove_buff"] = new TriggerDefinitionOverride("remove_buff") {
Names = BuildNameOverride(("arg1", "boxId"), ("arg2", "skillId"), ("arg3", "isPlayer")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("skillId", Int, Required), ("isPlayer", Bool, null)),
+ Types = BuildTypeOverride(("boxId", Required), ("skillId", Required), ("isPlayer", null)),
};
ActionOverride["remove_cinematic_talk"] = new TriggerDefinitionOverride("remove_cinematic_talk") {
Names = BuildNameOverride(),
@@ -507,11 +506,11 @@ static TriggerDefinitionOverride() {
};
ActionOverride["remove_effect_nif"] = new TriggerDefinitionOverride("remove_effect_nif") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, Required)),
+ Types = BuildTypeOverride(("spawnId", Required)),
};
ActionOverride["reset_camera"] = new TriggerDefinitionOverride("reset_camera") {
Names = BuildNameOverride(("arg1", "interpolationTime"), ("arg2", "interpolationTime")),
- Types = BuildTypeOverride(("interpolationTime", Float, null)),
+ Types = BuildTypeOverride(("interpolationTime", null)),
};
ActionOverride["reset_timer"] = new TriggerDefinitionOverride("reset_timer") {
Names = BuildNameOverride(("arg1", "timerId")),
@@ -523,7 +522,7 @@ static TriggerDefinitionOverride() {
};
ActionOverride["score_board_create"] = new TriggerDefinitionOverride("score_board_create") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("type", Str, null), ("title", Str, null), ("maxScore", Int, null)),
+ Types = BuildTypeOverride(("type", null), ("title", null), ("maxScore", null)),
};
ActionOverride["score_board_remove"] = new TriggerDefinitionOverride("score_board_remove") {
Names = BuildNameOverride(),
@@ -531,39 +530,39 @@ static TriggerDefinitionOverride() {
};
ActionOverride["score_board_set_score"] = new TriggerDefinitionOverride("score_board_set_score") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("score", Int, Required)),
+ Types = BuildTypeOverride(("score", Required)),
};
ActionOverride["select_camera"] = new TriggerDefinitionOverride("select_camera") {
Names = BuildNameOverride(("arg1", "triggerId"), ("arg2", "enable")),
- Types = BuildTypeOverride(("triggerId", Int, Required), ("enable", Bool, "True")),
+ Types = BuildTypeOverride(("triggerId", Required), ("enable", "True")),
};
ActionOverride["select_camera_path"] = new TriggerDefinitionOverride("select_camera_path") {
Names = BuildNameOverride(("arg1", "pathIds"), ("arg2", "returnView")),
- Types = BuildTypeOverride(("pathIds", IntList, Required), ("returnView", Bool, "True")),
+ Types = BuildTypeOverride(("pathIds", Required), ("returnView", "True")),
};
ActionOverride["set_achievement"] = new TriggerDefinitionOverride("set_achievement") {
Names = BuildNameOverride(("arg1", "triggerId"), ("arg2", "type"), ("arg3", "achieve")),
- Types = BuildTypeOverride(("triggerId", Int, null)),
+ Types = BuildTypeOverride(("triggerId", null)),
};
ActionOverride["set_actor"] = new TriggerDefinitionOverride("set_actor") {
Names = BuildNameOverride(("arg1", "triggerId"), ("arg2", "visible"), ("arg3", "initialSequence")),
- Types = BuildTypeOverride(("triggerId", Int, Required), ("visible", Bool, null), ("arg4", Bool, null), ("arg5", Bool, null)),
+ Types = BuildTypeOverride(("triggerId", Required), ("visible", null), ("arg4", null), ("arg5", null)),
};
ActionOverride["set_agent"] = new TriggerDefinitionOverride("set_agent") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "visible")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("visible", Bool, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("visible", null)),
};
ActionOverride["set_ai_extra_data"] = new TriggerDefinitionOverride("set_ai_extra_data") {
Names = BuildNameOverride(("boxID", "boxId")),
- Types = BuildTypeOverride(("key", Str, Required), ("value", Int, Required), ("isModify", Bool, null), ("boxId", Int, null)),
+ Types = BuildTypeOverride(("key", Required), ("value", Required), ("isModify", null), ("boxId", null)),
};
ActionOverride["set_ambient_light"] = new TriggerDefinitionOverride("set_ambient_light") {
Names = BuildNameOverride(("arg1", "primary"), ("arg2", "secondary"), ("arg3", "tertiary")),
- Types = BuildTypeOverride(("primary", Vector3, Required), ("secondary", Vector3, null), ("tertiary", Vector3, null)),
+ Types = BuildTypeOverride(("primary", Required), ("secondary", null), ("tertiary", null)),
};
ActionOverride["set_breakable"] = new TriggerDefinitionOverride("set_breakable") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "enable")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("enable", Bool, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("enable", null)),
};
ActionOverride["set_cinematic_intro"] = new TriggerDefinitionOverride("set_cinematic_intro") {
Names = BuildNameOverride(),
@@ -571,209 +570,209 @@ static TriggerDefinitionOverride() {
};
ActionOverride["set_cinematic_ui"] = new TriggerDefinitionOverride("set_cinematic_ui") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script")),
- Types = BuildTypeOverride(("type", Int, Required), ("script", Str, null), ("arg3", Bool, null)),
+ Types = BuildTypeOverride(("type", Required), ("script", null), ("arg3", null)),
};
ActionOverride["set_dialogue"] = new TriggerDefinitionOverride("set_dialogue") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "spawnId"), ("arg3", "script"), ("arg4", "time")),
- Types = BuildTypeOverride(("type", Int, Required), ("spawnId", Int, null), ("script", Str, Required), ("time", Int, null), ("arg5", Int, null), ("align", EnumAlign, null)),
+ Types = BuildTypeOverride(("type", Required), ("spawnId", null), ("script", Required), ("time", null), ("arg5", null), ("align", null)),
};
ActionOverride["set_cube"] = new TriggerDefinitionOverride("set_cube") {
Names = BuildNameOverride(("IDs", "triggerIds"), ("arg1", "triggerIds"), ("arg2", "isVisible")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("isVisible", Bool, null), ("randomCount", Int, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("isVisible", null), ("randomCount", null)),
};
ActionOverride["set_directional_light"] = new TriggerDefinitionOverride("set_directional_light") {
Names = BuildNameOverride(("arg1", "diffuseColor"), ("arg2", "specularColor")),
- Types = BuildTypeOverride(("diffuseColor", Vector3, Required), ("specularColor", Vector3, null)),
+ Types = BuildTypeOverride(("diffuseColor", Required), ("specularColor", null)),
};
ActionOverride["set_effect"] = new TriggerDefinitionOverride("set_effect") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "visible"), ("arg3", "startDelay"), ("arg4", "interval")),
- Types = BuildTypeOverride(("triggerIds", IntList, null), ("visible", Bool, null), ("startDelay", Int, null), ("interval", Int, null)),
+ Types = BuildTypeOverride(("triggerIds", null), ("visible", null), ("startDelay", null), ("interval", null)),
};
ActionOverride["set_event_ui"] = new TriggerDefinitionOverride(string.Empty) {
FunctionSplitter = "arg1",
FunctionLookup = new Dictionary {
- ["0"] = new("set_event_ui_round", splitter: "arg1") {
+ ["0"] = new TriggerDefinitionOverride("set_event_ui_round", splitter: "arg1") {
Names = BuildNameOverride(("arg2", "rounds"), ("arg4", "vOffset")),
- Types = BuildTypeOverride(("rounds", IntList, Required), ("arg3", Int, null), ("vOffset", Int, null)),
+ Types = BuildTypeOverride(("rounds", Required), ("arg3", null), ("vOffset", null)),
},
- ["1"] = new("set_event_ui_script", splitter: "arg1") {
+ ["1"] = new TriggerDefinitionOverride("set_event_ui_script", splitter: "arg1") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script"), ("arg3", "duration"), ("arg4", "boxIds")),
- Types = BuildTypeOverride(("type", EnumBannerType, Required), ("script", Str, null), ("duration", Int, Required), ("boxIds", StrList, null)),
+ Types = BuildTypeOverride(("type", Required), ("script", null), ("duration", Required), ("boxIds", null)),
},
- ["2"] = new("set_event_ui_countdown", splitter: "arg1") {
+ ["2"] = new TriggerDefinitionOverride("set_event_ui_countdown", splitter: "arg1") {
Names = BuildNameOverride(("arg2", "script"), ("arg3", "roundCountdown"), ("arg4", "boxIds")),
- Types = BuildTypeOverride(("script", Str, null), ("roundCountdown", IntList, Required), ("boxIds", StrList, null)),
+ Types = BuildTypeOverride(("script", null), ("roundCountdown", Required), ("boxIds", null)),
},
- ["3"] = new("set_event_ui_script", splitter: "arg1") {
+ ["3"] = new TriggerDefinitionOverride("set_event_ui_script", splitter: "arg1") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script"), ("arg3", "duration"), ("arg4", "boxIds")),
- Types = BuildTypeOverride(("type", EnumBannerType, Required), ("script", Str, null), ("duration", Int, Required), ("boxIds", StrList, null)),
+ Types = BuildTypeOverride(("type", Required), ("script", null), ("duration", Required), ("boxIds", null)),
},
- ["4"] = new("set_event_ui_script", splitter: "arg1") {
+ ["4"] = new TriggerDefinitionOverride("set_event_ui_script", splitter: "arg1") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script"), ("arg3", "duration"), ("arg4", "boxIds")),
- Types = BuildTypeOverride(("type", EnumBannerType, Required), ("script", Str, null), ("duration", Int, Required), ("boxIds", StrList, null)),
+ Types = BuildTypeOverride(("type", Required), ("script", null), ("duration", Required), ("boxIds", null)),
},
- ["5"] = new("set_event_ui_script", splitter: "arg1") {
+ ["5"] = new TriggerDefinitionOverride("set_event_ui_script", splitter: "arg1") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script"), ("arg3", "duration"), ("arg4", "boxIds")),
- Types = BuildTypeOverride(("type", EnumBannerType, Required), ("script", Str, null), ("duration", Int, Required), ("boxIds", StrList, null)),
+ Types = BuildTypeOverride(("type", Required), ("script", null), ("duration", Required), ("boxIds", null)),
},
- ["6"] = new("set_event_ui_script", splitter: "arg1") {
+ ["6"] = new TriggerDefinitionOverride("set_event_ui_script", splitter: "arg1") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script"), ("arg3", "duration"), ("arg4", "boxIds")),
- Types = BuildTypeOverride(("type", EnumBannerType, Required), ("script", Str, null), ("duration", Int, Required), ("boxIds", StrList, null)),
+ Types = BuildTypeOverride(("type", Required), ("script", null), ("duration", Required), ("boxIds", null)),
},
- ["7"] = new("set_event_ui_script", splitter: "arg1") {
+ ["7"] = new TriggerDefinitionOverride("set_event_ui_script", splitter: "arg1") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "script"), ("arg3", "duration"), ("arg4", "boxIds")),
- Types = BuildTypeOverride(("type", EnumBannerType, Required), ("script", Str, null), ("duration", Int, Required), ("boxIds", StrList, null)),
+ Types = BuildTypeOverride(("type", Required), ("script", null), ("duration", Required), ("boxIds", null)),
},
},
};
ActionOverride["set_gravity"] = new TriggerDefinitionOverride("set_gravity") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("gravity", Float, Required)),
+ Types = BuildTypeOverride(("gravity", Required)),
};
ActionOverride["set_interact_object"] = new TriggerDefinitionOverride("set_interact_object") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "state")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("state", Int, Required), ("arg4", Bool, null), ("arg3", Bool, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("state", Required), ("arg4", null), ("arg3", null)),
};
ActionOverride["set_ladder"] = new TriggerDefinitionOverride("set_ladder") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "visible"), ("arg3", "enable"), ("arg4", "fade")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("visible", Bool, null), ("enable", Bool, null), ("fade", Int, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("visible", null), ("enable", null), ("fade", null)),
};
ActionOverride["set_local_camera"] = new TriggerDefinitionOverride("set_local_camera") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("cameraId", Int, Required), ("enable", Bool, null)),
+ Types = BuildTypeOverride(("cameraId", Required), ("enable", null)),
};
ActionOverride["set_mesh"] = new TriggerDefinitionOverride("set_mesh") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "visible"), ("arg3", "startDelay"), ("arg4", "interval"), ("arg5", "fade")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("visible", Bool, null), ("startDelay", Int, null), ("interval", Int, null), ("fade", Float, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("visible", null), ("startDelay", null), ("interval", null), ("fade", null)),
};
ActionOverride["set_mesh_animation"] = new TriggerDefinitionOverride("set_mesh_animation") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "visible"), ("arg3", "startDelay"), ("arg4", "interval")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("visible", Bool, null), ("startDelay", Int, null), ("interval", Int, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("visible", null), ("startDelay", null), ("interval", null)),
};
ActionOverride["set_mini_game_area_for_hack"] = new TriggerDefinitionOverride("set_mini_game_area_for_hack") {
Names = BuildNameOverride(("boxID", "boxId")),
- Types = BuildTypeOverride(("boxId", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required)),
};
ActionOverride["set_npc_duel_hp_bar"] = new TriggerDefinitionOverride("set_npc_duel_hp_bar") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("isOpen", Bool, null), ("spawnId", Int, Required), ("durationTick", Int, null), ("npcHpStep", Int, null)),
+ Types = BuildTypeOverride(("isOpen", null), ("spawnId", Required), ("durationTick", null), ("npcHpStep", null)),
};
ActionOverride["set_npc_emotion_loop"] = new TriggerDefinitionOverride("set_npc_emotion_loop") {
Names = BuildNameOverride(("arg1", "spawnId"), ("arg2", "sequenceName"), ("arg3", "duration"), ("arg", "duration")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("duration", Float, null)),
+ Types = BuildTypeOverride(("spawnId", Required), ("duration", null)),
};
ActionOverride["set_npc_emotion_sequence"] = new TriggerDefinitionOverride("set_npc_emotion_sequence") {
Names = BuildNameOverride(("arg1", "spawnId"), ("arg2", "sequenceName"), ("arg3", "durationTick")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("sequenceName", Str, Required), ("durationTick", Int, null)),
+ Types = BuildTypeOverride(("spawnId", Required), ("sequenceName", Required), ("durationTick", null)),
};
ActionOverride["set_npc_rotation"] = new TriggerDefinitionOverride("set_npc_rotation") {
Names = BuildNameOverride(("arg1", "spawnId"), ("arg2", "rotation")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("rotation", Float, Required)),
+ Types = BuildTypeOverride(("spawnId", Required), ("rotation", Required)),
};
ActionOverride["set_onetime_effect"] = new TriggerDefinitionOverride("set_onetime_effect") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("id", Int, null), ("enable", Bool, null)),
+ Types = BuildTypeOverride(("id", null), ("enable", null)),
};
ActionOverride["set_pc_emotion_loop"] = new TriggerDefinitionOverride("set_pc_emotion_loop") {
Names = BuildNameOverride(("arg1", "sequenceName"), ("arg2", "duration"), ("arg3", "loop")),
- Types = BuildTypeOverride(("sequenceName", Str, Required), ("duration", Float, null), ("loop", Bool, null)),
+ Types = BuildTypeOverride(("sequenceName", Required), ("duration", null), ("loop", null)),
};
ActionOverride["set_pc_emotion_sequence"] = new TriggerDefinitionOverride("set_pc_emotion_sequence") {
Names = BuildNameOverride(("arg1", "sequenceNames")),
- Types = BuildTypeOverride(("sequenceNames", StrList, Required)),
+ Types = BuildTypeOverride(("sequenceNames", Required)),
};
ActionOverride["set_pc_rotation"] = new TriggerDefinitionOverride("set_pc_rotation") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("rotation", Vector3, Required)),
+ Types = BuildTypeOverride(("rotation", Required)),
};
ActionOverride["set_photo_studio"] = new TriggerDefinitionOverride("set_photo_studio") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("isEnable", Bool, null)),
+ Types = BuildTypeOverride(("isEnable", null)),
};
ActionOverride["set_portal"] = new TriggerDefinitionOverride("set_portal") {
Names = BuildNameOverride(("arg1", "portalId"), ("arg2", "visible"), ("arg3", "enable"), ("arg4", "minimapVisible"), ("arg", "minimapVisible")),
- Types = BuildTypeOverride(("portalId", Int, Required), ("visible", Bool, null), ("enable", Bool, null), ("minimapVisible", Bool, null), ("arg5", Bool, null)),
+ Types = BuildTypeOverride(("portalId", Required), ("visible", null), ("enable", null), ("minimapVisible", null), ("arg5", null)),
};
ActionOverride["set_pvp_zone"] = new TriggerDefinitionOverride("set_pvp_zone") {
Names = BuildNameOverride(("arg1", "boxId"), ("arg2", "prepareTime"), ("arg3", "matchTime"), ("arg4", "additionalEffectId"), ("arg5", "type"), ("arg6", "boxIds")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("prepareTime", Int, Required), ("matchTime", Int, Required), ("additionalEffectId", Int, null), ("type", Int, null), ("boxIds", IntList, null)),
+ Types = BuildTypeOverride(("boxId", Required), ("prepareTime", Required), ("matchTime", Required), ("additionalEffectId", null), ("type", null), ("boxIds", null)),
};
ActionOverride["set_quest_accept"] = new TriggerDefinitionOverride("set_quest_accept") {
Names = BuildNameOverride(("questID", "questId"), ("arg1", "questId")),
- Types = BuildTypeOverride(("questId", Int, Required)),
+ Types = BuildTypeOverride(("questId", Required)),
};
ActionOverride["set_quest_complete"] = new TriggerDefinitionOverride("set_quest_complete") {
Names = BuildNameOverride(("questID", "questId")),
- Types = BuildTypeOverride(("questId", Int, Required)),
+ Types = BuildTypeOverride(("questId", Required)),
};
ActionOverride["set_random_mesh"] = new TriggerDefinitionOverride("set_random_mesh") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "visible"), ("arg3", "startDelay"), ("arg4", "interval"), ("arg5", "fade")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("visible", Bool, null), ("startDelay", Int, null), ("interval", Int, null), ("fade", Int, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("visible", null), ("startDelay", null), ("interval", null), ("fade", null)),
};
ActionOverride["set_rope"] = new TriggerDefinitionOverride("set_rope") {
Names = BuildNameOverride(("arg1", "triggerId"), ("arg2", "visible"), ("arg3", "enable"), ("arg4", "fade")),
- Types = BuildTypeOverride(("triggerId", Int, Required), ("visible", Bool, null), ("enable", Bool, null), ("fade", Int, null)),
+ Types = BuildTypeOverride(("triggerId", Required), ("visible", null), ("enable", null), ("fade", null)),
};
ActionOverride["set_scene_skip"] = new TriggerDefinitionOverride("set_scene_skip") {
Names = BuildNameOverride(("arg1", "state"), ("arg2", "action")),
- Types = BuildTypeOverride(("state", State, null)),
+ Types = BuildTypeOverride(("state", null)),
};
ActionOverride["set_skill"] = new TriggerDefinitionOverride("set_skill") {
Names = BuildNameOverride(("objectIDs", "triggerIds"), ("arg1", "triggerIds"), ("arg2", "enable"), ("isEnable", "enable")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("enable", Bool, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("enable", null)),
};
ActionOverride["set_skip"] = new TriggerDefinitionOverride("set_skip") {
Names = BuildNameOverride(("arg1", "state")),
- Types = BuildTypeOverride(("state", State, null)),
+ Types = BuildTypeOverride(("state", null)),
};
ActionOverride["set_sound"] = new TriggerDefinitionOverride("set_sound") {
Names = BuildNameOverride(("arg1", "triggerId"), ("arg2", "enable")),
- Types = BuildTypeOverride(("triggerId", Int, Required), ("enable", Bool, null)),
+ Types = BuildTypeOverride(("triggerId", Required), ("enable", null)),
};
ActionOverride["set_state"] = new TriggerDefinitionOverride("set_state") {
Names = BuildNameOverride(("arg1", "id"), ("arg2", "states"), ("arg3", "randomize")),
- Types = BuildTypeOverride(("id", Int, Required), ("states", StateList, Required), ("randomize", Bool, null)),
+ Types = BuildTypeOverride(("id", Required), ("states", Required), ("randomize", null)),
};
ActionOverride["set_time_scale"] = new TriggerDefinitionOverride("set_time_scale") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("enable", Bool, null), ("startScale", Float, null), ("endScale", Float, null), ("duration", Float, null), ("interpolator", Int, null)),
+ Types = BuildTypeOverride(("enable", null), ("startScale", null), ("endScale", null), ("duration", null), ("interpolator", null)),
};
ActionOverride["set_timer"] = new TriggerDefinitionOverride("set_timer") {
Names = BuildNameOverride(("arg1", "timerId"), ("arg2", "seconds"), ("arg3", "autoRemove"), ("ara3", "autoRemove"), ("arg4", "display"), ("arg5", "vOffset"), ("arg6", "type")),
- Types = BuildTypeOverride(("seconds", Int, null), ("autoRemove", Bool, null), ("display", Bool, null), ("vOffset", Int, null)),
+ Types = BuildTypeOverride(("seconds", null), ("autoRemove", null), ("display", null), ("vOffset", null)),
};
ActionOverride["set_user_value"] = new TriggerDefinitionOverride("set_user_value") {
Names = BuildNameOverride(("triggerID", "triggerId")),
- Types = BuildTypeOverride(("triggerId", Int, null), ("key", Str, Required), ("value", Int, Required)),
+ Types = BuildTypeOverride(("triggerId", null), ("key", Required), ("value", Required)),
};
ActionOverride["set_user_value_from_dungeon_reward_count"] = new TriggerDefinitionOverride("set_user_value_from_dungeon_reward_count") {
Names = BuildNameOverride(("dungeonRewardID", "dungeonRewardId")),
- Types = BuildTypeOverride(("dungeonRewardId", Int, Required)),
+ Types = BuildTypeOverride(("dungeonRewardId", Required)),
};
ActionOverride["set_user_value_from_guild_vs_game_score"] = new TriggerDefinitionOverride("set_user_value_from_guild_vs_game_score") {
Names = BuildNameOverride(("teamID", "teamId")),
- Types = BuildTypeOverride(("teamId", Int, Required)),
+ Types = BuildTypeOverride(("teamId", Required)),
};
ActionOverride["set_user_value_from_user_count"] = new TriggerDefinitionOverride("set_user_value_from_user_count") {
Names = BuildNameOverride(("triggerBoxID", "triggerBoxId"), ("userTagID", "userTagId")),
- Types = BuildTypeOverride(("triggerBoxId", Int, Required), ("key", Str, Required), ("userTagId", Int, Required)),
+ Types = BuildTypeOverride(("triggerBoxId", Required), ("key", Required), ("userTagId", Required)),
};
ActionOverride["set_visible_breakable_object"] = new TriggerDefinitionOverride("set_visible_breakable_object") {
Names = BuildNameOverride(("arg1", "triggerIds"), ("arg2", "visible")),
- Types = BuildTypeOverride(("triggerIds", IntList, Required), ("visible", Bool, null)),
+ Types = BuildTypeOverride(("triggerIds", Required), ("visible", null)),
};
ActionOverride["set_visible_ui"] = new TriggerDefinitionOverride("set_visible_ui") {
Names = BuildNameOverride(("uiName", "uiNames")),
- Types = BuildTypeOverride(("uiNames", StrList, Required), ("visible", Bool, null)),
+ Types = BuildTypeOverride(("uiNames", Required), ("visible", null)),
};
ActionOverride["shadow_expedition"] = new TriggerDefinitionOverride("") {
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["OpenBossGauge"] = new("shadow_expedition_open_boss_gauge", splitter: "type") {
+ ["OpenBossGauge"] = new TriggerDefinitionOverride("shadow_expedition_open_boss_gauge", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("maxGaugePoint", Int, Required)),
+ Types = BuildTypeOverride(("maxGaugePoint", Required)),
},
- ["CloseBossGauge"] = new("shadow_expedition_close_boss_gauge", splitter: "type") {
+ ["CloseBossGauge"] = new TriggerDefinitionOverride("shadow_expedition_close_boss_gauge", splitter: "type") {
Names = BuildNameOverride(),
Types = BuildTypeOverride(),
},
@@ -781,69 +780,69 @@ static TriggerDefinitionOverride() {
};
ActionOverride["show_caption"] = new TriggerDefinitionOverride("show_caption") {
Names = BuildNameOverride(("offestRateX", "offsetRateX")),
- Types = BuildTypeOverride(("type", Str, Required), ("title", Str, Required), ("align", EnumAlign, null), ("offsetRateX", Float, null), ("offsetRateY", Float, null), ("duration", Int, null), ("scale", Float, null)),
+ Types = BuildTypeOverride(("type", Required), ("title", Required), ("align", null), ("offsetRateX", null), ("offsetRateY", null), ("duration", null), ("scale", null)),
};
ActionOverride["show_count_ui"] = new TriggerDefinitionOverride("show_count_ui") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("text", Str, Required), ("stage", Int, null), ("count", Int, Required), ("soundType", Int, "1")),
+ Types = BuildTypeOverride(("text", Required), ("stage", null), ("count", Required), ("soundType", "1")),
};
ActionOverride["show_event_result"] = new TriggerDefinitionOverride("show_event_result") {
Names = BuildNameOverride(("userTagID", "userTagId"), ("triggerBoxID", "triggerBoxId"), ("isOutSide", "isOutside")),
- Types = BuildTypeOverride(("type", Str, Required), ("text", Str, Required), ("duration", Int, null), ("userTagId", Int, null), ("triggerBoxId", Int, null), ("isOutside", Bool, null)),
+ Types = BuildTypeOverride(("type", Required), ("text", Required), ("duration", null), ("userTagId", null), ("triggerBoxId", null), ("isOutside", null)),
};
ActionOverride["show_guide_summary"] = new TriggerDefinitionOverride("show_guide_summary") {
Names = BuildNameOverride(("entityID", "entityId"), ("textID", "textId"), ("durationTime", "duration")),
- Types = BuildTypeOverride(("entityId", Int, Required), ("textId", Int, null), ("duration", Int, null)),
+ Types = BuildTypeOverride(("entityId", Required), ("textId", null), ("duration", null)),
};
ActionOverride["show_round_ui"] = new TriggerDefinitionOverride("show_round_ui") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required), ("duration", Int, null), ("isFinalRound", Bool, null)),
+ Types = BuildTypeOverride(("round", Required), ("duration", null), ("isFinalRound", null)),
};
ActionOverride["side_npc_talk"] = new TriggerDefinitionOverride("") {
- Types = BuildTypeOverride(("type", Str, "talk")),
+ Types = BuildTypeOverride(("type", "talk")),
FunctionSplitter = "type",
FunctionLookup = new Dictionary {
- ["talk"] = new("side_npc_talk", splitter: "type") {
+ ["talk"] = new TriggerDefinitionOverride("side_npc_talk", splitter: "type") {
Names = BuildNameOverride(("npcID", "npcId")),
- Types = BuildTypeOverride(("npcId", Int, Required), ("illust", Str, Required), ("duration", Int, Required), ("script", Str, Required)),
+ Types = BuildTypeOverride(("npcId", Required), ("illust", Required), ("duration", Required), ("script", Required)),
},
- ["talkbottom"] = new("side_npc_talk_bottom", splitter: "type") {
+ ["talkbottom"] = new TriggerDefinitionOverride("side_npc_talk_bottom", splitter: "type") {
Names = BuildNameOverride(("npcID", "npcId")),
- Types = BuildTypeOverride(("npcId", Int, Required), ("illust", Str, Required), ("duration", Int, Required), ("script", Str, Required)),
+ Types = BuildTypeOverride(("npcId", Required), ("illust", Required), ("duration", Required), ("script", Required)),
},
- ["movie"] = new("side_npc_movie", splitter: "type") {
+ ["movie"] = new TriggerDefinitionOverride("side_npc_movie", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("usm", Str, Required), ("duration", Int, Required)),
+ Types = BuildTypeOverride(("usm", Required), ("duration", Required)),
},
- ["cutin"] = new("side_npc_cutin", splitter: "type") {
+ ["cutin"] = new TriggerDefinitionOverride("side_npc_cutin", splitter: "type") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("illust", Str, Required), ("duration", Int, Required)),
+ Types = BuildTypeOverride(("illust", Required), ("duration", Required)),
},
},
};
ActionOverride["sight_range"] = new TriggerDefinitionOverride("sight_range") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("enable", Bool, null), ("range", Int, Required), ("rangeZ", Int, null), ("border", Int, null)),
+ Types = BuildTypeOverride(("enable", null), ("range", Required), ("rangeZ", null), ("border", null)),
};
ActionOverride["spawn_item_range"] = new TriggerDefinitionOverride("spawn_item_range") {
Names = BuildNameOverride(("rangeID", "rangeIds")),
- Types = BuildTypeOverride(("rangeIds", IntList, Required), ("randomPickCount", Int, Required)),
+ Types = BuildTypeOverride(("rangeIds", Required), ("randomPickCount", Required)),
};
ActionOverride["spawn_npc_range"] = new TriggerDefinitionOverride("spawn_npc_range") {
Names = BuildNameOverride(("rangeID", "rangeIds")),
- Types = BuildTypeOverride(("rangeIds", IntList, Required), ("isAutoTargeting", Bool, null), ("randomPickCount", Int, null), ("score", Int, null)),
+ Types = BuildTypeOverride(("rangeIds", Required), ("isAutoTargeting", null), ("randomPickCount", null), ("score", null)),
};
ActionOverride["start_combine_spawn"] = new TriggerDefinitionOverride("start_combine_spawn") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("groupId", IntList, Required), ("isStart", Bool, null)),
+ Types = BuildTypeOverride(("groupId", Required), ("isStart", null)),
};
ActionOverride["start_mini_game"] = new TriggerDefinitionOverride("start_mini_game") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("boxId", Int, Required), ("round", Int, Required), ("gameName", Str, Required), ("isShowResultUI", Bool, "True")),
+ Types = BuildTypeOverride(("boxId", Required), ("round", Required), ("gameName", Required), ("isShowResultUI", "True")),
};
ActionOverride["start_mini_game_round"] = new TriggerDefinitionOverride("start_mini_game_round") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("boxId", Int, Required), ("round", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("round", Required)),
};
ActionOverride["start_tutorial"] = new TriggerDefinitionOverride("start_tutorial") {
Names = BuildNameOverride(),
@@ -851,7 +850,7 @@ static TriggerDefinitionOverride() {
};
ActionOverride["talk_npc"] = new TriggerDefinitionOverride("talk_npc") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, Required)),
+ Types = BuildTypeOverride(("spawnId", Required)),
};
ActionOverride["unset_mini_game_area_for_hack"] = new TriggerDefinitionOverride("unset_mini_game_area_for_hack") {
Names = BuildNameOverride(),
@@ -859,23 +858,23 @@ static TriggerDefinitionOverride() {
};
ActionOverride["use_state"] = new TriggerDefinitionOverride("use_state") {
Names = BuildNameOverride(("arg1", "id"), ("arg2", "randomize")),
- Types = BuildTypeOverride(("id", Int, null), ("randomize", Bool, null)),
+ Types = BuildTypeOverride(("id", null), ("randomize", null)),
};
ActionOverride["user_tag_symbol"] = new TriggerDefinitionOverride("user_tag_symbol") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("symbol1", Str, Required), ("symbol2", Str, Required)),
+ Types = BuildTypeOverride(("symbol1", Required), ("symbol2", Required)),
};
ActionOverride["user_value_to_number_mesh"] = new TriggerDefinitionOverride("user_value_to_number_mesh") {
Names = BuildNameOverride(("startMeshID", "startMeshId")),
- Types = BuildTypeOverride(("key", Str, Required), ("startMeshId", Int, Required), ("digitCount", Int, Required)),
+ Types = BuildTypeOverride(("key", Required), ("startMeshId", Required), ("digitCount", Required)),
};
ActionOverride["visible_my_pc"] = new TriggerDefinitionOverride("visible_my_pc") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("isVisible", Bool, Required)),
+ Types = BuildTypeOverride(("isVisible", Required)),
};
ActionOverride["weather"] = new TriggerDefinitionOverride("weather") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("weatherType", EnumWeather, Required)),
+ Types = BuildTypeOverride(("weatherType", Required)),
};
ActionOverride["wedding_broken"] = new TriggerDefinitionOverride("wedding_broken") {
Names = BuildNameOverride(),
@@ -883,31 +882,31 @@ static TriggerDefinitionOverride() {
};
ActionOverride["wedding_move_user"] = new TriggerDefinitionOverride("wedding_move_user") {
Names = BuildNameOverride(("arg1", "mapId"), ("arg2", "portalIds"), ("arg3", "boxId")),
- Types = BuildTypeOverride(("entryType", Str, Required), ("mapId", Int, Required), ("portalIds", IntList, Required), ("boxId", Int, Required)),
+ Types = BuildTypeOverride(("entryType", Required), ("mapId", Required), ("portalIds", Required), ("boxId", Required)),
};
ActionOverride["wedding_mutual_agree"] = new TriggerDefinitionOverride("wedding_mutual_agree") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("agreeType", Str, Required)),
+ Types = BuildTypeOverride(("agreeType", Required)),
};
ActionOverride["wedding_mutual_cancel"] = new TriggerDefinitionOverride("wedding_mutual_cancel") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("agreeType", Str, Required)),
+ Types = BuildTypeOverride(("agreeType", Required)),
};
ActionOverride["wedding_set_user_emotion"] = new TriggerDefinitionOverride("wedding_set_user_emotion") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("entryType", Str, Required), ("id", Int, Required)),
+ Types = BuildTypeOverride(("entryType", Required), ("id", Required)),
};
ActionOverride["wedding_set_user_look_at"] = new TriggerDefinitionOverride("wedding_set_user_look_at") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("entryType", Str, Required), ("lookAtEntryType", Str, Required), ("immediate", Bool, null)),
+ Types = BuildTypeOverride(("entryType", Required), ("lookAtEntryType", Required), ("immediate", null)),
};
ActionOverride["wedding_set_user_rotation"] = new TriggerDefinitionOverride("wedding_set_user_rotation") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("entryType", Str, Required), ("rotation", Vector3, Required), ("immediate", Bool, null)),
+ Types = BuildTypeOverride(("entryType", Required), ("rotation", Required), ("immediate", null)),
};
ActionOverride["wedding_user_to_patrol"] = new TriggerDefinitionOverride("wedding_user_to_patrol") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("entryType", Str, Required), ("patrolIndex", Int, null)),
+ Types = BuildTypeOverride(("entryType", Required), ("patrolIndex", null)),
};
ActionOverride["wedding_vow_complete"] = new TriggerDefinitionOverride("wedding_vow_complete") {
Names = BuildNameOverride(),
@@ -915,11 +914,11 @@ static TriggerDefinitionOverride() {
};
ActionOverride["widget_action"] = new TriggerDefinitionOverride("widget_action") {
Names = BuildNameOverride(("arg1", "type"), ("arg2", "func"), ("arg3", "widgetArg")),
- Types = BuildTypeOverride(("type", Str, Required), ("func", Str, Required), ("widgetArgNum", Int, null)),
+ Types = BuildTypeOverride(("type", Required), ("func", Required), ("widgetArgNum", null)),
};
ActionOverride["write_log"] = new TriggerDefinitionOverride("write_log") {
Names = BuildNameOverride(("arg1", "logName"), ("arg2", "triggerId"), ("arg3", "event"), ("arg4", "level"), ("arg5", "subEvent")),
- Types = BuildTypeOverride(("logName", Str, Required), ("triggerId", Int, null), ("level", Int, null)),
+ Types = BuildTypeOverride(("logName", Required), ("triggerId", null), ("level", null)),
};
// Condition Override
@@ -937,16 +936,16 @@ static TriggerDefinitionOverride() {
};
ConditionOverride["always"] = new TriggerDefinitionOverride("always") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("arg1", Bool, "True")),
+ Types = BuildTypeOverride(("arg1", "True")),
};
ConditionOverride["bonus_game_reward_detected"] = new TriggerDefinitionOverride("bonus_game_reward") {
Names = BuildNameOverride(("arg1", "boxId"), ("arg2", "type")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("type", Int, Required)),
- Compare = BuildCompareOverride(Int, "type", ""),
+ Types = BuildTypeOverride(("boxId", Required), ("type", Required)),
+ Compare = BuildCompareOverride("type", ""),
};
ConditionOverride["check_any_user_additional_effect"] = new TriggerDefinitionOverride("check_any_user_additional_effect") {
Names = BuildNameOverride(("triggerBoxID", "boxId"), ("additionalEffectID", "additionalEffectId")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("additionalEffectId", Int, Required), ("level", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("additionalEffectId", Required), ("level", Required)),
};
ConditionOverride["check_dungeon_lobby_user_count"] = new TriggerDefinitionOverride("check_dungeon_lobby_user_count") {
Names = BuildNameOverride(),
@@ -954,30 +953,30 @@ static TriggerDefinitionOverride() {
};
ConditionOverride["check_npc_additional_effect"] = new TriggerDefinitionOverride("check_npc_additional_effect") {
Names = BuildNameOverride(("spawnPointID", "spawnId"), ("additionalEffectID", "additionalEffectId")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("additionalEffectId", Int, Required), ("level", Int, Required)),
+ Types = BuildTypeOverride(("spawnId", Required), ("additionalEffectId", Required), ("level", Required)),
};
ConditionOverride["check_npc_damage"] = new TriggerDefinitionOverride("npc_damage") {
Names = BuildNameOverride(("spawnPointID", "spawnId")),
- Types = BuildTypeOverride(("spawnId", Int, Required), ("damageRate", Float, Required), ("operator", Str, "GreaterEqual")),
- Compare = BuildCompareOverride(Float, "damageRate", "operator", "GreaterEqual"),
+ Types = BuildTypeOverride(("spawnId", Required), ("damageRate", Required), ("operator", "GreaterEqual")),
+ Compare = BuildCompareOverride("damageRate", "operator", "GreaterEqual"),
};
ConditionOverride["check_npc_extra_data"] = new TriggerDefinitionOverride("npc_extra_data") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("spawnPointId", Int, Required), ("extraDataKey", Str, Required), ("extraDataValue", Int, Required)),
- Compare = BuildCompareOverride(Int, "extraDataValue", "operator", Required),
+ Types = BuildTypeOverride(("spawnPointId", Required), ("extraDataKey", Required), ("extraDataValue", Required)),
+ Compare = BuildCompareOverride("extraDataValue", "operator", Required),
};
ConditionOverride["check_npc_hp"] = new TriggerDefinitionOverride("npc_hp") {
Names = BuildNameOverride(("spawnPointId", "spawnId")),
- Types = BuildTypeOverride(("value", Int, Required), ("spawnId", Int, Required), ("isRelative", Bool, Required)),
- Compare = BuildCompareOverride(Int, "value", "compare", Required),
+ Types = BuildTypeOverride(("value", Required), ("spawnId", Required), ("isRelative", Required)),
+ Compare = BuildCompareOverride("value", "compare", Required),
};
ConditionOverride["npc_is_dead_by_string_id"] = new TriggerDefinitionOverride("npc_is_dead_by_string_id") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("stringId", Str, Required)),
+ Types = BuildTypeOverride(("stringId", Required)),
};
ConditionOverride["check_same_user_tag"] = new TriggerDefinitionOverride("check_same_user_tag") {
Names = BuildNameOverride(("triggerBoxID", "boxId")),
- Types = BuildTypeOverride(("boxId", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required)),
};
ConditionOverride["check_user"] = new TriggerDefinitionOverride("check_user") {
Names = BuildNameOverride(),
@@ -985,57 +984,57 @@ static TriggerDefinitionOverride() {
};
ConditionOverride["check_user_count"] = new TriggerDefinitionOverride("user_count") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("checkCount", Int, null)),
- Compare = BuildCompareOverride(Int, "checkCount", ""),
+ Types = BuildTypeOverride(("checkCount", null)),
+ Compare = BuildCompareOverride("checkCount", ""),
};
ConditionOverride["count_users"] = new TriggerDefinitionOverride("count_users") {
Names = BuildNameOverride(("arg1", "boxId"), ("arg2", "minUsers"), ("arg3", "operator"), ("userTagID", "userTagId")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("minUsers", Int, Required), ("operator", Str, "GreaterEqual"), ("userTagId", Int, null)),
- Compare = BuildCompareOverride(Int, "minUsers", "operator", "GreaterEqual"),
+ Types = BuildTypeOverride(("boxId", Required), ("minUsers", Required), ("operator", "GreaterEqual"), ("userTagId", null)),
+ Compare = BuildCompareOverride("minUsers", "operator", "GreaterEqual"),
};
ConditionOverride["day_of_week"] = new TriggerDefinitionOverride("day_of_week") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("dayOfWeeks", IntList, Required)),
- Compare = BuildCompareOverride(Int, "dayOfWeeks", "", "in"),
+ Types = BuildTypeOverride(("dayOfWeeks", Required)),
+ Compare = BuildCompareOverride("dayOfWeeks", "", "in"),
};
ConditionOverride["detect_liftable_object"] = new TriggerDefinitionOverride("detect_liftable_object") {
Names = BuildNameOverride(("triggerBoxIDs", "boxIds"), ("itemID", "itemId")),
- Types = BuildTypeOverride(("boxIds", IntList, Required), ("itemId", Int, Required)),
+ Types = BuildTypeOverride(("boxIds", Required), ("itemId", Required)),
};
ConditionOverride["dungeon_check_play_time"] = new TriggerDefinitionOverride("dungeon_play_time") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("playSeconds", Int, Required), ("operator", Str, "GreaterEqual")),
- Compare = BuildCompareOverride(Int, "playSeconds", "operator", "GreaterEqual"),
+ Types = BuildTypeOverride(("playSeconds", Required), ("operator", "GreaterEqual")),
+ Compare = BuildCompareOverride("playSeconds", "operator", "GreaterEqual"),
};
ConditionOverride["dungeon_check_state"] = new TriggerDefinitionOverride("dungeon_state") {
Names = BuildNameOverride(),
Types = BuildTypeOverride(),
- Compare = BuildCompareOverride(Str, "checkState", ""),
+ Compare = BuildCompareOverride("checkState", ""),
};
ConditionOverride["dungeon_first_user_mission_score"] = new TriggerDefinitionOverride("dungeon_first_user_mission_score") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("score", Int, Required), ("operator", Str, "GreaterEqual")),
- Compare = BuildCompareOverride(Int, "score", "operator", "GreaterEqual"),
+ Types = BuildTypeOverride(("score", Required), ("operator", "GreaterEqual")),
+ Compare = BuildCompareOverride("score", "operator", "GreaterEqual"),
};
ConditionOverride["dungeon_id"] = new TriggerDefinitionOverride("dungeon_id") {
Names = BuildNameOverride(("dungeonID", "dungeonId")),
- Types = BuildTypeOverride(("dungeonId", Int, Required)),
- Compare = BuildCompareOverride(Int, "dungeonId", ""),
+ Types = BuildTypeOverride(("dungeonId", Required)),
+ Compare = BuildCompareOverride("dungeonId", ""),
};
ConditionOverride["dungeon_level"] = new TriggerDefinitionOverride("dungeon_level") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("level", Int, Required)),
- Compare = BuildCompareOverride(Int, "level", ""),
+ Types = BuildTypeOverride(("level", Required)),
+ Compare = BuildCompareOverride("level", ""),
};
ConditionOverride["dungeon_max_user_count"] = new TriggerDefinitionOverride("dungeon_max_user_count") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("value", Int, Required)),
- Compare = BuildCompareOverride(Int, "value", ""),
+ Types = BuildTypeOverride(("value", Required)),
+ Compare = BuildCompareOverride("value", ""),
};
ConditionOverride["dungeon_round_require"] = new TriggerDefinitionOverride("dungeon_round") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("round", Int, Required)),
- Compare = BuildCompareOverride(Int, "round", ""),
+ Types = BuildTypeOverride(("round", Required)),
+ Compare = BuildCompareOverride("round", ""),
};
ConditionOverride["dungeon_time_out"] = new TriggerDefinitionOverride("dungeon_timeout") {
Names = BuildNameOverride(),
@@ -1043,16 +1042,16 @@ static TriggerDefinitionOverride() {
};
ConditionOverride["dungeon_variable"] = new TriggerDefinitionOverride("dungeon_variable") {
Names = BuildNameOverride(("varID", "varId")),
- Types = BuildTypeOverride(("varId", Int, Required), ("value", Int, Required)),
- Compare = BuildCompareOverride(Int, "value", ""),
+ Types = BuildTypeOverride(("varId", Required), ("value", Required)),
+ Compare = BuildCompareOverride("value", ""),
};
ConditionOverride["guild_vs_game_scored_team"] = new TriggerDefinitionOverride("guild_vs_game_scored_team") {
Names = BuildNameOverride(("teamID", "teamId")),
- Types = BuildTypeOverride(("teamId", Int, Required)),
+ Types = BuildTypeOverride(("teamId", Required)),
};
ConditionOverride["guild_vs_game_winner_team"] = new TriggerDefinitionOverride("guild_vs_game_winner_team") {
Names = BuildNameOverride(("teamID", "teamId")),
- Types = BuildTypeOverride(("teamId", Int, Required)),
+ Types = BuildTypeOverride(("teamId", Required)),
};
ConditionOverride["is_dungeon_room"] = new TriggerDefinitionOverride("is_dungeon_room") {
Names = BuildNameOverride(),
@@ -1064,85 +1063,85 @@ static TriggerDefinitionOverride() {
};
ConditionOverride["monster_dead"] = new TriggerDefinitionOverride("monster_dead") {
Names = BuildNameOverride(("arg1", "spawnIds"), ("arg2", "autoTarget")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required), ("autoTarget", Bool, "True")),
+ Types = BuildTypeOverride(("spawnIds", Required), ("autoTarget", "True")),
};
ConditionOverride["monster_in_combat"] = new TriggerDefinitionOverride("monster_in_combat") {
Names = BuildNameOverride(("arg1", "spawnIds")),
- Types = BuildTypeOverride(("spawnIds", IntList, Required)),
+ Types = BuildTypeOverride(("spawnIds", Required)),
};
ConditionOverride["npc_detected"] = new TriggerDefinitionOverride("npc_detected") {
Names = BuildNameOverride(("arg1", "boxId"), ("arg2", "spawnIds")),
- Types = BuildTypeOverride(("boxId", Int, Required), ("spawnIds", IntList, Required)),
+ Types = BuildTypeOverride(("boxId", Required), ("spawnIds", Required)),
};
ConditionOverride["object_interacted"] = new TriggerDefinitionOverride("object_interacted") {
Names = BuildNameOverride(("arg1", "interactIds"), ("arg2", "state"), ("ar2", "state")),
- Types = BuildTypeOverride(("interactIds", IntList, Required), ("state", Int, "0")),
+ Types = BuildTypeOverride(("interactIds", Required), ("state", "0")),
};
ConditionOverride["pvp_zone_ended"] = new TriggerDefinitionOverride("pvp_zone_ended") {
Names = BuildNameOverride(("arg1", "boxId")),
- Types = BuildTypeOverride(("boxId", Int, Required)),
+ Types = BuildTypeOverride(("boxId", Required)),
};
ConditionOverride["quest_user_detected"] = new TriggerDefinitionOverride("quest_user_detected") {
Names = BuildNameOverride(("arg1", "boxIds"), ("arg2", "questIds"), ("arg3", "questStates"), ("arg4", "jobCode")),
- Types = BuildTypeOverride(("boxIds", IntList, Required), ("questIds", IntList, Required), ("questStates", IntList, Required), ("jobCode", Int, null)),
+ Types = BuildTypeOverride(("boxIds", Required), ("questIds", Required), ("questStates", Required), ("jobCode", null)),
};
ConditionOverride["random_condition"] = new TriggerDefinitionOverride("random_condition") {
Names = BuildNameOverride(("arg1", "weight")),
- Types = BuildTypeOverride(("weight", Float, Required)),
+ Types = BuildTypeOverride(("weight", Required)),
};
ConditionOverride["score_board_compare"] = new TriggerDefinitionOverride("score_board_score") {
Names = BuildNameOverride(("compareOp", "operator")),
- Types = BuildTypeOverride(("operator", Str, "GreaterEqual"), ("score", Int, Required)),
- Compare = BuildCompareOverride(Int, "score", "operator", "GreaterEqual"),
+ Types = BuildTypeOverride(("operator", "GreaterEqual"), ("score", Required)),
+ Compare = BuildCompareOverride("score", "operator", "GreaterEqual"),
};
ConditionOverride["shadow_expedition_reach_point"] = new TriggerDefinitionOverride("shadow_expedition_points") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("point", Int, Required)),
- Compare = BuildCompareOverride(Int, "point", "", "GreaterEqual"),
+ Types = BuildTypeOverride(("point", Required)),
+ Compare = BuildCompareOverride("point", "", "GreaterEqual"),
};
ConditionOverride["time_expired"] = new TriggerDefinitionOverride("time_expired") {
Names = BuildNameOverride(("arg1", "timerId")),
- Types = BuildTypeOverride(("timerId", Str, Required)),
+ Types = BuildTypeOverride(("timerId", Required)),
};
ConditionOverride["user_detected"] = new TriggerDefinitionOverride("user_detected") {
Names = BuildNameOverride(("arg1", "boxIds"), ("arg2", "jobCode")),
- Types = BuildTypeOverride(("boxIds", IntList, Required), ("jobCode", Int, null)),
+ Types = BuildTypeOverride(("boxIds", Required), ("jobCode", null)),
};
ConditionOverride["user_value"] = new TriggerDefinitionOverride("user_value") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("key", Str, Required), ("value", Int, Required), ("operator", Str, "Equal")),
- Compare = BuildCompareOverride(Int, "value", "operator"),
+ Types = BuildTypeOverride(("key", Required), ("value", Required), ("operator", "Equal")),
+ Compare = BuildCompareOverride("value", "operator"),
};
ConditionOverride["wait_and_reset_tick"] = new TriggerDefinitionOverride("wait_and_reset_tick") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("waitTick", Int, Required)),
+ Types = BuildTypeOverride(("waitTick", Required)),
};
ConditionOverride["wait_seconds_user_value"] = new TriggerDefinitionOverride("wait_seconds_user_value") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("key", Str, Required)),
+ Types = BuildTypeOverride(("key", Required)),
};
ConditionOverride["wait_tick"] = new TriggerDefinitionOverride("wait_tick") {
Names = BuildNameOverride(("arg1", "waitTick")),
- Types = BuildTypeOverride(("waitTick", Int, Required)),
+ Types = BuildTypeOverride(("waitTick", Required)),
};
ConditionOverride["wedding_entry_in_field"] = new TriggerDefinitionOverride("wedding_entry_in_field") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("entryType", Str, Required), ("isInField", Bool, Required)),
+ Types = BuildTypeOverride(("entryType", Required), ("isInField", Required)),
};
ConditionOverride["wedding_hall_state"] = new TriggerDefinitionOverride("wedding_hall_state") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("success", Bool, null)),
- Compare = BuildCompareOverride(Str, "hall_state", ""),
+ Types = BuildTypeOverride(("success", null)),
+ Compare = BuildCompareOverride("hall_state", ""),
};
ConditionOverride["wedding_mutual_agree_result"] = new TriggerDefinitionOverride("wedding_mutual_agree_result") {
Names = BuildNameOverride(),
- Types = BuildTypeOverride(("agreeType", Str, Required), ("success", Bool, "True")),
- Compare = BuildCompareOverride(Bool, "success", ""),
+ Types = BuildTypeOverride(("agreeType", Required), ("success", "True")),
+ Compare = BuildCompareOverride("success", ""),
};
ConditionOverride["widget_condition"] = new TriggerDefinitionOverride("widget_value") {
- Names = BuildNameOverride(("arg1", "type"), ("arg2", "name"), ("arg3", "condition")),
- Types = BuildTypeOverride(("type", Str, Required), ("name", Str, Required)),
- Compare = BuildCompareOverride(Int, "condition", "condition", ""),
+ Names = BuildNameOverride(("arg1", "type"), ("arg2", "widgetName"), ("arg3", "condition")),
+ Types = BuildTypeOverride(("type", Required), ("widgetName", Required)),
+ Compare = BuildCompareOverride("condition", "condition", ""),
};
}
@@ -1157,18 +1156,18 @@ private static Dictionary BuildNameOverride(params (string, stri
return mapping;
}
- private static Dictionary BuildTypeOverride(params (string, ScriptType, string?)[] overrides) {
- Dictionary mapping = [];
- foreach ((string name, ScriptType argType, string? defaultValue) in overrides) {
+ private static Dictionary BuildTypeOverride(params (string, string?)[] overrides) {
+ Dictionary mapping = [];
+ foreach ((string name, string? defaultValue) in overrides) {
string argName = TriggerTranslate.ToSnakeCase(name);
Debug.Assert(!mapping.ContainsKey(argName), $"Duplicate override key: {argName}");
- mapping.Add(argName, (argType, defaultValue));
+ mapping.Add(argName, defaultValue);
}
return mapping;
}
// Passing an invalid string as @default
- private static (ScriptType, string, string, string) BuildCompareOverride(ScriptType type, string field, string op, string @default = "Equal") {
- return (type, TriggerTranslate.ToSnakeCase(field), TriggerTranslate.ToSnakeCase(op), @default);
+ private static (string, string, string) BuildCompareOverride(string field, string op, string @default = "Equal") {
+ return (TriggerTranslate.ToSnakeCase(field), TriggerTranslate.ToSnakeCase(op), @default);
}
}
diff --git a/Maple2.File.Ingest/Utils/TriggerTranslate.cs b/Maple2.File.Ingest/Utils/TriggerTranslate.cs
index 74453b5f3..fdd97637d 100644
--- a/Maple2.File.Ingest/Utils/TriggerTranslate.cs
+++ b/Maple2.File.Ingest/Utils/TriggerTranslate.cs
@@ -4,7 +4,7 @@
namespace Maple2.File.Ingest.Utils;
public static class TriggerTranslate {
- private static readonly Dictionary ActionLookup = new() {
+ public static readonly Dictionary ActionLookup = new() {
{"대화를설정한다", "Set Dialogue"},
{"랜덤메쉬를설정한다", "Set Random Mesh"},
{"로그를남긴다", "Write Log"},
@@ -48,7 +48,7 @@ public static class TriggerTranslate {
{"전장점수를준다", "Allocate Battlefield Points"},
};
- private static readonly Dictionary ConditionLookup = new() {
+ public static readonly Dictionary ConditionLookup = new() {
{"랜덤조건", "Random Condition"},
{"NPC를감지했으면", "NPC Detected"},
{"몬스터가전투상태면", "Monster In Combat"},
diff --git a/Maple2.Model/Metadata/Constants.cs b/Maple2.Model/Metadata/Constants.cs
index 2c68cd5bc..f1f71240f 100644
--- a/Maple2.Model/Metadata/Constants.cs
+++ b/Maple2.Model/Metadata/Constants.cs
@@ -116,6 +116,8 @@ public static class Constant {
public const int MaxAllowedLatency = 2000;
+ public const bool DebugTriggers = false; // Set to true to enable debug triggers. (It'll write triggers to files and load triggers from files instead of DB)
+
public static IReadOnlyDictionary ContentRewards { get; } = new Dictionary {
{"miniGame", 1005},
{"dungeonHelper", 1006},
diff --git a/Maple2.Model/Metadata/TriggerMetadata.cs b/Maple2.Model/Metadata/TriggerMetadata.cs
new file mode 100644
index 000000000..c64c42711
--- /dev/null
+++ b/Maple2.Model/Metadata/TriggerMetadata.cs
@@ -0,0 +1,3 @@
+namespace Maple2.Model.Metadata;
+
+public record TriggerMetadata(string MapXBlock, string Name, string Xml);
diff --git a/Maple2.Server.Core/Modules/DataDbModule.cs b/Maple2.Server.Core/Modules/DataDbModule.cs
index be509f4a0..cd2a23f63 100644
--- a/Maple2.Server.Core/Modules/DataDbModule.cs
+++ b/Maple2.Server.Core/Modules/DataDbModule.cs
@@ -54,5 +54,6 @@ protected override void Load(ContainerBuilder builder) {
builder.RegisterType().SingleInstance();
builder.RegisterType().SingleInstance();
builder.RegisterType().SingleInstance();
+ builder.RegisterType().SingleInstance();
}
}
diff --git a/Maple2.Server.DebugGame/Graphics/DebugFieldWindow.cs b/Maple2.Server.DebugGame/Graphics/DebugFieldWindow.cs
index 637c0458f..ed0248258 100644
--- a/Maple2.Server.DebugGame/Graphics/DebugFieldWindow.cs
+++ b/Maple2.Server.DebugGame/Graphics/DebugFieldWindow.cs
@@ -10,7 +10,6 @@
using Silk.NET.Maths;
using Silk.NET.Windowing;
using System.Drawing;
-using static Community.CsharpSqlite.Sqlite3;
using static Maple2.Server.Game.Manager.Field.FieldManager;
namespace Maple2.Server.DebugGame.Graphics;
diff --git a/Maple2.Server.Game/Commands/TriggerCommand.cs b/Maple2.Server.Game/Commands/TriggerCommand.cs
index d35807c4d..d5f698bb9 100644
--- a/Maple2.Server.Game/Commands/TriggerCommand.cs
+++ b/Maple2.Server.Game/Commands/TriggerCommand.cs
@@ -35,10 +35,10 @@ private void Handle(InvocationContext ctx) {
ctx.Console.Out.WriteLine($"Triggers: {fieldTriggers.Count}");
foreach (FieldTrigger trigger in fieldTriggers) {
string triggerName = trigger.Value.Name;
- string[] triggerStates = GetStateNames(trigger);
- var result = new StringBuilder($"TriggerStates for {triggerName}, count: {triggerStates.Length}\n");
+ List triggerStates = trigger.GetStateNames();
+ var result = new StringBuilder($"TriggerStates for {triggerName}, count: {triggerStates.Count}\n");
- for (int i = 0; i < triggerStates.Length; i++) {
+ for (int i = 0; i < triggerStates.Count; i++) {
result.AppendLine($" -[{i}] {triggerStates[i]}");
}
@@ -79,8 +79,8 @@ private void Handle(InvocationContext ctx, string triggerName, int stateIndex) {
ctx.Console.Out.WriteLine($"Trigger {triggerName} reset.");
} else {
// Set trigger to specific state
- string[] triggerStates = GetStateNames(currentFieldTrigger);
- if (stateIndex >= triggerStates.Length) {
+ List triggerStates = currentFieldTrigger.GetStateNames();
+ if (stateIndex >= triggerStates.Count) {
ctx.Console.Error.WriteLine($"Invalid state index for {triggerName}");
return;
}
@@ -183,10 +183,4 @@ private void Handle(InvocationContext ctx, string functionName, string[] paramet
ctx.Console.Out.WriteLine($"Function {functionName} executed.");
}
}
-
- private static string[] GetStateNames(FieldTrigger trigger) {
- return trigger.Context.Scope.GetVariableNames()
- .Where(v => !v.StartsWith("__") && v != "trigger_api" && v != "initial_state")
- .ToArray();
- }
}
diff --git a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.Trigger.cs b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.Trigger.cs
index 7cad412ad..99d016c9b 100644
--- a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.Trigger.cs
+++ b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.Trigger.cs
@@ -3,7 +3,7 @@
using Maple2.Model.Metadata;
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Model.Widget;
-using Maple2.Server.Game.Scripting.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
namespace Maple2.Server.Game.Manager.Field;
@@ -15,7 +15,7 @@ public partial class FieldManager {
public readonly Dictionary Timers = new();
public readonly Dictionary UserValues = new();
public readonly Dictionary Widgets = new();
- public readonly Dictionary> States = new();
+ public readonly Dictionary> States = new();
public FieldTrigger? AddTrigger(TriggerModel trigger) {
try {
diff --git a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs
index 06d39bcf0..75b3371ee 100644
--- a/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs
+++ b/Maple2.Server.Game/Manager/Field/FieldManager/FieldManager.cs
@@ -50,6 +50,7 @@ public partial class FieldManager : IField {
public FunctionCubeMetadataStorage FunctionCubeMetadata { get; init; } = null!;
public ServerTableMetadataStorage ServerTableMetadata { get; init; } = null!;
public RideMetadataStorage RideMetadata { get; init; } = null!;
+ public TriggerScriptMetadata TriggerMetadata { get; init; } = null!;
public ItemStatsCalculator ItemStatsCalc { get; init; } = null!;
public Factory FieldFactory { get; init; } = null!;
public IGraphicsContext DebugGraphicsContext { get; init; } = null!;
diff --git a/Maple2.Server.Game/Manager/ShopManager.cs b/Maple2.Server.Game/Manager/ShopManager.cs
index 2ba5bff7e..e78b0e2f7 100644
--- a/Maple2.Server.Game/Manager/ShopManager.cs
+++ b/Maple2.Server.Game/Manager/ShopManager.cs
@@ -9,7 +9,6 @@
using Maple2.Server.Game.Packets;
using Maple2.Server.Game.Session;
using Maple2.Tools.Extensions;
-using Microsoft.Scripting.Utils;
using Serilog;
namespace Maple2.Server.Game.Manager;
diff --git a/Maple2.Server.Game/Maple2.Server.Game.csproj b/Maple2.Server.Game/Maple2.Server.Game.csproj
index f08313e0b..b5ec53617 100644
--- a/Maple2.Server.Game/Maple2.Server.Game.csproj
+++ b/Maple2.Server.Game/Maple2.Server.Game.csproj
@@ -23,10 +23,6 @@
-
-
-
-
@@ -62,9 +58,5 @@
Always
-
- Scripts/Trigger/trigger_api.py
- Always
-
diff --git a/Maple2.Server.Game/Model/Field/Entity/FieldTrigger.cs b/Maple2.Server.Game/Model/Field/Entity/FieldTrigger.cs
index 1d98bf446..cbd2e4e80 100644
--- a/Maple2.Server.Game/Model/Field/Entity/FieldTrigger.cs
+++ b/Maple2.Server.Game/Model/Field/Entity/FieldTrigger.cs
@@ -1,29 +1,95 @@
-using Maple2.Model.Metadata;
+using System.Diagnostics;
+using System.Xml;
+using Maple2.Model.Metadata;
using Maple2.Server.Game.Manager.Field;
using Maple2.Server.Game.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
using Maple2.Server.Game.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
+using Maple2.Tools;
+using Serilog;
namespace Maple2.Server.Game.Model;
public class FieldTrigger : FieldEntity {
- private static readonly TriggerScriptLoader TriggerLoader = new();
-
public readonly TriggerContext Context;
+ private readonly XmlDocument triggerDocument;
private long nextTick;
private TriggerState? state;
private TriggerState? nextState;
public FieldTrigger(FieldManager field, int objectId, TriggerModel value) : base(field, objectId, value) {
- Context = TriggerLoader.CreateContext(this);
+ Context = new TriggerContext(this);
+ var document = new XmlDocument();
+ string xml;
+ if (!Constant.DebugTriggers) {
+ field.TriggerMetadata.TryGet(Field.Metadata.XBlock, Value.Name.ToLower(), out TriggerMetadata? metadata);
+ if (metadata == null) {
+ throw new ArgumentException($"Trigger {Value.Name} not found in {Field.Metadata.XBlock}");
+ }
+ xml = metadata.Xml;
+ } else {
+ string triggerFilePath = Path.Combine(Paths.DEBUG_TRIGGERS_DIR, Field.Metadata.XBlock, Value.Name.ToLower() + ".xml");
+ if (!File.Exists(triggerFilePath)) {
+ throw new ArgumentException($"You are running DebugTriggers, but the trigger file does not exist: {triggerFilePath}");
+ }
+ xml = File.ReadAllText(triggerFilePath);
+ }
+
+ document.LoadXml(xml);
+ triggerDocument = document;
+
+ XmlElement? root = document.DocumentElement;
+ if (root is not { Name: "ms2" }) {
+ throw new ArgumentException($"Trigger {Value.Name} has no root element in {Field.Metadata.XBlock}");
+ }
+
+ XmlNode? initialState = root.SelectSingleNode("state");
+ if (initialState is not { Name: "state" }) {
+ throw new ArgumentException($"Trigger {Value.Name} has no element in {Field.Metadata.XBlock}");
+ }
+
+ nextState = new TriggerState(initialState, Context);
+ nextTick = field.FieldTick;
+ }
+
+ public List GetStates(string[] names) {
+ if (names.Length == 0) {
+ throw new ArgumentException("At least one state name must be provided.");
+ }
+
+ List states = [];
+ foreach (XmlNode stateNode in triggerDocument.SelectNodes("//state")!) {
+ if (stateNode is not XmlElement stateElement || !names.Contains(stateElement.GetAttribute("name"))) {
+ continue;
+ }
+ states.Add(new TriggerState(stateNode, Context));
+ }
+
+ return states;
+ }
- // We load the initial_state as nextState so on_enter() will be called.
- if (!TriggerLoader.TryInitScript(Context, Field.Metadata.XBlock, Value.Name.ToLower(), out nextState)) {
- throw new ArgumentException($"Invalid trigger for {Field.Metadata.XBlock}, {Value.Name.ToLower()}");
+ public TriggerState? GetState(string name) {
+ XmlNode? stateNode = triggerDocument.SelectSingleNode($"//state[@name='{name}']");
+ if (stateNode == null) {
+ return null;
}
- nextTick = Environment.TickCount64;
+ return new TriggerState(stateNode, Context);
+ }
+
+ public XmlNode? GetStateNode(string name) {
+ return triggerDocument.SelectSingleNode($"//state[@name='{name}']");
+ }
+
+ public List GetStateNames() {
+ List stateNames = [];
+ foreach (XmlNode stateNode in triggerDocument.SelectNodes("//state")!) {
+ if (stateNode is XmlElement stateElement) {
+ stateNames.Add(stateElement.GetAttribute("name"));
+ }
+ }
+ return stateNames;
}
public bool Skip() {
@@ -46,10 +112,10 @@ public override void Update(long tickCount) {
nextTick += Constant.NextStateTriggerDefaultTick;
if (nextState != null) {
- Context.DebugLog("[OnExit] {State}", state?.Name?.Value ?? "null");
+ Context.DebugLog("[OnExit] {State}", state?.Name ?? "null");
state?.OnExit();
state = nextState;
- Context.StartTick = Environment.TickCount64;
+ Context.StartTick = Field.FieldTick;
Context.DebugLog("[OnEnter] {State}", state.Name);
nextState = state.OnEnter();
@@ -66,12 +132,12 @@ public override void Update(long tickCount) {
/// Should only be used for debugging
///
public bool SetNextState(string next) {
- dynamic? stateClass = Context.Scope.GetVariable(next);
+ TriggerState? stateClass = GetState(next);
if (stateClass == null) {
return false;
}
- nextState = Context.CreateState(stateClass);
+ nextState = stateClass;
return nextState != null;
}
}
diff --git a/Maple2.Server.Game/PacketHandlers/UserChatHandler.cs b/Maple2.Server.Game/PacketHandlers/UserChatHandler.cs
index ad0fbebdf..02a274856 100644
--- a/Maple2.Server.Game/PacketHandlers/UserChatHandler.cs
+++ b/Maple2.Server.Game/PacketHandlers/UserChatHandler.cs
@@ -12,7 +12,6 @@
using Maple2.Server.Core.Packets;
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
using Maple2.Server.Game.Session;
using WorldClient = Maple2.Server.World.Service.World.WorldClient;
diff --git a/Maple2.Server.Game/Packets/CinematicPacket.cs b/Maple2.Server.Game/Packets/CinematicPacket.cs
index 69b6b95dd..eae29f2e1 100644
--- a/Maple2.Server.Game/Packets/CinematicPacket.cs
+++ b/Maple2.Server.Game/Packets/CinematicPacket.cs
@@ -1,7 +1,7 @@
using Maple2.PacketLib.Tools;
using Maple2.Server.Core.Constants;
using Maple2.Server.Core.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
namespace Maple2.Server.Game.Packets;
diff --git a/Maple2.Server.Game/Packets/MassiveEventPacket.cs b/Maple2.Server.Game/Packets/MassiveEventPacket.cs
index 87f782e99..db85f29ca 100644
--- a/Maple2.Server.Game/Packets/MassiveEventPacket.cs
+++ b/Maple2.Server.Game/Packets/MassiveEventPacket.cs
@@ -2,7 +2,7 @@
using Maple2.PacketLib.Tools;
using Maple2.Server.Core.Constants;
using Maple2.Server.Core.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
using Maple2.Tools.Extensions;
namespace Maple2.Server.Game.Packets;
diff --git a/Maple2.Server.Game/Packets/ProxyObjectPacket.cs b/Maple2.Server.Game/Packets/ProxyObjectPacket.cs
index 3227012f7..7f378a5f7 100644
--- a/Maple2.Server.Game/Packets/ProxyObjectPacket.cs
+++ b/Maple2.Server.Game/Packets/ProxyObjectPacket.cs
@@ -6,7 +6,6 @@
using Maple2.Server.Core.Constants;
using Maple2.Server.Core.Packets;
using Maple2.Server.Game.Model;
-using Microsoft.Scripting.Metadata;
namespace Maple2.Server.Game.Packets;
diff --git a/Maple2.Server.Game/Packets/TriggerPacket.cs b/Maple2.Server.Game/Packets/TriggerPacket.cs
index 25e049303..16b716dc2 100644
--- a/Maple2.Server.Game/Packets/TriggerPacket.cs
+++ b/Maple2.Server.Game/Packets/TriggerPacket.cs
@@ -5,7 +5,7 @@
using Maple2.Server.Core.Constants;
using Maple2.Server.Core.Packets;
using Maple2.Server.Game.Model;
-using Maple2.Server.Game.Scripting.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
using Maple2.Tools.Extensions;
namespace Maple2.Server.Game.Packets;
diff --git a/Maple2.Server.Game/Scripting/Scripts b/Maple2.Server.Game/Scripting/Scripts
deleted file mode 160000
index cb2084ac8..000000000
--- a/Maple2.Server.Game/Scripting/Scripts
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit cb2084ac8a5312bff07b90c81c5931014ad8bc23
diff --git a/Maple2.Server.Game/Scripting/Trigger/TriggerScriptLoader.cs b/Maple2.Server.Game/Scripting/Trigger/TriggerScriptLoader.cs
deleted file mode 100644
index 21f7cd991..000000000
--- a/Maple2.Server.Game/Scripting/Trigger/TriggerScriptLoader.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using System.Collections.Concurrent;
-using System.Diagnostics.CodeAnalysis;
-using System.Text.RegularExpressions;
-using IronPython.Hosting;
-using Maple2.Server.Game.Model;
-using Maple2.Server.Game.Trigger;
-using Microsoft.Scripting.Hosting;
-using Serilog;
-
-namespace Maple2.Server.Game.Scripting.Trigger;
-
-public partial class TriggerScriptLoader {
- private string rootDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripts", "Trigger");
-
- private readonly ScriptEngine engine;
- private readonly ConcurrentDictionary> scriptSources;
- private readonly ILogger logger = Log.Logger.ForContext();
-
- [GeneratedRegex(@"^from\s+(\w.+)\s+import\s+\*\s*$")]
- private static partial Regex ScriptImportRegex();
-
- public TriggerScriptLoader() {
- engine = Python.CreateEngine();
- ICollection paths = engine.GetSearchPaths();
- paths.Add(rootDir);
- engine.SetSearchPaths(paths);
-
- scriptSources = new ConcurrentDictionary>();
- }
-
- // Initializes a script for the specified trigger. If the script has not yet been loaded, also loads it to the cache.
- public bool TryInitScript(TriggerContext context, string xBlock, string name, [NotNullWhen(true)] out TriggerState? state) {
- if (!TryGetScript(Path.Combine(xBlock, name), out List? scripts)) {
- state = null;
- return false;
- }
-
- // Script "compilation" needs to be synchronized.
- lock (engine) {
- foreach (ScriptSource script in scripts) {
- try {
- script.Execute(context.Scope);
- } catch (Exception e) {
- logger.Error(e, "Error executing script {Script} in context {Context}", script.GetCode(), context);
- state = null;
- return false;
- }
- }
- }
-
- dynamic? initialStateClass = context.Scope.GetVariable("initial_state");
- if (initialStateClass == null) {
- state = null;
- return false;
- }
-
- dynamic? initialState = engine.Operations.CreateInstance(initialStateClass, context);
- if (initialState == null) {
- state = null;
- return false;
- }
-
- state = new TriggerState(initialState);
- return true;
- }
-
- ///
- /// Retrieve a previously cached ScriptSource or build a new one. Imports are also resolved from the cache.
- ///
- /// Path without root directory and file extension.
- /// Resulting scripts (and imports) to execute in order.
- ///
- private bool TryGetScript(string key, [NotNullWhen(true)] out List? scripts) {
- if (scriptSources.TryGetValue(key, out scripts)) {
- return true;
- }
-
- string scriptPath = Path.Combine(rootDir, $"{key}.py");
- if (!File.Exists(scriptPath)) {
- return false;
- }
-
- ScriptSource scriptSource = engine.CreateScriptSourceFromFile(scriptPath);
- string code = scriptSource.GetCode();
- string[] lines = code.Split(["\n", "\r\n"], StringSplitOptions.None);
- scripts = new List();
- for (int i = 0; i < lines.Length; i++) {
- // Match "from dungeon_common.checkusercount import *"
- Match import = ScriptImportRegex().Match(lines[i]);
- if (!import.Success) {
- continue;
- }
-
- string[] parts = import.Groups[1].Value.Split('.');
- if (!TryGetScript(string.Join("/", parts), out List? importScripts)) {
- logger.Error("Invalid shared script import: L{Num} {Line}", i, lines[i]);
- continue;
- }
-
- scripts.AddRange(importScripts);
- lines[i] = string.Empty;
- }
-
- // If there were any valid imports, we need to regenerate source with them removed.
- // Otherwise, we can just add the original source.
- scripts.Add(scripts.Count > 0 ? engine.CreateScriptSourceFromString(string.Join("\n", lines)) : scriptSource);
- scriptSources[key] = scripts;
- return true;
- }
-
- public TriggerContext CreateContext(FieldTrigger owner) {
- return new TriggerContext(engine, owner);
- }
-}
diff --git a/Maple2.Server.Game/Scripting/Trigger/TriggerState.cs b/Maple2.Server.Game/Scripting/Trigger/TriggerState.cs
deleted file mode 100644
index cec35313e..000000000
--- a/Maple2.Server.Game/Scripting/Trigger/TriggerState.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.Runtime.CompilerServices;
-
-namespace Maple2.Server.Game.Scripting.Trigger;
-
-public class TriggerState {
- private readonly dynamic state;
-
- public Lazy Name => new(() => {
- // ""
- string str = IronPython.Runtime.Operations.UserTypeOps.ToStringHelper(state);
- return str.Substring(str.IndexOf('<') + 1, str.IndexOf(' ') - str.IndexOf('<') - 1);
- });
-
- public TriggerState(dynamic state) {
- this.state = state;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public TriggerState? OnEnter() {
- dynamic? result = state.on_enter();
- return result != null ? new TriggerState(result) : null;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public TriggerState? OnTick() {
- dynamic? result = state.on_tick();
- return result != null ? new TriggerState(result) : null;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OnExit() {
- state.on_exit();
- }
-}
diff --git a/Maple2.Server.Game/Scripting/Trigger/TriggerContext.cs b/Maple2.Server.Game/Trigger/Helpers/ITriggerContext.cs
similarity index 87%
rename from Maple2.Server.Game/Scripting/Trigger/TriggerContext.cs
rename to Maple2.Server.Game/Trigger/Helpers/ITriggerContext.cs
index ebaf81c37..a2f614437 100644
--- a/Maple2.Server.Game/Scripting/Trigger/TriggerContext.cs
+++ b/Maple2.Server.Game/Trigger/Helpers/ITriggerContext.cs
@@ -1,6 +1,6 @@
using System.Numerics;
-namespace Maple2.Server.Game.Scripting.Trigger;
+namespace Maple2.Server.Game.Trigger.Helpers;
public interface ITriggerContext {
// Actions
@@ -157,11 +157,11 @@ public interface ITriggerContext {
public void SetQuestComplete(int questId);
public void SetRandomMesh(int[] triggerIds, bool visible, int startDelay, int interval, int fade);
public void SetRope(int triggerId, bool visible, bool enable, int fade);
- public void SetSceneSkip(dynamic state, string action);
+ public void SetSceneSkip(string state, string nextState);
public void SetSkill(int[] triggerIds, bool enable);
- public void SetSkip(dynamic state);
+ public void SetSkip(string state);
public void SetSound(int triggerId, bool enable);
- public void SetState(int id, dynamic[] states, bool randomize);
+ public void SetState(int id, string[] states, bool randomize);
public void SetTimeScale(bool enable, float startScale, float endScale, float duration, int interpolator);
public void SetTimer(string timerId, int seconds, bool autoRemove, bool display, int vOffset, string type, string desc);
public void SetUserValue(int triggerId, string key, int value);
@@ -209,51 +209,50 @@ public interface ITriggerContext {
public void WriteLog(string logName, string @event, int triggerId, string subEvent, int level);
// Conditions
- public int BonusGameReward(int boxId);
- public bool CheckAnyUserAdditionalEffect(int boxId, int additionalEffectId, int level);
- public bool CheckDungeonLobbyUserCount();
- public bool CheckNpcAdditionalEffect(int spawnId, int additionalEffectId, int level);
- public float NpcDamage(int spawnId);
- public int NpcExtraData(int spawnPointId, string extraDataKey);
- public int NpcHp(int spawnId, bool isRelative);
- public bool CheckSameUserTag(int boxId);
- public bool CheckUser();
- public int UserCount();
- public int CountUsers(int boxId, int userTagId);
- public int DayOfWeek(string desc);
- public bool DetectLiftableObject(int[] boxIds, int itemId);
- public int DungeonPlayTime();
- public string DungeonState();
- public int DungeonFirstUserMissionScore();
- public int DungeonId();
- public int DungeonLevel();
- public int DungeonMaxUserCount();
- public int DungeonRound();
+ public bool BonusGameReward(int boxId, int type);
+ public bool CheckAnyUserAdditionalEffect(int boxId, int additionalEffectId, int level, bool negate);
+ public bool CheckDungeonLobbyUserCount(bool negate);
+ public bool CheckNpcAdditionalEffect(int spawnId, int additionalEffectId, int level, bool negate);
+ public bool NpcDamage(int spawnId, float damageRate, OperatorType operatorType);
+ public bool NpcExtraData(int spawnPointId, string extraDataKey, int extraDataValue, OperatorType operatorType);
+ public bool NpcHp(int spawnId, bool isRelative, int value, CompareType compareType);
+ public bool CheckSameUserTag(int boxId, bool negate);
+ public bool CheckUser(bool negate);
+ public bool UserCount(int count);
+ public bool CountUsers(int boxId, int userTagId, int minUsers, OperatorType operatorType, bool negate);
+ public bool DayOfWeek(int[] dayOfWeeks, string desc, bool negate);
+ public bool DetectLiftableObject(int[] boxIds, int itemId, bool negate);
+ public bool DungeonPlayTime(int playSeconds);
+ public bool DungeonState(string checkState);
+ public bool DungeonFirstUserMissionScore(int score, OperatorType operatorType);
+ public bool DungeonId(int dungeonId);
+ public bool DungeonLevel(int level);
+ public bool DungeonMaxUserCount(int value);
+ public bool DungeonRound(int round);
public bool DungeonTimeout();
- public int DungeonVariable(int varId);
+ public bool DungeonVariable(int varId, int value);
public bool GuildVsGameScoredTeam(int teamId);
public bool GuildVsGameWinnerTeam(int teamId);
- public bool IsDungeonRoom();
- public bool IsPlayingMapleSurvival();
+ public bool IsDungeonRoom(bool negate);
+ public bool IsPlayingMapleSurvival(bool negate);
public bool MonsterDead(int[] spawnIds, bool autoTarget);
- public bool MonsterInCombat(int[] spawnIds);
- public bool NpcDetected(int boxId, int[] spawnIds);
+ public bool MonsterInCombat(int[] spawnIds, bool negate);
+ public bool NpcDetected(int boxId, int[] spawnIds, bool negate);
public bool NpcIsDeadByStringId(string stringId);
public bool ObjectInteracted(int[] interactIds, int state);
public bool PvpZoneEnded(int boxId);
- public bool QuestUserDetected(int[] boxIds, int[] questIds, int[] questStates, int jobCode);
+ public bool QuestUserDetected(int[] boxIds, int[] questIds, int[] questStates, int jobCode, bool negate);
public bool RandomCondition(float weight, string desc);
- public int ScoreBoardScore();
- public int ShadowExpeditionPoints();
+ public bool ScoreBoardScore(int score, OperatorType operatorType);
+ public bool ShadowExpeditionPoints(int score);
public bool TimeExpired(string timerId);
public bool UserDetected(int[] boxIds, int jobCode);
- public int UserValue(string key);
+ public bool UserValue(string key, int value, bool negate);
public bool WaitAndResetTick(int waitTick);
public bool WaitSecondsUserValue(string key, string desc);
public bool WaitTick(int waitTick);
public bool WeddingEntryInField(string entryType, bool isInField);
- public string WeddingHallState(bool success);
+ public bool WeddingHallState(string state, bool success);
public bool WeddingMutualAgreeResult(string agreeType);
- public int WidgetValue(string type, string name, string desc);
+ public bool WidgetValue(string type, string widgetName, int condition, bool negate, string desc);
}
-
diff --git a/Maple2.Server.Game/Scripting/Trigger/TriggerEnums.cs b/Maple2.Server.Game/Trigger/Helpers/TriggerEnums.cs
similarity index 80%
rename from Maple2.Server.Game/Scripting/Trigger/TriggerEnums.cs
rename to Maple2.Server.Game/Trigger/Helpers/TriggerEnums.cs
index 806f8cb52..3493e3e1c 100644
--- a/Maple2.Server.Game/Scripting/Trigger/TriggerEnums.cs
+++ b/Maple2.Server.Game/Trigger/Helpers/TriggerEnums.cs
@@ -1,4 +1,4 @@
-namespace Maple2.Server.Game.Scripting.Trigger;
+namespace Maple2.Server.Game.Trigger.Helpers;
// ReSharper disable InconsistentNaming
public enum Align { center = 0, left = 1, right = 2, bottomLeft = 3, bottomRight = 4, topCenter = 5, centerLeft = 6, centerRight = 7 }
@@ -15,3 +15,7 @@ public enum Weather { Clear = 0, Snow = 1, HeavySnow = 2, Rain = 3, HeavyRain =
public enum BannerType : byte { Lose = 0, GameOver = 1, Winner = 2, Bonus = 3, Draw = 4, Success = 5, Text = 6, Fail = 7, Countdown = 8, }
public enum SideNpcTalkType : byte { Default = 0, Movie = 1, CutIn = 2, TalkBottom = 3, Invasion = 4, Wedding = 5 }
+
+public enum OperatorType { Greater, GreaterEqual, Equal, LessEqual, Less };
+
+public enum CompareType { lowerEqual, lower, higher, higherEqual };
diff --git a/Maple2.Server.Game/Trigger/Helpers/TriggerFunctionMapping.cs b/Maple2.Server.Game/Trigger/Helpers/TriggerFunctionMapping.cs
new file mode 100644
index 000000000..b752de974
--- /dev/null
+++ b/Maple2.Server.Game/Trigger/Helpers/TriggerFunctionMapping.cs
@@ -0,0 +1,349 @@
+using System.Numerics;
+using System.Xml;
+
+namespace Maple2.Server.Game.Trigger.Helpers;
+
+public static class TriggerFunctionMapping {
+ public static readonly Dictionary> ActionMap = new Dictionary> {
+ { "add_balloon_talk", (ctx, attrs) => ctx.AddBalloonTalk(ParseInt(attrs?["spawn_id"]?.Value), attrs?["msg"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value), ParseInt(attrs?["delay_tick"]?.Value), ParseInt(attrs?["npc_id"]?.Value)) },
+ { "add_buff", (ctx, attrs) => ctx.AddBuff(ParseIntArray(attrs?["box_ids"]?.Value), ParseInt(attrs?["skill_id"]?.Value), ParseInt(attrs?["level"]?.Value), ParseBool(attrs?["ignore_player"]?.Value), ParseBool(attrs?["is_skill_set"]?.Value), attrs?["feature"]?.Value ?? string.Empty) },
+ { "add_cinematic_talk", (ctx, attrs) => ctx.AddCinematicTalk(ParseInt(attrs?["npc_id"]?.Value), attrs?["illust_id"]?.Value ?? string.Empty, attrs?["msg"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value), ParseAlign(attrs?["align"]?.Value), ParseInt(attrs?["delay_tick"]?.Value)) },
+ { "add_effect_nif", (ctx, attrs) => ctx.AddEffectNif(ParseInt(attrs?["spawn_id"]?.Value), attrs?["nif_path"]?.Value ?? string.Empty, ParseBool(attrs?["is_outline"]?.Value), ParseFloat(attrs?["scale"]?.Value), ParseInt(attrs?["rotate_z"]?.Value)) },
+ { "add_user_value", (ctx, attrs) => ctx.AddUserValue(attrs?["key"]?.Value ?? string.Empty, ParseInt(attrs?["value"]?.Value)) },
+ { "allocate_battlefield_points", (ctx, attrs) => ctx.AllocateBattlefieldPoints(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["points"]?.Value)) },
+ { "announce", (ctx, attrs) => ctx.Announce(ParseInt(attrs?["type"]?.Value), attrs?["content"]?.Value ?? string.Empty, ParseBool(attrs?["arg3"]?.Value)) },
+ { "arcade_boom_boom_ocean_clear_round", (ctx, attrs) => ctx.ArcadeBoomBoomOceanClearRound(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_boom_boom_ocean_end_game", (ctx, _) => ctx.ArcadeBoomBoomOceanEndGame() },
+ { "arcade_boom_boom_ocean_set_skill_score", (ctx, attrs) => ctx.ArcadeBoomBoomOceanSetSkillScore(ParseInt(attrs?["id"]?.Value), ParseInt(attrs?["score"]?.Value)) },
+ { "arcade_boom_boom_ocean_start_game", (ctx, attrs) => ctx.ArcadeBoomBoomOceanStartGame(ParseInt(attrs?["life_count"]?.Value)) },
+ { "arcade_boom_boom_ocean_start_round", (ctx, attrs) => ctx.ArcadeBoomBoomOceanStartRound(ParseInt(attrs?["round"]?.Value), ParseInt(attrs?["round_duration"]?.Value), ParseInt(attrs?["time_score_rate"]?.Value)) },
+ { "arcade_spring_farm_clear_round", (ctx, attrs) => ctx.ArcadeSpringFarmClearRound(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_spring_farm_end_game", (ctx, _) => ctx.ArcadeSpringFarmEndGame() },
+ { "arcade_spring_farm_set_interact_score", (ctx, attrs) => ctx.ArcadeSpringFarmSetInteractScore(ParseInt(attrs?["id"]?.Value), ParseInt(attrs?["score"]?.Value)) },
+ { "arcade_spring_farm_spawn_monster", (ctx, attrs) => ctx.ArcadeSpringFarmSpawnMonster(ParseIntArray(attrs?["spawn_ids"]?.Value), ParseInt(attrs?["score"]?.Value)) },
+ { "arcade_spring_farm_start_game", (ctx, attrs) => ctx.ArcadeSpringFarmStartGame(ParseInt(attrs?["life_count"]?.Value)) },
+ { "arcade_spring_farm_start_round", (ctx, attrs) => ctx.ArcadeSpringFarmStartRound(ParseInt(attrs?["ui_duration"]?.Value), ParseInt(attrs?["round"]?.Value), attrs?["time_score_type"]?.Value ?? string.Empty, ParseInt(attrs?["time_score_rate"]?.Value), ParseInt(attrs?["round_duration"]?.Value)) },
+ { "arcade_three_two_one_clear_round", (ctx, attrs) => ctx.ArcadeThreeTwoOneClearRound(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one_end_game", (ctx, _) => ctx.ArcadeThreeTwoOneEndGame() },
+ { "arcade_three_two_one_result_round", (ctx, attrs) => ctx.ArcadeThreeTwoOneResultRound(ParseInt(attrs?["result_direction"]?.Value)) },
+ { "arcade_three_two_one_result_round2", (ctx, attrs) => ctx.ArcadeThreeTwoOneResultRound2(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one_start_game", (ctx, attrs) => ctx.ArcadeThreeTwoOneStartGame(ParseInt(attrs?["life_count"]?.Value), ParseInt(attrs?["init_score"]?.Value)) },
+ { "arcade_three_two_one_start_round", (ctx, attrs) => ctx.ArcadeThreeTwoOneStartRound(ParseInt(attrs?["ui_duration"]?.Value), ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one2_clear_round", (ctx, attrs) => ctx.ArcadeThreeTwoOne2ClearRound(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one2_end_game", (ctx, _) => ctx.ArcadeThreeTwoOne2EndGame() },
+ { "arcade_three_two_one2_result_round", (ctx, attrs) => ctx.ArcadeThreeTwoOne2ResultRound(ParseInt(attrs?["result_direction"]?.Value)) },
+ { "arcade_three_two_one2_result_round2", (ctx, attrs) => ctx.ArcadeThreeTwoOne2ResultRound2(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one2_start_game", (ctx, attrs) => ctx.ArcadeThreeTwoOne2StartGame(ParseInt(attrs?["life_count"]?.Value), ParseInt(attrs?["init_score"]?.Value)) },
+ { "arcade_three_two_one2_start_round", (ctx, attrs) => ctx.ArcadeThreeTwoOne2StartRound(ParseInt(attrs?["ui_duration"]?.Value), ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one3_clear_round", (ctx, attrs) => ctx.ArcadeThreeTwoOne3ClearRound(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one3_end_game", (ctx, _) => ctx.ArcadeThreeTwoOne3EndGame() },
+ { "arcade_three_two_one3_result_round", (ctx, attrs) => ctx.ArcadeThreeTwoOne3ResultRound(ParseInt(attrs?["result_direction"]?.Value)) },
+ { "arcade_three_two_one3_result_round2", (ctx, attrs) => ctx.ArcadeThreeTwoOne3ResultRound2(ParseInt(attrs?["round"]?.Value)) },
+ { "arcade_three_two_one3_start_game", (ctx, attrs) => ctx.ArcadeThreeTwoOne3StartGame(ParseInt(attrs?["life_count"]?.Value), ParseInt(attrs?["init_score"]?.Value)) },
+ { "arcade_three_two_one3_start_round", (ctx, attrs) => ctx.ArcadeThreeTwoOne3StartRound(ParseInt(attrs?["ui_duration"]?.Value), ParseInt(attrs?["round"]?.Value)) },
+ { "change_background", (ctx, attrs) => ctx.ChangeBackground(attrs?["dds"]?.Value ?? string.Empty) },
+ { "change_monster", (ctx, attrs) => ctx.ChangeMonster(ParseInt(attrs?["from_spawn_id"]?.Value), ParseInt(attrs?["to_spawn_id"]?.Value)) },
+ { "close_cinematic", (ctx, _) => ctx.CloseCinematic() },
+ { "create_field_game", (ctx, attrs) => ctx.CreateFieldGame(ParseFieldGame(attrs?["type"]?.Value), ParseBool(attrs?["reset"]?.Value)) },
+ { "create_item", (ctx, attrs) => ctx.CreateItem(ParseIntArray(attrs?["spawn_ids"]?.Value), ParseInt(attrs?["trigger_id"]?.Value), ParseInt(attrs?["item_id"]?.Value), ParseInt(attrs?["arg5"]?.Value)) },
+ { "create_widget", (ctx, attrs) => ctx.CreateWidget(attrs?["type"]?.Value ?? string.Empty) },
+ { "dark_stream_clear_round", (ctx, attrs) => ctx.DarkStreamClearRound(ParseInt(attrs?["round"]?.Value)) },
+ { "dark_stream_spawn_monster", (ctx, attrs) => ctx.DarkStreamSpawnMonster(ParseIntArray(attrs?["spawn_ids"]?.Value), ParseInt(attrs?["score"]?.Value)) },
+ { "dark_stream_start_game", (ctx, attrs) => ctx.DarkStreamStartGame(ParseInt(attrs?["round"]?.Value)) },
+ { "dark_stream_start_round", (ctx, attrs) => ctx.DarkStreamStartRound(ParseInt(attrs?["round"]?.Value), ParseInt(attrs?["ui_duration"]?.Value), ParseInt(attrs?["damage_penalty"]?.Value)) },
+ { "debug_string", (ctx, attrs) => ctx.DebugString(attrs?["value"]?.Value ?? string.Empty, attrs?["feature"]?.Value ?? string.Empty) },
+ { "destroy_monster", (ctx, attrs) => ctx.DestroyMonster(ParseIntArray(attrs?["spawn_ids"]?.Value), ParseBool(attrs?["arg2"]?.Value)) },
+ { "dungeon_clear", (ctx, attrs) => ctx.DungeonClear(attrs?["ui_type"]?.Value ?? string.Empty) },
+ { "dungeon_clear_round", (ctx, attrs) => ctx.DungeonClearRound(ParseInt(attrs?["round"]?.Value)) },
+ { "dungeon_close_timer", (ctx, _) => ctx.DungeonCloseTimer() },
+ { "dungeon_disable_ranking", (ctx, _) => ctx.DungeonDisableRanking() },
+ { "dungeon_enable_give_up", (ctx, attrs) => ctx.DungeonEnableGiveUp(ParseBool(attrs?["is_enable"]?.Value)) },
+ { "dungeon_fail", (ctx, _) => ctx.DungeonFail() },
+ { "dungeon_mission_complete", (ctx, attrs) => ctx.DungeonMissionComplete(attrs?["feature"]?.Value ?? string.Empty, ParseInt(attrs?["mission_id"]?.Value)) },
+ { "dungeon_move_lap_time_to_now", (ctx, attrs) => ctx.DungeonMoveLapTimeToNow(ParseInt(attrs?["id"]?.Value)) },
+ { "dungeon_reset_time", (ctx, attrs) => ctx.DungeonResetTime(ParseInt(attrs?["seconds"]?.Value)) },
+ { "dungeon_set_end_time", (ctx, _) => ctx.DungeonSetEndTime() },
+ { "dungeon_set_lap_time", (ctx, attrs) => ctx.DungeonSetLapTime(ParseInt(attrs?["id"]?.Value), ParseInt(attrs?["lap_time"]?.Value)) },
+ { "dungeon_stop_timer", (ctx, _) => ctx.DungeonStopTimer() },
+ { "set_dungeon_variable", (ctx, attrs) => ctx.SetDungeonVariable(ParseInt(attrs?["var_id"]?.Value), ParseInt(attrs?["value"]?.Value)) },
+ { "enable_local_camera", (ctx, attrs) => ctx.EnableLocalCamera(ParseBool(attrs?["is_enable"]?.Value)) },
+ { "enable_spawn_point_pc", (ctx, attrs) => ctx.EnableSpawnPointPc(ParseInt(attrs?["spawn_id"]?.Value), ParseBool(attrs?["is_enable"]?.Value)) },
+ { "end_mini_game", (ctx, attrs) => ctx.EndMiniGame(ParseInt(attrs?["winner_box_id"]?.Value), attrs?["game_name"]?.Value ?? string.Empty, ParseBool(attrs?["is_only_winner"]?.Value)) },
+ { "end_mini_game_round", (ctx, attrs) => ctx.EndMiniGameRound(ParseInt(attrs?["winner_box_id"]?.Value), ParseFloat(attrs?["exp_rate"]?.Value), ParseFloat(attrs?["meso"]?.Value), ParseBool(attrs?["is_only_winner"]?.Value), ParseBool(attrs?["is_gain_loser_bonus"]?.Value), attrs?["game_name"]?.Value ?? string.Empty) },
+ { "face_emotion", (ctx, attrs) => ctx.FaceEmotion(ParseInt(attrs?["spawn_id"]?.Value), attrs?["emotion_name"]?.Value ?? string.Empty) },
+ { "field_game_constant", (ctx, attrs) => ctx.FieldGameConstant(attrs?["key"]?.Value ?? string.Empty, attrs?["value"]?.Value ?? string.Empty, attrs?["feature"]?.Value ?? string.Empty, ParseLocale(attrs?["locale"]?.Value)) },
+ { "field_game_message", (ctx, attrs) => ctx.FieldGameMessage(ParseInt(attrs?["custom"]?.Value), attrs?["type"]?.Value ?? string.Empty, ParseBool(attrs?["arg1"]?.Value), attrs?["script"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value)) },
+ { "field_war_end", (ctx, attrs) => ctx.FieldWarEnd(ParseBool(attrs?["is_clear"]?.Value)) },
+ { "give_exp", (ctx, attrs) => ctx.GiveExp(ParseInt(attrs?["box_id"]?.Value), ParseFloat(attrs?["rate"]?.Value), ParseBool(attrs?["arg3"]?.Value)) },
+ { "give_guild_exp", (ctx, attrs) => ctx.GiveGuildExp(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["type"]?.Value)) },
+ { "give_reward_content", (ctx, attrs) => ctx.GiveRewardContent(ParseInt(attrs?["reward_id"]?.Value)) },
+ { "guide_event", (ctx, attrs) => ctx.GuideEvent(ParseInt(attrs?["event_id"]?.Value)) },
+ { "guild_vs_game_end_game", (ctx, _) => ctx.GuildVsGameEndGame() },
+ { "guild_vs_game_give_contribution", (ctx, attrs) => ctx.GuildVsGameGiveContribution(ParseInt(attrs?["team_id"]?.Value), ParseBool(attrs?["is_win"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ { "guild_vs_game_give_reward", (ctx, attrs) => ctx.GuildVsGameGiveReward(attrs?["type"]?.Value ?? string.Empty, ParseInt(attrs?["team_id"]?.Value), ParseBool(attrs?["is_win"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ { "guild_vs_game_log_result", (ctx, attrs) => ctx.GuildVsGameLogResult(attrs?["desc"]?.Value ?? string.Empty) },
+ { "guild_vs_game_log_won_by_default", (ctx, attrs) => ctx.GuildVsGameLogWonByDefault(ParseInt(attrs?["team_id"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ { "guild_vs_game_result", (ctx, attrs) => ctx.GuildVsGameResult(attrs?["desc"]?.Value ?? string.Empty) },
+ { "guild_vs_game_score_by_user", (ctx, attrs) => ctx.GuildVsGameScoreByUser(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["score"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ { "hide_guide_summary", (ctx, attrs) => ctx.HideGuideSummary(ParseInt(attrs?["entity_id"]?.Value), ParseInt(attrs?["text_id"]?.Value)) },
+ { "init_npc_rotation", (ctx, attrs) => ctx.InitNpcRotation(ParseIntArray(attrs?["spawn_ids"]?.Value)) },
+ { "kick_music_audience", (ctx, attrs) => ctx.KickMusicAudience(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["portal_id"]?.Value)) },
+ { "limit_spawn_npc_count", (ctx, attrs) => ctx.LimitSpawnNpcCount(ParseInt(attrs?["limit_count"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ { "lock_my_pc", (ctx, attrs) => ctx.LockMyPc(ParseBool(attrs?["is_lock"]?.Value)) },
+ { "mini_game_camera_direction", (ctx, attrs) => ctx.MiniGameCameraDirection(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["camera_id"]?.Value)) },
+ { "mini_game_give_exp", (ctx, attrs) => ctx.MiniGameGiveExp(ParseInt(attrs?["box_id"]?.Value), ParseFloat(attrs?["exp_rate"]?.Value), ParseBool(attrs?["is_outside"]?.Value)) },
+ { "mini_game_give_reward", (ctx, attrs) => ctx.MiniGameGiveReward(ParseInt(attrs?["winner_box_id"]?.Value), attrs?["content_type"]?.Value ?? string.Empty, attrs?["game_name"]?.Value ?? string.Empty) },
+ { "move_npc", (ctx, attrs) => ctx.MoveNpc(ParseInt(attrs?["spawn_id"]?.Value), attrs?["patrol_name"]?.Value ?? string.Empty) },
+ { "move_npc_to_pos", (ctx, attrs) => ctx.MoveNpcToPos(ParseInt(attrs?["spawn_id"]?.Value), ParseVector3(attrs?["pos"]?.Value), ParseVector3(attrs?["rot"]?.Value)) },
+ { "move_random_user", (ctx, attrs) => ctx.MoveRandomUser(ParseInt(attrs?["map_id"]?.Value), ParseInt(attrs?["portal_id"]?.Value), ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["count"]?.Value)) },
+ { "move_to_portal", (ctx, attrs) => ctx.MoveToPortal(ParseInt(attrs?["user_tag_id"]?.Value), ParseInt(attrs?["portal_id"]?.Value), ParseInt(attrs?["box_id"]?.Value)) },
+ { "move_user", (ctx, attrs) => ctx.MoveUser(ParseInt(attrs?["map_id"]?.Value), ParseInt(attrs?["portal_id"]?.Value), ParseInt(attrs?["box_id"]?.Value)) },
+ { "move_user_path", (ctx, attrs) => ctx.MoveUserPath(attrs?["patrol_name"]?.Value ?? string.Empty) },
+ { "move_user_to_box", (ctx, attrs) => ctx.MoveUserToBox(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["portal_id"]?.Value)) },
+ { "move_user_to_pos", (ctx, attrs) => ctx.MoveUserToPos(ParseVector3(attrs?["pos"]?.Value), ParseVector3(attrs?["rot"]?.Value)) },
+ { "notice", (ctx, attrs) => ctx.Notice(ParseInt(attrs?["type"]?.Value), attrs?["script"]?.Value ?? string.Empty, ParseBool(attrs?["arg3"]?.Value)) },
+ { "npc_remove_additional_effect", (ctx, attrs) => ctx.NpcRemoveAdditionalEffect(ParseInt(attrs?["spawn_id"]?.Value), ParseInt(attrs?["additional_effect_id"]?.Value)) },
+ { "npc_to_patrol_in_box", (ctx, attrs) => ctx.NpcToPatrolInBox(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["npc_id"]?.Value), attrs?["spawn_id"]?.Value ?? string.Empty, attrs?["patrol_name"]?.Value ?? string.Empty) },
+ { "patrol_condition_user", (ctx, attrs) => ctx.PatrolConditionUser(attrs?["patrol_name"]?.Value ?? string.Empty, ParseInt(attrs?["patrol_index"]?.Value), ParseInt(attrs?["additional_effect_id"]?.Value)) },
+ { "play_scene_movie", (ctx, attrs) => ctx.PlaySceneMovie(attrs?["file_name"]?.Value ?? string.Empty, ParseInt(attrs?["movie_id"]?.Value), attrs?["skip_type"]?.Value ?? string.Empty) },
+ { "play_system_sound_by_user_tag", (ctx, attrs) => ctx.PlaySystemSoundByUserTag(ParseInt(attrs?["user_tag_id"]?.Value), attrs?["sound_key"]?.Value ?? string.Empty) },
+ { "play_system_sound_in_box", (ctx, attrs) => ctx.PlaySystemSoundInBox(attrs?["sound"]?.Value ?? string.Empty, ParseIntArray(attrs?["box_ids"]?.Value)) }, {
+ "random_additional_effect", (ctx, attrs) =>
+ ctx.RandomAdditionalEffect(attrs?["target"]?.Value ?? string.Empty, ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["spawn_id"]?.Value),
+ ParseInt(attrs?["target_count"]?.Value), ParseInt(attrs?["tick"]?.Value), ParseInt(attrs?["wait_tick"]?.Value), attrs?["target_effect"]?.Value ?? string.Empty, ParseInt(attrs?["additional_effect_id"]?.Value))
+ },
+ { "remove_balloon_talk", (ctx, attrs) => ctx.RemoveBalloonTalk(ParseInt(attrs?["spawn_id"]?.Value)) },
+ { "remove_buff", (ctx, attrs) => ctx.RemoveBuff(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["skill_id"]?.Value), ParseBool(attrs?["is_player"]?.Value)) },
+ { "remove_cinematic_talk", (ctx, _) => ctx.RemoveCinematicTalk() },
+ { "remove_effect_nif", (ctx, attrs) => ctx.RemoveEffectNif(ParseInt(attrs?["spawn_id"]?.Value)) },
+ { "reset_camera", (ctx, attrs) => ctx.ResetCamera(ParseFloat(attrs?["interpolation_time"]?.Value)) },
+ { "reset_timer", (ctx, attrs) => ctx.ResetTimer(attrs?["timer_id"]?.Value ?? string.Empty) },
+ { "room_expire", (ctx, _) => ctx.RoomExpire() },
+ { "score_board_create", (ctx, attrs) => ctx.ScoreBoardCreate(attrs?["type"]?.Value ?? string.Empty, attrs?["title"]?.Value ?? string.Empty, ParseInt(attrs?["max_score"]?.Value)) },
+ { "score_board_remove", (ctx, _) => ctx.ScoreBoardRemove() },
+ { "score_board_set_score", (ctx, attrs) => ctx.ScoreBoardSetScore(ParseInt(attrs?["score"]?.Value)) },
+ { "select_camera", (ctx, attrs) => ctx.SelectCamera(ParseInt(attrs?["trigger_id"]?.Value), ParseBool(attrs?["enable"]?.Value)) },
+ { "select_camera_path", (ctx, attrs) => ctx.SelectCameraPath(ParseIntArray(attrs?["path_ids"]?.Value), ParseBool(attrs?["return_view"]?.Value)) },
+ { "set_achievement", (ctx, attrs) => ctx.SetAchievement(ParseInt(attrs?["trigger_id"]?.Value), attrs?["type"]?.Value ?? string.Empty, attrs?["achieve"]?.Value ?? string.Empty) },
+ { "set_actor", (ctx, attrs) => ctx.SetActor(ParseInt(attrs?["trigger_id"]?.Value), ParseBool(attrs?["visible"]?.Value), attrs?["initial_sequence"]?.Value ?? string.Empty, ParseBool(attrs?["arg4"]?.Value), ParseBool(attrs?["arg5"]?.Value)) },
+ { "set_agent", (ctx, attrs) => ctx.SetAgent(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["visible"]?.Value)) },
+ { "set_ai_extra_data", (ctx, attrs) => ctx.SetAiExtraData(attrs?["key"]?.Value ?? string.Empty, ParseInt(attrs?["value"]?.Value), ParseBool(attrs?["is_modify"]?.Value), ParseInt(attrs?["box_id"]?.Value)) },
+ { "set_ambient_light", (ctx, attrs) => ctx.SetAmbientLight(ParseVector3(attrs?["primary"]?.Value), ParseVector3(attrs?["secondary"]?.Value), ParseVector3(attrs?["tertiary"]?.Value)) },
+ { "set_breakable", (ctx, attrs) => ctx.SetBreakable(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["enable"]?.Value)) },
+ { "set_cinematic_intro", (ctx, attrs) => ctx.SetCinematicIntro(attrs?["text"]?.Value ?? string.Empty) },
+ { "set_cinematic_ui", (ctx, attrs) => ctx.SetCinematicUi(ParseInt(attrs?["type"]?.Value), attrs?["script"]?.Value ?? string.Empty, ParseBool(attrs?["arg3"]?.Value)) },
+ { "set_cube", (ctx, attrs) => ctx.SetCube(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["is_visible"]?.Value), ParseInt(attrs?["random_count"]?.Value)) },
+ { "set_dialogue", (ctx, attrs) => ctx.SetDialogue(ParseInt(attrs?["type"]?.Value), ParseInt(attrs?["spawn_id"]?.Value), attrs?["script"]?.Value ?? string.Empty, ParseInt(attrs?["time"]?.Value), ParseInt(attrs?["arg5"]?.Value), ParseAlign(attrs?["align"]?.Value)) },
+ { "set_directional_light", (ctx, attrs) => ctx.SetDirectionalLight(ParseVector3(attrs?["diffuse_color"]?.Value), ParseVector3(attrs?["specular_color"]?.Value)) },
+ { "set_effect", (ctx, attrs) => ctx.SetEffect(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["visible"]?.Value), ParseInt(attrs?["start_delay"]?.Value), ParseInt(attrs?["interval"]?.Value)) },
+ { "set_event_ui_countdown", (ctx, attrs) => ctx.SetEventUiCountdown(attrs?["script"]?.Value ?? string.Empty, ParseIntArray(attrs?["round_countdown"]?.Value), attrs?["box_ids"]?.Value.Split(',') ?? []) },
+ { "set_event_ui_round", (ctx, attrs) => ctx.SetEventUiRound(ParseIntArray(attrs?["rounds"]?.Value), ParseInt(attrs?["v_offset"]?.Value), ParseInt(attrs?["arg3"]?.Value)) },
+ { "set_event_ui_script", (ctx, attrs) => ctx.SetEventUiScript(ParseBannerType(attrs?["type"]?.Value), attrs?["script"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value), attrs?["box_ids"]?.Value.Split(',') ?? []) },
+ { "set_gravity", (ctx, attrs) => ctx.SetGravity(ParseFloat(attrs?["gravity"]?.Value)) },
+ { "set_interact_object", (ctx, attrs) => ctx.SetInteractObject(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseInt(attrs?["state"]?.Value), ParseBool(attrs?["arg4"]?.Value), ParseBool(attrs?["arg3"]?.Value)) },
+ { "set_ladder", (ctx, attrs) => ctx.SetLadder(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["visible"]?.Value), ParseBool(attrs?["enable"]?.Value), ParseInt(attrs?["fade"]?.Value)) },
+ { "set_local_camera", (ctx, attrs) => ctx.SetLocalCamera(ParseInt(attrs?["camera_id"]?.Value), ParseBool(attrs?["enable"]?.Value)) },
+ { "set_mesh", (ctx, attrs) => ctx.SetMesh(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["visible"]?.Value), ParseInt(attrs?["start_delay"]?.Value), ParseInt(attrs?["interval"]?.Value), ParseFloat(attrs?["fade"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ { "set_mesh_animation", (ctx, attrs) => ctx.SetMeshAnimation(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["visible"]?.Value), ParseInt(attrs?["start_delay"]?.Value), ParseInt(attrs?["interval"]?.Value)) },
+ { "set_mini_game_area_for_hack", (ctx, attrs) => ctx.SetMiniGameAreaForHack(ParseInt(attrs?["box_id"]?.Value)) },
+ { "set_npc_duel_hp_bar", (ctx, attrs) => ctx.SetNpcDuelHpBar(ParseBool(attrs?["is_open"]?.Value), ParseInt(attrs?["spawn_id"]?.Value), ParseInt(attrs?["duration_tick"]?.Value), ParseInt(attrs?["npc_hp_step"]?.Value)) },
+ { "set_npc_emotion_loop", (ctx, attrs) => ctx.SetNpcEmotionLoop(ParseInt(attrs?["spawn_id"]?.Value), attrs?["sequence_name"]?.Value ?? string.Empty, ParseFloat(attrs?["duration"]?.Value)) },
+ { "set_npc_emotion_sequence", (ctx, attrs) => ctx.SetNpcEmotionSequence(ParseInt(attrs?["spawn_id"]?.Value), attrs?["sequence_name"]?.Value ?? string.Empty, ParseInt(attrs?["duration_tick"]?.Value)) },
+ { "set_npc_rotation", (ctx, attrs) => ctx.SetNpcRotation(ParseInt(attrs?["spawn_id"]?.Value), ParseFloat(attrs?["rotation"]?.Value)) },
+ { "set_onetime_effect", (ctx, attrs) => ctx.SetOnetimeEffect(ParseInt(attrs?["id"]?.Value), ParseBool(attrs?["enable"]?.Value), attrs?["path"]?.Value ?? string.Empty) },
+ { "set_pc_emotion_loop", (ctx, attrs) => ctx.SetPcEmotionLoop(attrs?["sequence_name"]?.Value ?? string.Empty, ParseFloat(attrs?["duration"]?.Value), ParseBool(attrs?["loop"]?.Value)) },
+ { "set_pc_emotion_sequence", (ctx, attrs) => ctx.SetPcEmotionSequence(attrs?["sequence_names"]?.Value.Split(',') ?? []) },
+ { "set_pc_rotation", (ctx, attrs) => ctx.SetPcRotation(ParseVector3(attrs?["rotation"]?.Value)) },
+ { "set_photo_studio", (ctx, attrs) => ctx.SetPhotoStudio(ParseBool(attrs?["is_enable"]?.Value)) },
+ { "set_portal", (ctx, attrs) => ctx.SetPortal(ParseInt(attrs?["portal_id"]?.Value), ParseBool(attrs?["visible"]?.Value), ParseBool(attrs?["enable"]?.Value), ParseBool(attrs?["minimap_visible"]?.Value), ParseBool(attrs?["arg5"]?.Value)) },
+ { "set_pvp_zone", (ctx, attrs) => ctx.SetPvpZone(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["prepare_time"]?.Value), ParseInt(attrs?["match_time"]?.Value), ParseInt(attrs?["additional_effect_id"]?.Value), ParseInt(attrs?["type"]?.Value), ParseIntArray(attrs?["box_ids"]?.Value)) },
+ { "set_quest_accept", (ctx, attrs) => ctx.SetQuestAccept(ParseInt(attrs?["quest_id"]?.Value)) },
+ { "set_quest_complete", (ctx, attrs) => ctx.SetQuestComplete(ParseInt(attrs?["quest_id"]?.Value)) },
+ { "set_random_mesh", (ctx, attrs) => ctx.SetRandomMesh(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["visible"]?.Value), ParseInt(attrs?["start_delay"]?.Value), ParseInt(attrs?["interval"]?.Value), ParseInt(attrs?["fade"]?.Value)) },
+ { "set_rope", (ctx, attrs) => ctx.SetRope(ParseInt(attrs?["trigger_id"]?.Value), ParseBool(attrs?["visible"]?.Value), ParseBool(attrs?["enable"]?.Value), ParseInt(attrs?["fade"]?.Value)) },
+ { "set_scene_skip", (ctx, attrs) => ctx.SetSceneSkip(attrs?["state"]?.Value ?? string.Empty, attrs?["action"]?.Value ?? string.Empty) },
+ { "set_skill", (ctx, attrs) => ctx.SetSkill(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["enable"]?.Value)) },
+ { "set_skip", (ctx, attrs) => ctx.SetSkip(attrs?["state"]?.Value ?? string.Empty) },
+ { "set_sound", (ctx, attrs) => ctx.SetSound(ParseInt(attrs?["trigger_id"]?.Value), ParseBool(attrs?["enable"]?.Value)) },
+ { "set_state", (ctx, attrs) => ctx.SetState(ParseInt(attrs?["id"]?.Value), attrs?["states"]?.Value.Split(',') ?? [], ParseBool(attrs?["randomize"]?.Value)) },
+ { "set_time_scale", (ctx, attrs) => ctx.SetTimeScale(ParseBool(attrs?["enable"]?.Value), ParseFloat(attrs?["start_scale"]?.Value), ParseFloat(attrs?["end_scale"]?.Value), ParseFloat(attrs?["duration"]?.Value), ParseInt(attrs?["interpolator"]?.Value)) },
+ { "set_timer", (ctx, attrs) => ctx.SetTimer(attrs?["timer_id"]?.Value ?? string.Empty, ParseInt(attrs?["seconds"]?.Value), ParseBool(attrs?["auto_remove"]?.Value), ParseBool(attrs?["display"]?.Value), ParseInt(attrs?["v_offset"]?.Value), attrs?["type"]?.Value ?? string.Empty, attrs?["desc"]?.Value ?? string.Empty) },
+ { "set_user_value", (ctx, attrs) => ctx.SetUserValue(ParseInt(attrs?["trigger_id"]?.Value), attrs?["key"]?.Value ?? string.Empty, ParseInt(attrs?["value"]?.Value)) },
+ { "set_user_value_from_dungeon_reward_count", (ctx, attrs) => ctx.SetUserValueFromDungeonRewardCount(attrs?["key"]?.Value ?? string.Empty, ParseInt(attrs?["dungeon_reward_id"]?.Value)) },
+ { "set_user_value_from_guild_vs_game_score", (ctx, attrs) => ctx.SetUserValueFromGuildVsGameScore(ParseInt(attrs?["team_id"]?.Value), attrs?["key"]?.Value ?? string.Empty) },
+ { "set_user_value_from_user_count", (ctx, attrs) => ctx.SetUserValueFromUserCount(ParseInt(attrs?["trigger_box_id"]?.Value), attrs?["key"]?.Value ?? string.Empty, ParseInt(attrs?["user_tag_id"]?.Value)) },
+ { "set_visible_breakable_object", (ctx, attrs) => ctx.SetVisibleBreakableObject(ParseIntArray(attrs?["trigger_ids"]?.Value), ParseBool(attrs?["visible"]?.Value)) },
+ { "set_visible_ui", (ctx, attrs) => ctx.SetVisibleUi(attrs?["ui_names"]?.Value.Split(',') ?? [], ParseBool(attrs?["visible"]?.Value)) },
+ { "shadow_expedition_close_boss_gauge", (ctx, _) => ctx.ShadowExpeditionCloseBossGauge() },
+ { "shadow_expedition_open_boss_gauge", (ctx, attrs) => ctx.ShadowExpeditionOpenBossGauge(ParseInt(attrs?["max_gauge_point"]?.Value), attrs?["title"]?.Value ?? string.Empty) }, {
+ "show_caption", (ctx, attrs) => ctx.ShowCaption(attrs?["type"]?.Value ?? string.Empty, attrs?["title"]?.Value ?? string.Empty, attrs?["desc"]?.Value ?? string.Empty,
+ ParseAlign(attrs?["align"]?.Value), ParseFloat(attrs?["offset_rate_x"]?.Value), ParseFloat(attrs?["offset_rate_y"]?.Value), ParseInt(attrs?["duration"]?.Value), ParseFloat(attrs?["scale"]?.Value))
+ },
+ { "show_count_ui", (ctx, attrs) => ctx.ShowCountUi(attrs?["text"]?.Value ?? string.Empty, ParseInt(attrs?["stage"]?.Value), ParseInt(attrs?["count"]?.Value), ParseInt(attrs?["sound_type"]?.Value)) },
+ { "show_event_result", (ctx, attrs) => ctx.ShowEventResult(attrs?["type"]?.Value ?? string.Empty, attrs?["text"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value), ParseInt(attrs?["user_tag_id"]?.Value), ParseInt(attrs?["trigger_box_id"]?.Value), ParseBool(attrs?["is_outside"]?.Value)) },
+ { "show_guide_summary", (ctx, attrs) => ctx.ShowGuideSummary(ParseInt(attrs?["entity_id"]?.Value), ParseInt(attrs?["text_id"]?.Value), ParseInt(attrs?["duration"]?.Value)) },
+ { "show_round_ui", (ctx, attrs) => ctx.ShowRoundUi(ParseInt(attrs?["round"]?.Value), ParseInt(attrs?["duration"]?.Value), ParseBool(attrs?["is_final_round"]?.Value)) },
+ { "side_npc_cutin", (ctx, attrs) => ctx.SideNpcCutin(attrs?["illust"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value)) },
+ { "side_npc_movie", (ctx, attrs) => ctx.SideNpcMovie(attrs?["usm"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value)) },
+ { "side_npc_talk", (ctx, attrs) => ctx.SideNpcTalk(ParseInt(attrs?["npc_id"]?.Value), attrs?["illust"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value), attrs?["script"]?.Value ?? string.Empty, attrs?["voice"]?.Value ?? string.Empty) },
+ { "side_npc_talk_bottom", (ctx, attrs) => ctx.SideNpcTalkBottom(ParseInt(attrs?["npc_id"]?.Value), attrs?["illust"]?.Value ?? string.Empty, ParseInt(attrs?["duration"]?.Value), attrs?["script"]?.Value ?? string.Empty) },
+ { "sight_range", (ctx, attrs) => ctx.SightRange(ParseBool(attrs?["enable"]?.Value), ParseInt(attrs?["range"]?.Value), ParseInt(attrs?["range_z"]?.Value), ParseInt(attrs?["border"]?.Value)) },
+ { "spawn_item_range", (ctx, attrs) => ctx.SpawnItemRange(ParseIntArray(attrs?["range_ids"]?.Value), ParseInt(attrs?["random_pick_count"]?.Value)) },
+ { "spawn_monster", (ctx, attrs) => ctx.SpawnMonster(ParseIntArray(attrs?["spawn_ids"]?.Value), ParseBool(attrs?["auto_target"]?.Value), ParseInt(attrs?["delay"]?.Value)) },
+ { "spawn_npc_range", (ctx, attrs) => ctx.SpawnNpcRange(ParseIntArray(attrs?["range_ids"]?.Value), ParseBool(attrs?["is_auto_targeting"]?.Value), ParseInt(attrs?["random_pick_count"]?.Value), ParseInt(attrs?["score"]?.Value)) },
+ { "start_combine_spawn", (ctx, attrs) => ctx.StartCombineSpawn(ParseIntArray(attrs?["group_id"]?.Value), ParseBool(attrs?["is_start"]?.Value)) },
+ { "start_mini_game", (ctx, attrs) => ctx.StartMiniGame(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["round"]?.Value), attrs?["game_name"]?.Value ?? string.Empty, ParseBool(attrs?["is_show_result_ui"]?.Value)) },
+ { "start_mini_game_round", (ctx, attrs) => ctx.StartMiniGameRound(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["round"]?.Value)) },
+ { "start_tutorial", (ctx, _) => ctx.StartTutorial() },
+ { "talk_npc", (ctx, attrs) => ctx.TalkNpc(ParseInt(attrs?["spawn_id"]?.Value)) },
+ { "unset_mini_game_area_for_hack", (ctx, _) => ctx.UnsetMiniGameAreaForHack() },
+ { "use_state", (ctx, attrs) => ctx.UseState(ParseInt(attrs?["id"]?.Value), ParseBool(attrs?["randomize"]?.Value)) },
+ { "user_tag_symbol", (ctx, attrs) => ctx.UserTagSymbol(attrs?["symbol1"]?.Value ?? string.Empty, attrs?["symbol2"]?.Value ?? string.Empty) },
+ { "user_value_to_number_mesh", (ctx, attrs) => ctx.UserValueToNumberMesh(attrs?["key"]?.Value ?? string.Empty, ParseInt(attrs?["start_mesh_id"]?.Value), ParseInt(attrs?["digit_count"]?.Value)) },
+ { "visible_my_pc", (ctx, attrs) => ctx.VisibleMyPc(ParseBool(attrs?["is_visible"]?.Value)) },
+ { "weather", (ctx, attrs) => ctx.Weather(ParseWeather(attrs?["weather_type"]?.Value)) },
+ { "wedding_broken", (ctx, _) => ctx.WeddingBroken() },
+ { "wedding_move_user", (ctx, attrs) => ctx.WeddingMoveUser(attrs?["entry_type"]?.Value ?? string.Empty, ParseInt(attrs?["map_id"]?.Value), ParseIntArray(attrs?["portal_ids"]?.Value), ParseInt(attrs?["box_id"]?.Value)) },
+ { "wedding_mutual_agree", (ctx, attrs) => ctx.WeddingMutualAgree(attrs?["agree_type"]?.Value ?? string.Empty) },
+ { "wedding_mutual_cancel", (ctx, attrs) => ctx.WeddingMutualCancel(attrs?["agree_type"]?.Value ?? string.Empty) },
+ { "wedding_set_user_emotion", (ctx, attrs) => ctx.WeddingSetUserEmotion(attrs?["entry_type"]?.Value ?? string.Empty, ParseInt(attrs?["id"]?.Value)) },
+ { "wedding_set_user_look_at", (ctx, attrs) => ctx.WeddingSetUserLookAt(attrs?["entry_type"]?.Value ?? string.Empty, attrs?["look_at_entry_type"]?.Value ?? string.Empty, ParseBool(attrs?["immediate"]?.Value)) },
+ { "wedding_set_user_rotation", (ctx, attrs) => ctx.WeddingSetUserRotation(attrs?["entry_type"]?.Value ?? string.Empty, ParseVector3(attrs?["rotation"]?.Value), ParseBool(attrs?["immediate"]?.Value)) },
+ { "wedding_user_to_patrol", (ctx, attrs) => ctx.WeddingUserToPatrol(attrs?["patrol_name"]?.Value ?? string.Empty, attrs?["entry_type"]?.Value ?? string.Empty, ParseInt(attrs?["patrol_index"]?.Value)) },
+ { "wedding_vow_complete", (ctx, _) => ctx.WeddingVowComplete() },
+ { "widget_action", (ctx, attrs) => ctx.WidgetAction(attrs?["type"]?.Value ?? string.Empty, attrs?["func"]?.Value ?? string.Empty, attrs?["widget_arg"]?.Value ?? string.Empty, attrs?["desc"]?.Value ?? string.Empty, ParseInt(attrs?["widget_arg_num"]?.Value)) },
+ { "write_log", (ctx, attrs) => ctx.WriteLog(attrs?["log_name"]?.Value ?? string.Empty, attrs?["event"]?.Value ?? string.Empty, ParseInt(attrs?["trigger_id"]?.Value), attrs?["sub_event"]?.Value ?? string.Empty, ParseInt(attrs?["level"]?.Value)) },
+
+ };
+
+ public static readonly Dictionary> ConditionMap = new Dictionary> {
+ { "bonus_game_reward", (ctx, attrs) => ctx.BonusGameReward(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["type"]?.Value)) },
+ { "check_any_user_additional_effect", (ctx, attrs) => ctx.CheckAnyUserAdditionalEffect(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["additional_effect_id"]?.Value), ParseInt(attrs?["level"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "check_dungeon_lobby_user_count", (ctx, attrs) => ctx.CheckDungeonLobbyUserCount(ParseBool(attrs?["negate"]?.Value)) },
+ { "check_npc_additional_effect", (ctx, attrs) => ctx.CheckNpcAdditionalEffect(ParseInt(attrs?["spawn_id"]?.Value), ParseInt(attrs?["additional_effect_id"]?.Value), ParseInt(attrs?["level"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "npc_damage", (ctx, attrs) => ctx.NpcDamage(ParseInt(attrs?["spawn_id"]?.Value), ParseFloat(attrs?["damageRate"]?.Value), ParseOperatorType(attrs?["operator"]?.Value)) },
+ { "npc_extra_data", (ctx, attrs) => ctx.NpcExtraData(ParseInt(attrs?["spawn_point_id"]?.Value), attrs?["extra_data_key"]?.Value ?? string.Empty, ParseInt(attrs?["extra_data_value"]?.Value), ParseOperatorType(attrs?["operator"]?.Value)) },
+ { "npc_hp", (ctx, attrs) => ctx.NpcHp(ParseInt(attrs?["spawn_id"]?.Value), ParseBool(attrs?["is_relative"]?.Value), ParseInt(attrs?["value"]?.Value), ParseCompareType(attrs?["compare_type"]?.Value)) },
+ { "check_same_user_tag", (ctx, attrs) => ctx.CheckSameUserTag(ParseInt(attrs?["box_id"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "check_user", (ctx, attrs) => ctx.CheckUser(ParseBool(attrs?["negate"]?.Value)) },
+ { "user_count", (ctx, attrs) => ctx.UserCount(ParseInt(attrs?["check_count"]?.Value)) },
+ { "count_users", (ctx, attrs) => ctx.CountUsers(ParseInt(attrs?["box_id"]?.Value), ParseInt(attrs?["user_tag_id"]?.Value), ParseInt(attrs?["min_users"]?.Value), ParseOperatorType(attrs?["operator"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "day_of_week", (ctx, attrs) => ctx.DayOfWeek(ParseIntArray(attrs?["day_of_weeks"]?.Value), attrs?["desc"]?.Value ?? string.Empty, ParseBool(attrs?["negate"]?.Value)) },
+ { "detect_liftable_object", (ctx, attrs) => ctx.DetectLiftableObject(ParseIntArray(attrs?["box_ids"]?.Value), ParseInt(attrs?["item_id"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "dungeon_play_time", (ctx, attrs) => ctx.DungeonPlayTime(ParseInt(attrs?["play_seconds"]?.Value)) },
+ { "dungeon_state", (ctx, attrs) => ctx.DungeonState(attrs?["check_state"]?.Value ?? string.Empty) },
+ { "dungeon_first_user_mission_score", (ctx, attrs) => ctx.DungeonFirstUserMissionScore(ParseInt(attrs?["score"]?.Value), ParseOperatorType(attrs?["operator"]?.Value)) },
+ { "dungeon_id", (ctx, attrs) => ctx.DungeonId(ParseInt(attrs?["dungeon_id"]?.Value)) },
+ { "dungeon_level", (ctx, attrs) => ctx.DungeonLevel(ParseInt(attrs?["level"]?.Value)) },
+ { "dungeon_max_user_count", (ctx, attrs) => ctx.DungeonMaxUserCount(ParseInt(attrs?["level"]?.Value)) },
+ { "dungeon_round", (ctx, attrs) => ctx.DungeonRound(ParseInt(attrs?["round"]?.Value)) },
+ { "dungeon_timeout", (ctx, _) => ctx.DungeonTimeout() },
+ { "dungeon_variable", (ctx, attrs) => ctx.DungeonVariable(ParseInt(attrs?["var_id"]?.Value), ParseInt(attrs?["value"]?.Value)) },
+ { "guild_vs_game_scored_team", (ctx, attrs) => ctx.GuildVsGameScoredTeam(ParseInt(attrs?["team_id"]?.Value)) },
+ { "guild_vs_game_winner_team", (ctx, attrs) => ctx.GuildVsGameWinnerTeam(ParseInt(attrs?["team_id"]?.Value)) },
+ { "is_dungeon_room", (ctx, attrs) => ctx.IsDungeonRoom(ParseBool(attrs?["negate"]?.Value)) },
+ { "is_playing_maple_survival", (ctx, attrs) => ctx.IsPlayingMapleSurvival(ParseBool(attrs?["negate"]?.Value)) },
+ { "monster_dead", (ctx, attrs) => ctx.MonsterDead(ParseIntArray(attrs?["spawn_ids"]?.Value), ParseBool(attrs?["auto_target"]?.Value)) },
+ { "monster_in_combat", (ctx, attrs) => ctx.MonsterInCombat(ParseIntArray(attrs?["spawn_ids"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "npc_detected", (ctx, attrs) => ctx.NpcDetected(ParseInt(attrs?["box_id"]?.Value), ParseIntArray(attrs?["spawn_ids"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "npc_is_dead_by_string_id", (ctx, attrs) => ctx.NpcIsDeadByStringId(attrs?["string_id"]?.Value ?? string.Empty) },
+ { "object_interacted", (ctx, attrs) => ctx.ObjectInteracted(ParseIntArray(attrs?["interact_ids"]?.Value), ParseInt(attrs?["state"]?.Value)) },
+ { "pvp_zone_ended", (ctx, attrs) => ctx.PvpZoneEnded(ParseInt(attrs?["box_id"]?.Value)) },
+ { "quest_user_detected", (ctx, attrs) => ctx.QuestUserDetected(ParseIntArray(attrs?["box_ids"]?.Value), ParseIntArray(attrs?["quest_ids"]?.Value), ParseIntArray(attrs?["quest_states"]?.Value), ParseInt(attrs?["job_code"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "random_condition", (ctx, attrs) => ctx.RandomCondition(ParseFloat(attrs?["weight"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ { "score_board_score", (ctx, attrs) => ctx.ScoreBoardScore(ParseInt(attrs?["score"]?.Value), ParseOperatorType(attrs?["compare_op"]?.Value)) },
+ { "shadow_expedition_points", (ctx, attrs) => ctx.ShadowExpeditionPoints(ParseInt(attrs?["score"]?.Value)) },
+ { "time_expired", (ctx, attrs) => ctx.TimeExpired(attrs?["timer_id"]?.Value ?? string.Empty) },
+ { "user_detected", (ctx, attrs) => ctx.UserDetected(ParseIntArray(attrs?["box_ids"]?.Value), ParseInt(attrs?["job_code"]?.Value)) },
+ { "user_value", (ctx, attrs) => ctx.UserValue(attrs?["key"]?.Value ?? string.Empty, ParseInt(attrs?["value"]?.Value), ParseBool(attrs?["negate"]?.Value)) },
+ { "wait_and_reset_tick", (ctx, attrs) => ctx.WaitAndResetTick(ParseInt(attrs?["wait_tick"]?.Value)) },
+ { "wait_seconds_user_value", (ctx, attrs) => ctx.WaitSecondsUserValue(attrs?["key"]?.Value ?? string.Empty, attrs?["desc"]?.Value ?? string.Empty) },
+ { "wait_tick", (ctx, attrs) => ctx.WaitTick(ParseInt(attrs?["wait_tick"]?.Value)) },
+ { "wedding_entry_in_field", (ctx, attrs) => ctx.WeddingEntryInField(attrs?["entry_type"]?.Value ?? string.Empty, ParseBool(attrs?["is_in_field"]?.Value)) },
+ { "wedding_hall_state", (ctx, attrs) => ctx.WeddingHallState(attrs?["hallState"]?.Value ?? string.Empty, ParseBool(attrs?["success"]?.Value)) },
+ { "wedding_mutual_agree_result", (ctx, attrs) => ctx.WeddingMutualAgreeResult(attrs?["agree_type"]?.Value ?? string.Empty) },
+ { "widget_value", (ctx, attrs) => ctx.WidgetValue(attrs?["type"]?.Value ?? string.Empty, attrs?["widget_name"]?.Value ?? string.Empty, ParseInt(attrs?["condition"]?.Value), ParseBool(attrs?["negate"]?.Value), attrs?["desc"]?.Value ?? string.Empty) },
+ };
+
+ private static Weather ParseWeather(string? value) {
+ if (string.IsNullOrEmpty(value)) return Weather.Clear;
+ return (Weather) Enum.Parse(typeof(Weather), value, true);
+ }
+
+ private static BannerType ParseBannerType(string? value) {
+ if (string.IsNullOrEmpty(value)) return BannerType.Lose;
+ return (BannerType) Enum.Parse(typeof(BannerType), value, true);
+ }
+
+ private static Locale ParseLocale(string? value) {
+ if (string.IsNullOrEmpty(value)) return Locale.ALL;
+ return (Locale) Enum.Parse(typeof(Locale), value, true);
+ }
+
+ private static FieldGame ParseFieldGame(string? value) {
+ if (string.IsNullOrEmpty(value)) return FieldGame.Unknown;
+ return (FieldGame) Enum.Parse(typeof(FieldGame), value, true);
+ }
+
+ private static Align ParseAlign(string? align) {
+ if (string.IsNullOrEmpty(align)) return Align.center;
+ return (Align) Enum.Parse(typeof(Align), align, true);
+ }
+
+ private static OperatorType ParseOperatorType(string? operatorType) {
+ if (string.IsNullOrEmpty(operatorType)) return OperatorType.GreaterEqual;
+ return (OperatorType) Enum.Parse(typeof(OperatorType), operatorType, true);
+ }
+
+ private static CompareType ParseCompareType(string? compareType) {
+ if (string.IsNullOrEmpty(compareType)) return CompareType.higher;
+ return (CompareType) Enum.Parse(typeof(CompareType), compareType, true);
+ }
+
+ public static int[] ParseIntArray(string? value) {
+ if (string.IsNullOrEmpty(value)) return [];
+ if (value is "all") return [-1]; // Special case for "all" to indicate all IDs.
+ // Handles ranges and comma-separated values and mixed usage.
+ if (value.Contains(',')) {
+ var result = new List();
+ foreach (string part in value.Split(',')) {
+ if (part.Contains('-')) {
+ string[] rangeParts = part.Split('-');
+ if (rangeParts.Length == 2 && int.TryParse(rangeParts[0], out int start) && int.TryParse(rangeParts[1], out int end)) {
+ result.AddRange(Enumerable.Range(start, end - start + 1));
+ }
+ } else if (int.TryParse(part, out int singleValue)) {
+ result.Add(singleValue);
+ }
+ }
+ return result.ToArray();
+ }
+ if (value.Contains('-')) {
+ string[] parts = value.Split('-');
+ if (parts.Length == 2 && int.TryParse(parts[0], out int start) && int.TryParse(parts[1], out int end)) {
+ return Enumerable.Range(start, end - start + 1).ToArray();
+ }
+ }
+ return value.Split(',').Select(int.Parse).ToArray();
+ }
+
+ public static int ParseInt(string? value) => int.TryParse(value, out int v) ? v : 0;
+
+ public static float ParseFloat(string? value) => float.TryParse(value, out float v) ? v : 0f;
+
+ public static bool ParseBool(string? value) {
+ if (string.IsNullOrEmpty(value)) return false;
+ return value == "1" || value.Equals("true", StringComparison.CurrentCultureIgnoreCase);
+ }
+
+ public static Vector3 ParseVector3(string? value) {
+ if (string.IsNullOrEmpty(value)) return Vector3.Zero;
+
+ string[] parts = value.Split(',');
+ if (parts.Length != 3 || !float.TryParse(parts[0], out float x) || !float.TryParse(parts[1], out float y) || !float.TryParse(parts[2], out float z)) {
+ return Vector3.Zero;
+ }
+
+ return new Vector3(x, y, z);
+ }
+}
diff --git a/Maple2.Server.Game/Trigger/Helpers/TriggerState.cs b/Maple2.Server.Game/Trigger/Helpers/TriggerState.cs
new file mode 100644
index 000000000..ecc4cbed2
--- /dev/null
+++ b/Maple2.Server.Game/Trigger/Helpers/TriggerState.cs
@@ -0,0 +1,143 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Xml;
+using Serilog;
+
+namespace Maple2.Server.Game.Trigger.Helpers;
+
+public class TriggerState {
+ private readonly XmlNode stateNode;
+ private readonly TriggerContext triggerContext;
+
+ public readonly string Name;
+
+ public TriggerState(XmlNode state, TriggerContext context) {
+ stateNode = state;
+ triggerContext = context;
+ Name = stateNode.Attributes?["name"]?.Value ?? throw new ArgumentException("State node must have a 'name' attribute");
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public TriggerState? OnEnter() {
+ XmlNode? section = stateNode.SelectSingleNode("onEnter");
+ if (section == null) return null;
+
+ foreach (XmlNode actionNode in section.SelectNodes("action")!) {
+ CallAction(actionNode);
+ }
+
+ if (!GetNextState(section, out XmlNode? nextState)) return null;
+
+ return new TriggerState(nextState, triggerContext);
+ }
+
+ public TriggerState? OnTick() {
+ XmlNodeList? section = stateNode.SelectNodes("condition");
+ if (section == null) return null;
+
+ foreach (XmlNode conditionNode in section) {
+ if (!CallCondition(conditionNode)) continue;
+
+ foreach (XmlNode actionNode in conditionNode.SelectNodes("action")!) {
+ CallAction(actionNode);
+ }
+
+ if (!GetNextState(conditionNode, out XmlNode? nextState)) continue;
+
+ return new TriggerState(nextState, triggerContext);
+ }
+ return null;
+ }
+
+ public void OnExit() {
+ XmlNode? section = stateNode.SelectSingleNode("onExit");
+ if (section == null) return;
+ foreach (XmlNode actionNode in section.SelectNodes("action")!) {
+ CallAction(actionNode);
+ }
+ }
+
+ private bool GetNextState(XmlNode condition, [NotNullWhen(true)] out XmlNode? xmlNode) {
+ XmlNode? nextStateNode = condition.SelectSingleNode("transition");
+ if (nextStateNode == null) {
+ xmlNode = null;
+ return false;
+ }
+
+ string nextStateName = nextStateNode.Attributes?["state"]?.Value ?? "";
+ if (string.IsNullOrEmpty(nextStateName)) {
+ xmlNode = null;
+ return false;
+ }
+
+ XmlNode? nextNode = triggerContext.Owner.GetStateNode(nextStateName);
+ if (nextNode == null) {
+ xmlNode = null;
+ return false;
+ }
+ xmlNode = nextNode;
+ return true;
+ }
+
+ private void CallAction(XmlNode actionNode) {
+ string actionName = actionNode.Attributes?["name"]?.Value ?? "";
+ TriggerFunctionMapping.ActionMap.TryGetValue(actionName, out Action? actionFunc);
+ if (actionFunc is not null) {
+ try {
+ actionFunc(triggerContext, actionNode.Attributes);
+ } catch (Exception e) {
+ Log.Logger.Error(e, "CallAction: error executing action '{ActionName}', Node: {Node}", actionName, actionNode.OuterXml);
+ }
+ return;
+ }
+ Log.Logger.Error("CallAction: action function not found for action '{ActionName}'", actionName);
+ }
+
+ private bool CallCondition(XmlNode conditionNode) {
+ string conditionName = conditionNode.Attributes?["name"]?.Value ?? "";
+
+ // Handle group conditions
+ if (conditionName is "any_one" or "all_of" or "true" or "always") {
+ XmlNode? groupNode = conditionNode.SelectSingleNode("group");
+ if (groupNode == null) {
+ Log.Logger.Error("CallCondition: group node not found for grouped condition '{ActionName}'", conditionName);
+ return false;
+ }
+ XmlNodeList? childConditions = groupNode.SelectNodes("condition");
+ if (childConditions == null || childConditions.Count == 0) {
+ Log.Logger.Error("CallCondition: no child conditions in group for '{ActionName}'", conditionName);
+ return false;
+ }
+
+ switch (conditionName) {
+ case "any_one":
+ foreach (XmlNode child in childConditions) {
+ if (CallCondition(child)) return true;
+ }
+ return false;
+ case "all_of":
+ foreach (XmlNode child in childConditions) {
+ if (!CallCondition(child)) return false;
+ }
+ return true;
+ case "true":
+ case "always":
+ return true;
+ }
+ }
+
+ TriggerFunctionMapping.ConditionMap.TryGetValue(conditionName, out Func? conditionFunc);
+ if (conditionFunc is not null) {
+ try {
+ bool result = conditionFunc(triggerContext, conditionNode.Attributes);
+ return result;
+ } catch (Exception e) {
+ Log.Logger.Error(e, "CallCondition: error executing condition '{ConditionName}', Node: {Node}", conditionName, conditionNode.OuterXml);
+ return false;
+ }
+ }
+
+ Log.Logger.Error("CallCondition: condition function not found for action '{ConditionName}'", conditionName);
+ return false;
+ }
+}
diff --git a/Maple2.Server.Game/Trigger/TriggerContext.Cinematic.cs b/Maple2.Server.Game/Trigger/TriggerContext.Cinematic.cs
index c86aca390..14dea1d00 100644
--- a/Maple2.Server.Game/Trigger/TriggerContext.Cinematic.cs
+++ b/Maple2.Server.Game/Trigger/TriggerContext.Cinematic.cs
@@ -1,6 +1,6 @@
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
namespace Maple2.Server.Game.Trigger;
@@ -69,15 +69,15 @@ public void SetCinematicUi(int type, string script, bool arg3) {
}
}
- public void SetSceneSkip(dynamic state, string nextState) {
- WarnLog("[SetSceneSkip] state:{State}, nextState:{NextState}", nameof(state), nextState);
- skipState = state;
+ public void SetSceneSkip(string state, string nextState) {
+ WarnLog("[SetSceneSkip] state:{State}, nextState:{NextState}", state, nextState);
+ skipState = Owner.GetState(state);
Broadcast(CinematicPacket.SetSkipScene(nextState));
}
- public void SetSkip(dynamic state) {
+ public void SetSkip(string state) {
WarnLog("[SetSkip] state:{State}", nameof(state));
- skipState = state;
+ skipState = Owner.GetState(state);
Broadcast(CinematicPacket.SetSkipState(""));
}
diff --git a/Maple2.Server.Game/Trigger/TriggerContext.Dungeon.cs b/Maple2.Server.Game/Trigger/TriggerContext.Dungeon.cs
index 91a5ee832..cad34e7cb 100644
--- a/Maple2.Server.Game/Trigger/TriggerContext.Dungeon.cs
+++ b/Maple2.Server.Game/Trigger/TriggerContext.Dungeon.cs
@@ -140,12 +140,15 @@ public void ShadowExpeditionCloseBossGauge() {
#endregion
#region Conditions
- public bool CheckDungeonLobbyUserCount() {
+ public bool CheckDungeonLobbyUserCount(bool negate) {
DebugLog("[CheckDungeonLobbyUserCount]");
if (Field is not DungeonFieldManager dungeonField) {
- return false;
+ return negate;
}
+ if (negate) {
+ return Field.Players.Values.Count < dungeonField.Size;
+ }
return Field.Players.Values.Count >= dungeonField.Size;
}
@@ -154,12 +157,15 @@ public bool DungeonTimeout() {
return false;
}
- public bool IsDungeonRoom() {
+ public bool IsDungeonRoom(bool negate) {
DebugLog("[IsDungeonRoom]");
+ if (negate) {
+ return Field is not DungeonFieldManager;
+ }
return Field is DungeonFieldManager;
}
- public bool IsPlayingMapleSurvival() {
+ public bool IsPlayingMapleSurvival(bool negate) {
ErrorLog("[IsPlayingMapleSurvival]");
return false;
}
diff --git a/Maple2.Server.Game/Trigger/TriggerContext.Field.cs b/Maple2.Server.Game/Trigger/TriggerContext.Field.cs
index 9e430d7f5..70f9d7d28 100644
--- a/Maple2.Server.Game/Trigger/TriggerContext.Field.cs
+++ b/Maple2.Server.Game/Trigger/TriggerContext.Field.cs
@@ -5,7 +5,7 @@
using Maple2.Model.Metadata;
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
using Maple2.Tools.Extensions;
namespace Maple2.Server.Game.Trigger;
@@ -504,11 +504,11 @@ public void FieldWarEnd(bool isClear) {
#endregion
#region Conditions
- public bool DetectLiftableObject(int[] boxIds, int itemId) {
+ public bool DetectLiftableObject(int[] boxIds, int itemId, bool negate) {
DebugLog("[DetectLiftableObject] boxIds:{Ids}, itemId:{ItemId}", string.Join(", ", boxIds), itemId);
if (itemId == 0) {
- return false;
+ return negate;
}
IEnumerable boxes = boxIds
@@ -519,23 +519,23 @@ public bool DetectLiftableObject(int[] boxIds, int itemId) {
var liftables = Field.EnumerateLiftables().Where(x => x.Value.ItemId == itemId && (x.State == LiftableState.Default || x.State == LiftableState.Disabled));
foreach (FieldLiftable liftable in liftables) {
if (boxes.Any(box => box.Contains(liftable.Position))) {
- return true;
+ return !negate;
}
}
- return false;
+ return negate;
}
public bool ObjectInteracted(int[] interactIds, int stateValue) {
var state = (InteractState) stateValue;
DebugLog("[ObjectInteracted] interactIds:{Ids}, state:{State}", string.Join(", ", interactIds), state);
foreach (FieldInteract interact in Field.EnumerateInteract()) {
- if (interactIds.Contains(interact.Value.Id) && interact.State != state) {
- return false;
+ if (interactIds.Contains(interact.Value.Id) && interact.State == state) {
+ return true;
}
}
- return true;
+ return false;
}
public bool PvpZoneEnded(int boxId) {
diff --git a/Maple2.Server.Game/Trigger/TriggerContext.Interface.cs b/Maple2.Server.Game/Trigger/TriggerContext.Interface.cs
index 45c5e43af..f70fdedf2 100644
--- a/Maple2.Server.Game/Trigger/TriggerContext.Interface.cs
+++ b/Maple2.Server.Game/Trigger/TriggerContext.Interface.cs
@@ -5,7 +5,7 @@
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Model.Widget;
using Maple2.Server.Game.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
+using Maple2.Server.Game.Trigger.Helpers;
using Maple2.Tools.Extensions;
namespace Maple2.Server.Game.Trigger;
@@ -194,13 +194,18 @@ public void WidgetAction(string type, string func, string widgetArg, string desc
}
#region Conditions
- public int WidgetValue(string type, string name, string desc) {
- DebugLog("[WidgetValue] type:{Type}, name:{Name}, desc:{Desc}", type, name, desc);
+ public bool WidgetValue(string type, string widgetName, int condition, bool negate, string desc = "") {
+ DebugLog("[WidgetValue] type:{Type}, widgetName:{Name}, desc:{Desc}", type, widgetName, desc);
if (!Field.Widgets.TryGetValue(type, out Widget? widget)) {
- return 0;
+ return negate;
}
- return widget.Conditions.GetValueOrDefault(name);
+
+ bool result = widget.Conditions.GetValueOrDefault(widgetName) == condition;
+ if (negate) {
+ return !result;
+ }
+ return result;
}
#endregion
}
diff --git a/Maple2.Server.Game/Trigger/TriggerContext.MiniGame.cs b/Maple2.Server.Game/Trigger/TriggerContext.MiniGame.cs
index 16533fd2b..7328ee3a9 100644
--- a/Maple2.Server.Game/Trigger/TriggerContext.MiniGame.cs
+++ b/Maple2.Server.Game/Trigger/TriggerContext.MiniGame.cs
@@ -5,8 +5,8 @@
using Maple2.Model.Metadata;
using Maple2.Server.Game.Model;
using Maple2.Server.Game.Packets;
-using Maple2.Server.Game.Scripting.Trigger;
-using Locale = Maple2.Server.Game.Scripting.Trigger.Locale;
+using Maple2.Server.Game.Trigger.Helpers;
+using Locale = Maple2.Server.Game.Trigger.Helpers.Locale;
namespace Maple2.Server.Game.Trigger;
@@ -144,7 +144,7 @@ public void StartMiniGameRound(int boxId, int round) {
public void UnsetMiniGameAreaForHack() { }
public void UseState(int id, bool randomize) {
- if (!Field.States.TryGetValue(id, out List