Movement manager add

This commit is contained in:
KimLS 2018-09-17 14:32:36 -07:00
parent c677169edd
commit 2224b83ae0
15 changed files with 342 additions and 127 deletions

View File

@ -92,6 +92,8 @@ Client::Client(EQStreamInterface* ieqs)
connect(1000),
eqs(ieqs)
{
//mMovementManager->AddClient(this);
// Live does not send datarate as of 3/11/2005
//eqs->SetDataRate(7);
ip = eqs->GetRemoteIP();

View File

@ -82,6 +82,7 @@ SET(zone_sources
merc.cpp
mob.cpp
mob_ai.cpp
mob_movement_manager.cpp
mod_functions.cpp
net.cpp
npc.cpp
@ -204,6 +205,7 @@ SET(zone_headers
message.h
merc.h
mob.h
mob_movement_manager.h
net.h
npc.h
npc_ai.h

View File

@ -53,6 +53,7 @@ extern volatile bool RunLoops;
#include "guild_mgr.h"
#include "quest_parser_collection.h"
#include "queryserv.h"
#include "mob_movement_manager.h"
extern QueryServ* QServ;
extern EntityList entity_list;
@ -156,7 +157,6 @@ Client::Client(EQStreamInterface* ieqs)
m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f),
last_region_type(RegionTypeUnsupported),
m_dirtyautohaters(false),
npc_close_scan_timer(6000),
hp_self_update_throttle_timer(300),
hp_other_update_throttle_timer(500),
position_update_timer(10000),
@ -166,6 +166,7 @@ Client::Client(EQStreamInterface* ieqs)
for (int client_filter = 0; client_filter < _FilterCount; client_filter++)
ClientFilters[client_filter] = FilterShow;
mMovementManager->AddClient(this);
character_id = 0;
conn_state = NoPacketsReceived;
client_data_loaded = false;
@ -339,6 +340,8 @@ Client::Client(EQStreamInterface* ieqs)
}
Client::~Client() {
mMovementManager->RemoveClient(this);
#ifdef BOTS
Bot::ProcessBotOwnerRefDelete(this);
#endif
@ -6464,7 +6467,7 @@ void Client::LocateCorpse()
SetHeading(CalculateHeadingToTarget(ClosestCorpse->GetX(), ClosestCorpse->GetY()));
SetTarget(ClosestCorpse);
SendTargetCommand(ClosestCorpse->GetID());
SendPositionUpdate(2);
SendPositionUpdate(true);
}
else if(!GetTarget())
Message_StringID(clientMessageError, SENSE_CORPSE_NONE);

View File

@ -1534,13 +1534,11 @@ private:
Timer afk_toggle_timer;
Timer helm_toggle_timer;
Timer aggro_meter_timer;
Timer npc_close_scan_timer;
Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */
Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
glm::vec3 m_Proximity;
glm::vec4 last_major_update_position;
void BulkSendInventoryItems();

View File

@ -4622,10 +4622,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u",
client_scan_npc_aggro_timer.GetDuration());
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
npc_close_scan_timer.Disable();
npc_close_scan_timer.Start(500);
client_scan_npc_aggro_timer.Disable();
client_scan_npc_aggro_timer.Start(500);
@ -4634,10 +4630,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
client_scan_npc_aggro_timer.GetDuration());
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
npc_close_scan_timer.Disable();
npc_close_scan_timer.Start(6000);
client_scan_npc_aggro_timer.Disable();
client_scan_npc_aggro_timer.Start(3000);
}

View File

