23.12.2014, 16:47
(
Последний раз редактировалось michalmonday; 27.01.2015 в 14:53.
Причина: Added instructions
)
__________________________________________________ ________________________________
Health-hack (bulletproof) detector - ******* video
Estimated reliability:

Calibration:
1. Increase delayer time in case if there are false detections
2. Evaluate if there are false detections by spectating each detected player
3. Repeat step 1 until there is no false detections
Individual script modification needed:
-afk check has to be added
-number of hits without losing health needed to take action(after calibration)
-final action (after calibration)
No-spread detector - ******* video
It's not effective if the player is waving the gun around.
Health-hack (bulletproof) detector - ******* video
Код:
#define FILTERSCRIPT #include <a_samp> new Float:previousHealthValue[MAX_PLAYERS], hits[MAX_PLAYERS], noDamageCount[MAX_PLAYERS], //count how many times the player didn't lose health after being hit bool:delayer[MAX_PLAYERS], // delayer is neccessary because damage is not updated quickly enough and gives false detections bool:afterSpawnCover[MAX_PLAYERS], //to avoid false detections straight after spawn which happened to me while testing it (it's set to 3 seconds right now) bool:isDead[MAX_PLAYERS]; // hp check to see if the player is dead didn't work(the value of hp stayed the same as before last shot) //////////////////////////////// //SETTINGS #define DELAY_TIME 500 // 500ms delay works well on my syrver with 2 players online, I'm not sure what's it's going to be like on a server with over 100 players online #define AFTER_SPAWN_COVER_TIME 3000 #define NO_DAMAGE_COUNT_LIMIT 0 // number of times the script detected someone taking no damage after shot needed to: send info to admins/kick/ban //SETTINGS //////////////////////////////// public OnFilterScriptInit() { print("\n--------------------------------------"); print("Health-hack detector by monday"); print("--------------------------------------\n"); return 1; } public OnPlayerConnect(playerid) { previousHealthValue[playerid] = 0.0; hits[playerid] = 0; noDamageCount[playerid] = 0; delayer[playerid] = false; return 1; } public OnPlayerDeath(playerid, killerid, reason) { isDead[playerid] = true; return 1; } public OnPlayerSpawn(playerid) { previousHealthValue[playerid] = 0.0; hits[playerid] = 0; delayer[playerid] = false; afterSpawnCover[playerid] = true; SetTimerEx("RemoveSpawnCover", AFTER_SPAWN_COVER_TIME, false, "i", playerid); isDead[playerid] = false; return 1; } forward SwitchDelay(playerid); public SwitchDelay(playerid) { delayer[playerid] = true; return 1; } forward RemoveSpawnCover(playerid); public RemoveSpawnCover(playerid) { afterSpawnCover[playerid] = false; return 1; } public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ) { if(hittype == BULLET_HIT_TYPE_PLAYER) { new Float:h, Float:a, Float:newHealthValue, message[128], cheaterName[MAX_PLAYER_NAME]; if(hits[hitid] == 0) { GetPlayerHealth(hitid, h); GetPlayerArmour(hitid, a); previousHealthValue[hitid] = h + a; if(isDead[hitid] == true || afterSpawnCover[hitid] == true) // + here must be a check for AFK to avoid false detections { hits[hitid] = 0; } else { SetTimerEx("SwitchDelay", DELAY_TIME, false, "i", hitid); } } else if(delayer[hitid] == true) { delayer[hitid] = false; GetPlayerHealth(hitid, h); GetPlayerArmour(hitid, a); newHealthValue = h + a; if(newHealthValue == previousHealthValue[hitid] && isDead[hitid] != true && afterSpawnCover[hitid] != true) { noDamageCount[hitid]++; if(noDamageCount[hitid] > NO_DAMAGE_COUNT_LIMIT) { //send message to admins, kick, ban GetPlayerName(hitid, cheaterName, sizeof(cheaterName)); format(message,sizeof(message),"%s didn't lose health %d times after being shot since his last login.",cheaterName, noDamageCount[hitid]); SendClientMessageToAll(0xED6755AA,message); } } else { previousHealthValue[hitid] = newHealthValue; //update health value if it decreased like it should } SetTimerEx("SwitchDelay", DELAY_TIME, false, "i", hitid); // new delay before next check } hits[hitid]++; } return 1; }

