mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
281 lines
5.4 KiB
C++
281 lines
5.4 KiB
C++
#include "mob_movement_manager.h"
|
|
#include "client.h"
|
|
#include "mob.h"
|
|
#include "../common/eq_packet_structs.h"
|
|
#include "../common/misc_functions.h"
|
|
|
|
#include <vector>
|
|
#include <map>
|
|
#include <stdlib.h>
|
|
|
|
extern double frame_time;
|
|
|
|
struct RotateCommand
|
|
{
|
|
RotateCommand() {
|
|
rotate_to = 0.0;
|
|
rotate_to_speed = 0.0;
|
|
rotate_dir = 1.0;
|
|
active = false;
|
|
started = false;
|
|
}
|
|
|
|
double rotate_to;
|
|
double rotate_to_speed;
|
|
double rotate_dir;
|
|
bool active;
|
|
bool started;
|
|
};
|
|
|
|
struct MovementCommand
|
|
{
|
|
MovementCommand() {
|
|
move_to_x = 0.0;
|
|
move_to_y = 0.0;
|
|
move_to_z = 0.0;
|
|
move_to_speed = 0.0;
|
|
last_sent_short_distance = 0.0;
|
|
last_sent_medium_distance = 0.0;
|
|
last_sent_long_distance = 0.0;
|
|
active = false;
|
|
}
|
|
|
|
double move_to_x;
|
|
double move_to_y;
|
|
double move_to_z;
|
|
double move_to_speed;
|
|
double last_sent_short_distance;
|
|
double last_sent_medium_distance;
|
|
double last_sent_long_distance;
|
|
bool active;
|
|
};
|
|
|
|
struct MovementStats
|
|
{
|
|
MovementStats() {
|
|
TotalSent = 0ULL;
|
|
TotalSentMovement = 0ULL;
|
|
TotalSentPosition = 0ULL;
|
|
TotalSentHeading = 0ULL;
|
|
}
|
|
|
|
uint64_t TotalSent;
|
|
uint64_t TotalSentMovement;
|
|
uint64_t TotalSentPosition;
|
|
uint64_t TotalSentHeading;
|
|
};
|
|
|
|
struct MobMovementEntry
|
|
{
|
|
RotateCommand RotateCommand;
|
|
MovementCommand MoveCommand;
|
|
};
|
|
|
|
struct MobMovementManager::Implementation
|
|
{
|
|
std::map<Mob*, MobMovementEntry> Entries;
|
|
std::vector<Client*> Clients;
|
|
MovementStats Stats;
|
|
};
|
|
|
|
MobMovementManager::MobMovementManager()
|
|
{
|
|
_impl.reset(new Implementation());
|
|
}
|
|
|
|
void MobMovementManager::ProcessRotateCommand(Mob *m, RotateCommand &cmd)
|
|
{
|
|
if (m->IsEngaged()) {
|
|
auto to = FixHeading(cmd.rotate_to);
|
|
m->SetHeading(to);
|
|
SendCommandToAllClients(m, 0.0, 0.0, 0.0, 0.0, 0);
|
|
cmd.active = false;
|
|
return;
|
|
}
|
|
|
|
if (!cmd.started) {
|
|
cmd.started = true;
|
|
|
|
SendCommandToAllClients(m, 0.0, 0.0, 0.0, cmd.rotate_dir * cmd.rotate_to_speed, 0);
|
|
}
|
|
|
|
auto from = FixHeading(m->GetHeading());
|
|
auto to = FixHeading(cmd.rotate_to);
|
|
float dist = 0.0;
|
|
if (cmd.rotate_dir > 0.0) {
|
|
if (to > from) {
|
|
dist = to - from;
|
|
}
|
|
else {
|
|
dist = 512.0 - from + to;
|
|
}
|
|
}
|
|
else {
|
|
if (from > to) {
|
|
dist = from - to;
|
|
}
|
|
else {
|
|
dist = (512.0 - to) + from;
|
|
}
|
|
}
|
|
|
|
auto td = cmd.rotate_to_speed * 19.0 * frame_time;
|
|
|
|
if (td >= dist) {
|
|
m->SetHeading(to);
|
|
SendCommandToAllClients(m, 0.0, 0.0, 0.0, 0.0, 0);
|
|
cmd.active = false;
|
|
}
|
|
|
|
from += td * cmd.rotate_dir;
|
|
m->SetHeading(FixHeading(from));
|
|
}
|
|
|
|
void MobMovementManager::SendCommandToAllClients(Mob *m, float dx, float dy, float dz, float dh, int anim)
|
|
{
|
|
EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
|
PlayerPositionUpdateServer_Struct *spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer;
|
|
FillCommandStruct(spu, m, dx, dy, dz, dh, anim);
|
|
|
|
for (auto &c : _impl->Clients) {
|
|
_impl->Stats.TotalSent++;
|
|
|
|
if (anim != 0) {
|
|
_impl->Stats.TotalSentMovement++;
|
|
}
|
|
else if (dh != 0) {
|
|
_impl->Stats.TotalSentHeading++;
|
|
}
|
|
else {
|
|
_impl->Stats.TotalSentPosition++;
|
|
}
|
|
|
|
c->QueuePacket(&outapp);
|
|
}
|
|
}
|
|
|
|
void MobMovementManager::FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim)
|
|
{
|
|
memset(spu, 0x00, sizeof(PlayerPositionUpdateServer_Struct));
|
|
spu->spawn_id = m->GetID();
|
|
spu->x_pos = FloatToEQ19(m->GetX());
|
|
spu->y_pos = FloatToEQ19(m->GetY());
|
|
spu->z_pos = FloatToEQ19(m->GetZ());
|
|
spu->heading = FloatToEQ12(m->GetHeading());
|
|
spu->delta_x = FloatToEQ13(dx);
|
|
spu->delta_y = FloatToEQ13(dy);
|
|
spu->delta_z = FloatToEQ13(dz);
|
|
spu->delta_heading = FloatToEQ10(dh);
|
|
spu->animation = anim;
|
|
}
|
|
|
|
float MobMovementManager::FixHeading(float in)
|
|
{
|
|
auto h = in;
|
|
while (h > 512.0) {
|
|
h -= 512.0;
|
|
}
|
|
|
|
while (h < 0.0) {
|
|
h += 512.0;
|
|
}
|
|
|
|
return h;
|
|
}
|
|
|
|
MobMovementManager::~MobMovementManager()
|
|
{
|
|
}
|
|
|
|
void MobMovementManager::Process()
|
|
{
|
|
for (auto &iter : _impl->Entries) {
|
|
auto &ent = iter.second;
|
|
|
|
if (ent.RotateCommand.active) {
|
|
ProcessRotateCommand(iter.first, ent.RotateCommand);
|
|
}
|
|
else if (ent.MoveCommand.active) {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void MobMovementManager::AddMob(Mob *m)
|
|
{
|
|
_impl->Entries.insert(std::make_pair(m, MobMovementEntry()));
|
|
}
|
|
|
|
void MobMovementManager::RemoveMob(Mob *m)
|
|
{
|
|
_impl->Entries.erase(m);
|
|
}
|
|
|
|
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::RotateTo(Mob *who, float to, float speed)
|
|
{
|
|
auto iter = _impl->Entries.find(who);
|
|
auto &ent = (*iter);
|
|
|
|
auto from = FixHeading(who->GetHeading());
|
|
to = FixHeading(to);
|
|
|
|
ent.second.RotateCommand.active = true;
|
|
ent.second.RotateCommand.started = false;
|
|
ent.second.RotateCommand.rotate_to = to;
|
|
ent.second.RotateCommand.rotate_to_speed = speed;
|
|
|
|
double pdist = 0.0;
|
|
double ndist = 0.0;
|
|
if (to > from) {
|
|
pdist = to - from;
|
|
}
|
|
else {
|
|
pdist = 512.0 - from + to;
|
|
}
|
|
|
|
if (from > to) {
|
|
ndist = from - to;
|
|
}
|
|
else {
|
|
ndist = (512.0 - to) + from;
|
|
}
|
|
|
|
if (pdist <= ndist) {
|
|
ent.second.RotateCommand.rotate_dir = 1.0;
|
|
}
|
|
else {
|
|
ent.second.RotateCommand.rotate_dir = -1.0;
|
|
}
|
|
}
|
|
|
|
void MobMovementManager::Teleport(Mob *who, float x, float y, float z, float heading)
|
|
{
|
|
}
|
|
|
|
void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, float speed)
|
|
{
|
|
|
|
}
|
|
|
|
void MobMovementManager::StopNavigation(Mob *who) {
|
|
|
|
}
|