@ -242,47 +242,6 @@ bool Client::Process() {
}
}
///* Build a close range list of NPC's */
//if (npc_close_scan_timer.Check()) {
// close_mobs.clear();
//
// /* Force spawn updates when traveled far */
// bool force_spawn_updates = false;
// float client_update_range = (RuleI(Range, ClientForceSpawnUpdateRange) * RuleI(Range, ClientForceSpawnUpdateRange));
// if (DistanceSquared(last_major_update_position, m_Position) >= client_update_range) {
// last_major_update_position = m_Position;
// force_spawn_updates = true;
// }
//
// float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan));
// auto &mob_list = entity_list.GetMobList();
// for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) {
// Mob* mob = itr->second;
//
// float distance = DistanceSquared(m_Position, mob->GetPosition());
// if (mob->IsNPC()) {
// if (distance <= scan_range) {
// close_mobs.insert(std::pair<Mob *, float>(mob, distance));
// }
// else if ((mob->GetAggroRange() * mob->GetAggroRange()) > scan_range) {
// close_mobs.insert(std::pair<Mob *, float>(mob, distance));
// }
// }
//
// if (force_spawn_updates && mob != this) {
//
// if (mob->is_distance_roamer) {
// mob->SendPositionUpdateToClient(this);
// continue;
// }
//
// if (distance <= client_update_range)
// mob->SendPositionUpdateToClient(this);
// }
//
// }
//}
bool may_use_attacks = false;
/*
Things which prevent us from attacking:
@ -460,7 +419,7 @@ bool Client::Process() {
{
animation = 0;
m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w);
SendPositionUpdate(2);
SendPositionUpdate(true);
}
}

View File

@ -23,6 +23,7 @@
#include "quest_parser_collection.h"
#include "string_ids.h"
#include "worldserver.h"
#include "mob_movement_manager.h"
#include <limits.h>
#include <math.h>
@ -116,12 +117,12 @@ Mob::Mob(const char* in_name,
position_update_melee_push_timer(500),
hate_list_cleanup_timer(6000)
{
mMovementManager = &MobMovementManager::Get();
mMovementManager->AddMob(this);
targeted = 0;
currently_fleeing = false;
last_major_update_position = m_Position;
is_distance_roamer = false;
AI_Init();
SetMoving(false);
moved = false;
@ -448,6 +449,8 @@ Mob::Mob(const char* in_name,
Mob::~Mob()
{
mMovementManager->RemoveMob(this);
AI_Stop();
if (GetPet()) {
if (GetPet()->Charmed())
@ -1450,59 +1453,12 @@ void Mob::StopMoving(float new_heading) {
/* Used for mobs standing still - this does not send a delta */
void Mob::SendPosition() {
//auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
//PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
//MakeSpawnUpdateNoDelta(spu);
//
//entity_list.QueueCloseClients(this, app, true, 200.0f, nullptr, false);
//
///* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */
//if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) {
// entity_list.QueueClients(this, app, true, true);
// last_major_update_position = m_Position;
// is_distance_roamer = true;
//}
//else {
// entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false);
//}
//
//safe_delete(app);
}
void Mob::SendPositionUpdateToClient(Client *client) {
//auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
//PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
//
//if(this->IsMoving())
// MakeSpawnUpdate(spawn_update);
//else
// MakeSpawnUpdateNoDelta(spawn_update);
//
//client->QueuePacket(app, false);
//
//safe_delete(app);
mMovementManager->SendPosition(this);
}
/* Position updates for mobs on the move */
void Mob::SendPositionUpdate(uint8 iSendToSelf) {
//auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
//PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
//MakeSpawnUpdate(spu);
//
//if (iSendToSelf == 2) {
// if (IsClient()) {
// CastToClient()->FastQueuePacket(&app, false);
// }
//}
//else if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) {
// entity_list.QueueClients(this, app, true, true);
// last_major_update_position = m_Position;
// is_distance_roamer = true;
//}
//else {
// entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false);
//}
//safe_delete(app);
void Mob::SendPositionUpdate(bool iSendToSelf) {
mMovementManager->SendPositionUpdate(this, iSendToSelf);
}
// this is for SendPosition()
@ -1518,11 +1474,6 @@ void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu) {
spu->heading = FloatToEQ12(m_Position.w);
spu->animation = 0;
spu->delta_heading = FloatToEQ10(0);
spu->padding0002 = 0;
spu->padding0006 = 7;
spu->padding0014 = 0x7f;
spu->padding0018 = 0x5df27;
}
// this is for SendPosUpdate()
@ -1535,10 +1486,6 @@ void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) {
spu->delta_y = FloatToEQ13(m_Delta.y);
spu->delta_z = FloatToEQ13(m_Delta.z);
spu->heading = FloatToEQ12(m_Position.w);
spu->padding0002 = 0;
spu->padding0006 = 7;
spu->padding0014 = 0x7f;
spu->padding0018 = 0x5df27;
#ifdef BOTS
if (this->IsClient() || this->IsBot())
#else

View File

@ -49,6 +49,7 @@ class Aura;
struct AuraRecord;
struct NewSpawn_Struct;
struct PlayerPositionUpdateServer_Struct;
class MobMovementManager;
const int COLLISION_BOX_SIZE = 8;
@ -164,8 +165,6 @@ public:
inline virtual bool IsMob() const { return true; }
inline virtual bool InZone() const { return true; }
bool is_distance_roamer;
//Somewhat sorted: needs documenting!
//Attack
@ -559,8 +558,7 @@ public:
void SetRunning(bool val) { m_is_running = val; }
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true);
void SetDelta(const glm::vec4& delta);
void SendPositionUpdateToClient(Client *client);
void SendPositionUpdate(uint8 iSendToSelf = 0);
void SendPositionUpdate(bool iSendToSelf = false);
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
void SendPosition();
@ -802,6 +800,7 @@ public:
void SendAppearancePacket(uint32 type, uint32 value, bool WholeZone = true, bool iIgnoreSelf = false, Client *specific_target=nullptr);
void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true);
inline EmuAppearance GetAppearance() const { return _appearance; }
inline const int GetAnimation() const { return animation; }
inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; }
inline void SetRunAnimSpeed(int8 in) { if (pRunAnimSpeed != in) { pRunAnimSpeed = in; } }
bool IsDestructibleObject() { return destructibleobject; }
@ -1247,8 +1246,6 @@ protected:
uint8 orig_level;
uint32 npctype_id;
glm::vec4 m_Position;
/* Used to determine when an NPC has traversed so many units - to send a zone wide pos update */
glm::vec4 last_major_update_position;
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
float base_size;
@ -1530,6 +1527,8 @@ protected:
AuraMgr aura_mgr;
AuraMgr trap_mgr;
MobMovementManager *mMovementManager;
private:
void _StopSong(); //this is not what you think it is
Mob* target;

