Redoing movement to introduce proper rotation

This commit is contained in:
KimLS 2018-09-24 22:41:53 -07:00
parent 1aa97957d8
commit 29ea65a71e
25 changed files with 423 additions and 1311 deletions

View File

@ -150,7 +150,7 @@ enum { //reuse times
enum { //timer settings, all in milliseconds enum { //timer settings, all in milliseconds
AImovement_duration = 100, AImovement_duration = 100,
AIthink_duration = 150, AIthink_duration = 50,
AIscanarea_delay = 6000, AIscanarea_delay = 6000,
AIfeignremember_delay = 500, AIfeignremember_delay = 500,
AItarget_check_duration = 500, AItarget_check_duration = 500,

View File

@ -119,7 +119,6 @@ Client::Client(EQStreamInterface* ieqs)
0, 0,
0 0
), ),
position_timer(250),
hpupdate_timer(2000), hpupdate_timer(2000),
camp_timer(29000), camp_timer(29000),
process_timer(100), process_timer(100),
@ -221,7 +220,6 @@ Client::Client(EQStreamInterface* ieqs)
npcflag = false; npcflag = false;
npclevel = 0; npclevel = 0;
pQueuedSaveWorkID = 0; pQueuedSaveWorkID = 0;
position_timer_counter = 0;
position_update_same_count = 0; position_update_same_count = 0;
fishing_timer.Disable(); fishing_timer.Disable();
shield_timer.Disable(); shield_timer.Disable();
@ -278,14 +276,6 @@ Client::Client(EQStreamInterface* ieqs)
XPRate = 100; XPRate = 100;
current_endurance = 0; current_endurance = 0;
m_TimeSinceLastPositionCheck = 0;
m_DistanceSinceLastPositionCheck = 0.0f;
m_ShadowStepExemption = 0;
m_KnockBackExemption = 0;
m_PortExemption = 0;
m_SenseExemption = 0;
m_AssistExemption = 0;
m_CheatDetectMoved = false;
CanUseReport = true; CanUseReport = true;
aa_los_them_mob = nullptr; aa_los_them_mob = nullptr;
los_status = false; los_status = false;
@ -5282,177 +5272,6 @@ void Client::ShowSkillsWindow()
this->SendPopupToClient(WindowTitle, WindowText.c_str()); this->SendPopupToClient(WindowTitle, WindowText.c_str());
} }
void Client::SetShadowStepExemption(bool v)
{
if(v == true)
{
uint32 cur_time = Timer::GetCurrentTime();
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
{
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
int runs = GetRunspeed();
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed);
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
{
if(IsShadowStepExempted())
{
if(m_DistanceSinceLastPositionCheck > 800)
{
CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ());
}
}
else if(IsKnockBackExempted())
{
//still potential to trigger this if you're knocked back off a
//HUGE fall that takes > 2.5 seconds
if(speed > 30.0f)
{
CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ());
}
}
else if(!IsPortExempted())
{
if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ()))
{
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
CheatDetected(MQWarp, GetX(), GetY(), GetZ());
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
}
else
{
CheatDetected(MQWarpLight, GetX(), GetY(), GetZ());
}
}
}
}
}
}
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
}
m_ShadowStepExemption = v;
}
void Client::SetKnockBackExemption(bool v)
{
if(v == true)
{
uint32 cur_time = Timer::GetCurrentTime();
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
{
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
int runs = GetRunspeed();
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
{
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed);
if(IsShadowStepExempted())
{
if(m_DistanceSinceLastPositionCheck > 800)
{
CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ());
}
}
else if(IsKnockBackExempted())
{
//still potential to trigger this if you're knocked back off a
//HUGE fall that takes > 2.5 seconds
if(speed > 30.0f)
{
CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ());
}
}
else if(!IsPortExempted())
{
if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ()))
{
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
CheatDetected(MQWarp, GetX(), GetY(), GetZ());
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
}
else
{
CheatDetected(MQWarpLight, GetX(), GetY(), GetZ());
}
}
}
}
}
}
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
}
m_KnockBackExemption = v;
}
void Client::SetPortExemption(bool v)
{
if(v == true)
{
uint32 cur_time = Timer::GetCurrentTime();
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
{
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
int runs = GetRunspeed();
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
{
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed);
if(IsShadowStepExempted())
{
if(m_DistanceSinceLastPositionCheck > 800)
{
CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ());
}
}
else if(IsKnockBackExempted())
{
//still potential to trigger this if you're knocked back off a
//HUGE fall that takes > 2.5 seconds
if(speed > 30.0f)
{
CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ());
}
}
else if(!IsPortExempted())
{
if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ()))
{
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
CheatDetected(MQWarp, GetX(), GetY(), GetZ());
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
}
else
{
CheatDetected(MQWarpLight, GetX(), GetY(), GetZ());
}
}
}
}
}
}
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
}
m_PortExemption = v;
}
void Client::Signal(uint32 data) void Client::Signal(uint32 data)
{ {
char buf[32]; char buf[32];
@ -5461,158 +5280,6 @@ void Client::Signal(uint32 data)
parse->EventPlayer(EVENT_SIGNAL, this, buf, 0); parse->EventPlayer(EVENT_SIGNAL, this, buf, 0);
} }
const bool Client::IsMQExemptedArea(uint32 zoneID, float x, float y, float z) const
{
float max_dist = 90000;
switch(zoneID)
{
case 2:
{
float delta = (x-(-713.6));
delta *= delta;
float distance = delta;
delta = (y-(-160.2));
delta *= delta;
distance += delta;
delta = (z-(-12.8));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
delta = (x-(-153.8));
delta *= delta;
distance = delta;
delta = (y-(-30.3));
delta *= delta;
distance += delta;
delta = (z-(8.2));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
break;
}
case 9:
{
float delta = (x-(-682.5));
delta *= delta;
float distance = delta;
delta = (y-(147.0));
delta *= delta;
distance += delta;
delta = (z-(-9.9));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
delta = (x-(-655.4));
delta *= delta;
distance = delta;
delta = (y-(10.5));
delta *= delta;
distance += delta;
delta = (z-(-51.8));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
break;
}
case 62:
case 75:
case 114:
case 209:
{
//The portals are so common in paineel/felwitheb that checking
//distances wouldn't be worth it cause unless you're porting to the
//start field you're going to be triggering this and that's a level of
//accuracy I'm willing to sacrifice
return true;
break;
}
case 24:
{
float delta = (x-(-183.0));
delta *= delta;
float distance = delta;
delta = (y-(-773.3));
delta *= delta;
distance += delta;
delta = (z-(54.1));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
delta = (x-(-8.8));
delta *= delta;
distance = delta;
delta = (y-(-394.1));
delta *= delta;
distance += delta;
delta = (z-(41.1));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
delta = (x-(-310.3));
delta *= delta;
distance = delta;
delta = (y-(-1411.6));
delta *= delta;
distance += delta;
delta = (z-(-42.8));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
delta = (x-(-183.1));
delta *= delta;
distance = delta;
delta = (y-(-1409.8));
delta *= delta;
distance += delta;
delta = (z-(37.1));
delta *= delta;
distance += delta;
if(distance < max_dist)
return true;
break;
}
case 110:
case 34:
case 96:
case 93:
case 68:
case 84:
{
if(GetBoatID() != 0)
return true;
break;
}
default:
break;
}
return false;
}
void Client::SendRewards() void Client::SendRewards()
{ {
std::vector<ClientReward> rewards; std::vector<ClientReward> rewards;

View File

@ -959,23 +959,7 @@ public:
void SendRules(Client* client); void SendRules(Client* client);
std::list<std::string> consent_list; std::list<std::string> consent_list;
//Anti-Cheat Stuff
uint32 m_TimeSinceLastPositionCheck;
float m_DistanceSinceLastPositionCheck;
bool m_CheatDetectMoved;
void SetShadowStepExemption(bool v);
void SetKnockBackExemption(bool v);
void SetPortExemption(bool v);
void SetSenseExemption(bool v) { m_SenseExemption = v; }
void SetAssistExemption(bool v) { m_AssistExemption = v; }
const bool IsShadowStepExempted() const { return m_ShadowStepExemption; }
const bool IsKnockBackExempted() const { return m_KnockBackExemption; }
const bool IsPortExempted() const { return m_PortExemption; }
const bool IsSenseExempted() const { return m_SenseExemption; }
const bool IsAssistExempted() const { return m_AssistExemption; }
const bool GetGMSpeed() const { return (gmspeed > 0); } const bool GetGMSpeed() const { return (gmspeed > 0); }
void CheatDetected(CheatTypes CheatType, float x, float y, float z);
const bool IsMQExemptedArea(uint32 zoneID, float x, float y, float z) const;
bool CanUseReport; bool CanUseReport;
//This is used to later set the buff duration of the spell, in slot to duration. //This is used to later set the buff duration of the spell, in slot to duration.
@ -1153,7 +1137,6 @@ public:
inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); } inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); }
void DragCorpses(); void DragCorpses();
inline void ClearDraggedCorpses() { DraggedCorpses.clear(); } inline void ClearDraggedCorpses() { DraggedCorpses.clear(); }
inline void ResetPositionTimer() { position_timer_counter = 0; }
void SendAltCurrencies(); void SendAltCurrencies();
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount); void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0); void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0);
@ -1497,9 +1480,6 @@ private:
WaterRegionType last_region_type; WaterRegionType last_region_type;
Timer position_timer;
uint8 position_timer_counter;
// this is used to try to cut back on position update reflections // this is used to try to cut back on position update reflections
int position_update_same_count; int position_update_same_count;
@ -1582,11 +1562,6 @@ private:
int XPRate; int XPRate;
bool m_ShadowStepExemption;
bool m_KnockBackExemption;
bool m_PortExemption;
bool m_SenseExemption;
bool m_AssistExemption;
bool alternate_currency_loaded; bool alternate_currency_loaded;
std::map<uint32, uint32> alternate_currency; std::map<uint32, uint32> alternate_currency;
std::queue<std::pair<uint32, int32>> alternate_currency_queued_operations; std::queue<std::pair<uint32, int32>> alternate_currency_queued_operations;

View File

@ -505,7 +505,6 @@ void Client::CompleteConnect()
client_state = CLIENT_CONNECTED; client_state = CLIENT_CONNECTED;
SendAllPackets(); SendAllPackets();
hpupdate_timer.Start(); hpupdate_timer.Start();
position_timer.Start();
autosave_timer.Start(); autosave_timer.Start();
SetDuelTarget(0); SetDuelTarget(0);
SetDueling(false); SetDueling(false);
@ -895,108 +894,6 @@ void Client::CompleteConnect()
worldserver.RequestTellQueue(GetName()); worldserver.RequestTellQueue(GetName());
} }
void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z)
{
//ToDo: Break warp down for special zones. Some zones have special teleportation pads or bad .map files which can trigger the detector without a legit zone request.
switch (CheatType)
{
case MQWarp: //Some zones may still have issues. Database updates will eliminate most if not all problems.
if (RuleB(Zone, EnableMQWarpDetector)
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
{
Message(13, "Large warp detected.");
char hString[250];
sprintf(hString, "/MQWarp with location %.2f, %.2f, %.2f", GetX(), GetY(), GetZ());
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
}
break;
case MQWarpShadowStep:
if (RuleB(Zone, EnableMQWarpDetector)
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
{
char *hString = nullptr;
MakeAnyLenString(&hString, "/MQWarp(SS) with location %.2f, %.2f, %.2f, the target was shadow step exempt but we still found this suspicious.", GetX(), GetY(), GetZ());
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
safe_delete_array(hString);
}
break;
case MQWarpKnockBack:
if (RuleB(Zone, EnableMQWarpDetector)
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
{
char *hString = nullptr;
MakeAnyLenString(&hString, "/MQWarp(KB) with location %.2f, %.2f, %.2f, the target was Knock Back exempt but we still found this suspicious.", GetX(), GetY(), GetZ());
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
safe_delete_array(hString);
}
break;
case MQWarpLight:
if (RuleB(Zone, EnableMQWarpDetector)
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
{
if (RuleB(Zone, MarkMQWarpLT))
{
char *hString = nullptr;
MakeAnyLenString(&hString, "/MQWarp(LT) with location %.2f, %.2f, %.2f, running fast but not fast enough to get killed, possibly: small warp, speed hack, excessive lag, marked as suspicious.", GetX(), GetY(), GetZ());
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
safe_delete_array(hString);
}
}
break;
case MQZone:
if (RuleB(Zone, EnableMQZoneDetector) && ((this->Admin() < RuleI(Zone, MQZoneExemptStatus) || (RuleI(Zone, MQZoneExemptStatus)) == -1)))
{
char hString[250];
sprintf(hString, "/MQZone used at %.2f, %.2f, %.2f to %.2f %.2f %.2f", GetX(), GetY(), GetZ(), x, y, z);
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
}
break;
case MQZoneUnknownDest:
if (RuleB(Zone, EnableMQZoneDetector) && ((this->Admin() < RuleI(Zone, MQZoneExemptStatus) || (RuleI(Zone, MQZoneExemptStatus)) == -1)))
{
char hString[250];
sprintf(hString, "/MQZone used at %.2f, %.2f, %.2f", GetX(), GetY(), GetZ());
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
}
break;
case MQGate:
if (RuleB(Zone, EnableMQGateDetector) && ((this->Admin() < RuleI(Zone, MQGateExemptStatus) || (RuleI(Zone, MQGateExemptStatus)) == -1))) {
Message(13, "Illegal gate request.");
char hString[250];
sprintf(hString, "/MQGate used at %.2f, %.2f, %.2f", GetX(), GetY(), GetZ());
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
if (zone)
{
this->SetZone(this->GetZoneID(), zone->GetInstanceID()); //Prevent the player from zoning, place him back in the zone where he tried to originally /gate.
}
else
{
this->SetZone(this->GetZoneID(), 0); //Prevent the player from zoning, place him back in the zone where he tried to originally /gate.
}
}
break;
case MQGhost: //Not currently implemented, but the framework is in place - just needs detection scenarios identified
if (RuleB(Zone, EnableMQGhostDetector) && ((this->Admin() < RuleI(Zone, MQGhostExemptStatus) || (RuleI(Zone, MQGhostExemptStatus)) == -1))) {
database.SetMQDetectionFlag(this->account_name, this->name, "/MQGhost", zone->GetShortName());
}
break;
default:
char *hString = nullptr;
MakeAnyLenString(&hString, "Unhandled HackerDetection flag with location %.2f, %.2f, %.2f.", GetX(), GetY(), GetZ());
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
safe_delete_array(hString);
break;
}
}
// connecting opcode handlers // connecting opcode handlers
/* /*
void Client::Handle_Connect_0x3e33(const EQApplicationPacket *app) void Client::Handle_Connect_0x3e33(const EQApplicationPacket *app)
@ -2948,7 +2845,6 @@ void Client::Handle_OP_Assist(const EQApplicationPacket *app)
Mob *new_target = assistee->GetTarget(); Mob *new_target = assistee->GetTarget();
if (new_target && (GetGM() || if (new_target && (GetGM() ||
Distance(m_Position, assistee->GetPosition()) <= TARGETING_RANGE)) { Distance(m_Position, assistee->GetPosition()) <= TARGETING_RANGE)) {
SetAssistExemption(true);
eid->entity_id = new_target->GetID(); eid->entity_id = new_target->GetID();
} else { } else {
eid->entity_id = 0; eid->entity_id = 0;
@ -3920,6 +3816,8 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app)
return; return;
controlling_boat_id = boat->GetID(); // set the client's BoatID to show that it's on this boat controlling_boat_id = boat->GetID(); // set the client's BoatID to show that it's on this boat
Message(0, "Board boat: %s", boatname);
return; return;
} }
@ -4427,9 +4325,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
sizeof(PlayerPositionUpdateClient_Struct), app->size); sizeof(PlayerPositionUpdateClient_Struct), app->size);
return; return;
} }
PlayerPositionUpdateClient_Struct *ppu = (PlayerPositionUpdateClient_Struct *) app->pBuffer; PlayerPositionUpdateClient_Struct *ppu = (PlayerPositionUpdateClient_Struct *) app->pBuffer;
/* Boat handling */ /* Boat handling */
if (ppu->spawn_id != GetID()) { if (ppu->spawn_id != GetID()) {
/* If player is controlling boat */ /* If player is controlling boat */
@ -4439,163 +4337,67 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
controlling_boat_id = 0; controlling_boat_id = 0;
return; return;
} }
auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading)); auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
boat->SetDelta(boat_delta); boat->SetDelta(boat_delta);
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct *ppus = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer; PlayerPositionUpdateServer_Struct *ppus = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
boat->MakeSpawnUpdate(ppus); boat->MakeSpawnUpdate(ppus);
entity_list.QueueCloseClients(boat, outapp, true, 300, this, false); entity_list.QueueCloseClients(boat, outapp, true, 300, this, false);
safe_delete(outapp); safe_delete(outapp);
/* Update the boat's position on the server, without sending an update */ /* Update the boat's position on the server, without sending an update */
boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ12toFloat(ppu->heading), false); boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ12toFloat(ppu->heading), false);
return; return;
} else return; } else return;
} }
float dist = 0; if (IsDraggingCorpse())
float tmp; DragCorpses();
tmp = m_Position.x - ppu->x_pos;
dist += tmp * tmp;
tmp = m_Position.y - ppu->y_pos;
dist += tmp * tmp;
dist = sqrt(dist);
/* Hack checks */
if (dist == 0) {
if (m_DistanceSinceLastPositionCheck > 0.0) {
uint32 cur_time = Timer::GetCurrentTime();
if ((cur_time - m_TimeSinceLastPositionCheck) > 0) {
float speed =
(m_DistanceSinceLastPositionCheck * 100) / (float) (cur_time - m_TimeSinceLastPositionCheck);
int runs = GetRunspeed();
if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
if (!GetGMSpeed() && (runs >= GetBaseRunspeed() ||
(speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) {
if (IsShadowStepExempted()) {
if (m_DistanceSinceLastPositionCheck > 800) {
CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos);
}
} else if (IsKnockBackExempted()) {
if (speed > 30.0f) {
CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos);
}
} else if (!IsPortExempted()) {
if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) {
if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos);
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
} else {
CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos);
}
}
}
}
}
SetShadowStepExemption(false);
SetKnockBackExemption(false);
SetPortExemption(false);
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
m_CheatDetectMoved = false;
}
} else {
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
m_CheatDetectMoved = false;
}
} else {
m_DistanceSinceLastPositionCheck += dist;
m_CheatDetectMoved = true;
if (m_TimeSinceLastPositionCheck == 0) {
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
} else {
uint32 cur_time = Timer::GetCurrentTime();
if ((cur_time - m_TimeSinceLastPositionCheck) > 2500) {
float speed =
(m_DistanceSinceLastPositionCheck * 100) / (float) (cur_time - m_TimeSinceLastPositionCheck);
int runs = GetRunspeed();
if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
if (!GetGMSpeed() && (runs >= GetBaseRunspeed() ||
(speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) {
if (IsShadowStepExempted()) {
if (m_DistanceSinceLastPositionCheck > 800) {
CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos);
}
} else if (IsKnockBackExempted()) {
if (speed > 30.0f) {
CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos);
}
} else if (!IsPortExempted()) {
if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) {
if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos);
} else {
CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos);
}
}
}
}
}
SetShadowStepExemption(false);
SetKnockBackExemption(false);
SetPortExemption(false);
m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f;
}
}
if (IsDraggingCorpse())
DragCorpses();
}
/* Check to see if PPU should trigger an update to the rewind position. */ /* Check to see if PPU should trigger an update to the rewind position. */
float rewind_x_diff = 0; float rewind_x_diff = 0;
float rewind_y_diff = 0; float rewind_y_diff = 0;
rewind_x_diff = ppu->x_pos - m_RewindLocation.x; rewind_x_diff = ppu->x_pos - m_RewindLocation.x;
rewind_x_diff *= rewind_x_diff; rewind_x_diff *= rewind_x_diff;
rewind_y_diff = ppu->y_pos - m_RewindLocation.y; rewind_y_diff = ppu->y_pos - m_RewindLocation.y;
rewind_y_diff *= rewind_y_diff; rewind_y_diff *= rewind_y_diff;
/* /*
We only need to store updated values if the player has moved. We only need to store updated values if the player has moved.
If the player has moved more than units for x or y, then we'll store If the player has moved more than units for x or y, then we'll store
his pre-PPU x and y for /rewind, in case he gets stuck. his pre-PPU x and y for /rewind, in case he gets stuck.
*/ */
if ((rewind_x_diff > 750) || (rewind_y_diff > 750)) if ((rewind_x_diff > 750) || (rewind_y_diff > 750))
m_RewindLocation = glm::vec3(m_Position); m_RewindLocation = glm::vec3(m_Position);
/* /*
If the PPU was a large jump, such as a cross zone gate or Call of Hero, If the PPU was a large jump, such as a cross zone gate or Call of Hero,
just update rewind coordinates to the new ppu coordinates. This will prevent exploitation. just update rewind coordinates to the new ppu coordinates. This will prevent exploitation.
*/ */
if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000)) if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000))
m_RewindLocation = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos); m_RewindLocation = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos);
if (proximity_timer.Check()) { if (proximity_timer.Check()) {
entity_list.ProcessMove(this, glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos)); entity_list.ProcessMove(this, glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos));
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity)) if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
ProcessTaskProximities(ppu->x_pos, ppu->y_pos, ppu->z_pos); ProcessTaskProximities(ppu->x_pos, ppu->y_pos, ppu->z_pos);
m_Proximity = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos); m_Proximity = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos);
} }
/* Update internal state */ /* Update internal state */
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading)); m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
if (IsTracking() && ((m_Position.x != ppu->x_pos) || (m_Position.y != ppu->y_pos))) { if (IsTracking() && ((m_Position.x != ppu->x_pos) || (m_Position.y != ppu->y_pos))) {
if (zone->random.Real(0, 100) < 70)//should be good if (zone->random.Real(0, 100) < 70)//should be good
CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20); CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20);
} }
/* Break Hide if moving without sneaking and set rewind timer if moved */ /* Break Hide if moving without sneaking and set rewind timer if moved */
if (ppu->y_pos != m_Position.y || ppu->x_pos != m_Position.x) { if (ppu->y_pos != m_Position.y || ppu->x_pos != m_Position.x) {
if ((hidden || improved_hidden) && !sneaking) { if ((hidden || improved_hidden) && !sneaking) {
@ -4614,17 +4416,17 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
} }
rewind_timer.Start(30000, true); rewind_timer.Start(30000, true);
} }
/* Handle client aggro scanning timers NPCs */ /* Handle client aggro scanning timers NPCs */
is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true; is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true;
if (is_client_moving) { if (is_client_moving) {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u", Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u",
client_scan_npc_aggro_timer.GetDuration()); client_scan_npc_aggro_timer.GetDuration());
if (client_scan_npc_aggro_timer.GetDuration() > 1000) { if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
client_scan_npc_aggro_timer.Disable(); client_scan_npc_aggro_timer.Disable();
client_scan_npc_aggro_timer.Start(500); client_scan_npc_aggro_timer.Start(500);
} }
} else { } else {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u", Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
@ -4634,15 +4436,15 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
client_scan_npc_aggro_timer.Start(3000); client_scan_npc_aggro_timer.Start(3000);
} }
} }
float new_heading = EQ12toFloat(ppu->heading); float new_heading = EQ12toFloat(ppu->heading);
int32 new_animation = ppu->animation; int32 new_animation = ppu->animation;
/* Update internal server position from what the client has sent */ /* Update internal server position from what the client has sent */
m_Position.x = ppu->x_pos; m_Position.x = ppu->x_pos;
m_Position.y = ppu->y_pos; m_Position.y = ppu->y_pos;
m_Position.z = ppu->z_pos; m_Position.z = ppu->z_pos;
/* Visual Debugging */ /* Visual Debugging */
if (RuleB(Character, OPClientUpdateVisualDebug)) { if (RuleB(Character, OPClientUpdateVisualDebug)) {
Log(Logs::General, Logs::Debug, "ClientUpdate: ppu x: %f y: %f z: %f h: %u", ppu->x_pos, ppu->y_pos, ppu->z_pos, Log(Logs::General, Logs::Debug, "ClientUpdate: ppu x: %f y: %f z: %f h: %u", ppu->x_pos, ppu->y_pos, ppu->z_pos,
@ -4650,43 +4452,43 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
this->SendAppearanceEffect(78, 0, 0, 0, 0); this->SendAppearanceEffect(78, 0, 0, 0, 0);
this->SendAppearanceEffect(41, 0, 0, 0, 0); this->SendAppearanceEffect(41, 0, 0, 0, 0);
} }
/* Only feed real time updates when client is moving */ /* Only feed real time updates when client is moving */
if (is_client_moving || new_heading != m_Position.w || new_animation != animation) { if (is_client_moving || new_heading != m_Position.w || new_animation != animation) {
animation = ppu->animation; animation = ppu->animation;
m_Position.w = EQ12toFloat(ppu->heading); m_Position.w = EQ12toFloat(ppu->heading);
/* Broadcast update to other clients */ /* Broadcast update to other clients */
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct *position_update = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer; PlayerPositionUpdateServer_Struct *position_update = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
MakeSpawnUpdate(position_update); MakeSpawnUpdate(position_update);
if (gm_hide_me) { if (gm_hide_me) {
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250); entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250);
} else { } else {
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true); entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true);
} }
/* Always send position updates to group - send when beyond normal ClientPositionUpdate range */ /* Always send position updates to group - send when beyond normal ClientPositionUpdate range */
Group *group = this->GetGroup(); Group *group = this->GetGroup();
Raid *raid = this->GetRaid(); Raid *raid = this->GetRaid();
if (raid) { if (raid) {
raid->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1)); raid->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
} else if (group) { } else if (group) {
group->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1)); group->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
} }
safe_delete(outapp); safe_delete(outapp);
} }
if (zone->watermap) { if (zone->watermap) {
if (zone->watermap->InLiquid(glm::vec3(m_Position))) { if (zone->watermap->InLiquid(glm::vec3(m_Position))) {
CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17); CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17);
// Dismount horses when entering water // Dismount horses when entering water
if (GetHorseId() && RuleB(Character, DismountWater)) { if (GetHorseId() && RuleB(Character, DismountWater)) {
SetHorseId(0); SetHorseId(0);
@ -4695,7 +4497,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
} }
CheckRegionTypeChanges(); CheckRegionTypeChanges();
} }
return;
} }
void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app) void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app)
@ -13666,12 +13467,6 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
GetTarget()->IsTargeted(1); GetTarget()->IsTargeted(1);
return; return;
} }
else if (IsAssistExempted())
{
GetTarget()->IsTargeted(1);
SetAssistExemption(false);
return;
}
else if (GetTarget()->IsClient()) else if (GetTarget()->IsClient())
{ {
//make sure this client is in our raid/group //make sure this client is in our raid/group
@ -13689,17 +13484,6 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
SetTarget((Mob*)nullptr); SetTarget((Mob*)nullptr);
return; return;
} }
else if (IsPortExempted())
{
GetTarget()->IsTargeted(1);
return;
}
else if (IsSenseExempted())
{
GetTarget()->IsTargeted(1);
SetSenseExemption(false);
return;
}
else if (IsXTarget(GetTarget())) else if (IsXTarget(GetTarget()))
{ {
GetTarget()->IsTargeted(1); GetTarget()->IsTargeted(1);

View File

@ -188,10 +188,6 @@ bool Client::Process() {
if (IsStunned() && stunned_timer.Check()) if (IsStunned() && stunned_timer.Check())
Mob::UnStun(); Mob::UnStun();
if (!m_CheatDetectMoved) {
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
}
if (bardsong_timer.Check() && bardsong != 0) { if (bardsong_timer.Check() && bardsong != 0) {
//NOTE: this is kinda a heavy-handed check to make sure the mob still exists before //NOTE: this is kinda a heavy-handed check to make sure the mob still exists before
//doing the next pulse on them... //doing the next pulse on them...
@ -412,31 +408,6 @@ bool Client::Process() {
} }
} }
if (position_timer.Check()) {
if (IsAIControlled())
{
if (!IsMoving())
{
animation = 0;
m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w);
SendPositionUpdate(true);
}
}
// Send a position packet every 8 seconds - if not done, other clients
// see this char disappear after 10-12 seconds of inactivity
if (position_timer_counter >= 36) { // Approx. 4 ticks per second
entity_list.SendPositionUpdates(this, pLastUpdateWZ, RuleI(Range, MobPositionUpdates), GetTarget(), true);
pLastUpdate = Timer::GetCurrentTime();
pLastUpdateWZ = pLastUpdate;
position_timer_counter = 0;
}
else {
pLastUpdate = Timer::GetCurrentTime();
position_timer_counter++;
}
}
if (HasVirus()) { if (HasVirus()) {
if (viral_timer.Check()) { if (viral_timer.Check()) {
viral_timer_counter++; viral_timer_counter++;

View File

@ -67,6 +67,7 @@
#include "water_map.h" #include "water_map.h"
#include "worldserver.h" #include "worldserver.h"
#include "fastmath.h" #include "fastmath.h"
#include "mob_movement_manager.h"
extern QueryServ* QServ; extern QueryServ* QServ;
extern WorldServer worldserver; extern WorldServer worldserver;
@ -265,6 +266,7 @@ int command_init(void)
command_add("modifynpcstat", "- Modifys a NPC's stats", 150, command_modifynpcstat) || command_add("modifynpcstat", "- Modifys a NPC's stats", 150, command_modifynpcstat) ||
command_add("motd", "[new motd] - Set message of the day", 150, command_motd) || command_add("motd", "[new motd] - Set message of the day", 150, command_motd) ||
command_add("movechar", "[charname] [zonename] - Move charname to zonename", 50, command_movechar) || command_add("movechar", "[charname] [zonename] - Move charname to zonename", 50, command_movechar) ||
command_add("movement", "Various movement commands", 200, command_movement) ||
command_add("myskills", "- Show details about your current skill levels", 0, command_myskills) || command_add("myskills", "- Show details about your current skill levels", 0, command_myskills) ||
command_add("mysqltest", "Akkadius MySQL Bench Test", 250, command_mysqltest) || command_add("mysqltest", "Akkadius MySQL Bench Test", 250, command_mysqltest) ||
command_add("mysql", "Mysql CLI, see 'help' for options.", 250, command_mysql) || command_add("mysql", "Mysql CLI, see 'help' for options.", 250, command_mysql) ||
@ -1258,6 +1260,63 @@ void command_movechar(Client *c, const Seperator *sep)
} }
} }
void command_movement(Client *c, const Seperator *sep)
{
auto &mgr = MobMovementManager::Get();
if (sep->arg[1][0] == 0) {
c->Message(0, "Usage: #movement stats/clearstats");
return;
}
if (strcasecmp(sep->arg[1], "stats") == 0)
{
//mgr.DumpStats(c);
}
else if (strcasecmp(sep->arg[1], "clearstats") == 0)
{
//mgr.ClearStats();
}
if (strcasecmp(sep->arg[1], "test") == 0)
{
auto target = c->GetTarget();
if (!target) {
c->Message(0, "Requires target");
}
auto heading = target->CalculateHeadingToTarget(c->GetX(), c->GetY());
mgr.RotateTo(target, heading, 16.0f);
//double a1 = atof(sep->arg[2]);
//double a2 = atof(sep->arg[3]);
//double a3 = atof(sep->arg[4]);
//double a4 = atof(sep->arg[5]);
//int a5 = atoi(sep->arg[6]);
//
////PlayerPositionUpdateServer_Struct
//EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
//PlayerPositionUpdateServer_Struct *spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer;
//
//memset(spu, 0x00, sizeof(PlayerPositionUpdateServer_Struct));
//spu->spawn_id = target->GetID();
//spu->x_pos = FloatToEQ19(target->GetX());
//spu->y_pos = FloatToEQ19(target->GetY());
//spu->z_pos = FloatToEQ19(target->GetZ());
//spu->heading = FloatToEQ12(target->GetHeading());
//spu->delta_x = FloatToEQ13(a1);
//spu->delta_y = FloatToEQ13(a2);
//spu->delta_z = FloatToEQ13(a3);
//spu->delta_heading = FloatToEQ10(a4);
//spu->animation = a5;
//
//c->QueuePacket(&outapp);
}
else {
c->Message(0, "Usage: #movement stats/clearstats");
}
}
void command_viewpetition(Client *c, const Seperator *sep) void command_viewpetition(Client *c, const Seperator *sep)
{ {
if (sep->arg[1][0] == 0) { if (sep->arg[1][0] == 0) {
@ -7260,7 +7319,7 @@ void command_pf(Client *c, const Seperator *sep)
c->Message(0, "POS: (%.2f, %.2f, %.2f)", who->GetX(), who->GetY(), who->GetZ()); c->Message(0, "POS: (%.2f, %.2f, %.2f)", who->GetX(), who->GetY(), who->GetZ());
c->Message(0, "WP: %s (%d/%d)", to_string(who->GetCurrentWayPoint()).c_str(), who->IsNPC()?who->CastToNPC()->GetMaxWp():-1); c->Message(0, "WP: %s (%d/%d)", to_string(who->GetCurrentWayPoint()).c_str(), who->IsNPC()?who->CastToNPC()->GetMaxWp():-1);
c->Message(0, "pause=%d RAspeed=%d", who->GetCWPP(), who->GetRunAnimSpeed()); c->Message(0, "pause=%d RAspeed=%d", who->GetCWPP(), who->GetRunAnimSpeed());
who->DumpMovement(c); //who->DumpMovement(c);
} else { } else {
c->Message(0, "ERROR: target required"); c->Message(0, "ERROR: target required");
} }

View File

@ -168,6 +168,7 @@ void command_merchantopenshop(Client *c, const Seperator *sep);
void command_modifynpcstat(Client *c, const Seperator *sep); void command_modifynpcstat(Client *c, const Seperator *sep);
void command_motd(Client *c, const Seperator *sep); void command_motd(Client *c, const Seperator *sep);
void command_movechar(Client *c, const Seperator *sep); void command_movechar(Client *c, const Seperator *sep);
void command_movement(Client *c, const Seperator *sep);
void command_myskills(Client *c, const Seperator *sep); void command_myskills(Client *c, const Seperator *sep);
void command_mysql(Client *c, const Seperator *sep); void command_mysql(Client *c, const Seperator *sep);
void command_mysqltest(Client *c, const Seperator *sep); void command_mysqltest(Client *c, const Seperator *sep);

View File

@ -2650,56 +2650,6 @@ void EntityList::RemoveDebuffs(Mob *caster)
} }
} }
// Currently, a new packet is sent per entity.
// @todo: Come back and use FLAG_COMBINED to pack
// all updates into one packet.
void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, float update_range, Entity *always_send, bool iSendEvenIfNotChanged)
{
// update_range = (update_range * update_range);
//
// EQApplicationPacket *outapp = 0;
// PlayerPositionUpdateServer_Struct *ppu = 0;
// Mob *mob = 0;
//
// auto it = mob_list.begin();
// while (it != mob_list.end()) {
//
// mob = it->second;
//
// if (
// mob && !mob->IsCorpse()
// && (it->second != client)
// && (mob->IsClient() || iSendEvenIfNotChanged || (mob->LastChange() >= cLastUpdate))
// && (it->second->ShouldISpawnFor(client))
// ) {
// if (
// update_range == 0
// || (it->second == always_send)
// || mob->IsClient()
// || (DistanceSquared(mob->GetPosition(), client->GetPosition()) <= update_range)
// ) {
// if (mob && mob->IsClient() && mob->GetID() > 0) {
// client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
//
// if (outapp == 0) {
// outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
// ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
// }
//
// mob->MakeSpawnUpdate(ppu);
//
// safe_delete(outapp);
// outapp = 0;
// }
// }
// }
//
// ++it;
// }
//
// safe_delete(outapp);
}
char *EntityList::MakeNameUnique(char *name) char *EntityList::MakeNameUnique(char *name)
{ {
bool used[300]; bool used[300];

View File

@ -372,7 +372,6 @@ public:
Mob* FindDefenseNPC(uint32 npcid); Mob* FindDefenseNPC(uint32 npcid);
void OpenDoorsNear(Mob* opener); void OpenDoorsNear(Mob* opener);
void UpdateWho(bool iSendFullUpdate = false); void UpdateWho(bool iSendFullUpdate = false);
void SendPositionUpdates(Client* client, uint32 cLastUpdate = 0, float update_range = 0, Entity* always_send = 0, bool iSendEvenIfNotChanged = false);
char* MakeNameUnique(char* name); char* MakeNameUnique(char* name);
static char* RemoveNumbers(char* name); static char* RemoveNumbers(char* name);
void SignalMobsByNPCID(uint32 npc_type, int signal_id); void SignalMobsByNPCID(uint32 npc_type, int signal_id);

View File

@ -1453,12 +1453,12 @@ void Mob::StopMoving(float new_heading) {
/* Used for mobs standing still - this does not send a delta */ /* Used for mobs standing still - this does not send a delta */
void Mob::SendPosition() { void Mob::SendPosition() {
mMovementManager->SendPosition(this); //mMovementManager->SendPosition(this);
} }
/* Position updates for mobs on the move */ /* Position updates for mobs on the move */
void Mob::SendPositionUpdate(bool iSendToSelf) { void Mob::SendPositionUpdate(bool iSendToSelf) {
mMovementManager->SendPositionUpdate(this, iSendToSelf); //mMovementManager->SendPositionUpdate(this, iSendToSelf);
} }
// this is for SendPosition() // this is for SendPosition()
@ -2710,13 +2710,7 @@ void Mob::FaceTarget(Mob* mob_to_face /*= 0*/) {
float current_heading = GetHeading(); float current_heading = GetHeading();
float new_heading = CalculateHeadingToTarget(faced_mob->GetX(), faced_mob->GetY()); float new_heading = CalculateHeadingToTarget(faced_mob->GetX(), faced_mob->GetY());
if(current_heading != new_heading) { if(current_heading != new_heading) {
SetHeading(new_heading); mMovementManager->RotateTo(this, new_heading, 16.0f);
if (moving) {
SendPositionUpdate();
}
else {
SendPosition();
}
} }
if(IsNPC() && !IsEngaged()) { if(IsNPC() && !IsEngaged()) {
@ -3170,20 +3164,6 @@ void Mob::SetNextIncHPEvent( int inchpevent )
{ {
nextinchpevent = inchpevent; nextinchpevent = inchpevent;
} }
//warp for quest function,from sandy
void Mob::Warp(const glm::vec3& location)
{
if(IsNPC())
entity_list.ProcessMove(CastToNPC(), location.x, location.y, location.z);
m_Position = glm::vec4(location, m_Position.w);
Mob* target = GetTarget();
if (target)
FaceTarget( target );
SendPosition();
}
int16 Mob::GetResist(uint8 type) const int16 Mob::GetResist(uint8 type) const
{ {
@ -3571,6 +3551,14 @@ void Mob::SetFlyMode(GravityBehavior flymode)
this->flymode = flymode; this->flymode = flymode;
} }
void Mob::Teleport(const glm::vec3 &pos)
{
}
void Mob::Teleport(const glm::vec4 &pos)
{
}
bool Mob::IsNimbusEffectActive(uint32 nimbus_effect) bool Mob::IsNimbusEffectActive(uint32 nimbus_effect)
{ {
if(nimbus_effect1 == nimbus_effect || nimbus_effect2 == nimbus_effect || nimbus_effect3 == nimbus_effect) if(nimbus_effect1 == nimbus_effect || nimbus_effect2 == nimbus_effect || nimbus_effect3 == nimbus_effect)
@ -4592,8 +4580,6 @@ void Mob::DoKnockback(Mob *caster, uint32 pushback, uint32 pushup)
{ {
if(IsClient()) if(IsClient())
{ {
CastToClient()->SetKnockBackExemption(true);
auto outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); auto outapp_push = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer; PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp_push->pBuffer;

View File

@ -542,7 +542,6 @@ public:
virtual inline int32 GetPrimaryFaction() const { return 0; } virtual inline int32 GetPrimaryFaction() const { return 0; }
//Movement //Movement
void Warp(const glm::vec3& location);
inline bool IsMoving() const { return moving; } inline bool IsMoving() const { return moving; }
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); } virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
virtual void GoToBind(uint8 bindnum = 0) { } virtual void GoToBind(uint8 bindnum = 0) { }
@ -568,14 +567,15 @@ public:
bool Spawned() { return spawned; }; bool Spawned() { return spawned; };
virtual bool ShouldISpawnFor(Client *c) { return true; } virtual bool ShouldISpawnFor(Client *c) { return true; }
void SetFlyMode(GravityBehavior flymode); void SetFlyMode(GravityBehavior flymode);
inline void Teleport(const glm::vec3 &NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y; void Teleport(const glm::vec3 &pos);
m_Position.z = NewPosition.z; }; void Teleport(const glm::vec4 &pos);
void TryMoveAlong(float distance, float angle, bool send = true); void TryMoveAlong(float distance, float angle, bool send = true);
void ProcessForcedMovement(); void ProcessForcedMovement();
inline void IncDeltaX(float in) { m_Delta.x += in; } inline void IncDeltaX(float in) { m_Delta.x += in; }
inline void IncDeltaY(float in) { m_Delta.y += in; } inline void IncDeltaY(float in) { m_Delta.y += in; }
inline void IncDeltaZ(float in) { m_Delta.z += in; } inline void IncDeltaZ(float in) { m_Delta.z += in; }
inline void SetForcedMovement(int in) { ForcedMovement = in; } inline void SetForcedMovement(int in) { ForcedMovement = in; }
void SetHeading(float iHeading) { m_Position.w = iHeading; }
//AI //AI
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel); static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
@ -602,7 +602,6 @@ public:
void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; } void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; }
bool HateSummon(); bool HateSummon();
void FaceTarget(Mob* mob_to_face = 0); void FaceTarget(Mob* mob_to_face = 0);
void SetHeading(float iHeading) { m_Position.w = iHeading; }
void WipeHateList(); void WipeHateList();
void AddFeignMemory(Client* attacker); void AddFeignMemory(Client* attacker);
void RemoveFromFeignMemory(Client* attacker); void RemoveFromFeignMemory(Client* attacker);
@ -980,7 +979,6 @@ public:
void TryFixZ(int32 z_find_offset = 5, bool fix_client_z = false); void TryFixZ(int32 z_find_offset = 5, bool fix_client_z = false);
void FixZ(int32 z_find_offset = 5, bool fix_client_z = false); void FixZ(int32 z_find_offset = 5, bool fix_client_z = false);
float GetFixedZ(const glm::vec3 &destination, int32 z_find_offset = 5); float GetFixedZ(const glm::vec3 &destination, int32 z_find_offset = 5);
void DumpMovement(Client *to);
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false); void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; } inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
@ -1251,8 +1249,8 @@ protected:
uint8 level; uint8 level;
uint8 orig_level; uint8 orig_level;
uint32 npctype_id; uint32 npctype_id;
glm::vec4 m_Position;
glm::vec4 m_Position;
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f) int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
float base_size; float base_size;
float size; float size;

View File

@ -916,7 +916,7 @@ void Client::AI_Process()
float dist = DistanceSquared(m_Position, owner->GetPosition()); float dist = DistanceSquared(m_Position, owner->GetPosition());
if (dist >= 202500) { // >= 450 distance if (dist >= 202500) { // >= 450 distance
Teleport(static_cast<glm::vec3>(owner->GetPosition())); Teleport(owner->GetPosition());
SendPositionUpdate(); // this shouldn't happen a lot (and hard to make it) so lets not rate limit SendPositionUpdate(); // this shouldn't happen a lot (and hard to make it) so lets not rate limit
} else if (dist >= 400) { // >=20 } else if (dist >= 400) { // >=20
if (AI_movement_timer->Check()) { if (AI_movement_timer->Check()) {
@ -936,86 +936,86 @@ void Client::AI_Process()
void Mob::ProcessForcedMovement() void Mob::ProcessForcedMovement()
{ {
// we are being pushed, we will hijack this movement timer //// we are being pushed, we will hijack this movement timer
// this also needs to be done before casting to have a chance to interrupt //// this also needs to be done before casting to have a chance to interrupt
// this flag won't be set if the mob can't be pushed (rooted etc) //// this flag won't be set if the mob can't be pushed (rooted etc)
if (AI_movement_timer->Check()) { //if (AI_movement_timer->Check()) {
bool bPassed = true; // bool bPassed = true;
glm::vec3 normal; // glm::vec3 normal;
//
// no zone map = fucked // // no zone map = fucked
if (zone->HasMap()) { // if (zone->HasMap()) {
// in front // // in front
m_CollisionBox[0].x = m_Position.x + 3.0f * g_Math.FastSin(0.0f); // m_CollisionBox[0].x = m_Position.x + 3.0f * g_Math.FastSin(0.0f);
m_CollisionBox[0].y = m_Position.y + 3.0f * g_Math.FastCos(0.0f); // m_CollisionBox[0].y = m_Position.y + 3.0f * g_Math.FastCos(0.0f);
m_CollisionBox[0].z = m_Position.z; // m_CollisionBox[0].z = m_Position.z;
//
// 45 right front // // 45 right front
m_CollisionBox[1].x = m_Position.x + 3.0f * g_Math.FastSin(64.0f); // m_CollisionBox[1].x = m_Position.x + 3.0f * g_Math.FastSin(64.0f);
m_CollisionBox[1].y = m_Position.y + 3.0f * g_Math.FastCos(64.0f); // m_CollisionBox[1].y = m_Position.y + 3.0f * g_Math.FastCos(64.0f);
m_CollisionBox[1].z = m_Position.z; // m_CollisionBox[1].z = m_Position.z;
//
// to right // // to right
m_CollisionBox[2].x = m_Position.x + 3.0f * g_Math.FastSin(128.0f); // m_CollisionBox[2].x = m_Position.x + 3.0f * g_Math.FastSin(128.0f);
m_CollisionBox[2].y = m_Position.y + 3.0f * g_Math.FastCos(128.0f); // m_CollisionBox[2].y = m_Position.y + 3.0f * g_Math.FastCos(128.0f);
m_CollisionBox[2].z = m_Position.z; // m_CollisionBox[2].z = m_Position.z;
//
// 45 right back // // 45 right back
m_CollisionBox[3].x = m_Position.x + 3.0f * g_Math.FastSin(192.0f); // m_CollisionBox[3].x = m_Position.x + 3.0f * g_Math.FastSin(192.0f);
m_CollisionBox[3].y = m_Position.y + 3.0f * g_Math.FastCos(192.0f); // m_CollisionBox[3].y = m_Position.y + 3.0f * g_Math.FastCos(192.0f);
m_CollisionBox[3].z = m_Position.z; // m_CollisionBox[3].z = m_Position.z;
//
// behind // // behind
m_CollisionBox[4].x = m_Position.x + 3.0f * g_Math.FastSin(256.0f); // m_CollisionBox[4].x = m_Position.x + 3.0f * g_Math.FastSin(256.0f);
m_CollisionBox[4].y = m_Position.y + 3.0f * g_Math.FastCos(256.0f); // m_CollisionBox[4].y = m_Position.y + 3.0f * g_Math.FastCos(256.0f);
m_CollisionBox[4].z = m_Position.z; // m_CollisionBox[4].z = m_Position.z;
//
// 45 left back // // 45 left back
m_CollisionBox[5].x = m_Position.x + 3.0f * g_Math.FastSin(320.0f); // m_CollisionBox[5].x = m_Position.x + 3.0f * g_Math.FastSin(320.0f);
m_CollisionBox[5].y = m_Position.y + 3.0f * g_Math.FastCos(320.0f); // m_CollisionBox[5].y = m_Position.y + 3.0f * g_Math.FastCos(320.0f);
m_CollisionBox[5].z = m_Position.z; // m_CollisionBox[5].z = m_Position.z;
//
// to left // // to left
m_CollisionBox[6].x = m_Position.x + 3.0f * g_Math.FastSin(384.0f); // m_CollisionBox[6].x = m_Position.x + 3.0f * g_Math.FastSin(384.0f);
m_CollisionBox[6].y = m_Position.y + 3.0f * g_Math.FastCos(384.0f); // m_CollisionBox[6].y = m_Position.y + 3.0f * g_Math.FastCos(384.0f);
m_CollisionBox[6].z = m_Position.z; // m_CollisionBox[6].z = m_Position.z;
//
// 45 left front // // 45 left front
m_CollisionBox[7].x = m_Position.x + 3.0f * g_Math.FastSin(448.0f); // m_CollisionBox[7].x = m_Position.x + 3.0f * g_Math.FastSin(448.0f);
m_CollisionBox[7].y = m_Position.y + 3.0f * g_Math.FastCos(448.0f); // m_CollisionBox[7].y = m_Position.y + 3.0f * g_Math.FastCos(448.0f);
m_CollisionBox[7].z = m_Position.z; // m_CollisionBox[7].z = m_Position.z;
//
// collision happened, need to move along the wall // // collision happened, need to move along the wall
float distance = 0.0f, shortest = std::numeric_limits<float>::infinity(); // float distance = 0.0f, shortest = std::numeric_limits<float>::infinity();
glm::vec3 tmp_nrm; // glm::vec3 tmp_nrm;
for (auto &vec : m_CollisionBox) { // for (auto &vec : m_CollisionBox) {
if (zone->zonemap->DoCollisionCheck(vec, vec + m_Delta, tmp_nrm, distance)) { // if (zone->zonemap->DoCollisionCheck(vec, vec + m_Delta, tmp_nrm, distance)) {
bPassed = false; // lets try with new projection next pass // bPassed = false; // lets try with new projection next pass
if (distance < shortest) { // if (distance < shortest) {
normal = tmp_nrm; // normal = tmp_nrm;
shortest = distance; // shortest = distance;
} // }
} // }
} // }
} // }
//
if (bPassed) { // if (bPassed) {
ForcedMovement = 0; // ForcedMovement = 0;
Teleport(m_Position + m_Delta); // Teleport(m_Position + m_Delta);
m_Delta = glm::vec4(); // m_Delta = glm::vec4();
SendPositionUpdate(); // SendPositionUpdate();
FixZ(); // so we teleport to the ground locally, we want the client to interpolate falling etc // FixZ(); // so we teleport to the ground locally, we want the client to interpolate falling etc
} else if (--ForcedMovement) { // } else if (--ForcedMovement) {
if (normal.z < -0.15f) // prevent too much wall climbing. ex. OMM's room in anguish // if (normal.z < -0.15f) // prevent too much wall climbing. ex. OMM's room in anguish
normal.z = 0.0f; // normal.z = 0.0f;
auto proj = glm::proj(static_cast<glm::vec3>(m_Delta), normal); // auto proj = glm::proj(static_cast<glm::vec3>(m_Delta), normal);
m_Delta.x -= proj.x; // m_Delta.x -= proj.x;
m_Delta.y -= proj.y; // m_Delta.y -= proj.y;
m_Delta.z -= proj.z; // m_Delta.z -= proj.z;
} else { // } else {
m_Delta = glm::vec4(); // well, we failed to find a spot to be forced to, lets give up // m_Delta = glm::vec4(); // well, we failed to find a spot to be forced to, lets give up
} // }
} //}
} }
void Mob::AI_Process() { void Mob::AI_Process() {

View File

@ -1,53 +1,81 @@
#include "mob_movement_manager.h" #include "mob_movement_manager.h"
#include "client.h" #include "client.h"
#include "mob.h" #include "mob.h"
#include "../common/timer.h" #include "../common/eq_packet_structs.h"
#include "../common/misc_functions.h"
#include <vector> #include <vector>
#include <map> #include <map>
#include <stdlib.h> #include <stdlib.h>
extern uint64_t frame_time; extern double frame_time;
struct MovementEntry struct RotateCommand
{ {
int animation; RotateCommand() {
float heading; rotate_to = 0.0;
bool dirty; rotate_to_speed = 0.0;
double last_sent_time; rotate_dir = 1.0;
double last_sent_time_long_distance; active = false;
started = false;
MovementEntry(Mob *m) {
animation = 0;
heading = m->GetHeading();
dirty = false;
last_sent_time = 0.0;
last_sent_time_long_distance = 0.0;
} }
double rotate_to;
double rotate_to_speed;
double rotate_dir;
bool active;
bool started;
}; };
struct MoveToEntry struct MovementCommand
{ {
float x; MovementCommand() {
float y; move_to_x = 0.0;
float z; move_to_y = 0.0;
float speed; move_to_z = 0.0;
bool active; move_to_speed = 0.0;
last_sent_short_distance = 0.0;
MoveToEntry() { last_sent_medium_distance = 0.0;
x = 0.0f; last_sent_long_distance = 0.0;
y = 0.0f;
z = 0.0f;
speed = 0.0f;
active = false; 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 struct MobMovementManager::Implementation
{ {
std::map<Mob*, MovementEntry> Entries; std::map<Mob*, MobMovementEntry> Entries;
std::map<Mob*, MoveToEntry> MoveEntries;
std::vector<Client*> Clients; std::vector<Client*> Clients;
MovementStats Stats;
}; };
MobMovementManager::MobMovementManager() MobMovementManager::MobMovementManager()
@ -55,57 +83,132 @@ MobMovementManager::MobMovementManager()
_impl.reset(new Implementation()); _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() MobMovementManager::~MobMovementManager()
{ {
} }
void MobMovementManager::Process() void MobMovementManager::Process()
{ {
double current_time = static_cast<double>(Timer::GetCurrentTime()) / 1000.0;
for (auto &mov : _impl->MoveEntries) {
auto &ent = mov.second;
if (ent.active) {
ProcessMovement(mov.first, ent.x, ent.y, ent.z, ent.speed);
}
}
for (auto &iter : _impl->Entries) { for (auto &iter : _impl->Entries) {
auto &ent = iter.second; auto &ent = iter.second;
if (ent.dirty) {
SendUpdate(iter.first, ent.animation, ent.heading);
ent.dirty = false; if (ent.RotateCommand.active) {
ent.last_sent_time = current_time; ProcessRotateCommand(iter.first, ent.RotateCommand);
ent.last_sent_time_long_distance = current_time; }
} else if (ent.animation != 0) { else if (ent.MoveCommand.active) {
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(iter.first, ent.animation, ent.heading);
ent.last_sent_time = current_time;
}
if (diff_long_range >= 6.0) {
SendUpdateLongDistance(iter.first, ent.animation, ent.heading);
ent.last_sent_time_long_distance = current_time;
}
} }
} }
} }
void MobMovementManager::AddMob(Mob *m) void MobMovementManager::AddMob(Mob *m)
{ {
_impl->Entries.insert(std::make_pair(m, MovementEntry(m))); _impl->Entries.insert(std::make_pair(m, MobMovementEntry()));
_impl->MoveEntries.insert(std::make_pair(m, MoveToEntry()));
} }
void MobMovementManager::RemoveMob(Mob *m) void MobMovementManager::RemoveMob(Mob *m)
{ {
_impl->Entries.erase(m); _impl->Entries.erase(m);
_impl->MoveEntries.erase(m);
} }
void MobMovementManager::AddClient(Client *c) void MobMovementManager::AddClient(Client *c)
@ -126,275 +229,52 @@ void MobMovementManager::RemoveClient(Client *c)
} }
} }
void MobMovementManager::SendPosition(Mob *who) void MobMovementManager::RotateTo(Mob *who, float to, float speed)
{ {
auto iter = _impl->Entries.find(who); auto iter = _impl->Entries.find(who);
auto &ent = iter->second; auto &ent = (*iter);
auto anim = 0; auto from = FixHeading(who->GetHeading());
auto heading = who->GetHeading(); to = FixHeading(to);
if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) { ent.second.RotateCommand.active = true;
ent.animation = anim; ent.second.RotateCommand.started = false;
ent.heading = heading; ent.second.RotateCommand.rotate_to = to;
ent.dirty = true; 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::SendPositionUpdate(Mob *who, bool send_to_self) void MobMovementManager::Teleport(Mob *who, float x, float y, float z, float heading)
{ {
auto iter = _impl->Entries.find(who);
auto &ent = iter->second;
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;
}
} }
void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, float speed) void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, float speed)
{ {
auto iter = _impl->MoveEntries.find(who);
auto &ent = iter->second;
ent.x = x;
ent.y = y;
ent.z = z;
ent.speed = speed;
ent.active = true;
} }
void MobMovementManager::StopNavigation(Mob *who) { void MobMovementManager::StopNavigation(Mob *who) {
auto iter = _impl->MoveEntries.find(who);
auto &ent = iter->second;
ent.active = false;
SendPosition(who);
}
void MobMovementManager::Dump(Mob *m, Client *to)
{
{
auto iter = _impl->Entries.find(m);
auto &ent = iter->second;
to->Message(0, "Packet: anim=%d, heading=%.2f, dirty=%s, last_sent_time=%.2f, last_sent_time_long_dist=%.2f",
ent.animation,
ent.heading,
ent.dirty ? "true" : "false",
ent.last_sent_time,
ent.last_sent_time_long_distance);
}
{
auto iter = _impl->MoveEntries.find(m);
auto &ent = iter->second;
to->Message(0, "Movement: speed=%.2f, x=%.2f, y=%.2f, z=%.2f, active=%s",
ent.speed,
ent.x,
ent.y,
ent.z,
ent.active ? "true" : "false");
}
}
bool MobMovementManager::HeadingEqual(float a, float b)
{
const float eps = 0.0001f;
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);
}
}
}
}
void MobMovementManager::ProcessMovement(Mob *who, float x, float y, float z, float speed)
{
if (who->GetID() == 0) {
return;
}
if (speed <= 0) {
who->SetCurrentSpeed(0);
return;
}
if (IsPositionEqual(x, y, z, who->GetX(), who->GetY(), who->GetZ())) {
StopNavigation(who);
return;
}
bool WaypointChanged = false;
bool NodeReached = false;
glm::vec3 Goal = who->UpdatePath(
x, y, z, speed, WaypointChanged, NodeReached
);
if (WaypointChanged || NodeReached) {
entity_list.OpenDoorsNear(who);
}
who->SetCurrentSpeed(static_cast<int>(speed));
who->SetRunAnimSpeed(speed);
#ifdef BOTS
if (who->IsClient() || who->IsBot())
#else
if (who->IsClient())
#endif
{
who->SetAnimation(speed * 0.55f);
}
auto &p = who->GetPosition();
//Setup Vectors
glm::vec3 tar(Goal.x, Goal.y, Goal.z);
glm::vec3 pos(p.x, p.y, p.z);
double len = glm::distance(pos, tar);
if (len == 0) {
return;
}
glm::vec3 dir = tar - pos;
glm::vec3 ndir = glm::normalize(dir);
double time_since_last = static_cast<double>(frame_time) / 1000.0;
double distance_moved = time_since_last * speed * 0.4f * 1.4f;
if (distance_moved > len) {
who->Teleport(Goal);
if (who->IsNPC()) {
entity_list.ProcessMove(who->CastToNPC(), Goal.x, Goal.y, Goal.z);
}
who->TryFixZ();
return;
}
else {
glm::vec3 npos = pos + (ndir * static_cast<float>(distance_moved));
who->Teleport(npos);
if (who->IsNPC()) {
entity_list.ProcessMove(who->CastToNPC(), npos.x, npos.y, npos.z);
}
}
who->SetHeading(who->CalculateHeadingToTarget(Goal.x, Goal.y));
SendPositionUpdate(who, false);
who->TryFixZ();
who->SetMoving(true);
if (who->IsClient()) {
who->SendPositionUpdate();
who->CastToClient()->ResetPositionTimer();
}
else {
who->SendPositionUpdate();
who->SetAppearance(eaStanding, false);
}
} }

View File

@ -4,6 +4,9 @@
class Mob; class Mob;
class Client; class Client;
struct RotateCommand;
struct PlayerPositionUpdateServer_Struct;
class MobMovementManager class MobMovementManager
{ {
public: public:
@ -14,11 +17,13 @@ public:
void AddClient(Client *c); void AddClient(Client *c);
void RemoveClient(Client *c); void RemoveClient(Client *c);
void SendPosition(Mob *who); void RotateTo(Mob *who, float to, float speed);
void SendPositionUpdate(Mob *who, bool send_to_self); void Teleport(Mob *who, float x, float y, float z, float heading);
void NavigateTo(Mob *who, float x, float y, float z, float speed); void NavigateTo(Mob *who, float x, float y, float z, float speed);
void StopNavigation(Mob *who); void StopNavigation(Mob *who);
void Dump(Mob *m, Client *to); //void Dump(Mob *m, Client *to);
//void DumpStats(Client *to);
//void ClearStats();
static MobMovementManager &Get() { static MobMovementManager &Get() {
static MobMovementManager inst; static MobMovementManager inst;
@ -30,12 +35,10 @@ private:
MobMovementManager(const MobMovementManager&); MobMovementManager(const MobMovementManager&);
MobMovementManager& operator=(const MobMovementManager&); MobMovementManager& operator=(const MobMovementManager&);
bool HeadingEqual(float a, float b); void ProcessRotateCommand(Mob *m, RotateCommand &cmd);
void SendUpdateTo(Mob *who, Client *c, int anim, float heading); void SendCommandToAllClients(Mob *m, float dx, float dy, float dz, float dh, int anim);
void SendUpdate(Mob *who, int anim, float heading); void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim);
void SendUpdateShortDistance(Mob *who, int anim, float heading); float FixHeading(float in);
void SendUpdateLongDistance(Mob *who, int anim, float heading);
void ProcessMovement(Mob *who, float x, float y, float z, float speed);
struct Implementation; struct Implementation;
std::unique_ptr<Implementation> _impl; std::unique_ptr<Implementation> _impl;

View File

@ -109,7 +109,7 @@ EQEmuLogSys LogSys;
const SPDat_Spell_Struct* spells; const SPDat_Spell_Struct* spells;
int32 SPDAT_RECORDS = -1; int32 SPDAT_RECORDS = -1;
const ZoneConfig *Config; const ZoneConfig *Config;
uint64_t frame_time = 0; double frame_time = 0.0;
void Shutdown(); void Shutdown();
extern void MapOpcodes(); extern void MapOpcodes();
@ -447,7 +447,7 @@ int main(int argc, char** argv) {
//Calculate frame time //Calculate frame time
std::chrono::time_point<std::chrono::system_clock> frame_now = std::chrono::system_clock::now(); std::chrono::time_point<std::chrono::system_clock> frame_now = std::chrono::system_clock::now();
frame_time = std::chrono::duration_cast<std::chrono::milliseconds>(frame_now - frame_prev).count(); frame_time = std::chrono::duration_cast<std::chrono::duration<double>>(frame_now - frame_prev).count();
frame_prev = frame_now; frame_prev = frame_now;
if (!eqsf_open && Config->ZonePort != 0) { if (!eqsf_open && Config->ZonePort != 0) {
@ -674,4 +674,4 @@ void UpdateWindowTitle(char* iNewTitle) {
} }
SetConsoleTitle(tmp); SetConsoleTitle(tmp);
#endif #endif
} }

View File

@ -12,7 +12,7 @@
extern Zone *zone; extern Zone *zone;
const int MaxNavmeshNodes = 4092; const int MaxNavmeshNodes = 4096;
struct PathfinderNavmesh::Implementation struct PathfinderNavmesh::Implementation
{ {
@ -43,9 +43,9 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
if (!m_impl->query) { if (!m_impl->query) {
m_impl->query = dtAllocNavMeshQuery(); m_impl->query = dtAllocNavMeshQuery();
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes);
} }
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes);
glm::vec3 current_location(start.x, start.z, start.y); glm::vec3 current_location(start.x, start.z, start.y);
glm::vec3 dest_location(end.x, end.z, end.y); glm::vec3 dest_location(end.x, end.z, end.y);

View File

@ -92,7 +92,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa
auto front = (*Route.begin()).pos; auto front = (*Route.begin()).pos;
if (PathingLoopCount > 5) { if (PathingLoopCount > 5) {
Teleport(front); Teleport(front); //todo new teleport
SendPosition(); SendPosition();
Route.pop_front(); Route.pop_front();

View File

@ -1166,55 +1166,6 @@ XS(XS_Mob_GMMove) {
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }
XS(XS_Mob_SendPosUpdate); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_SendPosUpdate) {
dXSARGS;
if (items < 1 || items > 2)
Perl_croak(aTHX_ "Usage: Mob::SendPosUpdate(THIS, [uint8 send_to_self = 0])");
{
Mob *THIS;
uint8 iSendToSelf;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV *) SvRV(ST(0)));
THIS = INT2PTR(Mob *, tmp);
} else
Perl_croak(aTHX_ "THIS is not of type Mob");
if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
if (items < 2)
iSendToSelf = 0;
else {
iSendToSelf = (uint8) SvUV(ST(1));
}
THIS->SendPositionUpdate(iSendToSelf != 0 ? true : false);
}
XSRETURN_EMPTY;
}
XS(XS_Mob_SendPosition); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_SendPosition) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: Mob::SendPosition(THIS)");
{
Mob *THIS;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV *) SvRV(ST(0)));
THIS = INT2PTR(Mob *, tmp);
} else
Perl_croak(aTHX_ "THIS is not of type Mob");
if (THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->SendPosition();
}
XSRETURN_EMPTY;
}
XS(XS_Mob_HasProcs); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_HasProcs); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_HasProcs) { XS(XS_Mob_HasProcs) {
dXSARGS; dXSARGS;
@ -8549,8 +8500,6 @@ XS(boot_Mob) {
newXSproto(strcpy(buf, "DoAnim"), XS_Mob_DoAnim, file, "$$;$"); newXSproto(strcpy(buf, "DoAnim"), XS_Mob_DoAnim, file, "$$;$");
newXSproto(strcpy(buf, "ChangeSize"), XS_Mob_ChangeSize, file, "$$;$"); newXSproto(strcpy(buf, "ChangeSize"), XS_Mob_ChangeSize, file, "$$;$");
newXSproto(strcpy(buf, "GMMove"), XS_Mob_GMMove, file, "$$$$;$"); newXSproto(strcpy(buf, "GMMove"), XS_Mob_GMMove, file, "$$$$;$");
newXSproto(strcpy(buf, "SendPosUpdate"), XS_Mob_SendPosUpdate, file, "$;$");
newXSproto(strcpy(buf, "SendPosition"), XS_Mob_SendPosition, file, "$");
newXSproto(strcpy(buf, "HasProcs"), XS_Mob_HasProcs, file, "$"); newXSproto(strcpy(buf, "HasProcs"), XS_Mob_HasProcs, file, "$");
newXSproto(strcpy(buf, "IsInvisible"), XS_Mob_IsInvisible, file, "$;$"); newXSproto(strcpy(buf, "IsInvisible"), XS_Mob_IsInvisible, file, "$;$");
newXSproto(strcpy(buf, "SetInvisible"), XS_Mob_SetInvisible, file, "$$"); newXSproto(strcpy(buf, "SetInvisible"), XS_Mob_SetInvisible, file, "$$");

View File

@ -217,7 +217,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p
{ {
npc->AssignWaypoints(grid); npc->AssignWaypoints(grid);
} }
npc->SendPositionUpdate();
return npc; return npc;
} }
return nullptr; return nullptr;
@ -241,7 +241,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v
{ {
npc->AssignWaypoints(grid); npc->AssignWaypoints(grid);
} }
npc->SendPositionUpdate();
return npc; return npc;
} }
return nullptr; return nullptr;
@ -1693,8 +1693,6 @@ void QuestManager::respawn(int npcTypeID, int grid) {
entity_list.AddNPC(owner->CastToNPC(),true,true); entity_list.AddNPC(owner->CastToNPC(),true,true);
if(grid > 0) if(grid > 0)
owner->CastToNPC()->AssignWaypoints(grid); owner->CastToNPC()->AssignWaypoints(grid);
owner->SendPositionUpdate();
} }
} }

View File

@ -27,7 +27,7 @@
#include <string.h> #include <string.h>
extern uint64_t frame_time; extern double frame_time;
int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target)
{ {
@ -1033,7 +1033,7 @@ void Mob::ProjectileAttack()
ProjectileAtk[i].skill = 0; ProjectileAtk[i].skill = 0;
ProjectileAtk[i].speed_mod = 0.0f; ProjectileAtk[i].speed_mod = 0.0f;
} else { } else {
ProjectileAtk[i].increment += frame_time; ProjectileAtk[i].increment += 1000 * frame_time;
} }
} }

View File

@ -826,8 +826,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
#endif #endif
if(IsClient()) if(IsClient())
{ {
CastToClient()->SetSenseExemption(true);
if (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater) if (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater)
{ {
bodyType bt = BT_Undead; bodyType bt = BT_Undead;
@ -4038,63 +4036,6 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
SetLevel(GetOrigLevel()); SetLevel(GetOrigLevel());
break; break;
} }
case SE_MovementSpeed:
{
if(IsClient())
{
Client *my_c = CastToClient();
uint32 cur_time = Timer::GetCurrentTime();
if((cur_time - my_c->m_TimeSinceLastPositionCheck) > 1000)
{
float speed = (my_c->m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - my_c->m_TimeSinceLastPositionCheck);
float runs = my_c->GetRunspeed();
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
if(!my_c->GetGMSpeed() && (runs >= my_c->GetBaseRunspeed() || (speed > (my_c->GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
{
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
my_c->m_DistanceSinceLastPositionCheck, (cur_time - my_c->m_TimeSinceLastPositionCheck), speed);
if(my_c->IsShadowStepExempted())
{
if(my_c->m_DistanceSinceLastPositionCheck > 800)
{
my_c->CheatDetected(MQWarpShadowStep, my_c->GetX(), my_c->GetY(), my_c->GetZ());
}
}
else if(my_c->IsKnockBackExempted())
{
//still potential to trigger this if you're knocked back off a
//HUGE fall that takes > 2.5 seconds
if(speed > 30.0f)
{
my_c->CheatDetected(MQWarpKnockBack, my_c->GetX(), my_c->GetY(), my_c->GetZ());
}
}
else if(!my_c->IsPortExempted())
{
if(!my_c->IsMQExemptedArea(zone->GetZoneID(), my_c->GetX(), my_c->GetY(), my_c->GetZ()))
{
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
my_c->m_TimeSinceLastPositionCheck = cur_time;
my_c->m_DistanceSinceLastPositionCheck = 0.0f;
my_c->CheatDetected(MQWarp, my_c->GetX(), my_c->GetY(), my_c->GetZ());
//my_c->Death(my_c, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
}
else
{
my_c->CheatDetected(MQWarpLight, my_c->GetX(), my_c->GetY(), my_c->GetZ());
}
}
}
}
}
}
my_c->m_TimeSinceLastPositionCheck = cur_time;
my_c->m_DistanceSinceLastPositionCheck = 0.0f;
}
}
} }
} }

