Merge branch 'master' into auras

This commit is contained in:
Michael Cook (mackal) 2017-07-14 23:14:13 -04:00
commit e05a45f6c7
16 changed files with 173 additions and 233 deletions

View File

@ -1,5 +1,11 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 7/14/2017 ==
Akkadius: HP Update tuning - HP Updates are now forced when a client is targeted
Akkadius: Client position updates should be smoother (granted the client has a good connection)
- Clients should also no longer randomly disappear
== 7/11/2017 == == 7/11/2017 ==
Akkadius: Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes Akkadius: Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes
Akkadius: Raid/Group Mana/Endurance updates should now update real-time once again Akkadius: Raid/Group Mana/Endurance updates should now update real-time once again

View File

@ -150,6 +150,7 @@ RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'h
RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior
RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation
RULE_BOOL(Character, UseOldConSystem, false) // Grant Health of Target's Target leadership AA on character creation RULE_BOOL(Character, UseOldConSystem, false) // Grant Health of Target's Target leadership AA on character creation
RULE_BOOL(Character, OPClientUpdateVisualDebug, false) // Shows a pulse and forward directional particle each time the client sends its position to server
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Mercs) RULE_CATEGORY(Mercs)

View File

@ -3551,7 +3551,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
Teleport(new_pos); Teleport(new_pos);
if (position_update_melee_push_timer.Check()) { if (position_update_melee_push_timer.Check()) {
SendPosUpdate(); SendPositionUpdate();
} }
} }
} }

View File

@ -2172,7 +2172,7 @@ void Bot::AI_Process() {
} }
if(IsMoving()) if(IsMoving())
SendPosUpdate(); SendPositionUpdate();
else else
SendPosition(); SendPosition();
} }
@ -2383,7 +2383,7 @@ void Bot::AI_Process() {
// TODO: Test RuleB(Bots, UpdatePositionWithTimer) // TODO: Test RuleB(Bots, UpdatePositionWithTimer)
if(IsMoving()) if(IsMoving())
SendPosUpdate(); SendPositionUpdate();
else else
SendPosition(); SendPosition();
} }
@ -2505,7 +2505,7 @@ void Bot::AI_Process() {
} }
if(IsMoving()) if(IsMoving())
SendPosUpdate(); SendPositionUpdate();
else else
SendPosition(); SendPosition();
} }

View File

@ -159,11 +159,12 @@ Client::Client(EQStreamInterface* ieqs)
m_dirtyautohaters(false), m_dirtyautohaters(false),
npc_close_scan_timer(6000), npc_close_scan_timer(6000),
hp_self_update_throttle_timer(300), hp_self_update_throttle_timer(300),
hp_other_update_throttle_timer(500) hp_other_update_throttle_timer(500),
position_update_timer(0)
{ {
for(int cf=0; cf < _FilterCount; cf++) for (int client_filter = 0; client_filter < _FilterCount; client_filter++)
ClientFilters[cf] = FilterShow; ClientFilters[client_filter] = FilterShow;
character_id = 0; character_id = 0;
conn_state = NoPacketsReceived; conn_state = NoPacketsReceived;
@ -196,7 +197,7 @@ Client::Client(EQStreamInterface* ieqs)
last_reported_endurance = 0; last_reported_endurance = 0;
last_reported_endurance_percent = 0; last_reported_endurance_percent = 0;
last_reported_mana_percent = 0; last_reported_mana_percent = 0;
gmhideme = false; gm_hide_me = false;
AFK = false; AFK = false;
LFG = false; LFG = false;
LFGFromLevel = 0; LFGFromLevel = 0;
@ -260,7 +261,7 @@ Client::Client(EQStreamInterface* ieqs)
memset(&m_epp, 0, sizeof(m_epp)); memset(&m_epp, 0, sizeof(m_epp));
PendingTranslocate = false; PendingTranslocate = false;
PendingSacrifice = false; PendingSacrifice = false;
BoatID = 0; controlling_boat_id = 0;
KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS)); KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS));
GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS)); GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS));
@ -1971,7 +1972,7 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
} }
bool Client::GMHideMe(Client* client) { bool Client::GMHideMe(Client* client) {
if (gmhideme) { if (gm_hide_me) {
if (client == 0) if (client == 0)
return true; return true;
else if (admin > client->Admin()) else if (admin > client->Admin())
@ -3240,9 +3241,9 @@ void Client::SetHideMe(bool flag)
{ {
EQApplicationPacket app; EQApplicationPacket app;
gmhideme = flag; gm_hide_me = flag;
if(gmhideme) if(gm_hide_me)
{ {
database.SetHideMe(AccountID(),true); database.SetHideMe(AccountID(),true);
CreateDespawnPacket(&app, false); CreateDespawnPacket(&app, false);
@ -6373,7 +6374,7 @@ void Client::LocateCorpse()
SetHeading(CalculateHeadingToTarget(ClosestCorpse->GetX(), ClosestCorpse->GetY())); SetHeading(CalculateHeadingToTarget(ClosestCorpse->GetX(), ClosestCorpse->GetY()));
SetTarget(ClosestCorpse); SetTarget(ClosestCorpse);
SendTargetCommand(ClosestCorpse->GetID()); SendTargetCommand(ClosestCorpse->GetID());
SendPosUpdate(2); SendPositionUpdate(2);
} }
else if(!GetTarget()) else if(!GetTarget())
Message_StringID(clientMessageError, SENSE_CORPSE_NONE); Message_StringID(clientMessageError, SENSE_CORPSE_NONE);

View File

@ -320,7 +320,7 @@ public:
bool GetRevoked() const { return revoked; } bool GetRevoked() const { return revoked; }
void SetRevoked(bool rev) { revoked = rev; } void SetRevoked(bool rev) { revoked = rev; }
inline uint32 GetIP() const { return ip; } inline uint32 GetIP() const { return ip; }
inline bool GetHideMe() const { return gmhideme; } inline bool GetHideMe() const { return gm_hide_me; }
void SetHideMe(bool hm); void SetHideMe(bool hm);
inline uint16 GetPort() const { return port; } inline uint16 GetPort() const { return port; }
bool IsDead() const { return(dead); } bool IsDead() const { return(dead); }
@ -1072,7 +1072,7 @@ public:
void Signal(uint32 data); void Signal(uint32 data);
Mob *GetBindSightTarget() { return bind_sight_target; } Mob *GetBindSightTarget() { return bind_sight_target; }
void SetBindSightTarget(Mob *n) { bind_sight_target = n; } void SetBindSightTarget(Mob *n) { bind_sight_target = n; }
const uint16 GetBoatID() const { return BoatID; } const uint16 GetBoatID() const { return controlling_boat_id; }
void SendRewards(); void SendRewards();
bool TryReward(uint32 claim_id); bool TryReward(uint32 claim_id);
QGlobalCache *GetQGlobals() { return qGlobals; } QGlobalCache *GetQGlobals() { return qGlobals; }
@ -1376,7 +1376,7 @@ private:
bool duelaccepted; bool duelaccepted;
std::list<uint32> keyring; std::list<uint32> keyring;
bool tellsoff; // GM /toggle bool tellsoff; // GM /toggle
bool gmhideme; bool gm_hide_me;
bool LFG; bool LFG;
bool LFP; bool LFP;
uint8 LFGFromLevel; uint8 LFGFromLevel;
@ -1396,7 +1396,7 @@ private:
uint32 weight; uint32 weight;
bool berserk; bool berserk;
bool dead; bool dead;
uint16 BoatID; uint16 controlling_boat_id;
uint16 TrackingID; uint16 TrackingID;
uint16 CustomerID; uint16 CustomerID;
uint16 TraderID; uint16 TraderID;
@ -1487,6 +1487,7 @@ private:
Timer npc_close_scan_timer; Timer npc_close_scan_timer;
Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */ Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */
Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */ Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
glm::vec3 m_Proximity; glm::vec3 m_Proximity;
void BulkSendInventoryItems(); void BulkSendInventoryItems();

View File

@ -1288,7 +1288,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
lsaccountid = atoi(row[2]); lsaccountid = atoi(row[2]);
gmspeed = atoi(row[3]); gmspeed = atoi(row[3]);
revoked = atoi(row[4]); revoked = atoi(row[4]);
gmhideme = atoi(row[5]); gm_hide_me = atoi(row[5]);
account_creation = atoul(row[6]); account_creation = atoul(row[6]);
} }
@ -1356,7 +1356,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (level) { level = m_pp.level; } if (level) { level = m_pp.level; }
/* If GM, not trackable */ /* If GM, not trackable */
if (gmhideme) { trackable = false; } if (gm_hide_me) { trackable = false; }
/* Set Con State for Reporting */ /* Set Con State for Reporting */
conn_state = PlayerProfileLoaded; conn_state = PlayerProfileLoaded;
@ -3882,7 +3882,7 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app)
Mob* boat = entity_list.GetMob(boatname); Mob* boat = entity_list.GetMob(boatname);
if (!boat || (boat->GetRace() != CONTROLLED_BOAT && boat->GetRace() != 502)) if (!boat || (boat->GetRace() != CONTROLLED_BOAT && boat->GetRace() != 502))
return; return;
BoatID = 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
return; return;
} }
@ -4373,7 +4373,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
if (dead) if (dead)
return; return;
//currently accepting two sizes, one has an extra byte on the end /* Invalid size check */
if (app->size != sizeof(PlayerPositionUpdateClient_Struct) if (app->size != sizeof(PlayerPositionUpdateClient_Struct)
&& app->size != (sizeof(PlayerPositionUpdateClient_Struct) + 1) && app->size != (sizeof(PlayerPositionUpdateClient_Struct) + 1)
) { ) {
@ -4382,30 +4382,30 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
} }
PlayerPositionUpdateClient_Struct* ppu = (PlayerPositionUpdateClient_Struct*)app->pBuffer; PlayerPositionUpdateClient_Struct* ppu = (PlayerPositionUpdateClient_Struct*)app->pBuffer;
/* Boat handling */
if (ppu->spawn_id != GetID()) { if (ppu->spawn_id != GetID()) {
// check if the id is for a boat the player is controlling /* If player is controlling boat */
if (ppu->spawn_id == BoatID) { if (ppu->spawn_id == controlling_boat_id) {
Mob* boat = entity_list.GetMob(BoatID); Mob* boat = entity_list.GetMob(controlling_boat_id);
if (boat == 0) { // if the boat ID is invalid, reset the id and abort if (boat == 0) {
BoatID = 0; controlling_boat_id = 0;
return; return;
} }
// set the boat's position deltas auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading);
auto boatDelta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading); boat->SetDelta(boat_delta);
boat->SetDelta(boatDelta);
// send an update to everyone nearby except the client controlling the boat 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, EQ19toFloat(ppu->heading), false); boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ19toFloat(ppu->heading), false);
return; return;
} }
else return; // if not a boat, do nothing else return;
} }
float dist = 0; float dist = 0;
@ -4416,51 +4416,34 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
dist += tmp*tmp; dist += tmp*tmp;
dist = sqrt(dist); dist = sqrt(dist);
//the purpose of this first block may not be readily apparent /* Hack checks */
//basically it's so people don't do a moderate warp every 2.5 seconds if (dist == 0) {
//letting it even out and basically getting the job done without triggering if (m_DistanceSinceLastPositionCheck > 0.0) {
if (dist == 0)
{
if (m_DistanceSinceLastPositionCheck > 0.0)
{
uint32 cur_time = Timer::GetCurrentTime(); uint32 cur_time = Timer::GetCurrentTime();
if ((cur_time - m_TimeSinceLastPositionCheck) > 0) if ((cur_time - m_TimeSinceLastPositionCheck) > 0) {
{
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
int runs = GetRunspeed(); int runs = GetRunspeed();
if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
{ if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) {
if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) if (IsShadowStepExempted()) {
{ if (m_DistanceSinceLastPositionCheck > 800) {
if (IsShadowStepExempted())
{
if (m_DistanceSinceLastPositionCheck > 800)
{
CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos);
} }
} }
else if (IsKnockBackExempted()) else if (IsKnockBackExempted()) {
{ if (speed > 30.0f) {
//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, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos);
} }
} }
else if (!IsPortExempted()) else if (!IsPortExempted()) {
{ if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) {
if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
{
if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
m_TimeSinceLastPositionCheck = cur_time; m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f; m_DistanceSinceLastPositionCheck = 0.0f;
CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos);
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT); //Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
} }
else else {
{
CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos);
} }
} }
@ -4475,64 +4458,42 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
m_CheatDetectMoved = false; m_CheatDetectMoved = false;
} }
} }
else else {
{
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime(); m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
m_CheatDetectMoved = false; m_CheatDetectMoved = false;
} }
} }
else else {
{
m_DistanceSinceLastPositionCheck += dist; m_DistanceSinceLastPositionCheck += dist;
m_CheatDetectMoved = true; m_CheatDetectMoved = true;
if (m_TimeSinceLastPositionCheck == 0) if (m_TimeSinceLastPositionCheck == 0) {
{
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime(); m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
} }
else else {
{
uint32 cur_time = Timer::GetCurrentTime(); uint32 cur_time = Timer::GetCurrentTime();
if ((cur_time - m_TimeSinceLastPositionCheck) > 2500) if ((cur_time - m_TimeSinceLastPositionCheck) > 2500) {
{
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
int runs = GetRunspeed(); int runs = GetRunspeed();
if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
{ if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) {
if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) if (IsShadowStepExempted()) {
{ if (m_DistanceSinceLastPositionCheck > 800) {
if (IsShadowStepExempted())
{
if (m_DistanceSinceLastPositionCheck > 800)
{
//if(!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos))
//{
CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos);
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
//}
} }
} }
else if (IsKnockBackExempted()) else if (IsKnockBackExempted()) {
{ if (speed > 30.0f) {
//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, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos);
} }
} }
else if (!IsPortExempted()) else if (!IsPortExempted()) {
{ if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) {
if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
{
if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
{
m_TimeSinceLastPositionCheck = cur_time; m_TimeSinceLastPositionCheck = cur_time;
m_DistanceSinceLastPositionCheck = 0.0f; m_DistanceSinceLastPositionCheck = 0.0f;
CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos);
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
} }
else else {
{
CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos); CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos);
} }
} }
@ -4551,7 +4512,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
DragCorpses(); 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;
@ -4560,14 +4521,19 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
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. /*
//If the player has moved more than units for x or y, then we'll store We only need to store updated values if the player has moved.
//his pre-PPU x and y for /rewind, in case he gets stuck. 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.
*/
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, /*
//just update rewind coords to the new ppu coords. This will prevent exploitation. 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.
*/
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);
@ -4580,7 +4546,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
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, ppu->delta_heading); m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, 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))) {
@ -4588,7 +4554,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
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) {
hidden = false; hidden = false;
@ -4633,39 +4599,39 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
client_scan_npc_aggro_timer.Start(3000); client_scan_npc_aggro_timer.Start(3000);
} }
} }
/* Update internal server position from what the client has sent */
m_Position.x = ppu->x_pos;
m_Position.y = ppu->y_pos;
m_Position.z = ppu->z_pos;
m_Position.w = EQ19toFloat(ppu->heading);
animation = ppu->animation;
// Outgoing client packet /* Visual Debugging */
float tmpheading = EQ19toFloat(ppu->heading); if (RuleB(Character, OPClientUpdateVisualDebug)) {
/* The clients send an update at best every 1.3 seconds Log(Logs::General, Logs::Debug, "ClientUpdate: ppu x: %f y: %f z: %f h: %u", ppu->x_pos, ppu->y_pos, ppu->z_pos, ppu->heading);
* We want to avoid reflecting these updates to other clients as much as possible this->SendAppearanceEffect(78, 0, 0, 0, 0);
* The client also sends an update every 280 ms while turning, if we prevent this->SendAppearanceEffect(41, 0, 0, 0, 0);
* sending these by checking if the location is the same too aggressively, clients end up spinning
* so keep a count of how many packets are the same within a tolerance and stop when we get there */
bool pos_same = FCMP(ppu->y_pos, m_Position.y) && FCMP(ppu->x_pos, m_Position.x) && FCMP(tmpheading, m_Position.w) && ppu->animation == animation;
if (!pos_same || (pos_same && position_update_same_count < 6))
{
if (pos_same)
position_update_same_count++;
else
position_update_same_count = 0;
m_Position.x = ppu->x_pos;
m_Position.y = ppu->y_pos;
m_Position.z = ppu->z_pos;
m_Position.w = tmpheading;
animation = ppu->animation;
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
MakeSpawnUpdate(ppu);
if (gmhideme)
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250);
else
entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, false);
safe_delete(outapp);
} }
/* Broadcast update to other clients */
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* position_update = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
MakeSpawnUpdate(position_update);
position_update_timer.Start(10000, true);
if (gm_hide_me) {
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250);
}
else {
entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, true);
}
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);
@ -4675,27 +4641,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
return; return;
} }
/*
void Client::Handle_OP_CloseContainer(const EQApplicationPacket *app)
{
if (app->size != sizeof(CloseContainer_Struct)) {
LogFile->write(EQEMuLog::Error, "Invalid size on CloseContainer_Struct: Expected %i, Got %i",
sizeof(CloseContainer_Struct), app->size);
return;
}
SetTradeskillObject(nullptr);
ClickObjectAck_Struct* oos = (ClickObjectAck_Struct*)app->pBuffer;
Entity* entity = entity_list.GetEntityObject(oos->drop_id);
if (entity && entity->IsObject()) {
Object* object = entity->CastToObject();
object->Close();
}
return;
}
*/
void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app) void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app)
{ {
if (app->size != sizeof(CombatAbility_Struct)) { if (app->size != sizeof(CombatAbility_Struct)) {
@ -8946,12 +8891,12 @@ void Client::Handle_OP_LeaveAdventure(const EQApplicationPacket *app)
void Client::Handle_OP_LeaveBoat(const EQApplicationPacket *app) void Client::Handle_OP_LeaveBoat(const EQApplicationPacket *app)
{ {
Mob* boat = entity_list.GetMob(this->BoatID); // find the mob corresponding to the boat id Mob* boat = entity_list.GetMob(this->controlling_boat_id); // find the mob corresponding to the boat id
if (boat) { if (boat) {
if ((boat->GetTarget() == this) && boat->GetHateAmount(this) == 0) // if the client somehow left while still controlling the boat (and the boat isn't attacking them) if ((boat->GetTarget() == this) && boat->GetHateAmount(this) == 0) // if the client somehow left while still controlling the boat (and the boat isn't attacking them)
boat->SetTarget(0); // fix it to stop later problems boat->SetTarget(0); // fix it to stop later problems
} }
this->BoatID = 0; this->controlling_boat_id = 0;
return; return;
} }

View File

@ -63,64 +63,49 @@ extern EntityList entity_list;
bool Client::Process() { bool Client::Process() {
bool ret = true; bool ret = true;
if (Connected() || IsLD()) if (Connected() || IsLD()) {
{
// try to send all packets that weren't sent before // try to send all packets that weren't sent before
if (!IsLD() && zoneinpacket_timer.Check()) if (!IsLD() && zoneinpacket_timer.Check()) {
{
SendAllPackets(); SendAllPackets();
} }
if (adventure_request_timer) if (adventure_request_timer) {
{ if (adventure_request_timer->Check()) {
if (adventure_request_timer->Check())
{
safe_delete(adventure_request_timer); safe_delete(adventure_request_timer);
} }
} }
if (adventure_create_timer) if (adventure_create_timer) {
{ if (adventure_create_timer->Check()) {
if (adventure_create_timer->Check())
{
safe_delete(adventure_create_timer); safe_delete(adventure_create_timer);
} }
} }
if (adventure_leave_timer) if (adventure_leave_timer) {
{ if (adventure_leave_timer->Check()) {
if (adventure_leave_timer->Check())
{
safe_delete(adventure_leave_timer); safe_delete(adventure_leave_timer);
} }
} }
if (adventure_door_timer) if (adventure_door_timer) {
{ if (adventure_door_timer->Check()) {
if (adventure_door_timer->Check())
{
safe_delete(adventure_door_timer); safe_delete(adventure_door_timer);
} }
} }
if (adventure_stats_timer) if (adventure_stats_timer) {
{ if (adventure_stats_timer->Check()) {
if (adventure_stats_timer->Check())
{
safe_delete(adventure_stats_timer); safe_delete(adventure_stats_timer);
} }
} }
if (adventure_leaderboard_timer) if (adventure_leaderboard_timer) {
{ if (adventure_leaderboard_timer->Check()) {
if (adventure_leaderboard_timer->Check())
{
safe_delete(adventure_leaderboard_timer); safe_delete(adventure_leaderboard_timer);
} }
} }
if (dead) if (dead) {
{
SetHP(-100); SetHP(-100);
if (RespawnFromHoverTimer.Check()) if (RespawnFromHoverTimer.Check())
HandleRespawnFromHover(0); HandleRespawnFromHover(0);
@ -134,6 +119,11 @@ bool Client::Process() {
if (hpupdate_timer.Check(false)) if (hpupdate_timer.Check(false))
SendHPUpdate(); SendHPUpdate();
/* I haven't naturally updated my position in 10 seconds, updating manually */
if (position_update_timer.Check()) {
SendPositionUpdate();
}
if (mana_timer.Check()) if (mana_timer.Check())
CheckManaEndUpdate(); CheckManaEndUpdate();
@ -271,15 +261,6 @@ bool Client::Process() {
close_mobs.insert(std::pair<Mob *, float>(mob, distance)); close_mobs.insert(std::pair<Mob *, float>(mob, distance));
} }
} }
/* Clients need to be kept up to date for position updates more often otherwise they disappear */
if (mob->IsClient() && this != mob && !mob->IsMoving() && distance <= client_update_range) {
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
mob->MakeSpawnUpdate(spawn_update);
this->FastQueuePacket(&app, false);
safe_delete(app);
}
} }
} }
@ -460,7 +441,7 @@ bool Client::Process() {
{ {
animation = 0; animation = 0;
m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w); m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w);
SendPosUpdate(2); SendPositionUpdate(2);
} }
} }

View File

@ -1589,7 +1589,7 @@ void Merc::AI_Process() {
} }
if(IsMoving()) if(IsMoving())
SendPosUpdate(); SendPositionUpdate();
else else
SendPosition(); SendPosition();
} }
@ -1714,7 +1714,7 @@ void Merc::AI_Process() {
} }
if(IsMoving()) if(IsMoving())
SendPosUpdate(); SendPositionUpdate();
else else
SendPosition(); SendPosition();
} }

