mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 01:11:29 +00:00
Redoing movement to introduce proper rotation
This commit is contained in:
parent
1aa97957d8
commit
29ea65a71e
@ -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,
|
||||||
|
|||||||
333
zone/client.cpp
333
zone/client.cpp
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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++;
|
||||||
|
|||||||
@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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];
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
36
zone/mob.cpp
36
zone/mob.cpp
@ -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;
|
||||||
|
|
||||||
|
|||||||
10
zone/mob.h
10
zone/mob.h
@ -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;
|
||||||
|
|||||||
162
zone/mob_ai.cpp
162
zone/mob_ai.cpp
@ -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() {
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
|
|
||||||
|
|||||||
@ -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, "$$");
|
||||||
|
|||||||
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user