View File

@ -305,8 +305,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
} }
//To prevent NPC ghosting when spells are cast from scripts //To prevent NPC ghosting when spells are cast from scripts
if (IsNPC() && IsMoving() && cast_time > 0) if (IsNPC() && IsMoving() && cast_time > 0) {
SendPosition(); StopNavigation();
}
if(resist_adjust) if(resist_adjust)
{ {
@ -2665,23 +2666,6 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
action->effect_flag = 4; action->effect_flag = 4;
if(spells[spell_id].pushback != 0.0f || spells[spell_id].pushup != 0.0f)
{
if(IsClient())
{
if(!IsBuffSpell(spell_id))
{
CastToClient()->SetKnockBackExemption(true);
}
}
}
if(IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep))
{
CastToClient()->SetShadowStepExemption(true);
}
if(!IsEffectInSpell(spell_id, SE_BindAffinity)) if(!IsEffectInSpell(spell_id, SE_BindAffinity))
{ {
CastToClient()->QueuePacket(packet); CastToClient()->QueuePacket(packet);
@ -3943,13 +3927,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
if(spells[spell_id].pushback != 0.0f || spells[spell_id].pushup != 0.0f) if(spells[spell_id].pushback != 0.0f || spells[spell_id].pushup != 0.0f)
{ {
if(spelltar->IsClient()) if (RuleB(Spells, NPCSpellPush) && !spelltar->IsRooted() && spelltar->ForcedMovement == 0) {
{
if(!IsBuffSpell(spell_id))
{
spelltar->CastToClient()->SetKnockBackExemption(true);
}
} else if (RuleB(Spells, NPCSpellPush) && !spelltar->IsRooted() && spelltar->ForcedMovement == 0) {
spelltar->m_Delta.x += action->force * g_Math.FastSin(action->hit_heading); spelltar->m_Delta.x += action->force * g_Math.FastSin(action->hit_heading);
spelltar->m_Delta.y += action->force * g_Math.FastCos(action->hit_heading); spelltar->m_Delta.y += action->force * g_Math.FastCos(action->hit_heading);
spelltar->m_Delta.z += action->hit_pitch; spelltar->m_Delta.z += action->hit_pitch;
@ -3957,11 +3935,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
} }
} }
if(spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep))
{
spelltar->CastToClient()->SetShadowStepExemption(true);
}
if(!IsEffectInSpell(spell_id, SE_BindAffinity)) if(!IsEffectInSpell(spell_id, SE_BindAffinity))
{ {
if(spelltar != this && spelltar->IsClient()) // send to target if(spelltar != this && spelltar->IsClient()) // send to target
@ -4940,18 +4913,7 @@ void Mob::Mesmerize()
if (casting_spell_id) if (casting_spell_id)
InterruptSpell(); InterruptSpell();
SendPosition(); StopNavigation();
/* this stuns the client for max time, with no way to break it
if (this->IsClient()){
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Stun, sizeof(Stun_Struct));
Stun_Struct* stunon = (Stun_Struct*) outapp->pBuffer;
stunon->duration = 0xFFFF;
this->CastToClient()->QueuePacket(outapp);
safe_delete(outapp);
} else {
SetRunAnimSpeed(0);
}
*/
} }
void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message) void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message)

