Skip to content

Commit ef500da

Browse files
committed
Merge branch 'add-random-based-triggers'
2 parents 2ec516c + a8e345e commit ef500da

File tree

5 files changed

+369
-0
lines changed

5 files changed

+369
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
[AddRandomBasedTriggerWindow]
2+
$Height=260
3+
$Width=300
4+
5+
$CC00=lblHeader:XNALabel
6+
$CC01=lblSubHeader:XNALabel
7+
$CC02=lblName:XNALabel
8+
$CC03=tbName:EditorTextBox
9+
$CC04=lblNumTriggers:XNALabel
10+
$CC05=tbNumTriggers:EditorNumberTextBox
11+
$CC06=lblElapsedTime:XNALabel
12+
$CC07=tbElapsedTime:EditorNumberTextBox
13+
$CC08=lblDelay:XNALabel
14+
$CC09=tbDelay:EditorNumberTextBox
15+
$CC10=cbEveryDiff:XNACheckBox
16+
$CC11=btnApply:EditorButton
17+
HasCloseButton=true
18+
19+
[lblHeader]
20+
$X=EMPTY_SPACE_SIDES
21+
$Y=EMPTY_SPACE_TOP
22+
FontIndex=1
23+
Text=Add Random Based Triggers
24+
25+
[lblSubHeader]
26+
$X=EMPTY_SPACE_SIDES
27+
$Y=getBottom(lblHeader) + VERTICAL_SPACING
28+
Text=Create triggers that randomly activate.
29+
30+
[lblName]
31+
$X=EMPTY_SPACE_SIDES
32+
$Y=getBottom(lblSubHeader) + (VERTICAL_SPACING * 3)
33+
Text=Trigger name:
34+
35+
[tbName]
36+
$X=150
37+
$Y=getY(lblName) + 1
38+
$Width=getWidth(AddRandomBasedTriggerWindow) - getX(tbName) - EMPTY_SPACE_SIDES
39+
40+
[lblNumTriggers]
41+
$X=getX(lblName)
42+
$Y=getBottom(lblName) + (VERTICAL_SPACING * 3)
43+
Text=Triggers to create:
44+
45+
[tbNumTriggers]
46+
$X=getX(tbName)
47+
$Y=getY(lblNumTriggers) + 1
48+
$Width=getWidth(tbName)
49+
50+
[lblElapsedTime]
51+
$X=getX(lblNumTriggers)
52+
$Y=getBottom(lblNumTriggers) + (VERTICAL_SPACING * 2)
53+
Text=Elapsed Time:
54+
55+
[tbElapsedTime]
56+
$X=getX(tbNumTriggers)
57+
$Y=getBottom(tbNumTriggers) + VERTICAL_SPACING + 1
58+
$Width=getWidth(tbNumTriggers)
59+
60+
[lblDelay]
61+
$X=getX(lblNumTriggers)
62+
$Y=getBottom(lblElapsedTime) + (VERTICAL_SPACING * 2)
63+
Text=Random Delay (min. 10):
64+
65+
[tbDelay]
66+
$X=getX(tbNumTriggers)
67+
$Y=getBottom(tbElapsedTime) + VERTICAL_SPACING + 1
68+
$Width=getWidth(tbNumTriggers)
69+
70+
[cbEveryDiff]
71+
$X=getX(lblDelay)
72+
$Y=getBottom(lblDelay) + (VERTICAL_SPACING * 3)
73+
Text=Create triggers for all difficulties
74+
75+
[btnApply]
76+
$Width=80
77+
$X=(getWidth(AddRandomBasedTriggerWindow) - getWidth(btnApply)) / 2
78+
$Y=getHeight(AddRandomBasedTriggerWindow) - getHeight(btnApply) - EMPTY_SPACE_BOTTOM
79+
Text=Apply