View File

@ -0,0 +1,259 @@
#include "mob_movement_manager.h"
#include "client.h"
#include "mob.h"
#include "../common/timer.h"
#include <vector>
#include <stdlib.h>
struct MobMovementEntry
{
Mob *m;
int animation;
float heading;
bool dirty;
double last_sent_time;
double last_sent_time_long_distance;
MobMovementEntry(Mob *m) {
this->m = m;
animation = 0;
heading = m->GetHeading();
dirty = false;
last_sent_time = 0.0;
last_sent_time_long_distance = 0.0;
}
};
struct MobMovementManager::Implementation
{
std::vector<MobMovementEntry> Entries;
std::vector<Client*> Clients;
};
MobMovementManager::MobMovementManager()
{
_impl.reset(new Implementation());
}
MobMovementManager::~MobMovementManager()
{
}
void MobMovementManager::Process()
{
double current_time = static_cast<double>(Timer::GetCurrentTime()) / 1000.0;
for (auto &ent : _impl->Entries) {
if (ent.dirty) {
SendUpdate(ent.m, ent.animation, ent.heading);
ent.dirty = false;
ent.last_sent_time = current_time;
ent.last_sent_time_long_distance = current_time;
} else if (ent.animation != 0) {
double diff_short_range = current_time - ent.last_sent_time;
double diff_long_range = current_time - ent.last_sent_time_long_distance;
if (diff_short_range >= 2.0) {
SendUpdateShortDistance(ent.m, ent.animation, ent.heading);
ent.last_sent_time = current_time;
}
if (diff_long_range >= 6.0) {
SendUpdateLongDistance(ent.m, ent.animation, ent.heading);
ent.last_sent_time_long_distance = current_time;
}
}
}
}
void MobMovementManager::AddMob(Mob *m)
{
_impl->Entries.push_back(MobMovementEntry(m));
}
void MobMovementManager::RemoveMob(Mob *m)
{
auto iter = _impl->Entries.begin();
while (iter != _impl->Entries.end()) {
auto &ent = *iter;
if (ent.m == m) {
_impl->Entries.erase(iter);
return;
}
++iter;
}
}
void MobMovementManager::AddClient(Client *c)
{
_impl->Clients.push_back(c);
}
void MobMovementManager::RemoveClient(Client *c)
{
auto iter = _impl->Clients.begin();
while (iter != _impl->Clients.end()) {
if (c == *iter) {
_impl->Clients.erase(iter);
return;
}
++iter;
}
}
void MobMovementManager::SendPosition(Mob *who)
{
auto iter = _impl->Entries.begin();
while (iter != _impl->Entries.end()) {
auto &ent = *iter;
if (ent.m == who) {
auto anim = 0;
auto heading = who->GetHeading();
if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) {
ent.animation = anim;
ent.heading = heading;
ent.dirty = true;
}
return;
}
++iter;
}
}
void MobMovementManager::SendPositionUpdate(Mob *who, bool send_to_self)
{
auto iter = _impl->Entries.begin();
while (iter != _impl->Entries.end()) {
auto &ent = *iter;
if (ent.m == who) {
auto anim = 0;
auto heading = who->GetHeading();
if (who->IsMoving()) {
if (who->IsClient()) {
anim = who->GetAnimation();
}
else {
anim = who->GetRunAnimSpeed();
}
}
if (send_to_self && who->IsClient()) {
SendUpdateTo(who, who->CastToClient(), anim, heading);
}
if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) {
ent.animation = anim;
ent.heading = heading;
ent.dirty = true;
}
return;
}
++iter;
}
}
bool MobMovementManager::HeadingEqual(float a, float b)
{
const float eps = 0.001f;
return abs(a - b) < eps;
}
void MobMovementManager::SendUpdateTo(Mob *who, Client *c, int anim, float heading)
{
EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer;
if (anim == 0) {
who->MakeSpawnUpdateNoDelta(spu);
}
else {
who->MakeSpawnUpdate(spu);
}
c->QueuePacket(&outapp);
}
void MobMovementManager::SendUpdate(Mob *who, int anim, float heading)
{
EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer;
if (anim == 0) {
who->MakeSpawnUpdateNoDelta(spu);
}
else {
who->MakeSpawnUpdate(spu);
}
for (auto &c : _impl->Clients) {
if (c != who) {
c->QueuePacket(&outapp);
}
else if (c->IsAIControlled()) {
c->QueuePacket(&outapp);
}
}
}
void MobMovementManager::SendUpdateShortDistance(Mob *who, int anim, float heading)
{
EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer;
if (anim == 0) {
who->MakeSpawnUpdateNoDelta(spu);
}
else {
who->MakeSpawnUpdate(spu);
}
for (auto &c : _impl->Clients) {
if (c != who) {
auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ());
if (dist <= 1000.0f) {
c->QueuePacket(&outapp);
}
}
else if (c->IsAIControlled()) {
auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ());
if (dist <= 1000.0f) {
c->QueuePacket(&outapp);
}
}
}
}
void MobMovementManager::SendUpdateLongDistance(Mob *who, int anim, float heading)
{
EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer;
if (anim == 0) {
who->MakeSpawnUpdateNoDelta(spu);
}
else {
who->MakeSpawnUpdate(spu);
}
for (auto &c : _impl->Clients) {
if (c != who) {
auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ());
if (dist > 1000.0f) {
c->QueuePacket(&outapp);
}
}
else if (c->IsAIControlled()) {
auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ());
if (dist > 1000.0f) {
c->QueuePacket(&outapp);
}
}
}
}

