Advertisement
Guest User

shotlog samp 21112019-01

a guest
Nov 21st, 2019
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.05 KB | None | 0 0
  1. local events = require 'lib.samp.events'
  2.  
  3. local settings = {
  4. max_lines = 30,
  5. fake_afk = false,
  6. remove_on_quit = false
  7. }
  8.  
  9. function create_empty_item()
  10. return {
  11. shots = 0,
  12. hits = 0,
  13. accuracy = 0,
  14. last = 0,
  15. nick = '',
  16. lines = {}
  17. }
  18. end
  19.  
  20. function get_speed_safely(id)
  21. if id == select(2, sampGetPlayerIdByCharHandle(1)) then return math.floor(getCharSpeed(1) * 3) end
  22. local res, ped = sampGetCharHandleBySampPlayerId(id)
  23. if not res then return 'UNK' else
  24. return math.floor(getCharSpeed(ped) * 3) end
  25. end
  26.  
  27. function get_vspeed_safely(id)
  28. local res, car = sampGetCarHandleBySampVehicleId(id)
  29. if not res then return 'UNK' else
  30. return math.floor(getCarSpeed(car) * 3) end
  31. end
  32.  
  33. function get_vehicle_model(id)
  34. local res, car = sampGetCarHandleBySampVehicleId(id)
  35. if res then return getNameOfVehicleModel(getCarModel(car)) else return 'UNK ' .. tostring(id) end
  36. end
  37.  
  38. function get_weapon_name(id)
  39. local weapons = {
  40. [22] = 'glock',
  41. [23] = 's glock',
  42. [24] = 'deagle',
  43. [25] = 'shotgun',
  44. [26] = 'sawn',
  45. [27] = 'spac12',
  46. [28] = 'uzi',
  47. [29] = 'mp5',
  48. [30] = 'ak47',
  49. [31] = 'm4',
  50. [32] = 'tec9',
  51. [33] = 'rifle',
  52. [34] = 'sniper',
  53. [38] = 'minigun'
  54. }
  55. return weapons[id] or 'UNK ' .. tostring(id)
  56. end
  57.  
  58. local pool = {}
  59.  
  60. local spectate, spectate_ped, spectate_id = false, 1, 0
  61.  
  62. function events.onSendBulletSync(data)
  63. process_bullet_sync(select(2, sampGetPlayerIdByCharHandle(1)), data)
  64. end
  65.  
  66. function events.onBulletSync(id, data)
  67. process_bullet_sync(id, data)
  68. end
  69.  
  70. function events.onPlayerQuit(id)
  71. if settings.remove_on_quit and pool[id] then
  72. pool[id] = nil
  73. end
  74. if spectate and id == spectate_id then
  75. restoreCamera()
  76. spectate = false
  77. sampAddChatMessage('Игрок недоступен, режим наблюдения выключен.', 0xAFAFAF)
  78. end
  79. end
  80.  
  81. function process_bullet_sync(id, data)
  82. if not pool[id] or pool[id].nick ~= sampGetPlayerNickname(id) then pool[id] = create_empty_item() end
  83.  
  84. local O, T = data.origin, data.target
  85. local distance = math.sqrt((O.x - T.x) ^ 2 + (O.y - T.y) ^ 2 + (O.z - T.z) ^ 2)
  86. local dist_text = ''
  87. if data.targetType == 1 or data.targetType == 2 then dist_text = ', ' .. math.floor(distance) .. 'm' end
  88.  
  89. local hit_name = 'ПРОМАХ'
  90. if data.targetType == 1 then hit_name = sampGetPlayerNickname(data.targetId) end
  91. if data.targetType == 2 then hit_name = get_vehicle_model(data.targetId) end
  92.  
  93. local speed_vs = ''
  94. if data.targetType == 1 then speed_vs = ', ' .. get_speed_safely(id) .. ' vs ' .. get_speed_safely(data.targetId) end
  95. if data.targetType == 2 then speed_vs = ', ' .. get_speed_safely(id) .. ' vs ' .. get_vspeed_safely(data.targetId) end
  96.  
  97. local time_since = os.clock() - pool[id].last
  98. if time_since > 5 and pool[id].shots > 0 then pool[id].lines[#pool[id].lines + 1] = '' end
  99. if time_since > 1 then time_since = 'ok' else time_since = math.floor(1000 * time_since) .. 'ms' end
  100.  
  101. pool[id].nick = sampGetPlayerNickname(id)
  102. pool[id].last = os.clock()
  103. pool[id].shots = pool[id].shots + 1
  104. if data.targetType == 1 or data.targetType == 2 then pool[id].hits = pool[id].hits + 1 end
  105. pool[id].accuracy = math.floor(100 * pool[id].hits / pool[id].shots)
  106.  
  107. local warning = ''
  108. if data.targetType == 1 and not isLineOfSightClear(O.x, O.y, O.z, T.x, T.y, T.z, true, false, false, true, true) then
  109. warning = ' {CCAA00}(стрельба сквозь текстуры){ABCDEF}'
  110. end
  111.  
  112. local line = string.format('%s > %s%s, %s%s > %s%s',
  113. pool[id].nick, get_weapon_name(data.weaponId), dist_text, time_since, speed_vs, hit_name, warning)
  114. pool[id].lines[#pool[id].lines + 1] = '[' .. os.date('%H:%M:%S') .. '] ' .. line
  115. if spectate and spectate_id == id then sampAddChatMessage('{6495ED}[SHOT] {FFFFFF}' .. line, -1) end
  116. end
  117.  
  118. function onSendPacket(id)
  119. if settings.fake_afk and (id == 200 or id == 207 or id == 211) then
  120. if sampIsDialogActive() then
  121. local did = sampGetCurrentDialogId()
  122. if did == 5555 or did == 5556 then return false end
  123. end
  124. end
  125. end
  126.  
  127. function get_color(id)
  128. return sampIsPlayerConnected(id) and ('%x'):format(sampGetPlayerColor(id)):sub(3) or '{abcdef}'
  129. end
  130.  
  131. local pids = {}
  132. function show_list()
  133. -- ### I know this is fucked up
  134. pids = {}
  135. local output = ''
  136. local sorted = {}
  137. local sorted_len = 0
  138. local pool_len = 0
  139. for i = 0, 999 do if pool[i] then pool_len = pool_len + 1 end end
  140. if pool_len == 0 then return sampAddChatMessage('В статистике стрельбы нет ни одной записи.', 0xAFAFAF) end
  141. while sorted_len ~= pool_len do
  142. local highest = -1
  143. local max = 0
  144. for i = 0, 999 do
  145. if pool[i] and not sorted[i] then
  146. if pool[i].accuracy >= max then
  147. max = pool[i].accuracy
  148. highest = i
  149. end
  150. end
  151. end
  152. sorted[highest] = true
  153. sorted_len = sorted_len + 1
  154. local off = off_mark(highest)
  155. output = output .. pool[highest].nick .. ' [ID ' .. highest .. ']' .. off .. '\t' ..
  156. pool[highest].hits .. '/' .. pool[highest].shots .. ' (' .. pool[highest].accuracy .. '%)\n'
  157. pids[#pids+1] = highest
  158. end
  159. sampShowDialog(5556, 'Статистика стрельбы', output, '>>', 'X', 4)
  160. end
  161.  
  162. local arrow_shown = false
  163. function show_stats(id, arrow)
  164. arrow_shown = arrow or false
  165. local off = off_mark(id)
  166. local output = '{ABCDEF}Статистика попаданий: ' .. pool[id].hits .. '/' .. pool[id].shots .. ' (' .. pool[id].accuracy .. '%)\n'
  167. local start = #pool[id].lines > settings.max_lines and #pool[id].lines - settings.max_lines or 1
  168. for i = start, #pool[id].lines do
  169. output = output .. '\n' .. pool[id].lines[i]
  170. end
  171. if arrow then
  172. sampShowDialog(5555, 'Лог выстрелов ' .. pool[id].nick .. ' [ID ' .. id .. ']' .. off, output, '<<', 'X')
  173. else
  174. sampShowDialog(5555, 'Лог выстрелов ' .. pool[id].nick .. ' [ID ' .. id .. ']' .. off, output, 'X')
  175. end
  176. end
  177.  
  178. function off_mark(id)
  179. if id == select(2, sampGetPlayerIdByCharHandle(1)) then return '' end
  180. if not sampIsPlayerConnected(id) or pool[id].nick ~= sampGetPlayerNickname(id) then return ' {AA0000}OFF{FFFFFF}'
  181. else return '' end
  182. end
  183.  
  184. local waiting = false
  185.  
  186. function events.onPlayerStreamIn(id)
  187. if spectate and id == spectate_id then
  188. lua_thread.create(function ()
  189. wait(1)
  190. waiting = false
  191. setCameraInFrontOfChar(select(2, sampGetCharHandleBySampPlayerId(id)))
  192. end)
  193. end
  194. end
  195.  
  196. function events.onPlayerStreamOut(id)
  197. if spectate and id == spectate_id then
  198. restoreCamera()
  199. waiting = true
  200. lua_thread.create(function ()
  201. wait(3000)
  202. if waiting then
  203. spectate = false
  204. sampAddChatMessage('Игрок недоступен, режим наблюдения выключен.', 0xAFAFAF)
  205. end
  206. end)
  207. end
  208. end
  209.  
  210. function main()
  211. while not isSampAvailable() do wait(100) end
  212. sampRegisterChatCommand('shotlog', function (id)
  213. if id == '' then return show_list() end
  214. id = tonumber(id)
  215. if not id then return sampAddChatMessage('Подсказка: /shotlog [ID]', 0xAFAFAF) end
  216. if not pool[id] then return sampAddChatMessage('Лог выстрелов указанного игрока пуст.', 0xAFAFAF) end
  217. show_stats(id)
  218. end)
  219. sampRegisterChatCommand('spec', function (id)
  220. if spectate then
  221. spectate = false
  222. restoreCamera()
  223. return sampAddChatMessage('Режим наблюдения выключен.', 0xAFAFAF)
  224. end
  225. id = tonumber(id)
  226. if not id then return sampAddChatMessage('Подсказка: /spec [ID]', 0xAFAFAF) end
  227. local res, ped = sampGetCharHandleBySampPlayerId(id)
  228. if not res then return sampAddChatMessage('Указанного игрока нет в зоне стрима.', 0xAFAFAF) end
  229. setCameraInFrontOfChar(ped)
  230. spectate = true
  231. spectate_ped = ped
  232. spectate_id = id
  233. sampAddChatMessage('Режим наблюдения включен.', 0xAFAFAF)
  234. end)
  235. while true do
  236. wait(1)
  237. local res, btn, item = sampHasDialogRespond(5556)
  238. if res and btn == 1 then show_stats(pids[item + 1], true) end
  239. local res2, btn2 = sampHasDialogRespond(5555)
  240. if res2 and arrow_shown and btn2 == 1 then show_list() end
  241. end
  242. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement