diff --git a/godot/models/animations/Aim_Fire.res b/godot/models/animations/Aim_Fire.res index 9a74411..cba062c 100644 Binary files a/godot/models/animations/Aim_Fire.res and b/godot/models/animations/Aim_Fire.res differ diff --git a/godot/models/animations/character_tree.tres b/godot/models/animations/character_tree.tres index 79528e2..43d2d8c 100644 --- a/godot/models/animations/character_tree.tres +++ b/godot/models/animations/character_tree.tres @@ -1,4 +1,4 @@ -[gd_resource type="AnimationNodeBlendTree" load_steps=46 format=3 uid="uid://c7rxfpfy7vt1b"] +[gd_resource type="AnimationNodeBlendTree" load_steps=48 format=3 uid="uid://c7rxfpfy7vt1b"] [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ukhqm"] animation = &"Aim" @@ -15,6 +15,9 @@ animation = &"Aim" [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_8rbkq"] animation = &"Aim_Fire" +[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_lg206"] +animation = &"Hit_backward" + [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ugv1e"] animation = &"RESET" @@ -225,6 +228,10 @@ switch_mode = 2 advance_mode = 2 advance_expression = "is_walking && walk_speed > 0.0" +[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_0ppx7"] +switch_mode = 2 +advance_mode = 2 + [sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_7smdg"] "states/Aim Down [aim]/node" = SubResource("AnimationNodeAnimation_ukhqm") "states/Aim Down [aim]/position" = Vector2(831.525, 251.767) @@ -233,6 +240,8 @@ advance_expression = "is_walking && walk_speed > 0.0" states/End/position = Vector2(195.182, 94.3447) "states/Fire [aim]/node" = SubResource("AnimationNodeAnimation_8rbkq") "states/Fire [aim]/position" = Vector2(919.525, 14.954) +states/Hit/node = SubResource("AnimationNodeAnimation_lg206") +states/Hit/position = Vector2(689.503, 14.954) "states/RESET To Aim/node" = SubResource("AnimationNodeAnimation_ugv1e") "states/RESET To Aim/position" = Vector2(755.258, 94.3447) states/Run/node = SubResource("AnimationNodeBlendTree_hmklb") @@ -244,7 +253,7 @@ states/Start/position = Vector2(572.26, 14.954) "states/Stationary [turn]/position" = Vector2(572.26, 94.3447) "states/Walk [turn]/node" = SubResource("AnimationNodeBlendTree_2mbyh") "states/Walk [turn]/position" = Vector2(572.26, 258.767) -transitions = ["Aim [aim] [turn]", "Aim Down [aim]", SubResource("AnimationNodeStateMachineTransition_4lybd"), "Aim Down [aim]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_5aafd"), "Aim [aim] [turn]", "Fire [aim]", SubResource("AnimationNodeStateMachineTransition_8f4gl"), "Fire [aim]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_xnat3"), "Walk [turn]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_12bos"), "Aim Down [aim]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_n0ndr"), "Walk [turn]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_0wc5e"), "Stationary [turn]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_4hisb"), "Start", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_bmty6"), "Stationary [turn]", "RESET To Aim", SubResource("AnimationNodeStateMachineTransition_kyd6p"), "RESET To Aim", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_w5kob"), "Stationary [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_g0i3x"), "Walk [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_ocffv"), "Run", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h0my5"), "Run", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_nymcr"), "Run", "Stab", SubResource("AnimationNodeStateMachineTransition_g5qf0"), "Stab", "Run", SubResource("AnimationNodeStateMachineTransition_27kmb"), "Stationary [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_4q0ot"), "Stab", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h6ujc"), "Walk [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_3bu8l"), "Stab", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_cpibo")] +transitions = ["Aim [aim] [turn]", "Aim Down [aim]", SubResource("AnimationNodeStateMachineTransition_4lybd"), "Aim Down [aim]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_5aafd"), "Aim [aim] [turn]", "Fire [aim]", SubResource("AnimationNodeStateMachineTransition_8f4gl"), "Fire [aim]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_xnat3"), "Walk [turn]", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_12bos"), "Aim Down [aim]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_n0ndr"), "Walk [turn]", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_0wc5e"), "Stationary [turn]", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_4hisb"), "Start", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_bmty6"), "Stationary [turn]", "RESET To Aim", SubResource("AnimationNodeStateMachineTransition_kyd6p"), "RESET To Aim", "Aim [aim] [turn]", SubResource("AnimationNodeStateMachineTransition_w5kob"), "Stationary [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_g0i3x"), "Walk [turn]", "Run", SubResource("AnimationNodeStateMachineTransition_ocffv"), "Run", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h0my5"), "Run", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_nymcr"), "Run", "Stab", SubResource("AnimationNodeStateMachineTransition_g5qf0"), "Stab", "Run", SubResource("AnimationNodeStateMachineTransition_27kmb"), "Stationary [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_4q0ot"), "Stab", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_h6ujc"), "Walk [turn]", "Stab", SubResource("AnimationNodeStateMachineTransition_3bu8l"), "Stab", "Walk [turn]", SubResource("AnimationNodeStateMachineTransition_cpibo"), "Hit", "Stationary [turn]", SubResource("AnimationNodeStateMachineTransition_0ppx7")] graph_offset = Vector2(-87.4971, -116.108) [sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_au62i"] diff --git a/godot/models/character.glb b/godot/models/character.glb index e00e63b..7a17ffd 100644 --- a/godot/models/character.glb +++ b/godot/models/character.glb @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dfc9bc9324457111ead036f113c607ad1922cc85a3c600ec03339226b4d9bbfd -size 20411536 +oid sha256:4e1ee4037943fe1d42ec6383b5e0e5b103b06d19fe3ab7c25611053edf8e0c3b +size 20637296 diff --git a/models/character.blend b/models/character.blend index d864349..a2579be 100644 --- a/models/character.blend +++ b/models/character.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1d872d2473ac5ed618ad4f3a9c59135714066fcf4640e800c4672dafb13bc28c -size 3286484 +oid sha256:1bc37c7c979305642afff0216f3ae7b12c34e24a67554322bc397110207971b2 +size 3558728 diff --git a/models/character.blend1 b/models/character.blend1 index e4406da..ce051ac 100644 Binary files a/models/character.blend1 and b/models/character.blend1 differ diff --git a/src/enemy.cpp b/src/enemy.cpp index 449b593..e23919f 100644 --- a/src/enemy.cpp +++ b/src/enemy.cpp @@ -32,61 +32,67 @@ void Enemy::chase_enter() { } void Enemy::chase() { - bool const is_chasing{!this->agent->is_navigation_finished()}; - this->anim_tree->set_lock_running(is_chasing); - this->anim_tree->set_aim_weapon(!is_chasing); - if(is_chasing) { + bool const at_end{!this->agent->is_navigation_finished()}; + this->anim_tree->set_lock_running(at_end); + this->anim_tree->set_aim_weapon(!at_end); + if(at_end) { gd::Vector3 const global_pos{this->get_global_position()}; gd::Vector3 const target{global_pos * 2 - this->agent->get_next_path_position()}; this->look_at({target.x, global_pos.y, target.z}); - } - if(this->get_global_position().distance_to(this->player->get_global_position()) >= this->agent->get_target_desired_distance()) + } else if(this->get_global_position().distance_to(this->player->get_global_position()) >= this->agent->get_target_desired_distance()) this->chase_enter(); // repath } -Enemy::ActionFn Enemy::miss_enter() { +Enemy::ActionFn Enemy::wait_line_of_sight() { + if(this->can_see_player) + return (ActionFn)&Enemy::take_aim; + else + return (ActionFn)&Enemy::wait_line_of_sight; +} + +Enemy::ActionFn Enemy::take_aim() { this->anim_tree->set_aim_weapon(true); - return (ActionFn)&Enemy::miss; + if(this->anim_tree->get_current_state().begins_with("Aim")) + return (ActionFn)&Enemy::hit; + else + return(ActionFn)&Enemy::take_aim; } Enemy::ActionFn Enemy::miss() { - if(this->anim_tree->get_current_state().begins_with("Fire") || this->anim_tree->get_fire_weapon()) // last shot still going - return (ActionFn)&Enemy::miss; if(this->can_see_player) { gd::Basis const basis{this->get_global_basis()}; - this->look_at(this->get_global_position() * 2 - this->player->get_global_position() + basis.get_column(0)); + this->look_at(this->get_global_position() * 2 - this->player->get_global_position() + basis.get_column(0) * 0.6f); this->anim_tree->set_aim_weapon(true); this->anim_tree->set_fire_weapon(); - if(this->anim_tree->get_fire_weapon()) { - gd::UtilityFunctions::print("!!! miss fired"); - return ++this->missed_shots > SHOTS_BEFORE_HIT ? (ActionFn)&Enemy::hit_enter : (ActionFn)&Enemy::miss_enter; - } + ++this->missed_shots; + return (ActionFn)&Enemy::wait_end_of_shot; } else { this->chase(); } return (ActionFn)&Enemy::miss; } -Enemy::ActionFn Enemy::hit_enter() { - this->anim_tree->set_aim_weapon(true); - return (ActionFn)&Enemy::hit; -} - Enemy::ActionFn Enemy::hit() { - if(this->anim_tree->get_current_state().begins_with("Fire") || this->anim_tree->get_fire_weapon()) // last shot still going - return (ActionFn)&Enemy::hit; - else if(this->can_see_player) { + if(this->can_see_player) { this->look_at(this->get_global_position() * 2 - this->player->get_global_position()); this->anim_tree->set_aim_weapon(true); this->anim_tree->set_fire_weapon(); this->missed_shots = 0; - return (ActionFn)&Enemy::miss_enter; + return (ActionFn)&Enemy::wait_end_of_shot; } else { this->chase(); } return (ActionFn)&Enemy::hit; } +Enemy::ActionFn Enemy::wait_end_of_shot() { + if(this->anim_tree->get_current_state().begins_with("Fire") || this->anim_tree->get_fire_weapon()) // last shot still going + return (ActionFn)&Enemy::wait_end_of_shot; + else + return this->missed_shots >= SHOTS_BEFORE_HIT ? (ActionFn)&Enemy::hit : (ActionFn)&Enemy::miss; + +} + void Enemy::_physics_process(double delta) { this->update_can_see_player(); gd::Basis const basis{this->get_global_basis()}; @@ -95,7 +101,7 @@ void Enemy::_physics_process(double delta) { basis.get_column(0) * motion.x + basis.get_column(1) * motion.y + basis.get_column(2) * motion.z - }); + });\ this->move_and_slide(); } @@ -107,7 +113,7 @@ void Enemy::damage() { void Enemy::notice_player(Player *player) { this->player = player; - this->current_action_fn = (ActionFn)&Enemy::miss_enter; + this->current_action_fn = (ActionFn)&Enemy::wait_line_of_sight; } void Enemy::update_can_see_player() { diff --git a/src/enemy.hpp b/src/enemy.hpp index ee7c3a8..96cf7ad 100644 --- a/src/enemy.hpp +++ b/src/enemy.hpp @@ -19,12 +19,13 @@ public: void update(); void chase_enter(); void chase(); - ActionFn miss_enter(); + ActionFn wait_line_of_sight(); + ActionFn take_aim(); ActionFn miss(); - ActionFn hit_enter(); ActionFn hit(); ActionFn stab_enter(); ActionFn stab(); + ActionFn wait_end_of_shot(); virtual void _physics_process(double delta) override; virtual void damage() override; @@ -34,10 +35,10 @@ public: void set_update_interval(float time); float get_update_interval() const; private: - int const SHOTS_BEFORE_HIT{2}; + int const SHOTS_BEFORE_HIT{1}; int missed_shots{0}; - double update_interval{0.2}; + double update_interval{0.4}; ActionFn current_action_fn{nullptr}; bool can_see_player{false}; Player *player{nullptr}; diff --git a/src/player.cpp b/src/player.cpp index 0b8921f..608c8fb 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -51,7 +51,7 @@ void Player::_physics_process(double delta [[maybe_unused]]) { } void Player::damage() { - this->anim_tree->death_animation(); + this->anim_tree->hit_animation(); } void Player::process_transform_camera(double delta) { diff --git a/src/player_anim_tree.cpp b/src/player_anim_tree.cpp index ded7b72..119181c 100644 --- a/src/player_anim_tree.cpp +++ b/src/player_anim_tree.cpp @@ -111,6 +111,10 @@ bool PlayerAnimTree::get_stab() { return is_set; } +void PlayerAnimTree::hit_animation() { + this->fsm->start("Hit", true); +} + void PlayerAnimTree::death_animation() { this->set("parameters/DeathSeek/request", 0.f); this->is_dead = true; diff --git a/src/player_anim_tree.hpp b/src/player_anim_tree.hpp index 68324f6..715aa89 100644 --- a/src/player_anim_tree.hpp +++ b/src/player_anim_tree.hpp @@ -36,6 +36,7 @@ public: bool get_fire_weapon(); void set_stab(); bool get_stab(); + void hit_animation(); void death_animation(); bool match_tags(Tags tags) const; gd::StringName const &get_current_state() const;