View File

@ -0,0 +1,38 @@
#pragma once
#include <memory>
class Mob;
class Client;
class MobMovementManager
{
public:
~MobMovementManager();
void Process();
void AddMob(Mob *m);
void RemoveMob(Mob *m);
void AddClient(Client *c);
void RemoveClient(Client *c);
void SendPosition(Mob *who);
void SendPositionUpdate(Mob *who, bool send_to_self);
static MobMovementManager &Get() {
static MobMovementManager inst;
return inst;
}
private:
MobMovementManager();
MobMovementManager(const MobMovementManager&);
MobMovementManager& operator=(const MobMovementManager&);
bool HeadingEqual(float a, float b);
void SendUpdateTo(Mob *who, Client *c, int anim, float heading);
void SendUpdate(Mob *who, int anim, float heading);
void SendUpdateShortDistance(Mob *who, int anim, float heading);
void SendUpdateLongDistance(Mob *who, int anim, float heading);
struct Implementation;
std::unique_ptr<Implementation> _impl;
};

View File

@ -1189,7 +1189,7 @@ XS(XS_Mob_SendPosUpdate) {
iSendToSelf = (uint8) SvUV(ST(1));
}
THIS->SendPositionUpdate(iSendToSelf);
THIS->SendPositionUpdate(iSendToSelf != 0 ? true : false);
}
XSRETURN_EMPTY;
}

