game2006/server/gameserver/movement.cc
aozhiwei 89c5b1d7c7 1
2022-12-28 15:00:52 +08:00

281 lines
7.5 KiB
C++

#include "precompile.h"
#include <math.h>
#include <glm/glm.hpp>
#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_];
{
a8::Vec2 dir = a8::Vec2(curr_point.dir.x, curr_point.dir.z);
float h = 0.0f;
if (owner_->room->map_instance->GetPosHeight(curr_point.curr_pos, h)) {
#ifdef DEBUG1
a8::XPrintf("pos:%f,%f,%f h1:%f\n",
{
owner_->GetPos().x,
owner_->GetPos().y,
owner_->GetPos().z,
h
});
#endif
curr_point.curr_pos.y = h;
} else {
//abort();
}
curr_point.curr_pos.AddVec2(dir * owner_->GetSpeed());
owner_->SetPos(curr_point.curr_pos);
if (owner_->room->map_instance->GetPosHeight(owner_->GetPos(), h)) {
#ifdef DEBUG1
a8::XPrintf("pos:%f,%f,%f h2:%f\n",
{
owner_->GetPos().x,
owner_->GetPos().y,
owner_->GetPos().z,
h
});
#endif
auto new_pos = owner_->GetPos();
new_pos.y = h;
owner_->SetPos(new_pos);
} else {
//abort();
}
}
if (owner_->GetPos().Distance2D2(curr_point.src_pos) - curr_point.distance >= 0.0001f) {
curr_point.tar_pos.y = curr_point.curr_pos.y;
owner_->SetPos(curr_point.tar_pos);
float h = 0.0f;
if (owner_->room->map_instance->GetPosHeight(owner_->GetPos(), h)) {
a8::XPrintf("pos:%f,%f,%f h3:%f\n",
{
owner_->GetPos().x,
owner_->GetPos().y,
owner_->GetPos().z,
h
});
auto new_pos = owner_->GetPos();
new_pos.y = h;
owner_->SetPos(new_pos);
} else {
//abort();
}
++path_index_;
if (path_index_ < paths_.size()) {
MovePathPoint& next_point = paths_[path_index_];
a8::Vec2 dir = owner_->GetPos().CalcDir2D(next_point.tar_pos);
dir.Normalize();
next_point.dir.x = dir.x;
next_point.dir.z = dir.y;
}
}
if (owner_->GetPos().x < 0 ||
owner_->GetPos().y < 0) {
abort();
}
return true;
}
void Movement::CalcTargetPos(float distance)
{
ClearPath();
#ifdef DEBUG1
if (!c->IsPlayer()) {
a8::XPrintf("CalcTaretPos old_size:%d\n", {paths_.size()});
}
#endif
Position pos = owner_->GetPos();
glm::vec3 start = owner_->GetPos().ToGlmVec3();
glm::vec3 end = pos.AddGlmVec3(owner_->GetMoveDir() * distance).ToGlmVec3();
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.x > owner_->room->GetMapMeta()->map_width() + 10) {
point.tar_pos.x = owner_->room->GetMapMeta()->map_width() - 10;
}
if (point.tar_pos.z > owner_->room->GetMapMeta()->map_height() + 10) {
point.tar_pos.z = owner_->room->GetMapMeta()->map_height() - 10;
}
if (point.tar_pos.x < 10) {
point.tar_pos.x = 10;
}
if (point.tar_pos.z < 10) {
point.tar_pos.z = 10;
}
} else {
glm::vec3 hit_point;
owner_->room->map_instance->Scale(start);
owner_->room->map_instance->Scale(end);
bool ret = owner_->room->map_instance->Raycast(0, start, end, hit_point, hit_result);
if (ret) {
owner_->room->map_instance->UnScale(hit_point);
point.tar_pos.FromGlmVec3(hit_point);
} else {
return;
}
}
point.distance = owner_->GetPos().Distance2D2(point.tar_pos);
point.src_pos = owner_->GetPos();
point.curr_pos = owner_->GetPos();
if (point.tar_pos.x < 0 ||
point.tar_pos.z < 0) {
abort();
}
#ifdef DEBUG
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.x,
point.src_pos.y,
point.src_pos.z,
point.tar_pos.x,
point.tar_pos.y,
point.tar_pos.z,
hit_result ? 1 : 0,
start.x,
start.y,
start.z,
end.x,
end.y,
end.z,
point.distance,
distance
});
}
#endif
if (point.distance < 0.00001f / owner_->room->GetMapMeta()->scale()) {
return;
}
a8::Vec2 dir = owner_->GetPos().CalcDir2D(point.tar_pos);
dir.Normalize();
point.dir.x = dir.x;
point.dir.z = dir.y;
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<glm::vec3>& paths)
{
#if 0
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 = last_pos;
p.src_pos.x *= 10.f;
p.src_pos.y *= 10.f;
p.src_pos.z *= 10.f;
p.tar_pos.x = paths[i].x * 10.f;
p.tar_pos.y = paths[i].y * 10.f;
p.tar_pos.z = paths[i].z * 10.f;
p.curr_pos = p.src_pos;
glm::vec2 src_pos;
glm::vec2 tar_pos;
src_pos.x = p.src_pos.x;
src_pos.y = p.src_pos.z;
tar_pos.x = p.tar_pos.x;
tar_pos.y = p.tar_pos.z;
{
a8::Vec2 v1;
a8::Vec2 v2;
v1.x = tar_pos.x;
v1.y = tar_pos.y;
v2.x = src_pos.x;
v2.y = src_pos.y;
p.distance = v1.Distance(v2);
}
glm::vec2 dir = tar_pos - src_pos;
dir = glm::normalize(dir);
if (isnan(dir.x)) {
abort();
}
if (isnan(dir.y)) {
abort();
}
p.dir.x = dir.x;
p.dir.y = 0;
p.dir.z = dir.y;
last_pos.x = paths[i].x;
last_pos.y = paths[i].y;
last_pos.z = paths[i].z;
#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);
}
#endif
is_find_path_ = true;
}
size_t Movement::GetPathSize()
{
return paths_.size();
}