Skip to content

Commit dfbf0b4

Browse files
committed
actually implement space toggling mod
whoops...
1 parent 918f912 commit dfbf0b4

File tree

1 file changed

+64
-9
lines changed

1 file changed

+64
-9
lines changed

src/willow1_mod_menu/lobby.py

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
# ruff: noqa: D103
22
import re
3+
import traceback
34
from typing import Any
45

56
import unrealsdk
67
from unrealsdk.hooks import Block
78
from unrealsdk.unreal import BoundFunction, UObject, WeakPointer, WrappedStruct
89

9-
from mods_base import CoopSupport, Game, Mod, get_ordered_mod_list, hook, html_to_plain_text
10+
from mods_base import (
11+
CoopSupport,
12+
EInputEvent,
13+
Game,
14+
Mod,
15+
get_ordered_mod_list,
16+
hook,
17+
html_to_plain_text,
18+
)
1019
from mods_base.mod_list import base_mod
1120

1221
from .util import find_focused_item
@@ -36,6 +45,7 @@ def open_lobby_mods_menu(frontend: WillowGFxMenuFrontend) -> None:
3645
init_content.enable()
3746
play_sound.enable()
3847
menu_close.enable()
48+
handle_input_key.enable()
3949

4050
frontend.OpenMP()
4151

@@ -56,6 +66,23 @@ def block_search_delegate(
5666
return Block
5767

5868

69+
def get_mod_title(mod: Mod) -> str:
70+
"""
71+
Combines the mod name and status into a single title.
72+
73+
Args:
74+
mod: The mod to ge tthe title of.
75+
Returns:
76+
The title to use for the mod in this menu.
77+
"""
78+
# Filter out the standard enabled statuses, for more variation in the list - it's harder
79+
# to tell what's enabled or not when every single entry has a suffix
80+
# If there's a custom status, we'll still show that
81+
status = html_to_plain_text(mod.get_status()).strip()
82+
suffix = "" if mod.is_enabled and status in ("Enabled", "Loaded") else f" ({status})"
83+
return html_to_plain_text(mod.name) + suffix
84+
85+
5986
# This hook is when the menu is actually initialized - we overwrite it with all our own logic
6087
@hook("WillowGame.WillowGFxLobbyMultiplayer:extInitContent")
6188
def init_content(
@@ -76,17 +103,11 @@ def init_content(
76103

77104
drawn_mods.clear()
78105
for mod in get_ordered_mod_list():
79-
# Filter out the standard enabled statuses, for more variation in the list - it's harder
80-
# to tell what's enabled or not when every single entry has a suffix
81-
# If there's a custom status, we'll still show that
82-
status = html_to_plain_text(mod.get_status()).strip()
83-
suffix = "" if mod.is_enabled and status in ("Enabled", "Loaded") else f" ({status})"
84-
85106
# This function has extra options for other commands, and a lot of base game calls pass
86107
# something like `menuAddItem(0, "title", "tag", "extHostP", "Focus:extMenuFocus")`
87108
# Unfortunately for us, it seems passing anything after the title also results in corruption
88109
# This gives us a rough time later on actually detecting select/focus
89-
obj.menuAddItem(0, html_to_plain_text(mod.name) + suffix)
110+
obj.menuAddItem(0, get_mod_title(mod))
90111
drawn_mods.append(mod)
91112

92113
obj.menuEnd()
@@ -152,7 +173,7 @@ def update_menu_for_mod(menu: WillowGFxLobbyMultiplayer, mod: Mod) -> None:
152173

153174
tooltip = "$<StringAliasMap:GFx_Accept> DETAILS"
154175
if not mod.enabling_locked:
155-
tooltip += " [Space] " + "DISABLE" if mod.is_enabled else "ENABLE"
176+
tooltip += " [Space] " + ("DISABLE" if mod.is_enabled else "ENABLE")
156177
tooltip += " <Strings:WillowMenu.TitleMenu.BackBar>"
157178

158179
menu.SetVariableString("lobby.tooltips.text", tooltip)
@@ -216,6 +237,39 @@ def select_next_tick(*_: Any) -> None:
216237
update_menu_for_mod(menu, mod)
217238

218239

240+
@hook("WillowGame.WillowGFxLobbyMultiplayer:HandleInputKey")
241+
def handle_input_key(
242+
obj: UObject,
243+
args: WrappedStruct,
244+
_ret: Any,
245+
_func: BoundFunction,
246+
) -> tuple[type[Block], bool] | None:
247+
key: str = args.ukey
248+
event: EInputEvent = args.uevent
249+
250+
if not (key == "SpaceBar" and event == EInputEvent.IE_Released):
251+
return None
252+
253+
mod = get_focused_mod(obj)
254+
if mod is None or mod.enabling_locked:
255+
return None
256+
257+
old_enabled = mod.is_enabled
258+
try:
259+
(mod.disable if old_enabled else mod.enable)()
260+
except Exception: # noqa: BLE001
261+
traceback.print_exc()
262+
263+
# Extra safety layer in case the mod rejected the toggle, no need to update if we haven't
264+
# changed state
265+
if old_enabled != mod.is_enabled:
266+
update_menu_for_mod(obj, mod)
267+
268+
obj.SetVariableString(find_focused_item(obj) + ".mLabel.text", get_mod_title(mod))
269+
270+
return Block, True
271+
272+
219273
@hook("WillowGame.WillowGFxLobbyMultiplayer:OnClose")
220274
def menu_close(
221275
_obj: UObject,
@@ -229,6 +283,7 @@ def menu_close(
229283
play_sound.disable()
230284
select_next_tick.disable()
231285
menu_close.disable()
286+
handle_input_key.disable()
232287

233288
global current_menu
234289
current_menu = WeakPointer()

0 commit comments

Comments
 (0)