From eb93ce635ebfa38aea18dd455f27bf79eb63e848 Mon Sep 17 00:00:00 2001 From: Berthalamew <40469582+Berthalamew@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:05:45 -0500 Subject: [PATCH] wip objects.c work (#12) * wip objects.c work * objects_disconnect_from_structure_bsp * match more functions * more objects work * objects_update work - 93.42% matching * match matrix4x3_transform_point * more objects work - fix duplicate symbol name at 1870800 * match object_choose_random_change_colors * match object_update * objects_garbage_collection work * match object_set_position * more object work * match objects_update * more object work * match object_select_random_region_permutations_by_variant * objects_in_sphere work 99.90% match * object name list calls * match objects_in_sphere * misc matches * match structure_bsp_definitions object * match objects_in_clusters_by_indices * more object work * match `edit_text_handle_key` * mark edit_text as matching * misc changes - match get_next_character - match data section in objects.c * object_export_function_values work * match object_compute_function_values * match object_get_orientation * added functions and adjust formatting * fix profile macros * formatting changes * more formatting * more formatting --------- Co-authored-by: punpckhdq <121350336+punpckhdq@users.noreply.github.com> --- config/config.json | 4 +- config/symbols.json | 83 +- source/ai/action_alert.c | 3 + source/ai/ai.h | 67 +- source/ai/ai_debug.h | 1 + source/ai/path_obstacles.c | 3 + source/bitmaps/bitmaps.h | 18 +- source/cache/cache_files.c | 47 + source/cache/cache_files.h | 4 + source/cache/predicted_resources.h | 5 +- source/cseries/cseries.h | 38 +- source/cseries/profile.h | 29 + source/cseries/stack_walk_windows.c | 2 +- source/devices/device_definitions.h | 91 + source/devices/devices.h | 59 +- source/dialogs/edit_text.c | 214 + source/dialogs/edit_text.h | 7 +- source/effects/contrail_definitions.h | 7 + source/effects/contrails.h | 5 +- source/effects/effect_definitions.h | 10 + source/effects/effects.h | 21 +- source/effects/particle_system_definitions.h | 6 + source/effects/particle_systems.h | 6 +- source/game/game.h | 64 +- source/game/game_engine.c | 37 + source/game/game_engine.h | 12 +- source/game/players.h | 69 + source/interface/terminal.c | 2 +- source/items/weapons.h | 4 +- source/math/integer_math.c | 4 +- source/math/integer_math.h | 14 +- source/math/matrix_math.c | 121 + source/math/periodic_functions.c | 3 + source/math/periodic_functions.h | 20 +- source/math/real_math.c | 39 + source/math/real_math.h | 357 ++ source/memory/data.c | 51 + source/memory/memory_pool.c | 21 + source/memory/memory_pool.h | 35 +- source/models/model_animation_definitions.c | 3 + source/models/model_animation_definitions.h | 102 +- source/models/model_animations.c | 3 + source/models/model_definitions.h | 105 +- source/models/models.c | 65 + source/models/models.h | 16 +- source/objects/damage.h | 11 +- source/objects/damage_resistances.h | 50 + source/objects/light_definitions.h | 6 + source/objects/object_definitions.h | 144 +- source/objects/object_deleted_procs.c | 20 + source/objects/object_lights.h | 13 +- source/objects/object_types.c | 48 + source/objects/object_types.h | 68 + source/objects/objects.c | 4891 +++++++++++++++-- source/objects/objects.h | 500 +- source/objects/widgets/widgets.h | 9 +- source/physics/bsp2d.h | 9 + source/physics/bsp3d.h | 15 +- source/physics/collision_bsp.h | 22 +- source/physics/collision_bsp_definitions.h | 17 + source/physics/collision_model_definitions.h | 30 +- source/physics/collision_models.h | 14 +- source/physics/collision_usage.h | 8 + source/physics/collisions.h | 95 +- source/physics/physics.h | 18 +- source/rasterizer/rasterizer_geometry.c | 3 + source/rasterizer/rasterizer_geometry.h | 33 + source/render/render.h | 21 + source/render/render_debug.h | 12 +- source/scenario/scenario.c | 13 + source/scenario/scenario.h | 44 + source/scenario/scenario_definitions.h | 112 + source/sound/game_sound.h | 2 + source/sound/sound_definitions.h | 9 + source/structures/cluster_partitions.h | 27 +- source/structures/leaf_map.h | 11 + source/structures/structure_bsp_definitions.c | 196 +- source/structures/structure_bsp_definitions.h | 96 +- source/structures/structure_lens_flares.c | 20 + source/structures/structures.h | 10 + source/tag_files/tag_groups.c | 2 +- source/tag_files/tag_groups.h | 4 + source/text/font_group.h | 2 + source/text/international_strings.c | 217 + source/text/international_strings.h | 8 +- source/units/units.c | 3 + source/units/units.h | 192 +- 87 files changed, 8336 insertions(+), 566 deletions(-) diff --git a/config/config.json b/config/config.json index 18ecb5bf..6c1d7861 100644 --- a/config/config.json +++ b/config/config.json @@ -430,7 +430,7 @@ { "name": "source/structures/structure_render.c", "index": 58, "status": "NonMatching" }, { "name": "source/structures/structure_lens_flares.c", "index": 59, "status": "NonMatching" }, { "name": "source/structures/structure_detail_objects.c", "index": 60, "status": "NonMatching" }, - { "name": "source/structures/structure_bsp_definitions.c", "index": 61, "status": "NonMatching" }, + { "name": "source/structures/structure_bsp_definitions.c", "index": 61, "status": "Matching" }, { "name": "source/structures/leaf_map.c", "index": 62, "status": "NonMatching" }, { "name": "source/structures/detail_object_definitions.c", "index": 63, "status": "Matching" }, { "name": "source/structures/cluster_partitions.c", "index": 64, "status": "NonMatching" }, @@ -705,7 +705,7 @@ { "name": "source/dialogs/picture_control.c", "index": 333, "status": "Matching" }, { "name": "source/dialogs/list_control.c", "index": 334, "status": "Matching" }, { "name": "source/dialogs/edit_text_control.c", "index": 335, "status": "Matching" }, - { "name": "source/dialogs/edit_text.c", "index": 336, "status": "NonMatching" }, + { "name": "source/dialogs/edit_text.c", "index": 336, "status": "Matching" }, { "name": "source/dialogs/dialogs.c", "index": 337, "status": "Matching" }, { "name": "source/dialogs/dialog_templates.c", "index": 338, "status": "Matching" }, { "name": "source/dialogs/dialog_controls.c", "index": 339, "status": "Matching" }, diff --git a/config/symbols.json b/config/symbols.json index 3edeed64..db0bd569 100644 --- a/config/symbols.json +++ b/config/symbols.json @@ -1801,7 +1801,7 @@ { "file_offset": 546832, "flags": 32, "name": "_device_frontfacing" }, { "file_offset": 546960, "flags": 32, "name": "_device_set_desired_position" }, { "file_offset": 547024, "flags": 32, "name": "_device_set_power" }, -{ "file_offset": 547104, "flags": 32, "name": "_code_00085920" }, +{ "file_offset": 547104, "flags": 32, "name": "_edit_text_fix_selection" }, { "file_offset": 547232, "flags": 32, "name": "_edit_text_selection_reset" }, { "file_offset": 547344, "flags": 32, "name": "_edit_text_get_selection_indices" }, { "file_offset": 547504, "flags": 32, "name": "_edit_text_new" }, @@ -3648,15 +3648,15 @@ { "file_offset": 862848, "flags": 32, "name": "_progress_bar_display" }, { "file_offset": 863008, "flags": 32, "name": "_terminal_initialize" }, { "file_offset": 863072, "flags": 32, "name": "_terminal_dispose" }, -{ "file_offset": 863120, "flags": 32, "name": "_code_000d2b90" }, +{ "file_offset": 863120, "flags": 32, "name": "_terminal_remove_line" }, { "file_offset": 863264, "flags": 32, "name": "_terminal_clear" }, { "file_offset": 863312, "flags": 32, "name": "_terminal_gets_active" }, { "file_offset": 863328, "flags": 32, "name": "_terminal_gets_begin" }, { "file_offset": 863456, "flags": 32, "name": "_terminal_gets_end" }, -{ "file_offset": 863488, "flags": 32, "name": "_code_000d2d00" }, -{ "file_offset": 863680, "flags": 32, "name": "_code_000d2dc0" }, +{ "file_offset": 863488, "flags": 32, "name": "_terminal_update_input" }, +{ "file_offset": 863680, "flags": 32, "name": "_terminal_update_output" }, { "file_offset": 863760, "flags": 32, "name": "_terminal_draw" }, -{ "file_offset": 864448, "flags": 32, "name": "_code_000d30c0" }, +{ "file_offset": 864448, "flags": 32, "name": "_terminal_new_line" }, { "file_offset": 864608, "flags": 32, "name": "_terminal_update" }, { "file_offset": 864656, "flags": 32, "name": "_terminal_printf" }, { "file_offset": 864960, "flags": 32, "name": "_code_000d32c0" }, @@ -5223,37 +5223,37 @@ { "file_offset": 1234416, "flags": 32, "name": "_object_definition_predict" }, { "file_offset": 1234464, "flags": 32, "name": "_object_predict" }, { "file_offset": 1234640, "flags": 32, "name": "_object_beautify" }, -{ "file_offset": 1234720, "flags": 32, "name": "_code_0012d720" }, -{ "file_offset": 1234880, "flags": 32, "name": "_code_0012d7c0" }, +{ "file_offset": 1234720, "flags": 32, "name": "_object_header_new" }, +{ "file_offset": 1234880, "flags": 32, "name": "_object_header_delete" }, { "file_offset": 1234960, "flags": 32, "name": "_object_header_block_get" }, { "file_offset": 1235104, "flags": 32, "name": "_object_header_block_allocate" }, -{ "file_offset": 1235440, "flags": 32, "name": "_code_0012d9f0" }, -{ "file_offset": 1235520, "flags": 32, "name": "_code_0012da40" }, -{ "file_offset": 1236032, "flags": 32, "name": "_code_0012dc40" }, -{ "file_offset": 1236144, "flags": 32, "name": "_code_0012dcb0" }, -{ "file_offset": 1236288, "flags": 32, "name": "_code_0012dd40" }, -{ "file_offset": 1236320, "flags": 32, "name": "_code_0012dd60" }, -{ "file_offset": 1236512, "flags": 32, "name": "_code_0012de20" }, -{ "file_offset": 1236992, "flags": 32, "name": "_code_0012e000" }, +{ "file_offset": 1235440, "flags": 32, "name": "_object_postprocess_node_matrices" }, +{ "file_offset": 1235520, "flags": 32, "name": "_object_choose_random_change_colors" }, +{ "file_offset": 1236032, "flags": 32, "name": "_object_find_region_permutations_available_with_variant" }, +{ "file_offset": 1236144, "flags": 32, "name": "_object_determine_variant_number" }, +{ "file_offset": 1236288, "flags": 32, "name": "_object_add_to_list" }, +{ "file_offset": 1236320, "flags": 32, "name": "_object_remove_from_list" }, +{ "file_offset": 1236512, "flags": 32, "name": "_object_compute_change_colors" }, +{ "file_offset": 1236992, "flags": 32, "name": "_object_compute_function_values" }, { "file_offset": 1237888, "flags": 32, "name": "_object_scripting_set_collideable" }, { "file_offset": 1237952, "flags": 32, "name": "_object_marker_begin" }, { "file_offset": 1238032, "flags": 32, "name": "_object_marker_end" }, { "file_offset": 1238096, "flags": 32, "name": "_object_unmarked_function" }, { "file_offset": 1238176, "flags": 32, "name": "_object_mark_function" }, -{ "file_offset": 1238272, "flags": 32, "name": "_code_0012e500" }, -{ "file_offset": 1238704, "flags": 32, "name": "_code_0012e6b0" }, -{ "file_offset": 1238864, "flags": 32, "name": "_code_0012e750" }, -{ "file_offset": 1238928, "flags": 32, "name": "_code_0012e790" }, -{ "file_offset": 1238944, "flags": 32, "name": "_code_0012e7a0" }, -{ "file_offset": 1238976, "flags": 32, "name": "_code_0012e7c0" }, -{ "file_offset": 1239104, "flags": 32, "name": "_code_0012e840" }, -{ "file_offset": 1239184, "flags": 32, "name": "_code_0012e890" }, +{ "file_offset": 1238272, "flags": 32, "name": "_attachments_new" }, +{ "file_offset": 1238704, "flags": 32, "name": "_object_connect_lights" }, +{ "file_offset": 1238864, "flags": 32, "name": "_object_name_list_allocate" }, +{ "file_offset": 1238928, "flags": 32, "name": "_object_name_list_free" }, +{ "file_offset": 1238944, "flags": 32, "name": "_object_name_list_clear" }, +{ "file_offset": 1238976, "flags": 32, "name": "_object_name_list_new" }, +{ "file_offset": 1239104, "flags": 32, "name": "_object_name_list_delete" }, +{ "file_offset": 1239184, "flags": 32, "name": "_object_name_list_lookup" }, { "file_offset": 1239216, "flags": 32, "name": "_objects_place" }, -{ "file_offset": 1239248, "flags": 32, "name": "_code_0012e8d0" }, +{ "file_offset": 1239248, "flags": 32, "name": "_recursive_object_adder" }, { "file_offset": 1239408, "flags": 32, "name": "_find_objects_from_point_vector" }, -{ "file_offset": 1240016, "flags": 32, "name": "_code_0012ebd0" }, -{ "file_offset": 1240064, "flags": 32, "name": "_code_0012ec00" }, -{ "file_offset": 1240208, "flags": 32, "name": "_code_0012ec90" }, +{ "file_offset": 1240016, "flags": 32, "name": "_sort_dumps" }, +{ "file_offset": 1240064, "flags": 32, "name": "_object_add_to_dump" }, +{ "file_offset": 1240208, "flags": 32, "name": "_object_dump_write" }, { "file_offset": 1240320, "flags": 32, "name": "_objects_dump_memory" }, { "file_offset": 1241184, "flags": 32, "name": "_objects_initialize" }, { "file_offset": 1241504, "flags": 32, "name": "_objects_initialize_for_new_map" }, @@ -5281,11 +5281,11 @@ { "file_offset": 1245088, "flags": 32, "name": "_objects_disconnect_from_structure_bsp" }, { "file_offset": 1245232, "flags": 32, "name": "_object_visible_to_any_player" }, { "file_offset": 1245728, "flags": 32, "name": "_object_pvs_activate" }, -{ "file_offset": 1245776, "flags": 32, "name": "_code_00130250" }, -{ "file_offset": 1245984, "flags": 32, "name": "_code_00130320" }, -{ "file_offset": 1246112, "flags": 32, "name": "_code_001303a0" }, +{ "file_offset": 1245776, "flags": 32, "name": "_object_select_random_region_permutations_by_variant" }, +{ "file_offset": 1245984, "flags": 32, "name": "_object_choose_random_region_permutations" }, +{ "file_offset": 1246112, "flags": 32, "name": "_object_create_attachments" }, { "file_offset": 1246160, "flags": 32, "name": "_objects_scripting_set_scale" }, -{ "file_offset": 1246224, "flags": 32, "name": "_code_00130410" }, +{ "file_offset": 1246224, "flags": 32, "name": "_object_delete_initial_recursive" }, { "file_offset": 1246480, "flags": 32, "name": "_object_delete" }, { "file_offset": 1246512, "flags": 32, "name": "_object_reconnect_to_map" }, { "file_offset": 1246976, "flags": 32, "name": "_object_get_node_matrix" }, @@ -5303,19 +5303,19 @@ { "file_offset": 1250240, "flags": 32, "name": "_object_compute_node_matrices" }, { "file_offset": 1256800, "flags": 32, "name": "_objects_scripting_detach" }, { "file_offset": 1256864, "flags": 32, "name": "_object_render_debug" }, -{ "file_offset": 1258064, "flags": 32, "name": "_code_00133250" }, +{ "file_offset": 1258064, "flags": 32, "name": "_attachments_delete" }, { "file_offset": 1258288, "flags": 32, "name": "_object_set_position" }, { "file_offset": 1258544, "flags": 32, "name": "_object_translate" }, { "file_offset": 1258704, "flags": 32, "name": "_object_new" }, { "file_offset": 1260176, "flags": 32, "name": "_object_attach_to_node" }, { "file_offset": 1260608, "flags": 32, "name": "_object_force_inside_bsp" }, -{ "file_offset": 1260864, "flags": 32, "name": "_code_00133d40" }, +{ "file_offset": 1260864, "flags": 32, "name": "_object_update" }, { "file_offset": 1261296, "flags": 32, "name": "_object_compute_node_matrices_recursive" }, -{ "file_offset": 1261440, "flags": 32, "name": "_code_00133f80" }, +{ "file_offset": 1261440, "flags": 32, "name": "_object_delete_attachments" }, { "file_offset": 1261504, "flags": 32, "name": "_object_new_from_scenario" }, { "file_offset": 1261744, "flags": 32, "name": "_object_attach_to_marker" }, { "file_offset": 1261968, "flags": 32, "name": "_object_new_by_name" }, -{ "file_offset": 1262080, "flags": 32, "name": "_code_00134200" }, +{ "file_offset": 1262080, "flags": 32, "name": "_object_delete_recursive" }, { "file_offset": 1262384, "flags": 32, "name": "_objects_scripting_attach" }, { "file_offset": 1262464, "flags": 32, "name": "_object_delete_immediately" }, { "file_offset": 1262496, "flags": 32, "name": "_objects_garbage_collection" }, @@ -7976,7 +7976,6 @@ { "file_offset": 1870665, "flags": 32, "name": "__fpmath" }, { "file_offset": 1870680, "flags": 32, "name": "__ftol2" }, { "file_offset": 1870800, "flags": 32, "name": "__chkstk" }, -{ "file_offset": 1870800, "flags": 32, "name": "__alloca_probe" }, { "file_offset": 1870816, "flags": 32, "name": "_sprintf" }, { "file_offset": 1870904, "flags": 32, "name": "__scprintf" }, { "file_offset": 1870953, "flags": 32, "name": "__snprintf" }, @@ -18942,7 +18941,7 @@ { "file_offset": 2661600, "flags": 0, "name": "??_C@_0IC@DHNDHHAP@definition?9?$DOpalette_tag_block_of@" }, { "file_offset": 2661732, "flags": 0, "name": "??_C@_0CL@LMPCIGEO@definition?9?$DOpalette_tag_block_of@" }, { "file_offset": 2661776, "flags": 0, "name": "??_C@_07OBIJJHNE@?$CGmatrix?$AA@" }, -{ "file_offset": 2661784, "flags": 0, "name": "_rdata_00289d98" }, +{ "file_offset": 2661784, "flags": 0, "name": "_object_memory_release_procs" }, { "file_offset": 2661808, "flags": 0, "name": "??_C@_0P@LFOALBOL@objects_update?$AA@" }, { "file_offset": 2661824, "flags": 0, "name": "??_C@_0IM@GHLCLNJO@iterator?9?$DOcluster_partition?$DN?$DN?$CGco@" }, { "file_offset": 2661964, "flags": 0, "name": "??_C@_0CB@HJEGKKGJ@c?3?2halo?2SOURCE?2objects?2objects?4c@" }, @@ -22155,7 +22154,7 @@ { "file_offset": 3195472, "flags": 0, "name": "_light_fixture_data_definition" }, { "file_offset": 3195632, "flags": 0, "name": "_placeholder_data_definition" }, { "file_offset": 3195792, "flags": 0, "name": "_object_type_definitions" }, -{ "file_offset": 3195840, "flags": 0, "name": "_data_0030c3c0" }, +{ "file_offset": 3195840, "flags": 0, "name": "?section@?1??objects_update@@9@9" }, { "file_offset": 3197368, "flags": 0, "name": "_debug_objects_bounding_spheres" }, { "file_offset": 3197376, "flags": 0, "name": "_data_0030c9c0" }, { "file_offset": 3197369, "flags": 0, "name": "_debug_objects_collision_models" }, @@ -22434,7 +22433,7 @@ { "file_offset": 4538416, "flags": 0, "name": "_bss_00454030" }, { "file_offset": 4538888, "flags": 0, "name": "_progress_bar_mode" }, { "file_offset": 4538908, "flags": 0, "name": "_last_t" }, -{ "file_offset": 4538916, "flags": 0, "name": "_bss_00454224" }, +{ "file_offset": 4538916, "flags": 0, "name": "_terminal_globals" }, { "file_offset": 4538944, "flags": 0, "name": "_bss_00454240" }, { "file_offset": 4541168, "flags": 0, "name": "_bss_00454af0" }, { "file_offset": 4541192, "flags": 0, "name": "_single_player_level_data" }, @@ -22481,7 +22480,9 @@ { "file_offset": 4550216, "flags": 0, "name": "_bss_00456e48" }, { "file_offset": 4550292, "flags": 0, "name": "_lights_game_globals" }, { "file_offset": 4550296, "flags": 0, "name": "_bss_00456e98" }, -{ "file_offset": 4550300, "flags": 0, "name": "_bss_00456e9c" }, +{ "file_offset": 4550300, "flags": 0, "name": "_object_name_list" }, +{ "file_offset": 4550304, "flags": 0, "name": "_object_memory_pool" }, +{ "file_offset": 4550308, "flags": 0, "name": "_object_globals" }, { "file_offset": 4550312, "flags": 0, "name": "_debug_objects_position_velocity" }, { "file_offset": 4550316, "flags": 0, "name": "_bss_00456eac" }, { "file_offset": 4550320, "flags": 0, "name": "_bss_00456eb0" }, @@ -22552,7 +22553,7 @@ { "file_offset": 4984048, "flags": 0, "name": "_bss_004c0cf0" }, { "file_offset": 4985088, "flags": 0, "name": "_bss_004c1100" }, { "file_offset": 4987144, "flags": 0, "name": "_bss_004c1908" }, -{ "file_offset": 4987392, "flags": 0, "name": "_bss_004c1a00" }, +{ "file_offset": 4987392, "flags": 0, "name": "_global_language_code" }, { "file_offset": 4987400, "flags": 0, "name": "_bss_004c1a08" }, { "file_offset": 4987912, "flags": 0, "name": "_bss_004c1c08" }, { "file_offset": 5032720, "flags": 0, "name": "_debug_biped_physics" }, diff --git a/source/ai/action_alert.c b/source/ai/action_alert.c index c9199b70..0f26025a 100644 --- a/source/ai/action_alert.c +++ b/source/ai/action_alert.c @@ -42,6 +42,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "actions.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/ai/ai.h b/source/ai/ai.h index cf90039a..5d896711 100644 --- a/source/ai/ai.h +++ b/source/ai/ai.h @@ -14,7 +14,72 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct ai_unit_information_look_data +{ + long unit_index; +}; + +struct ai_object_information_look_data +{ + long object_index; +}; + +struct ai_information_look_data +{ + union + { + struct ai_unit_information_look_data unit; + struct ai_object_information_look_data object; + }; +}; + +struct ai_allegiance_information_data +{ + short team1_index; + short team2_index; + boolean broken; +}; + +struct ai_combat_stimulus_information_data +{ + word pad; +}; + +struct ai_target_knowledge_information_data +{ + long prop_index; +}; + +struct ai_information_data +{ + union + { + struct ai_allegiance_information_data allegiance; + struct ai_combat_stimulus_information_data combat_stimulus; + struct ai_target_knowledge_information_data target_knowledge; + }; +}; + + +struct ai_information_packet +{ + long target_unit_index; + short communication_type; + short dialogue_type_index; + short damage_category; + boolean updated_dialogue_timers; + short look_priority; + short look_type; + struct ai_information_look_data look_data; + short information_type; + struct ai_information_data information_data; +}; + +/* ---------- prototypes/AI.C */ + +boolean ai_release_inactive_swarms(char *result_description, unsigned char *more_to_release, unsigned char *working_memory, short working_memory_size); +void ai_find_inactive_encounters(unsigned char *working_memory, short working_memory_size); +boolean ai_release_inactive_encounters(char *result_description, unsigned char *more_to_release, unsigned char *working_memory, short working_memory_size); /* ---------- globals */ diff --git a/source/ai/ai_debug.h b/source/ai/ai_debug.h index 801ca1e3..a5070aff 100644 --- a/source/ai/ai_debug.h +++ b/source/ai/ai_debug.h @@ -29,6 +29,7 @@ void ai_debug_change_selected_encounter(boolean a1); void ai_debug_change_selected_actor(boolean a1); +char *ai_debug_describe_actor(long actor_index, long unit_index, boolean include_squad, char *buffer, long bufsize); /* ---------- globals */ diff --git a/source/ai/path_obstacles.c b/source/ai/path_obstacles.c index 682be6c0..a479d8f7 100644 --- a/source/ai/path_obstacles.c +++ b/source/ai/path_obstacles.c @@ -62,6 +62,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "path.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/bitmaps/bitmaps.h b/source/bitmaps/bitmaps.h index e82df0f7..3f0ffab2 100644 --- a/source/bitmaps/bitmaps.h +++ b/source/bitmaps/bitmaps.h @@ -14,7 +14,23 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/BITMAPS.C */ + +/* ---------- prototypes/BITMAP_UTILITIES.C */ + +union real_rgb_color *rgb_colors_interpolate( + union real_rgb_color *rgb_result, + unsigned long flags, + union real_rgb_color const *rgb_lower_bound, + union real_rgb_color const *rgb_upper_bound, + real u); +union real_rgb_color *rgb_colors_interpolate_and_scale( + union real_rgb_color *rgb_result, + unsigned long flags, + union real_argb_color const *argb_lower_bound, + union real_argb_color const *argb_upper_bound, + union real_rgb_color const *rgb_scale, + real u); /* ---------- globals */ diff --git a/source/cache/cache_files.c b/source/cache/cache_files.c index 3bc77c95..087343f8 100644 --- a/source/cache/cache_files.c +++ b/source/cache/cache_files.c @@ -122,16 +122,63 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "cache_files.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ +struct cache_file_tag_instance +{ + long group_tag; + long parent_group_tags[2]; + long tag_index; + char *name; + void *base_address; + unsigned long unused[2]; +}; + /* ---------- prototypes */ +// TODO: +/*static*/ struct cache_file_tag_instance *cache_get_tag_instance(long tag_index); + /* ---------- globals */ /* ---------- public code */ +void *tag_get( + long group_tag, + long tag_index) +{ + char expected_group[16]; + char returned_group[16]; + + struct cache_file_tag_instance *tag_instance= cache_get_tag_instance(tag_index); + match_vassert( + "c:\\halo\\SOURCE\\cache\\cache_files.c", + 298, + tag_instance->group_tag == group_tag || + tag_instance->parent_group_tags[0] == group_tag || + tag_instance->parent_group_tags[1] == group_tag, + csprintf( + temporary, + "expected tag group '%s' but got '%s' for %08x", + tag_to_string(group_tag, expected_group), + tag_to_string(tag_instance->group_tag, returned_group), + tag_index) + ); + match_vassert( + "c:\\halo\\SOURCE\\cache\\cache_files.c", + 302, + tag_instance->base_address, + csprintf(temporary, "can't get() a tag with a base address!") + ); + + return tag_instance->base_address; +} + /* ---------- private code */ diff --git a/source/cache/cache_files.h b/source/cache/cache_files.h index 3574a96a..f0fbd11b 100644 --- a/source/cache/cache_files.h +++ b/source/cache/cache_files.h @@ -8,6 +8,10 @@ header included in hcex build. #define __CACHE_FILES_H #pragma once +/* ---------- headers */ + +#include "real_math.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/cache/predicted_resources.h b/source/cache/predicted_resources.h index 884a734a..431ac645 100644 --- a/source/cache/predicted_resources.h +++ b/source/cache/predicted_resources.h @@ -14,7 +14,10 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/PREDICTED_RESOURCES.C */ + +void predicted_resources_precache(struct tag_block *predicted_resources); +void predicted_resources_sound_precache(long sound_definition_index); /* ---------- globals */ diff --git a/source/cseries/cseries.h b/source/cseries/cseries.h index 005fe5d8..c21821a9 100644 --- a/source/cseries/cseries.h +++ b/source/cseries/cseries.h @@ -6,6 +6,9 @@ CSERIES.H #define __CSERIES_H #pragma once +#define _USE_MATH_DEFINES + +#include #include #include #include @@ -42,6 +45,33 @@ enum CHAR_BITS_BITS= 3 }; +enum +{ + _x= 0, + _y, + _z, + NUMBER_OF_RECTANGLE2D_COMPONENTS= 4, + NUMBER_OF_RECTANGLE3D_COMPONENTS= 6, + NUMBER_OF_VERTICES_PER_LINE= 2, + NUMBER_OF_VERTICES_PER_TRIANGLE= 3, + NUMBER_OF_VERTICES_PER_QUADRALATERAL= 4, + NUMBER_OF_VERTICES_PER_QUADRILATERAL= 4, + NUMBER_OF_VERTICES_PER_HEXAGON= 6, + NUMBER_OF_VERTICES_PER_PYRAMID= 5, + NUMBER_OF_VERTICES_PER_CUBE= 8, + NUMBER_OF_TRIANGLES_PER_QUADRILATERAL= 2, + NUMBER_OF_EDGES_PER_TRIANGLE= 3, + NUMBER_OF_EDGES_PER_QUADRALATERAL= 4, + NUMBER_OF_EDGES_PER_HEXAGON= 6, + NUMBER_OF_FACES_PER_CUBE= 6, + _rectangle_top_left= 0, + _rectangle_bottom_left= 1, + _rectangle_top_right= 2, + _rectangle_bottom_right= 3, + NUMBER_OF_POINTS_PER_RECTANGLE= 4, +}; + + #define NONE -1 /* ---------- macros */ @@ -82,7 +112,7 @@ enum #define PIN(n,floor,ceiling) ((n)<(floor) ? (floor) : CEILING(n,ceiling)) #define FLAG(b) (1<<(b)) -#define TEST_FLAG(flags, bit) ((flags)&(unsigned)FLAG(bit)) +#define TEST_FLAG(flags, bit) (((flags)&(unsigned)FLAG(bit))!=0) #define SET_FLAG(f, b, v) ((v) ? ((f)|=(unsigned)FLAG(b)) : ((f)&=(unsigned)~FLAG(b))) #define BIT_VECTOR_SIZE_IN_LONGS(bit_count) (((bit_count) + (LONG_BITS - 1)) >> LONG_BITS_BITS) @@ -94,6 +124,12 @@ enum #define NUMBEROF(array) (sizeof(array) / sizeof(array[0])) +#define VALID_INDEX(index, count) (index>=0 && index>SHORT_BITS) + /* ---------- fixed math */ #define SHORT_FIXED_TO_LONG(f) ((f)>>CHAR_BITS) diff --git a/source/cseries/profile.h b/source/cseries/profile.h index deb8f2cd..b74ec450 100644 --- a/source/cseries/profile.h +++ b/source/cseries/profile.h @@ -10,12 +10,41 @@ PROFILE.H /* ---------- macros */ +#define profile_enter(section) \ +if (profile_global_enable && section.profile_active) \ +{ \ + profile_enter_private(§ion); \ +} \ + +#define profile_exit(section) \ +if (profile_global_enable && section.profile_active) \ +{ \ + profile_exit_private(§ion); \ +} \ + /* ---------- structures */ +struct profile_section +{ + const char *name; + long section_index; + boolean profile_active; + short stack_depth; + long field_C; + unsigned __int64 field_10; + char __unknown18[1460]; + long field_5CC; + char __unknown5D0[40]; +}; + /* ---------- prototypes/PROFILE.C */ void profile_initialize(void); +void profile_enter_private(struct profile_section *objects_update_section); + +void profile_exit_private(struct profile_section *objects_update_section); + /* ---------- globals */ /* comm */ diff --git a/source/cseries/stack_walk_windows.c b/source/cseries/stack_walk_windows.c index b8568228..564edf67 100644 --- a/source/cseries/stack_walk_windows.c +++ b/source/cseries/stack_walk_windows.c @@ -151,7 +151,7 @@ struct _stack_walk_globals stack_walk_globals= void stack_walk_disregard_symbol_names( boolean disregard) { - stack_walk_globals.disregard_symbol_names = disregard; + stack_walk_globals.disregard_symbol_names= disregard; } void free_symbol_table( diff --git a/source/devices/device_definitions.h b/source/devices/device_definitions.h index 652f2fa3..2b12ddfa 100644 --- a/source/devices/device_definitions.h +++ b/source/devices/device_definitions.h @@ -8,12 +8,103 @@ header included in hcex build. #define __DEVICE_DEFINITIONS_H #pragma once +/* ---------- headers */ + +#include "objects/object_definitions.h" + /* ---------- constants */ +enum +{ + DEVICE_DEFINITION_TAG= 'devi', + DEVICE_DEFINITION_VERSION= 1, +}; + +enum +{ + _device_position_loops_bit= 0, + _device_position_animation_not_interpolated_bit, + NUMBER_OF_DEVICE_DEFINITION_FLAGS, +}; + +enum +{ + MACHINE_DEFINITION_TAG= 'mach', + MACHINE_DEFINITION_VERSION= 1, +}; + +enum +{ + _machine_is_pathfinding_obstacle_bit= 0, + _machine_is_not_pathfinding_obstacle_when_open_bit, + _machine_is_elevator_bit, + NUMBER_OF_MACHINE_FLAGS, +}; + + /* ---------- macros */ +#define device_definition_get(index) ((struct device_definition *)tag_get(DEVICE_DEFINITION_TAG, index)) + +#define machine_definition_get(index) ((struct machine_definition *)tag_get(MACHINE_DEFINITION_TAG, index)) + /* ---------- structures */ +struct _device_definition +{ + unsigned int flags; + real power_transition_time; + real power_acceleration_time; + real powered_position_transition_time; + real powered_position_acceleration_time; + real depowered_position_transition_time; + real depowered_position_acceleration_time; + short function_modes[4]; + struct tag_reference positive_start_effect; + struct tag_reference negative_start_effect; + struct tag_reference positive_stop_effect; + struct tag_reference negative_stop_effect; + struct tag_reference depowered_effect; + struct tag_reference repowered_effect; + real delay_time; + unsigned long delay_unused[2]; + struct tag_reference delay_effect; + real automatic_activation_radius; + unsigned long unused[21]; + real runtime_maximum_power_acceleration; + real runtime_maximum_power_velocity; + real runtime_maximum_depowered_position_acceleration; + real runtime_maximum_depowered_position_velocity; + real runtime_maximum_powered_position_acceleration; + real runtime_maximum_powered_position_velocity; + real runtime_delay_ticks; +}; + +struct device_definition +{ + struct _object_definition object; + struct _device_definition device; +}; + +struct _machine_definition +{ + short type; + word flags; + real door_open_time; + unsigned long unused1[20]; + short collision_response; + short elevator_node_index; + unsigned int unused2[13]; + long runtime_door_open_ticks; +}; + +struct machine_definition +{ + struct _object_definition object; + struct _device_definition device; + struct _machine_definition machine; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/devices/devices.h b/source/devices/devices.h index 521d2874..8158b402 100644 --- a/source/devices/devices.h +++ b/source/devices/devices.h @@ -8,13 +8,70 @@ header included in hcex build. #define __DEVICES_H #pragma once +/* ---------- headers */ + +#include "objects/objects.h" + /* ---------- constants */ +enum +{ + _scenario_device_initially_open_bit= 0, + _scenario_device_initially_off_bit, + _scenario_device_changes_only_once_bit, + _scenario_device_position_reversed_bit, + _scenario_device_not_usable_bit, + SCENARIO_DEVICE_DATUM_FLAGS, +}; + +enum +{ + _machine_does_not_operate_automatically_bit= 0, + _machine_one_sided_bit, + _machine_never_appears_locked_bit, + _machine_opened_by_melee_attack_bit, + NUMBER_OF_MACHINE_DATUM_FLAGS, +}; + /* ---------- macros */ /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct _device_datum +{ + unsigned long flags; + short power_group_index; + real power; + real power_velocity; + short position_group_index; + real position; + real position_velocity; + short delay_ticks; +}; + +struct device_datum +{ + long definition_index; + struct _object_datum object; + struct _device_datum device; +}; + +struct _machine_datum +{ + unsigned long flags; + long door_open_ticks; + real_point3d elevator_position; +}; + +struct machine_datum +{ + long definition_index; + struct _object_datum object; + struct _device_datum device; + struct _machine_datum machine; +}; + +/* ---------- prototypes/DEVICES.C */ /* ---------- globals */ diff --git a/source/dialogs/edit_text.c b/source/dialogs/edit_text.c index 13738b4d..25ace6d2 100644 --- a/source/dialogs/edit_text.c +++ b/source/dialogs/edit_text.c @@ -20,6 +20,12 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "edit_text.h" + +#include "input/input.h" +#include "text/international_strings.h" + /* ---------- constants */ /* ---------- macros */ @@ -28,8 +34,216 @@ symbols in this file: /* ---------- prototypes */ +static void edit_text_fix_selection(struct edit_text *edit); + /* ---------- globals */ /* ---------- public code */ +void edit_text_new( + struct edit_text *edit) +{ + match_assert("c:\\halo\\SOURCE\\dialogs\\edit_text.c", 25, valid_edit_text(edit)); + edit_text_selection_reset(edit); + + return; +} + +void edit_text_handle_key( + struct edit_text *edit, + struct key_stroke const *key) +{ + boolean backspace; + + match_assert("c:\\halo\\SOURCE\\dialogs\\edit_text.c", 35, valid_edit_text(edit)); + edit_text_fix_selection(edit); + + if (key->key_code==_key_backspace) + { + backspace= TRUE; + } + + if (key->key_code==_key_backspace || + key->key_code==_key_delete) + { + short selection_end; + short selection_start; + + if (edit_text_get_selection_indices( + edit, + &selection_start, + &selection_end)) + { + memmove( + &edit->buffer[selection_start], + &edit->buffer[selection_end], + strlen(&edit->buffer[selection_end])+1); + edit->insertion_point_index= selection_start; + edit->selection_start_index= NONE; + } + else if (key->key_code==_key_backspace && + edit->insertion_point_index > 0) + { + short src_index= edit->insertion_point_index; + get_previous_character( + (unsigned char *)edit->buffer, + &edit->insertion_point_index); + memmove( + &edit->buffer[edit->insertion_point_index], + &edit->buffer[src_index], + strlen(&edit->buffer[src_index])+1); + } + else if (key->key_code == _key_delete) + { + if (edit->insertion_point_index < strlen(edit->buffer)) + { + short next_index= edit->insertion_point_index; + get_next_character( + (unsigned char *)edit->buffer, + &next_index + ); + memmove( + &edit->buffer[edit->insertion_point_index], + &edit->buffer[next_index], + strlen(&edit->buffer[next_index])+1); + } + } + } + else if ( + key->key_code==_key_left_arrow || + key->key_code==_key_right_arrow) + { + short selection_end; + short selection_start; + + if (TEST_FLAG(key->modifier_flags, 0) || + !edit_text_get_selection_indices( + edit, + &selection_start, + &selection_end)) + { + if (TEST_FLAG(key->modifier_flags, 0) && edit->selection_start_index==NONE) + { + edit->selection_start_index= edit->insertion_point_index; + } + + if (key->key_code==_key_left_arrow && edit->insertion_point_index>0) + { + get_previous_character( + (unsigned char *)edit->buffer, + &edit->insertion_point_index); + } + else if (key->key_code==_key_right_arrow) + { + if (edit->insertion_point_indexbuffer)) + { + get_next_character( + (unsigned char *)edit->buffer, + &edit->insertion_point_index); + } + } + + if (edit->selection_start_index==edit->insertion_point_index) + { + edit->selection_start_index= NONE; + } + } + else + { + if (key->key_code==_key_left_arrow) + { + edit->insertion_point_index= selection_start; + edit->selection_start_index= NONE; + } + else + { + edit->insertion_point_index= selection_end; + edit->selection_start_index= NONE; + } + } + } + else if (key->ascii_code && key->ascii_code!=(byte)NONE) + { + short selection_end; + short selection_start; + + if (edit_text_get_selection_indices( + edit, + &selection_start, + &selection_end)) + { + memmove( + &edit->buffer[selection_start+1], + &edit->buffer[selection_end], + strlen(&edit->buffer[selection_end])+1); + + edit->insertion_point_index= selection_start; + edit->selection_start_index= NONE; + edit->buffer[edit->insertion_point_index++]= key->ascii_code; + } + else if (strlen(edit->buffer)maximum_length) + { + memmove( + &edit->buffer[edit->insertion_point_index+1], + &edit->buffer[edit->insertion_point_index], + strlen(&edit->buffer[edit->insertion_point_index])+1); + edit->buffer[edit->insertion_point_index++]= key->ascii_code; + } + } + + align_to_character( + (unsigned char *)edit->buffer, + &edit->insertion_point_index); + + return; +} + +boolean edit_text_get_selection_indices(struct edit_text *edit, short *start_index, short *end_index) +{ + boolean result= FALSE; + match_assert("c:\\halo\\SOURCE\\dialogs\\edit_text.c", 174, valid_edit_text(edit)); + edit_text_fix_selection(edit); + + if (edit->selection_start_index != NONE) + { + *start_index= edit->selection_start_index > edit->insertion_point_index ? edit->insertion_point_index : edit->selection_start_index; + *end_index= edit->selection_start_index > edit->insertion_point_index ? edit->selection_start_index : edit->insertion_point_index; + result= TRUE; + } + + return result; +} + +void edit_text_selection_reset( + struct edit_text *edit) +{ + match_assert("c:\\halo\\SOURCE\\dialogs\\edit_text.c", 159, valid_edit_text(edit)); + edit_text_fix_selection(edit); + edit->insertion_point_index= (short)strlen(edit->buffer); + edit->selection_start_index= NONE; + + return; +} + /* ---------- private code */ + +static void edit_text_fix_selection( + struct edit_text *edit) +{ + short length= (short)strlen(edit->buffer); + edit->insertion_point_index= PIN(edit->insertion_point_index, 0, length); + edit->selection_start_index= PIN(edit->selection_start_index, NONE, length); + + if (edit->insertion_point_index == edit->selection_start_index) + { + edit->selection_start_index= NONE; + } + + align_to_character((unsigned char *)edit->buffer, &edit->insertion_point_index); + if (edit->selection_start_index != NONE) + { + align_to_character((unsigned char*)edit->buffer, &edit->selection_start_index); + } + + return; +} diff --git a/source/dialogs/edit_text.h b/source/dialogs/edit_text.h index 4eb52ef0..7f744fc2 100644 --- a/source/dialogs/edit_text.h +++ b/source/dialogs/edit_text.h @@ -27,12 +27,9 @@ struct edit_text /* ---------- prototypes/EDIT_TEXT.C */ -void edit_text_handle_key(struct edit_text *edit, struct key_stroke const *key); - -boolean edit_text_get_selection_indices(struct edit_text *edit, short *start_index, short *end_index); - void edit_text_new(struct edit_text *edit); - +void edit_text_handle_key(struct edit_text *edit, struct key_stroke const *key); +boolean edit_text_get_selection_indices(struct edit_text *edit, short *start_index, short *end_index); void edit_text_selection_reset(struct edit_text *edit); /* ---------- globals */ diff --git a/source/effects/contrail_definitions.h b/source/effects/contrail_definitions.h index fbd19fa1..7e30e4e4 100644 --- a/source/effects/contrail_definitions.h +++ b/source/effects/contrail_definitions.h @@ -10,6 +10,13 @@ header included in hcex build. /* ---------- constants */ +enum +{ + CONTRAIL_DEFINITION_TAG= 'cont', + CONTRAIL_DEFINITION_VERSION= 3, + MAXIMUM_CONTRAIL_POINT_STATES_PER_CONTRAIL= 16, +}; + /* ---------- macros */ /* ---------- structures */ diff --git a/source/effects/contrails.h b/source/effects/contrails.h index c22c92c0..1fcf9db0 100644 --- a/source/effects/contrails.h +++ b/source/effects/contrails.h @@ -14,7 +14,10 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/CONTRAILS.C */ + +long contrail_new(long definition_index, long object_index, short attachment_index); +void contrail_owner_collision(long contrail_index, unsigned char object_dying, real dt); /* ---------- globals */ diff --git a/source/effects/effect_definitions.h b/source/effects/effect_definitions.h index b2e5589c..5c42886f 100644 --- a/source/effects/effect_definitions.h +++ b/source/effects/effect_definitions.h @@ -10,6 +10,16 @@ header included in hcex build. /* ---------- constants */ +enum +{ + EFFECT_DEFINITION_TAG= 'effe', + EFFECT_DEFINITION_VERSION= 4, + MAXIMUM_EFFECT_PARTICLES_PER_EVENT= 32, + MAXIMUM_EFFECT_PARTS_PER_EVENT= 32, + MAXIMUM_EFFECT_LOCATIONS= 32, + MAXIMUM_EFFECT_EVENTS= 32, +}; + /* ---------- macros */ /* ---------- structures */ diff --git a/source/effects/effects.h b/source/effects/effects.h index 600d8fab..930fa869 100644 --- a/source/effects/effects.h +++ b/source/effects/effects.h @@ -14,7 +14,26 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/EFFECTS.C */ + +long effect_new_looping( + long definition_index, + long object_index, + short scale_a_function_index, + short scale_b_function_index, + short change_color_index); + +long effect_new_from_object( + long definition_index, + long owner_object_index, + long object_index, + short force_local_player_index, + real scale_a, + real scale_b, + real_rgb_color const *color, + struct effect_vector_field const *impulse_field); + +void effect_delete(long effect_index); /* ---------- globals */ diff --git a/source/effects/particle_system_definitions.h b/source/effects/particle_system_definitions.h index 62dcc7e0..a75cb084 100644 --- a/source/effects/particle_system_definitions.h +++ b/source/effects/particle_system_definitions.h @@ -10,6 +10,12 @@ header included in hcex build. /* ---------- constants */ +enum +{ + PARTICLE_SYSTEM_DEFINITION_TAG= 'pctl', + PARTICLE_SYSTEM_DEFINITION_VERSION= 4, +}; + /* ---------- macros */ /* ---------- structures */ diff --git a/source/effects/particle_systems.h b/source/effects/particle_systems.h index 3ab63b8e..7c00cd0a 100644 --- a/source/effects/particle_systems.h +++ b/source/effects/particle_systems.h @@ -14,7 +14,11 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/PARTICLE_SYSTEMS.C */ + +long particle_system_new_attached(long definition_index, long object_index, short attachment_index); + +void particle_system_orphan(long system_index); /* ---------- globals */ diff --git a/source/game/game.h b/source/game/game.h index 30b81835..a1e064a8 100644 --- a/source/game/game.h +++ b/source/game/game.h @@ -32,6 +32,68 @@ enum /* ---------- structures */ +struct slayer_statistics +{ + short ignored; +}; + +struct ctf_statistics +{ + short flag_grabs; + short flag_returns; + short flag_scores; +}; + +struct oddball_statistics +{ + short time_with_the_ball; + short ball_carrier_kills; + short kills_as_ball_carrier; +}; + +struct king_statistics +{ + short time_on_hill; +}; + +struct race_statistics +{ + short last_lap_time; + short laps; + short best_lap_time; +}; + +union multiplayer_statistics +{ + struct slayer_statistics slayer_statistics; + struct ctf_statistics ctf_statistics; + struct oddball_statistics oddball_statistics; + struct king_statistics king_statistics; + struct race_statistics race_statistics; +}; + +struct game_statistics +{ + short sort_key; + short games_played; + short games_won; + short kills_in_a_row; + short multiple_kills; + short last_kill_time; + short kills[4]; + short assists[4]; + short friendly_fire_kills; + short deaths; + short suicides; + long shots_fired; + long shots_hit; + long seconds_online; + short killed_teammate_since_last_death; + short custom_data_size; + union multiplayer_statistics multiplayer_statistics; +}; + + /* ---------- prototypes/GAME.C */ void game_initialize(void); @@ -42,7 +104,7 @@ void game_unload(void); void game_dispose_from_old_map(void); void game_frame(real dt); void remove_quitting_players_from_game(void); -void game_tick(int ticks_remaining_this_frame); +void game_tick(long ticks_remaining_this_frame); void game_options_new(struct game_options *options); boolean game_options_verify(struct game_options *options); void game_initial_pulse(void); diff --git a/source/game/game_engine.c b/source/game/game_engine.c index 1d2b0567..a1f5f120 100644 --- a/source/game/game_engine.c +++ b/source/game/game_engine.c @@ -536,6 +536,11 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "game_engine.h" + +#include "objects.h" + /* ---------- constants */ /* ---------- macros */ @@ -546,6 +551,38 @@ symbols in this file: /* ---------- globals */ +struct game_engine *game_engine; + /* ---------- public code */ +boolean game_engine_running( + void) +{ + return game_engine!=NULL; +} + +long game_engine_remap_object_definition( + long definition_index) +{ + if (game_engine_running() && definition_index!=NONE) + { + switch (object_definition_get(definition_index)->object.type) + { + case _object_type_vehicle: + definition_index= game_engine_remap_vehicle(definition_index); + break; + case _object_type_weapon: + definition_index= game_engine_remap_weapon(definition_index); + break; + case _object_type_equipment: + definition_index= game_engine_remap_equipment(definition_index); + break; + default: + break; + } + } + + return definition_index; +} + /* ---------- private code */ diff --git a/source/game/game_engine.h b/source/game/game_engine.h index 03127998..b1e309d2 100644 --- a/source/game/game_engine.h +++ b/source/game/game_engine.h @@ -14,10 +14,20 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/GAME_ENGINE.C */ + +boolean game_engine_running(void); + +long game_engine_remap_object_definition(long definition_index); + +long game_engine_remap_vehicle(long vehicle_definition_index); +long game_engine_remap_equipment(long equipment_definition_index); +long game_engine_remap_weapon(long weapon_definition_index); /* ---------- globals */ +extern struct game_engine *game_engine; + /* ---------- public code */ #endif // __GAME_ENGINE_H diff --git a/source/game/players.h b/source/game/players.h index 24bf951b..fd663d19 100644 --- a/source/game/players.h +++ b/source/game/players.h @@ -10,12 +10,78 @@ header included in hcex build. /* ---------- constants */ +enum +{ + _player_powerup_active_camouflage= 0, + _player_powerup_full_spectrum_vision, + NUMBER_OF_PLAYER_POWERUPS, +}; + + /* ---------- macros */ +#define player_get(index) ((struct player_datum*)datum_get(player_data, index)) +#define player_try_and_get(index) ((struct player_datum*)datum_try_and_get(player_data, index)) + /* ---------- structures */ +struct player_action +{ + unsigned long control_flags; + real_euler_angles2d desired_facing; + real_vector2d throttle; + real primary_trigger; + short desired_weapon_index; + short desired_grenade_index; + short desired_zoom_level; + short pad; +}; + +struct network_player +{ + wchar_t name[12]; + short primary_color_index; + short icon_index; + char machine_index; + char controller_index; + char team_index; + char player_list_index; +}; + +struct player_datum +{ + short identifier; + short local_player_index; + wchar_t name[12]; + long squad_index; + long team_index; + long action_object_index; + short action_result; + short action_seat_index; + long respawn_timer; + long respawn_penalty; + long unit_index; + long dead_unit_index; + short cluster_index; + boolean swapped_weapons; + byte pad0; + long aim_assist_unit_index; + long aim_assist_timestamp; + struct network_player network_player_data; + short powerup_durations[NUMBER_OF_PLAYER_POWERUPS]; + struct game_statistics statistics; + long telefrag_timeout; + long quit_out_of_game_time; + boolean is_blocking_teleporter; + boolean quit_out_of_game; + struct player_action action_input; +}; + /* ---------- prototypes/PLAYERS.C */ +unsigned long const *players_get_combined_pvs_local(void); +unsigned long const *players_get_combined_pvs(void); + void player_control_fix_for_loaded_game_state(void); /* ---------- prototypes/PLAYER_QUEUES_NEW.C */ @@ -24,6 +90,9 @@ void update_queues_reset_and_fill_with_lies(void); /* ---------- globals */ +/* comm */ +struct data_array* player_data; + /* ---------- public code */ #endif // __PLAYERS_H diff --git a/source/interface/terminal.c b/source/interface/terminal.c index 06cebf86..0a8c2c95 100644 --- a/source/interface/terminal.c +++ b/source/interface/terminal.c @@ -213,7 +213,7 @@ void terminal_draw( if (terminal_globals.initialized) { - struct font_header *font= (struct font_header *)tag_get(FONT_GROUP_TAG, font_tag_index); + struct font_header *font= font_definition_get(font_tag_index); short line_height= font->ascending_height + font->descending_height + font->leading_height; if (terminal_globals.input_state) { diff --git a/source/items/weapons.h b/source/items/weapons.h index 704227c8..b1e285f1 100644 --- a/source/items/weapons.h +++ b/source/items/weapons.h @@ -14,7 +14,9 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/WEAPONS.C */ + +boolean weapon_is_flag(long weapon_index); /* ---------- globals */ diff --git a/source/math/integer_math.c b/source/math/integer_math.c index 08f19773..4c737c7a 100644 --- a/source/math/integer_math.c +++ b/source/math/integer_math.c @@ -265,7 +265,7 @@ short ceiling_log2( } unsigned long floor_power2( - unsigned short x) + word x) { long result= 1; while (result*2<= x) @@ -277,7 +277,7 @@ unsigned long floor_power2( } unsigned long ceiling_power2( - unsigned short x) + word x) { long result= 1; while (result < x) diff --git a/source/math/integer_math.h b/source/math/integer_math.h index b7510242..436e7fe8 100644 --- a/source/math/integer_math.h +++ b/source/math/integer_math.h @@ -10,7 +10,7 @@ INTEGER_MATH.H enum { - _adjust_rectangle_center = 0, + _adjust_rectangle_center= 0, _adjust_rectangle_alert, NUMBER_OF_ADJUST_RECTANGLE_MODES, }; @@ -33,6 +33,14 @@ union rectangle2d }; typedef union rectangle2d rectangle2d; +union byte_rectangle3d +{ + byte n[6]; + struct { byte x0, x1, y0, y1, z0, z1; }; +}; +typedef union byte_rectangle3d byte_rectangle3d; + + typedef unsigned long pixel32; /* ---------- prototypes/INTEGER_MATH.C */ @@ -54,8 +62,8 @@ unsigned char equal_rectangle2d(const rectangle2d *r1, const rectangle2d *r2); unsigned char equal_point2d(const point2d *p1, const point2d *p2); short floor_log2(unsigned long k); short ceiling_log2(unsigned long k); -unsigned long floor_power2(unsigned short x); -unsigned long ceiling_power2(unsigned short x); +unsigned long floor_power2(word x); +unsigned long ceiling_power2(word x); unsigned long integer_square_root(unsigned long k); unsigned char bit_vector_and(short count, const unsigned long *v0, const unsigned long *v1, unsigned long *result); void bit_vector_or(short count, const unsigned long *v0, const unsigned long *v1, unsigned long *result); diff --git a/source/math/matrix_math.c b/source/math/matrix_math.c index 349d1058..a0619613 100644 --- a/source/math/matrix_math.c +++ b/source/math/matrix_math.c @@ -86,6 +86,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "real_math.h" + /* ---------- constants */ /* ---------- macros */ @@ -98,4 +101,122 @@ symbols in this file: /* ---------- public code */ +void matrix4x3_inverse( + real_matrix4x3 const *matrix, + real_matrix4x3 *result) +{ + if (matrix->scale!=0.f) + { + real temp; + + real x= -matrix->position.x; + real y= -matrix->position.y; + real z= -matrix->position.z; + + if (matrix->scale!=1.f) + { + real scale= 1.f / matrix->scale; + result->scale= scale; + x *= scale; + y *= scale; + z *= scale; + } + else + { + result->scale= 1.f; + } + + result->n[0][0]= matrix->n[0][0]; + result->n[1][1]= matrix->n[1][1]; + result->n[2][2]= matrix->n[2][2]; + + temp= matrix->n[1][0]; + result->n[1][0]= matrix->n[0][1]; + result->n[0][1]= temp; + + temp= matrix->n[2][0]; + result->n[2][0]= matrix->n[0][2]; + result->n[0][2]= temp; + + temp= matrix->n[2][1]; + result->n[2][1]= matrix->n[1][2]; + result->n[1][2]= temp; + + result->n[3][0]= (x*result->n[0][0]) + y*result->n[1][0] + (z*result->n[2][0]); + result->n[3][1]= (x*result->n[0][1]) + y*result->n[1][1] + (z*result->n[2][1]); + result->n[3][2]= (x*result->n[0][2]) + y*result->n[1][2] + (z*result->n[2][2]); + } + else + { + memset(result, 0, sizeof(*result)); + } + + return; +} + +void matrix4x3_rotation_from_vectors( + real_matrix4x3 *matrix, + real_vector3d const *forward, + real_vector3d const *up) + +{ + matrix->scale= 1.f; + matrix->forward= *forward; + cross_product3d(up, forward, &matrix->left); + + matrix->up= *up; + set_real_point3d(&matrix->position, 0.f, 0.f, 0.f); + + return; +} + +void matrix4x3_from_point_and_vectors( + real_matrix4x3 *matrix, + real_point3d const *point, + real_vector3d const *forward, + real_vector3d const *up) +{ + matrix4x3_rotation_from_vectors(matrix, forward, up); + matrix->position= *point; + + return; +} + +real_point3d *matrix4x3_transform_point( + real_matrix4x3 const *matrix, + real_point3d const *point, + real_point3d *result) +{ + real x= point->x; + real y= point->y; + real z= point->z; + + if (matrix->scale != 1.f) + { + x *= matrix->scale; + y *= matrix->scale; + z *= matrix->scale; + } + + result->x= matrix->up.i*z + matrix->left.i*y + matrix->forward.i*x + matrix->position.x; + result->y= matrix->up.j*z + matrix->left.j*y + matrix->forward.j*x + matrix->position.y; + result->z= matrix->up.k*z + matrix->left.k*y + matrix->forward.k*x + matrix->position.z; + return result; +} + +real_vector3d *matrix4x3_transform_normal( + real_matrix4x3 const *matrix, + real_vector3d const *normal, + real_vector3d *result) +{ + real i= normal->i; + real j= normal->j; + real k= normal->k; + + result->i= i*matrix->forward.i + j*matrix->left.i + k*matrix->up.i; + result->j= i*matrix->forward.j + j*matrix->left.j + k*matrix->up.j; + result->k= i*matrix->forward.k + j*matrix->left.k + k*matrix->up.k; + return result; +} + /* ---------- private code */ diff --git a/source/math/periodic_functions.c b/source/math/periodic_functions.c index abee76c1..2886738b 100644 --- a/source/math/periodic_functions.c +++ b/source/math/periodic_functions.c @@ -90,6 +90,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "periodic_functions.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/math/periodic_functions.h b/source/math/periodic_functions.h index 63084ee3..3eeca544 100644 --- a/source/math/periodic_functions.h +++ b/source/math/periodic_functions.h @@ -8,13 +8,31 @@ header included in hcex build. #define __PERIODIC_FUNCTIONS_H #pragma once +/* ---------- headers */ + +#include "math/real_math.h" + /* ---------- constants */ +enum +{ + _transition_function_linear= 0, + _transition_function_early, + _transition_function_very_early, + _transition_function_late, + _transition_function_very_late, + _transition_function_cosine, + NUMBER_OF_TRANSITION_FUNCTIONS, +}; + /* ---------- macros */ /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/PERIODIC_FUNCTIONS.C */ + +real periodic_function_evaluate(short function_type, real time); +real transition_function_evaluate(short function_type, real value); /* ---------- globals */ diff --git a/source/math/real_math.c b/source/math/real_math.c index 4efdb15d..bf63feba 100644 --- a/source/math/real_math.c +++ b/source/math/real_math.c @@ -237,6 +237,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "real_math.h" + /* ---------- constants */ /* ---------- macros */ @@ -247,6 +250,42 @@ symbols in this file: /* ---------- globals */ +static const real_matrix4x3 private_identity4x3 = +{ + 1.f, + { + { 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f } + }, +}; + +static const real_matrix4x3 private_negative_identity4x3 = +{ + 1.f, + { + { -1.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f } + }, +}; + + +const real_point3d *const global_origin3d= (const real_point3d *const)&private_identity4x3.position; + +const real_point3d *const global_x_axis3d= (const real_point3d *const)&private_identity4x3.forward; +const real_point3d *const global_y_axis3d= (const real_point3d *const)&private_identity4x3.left; +const real_point3d *const global_z_axis3d= (const real_point3d *const)&private_identity4x3.up; +const real_point3d *const global_negative_x_axis3d= (const real_point3d *const)&private_negative_identity4x3.forward; +const real_point3d *const global_negative_y_axis3d= (const real_point3d *const)&private_negative_identity4x3.left; +const real_point3d *const global_negative_z_axis3d= (const real_point3d *const)&private_negative_identity4x3.up; + +const real_vector3d *const global_zero_vector3d= (const real_vector3d *const)&private_identity4x3.position; + +const real_vector3d *const global_forward3d= (const real_vector3d *const)&private_identity4x3.forward; +const real_vector3d *const global_left3d= (const real_vector3d *const)&private_identity4x3.left; +const real_vector3d *const global_up3d= (const real_vector3d *const)&private_identity4x3.up; + +const real_vector3d *const global_backward3d= (const real_vector3d *const)&private_negative_identity4x3.forward; +const real_vector3d *const global_right3d= (const real_vector3d *const)&private_negative_identity4x3.left; +const real_vector3d *const global_down3d= (const real_vector3d *const)&private_negative_identity4x3.up; + /* ---------- public code */ /* ---------- private code */ diff --git a/source/math/real_math.h b/source/math/real_math.h index 5a387a83..58524d23 100644 --- a/source/math/real_math.h +++ b/source/math/real_math.h @@ -10,8 +10,78 @@ file has inline function assertions. /* ---------- constants */ +#define _real_epsilon 0.0001f + /* ---------- macros */ +#define assert_valid_real_point3d(point)\ +vassert( \ + valid_real_point3d(point), \ + csprintf( \ + temporary, \ + "%s: assert_valid_real_point3d(%f, %f, %f)", \ + #point, (*point).x, (*point).y, (*point).z \ + ) \ +) + +#define assert_valid_real_vector3d(file, line, vector) \ +vassert( \ + valid_real_vector3d(vector), \ + csprintf( \ + temporary, \ + "%s: assert_valid_real_vector2d(%f, %f, %f)", \ + #vector, (*vector).i, (*vector).j, (*vector).k \ + ) \ +) + +#define assert_valid_real_vector3d_axes2(forward, up) \ +vassert( \ + valid_real_vector3d_axes2(forward, up), \ + csprintf( \ + temporary, \ + "%s, %s: assert_valid_real_vector3d_axes2(%f, %f, %f / %f, %f, %f)",\ + #forward, #up, \ + (*forward).i, (*forward).j, (*forward).k, (*up).i, (*up).j, (*up).k \ + ) \ +) + +#define match_assert_valid_real_point3d(file, line, point) \ +match_vassert( \ + file, \ + line, \ + valid_real_point3d(point), \ + csprintf( \ + temporary, \ + "%s: assert_valid_real_point3d(%f, %f, %f)", \ + #point, (*point).x, (*point).y, (*point).z \ + ) \ +) + +#define match_assert_valid_real_vector3d(file, line, vector) \ +match_vassert( \ + file, \ + line, \ + valid_real_vector3d(vector), \ + csprintf( \ + temporary, \ + "%s: assert_valid_real_vector2d(%f, %f, %f)", \ + #vector, (*vector).i, (*vector).j, (*vector).k \ + ) \ +) + +#define match_assert_valid_real_vector3d_axes2(file, line, forward, up) \ +match_vassert( \ + file, \ + line, \ + valid_real_vector3d_axes2(forward, up), \ + csprintf( \ + temporary, \ + "%s, %s: assert_valid_real_vector3d_axes2(%f, %f, %f / %f, %f, %f)",\ + #forward, #up, \ + (*forward).i, (*forward).j, (*forward).k, (*up).i, (*up).j, (*up).k \ + ) \ +) + /* ---------- structures */ typedef float real; @@ -169,8 +239,295 @@ typedef union real_argb_color real_argb_color; void real_math_initialize(void); void real_math_dispose(void); +real normalize3d(real_vector3d *v); + +void vectors3d_from_euler_angles3d(real_vector3d *forward, real_vector3d *up, real_euler_angles3d const *angles); + +/* ---------- prototypes/MATRIX_MATH.C */ + +void matrix4x3_identity(real_matrix4x3 *matrix); +void matrix4x3_transpose(real_matrix4x3 *matrix); +void matrix4x3_inverse(real_matrix4x3 const *matrix, real_matrix4x3 *result); +void matrix4x3_scale(real_matrix4x3 *matrix, real scale); +void matrix4x3_translation(real_matrix4x3 *matrix, real_point3d const *point); +void matrix4x3_rotation_from_axis_and_angle(real_matrix4x3 *matrix, real_vector3d const *axis, real sine, real cosine); +void matrix4x3_rotation_from_vectors(real_matrix4x3 *matrix, real_vector3d const *forward, real_vector3d const *up); +void matrix4x3_rotation_from_angles(real_matrix4x3 *matrix, real yaw, real pitch, real roll); +void matrix4x3_rotation_to_angles(real_matrix4x3 *matrix, real_euler_angles3d *angles); +void matrix4x3_rotation_from_quaternion(real_matrix4x3 *matrix, real_quaternion const *quaternion); +void matrix4x3_rotation_to_quaternion(real_matrix4x3 const *matrix, real_quaternion *quaternion); +void matrix4x3_from_point_and_vectors(real_matrix4x3 *matrix, real_point3d const *point, real_vector3d const *forward, real_vector3d const *up); +void matrix4x3_from_point_and_quaternion(real_matrix4x3 *matrix, real_point3d const *point, real_quaternion const *quaternion); +void matrix4x3_from_orientation(real_matrix4x3 *matrix, real_orientation const *orientation); +void matrix4x3_from_plane(real_matrix4x3 *matrix, real_plane3d const *plane); +void matrix4x3_to_point_and_vectors(real_matrix4x3 const *matrix, real_point3d *point, real_vector3d *forward, real_vector3d *up); +real_vector3d *vector_from_matrices4x3(real_matrix4x3 const *a, real_matrix4x3 const *b, real_vector3d *rotation); +real_point3d *matrix4x3_transform_point(real_matrix4x3 const *matrix, real_point3d const *point, real_point3d *result); +real_vector3d *matrix4x3_transform_vector(real_matrix4x3 const *matrix, real_vector3d const *vector, real_vector3d *result); +real_vector3d *matrix4x3_transform_normal(real_matrix4x3 const *matrix, real_vector3d const *normal, real_vector3d *result); +real_plane3d *matrix4x3_transform_plane(real_matrix4x3 const *matrix, real_plane3d const *plane, real_plane3d *result); +real_point3d *matrix4x3_inverse_transform_point(real_matrix4x3 const *matrix, real_point3d const *point, real_point3d *result); +real_vector3d *matrix4x3_inverse_transform_vector(real_matrix4x3 const *matrix, real_vector3d const *vector, real_vector3d *result); +real_vector3d *matrix4x3_inverse_transform_normal(real_matrix4x3 const *matrix, real_vector3d const *normal, real_vector3d *result); +real_plane3d *matrix4x3_inverse_transform_plane(real_matrix4x3 const *matrix, real_plane3d const *plane, real_plane3d *result); +void matrix4x3_multiply(real_matrix4x3 const *a, real_matrix4x3 const *b, real_matrix4x3 *result); + +/* ---------- prototypes/RANDOM_MATH.C */ + +unsigned long *get_global_random_seed_address(void); + +short seed_random_range(unsigned long *seed, short lower_bound, short upper_bound); + +real real_seed_random(unsigned long *seed); +real real_seed_random_range(unsigned long *seed, real lower_bound, real upper_bound); + /* ---------- globals */ +extern const real_point3d *const global_origin3d; + +extern const real_point3d *const global_x_axis3d; +extern const real_point3d *const global_y_axis3d; +extern const real_point3d *const global_z_axis3d; +extern const real_point3d *const global_negative_x_axis3d; +extern const real_point3d *const global_negative_y_axis3d; +extern const real_point3d *const global_negative_z_axis3d; + +extern const real_vector3d *const global_zero_vector3d; + +extern const real_vector3d *const global_forward3d; +extern const real_vector3d *const global_left3d; +extern const real_vector3d *const global_up3d; + +extern const real_vector3d *const global_backward3d; +extern const real_vector3d *const global_right3d; +extern const real_vector3d *const global_down3d; + /* ---------- public code */ +__inline real sine( + real angle) +{ + return sin(angle); +} + +__inline real cosine( + real angle) +{ + return cos(angle); +} + +__inline real tangent( + real angle) +{ + return tan(angle); +} + +__inline real arctangent( + real y, + real x) +{ + return atan2(y, x); +} + +__inline real arccosine(real x) +{ + return acos(x); +} + +__inline real arcsine(real x) +{ + return asin(x); +} + +__inline real signed_angular_difference( + real angle1, + real angle2) +{ + real result= angle2-angle1; + + if (result>=M_PI) + { + result-= (M_PI*2.f); + } + + if (result<=(-M_PI)) + { + result+= (M_PI*2.f); + } + + return result; +} + +__inline real_point3d *point_from_line3d(real_point3d const *p, real_vector3d const *v, real t, real_point3d *result) +{ + result->x= (v->i*t) + p->x; + result->y= (v->j*t) + p->y; + result->z= (v->k*t) + p->z; + return result; +} + +__inline real dot_product3d( + real_vector3d const *a, + real_vector3d const *b) +{ + return (a->i*b->i) + (a->j*b->j) + (a->k*b->k); +} + +__inline real_vector3d *vector_from_points3d( + real_point3d const *a, + real_point3d const *b, + real_vector3d *result) +{ + result->i= b->x-a->x; + result->j= b->y-a->y; + result->k= b->z-a->z; + return result; +} + +__inline real magnitude_squared3d( + real_vector3d const *vector) +{ + return vector->i*vector->i + vector->j*vector->j + vector->k*vector->k; +} + +__inline real distance_squared3d( + real_point3d const *a, + real_point3d const *b) +{ + real_vector3d v; + + return magnitude_squared3d(vector_from_points3d(a, b, &v)); +} + +__inline real_vector3d *negate_vector3d( + real_vector3d const *a, + real_vector3d *result) +{ + result->i= -a->i; + result->j= -a->j; + result->k= -a->k; + return result; +} + +__inline real_point3d *set_real_point3d( + real_point3d *p, + real x, + real y, + real z) +{ + p->x= x; + p->y= y; + p->z= z; + + return p; +} + +__inline boolean valid_real( + real n) +{ + return (*(long *)&n & 0x7F800000) != 0x7F800000; +} + +__inline boolean valid_realcmp( + real a, + real b) +{ + real result= a - b; + return valid_real(result) && fabs(result) < 0.01f; +} + +__inline boolean valid_real_point3d( + real_point3d const *p) +{ + return valid_real(p->x) && valid_real(p->y) && valid_real(p->z); +} + +__inline boolean valid_real_vector3d(real_vector3d const *v) +{ + return valid_real(v->i) && valid_real(v->j) && valid_real(v->k); +} + + +__inline boolean valid_real_normal3d( + real_vector3d const *n) +{ + return valid_realcmp(magnitude_squared3d(n), 1.f); +} + +__inline boolean valid_real_vector3d_axes2( + real_vector3d const *forward, + real_vector3d const *up) +{ + boolean result= FALSE; + if (valid_real_normal3d(forward) && valid_real_normal3d(up)) + { + real product= dot_product3d(forward, up); + if (valid_realcmp(product, 0.f)) + { + result= TRUE; + } + } + return result; +} + +__inline boolean valid_real_vector3d_axes3( + real_vector3d const *f, + real_vector3d const *l, + real_vector3d const *u) +{ + return + valid_real_normal3d(f) && + valid_real_normal3d(l) && + valid_real_normal3d(u) && + valid_realcmp(dot_product3d(f, l), 0.f) && + valid_realcmp(dot_product3d(l, u), 0.f) && + valid_realcmp(dot_product3d(u, f), 0.f); +} + +__inline boolean valid_real_matrix4x3( + real_matrix4x3 const *matrix) +{ + return + valid_real(matrix->scale) && + valid_real_vector3d_axes3(&matrix->forward, &matrix->left, &matrix->up) && + valid_real_point3d(&matrix->position); +} + +__inline real_vector3d *cross_product3d( + real_vector3d const *a, + real_vector3d const *b, + real_vector3d *result) +{ + real k= (a->i*b->j) - (a->j*b->i); + real j= (a->k*b->i) - (a->i*b->k); + real i= (a->j*b->k) - (a->k*b->j); + result->i= i; + result->j= j; + result->k= k; + + return result; +} + + +__inline boolean point_in_sphere( + real_point3d const *point, + real_point3d const *center, + real radius) +{ + return distance_squared3d(point, center)<=(radius*radius); +} + +__inline short random_range( + short lower_bound, + short upper_bound) +{ + return seed_random_range(get_global_random_seed_address(), lower_bound, upper_bound); +} + +__inline real real_random( + void) +{ + return real_seed_random(get_global_random_seed_address()); +} + #endif // __REAL_MATH_H diff --git a/source/memory/data.c b/source/memory/data.c index 20024ef7..97970589 100644 --- a/source/memory/data.c +++ b/source/memory/data.c @@ -62,6 +62,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "data.h" + /* ---------- constants */ /* ---------- macros */ @@ -76,4 +79,52 @@ static void datum_initialize(struct data_array *data, struct datum_header *heade /* ---------- public code */ +void data_verify( + struct data_array *data) +{ + match_assert("c:\\halo\\SOURCE\\memory\\data.c", 457, data); + + match_vassert( + "c:\\halo\\SOURCE\\memory\\data.c", + 470, + data->data && + data->signature=='d@t@' && + data->maximum_count>=0 && + data->count>=0 && + data->count<=data->maximum_count && + data->first_free_absolute_index>=0 && + data->first_free_absolute_index<=data->maximum_count && + data->actual_count>=0 && + data->actual_count<=data->count, + csprintf(temporary, "%s data array @%p is bad or not allocated", data->name, data)); + + return; +} + +void datum_delete( + struct data_array *data, + long index) +{ + struct datum_header *header= (struct datum_header *)datum_get(data, index); + header->identifier= 0; + + if (((short)index)first_free_absolute_index) + { + data->first_free_absolute_index= index; + } + + if (((short)index)+1==data->count) + { + do + { + header=(struct datum_header *)((byte *)header-data->size); + data->count--; + } + while (data->count > 0 && !header->identifier); + } + data->actual_count--; + + return; +} + /* ---------- private code */ diff --git a/source/memory/memory_pool.c b/source/memory/memory_pool.c index 46534540..f52c99fc 100644 --- a/source/memory/memory_pool.c +++ b/source/memory/memory_pool.c @@ -70,6 +70,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "memory_pool.h" + /* ---------- constants */ /* ---------- macros */ @@ -82,4 +85,22 @@ symbols in this file: /* ---------- public code */ +long memory_pool_get_free_size( + struct memory_pool *pool) +{ + return pool->free_size; +} + +long memory_pool_get_used_size( + struct memory_pool *pool) +{ + return !pool->last_block ? 0 : (unsigned long)pool->last_block + pool->last_block->size - (unsigned long)pool->base_address; +} + +long memory_pool_get_contiguous_free_size( + struct memory_pool *pool) +{ + return pool->size - memory_pool_get_used_size(pool); +} + /* ---------- private code */ diff --git a/source/memory/memory_pool.h b/source/memory/memory_pool.h index 7683655a..04677af9 100644 --- a/source/memory/memory_pool.h +++ b/source/memory/memory_pool.h @@ -14,7 +14,40 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct memory_pool_block +{ + unsigned long header_signature; + long size; + void **reference; + struct memory_pool_block *next_block; + struct memory_pool_block *previous_block; + unsigned long trailer_signature; +}; + +struct memory_pool +{ + unsigned long signature; + char name[32]; + void *base_address; + long size; + long free_size; + struct memory_pool_block *first_block; + struct memory_pool_block *last_block; +}; + +/* ---------- prototypes/MEMORY_POOL.C */ + +struct memory_pool *memory_pool_new(char const *name, long size); +void memory_pool_delete(struct memory_pool *pool); +long memory_pool_allocation_size(long size); +void memory_pool_initialize(struct memory_pool *pool, char const *name, long size); +boolean memory_pool_block_allocate(struct memory_pool *pool, void **reference, long size); +boolean memory_pool_block_reallocate(struct memory_pool *pool, void **reference, long new_size); +void memory_pool_block_free(struct memory_pool *pool, void **reference); +void memory_pool_compact(struct memory_pool *pool); +long memory_pool_get_free_size(struct memory_pool *pool); +long memory_pool_get_used_size(struct memory_pool *pool); +long memory_pool_get_contiguous_free_size(struct memory_pool *pool); /* ---------- globals */ diff --git a/source/models/model_animation_definitions.c b/source/models/model_animation_definitions.c index 63e8a636..45917fe2 100644 --- a/source/models/model_animation_definitions.c +++ b/source/models/model_animation_definitions.c @@ -262,6 +262,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "model_animation_definitions.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/models/model_animation_definitions.h b/source/models/model_animation_definitions.h index 92065acf..27696050 100644 --- a/source/models/model_animation_definitions.h +++ b/source/models/model_animation_definitions.h @@ -8,13 +8,113 @@ header included in hcex build. #define __MODEL_ANIMATION_DEFINITIONS_H #pragma once + +/* ---------- headers */ + +#include "math/real_math.h" +#include "tag_files/tag_files.h" +#include "tag_files/tag_groups.h" + /* ---------- constants */ +enum +{ + ANIMATION_GRAPH_TAG= 'antr', + ANIMATION_GRAPH_VERSION= 4, + MAXIMUM_FRAMES_PER_ANIMATION= 2048, + MAXIMUM_NODES_PER_ANIMATION= 64, + MAXIMUM_ANIMATIONS_PER_GRAPH= 256, + MAXIMUM_SOUND_REFERENCES_PER_ANIMATION_GRAPH= 257, + MINIMUM_COMPRESSED_ANIMATION_FRAME_COUNT= 6, +}; + +enum +{ + _animation_compressed_bit= 0, + _animation_world_relative_bit, + _animation_25Hz_bit, + NUMBER_OF_ANIMATION_FLAGS, +}; + /* ---------- macros */ +#define animation_graph_definition_get(index) ((struct animation_graph *)tag_get(ANIMATION_GRAPH_TAG, index)) + /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct animation +{ + char name[TAG_STRING_LENGTH+1]; + short type; + short frame_count; + short frame_size; + short frame_info_type; + unsigned long node_list_checksum; + short node_count; + short private_loop_frame_index; + real weight; + short private_key_frame_index; + short private_second_key_frame_index; + short next_animation_index; + word flags; + short sound_index; + short private_sound_frame_index; + byte private_left_foot_frame_index; + byte private_right_foot_frame_index; + short runtime_parent_animation_index; + real runtime_normalized_weight; + struct tag_data frame_info; + unsigned long nodes_with_translation_flags[2]; + long unused_translation[2]; + unsigned long nodes_with_rotation_flags[2]; + long unused_rotation[2]; + unsigned int nodes_with_scale_flags[2]; + long unused_scale[1]; + long compressed_data_offset; + struct tag_data default_data; + struct tag_data data; +}; + + +struct animation_graph +{ + struct tag_block object_overlays; + struct tag_block unit_seats; + struct tag_block weapon_animations; + struct tag_block vehicle_animations; + struct tag_block device_animations; + struct tag_block unit_damage_animations; + struct tag_block first_person_weapon_animations; + struct tag_block sound_references; + real limp_body_node_collision_radius; + word flags; + word pad; + struct tag_block nodes; + struct tag_block animations; // animation +}; + +/* ---------- prototypes/MODEL_ANIMATION_DEFINITIONS.C */ + +/* ---------- prototypes/MODEL_ANIMATIONS.C */ + +void animation_get_node_orientations( + struct model const *model, + struct animation const *animation, + short frame_index, + struct real_orientation *node_orientations); + +void inverse_kinematics_adjust_matrices( + struct real_matrix4x3 *desired_hand_matrix, + struct real_matrix4x3 *shoulder_matrix, + struct real_matrix4x3 *elbow_matrix, + struct real_matrix4x3 *hand_matrix); + +void interpolate_node_orientations( + short node_count, + struct real_orientation *original_node_orientations, + struct real_orientation *target_node_orientations, + short frame_index, + short frame_count); /* ---------- globals */ diff --git a/source/models/model_animations.c b/source/models/model_animations.c index 51aed79a..75414582 100644 --- a/source/models/model_animations.c +++ b/source/models/model_animations.c @@ -147,6 +147,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "model_animation_definitions.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/models/model_definitions.h b/source/models/model_definitions.h index 77c5544f..e896779f 100644 --- a/source/models/model_definitions.h +++ b/source/models/model_definitions.h @@ -8,13 +8,116 @@ header included in hcex build. #define __MODEL_DEFINITIONS_H #pragma once + +/* ---------- headers */ + +#include "math/real_math.h" +#include "tag_files/tag_files.h" +#include "tag_files/tag_groups.h" + /* ---------- constants */ +enum +{ + MODELS_GROUP_TAG= 'mode', + MODELS_GROUP_VERSION= 4, + MAXIMUM_MARKERS_PER_MODEL= 256, + MAXIMUM_INSTANCES_PER_MODEL_MARKER= 32, + MAXIMUM_GEOMETRIES_PER_MODEL= 256, + MAXIMUM_PARTS_PER_MODEL_GEOMETRY= 32, + MAXIMUM_VERTICES_PER_MODEL_GEOMETRY_PART= UNSIGNED_SHORT_MAX, + MAXIMUM_TRIANGLES_PER_MODEL_GEOMETRY_PART= UNSIGNED_SHORT_MAX, + MAXIMUM_NODES_PER_MODEL_GEOMETRY_PART= 22, + PADDED_MAXIMUM_NODES_PER_MODEL_GEOMETRY_PART= 24, + MAXIMUM_REGIONS_PER_MODEL= 32, + MAXIMUM_PERMUTATIONS_PER_MODEL_REGION= 32, + MAXIMUM_MARKERS_PER_MODEL_REGION_PERMUTATION= 64, + MAXIMUM_NODES_PER_MODEL= 64, + MAXIMUM_SHADERS_PER_MODEL= 32, + MAXIMUM_FUNCTION_VALUES_PER_MODEL= 4, + MAXIMUM_CHANGE_COLORS_PER_MODEL= 4, +}; + +enum +{ + _model_region_permutation_cannot_be_chosen_randomly_bit= 0, + NUMBER_OF_MODEL_REGION_PERMUTATION_FLAGS, +}; + /* ---------- macros */ +#define model_definition_get(index) ((struct model *)tag_get(MODELS_GROUP_TAG, index)) + /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct model_marker_instance +{ + byte region_index; + byte permutation_index; + byte node_index; + byte pad; + real_point3d translation; + real_quaternion rotation; +}; + +struct model_marker +{ + char name[32]; + long unused[5]; + struct tag_block instances; // model_marker_instance +}; + +struct model_node +{ + char name[TAG_STRING_LENGTH+1]; + short next_sibling_node_index; + short first_child_node_index; + short parent_node_index; + word pad; + real_point3d default_translation; + real_quaternion default_rotation; + real node_distance_from_parent; + long unused[8]; + real_matrix4x3 runtime_default_inverse_matrix; +}; + +struct model_region_permutation +{ + char name[TAG_STRING_LENGTH+1]; + long flags; + short variant_number; + word pad; + long unused[6]; + short geometry_indices[5]; + word pad2; + struct tag_block markers; // object_marker +}; + +struct model_region +{ + char name[TAG_STRING_LENGTH+1]; + long unused[8]; + struct tag_block permutations; // model_region_permutation +}; + +struct model +{ + unsigned long flags; + unsigned long node_list_checksum; + real detail_cutoff_pixels[5]; + short node_counts[5]; + word pad; + long unused1[2]; + real_vector2d base_map_scale; + long unused2[29]; + struct tag_block markers; // model_marker + struct tag_block nodes; // model_node + struct tag_block regions; // model_region + struct tag_block geometries; + struct tag_block shaders; +}; + +/* ---------- prototypes/MODEL_DEFINITIONS.C */ /* ---------- globals */ diff --git a/source/models/models.c b/source/models/models.c index d147ba15..5f41fa49 100644 --- a/source/models/models.c +++ b/source/models/models.c @@ -60,6 +60,14 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "models.h" + +#include "model_definitions.h" + +#include "math/real_math.h" +#include "objects/objects.h" + /* ---------- constants */ /* ---------- macros */ @@ -72,4 +80,61 @@ symbols in this file: /* ---------- public code */ +short model_get_marker_by_name( + long model_index, + char const *name, + byte const *region_permutations, + short const *node_remapping_table, + short node_count, + real_matrix4x3 const *node_matrices, + boolean mirrored_flag, + struct object_marker *markers, + short maximum_marker_count) +{ + short result= 0; + short marker_index= model_find_marker(model_index, name); + + match_assert("c:\\halo\\SOURCE\\models\\models.c", 760, node_matrices); + match_assert("c:\\halo\\SOURCE\\models\\models.c", 761, markers); + + if (marker_index!=NONE) + { + short i; + + struct model *model= model_definition_get(model_index); + struct model_marker* marker= TAG_BLOCK_GET_ELEMENT(&model->markers, marker_index, struct model_marker); + + for (i=0; iinstances.count; i++) + { + struct model_marker_instance* instance= TAG_BLOCK_GET_ELEMENT(&marker->instances, i, struct model_marker_instance); + if (!region_permutations || + region_permutations[instance->region_index]==instance->permutation_index) + { + struct object_marker *object_marker; + + if (result>=maximum_marker_count) + { + break; + } + + object_marker= &markers[result++]; + object_marker->node_index= node_remapping_table ? node_remapping_table[instance->node_index] : instance->node_index; + matrix4x3_from_point_and_quaternion(&object_marker->node_matrix, &instance->translation, &instance->rotation); + match_assert( + "c:\\halo\\SOURCE\\models\\models.c", + 785, + object_marker->node_index>=0 && object_marker->node_index<(node_remapping_table ? node_count : model->nodes.count)); + + matrix4x3_multiply(&node_matrices[object_marker->node_index], &object_marker->node_matrix, &object_marker->matrix); + if (mirrored_flag) + { + negate_vector3d(&object_marker->matrix.left, &object_marker->matrix.left); + } + } + } + } + + return result; +} + /* ---------- private code */ diff --git a/source/models/models.h b/source/models/models.h index 326a9a1e..6740cf06 100644 --- a/source/models/models.h +++ b/source/models/models.h @@ -14,7 +14,21 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/MODELS.C */ + +void model_get_node_orientations(struct model const *model, struct real_orientation *node_orientations); + +short model_find_marker(long model_index, char const *name); +short model_get_marker_by_name( + long model_index, + char const *name, + byte const *region_permutations, + short const *node_remapping_table, + short node_count, + struct real_matrix4x3 const *node_matrices, + boolean mirrored_flag, + struct object_marker *markers, + short maximum_marker_count); /* ---------- globals */ diff --git a/source/objects/damage.h b/source/objects/damage.h index f1202796..a4042d52 100644 --- a/source/objects/damage.h +++ b/source/objects/damage.h @@ -14,7 +14,16 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/DAMAGE.C */ + +void damage_initialize(void); +void damage_dispose(void); +void damage_initialize_for_new_map(void); +void damage_dispose_from_old_map(void); +void damage_render_debug(void); +void object_initialize_vitality(long object_index, real *custom_body_vitality, real *custom_shield_vitality); + +void object_damage_update(long object_index); /* ---------- globals */ diff --git a/source/objects/damage_resistances.h b/source/objects/damage_resistances.h index 946bf116..135f36a3 100644 --- a/source/objects/damage_resistances.h +++ b/source/objects/damage_resistances.h @@ -8,12 +8,62 @@ header included in hcex build. #define __DAMAGE_RESISTANCES_H #pragma once +/* ---------- headers */ + +#include "tag_files/tag_groups.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ +struct damage_resistance +{ + unsigned long flags; + short indirect_damage_material_index; + word pad2; + real maximum_body_vitality; + real body_system_shock; + long body_vitality_unused[6]; + real body_stun_unused[7]; + real friendly_damage_resistance; + long friendly_damage_unused[2]; + long body_unused[8]; + struct tag_reference localized_damage_effect; + real area_damage_effect_threshold; + struct tag_reference area_damage_effect; + real body_damaged_effect_threshold; + struct tag_reference body_damaged_effect; + struct tag_reference body_depleted_effect; + real body_destroyed_threshold; + struct tag_reference body_destroyed_effect; + real maximum_shield_vitality; + word pad0; + short shield_material_type; + long shield_vitality_unused[6]; + short shield_failure_function; + word pad1; + real shield_failure_threshold; + real maximum_shield_failure; + long shield_failure_unused[4]; + real minimum_shield_stun_damage; + real shield_stun_time; + real shield_recharge_time; + real shield_recharge_unused[4]; + long shield_unused[24]; + real shield_damaged_effect_threshold; + struct tag_reference shield_damaged_effect; + struct tag_reference shield_depleted_effect; + struct tag_reference shield_recharging_effect; + unsigned long unused2[2]; + real runtime_shield_recharge_velocity; + unsigned long unused[28]; + struct tag_block materials; + struct tag_block regions; + struct tag_block modifiers; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/objects/light_definitions.h b/source/objects/light_definitions.h index 3bc54162..aa166600 100644 --- a/source/objects/light_definitions.h +++ b/source/objects/light_definitions.h @@ -10,6 +10,12 @@ header included in hcex build. /* ---------- constants */ +enum +{ + LIGHT_DEFINITION_TAG= 'ligh', + LIGHT_DEFINITION_VERSION= 3, +}; + /* ---------- macros */ /* ---------- structures */ diff --git a/source/objects/object_definitions.h b/source/objects/object_definitions.h index 4f846680..4d3fa317 100644 --- a/source/objects/object_definitions.h +++ b/source/objects/object_definitions.h @@ -8,13 +8,155 @@ header included in hcex build. #define __OBJECT_DEFINITIONS_H #pragma once +/* ---------- headers */ + +#include "math/real_math.h" +#include "tag_files/tag_files.h" +#include "tag_files/tag_groups.h" + /* ---------- constants */ +enum +{ + OBJECT_DEFINITION_TAG= 'obje', + OBJECT_DEFINITION_VERSION= 1, + NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS= 4, + NUMBER_OF_INCOMING_OBJECT_FUNCTIONS= 4, + MAXIMUM_NUMBER_OF_ATTACHMENTS_PER_OBJECT= 8, + MAXIMUM_REGIONS_PER_OBJECT= 8, +}; + +enum +{ + _object_does_not_cast_shadow_bit= 0, + _object_transparency_self_occludes_bit, + _object_artificially_bright_bit, + _object_not_pathfinding_obstacle_bit, + NUMBER_OF_OBJECT_DEFINITION_FLAGS, +}; + +enum +{ + _object_runtime_scaled_change_colors_bit= 0, + NUMBER_OF_OBJECT_DEFINITION_RUNTIME_FLAGS, +}; + +enum +{ + _object_function_invert_function_bit= 0, + _object_function_additive_bit, + _object_function_does_not_deactivate_below_lower_bound_bit, + NUMBER_OF_OBJECT_FUNCTION_DEFINITION_FLAGS, +}; + +enum +{ + _object_function_clip_to_bounds= 0, + _object_function_clip_to_bounds_and_normalize, + _object_function_scale_to_fit_bounds, + NUMBER_OF_OBJECT_FUNCTION_BOUNDS_MODES, +}; + /* ---------- macros */ +#define object_definition_get(index) ((struct object_definition *)tag_get(OBJECT_DEFINITION_TAG, index)) + /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct object_attachment_definition +{ + struct tag_reference type; + char marker_name[TAG_STRING_LENGTH+1]; + short primary_scale_function_reference; + short secondary_scale_function_reference; + short change_color_reference; + word pad; + long unused[4]; +}; + +struct object_function_definition +{ + unsigned long flags; + real period; + short scale_period_by_function_index; + short function_type; + short scale_function_by_function_index; + short wobble_function_type; + real wobble_period; + real wobble_magnitude; + real square_wave_threshold; + short step_count; + short map_result_to_transition_function; + short sawtooth_count; + short add_function_index; + short scale_result_by_function_index; + short bounds_mode; + real lower_bound; + real upper_bound; + real pad2; + word pad3; + short turn_off_with_function_index; + real scale_by; + int unused1[63]; + real runtime_reciprocal_bounds_range; + real runtime_reciprocal_sawtooth_count; + real runtime_reciprocal_step_count; + real runtime_one_over_period; + char usage[TAG_STRING_LENGTH+1]; +}; + +struct object_change_color_permutation +{ + real weight; + real_rgb_color color_lower_bound; + real_rgb_color color_upper_bound; +}; + +struct object_change_color_definition +{ + short darken_by; + short scaled_by; + unsigned long scale_flags; + real_rgb_color color_lower_bound; + real_rgb_color color_upper_bound; + struct tag_block permutations; // object_change_color_permutation +}; + +struct _object_definition +{ + short type; + word flags; + real bounding_radius; + real_point3d bounding_offset; + real_point3d origin_offset; + real acceleration_scale; + unsigned long runtime_flags; + struct tag_reference model; + struct tag_reference animation_graph; + long unused3[10]; + struct tag_reference collision_model; + struct tag_reference physics; + struct tag_reference modifier_shader; + struct tag_reference creation_effect; + long unused1[21]; + real render_bounding_radius; + short function_modes[4]; + long unused2[11]; + short icon_text_index; + short forced_shader_permutation_index; + struct tag_block attachments; // object_attachment_definition + struct tag_block widgets; + struct tag_block functions; // object_function_definition + struct tag_block change_colors; // object_change_color_definition + struct tag_block predicted_resources; +}; + +struct object_definition +{ + struct _object_definition object; +}; + +/* ---------- prototypes/OBJECT_DEFINITIONS.C */ /* ---------- globals */ diff --git a/source/objects/object_deleted_procs.c b/source/objects/object_deleted_procs.c index a60f671a..db62671d 100644 --- a/source/objects/object_deleted_procs.c +++ b/source/objects/object_deleted_procs.c @@ -10,6 +10,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "objects.h" + /* ---------- constants */ /* ---------- macros */ @@ -20,6 +23,23 @@ symbols in this file: /* ---------- globals */ +object_deleted_proc object_deleted_procs[3]; + /* ---------- public code */ +void object_deleted_procs_call( + long deleted_object_index) +{ + long i=0; + + do + { + (object_deleted_procs[i])(deleted_object_index); + i++; + } + while (iobject.type); + boolean result= TRUE; + + for (i= 0; definition->part_definitions[i]; i++) + { + struct object_type_definition *current_definition= definition->part_definitions[i]; + + if (current_definition->datum_new && !current_definition->datum_new(object_index)) + { + result= FALSE; + break; + } + } + + return result; +} + +void object_type_delete( + long object_index) +{ + short i; + + struct object_type_definition *definition= object_type_definition_get(object_get(object_index)->object.type); + boolean result= TRUE; + + for (i= 0; definition->part_definitions[i]; i++) + { + struct object_type_definition *current_definition= definition->part_definitions[i]; + if (current_definition->datum_delete) + { + current_definition->datum_delete(object_index); + } + } + + return; +} + + /* ---------- private code */ diff --git a/source/objects/object_types.h b/source/objects/object_types.h index dd21285e..1cc4863a 100644 --- a/source/objects/object_types.h +++ b/source/objects/object_types.h @@ -8,6 +8,11 @@ OBJECT_TYPES.H /* ---------- constants */ +enum +{ + MAXIMUM_CHILDREN_PER_OBJECT_TYPE_DEFINITION= 16, +}; + enum { _object_type_biped= 0, @@ -47,4 +52,67 @@ enum _object_mask_remove_on_bsp_switch= (FLAG(_object_type_scenery)|FLAG(_object_type_light_fixture)) }; +/* ---------- structures */ + +struct object_type_definition +{ + char const *name; + unsigned long group_tag; + short game_datum_size; + short placement_tag_block_offset; + short palette_tag_block_offset; + short placement_tag_block_element_size; + void (*initialize)(); + void (*dispose)(); + void (*initialize_for_new_map)(); + void (*dispose_from_old_map)(); + void (*datum_adjust_placement)(long, struct object_placement_data *); + boolean (*datum_new)(long); + void (*datum_place)(long, void *); + void (*datum_delete)(long); + boolean(*datum_update)(long); + void (*datum_export_function_values)(long); + void (*handle_deleted_object)(long, long); + void (*handle_region_destroyed)(long, short, unsigned long); + boolean(*handle_parent_destroyed)(long); + void (*datum_preprocess_node_orientations)(long, struct real_orientation *); + void (*datum_postprocess_node_matrices)(long, struct real_matrix4x3 *); + void (*reset)(long); + void (*disconnect_from_structure_bsp)(long); + void (*notify_impulse_sound)(long, long, long); + void (*render_debug)(long); + struct object_type_definition *part_definitions[MAXIMUM_CHILDREN_PER_OBJECT_TYPE_DEFINITION]; + struct object_type_definition *next; +}; + +/* ---------- prototypes/OBJECT_TYPES.C */ + +struct object_type_definition *object_type_definition_get(short object_type); +short object_type_get_datum_size(short object_type); +char const *object_type_get_name(short object_type); + +void object_types_place_all(struct scenario *scenario); + +void object_types_initialize(void); +void object_types_dispose(void); +void object_types_initialize_for_new_map(void); +void object_types_dispose_from_old_map(void); +void object_type_adjust_placement(long object_index, struct object_placement_data *data); +boolean object_type_new(long object_index); +void object_type_place(long object_index, struct scenario_object_datum *scenario_object); + +void object_type_handle_deleted_object(long object_index, long deleted_object_index); + +void object_type_delete(long object_index); +boolean object_type_update(long object_index); +void object_type_export_function_values(long object_index); + +void object_type_preprocess_node_orientations(long object_index, struct real_orientation *node_orientations); +void object_type_postprocess_node_matrices(long object_index, struct real_matrix4x3 *node_matrices); +void object_type_reset(long object_index); +void object_type_disconnect_from_structure_bsp(long object_index); + +struct tag_block *scenario_get_object_type_scenario_datums(struct scenario *scenario, short object_type, long *size); +struct tag_block *scenario_get_object_type_scenario_palette(struct scenario *scenario, short object_type); + #endif // __OBJECT_TYPES_H diff --git a/source/objects/objects.c b/source/objects/objects.c index 2add0ecd..d6983bac 100644 --- a/source/objects/objects.c +++ b/source/objects/objects.c @@ -1,464 +1,4465 @@ /* OBJECTS.C - -symbols in this file: -0012CDC0 0020: - _cluster_get_first_noncollideable_object (0000) -0012CDE0 0020: - _cluster_get_next_noncollideable_object (0000) -0012CE00 0020: - _cluster_get_first_collideable_object (0000) -0012CE20 0020: - _cluster_get_next_collideable_object (0000) -0012CE40 0050: - _object_get_next_cluster (0000) -0012CE90 0040: - _object_try_and_get_and_verify_type (0000) -0012CED0 0070: - _object_get_and_verify_type (0000) -0012CF40 0040: - _object_iterator_new (0000) -0012CF80 00c0: - _object_iterator_next (0000) -0012D040 0080: - _object_get_ultimate_parent (0000) -0012D0C0 0010: - _object_add_scenario_permutation (0000) -0012D0D0 0030: - _object_set_object_index_for_name_index (0000) -0012D100 0070: - _objects_fix_for_deleted_object (0000) -0012D170 0230: - _object_set_garbage (0000) -0012D3A0 0010: - _garbage_collect_now (0000) -0012D3B0 0080: - _objects_information_get (0000) -0012D430 0030: - _object_pvs_set_object (0000) -0012D460 00a0: - _object_pvs_set_camera_point (0000) -0012D500 0010: - _object_pvs_clear (0000) -0012D510 00e0: - _objects_get_activating_cluster_index (0000) -0012D5F0 0030: - _object_definition_predict (0000) -0012D620 00b0: - _object_predict (0000) -0012D6D0 0050: - _object_beautify (0000) -0012D720 00a0: - _code_0012d720 (0000) -0012D7C0 0050: - _code_0012d7c0 (0000) -0012D810 0090: - _object_header_block_get (0000) -0012D8A0 0150: - _object_header_block_allocate (0000) -0012D9F0 0050: - _code_0012d9f0 (0000) -0012DA40 0200: - _code_0012da40 (0000) -0012DC40 0070: - _code_0012dc40 (0000) -0012DCB0 0090: - _code_0012dcb0 (0000) -0012DD40 0020: - _code_0012dd40 (0000) -0012DD60 00c0: - _code_0012dd60 (0000) -0012DE20 01e0: - _code_0012de20 (0000) -0012E000 0380: - _code_0012e000 (0000) -0012E380 0040: - _object_scripting_set_collideable (0000) -0012E3C0 0050: - _object_marker_begin (0000) -0012E410 0040: - _object_marker_end (0000) -0012E450 0050: - _object_unmarked_function (0000) -0012E4A0 0060: - _object_mark_function (0000) -0012E500 01b0: - _code_0012e500 (0000) -0012E6B0 00a0: - _code_0012e6b0 (0000) -0012E750 0040: - _code_0012e750 (0000) -0012E790 0010: - _code_0012e790 (0000) -0012E7A0 0020: - _code_0012e7a0 (0000) -0012E7C0 0080: - _code_0012e7c0 (0000) -0012E840 0050: - _code_0012e840 (0000) -0012E890 0020: - _code_0012e890 (0000) -0012E8B0 0020: - _objects_place (0000) -0012E8D0 00a0: - _code_0012e8d0 (0000) -0012E970 0260: - _find_objects_from_point_vector (0000) -0012EBD0 0030: - _code_0012ebd0 (0000) -0012EC00 0090: - _code_0012ec00 (0000) -0012EC90 0070: - _code_0012ec90 (0000) -0012ED00 0360: - _objects_dump_memory (0000) -0012F060 0140: - _objects_initialize (0000) -0012F1A0 00a0: - _objects_initialize_for_new_map (0000) -0012F240 00d0: - _objects_dispose_from_old_map (0000) -0012F310 0070: - _objects_dispose (0000) -0012F380 0050: - _object_activate (0000) -0012F3D0 0040: - _object_deactivate (0000) -0012F410 0060: - _object_reset (0000) -0012F470 00e0: - _object_placement_data_new (0000) -0012F550 0110: - _object_disconnect_from_map (0000) -0012F660 0060: - _object_get_first_cluster (0000) -0012F6C0 0030: - _object_get_node_matrices (0000) -0012F6F0 0050: - _object_get_attachment_marker_name (0000) -0012F740 0060: - _object_has_node (0000) -0012F7A0 0070: - _object_set_automatic_deactivation (0000) -0012F810 00b0: - _object_set_visibility (0000) -0012F8C0 00c0: - _object_get_velocities (0000) -0012F980 0030: - _object_get_location (0000) -0012F9B0 00d0: - _object_start_interpolation (0000) -0012FA80 0090: - _object_offset_interpolation (0000) -0012FB10 00e0: - _object_permute_region (0000) -0012FBF0 0080: - _object_get_function_value (0000) -0012FC70 0300: - _objects_in_clusters_by_indices (0000) -0012FF70 0030: - _object_index_from_name_index (0000) -0012FFA0 0090: - _objects_disconnect_from_structure_bsp (0000) -00130030 01f0: - _object_visible_to_any_player (0000) -00130220 0030: - _object_pvs_activate (0000) -00130250 00d0: - _code_00130250 (0000) -00130320 0080: - _code_00130320 (0000) -001303A0 0030: - _code_001303a0 (0000) -001303D0 0040: - _objects_scripting_set_scale (0000) -00130410 0100: - _code_00130410 (0000) -00130510 0020: - _object_delete (0000) -00130530 01d0: - _object_reconnect_to_map (0000) -00130700 0060: - _object_get_node_matrix (0000) -00130760 0110: - _object_get_marker_by_name (0000) -00130870 01a0: - _object_align_marker_to_matrix (0000) -00130A10 0130: - _object_detach (0000) -00130B40 0070: - _object_get_origin (0000) -00130BB0 0120: - _object_get_orientation (0000) -00130CD0 0060: - _object_get_world_matrix (0000) -00130D30 0110: - _object_inverse_kinematics (0000) -00130E40 01d0: - _objects_in_sphere (0000) -00131010 0140: - _objects_reconnect_to_structure_bsp (0000) -00131150 0070: - _objects_paparazzi (0000) -001311C0 0200: - _object_export_function_values (0000) -001313C0 19a0: - _object_compute_node_matrices (0000) -00132D60 0040: - _objects_scripting_detach (0000) -00132DA0 04b0: - _object_render_debug (0000) -00133250 00e0: - _code_00133250 (0000) -00133330 0100: - _object_set_position (0000) -00133430 00a0: - _object_translate (0000) -001334D0 05c0: - _object_new (0000) -00133A90 01b0: - _object_attach_to_node (0000) -00133C40 0100: - _object_force_inside_bsp (0000) -00133D40 01b0: - _code_00133d40 (0000) -00133EF0 0090: - _object_compute_node_matrices_recursive (0000) -00133F80 0040: - _code_00133f80 (0000) -00133FC0 00f0: - _object_new_from_scenario (0000) -001340B0 00e0: - _object_attach_to_marker (0000) -00134190 0070: - _object_new_by_name (0000) -00134200 0130: - _code_00134200 (0000) -00134330 0050: - _objects_scripting_attach (0000) -00134380 0020: - _object_delete_immediately (0000) -001343A0 0620: - _objects_garbage_collection (0000) -001349C0 0320: - _objects_update (0000) -00134CE0 0020: - _objects_memory_compact (0000) -00289D98 0018: - _rdata_00289d98 (0000) -00289DB0 000f: - ??_C@_0P@LFOALBOL@objects_update?$AA@ (0000) -00289DC0 008c: - ??_C@_0IM@GHLCLNJO@iterator?9?$DOcluster_partition?$DN?$DN?$CGco@ (0000) -00289E4C 0021: - ??_C@_0CB@HJEGKKGJ@c?3?2halo?2SOURCE?2objects?2objects?4c@ (0000) -00289E70 004a: - ??_C@_0EK@DDHBGNFK@got?5an?5object?5type?5we?5didn?8t?5exp@ (0000) -00289EBC 0038: - ??_C@_0DI@NJFAJKCK@uninitialized?5iterator?5passed?5to@ (0000) -00289EF4 003d: - ??_C@_0DN@LIGLDCO@TEST_FLAG?$CIgarbage_object?9?$DOobject@ (0000) -00289F34 0004: - __real@35800000 (0000) -00289F38 0040: - ??_C@_0EA@MOANJMN@object_pvs_set_camera_point?3?5cam@ (0000) -00289F78 008b: - ??_C@_0IL@PJOKFAFE@parent_object?9?$DOobject?4location?4c@ (0000) -0028A004 003c: - ??_C@_0DM@FAGPPIPE@reference?9?$DOoffset?$CLreference?9?$DOsiz@ (0000) -0028A040 0014: - ??_C@_0BE@CMKNCLBJ@reference?9?$DOoffset?$DO0?$AA@ (0000) -0028A058 005e: - ??_C@_0FO@DFFLELNG@block_reference_offset?$CLsizeof?$CIst@ (0000) -0028A0B8 001a: - ??_C@_0BK@GCHGANBE@block_reference_offset?$DO?$DN0?$AA@ (0000) -0028A0D4 0029: - ??_C@_0CJ@KJGPJOHH@object_header?9?$DOdata_size?$CLsize?$DM?$DNS@ (0000) -0028A100 0004: - __real@3f364cd7 (0000) -0028A104 0004: - __real@43d79081 (0000) -0028A108 0004: - __real@4412c849 (0000) -0028A10C 0004: - __real@439df252 (0000) -0028A110 0004: - __real@443a07f2 (0000) -0028A114 001e: - ??_C@_0BO@OPMGCPJ@?$CKfirst_object_reference?$CB?$DNNONE?$AA@ (0000) -0028A134 002b: - ??_C@_0CL@FNFNCGNP@?$CBobject_globals?9?$DOobject_marker_i@ (0000) -0028A160 002a: - ??_C@_0CK@IJOLKBMD@object_globals?9?$DOobject_marker_in@ (0000) -0028A18C 0011: - ??_C@_0BB@IDGMLLCF@object_name_list?$AA@ (0000) -0028A1A0 0011: - ??_C@_0BB@BEMCKCAE@object?5name?5list?$AA@ (0000) -0028A1B4 002d: - ??_C@_0CN@BNDNJDAG@an?5object?5with?5the?5name?5?8?$CFs?8?5alr@ (0000) -0028A1E4 003e: - ??_C@_0DO@EEADIGAP@name_index?$DO?$DN0?5?$CG?$CG?5name_index?$DMMAXI@ (0000) -0028A224 0031: - ??_C@_0DB@KFCPDNIH@?$CF?56d?5?$CI?$CF?56d?$CJ?5?$FL?$CF?57d?1?$CF?57d?1?$CF?57d?1?$CF?57d@ (0000) -0028A258 0063: - ??_C@_0GD@CPALGMGH@WARNING?3?5overflowed?5MAXIMUM_DUMP@ (0000) -0028A2BC 0017: - ??_C@_0BH@PBBFFOC@OBJECTS?5BY?5DEFINITION?6?$AA@ (0000) -0028A2D8 0043: - ??_C@_0ED@BEMDNONK@number?5?$CIactive?$CJ?5?$FLgarbage?1?5?5?5dead@ (0000) -0028A31C 0011: - ??_C@_0BB@GNMAIFEG@OBJECTS?5BY?5TYPE?6?$AA@ (0000) -0028A330 003d: - ??_C@_0DN@LIBJGINJ@?$CD?$CFd?5objects?5?$CI?$CD?$CFd?5active?$CJ?5using?5?$CF@ (0000) -0028A370 0015: - ??_C@_0BF@MGBBKKEM@d?3?2object_memory?4txt?$AA@ (0000) -0028A388 003f: - ??_C@_0DP@CAHEHEJH@?$CIheader?9?$DOtype?5?$DO?$DN?50?$CJ?5?$CG?$CG?5?$CIheader?9?$DO@ (0000) -0028A3C8 0016: - ??_C@_0BG@KNAIILHO@noncollideable?5object?$AA@ (0000) -0028A3E0 0013: - ??_C@_0BD@EPIKGCAI@collideable?5object?$AA@ (0000) -0028A3F4 000f: - ??_C@_0P@GCGFDHI@object_globals?$AA@ (0000) -0028A404 000f: - ??_C@_0P@CJDMFPHM@object?5globals?$AA@ (0000) -0028A414 0029: - ??_C@_0CJ@MPENCKAI@object_header_data?5?$CG?$CG?5object_mem@ (0000) -0028A440 0008: - ??_C@_07JPLKJBI@objects?$AA@ (0000) -0028A448 003e: - ??_C@_0DO@BAPNCPID@TEST_FLAG?$CIobject?9?$DOobject?4flags?0?5@ (0000) -0028A488 0028: - ??_C@_0CI@CPMOGOIB@DATUM_INDEX_TO_IDENTIFIER?$CIobject@ (0000) -0028A4B0 0041: - ??_C@_0EB@MPFJDMPL@?$CBTEST_FLAG?$CI_object_mask_cannot_i@ (0000) -0028A4F8 0048: - ??_C@_0EI@JLAEJIFD@function_index?$DO?$DN0?5?$CG?$CG?5function_in@ (0000) -0028A540 0020: - ??_C@_0CA@BCPJMOMG@?$CB?$CIweapon_is_flag?$CIobject_index?$CJ?$CJ?$AA@ (0000) -0028A560 003f: - ??_C@_0DP@KDEDEENE@?$CBTEST_FLAG?$CIobject?9?$DOobject?4flags?0@ (0000) -0028A5A0 002a: - ??_C@_0CK@OPKDPNPM@object_has_node?$CIobject_index?0?5no@ (0000) -0028A5CC 0017: - ??_C@_0BH@NBICGHKL@maximum_marker_count?$DO0?$AA@ (0000) -0028A5E4 0029: - ??_C@_0CJ@HEAMOBGB@valid_real_matrix4x3?$CIdestination@ (0000) -0028A610 0013: - ??_C@_0BD@EIOHMDGK@destination_matrix?$AA@ (0000) -0028A624 000d: - ??_C@_0N@BFMOEIFC@child_marker?$AA@ (0000) -0028A634 000f: - ??_C@_0P@DMPMGCLF@object_indices?$AA@ (0000) -0028A644 0009: - ??_C@_08CBBFJFMD@location?$AA@ (0000) -0028A650 0004: - __real@3e22f983 (0000) -0028A658 0008: - __real@3fefd70a40000000 (0000) -0028A660 002e: - ??_C@_0CO@LMCMMCPP@object_compute_node_matrices?5roo@ (0000) -0028A690 0019: - ??_C@_0BJ@DILLIKA@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5scale?5?$CFf?$AA@ (0000) -0028A6AC 001e: - ??_C@_0BO@GOPFPFFJ@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5posn?5?$CFf?5?$CFf?5?$CFf?$AA@ (0000) -0028A6CC 001e: - ??_C@_0BO@LGPKFCMO@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5up?5?5?5?$CFf?5?$CFf?5?$CFf?$AA@ (0000) -0028A6EC 001e: - ??_C@_0BO@MAAPDIJN@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5left?5?$CFf?5?$CFf?5?$CFf?$AA@ (0000) -0028A70C 001e: - ??_C@_0BO@NCBDHGGN@computed?5matrix?5fwd?5?5?$CFf?5?$CFf?5?$CFf?$AA@ (0000) -0028A72C 0011: - ??_C@_0BB@FAFHKCNL@?5?5no?5parent?5node?$AA@ (0000) -0028A740 0034: - ??_C@_0DE@DOJKDEHM@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5scale?5?$CIjaso@ (0000) -0028A774 0023: - ??_C@_0CD@OGEIOHJN@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5posn?5?$CFf?5?$CFf?5@ (0000) -0028A798 0023: - ??_C@_0CD@DOEHEAAK@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5up?5?5?5?$CFf?5?$CFf?5@ (0000) -0028A7BC 0023: - ??_C@_0CD@EILCCKFJ@?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5?5left?5?$CFf?5?$CFf?5@ (0000) -0028A7E0 0023: - ??_C@_0CD@LAKOFIJF@?5?5parent?9node?5matrix?5fwd?5?5?$CFf?5?$CFf?5@ (0000) -0028A804 0019: - ??_C@_0BJ@GEKCHFFM@?5?5origin?9offset?5?$CFf?5?$CFf?5?$CFf?$AA@ (0000) -0028A820 0026: - ??_C@_0CG@BFFOPNJD@?5?5center?9of?9mass?5translation?5?$CFf?5@ (0000) -0028A848 0032: - ??_C@_0DC@GBFDLHME@?5?5object?3?5pos?5?$CFf?5?$CFf?5?$CFf?0?5fwd?5?$CFf?5?$CF@ (0000) -0028A87C 0038: - ??_C@_0DI@HJPDAFKC@object_compute_node_matrices?5FAI@ (0000) -0028A8B4 0018: - ??_C@_0BI@DIJPGKII@?$CFs?5as?5parent?5node?5of?5?$CFs?$AA@ (0000) -0028A8D0 004f: - ??_C@_0EP@NMLLJPBP@?$CFs?5had?5a?5bad?5forward?5and?5up?5befo@ (0000) -0028A920 003e: - ??_C@_0DO@KBCIODOG@?$CFs?5had?5a?5bad?5position?5before?5com@ (0000) -0028A960 000f: - ??_C@_0P@HHCPIEKG@frame_index?$DO?$DN0?$AA@ (0000) -0028A970 000d: - ??_C@_0N@NCPDDPGK@new_position?$AA@ (0000) -0028A980 0021: - ??_C@_0CB@KICDPCDH@OUT?5OF?5OBJECTS?3?5cannot?5create?5?$CFs@ (0000) -0028A9A4 001e: - ??_C@_0BO@GAJHNFGD@?$CGdata?9?$DOtranslational_velocity?$AA@ (0000) -0028A9C4 0018: - ??_C@_0BI@EDEMGAJJ@?$CGdata?9?$DOangular_velocity?$AA@ (0000) -0028A9DC 000f: - ??_C@_0P@JNFNPCBA@?$CGdata?9?$DOforward?$AA@ (0000) -0028A9EC 000a: - ??_C@_09MMNHALDO@?$CGdata?9?$DOup?$AA@ (0000) -0028A9F8 002f: - ??_C@_0CP@KPEIPFOB@cannot?5attach?5an?5object?5to?5one?5o@ (0000) -0028AA28 0038: - ??_C@_0DI@OBHOMKDM@object_has_node?$CIparent_object_in@ (0000) -0028AA60 0020: - ??_C@_0CA@POCDJJBP@garbage?5collection?5warning?5?$CI?$CFs?$CJ?$AA@ (0000) -0028AA80 0015: - ??_C@_0BF@NBHLMPKH@removing?5objects?3?5?$CFs?$AA@ (0000) -0028AA98 0023: - ??_C@_0CD@DCKJKCF@garbage?5collection?5?$CFscritical?5?$CI?$CF@ (0000) -0028AABC 0007: - ??_C@_06BODLOOIB@still?5?$AA@ (0000) -0028AAC4 000e: - ??_C@_0O@ONNNEJPN@?$CFd?5slots?5free?$AA@ (0000) -0028AAD4 0014: - ??_C@_0BE@LODKOAIM@?$CF4?42f?$CF?$CF?5memory?5free?$AA@ (0000) -0028AAE8 0031: - ??_C@_0DB@GPANNPOD@compacted?5to?5?$CD?$CFd?5with?50x?$CFx?5conti@ (0000) -0028AB1C 002f: - ??_C@_0CP@FJGNMMGE@WARNING?3?5garbage?5collecting?5a?5li@ (0000) -0028AB4C 002d: - ??_C@_0CN@JMJCMKCA@garbage_object_count?$DMMAXIMUM_OBJ@ (0000) -0028AB7C 0034: - ??_C@_0DE@KFENFAAJ@?$CD?$CFd?5objects?5using?50x?$CFx?5bytes?5?$CI0x@ (0000) -0028ABB0 0039: - ??_C@_0DJ@NOLFDCHG@object_get?$CIobject_index?$CJ?9?$DOobject@ (0000) -0028ABEC 003b: - ??_C@_0DL@CLCAHNEH@object_get?$CIobject_index?$CJ?9?$DOobject@ (0000) -0028AC28 0023: - ??_C@_0CD@JHKFHGNF@object_header?9?$DOcluster_index?$CB?$DNNO@ (0000) -0030C3C0 05fa: - _data_0030c3c0 (0000) - _debug_objects_bounding_spheres (05f8) - _debug_objects_collision_models (05f9) -00456E9C 000d: - _bss_00456e9c (0000) - _debug_objects_position_velocity (000c) */ /* ---------- headers */ +#include "cseries.h" +#include "objects.h" + +#include "damage.h" +#include "light_definitions.h" +#include "object_lights.h" +#include "object_types.h" + +#include "ai/ai_debug.h" +#include "bitmaps/bitmaps.h" +#include "cache/predicted_resources.h" +#include "cseries/errors.h" +#include "cseries/profile.h" +#include "devices/device_definitions.h" +#include "devices/devices.h" +#include "editor/editor_stubs.h" +#include "effects/contrail_definitions.h" +#include "effects/contrails.h" +#include "effects/effect_definitions.h" +#include "effects/effects.h" +#include "effects/particle_system_definitions.h" +#include "effects/particle_systems.h" +#include "game/game.h" +#include "game/game_engine.h" +#include "game/players.h" +#include "items/weapons.h" +#include "main/console.h" +#include "math/periodic_functions.h" +#include "memory/memory_pool.h" +#include "models/model_animation_definitions.h" +#include "models/model_definitions.h" +#include "models/models.h" +#include "objects/widgets/widgets.h" +#include "physics/collision_bsp.h" +#include "physics/collision_model_definitions.h" +#include "physics/collision_models.h" +#include "physics/collision_usage.h" +#include "physics/collisions.h" +#include "physics/physics.h" +#include "render/render_debug.h" +#include "saved games/game_state.h" +#include "scenario/scenario.h" +#include "scenario/scenario_definitions.h" +#include "sound/sound_definitions.h" +#include "sound/game_sound.h" +#include "structures/structure_bsp_definitions.h" +#include "units/units.h" + /* ---------- constants */ + /* ---------- macros */ +#define MAXIMUM_DUMPS 1024 + + +// This is dangerous, bungie returns the same value regardless of whether the index is valid +#define OBJECT_INCOMING_FUNCTION_GET_VALUE(object, index) \ +((index)>=NUMBER_OF_INCOMING_OBJECT_FUNCTIONS+1 ? \ +(object)->object.incoming_function_values[(index)-1] : \ +(object)->object.incoming_function_values[(index)-1]) + /* ---------- structures */ +struct object_globals +{ + boolean initial_placement; + boolean object_marker_initialized; + boolean force_garbage_collection; + short active_garbage_object_count; + long first_garbage_object_index; + unsigned long last_active_cluster_bits[16]; + unsigned long active_cluster_bits[16]; + long last_garbage_warn_time; + short pvs_activation_type; + union + { + long object_index; + short cluster_index; + } pvs_activation; +}; + +struct object_memory_release_function +{ + void(*init_function)(unsigned char *, short); + boolean(*function)(char *, unsigned char *, unsigned char *, short); +}; + +struct dump_datum +{ + long definition_index; + short object_type; + short maximum_size; + long total_size; + short count; + short active_count; + short garbage_count; + short dead_count; + short outside_map_count; + short at_rest_count; +}; + /* ---------- prototypes */ +static void object_connect_lights(long object_index, boolean disconnect, boolean reconnect); +static void object_name_list_allocate(void); +static void object_name_list_free(void); +static void object_name_list_clear(void); +static void object_name_list_new(long object_index, short name_index); +static void object_name_list_delete(long object_index); +static long object_name_list_lookup(short name_index); +static long recursive_object_adder( + long object_index, + boolean(*add_object_function)(long, void *), + void *custom_data, + long object_count, + long maximum_count, + long *object_indices); +static long sort_dumps(struct dump_datum const *dump1, struct dump_datum const *dump2); +static void object_add_to_dump(long object_index, struct dump_datum *dump); +static void object_dump_write(FILE *stream, struct dump_datum *dump); +static short object_find_region_permutations_available_with_variant(struct model_region *region, short variant_number, short *available_indices); +static boolean object_select_random_region_permutations_by_variant(long object_index, struct model *model, short variant_number); +static short object_determine_variant_number(long object_index, struct model *model); +static void object_choose_random_region_permutations(long object_index); +static void object_add_to_list(long *first_object_reference, long object_index); +static void object_remove_from_list(long *first_object_reference, long object_index); +static void attachments_delete(long object_index); +static void object_create_attachments(long object_index); +static void object_delete_attachments(long object_index); +static void object_delete_recursive(long object_index, boolean delete_siblings); +static void object_compute_function_values(long object_index); +static void object_compute_change_colors(long object_index); + /* ---------- globals */ +static const struct object_memory_release_function object_memory_release_procs[3] = +{ + { NULL, ai_release_inactive_swarms }, + { ai_find_inactive_encounters, ai_release_inactive_encounters }, + { NULL, NULL } +}; +static struct object_globals *object_globals; +static struct memory_pool *object_memory_pool; +static long *object_name_list; + +static struct profile_section objects_update_section= {"objects_update", NONE, TRUE}; + +boolean debug_objects_position_velocity= FALSE; +boolean debug_objects_bounding_spheres= TRUE; +boolean debug_objects_collision_models= TRUE; + /* ---------- public code */ +long cluster_get_first_noncollideable_object( + long *reference_index, + short cluster_index) +{ + return cluster_partition_get_first_datum( + &noncollideable_object_cluster_partition, + reference_index, + cluster_index); +} + +long cluster_get_next_noncollideable_object( + long *reference_index) +{ + return cluster_partition_get_next_datum( + &noncollideable_object_cluster_partition, + reference_index); +} + +long cluster_get_first_collideable_object( + long *reference_index, + short cluster_index) +{ + return cluster_partition_get_first_datum( + &collideable_object_cluster_partition, + reference_index, + cluster_index); +} + +long cluster_get_next_collideable_object( + long *reference_index) +{ + return cluster_partition_get_next_datum( + &collideable_object_cluster_partition, + reference_index); +} + +short object_get_next_cluster( + struct object_cluster_iterator *iterator) +{ + match_assert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 1049, + iterator->cluster_partition==&collideable_object_cluster_partition || iterator->cluster_partition==&noncollideable_object_cluster_partition); + + return cluster_partition_get_next_cluster(iterator->cluster_partition, &iterator->reference_index); +} + +void *object_try_and_get_and_verify_type( + long object_index, + unsigned long valid_type_flags) +{ + struct object_header_datum* header= object_header_try_and_get(object_index); + void *result= NULL; + + if (header) + { + if (TEST_FLAG(valid_type_flags, header->type)) + { + result= header->datum; + } + } + + return result; +} + +void *object_get_and_verify_type( + long object_index, + unsigned long valid_type_flags) +{ + struct object_datum *result= object_header_get(object_index)->datum; + + match_vassert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 1690, + TEST_FLAG(valid_type_flags, result->object.type), + csprintf( + temporary, + "got an object type we didn't expect (expected one of 0x%08x but got #%d).", + valid_type_flags, + result->object.type)); + + return result; +} + +void object_iterator_new( + struct object_iterator *iterator, + unsigned long type_flags, + byte flags) +{ + data_verify(object_header_data); + iterator->signature= OBJECT_ITERATOR_SIGNATURE; + iterator->type_flags= type_flags; + iterator->flags= flags; + iterator->absolute_index= 0; + iterator->index= NONE; + + return; +} + +void *object_iterator_next( + struct object_iterator *iterator) +{ + short abs_index; + struct object_header_datum *header; + void *result= NULL; + + match_vassert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 1720, + iterator->signature==OBJECT_ITERATOR_SIGNATURE, + "uninitialized iterator passed to object_iterator_next()"); + + data_verify(object_header_data); + + abs_index= iterator->absolute_index; + + // The operation to get this header is inlined in the original code? + header= (struct object_header_datum *)((char*)object_header_data->data + sizeof(struct object_header_datum) * abs_index); + + while (abs_indexcount) + { + long index= DATUM_INDEX_NEW(abs_index++, header->identifier); + if (header->identifier) + { + if ((iterator->flags&header->flags)==iterator->flags && + TEST_FLAG(iterator->type_flags, header->type)) + { + iterator->index= index; + result= header->datum; + break; + } + } + ++header; + } + iterator->absolute_index= abs_index; + + return result; +} + +long object_get_ultimate_parent( + long object_index) +{ + long result= NONE; + struct object_datum *object; + for (;object_index!=NONE; object_index= object->object.parent_object_index) + { + result= object_index; + object= object_get(object_index); + } + + return result; +} + +void object_add_scenario_permutation( + long object_index, + struct scenario_object_permutation *permutation) +{ + return; +} + +void object_set_object_index_for_name_index( + short name_index, + long object_index) +{ + if (VALID_INDEX(name_index, global_scenario_get()->object_names.count)) + { + object_name_list[name_index]= object_index; + } + + return; +} + +void objects_fix_for_deleted_object( + long deleted_object_index) +{ + struct object_datum *object; + + struct object_iterator iterator; + object_iterator_new(&iterator, _object_mask_all, 0); + + for (object= (struct object_datum *)object_iterator_next(&iterator); + object; + object= (struct object_datum *)object_iterator_next(&iterator)) + { + if (object->object.umbrella_shield_object_index==deleted_object_index) + { + object->object.umbrella_shield_object_index= NONE; + } + object_type_handle_deleted_object(iterator.index, deleted_object_index); + } + + return; +} + +void object_set_garbage( + long object_index, + boolean garbage) +{ + struct object_datum *garbage_object; + struct object_datum* object= object_get(object_index); + + long garbage_object_index; + for (garbage_object_index= object_globals->first_garbage_object_index; + garbage_object_index!=NONE; + garbage_object_index= garbage_object->object.next_garbage_object_index) + { + garbage_object= object_get(garbage_object_index); + match_assert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 1952, + TEST_FLAG(garbage_object->object.flags, _object_garbage_bit)); + } + + if (garbage) + { + if (!TEST_FLAG(object->object.flags, _object_garbage_bit)) + { + if (!TEST_FLAG(object->object.flags, _object_cannot_be_garbage_bit)) + { + object->object.next_garbage_object_index= object_globals->first_garbage_object_index; + object_globals->first_garbage_object_index= object_index; + SET_FLAG(object->object.flags, _object_garbage_bit, TRUE); + } + } + } + else + { + if (TEST_FLAG(object->object.flags, _object_garbage_bit)) + { + long *garbage_object_index; + for (garbage_object_index= &object_globals->first_garbage_object_index; + *garbage_object_index!=object_index; + garbage_object_index= &object_get(*garbage_object_index)->object.next_garbage_object_index) + { + } + + *garbage_object_index= object->object.next_garbage_object_index; + object->object.next_garbage_object_index= NONE; + SET_FLAG(object->object.flags, _object_garbage_bit, FALSE); + } + } + + for (garbage_object_index= object_globals->first_garbage_object_index; + garbage_object_index!=NONE; + garbage_object_index= garbage_object->object.next_garbage_object_index) + { + garbage_object= object_get(garbage_object_index); + match_assert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 2006, + TEST_FLAG(garbage_object->object.flags, _object_garbage_bit)); + } + + return; +} + +void garbage_collect_now( + void) +{ + object_globals->force_garbage_collection= TRUE; + + return; +} + +void objects_information_get( + struct objects_information *information) +{ + short i; + struct object_header_datum *header; + + memset(information, 0, sizeof(*information)); + + header= (struct object_header_datum *)object_header_data->data; + for (i= 0; icount; header++) + { + if (header->identifier) + { + information->object_count++; + if (TEST_FLAG(header->flags, _object_header_active_bit)) + { + information->active_object_count++; + } + } + + i++; + } + + information->used_memory= 1.f - (real)memory_pool_get_contiguous_free_size(object_memory_pool) / 1048576.f; + + return; +} + +void object_pvs_set_object( + long object_index) +{ + if (object_index == NONE) + { + object_globals->pvs_activation_type= _pvs_activation_normal; + } + else + { + object_globals->pvs_activation_type= _pvs_activation_object; + object_globals->pvs_activation.object_index= object_index; + } + + return; +} + +void object_pvs_set_camera_point( + short camera_point_index) +{ + if (camera_point_index == NONE) + { + object_globals->pvs_activation_type= _pvs_activation_normal; + } + else + { + struct location location; + struct scenario_cutscene_camera_point *point= (struct scenario_cutscene_camera_point *)TAG_BLOCK_GET_ELEMENT( + &global_scenario_get()->cutscene_camera_points, + camera_point_index, + struct scenario_cutscene_camera_point); + + scenario_location_from_point(&location, &point->position); + if (location.cluster_index==NONE) + { + error( + _error_silent, + "object_pvs_set_camera_point: camera point %s is outside the map", + point->name); + object_globals->pvs_activation_type= FALSE; + } + else + { + object_globals->pvs_activation_type= _pvs_activation_cluster; + object_globals->pvs_activation.cluster_index= location.cluster_index; + } + } + + return; +} + +void object_pvs_clear(void) +{ + object_globals->pvs_activation_type= _pvs_activation_normal; + + return; +} + +short objects_get_activating_cluster_index( + void) +{ + struct object_header_datum *header; + short result= NONE; + + switch (object_globals->pvs_activation_type) + { + case _pvs_activation_cluster: + result= object_globals->pvs_activation.cluster_index; + break; + case _pvs_activation_object: + { + long index= object_globals->pvs_activation.object_index; + + header= object_header_try_and_get(index); + if (header && FLAG(header->type) && header->datum) + { + struct object_datum *parent_object= object_get(object_get_ultimate_parent(object_globals->pvs_activation.object_index)); + + if (TEST_FLAG(parent_object->object.flags, _object_connected_to_map_bit)) + { + if (parent_object->object.location.cluster_index!=NONE) + { + match_assert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 2279, + parent_object->object.location.cluster_index>=0 && + parent_object->object.location.cluster_indexclusters.count); + result= parent_object->object.location.cluster_index; + } + } + } + else + { + object_globals->pvs_activation_type= _pvs_activation_normal; + } + break; + } + default: + break; + } + + return result; +} + +void object_definition_predict( + long definition_index) +{ + if (definition_index!=NONE) + { + struct object_definition *object_definition= object_definition_get(definition_index); + predicted_resources_precache(&object_definition->object.predicted_resources); + } + + return; +} + +void object_predict( + long object_index) +{ + while (object_index!=NONE) + { + struct object_datum *object= object_get(object_index); + + object_definition_predict(object->definition_index); + object_predict(object->object.first_child_object_index); + + object_index= object->object.next_object_index; + } + + return; +} + +void object_beautify( + long object_index, + boolean beautiful) +{ + if (object_index!=NONE) + { + SET_FLAG(object_get(object_index)->object.flags, _object_movie_star_bit, beautiful); + } + + return; +} + +void *object_header_block_get( + long object_index, + struct object_header_block_reference *reference) +{ + struct object_header_datum *object_header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2443, reference->offset>0); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2444, reference->offset+reference->size<=object_header->data_size); + + return (byte *)object + reference->offset; +} + +static long object_header_new( + struct data_array *data, + long index, + short size) +{ + index= (index==NONE ? datum_new(data) : datum_new_at_index(data, index)); + + if (index!=NONE) + { + struct object_header_datum *header= (struct object_header_datum *)datum_get(data, index); + if (memory_pool_block_allocate(object_memory_pool, (void**)&header->datum, size)) + { + header->data_size= size; + memset(header->datum, 0, size); + } + else + { + datum_delete(data, index); + index= NONE; + } + } + + return index; +} + +static void object_header_delete( + struct data_array *data, + long object_index) +{ + struct object_header_datum *object_header= (struct object_header_datum *)datum_get(data, object_index); + + if (object_header->datum) + { + memory_pool_block_free(object_memory_pool, (void**)&object_header->datum); + } + + datum_delete(data, object_index); + object_header->datum= NULL; + object_header->flags= 0; + + return; +} + +boolean object_header_block_allocate( + long object_index, + short block_reference_offset, + short size) +{ + boolean result; + struct object_header_datum *object_header= object_header_get(object_index); + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2459, size>=0); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2460, object_header->data_size+size<=SHORT_MAX); + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2462, block_reference_offset>=0); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2463, block_reference_offset+sizeof(struct object_header_block_reference)<=object_header->data_size); + + if (memory_pool_block_reallocate( + object_memory_pool, + (void **)&object_header->datum, + size + object_header->data_size)) + { + struct object_header_block_reference *block; + short original_size= object_header->data_size; + + object_header->data_size+= size; + block= (struct object_header_block_reference *)((byte *)object_get(object_index) + block_reference_offset); + + block->offset= original_size; + block->size= size; + + memset(((byte *)object_header->datum) + block->offset, 0, size); + result= TRUE; + } + else + { + result= FALSE; + } + + return result; +} + +void object_scripting_set_collideable( + long object_index, + boolean collideable) +{ + if (object_index!=NONE) + { + struct object_datum *object= object_get(object_index); + SET_FLAG(object->object.flags, _object_no_collisions_bit, !collideable); + } + + return; +} + +void object_marker_begin( + void) +{ + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 3503, !object_globals->object_marker_initialized); + + ++global_object_marker; + object_globals->object_marker_initialized= TRUE; + + return; +} + +void object_marker_end( + void) +{ + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 3514, object_globals->object_marker_initialized); + + object_globals->object_marker_initialized= FALSE; + + return; +} + +boolean object_unmarked_function( + long object_index) +{ + struct object_datum *object= object_get(object_index); + boolean result; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 3526, object_globals->object_marker_initialized); + + result= object->object.magic_number!=global_object_marker; + + return result; +} + +boolean object_mark_function( + long object_index) +{ + boolean result; + struct object_datum *object= object_get(object_index); + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 3543, object_globals->object_marker_initialized); + + if (object->object.magic_number!=global_object_marker) + { + object->object.magic_number= global_object_marker; + result= TRUE; + } + else + { + result= FALSE; + } + + return result; +} + +void objects_place( + void) +{ + object_globals->initial_placement= TRUE; + object_types_place_all(global_scenario_get()); + object_globals->initial_placement= FALSE; + + return; +} + +// TODO: match +long find_objects_from_point_vector( + real_point3d const *position, + real_vector3d const *direction, + boolean (*add_object_function)(long, void *), + void *custom_data, + long maximum_object_count, + long *object_indices) +{ + long result= 0; + + if (scenario_leaf_index_from_point(position)!=NONE) + { + short cluster_index= TAG_BLOCK_GET_ELEMENT( + &global_structure_bsp_get()->leaves, + scenario_leaf_index_from_point(position) & LONG_MAX, + struct structure_leaf)->cluster_index; + + if (cluster_index!=NONE) + { + unsigned long* cluster_pvs; + short i; + short bit_vector_size; + + object_marker_begin(); + + cluster_pvs= structure_bsp_get_cluster_pvs(global_structure_bsp_get(), cluster_index); + bit_vector_size= BIT_VECTOR_SIZE_IN_LONGS(global_structure_bsp_get()->clusters.count); + + for (i=0; iclusters.count); + + for (j= offset; jdefinition_index) + { + index= object_num; + break; + } + } + + if (index==NONE) + { + if (object_count<(short)NUMBEROF(dumps)) + { + index= object_count++; + dumps[index].object_type= NONE; + dumps[index].definition_index= object->definition_index; + } + else + { + ++overflowed_object_count; + } + } + + header= object_header_get(iterator.index); + + if (index!=NONE) + { + object_add_to_dump(iterator.index, &dumps[index]); + } + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 4905, (header->type >= 0) && (header->type < NUMBER_OF_OBJECT_TYPES)); + object_add_to_dump(iterator.index, &dumps_by_type[header->type]); + } + + qsort( + dumps, + object_count, + sizeof(struct dump_datum), + (int(__cdecl *)(const void *, const void *))sort_dumps); + qsort( + dumps_by_type, + NUMBEROF(dumps_by_type), + sizeof(struct dump_datum), + (int(__cdecl *)(const void *, const void *))sort_dumps); + + file= fopen("d:\\object_memory.txt", "a+b"); + if (file) + { + struct objects_information information; + + objects_information_get(&information); + + fprintf( + file, + "#%d objects (#%d active) using %3.2f%% of available memory\n\n", + information.object_count, + information.active_object_count, + 100.f * information.used_memory); + + fprintf(file, "OBJECTS BY TYPE\n"); + fprintf(file, "number (active) [garbage/ dead/outside/at-rest] maxsize totsize\n"); + for (type= 0; type0) + { + fprintf( + file, + "WARNING: overflowed MAXIMUM_DUMPS (%d), this dump does not include %d objects that would not fit!\n", + MAXIMUM_DUMPS, + overflowed_object_count); + } + + fprintf(file, "\n"); + fclose(file); + } + + return; +} + +void objects_initialize( + void) +{ + damage_initialize(); + widgets_initialize(); + object_types_initialize(); + lights_initialize(); + + if (!game_in_editor()) + { + object_header_data= game_state_data_new("object", MAXIMUM_OBJECTS_PER_MAP, sizeof(struct object_header_datum)); + object_memory_pool= game_state_memory_pool_new("objects", OBJECT_MEMORY_POOL_SIZE); + } + else + { + object_header_data= data_new("object", MAXIMUM_OBJECTS_PER_MAP*5, sizeof(struct object_header_datum)); + object_memory_pool= memory_pool_new("objects", OBJECT_MEMORY_POOL_SIZE*5); + } + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 216, object_header_data && object_memory_pool); + + object_globals= (struct object_globals *)game_state_malloc("object globals", NULL, sizeof(*object_globals)); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 219, object_globals); + + object_name_list_allocate(); + cluster_partition_new(&collideable_object_cluster_partition, "collideable object"); + cluster_partition_new(&noncollideable_object_cluster_partition, "noncollideable object"); + + return; +} + +void objects_initialize_for_new_map( + void) +{ + damage_initialize_for_new_map(); + widgets_initialize_for_new_map(); + object_types_initialize_for_new_map(); + lights_initialize_for_new_map(); + + data_make_valid(object_header_data); + object_name_list_clear(); + + cluster_partition_make_valid(&collideable_object_cluster_partition); + cluster_partition_make_valid(&noncollideable_object_cluster_partition); + memset(object_globals->last_active_cluster_bits, 0, sizeof(object_globals->last_active_cluster_bits)); + memset(object_globals->active_cluster_bits, 0, sizeof(object_globals->active_cluster_bits)); + object_globals->pvs_activation_type= 0; + object_globals->object_marker_initialized= FALSE; + global_object_marker= 0; + object_globals->first_garbage_object_index= NONE; + object_globals->active_garbage_object_count= 0; + object_globals->last_garbage_warn_time= 0; + + return; +} + +void objects_dispose_from_old_map( + void) +{ + damage_dispose_from_old_map(); + widgets_dispose_from_old_map(); + object_types_dispose_from_old_map(); + lights_dispose_from_old_map(); + + if (object_header_data->valid) + { + long i; + for (i= data_next_index(object_header_data, NONE); + i!=NONE; + i= data_next_index(object_header_data, i)) + { + struct data_array *data= object_header_data; + struct object_header_datum *header= object_header_get(i); + + if (header->datum) + { + memory_pool_block_free(object_memory_pool, (void**)&header->datum); + } + + datum_delete(data, i); + header->datum= NULL; + header->flags= 0; + } + data_make_invalid(object_header_data); + } + + cluster_partition_make_invalid(&collideable_object_cluster_partition); + cluster_partition_make_invalid(&noncollideable_object_cluster_partition); + + return; +} + +void objects_dispose( + void) +{ + widgets_dispose(); + object_types_dispose(); + lights_dispose(); + + if (!game_in_editor()) + { + if (object_header_data) + { + object_header_data= 0; + } + } + else + { + data_dispose(object_header_data); + } + + if (object_memory_pool) + { + object_memory_pool= NULL; + } + + object_name_list_free(); + cluster_partition_delete(&collideable_object_cluster_partition); + cluster_partition_delete(&noncollideable_object_cluster_partition); + + return; +} + +void object_activate( + long object_index) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + + if (!TEST_FLAG(header->flags, _object_header_active_bit) && + !TEST_FLAG(object->object.flags, _object_cannot_be_activated_bit) && + object->object.parent_object_index==NONE) + { + SET_FLAG(header->flags, _object_header_active_bit, TRUE); + } + + return; +} + +void object_deactivate( + long object_index) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + + if (TEST_FLAG(header->flags, _object_header_active_bit)) + { + SET_FLAG(header->flags, _object_header_active_bit, FALSE); + } + + return; +} + +void object_reset( + long object_index) +{ + struct object_datum *object= object_get(object_index); + object->object.translational_velocity= *global_zero_vector3d; + object->object.angular_velocity= *global_zero_vector3d; + SET_FLAG(object->object.flags, _object_at_rest_bit, FALSE); + object_type_reset(object_index); + + return; +} + +void object_placement_data_new( + struct object_placement_data *data, + long definition_index, + long owner_object_index) +{ + long i; + struct object_header_datum *header; + + memset(data, 0, sizeof(*data)); + + data->definition_index= definition_index; + data->flags= 0; + data->forward= *global_forward3d; + data->up= *global_up3d; + data->variant_number= 0; + + header= object_header_try_and_get(owner_object_index); + if (header && FLAG(header->type) && header->datum) + { + struct object_datum *object= header->datum; + + data->owner_object_index= owner_object_index; + data->owner_player_index= object->object.owner_player_index; + data->owner_team_index= object->object.owner_team_index; + } + else + { + data->owner_object_index= NONE; + data->owner_player_index= NONE; + data->owner_team_index= NONE; + } + + i= 0; + do + { + data->change_colors[i]= *global_real_rgb_white; + i++; + } + while (ichange_colors)); + + return; +} + +void object_disconnect_from_map( + long object_index) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= header->datum; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 957, DATUM_INDEX_TO_IDENTIFIER(object_index)); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 958, TEST_FLAG(object->object.flags, _object_connected_to_map_bit)); + + if (object->object.parent_object_index!=NONE) + { + object_remove_from_list(&object_get(object->object.parent_object_index)->object.first_child_object_index, object_index); + } + else + { + cluster_partition_disconnect( + (TEST_FLAG(object_get(object_index)->object.flags, _object_has_collision_model_bit) ? + &collideable_object_cluster_partition : + &noncollideable_object_cluster_partition + ), + object_index, + &object->object.first_cluster_reference_index); + + if (TEST_FLAG(header->flags, _object_header_automatically_deactivate_bit)) + { + object_deactivate(object_index); + } + } + + SET_FLAG(object->object.flags, _object_connected_to_map_bit, FALSE); + SET_FLAG(header->flags, _object_header_connected_to_map_bit, FALSE); + + return; +} + +short object_get_first_cluster( + struct object_cluster_iterator *iterator, + long object_index) +{ + long ultimate_parent_index= object_get_ultimate_parent(object_index); + + iterator->cluster_partition= TEST_FLAG(object_get(ultimate_parent_index)->object.flags, _object_has_collision_model_bit) ? + &collideable_object_cluster_partition : + &noncollideable_object_cluster_partition; + + return cluster_partition_get_first_cluster( + iterator->cluster_partition, + &iterator->reference_index, + object_get(ultimate_parent_index)->object.first_cluster_reference_index); +} + +real_matrix4x3 *object_get_node_matrices( + long object_index) +{ + return (real_matrix4x3 *)object_header_block_get(object_index, &object_get(object_index)->object.node_matrices); +} + +char const *object_get_attachment_marker_name( + long object_index, + short attachment_index) +{ + const char *result; + + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (VALID_INDEX(attachment_index, object_definition->object.attachments.count)) + { + result= TAG_BLOCK_GET_ELEMENT( + &object_definition->object.attachments, + attachment_index, + struct object_attachment_definition)->marker_name; + } + else + { + result= NULL; + } + + return result; +} + +boolean object_has_node( + long object_index, + short node_index) +{ + struct object_datum *object= object_get(object_index); + long model_index= object_definition_get(object->definition_index)->object.model.index; + boolean result= FALSE; + + if (model_index==NONE) + { + if (!node_index) + { + result= TRUE; + } + } + else + { + struct model *model= model_definition_get(model_index); + if (VALID_INDEX(node_index, model->nodes.count)) + { + result= TRUE; + } + } + + return result; +} + +void object_set_automatic_deactivation( + long object_index, + boolean automatic_deactivation) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + + SET_FLAG(header->flags, _object_header_automatically_deactivate_bit, automatic_deactivation); + + if (automatic_deactivation) + { + if (object->object.parent_object_index==NONE && object->object.location.cluster_index==NONE) + { + object_deactivate(object_index); + } + } + else + { + if (!TEST_FLAG(header->flags, _object_header_active_bit)) + { + object_activate(object_index); + } + } + + return; +} + +void object_set_visibility( + long object_index, + boolean visible_flag) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (object_definition->object.model.index!=NONE) + { + if (TEST_FLAG(object->object.flags, _object_invisible_bit) && visible_flag) + { + object_connect_lights(object_index, FALSE, TRUE); + } + else if (!TEST_FLAG(object->object.flags, _object_invisible_bit) && !visible_flag) + { + object_connect_lights(object_index, TRUE, FALSE); + } + } + + if (!visible_flag || object_definition->object.model.index!=NONE) + { + struct object_header_datum *header= object_header_get(object_index); + + SET_FLAG(object->object.flags, _object_invisible_bit, !visible_flag); + SET_FLAG(header->flags, _object_header_visible_bit, visible_flag); + } + + return; +} + +void object_get_velocities( + long object_index, + real_vector3d *translational_velocity, + real_vector3d *angular_velocity) +{ + struct object_datum *ultimate_parent= object_get(object_index); + + while (ultimate_parent->object.parent_object_index!=NONE) + { + ultimate_parent= object_get(ultimate_parent->object.parent_object_index); + } + + if (translational_velocity) + { + *translational_velocity= ultimate_parent->object.translational_velocity; + } + + if (angular_velocity) + { + *angular_velocity= ultimate_parent->object.angular_velocity; + } + + return; +} + +struct location *object_get_location( + long object_index, + struct location *location) +{ + *location= object_get(object_get_ultimate_parent(object_index))->object.location; + + return location; +} + +void object_start_interpolation( + long object_index, + short frame_count) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + short node_count= model_definition_get(object_definition->object.model.index)->nodes.count; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1523, !TEST_FLAG(_object_mask_cannot_interpolate, object->object.type)); + + memcpy( + object_header_block_get(object_index, &object->object.original_node_orientations), + object_header_block_get(object_index, &object->object.node_orientations), + sizeof(real_orientation)*node_count); + if (frame_count>= + object->object.animation.interpolation_frame_count- + object->object.animation.interpolation_frame_index + ) + { + object->object.animation.interpolation_frame_index= 0; + object->object.animation.interpolation_frame_count= frame_count; + } + + return; +} + +void object_offset_interpolation( + long object_index, + real_vector3d *offset) +{ + struct object_datum *object= object_get(object_index); + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1546, !TEST_FLAG(_object_mask_cannot_interpolate, object->object.type)); + + if (object->object.animation.interpolation_frame_count) + { + real_orientation* orientation= (real_orientation *)object_header_block_get( + object_index, + &object->object.original_node_orientations); + orientation->translation.x+= offset->i; + orientation->translation.y+= offset->j; + orientation->translation.z+= offset->k; + } + + return; +} + +void object_permute_region( + long object_index, + char *permutation_name, + short desired_region_index, + boolean active_flag) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (object_definition->object.model.index!=NONE) + { + short region_index; + struct model* model= model_definition_get(object_definition->object.model.index); + + for (region_index= 0; region_indexregions.count; region_index++) + { + if (desired_region_index==NONE || desired_region_index==region_index) + { + short permutation_index; + struct model_region *region= TAG_BLOCK_GET_ELEMENT( + &model->regions, + region_index, + struct model_region); + + for (permutation_index= 0; permutation_indexpermutations.count; permutation_index++) + { + struct model_region_permutation *permutation= TAG_BLOCK_GET_ELEMENT( + ®ion->permutations, + permutation_index, + struct model_region_permutation); + + if (!_stricmp(permutation->name, permutation_name)) + { + object->object.region_permutations[region_index]= active_flag ? permutation_index : 0; + break; + } + } + } + } + } + + return; +} + +boolean object_get_function_value( + long object_index, + short function_index, + real *value_reference) +{ + boolean result; + struct object_datum *object= object_get(object_index); + + + if (function_index==NONE) + { + *value_reference= 1.f; + result= TRUE; + } + else + { + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1654, function_index>=0 && function_indexobject.outgoing_function_values[function_index]; + + result= TEST_FLAG(object->object.functions_active_flags, function_index); + } + + return result; +} + +short objects_in_clusters_by_indices( + unsigned long class_flags, + short cluster_count, + short const *cluster_indices, + short maximum_object_count, + long *object_indices) +{ + short cluster_index; + + short object_count= 0; + + if (!class_flags) + { + class_flags= NONE; + } + + object_marker_begin(); + + for (cluster_index= 0; cluster_index=maximum_object_count) + { + object_marker_end(); + return object_count; + } + object_indices[object_count++]= object_index; + } + } + } + + if (TEST_FLAG(class_flags, 1)) + { + long reference; + long object_index; + + for (object_index= cluster_get_first_noncollideable_object(&reference, cluster_num); + object_index!=NONE; + object_index= cluster_get_next_noncollideable_object(&reference)) + { + if (object_mark_function(object_index)) + { + if (object_count>=maximum_object_count) + { + object_marker_end(); + return object_count; + } + object_indices[object_count++]= object_index; + } + } + } + } + + object_marker_end(); + + return object_count; +} + +long object_index_from_name_index( + short name_index) +{ + return name_index>=0 && name_indexobject.flags, _object_connected_to_map_bit) && + object->object.parent_object_index==NONE) + { + object_disconnect_from_map(iterator.index); + + SET_FLAG(object->object.flags, _object_connected_to_map_bit, TRUE); + } + + object_type_disconnect_from_structure_bsp(iterator.index); + } + + return; +} + +boolean object_visible_to_any_player( + long object_index) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + boolean result= FALSE; + + if (TEST_FLAG(header->flags, _object_header_active_bit) && + TEST_FLAG(object->object.flags, _object_connected_to_map_bit) && + !TEST_FLAG(object->object.flags, _object_outside_of_map_bit)) + { + short cluster_index; + struct object_cluster_iterator iterator; + + const unsigned long* combined_pvs= players_get_combined_pvs(); + + for (cluster_index= object_get_first_cluster(&iterator, object_index); + cluster_index!=NONE && !BIT_VECTOR_TEST_FLAG(combined_pvs, cluster_index); + cluster_index= object_get_next_cluster(&iterator)) + { + ; + } + + if (cluster_index!=NONE) + { + long player_index; + const real bounding_area= object->object.bounding_sphere_radius*object->object.bounding_sphere_radius; + for (player_index= data_next_index(player_data, NONE); + player_index!=NONE; + player_index= data_next_index(player_data, player_index)) + { + struct player_datum *player= player_get(player_index); + + if (player->unit_index!=NONE) + { + real_point3d position; + unit_get_head_position(player->unit_index, &position); + if (distance_squared3d(&position, &object->object.bounding_sphere_center)unit_index)->unit.desired_aiming_vector, &head_to_bounding_sphere_vector)> + cosine( + (real)atan2( + object->object.bounding_sphere_radius, + normalize3d( + vector_from_points3d( + &position, + &object->object.bounding_sphere_center, + &head_to_bounding_sphere_vector) + ) + ) + 0.7853982f + ) + ) + { + result= TRUE; + break; + } + } + } + } + } + } + + return result; +} + +void object_pvs_activate( + long object_index) +{ + object_pvs_set_object(object_index); + + return; +} + +void objects_scripting_set_scale( + long object_index, + real scale, + short interpolation_frame_count) +{ + if (object_index!=NONE) + { + struct object_datum *object= object_get(object_index); + object->object.scale= scale; + if (!TEST_FLAG(_object_mask_cannot_interpolate, object->object.type)) + { + object_start_interpolation(object_index, interpolation_frame_count); + } + } + + return; +} + +static void object_delete_initial_recursive( + long object_index, + boolean delete_siblings) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + + if (game_engine_running() && object->object.type == _object_type_weapon) + { + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 829, !(weapon_is_flag(object_index))); + } + + if (object->object.first_child_object_index!=NONE) + { + object_delete_initial_recursive(object->object.first_child_object_index, TRUE); + } + + if (delete_siblings) + { + if (object->object.next_object_index!=NONE) + { + object_delete_initial_recursive(object->object.next_object_index, TRUE); + } + } + + SET_FLAG(header->flags, _object_header_being_deleted_bit, TRUE); + + object_set_visibility(object_index, FALSE); + object_name_list_delete(object_index); + + return; +} + +void object_delete( + long object_index) +{ + object_delete_initial_recursive(object_index, FALSE); + + return; +} + +void object_reconnect_to_map( + long object_index, + struct location const *location) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= header->datum; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 879, DATUM_INDEX_TO_IDENTIFIER(object_index)); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 880, !TEST_FLAG(object->object.flags, _object_connected_to_map_bit)); + + if (object->object.parent_object_index!=NONE) + { + struct object_datum *parent_object= object_get(object->object.parent_object_index); + object_add_to_list(&parent_object->object.first_child_object_index, object_index); + + SET_FLAG(header->flags, _object_header_child_bit, TRUE); + object->object.location.cluster_index=NONE; + } + else + { + if (!location) + { + struct location bounding_sphere_location; + + scenario_location_from_point(&bounding_sphere_location, &object->object.bounding_sphere_center); + location= &bounding_sphere_location; + + if (bounding_sphere_location.cluster_index==NONE) + { + scenario_location_from_point(&bounding_sphere_location, &object->object.position); + } + } + + if (location->cluster_index!=NONE) + { + object->object.location= *location; + header->cluster_index= object->object.location.cluster_index; + + SET_FLAG(object->object.flags, _object_outside_of_map_bit, FALSE); + } + else + { + SET_FLAG(object->object.flags, _object_outside_of_map_bit, TRUE); + } + + SET_FLAG(header->flags, _object_header_child_bit, FALSE); + + cluster_partition_reconnect( + (TEST_FLAG(object_get(object_index)->object.flags, _object_has_collision_model_bit) ? + &collideable_object_cluster_partition : + &noncollideable_object_cluster_partition + ), + object_index, + &object->object.first_cluster_reference_index, + &object->object.bounding_sphere_center, + object->object.bounding_sphere_radius, + &object->object.location); + + if (TEST_FLAG(header->flags, _object_header_automatically_deactivate_bit)) + { + if (header->cluster_index==NONE || !BIT_VECTOR_TEST_FLAG(players_get_combined_pvs(), header->cluster_index)) + { + if (TEST_FLAG(object->object.flags, _object_deleted_when_deactivated_bit)) + { + object_delete(object_index); + } + } + else + { + object_activate(object_index); + } + } + } + + SET_FLAG(object->object.flags, _object_connected_to_map_bit, TRUE); + SET_FLAG(header->flags, _object_header_connected_to_map_bit, TRUE); + + return; +} + +real_matrix4x3 *object_get_node_matrix( + long object_index, + short node_index) +{ + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1060, object_has_node(object_index, node_index)); + + return &((real_matrix4x3 *)object_header_block_get(object_index, &object_get(object_index)->object.node_matrices))[node_index]; +} + +short object_get_marker_by_name( + long object_index, + char const *name, + struct object_marker *markers, + short maximum_marker_count) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + short marker= model_get_marker_by_name( + object_definition->object.model.index, + name, + object->object.region_permutations, + FALSE, + NONE, + object_get_node_matrices(object_index), + TEST_FLAG(object->object.flags, _object_mirrored_bit), + markers, + maximum_marker_count); + + if (!marker) + { + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1113, maximum_marker_count>0); + + markers->node_index= 0; + matrix4x3_identity(&markers->node_matrix); + markers->matrix= *object_get_node_matrix(object_index, 0); + + if (TEST_FLAG(object->object.flags, _object_mirrored_bit)) + { + negate_vector3d(&markers->matrix.left, &markers->matrix.left); + } + + if (name && name[0]=='\0') + { + marker= 1; + } + } + + return marker; +} + +// TODO: match +void object_align_marker_to_matrix( + struct object_datum *object, + struct object_marker const *child_marker, + real_matrix4x3 const *destination_matrix) +{ + real_matrix4x3 marker_transform_matrix; + real_matrix4x3 final_matrix; + + real_vector3d vector; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1173, object); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1174, child_marker); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1175, destination_matrix); + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1177, valid_real_matrix4x3(destination_matrix)); + + matrix4x3_from_point_and_vectors(&final_matrix, &object->object.position, &object->object.forward, &object->object.up); + + matrix4x3_inverse(&final_matrix, &marker_transform_matrix); + matrix4x3_multiply(&marker_transform_matrix, &child_marker->matrix, &marker_transform_matrix); + matrix4x3_inverse(&marker_transform_matrix, &marker_transform_matrix); + matrix4x3_multiply(destination_matrix, &marker_transform_matrix, &final_matrix); + + object->object.position= final_matrix.position; + object->object.forward= final_matrix.forward; + + cross_product3d(&final_matrix.forward, &final_matrix.up, &vector); + cross_product3d(&vector, &final_matrix.forward, &object->object.up); + + normalize3d(&object->object.forward); + normalize3d(&object->object.up); + + return; +} + +void object_detach( + long child_object_index) +{ + real_matrix4x3 object_translation_matrix; + real_matrix4x3 matrix; + real_matrix4x3 object_rotation_matrix; + + real_matrix4x3 *node_matrix; + + struct object_datum *child_object= object_get(child_object_index); + struct object_datum *parent_object= object_get(child_object->object.parent_object_index); + + object_disconnect_from_map(child_object_index); + node_matrix= object_get_node_matrix(child_object->object.parent_object_index, child_object->object.parent_node_index); + + matrix4x3_translation(&object_translation_matrix, &child_object->object.position); + matrix4x3_rotation_from_vectors(&object_rotation_matrix, &child_object->object.forward, &child_object->object.up); + matrix4x3_multiply(node_matrix, &object_translation_matrix, &matrix); + matrix4x3_multiply(&matrix, &object_rotation_matrix, &matrix); + matrix4x3_to_point_and_vectors( + &matrix, + &child_object->object.position, + &child_object->object.forward, + &child_object->object.up); + + child_object->object.translational_velocity= parent_object->object.translational_velocity; + child_object->object.angular_velocity= parent_object->object.angular_velocity; + child_object->object.parent_node_index= NONE; + child_object->object.parent_object_index= NONE; + + object_reconnect_to_map(child_object_index, NULL); + object_activate(child_object_index); + + return; +} + +real_point3d *object_get_origin( + long object_index, + real_point3d *origin) +{ + struct object_datum *object= object_get(object_index); + + if (object->object.parent_object_index==NONE) + { + *origin= object->object.position; + } + else + { + real_matrix4x3 *matrix= object_get_node_matrix(object->object.parent_object_index, object->object.parent_node_index); + matrix4x3_transform_point(matrix, &object->object.position, origin); + } + + return origin; +} + +void object_get_orientation( + long object_index, + real_vector3d *forward, + real_vector3d *up) +{ + struct object_datum *object= object_get(object_index); + + if (object->object.parent_object_index==NONE) + { + if (forward) + { + *forward= object->object.forward; + } + if (up) + { + *up= object->object.up; + } + } + else + { + real_matrix4x3 *node_matrix= object_get_node_matrix( + object->object.parent_object_index, + object->object.parent_node_index); + + if (forward) + { + matrix4x3_transform_normal(node_matrix, &object->object.forward, forward); + } + if (up) + { + matrix4x3_transform_normal(node_matrix, &object->object.up, up); + } + } + + if (forward && up) + { + match_assert_valid_real_vector3d_axes2("c:\\halo\\SOURCE\\objects\\objects.c", 1462, forward, up); + } + + return; +} + +real_matrix4x3 *object_get_world_matrix( + long object_index, + real_matrix4x3 *matrix) +{ + struct object_datum *object= object_get(object_index); + matrix4x3_from_point_and_vectors(matrix, &object->object.position, &object->object.forward, &object->object.up); + + if (object->object.parent_object_index!=NONE) + { + real_matrix4x3* node_matrix= object_get_node_matrix(object->object.parent_object_index, object->object.parent_node_index); + matrix4x3_multiply(node_matrix, matrix, matrix); + } + + return matrix; +} + +void object_inverse_kinematics( + long hand_object_index, + char *hand_marker_name, + long grip_object_index, + char *grip_marker_name, + real_matrix4x3 *node_matrices) +{ + struct object_marker hand_marker; + struct object_marker grip_marker; + real_matrix4x3 desired_hand_matrix; + + struct object_datum *hand_object= object_get(hand_object_index); + struct object_definition *hand_object_definition= object_definition_get(hand_object->definition_index); + struct model *hand_model= model_definition_get(hand_object_definition->object.model.index); + + if (object_get_marker_by_name(hand_object_index, hand_marker_name, &hand_marker, 1) && + object_get_marker_by_name(grip_object_index, grip_marker_name, &grip_marker, 1)) + { + short hand_node_index= hand_marker.node_index; + short hand_parent_node_index= TAG_BLOCK_GET_ELEMENT(&hand_model->nodes, hand_node_index, struct model_node)->parent_node_index; + short desired_hand_index= NONE; + + if (hand_parent_node_index!=NONE) + { + desired_hand_index= TAG_BLOCK_GET_ELEMENT(&hand_model->nodes, hand_parent_node_index, struct model_node)->parent_node_index; + } + + if (desired_hand_index!=NONE) + { + matrix4x3_inverse(&hand_marker.node_matrix, &desired_hand_matrix); + matrix4x3_multiply(&grip_marker.matrix, &desired_hand_matrix, &desired_hand_matrix); + inverse_kinematics_adjust_matrices( + &desired_hand_matrix, + &node_matrices[desired_hand_index], + &node_matrices[hand_parent_node_index], + &node_matrices[hand_node_index]); + } + } + + return; +} + +short objects_in_sphere( + unsigned long class_flags, + unsigned long type_flags, + struct location const *location, + real_point3d const *center, + real radius, + long *object_indices, + short maximum_count) +{ + long temporary_object_indices[MAXIMUM_OBJECTS_PER_MAP]; + short cluster_indices[MAXIMUM_CLUSTERS_PER_STRUCTURE]; + + short cluster_count; + short object_count_in_clusters; + short object_index; + + short result= 0; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1779, location); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1780, center); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 1781, object_indices); + + if (!type_flags) + { + type_flags= NONE; + } + + cluster_count= structure_clusters_in_sphere( + location->cluster_index, + center, + radius, + NUMBEROF(cluster_indices), + cluster_indices); + object_count_in_clusters= objects_in_clusters_by_indices( + class_flags, + cluster_count, + cluster_indices, + NUMBEROF(temporary_object_indices), + temporary_object_indices); + for (object_index= 0; object_indexobject.type) && + point_in_sphere(center, &object->object.bounding_sphere_center, (object->object.bounding_sphere_radius)+radius)) + { + object_indices[result++]= temporary_object_indices[object_index]; + } + + } + + return result; +} + +void objects_reconnect_to_structure_bsp( + void) +{ + struct object_datum *object; + + struct object_iterator iterator; + + object_iterator_new(&iterator, _object_mask_all, 0); + + while(object= (struct object_datum *)object_iterator_next(&iterator)) + { + if (TEST_FLAG(object->object.flags, _object_connected_to_map_bit) && + object->object.parent_object_index==NONE) + { + struct location scenario_location; + + SET_FLAG(object->object.flags, _object_connected_to_map_bit, FALSE); + + object->object.location.cluster_index= NONE; + object_header_get(iterator.index)->cluster_index= NONE; + + scenario_location_from_point(&scenario_location, &object->object.bounding_sphere_center); + if (scenario_location.cluster_index==NONE) + { + struct collision_bsp_test_sphere_result result; + collision_bsp_test_sphere( + global_collision_bsp_get(), + 0, + NULL, + &object->object.bounding_sphere_center, + object->object.bounding_sphere_radius, + &result); + + if (result.leaf_count) + { + scenario_location.leaf_index= result.leaf_indices[0]; + if (result.leaf_indices[0] == -1) + { + scenario_location.cluster_index= -1; + } + else + { + scenario_location.cluster_index= TAG_BLOCK_GET_ELEMENT( + &global_structure_bsp_get()->leaves, + result.leaf_indices[0] & LONG_MAX, + struct structure_leaf)->cluster_index; + } + } + else + { + scenario_location_from_point(&scenario_location, &object->object.position); + } + } + object_reconnect_to_map(iterator.index, &scenario_location); + } + } + + return; +} + +void objects_paparazzi( + void) +{ + struct object_datum *object; + struct object_iterator iterator; + + object_iterator_new(&iterator, _object_mask_all, 0); + + while (object= (struct object_datum *)object_iterator_next(&iterator)) + { + if (TEST_FLAG(object->object.flags, _object_movie_star_bit)) + { + object_delete_initial_recursive(iterator.index, 0); + } + } + + return; +} + +void object_export_function_values( + long object_index) +{ + short i; + + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + for (i= 0; iobject.incoming_function_values); ++i) + { + if (object_definition->object.function_modes[i]) + { + short region_index; + real_matrix4x3 *node_matrix; + + real value= 0.f; + + switch (object_definition->object.function_modes[i]) + { + case _object_function_recent_body_damage: + value= object->object.current_body_damage; + break; + case _object_function_recent_shield_damage: + value= object->object.current_shield_damage; + break; + case _object_function_body_vitality: + value= object->object.body_vitality; + break; + case _object_function_shield_vitality: + value= object->object.shield_vitality; + value= MIN(value, 1.f); + break; + + case _object_function_random_constant: + if (object->object.incoming_function_values[i]==1.f) + { + value= real_random(); + } + break; + case _object_function_alive: + value= TEST_FLAG(object->object.damage_flags, _object_dead_bit) ? 0.f : 1.f; + break; + case _object_function_compass: + node_matrix= object_get_node_matrix(object_index, 0); + if (fabs(node_matrix->forward.k) < 0.995f) + { + value= signed_angular_difference(global_scenario_get()->local_north, arctangent(node_matrix->forward.i, node_matrix->forward.j)); + value= (0.15915494f * value) + 0.5f; + value= PIN(value, 0.f, 1.f); + } + else + { + value= object->object.incoming_function_values[i]; + } + break; + default: + region_index= object_definition->object.function_modes[i]-_object_function_first_region_damage; + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2630, region_index>=0 && region_indexobject.region_damage[region_index] / 255.f; + break; + } + object->object.incoming_function_values[i]= value; + } + + } + + return; +} + +void object_compute_node_matrices( + long object_index) +{ + real_orientation cannot_interpolate_node_orientations_storage[MAXIMUM_NODES_PER_MODEL]; + short node_stack[MAXIMUM_NODES_PER_MODEL]; + real_matrix4x3 node_matrix; + real_matrix4x3 object_translation_matrix; + real_matrix4x3 object_rotation_matrix; + real_matrix4x3 center_matrix; + real_point3d center; + real_matrix4x3 offset_matrix; + real_matrix4x3 parent_node_matrix_no_scale_no_mirror; + + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + real_matrix4x3 *object_nodes= (real_matrix4x3 *)object_header_block_get(object_index, &object->object.node_matrices); + real_orientation *node_orientations= + TEST_FLAG(_object_mask_cannot_interpolate, object->object.type) ? + cannot_interpolate_node_orientations_storage : + (real_orientation *)object_header_block_get(object_index, &object->object.node_orientations); + + if (object_definition->object.model.index!=NONE) + { + struct model *model; + real_matrix4x3 *object_node_matrix; + boolean world_relative; + + object_type_definition_get(object->object.type); + + model= model_definition_get(object_definition->object.model.index); + object_node_matrix= + object->object.parent_object_index!=NONE ? + object_get_node_matrix(object->object.parent_object_index, object->object.parent_node_index) : + 0; + + world_relative= FALSE; + if (object->object.animation.animation_graph_index!=NONE && + object->object.animation.state.index!=NONE) + { + short frame_index; + + struct animation_graph *animation_graph= animation_graph_definition_get( + object->object.animation.animation_graph_index); + struct animation* animation= TAG_BLOCK_GET_ELEMENT( + &animation_graph->animations, + object->object.animation.state.index, + struct animation); + + if (TEST_FLAG(object->object.flags, _object_animates_automatically_bit) && + animation->frame_count>0) + { + frame_index= object->object.animation.state.frame_index; + } + else + { + frame_index= (object_index + game_time_get()) % animation->frame_count; + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2704, frame_index>=0) + } + animation_get_node_orientations(model, animation, frame_index, node_orientations); + world_relative= TEST_FLAG(animation->flags, _animation_world_relative_bit); + } + else + { + model_get_node_orientations(model, node_orientations); + } + + if (object_definition->object.animation_graph.index!=NONE) + { + struct animation_graph *animation_graph= animation_graph_definition_get( + object->object.animation.animation_graph_index); + } + + // Scale the object orientations + if (object->object.scale>0.f) + { + node_orientations->scale*= object->object.scale; + node_orientations->translation.x*= object->object.scale; + node_orientations->translation.y*= object->object.scale; + node_orientations->translation.z*= object->object.scale; + } + + + if (object_definition->object.animation_graph.index!=NONE) + { + object_type_preprocess_node_orientations(object_index, node_orientations); + } + + if (object->object.animation.interpolation_frame_count>0) + { + match_assert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 2777, + !TEST_FLAG(_object_mask_cannot_interpolate, object->object.type)); + + interpolate_node_orientations( + model->nodes.count, + (real_orientation *)object_header_block_get( + object_index, + &object->object.original_node_orientations + ), + node_orientations, + object->object.animation.interpolation_frame_index, + object->object.animation.interpolation_frame_count); + } + } + else + { + object_nodes[0].scale= 1.f; + object_nodes[0].forward= object->object.forward; + object_nodes[0].up= object->object.up; + cross_product3d(&object_nodes[0].up, &object_nodes[0].forward, &object_nodes[0].left); + object_nodes[0].position= object->object.position; + } + + matrix4x3_transform_point( + object_nodes, + &object_definition->object.bounding_offset, + &object->object.bounding_sphere_center); + object->object.bounding_sphere_radius= object_definition->object.bounding_radius; + if (object->object.scale > 0.f) + { + object->object.bounding_sphere_radius*= object->object.scale; + } + + return; +} + +static void object_postprocess_node_matrices( + long object_index) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (object_definition->object.model.index!=NONE && + object_definition->object.animation_graph.index != NONE) + { + real_matrix4x3 *matrices= (real_matrix4x3 *)object_header_block_get( + object_index, + &object->object.node_matrices); + object_type_postprocess_node_matrices(object_index, matrices); + } + + return; +} + +static void object_choose_random_change_colors( + long object_index, + real_rgb_color *placement_change_colors) +{ + short cc_index; + + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + for (cc_index=0; cc_indexobject.base_change_colors); cc_index++) + { + object->object.base_change_colors[cc_index]= placement_change_colors[cc_index]; + + if (cc_indexobject.change_colors.count) + { + short permutation_index; + + struct object_change_color_definition *cc= TAG_BLOCK_GET_ELEMENT( + &object_definition->object.change_colors, + cc_index, + struct object_change_color_definition); + real weight= fmod( + fabs( + object->object.position.x*315.89313f + + object->object.position.y*587.12946f + + object->object.position.z*744.12415f + + (real)cc_index*431.12894f + ), + 1.f); + + for (permutation_index=0; permutation_indexpermutations.count; permutation_index++) + { + struct object_change_color_permutation *permutation= TAG_BLOCK_GET_ELEMENT( + &cc->permutations, + permutation_index, + struct object_change_color_permutation); + if (weight<=permutation->weight) + { + rgb_colors_interpolate( + &object->object.base_change_colors[cc_index], + 1, + &permutation->color_lower_bound, + &permutation->color_upper_bound, + fmod(fabs(object->object.position.y) + cc_index*0.71211f, 1.f)); + break; + } + } + } + + object->object.outgoing_change_colors[cc_index].red= PIN(object->object.base_change_colors[cc_index].red, 0.f, 1.f); + object->object.outgoing_change_colors[cc_index].green= PIN(object->object.base_change_colors[cc_index].green, 0.f, 1.f); + object->object.outgoing_change_colors[cc_index].blue= PIN(object->object.base_change_colors[cc_index].blue, 0.f, 1.f); + } + + return; +} + +void objects_scripting_detach( + long parent_object_index, + long child_object_index) +{ + if (parent_object_index!=NONE && + child_object_index!=NONE && + object_get(child_object_index)->object.parent_object_index == parent_object_index) + { + object_detach(child_object_index); + } + + return; +} + +void object_render_debug( + long object_index) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (debug_objects_root_node) + { + render_debug_matrix(TRUE, object_get_node_matrix(object_index, 0), 0.3f); + } + + if (debug_objects_names) + { + if (object->object.name_index!=NONE) + { + real_point3d origin; + + struct scenario_object_name* object_name= TAG_BLOCK_GET_ELEMENT( + &global_scenario_get()->object_names, + object->object.name_index, + struct scenario_object_name); + object_get_origin(object_index, &origin); + render_debug_string_at_point(FALSE, &origin, object_name->name, global_real_argb_purple); + } + } + + if (debug_objects_position_velocity) + { + real_vector3d velocity; + real_matrix4x3 world_matrix; + + char* model_name= strrchr(object_definition->object.model.name, '\\'); + object_get_world_matrix(object_index, &world_matrix); + object_get_velocities(object_index, &velocity, NULL); + + model_name= model_name ? &model_name[1] : object_definition->object.model.name; + + render_debug_string_at_point(0, &world_matrix.position, model_name, global_real_argb_orange); + render_debug_matrix(TRUE, &world_matrix, object->object.bounding_sphere_radius); + render_debug_vector(TRUE, &world_matrix.position, &velocity, 1.f, global_real_argb_yellow); + } + + if (debug_objects_bounding_spheres && + (object_definition->object.model.index!=NONE ||object_definition->object.collision_model.index!=NONE)) + { + const real_argb_color *draw_color= global_real_argb_black; + + // Bounding sphere is colored differently based on a couple factors: + // Red: Invalid bounding sphere + // Yellow: Active object + // Black: Inactive object + if (object->object.bounding_sphere_radius<=0.f) + { + draw_color= global_real_argb_red; + } + else + { + if (TEST_FLAG(object_header_get(object_index)->flags, _object_header_active_bit)) + { + draw_color= global_real_argb_yellow; + } + } + + render_debug_sphere( + TRUE, + &object->object.bounding_sphere_center, + object->object.bounding_sphere_radius>0.f ? object->object.bounding_sphere_radius : 1.f, + draw_color); + } + + if (debug_objects_collision_models) + { + struct collision_model_instance collision_model_instance; + if (collision_model_instance_new(&collision_model_instance, object_index)) + { + render_debug_collision_model(&collision_model_instance); + } + } + + if (debug_objects_physics) + { + struct physics_instance physics_instance; + if (physics_instance_new(&physics_instance, object_index)) + { + render_debug_physics(&physics_instance); + } + } + + if (debug_objects_pathfinding_spheres) + { + if (!TEST_FLAG(object->object.flags, _object_invisible_bit) && + !TEST_FLAG(object->object.damage_flags, _object_dead_bit)) + { + if ( + object->object.type != _object_type_machine || + TEST_FLAG(((struct machine_definition *)object_definition)->machine.flags, _machine_is_pathfinding_obstacle_bit) && + ( + !TEST_FLAG( + ((struct machine_definition *)object_definition)->machine.flags, + _machine_is_not_pathfinding_obstacle_when_open_bit + ) || + ((struct machine_datum *)object)->device.position!=1.f) + ) + { + if (object_definition->object.collision_model.index!=NONE) + { + real_matrix4x3 world_matrix; + short sphere_index; + + struct collision_model* collision_model= collision_model_definition_get( + object_definition->object.collision_model.index); + + object_get_world_matrix(object_index, &world_matrix); + + // Render all pathfinding spheres + + for (sphere_index= 0; sphere_indexpathfinding_spheres.count; ++sphere_index) + { + real_point3d origin; + + struct pathfinding_sphere *pathfinding_sphere= TAG_BLOCK_GET_ELEMENT( + &collision_model->pathfinding_spheres, + sphere_index, + struct pathfinding_sphere); + + if (pathfinding_sphere->node_index!=NONE) + { + real_matrix4x3 *node_matrix= object_get_node_matrix( + object_index, + pathfinding_sphere->node_index); + matrix4x3_transform_point( + node_matrix, + &pathfinding_sphere->center, + &origin); + } + else + { + matrix4x3_transform_point( + &world_matrix, + &pathfinding_sphere->center, + &origin); + } + render_debug_sphere( + TRUE, + &origin, + pathfinding_sphere->radius, + global_real_argb_blue); + } + + + if (collision_model->pathfinding_box.x0pathfinding_box.x1 && + collision_model->pathfinding_box.y0pathfinding_box.y1 && + collision_model->pathfinding_box.z0pathfinding_box.z1) + { + real_point3d line_points[NUMBER_OF_VERTICES_PER_LINE][NUMBER_OF_VERTICES_PER_LINE][NUMBER_OF_VERTICES_PER_LINE]; + short i; + short j; + short k; + + for (i= 0; ipathfinding_box.n[i + 0]; // x0 and x1 + line_points[i][j][k].y= collision_model->pathfinding_box.n[j + 2]; // y0 and y1 + line_points[i][j][k].z= collision_model->pathfinding_box.n[k + 4]; // z0 and z1 + matrix4x3_transform_point( + &world_matrix, + &line_points[i][j][k], + &line_points[i][j][k]); + } + } + } + + + for (i= 0; i < NUMBER_OF_VERTICES_PER_LINE; i++) + { + for (j= 0; j < NUMBER_OF_VERTICES_PER_LINE; j++) + { + for (k= 0; k < NUMBER_OF_VERTICES_PER_LINE; k++) + { + if (i==0) + { + render_debug_line( + TRUE, + &line_points[0][j][k], + &line_points[1][j][k], + global_real_argb_blue); + } + + if (j==0) + { + render_debug_line( + TRUE, + &line_points[i][0][k], + &line_points[i][1][k], + global_real_argb_blue); + } + + if (k==0) + { + render_debug_line( + TRUE, + &line_points[i][j][0], + &line_points[i][j][1], + global_real_argb_blue); + } + } + } + } + } + } + } + } + } + + return; +} + +static void attachments_new( + long object_index) +{ + long i; + + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + for (i= 0; iobject.attachments.count; i++) + { + long attachment_index; + + struct object_attachment_definition* attachment= TAG_BLOCK_GET_ELEMENT( + &object_definition->object.attachments, + i, + struct object_attachment_definition); + + short attachment_type= NONE; + if (attachment->type.index!=NONE) + { + switch (attachment->type.group_tag) + { + case LIGHT_DEFINITION_TAG: + attachment_type= _object_attachment_type_light; + break; + case LOOPING_SOUND_DEFINITION_TAG: + attachment_type= _object_attachment_type_looping_sound; + break; + case EFFECT_DEFINITION_TAG: + attachment_type= _object_attachment_type_effect; + break; + case CONTRAIL_DEFINITION_TAG: + attachment_type= _object_attachment_type_contrail; + break; + case PARTICLE_SYSTEM_DEFINITION_TAG: + attachment_type= _object_attachment_type_particle_system; + break; + } + } + + switch (attachment_type) + { + case _object_attachment_type_light: + attachment_index= light_new( + attachment->type.index, + object_index, + i, + attachment->primary_scale_function_reference-1, + attachment->change_color_reference-1); + break; + case _object_attachment_type_looping_sound: + attachment_index= game_looping_sound_new( + object_index, + attachment->type.index, + attachment->marker_name, + attachment->primary_scale_function_reference-1); + break; + case _object_attachment_type_effect: + attachment_index= effect_new_looping( + attachment->type.index, + object_index, + attachment->primary_scale_function_reference-1, + attachment->secondary_scale_function_reference-1, + attachment->change_color_reference-1); + break; + case _object_attachment_type_contrail: + attachment_index= contrail_new(attachment->type.index, object_index, i); + break; + case _object_attachment_type_particle_system: + attachment_index= particle_system_new_attached(attachment->type.index, object_index, i); + break; + } + + object->object.attachment_types[i]= attachment_type; + object->object.attachment_indices[i]= attachment_index; + } + + return; +} + +void object_set_position( + long object_index, + real_point3d const *position, + real_vector3d const *forward, + real_vector3d const *up) +{ + struct object_datum *object= object_get(object_index); + + object_disconnect_from_map(object_index); + + if (position) + { + object->object.position= *position; + } + + if (forward) + { + object->object.forward= *forward; + if (up) + { + object->object.up= *up; + } + else + { + real_vector3d right= {forward->j, -forward->i, 0.f}; + if (normalize3d(&right)==0.f) + { + right.i= 1.f; + right.k= 0.f; + right.j= 0.f; + } + cross_product3d(&right, forward, &object->object.up); + } + } + + object_compute_node_matrices(object_index); + object_reconnect_to_map(object_index, NULL); + + return; +} + +void object_translate( + long object_index, + real_point3d const *new_position, + struct location const *new_location) +{ + struct object_datum *object= object_get(object_index); + + match_assert_valid_real_point3d( + "c:\\halo\\SOURCE\\objects\\objects.c", + 562, + new_position); + + object_disconnect_from_map(object_index); + object->object.position= *new_position; + object_reconnect_to_map(object_index, new_location); + + return; +} + +long object_new( + struct object_placement_data *data) +{ + long object_index= NONE; + long definition_index= data->definition_index; + + + match_assert_valid_real_point3d("c:\\halo\\SOURCE\\objects\\objects.c", 618, &data->position) + match_assert_valid_real_vector3d_axes2("c:\\halo\\SOURCE\\objects\\objects.c", 619, &data->forward, &data->up); + match_assert_valid_real_vector3d("c:\\halo\\SOURCE\\objects\\objects.c", 620, &data->angular_velocity); + match_assert_valid_real_vector3d("c:\\halo\\SOURCE\\objects\\objects.c", 621, &data->translational_velocity); + + if (game_engine_running() && definition_index!=NONE) + { + definition_index= game_engine_remap_object_definition(definition_index); + } + + if (definition_index!=NONE) + { + struct object_definition *object_definition= object_definition_get(definition_index); + struct object_type_definition *type_definition= object_type_definition_get(object_definition->object.type); + + object_index= object_header_new(object_header_data, NONE, type_definition->game_datum_size); + + if (object_index!=NONE) + { + short node_count; + + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + boolean can_create_object= TRUE; + + SET_FLAG(header->flags, _object_header_being_created_bit, TRUE); + SET_FLAG(header->flags, _object_header_automatically_deactivate_bit, TRUE); + + header->type= object_definition->object.type; + object->definition_index= definition_index; + object->object.type= object_definition->object.type; + + object_type_adjust_placement(object_index, data); + + object->object.position= data->position; + object->object.forward= data->forward; + object->object.up= data->up; + object->object.translational_velocity= data->translational_velocity; + object->object.angular_velocity= data->angular_velocity; + + point_from_line3d( + &object->object.position, + &object->object.up, + data->height, + &object->object.position); + + SET_FLAG(object->object.flags, _object_mirrored_bit, TEST_FLAG(data->flags, _new_object_mirrored_bit)); + + object->object.location.cluster_index= NONE; + header->cluster_index= NONE; + + object->object.magic_number= global_object_marker-1; + object->object.umbrella_shield_object_index= NONE; + object->object.first_cluster_reference_index= NONE; + object->object.animation.state.index= NONE; + object->object.animation.animation_graph_index= object_definition->object.animation_graph.index; + object->object.cached_render_state_index= NONE; + object->object.parent_object_index= NONE; + object->object.next_object_index= NONE; + object->object.first_child_object_index= NONE; + object->object.name_index= NONE; + object->object.shield_damage_decay_timer= NONE; + object->object.body_damage_decay_timer= NONE; + + if (TEST_FLAG(object_definition->object.flags, _object_does_not_cast_shadow_bit)) + { + SET_FLAG(object->object.flags, _object_shadowless_bit, TRUE); + } + + SET_FLAG(object->object.flags, _object_has_collision_model_bit, object_definition->object.collision_model.index!=NONE); + + object_set_visibility(object_index, object_definition->object.model.index!=NONE); + object->object.owner_team_index= data->owner_team_index; + object->object.owner_player_index= data->owner_player_index; + object->object.owner_object_index= data->owner_object_index; + object->object.variant_number= data->variant_number; + object->object.forced_shader_permutation_index= object_definition->object.forced_shader_permutation_index; + + if (object_definition->object.model.index==NONE) + { + node_count=1; + } + else + { + node_count= model_definition_get(object_definition->object.model.index)->nodes.count; + } + + if (object_header_block_allocate( + object_index, + offsetof(struct object_datum, object.node_matrices), + sizeof(struct real_matrix4x3) * node_count)) + { + if (!TEST_FLAG(_object_mask_cannot_interpolate, object_definition->object.type) && + ( + !object_header_block_allocate( + object_index, + offsetof(struct object_datum, object.node_orientations), + sizeof(struct real_orientation) * node_count + ) || + !object_header_block_allocate( + object_index, + offsetof(struct object_datum, object.original_node_orientations), + sizeof(struct real_orientation) * node_count + ) + ) + ) + { + can_create_object= FALSE; + } + } + else + { + can_create_object= FALSE; + } + + // Get the object, we do this so we can verify that we're able to retrieve it in the future + object= object_get(object_index); + + if (can_create_object && object_type_new(object_index)) + { + boolean original_deleted_when_deactivated= TEST_FLAG(object->object.flags, _object_deleted_when_deactivated_bit); + + if (original_deleted_when_deactivated && + TEST_FLAG(data->flags, _new_object_never_automatically_delete_bit)) + { + SET_FLAG(object->object.flags, _object_deleted_when_deactivated_bit, FALSE); + } + + object_choose_random_change_colors(object_index, data->change_colors); + object_choose_random_region_permutations(object_index); + object_initialize_vitality(object_index, NULL, NULL); + object_compute_node_matrices(object_index); + object_reconnect_to_map(object_index, NULL); + object_postprocess_node_matrices(object_index); + object_type_export_function_values(object_index); + object_compute_function_values(object_index); + object_compute_change_colors(object_index); + + object_create_attachments(object_index); + + // Restore value + SET_FLAG(object->object.flags, _object_deleted_when_deactivated_bit, original_deleted_when_deactivated); + + if (!TEST_FLAG(header->flags, _object_header_active_bit) && + TEST_FLAG(object->object.flags, _object_deleted_when_deactivated_bit)) + { + if (TEST_FLAG(data->flags, _new_object_never_automatically_delete_bit)) + { + if (object->object.location.cluster_index!=NONE) + { + object_delete(object_index); + } + } + else + { + object_delete(object_index); + } + } + } + else + { + can_create_object= FALSE; + } + + if (can_create_object) + { + if (object_definition->object.creation_effect.index!=NONE) + { + effect_new_from_object( + object_definition->object.creation_effect.index, + object_index, + object_index, + NONE, + 0.f, + 0.f, + NULL, + NULL); + } + } + else + { + object_type_delete(object_index); + object_header_delete(object_header_data, object_index); + object_index= NONE; + } + } + } + + if (object_index==NONE && definition_index!=NONE) + { + char string[512]; + sprintf(string, "OUT OF OBJECTS: cannot create %s", tag_name_strip_path(tag_get_name(definition_index))); + console_printf(FALSE, "%s", string); + error(_error_log, "%s", string); + } + + return object_index; +} + + +void object_attach_to_node( + long parent_object_index, + long child_object_index, + short parent_node_index) +{ + long object_index; + struct object_datum *object; + + boolean valid= TRUE; + + for ( + object_index= parent_object_index; + object_index!=NONE; + object_index= object->object.parent_object_index) + { + object= object_get(object_index); + if (object_index == child_object_index) + { + valid= FALSE; + break; + } + } + + if (valid) + { + real_matrix4x3 inverse_node_matrix; + + struct object_datum *child_object= object_get(child_object_index); + struct object_datum *parent_object= object_get(parent_object_index); + boolean connected_to_map= TEST_FLAG(child_object->object.flags, _object_connected_to_map_bit); + + match_assert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 1235, + object_has_node(parent_object_index, parent_node_index)); + + if (connected_to_map) + { + object_disconnect_from_map(child_object_index); + } + + matrix4x3_inverse(object_get_node_matrix(parent_object_index, parent_node_index), &inverse_node_matrix); + matrix4x3_transform_point(&inverse_node_matrix, &child_object->object.position, &child_object->object.position); + matrix4x3_transform_normal(&inverse_node_matrix, &child_object->object.forward, &child_object->object.forward); + matrix4x3_transform_normal(&inverse_node_matrix, &child_object->object.up, &child_object->object.up); + child_object->object.parent_object_index= parent_object_index; + child_object->object.parent_node_index= parent_node_index; + + if (connected_to_map) + { + object_reconnect_to_map(child_object_index, NULL); + } + + object_deactivate(child_object_index); + + SET_FLAG(object_header_get(child_object_index)->flags, _object_header_do_not_update_bit, TRUE); + + object_compute_node_matrices(child_object_index); + } + else + { + match_vassert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 1225, + valid, + "cannot attach an object to one of its children"); + } + + return; +} + +boolean object_force_inside_bsp( + long object_index, + real_point3d const *known_good_point) +{ + struct collision_result collision; + + struct object_datum *object= object_get(object_index); + boolean result= FALSE; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2365, global_current_collision_user_depth < MAXIMUM_COLLISION_USER_STACK_DEPTH); + global_current_collision_users[global_current_collision_user_depth++]= 19; + + if (collision_test_line(_collision_test_for_projectiles_flags, known_good_point, &object->object.position, NONE, &collision) || + object->object.location.cluster_index==NONE) + { + if (collision.location.cluster_index!=NONE) + { + object_translate(object_index, &collision.point, &collision.location); + object_compute_node_matrices(object_index); + result= TRUE; + } + } + else + { + result= TRUE; + } + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2387, global_current_collision_user_depth > 1); + --global_current_collision_user_depth; + + return result; +} + +boolean object_update( + long object_index) +{ + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + boolean result= TRUE; + if (!TEST_FLAG(header->flags, _object_header_do_not_update_bit)) + { + if (TEST_FLAG(object->object.flags, _object_garbage_bit)) + { + ++object_globals->active_garbage_object_count; + } + + if (object->object.animation.interpolation_frame_count) + { + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 2508, !TEST_FLAG(_object_mask_cannot_interpolate, object->object.type)); + if (++object->object.animation.interpolation_frame_index>= + object->object.animation.interpolation_frame_count) + { + object->object.animation.interpolation_frame_count= 0; + } + } + + object_type_update(object_index); + if (object_definition->object.collision_model.index!=NONE) + { + object_damage_update(object_index); + } + + object_type_export_function_values(object_index); + + if (!TEST_FLAG(object->object.flags, _object_do_not_recompute_node_matrices_bit)) + { + object_compute_node_matrices(object_index); + } + + object_compute_function_values(object_index); + object_compute_change_colors(object_index); + + if ( + TEST_FLAG(object->object.flags, _object_dynamic_lighting_recompute_bit) && + ( + !TEST_FLAG(object->object.flags, _object_invisible_bit) || + object_definition_get(object->definition_index)->object.model.index==NONE + ) + ) + { + object_connect_lights(object_index, TRUE, TRUE); + } + + // Update children (if we have any) + if (object->object.first_child_object_index!=NONE) + { + object_update(object->object.first_child_object_index); + } + + if (object->object.parent_object_index!=NONE) + { + if (object->object.next_object_index!=NONE) + { + object_update(object->object.next_object_index); + } + } + + object_postprocess_node_matrices(object_index); + } + + return result; +} + +void object_compute_node_matrices_recursive( + long object_index) +{ + long child_index; + struct object_datum *child_object; + struct object_datum *object= object_get(object_index); + + object_compute_node_matrices(object_index); + + for ( + child_index= object->object.first_child_object_index; + child_index!=NONE; + child_index= child_object->object.next_object_index) + { + child_object= object_get(child_index); + object_compute_node_matrices_recursive(child_index); + } + + return; +} + +long object_new_from_scenario( + struct scenario_object_datum *scenario_object, + struct tag_block *palette) +{ + struct object_placement_data placement_data; + + long result= NONE; + + if (scenario_object->palette_entry_index!=NONE && + ( + !object_globals->initial_placement || + !TEST_FLAG(scenario_object->placement_flags, _scenario_object_placement_not_automatic_bit) + )) + { + if (scenario_object->name_index==NONE || + object_name_list_lookup(scenario_object->name_index)==NONE) + { + long definition_index= TAG_BLOCK_GET_ELEMENT( + palette, + scenario_object->palette_entry_index, + struct scenario_object_palette_entry + )->reference.index; + + if (definition_index!=NONE) + { + object_placement_data_new(&placement_data, definition_index, NONE); + placement_data.position= scenario_object->position; + vectors3d_from_euler_angles3d( + &placement_data.forward, + &placement_data.up, + &scenario_object->rotation); + placement_data.variant_number= scenario_object->variant_number; + + result= object_new(&placement_data); + if (result!=NONE) + { + object_type_place(result, scenario_object); + if (scenario_object->name_index!=NONE) + { + object_name_list_new(result, scenario_object->name_index); + } + } + } + } + } + + return result; +} + +void object_attach_to_marker( + long parent_object_index, + char const *parent_marker_name, + long child_object_index, + char const *child_marker_name) +{ + struct object_marker parent_marker; + struct object_marker child_marker; + real_matrix4x3 inverted_matrix; + + struct object_datum *child_object= object_get(child_object_index); + + object_get_marker_by_name(parent_object_index, parent_marker_name, &parent_marker, 1); + object_get_marker_by_name(child_object_index, child_marker_name, &child_marker, 1); + object_disconnect_from_map(child_object_index); + + if (child_marker_name && *child_marker_name) + { + object_align_marker_to_matrix(child_object, &child_marker, &parent_marker.matrix); + } + else + { + matrix4x3_inverse(&child_marker.node_matrix, &inverted_matrix); + matrix4x3_transform_point(&inverted_matrix, &parent_marker.matrix.position, &child_object->object.position); + matrix4x3_transform_normal(&inverted_matrix, &parent_marker.matrix.forward, &child_object->object.forward); + matrix4x3_transform_normal(&inverted_matrix, &parent_marker.matrix.up, &child_object->object.up); + } + + object_reconnect_to_map(child_object_index, NULL); + object_attach_to_node(parent_object_index, child_object_index, parent_marker.node_index); + + return; +} + +long object_new_by_name( + short name_index) +{ + long placement_tag_block_element_size; + struct scenario *scenario= global_scenario_get(); + + + struct scenario_object_name* name= TAG_BLOCK_GET_ELEMENT( + &scenario->object_names, + name_index, + struct scenario_object_name); + + struct tag_block* datum= scenario_get_object_type_scenario_datums( + scenario, + name->runtime_object_type, + &placement_tag_block_element_size); + + struct tag_block *palette= scenario_get_object_type_scenario_palette( + scenario, + name->runtime_object_type); + + struct scenario_object_datum *object= (struct scenario_object_datum *)tag_block_get_element_with_size( + datum, + name->runtime_scenario_datum_index, + placement_tag_block_element_size); + + return object_new_from_scenario( + object, + palette); +} + +void objects_scripting_attach( + long parent_object_index, + char const *parent_marker_name, + long child_object_index, + char const *child_marker_name) +{ + if (parent_object_index!=NONE && + child_object_index !=NONE && + object_get(child_object_index)->object.parent_object_index==NONE) + { + object_attach_to_marker(parent_object_index, parent_marker_name, child_object_index, child_marker_name); + } + + return; +} + +void object_delete_immediately( + long object_index) +{ + object_delete_initial_recursive(object_index, FALSE); + object_delete_recursive(object_index, FALSE); + + return; +} + +void objects_garbage_collection( + void) +{ + long garbage_object_indices[MAXIMUM_OBJECTS_PER_MAP]; + char warningbuf[512]; + unsigned char release_proc_working_memory[4096]; + char released_resultbuf[512]; + + long garbage_collect_mode= NONE; + + if (object_globals->force_garbage_collection) + { + garbage_collect_mode= _garbage_collect_everything; + } + else if (memory_pool_get_contiguous_free_size(object_memory_pool)>GARBAGE_LIMIT_FREE_MEMORY_CRITICAL) + { + if (MAXIMUM_OBJECTS_PER_MAP-object_header_data->actual_count>GARBAGE_LIMIT_FREE_OBJECTS_TRIGGER) + { + if (object_globals->active_garbage_object_count>=GARBAGE_LIMIT_ACTIVE_GARBAGE_TRIGGER) + { + garbage_collect_mode= _garbage_collect_active_objects; + } + } + else + { + garbage_collect_mode= _garbage_collect_for_space; + } + } + else + { + memory_pool_compact(object_memory_pool); + if (memory_pool_get_contiguous_free_size(object_memory_pool)<=GARBAGE_LIMIT_FREE_MEMORY_TRIGGER) + { + garbage_collect_mode= _garbage_collect_for_space; + } + else + { + object_globals->force_garbage_collection= FALSE; + } + } + + if (garbage_collect_mode!=NONE) + { + long garbage_object_index; + struct object_datum *object; + + short garbage_object_count= 0; + boolean should_collect= FALSE; + + if (debug_object_garbage_collection) + { + console_printf( + FALSE, + "#%d objects using 0x%x bytes (0x%x contiguous free)", + object_header_data->actual_count, + OBJECT_MEMORY_POOL_SIZE - memory_pool_get_free_size(object_memory_pool), + memory_pool_get_contiguous_free_size(object_memory_pool)); + } + + for ( + garbage_object_index= object_globals->first_garbage_object_index; + garbage_object_index!=NONE; + garbage_object_index=object->object.next_garbage_object_index) + { + object= object_get(garbage_object_index); + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 4289, garbage_object_countactive_garbage_object_count<=GARBAGE_LIMIT_ACTIVE_GARBAGE_TARGET; + break; + case _garbage_collect_for_space: + should_collect= TRUE; + break; + } + + if (should_collect || !garbage_object_count) + { + break; + } + + object_index= garbage_object_indices[--garbage_object_count]; + header= object_header_get(object_index); + + garbage_collect= TRUE; + if (garbage_collect_mode==_garbage_collect_active_objects) + { + garbage_collect= TEST_FLAG(header->flags, _object_header_active_bit); + } + + if (object_visible_to_any_player(object_index)) + { + garbage_collect= FALSE; + } + + if (garbage_collect) + { + struct object_datum *object= object_get(object_index); + + if (TEST_FLAG(_object_mask_unit, object->object.type) && !TEST_FLAG(object->object.damage_flags, _object_dead_bit)) + { + error( + _error_silent, + "WARNING: garbage collecting a living unit (%s)", + ai_debug_describe_actor(NONE, object_index, TRUE, temporary, NUMBEROF(temporary))); + } + + + if (TEST_FLAG(header->flags, _object_header_active_bit)) + { + --object_globals->active_garbage_object_count; + } + object_set_garbage(object_index, FALSE); + object_delete_immediately(object_index); + } + } + + memory_pool_compact(object_memory_pool); + + if (debug_object_garbage_collection) + { + console_printf( + FALSE, + "compacted to #%d with 0x%x contiguous bytes free", + object_header_data->actual_count, + memory_pool_get_contiguous_free_size(object_memory_pool)); + } + + if (!should_collect) + { + boolean update_time; + + const struct object_memory_release_function *current_release_procs= object_memory_release_procs; + boolean v0= FALSE; + boolean garbage_collection_after_first_attempt= FALSE; + boolean garbage_should_warn= TRUE; + + if (object_globals->last_garbage_warn_time!=NONE) + { + if (object_globals->last_garbage_warn_time+150>=game_time_get()) + { + garbage_should_warn= FALSE; + } + } + + update_time= FALSE; + while (TRUE) + { + boolean debug_garbage_collection= FALSE; + boolean status_still_critical= FALSE; + if (garbage_collect_mode==_garbage_collect_for_space) + { + long free_size= memory_pool_get_contiguous_free_size(object_memory_pool); + long free_objects= MAXIMUM_OBJECTS_PER_MAP-object_header_data->count; + boolean debug_slots_free= FALSE; + + if (free_size>GARBAGE_LIMIT_FREE_MEMORY_CRITICAL) + { + if (free_objects>GARBAGE_LIMIT_FREE_OBJECTS_CRITICAL) + { + if (free_size>GARBAGE_LIMIT_FREE_MEMORY_TRIGGER) + { + if (free_objects<=GARBAGE_LIMIT_FREE_OBJECTS_TRIGGER) + { + debug_garbage_collection= TRUE; + debug_slots_free= TRUE; + } + } + else + { + debug_garbage_collection= TRUE; + } + } + else + { + status_still_critical= TRUE; + debug_garbage_collection= TRUE; + debug_slots_free= TRUE; + } + } + else + { + status_still_critical= TRUE; + debug_garbage_collection= TRUE; + } + + if (debug_slots_free) + { + sprintf(warningbuf, "%d slots free", free_objects); + } + else + { + sprintf(warningbuf, "%4.2f%% memory free", ((free_size * 100.f) / 2097152.f)); + } + } + + if (status_still_critical || garbage_collection_after_first_attempt) + { + char tempbuffer[512]; + + const char *status; + if (garbage_collection_after_first_attempt) + { + status= status_still_critical ? "still " : "not "; + } + else + { + status= ""; + } + sprintf(tempbuffer, "garbage collection %scritical (%s)", status, warningbuf); + console_printf(FALSE, "%s", tempbuffer); + error(_error_log, "%s", tempbuffer); + update_time= TRUE; + } + else if (debug_garbage_collection && garbage_should_warn) + { + error(_error_silent, "garbage collection warning (%s)", warningbuf); + update_time= TRUE; + } + + if (status_still_critical) + { + boolean result= FALSE; + while (current_release_procs->function && !result) + { + boolean more_to_release= FALSE; + if (!v0 && current_release_procs->init_function) + { + current_release_procs->init_function( + release_proc_working_memory, + sizeof(release_proc_working_memory)); + v0= TRUE; + } + result= current_release_procs->function( + released_resultbuf, + &more_to_release, + release_proc_working_memory, + sizeof(release_proc_working_memory)); + if (result) + { + char tempbuffer[512]; + + sprintf(tempbuffer, "removing objects: %s", released_resultbuf); + console_printf(FALSE, "%s", tempbuffer); + error(_error_log, "%s", tempbuffer); + } + if (!more_to_release) + { + ++current_release_procs; + v0= FALSE; + } + } + + if (!result) + { + if (update_time) + { + object_globals->last_garbage_warn_time= game_time_get(); + } + break; + } + garbage_collection_after_first_attempt= TRUE; + memory_pool_compact(object_memory_pool); + } + } + } + } + + object_globals->force_garbage_collection= FALSE; + + return; +} + + +void objects_update( + void) +{ + unsigned long *last_active_cluster_bits; + unsigned long *active_cluster_bits; + short cluster_count; + short i; + struct object_header_datum *object_header; + + boolean dont_update_object= ((game_time_get()&1)!=0) && game_players_are_double_speed(); + + profile_enter(objects_update_section); + + object_globals->active_garbage_object_count= 0; + + last_active_cluster_bits= object_globals->last_active_cluster_bits; + active_cluster_bits= object_globals->active_cluster_bits; + cluster_count= global_structure_bsp_get()->clusters.count; + + memcpy(last_active_cluster_bits, active_cluster_bits, BIT_VECTOR_SIZE_IN_BYTES(cluster_count)); + memcpy(active_cluster_bits, players_get_combined_pvs(), BIT_VECTOR_SIZE_IN_BYTES(cluster_count)); + + if (csmemcmp(last_active_cluster_bits, active_cluster_bits, BIT_VECTOR_SIZE_IN_BYTES(cluster_count))) + { + object_header= (struct object_header_datum *)object_header_data->data; + for (i= 0; icount; ++object_header) + { + if (object_header->identifier && + TEST_FLAG(object_header->flags, _object_header_automatically_deactivate_bit) && + TEST_FLAG(object_header->flags, _object_header_connected_to_map_bit)) + { + if (TEST_FLAG(object_header->flags, _object_header_active_bit)) + { + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 369, object_header->cluster_index!=NONE); + if (!BIT_VECTOR_TEST_FLAG(active_cluster_bits, object_header->cluster_index)) + { + if (TEST_FLAG(object_header->datum->object.flags, _object_deleted_when_deactivated_bit)) + { + object_delete_initial_recursive(i, FALSE); + } + else + { + object_deactivate(i); + } + } + } + else if ( + !TEST_FLAG(object_header->flags, _object_header_child_bit) && + object_header->cluster_index != NONE && + BIT_VECTOR_TEST_FLAG(active_cluster_bits, object_header->cluster_index) + ) + { + object_activate(i); + } + } + + ++i; + } + + structure_decals_update( + last_active_cluster_bits, + active_cluster_bits, + cluster_count); + } + + object_header= (struct object_header_datum *)object_header_data->data; + for (i= 0; icount; ++object_header) + { + if (object_header->identifier) + { + if (TEST_FLAG(object_header->flags, _object_header_active_bit) && + !TEST_FLAG(object_header->flags, _object_header_being_created_bit)) + { + long object_index= DATUM_INDEX_NEW(i, object_header->identifier); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 416, object_get(object_index)->object.parent_object_index==NONE); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 417, object_get(object_index)->object.next_object_index==NONE); + + if (!dont_update_object || + TEST_FLAG(_object_mask_unit, object_header->type) && + unit_get(object_index)->unit.player_index!=NONE) + { + object_update(object_index); + } + } + } + ++i; + } + + object_header= (struct object_header_datum *)object_header_data->data; + for (i= 0; icount; ++object_header) + { + if (object_header->identifier) + { + SET_FLAG(object_header->flags, _object_header_do_not_update_bit, FALSE); + + if (TEST_FLAG(object_header->flags, _object_header_being_created_bit)) + { + SET_FLAG( + object_header->flags, + _object_header_being_created_bit, + FALSE); + object_update(DATUM_INDEX_NEW(i, object_header->identifier)); + } + + if (TEST_FLAG(object_header->flags, _object_header_being_deleted_bit)) + { + object_delete_recursive(DATUM_INDEX_NEW(i, object_header->identifier), FALSE); + } + } + ++i; + } + + objects_garbage_collection(); + + profile_exit(objects_update_section); + + return; +} + +void objects_memory_compact( + void) +{ + objects_garbage_collection(); + memory_pool_compact(object_memory_pool); + return; +} + /* ---------- private code */ + +static void object_connect_lights( + long object_index, + boolean disconnect, + boolean reconnect) +{ + struct object_datum *object= object_get(object_index); + + if (TEST_FLAG(object->object.flags, _object_has_attached_lights_bit)) + { + short i; + struct object_definition *object_definition= object_definition_get(object->definition_index); + + for (i=0; iobject.attachments.count; ++i) + { + if (!object->object.attachment_types[i] && object->object.attachment_indices[i]!=NONE) + { + if (disconnect) + { + light_disconnect_from_map(object->object.attachment_indices[i]); + } + if (reconnect) + { + light_reconnect_to_map(object->object.attachment_indices[i]); + } + } + } + } + + return; +} + +static void object_name_list_allocate( + void) +{ + object_name_list= (long*)game_state_malloc("object name list", NULL, MAXIMUM_OBJECT_NAMES_PER_SCENARIO * sizeof(*object_name_list)); + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 4072, object_name_list); + + return; +} + +static void object_name_list_free( + void) +{ + // Bungie never free'd this properly + + return; +} + +static void object_name_list_clear( + void) +{ + memset(object_name_list, NONE, MAXIMUM_OBJECT_NAMES_PER_SCENARIO * sizeof(*object_name_list)); + + return; +} + +static void object_name_list_new( + long object_index, + short name_index) +{ + struct object_datum *object= object_get(object_index); + + match_assert( + "c:\\halo\\SOURCE\\objects\\objects.c", + 4099, + name_index>=0 && name_indexobject.name_index= name_index; + } + else + { + error( + _error_silent, + "an object with the name '%s' already exists!", + TAG_BLOCK_GET_ELEMENT(&global_scenario_get()->object_names, name_index, struct scenario_object_name)->name); + } + + return; +} + +static void object_name_list_delete( + long object_index) +{ + struct object_datum *object= object_get(object_index); + + if (object->object.name_index!=NONE) + { + short i; + struct scenario *scenario= global_scenario_get(); + object->object.name_index= NONE; + + for (i=0; iobject_names.count; ++i) + { + if (object_name_list[i]==object_index) + { + object_name_list[i]= NONE; + } + } + } + + return; +} + +static long object_name_list_lookup( + short name_index) +{ + return VALID_INDEX(name_index, MAXIMUM_OBJECT_NAMES_PER_SCENARIO) ? object_name_list[name_index] : NONE; +} + +static long recursive_object_adder( + long object_index, + boolean(*add_object_function)(long, void *), + void *custom_data, + long object_count, + long maximum_count, + long *object_indices) +{ + struct object_datum *object= object_get(object_index); + + if (object_countobject.first_child_object_index!=NONE) + { + object_count= recursive_object_adder( + object->object.first_child_object_index, + add_object_function, + custom_data, + object_count, + maximum_count, + object_indices); + } + + if (object->object.next_object_index!=NONE) + { + object_count= recursive_object_adder( + object->object.next_object_index, + add_object_function, + custom_data, + object_count, + maximum_count, + object_indices); + } + } + return object_count; +} + +static long sort_dumps( + struct dump_datum const *dump1, + struct dump_datum const *dump2) +{ + long result; + if (dump1->total_size < dump2->total_size) + { + result= 1; + } + else if (dump1->total_size <= dump2->total_size) + { + result= 0; + } + else + { + result= -1; + } + + return result; +} + +static void object_add_to_dump( + long object_index, + struct dump_datum *dump) +{ + long parent_index; + struct object_datum *parent; + struct object_header_datum *header= object_header_get(object_index); + struct object_datum *object= object_get(object_index); + + + if (header->data_size>dump->maximum_size) + { + dump->maximum_size= header->data_size; + } + + dump->total_size+= header->data_size; + dump->count++; + + if (TEST_FLAG(header->flags, _object_header_active_bit)) + { + dump->active_count++; + } + + if (TEST_FLAG(object->object.flags, _object_garbage_bit)) + { + dump->garbage_count++; + } + + if (TEST_FLAG(object->object.damage_flags, _object_dead_bit)) + { + dump->dead_count++; + } + + if (TEST_FLAG(object->object.flags, _object_at_rest_bit)) + { + dump->at_rest_count++; + } + + parent_index= object_get_ultimate_parent(object_index); + parent= object_get(parent_index); + if (TEST_FLAG(parent->object.flags, _object_outside_of_map_bit) || parent->object.location.cluster_index==NONE) + { + dump->outside_map_count++; + } + return; +} + +static void object_dump_write( + FILE *stream, + struct dump_datum *dump) +{ + const char *name= "unknown"; + if (dump->definition_index!=NONE) + { + name= tag_get_name(dump->definition_index); + } + else + { + if (dump->object_type!=NONE) + { + name= object_type_get_name(dump->object_type); + } + } + + fprintf( + stream, + "% 6d (% 6d) [% 7d/% 7d/% 7d/% 7d] % 7d % 7d %s\r\n", + dump->count, + dump->active_count, + dump->garbage_count, + dump->dead_count, + dump->outside_map_count, + dump->at_rest_count, + dump->maximum_size, + dump->total_size, + name); + + return; +} + +static short object_find_region_permutations_available_with_variant( + struct model_region *region, + short variant_number, + short *available_indices) +{ + short i; + short result= 0; + + for (i= 0; ipermutations.count; i++) + { + struct model_region_permutation* permutation= TAG_BLOCK_GET_ELEMENT( + ®ion->permutations, + i, + struct model_region_permutation); + if (!TEST_FLAG(permutation->flags, _model_region_permutation_cannot_be_chosen_randomly_bit)) + { + if (permutation->variant_number==variant_number || + variant_number==NONE && permutation->variant_number< 100) + { + available_indices[result++]= i; + } + } + } + + return result; +} + +static boolean object_select_random_region_permutations_by_variant( + long object_index, + struct model *model, + short variant_number) +{ + short available_permutation_indices[32]; + short region_index; + + struct object_datum *object= object_get(object_index); + boolean result= TRUE; + + for (region_index=0; region_indexregions.count; region_index++) + { + struct model_region *region= TAG_BLOCK_GET_ELEMENT(&model->regions, region_index, struct model_region); + short permutation_index= object_find_region_permutations_available_with_variant(region, variant_number, available_permutation_indices); + + if (permutation_index==0 && variant_number!=NONE) + { + permutation_index= object_find_region_permutations_available_with_variant(region, 0, available_permutation_indices); + } + + if (!permutation_index) + { + object->object.region_permutations[region_index]= 0; + result= FALSE; + } + else + { + short permutation_num= permutation_index==1 ? 0 : random_range(0, permutation_index); + object->object.region_permutations[region_index]= available_permutation_indices[permutation_num]; + } + } + + return result; +} + +static short object_determine_variant_number( + long object_index, + struct model *model) +{ + short region_index; + + struct object_datum *object= object_get(object_index); + short result= 0; + + for (region_index=0; region_indexregions.count&& !result; region_index++) + { + struct model_region* region= TAG_BLOCK_GET_ELEMENT(&model->regions, region_index, struct model_region); + if (object->object.region_permutations[region_index] < region->permutations.count) + { + result= TAG_BLOCK_GET_ELEMENT( + ®ion->permutations, + object->object.region_permutations[region_index], + struct model_region_permutation + )->variant_number; + } + } + + return result; +} + +static void object_choose_random_region_permutations(long object_index) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (object_definition->object.model.index!=NONE) + { + struct model* model= model_definition_get(object_definition->object.model.index); + if (object->object.variant_number <= 0 || + !object_select_random_region_permutations_by_variant(object_index, model, object->object.variant_number)) + { + object_select_random_region_permutations_by_variant(object_index, model, NONE); + object->object.variant_number= object_determine_variant_number(object_index, model); + if (object->object.variant_number > 0) + { + object_select_random_region_permutations_by_variant(object_index, model, object->object.variant_number); + } + } + } + + return; +} + +static void object_add_to_list( + long *first_object_reference, + long object_index) +{ + struct object_datum *object= object_get(object_index); + object->object.next_object_index= *first_object_reference; + *first_object_reference= object_index; + + return; +} + +static void object_remove_from_list( + long *first_object_reference, + long object_index) +{ + while (*first_object_reference!=NONE) + { + struct object_datum *object= object_get(*first_object_reference); + + if (*first_object_reference==object_index) + { + *first_object_reference= object->object.next_object_index; + object->object.next_object_index= NONE; + break; + } + + first_object_reference= &object->object.next_object_index; + + match_assert("c:\\halo\\SOURCE\\objects\\objects.c", 3179, *first_object_reference!=NONE); + } + + return; +} + +static void attachments_delete( + long object_index) +{ + short attachment_index; + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + for (attachment_index=0; attachment_indexobject.attachments.count; ++attachment_index) + { + if (object->object.attachment_types[attachment_index]!=NONE && + object->object.attachment_indices[attachment_index]!=NONE) + { + switch (object->object.attachment_types[attachment_index]) + { + case _object_attachment_type_light: + light_delete(object->object.attachment_indices[attachment_index]); + break; + case _object_attachment_type_looping_sound: + game_looping_sound_delete(object->object.attachment_indices[attachment_index]); + break; + case _object_attachment_type_effect: + effect_delete(object->object.attachment_indices[attachment_index]); + break; + case _object_attachment_type_contrail: + object_compute_node_matrices(object_index); + contrail_owner_collision(object->object.attachment_indices[attachment_index], TRUE, 0.f); + break; + case _object_attachment_type_particle_system: + particle_system_orphan(object->object.attachment_indices[attachment_index]); + break; + default: + break; + } + } + } + + return; +} + +static void object_create_attachments( + long object_index) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + widgets_new(object_index); + attachments_new(object_index); + + return; +} + +static void object_delete_attachments( + long object_index) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + object_type_definition_get(object->object.type); + widgets_delete(object_index); + attachments_delete(object_index); + + return; +} + +static void object_delete_recursive( + long object_index, + boolean delete_siblings) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (TEST_FLAG(object->object.flags, _object_garbage_bit)) + { + object_set_garbage(object_index, FALSE); + } + + object_deleted_procs_call(object_index); + if (object->object.first_child_object_index!=NONE) + { + object_delete_recursive(object->object.first_child_object_index, TRUE); + } + + if (delete_siblings && object->object.next_object_index!=NONE) + { + object_delete_recursive(object->object.next_object_index, TRUE); + } + + object_deactivate(object_index); + object_delete_attachments(object_index); + + if (TEST_FLAG(object->object.flags, _object_connected_to_map_bit)) + { + object_disconnect_from_map(object_index); + } + + object_type_delete(object_index); + object_header_delete(object_header_data, object_index); + + return; +} + +static void object_compute_function_values( + long object_index) +{ + short function_index; + + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + real huh= (57 * DATUM_INDEX_TO_ABSOLUTE_INDEX(object_index) + game_time_get()) * 0.033333335f; + + for (function_index= 0; function_indexobject.functions.count; ++function_index) + { + real value; + real output; + + struct object_function_definition* function= TAG_BLOCK_GET_ELEMENT( + &object_definition->object.functions, + function_index, + struct object_function_definition); + boolean function_is_active= TRUE; + real period= function->runtime_one_over_period; + + if (function->scale_period_by_function_index) + { + real function_value= OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->scale_period_by_function_index); + if (function_value>0.f) + { + period= period/function_value; + } + } + + value= periodic_function_evaluate(function->function_type, huh*period); + + if (function->scale_function_by_function_index) + { + value*= OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->scale_function_by_function_index); + } + + if (TEST_FLAG(function->flags, _object_function_invert_function_bit)) + { + value= 1.f-value; + } + + if (function->wobble_magnitude!=0.f) + { + real val= periodic_function_evaluate(function->wobble_function_type, huh*function->wobble_period); + value+= (2.f*function->wobble_magnitude * (val-0.5f)); + } + + if (function->square_wave_threshold!=0.f) + { + value= value>function->square_wave_threshold ? 1.f : 0.f ; + } + + if (function->step_count>1) + { + real floor_value= floor(function->step_count*value); + value= floor_value*function->runtime_reciprocal_step_count; + } + + if (function->runtime_reciprocal_sawtooth_count>0.f) + { + value= fmod(value, function->runtime_reciprocal_sawtooth_count); + } + + if (function->add_function_index) + { + value+= OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->add_function_index); + value= MIN(value, 1.f); + } + + if (function->scale_result_by_function_index) + { + value*= OBJECT_INCOMING_FUNCTION_GET_VALUE(object, function->scale_result_by_function_index); + } + + output= transition_function_evaluate(function->map_result_to_transition_function, value); + + if (function->scale_by>0.f) + { + output*= function->scale_by; + } + + if (function->bounds_mode==_object_function_scale_to_fit_bounds) + { + output*= (function->upper_bound-function->lower_bound); + output+= function->lower_bound; + + if (function->lower_bound+_real_epsilon>=output) + { + function_is_active= TEST_FLAG(function->flags, _object_function_does_not_deactivate_below_lower_bound_bit); + } + } + else + { + if (function->lower_bound+_real_epsilon>=output) + { + output= function->lower_bound; + function_is_active= TEST_FLAG(function->flags, _object_function_does_not_deactivate_below_lower_bound_bit); + } + + if (output>function->upper_bound) + { + output= function->upper_bound; + } + + if (function->bounds_mode==_object_function_clip_to_bounds_and_normalize) + { + output= (output-function->lower_bound)*function->runtime_reciprocal_bounds_range; + } + } + + if (function->turn_off_with_function_index!=NONE && + !TEST_FLAG(object->object.functions_active_flags, function->turn_off_with_function_index)) + { + function_is_active= FALSE; + } + + if (TEST_FLAG(function->flags, _object_function_clip_to_bounds_and_normalize)) + { + output= fmod(output+object->object.outgoing_function_values[function_index], 1.f); + } + + object->object.outgoing_function_values[function_index]= output; + SET_FLAG(object->object.functions_active_flags, function_index, function_is_active); + } + + return; +} + +// TODO: match +static void object_compute_change_colors( + long object_index) +{ + struct object_datum *object= object_get(object_index); + struct object_definition *object_definition= object_definition_get(object->definition_index); + + if (TEST_FLAG(object_definition->object.runtime_flags, _object_runtime_scaled_change_colors_bit)) + { + long cc_index; + for (cc_index= 0; cc_indexobject.change_colors.count; cc_index++) + { + struct object_change_color_definition *change_color= TAG_BLOCK_GET_ELEMENT( + &object_definition->object.change_colors, + cc_index, + struct object_change_color_definition); + + if (change_color->scaled_by) + { + rgb_colors_interpolate( + &object->object.outgoing_change_colors[cc_index], + change_color->scale_flags, + &change_color->color_lower_bound, + &change_color->color_upper_bound, + object->object.incoming_function_values[change_color->scaled_by]); + } + + if (change_color->darken_by) + { + const real scale= object->object.incoming_function_values[change_color->scaled_by]; + object->object.outgoing_change_colors[cc_index].red*= scale; + object->object.outgoing_change_colors[cc_index].green*= scale; + object->object.outgoing_change_colors[cc_index].blue*= scale; + } + + object->object.outgoing_change_colors[cc_index].red= PIN( + object->object.outgoing_change_colors[cc_index].red, + 0.f, + 1.f); + object->object.outgoing_change_colors[cc_index].green= PIN( + object->object.outgoing_change_colors[cc_index].green, + 0.f, + 1.f); + object->object.outgoing_change_colors[cc_index].blue= PIN( + object->object.outgoing_change_colors[cc_index].blue, + 0.f, + 1.f); + } + } + + return; +} diff --git a/source/objects/objects.h b/source/objects/objects.h index 39fd29a9..7f59b684 100644 --- a/source/objects/objects.h +++ b/source/objects/objects.h @@ -8,16 +8,514 @@ file has inline function assertions. #define __OBJECTS_H #pragma once +/* ---------- headers */ + +#include "object_definitions.h" +#include "object_types.h" + +#include "math/real_math.h" +#include "memory/data.h" +#include "structures/cluster_partitions.h" + /* ---------- constants */ +enum +{ + OBJECT_ITERATOR_SIGNATURE= 0x86868686, + MAXIMUM_CLUSTERS_PER_OBJECT= 32, + OBJECT_MEMORY_POOL_SIZE= 0x100000, + GARBAGE_LIMIT_FREE_MEMORY_CRITICAL= 52428, + GARBAGE_LIMIT_FREE_MEMORY_TRIGGER= 104857, + GARBAGE_LIMIT_FREE_MEMORY_TARGET= 209715, + GARBAGE_LIMIT_FREE_OBJECTS_CRITICAL= 51, + GARBAGE_LIMIT_FREE_OBJECTS_TRIGGER= 102, + GARBAGE_LIMIT_FREE_OBJECTS_TARGET= 204, + GARBAGE_LIMIT_ACTIVE_GARBAGE_CRITICAL= 75, + GARBAGE_LIMIT_ACTIVE_GARBAGE_TRIGGER= 50, + GARBAGE_LIMIT_ACTIVE_GARBAGE_TARGET= 30, +}; + +enum +{ + MAXIMUM_MARKERS_PER_OBJECT= 64, + MAXIMUM_OBJECTS_PER_MAP= 2048, + MAXIMUM_RENDERED_OBJECTS= 256, +}; + +enum +{ + _object_header_active_bit= 0, + _object_header_visible_bit, + _object_header_being_created_bit, + _object_header_being_deleted_bit, + _object_header_do_not_update_bit, + _object_header_connected_to_map_bit, + _object_header_automatically_deactivate_bit, + _object_header_child_bit, + NUMBER_OF_OBJECT_HEADER_FLAGS, +}; + +enum +{ + _object_invisible_bit= 0, + _object_on_ground_bit, + _object_on_media_bit, + _object_partially_under_media_bit, + _object_wholly_under_media_bit, + _object_at_rest_bit, + _object_child_locations_invalid_bit, + _object_animates_automatically_bit, + _object_has_attached_lights_bit, + _object_has_attached_shader_bit, + _object_has_attached_looping_sounds_bit, + _object_connected_to_map_bit, + _object_mirrored_bit, + _object_dynamic_lighting_recompute_bit, + _object_static_lighting_recompute_bit, + _object_static_lighting_raycast_sideways_bit, + _object_garbage_bit, + _object_cannot_be_garbage_bit, + _object_shadowless_bit, + _object_deleted_when_deactivated_bit, + _object_cannot_be_activated_bit, + _object_outside_of_map_bit, + _object_movie_star_bit, + _object_do_not_recompute_node_matrices_bit, + _object_no_collisions_bit, + _object_has_collision_model_bit, + _object_force_baseline_update_bit, + _object_has_been_updated_from_network_bit, + NUMBER_OF_OBJECT_DATA_FLAGS, +}; + +enum +{ + _new_object_mirrored_bit= 0, + _new_object_never_automatically_delete_bit, + NUMBER_OF_NEW_OBJECT_DATA_FLAGS, +}; + + +enum +{ + _object_passed_body_damage_threshold_bit= 0, + _object_passed_shield_damage_threshold_bit, + _object_dead_bit, + _object_shield_depleted_bit, + _object_shield_over_charging_bit, + _object_die_act_of_god_bit, + _object_die_act_of_god_silent_bit, + _object_melee_attack_inhibited_bit, + _object_ranged_attack_inhibited_bit, + _object_walking_inhibited_bit, + _object_cannot_hold_weapon_bit, + _object_cannot_take_damage_bit, + _object_shield_charging_bit, + _object_die_act_of_god_no_statistics_bit, + NUMBER_OF_OBJECT_DAMAGE_FLAGS, +}; + +enum +{ + _object_attachment_type_light= 0, + _object_attachment_type_looping_sound, + _object_attachment_type_effect, + _object_attachment_type_contrail, + _object_attachment_type_particle_system, + NUMBER_OF_OBJECT_ATTACHMENT_TYPES, +}; + +enum +{ + _object_function_reference_none= 0, + _object_function_reference_a, + _object_function_reference_b, + _object_function_reference_c, + _object_function_reference_d, + NUMBER_OF_OBJECT_FUNCTION_REFERENCES, +}; + +enum +{ + _object_function_none= 0, + _object_function_body_vitality, + _object_function_shield_vitality, + _object_function_recent_body_damage, + _object_function_recent_shield_damage, + _object_function_random_constant, + _object_function_umbrella_shield_vitality, + _object_function_shield_stun, + _object_function_recent_umbrella_shield_vitality, + _object_function_umbrella_shield_stun, + _object_function_first_region_damage, + _object_function_last_region_damage= 17, + _object_function_alive, + _object_function_compass, + NUMBER_OF_OBJECT_FUNCTION_MODES, +}; + +enum +{ + _object_change_color_a= 0, + _object_change_color_b, + _object_change_color_c, + _object_change_color_d, + NUMBER_OF_OBJECT_CHANGE_COLORS, +}; + +enum +{ + _pvs_activation_normal= 0, + _pvs_activation_object, + _pvs_activation_cluster, + NUMBER_OF_OBJECT_PVS_ACTIVATION_TYPES, +}; + +enum +{ + _garbage_collect_everything= 0, + _garbage_collect_active_objects, + _garbage_collect_for_space, + NUMBER_OF_GARBAGE_COLLECTION_MODES, +}; + + /* ---------- macros */ +#define object_header_get(index) ((struct object_header_datum*)datum_get(object_header_data, (index))) +#define object_header_try_and_get(index) ((struct object_header_datum*)datum_try_and_get(object_header_data, (index))) + +#define object_get(index) ((struct object_datum*)object_get_and_verify_type(index, _object_mask_all)) +#define object_try_and_get(index) ((struct object_datum*)object_try_and_get_and_verify_type(index, _object_mask_all)) + /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +typedef void (*object_deleted_proc)(long); + + +struct object_cluster_iterator +{ + struct cluster_partition *cluster_partition; + long reference_index; +}; + +struct object_header_datum +{ + short identifier; + byte flags; + byte type; + short cluster_index; + short data_size; + struct object_datum *datum; +}; + +struct location +{ + long leaf_index; + short cluster_index; + word bonus; +}; + +struct animation_state +{ + short index; + short frame_index; +}; + +struct object_animation_state +{ + long animation_graph_index; + struct animation_state state; + short interpolation_frame_index; + short interpolation_frame_count; +}; + +struct object_header_block_reference +{ + short size; + short offset; +}; + +struct _object_datum +{ + unsigned long flags; + long magic_number; + real_point3d position; + real_vector3d translational_velocity; + real_vector3d forward; + real_vector3d up; + real_vector3d angular_velocity; + struct location location; + real_point3d bounding_sphere_center; + real bounding_sphere_radius; + real scale; + short type; + word render_flags; + short owner_team_index; + short name_index; + short idle_ticks; + short variant_number; + long owner_player_index; + long owner_object_index; + long owner_object_definition_index; + struct object_animation_state animation; + real maximum_body_vitality; + real maximum_shield_vitality; + real body_vitality; + real shield_vitality; + real current_shield_damage; + real current_body_damage; + long umbrella_shield_object_index; + real recent_shield_damage; + real recent_body_damage; + long shield_damage_decay_timer; + long body_damage_decay_timer; + short shield_stun_ticks; + word damage_flags; + long scenery_idx; + long first_cluster_reference_index; + long next_garbage_object_index; + long next_object_index; + long first_child_object_index; + long parent_object_index; + char parent_node_index; + byte pad[1]; + boolean force_shield_update; + byte functions_active_flags; + real incoming_function_values[NUMBER_OF_INCOMING_OBJECT_FUNCTIONS]; + real outgoing_function_values[NUMBER_OF_OUTGOING_OBJECT_FUNCTIONS]; + char attachment_types[MAXIMUM_NUMBER_OF_ATTACHMENTS_PER_OBJECT]; + long attachment_indices[MAXIMUM_NUMBER_OF_ATTACHMENTS_PER_OBJECT]; + long first_widget_index; + long cached_render_state_index; + word regions_destroyed_flags; + short forced_shader_permutation_index; + byte region_damage[MAXIMUM_REGIONS_PER_OBJECT]; + byte region_permutations[MAXIMUM_REGIONS_PER_OBJECT]; + real_rgb_color base_change_colors[NUMBER_OF_OBJECT_CHANGE_COLORS]; + real_rgb_color outgoing_change_colors[NUMBER_OF_OBJECT_CHANGE_COLORS]; + struct object_header_block_reference original_node_orientations; + struct object_header_block_reference node_orientations; + struct object_header_block_reference node_matrices; +}; + +struct object_datum +{ + long definition_index; + struct _object_datum object; +}; + +struct object_iterator +{ + unsigned long type_flags; + byte flags; + short absolute_index; + long index; + unsigned long signature; +}; + +struct objects_information +{ + short object_count; + short active_object_count; + real used_memory; +}; + +struct object_marker +{ + short node_index; + real_matrix4x3 node_matrix; + real_matrix4x3 matrix; +}; + +struct object_placement_data +{ + long definition_index; + unsigned long flags; + long owner_player_index; + long owner_object_index; + long owner_object_definition_index; + short owner_team_index; + short variant_number; + real_point3d position; + real height; + real_vector3d translational_velocity; + real_vector3d forward; + real_vector3d up; + real_vector3d angular_velocity; + real_rgb_color change_colors[NUMBER_OF_OBJECT_CHANGE_COLORS]; +}; + +/* ---------- prototypes/OBJECTS.C */ + +long cluster_get_first_noncollideable_object(long *reference_index, short cluster_index); +long cluster_get_next_noncollideable_object(long *reference_index); +long cluster_get_first_collideable_object(long *reference_index, short cluster_index); +long cluster_get_next_collideable_object(long *reference_index); +short object_get_next_cluster(struct object_cluster_iterator *iterator); +void *object_try_and_get_and_verify_type(long object_index, unsigned long valid_type_flags); +void *object_get_and_verify_type(long object_index, unsigned long valid_type_flags); +void object_iterator_new(struct object_iterator *iterator, unsigned long type_flags, byte flags); +void *object_iterator_next(struct object_iterator *iterator); +long object_get_ultimate_parent(long object_index); +void object_add_scenario_permutation(long object_index, struct scenario_object_permutation *permutation); +void object_set_object_index_for_name_index(short name_index, long object_index); +void objects_fix_for_deleted_object(long deleted_object_index); +void object_set_garbage(long object_index, boolean garbage); +void garbage_collect_now(void); +void objects_information_get(struct objects_information *information); +void object_pvs_set_object(long object_index); +void object_pvs_set_camera_point(short camera_point_index); +void object_pvs_clear(void); +short objects_get_activating_cluster_index(void); +void object_definition_predict(long definition_index); +void object_predict(long object_index); +void object_beautify(long object_index, boolean beautiful); +void *object_header_block_get(long object_index, struct object_header_block_reference *reference); +boolean object_header_block_allocate(long object_index, short block_reference_offset, short size); +void object_scripting_set_collideable(long object_index, boolean collideable); +void object_marker_begin(void); +void object_marker_end(void); +boolean object_unmarked_function(long object_index); +boolean object_mark_function(long object_index); +void objects_place(void); +long find_objects_from_point_vector( + real_point3d const *position, + real_vector3d const *direction, + boolean(*add_object_function)(long, void *), + void *custom_data, + long maximum_object_count, + long *object_indices); +void objects_dump_memory(void); +void objects_initialize(void); +void objects_initialize_for_new_map(void); +void objects_dispose_from_old_map(void); +void objects_dispose(void); +void object_activate(long object_index); +void object_deactivate(long object_index); +void object_reset(long object_index); +void object_placement_data_new(struct object_placement_data *data, long definition_index, long owner_object_index); +void object_disconnect_from_map(long object_index); +short object_get_first_cluster(struct object_cluster_iterator *iterator, long object_index); +real_matrix4x3 *object_get_node_matrices(long object_index); +char const *object_get_attachment_marker_name(long object_index, short attachment_index); +boolean object_has_node(long object_index, short node_index); +void object_set_automatic_deactivation(long object_index, boolean automatic_deactivation); +void object_set_visibility(long object_index, boolean visible_flag); +void object_get_velocities(long object_index, real_vector3d *translational_velocity, real_vector3d *angular_velocity); +struct location *object_get_location(long object_index, struct location *location); +void object_start_interpolation(long object_index, short frame_count); +void object_offset_interpolation(long object_index, real_vector3d *offset); +void object_permute_region(long object_index, char *permutation_name, short desired_region_index, boolean active_flag); +boolean object_get_function_value(long object_index, short function_index, real *value_reference); +short objects_in_clusters_by_indices(unsigned long class_flags, short cluster_count, short const *cluster_indices, short maximum_object_count, long *object_indices); +long object_index_from_name_index(short name_index); +void objects_disconnect_from_structure_bsp(void); +boolean object_visible_to_any_player(long object_index); +void object_pvs_activate(long object_index); +void objects_scripting_set_scale(long object_index, real scale, short interpolation_frame_count); +void object_delete(long object_index); +void object_reconnect_to_map(long object_index, struct location const *location); +real_matrix4x3 *object_get_node_matrix(long object_index, short node_index); +short object_get_marker_by_name(long object_index, char const *name, struct object_marker *markers, short maximum_marker_count); +void object_align_marker_to_matrix(struct object_datum *object, struct object_marker const *child_marker, real_matrix4x3 const *destination_matrix); +void object_detach(long child_object_index); +real_point3d *object_get_origin(long object_index, real_point3d *origin); +void object_get_orientation(long object_index, real_vector3d *forward, real_vector3d *up); +real_matrix4x3 *object_get_world_matrix(long object_index, real_matrix4x3 *matrix); +void object_inverse_kinematics(long hand_object_index, char *hand_marker_name, long grip_object_index, char *grip_marker_name, real_matrix4x3 *node_matrices); +short objects_in_sphere(unsigned long class_flags, unsigned long type_flags, struct location const *location, real_point3d const *center, real radius, long *object_indices, short maximum_count); +void objects_reconnect_to_structure_bsp(void); +void objects_paparazzi(void); +void object_export_function_values(long object_index); +void object_compute_node_matrices(long object_index); +void objects_scripting_detach(long parent_object_index, long child_object_index); +void object_render_debug(long object_index); +void object_set_position(long object_index, real_point3d const *position, real_vector3d const *forward, real_vector3d const *up); +void object_translate(long object_index, real_point3d const *new_position, struct location const *new_location); +long object_new(struct object_placement_data *data); +void object_attach_to_node(long parent_object_index, long child_object_index, short parent_node_index); +boolean object_force_inside_bsp(long object_index, real_point3d const *known_good_point); +boolean object_update(long object_index); +void object_compute_node_matrices_recursive(long object_index); +long object_new_from_scenario(struct scenario_object_datum *scenario_object, struct tag_block *palette); +void object_attach_to_marker(long parent_object_index, char const *parent_marker_name, long child_object_index, char const *child_marker_name); +long object_new_by_name(short name_index); +void objects_scripting_attach(long parent_object_index, char const *parent_marker_name, long child_object_index, char const *child_marker_name); +void object_delete_immediately(long object_index); +void objects_garbage_collection(void); +void objects_update(void); +void objects_memory_compact(void); + + +/* ---------- prototypes/OBJECT_DELETED_PROCS.C */ + +void object_deleted_procs_call(long deleted_object_index); /* ---------- globals */ +/* comm */ +boolean debug_objects_names; +boolean debug_objects_pathfinding_spheres; +boolean debug_objects_physics; +boolean debug_objects_root_node; + +/* comm */ +long global_object_marker; + +/* comm */ +struct cluster_partition noncollideable_object_cluster_partition; +struct cluster_partition collideable_object_cluster_partition; + +/* comm */ +boolean debug_object_garbage_collection; + +/* comm */ +struct data_array *object_header_data; + +extern boolean debug_objects_position_velocity; +extern boolean debug_objects_bounding_spheres; +extern boolean debug_objects_collision_models; + /* ---------- public code */ +__inline short object_get_type( + long object_index) +{ + return object_header_get(object_index)->type; +} + +__inline void object_get_bounding_sphere( + long object_index, + real_point3d *center, + real *radius) +{ + struct object_datum *object= object_get(object_index); + + match_assert("..\\objects\\objects.h", 535, center); + match_assert("..\\objects\\objects.h", 536, radius); + + *center= object->object.bounding_sphere_center; + *radius= object->object.bounding_sphere_radius; + + return; +} + +__inline void object_get_render_bounding_sphere( + long object_index, + real_point3d *center, + real *radius) +{ + struct object_datum *object= object_get(object_index); + + match_assert("..\\objects\\objects.h", 551, center); + match_assert("..\\objects\\objects.h", 552, radius); + + *center= object->object.bounding_sphere_center; + *radius= object_definition_get(object->definition_index)->object.render_bounding_radius; + + return; +} + + #endif // __OBJECTS_H diff --git a/source/objects/widgets/widgets.h b/source/objects/widgets/widgets.h index 83d1f80e..83c53148 100644 --- a/source/objects/widgets/widgets.h +++ b/source/objects/widgets/widgets.h @@ -14,7 +14,14 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/WIDGETS.C */ + +void widgets_initialize(void); +void widgets_initialize_for_new_map(void); +void widgets_dispose_from_old_map(void); +void widgets_dispose(void); +void widgets_new(long object_index); +void widgets_delete(long object_index); /* ---------- globals */ diff --git a/source/physics/bsp2d.h b/source/physics/bsp2d.h index a7cc0ab8..86209260 100644 --- a/source/physics/bsp2d.h +++ b/source/physics/bsp2d.h @@ -8,12 +8,21 @@ header included in hcex build. #define __BSP2D_H #pragma once +/* ---------- headers */ + +#include "tag_files/tag_groups.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ +struct bsp2d +{ + struct tag_block nodes; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/physics/bsp3d.h b/source/physics/bsp3d.h index c71e3558..178764a9 100644 --- a/source/physics/bsp3d.h +++ b/source/physics/bsp3d.h @@ -8,13 +8,26 @@ header included in hcex build. #define __BSP3D_H #pragma once + +/* ---------- headers */ + +#include "tag_files/tag_groups.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct bsp3d +{ + struct tag_block nodes; + struct tag_block planes; +}; + +/* ---------- prototypes/BSP3D.C */ + +long bsp3d_test_point(struct bsp3d const *bsp, long node_index, union real_point3d const *point); /* ---------- globals */ diff --git a/source/physics/collision_bsp.h b/source/physics/collision_bsp.h index 0eee375b..d1f10835 100644 --- a/source/physics/collision_bsp.h +++ b/source/physics/collision_bsp.h @@ -14,7 +14,27 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct collision_bsp_test_sphere_result +{ + long surface_count; + long surface_indices[256]; + long edge_count; + long edge_indices[256]; + long vertex_count; + long vertex_indices[256]; + long leaf_count; + long leaf_indices[256]; +}; + +/* ---------- prototypes/COLLISION_BSP.C */ + +boolean collision_bsp_test_sphere( + struct collision_bsp const *bsp, + short breakable_surface_count, + byte const *breakable_surface_flags, + union real_point3d const *center, + real radius, + struct collision_bsp_test_sphere_result *result); /* ---------- globals */ diff --git a/source/physics/collision_bsp_definitions.h b/source/physics/collision_bsp_definitions.h index b723a745..5f5cb215 100644 --- a/source/physics/collision_bsp_definitions.h +++ b/source/physics/collision_bsp_definitions.h @@ -8,12 +8,29 @@ header included in hcex build. #define __COLLISION_BSP_DEFINITIONS_H #pragma once + +/* ---------- headers */ + +#include "bsp2d.h" +#include "bsp3d.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ +struct collision_bsp +{ + struct bsp3d bsp3d; + struct tag_block leaves; + struct tag_block bsp2d_references; + struct bsp2d bsp2d; + struct tag_block surfaces; + struct tag_block edges; + struct tag_block vertices; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/physics/collision_model_definitions.h b/source/physics/collision_model_definitions.h index 6628ea0a..028f996c 100644 --- a/source/physics/collision_model_definitions.h +++ b/source/physics/collision_model_definitions.h @@ -8,13 +8,41 @@ header included in hcex build. #define __COLLISION_MODEL_DEFINITIONS_H #pragma once +/* ---------- headers */ + +#include "math/real_math.h" +#include "objects/damage_resistances.h" +#include "tag_files/tag_groups.h" + /* ---------- constants */ +// Couldn't find tag constants for this definition? + /* ---------- macros */ +#define collision_model_definition_get(index) ((struct collision_model *)tag_get('coll', index)) + /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct pathfinding_sphere +{ + short node_index; + word pad; + long unused[3]; + real_point3d center; + real radius; +}; + +struct collision_model +{ + struct damage_resistance resistance; + long unused[4]; + real_rectangle3d pathfinding_box; + struct tag_block pathfinding_spheres; // pathfinding_sphere + struct tag_block nodes; +}; + +/* ---------- prototypes/COLLISION_MODEL_DEFINITIONS.C */ /* ---------- globals */ diff --git a/source/physics/collision_models.h b/source/physics/collision_models.h index 660b5d0a..5b0baf27 100644 --- a/source/physics/collision_models.h +++ b/source/physics/collision_models.h @@ -14,7 +14,19 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct collision_model_instance +{ + long object_index; + const struct collision_model *model; + const byte *region_permutation_indices; + const struct real_matrix4x3 *matrices; +}; + +/* ---------- prototypes/COLLISION_MODELS.C */ + +boolean collision_model_instance_new(struct collision_model_instance *instance, long object_index); + +void render_debug_collision_model(struct collision_model_instance *instance); /* ---------- globals */ diff --git a/source/physics/collision_usage.h b/source/physics/collision_usage.h index d92fe119..18343078 100644 --- a/source/physics/collision_usage.h +++ b/source/physics/collision_usage.h @@ -10,6 +10,11 @@ header included in hcex build. /* ---------- constants */ +enum +{ + MAXIMUM_COLLISION_USER_STACK_DEPTH= 32, +}; + /* ---------- macros */ /* ---------- structures */ @@ -18,6 +23,9 @@ header included in hcex build. /* ---------- globals */ +extern short global_current_collision_user_depth; +extern short global_current_collision_users[MAXIMUM_COLLISION_USER_STACK_DEPTH]; + /* ---------- public code */ #endif // __COLLISION_USAGE_H diff --git a/source/physics/collisions.h b/source/physics/collisions.h index 19ef1357..ff42a138 100644 --- a/source/physics/collisions.h +++ b/source/physics/collisions.h @@ -8,16 +8,109 @@ header included in hcex build. #define __COLLISIONS_H #pragma once +/* ---------- headers */ + +#include "objects.h" + /* ---------- constants */ +enum +{ + _collision_test_front_facing_surfaces_bit= 0, + _collision_test_back_facing_surfaces_bit, + _collision_test_ignore_two_sided_surfaces_bit, + _collision_test_ignore_invisible_surfaces_bit, + _collision_test_ignore_breakable_surfaces_bit, + _collision_test_structure_bit, + _collision_test_media_bit, + _collision_test_objects_bit, + + _collision_test_objects_first_type_bit, + _collision_test_objects_bipeds_bit= _collision_test_objects_first_type_bit, + _collision_test_objects_vehicles_bit, + _collision_test_objects_weapons_bit, + _collision_test_objects_equipment_bit, + _collision_test_objects_garbage_bit, + _collision_test_objects_projectiles_bit, + _collision_test_objects_scenery_bit, + _collision_test_objects_machines_bit, + _collision_test_objects_controls_bit, + _collision_test_objects_light_fixtures_bit, + _collision_test_objects_placeholders_bit, + _collision_test_objects_last_type_bit, + + _collision_test_try_to_keep_location_valid_bit, + _collision_test_skip_passthrough_bipeds_bit, + _collision_test_use_vehicle_physics_bit, + + NUMBER_OF_COLLISION_TEST_FLAGS, + + _collision_test_objects_sight_blocking_flags= + FLAG(_collision_test_objects_vehicles_bit) | + FLAG(_collision_test_objects_scenery_bit) | + FLAG(_collision_test_objects_machines_bit), + + _collision_test_objects_all_types_flags= + FLAG(_collision_test_objects_last_type_bit+1)-FLAG(_collision_test_objects_first_type_bit), + + _collision_test_environment_flags= + FLAG(_collision_test_front_facing_surfaces_bit) | + FLAG(_collision_test_structure_bit) | + FLAG(_collision_test_media_bit), + + _collision_test_for_projectiles_flags= 0x1000E9, + _collision_test_for_projectiles_fat_flags= 0x89, + _collision_test_for_line_of_sight_flags= 0xC2AD, + _collision_test_for_bipeds_living_flags= 0x20C3A0, + _collision_test_for_bipeds_passthrough_living_flags= 0xC2A0, + _collision_test_for_bipeds_dead_flags= 0xC0A0, + _collision_test_for_vehicles_flags= 0xC0A0, +}; + /* ---------- macros */ /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct collision_result +{ + short type; + struct location start_location; + struct location location; + real t; + real_point3d point; + real_plane3d plane; + short material_type; + long object_index; + short region_index; + short node_index; + short bsp_index; + long surface_index; + long plane_designator; + byte flags; + byte breakable_surface_index; + short material_index; +}; + +/* ---------- prototypes/COLLISIONS.C */ + +boolean collision_test_vector(unsigned long flags, real_point3d const *point, real_vector3d const *vector, long ignore_object_index, struct collision_result *collision); /* ---------- globals */ /* ---------- public code */ +__inline boolean collision_test_line( + unsigned long flags, + real_point3d const *point0, + real_point3d const *point1, + long ignore_object_index, + struct collision_result *collision) +{ + real_vector3d vector; + + vector_from_points3d(point0, point1, &vector); + return collision_test_vector(flags, point0, &vector, ignore_object_index, collision); +} + + #endif // __COLLISIONS_H diff --git a/source/physics/physics.h b/source/physics/physics.h index 9fd2fcd2..196413db 100644 --- a/source/physics/physics.h +++ b/source/physics/physics.h @@ -8,13 +8,29 @@ header included in hcex build. #define __PHYSICS_H #pragma once +/* ---------- headers */ + +#include "math/real_math.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct physics_instance +{ + long object_index; + const struct physics_definition *physics; + real_matrix4x3 world_matrix; +}; + +/* ---------- prototypes/PHYSICS.C */ + +boolean physics_instance_new(struct physics_instance *instance, long object_index); + +void render_debug_physics(struct physics_instance *instance); + /* ---------- globals */ diff --git a/source/rasterizer/rasterizer_geometry.c b/source/rasterizer/rasterizer_geometry.c index 9298636a..74aa1e3b 100644 --- a/source/rasterizer/rasterizer_geometry.c +++ b/source/rasterizer/rasterizer_geometry.c @@ -94,6 +94,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "rasterizer_geometry.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/rasterizer/rasterizer_geometry.h b/source/rasterizer/rasterizer_geometry.h index d63c94fc..e33e775f 100644 --- a/source/rasterizer/rasterizer_geometry.h +++ b/source/rasterizer/rasterizer_geometry.h @@ -10,10 +10,43 @@ header included in hcex build. /* ---------- constants */ +enum +{ + _rasterizer_vertex_type_environment_uncompressed= 0, + _rasterizer_vertex_type_environment_compressed, + _rasterizer_vertex_type_environment_lightmap_uncompressed, + _rasterizer_vertex_type_environment_lightmap_compressed, + _rasterizer_vertex_type_model_uncompressed, + _rasterizer_vertex_type_model_compressed, + _rasterizer_vertex_type_dynamic_unlit, + _rasterizer_vertex_type_dynamic_lit, + _rasterizer_vertex_type_dynamic_screen, + _rasterizer_vertex_type_debug, + _rasterizer_vertex_type_decal, + _rasterizer_vertex_type_detail_object, + _rasterizer_vertex_type_environment_uncompressed_ff, + _rasterizer_vertex_type_environment_lightmap_uncompressed_ff, + _rasterizer_vertex_type_model_uncompressed_ff, + _rasterizer_vertex_type_model_processed, + _rasterizer_vertex_type_unlit_zsprite, + _rasterizer_vertex_type_widget, + NUMBER_OF_RASTERIZER_VERTEX_TYPES, +}; + /* ---------- macros */ /* ---------- structures */ +struct vertex_buffer +{ + short type; + word pad; + long count; + long offset; + void *base_address; + void *hardware_format; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/render/render.h b/source/render/render.h index 667a8cde..925e426b 100644 --- a/source/render/render.h +++ b/source/render/render.h @@ -33,6 +33,27 @@ enum /* ---------- structures */ +struct render_distant_light +{ + real_rgb_color color; + real_vector3d direction; +}; + +struct render_lighting +{ + real_rgb_color ambient_color; + short distant_light_count; + word pad; + struct render_distant_light distant_lights[MAXIMUM_RENDERED_DISTANT_LIGHTS]; + short point_light_count; + word pad1; + long point_light_indices[MAXIMUM_RENDERED_POINT_LIGHTS]; + real_argb_color reflection_tint_color; + real_vector3d shadow_vector; + real_rgb_color shadow_color; +}; + + struct rendered_cluster { short cluster_index; diff --git a/source/render/render_debug.h b/source/render/render_debug.h index 75163469..362dcb93 100644 --- a/source/render/render_debug.h +++ b/source/render/render_debug.h @@ -14,7 +14,17 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +/* ---------- prototypes/RENDER_DEBUG.C */ + +void render_debug_string_at_point(boolean immediate, real_point3d *point, const char *string, real_argb_color const *color); + +void render_debug_line(boolean immediate, real_point3d const *point0, real_point3d const *point1, real_argb_color const *color); + +void render_debug_vector(boolean immediate, real_point3d const *point, real_vector3d const *vector, real size, real_argb_color const *color); + +void render_debug_matrix(boolean immediate, const struct real_matrix4x3 *matrix, real size); + +void render_debug_sphere(boolean, real_point3d const *center, real radius, real_argb_color const *color); /* ---------- globals */ diff --git a/source/scenario/scenario.c b/source/scenario/scenario.c index cd4ee9a9..47dbd99d 100644 --- a/source/scenario/scenario.c +++ b/source/scenario/scenario.c @@ -161,6 +161,11 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "scenario.h" + +#include "physics/bsp3d.h" + /* ---------- constants */ /* ---------- macros */ @@ -173,4 +178,12 @@ symbols in this file: /* ---------- public code */ +long scenario_leaf_index_from_point( + const union real_point3d *point) +{ + match_assert("c:\\halo\\SOURCE\\scenario\\scenario.c", 213, global_bsp3d); + + return bsp3d_test_point(global_bsp3d, 0, point); +} + /* ---------- private code */ diff --git a/source/scenario/scenario.h b/source/scenario/scenario.h index d6365676..78422218 100644 --- a/source/scenario/scenario.h +++ b/source/scenario/scenario.h @@ -8,8 +8,46 @@ header included in hcex build. #define __SCENARIO_H #pragma once + +/* ---------- headers */ + +#include "real_math.h" + /* ---------- constants */ +enum +{ + MAXIMUM_SCENARIO_PLAYERS_PER_BLOCK= 0x100, + MAXIMUM_TRIGGER_VOLUMES_PER_SCENARIO= 0x100, + MAXIMUM_FUNCTIONS_PER_SCENARIO= 0x20, + MAXIMUM_OBJECT_NAMES_PER_SCENARIO= 0x200, + MAXIMUM_DEVICE_GROUPS_PER_SCENARIO= 0x80, + MAXIMUM_SCENARIO_OBJECT_PALETTE_ENTRIES_PER_BLOCK= 0x64, + MAXIMUM_CUTSCENE_FLAGS_PER_SCENARIO= 0x200, + MAXIMUM_CUTSCENE_CAMERA_POINTS_PER_SCENARIO= 0x200, + MAXIMUM_CUTSCENE_TITLES_PER_SCENARIO= 0x40, + MAXIMUM_SCENARIO_NETGAME_FLAGS_PER_SCENARIO= 0xC8, + MAXIMUM_SCENARIO_NETGAME_EQUIPMENT_PER_SCENARIO= 0xC8, + MAXIMUM_SCENARIO_STARTING_EQUIPMDNG_PER_SCENARIO= 0xC8, + MAXIMUM_STRUCTURE_BSPS_PER_SCENARIO= 0x10, + MAXIMUM_CHILD_SCENARIOS_PER_SCENARIO= 0x10, + MAXIMUM_SKIES_PER_SCENARIO= 0x8, + MAXIMUM_DECALS_PER_SCENARIO= 0x10000, + MAXIMUM_DECAL_PALETTES_PER_SCENARIO= 0x80, + MAXIMUM_SCENERY_DATUMS_PER_SCENARIO= 0x7D0, + MAXIMUM_SOUND_SCENERY_DATUMS_PER_SCENARIO= 0x100, + MAXIMUM_WEAPON_DATUMS_PER_SCENARIO= 0x80, + MAXIMUM_EQUIPMENT_DATUMS_PER_SCENARIO= 0x100, + MAXIMUM_BIPED_DATUMS_PER_SCENARIO= 0x80, + MAXIMUM_VEHICLE_DATUMS_PER_SCENARIO= 0x50, + MAXIMUM_MACHINE_DATUMS_PER_SCENARIO= 0x190, + MAXIMUM_CONTROL_DATUMS_PER_SCENARIO= 0x64, + MAXIMUM_LIGHT_FIXTURE_DATUMS_PER_SCENARIO= 0x1F4, + MAXIMUM_EDITOR_SCENARIO_DATA_SIZE= 0x10000, + MAXIMUM_EDITOR_COMMENTS= 0x400, + MAXIMUM_EDITOR_COMMENT_LENGTH= 0x4000, +}; + /* ---------- macros */ /* ---------- structures */ @@ -65,6 +103,12 @@ void scenario_get_atmospheric_fog(short local_player_index, short sky_index, rea extern long global_scenario_index; extern short global_structure_bsp_index; +/* comm */ +struct scenario *global_scenario; + +/* comm */ +struct bsp3d *global_bsp3d; + /* ---------- public code */ #endif // __SCENARIO_H diff --git a/source/scenario/scenario_definitions.h b/source/scenario/scenario_definitions.h index c82662f4..079e018f 100644 --- a/source/scenario/scenario_definitions.h +++ b/source/scenario/scenario_definitions.h @@ -8,12 +8,32 @@ header included in hcex build. #define __SCENARIO_DEFINITIONS_H #pragma once +/* ---------- headers */ + +#include "tag_files/tag_files.h" +#include "tag_files/tag_groups.h" + /* ---------- constants */ +enum +{ + _scenario_object_placement_not_automatic_bit= 0, + _scenario_object_placement_not_on_easy_bit, + _scenario_object_placement_not_on_normal_bit, + _scenario_object_placement_not_on_hard_bit, + NUMBER_OF_SCENARIO_OBJECT_LOCATION_PLACEMENT_FLAGS, +}; + /* ---------- macros */ /* ---------- structures */ +struct scenario_object_palette_entry +{ + struct tag_reference reference; + unsigned long unused[8]; +}; + struct scenario_object_datum { short palette_entry_index; @@ -32,6 +52,98 @@ struct scenario_placeholder_datum struct scenario_object_datum object; }; +struct scenario_object_name +{ + char name[TAG_STRING_LENGTH+1]; + short runtime_object_type; + short runtime_scenario_datum_index; +}; + +struct scenario_cutscene_camera_point +{ + long flags; + char name[TAG_STRING_LENGTH+1]; + long pad; + real_point3d position; + real_euler_angles3d orientation; + real field_of_view; + long unused[9]; +}; + +struct scenario +{ + struct tag_reference ugly_structure_bsp; + struct tag_reference unloved_globals; + struct tag_reference bad_sky; + struct tag_block sky_references; + short type; + word flags; + struct tag_block scenario_references; + real local_north; + unsigned long header_unused[5]; + long reference_unused[34]; + struct tag_block predicted_ui_resources; + struct tag_block functions; + struct tag_data editor_scenario_data; + struct tag_block comments; + long user_edit_unused[56]; + struct tag_block object_names; // scenario_object_name + struct tag_block scenery; + struct tag_block scenery_palette; + struct tag_block bipeds; + struct tag_block biped_palette; + struct tag_block vehicles; + struct tag_block vehicle_palette; + struct tag_block equipment; + struct tag_block equipment_palette; + struct tag_block weapons; + struct tag_block weapon_palette; + struct tag_block device_groups; + struct tag_block machines; + struct tag_block machine_palette; + struct tag_block controls; + struct tag_block control_palette; + struct tag_block light_fixtures; + struct tag_block light_fixtures_palette; + struct tag_block sound_scenery; + struct tag_block sound_scenery_palette; + struct tag_block unused_blocks[7]; + struct tag_block starting_profiles; + struct tag_block players; + struct tag_block trigger_volumes; + struct tag_block recorded_animations; + struct tag_block netgame_flags; + struct tag_block netgame_equipment; + struct tag_block scenario_starting_equipment; + struct tag_block bsp_switch_trigger_volumes; + struct tag_block decals; + struct tag_block decal_palette; + struct tag_block detail_object_collection_palette; + long render_unused[21]; + struct tag_block ai_actor_palette; + struct tag_block ai_encounters; + struct tag_block ai_command_lists; + struct tag_block ai_animation_references; + struct tag_block ai_script_references; + struct tag_block ai_recording_references; + struct tag_block ai_conversations; + struct tag_data hs_syntax_data; + struct tag_data hs_string_constants; + struct tag_block hs_scripts; + struct tag_block hs_globals; + struct tag_block hs_references; + struct tag_block hs_source_files; + long scripting_unused[6]; + struct tag_block cutscene_flags; + struct tag_block cutscene_camera_points; // scenario_cutscene_camera_point + struct tag_block cutscene_chapter_titles; + long rapidly_dwindling_unused_space[27]; + struct tag_reference custom_object_names; + struct tag_reference ingame_help_text; + struct tag_reference hud_messages; + struct tag_block structure_bsp_references; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/sound/game_sound.h b/source/sound/game_sound.h index 738b54c4..f1c1109b 100644 --- a/source/sound/game_sound.h +++ b/source/sound/game_sound.h @@ -18,6 +18,8 @@ header included in hcex build. void game_sound_clear(void); void game_sound_restore(void); +long game_looping_sound_new(long object_index, long definition_index, char const *marker_name, short function_index); +void game_looping_sound_delete(long looping_sound_index); /* ---------- globals */ diff --git a/source/sound/sound_definitions.h b/source/sound/sound_definitions.h index 24f4dbcd..8f6cfb05 100644 --- a/source/sound/sound_definitions.h +++ b/source/sound/sound_definitions.h @@ -10,6 +10,15 @@ file has inline function assertions. /* ---------- constants */ +enum +{ + LOOPING_SOUND_DEFINITION_TAG= 'lsnd', + LOOPING_SOUND_DEFINITION_VERSION= 3, + CUSTOM_MUSIC_PLAY_ID= 'mply', + MAXIMUM_TRACKS_PER_LOOPING_SOUND= 4, + MAXIMUM_DETAIL_SOUNDS_PER_LOOPING_SOUND= 32, +}; + /* ---------- macros */ /* ---------- structures */ diff --git a/source/structures/cluster_partitions.h b/source/structures/cluster_partitions.h index 72c33f2c..09740d2a 100644 --- a/source/structures/cluster_partitions.h +++ b/source/structures/cluster_partitions.h @@ -14,7 +14,32 @@ header included in hcex build. /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct cluster_partition +{ + long *cluster_first_data_references; + struct data_array *data_reference_data; + struct data_array *cluster_reference_data; +}; + +/* ---------- prototypes/CLUSTER_PARTITIONS.C */ + +void cluster_partition_new(struct cluster_partition *partition, char const *name); +void cluster_partition_make_valid(struct cluster_partition *partition); +void cluster_partition_make_invalid(struct cluster_partition *partition); +void cluster_partition_delete(struct cluster_partition *partition); +void cluster_partition_reconnect( + struct cluster_partition *partition, + long datum_index, + long *first_cluster_reference, + real_point3d const *position, + float radius, + struct location const *location); +void cluster_partition_disconnect(struct cluster_partition *partition, long datum_index, long *first_cluster_reference); +long cluster_partition_get_first_datum(struct cluster_partition const *partition, long *reference_index, short cluster_index); +long cluster_partition_get_next_datum(struct cluster_partition const *partition, long *reference_index); +long cluster_partition_get_first_cluster(struct cluster_partition const *partition, long *reference_index, long first_cluster_reference); +long cluster_partition_get_next_cluster(struct cluster_partition const *partition, long *reference_index); + /* ---------- globals */ diff --git a/source/structures/leaf_map.h b/source/structures/leaf_map.h index c731129c..30b1373e 100644 --- a/source/structures/leaf_map.h +++ b/source/structures/leaf_map.h @@ -8,12 +8,23 @@ header included in hcex build. #define __LEAF_MAP_H #pragma once +/* ---------- headers */ + +#include "tag_files/tag_groups.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ +struct leaf_map +{ + const struct bsp3d *bsp; + struct tag_block leaves; + struct tag_block portals; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/structures/structure_bsp_definitions.c b/source/structures/structure_bsp_definitions.c index 6169691f..c2a1f2bb 100644 --- a/source/structures/structure_bsp_definitions.c +++ b/source/structures/structure_bsp_definitions.c @@ -1,39 +1,12 @@ /* STRUCTURE_BSP_DEFINITIONS.C - -symbols in this file: -00182DA0 00a0: - _structure_bsp_get_cluster_pvs (0000) -00182E40 01b0: - _structure_bsp_find_material_for_surface (0000) -00182FF0 0030: - _vertex_type_from_shader_tag (0000) -00183020 00a0: - _structure_bsp_get_cluster_encoded_sound_data (0000) -001830C0 00a0: - _structure_bsp_get_cluster_encoded_sound_distance (0000) -002A1078 006c: - ??_C@_0GM@IEBDGEJL@?$CIcluster_index?$CL1?$CJ?$CKBIT_VECTOR_SIZ@ (0000) -002A10E8 0040: - ??_C@_0EA@EIICKPGK@cluster_index?$DO?$DN0?5?$CG?$CG?5cluster_inde@ (0000) -002A1128 0036: - ??_C@_0DG@NELJLNPJ@c?3?2halo?2SOURCE?2structures?2struct@ (0000) -002A1160 0044: - ??_C@_0EE@GCNBGNLI@surface_index?$DMmaterial?9?$DOfirst_su@ (0000) -002A11A4 002d: - ??_C@_0CN@DMFHEBIB@surface_index?$DO?$DNmaterial?9?$DOfirst_s@ (0000) -002A11D4 003b: - ??_C@_0DL@PINMBEBG@offset?$DO?$DN0?5?$CG?$CG?5offset?$DMstructure_bs@ (0000) -002A1210 0017: - ??_C@_0BH@FKLIMEJG@row_index?$DMcolumn_index?$AA@ (0000) -002A1228 0046: - ??_C@_0EG@FIKJDFNH@to_cluster_index?$DO?$DN0?5?$CG?$CG?5to_cluste@ (0000) -002A1270 004a: - ??_C@_0EK@GPLJLDED@from_cluster_index?$DO?$DN0?5?$CG?$CG?5from_cl@ (0000) */ /* ---------- headers */ +#include "cseries.h" +#include "structure_bsp_definitions.h" + /* ---------- constants */ /* ---------- macros */ @@ -46,4 +19,167 @@ symbols in this file: /* ---------- public code */ +unsigned long *structure_bsp_get_cluster_pvs( + struct structure_bsp *structure_bsp, + short cluster_index) +{ + match_assert("c:\\halo\\SOURCE\\structures\\structure_bsp_definitions.c", 36, cluster_index>=0 && cluster_indexclusters.count); + match_assert("c:\\halo\\SOURCE\\structures\\structure_bsp_definitions.c", + 37, + (cluster_index+1)*BIT_VECTOR_SIZE_IN_LONGS(structure_bsp->clusters.count)<=structure_bsp->cluster_data.size); + + // Get pointer to bitvector starting at the cluster index + return (unsigned long *)( + (byte *)structure_bsp->cluster_data.address + + sizeof(unsigned long) * cluster_index * + BIT_VECTOR_SIZE_IN_LONGS(structure_bsp->clusters.count)); +} + +void structure_bsp_find_material_for_surface( + struct structure_bsp *structure, + long surface_index, + short *lightmap_index, + short *material_index) +{ + struct structure_lightmap *lightmap; + struct structure_material *material; + short lightmap_last_index; + short material_last_index; + short i; + + i=0; + *lightmap_index= 0; + lightmap_last_index= structure->lightmaps.count-1; + + while (lightmap_last_index>i) + { + struct structure_lightmap *curr_lightmap; + + *lightmap_index= (lightmap_last_index-i) / 2+i; + curr_lightmap= TAG_BLOCK_GET_ELEMENT(&structure->lightmaps, *lightmap_index, struct structure_lightmap); + + if (surface_indexmaterials, 0, struct structure_material)->first_surface_index) + { + lightmap_last_index= *lightmap_index-1; + *lightmap_index= lightmap_last_index; + } + else + { + if (surface_index< + TAG_BLOCK_GET_ELEMENT(&curr_lightmap->materials, curr_lightmap->materials.count-1, struct structure_material)->surface_count+ + TAG_BLOCK_GET_ELEMENT(&curr_lightmap->materials, curr_lightmap->materials.count-1, struct structure_material)->first_surface_index) + { + break; + } + + i= *lightmap_index+1; + *lightmap_index= i; + } + } + + lightmap= TAG_BLOCK_GET_ELEMENT(&structure->lightmaps, *lightmap_index, struct structure_lightmap); + + i=0; + *material_index= 0; + material_last_index= lightmap->materials.count; + + while (imaterials, *material_index, struct structure_material); + + if (surface_indexfirst_surface_index) + { + material_last_index= *material_index-1; + *material_index= material_last_index; + } + else + { + if (surface_indexfirst_surface_index+curr_material->surface_count) + { + break; + } + + i= *material_index+1; + *material_index= i; + } + + } + + material= TAG_BLOCK_GET_ELEMENT(&lightmap->materials, *material_index, struct structure_material); + + match_assert("c:\\halo\\SOURCE\\structures\\structure_bsp_definitions.c", 102, surface_index>=material->first_surface_index); + match_assert("c:\\halo\\SOURCE\\structures\\structure_bsp_definitions.c", 103, surface_indexfirst_surface_index+material->surface_count); + + return; +} + +void vertex_type_from_shader_tag( + unsigned long group_tag, + short *vertex_type, + short *lightmap_vertex_type, + boolean compressed) +{ + if (compressed) + { + *vertex_type= _rasterizer_vertex_type_environment_compressed; + *lightmap_vertex_type= _rasterizer_vertex_type_environment_lightmap_compressed; + } + else + { + *vertex_type= _rasterizer_vertex_type_environment_uncompressed; + *lightmap_vertex_type= _rasterizer_vertex_type_environment_lightmap_uncompressed; + } + + return; +} + +byte *structure_bsp_get_cluster_encoded_sound_data( + struct structure_bsp *structure_bsp, + short row_index, + short column_index) +{ + short offset= row_index * (structure_bsp->clusters.count-1)-row_index*(row_index+1)/2+column_index-1; + + match_assert("c:\\halo\\SOURCE\\structures\\structure_bsp_definitions.c", 1202, row_index=0 && offsetsound_cluster_data.size); + + return &((byte *)structure_bsp->sound_cluster_data.address)[offset]; +} + +byte structure_bsp_get_cluster_encoded_sound_distance( + struct structure_bsp *structure_bsp, + short from_cluster_index, + short to_cluster_index) +{ + byte result; + + match_assert("c:\\halo\\SOURCE\\structures\\structure_bsp_definitions.c", 1215, from_cluster_index>=0 && from_cluster_indexclusters.count); + match_assert("c:\\halo\\SOURCE\\structures\\structure_bsp_definitions.c", 1216, to_cluster_index>=0 && to_cluster_indexclusters.count); + + if (from_cluster_index!=to_cluster_index) + { + if (from_cluster_index>to_cluster_index) + { + short temp= from_cluster_index; + from_cluster_index= to_cluster_index; + to_cluster_index= temp; + } + + result= *structure_bsp_get_cluster_encoded_sound_data( + structure_bsp, + from_cluster_index, + to_cluster_index); + } + else + { + result= 0; + } + + return result; +} + + /* ---------- private code */ diff --git a/source/structures/structure_bsp_definitions.h b/source/structures/structure_bsp_definitions.h index 5f2c6490..61a5fcdb 100644 --- a/source/structures/structure_bsp_definitions.h +++ b/source/structures/structure_bsp_definitions.h @@ -8,13 +8,107 @@ header included in hcex build. #define __STRUCTURE_BSP_DEFINITIONS_H #pragma once +/* ---------- headers */ + +#include "leaf_map.h" + +#include "math/integer_math.h" +#include "rasterizer/rasterizer_geometry.h" +#include "render/render.h" +#include "tag_files/tag_groups.h" + /* ---------- constants */ /* ---------- macros */ /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct structure_leaf +{ + byte_rectangle3d bounds; + word pad; + short cluster_index; + short surface_reference_count; + long first_surface_reference_index; +}; + +struct structure_material +{ + struct tag_reference shader; + short permutation_index; + word flags; + long first_surface_index; + long surface_count; + real_point3d centroid; + struct render_lighting lighting; + real_plane3d plane; + short breakable_surface_index; + word copious_unused_space; + struct vertex_buffer vertices; + struct vertex_buffer lightmap_vertices; + struct tag_data uncompressed_vertex_data; + struct tag_data compressed_vertex_data; +}; + +struct structure_lightmap +{ + short bitmap_index; + word pad; + long unused[4]; + struct tag_block materials; // structure_material +}; + +struct structure_bsp +{ + struct tag_reference lightmap_group; + real vehicle_floor; + real vehicle_ceiling; + long sad_unused[5]; + struct render_lighting default_lighting; + long lonely_unused; + struct tag_block collision_materials; + struct tag_block collision_bsp; // collision_bsp + struct tag_block nodes; + real_rectangle3d world_bounds; + struct tag_block leaves; // structure_leaf + struct tag_block surface_references; + struct tag_block surfaces; + struct tag_block lightmaps; // structure_lightmap + long render_unused[3]; + struct tag_block lens_flares; + struct tag_block lens_flare_markers; + struct tag_block clusters; + struct tag_data cluster_data; + struct tag_block cluster_portals; + long cluster_unused[3]; + struct tag_block breakable_surfaces; + struct tag_block fog_planes; + struct tag_block fog_regions; + struct tag_block fog_palette; + long fog_unused[6]; + struct tag_block weather_palette; + struct tag_block weather_polyhedra; + long weather_unused[6]; + struct tag_block pathfinding_surfaces; + struct tag_block pathfinding_edges; + struct tag_block background_sound_palette; + struct tag_block sound_environment_palette; + struct tag_data sound_cluster_data; + long sound_unused[6]; + struct tag_block markers; + struct tag_block detail_object_data; + struct tag_block runtime_decals; + long diminishing_misc_unused[2]; + struct leaf_map leaf_map; +}; + +/* ---------- prototypes/STRUCTURE_BSP_DEFINITIONS.C */ + +unsigned long *structure_bsp_get_cluster_pvs(struct structure_bsp *structure_bsp, short cluster_index); +void structure_bsp_find_material_for_surface(struct structure_bsp *structure, long surface_index, short *lightmap_index, short *material_index); +void vertex_type_from_shader_tag(unsigned long group_tag, short *vertex_type, short *lightmap_vertex_type, boolean compressed); +byte *structure_bsp_get_cluster_encoded_sound_data(struct structure_bsp *structure_bsp, short row_index, short column_index); +byte structure_bsp_get_cluster_encoded_sound_distance(struct structure_bsp *structure_bsp, short from_cluster_index, short to_cluster_index); /* ---------- globals */ diff --git a/source/structures/structure_lens_flares.c b/source/structures/structure_lens_flares.c index 80b97d00..43ff28b1 100644 --- a/source/structures/structure_lens_flares.c +++ b/source/structures/structure_lens_flares.c @@ -48,6 +48,11 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" + +#include "structure_bsp_definitions.h" +#include "physics/collision_bsp_definitions.h" + /* ---------- constants */ /* ---------- macros */ @@ -60,4 +65,19 @@ symbols in this file: /* ---------- public code */ +long cluster_index_from_point( + struct structure_bsp const *structure_bsp, + real_point3d const *point) +{ + long test_result= bsp3d_test_point(&TAG_BLOCK_GET_ELEMENT(&structure_bsp->collision_bsp, 0, struct collision_bsp)->bsp3d, 0, point); + long result= NONE; + + if (test_result!=NONE) + { + result= TAG_BLOCK_GET_ELEMENT(&structure_bsp->leaves, test_result&LONG_MAX, struct structure_leaf)->cluster_index; + } + + return result; +} + /* ---------- private code */ diff --git a/source/structures/structures.h b/source/structures/structures.h index 73b0ea47..fd09f99e 100644 --- a/source/structures/structures.h +++ b/source/structures/structures.h @@ -50,10 +50,20 @@ enum /* ---------- prototypes/STRUCTURES.C */ +short structure_clusters_in_sphere(short cluster_index, real_point3d const *position, real radius, short maximum_count, short *intersected_indices); + /* ---------- prototypes/STRUCTURE_DETAIL_OBJECTS.C */ void structure_detail_objects_flush(void); +/* ---------- prototypes/STRUCTURE_LENS_FLARES.C */ + +long cluster_index_from_point(struct structure_bsp const *structure_bsp, union real_point3d const *point); + +/* ---------- prototypes/STRUCTURE_RUNTIME_DECALS.C */ + +void structure_decals_update(unsigned long *old_combined_pvs, unsigned long *new_combined_pvs, short cluster_count); + /* ---------- globals */ /* ---------- public code */ diff --git a/source/tag_files/tag_groups.c b/source/tag_files/tag_groups.c index 0b1a1113..166855ed 100644 --- a/source/tag_files/tag_groups.c +++ b/source/tag_files/tag_groups.c @@ -17,7 +17,7 @@ long verify_tag_reference( long index; match_assert("c:\\halo\\SOURCE\\tag_files\\tag_groups.c", 3055, reference); - index = tag_loaded(reference->group_tag, reference->name); + index= tag_loaded(reference->group_tag, reference->name); match_vassert( "c:\\halo\\SOURCE\\tag_files\\tag_groups.c", 3061, reference->index==index, diff --git a/source/tag_files/tag_groups.h b/source/tag_files/tag_groups.h index 0a34dc2b..b6fbd2f8 100644 --- a/source/tag_files/tag_groups.h +++ b/source/tag_files/tag_groups.h @@ -8,6 +8,10 @@ header included in hcex build. #define __TAG_GROUPS_H #pragma once +/* ---------- headers */ + +#include "memory/byte_swapping.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/text/font_group.h b/source/text/font_group.h index d3e8c40a..8754fecd 100644 --- a/source/text/font_group.h +++ b/source/text/font_group.h @@ -17,6 +17,8 @@ enum /* ---------- macros */ +#define font_definition_get(index) ((struct font_header *)tag_get(FONT_GROUP_TAG, index)) + /* ---------- structures */ struct font_header diff --git a/source/text/international_strings.c b/source/text/international_strings.c index 62e15fef..e7fb23ae 100644 --- a/source/text/international_strings.c +++ b/source/text/international_strings.c @@ -28,6 +28,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "international_strings.h" + /* ---------- constants */ /* ---------- macros */ @@ -38,6 +41,220 @@ symbols in this file: /* ---------- globals */ +static short global_language_code; + /* ---------- public code */ +void set_language_code(short language_code) +{ + if (language_code<0 || language_code>=NUMBER_OF_LANGUAGE_CODES) + { + language_code= 0; + } + global_language_code= language_code; + + return; +} + +word get_next_character( + byte *string, + short *index) +{ + word result; + + match_vassert( + "c:\\halo\\SOURCE\\text\\international_strings.c", + 32, + *index>=0 && *index<=strlen((char *)string), + csprintf(temporary, "#%d is out of range in string @%p", *index, string)); + + string= &string[*index]; + + if (double_byte_character(string)) + { + // Construct the wide character by byteswapping the two chars + result= 0; + result|= string[0]<<8; + result|= string[1]<<0; + + *index+= 2; + } + else + { + result= string[0]; + *index+= 1; + } + + return result; +} + +word get_previous_character( + byte *string, + short *index) +{ + short i; + word result; + + match_vassert( + "c:\\halo\\SOURCE\\text\\international_strings.c", + 55, + VALID_INDEX(*index, (short)strlen((char *)string)), + csprintf(temporary, "#%d is out of range in string @%p", *index, string)); + + i= 0; + do + { + result= get_next_character(string, &i); + } + while (i<*index); + + + match_vwarn( + "c:\\halo\\SOURCE\\text\\international_strings.c", + 67, + i==*index, + csprintf(temporary, "index #%d is inbetween characters in string %p", *index, string)); + + *index= i; + + return result; +} + +void align_to_character( + unsigned char *string, + short *index) +{ + short i; + + match_vassert( + "c:\\halo\\SOURCE\\text\\international_strings.c", + 85, + *index>0 || *index <=(short)strlen((char *)string), + csprintf(temporary, "#%d is out of range in string @%p", *index, string)); + + i= 0; + while (i<*index) + { + get_next_character(string, &i); + } + *index= i; + + return; +} + +boolean double_byte_character( + byte *string) +{ + boolean result= FALSE; + byte character= string[0]; + + if (character!='\0') + { + byte next_character= string[1]; + if (character==(byte)('|') && + next_character && + strchr("ibukprlctn", next_character) + ) + { + result= TRUE; + } + else + { + switch (global_language_code) + { + case _language_japanese: + if ((character>=(byte)('\x81') && character<=(byte)('\x9F') || + character>=(byte)('\xE0') && character!=(byte)('\xFE')) && + next_character>=(byte)('@') && + next_character<=(byte)('\xFC') && + next_character!=(byte)('\x7F') + ) + { + result= TRUE; + } + break; + case _language_simple_chinese: + if (character>=(byte)('\xA1') && + character!=(byte)('\xFE') && + next_character>=(byte)('\xA1') && + next_character!=(byte)('\xFE') + ) + { + result= TRUE; + } + break; + case _language_traditional_chinese: + if (character>=(byte)('\x81') && + character!=(byte)('\xFE') && + (next_character>=(byte)('@') && next_character<=(byte)('~') || + next_character>=(byte)('\xA1') && next_character!=(byte)('\xFE')) + ) + { + result= TRUE; + } + break; + case _language_korean_wansung: + if (character>=(byte)('\x81') && + character!=(byte)('\xFE') && + ( + next_character>=(byte)('A') && next_character<=(byte)('Z') || + next_character>=(byte)('a') && next_character<=(byte)('z') || + next_character>=(byte)('\x81') && next_character!=(byte)('\xFE') + ) + ) + { + result= TRUE; + } + break; + case _language_korean_johab: + if ((character>=(byte)('\x84') && character<=(byte)('\xD3') || + character>=(byte)('\xD8') && character<=(byte)('\xDE') || + character>=(byte)('\xE0') && character<=(byte)('\xF9') + ) && + ( + next_character>=(byte)('A') && next_character<=(byte)('~') || + next_character>=(byte)('\x81') && next_character!=(byte)('\xFE') + ) + ) + { + result= TRUE; + } + break; + default: + break; + } + } + } + + return result; +} + +boolean character_in_pattern( + word character, + char *pattern) +{ + boolean result= FALSE; + boolean found= FALSE; + short index= 0; + + while (!found) + { + word next_character= get_next_character((unsigned char *)pattern, &index); + if (next_character) + { + if (next_character==character) + { + found= TRUE; + result= TRUE; + } + } + else + { + found= TRUE; + } + } + + return result; +} + /* ---------- private code */ diff --git a/source/text/international_strings.h b/source/text/international_strings.h index 1a3807ec..bdada60f 100644 --- a/source/text/international_strings.h +++ b/source/text/international_strings.h @@ -41,11 +41,11 @@ enum /* ---------- prototypes/INTERNATIONAL_STRINGS.C */ void set_language_code(short language_code); -unsigned short get_next_character(unsigned char *string, short *index); -unsigned short get_previous_character(unsigned char *string, short *index); +word get_next_character(byte *string, short *index); +word get_previous_character(byte *string, short *index); void align_to_character(unsigned char *string, short *index); -boolean double_byte_character(unsigned char *string); -boolean character_in_pattern(unsigned short character, char *pattern); +boolean double_byte_character(byte *string); +boolean character_in_pattern(word character, char *pattern); /* ---------- globals */ diff --git a/source/units/units.c b/source/units/units.c index f98069a8..e0a56c03 100644 --- a/source/units/units.c +++ b/source/units/units.c @@ -643,6 +643,9 @@ symbols in this file: /* ---------- headers */ +#include "cseries.h" +#include "units.h" + /* ---------- constants */ /* ---------- macros */ diff --git a/source/units/units.h b/source/units/units.h index bfb75785..2f6cca5e 100644 --- a/source/units/units.h +++ b/source/units/units.h @@ -8,13 +8,203 @@ header included in hcex build. #define __UNITS_H #pragma once +/* ---------- headers */ + +#include "ai/ai.h" +#include "objects/objects.h" + /* ---------- constants */ +enum +{ + MAXIMUM_WEAPONS_PER_UNIT= 4, + NUMBER_OF_UNIT_USER_ANIMATIONS= 2, +}; + +enum +{ + MAXIMUM_ATTACKERS_PER_UNIT= 4, +}; + +enum +{ + _unit_grenade_human_fragmentation= 0, + _unit_grenade_covenant_plasma, + NUMBER_OF_UNIT_GRENADE_TYPES +}; + /* ---------- macros */ +#define unit_get(index) ((struct unit_datum*)object_get_and_verify_type(index, _object_mask_unit)) +#define unit_try_and_get(index) ((struct unit_datum*)object_try_and_get_and_verify_type(index, _object_mask_unit)) + /* ---------- structures */ -/* ---------- prototypes/EXAMPLE.C */ +struct unit_animation +{ + word flags; + short aiming_screen_index; + short looking_screen_index; + short last_ping_animation_index; + char seat_index; + char weapon_index; + char weapon_type_index; + char state; + char action; + char overlay_action; + char desired_state; + char base_seat_index; + char emotion_index; + struct animation_state action_animation; + struct animation_state overlay_action_animation; + struct animation_state soft_ping_animation; + boolean aiming_with_euler_screen; + boolean looking_with_euler_screen; + real_rectangle2d aiming_screen_bounds; + real_rectangle2d looking_screen_bounds; + long external_animation_graph_index; + struct animation_state external_animation; +}; + +struct unit_speech_item +{ + short priority; + short vocalization_type; + long sound_definition_index; + short delay_time; + short ai_notification_delay; + short pause_time; + unsigned short pad; + struct ai_information_packet ai; +}; + +struct unit_speech +{ + struct unit_speech_item current; + struct unit_speech_item queued; + short damage_minor_decay_timer; + short damage_minor_sounds; + short damage_minor_timer; + short damage_major_timer; + long last_speech_finished_time; + boolean played; + boolean notified_ai; + boolean finished; + boolean pad; + short pre_delay_timer; + short sound_timer; + short ai_delay_timer; + short post_delay_timer; + long impulse_sound_index; +}; + +struct unit_attacker +{ + unsigned long game_time_stamp; + real damage_inflicted; + long object_index; + long player_index; +}; + +struct _unit_datum +{ + long actor_index; + long swarm_actor_index; + long swarm_next_unit_index; + long swarm_prev_unit_index; + unsigned long flags; + unsigned long control_flags; + short timer; + char shield_sap_timeout; + char magic_seat_index; + long persistent_control_timer; + unsigned long persistent_control_flags; + long player_index; + short last_unit_effect_type; + short override_emotion_animation_index; + long game_time_at_last_unit_effect; + real_vector3d desired_facing_vector; + real_vector3d desired_aiming_vector; + real_vector3d aiming_vector; + real_vector3d aiming_velocity; + real_vector3d desired_looking_vector; + real_vector3d looking_vector; + real_vector3d looking_velocity; + real_vector3d throttle; + real primary_trigger; + char aiming_speed; + char melee_attack_state; + char melee_continuous_damage_effect_timer; + byte flaming_death_delay; + char weapon_drop_delay_ticks; + char grenade_throw_state; + short grenade_throw_ticks; + short grenade_throw_full_power_ticks; + long grenade_object_index; + struct unit_animation animation; + real ambient_illumination; + real self_illumination; + real mouth_aperture; + long last_entrance_attempt; + short parent_seat_index; + short current_weapon_index; + short desired_weapon_index; + long weapon_object_indices[MAXIMUM_WEAPONS_PER_UNIT]; + long weapon_last_used_at_game_time[MAXIMUM_WEAPONS_PER_UNIT]; + long equipment_object_index; + char current_grenade_index; + char desired_grenade_index; + char grenade_counts[NUMBER_OF_UNIT_GRENADE_TYPES]; + char current_zoom_level; + char desired_zoom_level; + char gunner_inactive_ticks; + byte aiming_change; + long driver_object_index; + long gunner_object_index; + long last_vehicle_index; + long game_time_at_last_vehicle_exit; + short fake_encounter_index; + short fake_squad_index; + real seat_power[2]; + real integrated_light_power; + real integrated_light_battery; + real integrated_night_vision_power; + real_point3d seat_last_position; + real_vector3d seat_last_velocity; + real_vector3d seat_acceleration; + real_vector3d seat_desired_acceleration; + real active_camouflage; + real active_camouflage_super_amount; + long dialogue_index; + struct unit_speech speech; + short last_damage_category; + short delayed_damage_timer; + real delayed_damage_peak; + long delayed_damage_attacker_object_index; + long flaming_death_attacker_object_index; + real run_blindly_angle; + real run_blindly_angle_delta; + long time_of_death; + short feign_death_timer; + short cause_for_camo_regrowth; + real body_stun; + short body_stun_ticks; + short killing_spree_count; + long killing_spree_last_time; + struct unit_attacker attackers[MAXIMUM_ATTACKERS_PER_UNIT]; + short user_animation_indices[NUMBER_OF_UNIT_USER_ANIMATIONS]; +}; + +struct unit_datum +{ + long definition_index; + struct _object_datum object; + struct _unit_datum unit; +}; + +/* ---------- prototypes/UNITS.C */ + +void unit_get_head_position(long unit_index, union real_point3d *head_position); /* ---------- globals */