diff --git a/game/source/motor/motor_system_biped.cpp b/game/source/motor/motor_system_biped.cpp index 9fc8276bd..c9b126c49 100644 --- a/game/source/motor/motor_system_biped.cpp +++ b/game/source/motor/motor_system_biped.cpp @@ -1,12 +1,102 @@ #include "motor/motor_system_biped.hpp" +#include "cache/cache_files.hpp" +#include "cseries/cseries_events.hpp" +#include "game/cheats.hpp" +#include "game/game.hpp" +#include "memory/module.hpp" +#include "objects/objects.hpp" +#include "scenario/scenario.hpp" +#include "simulation/game_interface/simulation_game_action.hpp" +#include "units/biped_definitions.hpp" +#include "units/bipeds.hpp" + +HOOK_DECLARE(0x00BAE400, biped_falling_damage); + //.text:00BAD3B0 ; void __cdecl biped_adjust_aiming(long, euler_angles2d*, real*, real*) //.text:00BADC30 ; void __cdecl biped_build_axes_from_desired_facing(vector3d const*, vector3d const*, vector3d const*, vector3d*) //.text:00BAE000 ; double __cdecl biped_calculate_crouch_delta(long) -//.text:00BAE130 ; bool __cdecl biped_calculate_crouch_velocity_delta(long, real*) + +bool __cdecl biped_calculate_crouch_velocity_delta(long biped_index, real* crouch_velocity_delta) +{ + return INVOKE(0x00BAE130, biped_calculate_crouch_velocity_delta, biped_index, crouch_velocity_delta); +} + //.text:00BAE1F0 ; bool __cdecl biped_can_melee_target_unit(long, long) //.text:00BAE380 ; void __cdecl biped_clear_pathfinding_cache(long) -//.text:00BAE400 ; void __cdecl biped_falling_damage(long) + +void __cdecl biped_falling_damage(long biped_index) +{ + //INVOKE(0x00BAE400, biped_falling_damage, biped_index); + + biped_datum* biped = (biped_datum*)object_get_and_verify_type(biped_index, _object_mask_biped); + struct biped_definition* biped_definition = (struct biped_definition*)tag_get(BIPED_TAG, biped->definition_index); + + void* motor_state = object_header_block_get(biped_index, &biped->motor.motor_state); + REFERENCE_DECLARE(offset_pointer(motor_state, 4), byte_flags, motor_state_flags); + + s_game_globals_falling_damage& falling_damage = scenario_get_game_globals()->falling_damage[0]; + + bool v7 = + TEST_BIT(biped->unit.flags, 8) || + biped_definition->biped.flags.test(_biped_definition_flags_immune_to_falling_damage) || + TEST_BIT(biped->object.damage_flags, 8); + + real gravity_scale = biped_definition->biped.physics.ground_physics.gravity_scale; + if (gravity_scale <= 0.0f) + gravity_scale = 1.0f; + + if (!game_is_multiplayer() && biped->object.parent_object_index == NONE) + { + vector3d linear_velocity{}; + object_get_velocities(biped_index, &linear_velocity, NULL); + + real k = linear_velocity.k; + real crouch_velocity_delta = 0.0f; + if (TEST_BIT(motor_state_flags, 0) && biped_calculate_crouch_velocity_delta(biped_index, &crouch_velocity_delta)) + k -= crouch_velocity_delta; + + vector3d linear_local_space_velocity{}; + vector3d angular_local_space_velocity{}; + if (object_get_early_mover_local_space_velocity(biped_index, &linear_local_space_velocity, &angular_local_space_velocity, false, false)) + k -= linear_local_space_velocity.k; + + ASSERT(!game_is_predicted()); + + if ((!cheat.jetpack /*&& !game_skull_is_active(45)*/ || biped->unit.player_index == NONE) && + biped->biped.physics.get_mode() == c_character_physics_component::e_mode::_mode_ground && + -(falling_damage.runtime_maximum_falling_velocity * gravity_scale) > k) + { + if (!v7 && !TEST_BIT(biped->object.damage_flags, 2)) + { + SET_BIT(biped->biped.flags, 5, true); + s_damage_data damage_data{}; + damage_data.material_type = c_global_material_type(); + damage_data_new(&damage_data, falling_damage.distance_damage.index); + SET_BIT(damage_data.flags, 2, true); + damage_data.damage_reporting_info.type = _damage_reporting_type_falling_damage; + damage_compute_damage_owner_from_object_index(biped_index, &damage_data.damage_owner); + object_cause_damage_simple(&damage_data, biped_index, 5); + } + + if (!game_is_multiplayer() && + biped->object.flags.test(_object_outside_of_map_bit) && + biped->unit.player_index == NONE && + !simulation_query_object_is_predicted(biped_index)) + { + char const* object_description = "";// object_describe(biped_index); + generate_event(_event_level_warning, "WARNING: %s reached terminal velocity outside world (%f %f %f) and was erased", + object_description, + biped->object.position.x, + biped->object.position.y, + biped->object.position.z); + + object_delete(biped_index); + } + } + } +} + //.text:00BAE600 ; void __cdecl biped_get_control_vectors(long, bool, vector3d*, vector3d*, vector3d*) //.text:00BAE8D0 ; double __cdecl biped_get_player_specific_scale(long) //.text:00BAE9D0 ; void __cdecl biped_ground_plane_fix_transform_from_physics(long, real_matrix4x3*) diff --git a/game/source/motor/motor_system_biped.hpp b/game/source/motor/motor_system_biped.hpp index 3f59c932d..0ad4cb14b 100644 --- a/game/source/motor/motor_system_biped.hpp +++ b/game/source/motor/motor_system_biped.hpp @@ -1,2 +1,7 @@ #pragma once +#include "cseries/cseries.hpp" + +extern bool __cdecl biped_calculate_crouch_velocity_delta(long biped_index, real* crouch_velocity_delta); +extern void __cdecl biped_falling_damage(long biped_index); + diff --git a/game/source/objects/damage.cpp b/game/source/objects/damage.cpp index a8494b870..4177b0b8d 100644 --- a/game/source/objects/damage.cpp +++ b/game/source/objects/damage.cpp @@ -27,95 +27,6 @@ bool debug_player_damage = false; bool debug_damage = false; long global_debug_damage_object_index = NONE; -void render_debug_object_damage() -{ - if (debug_damage_radius) - { - // #TODO: implement - } - - if (debug_damage) - { - short_rectangle2d bounds{}; - interface_get_current_display_settings(NULL, NULL, NULL, &bounds); - bounds.x0 += short(real(bounds.x1 - bounds.x0) * 0.7f); - bounds.y0 += short(real(bounds.y1 - bounds.y0) * 0.1f); - - char string[2048]{}; - if (global_debug_damage_object_index == NONE) - { - csnzprintf(string, sizeof(string), "no object to debug|n(point and press space)"); - } - else - { - if (object_datum* object = object_get(global_debug_damage_object_index)) - { - csnzprintf(string, sizeof(string), "%s|nbody %0.3f|n current %0.3f|n recent %0.3f|nshield %0.3f|n current %0.3f|n recent %0.3f|n", - strrchr(tag_get_name(object->definition_index), '\\'), - object->object.body_vitality, - object->object.current_shield_damage, - object->object.recent_shield_damage, - object->object.shield_vitality, - object->object.current_body_damage, - object->object.recent_body_damage); - - if (s_model_damage_info const* damage_info = object_get_damage_info(global_debug_damage_object_index)) - { - if (damage_info->damage_sections.count > 0) - { - long element_count = 0; - struct object_damage_section* object_damage_section = (struct object_damage_section*)object_header_block_get_with_count(global_debug_damage_object_index, &object->object.damage_sections, sizeof(struct object_damage_section), &element_count); - - if (element_count > damage_info->damage_sections.count) - element_count = damage_info->damage_sections.count; - - for (long i = 0; i < element_count; i++) - { - s_model_damage_section& damage_section = damage_info->damage_sections[i]; - - csnzappendf(string, sizeof(string), " %s %0.3f|n", - damage_section.name.get_string(), - real(1.0f - real(real(object_damage_section->__unknown2) / 255.0f))); - } - } - } - } - else - { - global_debug_damage_object_index = NONE; - } - } - - c_rasterizer_draw_string draw_string; - c_font_cache_mt_safe font_cache; - - draw_string.set_bounds(&bounds); - draw_string.draw(&font_cache, string); - - if (input_key_frames_down(_key_code_spacebar, _input_type_game)) - { - e_output_user_index user_index = c_player_view::get_current()->get_player_view_output_user_index(); - long unit_index = player_mapping_get_unit_by_output_user(user_index); - - real_matrix4x3 camera{}; - c_player_view::get_player_render_camera_orientation(&camera); - vector3d forward{}; - scale_vector3d(&camera.forward, 50.0f, &forward); - - s_collision_test_flags flags{}; - flags.collision_flags.set(_collision_test_front_facing_surfaces_bit, true); - flags.object_flags.set(_collision_test_objects_bit, true); - - collision_result collision{}; - if (collision_test_vector(flags, &camera.position, &forward, unit_index, NONE, &collision)) - { - ASSERT(collision.type == _collision_result_object); - global_debug_damage_object_index = collision.object_index; - } - } - } -} - //real __cdecl compute_total_damage(struct s_damage_data* damage_data, struct s_damage_effect_definition* damage_effect_definition, struct damage_definition const* damage_definition, long object_index, bool* a5) real __cdecl compute_total_damage(s_damage_data* damage_data, void* damage_effect_definition, void const* damage_definition, long object_index, bool* a5) { @@ -123,7 +34,7 @@ real __cdecl compute_total_damage(s_damage_data* damage_data, void* damage_effec if (cheat.jetpack && TEST_MASK(FLAG(object_get_type(object_index)), _object_mask_biped)) { - if (damage_data->damage_reporting_info.type == _damage_reporting_type_falling_damage || damage_data->damage_reporting_info.type == _damage_reporting_type_generic_collision_damage) + if (damage_data->damage_reporting_info.type == _damage_reporting_type_generic_collision_damage) result = 0.0f; } @@ -165,6 +76,11 @@ void __cdecl damage_acceleration_queue_end() damage_globals->damage_acceleration_queue_active = false; } +void __cdecl damage_data_new(s_damage_data* damage_data, long definition_index) +{ + INVOKE(0x00B50330, damage_data_new, damage_data, definition_index); +} + void __cdecl damage_initialize_for_new_map() { //INVOKE(0x00B50720, damage_initialize_for_new_map); @@ -201,8 +117,103 @@ void __cdecl object_cause_damage(s_damage_data* damage_data, long object_index, HOOK_INVOKE(, object_cause_damage, damage_data, object_index, node_index, region_index, material_index, predictability); } +//void __cdecl object_cause_damage_simple(s_damage_data* damage_data, long object_index, e_predictability predictability) +void __cdecl object_cause_damage_simple(s_damage_data* damage_data, long object_index, long predictability) +{ + INVOKE(0x00B542A0, object_cause_damage_simple, damage_data, object_index, predictability); +} + s_model_damage_info const* __cdecl object_get_damage_info(long object_index) { return INVOKE(0x00B578D0, object_get_damage_info, object_index); } +void render_debug_object_damage() +{ + if (debug_damage_radius) + { + // #TODO: implement + } + + if (debug_damage) + { + short_rectangle2d bounds{}; + interface_get_current_display_settings(NULL, NULL, NULL, &bounds); + bounds.x0 += short(real(bounds.x1 - bounds.x0) * 0.7f); + bounds.y0 += short(real(bounds.y1 - bounds.y0) * 0.1f); + + char string[2048]{}; + if (global_debug_damage_object_index == NONE) + { + csnzprintf(string, sizeof(string), "no object to debug|n(point and press space)"); + } + else + { + if (object_datum* object = object_get(global_debug_damage_object_index)) + { + csnzprintf(string, sizeof(string), "%s|nbody %0.3f|n current %0.3f|n recent %0.3f|nshield %0.3f|n current %0.3f|n recent %0.3f|n", + strrchr(tag_get_name(object->definition_index), '\\'), + object->object.body_vitality, + object->object.current_shield_damage, + object->object.recent_shield_damage, + object->object.shield_vitality, + object->object.current_body_damage, + object->object.recent_body_damage); + + if (s_model_damage_info const* damage_info = object_get_damage_info(global_debug_damage_object_index)) + { + if (damage_info->damage_sections.count > 0) + { + long element_count = 0; + struct object_damage_section* object_damage_section = (struct object_damage_section*)object_header_block_get_with_count(global_debug_damage_object_index, &object->object.damage_sections, sizeof(struct object_damage_section), &element_count); + + if (element_count > damage_info->damage_sections.count) + element_count = damage_info->damage_sections.count; + + for (long i = 0; i < element_count; i++) + { + s_model_damage_section& damage_section = damage_info->damage_sections[i]; + + csnzappendf(string, sizeof(string), " %s %0.3f|n", + damage_section.name.get_string(), + real(1.0f - real(real(object_damage_section->__unknown2) / 255.0f))); + } + } + } + } + else + { + global_debug_damage_object_index = NONE; + } + } + + c_rasterizer_draw_string draw_string; + c_font_cache_mt_safe font_cache; + + draw_string.set_bounds(&bounds); + draw_string.draw(&font_cache, string); + + if (input_key_frames_down(_key_code_spacebar, _input_type_game)) + { + e_output_user_index user_index = c_player_view::get_current()->get_player_view_output_user_index(); + long unit_index = player_mapping_get_unit_by_output_user(user_index); + + real_matrix4x3 camera{}; + c_player_view::get_player_render_camera_orientation(&camera); + vector3d forward{}; + scale_vector3d(&camera.forward, 50.0f, &forward); + + s_collision_test_flags flags{}; + flags.collision_flags.set(_collision_test_front_facing_surfaces_bit, true); + flags.object_flags.set(_collision_test_objects_bit, true); + + collision_result collision{}; + if (collision_test_vector(flags, &camera.position, &forward, unit_index, NONE, &collision)) + { + ASSERT(collision.type == _collision_result_object); + global_debug_damage_object_index = collision.object_index; + } + } + } +} + diff --git a/game/source/objects/damage.hpp b/game/source/objects/damage.hpp index 5b88574b2..3937c580a 100644 --- a/game/source/objects/damage.hpp +++ b/game/source/objects/damage.hpp @@ -151,14 +151,16 @@ extern long global_debug_damage_object_index; struct s_model_damage_info; -extern void render_debug_object_damage(); - extern real __cdecl compute_total_damage(s_damage_data* damage_data, void* damage_effect_definition, void const* damage_definition, long object_index, bool* a5); extern void __cdecl damage_acceleration_apply(s_damage_globals::s_damage_acceleration const* damage_acceleration); extern void __cdecl damage_acceleration_queue_begin(); extern void __cdecl damage_acceleration_queue_end(); +extern void __cdecl damage_data_new(s_damage_data* damage_data, long definition_index); extern void __cdecl damage_initialize_for_new_map(); extern void __cdecl damage_update(); extern void __cdecl object_cause_damage(s_damage_data* damage_data, long object_index, short node_index, short region_index, short material_index, long predictability); +extern void __cdecl object_cause_damage_simple(s_damage_data* damage_data, long object_index, long predictability); extern s_model_damage_info const* __cdecl object_get_damage_info(long object_index); +extern void render_debug_object_damage(); + diff --git a/game/source/objects/damage_owner.cpp b/game/source/objects/damage_owner.cpp index 5293778b8..ddcf3f043 100644 --- a/game/source/objects/damage_owner.cpp +++ b/game/source/objects/damage_owner.cpp @@ -2,7 +2,11 @@ REFERENCE_DECLARE(0x01949360, s_damage_owner const* const, global_damage_owner_unknown); -//.text:00B770E0 ; void __cdecl damage_compute_damage_owner_from_object_index(long, s_damage_owner*) +void __cdecl damage_compute_damage_owner_from_object_index(long object_index, s_damage_owner* damage_owner) +{ + INVOKE(0x00B770E0, damage_compute_damage_owner_from_object_index, object_index, damage_owner); +} + //.text:00B771C0 ; void __cdecl damage_owner_set(s_damage_owner*, long, long, c_game_team) //.text:00B771F0 ; //.text:00B77200 ; diff --git a/game/source/objects/damage_owner.hpp b/game/source/objects/damage_owner.hpp index fc08b311e..467b4cab0 100644 --- a/game/source/objects/damage_owner.hpp +++ b/game/source/objects/damage_owner.hpp @@ -12,3 +12,5 @@ static_assert(sizeof(s_damage_owner) == 0xC); extern s_damage_owner const* const& global_damage_owner_unknown; +extern void __cdecl damage_compute_damage_owner_from_object_index(long object_index, s_damage_owner* damage_owner); + diff --git a/game/source/objects/object_early_movers.cpp b/game/source/objects/object_early_movers.cpp index 7c168f85c..96618347f 100644 --- a/game/source/objects/object_early_movers.cpp +++ b/game/source/objects/object_early_movers.cpp @@ -58,7 +58,12 @@ void __cdecl object_early_movers_initialize_for_new_map() } //.text:00B98AD0 ; bool __cdecl object_get_early_mover_local_space_acceleration(long, real_point3d const*, vector3d*, vector3d*, bool, bool) -//.text:00B98CF0 ; bool __cdecl object_get_early_mover_local_space_velocity(long, vector3d*, vector3d*, bool, bool) + +bool __cdecl object_get_early_mover_local_space_velocity(long object_index, vector3d* linear_local_space_velocity, vector3d* angular_local_space_velocity, bool a4, bool a5) +{ + return INVOKE(0x00B98CF0, object_get_early_mover_local_space_velocity, object_index, linear_local_space_velocity, angular_local_space_velocity, a4, a5); +} + //.text:00B98D30 ; bool __cdecl object_get_early_mover_local_space_velocity(long, real_point3d const*, vector3d*, vector3d*, bool, bool) void __cdecl object_get_early_movers(long const** object_early_movers, long* object_early_movers_count) diff --git a/game/source/objects/object_early_movers.hpp b/game/source/objects/object_early_movers.hpp index 08266bb33..11b9164b6 100644 --- a/game/source/objects/object_early_movers.hpp +++ b/game/source/objects/object_early_movers.hpp @@ -68,6 +68,7 @@ extern void __cdecl object_early_movers_dispose(); extern void __cdecl object_early_movers_dispose_from_old_map(); extern void __cdecl object_early_movers_initialize(); extern void __cdecl object_early_movers_initialize_for_new_map(); +extern bool __cdecl object_get_early_mover_local_space_velocity(long object_index, vector3d* linear_local_space_velocity, vector3d* angular_local_space_velocity, bool a4, bool a5); extern void __cdecl object_get_early_movers(long const** object_early_movers, long* object_early_movers_count); extern void __cdecl object_early_mover_render_debug();