View File

@ -853,7 +853,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
SetHeading(CalculateHeadingToTarget(ClosestMob->GetX(), ClosestMob->GetY()));
SetTarget(ClosestMob);
CastToClient()->SendTargetCommand(ClosestMob->GetID());
SendPositionUpdate(2);
SendPositionUpdate(true);
}
else
Message_StringID(clientMessageError, SENSE_NOTHING);

View File

@ -463,7 +463,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b
if (IsClient())
#endif
{
animation = speed / 2;
animation = speed * 0.55f;
}
//Setup Vectors
@ -481,7 +481,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b
}
double time_since_last = static_cast<double>(frame_time) / 1000.0;
double distance_moved = time_since_last * (speed + 100.0f);
double distance_moved = time_since_last * speed * 2.275f;
if (distance_moved > len) {
m_Position.x = x;
@ -492,6 +492,10 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b
entity_list.ProcessMove(CastToNPC(), x, y, z);
}
if (check_z && fix_z_timer.Check() && (!IsEngaged() || flee_mode || currently_fleeing)) {
FixZ();
}
return true;
}
else {
@ -505,11 +509,15 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b
}
}
if (check_z && fix_z_timer.Check() && !IsEngaged()) {
FixZ();
}
SetMoving(true);
m_Delta = glm::vec4(m_Position.x - pos.x, m_Position.y - pos.y, m_Position.z - pos.z, 0.0f);
if (IsClient()) {
SendPositionUpdate(1);
SendPositionUpdate();
CastToClient()->ResetPositionTimer();
}
else {

View File

@ -53,6 +53,7 @@
#include "worldserver.h"
#include "zone.h"
#include "zone_config.h"
#include "mob_movement_manager.h"
#include <time.h>
#include <ctime>
@ -861,6 +862,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
m_ucss_available = false;
m_last_ucss_update = 0;
mMovementManager = &MobMovementManager::Get();
}
Zone::~Zone() {
@ -1303,6 +1306,8 @@ bool Zone::Process() {
if(hotzone_timer.Check()) { UpdateHotzone(); }
mMovementManager->Process();
return true;
}

View File

@ -79,6 +79,7 @@ class WaterMap;
extern EntityList entity_list;
struct NPCType;
struct ServerZoneIncomingClient_Struct;
class MobMovementManager;
class Zone
{
@ -362,6 +363,8 @@ private:
bool m_ucss_available;
uint32 m_last_ucss_update;
MobMovementManager *mMovementManager;
};
#endif