View File

@ -93,7 +93,7 @@ void NPC::StopWandering()
{ // stops a mob from wandering, takes him off grid and sends him back to spawn point { // stops a mob from wandering, takes him off grid and sends him back to spawn point
roamer = false; roamer = false;
CastToNPC()->SetGrid(0); CastToNPC()->SetGrid(0);
SendPosition(); StopNavigation();
Log(Logs::Detail, Logs::Pathing, "Stop Wandering requested."); Log(Logs::Detail, Logs::Pathing, "Stop Wandering requested.");
return; return;
} }
@ -150,7 +150,7 @@ void NPC::PauseWandering(int pausetime)
moving = false; moving = false;
DistractedFromGrid = true; DistractedFromGrid = true;
Log(Logs::Detail, Logs::Pathing, "Paused Wandering requested. Grid %d. Resuming in %d ms (0=not until told)", GetGrid(), pausetime); Log(Logs::Detail, Logs::Pathing, "Paused Wandering requested. Grid %d. Resuming in %d ms (0=not until told)", GetGrid(), pausetime);
SendPosition(); StopNavigation();
if (pausetime < 1) { // negative grid number stops him dead in his tracks until ResumeWandering() if (pausetime < 1) { // negative grid number stops him dead in his tracks until ResumeWandering()
SetGrid(0 - GetGrid()); SetGrid(0 - GetGrid());
} }
@ -619,11 +619,6 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) {
return new_z; return new_z;
} }
void Mob::DumpMovement(Client *to)
{
mMovementManager->Dump(this, to);
}
void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) { void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) {
glm::vec3 current_loc(m_Position); glm::vec3 current_loc(m_Position);

View File

@ -1644,8 +1644,7 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, uint32 to, Clien
// this shouldn't open up any exploits since those situations are detected later on // this shouldn't open up any exploits since those situations are detected later on
if ((zone->HasWaterMap() && !zone->watermap->InZoneLine(glm::vec3(client->GetPosition()))) || (!zone->HasWaterMap() && closest_dist > 400.0f && closest_dist < max_distance2)) if ((zone->HasWaterMap() && !zone->watermap->InZoneLine(glm::vec3(client->GetPosition()))) || (!zone->HasWaterMap() && closest_dist > 400.0f && closest_dist < max_distance2))
{ {
if(client) //TODO cheat detection
client->CheatDetected(MQZoneUnknownDest, location.x, location.y, location.z); // Someone is trying to use /zone
Log(Logs::General, Logs::Status, "WARNING: Closest zone point for zone id %d is %f, you might need to update your zone_points table if you dont arrive at the right spot.", to, closest_dist); Log(Logs::General, Logs::Status, "WARNING: Closest zone point for zone id %d is %f, you might need to update your zone_points table if you dont arrive at the right spot.", to, closest_dist);
Log(Logs::General, Logs::Status, "<Real Zone Points>. %s", to_string(location).c_str()); Log(Logs::General, Logs::Status, "<Real Zone Points>. %s", to_string(location).c_str());
} }

View File

@ -95,7 +95,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
//unable to find a zone point... is there anything else //unable to find a zone point... is there anything else
//that can be a valid un-zolicited zone request? //that can be a valid un-zolicited zone request?
CheatDetected(MQZone, zc->x, zc->y, zc->z); //Todo cheat detection
Message(13, "Invalid unsolicited zone request."); Message(13, "Invalid unsolicited zone request.");
Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id); Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
SendZoneCancel(zc); SendZoneCancel(zc);
@ -130,7 +130,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
//then we assume this is invalid. //then we assume this is invalid.
if(!zone_point || zone_point->target_zone_id != target_zone_id) { if(!zone_point || zone_point->target_zone_id != target_zone_id) {
Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id); Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
CheatDetected(MQGate, zc->x, zc->y, zc->z); //todo cheat detection
SendZoneCancel(zc); SendZoneCancel(zc);
return; return;
} }
@ -252,7 +252,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
//for now, there are no other cases... //for now, there are no other cases...
//could not find a valid reason for them to be zoning, stop it. //could not find a valid reason for them to be zoning, stop it.
CheatDetected(MQZoneUnknownDest, 0.0, 0.0, 0.0); //todo cheat detection
Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%s'. Not near a zone point.", GetName(), target_zone_name); Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%s'. Not near a zone point.", GetName(), target_zone_name);
SendZoneCancel(zc); SendZoneCancel(zc);
return; return;
@ -296,7 +296,6 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
void Client::SendZoneCancel(ZoneChange_Struct *zc) { void Client::SendZoneCancel(ZoneChange_Struct *zc) {
//effectively zone them right back to where they were //effectively zone them right back to where they were
//unless we find a better way to stop the zoning process. //unless we find a better way to stop the zoning process.
SetPortExemption(true);
EQApplicationPacket *outapp = nullptr; EQApplicationPacket *outapp = nullptr;
outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct)); outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct));
ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer; ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer;
@ -316,8 +315,6 @@ void Client::SendZoneError(ZoneChange_Struct *zc, int8 err)
{ {
Log(Logs::General, Logs::Error, "Zone %i is not available because target wasn't found or character insufficent level", zc->zoneID); Log(Logs::General, Logs::Error, "Zone %i is not available because target wasn't found or character insufficent level", zc->zoneID);
SetPortExemption(true);
EQApplicationPacket *outapp = nullptr; EQApplicationPacket *outapp = nullptr;
outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct)); outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct));
ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer; ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer;
@ -488,8 +485,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
pShortZoneName = database.GetZoneName(zoneID); pShortZoneName = database.GetZoneName(zoneID);
database.GetZoneLongName(pShortZoneName, &pZoneName); database.GetZoneLongName(pShortZoneName, &pZoneName);
SetPortExemption(true);
if(!pZoneName) { if(!pZoneName) {
Message(13, "Invalid zone number specified"); Message(13, "Invalid zone number specified");
safe_delete_array(pZoneName); safe_delete_array(pZoneName);