Code:
Index: zone/client_packet.cpp
===================================================================
--- zone/client_packet.cpp (revision 110)
+++ zone/client_packet.cpp (working copy)
@@ -771,6 +771,82 @@
void Client::Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app) {
SendAATable();
}
+bool Client::WarpDetection(bool CTimer, float distance)
+{
+ float last_distance;
+ if (threshold_timer.GetRemainingTime() < 1 && ((RuleR(Zone, MQWarpThresholdTimer)) != -1)) { //Null: If the timer is done, reset threshold, then reset timer //Lieka: Integrated into Rules System.
+ warp_threshold = (RuleR(Zone, MQWarpLagThreshold)); //Lieka: Integrated warp_threshold value into Rules System. Original Value was 140.
+ threshold_timer.Start((RuleR(Zone, MQWarpThresholdTimer)), false); //Lieka: Integrated timer duration value into the Rules System. Original Value was 90000 (90 seconds).
+ }
+ if ((CTimer))
+ return false;
+ else
+ {
+ //Null Edit: made warp detector fire only when the sum of all the warps in a period of time are greater than a threshold
+ //this makes the warp detector more lax on small warps, but still drops the hammer on the big ones.
+ if (distance>140.0f) {
+ last_distance = (distance-140.0f);
+ warp_threshold -= last_distance;
+ last_warp_distance = last_distance;
+ }
+ return (warp_threshold < 0); //Null: If the threshold is met, hit them with the hammer
+ }
+}
+
+void Client::CheatDetected(CheatTypes CheatType)
+{ //[Paddy] 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 have serious issues, turning off warp flags for these zones.
+ if(!((zone->GetZoneID()==2)/*qeynos2*/ || (zone->GetZoneID()==9)/*freportw*/|| (zone->GetZoneID()==10)/*freporte*/ || (zone->GetZoneID()==34)/*nro*/ || (zone->GetZoneID()==24)/*erudin*/ || (zone->GetZoneID()==75)/*Paineel*/ || (zone->GetZoneID()==62)/*Felwitheb*/) && (RuleB(Zone, EnableMQWarpDetector) && ((this->Admin() < RuleI(Zone, MQWarpExemptStatus) || (RuleI(Zone, MQWarpExemptStatus)) == -1)))) //Lieka: Exempt these zones from the MQWarp detector (This may be depricated now, but these zones were problems in the past)
+ {
+ Message(13, "Your account has been reported for hacking.");
+ database.SetMQDetectionFlag(this->account_name,this->name, "/MQWarp", zone->GetShortName());
+ SetMana(0); //Lieka: Remove all mana from player.
+ SetHP(5); //Lieka: Set player's hitpoints to 5.
+ BuffFadeAll(); //Lieka: Wipe all of player's buffs.
+ SpellFinished((RuleI(Zone, MQWarpDetectionSpellID)), this); //Lieka: Integrated into Rules System. Spell to cast on players Default: 757 (Resurrection Effects).
+ worldserver.SendEmoteMessage(0,0,0,13,"<MQWarp Detector>. %s was just caught warping in %s. Come get your free kill!",this->GetName(),zone->GetLongName());
+ warp_threshold = 1; //Null: bringing the detector back up to one to avoid chain detections.
+ }
+ break;
+ case MQZone:
+ if(!( (zone->GetZoneID()==31)/*sola*/ || (zone->GetZoneID()==32)/*solb*/ || (zone->GetZoneID()==25)/*nek*/ || (zone->GetZoneID()==27)/*lava*/ ) && (RuleB(Zone, EnableMQZoneDetector))&& ((this->Admin() < RuleI(Zone, MQZoneExemptStatus) || (RuleI(Zone, MQZoneExemptStatus)) == -1))) //Lieka: Exempt these zones from the MQZone detector (This may be depricated now, but were problems in the past)
+ {
+ Message(13, "Your account has been reported for hacking.");
+ database.SetMQDetectionFlag(this->account_name,this->name, "/MQZone", zone->GetShortName());
+ SetMana(0); //Lieka: Remove all mana from player.
+ SetHP(5); //Lieka: Set player's hitpoints to 5.
+ BuffFadeAll(); //Lieka: Wipe all of player's buffs.
+ AddBuff(this,(RuleI(Zone, MQZoneDetectionSpellID)),30); //Lieka: Integrated into Rules System. Add (de)buff on player for 30 ticks. Default: 757 (Resurrection Effects).
+ worldserver.SendEmoteMessage(0,0,0,13,"<MQZone Detector>. %s as just caught using Macroquest to /Zone to %s. Come get your free kill!",this->GetName(),zone->GetLongName()); //Lieka: Broadcast to the server that the MQZone detector has caught a cheater.
+ }
+ break;
+ case MQGate:
+ if (RuleB(Zone, EnableMQGateDetector)&& ((this->Admin() < RuleI(Zone, MQGateExemptStatus) || (RuleI(Zone, MQGateExemptStatus)) == -1))) {
+ Message(13, "Your account has been reported for hacking.");
+ database.SetMQDetectionFlag(this->account_name,this->name, "/MQGate", zone->GetShortName());
+ this->SetZone(this->GetZoneID()); //Lieka: Prevent the player from zoning, place him back in the zone where he tried to originally /gate.
+ SetMana(0); //Lieka: Remove all mana from player.
+ SetHP(5); //Lieka: Set player's hitpoints to 5.
+ BuffFadeAll(); //Lieka: Wipe all of player's buffs.
+ AddBuff(this,(RuleI(Zone, MQGateDetectionSpellID)),30); //Lieka: Integrated into Rules System. Add (de)buff on player for 30 ticks. Default: 757 (Resurrection Effects).
+ worldserver.SendEmoteMessage(0,0,0,13,"<MQGate Detector>. %s was just caught using Macroquest to /Gate to %s. Come get your free kill!",this->GetName(),zone->GetLongName()); //Lieka: Broadcast to the server that the MQGate Detector has caught a cheater.
+ }
+ break;
+ case MQGhost: //Lieka: 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))) {
+ Message(13, "Your account has been reported for hacking.");
+ database.SetMQDetectionFlag(this->account_name,this->name, "/MQGhost", zone->GetShortName());
+ SetMana(0); //Lieka: Remove all mana from player.
+ SetHP(5); //Lieka: Set player's hitpoints to 5.
+ BuffFadeAll(); //Lieka: Wipe all of player's buffs.
+ SpellFinished((RuleI(Zone, MQGhostDetectionSpellID)), this); //Lieka: Integrated into Rules System. Spell to cast on players Default: 757 (Resurrection Effects).
+ worldserver.SendEmoteMessage(0,0,0,13,"<MQGhost Detector>. %s was just caught using Macroquest to /Ghost to %s. Come get your free kill!",this->GetName(),zone->GetLongName()); //Lieka: Broadcast to the server that the MQGate Detector has caught a cheater.
+ }
+ break;
+ }
+}
void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
{
@@ -796,9 +872,28 @@
dist += tmp*tmp;
tmp = y_pos - ppu->y_pos;
dist += tmp*tmp;
- tmp = z_pos - ppu->z_pos;
- dist += tmp*tmp;
- if(dist > 50.0f*50.0f) {
+
+ dist = sqrt(dist);
+ /*[Paddy] Cutting out the Z-Axis check. Not necessary and prevents long falls from triggering */
+ //tmp = z_pos - ppu->z_pos;
+ //dist += tmp*tmp;
+
+ /* Begin Cheat Detection*/
+ if ((this->cheat_timer.GetRemainingTime())>1 && (this->cheat_timer.Enabled())) //Lieka: Check to see if the cheat (exemption) timer is active - this is for debugging
+ {
+ //Spell timer is currently active
+ //worldserver.SendEmoteMessage(0,0,0,13,"Timer is Active. %d True: %s",this->cheat_timer.GetRemainingTime(), (this->cheat_timer.GetRemainingTime()>1)? "true" : "false"); //Leika Edit: Enable this to get debug messages.
+ }
+ else //Timer has elapsed or hasn't started, let's do a Warp Check
+ {
+ if ((WarpDetection(false, dist)) && ((admin <= RuleI(Zone, MQWarpExemptStatus)) || (RuleI(Zone, MQWarpExemptStatus) == -1))) //Exempt from warp detection if admin level is > Rule:Zone:MQWarpExemptStatus
+ {
+ printf("Warping Detected by %S Acct: %s Distance: %f.", GetName(), AccountName(), GetLWDistance());
+ CheatDetected(MQWarp); //Lieka: Execute MQWarp function on offending player
+ }
+ }
+ //Lieka End Edit
+ if(dist > 50.0f*50.0f) {
printf("%s: Large position change: %f units\n", GetName(), sqrtf(dist));
printf("Coords: (%.4f, %.4f, %.4f) -> (%.4f, %.4f, %.4f)\n",
x_pos, y_pos, z_pos, ppu->x_pos, ppu->y_pos, ppu->z_pos);
@@ -813,13 +908,13 @@
// this checking of heading/x_pos is cheap, and the result is
// subtle, but you'll notice your sense heading improve as you
// travel around
- if(
- ( (heading != ppu->heading) && !((int)heading % 3) ) || // turning
- ( (x_pos != ppu->x_pos) && !((int)x_pos % 6) ) // moving
- )
- {
- CheckIncreaseSkill(SENSE_HEADING, -20);
- }
+ if(
+ ( (heading != ppu->heading) && !((int)heading % 3) ) || // turning
+ ( (x_pos != ppu->x_pos) && !((int)x_pos % 6) ) // moving
+ )
+ {
+ CheckIncreaseSkill(SENSE_HEADING, -20);
+ }
if(proximity_timer.Check()) {
entity_list.ProcessMove(this, ppu->x_pos, ppu->y_pos, ppu->z_pos);
@@ -3154,6 +3249,7 @@
cout << "Wrong size on OP_GMSummon. Got: " << app->size << ", Expected: " << sizeof(GMSummon_Struct) << endl;
return;
}
+ this->cheat_timer.Start(5000, false); //Lieka: Exempt in-zone GM Summons from triggering MQWarp detector
OPGMSummon(app);
return;
}
@@ -6016,6 +6112,7 @@
// vesuvias - appearence fix
beard = m_pp.beard;
+ this->cheat_timer.Start(2500,false); //Lieka: Prevent tripping the MQWarp detector when logging in after LD - basically gives a grace period for large position changes.
//if we zone in with invalid Z, fix it.
@@ -6648,6 +6745,8 @@
}
}
}
+
+ this->cheat_timer.Start(2500,false); //Lieka: Prevent tripping the MQWarp detector when arriving in a new zone.
client_data_loaded = true;
int x;