Files
Cesarus85--ringfall-mjolnir-vr/source/interface/ui_widget_game_data_input_functions.c
T
xshxdex98 60cd1254d6 Fix the decompiled code's latent bugs, and say plainly what is kept
Uninitialised locals get values (debug vertex, datastore result, index
buffer, map tool direction, AI entry points, escape alignment, grenade aim
from a vehicle, game options descriptions, unreachable switch arms), the
AI's squad and platoon records move whole, a speech cause point is read,
the geosphere's out-of-memory path frees itself, a console cond clause
without a result is refused, and the crash reporter rejects truncated map
files. Gameplay the original game has, kept so it plays the same, is noted
in a line rather than a page.

(cherry picked from commit 75afc4a1e57af2ba697e8be0e33b2afeee7639f8)
2026-10-10 12:53:22 +13:00

4343 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 = 0;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x8F5,
widget->type == _ui_widget_type_column_list,
"expected column list for multiplayer game options list");
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x8F8,
widget->parameters.list.extended_description &&
widget->parameters.list.extended_description->type == _ui_widget_type_text_box,
"expected a text box for multiplayer game options list extended description");
definition = ui_widget_definition_get(widget->definition_tag_index);
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x8FE,
definition->child_count > 0,
"expected some list items for multiplayer game settings list");
extended_description = widget->parameters.list.extended_description;
if (widget->focused_child)
{
description_index = 0;
column = widget->child;
while (column)
{
spinner_list = column->child;
while (spinner_list && spinner_list->type != _ui_widget_type_spinner_list)
spinner_list = spinner_list->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x90C,
spinner_list,
"expected a spinner list somewhere in the multiplayer game options settings list item makeup");
if (column == widget->focused_child)
{
/* port: an extra item's own description (ui_widget.c) */
short extra_description = ui_widget_spinner_extra_description(spinner_list,
spinner_list->parameters.list.selected_list_item_index);
if (extra_description != NONE)
{
widget->parameters.list.extended_description->parameters.text_box.string_list_index =
extra_description;
return;
}
description_index += spinner_list->parameters.list.selected_list_item_index;
break;
}
/* port: only the items of a spinner's string list's own have
descriptions in its tag */
description_index += ui_widget_spinner_own_item_count(spinner_list);
column = column->next;
}
}
extended_description->parameters.text_box.string_list_index = (short)description_index;
return;
}
static void game_options_menu_update_pic_desc(
struct widget_instance *widget)
{
struct widget_instance *column;
struct widget_instance *extended_description;
struct widget_instance *spinner_list;
struct ui_widget_definition *definition;
long description_index = 0;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x980,
widget->type == _ui_widget_type_column_list,
"expected column list for game options list");
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x983,
widget->parameters.list.extended_description &&
widget->parameters.list.extended_description->type == _ui_widget_type_bitmap,
"expected a picture (container) for game options list extended description");
definition = ui_widget_definition_get(widget->definition_tag_index);
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x988,
definition->child_count > 0,
"expected some list items for game settings list");
extended_description = widget->parameters.list.extended_description;
if (widget->focused_child)
{
description_index = 0;
column = widget->child;
while (column)
{
spinner_list = column->child;
while (spinner_list && spinner_list->type != _ui_widget_type_spinner_list)
spinner_list = spinner_list->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x996,
spinner_list,
"expected a spinner list somewhere in the multiplayer game options settings list item makeup");
if (column == widget->focused_child)
{
/* port: an extra item shows its spinner's last picture of its own */
description_index += MIN(spinner_list->parameters.list.selected_list_item_index,
ui_widget_spinner_own_item_count(spinner_list) - 1);
break;
}
description_index += ui_widget_spinner_own_item_count(spinner_list);
column = column->next;
}
}
extended_description->animation.current_frame_index = (short)description_index;
return;
}
static void multiplayer_game_set_text_box_for_map_name(
struct widget_instance *widget)
{
struct network_game *game;
char const *map_name;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xA39,
widget->type == _ui_widget_type_text_box,
"expected text box widget for mp game settings text");
game = network_game_get_game();
if (game)
{
map_name = game->map.name;
/* port: a Custom Edition map shows its own name */
if (custom_edition_map_display_index(map_name) != NONE)
{
widget->parameters.text_box.string_list_index = custom_edition_map_display_index(map_name);
return;
}
if (strstr(map_name, "beavercreek"))
{
widget->parameters.text_box.string_list_index = 0;
return;
}
if (strstr(map_name, "sidewinder"))
{
widget->parameters.text_box.string_list_index = 1;
return;
}
if (strstr(map_name, "damnation"))
{
widget->parameters.text_box.string_list_index = 2;
return;
}
if (strstr(map_name, "ratrace"))
{
widget->parameters.text_box.string_list_index = 3;
return;
}
if (strstr(map_name, "prisoner"))
{
widget->parameters.text_box.string_list_index = 4;
return;
}
if (strstr(map_name, "hangemhigh"))
{
widget->parameters.text_box.string_list_index = 5;
return;
}
if (strstr(map_name, "chillout"))
{
widget->parameters.text_box.string_list_index = 6;
return;
}
if (strstr(map_name, "carousel"))
{
widget->parameters.text_box.string_list_index = 7;
return;
}
if (strstr(map_name, "boardingaction"))
{
widget->parameters.text_box.string_list_index = 8;
return;
}
if (strstr(map_name, "bloodgulch"))
{
widget->parameters.text_box.string_list_index = 9;
return;
}
if (strstr(map_name, "wizard"))
{
widget->parameters.text_box.string_list_index = 10;
return;
}
if (strstr(map_name, "putput"))
{
widget->parameters.text_box.string_list_index = 11;
return;
}
widget->parameters.text_box.string_list_index = strstr(map_name, "longest") ? 12 : 13;
return;
}
error(2, "no network game");
return;
}
static void multiplayer_game_set_text_box_for_game_ruleset(
struct widget_instance *widget)
{
struct network_game *game;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xA59,
widget->type == _ui_widget_type_text_box,
"expected text box widget for mp game settings text");
game = network_game_get_game();
if (game)
{
switch (game->variant.game_engine_index)
{
case game_engine_ctf:
if (game->variant.game_engine_variant.ctf.assault == TRUE)
{
widget->parameters.text_box.string_list_index =
game->variant.game_engine_variant.ctf.single_flag_time ?
_multiplayer_game_text_string_single_flag_assault :
_multiplayer_game_text_string_assault;
}
else
{
widget->parameters.text_box.string_list_index =
game->variant.game_engine_variant.ctf.single_flag_time ?
_multiplayer_game_text_string_single_flag_ctf :
_multiplayer_game_text_string_capture_the_flag;
}
break;
case game_engine_slayer:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_slayer;
break;
case game_engine_oddball:
switch (game->variant.game_engine_variant.oddball.oddball_ball_type)
{
case 1:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_reverse_tag;
break;
case 2:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_juggernaut;
break;
default:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_oddball;
break;
}
break;
case game_engine_king:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_king_of_the_hill;
break;
case game_engine_race:
switch (game->variant.game_engine_variant.race.race_type)
{
case 2:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_rally;
break;
default:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_race;
break;
}
break;
default:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_unknown_game_type;
break;
}
return;
}
error(2, "no network game");
return;
}
static void multiplayer_game_set_text_box_for_teams_noteams(
struct widget_instance *widget)
{
struct network_game *game;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xAAA,
widget->type == _ui_widget_type_text_box,
"expected text box widget for mp game settings text");
game = network_game_get_game();
if (game)
{
widget->parameters.text_box.string_list_index = game->variant.universal_variant.teams != TRUE ? 13 : 12;
return;
}
error(2, "no network game");
return;
}
static void multiplayer_game_set_text_box_for_score_limit(
struct widget_instance *widget)
{
struct network_game *game;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xAC3,
widget->type == _ui_widget_type_text_box,
"expected text box widget for mp game settings text");
game = network_game_get_game();
if (game)
{
widget->parameters.text_box.text = ui_widget_realloc(
widget->parameters.text_box.text,
0x10,
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xAC8);
if (widget->parameters.text_box.text)
{
usnprintf(widget->parameters.text_box.text, 7, L"%d", game->variant.universal_variant.score_to_win);
widget->parameters.text_box.text[7] = 0;
}
return;
}
error(2, "no network game");
return;
}
static void multiplayer_game_set_text_box_for_score_limit_type(
struct widget_instance *widget)
{
struct network_game *game;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xADC,
widget->type == _ui_widget_type_text_box,
"expected text box widget for mp game settings text");
game = network_game_get_game();
if (game)
{
switch (game->variant.game_engine_index)
{
case game_engine_ctf:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_captures;
break;
case game_engine_slayer:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_frags;
break;
case game_engine_oddball:
widget->parameters.text_box.string_list_index = game->variant.game_engine_variant.oddball.oddball_ball_type == 2 ?
_multiplayer_game_text_string_frags : _multiplayer_game_text_string_minutes;
break;
case game_engine_king:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_minutes;
break;
case game_engine_race:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_laps;
break;
default:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_frags;
break;
}
return;
}
error(2, "no network game");
return;
}
static void multiplayer_game_set_bitmap_for_map(
struct widget_instance *widget)
{
struct network_game *game;
char const *map_name;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xB09,
widget->type == _ui_widget_type_bitmap,
"expected container widget for mp game settings bitmap");
game = network_game_get_game();
if (game)
{
map_name = game->map.name;
/* port: a Custom Edition map shows its own picture */
if (custom_edition_map_display_index(map_name) != NONE)
{
widget->animation.current_frame_index = custom_edition_map_display_index(map_name);
return;
}
if (strstr(map_name, "beavercreek"))
{
widget->animation.current_frame_index = 0;
return;
}
if (strstr(map_name, "sidewinder"))
{
widget->animation.current_frame_index = 1;
return;
}
if (strstr(map_name, "damnation"))
{
widget->animation.current_frame_index = 2;
return;
}
if (strstr(map_name, "ratrace"))
{
widget->animation.current_frame_index = 3;
return;
}
if (strstr(map_name, "prisoner"))
{
widget->animation.current_frame_index = 4;
return;
}
if (strstr(map_name, "hangemhigh"))
{
widget->animation.current_frame_index = 5;
return;
}
if (strstr(map_name, "chillout"))
{
widget->animation.current_frame_index = 6;
return;
}
if (strstr(map_name, "carousel"))
{
widget->animation.current_frame_index = 7;
return;
}
if (strstr(map_name, "boardingaction"))
{
widget->animation.current_frame_index = 8;
return;
}
if (strstr(map_name, "bloodgulch"))
{
widget->animation.current_frame_index = 9;
return;
}
if (strstr(map_name, "wizard"))
{
widget->animation.current_frame_index = 10;
return;
}
if (strstr(map_name, "putput"))
{
widget->animation.current_frame_index = 11;
return;
}
widget->animation.current_frame_index = strstr(map_name, "longest") ? 12 : 13;
return;
}
error(2, "no network game");
return;
}
static void multiplayer_game_set_bitmap_for_ruleset(
struct widget_instance *widget)
{
struct network_game *game;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xB28,
widget->type == _ui_widget_type_bitmap,
"expected container widget for mp game settings bitmap");
game = network_game_get_game();
if (game)
{
switch (game->variant.game_engine_index)
{
case game_engine_ctf:
widget->animation.current_frame_index = _multiplayer_game_bitmap_ctf;
break;
case game_engine_slayer:
widget->animation.current_frame_index = _multiplayer_game_bitmap_slayer;
break;
case game_engine_oddball:
widget->animation.current_frame_index = _multiplayer_game_bitmap_oddball;
break;
case game_engine_king:
widget->animation.current_frame_index = _multiplayer_game_bitmap_king;
break;
case game_engine_race:
widget->animation.current_frame_index = _multiplayer_game_bitmap_race;
break;
default:
widget->animation.current_frame_index = _multiplayer_game_bitmap_unknown;
break;
}
return;
}
error(2, "no network game");
return;
}
static void multiplayer_game_set_text_box_for_number_of_players(
struct widget_instance *widget)
{
struct network_game *game;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xB4E,
widget->type == _ui_widget_type_text_box,
"expected text box widget for mp game settings text");
game = network_game_get_game();
if (game)
{
widget->parameters.text_box.text = ui_widget_realloc(
widget->parameters.text_box.text,
8,
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xB56);
if (widget->parameters.text_box.text)
{
/* room for a three-digit count: the Linux runtime's _vsnwprintf
writes its terminator inside the count */
usnprintf(widget->parameters.text_box.text, 4, L"%d", game->player_count);
widget->parameters.text_box.text[3] = 0;
}
return;
}
error(2, "no network game");
return;
}
static void multiplayer_edit_profile_set_ruleset_textbox_string_index(
struct widget_instance *widget)
{
struct game_variant *profile;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xB69,
widget->type == _ui_widget_type_text_box,
"expected a text box widget for mp profile edit ruleset text widget");
profile = player_ui_get_edit_playlist_profile();
if (profile)
{
switch (profile->game_engine_index)
{
case game_engine_ctf:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_capture_the_flag;
break;
case game_engine_slayer:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_slayer;
break;
case game_engine_oddball:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_oddball;
break;
case game_engine_king:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_king_of_the_hill;
break;
case game_engine_race:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_race;
break;
default:
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_unknown_game_type;
break;
}
return;
}
error(2, "not currently editing a game variant");
return;
}
static void system_link_status_check(
struct widget_instance *widget)
{
(void)widget;
if (!transport_network_available() && !network_game_is_splitscreen_local())
{
display_error_when_main_menu_loaded(_error_network_connection_lost);
main_goto_main_menu();
error(2, "network connection went down!");
}
return;
}
static void multiplayer_game_directions(
struct widget_instance *widget)
{
struct network_game *game = network_game_get_game();
struct network_game_server *server = global_network_game_server_get();
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xBAD,
widget->type == _ui_widget_type_text_box,
"expected text box widget for team game directions");
if (server)
{
/* port: one machine and one player may start (server_alone) */
boolean waiting_for_machines = !network_game_is_splitscreen_local() &&
game &&
game->machine_count < 1;
if (!waiting_for_machines &&
network_game_is_splitscreen_local() &&
game &&
game->player_count < 1)
{
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_waiting_for_player;
widget->visible = TRUE;
return;
}
if (waiting_for_machines)
{
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_waiting_for_machine;
widget->visible = TRUE;
return;
}
}
if (game &&
game->variant.universal_variant.teams == TRUE &&
network_game_client_get_seconds_to_game_start(global_network_game_client_get()) < 0)
{
long team_one_player_count = 0;
long team_zero_player_count = 0;
long player_index;
for (player_index = 0;
player_index < NUMBEROF(game->players);
player_index++)
{
if (network_player_is_valid(&game->players[player_index]))
{
switch (game->players[player_index].team_index)
{
case _team_red:
team_zero_player_count++;
break;
case _team_blue:
team_one_player_count++;
break;
}
}
}
if (team_zero_player_count && team_one_player_count)
{
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_teams_ready;
}
else
{
widget->parameters.text_box.string_list_index =
_multiplayer_game_text_string_waiting_for_teams;
}
widget->visible = TRUE;
return;
}
widget->visible = FALSE;
return;
}
static void teams_no_teams_mp_game_bitmap_update(
struct widget_instance *widget)
{
struct network_game *game = network_game_get_game();
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xBFC,
widget->type == _ui_widget_type_bitmap,
"expected a container bitmap for mp pregame header widget");
if (game)
widget->animation.current_frame_index = game->variant.universal_variant.teams != TRUE;
return;
}
static void warn_if_difficulty_will_nuke_saved_game(
struct widget_instance *difficulty_screen_widget)
{
struct widget_instance *difficulty_list = difficulty_screen_widget->child;
struct widget_instance *warning_widget;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xC1F,
difficulty_list && difficulty_list->type == _ui_widget_type_column_list,
"this doesn't look like the difficulty list widget");
warning_widget = difficulty_list->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xC23,
warning_widget && warning_widget->type == _ui_widget_type_text_box,
"this doesn't look like the difficulty list widget (expected warning text box)");
if (persistant_game_data_info.valid == TRUE &&
_stricmp(persistant_game_data_info.map_name, main_get_map_name()) == 0)
{
warning_widget->visible =
difficulty_list->parameters.list.selected_list_item_index !=
persistant_game_data_info.difficulty;
}
else
warning_widget->visible = FALSE;
return;
}
static void dim_if_no_system_link_cable(
struct widget_instance *widget)
{
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xC3C,
widget->type == _ui_widget_type_text_box,
"expected a text box widget for system link menu text item");
widget->alpha_modifier = transport_network_available() ? 1.0f : 0.333f;
return;
}
static void spinner_list_3wide_determine_displayed_item_indices(
struct widget_instance *list_widget,
long *displayed_item_indices)
{
struct widget_instance *focused_child = list_widget->focused_child;
struct widget_instance *first_child = list_widget->child;
if (focused_child == first_child)
{
displayed_item_indices[0] = list_widget->parameters.list.selected_list_item_index;
displayed_item_indices[1] = displayed_item_indices[0] + 1;
if (displayed_item_indices[1] == list_widget->parameters.list.number_of_items)
displayed_item_indices[1] = 0;
displayed_item_indices[2] = displayed_item_indices[1] + 1;
if (displayed_item_indices[2] == list_widget->parameters.list.number_of_items)
displayed_item_indices[2] = 0;
}
else if (focused_child == first_child->next)
{
displayed_item_indices[1] = list_widget->parameters.list.selected_list_item_index;
displayed_item_indices[0] = displayed_item_indices[1] - 1;
if (displayed_item_indices[0] < 0)
{
displayed_item_indices[0] =
list_widget->parameters.list.number_of_items - 1;
}
displayed_item_indices[2] = displayed_item_indices[1] + 1;
if (displayed_item_indices[2] == list_widget->parameters.list.number_of_items)
displayed_item_indices[2] = 0;
}
else
{
displayed_item_indices[2] = list_widget->parameters.list.selected_list_item_index;
displayed_item_indices[1] = displayed_item_indices[2] - 1;
if (displayed_item_indices[1] < 0)
{
displayed_item_indices[1] =
list_widget->parameters.list.number_of_items - 1;
}
displayed_item_indices[0] = displayed_item_indices[1] - 1;
if (displayed_item_indices[0] < 0)
{
displayed_item_indices[0] =
list_widget->parameters.list.number_of_items - 1;
}
}
if (displayed_item_indices[0] >= list_widget->parameters.list.number_of_items)
displayed_item_indices[0] = NONE;
if (displayed_item_indices[1] >= list_widget->parameters.list.number_of_items)
displayed_item_indices[1] = NONE;
if (displayed_item_indices[2] >= list_widget->parameters.list.number_of_items)
displayed_item_indices[2] = NONE;
return;
}
static void player_profile_update_cache_for_nwide_list(
long *profile_indices,
long profile_index_count)
{
boolean still_wanted[3] = { FALSE };
long cache_index;
long requested_index;
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_player_profile); cache_index++)
{
if (cached_player_profile[cache_index].profile_index == NONE)
continue;
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
{
if (cached_player_profile[cache_index].profile_index == profile_indices[requested_index])
{
still_wanted[cache_index] = TRUE;
break;
}
}
}
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
{
if (profile_indices[requested_index] == NONE)
continue;
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_player_profile); cache_index++)
{
if (profile_indices[requested_index] == cached_player_profile[cache_index].profile_index)
break;
}
if (cache_index == (long)NUMBEROF(cached_player_profile))
{
for (cache_index = 0; cache_index < (long)NUMBEROF(still_wanted); cache_index++)
{
if (still_wanted[cache_index] != TRUE)
break;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xCA2,
cache_index < (long)NUMBEROF(cached_player_profile),
"not enough cache profiles");
}
if (player_profile_get(
profile_indices[requested_index],
&cached_player_profile[cache_index].profile))
{
cached_player_profile[cache_index].profile_index = profile_indices[requested_index];
still_wanted[cache_index] = TRUE;
}
else
error(2, "failed to cache player profile");
}
}
return;
}
static void variant_profile_update_cache_for_nwide_list(
long *profile_indices,
long profile_index_count)
{
boolean still_wanted[3] = { FALSE };
long cache_index;
long requested_index;
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_variant_profile); cache_index++)
{
if (cached_variant_profile[cache_index].profile_index == NONE)
continue;
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
{
if (cached_variant_profile[cache_index].profile_index == profile_indices[requested_index])
{
still_wanted[cache_index] = TRUE;
break;
}
}
}
for (requested_index = 0; requested_index < profile_index_count; requested_index++)
{
if (profile_indices[requested_index] == NONE)
continue;
for (cache_index = 0; cache_index < (long)NUMBEROF(cached_variant_profile); cache_index++)
{
if (profile_indices[requested_index] == cached_variant_profile[cache_index].profile_index)
break;
}
if (cache_index == (long)NUMBEROF(cached_variant_profile))
{
for (cache_index = 0; cache_index < (long)NUMBEROF(still_wanted); cache_index++)
{
if (still_wanted[cache_index] != TRUE)
break;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0xCD5,
cache_index < (long)NUMBEROF(cached_variant_profile),
"not enough cache profiles");
}
if (playlist_profile_get(
profile_indices[requested_index],
(struct game_variant *)&cached_variant_profile[cache_index].profile))
{
cached_variant_profile[cache_index].profile_index = profile_indices[requested_index];
still_wanted[cache_index] = TRUE;
}
else
error(2, "failed to cache playlist profile");
}
}
return;
}
static void mutliplayer_settings_select_list_update_displayed_items(
struct widget_instance *list_widget)
{
long descriptions_tag_index = tag_loaded(
UNICODE_STRING_LIST_TAG,
"ui\\shell\\strings\\game_variant_descriptions");
struct ui_widget_definition *definition = ui_widget_definition_get(
list_widget->definition_tag_index);
long displayed_item_indices[3];
long profile_indices[3];
long item_index;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x67D,
definition->type == _ui_widget_type_spinner_list,
"expected a spinner list for 'multiplayer settings select' widget");
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x67E,
definition->child_count == 3,
"expected 3 children (list items) for 'multiplayer settings select' widget");
spinner_list_3wide_determine_displayed_item_indices(
list_widget,
displayed_item_indices);
for (item_index = 0; item_index < 3; item_index++)
{
if (displayed_item_indices[item_index] != NONE)
{
profile_indices[item_index] = ((long *)list_widget->parameters.list.list_items)
[displayed_item_indices[item_index]];
}
else
profile_indices[item_index] = NONE;
}
variant_profile_update_cache_for_nwide_list(
profile_indices,
NUMBEROF(profile_indices));
for (item_index = 0;
item_index < 3 &&
displayed_item_indices[item_index] != NONE;
item_index++)
{
struct widget_instance *item = widget_instance_get_nth_child(
list_widget,
item_index);
struct widget_instance *description_box = item->child;
struct widget_instance *icon = description_box->next;
struct widget_instance *label_box = icon->next;
struct widget_instance *description_container = label_box->next;
struct playlist_profile *profile = NULL;
long profile_index;
long cache_index;
definition = ui_widget_definition_get(item->definition_tag_index);
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x69E,
definition->child_count != 0,
"expected 3 children in multiplayer settings list item (name, pic, desc)");
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x6A0,
ui_widget_definition_get(description_box->definition_tag_index)->type ==
_ui_widget_type_text_box,
"expected a text box widget for the list item's first child (map name)");
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x6A2,
ui_widget_definition_get(icon->definition_tag_index)->type ==
_ui_widget_type_bitmap,
"expected a container widget for the list item's second child (map pic)");
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x6A4,
ui_widget_definition_get(label_box->definition_tag_index)->type ==
_ui_widget_type_text_box,
"expected a text box widget for the list item's third child (map description)");
profile_index = ((long *)list_widget->parameters.list.list_items)
[displayed_item_indices[item_index]];
if (profile_index != NONE)
{
for (cache_index = 0;
cache_index < (long)NUMBEROF(cached_variant_profile);
cache_index++)
{
if (cached_variant_profile[cache_index].profile_index == profile_index)
{
profile = &cached_variant_profile[cache_index].profile;
break;
}
}
}
description_container->visible = FALSE;
if (profile)
{
description_box->parameters.text_box.text = ui_widget_realloc(
description_box->parameters.text_box.text,
0x100,
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x6BA);
if (description_box->parameters.text_box.text)
{
ustrncpy(description_box->parameters.text_box.text, profile->name, 0x7F);
description_box->parameters.text_box.text[0x7F] = 0;
}
icon->animation.current_frame_index = _multiplayer_game_bitmap_unknown;
label_box->parameters.text_box.text = ui_widget_realloc(
label_box->parameters.text_box.text,
0x200,
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x6C1);
if (label_box->parameters.text_box.text)
label_box->parameters.text_box.text[0] = 0;
if (TEST_FLAG(profile->flags, 0))
{
long string_index = (profile->flags >> 8) + 10;
switch (profile->engine_type)
{
case game_engine_ctf:
icon->animation.current_frame_index = _multiplayer_game_bitmap_ctf;
break;
case game_engine_slayer:
icon->animation.current_frame_index = _multiplayer_game_bitmap_slayer;
break;
case game_engine_oddball:
icon->animation.current_frame_index = _multiplayer_game_bitmap_oddball;
break;
case game_engine_king:
icon->animation.current_frame_index = _multiplayer_game_bitmap_king;
break;
case game_engine_race:
icon->animation.current_frame_index = _multiplayer_game_bitmap_race;
break;
}
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(
descriptions_tag_index,
string_index),
0xFF);
label_box->parameters.text_box.text[0xFF] = 0;
}
description_container->visible = TRUE;
continue;
}
switch (profile->engine_type)
{
case game_engine_ctf:
icon->animation.current_frame_index = _multiplayer_game_bitmap_ctf;
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
{
if (profile->teams == TRUE)
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 1),
0xFF);
}
else
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 0),
0xFF);
}
label_box->parameters.text_box.text[0xFF] = 0;
}
break;
case game_engine_slayer:
icon->animation.current_frame_index = _multiplayer_game_bitmap_slayer;
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
{
if (profile->teams == TRUE)
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 3),
0xFF);
}
else
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 2),
0xFF);
}
label_box->parameters.text_box.text[0xFF] = 0;
}
break;
case game_engine_oddball:
icon->animation.current_frame_index = _multiplayer_game_bitmap_oddball;
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
{
if (profile->teams == TRUE)
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 5),
0xFF);
}
else
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 4),
0xFF);
}
label_box->parameters.text_box.text[0xFF] = 0;
}
break;
case game_engine_king:
icon->animation.current_frame_index = _multiplayer_game_bitmap_king;
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
{
if (profile->teams == TRUE)
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 7),
0xFF);
}
else
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 6),
0xFF);
}
label_box->parameters.text_box.text[0xFF] = 0;
}
break;
case game_engine_race:
icon->animation.current_frame_index = _multiplayer_game_bitmap_race;
if (descriptions_tag_index != NONE && label_box->parameters.text_box.text)
{
if (profile->teams == TRUE)
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 9),
0xFF);
}
else
{
ustrncpy(
label_box->parameters.text_box.text,
unicode_string_list_get_string(descriptions_tag_index, 8),
0xFF);
}
label_box->parameters.text_box.text[0xFF] = 0;
}
break;
}
continue;
}
description_box->parameters.text_box.text = ui_widget_realloc(
description_box->parameters.text_box.text,
0x100,
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x751);
if (description_box->parameters.text_box.text)
description_box->parameters.text_box.text[0] = 0;
icon->animation.current_frame_index = _multiplayer_game_bitmap_unknown;
label_box->parameters.text_box.text = ui_widget_realloc(
label_box->parameters.text_box.text,
0x200,
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x756);
if (label_box->parameters.text_box.text)
{
long labels_tag_index = tag_loaded(
UNICODE_STRING_LIST_TAG,
"ui\\shell\\main_menu\\player_profiles_select\\profile_description_labels");
label_box->parameters.text_box.text[0] = 0;
if (labels_tag_index != NONE)
{
wchar_t const *label_text = unicode_string_list_get_string(
labels_tag_index,
5);
ustrncpy(
label_box->parameters.text_box.text,
label_text,
0xFF);
label_box->parameters.text_box.text[0xFF] = 0;
}
}
}
return;
}
static void player_profile_3wide_list_update(
struct widget_instance *list_widget)
{
long displayed_item_indices[3] = { NONE, NONE, NONE };
long profile_indices[3];
struct ui_widget_definition *definition = ui_widget_definition_get(
list_widget->definition_tag_index);
long item_index;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x78A,
definition->type == _ui_widget_type_spinner_list,
"expected a spinner list for 'player settings select' widget");
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x78B,
definition->child_count == 3,
"expected 3 children (list items) for 'player settings select' widget");
spinner_list_3wide_determine_displayed_item_indices(
list_widget,
displayed_item_indices);
for (item_index = 0; item_index < 3; item_index++)
{
if (displayed_item_indices[item_index] != NONE)
{
profile_indices[item_index] = ((long *)list_widget->parameters.list.list_items)
[displayed_item_indices[item_index]];
}
else
profile_indices[item_index] = NONE;
}
player_profile_update_cache_for_nwide_list(profile_indices, 3);
for (item_index = 0;
item_index < 3 && displayed_item_indices[item_index] != NONE;
item_index++)
{
struct widget_instance *item = widget_instance_get_nth_child(
list_widget,
item_index);
struct widget_instance *profile_name;
struct widget_instance *color_picture;
struct widget_instance *description_fields;
struct widget_instance *empty_profile_label;
struct widget_instance *current_level_label;
struct widget_instance *current_level_text;
struct widget_instance *current_skill_label;
struct widget_instance *current_skill_text;
struct widget_instance *controls_label;
struct widget_instance *controls_text;
struct player_profile *profile = NULL;
long profile_index;
long cache_index;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7AF,
item && item->type == _ui_widget_type_bitmap,
"expected profile item description container widget");
profile_name = item->child;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7B2,
profile_name && profile_name->type == _ui_widget_type_text_box,
"expected a text box widget for profile name");
color_picture = profile_name->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7B5,
color_picture && color_picture->type == _ui_widget_type_bitmap,
"expected a container widget for the profile color picture");
description_fields = color_picture->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7B8,
description_fields && description_fields->type == _ui_widget_type_bitmap,
"expected a container widget for the profile description fields");
empty_profile_label = description_fields->child;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7BB,
empty_profile_label && empty_profile_label->type == _ui_widget_type_text_box,
"expected a text box widget for the 'empty profile' label");
current_level_label = empty_profile_label->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7BE,
current_level_label && current_level_label->type == _ui_widget_type_text_box,
"expected a text box widget for the current level label");
current_level_text = current_level_label->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7C1,
current_level_text && current_level_text->type == _ui_widget_type_text_box,
"expected a text box widget for the current level text field");
current_skill_label = current_level_text->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7C4,
current_skill_label && current_skill_label->type == _ui_widget_type_text_box,
"expected a text box widget for the current skill level label");
current_skill_text = current_skill_label->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7C7,
current_skill_text && current_skill_text->type == _ui_widget_type_text_box,
"expected a text box widget for the profile's current skill level text field");
controls_label = current_skill_text->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7CA,
controls_label && controls_label->type == _ui_widget_type_text_box,
"expected a text box widget for the controls label");
controls_text = controls_label->next;
match_vassert(
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7CD,
controls_text && controls_text->type == _ui_widget_type_text_box,
"expected a text box widget for the controls text field");
profile_index = ((long *)list_widget->parameters.list.list_items)
[displayed_item_indices[item_index]];
if (profile_index != NONE)
{
for (cache_index = 0;
cache_index < (long)NUMBEROF(cached_player_profile);
cache_index++)
{
if (cached_player_profile[cache_index].profile_index == profile_index)
{
profile = &cached_player_profile[cache_index].profile;
break;
}
}
}
if (profile)
{
profile_name->visible = TRUE;
empty_profile_label->visible = FALSE;
current_level_label->visible = TRUE;
current_level_text->visible = TRUE;
current_skill_label->visible = TRUE;
current_skill_text->visible = TRUE;
controls_label->visible = TRUE;
controls_text->visible = TRUE;
profile_name->parameters.text_box.text = ui_widget_realloc(
profile_name->parameters.text_box.text,
0x18,
"c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c",
0x7E7);
if (profile_name->parameters.text_box.text)
{
if (TEST_FLAG(profile->flags, _player_profile_default_profile_bit))
{
wchar_t const *name;
long default_name_index = profile->flags >> 8;
long names_tag_index = tag_loaded(
UNICODE_STRING_LIST_TAG,
"ui\\shell\\strings\\default_player_profile_names");
if (names_tag_index != NONE)
{
name = unicode_string_list_get_string(
names_tag_index,
(short)default_name_index);
}
else
name = L"<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,
};