Extended Movement Manager to have a FlyTo

This commit is contained in:
Noudess 2020-04-30 11:35:09 -04:00
parent 855e592d22
commit 2bcaf2a476
2 changed files with 165 additions and 0 deletions

View File

@ -263,6 +263,146 @@ protected:
double m_total_v_dist;
};
class FlyToCommand : public IMovementCommand {
public:
FlyToCommand(float x, float y, float z, MobMovementMode mob_movement_mode)
{
m_distance_moved_since_correction = 0.0;
m_move_to_x = x;
m_move_to_y = y;
m_move_to_z = z;
m_move_to_mode = mob_movement_mode;
m_last_sent_time = 0.0;
m_last_sent_speed = 0;
m_started = false;
m_total_h_dist = 0.0;
m_total_v_dist = 0.0;
}
virtual ~FlyToCommand()
{
}
/**
* @param mob_movement_manager
* @param mob
* @return
*/
virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
{
if (!mob->IsAIControlled()) {
return true;
}
//Send a movement packet when you start moving
double current_time = static_cast<double>(Timer::GetCurrentTime()) / 1000.0;
int current_speed = 0;
if (m_move_to_mode == MovementRunning) {
if (mob->IsFeared()) {
current_speed = mob->GetFearSpeed();
}
else {
current_speed = mob->GetRunspeed();
}
}
else {
current_speed = mob->GetWalkspeed();
}
if (!m_started) {
m_started = true;
//rotate to the point
mob->SetMoving(true);
mob->SetHeading(mob->CalculateHeadingToTarget(m_move_to_x, m_move_to_y));
m_last_sent_speed = current_speed;
m_last_sent_time = current_time;
m_total_h_dist = DistanceNoZ(mob->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f));
m_total_v_dist = m_move_to_z - mob->GetZ();
mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
//When speed changes
if (current_speed != m_last_sent_speed) {
m_distance_moved_since_correction = 0.0;
m_last_sent_speed = current_speed;
m_last_sent_time = current_time;
mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
//If x seconds have passed without sending an update.
if (current_time - m_last_sent_time >= 0.5) {
m_distance_moved_since_correction = 0.0;
m_last_sent_speed = current_speed;
m_last_sent_time = current_time;
mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
auto &p = mob->GetPosition();
glm::vec2 tar(m_move_to_x, m_move_to_y);
glm::vec2 pos(p.x, p.y);
double len = glm::distance(pos, tar);
if (len == 0) {
return true;
}
mob->SetMoved(true);
glm::vec2 dir = tar - pos;
glm::vec2 ndir = glm::normalize(dir);
double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
if (distance_moved > len) {
if (mob->IsNPC()) {
entity_list.ProcessMove(mob->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z);
}
mob->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z);
if (RuleB(Map, FixZWhenPathing)) {
mob->FixZ();
}
return true;
}
else {
glm::vec2 npos = pos + (ndir * static_cast<float>(distance_moved));
len -= distance_moved;
double total_distance_traveled = m_total_h_dist - len;
double start_z = m_move_to_z - m_total_v_dist;
double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist));
if (mob->IsNPC()) {
entity_list.ProcessMove(mob->CastToNPC(), npos.x, npos.y, z_at_pos);
}
mob->SetPosition(npos.x, npos.y, z_at_pos);
}
return false;
}
virtual bool Started() const
{
return m_started;
}
protected:
double m_distance_moved_since_correction;
double m_move_to_x;
double m_move_to_y;
double m_move_to_z;
MobMovementMode m_move_to_mode;
bool m_started;
double m_last_sent_time;
int m_last_sent_speed;
double m_total_h_dist;
double m_total_v_dist;
};
class SwimToCommand : public MoveToCommand {
public:
SwimToCommand(float x, float y, float z, MobMovementMode mob_movement_mode) : MoveToCommand(x, y, z, mob_movement_mode)
@ -921,6 +1061,8 @@ void MobMovementManager::FillCommandStruct(
*/
void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode)
{
Mob *target=who->GetTarget();
if (!zone->HasMap() || !zone->HasWaterMap()) {
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
@ -936,6 +1078,16 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove
else if (who->IsUnderwaterOnly()) {
UpdatePathUnderwater(who, x, y, z, mob_movement_mode);
}
// If we can fly, and we have a target and we have LoS, simply fly to them.
// if we ever lose LoS we go back to mesh run mode.
else if (target && who->GetFlyMode() == GravityBehavior::Flying &&
who->CheckLosFN(x,y,z,target->GetSize())) {
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
PushFlyTo(ent.second, x, y, z, mob_movement_mode);
PushStopMoving(ent.second);
}
else {
UpdatePathGround(who, x, y, z, mob_movement_mode);
}
@ -1275,6 +1427,18 @@ void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to,
ent.Commands.push_back(std::unique_ptr<IMovementCommand>(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mob_movement_mode)));
}
/**
* @param ent
* @param x
* @param y
* @param z
* @param mob_movement_mode
*/
void MobMovementManager::PushFlyTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode)
{
ent.Commands.push_back(std::unique_ptr<IMovementCommand>(new FlyToCommand(x, y, z, mob_movement_mode)));
}
/**
* @param mob_movement_entry
*/

View File

@ -85,6 +85,7 @@ private:
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
void PushFlyTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode);
void PushStopMoving(MobMovementEntry &mob_movement_entry);
void PushEvadeCombat(MobMovementEntry &mob_movement_entry);