mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-17 18:00:25 +02:00
4353 lines
138 KiB
C
4353 lines
138 KiB
C
/*
|
|
UI_WIDGET_GAME_DATA_INPUT_FUNCTIONS.C
|
|
|
|
symbols in this file:
|
|
000E01B0 0060:
|
|
_ui_widget_game_data_function_invoke (0000)
|
|
000E0210 0010:
|
|
_code_000e0210 (0000)
|
|
000E0220 0110:
|
|
_code_000e0220 (0000)
|
|
000E0330 00b0:
|
|
_code_000e0330 (0000)
|
|
000E03E0 00b0:
|
|
_code_000e03e0 (0000)
|
|
000E0490 0080:
|
|
_code_000e0490 (0000)
|
|
000E0510 0110:
|
|
_code_000e0510 (0000)
|
|
000E0620 0090:
|
|
_code_000e0620 (0000)
|
|
000E06B0 07e0:
|
|
_code_000e06b0 (0000)
|
|
000E0E90 07c0:
|
|
_code_000e0e90 (0000)
|
|
000E1650 04c0:
|
|
_code_000e1650 (0000)
|
|
000E1B10 0120:
|
|
_code_000e1b10 (0000)
|
|
000E1C30 00b0:
|
|
_code_000e1c30 (0000)
|
|
000E1CE0 0130:
|
|
_code_000e1ce0 (0000)
|
|
000E1E10 0090:
|
|
_code_000e1e10 (0000)
|
|
000E1EA0 0130:
|
|
_code_000e1ea0 (0000)
|
|
000E1FD0 0090:
|
|
_code_000e1fd0 (0000)
|
|
000E2060 00b0:
|
|
_code_000e2060 (0000)
|
|
000E2110 00b0:
|
|
_code_000e2110 (0000)
|
|
000E21C0 00c0:
|
|
_code_000e21c0 (0000)
|
|
000E2280 0090:
|
|
_code_000e2280 (0000)
|
|
000E2310 01c0:
|
|
_code_000e2310 (0000)
|
|
000E24D0 0110:
|
|
_code_000e24d0 (0000)
|
|
000E25E0 0070:
|
|
_code_000e25e0 (0000)
|
|
000E2650 0090:
|
|
_code_000e2650 (0000)
|
|
000E26E0 00b0:
|
|
_code_000e26e0 (0000)
|
|
000E2790 01c0:
|
|
_code_000e2790 (0000)
|
|
000E2950 00b0:
|
|
_code_000e2950 (0000)
|
|
000E2A00 00a0:
|
|
_code_000e2a00 (0000)
|
|
000E2AA0 00b0:
|
|
_code_000e2aa0 (0000)
|
|
000E2B50 0030:
|
|
_code_000e2b50 (0000)
|
|
000E2B80 0140:
|
|
_code_000e2b80 (0000)
|
|
000E2CC0 0050:
|
|
_code_000e2cc0 (0000)
|
|
000E2D10 00b0:
|
|
_code_000e2d10 (0000)
|
|
000E2DC0 0050:
|
|
_code_000e2dc0 (0000)
|
|
000E2E10 00b0:
|
|
_code_000e2e10 (0000)
|
|
000E2EC0 0110:
|
|
_code_000e2ec0 (0000)
|
|
000E2FD0 0110:
|
|
_code_000e2fd0 (0000)
|
|
000E30E0 0030:
|
|
_code_000e30e0 (0000)
|
|
000E3110 0030:
|
|
_code_000e3110 (0000)
|
|
000E3140 02c0:
|
|
_code_000e3140 (0000)
|
|
000E3400 0590:
|
|
_code_000e3400 (0000)
|
|
000E3990 04d0:
|
|
_code_000e3990 (0000)
|
|
000E3E60 0480:
|
|
_code_000e3e60 (0000)
|
|
000E42E0 0190:
|
|
_code_000e42e0 (0000)
|
|
000E4470 01b0:
|
|
_code_000e4470 (0000)
|
|
00276E0C 0018:
|
|
_rdata_00276e0c (0000)
|
|
00276E24 002b:
|
|
??_C@_0CL@DNDKGOAJ@invalid?5game_data_input_referenc@ (0000)
|
|
00276E50 003f:
|
|
??_C@_0DP@OKLHFPEA@c?3?2halo?2SOURCE?2interface?2ui_widg@ (0000)
|
|
00276E90 0052:
|
|
??_C@_0FC@OBGFIFIH@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00276EE8 0052:
|
|
??_C@_0FC@LKBMLMHJ@expected?5a?5container?5widget?5for?5@ (0000)
|
|
00276F3C 0038:
|
|
??_C@_0DI@JCPEOBOE@this?5doesn?8t?5look?5like?5the?5setti@ (0000)
|
|
00276F74 003e:
|
|
??_C@_0DO@LONIMMNH@invalid?5widget?5trying?5to?5update?5@ (0000)
|
|
00276FB8 005e:
|
|
??_C@_0FO@FDLMAEGD@expected?5a?5container?5widget?5w?1?52@ (0000)
|
|
00277018 004d:
|
|
??_C@_0EN@HLAAGDPF@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277068 004d:
|
|
??_C@_0EN@KLLFONFN@expected?5a?5container?5widget?5for?5@ (0000)
|
|
002770B8 003a:
|
|
??_C@_0DK@ENICFAKO@this?5doesn?8t?5look?5like?5the?5diffi@ (0000)
|
|
002770F4 000e:
|
|
??_C@_0O@JEJFBGJL@01?401?414?42342?$AA@ (0000)
|
|
00277104 0008:
|
|
??_C@_07GIJHABND@longest?$AA@ (0000)
|
|
0027710C 0007:
|
|
??_C@_06KLBAJMAC@putput?$AA@ (0000)
|
|
00277114 0007:
|
|
??_C@_06CLLOKCD@wizard?$AA@ (0000)
|
|
0027711C 000b:
|
|
??_C@_0L@BAHFJNLA@bloodgulch?$AA@ (0000)
|
|
00277128 000f:
|
|
??_C@_0P@NBJBBIIG@boardingaction?$AA@ (0000)
|
|
00277138 0009:
|
|
??_C@_08CNOAMHDF@carousel?$AA@ (0000)
|
|
00277144 0009:
|
|
??_C@_08DIOAEAHJ@chillout?$AA@ (0000)
|
|
00277150 000b:
|
|
??_C@_0L@GMPBGCHN@hangemhigh?$AA@ (0000)
|
|
0027715C 0009:
|
|
??_C@_08HDGLKCD@prisoner?$AA@ (0000)
|
|
00277168 0008:
|
|
??_C@_07JLEJHHKP@ratrace?$AA@ (0000)
|
|
00277170 000a:
|
|
??_C@_09COCHMMPL@damnation?$AA@ (0000)
|
|
0027717C 000b:
|
|
??_C@_0L@IAKJCANM@sidewinder?$AA@ (0000)
|
|
00277188 000c:
|
|
??_C@_0M@PGDPDJHM@beavercreek?$AA@ (0000)
|
|
00277194 0024:
|
|
??_C@_0CE@OEFEPJGP@expected?5?8score?5limit?5type?8?5text@ (0000)
|
|
002771B8 001f:
|
|
??_C@_0BP@DNJAOFEP@expected?5?8score?5limit?8?5textbox?$AA@ (0000)
|
|
002771D8 0025:
|
|
??_C@_0CF@KNIJBDBO@expected?5?8number?5of?5players?8?5tex@ (0000)
|
|
00277200 0020:
|
|
??_C@_0CA@LGKDOIEO@expected?5?8teams?5on?1off?8?5textbox?$AA@ (0000)
|
|
00277220 001b:
|
|
??_C@_0BL@BDLKAALE@expected?5?8ruleset?8?5textbox?$AA@ (0000)
|
|
0027723C 001c:
|
|
??_C@_0BM@CJHKAJCC@expected?5?8map?5name?8?5textbox?$AA@ (0000)
|
|
00277258 0024:
|
|
??_C@_0CE@DLEPIMAK@expected?5?8open?1closed?5game?8?5text@ (0000)
|
|
00277280 0043:
|
|
??_C@_0ED@MOEHAAMO@this?5doesn?8t?5look?5like?5the?5serve@ (0000)
|
|
002772C4 000c:
|
|
??_C@_1M@MOFLFCEC@?$AA?$CF?$AAs?$AA?5?$AA?$CF?$AAs?$AA?$AA@ (0000)
|
|
002772D0 0037:
|
|
??_C@_0DH@HCIIGMBA@this?5doesn?8t?5look?5like?5the?5net?5g@ (0000)
|
|
00277308 0024:
|
|
??_C@_0CE@ICIOPGOK@j?$DM?$CIMAXIMUM_NETWORK_MACHINE_COUNT@ (0000)
|
|
0027732C 0036:
|
|
??_C@_0DG@MINPNJCD@expected?5a?5spinner?5list?5for?5loca@ (0000)
|
|
00277364 0030:
|
|
??_C@_0DA@DJJOFFI@expected?5a?5text?5box?5for?5local?5pl@ (0000)
|
|
00277394 003d:
|
|
??_C@_0DN@HELEDMHI@expected?5container?5widget?5for?5lo@ (0000)
|
|
002773D4 0004:
|
|
??_C@_13HGPDMIBE@?$AA?$DP?$AA?$AA@ (0000)
|
|
002773D8 001a:
|
|
??_C@_1BK@JLDDOLFH@?$AA?$CF?$AAd?$AA?3?$AA?$CF?$AA0?$AA2?$AAd?$AA?3?$AA?$CF?$AA0?$AA2?$AAd?$AA?$AA@ (0000)
|
|
002773F4 0014:
|
|
??_C@_1BE@HOCBODIC@?$AA?$CF?$AA0?$AA2?$AAd?$AA?3?$AA?$CF?$AA0?$AA2?$AAd?$AA?$AA@ (0000)
|
|
00277408 000e:
|
|
??_C@_1O@KKMDEBPC@?$AA0?$AA?3?$AA?$CF?$AA0?$AA2?$AAd?$AA?$AA@ (0000)
|
|
00277418 000a:
|
|
??_C@_19FLLBDBFH@?$AA?9?$AA?3?$AA?9?$AA?9?$AA?$AA@ (0000)
|
|
00277424 003b:
|
|
??_C@_0DL@IGDJEBKB@this?5doesn?8t?5look?5like?5the?5net?5p@ (0000)
|
|
00277460 0069:
|
|
??_C@_0GJ@GDGAOPKB@expected?5a?5container?5widget?5w?1?52@ (0000)
|
|
002774D0 005c:
|
|
??_C@_0FM@EACADPLD@expected?5a?5spinner?5list?5somewher@ (0000)
|
|
0027752C 003c:
|
|
??_C@_0DM@MLIDECNJ@expected?5some?5list?5items?5for?5mul@ (0000)
|
|
00277568 004b:
|
|
??_C@_0EL@PGAPPADO@expected?5a?5text?5box?5for?5multipla@ (0000)
|
|
002775B4 0037:
|
|
??_C@_0DH@NAJMEKMA@expected?5column?5list?5for?5multipl@ (0000)
|
|
002775EC 0027:
|
|
??_C@_0CH@OMEIFLEC@expected?5a?5text?5box?5for?5objectiv@ (0000)
|
|
00277614 0030:
|
|
??_C@_0DA@MCJKJCJL@expected?5some?5list?5items?5for?5gam@ (0000)
|
|
00277648 004a:
|
|
??_C@_0EK@NOJLKNLA@expected?5a?5picture?5?$CIcontainer?$CJ?5f@ (0000)
|
|
00277694 002b:
|
|
??_C@_0CL@LGIIOMBB@expected?5column?5list?5for?5game?5op@ (0000)
|
|
002776C0 004f:
|
|
??_C@_0EP@BOHIHIIA@expected?5a?5picture?5?$CIcontainer?$CJ?5f@ (0000)
|
|
00277710 0030:
|
|
??_C@_0DA@GGNAKDLF@expected?5column?5list?5for?5main?5me@ (0000)
|
|
00277740 0039:
|
|
??_C@_0DJ@NEPMGIAE@profile?5display?5name?5requires?5a?5@ (0000)
|
|
0027777C 0034:
|
|
??_C@_0DE@IDFNJNLE@expected?5a?5text?5box?5widget?5for?5p@ (0000)
|
|
002777B0 0025:
|
|
??_C@_0CF@LGDBPHO@not?5currently?5editing?5a?5game?5var@ (0000)
|
|
002777D8 003a:
|
|
??_C@_0DK@DJCOLPLF@profile?5color?5picture?5requires?5a@ (0000)
|
|
00277814 0010:
|
|
??_C@_0BA@NMGAHKFN@no?5network?5game?$AA@ (0000)
|
|
00277824 0033:
|
|
??_C@_0DD@GEABDGEJ@expected?5text?5box?5widget?5for?5mp?5@ (0000)
|
|
00277858 0036:
|
|
??_C@_0DG@FJNIMEAA@expected?5container?5widget?5for?5mp@ (0000)
|
|
00277890 0043:
|
|
??_C@_0ED@NCOLLMLO@expected?5a?5text?5box?5widget?5for?5m@ (0000)
|
|
002778D4 001e:
|
|
??_C@_0BO@DGGONLGF@network?5connection?5went?5down?$CB?$AA@ (0000)
|
|
002778F4 0032:
|
|
??_C@_0DC@LKBOPPAG@expected?5text?5box?5widget?5for?5tea@ (0000)
|
|
00277928 0039:
|
|
??_C@_0DJ@NJMHKDFJ@expected?5a?5container?5bitmap?5for?5@ (0000)
|
|
00277968 004e:
|
|
??_C@_0EO@HIEOEPPB@this?5doesn?8t?5look?5like?5the?5diffi@ (0000)
|
|
002779B8 0032:
|
|
??_C@_0DC@GEEGOIHG@this?5doesn?8t?5look?5like?5the?5diffi@ (0000)
|
|
002779EC 003a:
|
|
??_C@_0DK@NIBNNGB@expected?5a?5text?5box?5widget?5for?5s@ (0000)
|
|
00277A28 001f:
|
|
??_C@_0BP@PBNOOFFO@failed?5to?5cache?5player?5profile?$AA@ (0000)
|
|
00277A48 001a:
|
|
??_C@_0BK@NPAODFGK@not?5enough?5cache?5profiles?$AA@ (0000)
|
|
00277A64 0021:
|
|
??_C@_0CB@DCGNELO@failed?5to?5cache?5playlist?5profile@ (0000)
|
|
00277A88 0059:
|
|
??_C@_0FJ@HDIOHFBC@?$CIdisplayed_item_index?$FLi?$FN?$DO?$DN0?$CJ?5?$CG?$CG?5@ (0000)
|
|
00277AE8 004d:
|
|
??_C@_0EN@KBJCFCDK@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277B38 0047:
|
|
??_C@_0EH@BMDDKENI@expected?5a?5container?5widget?5for?5@ (0000)
|
|
00277B80 0046:
|
|
??_C@_0EG@BILAIBJ@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277BC8 003e:
|
|
??_C@_0DO@GFLPMCBB@expected?53?5children?5in?5solo?5leve@ (0000)
|
|
00277C08 003b:
|
|
??_C@_0DL@JGGBBFAD@expected?53?5children?5?$CIlist?5items?$CJ@ (0000)
|
|
00277C44 0032:
|
|
??_C@_0DC@NCJBNPIM@expected?5a?5spinner?5list?5for?5?8lev@ (0000)
|
|
00277C78 0045:
|
|
??_C@_0EF@FMFFIBMC@ui?2shell?2main_menu?2player_profil@ (0000)
|
|
00277CC0 0048:
|
|
??_C@_0EI@ELIPCFPI@expected?53?5children?5in?5multiplay@ (0000)
|
|
00277D08 004a:
|
|
??_C@_0EK@HCEDFOBE@expected?53?5children?5?$CIlist?5items?$CJ@ (0000)
|
|
00277D58 0041:
|
|
??_C@_0EB@FBEKHKKG@expected?5a?5spinner?5list?5for?5?8mul@ (0000)
|
|
00277D9C 002b:
|
|
??_C@_0CL@JILCPJHH@ui?2shell?2strings?2game_variant_de@ (0000)
|
|
00277DC8 002e:
|
|
??_C@_0CO@INDPLGAP@ui?2shell?2strings?2default_player_@ (0000)
|
|
00277DF8 0037:
|
|
??_C@_0DH@NLJJIMJD@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277E30 0032:
|
|
??_C@_0DC@JNCAIEDE@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277E68 004c:
|
|
??_C@_0EM@BLNIGFHJ@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277EB4 003d:
|
|
??_C@_0DN@HCKJKMCH@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277EF4 003c:
|
|
??_C@_0DM@MHGJENJN@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277F30 0037:
|
|
??_C@_0DH@MMEDOPKB@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277F68 0039:
|
|
??_C@_0DJ@ONHHKFOO@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00277FA4 003f:
|
|
??_C@_0DP@NCMBAOPB@expected?5a?5container?5widget?5for?5@ (0000)
|
|
00277FE4 003a:
|
|
??_C@_0DK@BBPFDPKF@expected?5a?5container?5widget?5for?5@ (0000)
|
|
00278020 002c:
|
|
??_C@_0CM@DEIEIGNN@expected?5a?5text?5box?5widget?5for?5p@ (0000)
|
|
0027804C 0033:
|
|
??_C@_0DD@FHDLHMLN@expected?5profile?5item?5descriptio@ (0000)
|
|
00278080 0045:
|
|
??_C@_0EF@EGDOMIGB@expected?53?5children?5?$CIlist?5items?$CJ@ (0000)
|
|
002780C8 003c:
|
|
??_C@_0DM@DDPGFGBL@expected?5a?5spinner?5list?5for?5?8pla@ (0000)
|
|
00278108 0048:
|
|
??_C@_0EI@EBGMHFNB@ui?2shell?2main_menu?2player_profil@ (0000)
|
|
00278150 004a:
|
|
??_C@_0EK@KOGGNIM@ui?2shell?2main_menu?2player_profil@ (0000)
|
|
0027819C 0010:
|
|
??_C@_1BA@KGLKGBLH@?$AA?$CF?$AAs?$AA?$CF?$AAh?$AAs?$AA?$CF?$AAs?$AA?$AA@ (0000)
|
|
002781B0 0047:
|
|
??_C@_0EH@KIGMJNHF@ui?2shell?2main_menu?2player_profil@ (0000)
|
|
002781F8 004d:
|
|
??_C@_0EN@HFOKHEMO@ui?2shell?2main_menu?2player_profil@ (0000)
|
|
00278248 0018:
|
|
??_C@_0BI@NPNPHOJO@invalid?5list?5item?5index?$AA@ (0000)
|
|
00278260 0034:
|
|
??_C@_0DE@PLLADONH@qtr?9screen?5profile?5list?5has?5inva@ (0000)
|
|
00278298 0074:
|
|
??_C@_0HE@COKMIIBF@expected?5qtr?9screen?5profile?5sele@ (0000)
|
|
00278310 004c:
|
|
??_C@_0EM@MHFANJGA@expected?50?5children?5?$CI1?9wide?5spin@ (0000)
|
|
0027835C 003f:
|
|
??_C@_0DP@KPGPKHEI@expected?5a?5spinner?5list?5for?5?8mp?5@ (0000)
|
|
002783A0 004c:
|
|
??_C@_0EM@HDAEPJAF@expected?5qtr?9screen?5profile?5sele@ (0000)
|
|
002783F0 0049:
|
|
??_C@_0EJ@GDOHFLDE@expected?5a?5container?5widget?5for?5@ (0000)
|
|
00278440 0048:
|
|
??_C@_0EI@LGHFKCIE@expected?5a?5text?5box?5widget?5for?5t@ (0000)
|
|
00278488 0041:
|
|
??_C@_0EB@BNHDKAMN@expected?52?5children?5in?5player?5co@ (0000)
|
|
002784D0 0042:
|
|
??_C@_0EC@LDEDNGKC@expected?53?5children?5?$CIlist?5items?$CJ@ (0000)
|
|
00278514 0039:
|
|
??_C@_0DJ@CBCMOOFM@expected?5a?5spinner?5list?5for?5?8pla@ (0000)
|
|
00278550 002c:
|
|
??_C@_0CM@CMCNFHCF@no?5list?5items?5associated?5with?5co@ (0000)
|
|
00306288 00a4:
|
|
_data_00306288 (0000)
|
|
00454C60 00a8:
|
|
_bss_00454c60 (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries/cseries.h"
|
|
#include "cseries/cseries_windows.h"
|
|
#include "cseries/errors.h"
|
|
#include "bungie_net/network/transport.h"
|
|
#include "interface/ui_widget.h"
|
|
#include "interface/ui_widget_definitions.h"
|
|
#include "interface/ui_widget_game_data_input_functions.h"
|
|
#include "interface/hud_messaging.h"
|
|
#include "interface/player_ui.h"
|
|
#include "game/game_engine.h"
|
|
#include "game/players.h"
|
|
#include "main/main.h"
|
|
#include "networking/network_client_manager.h"
|
|
#include "networking/network_game_globals.h"
|
|
#include "networking/network_game_manager.h"
|
|
#include "networking/network_messages.h"
|
|
#include "saved games/player_profile.h"
|
|
#include "saved games/playlist_profile.h"
|
|
#include "text/text_group.h"
|
|
#include "text/unicode.h"
|
|
#include "custom_edition_maps.h" /* port: port/linux/game/custom_edition_maps.c */
|
|
#include "halo_menus.h" /* port: PC_MENU_FUNCTION_BASE */
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
_ui_widget_type_bitmap = 0,
|
|
_ui_widget_type_text_box,
|
|
_ui_widget_type_spinner_list,
|
|
_ui_widget_type_column_list,
|
|
};
|
|
|
|
enum
|
|
{
|
|
/* the native builds' session limit (port/linux/include/halo_port_limits.h) */
|
|
MAXIMUM_NETWORK_MACHINE_COUNT = HALO_PORT_MAXIMUM_NETWORK_MACHINES,
|
|
MAXIMUM_NETWORK_ADVERTISED_GAMES = 9,
|
|
};
|
|
|
|
enum
|
|
{
|
|
/* the networked pregame screen has panels for the local machine and three
|
|
remote machines, fewer than the native builds' sessions can hold */
|
|
NUMBER_OF_REMOTE_MACHINE_PANELS = 3,
|
|
};
|
|
|
|
enum network_game_platform
|
|
{
|
|
_network_game_platform_xbox,
|
|
_network_game_platform_pc,
|
|
NUMBER_OF_NETWORK_GAME_PLATFORMS,
|
|
};
|
|
|
|
enum multiplayer_game_text_string
|
|
{
|
|
_multiplayer_game_text_string_capture_the_flag = 3,
|
|
_multiplayer_game_text_string_slayer,
|
|
_multiplayer_game_text_string_oddball,
|
|
_multiplayer_game_text_string_king_of_the_hill,
|
|
_multiplayer_game_text_string_race,
|
|
_multiplayer_game_text_string_unknown_game_type,
|
|
_multiplayer_game_text_string_captures = 22,
|
|
_multiplayer_game_text_string_minutes,
|
|
_multiplayer_game_text_string_frags,
|
|
_multiplayer_game_text_string_laps,
|
|
_multiplayer_game_text_string_teams_ready,
|
|
_multiplayer_game_text_string_waiting_for_teams,
|
|
_multiplayer_game_text_string_single_flag_assault = 28,
|
|
_multiplayer_game_text_string_assault,
|
|
_multiplayer_game_text_string_single_flag_ctf,
|
|
_multiplayer_game_text_string_reverse_tag,
|
|
_multiplayer_game_text_string_juggernaut,
|
|
_multiplayer_game_text_string_rally,
|
|
_multiplayer_game_text_string_waiting_for_machine = 34,
|
|
_multiplayer_game_text_string_waiting_for_player,
|
|
};
|
|
|
|
enum multiplayer_game_bitmap_frame
|
|
{
|
|
_multiplayer_game_bitmap_ctf = 0,
|
|
_multiplayer_game_bitmap_king,
|
|
_multiplayer_game_bitmap_slayer,
|
|
_multiplayer_game_bitmap_oddball,
|
|
_multiplayer_game_bitmap_race,
|
|
_multiplayer_game_bitmap_unknown,
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
/* Same TU-local definition as network_client_manager.c, network_game_manager.c,
|
|
network_server_manager.c and network_server_message_handler.c; no shared header
|
|
owns it. January assertion strings in those objects preserve the macro name. */
|
|
/* widened: a char machine index is always below the native builds' 128
|
|
machines, and clang warns about the always-true char comparison */
|
|
#define network_machine_is_valid(machine) \
|
|
((machine) && (machine)->machine_index >= 0 && \
|
|
(long)(machine)->machine_index < MAXIMUM_NETWORK_MACHINE_COUNT)
|
|
|
|
/* ---------- structures */
|
|
|
|
struct ui_widget_text_box_parameters
|
|
{
|
|
wchar_t *text;
|
|
short string_list_index;
|
|
byte padding06[0x0E];
|
|
};
|
|
|
|
struct ui_widget_list_parameters
|
|
{
|
|
short selected_list_item_index;
|
|
short list_item_top_index;
|
|
void *list_items;
|
|
word number_of_items;
|
|
word padding0E;
|
|
struct widget_instance *extended_description;
|
|
wchar_t *item_text;
|
|
};
|
|
|
|
union ui_widget_parameters
|
|
{
|
|
struct ui_widget_text_box_parameters text_box;
|
|
struct ui_widget_list_parameters list;
|
|
};
|
|
|
|
struct ui_widget_animation_data
|
|
{
|
|
short current_frame_index;
|
|
short first_frame_index;
|
|
short last_frame_index;
|
|
short number_of_sprite_frames;
|
|
};
|
|
|
|
struct widget_instance
|
|
{
|
|
long definition_tag_index;
|
|
char const *name;
|
|
short local_player_index;
|
|
short horizontal_offset;
|
|
short vertical_offset;
|
|
short type;
|
|
boolean visible;
|
|
boolean render_regardless_of_controller_index;
|
|
boolean never_receive_events;
|
|
boolean pause_game_time;
|
|
boolean delete_recursion_lock;
|
|
boolean error_dialog;
|
|
boolean close_if_local_player_controller_present;
|
|
byte padding17;
|
|
unsigned long creation_time;
|
|
unsigned long milliseconds_to_auto_close;
|
|
unsigned long auto_close_fade_time;
|
|
real alpha_modifier;
|
|
struct widget_instance *previous;
|
|
struct widget_instance *next;
|
|
struct widget_instance *parent;
|
|
struct widget_instance *child;
|
|
struct widget_instance *focused_child;
|
|
union ui_widget_parameters parameters;
|
|
struct ui_widget_animation_data animation;
|
|
};
|
|
|
|
struct network_advertised_game
|
|
{
|
|
byte padding00[0x30];
|
|
wchar_t game_name[16];
|
|
long padding50;
|
|
char map_name[0x80];
|
|
short engine_type;
|
|
short machine_count;
|
|
word player_count;
|
|
short maximum_player_count;
|
|
short score_limit;
|
|
short platform;
|
|
boolean open;
|
|
boolean valid;
|
|
boolean has_teams;
|
|
boolean oddball_variant;
|
|
};
|
|
|
|
typedef char network_advertised_game_size_assert[
|
|
sizeof(struct network_advertised_game) == 0xE4 ? 1 : -1];
|
|
typedef char network_advertised_game_game_name_offset_assert[
|
|
offsetof(struct network_advertised_game, game_name) == 0x30 ? 1 : -1];
|
|
typedef char network_advertised_game_engine_type_offset_assert[
|
|
offsetof(struct network_advertised_game, engine_type) == 0xD4 ? 1 : -1];
|
|
typedef char network_advertised_game_platform_offset_assert[
|
|
offsetof(struct network_advertised_game, platform) == 0xDE ? 1 : -1];
|
|
typedef char network_machine_size_assert[
|
|
sizeof(struct network_machine) == 0x44 ? 1 : -1];
|
|
/* the native builds' session limits move the players; every copy of the
|
|
record is checked against port/linux/include/halo_port_limits.h (this one
|
|
declares it only up to the players) */
|
|
typedef char network_game_players_offset_assert[
|
|
offsetof(struct network_game, players) == HALO_PORT_NETWORK_GAME_PLAYERS_OFFSET ? 1 : -1];
|
|
typedef char network_game_players_end_assert[
|
|
offsetof(struct network_game, players) + sizeof(((struct network_game *)0)->players) ==
|
|
HALO_PORT_NETWORK_GAME_PLAYERS_END ? 1 : -1];
|
|
typedef char network_game_size_assert[
|
|
sizeof(struct network_game) <= HALO_PORT_NETWORK_GAME_SIZE ? 1 : -1];
|
|
|
|
struct playlist_profile
|
|
{
|
|
wchar_t name[12];
|
|
enum game_engine_type engine_type;
|
|
boolean teams;
|
|
byte padding1D[0x47];
|
|
word flags;
|
|
byte padding66[2];
|
|
};
|
|
|
|
struct persistent_game_data_info_view
|
|
{
|
|
char map_name[0x100];
|
|
short difficulty;
|
|
byte map_index;
|
|
boolean valid;
|
|
boolean corrupted;
|
|
};
|
|
|
|
struct single_player_level_entry
|
|
{
|
|
char const *map_name;
|
|
boolean available;
|
|
boolean completion_marker;
|
|
boolean difficulty_marker;
|
|
boolean cooperative_marker;
|
|
};
|
|
|
|
struct cached_player_profile_entry
|
|
{
|
|
long profile_index;
|
|
struct player_profile profile;
|
|
};
|
|
|
|
struct cached_variant_profile_entry
|
|
{
|
|
long profile_index;
|
|
struct playlist_profile profile;
|
|
};
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static int list_indices_sort_proc(
|
|
void const *index1,
|
|
void const *index2);
|
|
static void spinner_list_3wide_determine_displayed_item_indices(
|
|
struct widget_instance *list_widget,
|
|
long *displayed_item_indices);
|
|
static long filter_invalid_list_indices(
|
|
long *indices,
|
|
long number_of_items);
|
|
static void widget_function_null(
|
|
struct widget_instance *widget);
|
|
static void settings_menu_update_extended_description(
|
|
struct widget_instance *widget);
|
|
static void playlist_settings_menu_update_extended_description(
|
|
struct widget_instance *widget);
|
|
static void playlist_gametype_select_menu_update_extended_description(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_type_menu_update_extended_description(
|
|
struct widget_instance *widget);
|
|
static void solo_level_select_list_update_displayed_items(
|
|
struct widget_instance *widget);
|
|
static void difficulty_select_menu_update_extended_description(
|
|
struct widget_instance *widget);
|
|
static void set_textbox_to_build_number(
|
|
struct widget_instance *widget);
|
|
static void server_list_menu_update(
|
|
struct widget_instance *widget);
|
|
static void network_pregame_status_screen_update(
|
|
struct widget_instance *widget);
|
|
static void splitscreen_pregame_status_screen_update(
|
|
struct widget_instance *widget);
|
|
static void netgame_prejoin_players(
|
|
struct widget_instance *widget);
|
|
static void mutliplayer_settings_select_list_update_displayed_items(
|
|
struct widget_instance *widget);
|
|
static void player_profile_3wide_list_update(
|
|
struct widget_instance *widget);
|
|
static void player_profile_edit_select_menu_update_extended_description(
|
|
struct widget_instance *widget);
|
|
static void player_profile_1wide_list_update(
|
|
struct widget_instance *widget);
|
|
static void solo_game_objective_text(
|
|
struct widget_instance *widget);
|
|
static void player_profile_color_picker_update(
|
|
struct widget_instance *widget);
|
|
static void main_menu_animation_fakery(
|
|
struct widget_instance *widget);
|
|
static void mp_level_select_list_update_displayed_items(
|
|
struct widget_instance *widget);
|
|
static void get_active_player_profile_display_name(
|
|
struct widget_instance *widget);
|
|
static void get_editable_player_profile_display_name(
|
|
struct widget_instance *widget);
|
|
static void get_editable_playlist_profile_display_name(
|
|
struct widget_instance *widget);
|
|
static void get_active_player_profile_color_index(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_text_box_for_map_name(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_text_box_for_game_ruleset(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_text_box_for_teams_noteams(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_text_box_for_score_limit(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_text_box_for_score_limit_type(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_bitmap_for_map(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_bitmap_for_ruleset(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_set_text_box_for_number_of_players(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_edit_profile_set_ruleset_textbox_string_index(
|
|
struct widget_instance *widget);
|
|
static void system_link_status_check(
|
|
struct widget_instance *widget);
|
|
static void multiplayer_game_directions(
|
|
struct widget_instance *widget);
|
|
static void teams_no_teams_mp_game_bitmap_update(
|
|
struct widget_instance *widget);
|
|
static void warn_if_difficulty_will_nuke_saved_game(
|
|
struct widget_instance *widget);
|
|
static void dim_if_no_system_link_cable(
|
|
struct widget_instance *widget);
|
|
|
|
/* port: ui_widget.c's and port/linux/game/menu_tags.c's */
|
|
short ui_widget_port_list_index(
|
|
struct widget_instance *list_widget);
|
|
boolean pc_menu_tag(
|
|
long tag_index);
|
|
|
|
/* ---------- globals */
|
|
|
|
static ui_widget_game_data_function game_data_input_function_list[41];
|
|
|
|
extern struct persistent_game_data_info_view persistant_game_data_info;
|
|
extern struct single_player_level_entry single_player_level_data[10];
|
|
extern struct cached_player_profile_entry cached_player_profile[3];
|
|
extern struct cached_variant_profile_entry cached_variant_profile[3];
|
|
|
|
/* Controller-color bitmap frame indices for each local player, selected by
|
|
team. The first table is ordered [no teams, team 1, team 0] for the networked
|
|
pregame screen; the second is [no teams, team 0, team 1] for splitscreen. */
|
|
static byte const local_player_controller_bitmap_frames[2][MAXIMUM_LOCAL_PLAYERS][3] =
|
|
{
|
|
{{3, 4, 5}, {6, 7, 8}, {9, 10, 11}, {12, 13, 14}},
|
|
{{3, 5, 4}, {6, 8, 7}, {9, 11, 10}, {12, 14, 13}}
|
|
};
|
|
|
|
/* port: the display index of a Custom Edition multiplayer map this machine
|
|
has, which the menus show by its own name and picture even when its name
|
|
holds an Xbox level's (port/linux/game/custom_edition_maps.c), or NONE */
|
|
static short custom_edition_map_display_index(
|
|
char const *map_name)
|
|
{
|
|
short display_index = custom_edition_maps_display_index(map_name);
|
|
|
|
return display_index != NONE && !custom_edition_maps_campaign(display_index) ? display_index : NONE;
|
|
}
|
|
|
|
/* ---------- public code */
|
|
|
|
void ui_widget_game_data_function_invoke(
|
|
struct widget_instance *widget,
|
|
word function)
|
|
{
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x10A,
|
|
widget);
|
|
|
|
/* port: the menus' own functions (port/linux/game/menu_functions.c) */
|
|
if (function >= PC_MENU_FUNCTION_BASE && function < 0x8000)
|
|
{
|
|
extern void pc_menu_game_data_function_invoke(struct widget_instance *widget, long function);
|
|
|
|
pc_menu_game_data_function_invoke(widget, function - PC_MENU_FUNCTION_BASE);
|
|
return;
|
|
}
|
|
if ((short)function >= 0 && function < NUMBEROF(game_data_input_function_list))
|
|
{
|
|
game_data_input_function_list[(short)function](widget);
|
|
return;
|
|
}
|
|
|
|
error(2, "invalid game_data_input_reference_function");
|
|
return;
|
|
}
|
|
|
|
static void widget_function_null(
|
|
struct widget_instance *widget)
|
|
{
|
|
(void)widget;
|
|
return;
|
|
}
|
|
|
|
static void settings_menu_update_extended_description(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct ui_widget_definition *description_definition = ui_widget_definition_get(
|
|
list_widget->parameters.list.extended_description->definition_tag_index);
|
|
struct widget_instance *description_picture;
|
|
struct widget_instance *description_text;
|
|
struct widget_instance *child;
|
|
short index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x12C,
|
|
list_widget->focused_child && list_widget->parameters.list.extended_description,
|
|
"invalid widget trying to update its extended list description");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x12D,
|
|
description_definition->child_count == 2,
|
|
"this doesn't look like the settings select widget to me");
|
|
|
|
description_picture = list_widget->parameters.list.extended_description->child;
|
|
description_text = description_picture->next;
|
|
/* port: in the PC version's lists (port/assets/menus), the item's number
|
|
among those that take events, as its game counts them (past its labels) */
|
|
index = ui_widget_port_list_index(list_widget);
|
|
|
|
if (index != NONE)
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x138,
|
|
description_picture->type == _ui_widget_type_bitmap,
|
|
"expected a container widget for the settings select list extended description pic");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x139,
|
|
description_text->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the settings select list extended description text");
|
|
|
|
description_picture->animation.current_frame_index = index;
|
|
description_text->parameters.text_box.string_list_index = index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void playlist_settings_menu_update_extended_description(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct widget_instance *child;
|
|
struct widget_instance *description_child;
|
|
struct ui_widget_definition *description_definition;
|
|
short index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x14D,
|
|
list_widget && list_widget->focused_child && list_widget->parameters.list.extended_description,
|
|
"invalid widget trying to update its extended list description");
|
|
|
|
/* port: in the PC version's lists (port/assets/menus), the item's number
|
|
among those that take events, as its game counts them (past its labels) */
|
|
index = ui_widget_port_list_index(list_widget);
|
|
|
|
if (index != NONE)
|
|
{
|
|
description_definition = ui_widget_definition_get(
|
|
list_widget->parameters.list.extended_description->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x15B,
|
|
description_definition->child_count == 2,
|
|
"expected a container widget w/ 2 children for the playlist settings list extended description");
|
|
|
|
description_child = list_widget->parameters.list.extended_description->child;
|
|
description_child->parameters.text_box.string_list_index = index;
|
|
description_child->next->animation.current_frame_index = index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void playlist_gametype_select_menu_update_extended_description(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct widget_instance *child;
|
|
struct widget_instance *description_child;
|
|
struct ui_widget_definition *description_definition;
|
|
short index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x173,
|
|
list_widget && list_widget->focused_child && list_widget->parameters.list.extended_description,
|
|
"invalid widget trying to update its extended list description");
|
|
|
|
/* port: in the PC version's lists (port/assets/menus), the item's number
|
|
among those that take events, as its game counts them (past its labels) */
|
|
index = ui_widget_port_list_index(list_widget);
|
|
|
|
if (index != NONE)
|
|
{
|
|
description_definition = ui_widget_definition_get(
|
|
list_widget->parameters.list.extended_description->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x181,
|
|
description_definition->child_count == 2,
|
|
"expected a container widget w/ 2 children for the playlist settings list extended description");
|
|
|
|
description_child = list_widget->parameters.list.extended_description->child;
|
|
description_child->parameters.text_box.string_list_index = index;
|
|
description_child->next->animation.current_frame_index = index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_type_menu_update_extended_description(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct widget_instance *child;
|
|
short index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x1A6,
|
|
list_widget && list_widget->focused_child &&
|
|
list_widget->parameters.list.extended_description &&
|
|
list_widget->parameters.list.extended_description->child &&
|
|
list_widget->parameters.list.extended_description->child->next,
|
|
"invalid widget trying to update its extended list description");
|
|
|
|
/* port: in the PC version's lists (port/assets/menus), the item's number
|
|
among those that take events, as its game counts them (past its labels) */
|
|
index = ui_widget_port_list_index(list_widget);
|
|
|
|
if (index != NONE)
|
|
{
|
|
list_widget->parameters.list.extended_description->child->
|
|
animation.current_frame_index = index;
|
|
list_widget->parameters.list.extended_description->child->next->
|
|
parameters.text_box.string_list_index = index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void difficulty_select_menu_update_extended_description(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct ui_widget_definition *description_definition = ui_widget_definition_get(
|
|
list_widget->parameters.list.extended_description->definition_tag_index);
|
|
struct widget_instance *description_picture;
|
|
struct widget_instance *description_text;
|
|
struct widget_instance *child;
|
|
short index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x237,
|
|
list_widget->focused_child && list_widget->parameters.list.extended_description,
|
|
"invalid widget trying to update its extended list description");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x238,
|
|
/* port: the PC version's (port/assets/menus) has the profile's name too */
|
|
description_definition->child_count == 2 ||
|
|
(description_definition->child_count == 3 && pc_menu_tag(list_widget->definition_tag_index)),
|
|
"this doesn't look like the difficulty select widget to me");
|
|
|
|
description_picture = list_widget->parameters.list.extended_description->child;
|
|
description_text = description_picture->next;
|
|
/* port: in the PC version's lists, among the items that take events; its
|
|
buttons (past its four difficulties) leave the last one shown, which its
|
|
OK button then sets (port/linux/game/menu_functions.c) */
|
|
index = ui_widget_port_list_index(list_widget);
|
|
if (pc_menu_tag(list_widget->definition_tag_index) && index >= 4)
|
|
index = NONE;
|
|
|
|
if (index != NONE)
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x243,
|
|
description_picture->type == _ui_widget_type_bitmap,
|
|
"expected a container widget for the difficulty list extended description pic");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x244,
|
|
description_text->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the difficulty list extended description text");
|
|
|
|
description_picture->animation.current_frame_index = index;
|
|
description_text->parameters.text_box.string_list_index = index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void server_list_menu_update(
|
|
struct widget_instance *widget)
|
|
{
|
|
/* Name, nine-element size and function scope from the 2003 PC demo PDB and the HCEX PDB (static
|
|
local of server_list_menu_update; their element type is named advertised_game_data). Neither
|
|
PDB records the block: placing it at the top of the function is unattested. January
|
|
corroborates: .bss +0, referenced only by this function. */
|
|
static struct network_advertised_game *displayed_servers[MAXIMUM_NETWORK_ADVERTISED_GAMES];
|
|
struct network_game_client *client = global_network_game_client_get();
|
|
long displayed_server_count = 0;
|
|
|
|
csmemset(
|
|
displayed_servers,
|
|
0,
|
|
MAXIMUM_NETWORK_ADVERTISED_GAMES * sizeof(*displayed_servers));
|
|
if (client)
|
|
{
|
|
struct ui_widget_definition *definition = ui_widget_definition_get(
|
|
widget->definition_tag_index);
|
|
struct network_advertised_game *available_games =
|
|
network_game_client_get_available_games(client);
|
|
struct widget_instance *item;
|
|
unsigned long milliseconds_since_creation;
|
|
long game_index;
|
|
long item_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x297,
|
|
definition->type == _ui_widget_type_column_list &&
|
|
definition->child_count == 9,
|
|
"this doesn't look like the net game server list widget");
|
|
|
|
for (game_index = 0;
|
|
game_index < MAXIMUM_NETWORK_ADVERTISED_GAMES;
|
|
game_index++)
|
|
{
|
|
if (network_game_client_advertised_game_is_valid(&available_games[game_index]) &&
|
|
available_games[game_index].platform == _network_game_platform_xbox &&
|
|
available_games[game_index].open)
|
|
{
|
|
displayed_servers[displayed_server_count] = &available_games[game_index];
|
|
displayed_server_count++;
|
|
}
|
|
}
|
|
|
|
for (game_index = 0;
|
|
game_index < MAXIMUM_NETWORK_ADVERTISED_GAMES;
|
|
game_index++)
|
|
{
|
|
if (network_game_client_advertised_game_is_valid(&available_games[game_index]) &&
|
|
available_games[game_index].platform == _network_game_platform_xbox &&
|
|
!available_games[game_index].open)
|
|
{
|
|
displayed_servers[displayed_server_count] = &available_games[game_index];
|
|
displayed_server_count++;
|
|
}
|
|
}
|
|
|
|
widget->parameters.list.list_items = displayed_servers;
|
|
widget->parameters.list.number_of_items = (word)displayed_server_count;
|
|
widget->parameters.list.selected_list_item_index = (short)CEILING(
|
|
widget->parameters.list.selected_list_item_index,
|
|
displayed_server_count - 1);
|
|
|
|
for (item = widget->child, item_index = 0;
|
|
item && item_index < displayed_server_count;
|
|
item = item->next, item_index++)
|
|
{
|
|
item->parameters.text_box.text = ui_widget_realloc(
|
|
item->parameters.text_box.text,
|
|
0x40,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x2C5);
|
|
if (item->parameters.text_box.text)
|
|
{
|
|
if (displayed_servers[item_index]->open == TRUE)
|
|
{
|
|
ustrncpy(
|
|
item->parameters.text_box.text,
|
|
displayed_servers[item_index]->game_name,
|
|
0x1F);
|
|
}
|
|
else
|
|
{
|
|
long text_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\multiplayer_game_text");
|
|
wchar_t const *closed_game_prefix =
|
|
unicode_string_list_get_string(text_tag_index, 19);
|
|
|
|
usnprintf(
|
|
item->parameters.text_box.text,
|
|
0x1F,
|
|
L"%s %s",
|
|
closed_game_prefix,
|
|
displayed_servers[item_index]->game_name);
|
|
}
|
|
item->parameters.text_box.text[0x1F] = 0;
|
|
}
|
|
}
|
|
|
|
if (displayed_server_count > 0 &&
|
|
widget->parameters.list.selected_list_item_index < 0)
|
|
{
|
|
widget->parameters.list.selected_list_item_index = 0;
|
|
}
|
|
|
|
milliseconds_since_creation = system_milliseconds() - widget->creation_time;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x2F7,
|
|
ui_widget_definition_get(
|
|
widget->parameters.list.extended_description->definition_tag_index)->child_count == 5,
|
|
"this doesn't look like the server list extended description widget");
|
|
|
|
{
|
|
struct widget_instance *game_type_bitmap =
|
|
widget->parameters.list.extended_description->child;
|
|
struct widget_instance *map_bitmap = game_type_bitmap->next;
|
|
struct widget_instance *description_container = map_bitmap->next;
|
|
struct widget_instance *message_text = description_container->next;
|
|
struct widget_instance *open_closed_text = description_container->child;
|
|
struct widget_instance *map_name_text;
|
|
struct widget_instance *ruleset_text;
|
|
struct widget_instance *teams_text;
|
|
struct widget_instance *number_of_players_text;
|
|
struct widget_instance *score_limit_text;
|
|
struct widget_instance *score_limit_type_text;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x2FF,
|
|
open_closed_text && open_closed_text->type == _ui_widget_type_text_box,
|
|
"expected 'open/closed game' textbox");
|
|
map_name_text = open_closed_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x301,
|
|
map_name_text && map_name_text->type == _ui_widget_type_text_box,
|
|
"expected 'map name' textbox");
|
|
ruleset_text = map_name_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x303,
|
|
ruleset_text && ruleset_text->type == _ui_widget_type_text_box,
|
|
"expected 'ruleset' textbox");
|
|
teams_text = ruleset_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x305,
|
|
teams_text && teams_text->type == _ui_widget_type_text_box,
|
|
"expected 'teams on/off' textbox");
|
|
number_of_players_text = teams_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x307,
|
|
number_of_players_text &&
|
|
number_of_players_text->type == _ui_widget_type_text_box,
|
|
"expected 'number of players' textbox");
|
|
score_limit_text = number_of_players_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x309,
|
|
score_limit_text && score_limit_text->type == _ui_widget_type_text_box,
|
|
"expected 'score limit' textbox");
|
|
score_limit_type_text = score_limit_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x30B,
|
|
score_limit_type_text &&
|
|
score_limit_type_text->type == _ui_widget_type_text_box,
|
|
"expected 'score limit type' textbox");
|
|
|
|
if (widget->parameters.list.selected_list_item_index >= 0)
|
|
{
|
|
struct network_advertised_game *server = displayed_servers[
|
|
widget->parameters.list.selected_list_item_index];
|
|
char const *map_name;
|
|
|
|
switch (server->engine_type)
|
|
{
|
|
case game_engine_ctf:
|
|
game_type_bitmap->animation.current_frame_index =
|
|
_multiplayer_game_bitmap_ctf;
|
|
break;
|
|
case game_engine_slayer:
|
|
game_type_bitmap->animation.current_frame_index =
|
|
_multiplayer_game_bitmap_slayer;
|
|
break;
|
|
case game_engine_oddball:
|
|
game_type_bitmap->animation.current_frame_index =
|
|
_multiplayer_game_bitmap_oddball;
|
|
break;
|
|
case game_engine_king:
|
|
game_type_bitmap->animation.current_frame_index =
|
|
_multiplayer_game_bitmap_king;
|
|
break;
|
|
case game_engine_race:
|
|
game_type_bitmap->animation.current_frame_index =
|
|
_multiplayer_game_bitmap_race;
|
|
break;
|
|
default:
|
|
game_type_bitmap->animation.current_frame_index =
|
|
_multiplayer_game_bitmap_unknown;
|
|
break;
|
|
}
|
|
|
|
map_name = server->map_name;
|
|
if (strstr(map_name, "beavercreek"))
|
|
map_bitmap->animation.current_frame_index = 0;
|
|
else if (strstr(map_name, "sidewinder"))
|
|
map_bitmap->animation.current_frame_index = 1;
|
|
else if (strstr(map_name, "damnation"))
|
|
map_bitmap->animation.current_frame_index = 2;
|
|
else if (strstr(map_name, "ratrace"))
|
|
map_bitmap->animation.current_frame_index = 3;
|
|
else if (strstr(map_name, "prisoner"))
|
|
map_bitmap->animation.current_frame_index = 4;
|
|
else if (strstr(map_name, "hangemhigh"))
|
|
map_bitmap->animation.current_frame_index = 5;
|
|
else if (strstr(map_name, "chillout"))
|
|
map_bitmap->animation.current_frame_index = 6;
|
|
else if (strstr(map_name, "carousel"))
|
|
map_bitmap->animation.current_frame_index = 7;
|
|
else if (strstr(map_name, "boardingaction"))
|
|
map_bitmap->animation.current_frame_index = 8;
|
|
else if (strstr(map_name, "bloodgulch"))
|
|
map_bitmap->animation.current_frame_index = 9;
|
|
else if (strstr(map_name, "wizard"))
|
|
map_bitmap->animation.current_frame_index = 10;
|
|
else if (strstr(map_name, "putput"))
|
|
map_bitmap->animation.current_frame_index = 11;
|
|
else if (strstr(map_name, "longest"))
|
|
map_bitmap->animation.current_frame_index = 12;
|
|
else
|
|
map_bitmap->animation.current_frame_index = 13;
|
|
/* port: a Custom Edition map shows its own name and picture */
|
|
if (custom_edition_map_display_index(map_name) != NONE)
|
|
map_bitmap->animation.current_frame_index = custom_edition_map_display_index(map_name);
|
|
|
|
open_closed_text->parameters.text_box.string_list_index =
|
|
(server->open == TRUE) ? 20 : 21;
|
|
map_name_text->parameters.text_box.string_list_index =
|
|
map_bitmap->animation.current_frame_index;
|
|
|
|
switch (server->engine_type)
|
|
{
|
|
case game_engine_ctf:
|
|
ruleset_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_capture_the_flag;
|
|
break;
|
|
case game_engine_slayer:
|
|
ruleset_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_slayer;
|
|
break;
|
|
case game_engine_oddball:
|
|
ruleset_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_oddball;
|
|
break;
|
|
case game_engine_king:
|
|
ruleset_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_king_of_the_hill;
|
|
break;
|
|
case game_engine_race:
|
|
ruleset_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_race;
|
|
break;
|
|
default:
|
|
ruleset_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_unknown_game_type;
|
|
break;
|
|
}
|
|
|
|
teams_text->parameters.text_box.string_list_index =
|
|
(server->has_teams == TRUE) ? 12 : 13;
|
|
|
|
number_of_players_text->parameters.text_box.text = ui_widget_realloc(
|
|
number_of_players_text->parameters.text_box.text,
|
|
8,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x364);
|
|
if (number_of_players_text->parameters.text_box.text)
|
|
{
|
|
/* room for a three-digit count: the Linux runtime's
|
|
_vsnwprintf writes its terminator inside the count */
|
|
usnprintf(
|
|
number_of_players_text->parameters.text_box.text,
|
|
4,
|
|
L"%d",
|
|
server->player_count);
|
|
number_of_players_text->parameters.text_box.text[3] = 0;
|
|
}
|
|
|
|
score_limit_text->parameters.text_box.text = ui_widget_realloc(
|
|
score_limit_text->parameters.text_box.text,
|
|
8,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x369);
|
|
if (score_limit_text->parameters.text_box.text)
|
|
{
|
|
usnprintf(
|
|
score_limit_text->parameters.text_box.text,
|
|
3,
|
|
L"%d",
|
|
server->score_limit);
|
|
score_limit_text->parameters.text_box.text[3] = 0;
|
|
}
|
|
|
|
switch (server->engine_type)
|
|
{
|
|
case game_engine_ctf:
|
|
score_limit_type_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_captures;
|
|
break;
|
|
case game_engine_slayer:
|
|
score_limit_type_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_frags;
|
|
break;
|
|
case game_engine_oddball:
|
|
score_limit_type_text->parameters.text_box.string_list_index =
|
|
(server->oddball_variant == TRUE) ?
|
|
_multiplayer_game_text_string_frags :
|
|
_multiplayer_game_text_string_minutes;
|
|
break;
|
|
case game_engine_king:
|
|
score_limit_type_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_minutes;
|
|
break;
|
|
case game_engine_race:
|
|
score_limit_type_text->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_laps;
|
|
break;
|
|
default:
|
|
score_limit_type_text->parameters.text_box.string_list_index = 1;
|
|
break;
|
|
}
|
|
|
|
message_text->parameters.text_box.string_list_index = 2;
|
|
message_text->visible = FALSE;
|
|
|
|
if (!widget->focused_child)
|
|
{
|
|
widget->parameters.list.selected_list_item_index = 0;
|
|
widget->focused_child = widget->child;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
game_type_bitmap->animation.current_frame_index =
|
|
_multiplayer_game_bitmap_unknown;
|
|
map_bitmap->animation.current_frame_index = 13;
|
|
open_closed_text->parameters.text_box.string_list_index = 1;
|
|
map_name_text->parameters.text_box.string_list_index = 14;
|
|
ruleset_text->parameters.text_box.string_list_index = 1;
|
|
teams_text->parameters.text_box.string_list_index = 1;
|
|
|
|
number_of_players_text->parameters.text_box.text = ui_widget_realloc(
|
|
number_of_players_text->parameters.text_box.text,
|
|
8,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x3A3);
|
|
if (number_of_players_text->parameters.text_box.text)
|
|
number_of_players_text->parameters.text_box.text[0] = 0;
|
|
|
|
score_limit_text->parameters.text_box.text = ui_widget_realloc(
|
|
score_limit_text->parameters.text_box.text,
|
|
8,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x3A7);
|
|
if (score_limit_text->parameters.text_box.text)
|
|
score_limit_text->parameters.text_box.text[0] = 0;
|
|
|
|
score_limit_type_text->parameters.text_box.string_list_index = 1;
|
|
message_text->parameters.text_box.string_list_index =
|
|
(milliseconds_since_creation >= 1000) ? 1 : 0;
|
|
message_text->visible = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void network_pregame_status_screen_update(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game = network_game_get_game();
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x3FC,
|
|
ui_widget_definition_get(widget->definition_tag_index)->child_count == 6,
|
|
"this doesn't look like the net pregame status screen to me");
|
|
|
|
if (game)
|
|
{
|
|
short local_machine_index = network_game_client_get_machine_index(
|
|
global_network_game_client_get());
|
|
struct widget_instance *local_machine_widget = widget->child;
|
|
struct widget_instance *second_machine_widget;
|
|
struct widget_instance *third_machine_widget;
|
|
struct widget_instance *fourth_machine_widget;
|
|
struct widget_instance *status_text;
|
|
struct widget_instance *countdown_text;
|
|
struct widget_instance *machine_name_text;
|
|
struct widget_instance *machine_icon;
|
|
wchar_t const *machine_name;
|
|
long local_player_indices[MAXIMUM_LOCAL_PLAYERS];
|
|
struct widget_instance *player_widgets[MAXIMUM_LOCAL_PLAYERS];
|
|
long local_player_count;
|
|
long machine_index;
|
|
long player_index;
|
|
long local_player_index;
|
|
long length;
|
|
boolean local_machine_found;
|
|
|
|
second_machine_widget = local_machine_widget->next;
|
|
third_machine_widget = second_machine_widget->next;
|
|
fourth_machine_widget = third_machine_widget->next;
|
|
status_text = fourth_machine_widget->next;
|
|
countdown_text = status_text->next;
|
|
|
|
countdown_text->parameters.text_box.text = ui_widget_realloc(
|
|
countdown_text->parameters.text_box.text,
|
|
0x20,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x40B);
|
|
if (countdown_text->parameters.text_box.text)
|
|
{
|
|
short seconds_to_game_start = network_game_client_get_seconds_to_game_start(
|
|
global_network_game_client_get());
|
|
boolean waiting_for_machines = (global_network_game_server_get() &&
|
|
game->machine_count < 2);
|
|
|
|
ustrncpy(countdown_text->parameters.text_box.text, L"-:--", 15);
|
|
status_text->visible = TRUE;
|
|
status_text->parameters.text_box.string_list_index = 0;
|
|
countdown_text->visible = TRUE;
|
|
if (seconds_to_game_start == 0)
|
|
{
|
|
status_text->parameters.text_box.string_list_index = 1;
|
|
countdown_text->visible = FALSE;
|
|
}
|
|
else if (seconds_to_game_start > 0)
|
|
{
|
|
if (seconds_to_game_start < 60)
|
|
{
|
|
usnprintf(
|
|
countdown_text->parameters.text_box.text,
|
|
15,
|
|
L"0:%02d",
|
|
seconds_to_game_start);
|
|
}
|
|
else if (seconds_to_game_start < 3600)
|
|
{
|
|
long minutes = seconds_to_game_start / 60;
|
|
|
|
usnprintf(
|
|
countdown_text->parameters.text_box.text,
|
|
15,
|
|
L"%02d:%02d",
|
|
minutes,
|
|
seconds_to_game_start - minutes * 60);
|
|
}
|
|
else
|
|
{
|
|
long hours = seconds_to_game_start / 3600;
|
|
long minutes = (seconds_to_game_start - hours * 3600) / 60;
|
|
|
|
usnprintf(
|
|
countdown_text->parameters.text_box.text,
|
|
15,
|
|
L"%d:%02d:%02d",
|
|
hours,
|
|
minutes,
|
|
seconds_to_game_start - (hours * 60 + minutes) * 60);
|
|
}
|
|
}
|
|
else if (waiting_for_machines || game->variant.universal_variant.teams == TRUE)
|
|
{
|
|
status_text->visible = FALSE;
|
|
countdown_text->visible = FALSE;
|
|
}
|
|
countdown_text->parameters.text_box.text[15] = 0;
|
|
}
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x44C,
|
|
ui_widget_definition_get(local_machine_widget->definition_tag_index)->child_count == 6,
|
|
"this doesn't look like the net pregame status screen to me");
|
|
|
|
local_machine_found = FALSE;
|
|
machine_name = L"?";
|
|
machine_name_text = local_machine_widget->child;
|
|
machine_icon = machine_name_text->next;
|
|
player_widgets[0] = machine_icon->next;
|
|
player_widgets[1] = player_widgets[0]->next;
|
|
player_widgets[2] = player_widgets[1]->next;
|
|
player_widgets[3] = player_widgets[2]->next;
|
|
|
|
for (machine_index = 0;
|
|
machine_index < MAXIMUM_NETWORK_MACHINE_COUNT;
|
|
machine_index++)
|
|
{
|
|
struct network_machine *machine = &game->machines[machine_index];
|
|
|
|
if (network_machine_is_valid(machine) &&
|
|
machine->machine_index == local_machine_index)
|
|
{
|
|
struct network_machine *local_machine = network_game_client_get_machine(
|
|
global_network_game_client_get());
|
|
|
|
if (local_machine && local_machine->name[0])
|
|
machine_name = local_machine->name;
|
|
local_machine_found = TRUE;
|
|
}
|
|
}
|
|
|
|
csmemset(local_player_indices, NONE, sizeof(local_player_indices));
|
|
local_player_count = 0;
|
|
for (player_index = 0;
|
|
player_index < (long)NUMBEROF(game->players);
|
|
player_index++)
|
|
{
|
|
if (network_player_is_valid(&game->players[player_index]) &&
|
|
game->players[player_index].machine_index == local_machine_index)
|
|
{
|
|
local_player_indices[game->players[player_index].controller_index] = player_index;
|
|
local_player_count++;
|
|
if (local_player_count == MAXIMUM_LOCAL_PLAYERS)
|
|
break;
|
|
}
|
|
}
|
|
|
|
length = ustrlen(machine_name);
|
|
machine_name_text->parameters.text_box.text = ui_widget_realloc(
|
|
machine_name_text->parameters.text_box.text,
|
|
(word)(2 * length + 2),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x47B);
|
|
if (machine_name_text->parameters.text_box.text)
|
|
{
|
|
ustrncpy(machine_name_text->parameters.text_box.text, machine_name, length);
|
|
machine_name_text->parameters.text_box.text[length] = 0;
|
|
}
|
|
machine_icon->animation.current_frame_index = local_machine_found ? 1 : 0;
|
|
|
|
for (local_player_index = 0;
|
|
local_player_index < MAXIMUM_LOCAL_PLAYERS;
|
|
local_player_index++)
|
|
{
|
|
struct widget_instance *controller_bitmap;
|
|
struct widget_instance *name_text;
|
|
struct widget_instance *team_list;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x485,
|
|
ui_widget_definition_get(
|
|
player_widgets[local_player_index]->definition_tag_index)->child_count == 3,
|
|
"this doesn't look like the net pregame status screen to me");
|
|
|
|
controller_bitmap = player_widgets[local_player_index]->child;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x48B,
|
|
controller_bitmap && controller_bitmap->type == _ui_widget_type_bitmap,
|
|
"expected container widget for local player controller bitmap");
|
|
name_text = controller_bitmap->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x48D,
|
|
name_text && name_text->type == _ui_widget_type_text_box,
|
|
"expected a text box for local player name field");
|
|
team_list = name_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x48F,
|
|
team_list && team_list->type == _ui_widget_type_spinner_list,
|
|
"expected a spinner list for local player team display");
|
|
|
|
if (!game->variant.universal_variant.teams)
|
|
widget_instance_set_visibility_recursive(team_list, FALSE);
|
|
else
|
|
widget_instance_set_visibility_recursive(team_list, TRUE);
|
|
|
|
if (local_player_indices[local_player_index] == NONE)
|
|
{
|
|
controller_bitmap->animation.current_frame_index = 0;
|
|
name_text->parameters.text_box.text = ui_widget_realloc(
|
|
name_text->parameters.text_box.text,
|
|
2,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x49D);
|
|
if (name_text->parameters.text_box.text)
|
|
name_text->parameters.text_box.text[0] = 0;
|
|
team_list->parameters.list.selected_list_item_index = 2;
|
|
}
|
|
else
|
|
{
|
|
long name_length = ustrlen(
|
|
game->players[local_player_indices[local_player_index]].name);
|
|
|
|
name_text->parameters.text_box.text = ui_widget_realloc(
|
|
name_text->parameters.text_box.text,
|
|
(word)(2 * name_length + 2),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x4A6);
|
|
if (name_text->parameters.text_box.text)
|
|
{
|
|
ustrncpy(
|
|
name_text->parameters.text_box.text,
|
|
game->players[local_player_indices[local_player_index]].name,
|
|
name_length);
|
|
name_text->parameters.text_box.text[name_length] = 0;
|
|
}
|
|
|
|
if (!game->variant.universal_variant.teams)
|
|
{
|
|
controller_bitmap->animation.current_frame_index = 1;
|
|
}
|
|
else
|
|
{
|
|
switch (game->players[local_player_indices[local_player_index]].team_index)
|
|
{
|
|
case _team_red:
|
|
controller_bitmap->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[0][local_player_index][2];
|
|
team_list->parameters.list.selected_list_item_index = 0;
|
|
break;
|
|
case _team_blue:
|
|
controller_bitmap->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[0][local_player_index][1];
|
|
team_list->parameters.list.selected_list_item_index = 1;
|
|
break;
|
|
default:
|
|
controller_bitmap->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[0][local_player_index][0];
|
|
team_list->parameters.list.selected_list_item_index = 2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
/* one entry per remote machine panel, not per remote machine */
|
|
long machine_indices[NUMBER_OF_REMOTE_MACHINE_PANELS];
|
|
struct widget_instance *machine_widgets[NUMBER_OF_REMOTE_MACHINE_PANELS];
|
|
long machine_widget_index;
|
|
long j;
|
|
|
|
machine_widgets[0] = second_machine_widget;
|
|
machine_widgets[1] = third_machine_widget;
|
|
machine_widgets[2] = fourth_machine_widget;
|
|
csmemset(machine_indices, NONE, sizeof(machine_indices));
|
|
for (machine_index = 0, j = 0;
|
|
machine_index < MAXIMUM_NETWORK_MACHINE_COUNT;
|
|
machine_index++)
|
|
{
|
|
struct network_machine *machine = &game->machines[machine_index];
|
|
|
|
if (network_machine_is_valid(machine) &&
|
|
machine->machine_index != local_machine_index)
|
|
{
|
|
/* more remote machines than panels: show the first ones */
|
|
if (j >= NUMBER_OF_REMOTE_MACHINE_PANELS)
|
|
break;
|
|
|
|
machine_indices[j] = machine_index;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
for (machine_widget_index = 0;
|
|
machine_widget_index < NUMBER_OF_REMOTE_MACHINE_PANELS;
|
|
machine_widget_index++)
|
|
{
|
|
struct widget_instance *remote_machine_icon;
|
|
struct widget_instance *remote_machine_name_text;
|
|
struct widget_instance *player_widget;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x4DD,
|
|
ui_widget_definition_get(
|
|
machine_widgets[machine_widget_index]->definition_tag_index)->child_count == 6,
|
|
"this doesn't look like the net pregame status screen to me");
|
|
|
|
remote_machine_icon = machine_widgets[machine_widget_index]->child;
|
|
remote_machine_name_text = remote_machine_icon->next;
|
|
if (machine_indices[machine_widget_index] == NONE)
|
|
{
|
|
remote_machine_icon->animation.current_frame_index = 0;
|
|
remote_machine_name_text->parameters.text_box.text = ui_widget_realloc(
|
|
remote_machine_name_text->parameters.text_box.text,
|
|
2,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x4E7);
|
|
if (remote_machine_name_text->parameters.text_box.text)
|
|
remote_machine_name_text->parameters.text_box.text[0] = 0;
|
|
|
|
player_widget = remote_machine_name_text->next;
|
|
for (local_player_index = 0;
|
|
local_player_index < MAXIMUM_LOCAL_PLAYERS;
|
|
local_player_index++)
|
|
{
|
|
if (!player_widget)
|
|
break;
|
|
|
|
player_widget->animation.current_frame_index = 2;
|
|
player_widget = player_widget->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
remote_machine_icon->animation.current_frame_index = 1;
|
|
length = ustrlen(game->machines[machine_indices[machine_widget_index]].name);
|
|
remote_machine_name_text->parameters.text_box.text = ui_widget_realloc(
|
|
remote_machine_name_text->parameters.text_box.text,
|
|
(word)(2 * length + 2),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x4F4);
|
|
if (remote_machine_name_text->parameters.text_box.text)
|
|
{
|
|
ustrncpy(
|
|
remote_machine_name_text->parameters.text_box.text,
|
|
game->machines[machine_indices[machine_widget_index]].name,
|
|
length);
|
|
remote_machine_name_text->parameters.text_box.text[length] = 0;
|
|
}
|
|
|
|
csmemset(local_player_indices, NONE, sizeof(local_player_indices));
|
|
for (player_index = 0;
|
|
player_index < (long)NUMBEROF(game->players);
|
|
player_index++)
|
|
{
|
|
if (network_player_is_valid(&game->players[player_index]) &&
|
|
game->players[player_index].machine_index ==
|
|
game->machines[machine_indices[machine_widget_index]].machine_index)
|
|
{
|
|
local_player_indices[game->players[player_index].controller_index] =
|
|
player_index;
|
|
}
|
|
}
|
|
|
|
player_widget = remote_machine_name_text->next;
|
|
for (local_player_index = 0;
|
|
local_player_index < MAXIMUM_LOCAL_PLAYERS;
|
|
local_player_index++)
|
|
{
|
|
if (!player_widget)
|
|
break;
|
|
|
|
if (local_player_indices[local_player_index] == NONE)
|
|
{
|
|
player_widget->animation.current_frame_index = 2;
|
|
}
|
|
else if (!game->variant.universal_variant.teams)
|
|
{
|
|
player_widget->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[0][local_player_index][0];
|
|
}
|
|
else
|
|
{
|
|
switch (game->players[
|
|
local_player_indices[local_player_index]].team_index)
|
|
{
|
|
case _team_red:
|
|
player_widget->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[0][local_player_index][2];
|
|
break;
|
|
case _team_blue:
|
|
player_widget->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[0][local_player_index][1];
|
|
break;
|
|
default:
|
|
player_widget->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[0][local_player_index][0];
|
|
break;
|
|
}
|
|
}
|
|
player_widget = player_widget->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void splitscreen_pregame_status_screen_update(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game = network_game_get_game();
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x550,
|
|
ui_widget_definition_get(widget->definition_tag_index)->child_count == 3,
|
|
"this doesn't look like the net pregame status screen to me");
|
|
|
|
if (game)
|
|
{
|
|
short local_machine_index = network_game_client_get_machine_index(
|
|
global_network_game_client_get());
|
|
struct widget_instance *status_container = widget->child;
|
|
struct widget_instance *status_text = status_container->next;
|
|
struct widget_instance *countdown_text = status_text->next;
|
|
struct widget_instance *machine_name_text;
|
|
struct widget_instance *machine_icon;
|
|
struct widget_instance *player_widgets[MAXIMUM_LOCAL_PLAYERS];
|
|
wchar_t const *machine_name;
|
|
long local_player_indices[MAXIMUM_LOCAL_PLAYERS];
|
|
long local_player_count;
|
|
long machine_index;
|
|
long player_index;
|
|
long local_player_index;
|
|
long length;
|
|
boolean local_machine_found;
|
|
|
|
countdown_text->parameters.text_box.text = ui_widget_realloc(
|
|
countdown_text->parameters.text_box.text,
|
|
0x20,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x55C);
|
|
if (countdown_text->parameters.text_box.text)
|
|
{
|
|
short seconds_to_game_start = network_game_client_get_seconds_to_game_start(
|
|
global_network_game_client_get());
|
|
|
|
ustrncpy(countdown_text->parameters.text_box.text, L"-:--", 15);
|
|
status_text->visible = TRUE;
|
|
status_text->parameters.text_box.string_list_index = 0;
|
|
countdown_text->visible = TRUE;
|
|
if (seconds_to_game_start == 0)
|
|
{
|
|
status_text->parameters.text_box.string_list_index = 1;
|
|
countdown_text->visible = FALSE;
|
|
}
|
|
else if (seconds_to_game_start > 0)
|
|
{
|
|
if (seconds_to_game_start < 60)
|
|
{
|
|
usnprintf(
|
|
countdown_text->parameters.text_box.text,
|
|
15,
|
|
L"0:%02d",
|
|
seconds_to_game_start);
|
|
}
|
|
else if (seconds_to_game_start < 3600)
|
|
{
|
|
long minutes = seconds_to_game_start / 60;
|
|
|
|
usnprintf(
|
|
countdown_text->parameters.text_box.text,
|
|
15,
|
|
L"%02d:%02d",
|
|
minutes,
|
|
seconds_to_game_start - minutes * 60);
|
|
}
|
|
else
|
|
{
|
|
long hours = seconds_to_game_start / 3600;
|
|
long minutes = (seconds_to_game_start - hours * 3600) / 60;
|
|
|
|
usnprintf(
|
|
countdown_text->parameters.text_box.text,
|
|
15,
|
|
L"%d:%02d:%02d",
|
|
hours,
|
|
minutes,
|
|
seconds_to_game_start - (hours * 60 + minutes) * 60);
|
|
}
|
|
}
|
|
else if (game->player_count < 2 || game->variant.universal_variant.teams == TRUE)
|
|
{
|
|
status_text->visible = FALSE;
|
|
countdown_text->visible = FALSE;
|
|
}
|
|
countdown_text->parameters.text_box.text[15] = 0;
|
|
}
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x592,
|
|
ui_widget_definition_get(status_container->definition_tag_index)->child_count == 6,
|
|
"this doesn't look like the net pregame status screen to me");
|
|
|
|
local_machine_found = FALSE;
|
|
machine_name = L"?";
|
|
machine_name_text = status_container->child;
|
|
machine_icon = machine_name_text->next;
|
|
player_widgets[0] = machine_icon->next;
|
|
player_widgets[1] = player_widgets[0]->next;
|
|
player_widgets[2] = player_widgets[1]->next;
|
|
player_widgets[3] = player_widgets[2]->next;
|
|
|
|
for (machine_index = 0;
|
|
machine_index < MAXIMUM_NETWORK_MACHINE_COUNT;
|
|
machine_index++)
|
|
{
|
|
struct network_machine *machine = &game->machines[machine_index];
|
|
|
|
if (network_machine_is_valid(machine) &&
|
|
machine->machine_index == local_machine_index)
|
|
{
|
|
struct network_machine *local_machine = network_game_client_get_machine(
|
|
global_network_game_client_get());
|
|
|
|
if (local_machine && local_machine->name[0])
|
|
machine_name = local_machine->name;
|
|
local_machine_found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
csmemset(local_player_indices, NONE, sizeof(local_player_indices));
|
|
local_player_count = 0;
|
|
for (player_index = 0;
|
|
player_index < (long)NUMBEROF(game->players);
|
|
player_index++)
|
|
{
|
|
if (network_player_is_valid(&game->players[player_index]) &&
|
|
game->players[player_index].machine_index == local_machine_index)
|
|
{
|
|
local_player_indices[game->players[player_index].controller_index] = player_index;
|
|
local_player_count++;
|
|
if (local_player_count == MAXIMUM_LOCAL_PLAYERS)
|
|
break;
|
|
}
|
|
}
|
|
|
|
length = ustrlen(machine_name);
|
|
machine_name_text->parameters.text_box.text = ui_widget_realloc(
|
|
machine_name_text->parameters.text_box.text,
|
|
(word)(2 * length + 2),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x5C2);
|
|
if (machine_name_text->parameters.text_box.text)
|
|
{
|
|
ustrncpy(machine_name_text->parameters.text_box.text, machine_name, length);
|
|
machine_name_text->parameters.text_box.text[length] = 0;
|
|
}
|
|
machine_icon->animation.current_frame_index = local_machine_found ? 1 : 0;
|
|
|
|
for (local_player_index = 0;
|
|
local_player_index < MAXIMUM_LOCAL_PLAYERS;
|
|
local_player_index++)
|
|
{
|
|
struct widget_instance *controller_bitmap;
|
|
struct widget_instance *name_text;
|
|
struct widget_instance *team_list;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x5CC,
|
|
ui_widget_definition_get(
|
|
player_widgets[local_player_index]->definition_tag_index)->child_count == 3,
|
|
"this doesn't look like the net pregame status screen to me");
|
|
|
|
controller_bitmap = player_widgets[local_player_index]->child;
|
|
name_text = controller_bitmap->next;
|
|
team_list = name_text->next;
|
|
|
|
if (!game->variant.universal_variant.teams)
|
|
widget_instance_set_visibility_recursive(team_list, FALSE);
|
|
|
|
if (local_player_indices[local_player_index] == NONE)
|
|
{
|
|
controller_bitmap->animation.current_frame_index = 0;
|
|
name_text->parameters.text_box.text = ui_widget_realloc(
|
|
name_text->parameters.text_box.text,
|
|
2,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x5DB);
|
|
if (name_text->parameters.text_box.text)
|
|
name_text->parameters.text_box.text[0] = 0;
|
|
team_list->parameters.list.selected_list_item_index = 0;
|
|
}
|
|
else
|
|
{
|
|
long name_length = ustrlen(
|
|
game->players[local_player_indices[local_player_index]].name);
|
|
|
|
name_text->parameters.text_box.text = ui_widget_realloc(
|
|
name_text->parameters.text_box.text,
|
|
(word)(2 * name_length + 2),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x5E4);
|
|
if (name_text->parameters.text_box.text)
|
|
{
|
|
ustrncpy(
|
|
name_text->parameters.text_box.text,
|
|
game->players[local_player_indices[local_player_index]].name,
|
|
name_length);
|
|
name_text->parameters.text_box.text[name_length] = 0;
|
|
}
|
|
|
|
if (!game->variant.universal_variant.teams)
|
|
{
|
|
controller_bitmap->animation.current_frame_index = 1;
|
|
}
|
|
else
|
|
{
|
|
switch (game->players[local_player_indices[local_player_index]].team_index)
|
|
{
|
|
case _team_red:
|
|
controller_bitmap->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[1][local_player_index][1];
|
|
team_list->parameters.list.selected_list_item_index = 0;
|
|
break;
|
|
case _team_blue:
|
|
controller_bitmap->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[1][local_player_index][2];
|
|
team_list->parameters.list.selected_list_item_index = 1;
|
|
break;
|
|
default:
|
|
controller_bitmap->animation.current_frame_index =
|
|
local_player_controller_bitmap_frames[1][local_player_index][0];
|
|
team_list->parameters.list.selected_list_item_index = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void netgame_prejoin_players(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game_client *client = global_network_game_client_get();
|
|
union
|
|
{
|
|
long index;
|
|
short client_state_data;
|
|
} state_or_index;
|
|
boolean local_player_wants_to_join[4];
|
|
|
|
(void)widget;
|
|
if (client &&
|
|
network_game_client_get_state(client, &state_or_index.client_state_data) == 2)
|
|
{
|
|
struct network_game *game = network_game_get_game();
|
|
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x614,
|
|
game);
|
|
|
|
for (state_or_index.index = 0; (short)state_or_index.index < 4; state_or_index.index++)
|
|
{
|
|
local_player_wants_to_join[(short)state_or_index.index] =
|
|
player_ui_local_player_wants_to_play_multiplayer((short)state_or_index.index);
|
|
}
|
|
|
|
/* every player slot of the native builds' larger sessions */
|
|
for (state_or_index.index = 0;
|
|
(short)state_or_index.index < (short)NUMBEROF(game->players);
|
|
state_or_index.index++)
|
|
{
|
|
if (network_player_is_valid(&game->players[(short)state_or_index.index]) &&
|
|
network_game_player_is_local(&game->players[(short)state_or_index.index]))
|
|
{
|
|
local_player_wants_to_join[
|
|
game->players[(short)state_or_index.index].controller_index] = FALSE;
|
|
}
|
|
}
|
|
|
|
for (state_or_index.index = 0; (short)state_or_index.index < 4; state_or_index.index++)
|
|
{
|
|
if (local_player_wants_to_join[(short)state_or_index.index] &&
|
|
!network_game_client_add_player(client, (short)state_or_index.index))
|
|
{
|
|
network_event("failed to send join request");
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void set_textbox_to_build_number(
|
|
struct widget_instance *widget)
|
|
{
|
|
/* Name, type and function scope from the 2003 PC demo PDB and the HCEX PDB (static local
|
|
wchar_t build_number_string[0x40]). Neither PDB records the block: placing it at the top of
|
|
the function is unattested. January corroborates: .bss +0x28, referenced only here. */
|
|
static wchar_t build_number_string[64];
|
|
|
|
if (!build_number_string[0])
|
|
{
|
|
ascii_to_wide(
|
|
"01.01.14.2342",
|
|
build_number_string,
|
|
sizeof(build_number_string));
|
|
}
|
|
|
|
if (!widget->parameters.text_box.text)
|
|
{
|
|
widget->parameters.text_box.text = ui_widget_realloc(
|
|
NULL,
|
|
sizeof(build_number_string),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x25E);
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
csmemset(
|
|
widget->parameters.text_box.text,
|
|
0,
|
|
sizeof(build_number_string));
|
|
}
|
|
}
|
|
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
ustrncpy(
|
|
widget->parameters.text_box.text,
|
|
build_number_string,
|
|
NUMBEROF(build_number_string) - 1);
|
|
widget->parameters.text_box.text[NUMBEROF(build_number_string) - 1] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void solo_game_objective_text(
|
|
struct widget_instance *widget)
|
|
{
|
|
wchar_t const *objective = hud_messaging_get_objective();
|
|
long length = objective && *objective ? ustrlen(objective) : 0;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x924,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected a text box for objective text");
|
|
|
|
if (length > 0)
|
|
{
|
|
widget->parameters.text_box.text = ui_widget_realloc(
|
|
widget->parameters.text_box.text,
|
|
(word)(2 * length + 2),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x928);
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
ustrncpy(widget->parameters.text_box.text, objective, length);
|
|
widget->parameters.text_box.text[length] = 0;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void main_menu_animation_fakery(
|
|
struct widget_instance *widget)
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9AB,
|
|
widget->type == _ui_widget_type_column_list,
|
|
"expected column list for main menu options list");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9AE,
|
|
widget->parameters.list.extended_description &&
|
|
widget->parameters.list.extended_description->type == _ui_widget_type_bitmap,
|
|
"expected a picture (container) for main menu options list extended description");
|
|
|
|
widget->parameters.list.extended_description->animation.current_frame_index =
|
|
widget->parameters.list.selected_list_item_index;
|
|
widget->parameters.list.extended_description->animation.current_frame_index = (short)FLOOR(
|
|
widget->parameters.list.extended_description->animation.current_frame_index,
|
|
0);
|
|
return;
|
|
}
|
|
|
|
static void get_active_player_profile_display_name(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct player_profile profile;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9EC,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for profile display name");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9EE,
|
|
widget->local_player_index >= 0 && widget->local_player_index < 4,
|
|
"profile display name requires a valid local player index");
|
|
|
|
player_ui_get_active_player_profile(widget->local_player_index, &profile);
|
|
widget->parameters.text_box.text = ui_widget_realloc(
|
|
widget->parameters.text_box.text,
|
|
sizeof(profile.player_name),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9F0);
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
ustrncpy(widget->parameters.text_box.text, profile.player_name, NUMBEROF(profile.player_name) - 1);
|
|
widget->parameters.text_box.text[NUMBEROF(profile.player_name) - 1] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void get_editable_player_profile_display_name(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct player_profile *profile;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9FE,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for profile display name");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA00,
|
|
widget->local_player_index >= 0 && widget->local_player_index < 4,
|
|
"profile display name requires a valid local player index");
|
|
|
|
profile = player_ui_get_edit_player_profile();
|
|
if (profile)
|
|
{
|
|
widget->parameters.text_box.text = ui_widget_realloc(
|
|
widget->parameters.text_box.text,
|
|
sizeof(profile->player_name),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA04);
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
ustrncpy(widget->parameters.text_box.text, profile->player_name, NUMBEROF(profile->player_name) - 1);
|
|
widget->parameters.text_box.text[NUMBEROF(profile->player_name) - 1] = 0;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void get_editable_playlist_profile_display_name(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct game_variant *profile;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA13,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for profile display name");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA15,
|
|
widget->local_player_index >= 0 && widget->local_player_index < 4,
|
|
"profile display name requires a valid local player index");
|
|
|
|
profile = player_ui_get_edit_playlist_profile();
|
|
if (profile)
|
|
{
|
|
widget->parameters.text_box.text = ui_widget_realloc(
|
|
widget->parameters.text_box.text,
|
|
sizeof(profile->human_readable_game_description),
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA19);
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
ustrncpy(widget->parameters.text_box.text, profile->human_readable_game_description, NUMBEROF(profile->human_readable_game_description) - 1);
|
|
widget->parameters.text_box.text[NUMBEROF(profile->human_readable_game_description) - 1] = 0;
|
|
}
|
|
}
|
|
else
|
|
error(2, "not currently editing a game variant");
|
|
return;
|
|
}
|
|
|
|
static void get_active_player_profile_color_index(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct player_profile profile;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA2D,
|
|
widget->local_player_index >= 0 && widget->local_player_index < 4,
|
|
"profile color picture requires a valid local player index");
|
|
|
|
player_ui_get_active_player_profile(widget->local_player_index, &profile);
|
|
widget->animation.current_frame_index = (short)PIN(
|
|
profile.primary_color_index,
|
|
0,
|
|
player_profile_number_of_available_primary_colors() - 1);
|
|
return;
|
|
}
|
|
|
|
static void player_profile_edit_select_menu_update_extended_description(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct widget_instance *child;
|
|
struct widget_instance *description_child;
|
|
struct ui_widget_definition *description_definition;
|
|
short index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x836,
|
|
list_widget && list_widget->focused_child && list_widget->parameters.list.extended_description,
|
|
"invalid widget trying to update its extended list description");
|
|
|
|
index = 0;
|
|
child = list_widget->child;
|
|
while (child)
|
|
{
|
|
if (child == list_widget->focused_child)
|
|
break;
|
|
child = child->next;
|
|
index++;
|
|
}
|
|
/* port: the PC version's buttons (a list of their own, past its items)
|
|
leave the last item's description shown, as they have none */
|
|
if (pc_menu_tag(list_widget->definition_tag_index) && list_widget->focused_child->type == _ui_widget_type_column_list)
|
|
index = NONE;
|
|
|
|
if (index != NONE)
|
|
{
|
|
description_definition = ui_widget_definition_get(
|
|
list_widget->parameters.list.extended_description->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x844,
|
|
description_definition->child_count == 2,
|
|
"expected a container widget w/ 2 children for the player profile edit settings list extended description");
|
|
|
|
description_child = list_widget->parameters.list.extended_description->child;
|
|
description_child->parameters.text_box.string_list_index = index;
|
|
description_child->next->animation.current_frame_index = index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void game_options_menu_update_text_desc(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct widget_instance *column;
|
|
struct widget_instance *extended_description;
|
|
struct widget_instance *spinner_list;
|
|
struct ui_widget_definition *definition;
|
|
long description_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x8F5,
|
|
widget->type == _ui_widget_type_column_list,
|
|
"expected column list for multiplayer game options list");
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x8F8,
|
|
widget->parameters.list.extended_description &&
|
|
widget->parameters.list.extended_description->type == _ui_widget_type_text_box,
|
|
"expected a text box for multiplayer game options list extended description");
|
|
|
|
definition = ui_widget_definition_get(widget->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x8FE,
|
|
definition->child_count > 0,
|
|
"expected some list items for multiplayer game settings list");
|
|
|
|
extended_description = widget->parameters.list.extended_description;
|
|
if (widget->focused_child)
|
|
{
|
|
description_index = 0;
|
|
column = widget->child;
|
|
while (column)
|
|
{
|
|
spinner_list = column->child;
|
|
while (spinner_list && spinner_list->type != _ui_widget_type_spinner_list)
|
|
spinner_list = spinner_list->next;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x90C,
|
|
spinner_list,
|
|
"expected a spinner list somewhere in the multiplayer game options settings list item makeup");
|
|
|
|
if (column == widget->focused_child)
|
|
{
|
|
/* port: an extra item's own description (ui_widget.c) */
|
|
short extra_description = ui_widget_spinner_extra_description(spinner_list,
|
|
spinner_list->parameters.list.selected_list_item_index);
|
|
|
|
if (extra_description != NONE)
|
|
{
|
|
widget->parameters.list.extended_description->parameters.text_box.string_list_index =
|
|
extra_description;
|
|
return;
|
|
}
|
|
description_index += spinner_list->parameters.list.selected_list_item_index;
|
|
break;
|
|
}
|
|
|
|
/* port: only the items of a spinner's string list's own have
|
|
descriptions in its tag */
|
|
description_index += ui_widget_spinner_own_item_count(spinner_list);
|
|
column = column->next;
|
|
}
|
|
}
|
|
|
|
/* BUG (preserved for exact matching): description_index is assigned only when the
|
|
* list has a focused child. Without one, January stores the low word of the widget
|
|
* argument slot instead (0x4e1ce0: +0xa4 branches to +0x119 mov dx,[ebp+8]; the slot
|
|
* is never written). Whether a game options list is updated without a focused child
|
|
* is not shown. A corrected build should initialise description_index to 0.
|
|
* Source-policy approval pending (2026-09-27 audit). */
|
|
extended_description->parameters.text_box.string_list_index = (short)description_index;
|
|
return;
|
|
}
|
|
|
|
static void game_options_menu_update_pic_desc(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct widget_instance *column;
|
|
struct widget_instance *extended_description;
|
|
struct widget_instance *spinner_list;
|
|
struct ui_widget_definition *definition;
|
|
long description_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x980,
|
|
widget->type == _ui_widget_type_column_list,
|
|
"expected column list for game options list");
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x983,
|
|
widget->parameters.list.extended_description &&
|
|
widget->parameters.list.extended_description->type == _ui_widget_type_bitmap,
|
|
"expected a picture (container) for game options list extended description");
|
|
|
|
definition = ui_widget_definition_get(widget->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x988,
|
|
definition->child_count > 0,
|
|
"expected some list items for game settings list");
|
|
|
|
extended_description = widget->parameters.list.extended_description;
|
|
if (widget->focused_child)
|
|
{
|
|
description_index = 0;
|
|
column = widget->child;
|
|
while (column)
|
|
{
|
|
spinner_list = column->child;
|
|
while (spinner_list && spinner_list->type != _ui_widget_type_spinner_list)
|
|
spinner_list = spinner_list->next;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x996,
|
|
spinner_list,
|
|
"expected a spinner list somewhere in the multiplayer game options settings list item makeup");
|
|
|
|
if (column == widget->focused_child)
|
|
{
|
|
/* port: an extra item shows its spinner's last picture of its own */
|
|
description_index += MIN(spinner_list->parameters.list.selected_list_item_index,
|
|
ui_widget_spinner_own_item_count(spinner_list) - 1);
|
|
break;
|
|
}
|
|
|
|
description_index += ui_widget_spinner_own_item_count(spinner_list);
|
|
column = column->next;
|
|
}
|
|
}
|
|
|
|
/* BUG (preserved for exact matching): as in game_options_menu_update_text_desc,
|
|
* without a focused child January stores the low word of the widget argument slot
|
|
* (0x4e1ea0 +0x119 mov dx,[ebp+8]). Whether that occurs is not shown. A corrected
|
|
* build should initialise description_index to 0. Source-policy approval pending
|
|
* (2026-09-27 audit). */
|
|
extended_description->animation.current_frame_index = (short)description_index;
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_text_box_for_map_name(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
char const *map_name;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA39,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected text box widget for mp game settings text");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
map_name = game->map.name;
|
|
/* port: a Custom Edition map shows its own name */
|
|
if (custom_edition_map_display_index(map_name) != NONE)
|
|
{
|
|
widget->parameters.text_box.string_list_index = custom_edition_map_display_index(map_name);
|
|
return;
|
|
}
|
|
if (strstr(map_name, "beavercreek"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 0;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "sidewinder"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 1;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "damnation"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 2;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "ratrace"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 3;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "prisoner"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 4;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "hangemhigh"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 5;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "chillout"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 6;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "carousel"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 7;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "boardingaction"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 8;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "bloodgulch"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 9;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "wizard"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 10;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "putput"))
|
|
{
|
|
widget->parameters.text_box.string_list_index = 11;
|
|
return;
|
|
}
|
|
|
|
widget->parameters.text_box.string_list_index = strstr(map_name, "longest") ? 12 : 13;
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_text_box_for_game_ruleset(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xA59,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected text box widget for mp game settings text");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
switch (game->variant.game_engine_index)
|
|
{
|
|
case game_engine_ctf:
|
|
if (game->variant.game_engine_variant.ctf.assault == TRUE)
|
|
{
|
|
widget->parameters.text_box.string_list_index =
|
|
game->variant.game_engine_variant.ctf.single_flag_time ?
|
|
_multiplayer_game_text_string_single_flag_assault :
|
|
_multiplayer_game_text_string_assault;
|
|
}
|
|
else
|
|
{
|
|
widget->parameters.text_box.string_list_index =
|
|
game->variant.game_engine_variant.ctf.single_flag_time ?
|
|
_multiplayer_game_text_string_single_flag_ctf :
|
|
_multiplayer_game_text_string_capture_the_flag;
|
|
}
|
|
break;
|
|
case game_engine_slayer:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_slayer;
|
|
break;
|
|
case game_engine_oddball:
|
|
switch (game->variant.game_engine_variant.oddball.oddball_ball_type)
|
|
{
|
|
case 1:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_reverse_tag;
|
|
break;
|
|
case 2:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_juggernaut;
|
|
break;
|
|
default:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_oddball;
|
|
break;
|
|
}
|
|
break;
|
|
case game_engine_king:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_king_of_the_hill;
|
|
break;
|
|
case game_engine_race:
|
|
switch (game->variant.game_engine_variant.race.race_type)
|
|
{
|
|
case 2:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_rally;
|
|
break;
|
|
default:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_race;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_unknown_game_type;
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_text_box_for_teams_noteams(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xAAA,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected text box widget for mp game settings text");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
widget->parameters.text_box.string_list_index = game->variant.universal_variant.teams != TRUE ? 13 : 12;
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_text_box_for_score_limit(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xAC3,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected text box widget for mp game settings text");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
widget->parameters.text_box.text = ui_widget_realloc(
|
|
widget->parameters.text_box.text,
|
|
0x10,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xAC8);
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
usnprintf(widget->parameters.text_box.text, 7, L"%d", game->variant.universal_variant.score_to_win);
|
|
widget->parameters.text_box.text[7] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_text_box_for_score_limit_type(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xADC,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected text box widget for mp game settings text");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
switch (game->variant.game_engine_index)
|
|
{
|
|
case game_engine_ctf:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_captures;
|
|
break;
|
|
case game_engine_slayer:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_frags;
|
|
break;
|
|
case game_engine_oddball:
|
|
widget->parameters.text_box.string_list_index = game->variant.game_engine_variant.oddball.oddball_ball_type == 2 ?
|
|
_multiplayer_game_text_string_frags : _multiplayer_game_text_string_minutes;
|
|
break;
|
|
case game_engine_king:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_minutes;
|
|
break;
|
|
case game_engine_race:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_laps;
|
|
break;
|
|
default:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_frags;
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_bitmap_for_map(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
char const *map_name;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xB09,
|
|
widget->type == _ui_widget_type_bitmap,
|
|
"expected container widget for mp game settings bitmap");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
map_name = game->map.name;
|
|
/* port: a Custom Edition map shows its own picture */
|
|
if (custom_edition_map_display_index(map_name) != NONE)
|
|
{
|
|
widget->animation.current_frame_index = custom_edition_map_display_index(map_name);
|
|
return;
|
|
}
|
|
if (strstr(map_name, "beavercreek"))
|
|
{
|
|
widget->animation.current_frame_index = 0;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "sidewinder"))
|
|
{
|
|
widget->animation.current_frame_index = 1;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "damnation"))
|
|
{
|
|
widget->animation.current_frame_index = 2;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "ratrace"))
|
|
{
|
|
widget->animation.current_frame_index = 3;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "prisoner"))
|
|
{
|
|
widget->animation.current_frame_index = 4;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "hangemhigh"))
|
|
{
|
|
widget->animation.current_frame_index = 5;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "chillout"))
|
|
{
|
|
widget->animation.current_frame_index = 6;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "carousel"))
|
|
{
|
|
widget->animation.current_frame_index = 7;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "boardingaction"))
|
|
{
|
|
widget->animation.current_frame_index = 8;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "bloodgulch"))
|
|
{
|
|
widget->animation.current_frame_index = 9;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "wizard"))
|
|
{
|
|
widget->animation.current_frame_index = 10;
|
|
return;
|
|
}
|
|
if (strstr(map_name, "putput"))
|
|
{
|
|
widget->animation.current_frame_index = 11;
|
|
return;
|
|
}
|
|
|
|
widget->animation.current_frame_index = strstr(map_name, "longest") ? 12 : 13;
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_bitmap_for_ruleset(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xB28,
|
|
widget->type == _ui_widget_type_bitmap,
|
|
"expected container widget for mp game settings bitmap");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
switch (game->variant.game_engine_index)
|
|
{
|
|
case game_engine_ctf:
|
|
widget->animation.current_frame_index = _multiplayer_game_bitmap_ctf;
|
|
break;
|
|
case game_engine_slayer:
|
|
widget->animation.current_frame_index = _multiplayer_game_bitmap_slayer;
|
|
break;
|
|
case game_engine_oddball:
|
|
widget->animation.current_frame_index = _multiplayer_game_bitmap_oddball;
|
|
break;
|
|
case game_engine_king:
|
|
widget->animation.current_frame_index = _multiplayer_game_bitmap_king;
|
|
break;
|
|
case game_engine_race:
|
|
widget->animation.current_frame_index = _multiplayer_game_bitmap_race;
|
|
break;
|
|
default:
|
|
widget->animation.current_frame_index = _multiplayer_game_bitmap_unknown;
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_set_text_box_for_number_of_players(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xB4E,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected text box widget for mp game settings text");
|
|
|
|
game = network_game_get_game();
|
|
if (game)
|
|
{
|
|
widget->parameters.text_box.text = ui_widget_realloc(
|
|
widget->parameters.text_box.text,
|
|
8,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xB56);
|
|
if (widget->parameters.text_box.text)
|
|
{
|
|
/* room for a three-digit count: the Linux runtime's _vsnwprintf
|
|
writes its terminator inside the count */
|
|
usnprintf(widget->parameters.text_box.text, 4, L"%d", game->player_count);
|
|
widget->parameters.text_box.text[3] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
error(2, "no network game");
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_edit_profile_set_ruleset_textbox_string_index(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct game_variant *profile;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xB69,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for mp profile edit ruleset text widget");
|
|
|
|
profile = player_ui_get_edit_playlist_profile();
|
|
if (profile)
|
|
{
|
|
switch (profile->game_engine_index)
|
|
{
|
|
case game_engine_ctf:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_capture_the_flag;
|
|
break;
|
|
case game_engine_slayer:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_slayer;
|
|
break;
|
|
case game_engine_oddball:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_oddball;
|
|
break;
|
|
case game_engine_king:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_king_of_the_hill;
|
|
break;
|
|
case game_engine_race:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_race;
|
|
break;
|
|
default:
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_unknown_game_type;
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
error(2, "not currently editing a game variant");
|
|
return;
|
|
}
|
|
|
|
static void system_link_status_check(
|
|
struct widget_instance *widget)
|
|
{
|
|
(void)widget;
|
|
|
|
if (!transport_network_available() && !network_game_is_splitscreen_local())
|
|
{
|
|
display_error_when_main_menu_loaded(_error_network_connection_lost);
|
|
main_goto_main_menu();
|
|
error(2, "network connection went down!");
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void multiplayer_game_directions(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game = network_game_get_game();
|
|
struct network_game_server *server = global_network_game_server_get();
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xBAD,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected text box widget for team game directions");
|
|
|
|
if (server)
|
|
{
|
|
boolean waiting_for_machines = !network_game_is_splitscreen_local() &&
|
|
game &&
|
|
game->machine_count < 2;
|
|
|
|
if (!waiting_for_machines &&
|
|
network_game_is_splitscreen_local() &&
|
|
game &&
|
|
game->player_count < 2)
|
|
{
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_waiting_for_player;
|
|
widget->visible = TRUE;
|
|
return;
|
|
}
|
|
|
|
if (waiting_for_machines)
|
|
{
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_waiting_for_machine;
|
|
widget->visible = TRUE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (game &&
|
|
game->variant.universal_variant.teams == TRUE &&
|
|
network_game_client_get_seconds_to_game_start(global_network_game_client_get()) < 0)
|
|
{
|
|
long team_one_player_count = 0;
|
|
long team_zero_player_count = 0;
|
|
long player_index;
|
|
|
|
for (player_index = 0;
|
|
player_index < NUMBEROF(game->players);
|
|
player_index++)
|
|
{
|
|
if (network_player_is_valid(&game->players[player_index]))
|
|
{
|
|
switch (game->players[player_index].team_index)
|
|
{
|
|
case _team_red:
|
|
team_zero_player_count++;
|
|
break;
|
|
case _team_blue:
|
|
team_one_player_count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (team_zero_player_count && team_one_player_count)
|
|
{
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_teams_ready;
|
|
}
|
|
else
|
|
{
|
|
widget->parameters.text_box.string_list_index =
|
|
_multiplayer_game_text_string_waiting_for_teams;
|
|
}
|
|
|
|
widget->visible = TRUE;
|
|
return;
|
|
}
|
|
|
|
widget->visible = FALSE;
|
|
return;
|
|
}
|
|
|
|
static void teams_no_teams_mp_game_bitmap_update(
|
|
struct widget_instance *widget)
|
|
{
|
|
struct network_game *game = network_game_get_game();
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xBFC,
|
|
widget->type == _ui_widget_type_bitmap,
|
|
"expected a container bitmap for mp pregame header widget");
|
|
|
|
if (game)
|
|
widget->animation.current_frame_index = game->variant.universal_variant.teams != TRUE;
|
|
return;
|
|
}
|
|
|
|
static void warn_if_difficulty_will_nuke_saved_game(
|
|
struct widget_instance *difficulty_screen_widget)
|
|
{
|
|
struct widget_instance *difficulty_list = difficulty_screen_widget->child;
|
|
struct widget_instance *warning_widget;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xC1F,
|
|
difficulty_list && difficulty_list->type == _ui_widget_type_column_list,
|
|
"this doesn't look like the difficulty list widget");
|
|
|
|
warning_widget = difficulty_list->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xC23,
|
|
warning_widget && warning_widget->type == _ui_widget_type_text_box,
|
|
"this doesn't look like the difficulty list widget (expected warning text box)");
|
|
|
|
if (persistant_game_data_info.valid == TRUE &&
|
|
_stricmp(persistant_game_data_info.map_name, main_get_map_name()) == 0)
|
|
{
|
|
warning_widget->visible =
|
|
difficulty_list->parameters.list.selected_list_item_index !=
|
|
persistant_game_data_info.difficulty;
|
|
}
|
|
else
|
|
warning_widget->visible = FALSE;
|
|
return;
|
|
}
|
|
|
|
static void dim_if_no_system_link_cable(
|
|
struct widget_instance *widget)
|
|
{
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xC3C,
|
|
widget->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for system link menu text item");
|
|
|
|
widget->alpha_modifier = transport_network_available() ? 1.0f : 0.333f;
|
|
return;
|
|
}
|
|
|
|
static void spinner_list_3wide_determine_displayed_item_indices(
|
|
struct widget_instance *list_widget,
|
|
long *displayed_item_indices)
|
|
{
|
|
struct widget_instance *focused_child = list_widget->focused_child;
|
|
struct widget_instance *first_child = list_widget->child;
|
|
|
|
if (focused_child == first_child)
|
|
{
|
|
displayed_item_indices[0] = list_widget->parameters.list.selected_list_item_index;
|
|
displayed_item_indices[1] = displayed_item_indices[0] + 1;
|
|
if (displayed_item_indices[1] == list_widget->parameters.list.number_of_items)
|
|
displayed_item_indices[1] = 0;
|
|
displayed_item_indices[2] = displayed_item_indices[1] + 1;
|
|
if (displayed_item_indices[2] == list_widget->parameters.list.number_of_items)
|
|
displayed_item_indices[2] = 0;
|
|
}
|
|
else if (focused_child == first_child->next)
|
|
{
|
|
displayed_item_indices[1] = list_widget->parameters.list.selected_list_item_index;
|
|
displayed_item_indices[0] = displayed_item_indices[1] - 1;
|
|
if (displayed_item_indices[0] < 0)
|
|
{
|
|
displayed_item_indices[0] =
|
|
list_widget->parameters.list.number_of_items - 1;
|
|
}
|
|
displayed_item_indices[2] = displayed_item_indices[1] + 1;
|
|
if (displayed_item_indices[2] == list_widget->parameters.list.number_of_items)
|
|
displayed_item_indices[2] = 0;
|
|
}
|
|
else
|
|
{
|
|
displayed_item_indices[2] = list_widget->parameters.list.selected_list_item_index;
|
|
displayed_item_indices[1] = displayed_item_indices[2] - 1;
|
|
if (displayed_item_indices[1] < 0)
|
|
{
|
|
displayed_item_indices[1] =
|
|
list_widget->parameters.list.number_of_items - 1;
|
|
}
|
|
displayed_item_indices[0] = displayed_item_indices[1] - 1;
|
|
if (displayed_item_indices[0] < 0)
|
|
{
|
|
displayed_item_indices[0] =
|
|
list_widget->parameters.list.number_of_items - 1;
|
|
}
|
|
}
|
|
|
|
if (displayed_item_indices[0] >= list_widget->parameters.list.number_of_items)
|
|
displayed_item_indices[0] = NONE;
|
|
if (displayed_item_indices[1] >= list_widget->parameters.list.number_of_items)
|
|
displayed_item_indices[1] = NONE;
|
|
if (displayed_item_indices[2] >= list_widget->parameters.list.number_of_items)
|
|
displayed_item_indices[2] = NONE;
|
|
return;
|
|
}
|
|
|
|
static void player_profile_update_cache_for_nwide_list(
|
|
long *profile_indices,
|
|
long profile_index_count)
|
|
{
|
|
boolean still_wanted[3] = { FALSE };
|
|
long cache_index;
|
|
long requested_index;
|
|
|
|
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_player_profile); cache_index++)
|
|
{
|
|
if (cached_player_profile[cache_index].profile_index == NONE)
|
|
continue;
|
|
|
|
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
|
|
{
|
|
if (cached_player_profile[cache_index].profile_index == profile_indices[requested_index])
|
|
{
|
|
still_wanted[cache_index] = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
|
|
{
|
|
if (profile_indices[requested_index] == NONE)
|
|
continue;
|
|
|
|
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_player_profile); cache_index++)
|
|
{
|
|
if (profile_indices[requested_index] == cached_player_profile[cache_index].profile_index)
|
|
break;
|
|
}
|
|
|
|
if (cache_index == (long)NUMBEROF(cached_player_profile))
|
|
{
|
|
for (cache_index = 0; cache_index < (long)NUMBEROF(still_wanted); cache_index++)
|
|
{
|
|
if (still_wanted[cache_index] != TRUE)
|
|
break;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xCA2,
|
|
cache_index < (long)NUMBEROF(cached_player_profile),
|
|
"not enough cache profiles");
|
|
}
|
|
|
|
if (player_profile_get(
|
|
profile_indices[requested_index],
|
|
&cached_player_profile[cache_index].profile))
|
|
{
|
|
cached_player_profile[cache_index].profile_index = profile_indices[requested_index];
|
|
still_wanted[cache_index] = TRUE;
|
|
}
|
|
else
|
|
error(2, "failed to cache player profile");
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void variant_profile_update_cache_for_nwide_list(
|
|
long *profile_indices,
|
|
long profile_index_count)
|
|
{
|
|
boolean still_wanted[3] = { FALSE };
|
|
long cache_index;
|
|
long requested_index;
|
|
|
|
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_variant_profile); cache_index++)
|
|
{
|
|
if (cached_variant_profile[cache_index].profile_index == NONE)
|
|
continue;
|
|
|
|
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
|
|
{
|
|
if (cached_variant_profile[cache_index].profile_index == profile_indices[requested_index])
|
|
{
|
|
still_wanted[cache_index] = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
|
|
{
|
|
if (profile_indices[requested_index] == NONE)
|
|
continue;
|
|
|
|
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_variant_profile); cache_index++)
|
|
{
|
|
if (profile_indices[requested_index] == cached_variant_profile[cache_index].profile_index)
|
|
break;
|
|
}
|
|
|
|
if (cache_index == (long)NUMBEROF(cached_variant_profile))
|
|
{
|
|
for (cache_index = 0; cache_index < (long)NUMBEROF(still_wanted); cache_index++)
|
|
{
|
|
if (still_wanted[cache_index] != TRUE)
|
|
break;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0xCD5,
|
|
cache_index < (long)NUMBEROF(cached_variant_profile),
|
|
"not enough cache profiles");
|
|
}
|
|
|
|
if (playlist_profile_get(
|
|
profile_indices[requested_index],
|
|
(struct game_variant *)&cached_variant_profile[cache_index].profile))
|
|
{
|
|
cached_variant_profile[cache_index].profile_index = profile_indices[requested_index];
|
|
still_wanted[cache_index] = TRUE;
|
|
}
|
|
else
|
|
error(2, "failed to cache playlist profile");
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void mutliplayer_settings_select_list_update_displayed_items(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
long descriptions_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\strings\\game_variant_descriptions");
|
|
struct ui_widget_definition *definition = ui_widget_definition_get(
|
|
list_widget->definition_tag_index);
|
|
long displayed_item_indices[3];
|
|
long profile_indices[3];
|
|
long item_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x67D,
|
|
definition->type == _ui_widget_type_spinner_list,
|
|
"expected a spinner list for 'multiplayer settings select' widget");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x67E,
|
|
definition->child_count == 3,
|
|
"expected 3 children (list items) for 'multiplayer settings select' widget");
|
|
|
|
spinner_list_3wide_determine_displayed_item_indices(
|
|
list_widget,
|
|
displayed_item_indices);
|
|
for (item_index = 0; item_index < 3; item_index++)
|
|
{
|
|
if (displayed_item_indices[item_index] != NONE)
|
|
{
|
|
profile_indices[item_index] = ((long *)list_widget->parameters.list.list_items)
|
|
[displayed_item_indices[item_index]];
|
|
}
|
|
else
|
|
profile_indices[item_index] = NONE;
|
|
}
|
|
variant_profile_update_cache_for_nwide_list(
|
|
profile_indices,
|
|
NUMBEROF(profile_indices));
|
|
|
|
for (item_index = 0;
|
|
item_index < 3 &&
|
|
displayed_item_indices[item_index] != NONE;
|
|
item_index++)
|
|
{
|
|
struct widget_instance *item = widget_instance_get_nth_child(
|
|
list_widget,
|
|
item_index);
|
|
struct widget_instance *description_box = item->child;
|
|
struct widget_instance *icon = description_box->next;
|
|
struct widget_instance *label_box = icon->next;
|
|
struct widget_instance *description_container = label_box->next;
|
|
struct playlist_profile *profile = NULL;
|
|
long profile_index;
|
|
long cache_index;
|
|
|
|
definition = ui_widget_definition_get(item->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x69E,
|
|
definition->child_count != 0,
|
|
"expected 3 children in multiplayer settings list item (name, pic, desc)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x6A0,
|
|
ui_widget_definition_get(description_box->definition_tag_index)->type ==
|
|
_ui_widget_type_text_box,
|
|
"expected a text box widget for the list item's first child (map name)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x6A2,
|
|
ui_widget_definition_get(icon->definition_tag_index)->type ==
|
|
_ui_widget_type_bitmap,
|
|
"expected a container widget for the list item's second child (map pic)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x6A4,
|
|
ui_widget_definition_get(label_box->definition_tag_index)->type ==
|
|
_ui_widget_type_text_box,
|
|
"expected a text box widget for the list item's third child (map description)");
|
|
|
|
profile_index = ((long *)list_widget->parameters.list.list_items)
|
|
[displayed_item_indices[item_index]];
|
|
if (profile_index != NONE)
|
|
{
|
|
for (cache_index = 0;
|
|
cache_index < (long)NUMBEROF(cached_variant_profile);
|
|
cache_index++)
|
|
{
|
|
if (cached_variant_profile[cache_index].profile_index == profile_index)
|
|
{
|
|
profile = &cached_variant_profile[cache_index].profile;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
description_container->visible = FALSE;
|
|
if (profile)
|
|
{
|
|
description_box->parameters.text_box.text = ui_widget_realloc(
|
|
description_box->parameters.text_box.text,
|
|
0x100,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x6BA);
|
|
if (description_box->parameters.text_box.text)
|
|
{
|
|
ustrncpy(description_box->parameters.text_box.text, profile->name, 0x7F);
|
|
description_box->parameters.text_box.text[0x7F] = 0;
|
|
}
|
|
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_unknown;
|
|
label_box->parameters.text_box.text = ui_widget_realloc(
|
|
label_box->parameters.text_box.text,
|
|
0x200,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x6C1);
|
|
if (label_box->parameters.text_box.text)
|
|
label_box->parameters.text_box.text[0] = 0;
|
|
|
|
if (TEST_FLAG(profile->flags, 0))
|
|
{
|
|
long string_index = (profile->flags >> 8) + 10;
|
|
|
|
switch (profile->engine_type)
|
|
{
|
|
case game_engine_ctf:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_ctf;
|
|
break;
|
|
case game_engine_slayer:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_slayer;
|
|
break;
|
|
case game_engine_oddball:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_oddball;
|
|
break;
|
|
case game_engine_king:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_king;
|
|
break;
|
|
case game_engine_race:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_race;
|
|
break;
|
|
}
|
|
|
|
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(
|
|
descriptions_tag_index,
|
|
string_index),
|
|
0xFF);
|
|
label_box->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
description_container->visible = TRUE;
|
|
continue;
|
|
}
|
|
|
|
switch (profile->engine_type)
|
|
{
|
|
case game_engine_ctf:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_ctf;
|
|
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
|
|
{
|
|
if (profile->teams == TRUE)
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 1),
|
|
0xFF);
|
|
}
|
|
else
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 0),
|
|
0xFF);
|
|
}
|
|
label_box->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
break;
|
|
case game_engine_slayer:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_slayer;
|
|
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
|
|
{
|
|
if (profile->teams == TRUE)
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 3),
|
|
0xFF);
|
|
}
|
|
else
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 2),
|
|
0xFF);
|
|
}
|
|
label_box->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
break;
|
|
case game_engine_oddball:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_oddball;
|
|
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
|
|
{
|
|
if (profile->teams == TRUE)
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 5),
|
|
0xFF);
|
|
}
|
|
else
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 4),
|
|
0xFF);
|
|
}
|
|
label_box->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
break;
|
|
case game_engine_king:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_king;
|
|
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
|
|
{
|
|
if (profile->teams == TRUE)
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 7),
|
|
0xFF);
|
|
}
|
|
else
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 6),
|
|
0xFF);
|
|
}
|
|
label_box->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
break;
|
|
case game_engine_race:
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_race;
|
|
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
|
|
{
|
|
if (profile->teams == TRUE)
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 9),
|
|
0xFF);
|
|
}
|
|
else
|
|
{
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
unicode_string_list_get_string(descriptions_tag_index, 8),
|
|
0xFF);
|
|
}
|
|
label_box->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
description_box->parameters.text_box.text = ui_widget_realloc(
|
|
description_box->parameters.text_box.text,
|
|
0x100,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x751);
|
|
if (description_box->parameters.text_box.text)
|
|
description_box->parameters.text_box.text[0] = 0;
|
|
|
|
icon->animation.current_frame_index = _multiplayer_game_bitmap_unknown;
|
|
label_box->parameters.text_box.text = ui_widget_realloc(
|
|
label_box->parameters.text_box.text,
|
|
0x200,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x756);
|
|
if (label_box->parameters.text_box.text)
|
|
{
|
|
long labels_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\main_menu\\player_profiles_select\\profile_description_labels");
|
|
|
|
label_box->parameters.text_box.text[0] = 0;
|
|
if (labels_tag_index != NONE)
|
|
{
|
|
wchar_t const *label_text = unicode_string_list_get_string(
|
|
labels_tag_index,
|
|
5);
|
|
|
|
ustrncpy(
|
|
label_box->parameters.text_box.text,
|
|
label_text,
|
|
0xFF);
|
|
label_box->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void player_profile_3wide_list_update(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
long displayed_item_indices[3] = { NONE, NONE, NONE };
|
|
long profile_indices[3];
|
|
struct ui_widget_definition *definition = ui_widget_definition_get(
|
|
list_widget->definition_tag_index);
|
|
long item_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x78A,
|
|
definition->type == _ui_widget_type_spinner_list,
|
|
"expected a spinner list for 'player settings select' widget");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x78B,
|
|
definition->child_count == 3,
|
|
"expected 3 children (list items) for 'player settings select' widget");
|
|
|
|
spinner_list_3wide_determine_displayed_item_indices(
|
|
list_widget,
|
|
displayed_item_indices);
|
|
for (item_index = 0; item_index < 3; item_index++)
|
|
{
|
|
if (displayed_item_indices[item_index] != NONE)
|
|
{
|
|
profile_indices[item_index] = ((long *)list_widget->parameters.list.list_items)
|
|
[displayed_item_indices[item_index]];
|
|
}
|
|
else
|
|
profile_indices[item_index] = NONE;
|
|
}
|
|
player_profile_update_cache_for_nwide_list(profile_indices, 3);
|
|
|
|
for (item_index = 0;
|
|
item_index < 3 && displayed_item_indices[item_index] != NONE;
|
|
item_index++)
|
|
{
|
|
struct widget_instance *item = widget_instance_get_nth_child(
|
|
list_widget,
|
|
item_index);
|
|
struct widget_instance *profile_name;
|
|
struct widget_instance *color_picture;
|
|
struct widget_instance *description_fields;
|
|
struct widget_instance *empty_profile_label;
|
|
struct widget_instance *current_level_label;
|
|
struct widget_instance *current_level_text;
|
|
struct widget_instance *current_skill_label;
|
|
struct widget_instance *current_skill_text;
|
|
struct widget_instance *controls_label;
|
|
struct widget_instance *controls_text;
|
|
struct player_profile *profile = NULL;
|
|
long profile_index;
|
|
long cache_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7AF,
|
|
item && item->type == _ui_widget_type_bitmap,
|
|
"expected profile item description container widget");
|
|
|
|
profile_name = item->child;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7B2,
|
|
profile_name && profile_name->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for profile name");
|
|
color_picture = profile_name->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7B5,
|
|
color_picture && color_picture->type == _ui_widget_type_bitmap,
|
|
"expected a container widget for the profile color picture");
|
|
description_fields = color_picture->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7B8,
|
|
description_fields && description_fields->type == _ui_widget_type_bitmap,
|
|
"expected a container widget for the profile description fields");
|
|
|
|
empty_profile_label = description_fields->child;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7BB,
|
|
empty_profile_label && empty_profile_label->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the 'empty profile' label");
|
|
current_level_label = empty_profile_label->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7BE,
|
|
current_level_label && current_level_label->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the current level label");
|
|
current_level_text = current_level_label->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7C1,
|
|
current_level_text && current_level_text->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the current level text field");
|
|
current_skill_label = current_level_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7C4,
|
|
current_skill_label && current_skill_label->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the current skill level label");
|
|
current_skill_text = current_skill_label->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7C7,
|
|
current_skill_text && current_skill_text->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the profile's current skill level text field");
|
|
controls_label = current_skill_text->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7CA,
|
|
controls_label && controls_label->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the controls label");
|
|
controls_text = controls_label->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7CD,
|
|
controls_text && controls_text->type == _ui_widget_type_text_box,
|
|
"expected a text box widget for the controls text field");
|
|
|
|
profile_index = ((long *)list_widget->parameters.list.list_items)
|
|
[displayed_item_indices[item_index]];
|
|
if (profile_index != NONE)
|
|
{
|
|
for (cache_index = 0;
|
|
cache_index < (long)NUMBEROF(cached_player_profile);
|
|
cache_index++)
|
|
{
|
|
if (cached_player_profile[cache_index].profile_index == profile_index)
|
|
{
|
|
profile = &cached_player_profile[cache_index].profile;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (profile)
|
|
{
|
|
profile_name->visible = TRUE;
|
|
empty_profile_label->visible = FALSE;
|
|
current_level_label->visible = TRUE;
|
|
current_level_text->visible = TRUE;
|
|
current_skill_label->visible = TRUE;
|
|
current_skill_text->visible = TRUE;
|
|
controls_label->visible = TRUE;
|
|
controls_text->visible = TRUE;
|
|
|
|
profile_name->parameters.text_box.text = ui_widget_realloc(
|
|
profile_name->parameters.text_box.text,
|
|
0x18,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x7E7);
|
|
if (profile_name->parameters.text_box.text)
|
|
{
|
|
if (TEST_FLAG(profile->flags, _player_profile_default_profile_bit))
|
|
{
|
|
wchar_t const *name;
|
|
long default_name_index = profile->flags >> 8;
|
|
long names_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\strings\\default_player_profile_names");
|
|
if (names_tag_index != NONE)
|
|
{
|
|
name = unicode_string_list_get_string(
|
|
names_tag_index,
|
|
(short)default_name_index);
|
|
}
|
|
else
|
|
name = L"<unknown>";
|
|
ustrncpy(profile_name->parameters.text_box.text, name, 0xB);
|
|
profile_name->parameters.text_box.text[0xB] = 0;
|
|
}
|
|
else
|
|
{
|
|
ustrncpy(
|
|
profile_name->parameters.text_box.text,
|
|
profile->player_name,
|
|
0xB);
|
|
profile_name->parameters.text_box.text[0xB] = 0;
|
|
}
|
|
}
|
|
|
|
color_picture->animation.current_frame_index = (short)PIN(
|
|
profile->primary_color_index,
|
|
0,
|
|
player_profile_number_of_available_primary_colors() - 1);
|
|
|
|
if (TEST_FLAG(profile->flags, _player_profile_default_profile_bit))
|
|
{
|
|
current_level_text->visible = FALSE;
|
|
current_skill_text->visible = FALSE;
|
|
}
|
|
else
|
|
{
|
|
short highest_level;
|
|
short highest_difficulty;
|
|
|
|
player_profile_get_highest_completed_solo_level(
|
|
profile,
|
|
&highest_level,
|
|
&highest_difficulty);
|
|
highest_level = (short)MIN(highest_level + 1, 9);
|
|
current_level_text->parameters.text_box.string_list_index = highest_level;
|
|
current_skill_text->parameters.text_box.string_list_index = highest_difficulty;
|
|
controls_text->parameters.text_box.string_list_index =
|
|
profile->controller_settings.invert_look == TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
profile_name->visible = FALSE;
|
|
color_picture->animation.current_frame_index =
|
|
player_profile_number_of_available_primary_colors();
|
|
empty_profile_label->visible = TRUE;
|
|
current_level_label->visible = FALSE;
|
|
current_level_text->visible = FALSE;
|
|
current_skill_label->visible = FALSE;
|
|
current_skill_text->visible = FALSE;
|
|
controls_label->visible = FALSE;
|
|
controls_text->visible = FALSE;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void player_profile_1wide_list_update(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct widget_instance *name_bitmap;
|
|
struct widget_instance *profile_description;
|
|
struct player_profile *profile;
|
|
struct ui_widget_definition *definition;
|
|
long profile_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x85E,
|
|
list_widget->parent,
|
|
"expected qtr-screen profile select list to be wrapped in a container widget");
|
|
|
|
definition = ui_widget_definition_get(list_widget->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x864,
|
|
definition->type == _ui_widget_type_spinner_list,
|
|
"expected a spinner list for 'mp player settings select' widget");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x865,
|
|
definition->child_count == 0,
|
|
"expected 0 children (1-wide spinner) for 'mp player settings select' widget");
|
|
|
|
definition = ui_widget_definition_get(list_widget->parent->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x867,
|
|
definition->child_count == 3,
|
|
"expected qtr-screen profile select wrapper screen to have 3 child widgets (pic, description, list... in that order)");
|
|
|
|
name_bitmap = list_widget->parent->child;
|
|
profile_description = name_bitmap->next;
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x86D,
|
|
list_widget == profile_description->next,
|
|
"expected qtr-screen profile select wrapper screen to have 3 child widgets (pic, description, list... in that order)");
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x86F,
|
|
list_widget->parameters.list.selected_list_item_index >= 0 &&
|
|
list_widget->parameters.list.selected_list_item_index <
|
|
list_widget->parameters.list.number_of_items,
|
|
"qtr-screen profile list has invalid list item index");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x872,
|
|
list_widget->parameters.list.selected_list_item_index >= 0 &&
|
|
list_widget->parameters.list.selected_list_item_index <
|
|
list_widget->parameters.list.number_of_items,
|
|
"invalid list item index");
|
|
|
|
profile_index = ((long *)list_widget->parameters.list.list_items)
|
|
[list_widget->parameters.list.selected_list_item_index];
|
|
player_profile_update_cache_for_nwide_list(&profile_index, 1);
|
|
profile = NULL;
|
|
|
|
if (profile_index != NONE)
|
|
{
|
|
long cache_index;
|
|
|
|
for (cache_index = 0;
|
|
cache_index < (long)NUMBEROF(cached_player_profile);
|
|
cache_index++)
|
|
{
|
|
if (cached_player_profile[cache_index].profile_index == profile_index)
|
|
{
|
|
profile = &cached_player_profile[cache_index].profile;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (profile)
|
|
{
|
|
list_widget->parameters.list.item_text = ui_widget_realloc(
|
|
list_widget->parameters.list.item_text,
|
|
0x18,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x886);
|
|
if (list_widget->parameters.list.item_text)
|
|
{
|
|
if (TEST_FLAG(profile->flags, _player_profile_default_profile_bit))
|
|
{
|
|
long default_name_index = profile->flags >> 8;
|
|
long names_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\strings\\default_player_profile_names");
|
|
wchar_t const *profile_name = L"";
|
|
|
|
if (names_tag_index != NONE)
|
|
{
|
|
profile_name = unicode_string_list_get_string(
|
|
names_tag_index,
|
|
(short)default_name_index);
|
|
}
|
|
|
|
ustrncpy(list_widget->parameters.list.item_text, profile_name, 0xB);
|
|
list_widget->parameters.list.item_text[0xB] = 0;
|
|
}
|
|
else
|
|
{
|
|
ustrncpy(list_widget->parameters.list.item_text, profile->player_name, 0xB);
|
|
list_widget->parameters.list.item_text[0xB] = 0;
|
|
}
|
|
|
|
name_bitmap->animation.current_frame_index = (short)PIN(
|
|
profile->primary_color_index,
|
|
0,
|
|
player_profile_number_of_available_primary_colors() - 1);
|
|
|
|
profile_description->parameters.text_box.text = ui_widget_realloc(
|
|
profile_description->parameters.text_box.text,
|
|
0x200,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x89C);
|
|
if (profile_description->parameters.text_box.text)
|
|
{
|
|
if (TEST_FLAG(profile->flags, _player_profile_default_profile_bit))
|
|
{
|
|
long joystick_descriptions_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\main_menu\\player_profiles_select\\joystick_set_defaults_descriptions");
|
|
long button_descriptions_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\main_menu\\player_profiles_select\\button_set_long_descriptions");
|
|
|
|
if (joystick_descriptions_tag_index != NONE &&
|
|
button_descriptions_tag_index != NONE)
|
|
{
|
|
wchar_t const *joystick_description = unicode_string_list_get_string(
|
|
joystick_descriptions_tag_index,
|
|
profile->controller_settings.joystick_preset);
|
|
wchar_t const *button_description = unicode_string_list_get_string(
|
|
button_descriptions_tag_index,
|
|
profile->controller_settings.button_preset);
|
|
|
|
usnprintf(
|
|
profile_description->parameters.text_box.text,
|
|
0xFF,
|
|
L"%s%hs%s",
|
|
joystick_description,
|
|
"\r\n",
|
|
button_description);
|
|
profile_description->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
else
|
|
profile_description->parameters.text_box.text[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
long joystick_descriptions_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\main_menu\\player_profiles_select\\joystick_set_short_descriptions");
|
|
long button_descriptions_tag_index = tag_loaded(
|
|
UNICODE_STRING_LIST_TAG,
|
|
"ui\\shell\\main_menu\\player_profiles_select\\button_set_short_descriptions");
|
|
|
|
if (joystick_descriptions_tag_index != NONE &&
|
|
button_descriptions_tag_index != NONE)
|
|
{
|
|
wchar_t const *joystick_description = unicode_string_list_get_string(
|
|
joystick_descriptions_tag_index,
|
|
profile->controller_settings.joystick_preset);
|
|
wchar_t const *button_description = unicode_string_list_get_string(
|
|
button_descriptions_tag_index,
|
|
profile->controller_settings.button_preset);
|
|
|
|
usnprintf(
|
|
profile_description->parameters.text_box.text,
|
|
0xFF,
|
|
L"%s%hs%s",
|
|
joystick_description,
|
|
"\r\n",
|
|
button_description);
|
|
}
|
|
}
|
|
|
|
profile_description->parameters.text_box.text[0xFF] = 0;
|
|
}
|
|
}
|
|
}
|
|
else if (list_widget->parameters.list.number_of_items > 0)
|
|
{
|
|
list_widget->parameters.list.number_of_items = (word)filter_invalid_list_indices(
|
|
(long *)list_widget->parameters.list.list_items,
|
|
list_widget->parameters.list.number_of_items);
|
|
list_widget->parameters.list.selected_list_item_index = (short)PIN(
|
|
list_widget->parameters.list.selected_list_item_index,
|
|
0,
|
|
list_widget->parameters.list.number_of_items - 1);
|
|
player_profile_1wide_list_update(list_widget);
|
|
}
|
|
else
|
|
{
|
|
list_widget->parameters.list.item_text = ui_widget_realloc(
|
|
list_widget->parameters.list.item_text,
|
|
4,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x8D2);
|
|
if (list_widget->parameters.list.item_text)
|
|
list_widget->parameters.list.item_text[0] = 0;
|
|
|
|
name_bitmap->animation.current_frame_index = 0;
|
|
profile_description->parameters.text_box.text = ui_widget_realloc(
|
|
profile_description->parameters.text_box.text,
|
|
4,
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x8D7);
|
|
if (profile_description->parameters.text_box.text)
|
|
profile_description->parameters.text_box.text[0] = 0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void solo_level_select_list_update_displayed_items(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct player_profile profile;
|
|
short highest_level;
|
|
short highest_difficulty;
|
|
struct ui_widget_definition *definition;
|
|
long item_index;
|
|
long displayed_item_indices[3];
|
|
|
|
player_ui_get_active_player_profile(0, &profile);
|
|
player_profile_get_highest_completed_solo_level(
|
|
&profile,
|
|
&highest_level,
|
|
&highest_difficulty);
|
|
|
|
definition = ui_widget_definition_get(list_widget->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x1E0,
|
|
definition->type == _ui_widget_type_spinner_list,
|
|
"expected a spinner list for 'level select' widget");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x1E1,
|
|
definition->child_count == 3,
|
|
"expected 3 children (list items) for 'level select' widget");
|
|
|
|
spinner_list_3wide_determine_displayed_item_indices(
|
|
list_widget,
|
|
displayed_item_indices);
|
|
|
|
for (item_index = 0; item_index < 3; item_index++)
|
|
{
|
|
struct widget_instance *item;
|
|
struct widget_instance *map_name;
|
|
struct widget_instance *map_bitmap;
|
|
struct widget_instance *map_description;
|
|
struct widget_instance *completion_marker;
|
|
struct widget_instance *difficulty_marker;
|
|
struct widget_instance *cooperative_marker;
|
|
|
|
if (displayed_item_indices[item_index] == NONE)
|
|
break;
|
|
|
|
item = widget_instance_get_nth_child(
|
|
list_widget,
|
|
item_index);
|
|
map_name = item->child;
|
|
map_bitmap = map_name->next;
|
|
map_description = map_bitmap->next;
|
|
completion_marker = map_description->next;
|
|
difficulty_marker = completion_marker->next;
|
|
cooperative_marker = difficulty_marker->next;
|
|
|
|
definition = ui_widget_definition_get(item->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x1F6,
|
|
definition->child_count,
|
|
"expected 3 children in solo level list item (name, pic, desc)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x1F8,
|
|
ui_widget_definition_get(map_name->definition_tag_index)->type ==
|
|
_ui_widget_type_text_box,
|
|
"expected a text box widget for the list item's first child (map name)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x1FA,
|
|
ui_widget_definition_get(map_bitmap->definition_tag_index)->type ==
|
|
_ui_widget_type_bitmap,
|
|
"expected a container widget for the list item's second child (map pic)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x1FC,
|
|
ui_widget_definition_get(map_description->definition_tag_index)->type ==
|
|
_ui_widget_type_text_box,
|
|
"expected a text box widget for the list item's third child (map description)");
|
|
|
|
completion_marker->animation.current_frame_index = 1;
|
|
difficulty_marker->animation.current_frame_index = 2;
|
|
cooperative_marker->animation.current_frame_index = 3;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x204,
|
|
displayed_item_indices[item_index] >= 0 &&
|
|
displayed_item_indices[item_index] < 10,
|
|
"(displayed_item_index[i]>=0) && (displayed_item_index[i]<NUMBER_OF_SINGLE_PLAYER_LEVELS)");
|
|
|
|
if (!single_player_level_data[displayed_item_indices[item_index]].available &&
|
|
!single_player_level_data[displayed_item_indices[item_index]].completion_marker &&
|
|
!single_player_level_data[displayed_item_indices[item_index]].difficulty_marker &&
|
|
!single_player_level_data[displayed_item_indices[item_index]].cooperative_marker)
|
|
{
|
|
map_name->parameters.text_box.string_list_index = 10;
|
|
map_bitmap->animation.current_frame_index = 10;
|
|
map_description->parameters.text_box.string_list_index = 10;
|
|
completion_marker->visible = FALSE;
|
|
difficulty_marker->visible = FALSE;
|
|
cooperative_marker->visible = FALSE;
|
|
}
|
|
else
|
|
{
|
|
map_name->parameters.text_box.string_list_index =
|
|
(short)displayed_item_indices[item_index];
|
|
map_bitmap->animation.current_frame_index =
|
|
(short)displayed_item_indices[item_index];
|
|
map_description->parameters.text_box.string_list_index =
|
|
(short)displayed_item_indices[item_index];
|
|
|
|
if (persistant_game_data_info.valid == TRUE &&
|
|
displayed_item_indices[item_index] ==
|
|
(char)persistant_game_data_info.map_index)
|
|
{
|
|
map_description->parameters.text_box.string_list_index = 11;
|
|
}
|
|
|
|
completion_marker->visible = single_player_level_data[
|
|
displayed_item_indices[item_index]].completion_marker;
|
|
difficulty_marker->visible = single_player_level_data[
|
|
displayed_item_indices[item_index]].difficulty_marker;
|
|
cooperative_marker->visible = single_player_level_data[
|
|
displayed_item_indices[item_index]].cooperative_marker;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void player_profile_color_picker_update(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct ui_widget_definition *definition;
|
|
long displayed_item_indices[3];
|
|
long item_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x944,
|
|
list_widget->parameters.list.list_items,
|
|
"no list items associated with color picker!");
|
|
|
|
definition = ui_widget_definition_get(list_widget->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x949,
|
|
definition->type == _ui_widget_type_spinner_list,
|
|
"expected a spinner list for 'player color picker' widget");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x94A,
|
|
definition->child_count == 3,
|
|
"expected 3 children (list items) for 'player color picker' widget");
|
|
|
|
spinner_list_3wide_determine_displayed_item_indices(
|
|
list_widget,
|
|
displayed_item_indices);
|
|
|
|
for (item_index = 0;
|
|
item_index < 3 &&
|
|
displayed_item_indices[item_index] != NONE;
|
|
item_index++)
|
|
{
|
|
struct widget_instance *item = widget_instance_get_nth_child(
|
|
list_widget,
|
|
item_index);
|
|
struct widget_instance *text_box = item->child;
|
|
struct widget_instance *bitmap = text_box->next;
|
|
short color_index;
|
|
|
|
definition = ui_widget_definition_get(item->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x95B,
|
|
definition->child_count == 2,
|
|
"expected 2 children in player color picker list item (name, pic)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x95D,
|
|
ui_widget_definition_get(text_box->definition_tag_index)->type ==
|
|
_ui_widget_type_text_box,
|
|
"expected a text box widget for the list item's first child (color name)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x95F,
|
|
ui_widget_definition_get(bitmap->definition_tag_index)->type ==
|
|
_ui_widget_type_bitmap,
|
|
"expected a container widget for the list item's second child (color pic)");
|
|
|
|
color_index = ((byte *)list_widget->parameters.list.list_items)
|
|
[displayed_item_indices[item_index]];
|
|
text_box->parameters.text_box.string_list_index = color_index;
|
|
bitmap->animation.current_frame_index = color_index;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static void mp_level_select_list_update_displayed_items(
|
|
struct widget_instance *list_widget)
|
|
{
|
|
struct ui_widget_definition *definition = ui_widget_definition_get(
|
|
list_widget->definition_tag_index);
|
|
long displayed_item_indices[3];
|
|
long item_index;
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9BF,
|
|
definition->type == _ui_widget_type_spinner_list,
|
|
"expected a spinner list for 'level select' widget");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9C0,
|
|
definition->child_count == 3,
|
|
"expected 3 children (list items) for 'level select' widget");
|
|
|
|
spinner_list_3wide_determine_displayed_item_indices(
|
|
list_widget,
|
|
displayed_item_indices);
|
|
|
|
for (item_index = 0;
|
|
item_index < 3 &&
|
|
displayed_item_indices[item_index] != NONE;
|
|
item_index++)
|
|
{
|
|
struct widget_instance *item = widget_instance_get_nth_child(
|
|
list_widget,
|
|
item_index);
|
|
struct widget_instance *map_name = item->child;
|
|
struct widget_instance *map_bitmap = map_name->next;
|
|
struct widget_instance *map_description = map_bitmap->next;
|
|
|
|
definition = ui_widget_definition_get(item->definition_tag_index);
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9D2,
|
|
definition->child_count,
|
|
"expected 3 children in solo level list item (name, pic, desc)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9D4,
|
|
ui_widget_definition_get(map_name->definition_tag_index)->type ==
|
|
_ui_widget_type_text_box,
|
|
"expected a text box widget for the list item's first child (map name)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9D6,
|
|
ui_widget_definition_get(map_bitmap->definition_tag_index)->type ==
|
|
_ui_widget_type_bitmap,
|
|
"expected a container widget for the list item's second child (map pic)");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
|
|
0x9D8,
|
|
ui_widget_definition_get(map_description->definition_tag_index)->type ==
|
|
_ui_widget_type_text_box,
|
|
"expected a text box widget for the list item's third child (map description)");
|
|
|
|
/* port: the Custom Edition maps after the Xbox levels show their own
|
|
names, pictures and descriptions (port/linux/game/custom_edition_maps.c) */
|
|
displayed_item_indices[item_index] = custom_edition_maps_level_display_index(
|
|
(short)displayed_item_indices[item_index]);
|
|
map_name->parameters.text_box.string_list_index =
|
|
(short)displayed_item_indices[item_index];
|
|
map_bitmap->animation.current_frame_index =
|
|
(short)displayed_item_indices[item_index];
|
|
map_description->parameters.text_box.string_list_index =
|
|
(short)displayed_item_indices[item_index];
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static int list_indices_sort_proc(
|
|
void const *index1,
|
|
void const *index2)
|
|
{
|
|
long first = *(long const *)index1;
|
|
long second = *(long const *)index2;
|
|
|
|
if (first == NONE)
|
|
{
|
|
if (second != first)
|
|
return 1;
|
|
}
|
|
else if (second == NONE)
|
|
return second;
|
|
return 0;
|
|
}
|
|
|
|
static long filter_invalid_list_indices(
|
|
long *indices,
|
|
long number_of_items)
|
|
{
|
|
long count;
|
|
|
|
qsort(indices, number_of_items, sizeof(long), list_indices_sort_proc);
|
|
for (count = 0; count < number_of_items; count++)
|
|
{
|
|
if (indices[count] == NONE)
|
|
break;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/* ---------- callback table */
|
|
|
|
static ui_widget_game_data_function game_data_input_function_list[41] =
|
|
{
|
|
widget_function_null,
|
|
settings_menu_update_extended_description,
|
|
widget_function_null,
|
|
playlist_settings_menu_update_extended_description,
|
|
playlist_gametype_select_menu_update_extended_description,
|
|
multiplayer_type_menu_update_extended_description,
|
|
solo_level_select_list_update_displayed_items,
|
|
difficulty_select_menu_update_extended_description,
|
|
set_textbox_to_build_number,
|
|
server_list_menu_update,
|
|
network_pregame_status_screen_update,
|
|
splitscreen_pregame_status_screen_update,
|
|
netgame_prejoin_players,
|
|
mutliplayer_settings_select_list_update_displayed_items,
|
|
player_profile_3wide_list_update,
|
|
player_profile_edit_select_menu_update_extended_description,
|
|
player_profile_1wide_list_update,
|
|
game_options_menu_update_text_desc,
|
|
solo_game_objective_text,
|
|
player_profile_color_picker_update,
|
|
game_options_menu_update_pic_desc,
|
|
main_menu_animation_fakery,
|
|
mp_level_select_list_update_displayed_items,
|
|
get_active_player_profile_display_name,
|
|
get_editable_player_profile_display_name,
|
|
get_editable_playlist_profile_display_name,
|
|
get_active_player_profile_color_index,
|
|
multiplayer_game_set_text_box_for_map_name,
|
|
multiplayer_game_set_text_box_for_game_ruleset,
|
|
multiplayer_game_set_text_box_for_teams_noteams,
|
|
multiplayer_game_set_text_box_for_score_limit,
|
|
multiplayer_game_set_text_box_for_score_limit_type,
|
|
multiplayer_game_set_bitmap_for_map,
|
|
multiplayer_game_set_bitmap_for_ruleset,
|
|
multiplayer_game_set_text_box_for_number_of_players,
|
|
multiplayer_edit_profile_set_ruleset_textbox_string_index,
|
|
system_link_status_check,
|
|
multiplayer_game_directions,
|
|
teams_no_teams_mp_game_bitmap_update,
|
|
warn_if_difficulty_will_nuke_saved_game,
|
|
dim_if_no_system_link_cable,
|
|
};
|