Skip to content

Commit 3fb085a

Browse files
committed
update(menus): More impl
1 parent c1102db commit 3fb085a

File tree

6 files changed

+227
-25
lines changed

6 files changed

+227
-25
lines changed

managed/src/SwiftlyS2.Core/Modules/Menus/Menu.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ internal class Menu : IMenu
1111
public string Title { get; set; } = "";
1212
public int MaxTitleLength { get; set; } = 32;
1313
public List<IMenuOption> Options { get; set; } = new();
14-
public List<IMenuOption>? PreviousOptions { get; set; } = new();
1514
public bool? FreezePlayer { get; set; } = null;
1615
public bool HasSound { get; set; } = true;
1716
public IMenu? ParentMenu { get; set; } = null;

managed/src/SwiftlyS2.Core/Modules/Menus/MenuManager.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ public void OpenSubMenu(IPlayer player, IMenu menu)
132132
MenuHistories[player] = new Stack<IMenu>();
133133

134134
MenuHistories[player].Push(currentMenu);
135+
menu.ParentMenu = currentMenu;
135136
}
136137

137138
OpenMenus[player] = menu;

managed/src/SwiftlyS2.Core/Modules/Menus/MenuService.cs

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using SwiftlyS2.Shared;
22
using SwiftlyS2.Shared.Events;
3+
using SwiftlyS2.Shared.Menus;
34
using SwiftlyS2.Shared.Misc;
5+
using SwiftlyS2.Shared.Players;
6+
using SwiftlyS2.Shared.SchemaDefinitions;
47
using SwiftlyS2.Shared.Sounds;
58

69
namespace SwiftlyS2.Core.Menus;
@@ -51,6 +54,9 @@ public MenuService(ISwiftlyCore core)
5154

5255
_exitSound.Name = _core.Menus.Settings.SoundExitName;
5356
_exitSound.Volume = _core.Menus.Settings.SoundExitVolume;
57+
58+
_core.Menus.OnMenuOpened += OnMenuOpened;
59+
_core.Menus.OnMenuClosed += OnMenuClosed;
5460
}
5561

5662
~MenuService()
@@ -59,6 +65,34 @@ public MenuService(ISwiftlyCore core)
5965
_core.Command.UnhookClientChat(ClientChatHook);
6066
}
6167

68+
private void OnMenuOpened(IPlayer player, IMenu menu)
69+
{
70+
var pawn = player.Pawn;
71+
if (pawn == null) return;
72+
73+
if (menu.FreezePlayer == true)
74+
{
75+
pawn.MoveType = MoveType_t.MOVETYPE_INVALID;
76+
pawn.MoveTypeUpdated();
77+
78+
pawn.ActualMoveType = MoveType_t.MOVETYPE_INVALID;
79+
}
80+
}
81+
82+
private void OnMenuClosed(IPlayer player, IMenu menu)
83+
{
84+
var pawn = player.Pawn;
85+
if (pawn == null) return;
86+
87+
if (menu.FreezePlayer == true)
88+
{
89+
pawn.MoveType = MoveType_t.MOVETYPE_WALK;
90+
pawn.MoveTypeUpdated();
91+
92+
pawn.ActualMoveType = MoveType_t.MOVETYPE_WALK;
93+
}
94+
}
95+
6296
private void OnClientKeyStateChanged(IOnClientKeyStateChangedEvent @event)
6397
{
6498
var player = _core.PlayerManager.GetPlayer(@event.PlayerId);
@@ -75,65 +109,86 @@ private void OnClientKeyStateChanged(IOnClientKeyStateChangedEvent @event)
75109
{
76110
menu.ChangePosition(1);
77111

78-
_scrollSound.Recipients.AddRecipient(@event.PlayerId);
79-
_scrollSound.Emit();
80-
_scrollSound.Recipients.RemoveRecipient(@event.PlayerId);
112+
if (menu.HasSound)
113+
{
114+
_scrollSound.Recipients.AddRecipient(@event.PlayerId);
115+
_scrollSound.Emit();
116+
_scrollSound.Recipients.RemoveRecipient(@event.PlayerId);
117+
}
81118
}
82119
else if (@event.Key == exitKey && @event.Pressed && menu.CanExit)
83120
{
84121
_core.Menus.CloseMenu(player);
85122

86-
_exitSound.Recipients.AddRecipient(@event.PlayerId);
87-
_exitSound.Emit();
88-
_exitSound.Recipients.RemoveRecipient(@event.PlayerId);
123+
if (menu.HasSound)
124+
{
125+
_exitSound.Recipients.AddRecipient(@event.PlayerId);
126+
_exitSound.Emit();
127+
_exitSound.Recipients.RemoveRecipient(@event.PlayerId);
128+
}
89129
}
90130
else if (@event.Key == useKey && @event.Pressed)
91131
{
92132
var option = menu.Options[menu.CurrentIndex];
93133
if (!option.Disabled && option.OnChoice != null)
94134
{
95135
option.OnChoice(player, option, menu);
96-
_useSound.Recipients.AddRecipient(@event.PlayerId);
97-
_useSound.Emit();
98-
_useSound.Recipients.RemoveRecipient(@event.PlayerId);
136+
if (menu.HasSound)
137+
{
138+
_useSound.Recipients.AddRecipient(@event.PlayerId);
139+
_useSound.Emit();
140+
_useSound.Recipients.RemoveRecipient(@event.PlayerId);
141+
}
99142
}
100143
}
101144
}
102145
else if (_core.Menus.Settings.InputMode == "wasd")
103146
{
104147
if (@event.Key == KeyKind.W && @event.Pressed)
105148
{
106-
menu.ChangePosition(1);
149+
menu.ChangePosition(-1);
107150

108-
_scrollSound.Recipients.AddRecipient(@event.PlayerId);
109-
_scrollSound.Emit();
110-
_scrollSound.Recipients.RemoveRecipient(@event.PlayerId);
151+
if (menu.HasSound)
152+
{
153+
_scrollSound.Recipients.AddRecipient(@event.PlayerId);
154+
_scrollSound.Emit();
155+
_scrollSound.Recipients.RemoveRecipient(@event.PlayerId);
156+
}
111157
}
112158
else if (@event.Key == KeyKind.S && @event.Pressed)
113159
{
114-
menu.ChangePosition(-1);
160+
menu.ChangePosition(1);
115161

116-
_scrollSound.Recipients.AddRecipient(@event.PlayerId);
117-
_scrollSound.Emit();
118-
_scrollSound.Recipients.RemoveRecipient(@event.PlayerId);
162+
if (menu.HasSound)
163+
{
164+
_scrollSound.Recipients.AddRecipient(@event.PlayerId);
165+
_scrollSound.Emit();
166+
_scrollSound.Recipients.RemoveRecipient(@event.PlayerId);
167+
}
119168
}
120169
else if (@event.Key == KeyKind.A && @event.Pressed && menu.CanExit)
121170
{
122171
_core.Menus.CloseMenu(player);
123172

124-
_exitSound.Recipients.AddRecipient(@event.PlayerId);
125-
_exitSound.Emit();
126-
_exitSound.Recipients.RemoveRecipient(@event.PlayerId);
173+
if (menu.HasSound)
174+
{
175+
_exitSound.Recipients.AddRecipient(@event.PlayerId);
176+
_exitSound.Emit();
177+
_exitSound.Recipients.RemoveRecipient(@event.PlayerId);
178+
}
127179
}
128180
else if (@event.Key == KeyKind.D && @event.Pressed)
129181
{
130182
var option = menu.Options[menu.CurrentIndex];
131183
if (!option.Disabled && option.OnChoice != null)
132184
{
133185
option.OnChoice(player, option, menu);
134-
_useSound.Recipients.AddRecipient(@event.PlayerId);
135-
_useSound.Emit();
136-
_useSound.Recipients.RemoveRecipient(@event.PlayerId);
186+
if (menu.HasSound)
187+
{
188+
_useSound.Recipients.AddRecipient(@event.PlayerId);
189+
_useSound.Emit();
190+
_useSound.Recipients.RemoveRecipient(@event.PlayerId);
191+
}
137192
}
138193
}
139194
}

managed/src/SwiftlyS2.Shared/Modules/Menus/IMenu.cs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,93 @@ public enum MenuType
1010

