Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Server Code Submissions

Reply
 
Thread Tools Display Modes
  #16  
Old 03-29-2008, 07:01 AM
cavedude's Avatar
cavedude
The PEQ Dude
 
Join Date: Apr 2003
Location: -
Posts: 1,988
Default

I understand completely, getting a clean diff from TGC wouldn't be easy either so I sympathize.
Reply With Quote
  #17  
Old 03-29-2008, 09:39 AM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

Ok, sorry for the false start. Yeah there were a few typos, etc with the previous code, I went through it again, and got a diff from it and 0.7.0-1102

Code:
Index: common/database.cpp

===================================================================

--- common/database.cpp	(revision 110)

+++ common/database.cpp	(working copy)

@@ -1458,6 +1458,24 @@

 	return true;
 }
 
+bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Lieka:  Utilize the "hacker" table, but also give zone information.

+	char errbuf[MYSQL_ERRMSG_SIZE];

+	char *query = 0;

+	int32	affected_rows = 0;

+	if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone), errbuf, 0,&affected_rows)) {

+		cerr << "Error in SetMQDetectionFlag query '" << query << "' " << errbuf << endl;

+		return false;

+	}

+	safe_delete_array(query);

+	

+	if (affected_rows == 0)

+	{

+		return false;

+	}

+	

+	return true;

+}
+
 int8 Database::GetRaceSkill(int8 skillid, int8 in_race)
 {
 	int16 race_cap = 0;
Index: common/database.h

===================================================================

--- common/database.h	(revision 110)

+++ common/database.h	(working copy)

@@ -118,6 +118,7 @@

 	bool	MoveCharacterToZone(int32 iCharID, const char* iZonename);
 	bool	UpdateName(const char* oldname, const char* newname);
 	bool	SetHackerFlag(const char* accountname, const char* charactername, const char* hacked);
+	bool	SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone);
 	bool	AddToNameFilter(const char* name);
 	bool	ReserveName(int32 account_id, char* name);
 	bool	CreateCharacter(uint32 account_id, char* name, int16 gender, int16 race, int16 class_, int8 str, int8 sta, int8 cha, int8 dex, int8 int_, int8 agi, int8 wis, int8 face);
Index: common/ruletypes.h

===================================================================

--- common/ruletypes.h	(revision 110)

+++ common/ruletypes.h	(working copy)

@@ -65,6 +65,21 @@

 RULE_INT ( Zone,  ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection
 RULE_INT ( Zone,  GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone
 RULE_BOOL ( Zone, EnableShadowrest, 0 ) // enables or disables the shadowrest zone feature for player corpses. Default is turned off.
+RULE_INT ( Zone, MQWarpExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.

+RULE_INT ( Zone, MQZoneExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.

+RULE_INT ( Zone, MQGateExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.

+RULE_INT ( Zone, MQGhostExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.

+RULE_BOOL ( Zone, EnableMQWarpDetector, false ) //Lieka:  Enable the MQWarp Detector.  Set to False to disable this feature.

+RULE_BOOL ( Zone, EnableMQZoneDetector, false ) //Lieka:  Enable the MQZone Detector.  Set to False to disable this feature.

+RULE_BOOL ( Zone, EnableMQGateDetector, false ) //Lieka:  Enable the MQGate Detector.  Set to False to disable this feature.

+RULE_BOOL ( Zone, EnableMQGhostDetector, false ) //Lieka:  Enable the MQGhost Detector.  Set to False to disable this feature.

+RULE_REAL ( Zone, MQWarpDetectorDistance, 30 ) //Lieka:  Distance a player must travel between client to server location updates before a warp is registered.  30 allows for beyond GM speed without lag.

+RULE_REAL ( Zone, MQWarpLagThreshold, 140 ) //Lieka:  Distance beyond the Zone:MQWarpDetectorDistance that a player must travel within the MQWarpThresholdTimer amount of time before tripping the MQWarp detector.  Set to 0 to disable this feature.

+RULE_REAL ( Zone, MQWarpThresholdTimer, 90000 ) //Lieka:  Amount of time before the warp_threshold resets to the Zone:MQWarpLagThreshold value.  Default: 90000 (900 seconds/15 minutes).  Set to -1 to disable this feature.

+RULE_INT ( Zone, MQWarpDetectionSpellID, 757 ) //Lieka:  Which spell ID will be cast on players that incur the hammer of the MQ Detector.  This spell will be actually cast, don't pick a resistible spell.  Default: 757 (Resurrection Effects)

+RULE_INT ( Zone, MQGateDetectionSpellID, 757 ) //Lieka:  Which spell ID debuff will be cast on players that incur the hammer of the MQGateDetector.  This spell will be added as a debuff while zoning.  Default: 757 (Resurrection Effects)

+RULE_INT ( Zone, MQZoneDetectionSpellID, 757 ) //Lieka:  Which spell ID debuff will be cast on players that incur the hammer of the MQGateDetector.  This spell will be added as a debuff while zoning.  Default: 757 (Resurrection Effects)

+RULE_INT ( Zone, MQGhostDetectionSpellID, 757 ) //Lieka:  Which spell ID will be cast on players that incur the hammer of the MQGhostDetector.  This spell will be actually cast, don't pick a resistable spell.  Default: 757 (Resurrection Effects)
 RULE_CATEGORY_END()
 
 RULE_CATEGORY( Map )


Index: zone/client.cpp

===================================================================

--- zone/client.cpp	(revision 110)

+++ zone/client.cpp	(working copy)

@@ -2304,7 +2304,7 @@

 	float dx=cheat_x-x_pos;
 	float dy=cheat_y-y_pos;
 	float result=sqrtf((dx*dx)+(dy*dy));
-	return result>70;
+	return result>(RuleR(Zone, MQWarpDetectorDistance)); //Lieka:  Integrated into Rules System; default value is 30, this allows for beyond GM speed without lag.
 }
 
 void Client::SetHideMe(bool flag)
Index: zone/client.h

===================================================================

--- zone/client.h	(revision 110)

+++ zone/client.h	(working copy)

@@ -152,6 +152,13 @@

 	EvacToSafeCoords
 } ZoneMode;
 
+typedef enum {

+	MQWarp,

+	MQZone,

+	MQGate,

+	MQGhost

+} CheatTypes;
+
 class ClientFactory {
 public:
 	Client *MakeClient(EQStream* ieqs);
@@ -175,6 +182,8 @@

 	void	Trader_StartTrader();
 	int8	WithCustomer();
 	bool	CheckCheat();
+	void	CheatDetected(CheatTypes Cheat);

+	bool	WarpDetection(bool CTimer, float Distance);
 	virtual bool IsClient() const { return true; }
 	virtual void DBAWComplete(int8 workpt_b1, DBAsyncWork* dbaw);
 	bool	FinishConnState2(DBAsyncWork* dbaw);

Index: zone/client_process.cpp

===================================================================

--- zone/client_process.cpp	(revision 110)

+++ zone/client_process.cpp	(working copy)

@@ -921,6 +921,7 @@

 		return;
 	const Resurrect_Struct* ra = (const Resurrect_Struct*) app->pBuffer;
 	if (ra->action == 1) {
+		this->cheat_timer.Start(3500, false); //[Paddy] Allow getting rezzed without triggering 

 		cout << "Player " << this->name << " got a " << (int16)spells[ra->spellid].base[0] << "% Rezz" << endl;
 		this->BuffFadeAll();
 		SetMana(0);
@@ -1481,6 +1482,7 @@

 		}
 		if(st)
 		{
+			this->cheat_timer.Start(3500, false);//[Paddy] Allow PC's to be summoned without triggering Warp Detection

 			Message(0, "Local: Summoning %s to %i, %i, %i", gms->charname, gms->x, gms->y, gms->z);
 			if (st->IsClient() && (st->CastToClient()->GetAnon() != 1 || this->Admin() >= st->CastToClient()->Admin()))
 				st->CastToClient()->MovePC((float)gms->x, (float)gms->y, (float)gms->z, this->GetHeading(), 2, true);
@@ -1512,6 +1514,7 @@

 			else {
 				//all options have been exhausted
 				//summon our target...
+				this->cheat_timer.Start(3500, false); //Lieka:  Don't want to trip the MQWarp detector here either.

 				if(GetTarget() && GetTarget()->IsCorpse()){
 					GetTarget()->CastToCorpse()->Summon(this, false);
 				}


Index: zone/command.cpp

===================================================================

--- zone/command.cpp	(revision 110)

+++ zone/command.cpp	(working copy)

@@ -1364,6 +1364,7 @@

 			c->Message(0, "You may not summon a player.");
 			return;
 		}
+		t->CastToClient()->cheat_timer.Start(3500,false); //Lieka:  Prevent Zone-to-Zone GM Summons from triggering the MQZone and MQWarp detectors.

 		c->Message(0, "Summoning player %s to %1.1f, %1.1f, %1.1f", t->GetName(), c->GetX(), c->GetY(), c->GetZ());
 		t->CastToClient()->MovePC(zone->GetZoneID(), c->GetX(), c->GetY(), c->GetZ(), c->GetHeading(), 2, GMSummon);
 	}
@@ -1409,9 +1410,11 @@

 		}
 	}
 		
-	if (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4))
+	if (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4)) {
 		//zone to specific coords
+		c->CastToClient()->cheat_timer.Start(3500,false);  //Lieka:  Not sure why we put this here... should be an admin if you are zoning to special coordinates by this point.

 		c->MovePC(zoneid, atof(sep->arg[2]), atof(sep->arg[3]), atof(sep->arg[4]), 0.0f, 0);
+	}
 	else
 		//zone to safe coords
 		c->MovePC(zoneid, 0.0f, 0.0f, 0.0f, 0.0f, 0, ZoneToSafeCoords);
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)
Reply With Quote
  #18  
