diff --git a/src/TSMapEditor/Config/Default/UI/Windows/CreateRandomTriggerSetWindow.ini b/src/TSMapEditor/Config/Default/UI/Windows/CreateRandomTriggerSetWindow.ini new file mode 100644 index 000000000..fd6efdbd1 --- /dev/null +++ b/src/TSMapEditor/Config/Default/UI/Windows/CreateRandomTriggerSetWindow.ini @@ -0,0 +1,98 @@ +[CreateRandomTriggerSetWindow] +$Height=300 +$Width=300 + +$CC00=lblHeader:XNALabel +$CC01=lblSubHeader:XNALabel +$CC02=lblName:XNALabel +$CC03=tbName:EditorTextBox +$CC04=lblColor:XNALabel +$CC05=ddColor:XNADropDown +$CC06=lblNumTriggers:XNALabel +$CC07=tbNumTriggers:EditorNumberTextBox +$CC08=lblElapsedTime:XNALabel +$CC09=tbElapsedTime:EditorNumberTextBox +$CC10=lblDelay:XNALabel +$CC11=tbDelay:EditorNumberTextBox +$CC12=cbEveryDiff:XNACheckBox +$CC13=btnApply:EditorButton +HasCloseButton=true + +[lblHeader] +$X=EMPTY_SPACE_SIDES +$Y=EMPTY_SPACE_TOP +FontIndex=1 +Text=Create Random Trigger Set + +[lblSubHeader] +$X=EMPTY_SPACE_SIDES +$Y=getBottom(lblHeader) + VERTICAL_SPACING +Text=Create a set of triggers of which only one is@randomly activated in-game. This allows you to @quickly add variance to in-game events. + +[lblName] +$X=EMPTY_SPACE_SIDES +$Y=getBottom(lblSubHeader) + (VERTICAL_SPACING * 3) +Text=Trigger name: + +[tbName] +$X=150 +$Y=getY(lblName) + 1 +$Width=getWidth(CreateRandomTriggerSetWindow) - getX(tbName) - EMPTY_SPACE_SIDES +AllowComma=no + +[lblColor] +$X=getX(lblName) +$Y=getBottom(lblName) + (VERTICAL_SPACING * 2) +Text=Color: + +[ddColor] +$X=getX(tbName) +$Y=getY(lblColor) + 1 +$Width=getWidth(tbName) + +[lblNumTriggers] +$X=getX(lblName) +$Y=getBottom(lblColor) + (VERTICAL_SPACING * 2) +Text=No. of triggers to create: + +[tbNumTriggers] +$X=getX(tbName) +$Y=getY(lblNumTriggers) + 1 +$Width=getWidth(tbName) +AllowComma=no +AllowDecimals=no + +[lblElapsedTime] +$X=getX(lblNumTriggers) +$Y=getBottom(lblNumTriggers) + (VERTICAL_SPACING * 2) +Text=Elapsed Time: + +[tbElapsedTime] +$X=getX(tbNumTriggers) +$Y=getY(lblElapsedTime) + 1 +$Width=getWidth(tbNumTriggers) +AllowComma=no +AllowDecimals=no + +[lblDelay] +$X=getX(lblNumTriggers) +$Y=getBottom(lblElapsedTime) + (VERTICAL_SPACING * 2) +Text=Random Delay (min. 10): + +[tbDelay] +$X=getX(tbNumTriggers) +$Y=getY(lblDelay) +$Width=getWidth(tbNumTriggers) +AllowComma=no +AllowDecimals=no + +[cbEveryDiff] +$X=getX(lblDelay) +$Y=getBottom(lblDelay) + (VERTICAL_SPACING * 3) +Text=Create triggers for all difficulties + +[btnApply] +$Width=80 +$X=horizontalCenterOnParent() +$Y=getHeight(CreateRandomTriggerSetWindow) - getHeight(btnApply) - EMPTY_SPACE_BOTTOM +Text=Apply \ No newline at end of file diff --git a/src/TSMapEditor/TSMapEditor.csproj b/src/TSMapEditor/TSMapEditor.csproj index d8e3f69cf..e413541a7 100644 --- a/src/TSMapEditor/TSMapEditor.csproj +++ b/src/TSMapEditor/TSMapEditor.csproj @@ -1,4 +1,4 @@ - + net8.0-windows WinExe @@ -323,6 +323,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/src/TSMapEditor/UI/Windows/CreateRandomTriggerSetWindow.cs b/src/TSMapEditor/UI/Windows/CreateRandomTriggerSetWindow.cs new file mode 100644 index 000000000..0b148a6a9 --- /dev/null +++ b/src/TSMapEditor/UI/Windows/CreateRandomTriggerSetWindow.cs @@ -0,0 +1,259 @@ +using Rampastring.Tools; +using Rampastring.XNAUI; +using Rampastring.XNAUI.XNAControls; +using System; +using System.Collections.Generic; +using TSMapEditor.Models; +using TSMapEditor.UI.Controls; + +namespace TSMapEditor.UI.Windows +{ + public class RandomTriggerSetTriggersCreatedEventArgs : EventArgs + { + public RandomTriggerSetTriggersCreatedEventArgs(Trigger baseTrigger) + { + BaseTrigger = baseTrigger; + } + + public Trigger BaseTrigger { get; } + } + + public class CreateRandomTriggerSetWindow : INItializableWindow + { + public CreateRandomTriggerSetWindow(WindowManager windowManager, Map map) : base(windowManager) + { + this.map = map; + } + + private readonly Map map; + + private EditorTextBox tbName; + private XNADropDown ddColor; + private EditorNumberTextBox tbNumTriggers; + private EditorNumberTextBox tbElapsedTime; + private EditorNumberTextBox tbDelay; + private XNACheckBox cbEveryDiff; + private EditorButton btnApply; + + public event EventHandler RandomTriggerSetTriggersCreated; + + public override void Initialize() + { + Name = nameof(CreateRandomTriggerSetWindow); + base.Initialize(); + + tbName = FindChild(nameof(tbName)); + ddColor = FindChild(nameof(ddColor)); + tbNumTriggers = FindChild(nameof(tbNumTriggers)); + tbElapsedTime = FindChild(nameof(tbElapsedTime)); + tbDelay = FindChild(nameof(tbDelay)); + cbEveryDiff = FindChild(nameof(cbEveryDiff)); + btnApply = FindChild(nameof(btnApply)); + + ddColor.AddItem("None"); + Array.ForEach(Trigger.SupportedColors, sc => + { + ddColor.AddItem(sc.Name, sc.Value); + }); + + btnApply.LeftClick += BtnApply_LeftClick; + } + + public void BtnApply_LeftClick(object sender, EventArgs e) + { + if (!Validate()) + { + return; + } + + string name = tbName.Text; + string color = ddColor.SelectedItem.Text == "None" ? string.Empty : ddColor.SelectedItem.Text; + int elapsedTime = tbElapsedTime.Value; + int count = tbNumTriggers.Value; + int delay = tbDelay.Value; + bool createForEveryDifficulty = cbEveryDiff.Checked; + + List baseTriggers = []; + + if (createForEveryDifficulty) + { + baseTriggers.Add(CreateRandomTriggersSet(name, elapsedTime, count, delay, color, Difficulty.Hard)); + baseTriggers.Add(CreateRandomTriggersSet(name, elapsedTime, count, delay, color, Difficulty.Medium)); + baseTriggers.Add(CreateRandomTriggersSet(name, elapsedTime, count, delay, color, Difficulty.Easy)); + } + else + { + baseTriggers.Add(CreateRandomTriggersSet(name, elapsedTime, count, delay, color)); + } + + Hide(); + RandomTriggerSetTriggersCreated?.Invoke(this, new RandomTriggerSetTriggersCreatedEventArgs(baseTriggers[0])); + } + + private Trigger CreateRandomTriggersSet(string name, int elapsedTime, int count, int delay, string color, Difficulty? difficulty = null) + { + if (difficulty != null) + { + name = $"{difficulty.ToString()[0]} {name}"; + } + + var baseTrigger = CreateBaseTrigger(name, elapsedTime, color, difficulty); + var childTriggers = CreateChildTriggers(name, count, delay, color); + AssociateTriggers(baseTrigger, childTriggers); + + return baseTrigger; + } + + private bool Validate() + { + if (string.IsNullOrWhiteSpace(tbName.Text)) + { + EditorMessageBox.Show(WindowManager, "Missing Trigger Name", + "Please enter a name for the triggers", MessageBoxButtons.OK); + return false; + } + + if (tbNumTriggers.Value < 2) + { + EditorMessageBox.Show(WindowManager, "Invalid Number of Triggers", + "Please enter a value of 2 or more", MessageBoxButtons.OK); + return false; + } + + if (tbElapsedTime.Value < 0) + { + EditorMessageBox.Show(WindowManager, "Invalid Elapsed Time", + "Please enter a value of 0 or more", MessageBoxButtons.OK); + return false; + } + + if (tbDelay.Value < 10) + { + EditorMessageBox.Show(WindowManager, "Invalid Random Delay", + "Please enter a value of 10 or more", MessageBoxButtons.OK); + return false; + } + + return true; + } + + private Trigger CreateBaseTrigger(string name, int elapsedTime, string color, Difficulty? difficulty) + { + string triggerName = $"{name} base"; + + var baseTrigger = new Trigger(map.GetNewUniqueInternalId()); + baseTrigger.Name = triggerName; + baseTrigger.HouseType = "Neutral"; + + if (!string.IsNullOrWhiteSpace(color)) + { + baseTrigger.EditorColor = color; + } + + if (difficulty != null) + { + baseTrigger.Hard = difficulty == Difficulty.Hard; + baseTrigger.Normal = difficulty == Difficulty.Medium; + baseTrigger.Easy = difficulty == Difficulty.Easy; + + int diffGlobalVariableIndex = map.Rules.GlobalVariables.FindIndex(gv => gv.Name == $"Difficulty {difficulty}"); + + if (diffGlobalVariableIndex < 0) + { + Logger.Log($"{nameof(CreateRandomTriggerSetWindow)}.{nameof(CreateBaseTrigger)}: {difficulty} difficulty global variable not found!"); + } + else + { + var globalSetCondition = new TriggerCondition(); + globalSetCondition.ConditionIndex = 27; // Global Is Set + globalSetCondition.Parameters[1] = diffGlobalVariableIndex.ToString(); + + baseTrigger.Conditions.Add(globalSetCondition); + } + } + + var elapsedTimeCondition = new TriggerCondition(); + elapsedTimeCondition.ConditionIndex = 13; // Elapsed Time + elapsedTimeCondition.Parameters[1] = elapsedTime.ToString(); + + baseTrigger.Conditions.Add(elapsedTimeCondition); + + map.Triggers.Add(baseTrigger); + map.Tags.Add(new Tag() { ID = map.GetNewUniqueInternalId(), Name = baseTrigger.Name + " (tag)", Trigger = baseTrigger, Repeating = 2 }); + + return baseTrigger; + } + + private List CreateChildTriggers(string name, int count, int delay, string color) + { + List triggers = []; + + for (int i = 0; i < count; i++) + { + var childTrigger = new Trigger(map.GetNewUniqueInternalId()); + childTrigger.Name = $"{name} {i + 1}"; + childTrigger.HouseType = "Neutral"; + childTrigger.Disabled = true; + + if (!string.IsNullOrWhiteSpace(color)) + { + childTrigger.EditorColor = color; + } + + var randomDelayCondition = new TriggerCondition(); + randomDelayCondition.ConditionIndex = 51; // Random Delay + randomDelayCondition.Parameters[1] = delay.ToString(); + + childTrigger.Conditions.Add(randomDelayCondition); + + map.Triggers.Add(childTrigger); + map.Tags.Add(new Tag() { ID = map.GetNewUniqueInternalId(), Name = childTrigger.Name + " (tag)", Trigger = childTrigger, Repeating = 2 }); + + triggers.Add(childTrigger); + } + + return triggers; + } + + private void AssociateTriggers(Trigger baseTrigger, List childTriggers) + { + foreach (var childTrigger in childTriggers) + { + // base trigger needs to enable each of the child triggers + var enableTriggerAction = new TriggerAction(); + enableTriggerAction.ActionIndex = 53; // Enable Trigger + enableTriggerAction.Parameters[0] = "2"; + enableTriggerAction.Parameters[1] = childTrigger.ID; + + baseTrigger.Actions.Add(enableTriggerAction); + + // each child trigger needs to disable itself and each other child trigger + foreach (var siblingTrigger in childTriggers) + { + var disableTriggerAction = new TriggerAction(); + disableTriggerAction.ActionIndex = 54; // Disable Trigger + disableTriggerAction.Parameters[0] = "2"; + disableTriggerAction.Parameters[1] = siblingTrigger.ID; + + childTrigger.Actions.Add(disableTriggerAction); + } + } + } + + public void Open() + { + Show(); + ResetValues(); + } + + public void ResetValues() + { + tbName.Text = string.Empty; + ddColor.SelectedIndex = 0; + tbNumTriggers.Value = 3; + tbElapsedTime.Value = 100; + tbDelay.Value = 10; + cbEveryDiff.Checked = false; + } + } +} diff --git a/src/TSMapEditor/UI/Windows/TriggersWindow.cs b/src/TSMapEditor/UI/Windows/TriggersWindow.cs index 33521df34..fe1ff7da6 100644 --- a/src/TSMapEditor/UI/Windows/TriggersWindow.cs +++ b/src/TSMapEditor/UI/Windows/TriggersWindow.cs @@ -103,6 +103,7 @@ public TriggersWindow(WindowManager windowManager, Map map, EditorState editorSt private SelectSpeechWindow selectSpeechWindow; private SelectSoundWindow selectSoundWindow; private SelectParticleSystemTypeWindow selectParticleSystemTypeWindow; + private CreateRandomTriggerSetWindow createRandomTriggerSetWindow; private XNAContextMenu actionContextMenu; private XNAContextMenu eventContextMenu; @@ -216,6 +217,7 @@ public override void Initialize() ddActions.AddItem(new XNADropDownItem() { Text = contextMenuOption.Text, Tag = contextMenuOption.SelectAction }); } ddActions.AddItem(new XNADropDownItem() { Text = "Re-generate Trigger IDs", Tag = new Action(RegenerateIDs) }); + ddActions.AddItem(new XNADropDownItem() { Text = "Create Random Trigger Set", Tag = new Action(OpenCreateRandomTriggersSetWindow) }); ddActions.SelectedIndex = 0; ddActions.SelectedIndexChanged += DdActions_SelectedIndexChanged; @@ -305,6 +307,10 @@ public override void Initialize() var particleSystemTypeDarkeningPanel = DarkeningPanel.InitializeAndAddToParentControlWithChild(WindowManager, Parent, selectParticleSystemTypeWindow); particleSystemTypeDarkeningPanel.Hidden += ParticleSystemTypeDarkeningPanel_Hidden; + createRandomTriggerSetWindow = new CreateRandomTriggerSetWindow(WindowManager, map); + var createRandomTriggersSetDarkeningPanel = DarkeningPanel.InitializeAndAddToParentControlWithChild(WindowManager, Parent, createRandomTriggerSetWindow); + createRandomTriggerSetWindow.RandomTriggerSetTriggersCreated += CreateRandomTriggerSetWindow_RandomTriggersSetCreated; + eventContextMenu = new EditorContextMenu(WindowManager); eventContextMenu.Name = nameof(eventContextMenu); eventContextMenu.Width = lbEvents.Width; @@ -344,7 +350,13 @@ public override void Initialize() lbTriggers.RightClick += (s, e) => { lbTriggers.SelectedIndex = lbTriggers.HoveredIndex; if (lbTriggers.SelectedItem != null) triggerContextMenu.Open(GetCursorPoint()); }; lbTriggers.SelectedIndexChanged += LbTriggers_SelectedIndexChanged; - WindowManager.WindowSizeChangedByUser += WindowManager_WindowSizeChangedByUser; + WindowManager.WindowSizeChangedByUser += WindowManager_WindowSizeChangedByUser; + } + + private void CreateRandomTriggerSetWindow_RandomTriggersSetCreated(object sender, RandomTriggerSetTriggersCreatedEventArgs e) + { + ListTriggers(); + SelectTrigger(e.BaseTrigger); } private void WindowManager_WindowSizeChangedByUser(object sender, EventArgs e) @@ -2324,5 +2336,11 @@ private void OpenTeamType(TeamType teamType) TeamTypeOpened?.Invoke(this, new TeamTypeEventArgs(teamType)); PutOnBackground(); } + + private void OpenCreateRandomTriggersSetWindow() + { + createRandomTriggerSetWindow.Open(); + PutOnBackground(); + } } }