1111
public interface IMenu
1212
{
13+
/// <summary>
14+
/// The title of the menu.
15+
/// </summary>
1316
public string Title { get; set; }
17+
/// <summary>
18+
/// The maximum length of the title. (default: 32)
19+
/// </summary>
1420
public int MaxTitleLength { get; set; }
21+
/// <summary>
22+
/// The options in the menu. Not supposed to be modified manually.
23+
/// </summary>
1524
public List<IMenuOption> Options { get; set; }
16-
public List<IMenuOption>? PreviousOptions { get; set; }
25+
/// <summary>
26+
/// Whether to freeze the player while the menu is open.
27+
/// </summary>
1728
public bool? FreezePlayer { get; set; }
29+
/// <summary>
30+
/// Whether the menu has sound effects.
31+
/// </summary>
1832
public bool HasSound { get; set; }
33+
/// <summary>
34+
/// The parent menu if this is a submenu.
35+
/// </summary>
1936
public IMenu? ParentMenu { get; set; }
37+
/// <summary>
38+
/// Whether the menu can be exited.
39+
/// </summary>
2040
public bool CanExit { get; set; }
41+
/// <summary>
42+
/// The kind of the menu.
43+
/// </summary>
2144
public MenuType Kind { get; set; }
45+
/// <summary>
46+
/// The color of the menu.
47+
/// </summary>
2248
public Color Color { get; set; }
49+
/// <summary>
50+
/// The text to render to the user.
51+
/// </summary>
2352
public string? RenderText { get; }
53+
/// <summary>
54+
/// The current item selected.
55+
/// </summary>
2456
public int CurrentIndex { get; set; }
2557

58+
/// <summary>
59+
/// Add an option to the menu.
60+
/// </summary>
61+
/// <param name="display">Text to display</param>
62+
/// <param name="onChoice">Use Callback</param>
63+
/// <param name="defaultDisabled">Make it disabled by default</param>
64+
/// <returns>Menu Option</returns>
2665
public ref IMenuOption AddOption(string display, Action<IPlayer, IMenuOption, IMenu>? onChoice, bool defaultDisabled = false);
66+
/// <summary>
67+
/// Add a boolean option to the menu.
68+
/// </summary>
69+
/// <param name="display">Text to display</param>
70+
/// <param name="defaultValue">Default value</param>
71+
/// <param name="onChoice">Use Callback</param>
72+
/// <param name="defaultDisabled">Make it disabled by default</param>
73+
/// <returns>Menu Option</returns>
2774
public ref IMenuOption AddBoolOption(string display, bool defaultValue, Action<IPlayer, IMenuOption, IMenu>? onChoice, bool defaultDisabled = false);
75+
/// <summary>
76+
/// Add an input option to the menu.
77+
/// </summary>
78+
/// <param name="display">Text to display</param>
79+
/// <param name="placeholder">Placeholder text</param>
80+
/// <param name="inputRequestMessage">Input request message</param>
81+
/// <param name="onInput">Use Callback</param>
82+
/// <param name="defaultDisabled">Make it disabled by default</param>
83+
/// <returns>Menu Option</returns>
2884
public ref IMenuOption AddInputOption(string display, string placeholder, string? inputRequestMessage, Action<IPlayer, IMenuOption, IMenu, string>? onInput, bool defaultDisabled = false);
85+
/// <summary>
86+
/// Add a slider option to the menu.
87+
/// </summary>
88+
/// <param name="display">Text to display</param>
89+
/// <param name="values">List of values</param>
90+
/// <param name="defaultValue">Default value</param>
91+
/// <param name="displayItems">Number of items to display</param>
92+
/// <param name="onSlide">Use Callback</param>
93+
/// <param name="defaultDisabled">Make it disabled by default</param>
94+
/// <returns>Menu Option</returns>
2995
public ref IMenuOption AddSliderOption(string display, List<object> values, object? defaultValue, int displayItems, Action<IPlayer, IMenuOption, IMenu, int, object>? onSlide, bool defaultDisabled = false);
3096

97+
/// <summary>
98+
/// Changes the current position by a certain count.
99+
/// </summary>
100+
/// <param name="count">The amount of advancements to make in front or in back</param>
31101
public void ChangePosition(int count);
32102
}

managed/src/SwiftlyS2.Shared/Modules/Menus/IMenuManager.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,66 @@ public struct MenuSettings
2222

