mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
Extended Movement Manager to have a FlyTo
This commit is contained in:
parent
855e592d22
commit
2bcaf2a476
@ -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
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user