diff --git a/src/liborng/nodes/character_nodes/character_3d.cpp b/src/liborng/nodes/character_nodes/character_3d.cpp index 396ba28..d2c0719 100644 --- a/src/liborng/nodes/character_nodes/character_3d.cpp +++ b/src/liborng/nodes/character_nodes/character_3d.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include using namespace godot; @@ -25,7 +27,6 @@ using namespace godot; void Character3D::_ready() { - this->skeleton_list.clear(); if (this->character_skeleton) { this->_rebuild_mesh_instances(); @@ -35,7 +36,7 @@ void Character3D::_ready() void Character3D::set_meshes(TypedArray m) { this->meshes = m; - this->full_aabb = AABB(); + this->_full_aabb = AABB(); this->_rebuild_mesh_instances(); } @@ -48,10 +49,21 @@ void Character3D::set_character_skeleton(CharacterSkeleton3D *cs) void Character3D::take_damage(const HurtboxDamage &hit_data) { - for (const auto &[character_skeleton, bones] : hit_data.bones) + if (this->_hurtbox_queue.empty()) + CALL_NEXT_FRAME(callable_mp(this, &Character3D::_next_hurtbox_in_queue)); + this->_hurtbox_queue.emplace_back(hit_data); +} + +void Character3D::_next_hurtbox_in_queue() +{ + HurtboxDamage &hit_data = this->_hurtbox_queue.front(); + if (!hit_data.bones.empty()) { - Skeleton3D *skeleton = character_skeleton->get_skeleton(); + CharacterSkeleton3D *character_skeleton = hit_data.bones.begin()->first; + const std::vector &bone_hits = hit_data.bones.begin()->second; + hit_data.bones.erase(this->_hurtbox_queue.begin()->bones.begin()); + Skeleton3D *skeleton = character_skeleton->get_skeleton(); const Plane &local_slice_plane = skeleton->get_global_transform().inverse().xform(Plane(hit_data.global_hit_transform.get_basis().get_column(1), hit_data.global_hit_transform.origin)); std::vector sliced_mesh_instances = character_skeleton->get_mesh_instances(); @@ -63,7 +75,7 @@ void Character3D::take_damage(const HurtboxDamage &hit_data) MeshInstance3D *original_mesh_instance = sliced_mesh_instances[i]; Ref first_half; first_half.instantiate(); Ref other_half; other_half.instantiate(); - PackedVector3Array &impact_points = MeshEditingLibrary::slice_mesh(original_mesh_instance, skeleton, this->full_aabb, local_slice_plane, first_half, other_half, MeshEditingLibrary::CAP_UV_FILL_MESH_BOUNDS, this->inner_materials); + PackedVector3Array &impact_points = MeshEditingLibrary::slice_mesh(original_mesh_instance, skeleton, this->_full_aabb, local_slice_plane, first_half, other_half, MeshEditingLibrary::CAP_UV_FILL_MESH_BOUNDS, this->inner_materials); if (first_half->get_surface_count() <= 0 && other_half->get_surface_count() > 0) { @@ -103,6 +115,13 @@ void Character3D::take_damage(const HurtboxDamage &hit_data) new_character_skeleton->set_meshes(other_half_meshes_to_add); } } + else + { + this->_hurtbox_queue.erase(this->_hurtbox_queue.begin()); + } + + if (!this->_hurtbox_queue.empty()) + CALL_NEXT_FRAME(callable_mp(this, &Character3D::_next_hurtbox_in_queue)); } @@ -114,34 +133,28 @@ void Character3D::_on_fell_out_of_world() void Character3D::_rebuild_mesh_instances() { - if (!this->is_node_ready()) return; + if (!this->character_skeleton || !this->is_node_ready()) + return; - uint16_t num_mesh_instances = this->_mesh_instances.size(); - for (uint16_t i = 0; i < num_mesh_instances; i++) + std::vector mesh_instances = this->character_skeleton->set_meshes(this->meshes); + const uint32_t num_meshes = mesh_instances.size(); + this->_full_aabb = AABB(); + for (const MeshInstance3D *mesh_instance : mesh_instances) { - this->_mesh_instances[i]->queue_free(); - } - - if (!this->character_skeleton) return; - - this->_mesh_instances = this->character_skeleton->set_meshes(this->meshes); - const uint32_t num_meshes = this->_mesh_instances.size(); - for (const MeshInstance3D *mesh_instance : this->_mesh_instances) - { - const Vector3 &full_aabb_position = this->full_aabb.get_position(); - const Vector3 &full_aabb_size = this->full_aabb.get_size(); + const Vector3 &full_aabb_position = this->_full_aabb.get_position(); + const Vector3 &full_aabb_size = this->_full_aabb.get_size(); const AABB &aabb = mesh_instance->get_aabb(); const Vector3 &aabb_position = aabb.get_position(); const Vector3 &aabb_size = aabb.get_size(); - this->full_aabb.set_position(Vector3( + this->_full_aabb.set_position(Vector3( UtilityFunctions::minf(full_aabb_position.x, aabb_position.x), UtilityFunctions::minf(full_aabb_position.y, aabb_position.y), UtilityFunctions::minf(full_aabb_position.z, aabb_position.z) )); - this->full_aabb.set_size(Vector3( + this->_full_aabb.set_size(Vector3( UtilityFunctions::maxf(full_aabb_position.x, aabb_size.x), UtilityFunctions::maxf(full_aabb_position.y, aabb_size.y), UtilityFunctions::maxf(full_aabb_position.z, aabb_size.z) diff --git a/src/liborng/nodes/character_nodes/character_3d.h b/src/liborng/nodes/character_nodes/character_3d.h index 9c878fe..c2fb51d 100644 --- a/src/liborng/nodes/character_nodes/character_3d.h +++ b/src/liborng/nodes/character_nodes/character_3d.h @@ -47,15 +47,15 @@ protected: private: void _rebuild_mesh_instances(); + void _next_hurtbox_in_queue(); TypedArray meshes; CharacterSkeleton3D *character_skeleton = nullptr; - AABB full_aabb; + AABB _full_aabb; TypedArray inner_materials; - std::vector _mesh_instances; - std::vector skeleton_list; + std::vector _hurtbox_queue; // Godot boilerplate below protected: diff --git a/src/liborng/nodes/character_nodes/character_skeleton3d.cpp b/src/liborng/nodes/character_nodes/character_skeleton3d.cpp index d8ff732..9204a5b 100644 --- a/src/liborng/nodes/character_nodes/character_skeleton3d.cpp +++ b/src/liborng/nodes/character_nodes/character_skeleton3d.cpp @@ -9,6 +9,8 @@ #include "orng_macros.h" +#include +#include #include #include using namespace godot; @@ -18,27 +20,30 @@ std::vector CharacterSkeleton3D::set_meshes(TypedArrayskeleton) { - uint16_t num_mesh_instances = this->_mesh_instances.size(); - for (uint16_t i = 0; i < num_mesh_instances; i++) - { - this->_mesh_instances[i]->queue_free(); - } + this->_old_mesh_instances = this->_mesh_instances; this->_mesh_instances.clear(); uint16_t num_new_meshes = meshes.size(); for (uint16_t i = 0; i < num_new_meshes; i++) { MeshInstance3D *mesh_instance = memnew(MeshInstance3D); - this->skeleton->add_child(mesh_instance, false, Node::INTERNAL_MODE_BACK); - mesh_instance->set_owner(this->get_owner()); mesh_instance->set_mesh(meshes[i]); mesh_instance->set_skeleton_path(this->skeleton->get_path()); + this->skeleton->add_child(mesh_instance, false, Node::INTERNAL_MODE_BACK); this->_mesh_instances.emplace_back(mesh_instance); } + + CALL_NEXT_FRAME(callable_mp(this, &CharacterSkeleton3D::_delete_old_meshes)); } return this->_mesh_instances; } +void CharacterSkeleton3D::_delete_old_meshes() +{ + for (MeshInstance3D *old_mesh : this->_old_mesh_instances) + old_mesh->queue_free(); + this->_old_mesh_instances.clear(); +} void CharacterSkeleton3D::_activate_ragdoll() diff --git a/src/liborng/nodes/character_nodes/character_skeleton3d.h b/src/liborng/nodes/character_nodes/character_skeleton3d.h index 8bd6b8f..7a77049 100644 --- a/src/liborng/nodes/character_nodes/character_skeleton3d.h +++ b/src/liborng/nodes/character_nodes/character_skeleton3d.h @@ -43,7 +43,8 @@ protected: void set_animation_tree(AnimationTree *at) { this->animation_tree = at; } private: - void _refresh_skins_and_meshes(); + // void _refresh_skins_and_meshes(); + void _delete_old_meshes(); void _activate_ragdoll(); @@ -53,6 +54,7 @@ private: AnimationTree *animation_tree = nullptr; std::vector _mesh_instances; + std::vector _old_mesh_instances; // Godot boilerplate below protected: diff --git a/src/liborng/nodes/hurtbox/hurtbox_base.cpp b/src/liborng/nodes/hurtbox/hurtbox_base.cpp index 7e5a65c..115ef19 100644 --- a/src/liborng/nodes/hurtbox/hurtbox_base.cpp +++ b/src/liborng/nodes/hurtbox/hurtbox_base.cpp @@ -17,6 +17,8 @@ #include using namespace godot; +#include + void HurtboxBase::_enter_tree() { @@ -58,7 +60,7 @@ void HurtboxBase::_physics_process(double delta) const TypedArray &bodies = this->get_overlapping_bodies(); const uint32_t num_bodies = bodies.size(); - std::vector new_hit_bodies; + std::unordered_set new_hit_bodies; std::vector new_hit_skeletons; for (uint32_t i = 0; i < num_bodies; i++) @@ -71,7 +73,7 @@ void HurtboxBase::_physics_process(double delta) { if (std::find(this->hit_bodies.begin(), this->hit_bodies.end(), body) == this->hit_bodies.end()) { - new_hit_bodies.emplace_back(body); + new_hit_bodies.emplace(body); if (std::find(new_hit_skeletons.begin(), new_hit_skeletons.end(), character_skeleton) == new_hit_skeletons.end()) { @@ -110,12 +112,32 @@ void HurtboxBase::_send_next_in_queue() { if (!this->hit_data_queue.empty()) { - const std::map>::iterator &first_in_queue = this->hit_data_queue.begin(); - for (const HurtboxDamage &damage : first_in_queue->second) + IDamageable *closest_damageable = nullptr; + float shortest_distance_from_hurtbox = FLT_MAX; + bool found_character_3d = false; + for (const auto &[damageable, hit_data_list] : this->hit_data_queue) { - first_in_queue->first->take_damage(damage); + if (const Character3D *node = (Character3D*)(damageable)) + { + const float distance_to_hurtbox = node->get_global_position().distance_squared_to(this->get_global_position()); + if (distance_to_hurtbox < shortest_distance_from_hurtbox) + { + closest_damageable = damageable; + shortest_distance_from_hurtbox = distance_to_hurtbox; + found_character_3d = true; + } + // if (!found_character_3d && const SliceablePhysicsObject3D *node = (SliceablePhysicsObject3D*)(damageable) ) + // { + // // This is where we handle regular physics objects. + // } + } + } + if (closest_damageable) + { + for (const HurtboxDamage &damage : this->hit_data_queue[closest_damageable]) + closest_damageable->take_damage(damage); + this->hit_data_queue.erase(closest_damageable); } - this->hit_data_queue.erase(this->hit_data_queue.begin()); } if (this->hit_data_queue.empty() && this->remaining_life <= 0.0f)