View File

@ -1437,7 +1437,7 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
} }
} }
// this one just warps the mob to the current location /* Used for NPCs mainly */
void Mob::SendPosition() void Mob::SendPosition()
{ {
@ -1446,7 +1446,7 @@ void Mob::SendPosition()
MakeSpawnUpdateNoDelta(spu); MakeSpawnUpdateNoDelta(spu);
/* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */ /* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */
if (DistanceSquared(last_major_update_position, m_Position) > (100 * 100)) { if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) {
entity_list.QueueClients(this, app, true, true); entity_list.QueueClients(this, app, true, true);
last_major_update_position = m_Position; last_major_update_position = m_Position;
} }
@ -1458,7 +1458,7 @@ void Mob::SendPosition()
} }
// this one is for mobs on the move, with deltas - this makes them walk // this one is for mobs on the move, with deltas - this makes them walk
void Mob::SendPosUpdate(uint8 iSendToSelf) { void Mob::SendPositionUpdate(uint8 iSendToSelf) {
auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer;
MakeSpawnUpdate(spu); MakeSpawnUpdate(spu);
@ -1496,27 +1496,27 @@ void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu) {
// this is for SendPosUpdate() // this is for SendPosUpdate()
void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) { void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) {
spu->spawn_id = GetID(); spu->spawn_id = GetID();
spu->x_pos = FloatToEQ19(m_Position.x); spu->x_pos = FloatToEQ19(m_Position.x);
spu->y_pos = FloatToEQ19(m_Position.y); spu->y_pos = FloatToEQ19(m_Position.y);
spu->z_pos = FloatToEQ19(m_Position.z); spu->z_pos = FloatToEQ19(m_Position.z);
spu->delta_x = NewFloatToEQ13(m_Delta.x); spu->delta_x = NewFloatToEQ13(m_Delta.x);
spu->delta_y = NewFloatToEQ13(m_Delta.y); spu->delta_y = NewFloatToEQ13(m_Delta.y);
spu->delta_z = NewFloatToEQ13(m_Delta.z); spu->delta_z = NewFloatToEQ13(m_Delta.z);
spu->heading = FloatToEQ19(m_Position.w); spu->heading = FloatToEQ19(m_Position.w);
spu->padding0002 =0; spu->padding0002 = 0;
spu->padding0006 =7; spu->padding0006 = 7;
spu->padding0014 =0x7f; spu->padding0014 = 0x7f;
spu->padding0018 =0x5df27; spu->padding0018 = 0x5df27;
#ifdef BOTS #ifdef BOTS
if (this->IsClient() || this->IsBot()) if (this->IsClient() || this->IsBot())
#else #else
if(this->IsClient()) if (this->IsClient())
#endif #endif
spu->animation = animation; spu->animation = animation;
else else
spu->animation = pRunAnimSpeed;//animation; spu->animation = pRunAnimSpeed;//animation;
spu->delta_heading = NewFloatToEQ13(m_Delta.w); spu->delta_heading = NewFloatToEQ13(m_Delta.w);
} }
@ -2745,7 +2745,7 @@ void Mob::FaceTarget(Mob* MobToFace) {
if(oldheading != newheading) { if(oldheading != newheading) {
SetHeading(newheading); SetHeading(newheading);
if(moving) if(moving)
SendPosUpdate(); SendPositionUpdate();
else else
{ {
SendPosition(); SendPosition();

View File

@ -542,7 +542,7 @@ public:
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true); virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true);
void SetDelta(const glm::vec4& delta); void SetDelta(const glm::vec4& delta);
void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; } void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; }
void SendPosUpdate(uint8 iSendToSelf = 0); void SendPositionUpdate(uint8 iSendToSelf = 0);
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
void SendPosition(); void SendPosition();

View File

@ -1006,7 +1006,12 @@ void Mob::AI_Process() {
} }
else if (!this->CheckLosFN(this->GetTarget())) { else if (!this->CheckLosFN(this->GetTarget())) {
Mob* target = this->GetTarget(); Mob* target = this->GetTarget();
this->GMMove(target->GetX(), target->GetY(), target->GetZ(), target->GetHeading());
m_Position.x = target->GetX();
m_Position.y = target->GetY();
m_Position.z = target->GetZ();
m_Position.w = target->GetHeading();
SendPosition();
} }
} }
} }