2323
public interface IMenuManager
2424
{
25+
/// <summary>
26+
/// Creates a new menu instance.
27+
/// </summary>
28+
/// <param name="title">The title of the menu.</param>
29+
/// <param name="freezePlayer">Whether to freeze the player while the menu is open.</param>
30+
/// <param name="hasSound">Whether the menu has sound effects.</param>
31+
/// <param name="canExit">Whether the menu can be exited.</param>
32+
/// <returns>Menu Object</returns>
2533
public IMenu CreateMenu(string title, bool freezePlayer, bool hasSound, bool canExit);
34+
/// <summary>
35+
/// Opens a menu for a player.
36+
/// </summary>
2637
public void OpenMenu(IPlayer player, IMenu menu);
38+
/// <summary>
39+
/// Closes the current menu for a player.
40+
/// </summary>
2741
public void CloseMenu(IPlayer player);
42+
/// <summary>
43+
/// Gets the player associated with a menu.
44+
/// </summary>
2845
public IPlayer? GetPlayerFromMenu(IMenu menu);
46+
/// <summary>
47+
/// Checks if a menu is currently open for a player.
48+
/// </summary>
2949
public bool IsMenuOpen(IPlayer player);
50+
/// <summary>
51+
/// Gets the current menu for a player, or null if no menu is open.
52+
/// </summary>
3053
public IMenu? GetCurrentMenu(IPlayer player);
54+
/// <summary>
55+
/// Opens a submenu for a player, closing the current menu.
56+
/// </summary>
3157
public void OpenSubMenu(IPlayer player, IMenu menu);
3258

59+
/// <summary>
60+
/// Sets an input state callback for a player.
61+
/// </summary>
3362
public void SetInputState(IPlayer player, Action<IPlayer, IMenuOption, IMenu, string>? onInput);
63+
/// <summary>
64+
/// Checks if a player has an input state callback set.
65+
/// </summary>
3466
public bool HasInputState(IPlayer player);
67+
/// <summary>
68+
/// Gets the input state callback for a player.
69+
/// </summary>
3570
public Action<IPlayer, IMenuOption, IMenu, string>? GetInputState(IPlayer player);
3671

3772
public void RenderForPlayer(IPlayer player);
3873
public void ClearRenderForPlayer(IPlayer player);
3974

75+
/// <summary>
76+
/// Event triggered when a menu is opened.
77+
/// </summary>
4078
public event Action<IPlayer, IMenu>? OnMenuOpened;
79+
/// <summary>
80+
/// Event triggered when a menu is closed.
81+
/// </summary>
4182
public event Action<IPlayer, IMenu>? OnMenuClosed;
83+
/// <summary>
84+
/// Menu settings.
85+
/// </summary>
4286
public MenuSettings Settings { get; }
4387
}

managed/src/SwiftlyS2.Shared/Modules/Menus/IMenuOption.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,48 @@ public enum OptionType
1212

1313
public interface IMenuOption
1414
{
15+
/// <summary>
16+
/// The menu this option belongs to.
17+
/// </summary>
1518
public IMenu? Menu { get; set; }
19+
/// <summary>
20+
/// The text to display for this option.
21+
/// </summary>
1622
public string Display { get; set; }
23+
/// <summary>
24+
/// The callback to invoke when this option is selected.
25+
/// </summary>
1726
public Action<IPlayer, IMenuOption, IMenu>? OnChoice { get; set; }
27+
/// <summary>
28+
/// The callback to invoke when input is received for this option (only for Input type).
29+
/// </summary>
1830
public int Index { get; set; }
31+
/// <summary>
32+
/// The type of this option (Button, Bool, Input, Slider).
33+
/// </summary>
1934
public OptionType Type { get; set; }
35+
/// <summary>
36+
/// Whether this option is disabled.
37+
/// </summary>
2038
public bool Disabled { get; set; }
39+
/// <summary>
40+
/// The default value for this option (only for Bool, Input, Slider types).
41+
/// </summary>
2142
public object? DefaultValue { get; set; }
43+
/// <summary>
44+
/// The number of items to display on screen for slider
45+
/// </summary>
2246
public int SliderDisplayItems { get; set; }
47+
/// <summary>
48+
/// The possible values for this option (only for Slider type).
49+
/// </summary>
2350
public List<object>? SliderValues { get; set; }
51+
/// <summary>
52+
/// The current value of this option (only for Bool, Input, Slider types).
53+
/// </summary>
2454
public object? Value { get; set; }
55+
/// <summary>
56+
/// The currently selected index for this option (only for Slider type).
57+
/// </summary>
2558
public int SelectedIndex { get; }
2659
}

0 commit comments

Comments
 (0)