mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-21 16:00:30 +02:00
1208 lines
29 KiB
C
1208 lines
29 KiB
C
/*
|
|
HUD_MESSAGING.C
|
|
|
|
symbols in this file:
|
|
000C3810 0080:
|
|
_render_state_text (0000)
|
|
000C3890 0190:
|
|
_render_state_bitmap (0000)
|
|
000C3A20 0020:
|
|
_hud_messaging_initialize (0000)
|
|
000C3A40 0030:
|
|
_hud_messaging_initialize_for_new_map (0000)
|
|
000C3A70 0010:
|
|
_hud_messaging_dispose_from_old_map (0000)
|
|
000C3A80 0010:
|
|
_hud_messaging_dispose (0000)
|
|
000C3A90 0050:
|
|
_scripted_hud_set_state_message (0000)
|
|
000C3AE0 0040:
|
|
_scripted_hud_set_flashing_state (0000)
|
|
000C3B20 0040:
|
|
_scripted_hud_restart_flashing (0000)
|
|
000C3B60 00a0:
|
|
_scripted_hud_set_objective (0000)
|
|
000C3C00 0080:
|
|
_scripted_hud_set_timer_time (0000)
|
|
000C3C80 0020:
|
|
_scripted_hud_set_timer_warning_cutoff (0000)
|
|
000C3CA0 0060:
|
|
_scripted_hud_set_timer_position (0000)
|
|
000C3D00 0020:
|
|
_scripted_hud_show_timer (0000)
|
|
000C3D20 0050:
|
|
_scripted_hud_pause_timer (0000)
|
|
000C3D70 0050:
|
|
_scripted_hud_get_timer_ticks (0000)
|
|
000C3DC0 0030:
|
|
_scripted_hud_time_code_show (0000)
|
|
000C3DF0 0040:
|
|
_scripted_hud_time_code_start (0000)
|
|
000C3E30 0020:
|
|
_scripted_hud_time_code_reset (0000)
|
|
000C3E50 02c0:
|
|
_hud_render_timer (0000)
|
|
000C4110 00a0:
|
|
_hud_set_state_message (0000)
|
|
000C41B0 0060:
|
|
_hud_set_state_message_icon (0000)
|
|
000C4210 0070:
|
|
_hud_set_state_message_text (0000)
|
|
000C4280 0070:
|
|
_hud_enable_custom_state_message (0000)
|
|
000C42F0 0040:
|
|
_hud_set_state_text (0000)
|
|
000C4330 00c0:
|
|
_hud_messaging_get_objective (0000)
|
|
000C43F0 0080:
|
|
_find_free_hud_message (0000)
|
|
000C4470 0030:
|
|
_compare_messages (0000)
|
|
000C44A0 0040:
|
|
_scripted_hud_messages_clear (0000)
|
|
000C44E0 0020:
|
|
_hud_get_font_index (0000)
|
|
000C4500 0030:
|
|
_hud_get_text_color (0000)
|
|
000C4530 0010:
|
|
_hud_messaging_globals_update (0000)
|
|
000C4540 0080:
|
|
_hud_print_message (0000)
|
|
000C45C0 00a0:
|
|
_hud_add_item_message (0000)
|
|
000C4660 0070:
|
|
_hud_broadcast_team_message (0000)
|
|
000C46D0 0b70:
|
|
_hud_messaging_update (0000)
|
|
0026FEE4 000e:
|
|
??_C@_0O@JAAAMDJP@hud?5messaging?$AA@ (0000)
|
|
0026FEF4 003f:
|
|
??_C@_0DP@DEHGFPPE@trying?5to?5restart?5help?5text?5flas@ (0000)
|
|
0026FF34 002b:
|
|
??_C@_0CL@KDPBOCMB@objective?5text?5MUST?5only?5be?5text@ (0000)
|
|
0026FF60 0008:
|
|
__real@4004000000000000 (0000)
|
|
0026FF68 0029:
|
|
??_C@_0CJ@FOFBAHGJ@c?3?2halo?2SOURCE?2interface?2hud_mes@ (0000)
|
|
0026FF94 0026:
|
|
??_C@_0CG@FLCOGOLF@element?9?$DOtype?$DN?$DN_hud_message_type@ (0000)
|
|
0026FFBC 001a:
|
|
??_C@_0BK@PKALLFKO@message?9?$DOelement_count?$DN?$DN1?$AA@ (0000)
|
|
0026FFD8 0022:
|
|
??_C@_1CC@FMBGLMAK@?$AA?$DM?$AAn?$AAo?$AA?5?$AAb?$AAu?$AAt?$AAt?$AAo?$AAn?$AA?5?$AAi?$AAc?$AAo?$AAn?$AA?$DO?$AA?$AA@ (0000)
|
|
0026FFFC 0022:
|
|
??_C@_0CC@OCKONGBA@help?5text?5cannot?5use?5custom?5icon@ (0000)
|
|
00270020 0037:
|
|
??_C@_0DH@PPCCMLMB@help?5message?5using?5old?5code?4?5get@ (0000)
|
|
00270058 0014:
|
|
??_C@_1BE@ELICABCK@?$AA?$DM?$AAu?$AAn?$AAk?$AAn?$AAo?$AAw?$AAn?$AA?$DO?$AA?$AA@ (0000)
|
|
0027006C 0037:
|
|
??_C@_0DH@GJFOKBEC@global_scenario_get?$CI?$CJ?9?$DOcustom_ob@ (0000)
|
|
002700A4 0028:
|
|
??_C@_0CI@PMMKILCE@custom_index?$DMNUMBER_OF_HUD_CUSTO@ (0000)
|
|
002700CC 0013:
|
|
??_C@_0BD@LPFKFODL@show_state_message?$AA@ (0000)
|
|
002700E0 0054:
|
|
??_C@_0FE@EGLPDJAB@hud_messaging_globals?9?$DOobjective@ (0000)
|
|
002E4C4C 001c:
|
|
_button_mappings (0000)
|
|
_time_code_time (0010)
|
|
_time_code_stop_time (0014)
|
|
00453AB8 0004:
|
|
_hud_messaging_globals (0000)
|
|
*/
|
|
|
|
/* ---------- headers */
|
|
|
|
#include "cseries/cseries.h"
|
|
|
|
#include "cseries/errors.h"
|
|
#include "game/game.h"
|
|
#include "game/game_engine.h"
|
|
#include "game/players.h"
|
|
#include "interface/hud_draw.h"
|
|
#include "interface/hud_messaging.h"
|
|
#include "interface/interface.h"
|
|
#include "render/render.h"
|
|
#include "render/render_debug.h"
|
|
#include "saved games/game_state.h"
|
|
#include "scenario/scenario.h"
|
|
#include "scenario/scenario_definitions.h"
|
|
#include "tag_files/tag_groups.h"
|
|
#include "text/unicode.h"
|
|
|
|
#include <stddef.h>
|
|
|
|
/* ---------- constants */
|
|
|
|
enum
|
|
{
|
|
hud_message_text_group_tag = 'hmt ',
|
|
hud_number_group_tag = 'hud#',
|
|
NUMBER_OF_HUD_MESSAGING_DATUMS = 4,
|
|
NUMBER_OF_HUD_MESSAGES_PER_DATUM = 4,
|
|
MAXIMUM_HUD_STATE_MESSAGE_TEXT_LENGTH = 256
|
|
};
|
|
|
|
enum hud_corner
|
|
{
|
|
_hud_corner_top_left,
|
|
_hud_corner_top_right,
|
|
_hud_corner_bottom_left,
|
|
_hud_corner_bottom_right,
|
|
_hud_corner_center,
|
|
NUMBER_OF_HUD_CORNERS
|
|
};
|
|
|
|
enum hud_number_show_flags
|
|
{
|
|
_hud_number_show_all_leading_zeros_bit,
|
|
_hud_number_show_only_when_zoomed_bit,
|
|
_hud_number_show_trailing_m_bit,
|
|
NUMBER_OF_HUD_NUMBER_SHOW_FLAGS
|
|
};
|
|
|
|
/* ---------- macros */
|
|
|
|
#define HUD_MESSAGE_TEXT_DEFINITION_GET(index) \
|
|
((struct hud_message_text_definition *)tag_get(hud_message_text_group_tag, (index)))
|
|
#define HUD_NUMBER_DEFINITION_GET(index) \
|
|
((struct hud_number_definition *)tag_get(hud_number_group_tag, (index)))
|
|
|
|
/* ---------- structures */
|
|
|
|
struct hud_message_definition
|
|
{
|
|
long time;
|
|
wchar_t text[63];
|
|
boolean valid;
|
|
boolean magic_number;
|
|
long item_definition_index;
|
|
short quantity;
|
|
char message_offset;
|
|
byte pad8B;
|
|
};
|
|
|
|
struct hud_state_message_definition
|
|
{
|
|
char name[32];
|
|
word text_start_index;
|
|
word element_start_index;
|
|
byte element_count;
|
|
byte pad25[3];
|
|
long unused28[6];
|
|
};
|
|
|
|
enum
|
|
{
|
|
_hud_message_type_text,
|
|
_hud_message_type_icon,
|
|
NUMBER_OF_HUD_MESSAGE_TYPES
|
|
};
|
|
|
|
struct hud_state_message_element
|
|
{
|
|
byte type;
|
|
byte data;
|
|
};
|
|
|
|
struct icon_hud_element_definition;
|
|
|
|
struct hud_state_message_text_info_definition
|
|
{
|
|
short string_index;
|
|
boolean uses_scenario_names;
|
|
byte reserved3;
|
|
};
|
|
|
|
union hud_state_message_info_definition
|
|
{
|
|
struct icon_hud_element_definition const *icon;
|
|
struct hud_state_message_text_info_definition text;
|
|
};
|
|
|
|
struct hud_state_message_runtime_definition
|
|
{
|
|
wchar_t message_buffer[MAXIMUM_HUD_STATE_MESSAGE_TEXT_LENGTH];
|
|
byte reserved200[4];
|
|
union hud_state_message_info_definition info[8];
|
|
struct hud_state_message_definition *state_message;
|
|
boolean valid;
|
|
byte is_text_flags;
|
|
byte reserved22A[2];
|
|
};
|
|
|
|
struct hud_messaging_datum_definition
|
|
{
|
|
struct hud_message_definition messages[NUMBER_OF_HUD_MESSAGES_PER_DATUM];
|
|
struct hud_state_message_runtime_definition state_message;
|
|
short first_message;
|
|
boolean leave_first_line_blank;
|
|
boolean custom_message;
|
|
};
|
|
|
|
struct hud_message_text_definition
|
|
{
|
|
struct tag_data text_data;
|
|
struct tag_block elements;
|
|
struct tag_block messages;
|
|
long unused2C[21];
|
|
};
|
|
|
|
struct hud_scripted_globals_definition
|
|
{
|
|
boolean show_hud;
|
|
boolean show_hud_help_text;
|
|
byte reserved2[2];
|
|
};
|
|
|
|
struct hud_timer_data_definition
|
|
{
|
|
long reference_time;
|
|
short ticks;
|
|
short flash_cutoff;
|
|
point2d position;
|
|
short corner;
|
|
boolean paused;
|
|
boolean enabled;
|
|
};
|
|
|
|
struct hud_absolute_placement_definition
|
|
{
|
|
short corner;
|
|
short pad;
|
|
long unused[8];
|
|
};
|
|
|
|
struct hud_placement_definition
|
|
{
|
|
point2d offset;
|
|
real_vector2d scale;
|
|
short multiplayer_scaling_flags;
|
|
short pad;
|
|
long unused[5];
|
|
};
|
|
|
|
struct hud_objective_runtime_definition
|
|
{
|
|
struct hud_state_message_definition *message;
|
|
short uptime;
|
|
short pad6;
|
|
};
|
|
|
|
struct hud_messaging_globals_definition
|
|
{
|
|
struct hud_messaging_datum_definition message_data[NUMBER_OF_HUD_MESSAGING_DATUMS];
|
|
long flash_start_time;
|
|
boolean use_flash;
|
|
byte magic_number;
|
|
byte reserved1186[6];
|
|
struct hud_state_message_definition *help_message;
|
|
struct hud_objective_runtime_definition objective;
|
|
struct hud_timer_data_definition timer;
|
|
};
|
|
|
|
struct hud_color_definition
|
|
{
|
|
unsigned long color;
|
|
unsigned long flash_color;
|
|
real flash_period;
|
|
real flash_delay;
|
|
short number_of_flashes;
|
|
word flash_flags;
|
|
real flash_length;
|
|
unsigned long disabled_color;
|
|
union
|
|
{
|
|
long unused;
|
|
struct
|
|
{
|
|
short up_ticks;
|
|
short fade_ticks;
|
|
} objective;
|
|
} custom;
|
|
};
|
|
|
|
struct number_hud_element_definition
|
|
{
|
|
struct hud_placement_definition placement;
|
|
struct hud_color_definition colors;
|
|
char digits;
|
|
byte number_flags;
|
|
char fractional_digits;
|
|
byte pad;
|
|
long unused[3];
|
|
};
|
|
|
|
struct hud_number_definition
|
|
{
|
|
struct tag_reference number_bitmap;
|
|
char character_width;
|
|
char screen_width;
|
|
char x_offset;
|
|
char y_offset;
|
|
char decimal_point_width;
|
|
char colon_width;
|
|
short pad;
|
|
long unused[19];
|
|
};
|
|
|
|
struct hud_timer_definition
|
|
{
|
|
struct hud_color_definition color;
|
|
struct hud_color_definition time_up_color;
|
|
long unused[10];
|
|
};
|
|
|
|
struct hud_messaging_parameters_definition
|
|
{
|
|
byte reserved000[0x48];
|
|
struct tag_reference single_player_font;
|
|
struct tag_reference multi_player_font;
|
|
real up_time;
|
|
real fade_time;
|
|
real_argb_color state_color;
|
|
real_argb_color text_color;
|
|
real spacing;
|
|
struct tag_reference hud_item_messages;
|
|
struct tag_reference messaging_icons;
|
|
struct tag_reference alternate_icon_text;
|
|
struct tag_block button_icons;
|
|
struct hud_color_definition color;
|
|
struct tag_reference hud_messages;
|
|
struct hud_color_definition objective_color;
|
|
};
|
|
|
|
struct hud_globals_definition
|
|
{
|
|
struct hud_messaging_parameters_definition messaging;
|
|
byte reserved120[0x240];
|
|
struct hud_timer_definition timer_definition;
|
|
};
|
|
|
|
typedef char hud_timer_data_size_assert[
|
|
sizeof(struct hud_timer_data_definition) == 0x10 ? 1 : -1];
|
|
typedef char hud_message_valid_offset_assert[
|
|
offsetof(struct hud_message_definition, valid) == 0x82 ? 1 : -1];
|
|
typedef char hud_message_size_assert[
|
|
sizeof(struct hud_message_definition) == 0x8C ? 1 : -1];
|
|
typedef char hud_state_message_text_info_size_assert[
|
|
sizeof(struct hud_state_message_text_info_definition) == 4 ? 1 : -1];
|
|
typedef char hud_state_message_info_size_assert[
|
|
sizeof(union hud_state_message_info_definition) == 4 ? 1 : -1];
|
|
typedef char hud_state_message_runtime_size_assert[
|
|
sizeof(struct hud_state_message_runtime_definition) == 0x22C ? 1 : -1];
|
|
typedef char hud_state_message_runtime_info_offset_assert[
|
|
offsetof(struct hud_state_message_runtime_definition, info) == 0x204 ? 1 : -1];
|
|
typedef char hud_state_message_runtime_state_message_offset_assert[
|
|
offsetof(struct hud_state_message_runtime_definition, state_message) == 0x224 ? 1 : -1];
|
|
typedef char hud_state_message_runtime_valid_offset_assert[
|
|
offsetof(struct hud_state_message_runtime_definition, valid) == 0x228 ? 1 : -1];
|
|
typedef char hud_state_message_runtime_is_text_flags_offset_assert[
|
|
offsetof(struct hud_state_message_runtime_definition, is_text_flags) == 0x229 ? 1 : -1];
|
|
typedef char hud_messaging_datum_state_message_offset_assert[
|
|
offsetof(struct hud_messaging_datum_definition, state_message) == 0x230 ? 1 : -1];
|
|
typedef char hud_messaging_datum_leave_first_line_blank_offset_assert[
|
|
offsetof(struct hud_messaging_datum_definition, leave_first_line_blank) == 0x45E ? 1 : -1];
|
|
typedef char hud_messaging_datum_custom_message_offset_assert[
|
|
offsetof(struct hud_messaging_datum_definition, custom_message) == 0x45F ? 1 : -1];
|
|
typedef char hud_messaging_datum_size_assert[
|
|
sizeof(struct hud_messaging_datum_definition) == 0x460 ? 1 : -1];
|
|
typedef char hud_messaging_globals_size_assert[
|
|
sizeof(struct hud_messaging_globals_definition) == 0x11A8 ? 1 : -1];
|
|
typedef char hud_messaging_flash_start_time_offset_assert[
|
|
offsetof(struct hud_messaging_globals_definition, flash_start_time) == 0x1180 ? 1 : -1];
|
|
typedef char hud_messaging_use_flash_offset_assert[
|
|
offsetof(struct hud_messaging_globals_definition, use_flash) == 0x1184 ? 1 : -1];
|
|
typedef char hud_messaging_magic_number_offset_assert[
|
|
offsetof(struct hud_messaging_globals_definition, magic_number) == 0x1185 ? 1 : -1];
|
|
typedef char hud_messaging_help_message_offset_assert[
|
|
offsetof(struct hud_messaging_globals_definition, help_message) == 0x118C ? 1 : -1];
|
|
typedef char hud_messaging_timer_offset_assert[
|
|
offsetof(struct hud_messaging_globals_definition, timer) == 0x1198 ? 1 : -1];
|
|
typedef char hud_messaging_timer_flash_cutoff_offset_assert[
|
|
offsetof(struct hud_messaging_globals_definition, timer.flash_cutoff) == 0x119E ? 1 : -1];
|
|
typedef char hud_messaging_timer_enabled_offset_assert[
|
|
offsetof(struct hud_messaging_globals_definition, timer.enabled) == 0x11A7 ? 1 : -1];
|
|
typedef char hud_messaging_parameters_size_assert[
|
|
sizeof(struct hud_messaging_parameters_definition) == 0x120 ? 1 : -1];
|
|
typedef char hud_messaging_single_player_font_index_offset_assert[
|
|
offsetof(struct hud_messaging_parameters_definition, single_player_font.index) == 0x54 ? 1 : -1];
|
|
typedef char hud_messaging_multi_player_font_index_offset_assert[
|
|
offsetof(struct hud_messaging_parameters_definition, multi_player_font.index) == 0x64 ? 1 : -1];
|
|
typedef char hud_messaging_state_color_offset_assert[
|
|
offsetof(struct hud_messaging_parameters_definition, state_color) == 0x70 ? 1 : -1];
|
|
typedef char hud_globals_messaging_offset_assert[
|
|
offsetof(struct hud_globals_definition, messaging) == 0 ? 1 : -1];
|
|
typedef char hud_absolute_placement_size_assert[
|
|
sizeof(struct hud_absolute_placement_definition) == 0x24 ? 1 : -1];
|
|
typedef char hud_placement_size_assert[
|
|
sizeof(struct hud_placement_definition) == 0x24 ? 1 : -1];
|
|
typedef char number_hud_element_size_assert[
|
|
sizeof(struct number_hud_element_definition) == 0x54 ? 1 : -1];
|
|
typedef char hud_number_size_assert[
|
|
sizeof(struct hud_number_definition) == 0x64 ? 1 : -1];
|
|
typedef char hud_globals_timer_definition_offset_assert[
|
|
offsetof(struct hud_globals_definition, timer_definition) == 0x360 ? 1 : -1];
|
|
|
|
/* ---------- prototypes */
|
|
|
|
static struct hud_message_definition *find_free_hud_message(
|
|
struct hud_messaging_datum_definition *datum,
|
|
long item_definition_index,
|
|
char message_offset);
|
|
|
|
/* ---------- globals */
|
|
|
|
static struct hud_messaging_globals_definition *hud_messaging_globals;
|
|
extern struct hud_globals_definition *hud_globals;
|
|
extern struct hud_messaging_parameters_definition *hud_msg_def;
|
|
extern struct hud_scripted_globals_definition *hud_scripted_globals;
|
|
extern long time_code_time;
|
|
extern long time_code_stop_time;
|
|
|
|
/* ---------- public code */
|
|
|
|
void hud_messaging_initialize(
|
|
void)
|
|
{
|
|
hud_messaging_globals = game_state_malloc(
|
|
"hud messaging",
|
|
NULL,
|
|
sizeof(*hud_messaging_globals));
|
|
return;
|
|
}
|
|
|
|
void hud_messaging_initialize_for_new_map(
|
|
void)
|
|
{
|
|
hud_msg_def = &hud_globals->messaging;
|
|
csmemset(hud_messaging_globals, 0, sizeof(*hud_messaging_globals));
|
|
return;
|
|
}
|
|
|
|
void hud_messaging_dispose_from_old_map(
|
|
void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void hud_messaging_dispose(
|
|
void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_set_state_message(
|
|
short message_index)
|
|
{
|
|
struct scenario *scenario = global_scenario_get();
|
|
|
|
if (hud_scripted_globals->show_hud_help_text &&
|
|
scenario->hud_messages.index != NONE)
|
|
{
|
|
struct hud_message_text_definition *hud_messages = HUD_MESSAGE_TEXT_DEFINITION_GET(
|
|
scenario->hud_messages.index);
|
|
|
|
hud_messaging_globals->help_message = TAG_BLOCK_GET_ELEMENT(
|
|
&hud_messages->messages,
|
|
message_index,
|
|
struct hud_state_message_definition);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_set_flashing_state(
|
|
boolean flash)
|
|
{
|
|
long time;
|
|
|
|
if (flash && !hud_messaging_globals->use_flash)
|
|
{
|
|
time = game_time_get();
|
|
hud_messaging_globals->flash_start_time = time;
|
|
hud_messaging_globals->use_flash = flash;
|
|
return;
|
|
}
|
|
hud_messaging_globals->use_flash = flash;
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_restart_flashing(
|
|
void)
|
|
{
|
|
if (hud_messaging_globals->use_flash)
|
|
hud_messaging_globals->flash_start_time = game_time_get();
|
|
else
|
|
error(
|
|
_error_silent,
|
|
"trying to restart help text flashing when flashing is disabled");
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_set_objective(
|
|
short message_index)
|
|
{
|
|
struct scenario *scenario = global_scenario_get();
|
|
|
|
if (scenario->hud_messages.index != NONE)
|
|
{
|
|
struct hud_message_text_definition *hud_messages =
|
|
HUD_MESSAGE_TEXT_DEFINITION_GET(scenario->hud_messages.index);
|
|
struct hud_state_message_definition *message = TAG_BLOCK_GET_ELEMENT(
|
|
&hud_messages->messages,
|
|
message_index,
|
|
struct hud_state_message_definition);
|
|
struct hud_state_message_element *element = TAG_BLOCK_GET_ELEMENT(
|
|
&hud_messages->elements,
|
|
message->element_start_index,
|
|
struct hud_state_message_element);
|
|
|
|
if (message->element_count == 1 && element->type == _hud_message_type_text)
|
|
{
|
|
struct hud_globals_definition *hud = hud_globals;
|
|
struct hud_messaging_globals_definition *globals = hud_messaging_globals;
|
|
short up_ticks;
|
|
short fade_ticks;
|
|
|
|
globals->objective.message = message;
|
|
up_ticks = hud->messaging.objective_color.custom.objective.up_ticks;
|
|
fade_ticks = hud->messaging.objective_color.custom.objective.fade_ticks;
|
|
globals->objective.uptime = fade_ticks + up_ticks;
|
|
}
|
|
else
|
|
{
|
|
error(
|
|
_error_silent,
|
|
"objective text MUST only be text, no icons");
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_set_timer_time(
|
|
short minutes,
|
|
word seconds)
|
|
{
|
|
struct hud_timer_data_definition *timer;
|
|
long time;
|
|
|
|
hud_messaging_globals->timer.ticks = 30 * (60 * minutes + seconds);
|
|
timer = &hud_messaging_globals->timer;
|
|
timer->paused = FALSE;
|
|
timer->enabled = TRUE;
|
|
time = game_time_get();
|
|
timer = &hud_messaging_globals->timer;
|
|
timer->reference_time = time;
|
|
timer->corner = PIN(timer->corner, 0, 4);
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_set_timer_warning_cutoff(
|
|
short minutes,
|
|
word seconds)
|
|
{
|
|
hud_messaging_globals->timer.flash_cutoff = 30 * (60 * minutes + seconds);
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_set_timer_position(
|
|
short x,
|
|
short y,
|
|
short corner)
|
|
{
|
|
struct hud_messaging_globals_definition *globals = hud_messaging_globals;
|
|
|
|
globals->timer.position.n[0] = x;
|
|
globals->timer.position.n[1] = y;
|
|
globals->timer.corner = PIN(corner, 0, 4);
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_show_timer(
|
|
boolean show)
|
|
{
|
|
hud_messaging_globals->timer.enabled = show;
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_pause_timer(
|
|
boolean paused)
|
|
{
|
|
struct hud_timer_data_definition *timer = &hud_messaging_globals->timer;
|
|
short now;
|
|
|
|
timer->paused = paused;
|
|
if (timer->ticks > 0)
|
|
{
|
|
if (paused)
|
|
{
|
|
now = (short)game_time_get();
|
|
timer->ticks += timer->reference_time - now;
|
|
return;
|
|
}
|
|
|
|
now = (short)game_time_get();
|
|
timer->ticks += now - timer->reference_time;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
short scripted_hud_get_timer_ticks(
|
|
void)
|
|
{
|
|
struct hud_timer_data_definition *timer = &hud_messaging_globals->timer;
|
|
boolean enabled = timer->enabled;
|
|
short result = 0;
|
|
|
|
if (enabled)
|
|
{
|
|
if (timer->ticks == NONE)
|
|
return NONE;
|
|
result = timer->ticks;
|
|
|
|
if (!timer->paused)
|
|
{
|
|
return (short)(
|
|
(word)(timer->ticks + (word)timer->reference_time) -
|
|
game_time_get());
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void scripted_hud_time_code_show(
|
|
boolean show)
|
|
{
|
|
if (show)
|
|
{
|
|
time_code_time = game_time_get();
|
|
time_code_stop_time = time_code_time;
|
|
return;
|
|
}
|
|
time_code_time = NONE;
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_time_code_start(
|
|
boolean start)
|
|
{
|
|
if (start)
|
|
{
|
|
time_code_time += game_time_get() - time_code_stop_time;
|
|
time_code_stop_time = NONE;
|
|
return;
|
|
}
|
|
time_code_stop_time = game_time_get();
|
|
|
|
return;
|
|
}
|
|
|
|
void scripted_hud_time_code_reset(
|
|
void)
|
|
{
|
|
long time = game_time_get();
|
|
|
|
time_code_time = time;
|
|
if (time_code_stop_time != NONE)
|
|
time_code_stop_time = time;
|
|
|
|
return;
|
|
}
|
|
|
|
void hud_render_timer(
|
|
void)
|
|
{
|
|
struct hud_timer_data_definition *timer = &hud_messaging_globals->timer;
|
|
|
|
if (timer->enabled)
|
|
{
|
|
struct hud_absolute_placement_definition placement = { timer->corner };
|
|
struct number_hud_element_definition numbers;
|
|
long current_time = game_time_get();
|
|
short flash = FALSE;
|
|
short digit_advance = 0;
|
|
short timer_ticks = scripted_hud_get_timer_ticks();
|
|
long hud_number_index;
|
|
|
|
numbers.digits = 2;
|
|
numbers.fractional_digits = 4;
|
|
numbers.number_flags = FLAG(_hud_number_show_all_leading_zeros_bit);
|
|
numbers.placement.offset = timer->position;
|
|
numbers.placement.scale.i = 1.0f;
|
|
numbers.placement.scale.j = 1.0f;
|
|
|
|
hud_number_index = interface_get_tag_index(_interface_hud_digits);
|
|
if (hud_number_index != NONE)
|
|
{
|
|
struct hud_number_definition *hud_number =
|
|
HUD_NUMBER_DEFINITION_GET(hud_number_index);
|
|
|
|
digit_advance = (short)(long)((real)hud_number->screen_width * 2.0f);
|
|
}
|
|
|
|
switch (timer->corner)
|
|
{
|
|
case _hud_corner_top_left:
|
|
case _hud_corner_bottom_left:
|
|
break;
|
|
|
|
case _hud_corner_top_right:
|
|
case _hud_corner_bottom_right:
|
|
numbers.placement.offset.x += 5 * digit_advance;
|
|
digit_advance = -digit_advance;
|
|
break;
|
|
|
|
case _hud_corner_center:
|
|
numbers.placement.offset.x -= 3 * digit_advance;
|
|
break;
|
|
|
|
default:
|
|
match_assert(
|
|
"c:\\halo\\SOURCE\\interface\\hud_messaging.c",
|
|
0x1F8,
|
|
!"unreachable");
|
|
break;
|
|
}
|
|
|
|
if (timer_ticks > 0)
|
|
{
|
|
numbers.colors = hud_globals->timer_definition.color;
|
|
{
|
|
short flash_cutoff = timer->flash_cutoff;
|
|
|
|
if (timer_ticks <= flash_cutoff)
|
|
{
|
|
flash = TRUE;
|
|
if (timer->ticks > flash_cutoff)
|
|
{
|
|
timer->ticks = flash_cutoff;
|
|
timer->reference_time =
|
|
flash_cutoff - timer_ticks + current_time;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long reference_time = timer->reference_time;
|
|
|
|
timer->ticks = NONE;
|
|
numbers.colors = hud_globals->timer_definition.time_up_color;
|
|
flash = TRUE;
|
|
if (reference_time == NONE)
|
|
timer->reference_time = game_time_get();
|
|
}
|
|
|
|
{
|
|
short clamped_ticks = MAX(timer_ticks, 0);
|
|
short total_seconds = clamped_ticks / TICKS_PER_SECOND;
|
|
double offset_advance;
|
|
|
|
hud_draw_numbers(
|
|
render.local_player_index,
|
|
&placement,
|
|
&numbers,
|
|
total_seconds / SECONDS_PER_MINUTE,
|
|
NONE,
|
|
flash,
|
|
timer->reference_time,
|
|
2.0f);
|
|
|
|
offset_advance = (double)digit_advance * 2.5;
|
|
numbers.placement.offset.x = (short)(long)(
|
|
(double)numbers.placement.offset.x + offset_advance);
|
|
hud_draw_numbers(
|
|
render.local_player_index,
|
|
&placement,
|
|
&numbers,
|
|
total_seconds % SECONDS_PER_MINUTE,
|
|
NONE,
|
|
flash,
|
|
timer->reference_time,
|
|
2.0f);
|
|
|
|
numbers.placement.offset.x = (short)(long)(
|
|
(double)numbers.placement.offset.x + offset_advance);
|
|
hud_draw_numbers(
|
|
render.local_player_index,
|
|
&placement,
|
|
&numbers,
|
|
100 * (clamped_ticks % TICKS_PER_SECOND) / TICKS_PER_SECOND,
|
|
NONE,
|
|
flash,
|
|
timer->reference_time,
|
|
2.0f);
|
|
}
|
|
}
|
|
|
|
if (time_code_time != NONE)
|
|
{
|
|
long stop_time = time_code_stop_time;
|
|
|
|
if (stop_time == NONE)
|
|
stop_time = game_time_get();
|
|
sprintf(temporary, "%d", stop_time - time_code_time);
|
|
render_debug_string(TRUE, temporary);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void hud_set_state_message(
|
|
short local_player_index,
|
|
short message_index)
|
|
{
|
|
if (!hud_scripted_globals->show_hud_help_text)
|
|
{
|
|
long hud_messages_index = hud_globals->messaging.hud_messages.index;
|
|
|
|
if (hud_messages_index != NONE)
|
|
{
|
|
struct hud_messaging_globals_definition *globals = hud_messaging_globals;
|
|
struct hud_messaging_datum_definition *datum =
|
|
&globals->message_data[local_player_index];
|
|
|
|
if (message_index != NONE)
|
|
{
|
|
struct hud_message_text_definition *hud_messages =
|
|
HUD_MESSAGE_TEXT_DEFINITION_GET(hud_messages_index);
|
|
|
|
if (message_index < hud_messages->messages.count)
|
|
{
|
|
datum->state_message.state_message = TAG_BLOCK_GET_ELEMENT(
|
|
&hud_messages->messages,
|
|
message_index,
|
|
struct hud_state_message_definition);
|
|
datum->state_message.is_text_flags = 0;
|
|
}
|
|
else
|
|
{
|
|
message_index = NONE;
|
|
}
|
|
}
|
|
|
|
datum->state_message.valid = message_index != NONE;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
hud_set_state_message_icon(
|
|
short local_player_index,
|
|
short custom_icon_index,
|
|
struct icon_hud_element_definition const *icon)
|
|
{
|
|
struct hud_messaging_datum_definition *datum =
|
|
&hud_messaging_globals->message_data[local_player_index];
|
|
|
|
if (datum->state_message.valid &&
|
|
!hud_scripted_globals->show_hud_help_text &&
|
|
datum->state_message.state_message)
|
|
{
|
|
datum->state_message.info[custom_icon_index].icon = icon;
|
|
datum->state_message.is_text_flags &= ~(1 << custom_icon_index);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
hud_set_state_message_text(
|
|
short local_player_index,
|
|
short custom_icon_index,
|
|
short icon_string_index,
|
|
boolean uses_scenario_names)
|
|
{
|
|
struct hud_messaging_datum_definition *datum =
|
|
&hud_messaging_globals->message_data[local_player_index];
|
|
|
|
if (datum->state_message.valid &&
|
|
!hud_scripted_globals->show_hud_help_text &&
|
|
datum->state_message.state_message)
|
|
{
|
|
datum->state_message.info[custom_icon_index].text.string_index = icon_string_index;
|
|
datum->state_message.info[custom_icon_index].text.uses_scenario_names = uses_scenario_names;
|
|
datum->state_message.is_text_flags |= 1 << custom_icon_index;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
hud_enable_custom_state_message(
|
|
short local_player_index,
|
|
boolean enabled)
|
|
{
|
|
struct hud_messaging_datum_definition *datum =
|
|
&hud_messaging_globals->message_data[local_player_index];
|
|
|
|
datum->leave_first_line_blank |= datum->state_message.valid != enabled;
|
|
datum->state_message.valid = enabled;
|
|
datum->state_message.state_message = NULL;
|
|
if (enabled)
|
|
{
|
|
datum->state_message.state_message = NULL;
|
|
ustrncpy(
|
|
datum->state_message.message_buffer,
|
|
L"",
|
|
MAXIMUM_HUD_STATE_MESSAGE_TEXT_LENGTH - 1);
|
|
}
|
|
datum->custom_message = enabled;
|
|
|
|
return;
|
|
}
|
|
|
|
void hud_set_state_text(
|
|
short local_player_index,
|
|
wchar_t const *message)
|
|
{
|
|
struct hud_messaging_datum_definition *datum =
|
|
&hud_messaging_globals->message_data[local_player_index];
|
|
|
|
ustrncpy(
|
|
datum->state_message.message_buffer,
|
|
message,
|
|
MAXIMUM_HUD_STATE_MESSAGE_TEXT_LENGTH - 1);
|
|
datum->state_message.message_buffer[MAXIMUM_HUD_STATE_MESSAGE_TEXT_LENGTH - 1] = L'\0';
|
|
|
|
return;
|
|
}
|
|
|
|
wchar_t *hud_messaging_get_objective(
|
|
void)
|
|
{
|
|
wchar_t *result = NULL;
|
|
|
|
if (hud_messaging_globals->objective.message)
|
|
{
|
|
struct scenario *scenario = global_scenario_get();
|
|
struct hud_message_text_definition *hud_messages =
|
|
HUD_MESSAGE_TEXT_DEFINITION_GET(scenario->hud_messages.index);
|
|
struct hud_state_message_definition *message =
|
|
hud_messaging_globals->objective.message;
|
|
struct hud_state_message_element *element = TAG_BLOCK_GET_ELEMENT(
|
|
&hud_messages->elements,
|
|
message->element_start_index,
|
|
struct hud_state_message_element);
|
|
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\hud_messaging.c",
|
|
0x2A2,
|
|
message->element_count == 1,
|
|
"message->element_count==1");
|
|
match_vassert(
|
|
"c:\\halo\\SOURCE\\interface\\hud_messaging.c",
|
|
0x2A3,
|
|
element->type == _hud_message_type_text,
|
|
"element->type==_hud_message_type_text");
|
|
|
|
result = tag_data_get_pointer(
|
|
&hud_messages->text_data,
|
|
message->text_start_index * sizeof(wchar_t),
|
|
element->data * sizeof(wchar_t));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void scripted_hud_messages_clear(
|
|
void)
|
|
{
|
|
struct hud_messaging_datum_definition *datum = hud_messaging_globals->message_data;
|
|
long datum_count = NUMBER_OF_HUD_MESSAGING_DATUMS;
|
|
|
|
do
|
|
{
|
|
struct hud_message_definition *message = datum->messages;
|
|
long message_count = NUMBER_OF_HUD_MESSAGES_PER_DATUM;
|
|
|
|
do
|
|
{
|
|
message->valid = FALSE;
|
|
message++;
|
|
}
|
|
while (--message_count);
|
|
|
|
datum++;
|
|
}
|
|
while (--datum_count);
|
|
|
|
return;
|
|
}
|
|
|
|
long hud_get_font_index(
|
|
void)
|
|
{
|
|
if (local_player_count() > 1 &&
|
|
hud_msg_def->multi_player_font.index != NONE)
|
|
{
|
|
return hud_msg_def->multi_player_font.index;
|
|
}
|
|
|
|
return hud_msg_def->single_player_font.index;
|
|
}
|
|
|
|
real_argb_color *hud_get_text_color(
|
|
real_argb_color *result)
|
|
{
|
|
*result = hud_msg_def->state_color;
|
|
|
|
return result;
|
|
}
|
|
|
|
void hud_messaging_globals_update(
|
|
void)
|
|
{
|
|
hud_messaging_globals->magic_number = 0;
|
|
return;
|
|
}
|
|
|
|
void hud_print_message(
|
|
short local_player_index,
|
|
wchar_t const *message_text)
|
|
{
|
|
if (local_player_index != NONE)
|
|
{
|
|
struct hud_messaging_datum_definition *datum =
|
|
&hud_messaging_globals->message_data[local_player_index];
|
|
struct hud_message_definition *message = find_free_hud_message(
|
|
datum,
|
|
NONE,
|
|
0);
|
|
|
|
ustrncpy(message->text, message_text, NUMBEROF(message->text));
|
|
message->item_definition_index = NONE;
|
|
message->time = game_time_get();
|
|
message->valid = TRUE;
|
|
message->magic_number = hud_messaging_globals->magic_number++;
|
|
datum->leave_first_line_blank = FALSE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void hud_add_item_message(
|
|
short local_player_index,
|
|
long item_definition_index,
|
|
short quantity,
|
|
char message_offset)
|
|
{
|
|
if (local_player_index != NONE)
|
|
{
|
|
struct hud_messaging_datum_definition *datum =
|
|
&hud_messaging_globals->message_data[local_player_index];
|
|
struct hud_message_definition *message = find_free_hud_message(
|
|
datum,
|
|
item_definition_index,
|
|
message_offset);
|
|
|
|
if (!message->valid)
|
|
message->quantity = 0;
|
|
message->quantity += quantity;
|
|
message->item_definition_index = item_definition_index;
|
|
message->message_offset = message_offset;
|
|
message->time = game_time_get();
|
|
message->valid = TRUE;
|
|
message->magic_number = hud_messaging_globals->magic_number++;
|
|
datum->leave_first_line_blank = FALSE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void hud_broadcast_team_message(
|
|
long victim_player_index,
|
|
wchar_t const *message)
|
|
{
|
|
if (game_engine_running())
|
|
{
|
|
short local_player_index;
|
|
|
|
for (local_player_index = 0;
|
|
local_player_index < MAXIMUM_LOCAL_PLAYERS;
|
|
local_player_index++)
|
|
{
|
|
long player_index = local_player_get_player_index(local_player_index);
|
|
|
|
if (player_index != NONE &&
|
|
player_get(player_index)->team_index == player_get(victim_player_index)->team_index)
|
|
{
|
|
hud_print_message(local_player_index, message);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* ---------- private code */
|
|
|
|
static struct hud_message_definition *find_free_hud_message(
|
|
struct hud_messaging_datum_definition *datum,
|
|
long item_definition_index,
|
|
char message_offset)
|
|
{
|
|
struct hud_message_definition *result = NULL;
|
|
long oldest_time = LONG_MAX;
|
|
short oldest_message_index = 0;
|
|
short message_index = 0;
|
|
|
|
do
|
|
{
|
|
struct hud_message_definition *message = &datum->messages[message_index];
|
|
|
|
if ((item_definition_index != NONE &&
|
|
item_definition_index == message->item_definition_index &&
|
|
message_offset == message->message_offset) || !message->valid)
|
|
{
|
|
result = message;
|
|
if (item_definition_index == NONE ||
|
|
item_definition_index == message->item_definition_index)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else if (oldest_time > message->time)
|
|
{
|
|
oldest_time = message->time;
|
|
oldest_message_index = message_index;
|
|
}
|
|
|
|
message_index++;
|
|
}
|
|
while ((word)message_index < NUMBER_OF_HUD_MESSAGES_PER_DATUM);
|
|
|
|
if (!result)
|
|
result = &datum->messages[oldest_message_index];
|
|
|
|
return result;
|
|
}
|
|
|
|
static long compare_messages(
|
|
struct hud_message_definition const *message_a,
|
|
struct hud_message_definition const *message_b)
|
|
{
|
|
long difference = message_b->time - message_a->time;
|
|
|
|
if (!difference)
|
|
{
|
|
difference = message_b->item_definition_index - message_a->item_definition_index;
|
|
if (!difference)
|
|
difference = message_b->magic_number - message_a->magic_number;
|
|
}
|
|
|
|
return difference;
|
|
}
|