Advertisement
Guest User

AC

a guest
Nov 27th, 2014
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.26 KB | None | 0 0
  1. -- CONFIG SECTION
  2.  
  3. checkInterval = 60 -- The interval in seconds after which the script will check all players' ratings and compare them.
  4. -- Ratings fluctuate a lot during the first minutes of playing and need some time to even out.
  5. -- The shorter you choose the interval, the higher the chance of unjustified warnings/kicks.
  6.  
  7. minPlayTimePercentage = 40 -- The minimum percentage of _checkInterval that a player needs to have already spent playing
  8. -- for his rating to be taking into account (spectator time does not count).
  9. -- This is done to prevent recently joined players with biased ratings from affecting the average or getting kicked.
  10. -- EXAMPLE: If the interval is 10min and the playTimePercentage is 80, then all players who have not yet
  11. -- spent at least 8 minutes playing during the current map are ignored.
  12.  
  13.  
  14. percentageThreshold = 188 -- A player will be punished if they exceed all players' average rating by this many percent
  15.  
  16.  
  17. kickLimit = 0 -- A player will be warned this many times before being kicked from the server.
  18. -- Set to 0 to insta-kick without warnings.
  19. -- NOTE: The script only works per round, nothing is saved between maps!
  20. -- So keep in mind that it takes a player (_kickLimit + 1) * _checkInterval seconds to be kicked.
  21. -- On short maps, this might be unreachable with the default values.
  22. -- EXAMPLE: Your interval is 10 minutes, your kicklimit 2.
  23. -- That means it takes a player at least 30 minutes to be kicked by the script.
  24. -- Most matches will be over by that time meaning the player will go unaffected.
  25. -- An inter-round solution might be necessary, maybe in a future release
  26.  
  27.  
  28. kickReason = "AntiCheat has kicked - due to aimbot/multihack." -- The message that is displayed to kicked players
  29.  
  30.  
  31. banTime = 14400 -- The time in seconds that a kicked player will be banned from the server
  32.  
  33.  
  34. -- By default, the script will check all players Kills/Deaths, Damage Given/Received and Kills/Second ratio and calculate the average.
  35. -- If you want one ratio to have a higher weighting or completely disable one, alter their multipliers here.
  36. -- A multiplier of 0 means the ratio will be ignored.
  37. -- NOTE: Kills/Deaths & Kills/Second ratios respect the weapon whitelist (if enabled), damage ratio doesn't
  38. -- EXAMPLE: If all multipliers are equal, the average will consist of 33%/33%/33%
  39. -- If you set the multipliers to 2/1/3, the average will be 33%/17%/50%
  40. -- For 1/0/2, the average will be 33%/0%/67%
  41.  
  42. multiplier_killDeathRatio = 1 -- multiplier of "kills per life" ratio
  43.  
  44. multiplier_damageRatio = 1 -- multiplier of "damage given/received" ratio
  45.  
  46. multiplier_killsPerSecondRatio = 1 -- multiplier of "kills per second" ratio
  47.  
  48.  
  49. minimumPlayers = 3 -- The script will only become active when at least this many people are playing and have served
  50. -- _minPlayTimePercentage of _checkInterval - spectators and newly joined players are ignored.
  51. -- With only two players playing, one being an average player and the other one a complete retard,
  52. -- it would get the normal player kicked because of the skill difference. Hence the minimum limit.
  53.  
  54. --[[
  55. -- This script gives you the possibility to whitelist certain weapons.
  56. -- Kills/Deaths from a whitelisted weapons don't count.
  57. -- This is done to prevent e.g. artillery or landmine kills from getting a player kicked.
  58. -- If people start complaining about getting kicked for rifle grenade or mortar kills, you can whitelist these weapons.
  59. -- The whitelist is commented out and thus inactive by default. If you want to use it, remove the comment tags and PROPERLY SET IT UP.
  60. -- The damage ratio does not respect the whitelist, meaning it will also contain damage done by whitelisted weapons.
  61. -- NOTE: Below MOD list is for etpro, your mod might use a different one!
  62. -- See if you can find it by searching for "methodOfDeath" or "meansOfDeath"
  63. -- MOD list for No Quarter: http://shitstorm.org/noquarter/wiki/index.php?title=Lua_Scripting#MOD:_Means_of_Death
  64. -- NOTE: LUA TABLES START AT INDEX 1 !!!
  65.  
  66. weaponWhitelist = {
  67.  
  68. -- true = don't count kills
  69. -- false = count kills
  70.  
  71. true, -- MOD_MACHINEGUN
  72. true, -- MOD_BROWNING
  73. true, -- MOD_MG42
  74. false, -- MOD_GRENADE
  75. true, -- MOD_ROCKET
  76. true, -- MOD_KNIFE
  77. false, -- MOD_LUGER
  78. false, -- MOD_COLT
  79. false, -- MOD_MP40
  80. false, -- MOD_THOMPSON
  81. false, -- MOD_STEN
  82. false, -- MOD_GARAND
  83. false, -- MOD_SNOOPERSCOPE
  84. false, -- MOD_SILENCER
  85. false, -- MOD_FG42
  86. false, -- MOD_FG42SCOPE
  87. false, -- MOD_PANZERFAUST
  88. false, -- MOD_GRENADE_LAUNCHER
  89. true, -- MOD_FLAMETHROWER
  90. false, -- MOD_GRENADE_PINEAPPLE
  91. false, -- MOD_CROSS
  92. false, -- MOD_MAPMORTAR
  93. false, -- MOD_MAPMORTAR_SPLASH
  94. false, -- MOD_KICKED
  95. false, -- MOD_GRABBER
  96. true, -- MOD_DYNAMITE
  97. true, -- MOD_AIRSTRIKE
  98. false, -- MOD_SYRINGE
  99. true, -- MOD_AMMO
  100. true, -- MOD_ARTY
  101. true, -- MOD_WATER
  102. true, -- MOD_SLIME
  103. true, -- MOD_LAVA
  104. true, -- MOD_CRUSH
  105. true, -- MOD_TELEFRAG
  106. true, -- MOD_FALLING
  107. false, -- MOD_SUICIDE
  108. true, -- MOD_TARGET_LASER
  109. true, -- MOD_TRIGGER_HURT
  110. true, -- MOD_EXPLOSIVE
  111. false, -- MOD_CARBINE
  112. false, -- MOD_KAR98
  113. false, -- MOD_GPG40
  114. false, -- MOD_M7
  115. true, -- MOD_LANDMINE
  116. true, -- MOD_SATCHEL
  117. true, -- MOD_TRIPMINE
  118. true, -- MOD_SMOKEBOMB
  119. false, -- MOD_MOBILE_MG42
  120. false, -- MOD_SILENCED_COLT
  121. false, -- MOD_GARAND_SCOPE
  122. true, -- MOD_CRUSH_CONSTRUCTION
  123. true, -- MOD_CRUSH_CONSTRUCTIONDEATH
  124. true, -- MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER
  125. false, -- MOD_K43
  126. false, -- MOD_K43_SCOPE
  127. true, -- MOD_MORTAR
  128. false, -- MOD_AKIMBO_COLT
  129. false, -- MOD_AKIMBO_LUGER
  130. false, -- MOD_AKIMBO_SILENCEDCOLT
  131. false, -- MOD_AKIMBO_SILENCEDLUGER
  132. true, -- MOD_SMOKEGRENADE
  133. true, -- MOD_SWAP_PLACES
  134. true -- MOD_SWITCHTEAM
  135.  
  136. -- NOTE: THERE'S NO COMMA AFTER THE LAST ENTRY !!
  137. }
  138. --]]
  139.  
  140. -- playerWhiteList = "nopro_playerWhitelist.dat"
  141. -- This script gives you the possibility to exclude players from being punished by the script.
  142. -- You can do this if you and the script can't agree whether a player is "too skilled" for the server.
  143. -- Enable the whitelist by removing the comment tags and creating the (empty) file inside your etmain or mod folder - the script can't do it !!
  144. -- Add players to the list at runtime with the server-side command "!nopro <name>".
  145. -- You can add a custom shrubbot command to let your admins do this without having to share the rcon password.
  146.  
  147. -- debugSettings = true -- The default values are most likely non-functional.
  148. -- I have tested the script with bots to make sure it works properly but I have no human players to test this with
  149. -- so I leave tweaking the settings to you.
  150. -- If you enable debugging, the script prints some debug info to global chat every time the interval runs out.
  151. -- This will hopefully help you to adjust the settings to your needs.
  152. -- NOTE: When you first run the script, set kickLimit to something unreachably high and make sure you don't have
  153. -- unjustified kicks before actually "arming" the script or you might scare off your playerbase
  154.  
  155.  
  156. -- END OF CONFIG SECTION
  157.  
  158. ----------------------------------------------------------------
  159. -- DONT CHANGE ANYTHING BELOW UNLESS YOU KNOW WHAT YOU ARE DOING
  160. ----------------------------------------------------------------
  161.  
  162. timesWarned = {} -- number of times a player has already been warned
  163. whitelist = {} -- contains GUIDs of player whitelist
  164. kills = {} -- custom kills counter, for weapon white list
  165. deaths = {} -- custom deaths counter, for weapon white list
  166. lastStartTime = {} -- timestamp of when client joined a team (if on a team, else nil)
  167. timePlayedAlready = {} -- time that client has already spent on a team in current map (in milliseconds)
  168.  
  169. function et_RunFrame( levelTime )
  170.  
  171. if math.mod(levelTime,checkInterval) ~= 0 then return end
  172.  
  173. if et.trap_Cvar_Get("gamestate") ~= "0" then return end
  174.  
  175. local avg_killDeathRatio = 0
  176. local avg_damageRatio = 0
  177. local avg_killsPerSecondRatio = 0
  178.  
  179. local killDeathRatio = {}
  180. local damageRatio = {}
  181. local killsPerSecondRatio = {}
  182.  
  183. local ratedPlayers = {} -- contains all clients that are being checked for ratio violations
  184. local numRatedPlayers = 0 -- rated = (!BOT && !WHITELISTED && MINIMUM_INTERVAL_PERCENTAGE_SERVED)
  185. local numActivePlayers = 0 -- amount of human players not in spectator, for minimum player count
  186.  
  187. for i=0,tonumber(et.trap_Cvar_Get("sv_maxclients"))-1 do
  188.  
  189. if et.gentity_get(i, "pers.connected") > 0 and et.gentity_get(i, "pers.localClient") == 0 then
  190.  
  191. local sessionPlayTime = (timePlayedAlready[i] or 0) + (lastStartTime[i] and (et.trap_Milliseconds() - lastStartTime[i]) or 0)
  192.  
  193. if sessionPlayTime > (checkInterval * minPlayTimePercentage / 100) then
  194.  
  195. local kills = (weaponWhitelist and (kills[i] or 0) or et.gentity_get(i, "sess.kills"))
  196. -- adding 1 to avoid division by 0
  197. local deaths = (weaponWhitelist and (deaths[i] or 0) or et.gentity_get(i, "sess.deaths")) + 1
  198.  
  199. killDeathRatio[i] = kills / deaths
  200. damageRatio[i] = et.gentity_get(i, "sess.damage_given") / (et.gentity_get(i, "sess.damage_received") + 1)
  201. killsPerSecondRatio[i] = kills / sessionPlayTime -- kills per millisecond, really
  202.  
  203. avg_killDeathRatio = avg_killDeathRatio + killDeathRatio[i]
  204. avg_damageRatio = avg_damageRatio + damageRatio[i]
  205. avg_killsPerSecondRatio = avg_killsPerSecondRatio + killsPerSecondRatio[i]
  206.  
  207. numRatedPlayers = numRatedPlayers + 1
  208.  
  209. local team = et.gentity_get(i, "sess.sessionTeam")
  210.  
  211. if team == 1 or team == 2 then
  212. numActivePlayers = numActivePlayers + 1
  213. end
  214.  
  215. if not whitelist[et.Info_ValueForKey(et.trap_GetUserinfo(i),"cl_guid")] then
  216. ratedPlayers[i] = true
  217. end
  218. end
  219. end
  220. end
  221.  
  222. if numActivePlayers < minimumPlayers then return end -- don't continue if the minimum player count is not reached
  223.  
  224. if numRatedPlayers == 0 then return end -- prevent division by 0
  225.  
  226. avg_killDeathRatio = avg_killDeathRatio / numRatedPlayers
  227. avg_damageRatio = avg_damageRatio / numRatedPlayers
  228. avg_killsPerSecondRatio = avg_killsPerSecondRatio / numRatedPlayers
  229.  
  230. if debugSettings then
  231. sendCmd("qsay Average killDeathRatio: " .. avg_killDeathRatio)
  232. sendCmd("qsay Average damageRatio: " .. avg_damageRatio)
  233. sendCmd("qsay Average killsPerSecondRatio: " .. avg_killsPerSecondRatio)
  234. end
  235.  
  236. local ignore_killDeathRatio = (avg_killDeathRatio == 0 and true or false)
  237. local ignore_damageRatio = (avg_damageRatio == 0 and true or false)
  238. local ignore_killsPerSecondRatio = (avg_killsPerSecondRatio == 0 and true or false)
  239.  
  240. if ignore_killDeathRatio and ignore_damageRatio and ignore_killsPerSecondRatio then return end -- no data yet
  241.  
  242. for i, v in pairs(ratedPlayers) do
  243.  
  244. ratio = ((ignore_killDeathRatio and 0 or ((killDeathRatio[i] - avg_killDeathRatio) / (avg_killDeathRatio / 100) * multiplier_killDeathRatio))
  245. + (ignore_damageRatio and 0 or ((damageRatio[i] - avg_damageRatio) / (avg_damageRatio / 100) * multiplier_damageRatio))
  246. + (ignore_killsPerSecondRatio and 0 or ((killsPerSecondRatio[i] - avg_killsPerSecondRatio) / (avg_killsPerSecondRatio / 100) * multiplier_killsPerSecondRatio)))
  247. / ((ignore_killDeathRatio and 0 or multiplier_killDeathRatio) + (ignore_damageRatio and 0 or multiplier_damageRatio) + (ignore_killsPerSecondRatio and 0 or multiplier_killsPerSecondRatio))
  248.  
  249. if debugSettings then
  250. sendCmd("qsay Rating of " .. et.Info_ValueForKey(et.trap_GetUserinfo(i),"name") .. " ^7is off by " .. math.floor(ratio + 0.5) .. " percent")
  251. end
  252.  
  253. if ratio > percentageThreshold then -- YUNOSUPPORTCONTINUE
  254.  
  255. et.G_globalSound("sound/misc/referee.wav")
  256.  
  257. if kickLimit > (timesWarned[i] or 0) then -- warn
  258.  
  259. timesWarned[i] = (timesWarned[i] or 0) + 1
  260. sendCmd("qsay ^dnopro: ^7" .. et.Info_ValueForKey(et.trap_GetUserinfo(i),"name") .. " ^9has been warned for having a ratio of ^2"
  261. .. math.floor(ratio + 0.5) .. " ^9percent above average")
  262. et.trap_SendServerCommand(i, "cp \"^3*** ^1WARNING " .. timesWarned[i] .. "/" .. kickLimit .. " - OPEN CONSOLE FOR DETAILS! ^3***")
  263. et.trap_SendServerCommand(i, "print \"^1=========================\n")
  264. et.trap_SendServerCommand(i, "print \"^1*** ^3SKILL WARNING " .. timesWarned[i] .. "/" .. kickLimit .. " ^1***\n")
  265. et.trap_SendServerCommand(i, "print \"^1=========================\n")
  266. et.trap_SendServerCommand(i, "print \"^3You have exceeded this server's average skill rating of this session by ^2"
  267. .. math.floor(ratio + 0.5) .. "^3 percent.\n")
  268. et.trap_SendServerCommand(i, "print \"^3Only a deviation of " .. percentageThreshold .. " percent is allowed.\n")
  269. et.trap_SendServerCommand(i, "print \"^3You seem to be overqualified for this server. Please find a more suitable one!\n")
  270. et.trap_SendServerCommand(i, "print \"^1=========================\n")
  271. else
  272. et.trap_DropClient( i, kickReason, banTime ) -- kick
  273. end
  274. end
  275. end
  276. end
  277.  
  278. function et_Print(text)
  279.  
  280. if string.sub(text,1,13) ~= "ClientBegin: " then return end
  281.  
  282. local id = tonumber(string.sub(text,14))
  283.  
  284. if not id then return end
  285.  
  286. local team = et.gentity_get(id, "sess.sessionTeam")
  287.  
  288. if (team == 1 or team == 2) then
  289.  
  290. if lastStartTime[id] then return end -- team -> team, ignore
  291.  
  292. lastStartTime[id] = et.trap_Milliseconds() -- spec -> team
  293.  
  294. else
  295. if not lastStartTime[id] then return end -- spec -> spec, ignore
  296.  
  297. timePlayedAlready[id] = (timePlayedAlready[id] or 0) + (et.trap_Milliseconds() - lastStartTime[id])
  298. lastStartTime[id] = nil -- team -> spec
  299. end
  300. end
  301.  
  302. function et_ClientConnect( clientNum, firstTime, isBot )
  303.  
  304. if firstTime == 0 or isBot == 1 then return end
  305.  
  306. timesWarned[clientNum] = nil
  307. end
  308.  
  309. function et_Obituary( victim, killer, meansOfDeath )
  310.  
  311. if killer == 1022 or victim == killer or killer == 1023
  312. or et.gentity_get(victim, "sess.sessionTeam") == et.gentity_get(killer, "sess.sessionTeam") then return end
  313. -- 1022 = worldspawn, 1023 = ENTITYNUM_NONE
  314. -- don't count kills by self, team and world
  315.  
  316. kills[killer] = kills[killer] + 1
  317. deaths[victim] = deaths[victim] + 1
  318. end
  319.  
  320. function sendCmd(cmd)
  321. et.trap_SendConsoleCommand(et.EXEC_APPEND, cmd .. ";")
  322. end
  323.  
  324. function et_InitGame(levelTime, randomSeed, restart)
  325.  
  326. if (multiplier_killDeathRatio + multiplier_damageRatio + multiplier_killsPerSecondRatio) == 0 then
  327.  
  328. sendCmd("qsay ^dnopro: ^9Ratio multipliers add up to 0, set at least one > 0. Aborting..")
  329. et.RegisterModname("one4oneAC [INACTIVE]")
  330. timesWarned = nil
  331. whitelist = nil
  332. kills = nil
  333. deaths = nil
  334. lastStartTime = nil
  335. timePlayedAlready = nil
  336. et_RunFrame = nil
  337. et_Print = nil
  338. et_ClientConnect = nil
  339. et_Obituary = nil
  340. sendCmd = nil
  341. et_ConsoleCommand = nil
  342. return
  343. end
  344.  
  345. checkInterval = checkInterval * 1000 -- transform to milliseconds
  346.  
  347. if not weaponWhitelist then
  348. et_Obituary = nil
  349. kills = nil
  350. deaths = nil
  351. end
  352.  
  353. et.RegisterModname("one4oneAC")
  354.  
  355. if not playerWhiteList then
  356. et_ConsoleCommand = nil
  357. return
  358. end
  359.  
  360. local fd,len = et.trap_FS_FOpenFile(playerWhiteList, et.FS_READ)
  361.  
  362. if len < 0 then
  363. sendCmd("qsay ^dnopro: ^9Couldn't open whitelist file ^7" .. playerWhiteList .. "^9. Make sure it exists and has proper file permissions")
  364. else
  365. for line in string.gfind(et.trap_FS_Read(fd, len), "(%x+)") do
  366.  
  367. if not line then break end
  368.  
  369. if string.len(line) == 32 and not whitelist[line] then
  370. whitelist[line] = true
  371. end
  372. end
  373. end
  374.  
  375. et.trap_FS_FCloseFile(fd)
  376. end
  377.  
  378. function et_ConsoleCommand(command)
  379.  
  380. if string.lower(et.trap_Argv(0)) ~= "!nopro" then return 0 end
  381.  
  382. local feedback
  383. local arg1 = et.trap_Argv(1)
  384. local id = et.ClientNumberFromString(arg1)
  385.  
  386. if arg1 == "" then
  387. feedback = "^9Usage: ^2!nopro <playerName> ^9to add a player to the whitelist"
  388.  
  389. elseif not id or id == -1 then
  390. feedback = "^9No or multiple matches found for player ^7" .. arg1 .. "^9. Be more specific or use client #"
  391.  
  392. else
  393. local guid = et.Info_ValueForKey(et.trap_GetUserinfo(id),"cl_guid")
  394. local name = et.Info_ValueForKey(et.trap_GetUserinfo(id),"name")
  395.  
  396. if et.gentity_get(id, "pers.localClient") == 1 then
  397. feedback = "^7" .. name .. " ^9is a bot and can't be whitelisted"
  398.  
  399. elseif whitelist[guid] then
  400. feedback = "^7" .. name .. " ^9is already on the whitelist"
  401.  
  402. elseif not guid or string.len(guid) ~= 32 then
  403. feedback = "^7" .. name .. " ^9doesn't have a GUID and can't be whitelisted"
  404.  
  405. else
  406. local fd,len = et.trap_FS_FOpenFile(playerWhiteList, et.FS_APPEND)
  407.  
  408. if len < 0 then
  409. feedback = "^9Couldn't open whitelist file ^7" .. playerWhiteList .. "^9. Make sure it exists and has proper file permissions"
  410. else
  411. local data = guid .. " | " .. name .. "\n"
  412.  
  413. bytes_written = et.trap_FS_Write(data, string.len(data), fd)
  414.  
  415. if bytes_written <= 0 then
  416. feedback = "^9Couldn't write to whitelist file ^7" .. playerWhiteList .. "^9. Make sure it exists and has proper file permissions"
  417. else
  418. whitelist[guid] = true
  419.  
  420. feedback = "^7" .. name " ^9has been successfully added to the whitelist"
  421. end
  422. end
  423.  
  424. et.trap_FS_FCloseFile(fd)
  425. end
  426. end
  427.  
  428. et.G_Print("^dnopro: " .. feedback .. "\n") -- this line prints to server console
  429.  
  430. -- sendCmd("qsay ^dnopro: " .. feedback) -- this line prints to global chat
  431.  
  432. return 1
  433. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement