Files
Cesarus85--ringfall-mjolnir-vr/source/interface/ui_widget_game_data_input_functions.c
T

4353 lines
138 KiB
C

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