/* 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 = 0; 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; } } 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 = 0; 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; } } 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) { /* port: one machine and one player may start (server_alone) */ boolean waiting_for_machines = !network_game_is_splitscreen_local() && game && game->machine_count < 1; if (!waiting_for_machines && network_game_is_splitscreen_local() && game && game->player_count < 1) { 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""; 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]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, };