Calibration:
1. Increase delayer time in case if there are false detections
2. Evaluate if there are false detections by spectating each detected player
3. Repeat step 1 until there is no false detections
Individual script modification needed:
-afk check has to be added
-number of hits without losing health needed to take action(after calibration)
-final action (after calibration)
No-spread detector - ******* video
It's not effective if the player is waving the gun around.
Код:
#define FILTERSCRIPT #include <a_samp> new hitsInaRow[MAX_PLAYERS]; new Float:lastMiddle_X[MAX_PLAYERS]; new Float:lastMiddle_Y[MAX_PLAYERS]; new Float:lastMiddle_Z[MAX_PLAYERS]; new Float:lastHit_X[MAX_PLAYERS]; new Float:lastHit_Y[MAX_PLAYERS]; new Float:lastHit_Z[MAX_PLAYERS]; new weaponUsed[MAX_PLAYERS]; new Float:averageSpread[MAX_PLAYERS]; public OnFilterScriptInit() { print("\n--------------------------------------"); print("No-spread detector by monday"); print("--------------------------------------\n"); return 1; } stock Float:GetPositiveNumber(Float:number) { if(0.0 > number) { number *= -1.0; } return number; } stock Float:GetDistanceBetweenPoints(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2) { return VectorSize(x1-x2, y1-y2, z1-z2); } public OnPlayerConnect(playerid) { hitsInaRow[playerid]=0; lastMiddle_X[playerid]=0.0; lastMiddle_Y[playerid]=0.0; lastMiddle_Z[playerid]=0.0; lastHit_X[playerid]=0.0; lastHit_Y[playerid]=0.0; lastHit_Z[playerid]=0.0; averageSpread[playerid]=0.0; weaponUsed[playerid] = 0; return 1; } forward SpreadCheckReset(playerid); public SpreadCheckReset(playerid) { hitsInaRow[playerid]=0; lastMiddle_X[playerid]=0.0; lastMiddle_Y[playerid]=0.0; lastMiddle_Z[playerid]=0.0; lastHit_X[playerid]=0.0; lastHit_Y[playerid]=0.0; lastHit_Z[playerid]=0.0; averageSpread[playerid]=0.0; weaponUsed[playerid] = 0; return 1; } forward OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ); public OnPlayerWeaponShot(playerid, weaponid, hittype, hitid, Float:fX, Float:fY, Float:fZ) { new Float:fOriginX, Float:fOriginY, Float:fOriginZ, Float:fVX, Float:fVY, Float:fVZ, Float:fHitPosX, Float:fHitPosY, Float:fHitPosZ, Float:middle_x, Float:middle_y, Float:middle_z, Float:compareMiddle_x, Float:compareMiddle_y, Float:compareMiddle_z, Float:compareHit_x, Float:compareHit_y, Float:compareHit_z, Float:compareBoth_x, Float:compareBoth_y, Float:compareBoth_z, Float:distance, Float:spreadValue, Float:spreadLimit, cheaterName[MAX_PLAYER_NAME], hitsNeeded, weaponTime, currentWeapon, finalMessage[128], gunName[32], spread[128]; currentWeapon = GetPlayerWeapon(playerid); GetPlayerLastShotVectors(playerid, fOriginX, fOriginY, fOriginZ, fHitPosX, fHitPosY, fHitPosZ); distance = GetDistanceBetweenPoints(fOriginX, fOriginY, fOriginZ, fHitPosX, fHitPosY, fHitPosZ); GetPlayerCameraFrontVector(playerid, fVX, fVY, fVZ); middle_x = fOriginX + floatmul(fVX, distance); middle_y = fOriginY + floatmul(fVY, distance); middle_z = fOriginZ + floatmul(fVZ, distance); // middle_x, middle_y, middle_z = middle of the screen // fHitPosX, fHitPosY, fHitPosZ = shooting point //compare with the last shot compareMiddle_x = GetPositiveNumber(middle_x - lastMiddle_X[playerid]); compareMiddle_y = GetPositiveNumber(middle_y - lastMiddle_Y[playerid]); compareMiddle_z = GetPositiveNumber(middle_z - lastMiddle_Z[playerid]); compareHit_x = GetPositiveNumber(fHitPosX - lastHit_X[playerid]); compareHit_y = GetPositiveNumber(fHitPosY - lastHit_Y[playerid]); compareHit_z = GetPositiveNumber(fHitPosZ - lastHit_Z[playerid]); compareBoth_x = GetPositiveNumber(compareMiddle_x - compareHit_x); compareBoth_y = GetPositiveNumber(compareMiddle_y - compareHit_y); compareBoth_z = GetPositiveNumber(compareMiddle_z - compareHit_z); spreadValue = GetPositiveNumber(compareBoth_x + compareBoth_y + compareBoth_z); //replace last shot data with new one lastMiddle_X[playerid] = middle_x; lastMiddle_Y[playerid] = middle_y; lastMiddle_Z[playerid] = middle_z; lastHit_X[playerid] = fHitPosX; lastHit_Y[playerid] = fHitPosY; lastHit_Z[playerid] = fHitPosZ; if (weaponUsed[playerid] != currentWeapon) { weaponUsed[playerid] = currentWeapon; SpreadCheckReset(playerid); return 1; } if (currentWeapon == 31 || currentWeapon == 30 ||currentWeapon == 28 || currentWeapon == 32 ||currentWeapon == 29) //m4, ak47, tec, uzi, mp5 - all of them are set to m4's limit which is the most accurate weapon. Mp5 has a bit faster shooting rate than other weapons included but its spread is also higher so it's not an issue, I tested it and it's not even close to get false detection { hitsNeeded = 3; // weaponTime = 500; //time after which the stored hits will be reset(to make sure that there is no breaks between single shots) weaponUsed[playerid] = currentWeapon; } else { if (currentWeapon == 24)//deagle { hitsNeeded = 2; weaponTime = 1600; weaponUsed[playerid] = currentWeapon; } else { return 1; } } if( GetPlayerSpecialAction(playerid) == SPECIAL_ACTION_DUCK ) { spreadLimit = 0.00075 * distance; //decreased limit if the player is crouching } else { spreadLimit = 0.00140 * distance; } format(spread, sizeof(spread), "Spread: %f Limit: %f",spreadValue, spreadLimit); //SendClientMessage(playerid, -1, spread); if(spreadValue < spreadLimit && 200.0 > distance > 3.0) { hitsInaRow[playerid]++; averageSpread[playerid] = averageSpread[playerid] + spreadValue; } if (hitsInaRow[playerid] == 1) { SetTimerEx("SpreadCheckReset", weaponTime, 0, "i", playerid); } if (hitsInaRow[playerid] == hitsNeeded || hitsInaRow[playerid] > hitsNeeded) { //send message to admins, kick, ban GetWeaponName(currentWeapon, gunName, sizeof(gunName)); GetPlayerName(playerid, cheaterName, MAX_PLAYER_NAME); averageSpread[playerid] /= float(hitsInaRow[playerid]); format(finalMessage, sizeof(finalMessage), "%s is shooting under spread limit using %s. Average spread=%f Limit=%f", cheaterName, gunName, averageSpread[playerid], spreadLimit); SendClientMessageToAll(0xED6755AA,finalMessage); SpreadCheckReset(playerid); } return 1; }