Old 03-29-2008, 09:42 AM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

Code:
Index: zone/mob.h

===================================================================

--- zone/mob.h	(revision 110)

+++ zone/mob.h	(working copy)

@@ -455,7 +455,8 @@

 	inline Mob*			GetTarget()			const { return target; }
 	virtual void SetTarget(Mob* mob);
 	virtual inline float		GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); }
-	
+	float GetLWDistance()					{ return last_warp_distance; }    //Null:  these are used to return the values to #showstats

+	float GetWarpThreshold()				{ return warp_threshold; }		  //this one too	
 	bool IsLoggingEnabled() const { return(logging_enabled); }
 	void EnableLogging() { logging_enabled = true; }
 	void DisableLogging() { logging_enabled = false; }
@@ -783,6 +784,10 @@

 	
 	//temporary:
 	bool fix_pathing;
+	Timer cheat_timer; //Lieka:  Timer used to check for movement exemptions/client-based, unsolicited zone exemptions

+	Timer threshold_timer;  //Null:  threshold timer

+	float warp_threshold;   //Null:  threshold for warp detector

+	float last_warp_distance;  //Null:  last distance logged as a warp, used for logs and #showstats
 	inline float GetCWPX() const { return(cur_wp_x); }
 	inline float GetCWPY() const { return(cur_wp_y); }
 	inline float GetCWPZ() const { return(cur_wp_z); }



 

Index: zone/zoning.cpp

===================================================================

--- zone/zoning.cpp	(revision 110)

+++ zone/zoning.cpp	(working copy)

@@ -55,6 +55,7 @@

 		case ZoneToSafeCoords:
 			//going to safe coords, but client dosent know where?
 			//assume it is this zone for now.
+			cheat_timer.Start(35000,false); //Lieka:  Allow Zone/Evac to Safe Coords without triggering MQWarp detector.
 			target_zone_id = zone->GetZoneID();
 			break;
 		case GMSummon:
@@ -74,10 +75,13 @@

 			if(zone_point) {
 				//we found a zone point, which is a reasonable distance away
 				//assume that is the one were going with.
+				cheat_timer.Start(3500,false); //Lieka:  Allow Zone normal zoning without triggering MQZone detector.
 				target_zone_id = zone_point->target_zone_id;
 			} else {
 				//unable to find a zone point... is there anything else
 				//that can be a valid un-zolicited zone request?
+
+				this->CheatDetected(MQZone); //Lieka:  Bring down the hammer, they are trying to zone without meeting any of the above criteria.
 				
 				Message(13, "Invalid unsolicited zone request.");
 				LogFile->write(EQEMuLog::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
@@ -105,6 +109,11 @@

 			if(!zone_point || zone_point->target_zone_id != target_zone_id) {
 				Message(13, "Invalid unsolicited zone request.");
 				LogFile->write(EQEMuLog::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
+
+				if ((this->cheat_timer.GetRemainingTime())<1 || (!this->cheat_timer.Enabled())){ //Lieka:  Disable MQGate Detector if timer is active.

+				this->CheatDetected(MQGate);

+				}
+
 				SendZoneCancel(zc);
 				return;
 			}
@@ -168,6 +177,7 @@

 		ignorerestrictions = 1;	//can always get to our bind point? seems exploitable
 		break;
 	case ZoneSolicited:  //we told the client to zone somewhere, so we know where they are going.
+		cheat_timer.Start(3500,false); //Lieka:  Allow Server Forced Zoning without triggering MQZone detector.
 		//recycle zonesummon variables
 		dest_x = zonesummon_x;
 		dest_y = zonesummon_y;
@@ -204,6 +214,7 @@

 		//for now, there are no other cases...
 		
 		//could not find a valid reason for them to be zoning, stop it.
+		this->CheatDetected(MQZone);  //Lieka:  Bring down the hammer, we don't let hackers off that easily...
 		Message(13, "Invalid unsolicited zone request.");
 		LogFile->write(EQEMuLog::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%s'. Not near a zone point.", GetName(), target_zone_name);
 		SendZoneCancel(zc);
@@ -218,12 +229,15 @@

 	//not sure when we would use ZONE_ERROR_NOTREADY
 
 	//enforce min status and level
-	if (!ignorerestrictions && (Admin() < minstatus || GetLevel() < minlevel))
+	if (!ignorerestrictions && (Admin() < minstatus || GetLevel() < minlevel)) {
+		this->cheat_timer.Start(3500,false); //Lieka:  Don't set off warp detector for when a player is moved to the safe-spot for trying to access a zone without the appropriate level or status requirements (i.e. zoning into FearPlane at level 30, etc)

 		myerror = ZONE_ERROR_NOEXPERIENCE;
+	}
 	
 	if(!ignorerestrictions && flag_needed[0] != '\0') {
 		//the flag needed string is not empty, meaning a flag is required.
 		if(Admin() < minStatusToIgnoreZoneFlags && !HasZoneFlag(target_zone_id)) {
+			this->cheat_timer.Start(3500,false); //Lieka:  Don't set off warp detector for when a player is moved to the safe-spot for trying to access a zone without the appropriate flag.

 			Message(13, "You must have the flag %s to enter this zone.");
 			myerror = ZONE_ERROR_NOEXPERIENCE;
 		}
@@ -265,6 +279,7 @@

 	//effectively zone them right back to where they were
 	//unless we find a better way to stop the zoning process.
 	EQApplicationPacket *outapp;
+	cheat_timer.Start(3500,false); //Lieka:  Disable MQ Warp & MQ Gate Detector when zoning fails. (not high enough level, etc)
 	outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct));
 	ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer;
 	strcpy(zc2->char_name, zc->char_name);
@@ -279,6 +294,7 @@

 
 void Client::SendZoneError(ZoneChange_Struct *zc, sint8 err) {
 	LogFile->write(EQEMuLog::Error, "Zone %i is not available because target wasn't found or character insufficent level", zc->zoneID);
+	cheat_timer.Start(3500,false);//Lieka:  Disable /Warp & /Gate Detector when zoning fails. (not high enough level, etc)
 	
 	EQApplicationPacket *outapp;
 	outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct));
@@ -424,57 +440,64 @@

 	database.GetZoneLongName(pShortZoneName, &pZoneName);
 	iZoneNameLength = strlen(pZoneName);
 		
-	switch(zm) {
-		case EvacToSafeCoords:
-		case ZoneToSafeCoords:
-			x = zone->safe_x();
-			y = zone->safe_y();
-			z = zone->safe_z();
-			heading = heading;
-			break;
-		case GMSummon:
-			zonesummon_x = x_pos = x;
-			zonesummon_y = y_pos = y;
-			zonesummon_z = z_pos = z;
-			heading = heading;
-			
-			zonesummon_id = zoneID;
-			zonesummon_ignorerestrictions = 1;
-			break;
-		case ZoneSolicited:
-			zonesummon_x = x;
-			zonesummon_y = y;
-			zonesummon_z = z;
-			heading = heading;
-			
-			zonesummon_id = zoneID;
-			zonesummon_ignorerestrictions = ignorerestrictions;
-			break;
-		case GateToBindPoint:
-			x = x_pos = m_pp.binds[0].x;
-			y = y_pos = m_pp.binds[0].y;
-			z = z_pos = m_pp.binds[0].z;
-			heading = m_pp.binds[0].heading;
-			break;
-		case ZoneToBindPoint:
-			x = x_pos = m_pp.binds[0].x;
-			y = y_pos = m_pp.binds[0].y;
-			z = z_pos = m_pp.binds[0].z;
-			heading = m_pp.binds[0].heading;
-			
-			zonesummon_ignorerestrictions = 1;
-			LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
-			break;
-		case SummonPC:
-			zonesummon_x = x_pos = x;
-			zonesummon_y = y_pos = y;
-			zonesummon_z = z_pos = z;
-			heading = heading;
-			break;
-		default:
-			LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
-			ReadyToZone = false;
-			break;
+	switch(zm) {

+		case EvacToSafeCoords:

+			this->cheat_timer.Start(2500,false);// Null: added a timers to this location because sometimes the ones in the other locations of code were not doing the job

+		case ZoneToSafeCoords:

+			this->cheat_timer.Start(2500,false);

+			x = zone->safe_x();

+			y = zone->safe_y();

+			z = zone->safe_z();

+			heading = heading;

+			break;

+		case GMSummon:

+			this->cheat_timer.Start(2500,false);

+			zonesummon_x = x_pos = x;

+			zonesummon_y = y_pos = y;

+			zonesummon_z = z_pos = z;

+			heading = heading;

+			

+			zonesummon_id = zoneID;

+			zonesummon_ignorerestrictions = 1;

+			break;

+		case ZoneSolicited:

+			this->cheat_timer.Start(2500,false);

+			zonesummon_x = x;

+			zonesummon_y = y;

+			zonesummon_z = z;

+			heading = heading;

+			

+			zonesummon_id = zoneID;

+			zonesummon_ignorerestrictions = ignorerestrictions;

+			break;

+		case GateToBindPoint:

+			this->cheat_timer.Start(2500,false);

+			x = x_pos = m_pp.binds[0].x;

+			y = y_pos = m_pp.binds[0].y;

+			z = z_pos = m_pp.binds[0].z;

+			heading = m_pp.binds[0].heading;

+			break;

+		case ZoneToBindPoint:

+			this->cheat_timer.Start(2500,false);

+			x = x_pos = m_pp.binds[0].x;

+			y = y_pos = m_pp.binds[0].y;

+			z = z_pos = m_pp.binds[0].z;

+			heading = m_pp.binds[0].heading;

+			

+			zonesummon_ignorerestrictions = 1;

+			LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);

+			break;

+		case SummonPC:

+			this->cheat_timer.Start(2500,false);

+			zonesummon_x = x_pos = x;

+			zonesummon_y = y_pos = y;

+			zonesummon_z = z_pos = z;

+			heading = heading;

+			break;

+		default:

+			LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");

+			ReadyToZone = false;

+			break;

 	}
 
 	if(ReadyToZone) {
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)
Reply With Quote
  #19  
Old 03-29-2008, 09:43 AM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

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;
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)
Reply With Quote
  #20  
Old 03-29-2008, 09:44 AM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

Code:
Index: zone/spell_effects.cpp

===================================================================

--- zone/spell_effects.cpp	(revision 110)

+++ zone/spell_effects.cpp	(working copy)

@@ -1682,11 +1682,13 @@

 
 			case SE_SummonPC:
 			{
-				if(IsClient())
-					CastToClient()->MovePC(zone->GetZoneID(), caster->GetX(), caster->GetY(), caster->GetZ(), caster->GetHeading(), 2, SummonPC);
-				else
-					caster->Message(13, "This spell can only be cast on players.");
-
+			if(IsClient()){

+					CastToClient()->cheat_timer.Start(3500, false);  //Lieka:  Exempt spells the "SummonPC" effect from triggering the MQWarp detector.

+					CastToClient()->MovePC(zone->GetZoneID(), caster->GetX(), caster->GetY(), caster->GetZ(), caster->GetHeading(), 2, SummonPC);

+					Message(15, "You have been summoned!");

+				} else {

+					caster->Message(13, "This spell can only be cast on players.");

+				}
 				break;
 			}
 
Index: zone/spells.cpp

===================================================================

--- zone/spells.cpp	(revision 110)

+++ zone/spells.cpp	(working copy)

@@ -942,6 +942,16 @@

 		if(IsClient())
 		{
 			this->CastToClient()->CheckSongSkillIncrease(spell_id);
+			//Lieka start Edit:  Fixing Warp Detector triggered for Bard Songs

+			if ((IsGateSpell(spell_id)) ||//Lieka Edit Begin:  Checking effects within the spell, rather than hardcoding Spell IDs.

+				(IsTeleportSpell(spell_id)) ||

+				(IsSuccorSpell(spell_id)) ||

+				(IsShadowStepSpell(spell_id)) ||

+				(IsGateSpell(spell_id)))

+				{

+						this->cheat_timer.Start(2000,false);  //Lieka:  Exempt above effects from setting off MQWarp detector due to intrazone movement generated from the bard song effects

+				}

+				//Lieka end edit.
 		}
 		// go again in 6 seconds
 //this is handled with bardsong_timer
@@ -972,8 +982,15 @@

 				
 				c->CheckSpecializeIncrease(spell_id);
 			}