src/TSMapEditor/TSMapEditor.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@
342342
<None Update="Config\Default\UI\Windows\VehicleOptionsWindow.ini">
343343
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
344344
</None>
345+
<None Update="Config\Default\UI\Windows\AddRandomBasedTriggerWindow.ini">
346+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
347+
</None>
345348
<None Update="Content\celltag.png">
346349
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
347350
</None>
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
using Rampastring.Tools;
2+
using Rampastring.XNAUI;
3+
using Rampastring.XNAUI.XNAControls;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using TSMapEditor.Models;
10+
using TSMapEditor.UI.Controls;
11+
12+
namespace TSMapEditor.UI.Windows
13+
{
14+
public class RandomBasedTriggersCreatedEventArgs : EventArgs
15+
{
16+
public RandomBasedTriggersCreatedEventArgs(Trigger baseTrigger)
17+
{
18+
BaseTrigger = baseTrigger;
19+
}
20+
21+
public Trigger BaseTrigger { get; }
22+
}
23+
24+
public class AddRandomBasedTriggerWindow : INItializableWindow
25+
{
26+
public AddRandomBasedTriggerWindow(WindowManager windowManager, Map map) : base(windowManager)
27+
{
28+
this.map = map;
29+
}
30+
31+
private readonly Map map;
32+
33+
private EditorTextBox tbName;
34+
private EditorNumberTextBox tbNumTriggers;
35+
private EditorNumberTextBox tbElapsedTime;
36+
private EditorNumberTextBox tbDelay;
37+
private XNACheckBox cbEveryDiff;
38+
private EditorButton btnApply;
39+
40+
public event EventHandler<RandomBasedTriggersCreatedEventArgs> RandomBasedTriggersCreated;
41+
42+
public override void Initialize()
43+
{
44+
Name = nameof(AddRandomBasedTriggerWindow);
45+
base.Initialize();
46+
47+
tbName = FindChild<EditorTextBox>(nameof(tbName));
48+
tbName.AllowComma = false;
49+
50+
tbNumTriggers = FindChild<EditorNumberTextBox>(nameof(tbNumTriggers));
51+
tbNumTriggers.AllowComma = false;
52+
tbNumTriggers.AllowDecimals = false;
53+
54+
tbElapsedTime = FindChild<EditorNumberTextBox>(nameof(tbElapsedTime));
55+
tbElapsedTime.AllowComma = false;
56+
tbElapsedTime.AllowDecimals = false;
57+
58+
tbDelay = FindChild<EditorNumberTextBox>(nameof(tbDelay));
59+
tbDelay.AllowComma = false;
60+
tbDelay.AllowDecimals = false;
61+
62+
cbEveryDiff = FindChild<XNACheckBox>(nameof(cbEveryDiff));
63+
btnApply = FindChild<EditorButton>(nameof(btnApply));
64+
65+
btnApply.LeftClick += BtnApply_LeftClick;
66+
}
67+
68+
public void BtnApply_LeftClick(object sender, EventArgs e)
69+
{
70+
if (!Validate())
71+
{
72+
return;
73+
}
74+
75+
string name = tbName.Text;
76+
int elapsedTime = tbElapsedTime.Value;
77+
int count = tbNumTriggers.Value;
78+
int delay = tbDelay.Value;
79+
bool createForEveryDifficulty = cbEveryDiff.Checked;
80+
81+
List<Trigger> baseTriggers = [];
82+
83+
if (createForEveryDifficulty)
84+
{
85+
baseTriggers.Add(CreateRandomBasedTriggers(name, elapsedTime, count, delay, Difficulty.Hard));
86+
baseTriggers.Add(CreateRandomBasedTriggers(name, elapsedTime, count, delay, Difficulty.Medium));
87+
baseTriggers.Add(CreateRandomBasedTriggers(name, elapsedTime, count, delay, Difficulty.Easy));
88+
} else
89+
{
90+
baseTriggers.Add(CreateRandomBasedTriggers(name, elapsedTime, count, delay));
91+
}
92+
93+
Hide();
94+
RandomBasedTriggersCreated?.Invoke(this, new RandomBasedTriggersCreatedEventArgs(baseTriggers[0]));
95+
}
96+
97+
private Trigger CreateRandomBasedTriggers(string name, int elapsedTime, int count, int delay, Difficulty? difficulty = null)
98+
{
99+
if (difficulty != null)
100+
{
101+
name = $"{difficulty.ToString()[0]} {name}";
102+
}
103+
104+
var baseTrigger = CreateBaseTrigger(name, elapsedTime, difficulty);
105+
var childTriggers = CreateChildTriggers(name, count, delay);
106+
AssociateTriggers(baseTrigger, childTriggers);
107+
108+
return baseTrigger;
109+
}
110+
111+
private bool Validate()
112+
{
113+
if (tbName.Text == string.Empty)
114+
{
115+
EditorMessageBox.Show(WindowManager, "Missing Trigger Name",
116+
"Please enter a name for the triggers", MessageBoxButtons.OK);
117+
return false;
118+
}
119+
120+
if (tbNumTriggers.Value < 2)
121+
{
122+
EditorMessageBox.Show(WindowManager, "Invalid Number of Triggers",
123+
"Please enter a value of 2 or more", MessageBoxButtons.OK);
124+
return false;
125+
}
126+
127+
if (tbElapsedTime.Value < 0)
128+
{
129+
EditorMessageBox.Show(WindowManager, "Invalid Elapsed Time",
130+
"Please enter a value of 0 or more", MessageBoxButtons.OK);
131+
return false;
132+
}
133+
134+
if (tbDelay.Value < 10)
135+
{
136+
EditorMessageBox.Show(WindowManager, "Invalid Random Delay",
137+
"Please enter a value of 10 or more", MessageBoxButtons.OK);
138+
return false;
139+
}
140+
141+
return true;
142+
}
143+
144+
private Trigger CreateBaseTrigger(string name, int elapsedTime, Difficulty? difficulty)
145+
{
146+
string triggerName = $"{name} base";
147+
148+
var baseTrigger = new Trigger(map.GetNewUniqueInternalId());
149+
baseTrigger.Name = triggerName;
150+
baseTrigger.HouseType = "Neutral";
151+
152+
if (difficulty != null)
153+
{
154+
baseTrigger.Hard = difficulty == Difficulty.Hard;
155+
baseTrigger.Normal = difficulty == Difficulty.Medium;
156+
baseTrigger.Easy = difficulty == Difficulty.Easy;
157+
158+
int diffGlobalVariableIndex = map.Rules.GlobalVariables.FindIndex(gv => gv.Name == $"Difficulty {difficulty}");
159+
160+
if (diffGlobalVariableIndex < 0)
161+
{
162+
Logger.Log($"{nameof(AddRandomBasedTriggerWindow)}.{nameof(CreateBaseTrigger)}: {difficulty} difficulty global variable not found!");
163+
164+
EditorMessageBox.Show(WindowManager, "Invalid Difficulty",
165+
$"The difficulty '{difficulty}' is not defined in the map's rules. Skipping Global Is Set event assignment to trigger", MessageBoxButtons.OK);
166+
} else
167+
{
168+
var globalSetCondition = new TriggerCondition();
169+
globalSetCondition.ConditionIndex = 27; // Global Is Set
170+
globalSetCondition.Parameters[1] = diffGlobalVariableIndex.ToString();
171+
172+
baseTrigger.Conditions.Add(globalSetCondition);
173+
}
174+
}
175+
176+
177+
var elapsedTimeCondition = new TriggerCondition();
178+
elapsedTimeCondition.ConditionIndex = 13; // Elapsed Time
179+
elapsedTimeCondition.Parameters[1] = elapsedTime.ToString();
180+
181+
baseTrigger.Conditions.Add(elapsedTimeCondition);
182+
183+
map.Triggers.Add(baseTrigger);
184+
map.Tags.Add(new Tag() { ID = map.GetNewUniqueInternalId(), Name = baseTrigger.Name + " (tag)", Trigger = baseTrigger, Repeating = 2 });
185+
186+
return baseTrigger;
187+
}
188+
189+
private List<Trigger> CreateChildTriggers(string name, int count, int delay)
190+
{
191+
List<Trigger> triggers = [];
192+
193+
for (int i = 0; i < count; i++)
194+
{
195+
var childTrigger = new Trigger(map.GetNewUniqueInternalId());
196+
childTrigger.Name = $"{name} {i + 1}";
197+
childTrigger.HouseType = "Neutral";
198+
childTrigger.Disabled = true;
199+
200+
var randomDelayCondition = new TriggerCondition();
201+
randomDelayCondition.ConditionIndex = 51; // Random Delay
202+
randomDelayCondition.Parameters[1] = delay.ToString();
203+
204+
childTrigger.Conditions.Add(randomDelayCondition);
205+
206+
map.Triggers.Add(childTrigger);
207+
map.Tags.Add(new Tag() { ID = map.GetNewUniqueInternalId(), Name = childTrigger.Name + " (tag)", Trigger = childTrigger, Repeating = 2 });
208+
209+
triggers.Add(childTrigger);
210+
}
211+
212+
return triggers;
213+
}
214+
215+
private void AssociateTriggers(Trigger baseTrigger, List<Trigger> childTriggers)
216+
{
217+
foreach (var childTrigger in childTriggers)
218+
{
219+
// base trigger needs to enable each of the child triggers
220+
var enableTriggerAction = new TriggerAction();
221+
enableTriggerAction.ActionIndex = 53; // Enable Trigger
222+
enableTriggerAction.Parameters[0] = "2";
223+
enableTriggerAction.Parameters[1] = childTrigger.ID;
224+
225+
baseTrigger.Actions.Add(enableTriggerAction);
226+
227+
// each child trigger needs to disable itself and each other child trigger
228+
foreach (var siblingTrigger in childTriggers)
229+
{
230+
var disableTriggerAction = new TriggerAction();
231+
disableTriggerAction.ActionIndex = 54; // Disable Trigger
232+
disableTriggerAction.Parameters[0] = "2";
233+
disableTriggerAction.Parameters[1] = siblingTrigger.ID;
234+
235+
childTrigger.Actions.Add(disableTriggerAction);
236+
}
237+
}
238+
}
239+
240+
public void Open()
241+
{
242+
Show();
243+
ResetValues();
244+
}
245+
246+
public void ResetValues()
247+
{
248+
tbName.Text = string.Empty;
249+
tbNumTriggers.Value = 3;
250+
tbElapsedTime.Value = 100;
251+
tbDelay.Value = 10;
252+
cbEveryDiff.Checked = false;
253+
}
254+
}
255+
}

src/TSMapEditor/UI/Windows/TriggersWindow.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ public enum TriggerSortMode
2424
ColorThenName,
2525
}
2626

27+
public class AddRandomBasedTriggersEventArgs : EventArgs
28+
{
29+
public AddRandomBasedTriggersEventArgs() { }
30+
}
31+
2732
public class TriggersWindow : INItializableWindow
2833
{
2934
public TriggersWindow(WindowManager windowManager, Map map, EditorState editorState, ICursorActionTarget cursorActionTarget) : base(windowManager)
@@ -37,6 +42,7 @@ public TriggersWindow(WindowManager windowManager, Map map, EditorState editorSt
3742
}
3843

3944
public event EventHandler<TeamTypeEventArgs> TeamTypeOpened;
45+
public event EventHandler<AddRandomBasedTriggersEventArgs> AddRandomBasedTriggersOpened;
4046

4147
private readonly Map map;
4248
private readonly ICursorActionTarget cursorActionTarget;
@@ -104,6 +110,7 @@ public TriggersWindow(WindowManager windowManager, Map map, EditorState editorSt
104110
private SelectSpeechWindow selectSpeechWindow;
105111
private SelectSoundWindow selectSoundWindow;
106112
private SelectParticleSystemTypeWindow selectParticleSystemTypeWindow;
113+
private AddRandomBasedTriggerWindow addRandomBasedTriggerWindow;
107114

108115
private XNAContextMenu actionContextMenu;
109116
private XNAContextMenu eventContextMenu;
@@ -217,6 +224,7 @@ public override void Initialize()
217224
ddActions.AddItem(new XNADropDownItem() { Text = contextMenuOption.Text, Tag = contextMenuOption.SelectAction });
218225
}
219226
ddActions.AddItem(new XNADropDownItem() { Text = "Re-generate Trigger IDs", Tag = new Action(RegenerateIDs) });
227+
ddActions.AddItem(new XNADropDownItem() { Text = "Add Random Based Triggers", Tag = new Action(OpenAddRandomBasedTriggersWindow) });
220228

221229
ddActions.SelectedIndex = 0;
222230
ddActions.SelectedIndexChanged += DdActions_SelectedIndexChanged;
@@ -2332,5 +2340,11 @@ private void OpenTeamType(TeamType teamType)
23322340
TeamTypeOpened?.Invoke(this, new TeamTypeEventArgs(teamType));
23332341
PutOnBackground();
23342342
}
2343+
2344+
private void OpenAddRandomBasedTriggersWindow()
2345+
{
2346+
AddRandomBasedTriggersOpened?.Invoke(this, new AddRandomBasedTriggersEventArgs());
2347+
PutOnBackground();
2348+
}
23352349
}
23362350
}

0 commit comments

Comments
 (0)