#include "precompile.h" #include #include #include "movement.h" #include "moveableentity.h" #include "room.h" #include "mapinstance.h" #include "creature.h" #include "mt/Map.h" Movement::Movement(Creature* owner) { owner_ = owner; } bool Movement::UpdatePosition() { if (path_index_ >= paths_.size()) { ClearPath(); is_find_path_ = false; return false; } MovePathPoint& curr_point = paths_[path_index_]; { curr_point.curr_pos.AddGlmVec3(curr_point.dir * owner_->GetSpeed()); owner_->SetPos(curr_point.curr_pos); owner_->room->map_instance->CheckTerrain(owner_, curr_point.same_polys_flags, curr_point.spec_polys); } if (owner_->GetPos().Distance2D2(curr_point.src_pos) - curr_point.distance >= 0.0001f) { curr_point.tar_pos.SetY(curr_point.curr_pos.GetY()); owner_->SetPos(curr_point.tar_pos); ++path_index_; if (path_index_ < paths_.size()) { MovePathPoint& next_point = paths_[path_index_]; glm::vec3 dir = next_point.tar_pos.ToGlmVec3() - owner_->GetPos().ToGlmVec3(); GlmHelper::Normalize(dir); next_point.dir.x = dir.x; next_point.dir.y = dir.y; next_point.dir.z = dir.z; } } owner_->AdjustPos(); #if 0 if (owner_->GetPos().GetX() < 0 || owner_->GetPos().GetZ() < 0) { abort(); } #endif return true; } void Movement::CalcTargetPos(float distance) { ClearPath(); #ifdef DEBUG1 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 = pos.AddGlmVec3(owner_->GetMoveDir() * distance).ToGlmVec3(); 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; } 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; } if (point.tar_pos.GetX() < 0 || point.tar_pos.GetZ() < 0) { abort(); } } 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 DEBUG1 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; } 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); } void Movement::ClearPath() { is_find_path_ = false; path_index_ = 0; paths_.clear(); } void Movement::AddPaths(const glm::vec3& start, std::vector& paths) { if (paths.empty()) { abort(); return; } glm::vec3 last_pos; last_pos.x = start.x; last_pos.y = start.y; last_pos.z = start.z; size_t i = 0; if (std::abs(last_pos.x - paths[0].x) < 0.00001f && std::abs(last_pos.z - paths[0].z) < 0.00001f) { if (paths.size() < 2) { abort(); } ++i; } for (; i < paths.size(); ++i) { MovePathPoint p; p.src_pos.FromGlmVec3(owner_->room->map_instance->UnScaleEx(last_pos)); p.tar_pos.FromGlmVec3(owner_->room->map_instance->UnScaleEx(paths[i])); p.dir = p.tar_pos.ToGlmVec3() - p.src_pos.ToGlmVec3(); GlmHelper::Normalize(p.dir); p.curr_pos = p.src_pos; last_pos = paths[i]; #ifdef DEBUG1 a8::XPrintf("AddPaths size:%d i:%d src_pos:%f,%f tar_pos:%f:%f\n", { paths.size(), i, src_pos.x, src_pos.y, tar_pos.x, tar_pos.y}); #endif paths_.push_back(p); } is_find_path_ = true; } size_t Movement::GetPathSize() { return paths_.size(); }