+			if ((IsGateSpell(spell_id)) ||//Lieka Edit Begin:  Checking effects within the spell, rather than hardcoding Spell IDs.

+				(IsTeleportSpell(spell_id)) ||

+				(IsSuccorSpell(spell_id)) ||

+				(IsShadowStepSpell(spell_id)) ||

+				(IsGateSpell(spell_id)))

+				{

+				c->cheat_timer.Start(2000,false); //Lieka:  Exempt above effects from setting off MQWarp detector due to intrazone movement generated from the spell effects

+				}		
 			
-			
 		}
 
 		// there should be no casting going on now
@@ -2242,6 +2259,17 @@

 	action->instrument_mod = GetInstrumentMod(spell_id);
 	action->buff_unknown = 0;
 
+		//Lieka start Edit:  Fixing Warp Detector triggered by spells cast on the player.

+	if ((IsGateSpell(spell_id)) ||//Lieka Edit Begin:  Checking effects within the spell, rather than hardcoding Spell IDs.

+		(IsTeleportSpell(spell_id)) ||

+		(IsSuccorSpell(spell_id)) ||

+		(IsShadowStepSpell(spell_id)) ||

+		(IsGateSpell(spell_id)))

+		{

+				spelltar->cheat_timer.Start(2000,false); //Lieka:  Exempt above effects from setting off MQWarp detector due to intrazone movement generated from the spell effects

+		}

+		//Lieka end edit.
+
 	if(spelltar->IsClient())	// send to target
 		spelltar->CastToClient()->QueuePacket(action_packet);
 	if(IsClient())	// send to caster


Index: zone/zone.cpp

===================================================================

--- zone/zone.cpp	(revision 110)

+++ zone/zone.cpp	(working copy)

@@ -1185,7 +1185,7 @@

 	}
 }
 
