3
3
import sys
4
4
import asyncio
5
5
import random
6
- from typing import Tuple , List , Iterable
7
- from worlds .wargroove .Items import faction_table , CommanderData
6
+ from typing import Tuple , List , Iterable , Dict
7
+
8
+ from worlds .wargroove import WargrooveWorld
9
+ from worlds .wargroove .Items import item_table , faction_table , CommanderData , ItemData
8
10
9
11
import ModuleUpdate
10
12
ModuleUpdate .update ()
11
13
12
14
import Utils
13
15
import json
16
+ import logging
14
17
15
18
if __name__ == "__main__" :
16
19
Utils .init_logging ("WargrooveClient" , exception_logger = "Client" )
20
+ Utils .init_logging ("WG" , exception_logger = "Client" )
17
21
18
22
from NetUtils import NetworkItem , ClientStatus
19
23
from CommonClient import gui_enabled , logger , get_base_parser , ClientCommandProcessor , \
20
24
CommonContext , server_loop
21
25
26
+ wg_logger = logging .getLogger ("WG" )
27
+
22
28
23
29
class WargrooveClientCommandProcessor (ClientCommandProcessor ):
24
30
def _cmd_resync (self ):
@@ -33,23 +39,32 @@ def _cmd_commander(self, *commander_name: Iterable[str]):
33
39
else :
34
40
if self .ctx .can_choose_commander :
35
41
commanders = self .ctx .get_commanders ()
36
- logger .info ('Unlocked commanders: ' +
37
- ', ' .join ((commander .name for commander , unlocked in commanders if unlocked ))
38
- )
39
- logger .info ('Locked commanders: ' +
40
- ', ' .join ((commander .name for commander , unlocked in commanders if not unlocked ))
41
- )
42
+ wg_logger .info ('Unlocked commanders: ' +
43
+ ', ' .join ((commander .name for commander , unlocked in commanders if unlocked )))
44
+ wg_logger .info ('Locked commanders: ' +
45
+ ', ' .join ((commander .name for commander , unlocked in commanders if not unlocked )))
42
46
else :
43
- logger .error ('Cannot set commanders in this game mode.' )
47
+ wg_logger .error ('Cannot set commanders in this game mode.' )
44
48
45
49
46
50
class WargrooveContext (CommonContext ):
47
51
command_processor : int = WargrooveClientCommandProcessor
48
52
game = "Wargroove"
49
53
items_handling = 0b111 # full remote
50
54
current_commander : CommanderData = faction_table ["Starter" ][0 ]
51
- can_choose_commander : bool
55
+ can_choose_commander : bool = False
56
+ commander_defense_boost_multiplier : int = 0
57
+ income_boost_multiplier : int = 0
52
58
starting_groove_multiplier : float
59
+ faction_item_ids = {
60
+ 'Starter' : 0 ,
61
+ 'Cherrystone' : 52025 ,
62
+ 'Felheim' : 52026 ,
63
+ 'Floran' : 52027 ,
64
+ 'Heavensong' : 52028 ,
65
+ 'Requiem' : 52029 ,
66
+ 'Outlaw' : 52030
67
+ }
53
68
54
69
def __init__ (self , server_address , password ):
55
70
super (WargrooveContext , self ).__init__ (server_address , password )
@@ -108,13 +123,17 @@ def on_package(self, cmd: str, args: dict):
108
123
slot_data = args ["slot_data" ]
109
124
json .dump (args ["slot_data" ], f )
110
125
self .can_choose_commander = slot_data ["can_choose_commander" ]
126
+ print ('can choose commander:' , self .can_choose_commander )
111
127
self .starting_groove_multiplier = slot_data ["starting_groove_multiplier" ]
128
+ self .income_boost_multiplier = slot_data ["income_boost" ]
129
+ self .commander_defense_boost_multiplier = slot_data ["commander_defense_boost" ]
112
130
f .close ()
113
131
for ss in self .checked_locations :
114
132
filename = f"send{ ss } "
115
133
with open (os .path .join (self .game_communication_path , filename ), 'w' ) as f :
116
134
f .close ()
117
135
self .update_commander_data ()
136
+ self .ui .update_tracker ()
118
137
119
138
random .seed (self .seed_name + str (self .slot ))
120
139
# Our indexes start at 1 and we have 23 levels
@@ -168,6 +187,7 @@ def on_package(self, cmd: str, args: dict):
168
187
self .player_names [network_item .player ])
169
188
f .close ()
170
189
self .update_commander_data ()
190
+ self .ui .update_tracker ()
171
191
172
192
if cmd in {"RoomUpdate" }:
173
193
if "checked_locations" in args :
@@ -178,15 +198,128 @@ def on_package(self, cmd: str, args: dict):
178
198
179
199
def run_gui (self ):
180
200
"""Import kivy UI system and start running it as self.ui_task."""
181
- from kvui import GameManager
201
+ from kvui import GameManager , HoverBehavior , ServerToolTip
202
+ from kivy .uix .tabbedpanel import TabbedPanelItem
203
+ from kivy .lang import Builder
204
+ from kivy .uix .button import Button
205
+ from kivy .uix .togglebutton import ToggleButton
206
+ from kivy .uix .boxlayout import BoxLayout
207
+ from kivy .uix .gridlayout import GridLayout
208
+ from kivy .uix .image import AsyncImage , Image
209
+ from kivy .uix .stacklayout import StackLayout
210
+ from kivy .uix .label import Label
211
+ from kivy .properties import ColorProperty
212
+ from kivy .uix .image import Image
213
+ import pkgutil
214
+
215
+ class TrackerLayout (BoxLayout ):
216
+ pass
217
+
218
+ class CommanderSelect (BoxLayout ):
219
+ pass
220
+
221
+ class CommanderButton (ToggleButton ):
222
+ pass
223
+
224
+ class FactionBox (BoxLayout ):
225
+ pass
226
+
227
+ class CommanderGroup (BoxLayout ):
228
+ pass
229
+
230
+ class ItemTracker (BoxLayout ):
231
+ pass
232
+
233
+ class ItemLabel (Label ):
234
+ pass
182
235
183
236
class WargrooveManager (GameManager ):
184
237
logging_pairs = [
185
- ("Client" , "Archipelago" )
238
+ ("Client" , "Archipelago" ),
239
+ ("WG" , "WG Console" ),
186
240
]
187
241
base_title = "Archipelago Wargroove Client"
242
+ ctx : WargrooveContext
243
+ unit_tracker : ItemTracker
244
+ trigger_tracker : BoxLayout
245
+ boost_tracker : BoxLayout
246
+ commander_buttons : Dict [int , List [CommanderButton ]]
247
+ tracker_items = {
248
+ "Swordsman" : ItemData (None , "Unit" , False ),
249
+ "Dog" : ItemData (None , "Unit" , False ),
250
+ ** item_table
251
+ }
252
+
253
+ def build (self ):
254
+ container = super ().build ()
255
+ panel = TabbedPanelItem (text = "Wargroove" )
256
+ panel .content = self .build_tracker ()
257
+ self .tabs .add_widget (panel )
258
+ return container
259
+
260
+ def build_tracker (self ) -> TrackerLayout :
261
+ try :
262
+ tracker = TrackerLayout (orientation = "horizontal" )
263
+ commander_select = CommanderSelect (orientation = "vertical" )
264
+ self .commander_buttons = {}
265
+
266
+ for faction , commanders in faction_table .items ():
267
+ faction_box = FactionBox (size_hint = (None , None ), width = 100 * len (commanders ), height = 70 )
268
+ commander_group = CommanderGroup ()
269
+ commander_buttons = []
270
+ for commander in commanders :
271
+ commander_button = CommanderButton (text = commander .name , group = "commanders" )
272
+ if faction == "Starter" :
273
+ commander_button .disabled = False
274
+ commander_button .bind (on_press = lambda instance : self .ctx .set_commander (instance .text ))
275
+ commander_buttons .append (commander_button )
276
+ commander_group .add_widget (commander_button )
277
+ self .commander_buttons [faction ] = commander_buttons
278
+ faction_box .add_widget (Label (text = faction , size_hint_x = None , pos_hint = {'left' : 1 }, size_hint_y = None , height = 10 ))
279
+ faction_box .add_widget (commander_group )
280
+ commander_select .add_widget (faction_box )
281
+ item_tracker = ItemTracker (padding = [0 ,20 ])
282
+ self .unit_tracker = BoxLayout (orientation = "vertical" )
283
+ other_tracker = BoxLayout (orientation = "vertical" )
284
+ self .trigger_tracker = BoxLayout (orientation = "vertical" )
285
+ self .boost_tracker = BoxLayout (orientation = "vertical" )
286
+ other_tracker .add_widget (self .trigger_tracker )
287
+ other_tracker .add_widget (self .boost_tracker )
288
+ item_tracker .add_widget (self .unit_tracker )
289
+ item_tracker .add_widget (other_tracker )
290
+ tracker .add_widget (commander_select )
291
+ tracker .add_widget (item_tracker )
292
+ self .update_tracker ()
293
+ return tracker
294
+ except Exception as e :
295
+ print (e )
296
+
297
+ def update_tracker (self ):
298
+ received_ids = [item .item for item in self .ctx .items_received ]
299
+ for faction , item_id in self .ctx .faction_item_ids .items ():
300
+ for commander_button in self .commander_buttons [faction ]:
301
+ commander_button .disabled = not (faction == "Starter" or item_id in received_ids )
302
+ self .unit_tracker .clear_widgets ()
303
+ self .trigger_tracker .clear_widgets ()
304
+ for name , item in self .tracker_items .items ():
305
+ if item .type in ("Unit" , "Trigger" ):
306
+ status_color = (1 , 1 , 1 , 1 ) if item .code is None or item .code in received_ids else (0.6 , 0.2 , 0.2 , 1 )
307
+ label = ItemLabel (text = name , color = status_color )
308
+ if item .type == "Unit" :
309
+ self .unit_tracker .add_widget (label )
310
+ else :
311
+ self .trigger_tracker .add_widget (label )
312
+ self .boost_tracker .clear_widgets ()
313
+ extra_income = received_ids .count (52023 ) * self .ctx .income_boost_multiplier
314
+ extra_defense = received_ids .count (52024 ) * self .ctx .commander_defense_boost_multiplier
315
+ income_boost = ItemLabel (text = "Extra Income: " + str (extra_income ))
316
+ defense_boost = ItemLabel (text = "Comm Defense: " + str (100 + extra_defense ))
317
+ self .boost_tracker .add_widget (income_boost )
318
+ self .boost_tracker .add_widget (defense_boost )
188
319
189
320
self .ui = WargrooveManager (self )
321
+ data = pkgutil .get_data (WargrooveWorld .__module__ , "Wargroove.kv" ).decode ()
322
+ Builder .load_string (data )
190
323
self .ui_task = asyncio .create_task (self .ui .async_run (), name = "UI" )
191
324
192
325
def update_commander_data (self ):
@@ -211,34 +344,35 @@ def update_commander_data(self):
211
344
filename = 'commander.json'
212
345
with open (os .path .join (self .game_communication_path , filename ), 'w' ) as f :
213
346
json .dump (data , f )
347
+ if self .ui :
348
+ self .ui .update_tracker ()
214
349
215
350
def set_commander (self , commander_name : str ) -> bool :
216
351
"""Sets the current commander to the given one, if possible"""
217
352
if not self .can_choose_commander :
218
- logger .error ("Cannot set commanders in this game mode." )
353
+ wg_logger .error ("Cannot set commanders in this game mode." )
219
354
return
220
355
match_name = commander_name .lower ()
221
356
for commander , unlocked in self .get_commanders ():
222
357
if commander .name .lower () == match_name or commander .alt_name and commander .alt_name .lower () == match_name :
223
358
if unlocked :
224
359
self .current_commander = commander
225
360
self .syncing = True
226
- logger .info (f"Commander set to { commander .name } ." )
361
+ wg_logger .info (f"Commander set to { commander .name } ." )
227
362
self .update_commander_data ()
228
363
return True
229
364
else :
230
- logger .error (f"Commander { commander .name } has not been unlocked." )
365
+ wg_logger .error (f"Commander { commander .name } has not been unlocked." )
231
366
return False
232
367
else :
233
- logger .error (f"{ commander_name } is not a recognized Wargroove commander." )
368
+ wg_logger .error (f"{ commander_name } is not a recognized Wargroove commander." )
234
369
235
370
def get_commanders (self ) -> List [Tuple [CommanderData , bool ]]:
236
371
"""Gets a list of commanders with their unlocked status"""
237
- received_item_names = (self .item_names [network_item .item ] for network_item in self .items_received )
238
- received_factions = {item_name [:- 11 ] for item_name in received_item_names if item_name .endswith (' Commanders' )}
239
372
commanders = []
373
+ received_ids = [item .item for item in self .items_received ]
240
374
for faction in faction_table .keys ():
241
- unlocked = faction == 'Starter' or str ( faction ) in received_factions
375
+ unlocked = faction == 'Starter' or self . faction_item_ids [ faction ] in received_ids
242
376
commanders += [(commander , unlocked ) for commander in faction_table [faction ]]
243
377
return commanders
244
378
0 commit comments