mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 22:58:34 +00:00
Redoing movement to introduce proper rotation
This commit is contained in:
+37
-253
@@ -505,7 +505,6 @@ void Client::CompleteConnect()
|
||||
client_state = CLIENT_CONNECTED;
|
||||
SendAllPackets();
|
||||
hpupdate_timer.Start();
|
||||
position_timer.Start();
|
||||
autosave_timer.Start();
|
||||
SetDuelTarget(0);
|
||||
SetDueling(false);
|
||||
@@ -895,108 +894,6 @@ void Client::CompleteConnect()
|
||||
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
|
||||
/*
|
||||
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();
|
||||
if (new_target && (GetGM() ||
|
||||
Distance(m_Position, assistee->GetPosition()) <= TARGETING_RANGE)) {
|
||||
SetAssistExemption(true);
|
||||
eid->entity_id = new_target->GetID();
|
||||
} else {
|
||||
eid->entity_id = 0;
|
||||
@@ -3920,6 +3816,8 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app)
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -4427,9 +4325,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
sizeof(PlayerPositionUpdateClient_Struct), app->size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PlayerPositionUpdateClient_Struct *ppu = (PlayerPositionUpdateClient_Struct *) app->pBuffer;
|
||||
|
||||
|
||||
/* Boat handling */
|
||||
if (ppu->spawn_id != GetID()) {
|
||||
/* If player is controlling boat */
|
||||
@@ -4439,163 +4337,67 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
controlling_boat_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||
boat->SetDelta(boat_delta);
|
||||
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct *ppus = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
|
||||
boat->MakeSpawnUpdate(ppus);
|
||||
entity_list.QueueCloseClients(boat, outapp, true, 300, this, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
|
||||
/* 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);
|
||||
return;
|
||||
} else return;
|
||||
}
|
||||
|
||||
float dist = 0;
|
||||
float tmp;
|
||||
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();
|
||||
}
|
||||
|
||||
if (IsDraggingCorpse())
|
||||
DragCorpses();
|
||||
|
||||
/* Check to see if PPU should trigger an update to the rewind position. */
|
||||
float rewind_x_diff = 0;
|
||||
float rewind_y_diff = 0;
|
||||
|
||||
|
||||
rewind_x_diff = ppu->x_pos - m_RewindLocation.x;
|
||||
rewind_x_diff *= rewind_x_diff;
|
||||
rewind_y_diff = ppu->y_pos - m_RewindLocation.y;
|
||||
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
|
||||
his pre-PPU x and y for /rewind, in case he gets stuck.
|
||||
*/
|
||||
|
||||
|
||||
if ((rewind_x_diff > 750) || (rewind_y_diff > 750))
|
||||
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 coordinates to the new ppu coordinates. This will prevent exploitation.
|
||||
*/
|
||||
|
||||
|
||||
if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000))
|
||||
m_RewindLocation = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
|
||||
|
||||
if (proximity_timer.Check()) {
|
||||
entity_list.ProcessMove(this, glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos));
|
||||
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
|
||||
ProcessTaskProximities(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 */
|
||||
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 (zone->random.Real(0, 100) < 70)//should be good
|
||||
CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20);
|
||||
}
|
||||
|
||||
|
||||
/* 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 ((hidden || improved_hidden) && !sneaking) {
|
||||
@@ -4614,17 +4416,17 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
}
|
||||
rewind_timer.Start(30000, true);
|
||||
}
|
||||
|
||||
|
||||
/* Handle client aggro scanning timers NPCs */
|
||||
is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true;
|
||||
|
||||
|
||||
if (is_client_moving) {
|
||||
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u",
|
||||
client_scan_npc_aggro_timer.GetDuration());
|
||||
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
|
||||
client_scan_npc_aggro_timer.Disable();
|
||||
client_scan_npc_aggro_timer.Start(500);
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float new_heading = EQ12toFloat(ppu->heading);
|
||||
int32 new_animation = ppu->animation;
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
|
||||
/* Visual Debugging */
|
||||
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,
|
||||
@@ -4650,43 +4452,43 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
||||
this->SendAppearanceEffect(41, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Only feed real time updates when client is moving */
|
||||
if (is_client_moving || new_heading != m_Position.w || new_animation != animation) {
|
||||
|
||||
|
||||
animation = ppu->animation;
|
||||
m_Position.w = EQ12toFloat(ppu->heading);
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
if (gm_hide_me) {
|
||||
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250);
|
||||
} else {
|
||||
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Always send position updates to group - send when beyond normal ClientPositionUpdate range */
|
||||
Group *group = this->GetGroup();
|
||||
Raid *raid = this->GetRaid();
|
||||
|
||||
|
||||
if (raid) {
|
||||
raid->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
||||
} else if (group) {
|
||||
group->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
||||
}
|
||||
|
||||
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
|
||||
if (zone->watermap) {
|
||||
if (zone->watermap->InLiquid(glm::vec3(m_Position))) {
|
||||
CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17);
|
||||
|
||||
|
||||
// Dismount horses when entering water
|
||||
if (GetHorseId() && RuleB(Character, DismountWater)) {
|
||||
SetHorseId(0);
|
||||
@@ -4695,7 +4497,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
}
|
||||
CheckRegionTypeChanges();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app)
|
||||
@@ -13666,12 +13467,6 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
|
||||
GetTarget()->IsTargeted(1);
|
||||
return;
|
||||
}
|
||||
else if (IsAssistExempted())
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
SetAssistExemption(false);
|
||||
return;
|
||||
}
|
||||
else if (GetTarget()->IsClient())
|
||||
{
|
||||
//make sure this client is in our raid/group
|
||||
@@ -13689,17 +13484,6 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
|
||||
SetTarget((Mob*)nullptr);
|
||||
return;
|
||||
}
|
||||
else if (IsPortExempted())
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
return;
|
||||
}
|
||||
else if (IsSenseExempted())
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
SetSenseExemption(false);
|
||||
return;
|
||||
}
|
||||
else if (IsXTarget(GetTarget()))
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
|
||||
Reference in New Issue
Block a user