-ZonePoint* Zone::GetClosestZonePoint(float x, float y, float z, int32 to, float max_distance) {
+ZonePoint* Zone::GetClosestZonePoint(float x, float y, float z, int32 to, float max_distance, Client* client) {
 	LinkedListIterator<ZonePoint*> iterator(zone_point_list);
 	ZonePoint* closest_zp = 0;
 	float closest_dist = FLT_MAX;
@@ -1214,8 +1214,14 @@

 	}
 	
 	if(closest_dist>(200.0f*200.0f) && closest_dist<max_distance2)
-		LogFile->write(EQEMuLog::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);
-	
+		{

+		client->CheatDetected(MQZone); //[Paddy] Someone is trying to use /zone

+		LogFile->write(EQEMuLog::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);

+		LogFile->write(EQEMuLog::Status, "<Real Zone Points>.  %f x %f y %fz ",x,y,z);

+		//worldserver.SendEmoteMessage(0,0,0,13,"<Real Zone Points>.  %f x %f y %fz ",x,y,z);

+		closest_zp = NULL; //Lieka:  Prevent the zone request from happening.

+	}
+
 	if(closest_dist > max_distance2)
 		closest_zp = NULL;
 	
Index: zone/zone.h

===================================================================

--- zone/zone.h	(revision 110)

+++ zone/zone.h	(working copy)

@@ -108,7 +108,7 @@

 	
 	int32	CountSpawn2();
 	ZonePoint* GetClosestZonePoint(float x, float y, float z, const char* to_name, float max_distance = 40000.0f);
-	ZonePoint* GetClosestZonePoint(float x, float y, float z, int32	to, float max_distance = 40000.0f);
+	ZonePoint* GetClosestZonePoint(float x, float y, float z, int32	to, float max_distance = 40000.0f, Client* client = NULL);
 	ZonePoint* GetClosestZonePointWithoutZone(float x, float y, float z, float max_distance = 40000.0f);
 	SpawnGroupList spawn_group_list;



Index: zone/mob.cpp

===================================================================

--- zone/mob.cpp	(revision 110)

+++ zone/mob.cpp	(working copy)

@@ -100,8 +100,10 @@

 		tic_timer(6000),
 		mana_timer(2000),
 		spellend_timer(0),
+		cheat_timer(0), //Lieka:  Timer for MQ Detector exemptions
 		stunned_timer(0),
 		bardsong_timer(6000),
+		threshold_timer(0), //Lieka:  Timer to allow exemptions MQWarp related to lag

 #ifdef FLEE_HP_RATIO
 		flee_timer(FLEE_CHECK_TIMER),
 #endif
@@ -121,7 +123,8 @@

 	AI_Init();
 	SetMoving(false);
 	moved=false;
-
+	warp_threshold = 140;            //Null:  set the threshold on creation of mob instance

+	last_warp_distance = 0;			 //Null: set this one to zero also just because.

 	_egnode = NULL;
 	adverrorinfo = 0;
 	name[0]=0;
@@ -231,7 +234,7 @@

 //	guildeqid = GUILD_NONE;
 	
     spellend_timer.Disable();
-	
+	cheat_timer.Disable();
 	bardsong_timer.Disable();
 	bardsong = 0;
 	bardsong_target_id = 0;
@@ -874,6 +877,7 @@

 	client->Message(0, "  STR: %i  STA: %i  DEX: %i  AGI: %i  INT: %i  WIS: %i  CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA());
 	client->Message(0, "  MR: %i  PR: %i  FR: %i  CR: %i  DR: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR());
 	client->Message(0, "  Race: %i  BaseRace: %i  Texture: %i  HelmTexture: %i  Gender: %i  BaseGender: %i", GetRace(), GetBaseRace(), GetTexture(), GetHelmTexture(), GetGender(), GetBaseGender());
+	client->Message(0, "  Last Warp Distance: %f Threshold Remaining: %f", GetLWDistance(), GetWarpThreshold());   //Null:  added this to check players last warp distance for debuging.

 	if (client->Admin() >= 100) {
 		client->Message(0, "  EntityID: %i  PetID: %i  OwnerID: %i  AIControlled: %i", this->GetID(), this->GetPetID(), this->GetOwnerID(), this->IsAIControlled());
 		if (this->IsClient()) {
@@ -1842,6 +1846,10 @@

 		// RangerDown - GMMove doesn't seem to be working well with players, so use MovePC for them, GMMove for NPC's
 		if (target->IsClient())
 			target->CastToClient()->MovePC(zone->GetZoneID(), x_pos, y_pos, z_pos, target->GetHeading(), 0, SummonPC);
+			if (target->IsClient()) {

+			target->CastToClient()->cheat_timer.Start(3500,false); //Lieka:  Prevent Mob Summons from tripping hack detector.

+			target->CastToClient()->MovePC(zone->GetZoneID(), x_pos, y_pos, z_pos, target->GetHeading(), 0, SummonPC);

+		}
 		else
 			GetHateTop()->GMMove(x_pos, y_pos, z_pos, target->GetHeading());
         return true;
}

Index: zone/spdat.cpp

===================================================================

--- zone/spdat.cpp	(revision 110)

+++ zone/spdat.cpp	(working copy)

@@ -637,6 +637,39 @@

 	return Result;
 }
 
+bool IsShadowStepSpell(int16 spell_id) {

+	if (IsEffectInSpell(spell_id, SE_ShadowStep)){

+		return true;

+	}

+	else {

+		return false;

+	}

+}

+bool IsSuccorSpell(int16 spell_id) {

+	if (IsEffectInSpell(spell_id, SE_Succor)){

+		return true;

+	}

+	else {

+		return false;

+	}

+}

+bool IsTeleportSpell(int16 spell_id) {

+	if (IsEffectInSpell(spell_id, SE_Teleport)){

+		return true;

+	}

+	else {

+		return false;

+	}

+}

+bool IsGateSpell(int16 spell_id) {

+	if (IsEffectInSpell(spell_id, SE_Gate)){

+		return true;

+	}

+	else {

+		return false;

+	}

+}
+
 bool IsMagicRuneSpell(int16 spell_id) {
 	bool Result = false;


Index: zone/spdat.h

===================================================================

--- zone/spdat.h	(revision 110)

+++ zone/spdat.h	(working copy)

@@ -531,6 +531,10 @@

 bool IsResurrectionEffects(int16 spell_id);
 bool IsRuneSpell(int16 spell_id);
 bool IsMagicRuneSpell(int16 spell_id);
+bool IsShadowStepSpell(int16 spell_id);

+bool IsSuccorSpell(int16 spell_id);

+bool IsTeleportSpell(int16 spell_id);

+bool IsGateSpell(int16 spell_id);
 bool IsManaTapSpell(int16 spell_id);
 bool IsAllianceSpellLine(int16 spell_id);
 bool IsDeathSaveSpell(int16 spell_id);
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)
Reply With Quote
  #21  
Old 03-29-2008, 09:48 AM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

Updated the SQL to address a couple of issues too.

Code:
ALTER TABLE `hackers` 
ADD COLUMN `zone` TEXT AFTER `hacked`;
ADD COLUMN `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `zone`;
Code:
insert into rule_values values (0, Zone:EnableMQWarpDetector, false);
insert into rule_values values (0, Zone:EnableMQZoneDetector, false);
insert into rule_values values (0, Zone:EnableMQGateDetector, false);
insert into rule_values values (0, Zone:EnableMQGhostDetector, false);

insert into rule_values values (0, Zone:MQWarpExemptStatus, 50);
insert into rule_values values (0, Zone:MQGateExemptStatus, 50);
insert into rule_values values (0, Zone:MQZoneExemptStatus, 50);
insert into rule_values values (0, Zone:MQGhostExemptStatus, 50);

insert into rule_values values (0, Zone:MQWarpDetectorDistance, 30);
insert into rule_values values (0, Zone:MQWarpLagThreshold, 140);
insert into rule_values values (0, Zone:MQWarpThresholdTimer, 90000);

insert into rule_values values (0, Zone:MQWarpDetectionSpellID, 757);
insert into rule_values values (0, Zone:MQGateDetectionSpellID, 757);
insert into rule_values values (0, Zone:MQZoneDetectionSpellID, 757);
insert into rule_values values (0, Zone:MQGhostDetectionSpellID, 757);
Hopefully it should be good now. Let me know if you have any questions or concerns.

Dax
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)
Reply With Quote
  #22  
Old 03-29-2008, 11:42 AM
cavedude's Avatar
cavedude
The PEQ Dude
 
Join Date: Apr 2003
Location: -
Posts: 1,988
Default

Compiled perfectly! I'm going to play around now, thank you!
Reply With Quote
  #23  
Old 03-29-2008, 12:16 PM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

Glad to hear it - there might be some issues from tying it into the rules system (I'm hoping not, but it was not tested nearly as thoroughly with the rules setup as it was prior to it), but other than that, it should be pretty much as it reads. Let me know if you have any questions or concerns.

Thanks,
Dax
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)
Reply With Quote
  #24  
Old 03-29-2008, 12:42 PM
Semedaien
Sarnak
 
Join Date: Dec 2006
Posts: 68
Default

Awsome man, thank you for the wonderful contribution to the emu community!
Reply With Quote
  #25  
Old 03-29-2008, 02:51 PM
KLS
Administrator
 
Join Date: Sep 2006
Posts: 1,348
Default

Yeah, thank you much. This is very much needed, I'm gonna let it sit on PEQ for a bit and see what CD thinks about it before moving it to official source. If there's a situation where false positives happen a lot I'd just like to resolve it before it gets put in is all.
Reply With Quote
  #26  
Old 03-31-2008, 01:54 AM
So_1337
Dragon
 
Join Date: May 2006
Location: Cincinnati, OH
Posts: 689
Default

Absolutely brilliant! Always such quality from you
Reply With Quote
  #27  
Old 04-02-2008, 06:51 AM
Angelox
AX Classic Developer
 
Join Date: May 2006
Location: filler
Posts: 2,049
Default

I moved part of this to another forum (Development:: Development) as "MQWarp/MQZone/MQGate Detector Discussion".
This forum is intended for submissions only, so I tried to split up the thread as best I could - use the new thread for discussion.
Reply With Quote
  #28  
Old 04-14-2008, 10:15 AM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

Yes, we merged back with the eqemu source and use Wildcard's updates to the zoning stuff (getting all the bugs worked out of it made for an interesting week on our server ).

Here are the source snippets involved in pulling the zonepoints, then checking them against a zone request.

Here's the code that pulls and checks the zone points:


SQL query that pulls the zone points into the code:
from .\zone\zone.cpp
Code:
bool ZoneDatabase::LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list,const char* zonename)
{
	char errbuf[MYSQL_ERRMSG_SIZE];
	char *query = 0;
	MYSQL_RES *result;
	MYSQL_ROW row;
	zone_point_list->Clear();
	zone->numzonepoints = 0;
	MakeAnyLenString(&query, "SELECT x,y,z,target_x,target_y,target_z,target_zone_id,heading,target_heading,number FROM zone_points WHERE zone='%s' order by number", zonename);
	if (RunQuery(query, strlen(query), errbuf, &result))
	{
		safe_delete_array(query);
		while((row = mysql_fetch_row(result)))
		{
			ZonePoint* zp = new ZonePoint;
			zp->x = atof(row[0]);
			zp->y = atof(row[1]);
			zp->z = atof(row[2]);
			zp->target_x = atof(row[3]);
			zp->target_y = atof(row[4]);
			zp->target_z = atof(row[5]);
			zp->target_zone_id = atoi(row[6]);
			zp->heading=atof(row[7]);
			zp->target_heading=atof(row[8]);
			zp->number=atoi(row[9]);
			zone_point_list->Insert(zp);
			zone->numzonepoints++;
		}
		mysql_free_result(result);
	}
	else
	{
		cerr << "Error1 in LoadStaticZonePoints query '" << query << "' " << errbuf << endl;
		safe_delete_array(query);
		return false;
	}
return true;
}
Here is the function that checks for the closest zone points.

Code:
ZonePoint* Zone::GetClosestZonePoint(float x, float y, float z, int32 to, float max_distance, Client* client) {
	LinkedListIterator<ZonePoint*> iterator(zone_point_list);
	ZonePoint* closest_zp = 0;
	float closest_dist = FLT_MAX;
	float max_distance2 = max_distance*max_distance;
	iterator.Reset();
	while(iterator.MoreElements())
	{
		ZonePoint* zp = iterator.GetData();
		if (zp->target_zone_id == to)
		{
			float delta_x = zp->x - x;
			float delta_y = zp->y - y;
			if(zp->x == 999999 || zp->x == -999999)
				delta_x = 0;
			if(zp->y == 999999 || zp->y == -999999)
				delta_y = 0;

			float dist = delta_x*delta_x+delta_y*delta_y;///*+(zp->z-z)*(zp->z-z)*/;
			if (dist < closest_dist)
			{
				closest_zp = zp;
				closest_dist = dist;
			}
		}
		iterator.Advance();
	}
	
	if(closest_dist>(200.0f*200.0f) && closest_dist<max_distance2)
		{
		client->CheatDetected(MQZone); //[Paddy] Someone is trying to use /zone
		LogFile->write(EQEMuLog::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);
		LogFile->write(EQEMuLog::Status, "<Real Zone Points>.  %f x %f y %fz ",x,y,z);
		//worldserver.SendEmoteMessage(0,0,0,13,"<Real Zone Points>.  %f x %f y %fz ",x,y,z);
		closest_zp = NULL; //Lieka:  Prevent the zone request from happening.
	}
In the `zone_points` table, your current entries are fine - they're just incomplete. If you
Code:
select * from zone_points where y = 0 && x = 0 && z = 0;
then you will see the entries that need to be updated (pretty much all of them). I've already posted the list for old world zones, but kunark+ need to still be updated.

Basically, when there's an unsolicited zone request from the client (i.e. the client requests a zone change):

The function "ZonePoint* Zone::GetClosestZonePoint(float x, float y, float z, int32 to, float max_distance, Client* client)" compares the x, y (not target_x and target_y) in the records that match the target_zone_id within your zone_points table against the client's current x, y. If the (zonepoint->x - client->x) * (zonepoint->y - client->y) > 4000 (200*200), then it assumes that the zone request is the result of a hack (which it most likely is). So, if you have 0, 0 for a value in your x, y in the zone_points table, then unless the client is attempting to use that zone_point from close to that x, y in the zone, it will detect a /MQZone attempt. If the zone that the client is using is a zone wall (like East Commons -> West Freeport), you'll put 999999 for the x or y (whichever is appropriate), and it will exempt it that (x or y) from the check (because it's too damn hard to draw a line in the database).

Once you update these records in your zone_points table, you can #reloadzps from within that zone (the source zone, not the target zone), and retest them.

I hope that helps,
Dax
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)

Last edited by TheLieka; 04-14-2008 at 06:18 PM..
Reply With Quote
  #29  
Old 04-16-2008, 03:51 AM
TheLieka
Developer
 
Join Date: Oct 2004
Location: THE ATL (wut wut)
Posts: 325
Default

Ax - the submission thread for this is locked, could you move this code over for me?

I don't have a ton of time to document this, but it's well documented in the code. Long story short -
  • Warp detection is now done by velocity rather than just distance. The time measurement is taken between Player Position Update packets being received.
  • The velocity is taken by taking the distance / time since last PPU.
  • If the detector trips, it moves the player back to his previous PPU location.
  • Added the following rules:
    For Disabling MQDetector Penalties (Punishment for the player)
    For Disabling SQL Logging (haven't replaced it with text logging, but if it's a performance concern you can now disable it in the rules)
    For Disabling MQDetector Broadcast
    For Setting the Speed Limit (speed measured by units / second - this rule specifies the number of units a player is allowed to travel per second. From testing: 3-4 is level 50 SoW, 7 - 10 is GM Speed
  • Added 4 new items to #showstats:
    Last PPU Time: Indicates how long it was since the last PPU for the player (in hundredths of a second)
    Longest PPU Time: Records the longest time between PPUs for the player (in hundredths of a second)
    Current Movement Speed: Indicates the current movement speed of the player
    Highest Movement Speed: Indicates the highest movement speed of the player

That's pretty much it - the rest is the same as my original submission, but I think these updates should be what the code needed.

Let me know what you think.

Thanks,
Dax

This Diff was taken against 0.7.0-1102
Code:
diff  c:/EQEmu_0.7.0_1102_source/zone/client.h c:/VZ-TZ-Diff/zone/client.h
151a152
> 	WarpDetected,			// Lieka:  Return client to pre-warp location
154a156,162
> typedef enum {
> 	MQWarp,
> 	MQZone,
> 	MQGate,
> 	MQGhost
> } CheatTypes;
> 
177a186,187
> 	void	CheatDetected(CheatTypes Cheat);
> 	bool	WarpDetection(bool CTimer, float Distance, int32 last_ppu_timer);
diff  c:/EQEmu_0.7.0_1102_source/zone/client_packet.cpp c:/VZ-TZ-Diff/zone/client_packet.cpp
773a774,860
> bool Client::WarpDetection(bool CTimer, float distance, int32 last_ppu_timer) //Lieka:  Completely reworked this function.  Rather than basing warp detection on large movement diffs, we now base it on the player's speed (update distance / update time)
> {	
> 	if (CTimer)
> 		return false;
> 	else
> 	{
> 	movement_speed = distance / (last_ppu_timer/100);
> 	if (movement_speed > highest_movement_speed) {
> 		highest_movement_speed = movement_speed;
> 	}
> 	return (movement_speed > RuleR(Zone, MQWarpSpeedLimit)); //Lieka:  If the player breaks the speed limit, bring down 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)
> 			{
> 				if (!RuleB(Zone, MQDetectorDisableSQLLogging)){
> 				Message(13, "Your account has been reported for hacking.");
> 				database.SetMQDetectionFlag(this->account_name, this->name, "/MQWarp", zone->GetShortName());
> 				}
> 				if(!RuleB(Zone, MQDetectorDisablePenalties)){ //Lieka:  Toggle Negative effects based on rule value
> 				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).
> 				}
> 				if(!RuleB(Zone, MQDetectorDisableBroadcast)) //Lieka:  Toggle broadcast based on rule value
> 					worldserver.SendEmoteMessage(0,0,0,13,"<MQWarp Detector>.  %s was just caught warping in %s.  Come get your free kill!",this->GetName(),zone->GetLongName());
> 			}
> 			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)
> 			{
> 				if (!RuleB(Zone, MQDetectorDisableSQLLogging)){
> 				Message(13, "Your account has been reported for hacking.");
> 				database.SetMQDetectionFlag(this->account_name, this->name, "/MQZone", zone->GetShortName());
> 				}
> 				if(!RuleB(Zone, MQDetectorDisablePenalties)){ //Lieka:  Toggle Negative effects based on rule value
> 				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).
> 				}
> 				if(!RuleB(Zone, MQDetectorDisableBroadcast)) //Lieka:  Toggle broadcast based on rule value
> 					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))) {
> 				if (!RuleB(Zone, MQDetectorDisableSQLLogging)){
> 				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.
> 				if(!RuleB(Zone, MQDetectorDisablePenalties)){ //Lieka:  Toggle Negative effects based on rule value
> 				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).
> 				}
> 				if(!RuleB(Zone, MQDetectorDisableBroadcast)) //Lieka:  Toggle broadcast based on rule value
> 					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))) {
> 				if (!RuleB(Zone, MQDetectorDisableSQLLogging)){
> 				Message(13, "Your account has been reported for hacking.");
> 				database.SetMQDetectionFlag(this->account_name, this->name, "/MQGhost", zone->GetShortName());
> 				}
> 				if(!RuleB(Zone, MQDetectorDisablePenalties)){ //Lieka:  Toggle Negative effects based on rule value
> 				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).
> 				}
> 				if(!RuleB(Zone, MQDetectorDisableBroadcast)) //Lieka:  Toggle broadcast based on rule value
> 					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;
> 	}
> }
791,792c878,888
< 	
< 	
---
> 	//Lieka:  Track duration between Player Position Updates to determine lag (for warp detection).
> 	if (ppu_timer.Enabled()) { 
> 		last_ppu_timer = 40000 - ppu_timer.GetRemainingTime(); 
> 		if(last_ppu_timer > longest_ppu_timer) {
> 			longest_ppu_timer = last_ppu_timer;
> 		}
> 	} else {
> 		last_ppu_timer = 1;
> 	}
> 	ppu_timer.Start(40000, true);
> 
799,801c895,918
< 	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())) || longest_ppu_timer < 2) //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, last_ppu_timer)) && ((RuleB(Zone,EnableMQGateDetector) && (admin <= RuleI(Zone, MQWarpExemptStatus)) || (RuleI(Zone, MQWarpExemptStatus) == -1)))) //Exempt from warp detection if admin level is >  Rule:Zone:MQWarpExemptStatus
> 		{
> 			printf("Warping Detected by %s Distance: %f.", GetName(), dist);
> 			this->CastToClient()->MovePC(zone->GetZoneID(), x_pos, y_pos, z_pos, heading, 2, WarpDetected); //Lieka Edit:  Move player back to pre-warp location
> 			CheatDetected(MQWarp); //Lieka:  Execute MQWarp function on offending player
> 			return;
> 			}
> 	}
> 	//Lieka End Edit
> 		if(dist > 50.0f*50.0f) {
816,822c933,939
< 	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);
> 	}
3156a3274
> 	this->cheat_timer.Start(5000, false); //Lieka:  Exempt in-zone GM Summons from triggering MQWarp detector
6018a6137
> 	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.
6650a6770,6771
> 
> 	this->cheat_timer.Start(2500,false); //Lieka:  Prevent tripping the MQWarp detector when arriving in a new zone.
diff  c:/EQEmu_0.7.0_1102_source/zone/client_process.cpp c:/VZ-TZ-Diff/zone/client_process.cpp
923a924
> 		this->cheat_timer.Start(3500, false); //[Paddy] Allow getting rezzed without triggering 
1483a1485
> 			this->cheat_timer.Start(3500, false);//[Paddy] Allow PC's to be summoned without triggering Warp Detection
1514a1517
> 				this->cheat_timer.Start(3500, false); //Lieka:  Don't want to trip the MQWarp detector here either.
diff  c:/EQEmu_0.7.0_1102_source/zone/command.cpp c:/VZ-TZ-Diff/zone/command.cpp
1366a1367
> 		t->CastToClient()->cheat_timer.Start(3500,false); //Lieka:  Prevent Zone-to-Zone GM Summons from triggering the MQZone and MQWarp detectors.
1412c1413
< 	if (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4))
---
> 	if (sep->IsNumber(2) || sep->IsNumber(3) || sep->IsNumber(4)) {
1413a1415
> 		c->CastToClient()->cheat_timer.Start(3500,false);  //Lieka:  Not sure why we put this here... should be an admin if you are zoning to special coordinates by this point.
1414a1417
> 	}
diff  c:/EQEmu_0.7.0_1102_source/zone/mob.cpp c:/VZ-TZ-Diff/zone/mob.cpp
102a103
> 		cheat_timer(0), //Lieka:  Timer for MQ Detector exemptions
104a106
> 		ppu_timer(0), //Lieka:  Timer to track time between Player Update Packets (to detect lag) for MQWarp detection
124c126,129
< 
---
> 	longest_ppu_timer = 0;			 //Lieka:  reset longest player packet update timer record on creation of mob instance
> 	last_ppu_timer = 0;				 //Lieka:  reset last player packet update timer record on creation of mob instance
> 	movement_speed = 0;				 //Lieka:  reset player movement speed record on creation of mob instance
> 	highest_movement_speed = 0;		 //Lieka:  reset highest recorded player movement speed on creation of mob instance
234c239
< 	
---
> 	cheat_timer.Disable();
876a882,883
> 	client->Message(0, "  Last Player Position Update Timer: %i  Longest Player Position Update Timer: %i", GetLastPPUTimer(), GetLongestPPUTimer()); //Lieka:  added this to monitor player lag for MQWarp detection.
> 	client->Message(0, "  Current Movement Speed: %i  Highest Movement Speed: %i", GetMovementSpeed(), GetHighestMovementSpeed()); //Lieka:  added this to monitor player's movement speed (based on last PPU update / PPU time.
1844a1852,1855
> 			if (target->IsClient()) {
> 			target->CastToClient()->cheat_timer.Start(3500,false); //Lieka:  Prevent Mob Summons from tripping hack detector.
> 			target->CastToClient()->MovePC(zone->GetZoneID(), x_pos, y_pos, z_pos, target->GetHeading(), 0, SummonPC);
> 		}
diff  c:/EQEmu_0.7.0_1102_source/zone/mob.h c:/VZ-TZ-Diff/zone/mob.h
458c458,461
< 	
---
> 	int32 GetLastPPUTimer()					{ return last_ppu_timer; }  //Lieka:  Used in #showstats mainly for debugging and monitoring players
> 	int32 GetLongestPPUTimer()				{ return longest_ppu_timer; }  //Lieka:  Used in #showstats mainly for debugging and monitoring players
> 	int32 GetMovementSpeed()				{ return movement_speed; }	//Lieka:  Used in #showstats mainly for debugging and monitoring players
> 	int32 GetHighestMovementSpeed()			{ return highest_movement_speed; } //Lieka: Used in #showstats mainly for debugging and monitorint players	
785a789,794
> 	Timer cheat_timer; //Lieka:  Timer used to check for movement exemptions/client-based, unsolicited zone exemptions
> 	Timer ppu_timer; //Lieka:  Timer used to track amount of time between Player Position Updates.
> 	int32 last_ppu_timer;  //Lieka:  Indicates last amount of time between the player's PPUs.
> 	int32 longest_ppu_timer; //Lieka:  indicates longest time that the player gone without a PPU (while in the current zone).
> 	float movement_speed;  //Lieka:  Calculated movement speed in units / second.
> 	float highest_movement_speed; //Lieka:  Highest movement speed reached.
diff  c:/EQEmu_0.7.0_1102_source/zone/spdat.cpp c:/VZ-TZ-Diff/zone/spdat.cpp
639a640,672
> bool IsShadowStepSpell(int16 spell_id) {
> 	if (IsEffectInSpell(spell_id, SE_ShadowStep)){
> 		return true;
> 	}
> 	else {
> 		return false;
> 	}
> }
> bool IsSuccorSpell(int16 spell_id) {
> 	if (IsEffectInSpell(spell_id, SE_Succor)){
> 		return true;
> 	}
> 	else {
> 		return false;
> 	}
> }
> bool IsTeleportSpell(int16 spell_id) {
> 	if (IsEffectInSpell(spell_id, SE_Teleport)){
> 		return true;
> 	}
> 	else {
> 		return false;
> 	}
> }
> bool IsGateSpell(int16 spell_id) {
> 	if (IsEffectInSpell(spell_id, SE_Gate)){
> 		return true;
> 	}
> 	else {
> 		return false;
> 	}
> }
> 
diff  c:/EQEmu_0.7.0_1102_source/zone/spdat.h c:/VZ-TZ-Diff/zone/spdat.h
533a534,537
> bool IsShadowStepSpell(int16 spell_id);
> bool IsSuccorSpell(int16 spell_id);
> bool IsTeleportSpell(int16 spell_id);
> bool IsGateSpell(int16 spell_id);
diff  c:/EQEmu_0.7.0_1102_source/zone/spell_effects.cpp c:/VZ-TZ-Diff/zone/spell_effects.cpp
1685,1689c1685,1690
< 				if(IsClient())
< 					CastToClient()->MovePC(zone->GetZoneID(), caster->GetX(), caster->GetY(), caster->GetZ(), caster->GetHeading(), 2, SummonPC);
< 				else
< 					caster->Message(13, "This spell can only be cast on players.");
< 
---
> 			if(IsClient()){
> 					CastToClient()->cheat_timer.Start(3500, false);  //Lieka:  Exempt spells the "SummonPC" effect from triggering the MQWarp detector.
> 					CastToClient()->MovePC(zone->GetZoneID(), caster->GetX(), caster->GetY(), caster->GetZ(), caster->GetHeading(), 2, SummonPC);
> 				} else {
> 					caster->Message(13, "This spell can only be cast on players.");
> 				}
diff  c:/EQEmu_0.7.0_1102_source/zone/spells.cpp c:/VZ-TZ-Diff/zone/spells.cpp
944a945,954
> 			//Lieka start Edit:  Fixing Warp Detector triggered for Bard Songs
> 			if ((IsGateSpell(spell_id)) ||//Lieka Edit Begin:  Checking effects within the spell, rather than hardcoding Spell IDs.
> 				(IsTeleportSpell(spell_id)) ||
> 				(IsSuccorSpell(spell_id)) ||
> 				(IsShadowStepSpell(spell_id)) ||
> 				(IsGateSpell(spell_id)))
> 				{
> 						this->cheat_timer.Start(2000,false);  //Lieka:  Exempt above effects from setting off MQWarp detector due to intrazone movement generated from the bard song effects
> 				}
> 				//Lieka end edit.
975c985,992
< 			
---
> 			if ((IsGateSpell(spell_id)) ||//Lieka Edit Begin:  Checking effects within the spell, rather than hardcoding Spell IDs.
> 				(IsTeleportSpell(spell_id)) ||
> 				(IsSuccorSpell(spell_id)) ||
> 				(IsShadowStepSpell(spell_id)) ||
> 				(IsGateSpell(spell_id)))
> 				{
> 				c->cheat_timer.Start(2000,false); //Lieka:  Exempt above effects from setting off MQWarp detector due to intrazone movement generated from the spell effects
> 				}		
2243a2261,2271
> 
> 		//Lieka start Edit:  Fixing Warp Detector triggered by spells cast on the player.
> 	if ((IsGateSpell(spell_id)) ||//Lieka Edit Begin:  Checking effects within the spell, rather than hardcoding Spell IDs.
> 		(IsTeleportSpell(spell_id)) ||
> 		(IsSuccorSpell(spell_id)) ||
> 		(IsShadowStepSpell(spell_id)) ||
> 		(IsGateSpell(spell_id)))
> 		{
> 				spelltar->cheat_timer.Start(2000,false); //Lieka:  Exempt above effects from setting off MQWarp detector due to intrazone movement generated from the spell effects
> 		}
> 		//Lieka end edit.
diff  c:/EQEmu_0.7.0_1102_source/zone/zone.cpp c:/VZ-TZ-Diff/zone/zone.cpp
1188c1188
< ZonePoint* Zone::GetClosestZonePoint(float x, float y, float z, int32 to, float max_distance) {
---
> ZonePoint* Zone::GetClosestZonePoint(float x, float y, float z, int32 to, float max_distance, Client* client) {
1217,1218c1217,1224
< 		LogFile->write(EQEMuLog::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);
< 	
---
> 		{
> 		client->CheatDetected(MQZone); //[Paddy] Someone is trying to use /zone
> 		LogFile->write(EQEMuLog::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);
> 		LogFile->write(EQEMuLog::Status, "<Real Zone Points>.  %f x %f y %fz ",x,y,z);
> 		//worldserver.SendEmoteMessage(0,0,0,13,"<Real Zone Points>.  %f x %f y %fz ",x,y,z);
> 		closest_zp = NULL; //Lieka:  Prevent the zone request from happening.
> 	}
> 
diff  c:/EQEmu_0.7.0_1102_source/zone/zone.h c:/VZ-TZ-Diff/zone/zone.h
111c111
< 	ZonePoint* GetClosestZonePoint(float x, float y, float z, int32	to, float max_distance = 40000.0f);
---
> 	ZonePoint* GetClosestZonePoint(float x, float y, float z, int32	to, float max_distance = 40000.0f, Client* client = NULL);
diff  c:/EQEmu_0.7.0_1102_source/zone/zoning.cpp c:/VZ-TZ-Diff/zone/zoning.cpp
57a58
> 			cheat_timer.Start(35000,false); //Lieka:  Allow Zone/Evac to Safe Coords without triggering MQWarp detector.
76a78
> 				cheat_timer.Start(3500,false); //Lieka:  Allow Zone normal zoning without triggering MQZone detector.
80a83,84
> 
> 				this->CheatDetected(MQZone); //Lieka:  Bring down the hammer, they are trying to zone without meeting any of the above criteria.
107a112,116
> 
> 				if ((this->cheat_timer.GetRemainingTime())<1 || (!this->cheat_timer.Enabled())){ //Lieka:  Disable MQGate Detector if timer is active.
> 				this->CheatDetected(MQGate);
> 				}
> 
170a180
> 		cheat_timer.Start(3500,false); //Lieka:  Allow Server Forced Zoning without triggering MQZone detector.
206a217
> 		this->CheatDetected(MQZone);  //Lieka:  Bring down the hammer, we don't let hackers off that easily...
221c232,233
< 	if (!ignorerestrictions && (Admin() < minstatus || GetLevel() < minlevel))
---
> 	if (!ignorerestrictions && (Admin() < minstatus || GetLevel() < minlevel)) {
> 		this->cheat_timer.Start(3500,false); //Lieka:  Don't set off warp detector for when a player is moved to the safe-spot for trying to access a zone without the appropriate level or status requirements (i.e. zoning into FearPlane at level 30, etc)
222a235
> 	}
226a240
> 			this->cheat_timer.Start(3500,false); //Lieka:  Don't set off warp detector for when a player is moved to the safe-spot for trying to access a zone without the appropriate flag.
267a282
> 	cheat_timer.Start(3500,false); //Lieka:  Disable MQ Warp & MQ Gate Detector when zoning fails. (not high enough level, etc)
281a297
> 	cheat_timer.Start(3500,false);//Lieka:  Disable /Warp & /Gate Detector when zoning fails. (not high enough level, etc)
410a427,430
> 		case WarpDetected:
> 			Message(15, "Returning to pre-warp location.");
> 			ZonePC(zoneID, x, y, z, heading, ignorerestrictions, zm);
> 			break;
427,477c447,511
< 	switch(zm) {
< 		case EvacToSafeCoords:
< 		case ZoneToSafeCoords:
< 			x = zone->safe_x();
< 			y = zone->safe_y();
< 			z = zone->safe_z();
< 			heading = heading;
< 			break;
< 		case GMSummon:
< 			zonesummon_x = x_pos = x;
< 			zonesummon_y = y_pos = y;
< 			zonesummon_z = z_pos = z;
< 			heading = heading;
< 			
< 			zonesummon_id = zoneID;
< 			zonesummon_ignorerestrictions = 1;
< 			break;
< 		case ZoneSolicited:
< 			zonesummon_x = x;
< 			zonesummon_y = y;
< 			zonesummon_z = z;
< 			heading = heading;
< 			
< 			zonesummon_id = zoneID;
< 			zonesummon_ignorerestrictions = ignorerestrictions;
< 			break;
< 		case GateToBindPoint:
< 			x = x_pos = m_pp.binds[0].x;
< 			y = y_pos = m_pp.binds[0].y;
< 			z = z_pos = m_pp.binds[0].z;
< 			heading = m_pp.binds[0].heading;
< 			break;
< 		case ZoneToBindPoint:
< 			x = x_pos = m_pp.binds[0].x;
< 			y = y_pos = m_pp.binds[0].y;
< 			z = z_pos = m_pp.binds[0].z;
< 			heading = m_pp.binds[0].heading;
< 			
< 			zonesummon_ignorerestrictions = 1;
< 			LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
< 			break;
< 		case SummonPC:
< 			zonesummon_x = x_pos = x;
< 			zonesummon_y = y_pos = y;
< 			zonesummon_z = z_pos = z;
< 			heading = heading;
< 			break;
< 		default:
< 			LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
< 			ReadyToZone = false;
< 			break;
---
> 	switch(zm) {
> 		case EvacToSafeCoords:
> 			this->cheat_timer.Start(2500,false);// Null: added a timers to this location because sometimes the ones in the other locations of code were not doing the job
> 		case ZoneToSafeCoords:
> 			this->cheat_timer.Start(2500,false);
> 			x = zone->safe_x();
> 			y = zone->safe_y();
> 			z = zone->safe_z();
> 			heading = heading;
> 			break;
> 		case GMSummon:
> 			this->cheat_timer.Start(2500,false);
> 			zonesummon_x = x_pos = x;
> 			zonesummon_y = y_pos = y;
> 			zonesummon_z = z_pos = z;
> 			heading = heading;
> 			
> 			zonesummon_id = zoneID;
> 			zonesummon_ignorerestrictions = 1;
> 			break;
> 		case ZoneSolicited:
> 			this->cheat_timer.Start(2500,false);
> 			zonesummon_x = x;
> 			zonesummon_y = y;
> 			zonesummon_z = z;
> 			heading = heading;
> 			
> 			zonesummon_id = zoneID;
> 			zonesummon_ignorerestrictions = ignorerestrictions;
> 			break;
> 		case GateToBindPoint:
> 			this->cheat_timer.Start(2500,false);
> 			x = x_pos = m_pp.binds[0].x;
> 			y = y_pos = m_pp.binds[0].y;
> 			z = z_pos = m_pp.binds[0].z;
> 			heading = m_pp.binds[0].heading;
> 			break;
> 		case ZoneToBindPoint:
> 			this->cheat_timer.Start(2500,false);
> 			x = x_pos = m_pp.binds[0].x;
> 			y = y_pos = m_pp.binds[0].y;
> 			z = z_pos = m_pp.binds[0].z;
> 			heading = m_pp.binds[0].heading;
> 			
> 			zonesummon_ignorerestrictions = 1;
> 			LogFile->write(EQEMuLog::Debug, "Player %s has died and will be zoned to bind point in zone: %s at LOC x=%f, y=%f, z=%f, heading=%f", GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
> 			break;
> 		case SummonPC:
> 			this->cheat_timer.Start(2500,false);
> 			zonesummon_x = x_pos = x;
> 			zonesummon_y = y_pos = y;
> 			zonesummon_z = z_pos = z;
> 			heading = heading;
> 			break;
> 		case WarpDetected:
> 			this->cheat_timer.Disable();
> 			zonesummon_x = x_pos = x;
> 			zonesummon_y = y_pos = y;
> 			zonesummon_z = z_pos = z;
> 			heading = heading;
> 			break;
> 		default:
> 			LogFile->write(EQEMuLog::Error, "Client::ZonePC() received a reguest to perform an unsupported client zone operation.");
> 			ReadyToZone = false;
> 			break;
diff  c:/EQEmu_0.7.0_1102_source/common/database.h c:/VZ-TZ-Diff/common/database.h
120a121
> 	bool	SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone);
diff  c:/EQEmu_0.7.0_1102_source/common/ruletypes.h c:/VZ-TZ-Diff/common/ruletypes.h
67a68,84
> RULE_INT ( Zone, MQWarpExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.
> RULE_INT ( Zone, MQZoneExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.
> RULE_INT ( Zone, MQGateExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.
> RULE_INT ( Zone, MQGhostExemptStatus, 50 ) //Lieka:  Required status level to exempt the MQWarpDetector.  Set to -1 to disable this feature.
> RULE_BOOL ( Zone, EnableMQWarpDetector, false ) //Lieka:  Enable the MQWarp Detector.  Set to False to disable this feature.
> RULE_BOOL ( Zone, EnableMQZoneDetector, false ) //Lieka:  Enable the MQZone Detector.  Set to False to disable this feature.
> RULE_BOOL ( Zone, EnableMQGateDetector, false ) //Lieka:  Enable the MQGate Detector.  Set to False to disable this feature.
> RULE_BOOL ( Zone, EnableMQGhostDetector, false ) //Lieka:  Enable the MQGhost Detector.  Set to False to disable this feature.
> RULE_REAL ( Zone, MQWarpSpeedLimit, 30 ) //Lieka:  Units / second that a player is allowed to travel before a warp is registered. At level 50 SoW = 4, GM Speed = 7 Default value: 10
> RULE_INT ( Zone, MQWarpDetectionSpellID, 757 ) //Lieka:  Which spell ID will be cast on players that incur the hammer of the MQ Detector.  This spell will be actually cast, don't pick a resistible spell.  Default: 757 (Resurrection Effects)
> RULE_INT ( Zone, MQGateDetectionSpellID, 757 ) //Lieka:  Which spell ID debuff will be cast on players that incur the hammer of the MQGateDetector.  This spell will be added as a debuff while zoning.  Default: 757 (Resurrection Effects)
> RULE_INT ( Zone, MQZoneDetectionSpellID, 757 ) //Lieka:  Which spell ID debuff will be cast on players that incur the hammer of the MQGateDetector.  This spell will be added as a debuff while zoning.  Default: 757 (Resurrection Effects)
> RULE_INT ( Zone, MQGhostDetectionSpellID, 757 ) //Lieka:  Which spell ID will be cast on players that incur the hammer of the MQGhostDetector.  This spell will be actually cast, don't pick a resistable spell.  Default: 757 (Resurrection Effects)
> RULE_BOOL ( Zone, MQDetectorDisablePenalties, false ) //Lieka:  Disable penalties (including spell IDs in other MQ rules above when a player triggers a detector.  Default value: false
> RULE_BOOL ( Zone, MQDetectorDisableBroadcast, false ) //Lieka:  Disable the broadcast message when the use of MQ is detected.  Default Value:  false
> RULE_BOOL ( Zone, MQDetectorDisableSQLLogging, false ) //Lieka:  Disable logging of MQDetector events into SQL.  Default Value:  false
> 
diff  c:/EQEmu_0.7.0_1102_source/common/database.cpp c:/VZ-TZ-Diff/common/database.cpp
1460a1461,1478
> bool Database::SetMQDetectionFlag(const char* accountname, const char* charactername, const char* hacked, const char* zone) { //Lieka:  Utilize the "hacker" table, but also give zone information.
> 	char errbuf[MYSQL_ERRMSG_SIZE];
> 	char *query = 0;
> 	int32	affected_rows = 0;
> 	if (!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO hackers(account,name,hacked,zone) values('%s','%s','%s','%s')", accountname, charactername, hacked, zone), errbuf, 0,&affected_rows)) {
> 		cerr << "Error in SetMQDetectionFlag query '" << query << "' " << errbuf << endl;
> 		return false;
> 	}
> 	safe_delete_array(query);
> 	
> 	if (affected_rows == 0)
> 	{
> 		return false;
> 	}
> 	
> 	return true;
> }
>
SQL Rules
Code:
insert into rule_values values (0, 'Zone:MQWarpExemptStatus', 50);
insert into rule_values values (0, 'Zone:MQZoneExemptStatus', 50);
insert into rule_values values (0, 'Zone:MQGateExemptStatus', 50);
insert into rule_values values (0, 'Zone:MQGhostExemptStatus', 50);
insert into rule_values values (0, 'Zone:EnableMQWarpDetector', 'false');
insert into rule_values values (0, 'Zone:EnableMQZoneDetector', 'false');
insert into rule_values values (0, 'Zone:EnableMQGateDetector', 'false');
insert into rule_values values (0, 'Zone:EnableMQGhostDetector', 'false');
insert into rule_values values (0, 'Zone:MQWarpSpeedLimit', 30);
insert into rule_values values (0, 'Zone:MQWarpDetectionSpellID', 757);
insert into rule_values values (0, 'Zone:MQGateDetectionSpellID', 757);
insert into rule_values values (0, 'Zone:MQZoneDetectionSpellID', 757);
insert into rule_values values (0, 'Zone:MQGhostDetectionSpellID', 757);
insert into rule_values values (0, 'Zone:MQDetectorDisablePenalties', 'false');
insert into rule_values values (0, 'Zone:MQDetectorDisableBroadcast', 'false');
insert into rule_values values (0, 'Zone:MQDetectorDisableSQLLogging', 'false');
__________________
Daxum



Former ServerOp - Vallon Zek / Tallon Zek Emu Server - Legit / Guild PvP - (2007 - 2011 RIP)

Last edited by TheLieka; 04-16-2008 at 11:54 AM..
Reply With Quote
  #30  
Old 05-02-2008, 12:35 AM
Doodman's Avatar
Doodman
Developer
 
Join Date: Aug 2003
Posts: 246
Default

Just a couple of comments on the code.

Firstly, excellent work. I love to see fixes for cheats and MQ type hacks.

One thing tho. might not even be yours, but they it was in yours posts:
Quote:
Code:
bool Client::CheckCheat(){
	
		float dx=cheat_x-x_pos;
		float dy=cheat_y-y_pos;
		float result=sqrtf((dx*dx)+(dy*dy));
		return result>(RuleR(Zone, MQWarpDetectorDistance)); //Lieka:  Integrated into Rules System; default value is 30, this allows for beyond GM speed without lag.
Consider pre-squaring "RuleR(Zone, MQWarpDetectorDistance)" and eliminate the sqrtf(). sqrt() is very expensive. Most times you don't need raw distance, you just need to compare the two. i.e.
Expensive: if (sqrtf((dx*dx)+(dy*dy)) > 30)
Cheaper: if (((dx*dx)+(dy*dy)) > 900)

Yet they accomplish the same result.

Just some tips, otherwise looks good.
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 12:05 PM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3