View File

@ -1268,7 +1268,7 @@ XS(XS_Mob_SendPosUpdate)
iSendToSelf = (uint8)SvUV(ST(1)); iSendToSelf = (uint8)SvUV(ST(1));
} }
THIS->SendPosUpdate(iSendToSelf); THIS->SendPositionUpdate(iSendToSelf);
} }
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }

View File

@ -215,7 +215,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p
{ {
npc->AssignWaypoints(grid); npc->AssignWaypoints(grid);
} }
npc->SendPosUpdate(); npc->SendPositionUpdate();
return npc; return npc;
} }
return nullptr; return nullptr;
@ -237,7 +237,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v
{ {
npc->AssignWaypoints(grid); npc->AssignWaypoints(grid);
} }
npc->SendPosUpdate(); npc->SendPositionUpdate();
return npc; return npc;
} }
return nullptr; return nullptr;
@ -1660,7 +1660,7 @@ void QuestManager::respawn(int npcTypeID, int grid) {
if(grid > 0) if(grid > 0)
owner->CastToNPC()->AssignWaypoints(grid); owner->CastToNPC()->AssignWaypoints(grid);
owner->SendPosUpdate(); owner->SendPositionUpdate();
} }
} }

View File

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

View File

@ -614,12 +614,12 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
if (IsClient()) if (IsClient())
{ {
SendPosUpdate(1); SendPositionUpdate(1);
CastToClient()->ResetPositionTimer(); CastToClient()->ResetPositionTimer();
} }
else else
{ {
SendPosUpdate(); SendPositionUpdate();
SetAppearance(eaStanding, false); SetAppearance(eaStanding, false);
} }
@ -702,7 +702,7 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ
this->SetMoving(true); this->SetMoving(true);
moved = true; moved = true;
m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f); m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
SendPosUpdate(); SendPositionUpdate();
} }
tar_ndx++; tar_ndx++;