Advertisement
HR_Shaft

Headshot Announcer v2 for Sapp

Jan 16th, 2017
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.42 KB | None | 0 0
  1. -- Headshot Announcer v2
  2. -- by H® Shaft
  3.  
  4. -- changelog 1/16/2017
  5.     -- corrected a couple typos where [id] should have been PlayerIndex instead
  6.     -- corrected show stats to correctly attribute headshot counts
  7.     -- edited to only read memory if a game is running to prevent crashes
  8.     -- corrected OnDamageLookup to only work if damage was caused by another player
  9.  
  10. -- The PRIMARY purpose of this script:
  11. -- is to announce when a player is killed by a "head-shot", and -
  12. -- to show everyone their "kills by head-shots count" in (parenthesis).
  13.  
  14. -- **Example** this kill message shows H® Shaft has '14' head-shot-kills:
  15.  
  16.     -- " BOOM! H® Shaft ASSASSINATED New001 with a HEAD-SHOT! (14) "
  17.  
  18. -- The SECONDARY purpose of this script to allow admins identify all players kill counts -vs- kills-by-headshot counts
  19. -- Note: many players are very good at killing by headshots; it doesn't mean they are cheating or aim-botting!
  20.  
  21. -- ADMIN USAGE:
  22. -- admins can type "/ss" for the ShowStats command to see all players kill counts -vs- kills-by-headshot counts
  23. -- admins can specify the admin level of those who can execute the command (see ADMIN_LEVEL below)
  24.  
  25. -- SAMPLE OUTPUT of ShowStats command (Player # is ID#):
  26. -- ID#: 1 --   H® Shaft --  KILLS: 4 --   HEADSHOTS: 3
  27. -- ID#: 2 --   Killer   --  KILLS: 0 --   HEADSHOTS: 0
  28.  
  29. -- This admin level and higher can use the /ss (ShowStats) command, and see all players head shot scores
  30. ADMIN_LEVEL = 2
  31.  
  32. -- if set to true, when the /ss command is used, log all players kill counts and kills-by-headshot counts into sapps log
  33. LOG_RESULTS = true
  34.  
  35. -- The command to use to "reset the map" AND reset players kill count and kills-by-headshot counts zero
  36. RESET_COMMAND = "reset"
  37.  
  38. --- END CONFIGURATION ----
  39. --- don't edit below  ---
  40. api_version = "1.9.0.0"
  41.  
  42. function OnScriptLoad()
  43.     register_callback(cb['EVENT_JOIN'], "OnPlayerJoin")
  44.     register_callback(cb['EVENT_GAME_START'], "OnNewGame")
  45.     register_callback(cb['EVENT_GAME_END'], "OnGameEnd")
  46.     register_callback(cb['EVENT_DIE'], "OnPlayerDie")
  47.     register_callback(cb['EVENT_CHAT'], "OnPlayerChat")
  48.     register_callback(cb['EVENT_DAMAGE_APPLICATION'], "OnDamageApplication")
  49.     register_callback(cb['EVENT_COMMAND'], "OnCommand")
  50.     head_shot = {}
  51.     headshot_count = {}
  52.     if get_var(0, "$gt") ~= "n/a" then
  53.         OnNewGame()    
  54.     end
  55. end
  56.  
  57. function OnScriptUnload() end
  58.  
  59. function OnNewGame()
  60.     game_started = true
  61.     for i = 1, 16 do
  62.         if player_present(i) then
  63.             head_shot[i] = false
  64.             headshot_count[i] = 0          
  65.         end
  66.     end
  67. end
  68.  
  69. function OnGameEnd()
  70.     game_started = false
  71.     for i = 1,16 do
  72.         if player_present(i) then
  73.             local id = get_var(i, "$n")
  74.             if headshot_count[i] == nil then headshot_count[i] = 0 end
  75.             local headshots = tonumber(headshot_count[i])
  76.             local name = get_var(i, "$name")
  77.             local kills = tonumber(get_var(i, "$kills"))
  78.             if kills == nil then kills = 0 end
  79.             local player_stats = string.format("ID#: %s --   %s --  KILLS: %s --   HEADSHOTS: %s", id, name, kills, headshots)
  80.             if (LOG_RESULTS == true) then
  81.                 execute_command("log_note \""..player_stats.."\"")
  82.             end
  83.             head_shot[i] = false
  84.             headshot_count[i] = 0  
  85.         end
  86.     end    
  87. end
  88.  
  89. function OnPlayerJoin(PlayerIndex)
  90.     if player_present(PlayerIndex) then
  91.         head_shot[PlayerIndex] = false
  92.         headshot_count[PlayerIndex] = 0
  93.     end
  94. end
  95.  
  96. function OnPlayerLeave(PlayerIndex)
  97.     head_shot[PlayerIndex] = nil
  98.     headshot_count[PlayerIndex] = nil
  99. end
  100.  
  101. function OnDamageApplication(PlayerIndex, CauserIndex, MetaID, Damage, HitString, Backtap)
  102.     if player_present(PlayerIndex) then
  103.         if (CauserIndex ~= nil) then
  104.             local CausesHeadShot = OnDamageLookup(PlayerIndex, CauserIndex)
  105.             if (CausesHeadShot ~= nil) then
  106.                 if (HitString == "head") then
  107.                     head_shot[PlayerIndex] = true
  108.                 else
  109.                     head_shot[PlayerIndex] = false
  110.                 end
  111.             else
  112.                 head_shot[PlayerIndex] = false
  113.             end
  114.         end    
  115.     end
  116. end
  117.  
  118. function OnDamageLookup(ReceiverIndex, CauserIndex)
  119.     local response = nil
  120.     if get_var(0, "$gt") ~= "n/a" then
  121.         if (CauserIndex and ReceiverIndex ~= CauserIndex) then
  122.             if (CauserIndex ~= 0) then
  123.                 local r_team = read_word(get_player(ReceiverIndex) + 0x20)
  124.                 local c_team = read_word(get_player(CauserIndex) + 0x20)
  125.                 if (r_team ~= c_team) then
  126.                     local tag_address = read_dword(0x40440000)
  127.                     local tag_count = read_word(0x4044000C)
  128.                     for A=0,tag_count-1 do
  129.                         local tag_id = tag_address + A * 0x20
  130.                         if (read_dword(tag_id) == 1785754657) then
  131.                             local tag_data = read_dword(tag_id + 0x14)
  132.                             if (tag_data ~= nil) then  
  133.                                 if (read_word(tag_data + 0x1C6) == 5) or (read_word(tag_data + 0x1C6) == 6) then -- damage category: bullets
  134.                                     if (read_bit(tag_data + 0x1C8, 1) == 1) then -- damage effect: can cause head shots
  135.                                         response = true
  136.                                     else
  137.                                         response = false
  138.                                     end
  139.                                 end                
  140.                             end
  141.                         end
  142.                     end                                
  143.                 end
  144.             else
  145.                 response = false               
  146.             end
  147.         end
  148.     end
  149.     return response
  150. end
  151.  
  152. function OnPlayerDie(PlayerIndex, KillerIndex)
  153.     if (game_started == true) then
  154.         local killer = tonumber(KillerIndex)
  155.         if (killer > 0) then -- killer is another player       
  156.             local vname = get_var(PlayerIndex, "$name")
  157.             local kname = get_var(KillerIndex,"$name")
  158.             local ktype = string.upper(generatekill(killtype))
  159.             if headshot_count[KillerIndex] == nil then headshot_count[KillerIndex] = 0 end
  160.             if (PlayerIndex ~= killer) then
  161.                 if (get_var(KillerIndex, "$team") ~= get_var(PlayerIndex, "$team")) then
  162.                     if (head_shot[PlayerIndex] == true) then
  163.                         headshot_count[killer] = headshot_count[killer] + 1
  164.                         local count = headshot_count[killer]
  165.                         if (kname ~= nil) then
  166.                             if (ktype~= nil) then
  167.                                 say_all("BOOM!  " ..kname .. "  " .. ktype .. "  " .. vname .. " with a HEAD-SHOT! (" .. count .. ")")
  168.                             else
  169.                                 say_all("BOOM! " ..kname .. " NAILED " .. vname .. " with a HEAD-SHOT! (" .. count .. ")")
  170.                             end
  171.                         else
  172.                             say_all("BOOM! " ..vname .. " was  GUTTED  by a 'random' HEAD-SHOT!") -- killer unknown, such as killer left server, or error
  173.                         end
  174.                     end
  175.                 end
  176.             end
  177.             head_shot[PlayerIndex] = false
  178.         end
  179.     end
  180. end
  181.  
  182. function OnPlayerChat(PlayerIndex, Message)
  183.     local response = nil
  184.     if Message == nil then
  185.         return true
  186.     end
  187.     local name = get_var(PlayerIndex,"$name")
  188.     local Message = string.lower(Message)
  189.     local isadmin = nil
  190.     if (tonumber(get_var(PlayerIndex,"$lvl"))) >= ADMIN_LEVEL then isadmin = true else isadmin = false end
  191.     if Message ~= nil then
  192.    
  193.         if (Message == "/ss") then
  194.             if (isadmin == true) then
  195.                 local data1 = string.format("%s used the showstats (/ss) command. ", tostring(name))
  196.                 if (LOG_RESULTS == true) then
  197.                     execute_command("log_note \""..data1.."\"")
  198.                 end
  199.                 ShowStats(PlayerIndex) 
  200.                 response = false
  201.             else
  202.                 local data2 = string.format("%s attempted to use the showstats (/ss) command. ", tostring(name))
  203.                 if (LOG_RESULTS == true) then
  204.                     execute_command("log_note \""..data2.."\"")
  205.                 end                
  206.                 say(PlayerIndex, "You are not allowed to use this command, or you must log in first.")
  207.                 response = true
  208.             end
  209.         end
  210.        
  211.     end
  212.     return response
  213. end    
  214.  
  215. function ShowStats(PlayerIndex)
  216.     for j=1,30 do
  217.         rprint(PlayerIndex," ")
  218.     end
  219.     for i = 1,16 do
  220.         if player_present(i) then
  221.             local id = get_var(i, "$n")
  222.             if headshot_count[i] == nil then headshot_count[i] = 0 end
  223.             local headshots = headshot_count[i]
  224.             local name = get_var(i, "$name")
  225.             local kills = tonumber(get_var(i, "$kills"))
  226.             if kills == nil then kills = 0 end
  227.             local player_stats = string.format("ID#: %s --   %s --  KILLS: %s --   HEADSHOTS: %s", id, name, kills, headshots)
  228.             rprint(PlayerIndex, player_stats)
  229.             if (LOG_RESULTS == true) then
  230.                 execute_command("log_note \""..player_stats.."\"")
  231.             end
  232.         end    
  233.     end    
  234. end
  235.  
  236. function OnCommand(PlayerIndex,Command,Environment,Password)
  237.     Command = string.lower(Command)
  238.     -- if chat command, i.e. chat: /reset
  239.     if (Environment == 2) then
  240.         if (Command == RESET_COMMAND) or (Command == "/reset") or (Command == "reset") then
  241.             if (tonumber(get_var(PlayerIndex, "$lvl")) >= ADMIN_LEVEL) then
  242.                 for i = 1, 16 do
  243.                     if player_present(i) then
  244.                         head_shot[i] = false
  245.                         headshot_count[i] = 0      
  246.                     end
  247.                 end
  248.                 execute_command("sv_map_reset")
  249.                 return false
  250.             end
  251.         end
  252.     -- if console or rcon  
  253.     elseif (Environment == 0) or (Environment == 1) then
  254.         if (Command == "sv_map_reset") or (Command == RESET_COMMAND) then
  255.             for i = 1, 16 do
  256.                 if player_present(i) then
  257.                     head_shot[i] = false
  258.                     headshot_count[i] = 0      
  259.                 end
  260.             end
  261.             execute_command("sv_map_reset")    
  262.             return true
  263.         end
  264.     end
  265.     return true
  266. end
  267.  
  268. function generatekill(killtype)
  269.     local killtype = {"destroyed", "fubbared", "disemboweled", "violated", "eviscerated", "assassinated", "slaughtered", "exterminated", "murdered", "eradicated", "executed", "snuffed", "eliminated", "liquidated"}
  270.     local killcount = #killtype
  271.     local rand_type = rand(1, killcount+1)
  272.     local kill_type = string.format("%s",  killtype[rand_type])
  273.     if (kill_type ~= nil) then
  274.         return kill_type
  275.     else
  276.         return "killed"
  277.     end
  278. end
  279.  
  280. function OnError(Message)
  281.     print(debug.traceback())
  282. end
  283.    
  284. -- Created by H® Shaft
  285. -- Visit http://halorace.org/forum/index.php
  286.  
  287. -- The player -db-GoNe/Juhleek - a well spoken liar, cheat.
  288. -- -db- is: "diverging from the believable" - How ironic. A race clan where admins use rcon to favor themselves to win.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement