diff --git a/server/gameserver/movement.cc b/server/gameserver/movement.cc index 71e7c627..4fc7243b 100644 --- a/server/gameserver/movement.cc +++ b/server/gameserver/movement.cc @@ -293,5 +293,110 @@ void Movement::AdjustLastPath(float distance) bool Movement::MoveToPos(const glm::vec3& target_pos) { - return false; + ClearPath(); +#ifdef MYDEBUG1 + if (owner_->IsPlayer()) { + a8::XPrintf("CalcTaretPos old_size:%d distance:%f\n", {paths_.size(), distance}); + } +#endif + Position pos = owner_->GetPos(); + glm::vec3 start = owner_->GetPos().ToGlmVec3(); + glm::vec3 end = target_pos; + if (end.x < 0.0f) { + end.x = 0.0f; + } + if (end.z < 0.0f) { + end.z = 0.0f; + } + + bool hit_result = false; + MovePathPoint point; + if (owner_->HasBuffEffect(kBET_ThroughWall) || + owner_->HasBuffEffect(kBET_Fly) || + owner_->HasBuffEffect(kBET_Jump)) { + point.tar_pos.FromGlmVec3(end); + if (point.tar_pos.GetX() > owner_->room->GetMapMeta()->map_width() + 10) { + point.tar_pos.SetX(owner_->room->GetMapMeta()->map_width() - 10); + } + if (point.tar_pos.GetZ() > owner_->room->GetMapMeta()->map_height() + 10) { + point.tar_pos.SetZ(owner_->room->GetMapMeta()->map_height() - 10); + } + if (point.tar_pos.GetX() < 10) { + point.tar_pos.SetX(10); + } + if (point.tar_pos.GetZ() < 10) { + point.tar_pos.SetZ(10); + } + } else { + unsigned short exclude_flags = 0; + if (owner_->HasBuffEffect(kBET_Driver)) { + exclude_flags = SAMPLE_POLYFLAGS_DOOR | SAMPLE_POLYFLAGS_HOP; + } + glm::vec3 hit_point; + owner_->room->map_instance->Scale(start); + owner_->room->map_instance->Scale(end); + bool ret = owner_->room->map_instance->RaycastEx(start, end, hit_point, hit_result, + point.same_polys_flags, point.spec_polys, exclude_flags); + if (ret) { + owner_->room->map_instance->UnScale(hit_point); + point.tar_pos.FromGlmVec3(hit_point); + } else { + return false; + } + if (point.tar_pos.GetX() < 0 || + point.tar_pos.GetZ() < 0) { + return false; + #if 0 + abort(); + #endif + } + } + point.distance = owner_->GetPos().Distance2D2(point.tar_pos); + point.src_pos = owner_->GetPos(); + point.curr_pos = owner_->GetPos(); + + if (point.tar_pos.GetX() < 0 || + point.tar_pos.GetZ() < 0) { + abort(); + } +#ifdef MYDEBUG1 + if (owner_->IsPlayer()) { + a8::XPrintf("CalcTargetPos src_pos:%f,%f,%f tar_pos:%f,%f,%f is_hit:%d start:%f,%f,%f end:%f,%f,%f distance:%f src_distance:%f\n", + { + point.src_pos.GetX(), + point.src_pos.GetY(), + point.src_pos.GetZ(), + point.tar_pos.GetX(), + point.tar_pos.GetY(), + point.tar_pos.GetZ(), + hit_result ? 1 : 0, + + start.x, + start.y, + start.z, + + end.x, + end.y, + end.z, + point.distance, + distance + }); + } +#endif + + const float safe_distance = 2.0f; + if (point.distance < safe_distance + 1.0f / owner_->room->GetMapMeta()->scale()) { + return false; + } + + glm::vec3 dir = point.tar_pos.ToGlmVec3() - owner_->GetPos().ToGlmVec3(); + GlmHelper::Normalize(dir); + point.dir.x = dir.x; + point.dir.y = dir.y; + point.dir.z = dir.z; + point.distance -= safe_distance; + point.tar_pos.FromGlmVec3(owner_->GetPos().ToGlmVec3() + point.dir * point.distance); + + paths_.push_back(point); + return true; }