Advertisement
HR_Shaft

Sapp/Phasor Compatibility Failure - useful but broken

Apr 3rd, 2015
481
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 71.38 KB | None | 0 0
  1. -- ============ THIS WAS AN ATTEMPT THAT FAILED - SCRIPT DOES NOT WORK - BUT CONTAINS VALUABLE SCRIPTING ELEMENTS =============
  2.  
  3. -- Sapp and Phasor Compatibility Module
  4. -- Created by Wizard
  5. -- Add this line to the end of your script to use this module:
  6. -- _G = require"thefilenameofthisscript"
  7.  
  8. --[[
  9. How to install this module:
  10. Download the script, find your server directory, and put it in the lua folder. If your server does not have a 'lua' folder,
  11. then just create it manually.
  12.  
  13. How to use:
  14. Using this script is easy, simply add this line to the BOTTOM of your script:
  15. _G = require"thefilenameofthisscript"  -- whatever you name this script, should refer to this file name.
  16. ]]
  17.  
  18. local sapp_version = "1.7.0.0"
  19. local phasor_version = 200
  20.  
  21. _SERVERAPP = cb and say_all and "Sapp" or getrandomnumber and isinvehicle and "Phasor" --or error("Dafuq? What server app are you using?") -- easiest way
  22. _GAME = _SERVERAPP == "Sapp" and halo_type or readbyte and readbyte(0x630E78) == 7 and "PC" or "CE" -- skillz
  23. local _G = _G -- so the main script can't change this.
  24.  
  25. -- Localized functions.
  26. local random, abs = math.random, abs
  27. local type = type
  28. local clock, time = os.clock, os.time
  29. local concat = table.concat
  30. local gmatch, char, byte, match, find, format, lower, sub, gsub = string.gmatch, string.char, string.byte, string.match, string.find, string.format, string.lower, string.sub, string.gsub
  31. local orig_xpcall = xpcall
  32. local real_register_callback = register_callback
  33.  
  34. -- Lua Version Compatibility Definitions.
  35. bit = not bit32 and require"bit" or bit32
  36. bit32 = bit32 or bit
  37. getfenv = getfenv or function(f)
  38.     f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
  39.     local name, val
  40.     local up = 0
  41.     repeat
  42.         up = up + 1
  43.         name, val = debug.getupvalue(f, up)
  44.     until name == '_ENV' or name == nil
  45.     return val
  46. end
  47. math.atan = math.atan or math.atan2
  48. math.atan2 = math.atan2 or math.atan
  49. math.ldexp = math.ldexp or function(x, exp) return x * 2.0^exp end
  50. math.log10 = math.log10 or function(num) return math.log(num, 10) end
  51. package.loaders = package.loaders or package.searchers
  52. package.searchers = package.loaders
  53. load = load or loadstring
  54. loadstring = loadstring or load
  55. table.maxn = table.maxn or (
  56.     function(t)
  57.         local maxval = 0
  58.         for key,value in next,t do
  59.             if type(key) == "number" and key > maxval then
  60.                 maxval = key
  61.             end
  62.         end
  63.         return maxval
  64.     end
  65. )
  66. setfenv = setfenv or function(f, t)
  67.     f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
  68.     local name
  69.     local up = 0
  70.     repeat
  71.         up = up + 1
  72.         name = debug.getupvalue(f, up)
  73.     until name == '_ENV' or name == nil
  74.     if name then
  75.         debug.upvaluejoin(f, up, function() return name end, 1) -- use unique upvalue
  76.         debug.setupvalue (f, up, t)
  77.     end
  78. end
  79. table.getn = table.getn or function(t) return rawlen(t) end
  80. table.unpack = table.unpack or unpack
  81. unpack = unpack or table.unpack
  82. xpcall = _SERVERAPP == "Sapp" and function(f, msgh, ...) local args = {...} return orig_xpcall(function() f(unpack(args)) end, msgh) end or xpcall
  83.  
  84. local function WriteLog(filename, logStr)
  85.     local file = assert(io.open(filename, "a"))
  86.     file:write(string.format("%s\t%s\n", os.date "%Y/%m/%d %H:%M:%S", logStr))
  87.     file:close()
  88. end
  89.  
  90. local function ypcall(func, ...)
  91.     if type(func) ~= "function" then
  92.         return nil
  93.     end
  94.    
  95.     local success,result1,result2 = xpcall(func, function(err) print(debug.traceback(err)) end, ...)
  96.     if success == false and type(result1) == "string" then
  97.         local err = "Error in " .. result1
  98.         WriteLog(getprofilepath() .. "\\logs\\ScriptLogs.log", err)
  99.         hprintf(err)
  100.         pcall(OnError, result1)
  101.     end
  102.     return result1, result2
  103. end
  104.  
  105. -- Private variables.
  106. local prevent_join = {}
  107. local player_scores = {}
  108. local timers = {}
  109. local svcmd_echo
  110. local dont_doublecall_onvehicleeject
  111. local dont_doublecall_onvehicleentry
  112. local script_loaded_midgame
  113.  
  114. cb = cb or {
  115.     EVENT_TICK = 1,
  116.     EVENT_ALIVE = 2,
  117.     EVENT_AREA_ENTER = 3,
  118.     EVENT_AREA_EXIT = 4,
  119.     EVENT_PRESPAWN = 5,
  120.     EVENT_SPAWN = 6,
  121.     EVENT_KILL = 7,
  122.     EVENT_DIE = 8,
  123.     EVENT_SNAP = 9,
  124.     EVENT_WARP = 10,
  125.     EVENT_WEAPON_PICKUP = 11,
  126.     EVENT_WEAPON_DROP = 12,
  127.     EVENT_VEHICLE_ENTER = 13,
  128.     EVENT_VEHICLE_EXIT = 14,
  129.     EVENT_BETRAY = 15,
  130.     EVENT_SUICIDE = 16,
  131.     EVENT_SCORE = 17,
  132.     EVENT_TEAM_SWITCH = 18,
  133.     EVENT_JOIN = 19,
  134.     EVENT_LEAVE = 20,
  135.     EVENT_CAMP = 21,
  136.     EVENT_LOGIN = 22,
  137.     EVENT_GAME_START = 23,
  138.     EVENT_GAME_END = 24,
  139.     EVENT_CHAT = 25,
  140.     EVENT_COMMAND = 26,
  141.     EVENT_ECHO = 27,
  142.     EVENT_OBJECT_SPAWN = 28,
  143. }
  144.  
  145. local phasorEvents = {
  146.     OnScriptLoad = OnScriptLoad or true,
  147.     OnNewGame = OnNewGame or true,
  148.     OnGameEnd = OnGameEnd or true,
  149.     OnServerChat = OnServerChat or true,
  150.     OnServerCommandAttempt = OnServerCommandAttempt or true,
  151.     OnServerCommand = OnServerCommand or true,
  152.     OnNameRequest = OnNameRequest or true,
  153.     OnBanCheck = OnBanCheck or true,
  154.     OnPlayerJoin = OnPlayerJoin or true,
  155.     OnPlayerLeave = OnPlayerLeave or true,
  156.     OnPlayerKill = OnPlayerKill or true,
  157.     OnKillMultiplier = OnKillMultiplier or true,
  158.     OnPlayerSpawn = OnPlayerSpawn or true,
  159.     OnPlayerSpawnEnd = OnPlayerSpawnEnd or true,
  160.     OnWeaponAssignment = OnWeaponAssignment or true,
  161.     OnWeaponReload = OnWeaponReload or true,
  162.     OnObjectCreationAttempt = OnObjectCreationAttempt or true,
  163.     OnObjectCreation = OnObjectCreation or true,
  164.     OnObjectInteraction = OnObjectInteraction or true,
  165.     OnTeamDecision = OnTeamDecision or true,
  166.     OnTeamChange = OnTeamChange or true,
  167.     OnDamageLookup = OnDamageLookup or true,
  168.     OnDamageApplication = OnDamageApplication or true,
  169.     OnVehicleEntry = OnVehicleEntry or true,
  170.     OnVehicleEject = OnVehicleEject or true,
  171. }
  172.  
  173. local events
  174. events = {
  175.    
  176.     [cb.EVENT_TICK] = {
  177.         register = function(funcname)
  178.             if _SERVERAPP == "Phasor" then
  179.                 -- This won't work if you want to literally use it for like checking if someone is crouched (actually, it might depending on how Phasor timers work), but should imitate the behavior well enough
  180.                 local tick_id = registertimer(33, "__tick_event")
  181.                 function __tick_event(id)
  182.                     if tick_id ~= id then return false end
  183.                     ypcall(_G[funcname])
  184.                     return true
  185.                 end
  186.             else
  187.                 function __clientupdate_event()
  188.                     local playerId, playerObjId, m_playerObj, weaponObjId, m_weaponObj, weapstate
  189.                     for playerIndex = 1,16 do
  190.                         playerId = to_real_index(playerIndex)
  191.                         if playerId == -1 then goto continue end
  192.                        
  193.                         playerObjId = getplayerobjectid(playerId)
  194.                         m_playerObj = get_object_memory(playerObjId)
  195.                         if m_playerObj == 0 then goto continue end
  196.                        
  197.                         if OnClientUpdate then OnClientUpdate(playerId, playerObjId) end
  198.                         if not OnWeaponReload then goto continue end
  199.                        
  200.                         weaponObjId = read_dword(m_playerObj + 0x118)
  201.                         m_weaponObj = get_object_memory(weaponObjId)
  202.                         if m_weaponObj == 0 then goto continue end
  203.                        
  204.                         weapstate = read_byte(m_weaponObj + 0x238)
  205.                         if weapstate == 5 or weapstate == 6 then
  206.                             OnWeaponReload(playerId, weaponObjId) -- Not possible to block this yet.
  207.                         end
  208.                        
  209.                         ::continue::
  210.                     end
  211.                     ypcall(_G[funcname])
  212.                 end
  213.                 real_register_callback(cb.EVENT_TICK, "__clientupdate_event")
  214.             end
  215.         end
  216.     },
  217.     [cb.EVENT_ALIVE] = {
  218.         register = function(funcname)
  219.             if _SERVERAPP == "Phasor" then
  220.                 local __alive_id = registertimer(1000, "__alivetimer")
  221.                 function __alivetimer(id)
  222.                     if __alive_id ~= id then return false end
  223.                     for playerId = 0,15 do
  224.                         if getplayer(playerId) and getobject(getplayerobjectid(playerId)) then
  225.                             ypcall(_G[funcname], playerIndex)
  226.                         end
  227.                     end
  228.                     return true
  229.                 end
  230.             else
  231.                 real_register_callback(cb.EVENT_ALIVE, funcname)
  232.             end
  233.         end,
  234.     },
  235.     [cb.EVENT_AREA_ENTER] = {
  236.         register = function(funcname)
  237.             if _SERVERAPP == "Phasor" then
  238.                 events[cb.EVENT_AREA_ENTER][1] = funcname
  239.             else
  240.                 real_register_callback(cb.EVENT_AREA_ENTER, funcname)
  241.             end
  242.         end
  243.     },
  244.     [cb.EVENT_AREA_EXIT] = {
  245.         register = function(funcname)
  246.             if _SERVERAPP == "Phasor" then
  247.                 events[cb.EVENT_AREA_EXIT][1] = funcname
  248.             else
  249.                 real_register_callback(cb.EVENT_AREA_EXIT, funcname)
  250.             end
  251.         end
  252.     },
  253.     [cb.EVENT_PRESPAWN] = {
  254.         register = function(funcname)
  255.             if _SERVERAPP == "Phasor" then
  256.                 function OnPlayerSpawn(playerId, playerObjId)
  257.                     playerObjId = playerObjId or getplayerobjectid(playerId)
  258.                     if __orig_spawn_event then __orig_spawn_event(playerId, playerObjId) end
  259.                     local playerIndex = resolveplayer(playerId)
  260.                     if events[cb.EVENT_WEAPON_PICKUP][1] then
  261.                         local m_playerObj = getobject(playerObjId)
  262.                         for slot = 0,3 do
  263.                             if getobject(readdword(m_playerObj + 0x2F8+slot*4)) then
  264.                                 ypcall(_G[events[cb.EVENT_WEAPON_PICKUP][1]], playerIndex, slot+1, 1)
  265.                             end
  266.                         end
  267.                     end
  268.                     ypcall(_G[funcname], playerIndex)
  269.                 end
  270.             else
  271.                 function __onspawn_event(playerIndex)
  272.                     if prevent_join[playerIndex] then
  273.                         return nil
  274.                     end
  275.                     local playerId = to_real_index(playerIndex)
  276.                     local playerObjId = getplayerobjectid(playerId)
  277.                     ypcall(phasorEvents.OnPlayerSpawn, playerId, playerObjId)
  278.                     if phasorEvents.OnWeaponAssignment then
  279.                         local m_playerObj = get_object_memory(playerObjId)
  280.                         local m_weaponObj, mapId, result, weaponObjId
  281.                         for slot = 0,3 do
  282.                             weaponObjId = read_dword(m_playerObj + 0x2F8 + slot*4)
  283.                             m_weaponObj = get_object_memory(weaponObjId)
  284.                             mapId = m_weaponObj and read_dword(m_weaponObj)
  285.                             if mapId then
  286.                                 result = ypcall(phasorEvents.OnWeaponAssignment, playerId, playerObjId, slot, mapId)
  287.                                 if result == false then
  288.                                     destroy_object(weaponObjId)
  289.                                 elseif tonumber(result) then
  290.                                     destroy_object(weaponObjId)
  291.                                     assign_weapon(playerIndex, spawn_object("", "", 1, 2, 3, 0, tonumber(result)))
  292.                                 end
  293.                             end
  294.                         end
  295.                     end
  296.                 end
  297.                 real_register_callback(cb.EVENT_PRESPAWN, "__onspawn_event")
  298.             end
  299.         end,
  300.     },
  301.     [cb.EVENT_SPAWN] = {
  302.         register = function(funcname)
  303.             if _SERVERAPP == "Phasor" then
  304.                 function OnPlayerSpawnEnd(playerId, playerObjId)
  305.                     ypcall(phasorEvents.OnPlayerSpawnEnd, playerId, playerObjId)
  306.                     ypcall(_G[funcname], resolveplayer(playerId))
  307.                 end
  308.             else
  309.                 function __onspawnend_event(playerIndex)
  310.                     if prevent_join[playerIndex] then
  311.                         return nil
  312.                     end
  313.                     local playerId = to_real_index(playerIndex)
  314.                     ypcall(phasorEvents.OnPlayerSpawnEnd, playerId, getplayerobjectid(playerId))
  315.                     ypcall(_G[funcname], playerIndex)
  316.                 end
  317.                 real_register_callback(cb.EVENT_SPAWN, "__onspawnend_event")
  318.             end
  319.         end
  320.     },
  321.     [cb.EVENT_KILL] = {
  322.         dependencies = {cb.EVENT_DIE},
  323.         register = function(funcname)
  324.             if _SERVERAPP == "Phasor" then
  325.                 events[cb.EVENT_KILL][1] = funcname
  326.             else
  327.                 real_register_callback(cb.EVENT_KILL, funcname)
  328.             end
  329.         end,
  330.     },
  331.     [cb.EVENT_DIE] = {
  332.         register = function(funcname)
  333.             if _SERVERAPP == "Phasor" then
  334.                 function OnPlayerKill(killerPlayerId, victimPlayerId, mode)
  335.                     ypcall(phasorEvents.OnPlayerKill, killerPlayerId, victimPlayerId, mode)
  336.                     local killerPlayerIndex, victimPlayerIndex = killerPlayerId and resolveplayer(killerPlayerId), resolveplayer(victimPlayerId)
  337.                     if mode == 5 then
  338.                         ypcall(_G[events[cb.EVENT_BETRAY][1]], killerPlayerIndex, victimPlayerIndex)
  339.                     elseif mode == 6 then
  340.                         ypcall(_G[events[cb.EVENT_SUICIDE][1]], victimPlayerIndex)
  341.                     end
  342.  
  343.                     ypcall(_G[events[cb.EVENT_DIE][1]], victimPlayerIndex)
  344.                     if killerPlayerId then
  345.                         ypcall(_G[events[cb.EVENT_KILL][1]], killerPlayerId, victimPlayerId)
  346.                     end
  347.                 end
  348.             else
  349.                 -- Broken: Falling kill vs server kill.
  350.                 function __kill_event(victim, killer)
  351.                     if prevent_join[playerIndex] then
  352.                         return nil
  353.                     end
  354.                     local mode
  355.                     local kteam, vteam
  356.                     local victimPlayerId = to_real_index(victim) -- should always be valid
  357.                     local killerPlayerId = to_real_index(killer)
  358.                     killerPlayerId = killerPlayerId ~= -1 and killerPlayerId or nil
  359.                     if killer == "-1" then
  360.                         mode = 1 -- Server kill OR FALL DAMAGE since that's broken
  361.                     elseif killer == "guardians" then
  362.                         mode = 2 -- Guardian kill
  363.                     elseif killer == 0 then
  364.                         mode = 3 -- Killed by a vehicle
  365.                     else
  366.                         goto finishRemaining
  367.                     end
  368.  
  369.                     goto OnPlayerKillCall
  370.                    
  371.                     ::finishRemaining::
  372.                     kteam = killerPlayerId and getteam(killerPlayerId)
  373.                     vteam = getteam(victimPlayerId)
  374.                     if victimPlayerId == killerPlayerId then
  375.                         mode = 6 -- Suicide
  376.                     elseif victimPlayerId ~= killerPlayerId and vteam ~= kteam then
  377.                         mode = 4 -- Killed by another player.
  378.                         if OnKillMultiplier then
  379.                             local multiplier = 0
  380.                             local m_kplayer = get_player(killer)
  381.                             local multikill = read_word(m_kplayer + 0x98)
  382.                             local spree = read_word(m_kplayer + 0x96)
  383.                             if multikill == 2 or multikill == 16 then
  384.                                 multiplier = 7 -- Double Kill.
  385.                             elseif multikill == 3 or multikill == 15 then
  386.                                 multiplier = 9 -- Triple Kill.
  387.                             elseif spree == 5 then
  388.                                 multiplier = 11 -- Killing Spree.
  389.                             elseif spree == 10 or (spree ~= 0 and spree % 5 == 0) then
  390.                                 multiplier = 12 -- Running Riot.
  391.                             elseif multikill >= 4 then
  392.                                 multiplier = 10 -- Killtacular.
  393.                             else
  394.                                 goto OnPlayerKillCall
  395.                             end
  396.                             OnKillMultiplier(killerPlayerId, multiplier)
  397.                         end
  398.                     elseif victimPlayerId ~= killerPlayerId and vteam == kteam then
  399.                         mode = 5 -- Betrayed
  400.                     end
  401.                    
  402.                     ::OnPlayerKillCall::
  403.                     if ypcall(phasorEvents.OnPlayerKill, killerPlayerId, victimPlayerId, mode) == false then
  404.                         -- thanks 002 for the silent kill code
  405.                         local m_player = get_player(victim)
  406.                         timer(0, "__ResetPlayerKill", m_player, read_word(m_player + 0xD4))
  407.                         write_word(m_player + 0xD4, 0xFFFF)
  408.                     end
  409.                     ypcall(_G[funcname], victim, killer)
  410.                 end
  411.                 function __ResetPlayerKill(m_player, old_value)
  412.                     write_word(m_player + 0xD4, old_value)
  413.                     return false
  414.                 end
  415.                 real_register_callback(cb.EVENT_DIE, "__kill_event")
  416.             end
  417.         end
  418.     },
  419.     [cb.EVENT_SNAP] = {
  420.         register = function(funcname)
  421.             if _SERVERAPP == "Phasor" then
  422.                 events[cb.EVENT_SNAP][1] = funcname
  423.             else
  424.                 real_register_callback(cb.EVENT_SNAP, funcname)
  425.             end
  426.         end
  427.     },
  428.     [cb.EVENT_WARP] = {
  429.         register = function(funcname)
  430.             if _SERVERAPP == "Phasor" then
  431.                 events[cb.EVENT_WARP][1] = funcname
  432.             else
  433.                 real_register_callback(cb.EVENT_WARP, funcname)
  434.             end
  435.         end
  436.     },
  437.     [cb.EVENT_WEAPON_PICKUP] = {
  438.         dependencies = {cb.EVENT_PRESPAWN},
  439.         register = function(funcname)
  440.             local weapons = {[0]={}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}
  441.             local playerObjId, m_playerObj, weaponObjId, thisWeaponEntry, frags, plasmas, playerIndex
  442.             local pickup_id = registertimer(500, "__weaponCheckTimer")
  443.             function __weaponCheckTimer(id, count)
  444.                 if pickup_id ~= id then return false end
  445.                 for playerId = 0,15 do
  446.                     if not getplayer(playerId) then
  447.                         goto resetweapons
  448.                     end
  449.                    
  450.                     playerObjId = getplayerobjectid(playerId)
  451.                     m_playerObj = getobject(playerObjId)
  452.                     if not m_playerObj then
  453.                         goto resetweapons
  454.                     end
  455.                    
  456.                     playerIndex = resolveplayer(playerId)
  457.                     thisWeaponEntry = weapons[playerId]
  458.                     for slot = 1,4 do
  459.                         weaponObjId = readdword(m_playerObj + 0x2F8 + (slot-1)*4)
  460.                         if thisWeaponEntry[slot] ~= weaponObjId then
  461.                             if thisWeaponEntry[slot] then
  462.                                 if weaponObjId ~= 0xFFFFFFFF then
  463.                                     ypcall(_G[events[cb.EVENT_WEAPON_DROP][1]], playerIndex, slot, 1)
  464.                                 elseif thisWeaponEntry[slot] ~= 0xFFFFFFFF then
  465.                                     ypcall(_G[events[cb.EVENT_WEAPON_DROP][1]], playerIndex, slot, 1)
  466.                                     ypcall(_G[funcname], playerIndex, slot, 1)
  467.                                 else
  468.                                     ypcall(_G[funcname], playerIndex, slot, 1)
  469.                                 end
  470.                             end
  471.                             thisWeaponEntry[slot] = weaponObjId
  472.                         end
  473.                     end
  474.                    
  475.                     frags = readbyte(m_playerObj + 0x31E)
  476.                     if thisWeaponEntry[5] ~= frags then
  477.                         if thisWeaponEntry[5] then
  478.                             for i = (thisWeaponEntry[5] or 0),frags do
  479.                                 ypcall(_G[funcname], playerIndex, 2, 2)
  480.                             end
  481.                         end
  482.                         thisWeaponEntry[5] = frags
  483.                     end
  484.                     plasmas = readbyte(m_playerObj + 0x31F)
  485.                     if thisWeaponEntry[6] ~= plasmas then
  486.                         if thisWeaponEntry[6] then
  487.                             for i = (thisWeaponEntry[6] or 0),plasmas do
  488.                                 ypcall(_G[funcname], playerIndex, 2, 2)
  489.                             end
  490.                         end
  491.                         thisWeaponEntry[6] = plasmas
  492.                     end
  493.                    
  494.                     goto continue
  495.                    
  496.                     ::resetweapons::
  497.                     thisWeaponEntry = weapons[playerId]
  498.                     if next(thisWeaponEntry) then
  499.                         for slot = 1,6 do
  500.                             thisWeaponEntry[slot] = nil
  501.                         end
  502.                     end
  503.                    
  504.                     ::continue::
  505.                 end
  506.                 ::endFunc::
  507.                 return true
  508.             end
  509.         end
  510.     },
  511.     [cb.EVENT_WEAPON_DROP] = {
  512.         dependencies = {cb.EVENT_WEAPON_PICKUP},
  513.         register = function(funcname)
  514.             if _SERVERAPP == "Phasor" then
  515.                 events[cb.EVENT_WEAPON_DROP][1] = funcname
  516.             else
  517.                 real_register_callback(cb.EVENT_WEAPON_DROP, funcname)
  518.             end
  519.         end
  520.     },
  521.     [cb.EVENT_VEHICLE_ENTER] = {
  522.         register = function(funcname)
  523.             if _SERVERAPP == "Phasor" then
  524.                 function OnVehicleEntry(playerId, __, seat)
  525.                     ypcall(phasorEvents.OnVehicleEntry, playerId, __, seat)
  526.                     ypcall(_G[funcname], resolveplayer(playerId), seat)
  527.                 end
  528.             else
  529.                 -- Hacky: Player can drive the vehicle for a whole 2 seconds before the script can eject them.
  530.                 function __vehicleentry_event(playerIndex, seat)
  531.                     if prevent_join[playerIndex] then
  532.                         return nil
  533.                     end
  534.                    
  535.                     local vehicleObjId = read_dword(get_dynamic_player(playerIndex) + 0x11C)
  536.                     if ypcall(phasorEvents.OnVehicleEntry, to_real_index(playerIndex), vehicleObjId, seat, read_dword(get_object_memory(vehicleObjId)), true) == false then
  537.                         timer(2000, "__prevententry", playerIndex)
  538.                     else
  539.                         ypcall(_G[funcname], playerIndex, seat)
  540.                     end
  541.                    
  542.                     function __prevententry(playerIndex)
  543.                         dont_doublecall_onvehicleeject = true
  544.                         exit_vehicle(playerIndex)
  545.                         dont_doublecall_onvehicleeject = false
  546.                         return false
  547.                     end
  548.                 end
  549.                 real_register_callback(cb.EVENT_VEHICLE_ENTER, "__vehicleentry_event")
  550.             end
  551.         end
  552.     },
  553.     [cb.EVENT_VEHICLE_EXIT] = {
  554.         register = function(funcname)
  555.             if _SERVERAPP == "Phasor" then
  556.                 function OnVehicleEject(playerId)
  557.                     ypcall(phasorEvents.OnVehicleEject, playerId)
  558.                     ypcall(_G[funcname], resolveplayer(playerId))
  559.                 end
  560.             else
  561.                 -- Broken: No way to determine if the player is being forcibly ejected or not.
  562.                 -- Hacky: Puts player back in vehicle after 1 second.
  563.                 function __vehicleexit_event(playerIndex)
  564.                     if prevent_join[playerIndex] then
  565.                         return nil
  566.                     end
  567.                     local m_playerObj = get_dynamic_player(playerIndex)
  568.                     local seat = read_word(m_playerObj + 0x120)
  569.                     if ypcall(phasorEvents.OnVehicleEject, to_real_index(playerIndex), seat) == false then
  570.                         timer(1000, "__preventejection", vehicleObjId, playerIndex, read_word(m_playerObj + 0x120))
  571.                     else
  572.                         ypcall(_G[funcname], playerIndex)
  573.                     end
  574.                 end
  575.                 function __preventejection(vehicleObjId, playerIndex, seat)
  576.                     dont_doublecall_onvehicleentry = true
  577.                     enter_vehicle(vehicleObjId, playerIndex, seat)
  578.                     dont_doublecall_onvehicleentry = false
  579.                     return false
  580.                 end
  581.                 real_register_callback(cb.EVENT_VEHICLE_EXIT, "__vehicleexit_event")
  582.             end
  583.         end
  584.     },
  585.     [cb.EVENT_BETRAY] = {
  586.         dependencies = {cb.EVENT_DIE},
  587.         register = function(funcname)
  588.             if _SERVERAPP == "Phasor" then
  589.                 events[cb.EVENT_BETRAY][1] = funcname
  590.             else
  591.                 real_register_callback(cb.EVENT_BETRAY, funcname)
  592.             end
  593.         end
  594.     },
  595.     [cb.EVENT_SUICIDE] = {
  596.         dependencies = {cb.EVENT_DIE},
  597.         register = function(funcname)
  598.             if _SERVERAPP == "Phasor" then
  599.                 events[cb.EVENT_SUICIDE][1] = funcname
  600.             else
  601.                 real_register_callback(cb.EVENT_SUICIDE, funcname)
  602.             end
  603.         end
  604.     },
  605.     [cb.EVENT_SCORE] = {
  606.         register = function(funcname)
  607.            
  608.             local function getscore(playerId)
  609.                 if gametype == 1 then
  610.                     return readshort(getplayer(playerId) + 0xC8)
  611.                 elseif gametype == 2 then
  612.                     return readint((_GAME == "PC" and 0x63A0E8 or 0x5BE108) + 0x40+playerId*4)
  613.                 elseif gametype == 3 then
  614.                     return readint((_GAME == "PC" and 0x639E58 or 0x5BDE78) + 0x84+playerId*4)
  615.                 elseif gametype == 4 then
  616.                     return readshort(getplayer(playerId) + 0xC4)
  617.                 elseif gametype == 5 then
  618.                     return readshort(getplayer(playerId) + 0xC6)
  619.                 end
  620.             end
  621.  
  622.             local score_timer_id = registertimer(1000, "__OnPlayerScoreCheck")
  623.             function __OnPlayerScoreCheck(id, count)
  624.                 if score_timer_id ~= id then return false end
  625.                 for playerId = 0,15 do
  626.                     if getplayer(playerId) then
  627.                         local score = getscore(playerId)
  628.                         if score ~= player_scores[playerId] then
  629.                             ypcall(_G[funcname], resolveplayer(playerId))
  630.                             player_scores[playerId] = score
  631.                         end
  632.                     end
  633.                 end
  634.                 return true
  635.             end
  636.         end
  637.     },
  638.     [cb.EVENT_TEAM_SWITCH] = {
  639.         register = function(funcname)
  640.             if _SERVERAPP == "Phasor" then
  641.                 function OnTeamChange(playerId, old_team, new_team, relevant)
  642.                     ypcall(phasorEvents.OnTeamChange, playerId, old_team, new_team, relevant)
  643.                     ypcall(_G[funcname], resolveplayer(playerId))
  644.                 end
  645.             else
  646.                 function __teamchange_event(playerIndex)
  647.                     local playerId = to_real_index(playerIndex)
  648.                     local new_team = getteam(playerId)
  649.                     local old_team = abs(old_team - 1)
  650.                    
  651.                     -- Broken: No way to check if this can be blocked (team switch in escape menu) vs command-executed.
  652.                     -- A solution is to assume it always can be blocked and use our method of blocking it.
  653.                     if ypcall(phasorEvents.OnTeamChange, playerId, old_team, new_team, false) == false then
  654.                         write_byte(get_player(playerIndex) + 0x20, old_team)
  655.                     end
  656.                    
  657.                     ypcall(_G[funcname], playerIndex)
  658.                 end
  659.                 real_register_callback(cb.EVENT_TEAM_SWITCH, "__teamchange_event")
  660.             end
  661.         end
  662.     },
  663.     [cb.EVENT_JOIN] = {
  664.         register = function(funcname)
  665.             if _SERVERAPP == "Phasor" then
  666.                 function OnPlayerJoin(playerId)
  667.                     ypcall(phasorEvents.OnPlayerJoin, playerId)
  668.                     ypcall(_G[funcname], resolveplayer(playerId))
  669.                 end
  670.             else
  671.                 -- Broken: No way to change name OnNameRequest
  672.                 -- Hacky: Player is banned onplayerjoin, so they will still enter the server for a brief minute.
  673.                 function __onjoin_event(playerIndex)
  674.                     local team = get_var(playerIndex, "$team")
  675.                     local new_team = tonumber(ypcall(phasorEvents.OnTeamDecision, team))
  676.                     if new_team and team ~= new_team then
  677.                         write_byte(get_player(playerIndex) + 0x20, new_team)
  678.                     end
  679.                     local hash = get_var(playerIndex, "$hash")
  680.                     if ypcall(phasorEvents.OnNameRequest, hash, get_var(playerIndex, "$name")) == false then
  681.                         write_word(get_player(playerIndex) + 0x2C, 0x7FFF) -- Don't let them spawn.
  682.                         local msg = "Your name is not allowed in this server. Please leave and change it."
  683.                         say(msg, playerIndex)
  684.                         rprint(msg, playerIndex)
  685.                         prevent_join[playerIndex] = true -- Prevents the player from spawning, etc in scripts code.
  686.                     end
  687.                     if ypcall(phasorEvents.OnBanCheck, hash, get_var(playerIndex, "$ip")) == false then
  688.                         execute_command("sv_ban " .. playerIndex .. " 1s")
  689.                         prevent_join[playerIndex] = true -- Prevents the player from spawning, etc in scripts code.
  690.                     end
  691.                     if prevent_join[playerIndex] then
  692.                         return nil
  693.                     end
  694.                     ypcall(phasorEvents.OnPlayerJoin, to_real_index(playerIndex), new_team)
  695.                     ypcall(_G[funcname], playerIndex)
  696.                 end
  697.                 real_register_callback(cb.EVENT_JOIN, "__onjoin_event")
  698.             end
  699.         end
  700.     },
  701.     [cb.EVENT_LEAVE] = {
  702.         register = function(funcname)
  703.             if _SERVERAPP == "Phasor" then
  704.                 function OnPlayerLeave(playerId)
  705.                     ypcall(phasorEvents.OnPlayerLeave, playerId)
  706.                     ypcall(_G[funcname], resolveplayer(playerId))
  707.                 end
  708.             else
  709.                 function __playerleave_event(playerIndex)
  710.                     if prevent_join[playerIndex] then
  711.                         prevent_join[playerIndex] = nil
  712.                         return nil
  713.                     end
  714.                     ypcall(phasorEvents.OnPlayerLeave, to_real_index(playerIndex))
  715.                     ypcall(_G[funcname], playerIndex)
  716.                 end
  717.                 real_register_callback(cb.EVENT_LEAVE, "__playerleave_event")
  718.             end
  719.         end
  720.     },
  721.     [cb.EVENT_CAMP] = {
  722.         register = function(funcname)
  723.             if _SERVERAPP == "Phasor" then
  724.                 events[cb.EVENT_WARP][1] = funcname
  725.             else
  726.                 real_register_callback(cb.EVENT_WARP, funcname)
  727.             end
  728.         end
  729.     },
  730.     [cb.EVENT_LOGIN] = {
  731.         register = function(funcname)
  732.             if _SERVERAPP == "Phasor" then
  733.                 events[cb.EVENT_WARP][1] = funcname
  734.             else
  735.                 real_register_callback(cb.EVENT_WARP, funcname)
  736.             end
  737.         end
  738.     },
  739.     [cb.EVENT_GAME_START] = {
  740.         register = function(funcname)
  741.             if _SERVERAPP == "Phasor" then
  742.                 function OnNewGame(map)
  743.                     ypcall(phasorEvents.OnNewGame, map)
  744.                     ypcall(_G[funcname])
  745.                 end
  746.             else
  747.                 function __newgame_event()
  748.                     ypcall(phasorEvents.OnNewGame, get_var(0, "$map"))
  749.                     ypcall(_G[funcname])
  750.                 end
  751.                 real_register_callback(cb.EVENT_GAME_START, "__newgame_event")
  752.             end
  753.         end
  754.     },
  755.     [cb.EVENT_GAME_END] = {
  756.         register = function(funcname)
  757.             if _SERVERAPP == "Phasor" then
  758.                 local ongameend_called
  759.                 function OnGameEnd(mode)
  760.                     ypcall(phasorEvents.OnGameEnd, mode)
  761.                     if not ongameend_called then
  762.                         ypcall(_G[funcname])
  763.                         ongameend_called = true
  764.                     end
  765.                 end
  766.             else
  767.                 -- I don't even need to explain how hacky this is, but suprisingly it works perfectly.
  768.                 function __gameend_event()
  769.                     OnGameEnd(1)
  770.                     ypcall(_G[funcname])
  771.                     function __OnGameEndTimer1() OnGameEnd(2) end
  772.                     function __OnGameEndTimer2() OnGameEnd(3) end
  773.                     timer(7000,  "__OnGameEndTimer1")
  774.                     timer(12000, "__OnGameEndTimer2")
  775.                 end
  776.                 real_register_callback(cb.EVENT_GAME_END, "__gameend_event")
  777.             end
  778.         end
  779.     },
  780.     [cb.EVENT_CHAT] = {
  781.         register = function(funcname)
  782.             if _SERVERAPP == "Phasor" then
  783.                 function OnServerChat(playerId, chattype, message)
  784.                     if playerId and chattype ~= 4 then
  785.                         local response = ypcall(phasorEvents.OnServerChat, playerId, chattype, message)
  786.                         response = response ~= false and ypcall(_G[funcname], to_player_index(playerId), message)
  787.                     end
  788.                 end
  789.             else
  790.                 -- Broken: No way to modify messages
  791.                 -- Broken: No way to determine what TYPE of message is being passed.
  792.                 function __serverchat_event(playerIndex, message)
  793.                     if message:sub(1, 5) ~= "/lead" and message:sub(1, 5) ~= "\\lead" then
  794.                         local response = ypcall(phasorEvents.OnServerChat, to_real_index(playerIndex), 0, message)
  795.                         response = response ~= false and ypcall(_G[funcname], playerIndex, message)
  796.                     end
  797.                 end
  798.                 real_register_callback(cb.EVENT_CHAT, "__serverchat_event")
  799.             end
  800.         end
  801.     },
  802.     [cb.EVENT_COMMAND] = {
  803.         register = function(funcname)
  804.             local function respond(message)
  805.                 if env == 0 then
  806.                     cprint(message)
  807.                 elseif env == 1 then
  808.                     rprint(playerIndex, message)
  809.                 elseif env == 2 then
  810.                     say(playerIndex, message)
  811.                 elseif getplayer(playerId) then
  812.                     sendconsoletext(playerId, message)
  813.                 else
  814.                     hprintf(message)
  815.                 end
  816.             end
  817.             if _SERVERAPP == "Phasor" then
  818.                 local sappattemptcalled = true
  819.                 function OnServerCommandAttempt(playerId, command, password)
  820.                     local respond = respond
  821.                     local result = ypcall(phasorEvents.OnServerCommandAttempt, playerId, command, password)
  822.                    
  823.                     local playerIndex = resolveplayer(playerId)
  824.                     local result2 = ypcall(_G[funcname], playerIndex, command, playerId and 1 or 0, password)
  825.                     sappattemptcalled = true
  826.                     if result ~= false then
  827.                         return result or result2
  828.                     end
  829.                     return false
  830.                 end
  831.                 local __orig_command_event = __OnServerCommand
  832.                 function OnServerCommand(playerId, command)
  833.                     local respond = respond
  834.                     local result = ypcall(phasorEvents.OnServerCommand, playerId, command)
  835.                    
  836.                     if sappattemptcalled then
  837.                         sappattemptcalled = nil
  838.                         return result
  839.                     end
  840.                    
  841.                     local playerIndex = resolveplayer(playerId)
  842.                     ypcall(_G[funcname], playerIndex, command, playerId and 1 or 0, _GAME == "PC" and read_string(0x69BA5C8) or read_string(0x61FC8C8))
  843.                 end
  844.             else
  845.                 function __command_event(playerIndex, command, env, rcon)
  846.                     local respond = respond
  847.                     local playerId = to_real_index(playerIndex) or -1
  848.                     playerId = playerId ~= -1 and playerId or nil
  849.                     local result
  850.                     if env == 1 then
  851.                         if _GAME == "PC" and read_string(0x69BA5C8) == rcon or read_string(0x61FC8C8) == rcon then
  852.                             result = ypcall(phasorEvents.OnServerCommand, playerId, command)
  853.                         elseif ypcall(phasorEvents.OnServerCommandAttempt, playerId, command, rcon) then
  854.                             result = ypcall(phasorEvents.OnServerCommand, playerId, command)
  855.                         end
  856.                     else
  857.                         result = ypcall(OnServerCommand, playerId, command)
  858.                     end
  859.                    
  860.                     if result ~= false then
  861.                         return result or ypcall(_G[funcname], playerIndex, command, env, rcon)
  862.                     end
  863.                 end
  864.                 real_register_callback(cb.EVENT_COMMAND, "__command_event")
  865.             end
  866.         end
  867.     },
  868.     [cb.EVENT_ECHO] = {
  869.         register = function(funcname)
  870.             if _SERVERAPP == "Phasor" then
  871.                 events[cb.EVENT_ECHO][1] = funcname
  872.             else
  873.                 function __echo_event(playerIndex, output)
  874.                     ypcall(_G[funcname], playerIndex, output)
  875.                     if svcmd_echo then
  876.                         svcmd_echo = svcmd_echo .. "\n" .. output
  877.                     end
  878.                 end
  879.                 real_register_callback(cb.EVENT_ECHO, "__echo_event")
  880.             end
  881.         end
  882.     },
  883.     [cb.EVENT_OBJECT_SPAWN] = {
  884.         register = function(funcname)
  885.             if _SERVERAPP == "Phasor" then
  886.                 function OnObjectCreationAttempt(mapId, parentObjId, playerId)
  887.                     ypcall(phasorEvents.OnObjectCreationAttempt, mapId, parentObjId, playerId)
  888.                     ypcall(_G[funcname], resolveplayer(playerId), mapId, parentObjId, readword(0x4005062C + 0x32) * 0x10000 + readword(0x4005062C + 0x2C))
  889.                 end
  890.             else
  891.                 function __objectcreate_event(playerIndex, mapId, parentObjId, objectId)
  892.                     if prevent_join[playerIndex] then
  893.                         return nil
  894.                     end
  895.                    
  896.                     local playerId = to_real_index(playerIndex)
  897.                     playerId = playerId ~= -1 and playerId or nil
  898.                     local response = ypcall(phasorEvents.OnObjectCreationAttempt, mapId, parentObjId, playerId)
  899.                     if response ~= false then -- don't call onobjectcreation if the attempt was terminated.
  900.                         response = ypcall(phasorEvents.OnObjectCreation, objectId) ~= false and tonumber(response)
  901.                     end
  902.                    
  903.                     if response ~= false then
  904.                         local response2 = ypcall(_G[funcname], playerIndex, mapId, parentObjId, objectId)
  905.                         if response2 ~= false then
  906.                             response = response2 or response
  907.                         else
  908.                             response = false
  909.                         end
  910.                     end
  911.                    
  912.                     if response then
  913.                         return true,response
  914.                     elseif response ~= false and not playerId and parentObjId ~= 0xFFFFFFFF then
  915.                         local response2 = ypcall(phasorEvents.OnWeaponAssignment, playerId, parentObjId, 0, mapId)
  916.                         if response2 ~= false then
  917.                             response = response2 or response
  918.                         else
  919.                             response = false
  920.                         end
  921.                     end
  922.                    
  923.                     return response
  924.                 end
  925.                 real_register_callback(cb.EVENT_OBJECT_SPAWN, "__objectcreate_event")
  926.             end
  927.         end
  928.     },
  929. }
  930.  
  931. --[==[local eventsMT = {
  932.     __call = function(self, a,b,c,d,e,f,g)
  933.         for i = 1,#self do
  934.             _G[self[i]](a,b,c,d,e,f,g)
  935.         end
  936.     end
  937. }
  938. for k,v in next,events do
  939.     setmetatable(v, eventsMT)
  940. end]==]
  941.  
  942. -- Private functions
  943.  
  944. function events:Create(event, funcname)
  945.    
  946.     funcname = funcname ~= "##INTERNAL_ONLY##" and funcname
  947.    
  948.     -- Register our event.
  949.     self[#self+1] = funcname
  950.     self.register(funcname)
  951.    
  952.     -- Create dependencies.
  953.     local dependencies = self.dependencies
  954.     local dependency, dependencyEvent
  955.     local newBlankFuncStr
  956.     if dependencies then
  957.         for i = 1,#dependencies do dependency = dependencies[i]
  958.             dependencyEvent = events[dependency]
  959.             -- Only create the event dependency if it isn't already created.
  960.             if not dependencyEvent[1] then
  961.                 newBlankFuncStr = "__" .. funcname
  962.                 events.Create(dependencyEvent, dependency, newBlankFuncStr)
  963.                 _G[newBlankFuncStr] = function() end
  964.             end
  965.         end
  966.     end
  967. end
  968.  
  969. local function registerPhasorEvents()
  970.  
  971.     -- bool     OnObjectInteraction (halo::s_player &player, halo::ident objid, halo::ident mapid)
  972.         -- Called when a player interacts with an object (ie stands on it)
  973.      
  974.     -- bool     OnDamageLookup (halo::s_damage_info *dmg, void *metaData, halo::ident receiver, halo::damage_script_options &out)
  975.         -- Called when the server needs to apply damage to an object.
  976.      
  977.     -- bool     OnDamageApplication (const halo::s_damage_info *dmg, halo::ident receiver, const halo::s_hit_info *hit, bool backtap)
  978.         -- Called when the server is about to apply damage to an object.
  979.        
  980.     local nonexistant_func = "##INTERNAL_ONLY##"
  981.     register_callback(cb.EVENT_ECHO, nonexistant_func)
  982.     if OnServerChat then
  983.         register_callback(cb.EVENT_CHAT, nonexistant_func)
  984.     end
  985.     if OnTeamDecision or OnNameRequest or OnBanCheck or OnPlayerJoin then
  986.         register_callback(cb.EVENT_JOIN, nonexistant_func)
  987.     end
  988.     if OnWeaponReload or OnClientUpdate then
  989.         register_callback(cb.EVENT_TICK, nonexistant_func)
  990.     end
  991.     if OnGameEnd then
  992.         register_callback(cb.EVENT_GAME_END, nonexistant_func)
  993.     end
  994.     if OnNewGame then
  995.         register_callback(cb.EVENT_GAME_START, nonexistant_func)
  996.     end
  997.     if OnKillMultiplier or OnPlayerKill then
  998.         register_callback(cb.EVENT_DIE, nonexistant_func)
  999.     end
  1000.     if OnObjectCreation or OnObjectCreationAttempt or OnWeaponAssignment then
  1001.         register_callback(cb.EVENT_OBJECT_SPAWN, nonexistant_func)
  1002.     end
  1003.     if OnPlayerLeave then
  1004.         register_callback(cb.EVENT_LEAVE, nonexistant_func)
  1005.     end
  1006.     if OnPlayerSpawn or OnWeaponAssignment then
  1007.         register_callback(cb.EVENT_PRESPAWN, nonexistant_func)
  1008.     end
  1009.     if OnPlayerSpawnEnd then
  1010.         register_callback(cb.EVENT_SPAWN, nonexistant_func)
  1011.     end
  1012.     if OnServerCommand or OnServerCommandAttempt then
  1013.         register_callback(cb.EVENT_COMMAND, nonexistant_func)
  1014.     end
  1015.     if OnTeamChange then
  1016.         register_callback(cb.EVENT_TEAM_SWITCH, nonexistant_func)
  1017.     end
  1018.     if OnVehicleEntry then
  1019.         register_callback(cb.EVENT_VEHICLE_ENTER, nonexistant_func)
  1020.     end
  1021.     if OnVehicleEject then
  1022.         register_callback(cb.EVENT_VEHICLE_EXIT, nonexistant_func)
  1023.     end
  1024.     safe_read(true)
  1025.     safe_write(true)
  1026. end
  1027.  
  1028. local __say = say
  1029. local kill = kill
  1030.  
  1031. local function trim(str)
  1032.     return gsub(str, "^[%c%s]*(.-)[%c%s]*$", "%1") or str
  1033. end
  1034.  
  1035. -- Definitions for All Phasor Functions
  1036.  
  1037. GetRequiredVersion = GetRequiredVersion or function() return phasor_version end
  1038. required_version = phasor_version
  1039.  
  1040. applycamo = applycamo or ( -- Good
  1041.     function(playerId, duration)
  1042.         local playerIndex = to_player_index(playerId)
  1043.         assert(playerIndex ~= 0, "invalid player id")
  1044.         camo(playerIndex, duration * 30)
  1045.     end
  1046. )
  1047. applydmg = applydmg -- Not in Sapp.
  1048. applydmgtag = applydmgtag -- Not in Sapp.
  1049. assignweapon = assignweapon or ( -- Good
  1050.     function(playerId, objectId)
  1051.         local playerIndex = to_player_index(playerId)
  1052.         assert(playerIndex ~= 0, "invalid player id")
  1053.         return assign_weapon(objectId, playerIndex)
  1054.     end
  1055. )
  1056. changeteam = changeteam or ( -- Good
  1057.     function(playerId, bKill)
  1058.         local playerIndex = to_player_index(playerId)
  1059.         assert(playerIndex ~= 0, "invalid player id")
  1060.         local m_player = get_player(playerIndex)
  1061.         local team = read_byte(m_player + 0x20)
  1062.         local new_team = abs(team - 1)
  1063.         if not OnTeamChange2 or OnTeamChange2(playerId, team, new_team, true) ~= false then
  1064.             write_byte(m_player + 0x20, new_team)
  1065.             if bKill then kill(playerIndex) end
  1066.         end
  1067.     end
  1068. )
  1069. createobject = createobject or ( -- Good
  1070.     function(mapId, parentObjId, respawn_time, bRecycle, x, y, z)
  1071.         local objectId = spawn_object("", "", x, y, z, 0, mapId)
  1072.         return objectId ~= 0 and objectId or nil
  1073.     end
  1074. )
  1075. destroyobject = destroyobject or ( -- Good
  1076.     function(objectId)
  1077.         assert(getobject(objectId), "invalid object id")
  1078.         destroy_object(objectId)
  1079.     end
  1080. )
  1081. entervehicle = entervehicle or ( -- Good
  1082.     function(playerId, objectId, seat)
  1083.         local playerIndex = to_player_index(playerId)
  1084.         assert(playerIndex ~= 0, "invalid player id")
  1085.         assert(getobject(objectId), "invalid object id")
  1086.         return enter_vehicle(objectId, playerIndex, seat) or nil
  1087.     end
  1088. )
  1089. exitvehicle = exitvehicle or ( -- Good
  1090.     function(playerId)
  1091.         local playerIndex = to_player_index(playerId)
  1092.         assert(playerIndex ~= 0, "invalid player id")
  1093.         exit_vehicle(playerIndex)
  1094.     end
  1095. )
  1096. gethash = gethash or ( -- Good
  1097.     function(playerId)
  1098.         local playerIndex = to_player_index(playerId)
  1099.         assert(playerIndex ~= 0, "invalid player id")
  1100.         local result = get_var(playerIndex, "$hash")
  1101.         return result ~= 0 and result or nil
  1102.     end
  1103. )
  1104. getip = getip or ( -- Good
  1105.     function(playerId)
  1106.         local playerIndex = to_player_index(playerId)
  1107.         assert(playerIndex ~= 0, "invalid player id")
  1108.         local network_machine_pointer = _GAME == "PC" and 0x745BA0 or 0x6C7980
  1109.         local network_pointer = read_dword(read_dword(read_dword(read_dword(network_machine_pointer) + 0xAA0 + read_byte(get_player(playerIndex) + 0x64)*4)))
  1110.         assert(network_pointer ~= 0, "'getip' cannot be used in OnPlayerLeave or EVENT_LEAVE")
  1111.         return format("%i.%i.%i.%i", read_byte(network_pointer), read_byte(network_pointer + 0x1), read_byte(network_pointer + 0x2), read_byte(network_pointer + 0x3)) -- Player's IP Address (127.0.0.1 if host)
  1112.     end
  1113. )
  1114. getname = getname or ( -- Good
  1115.     function(playerId)
  1116.         local playerIndex = to_player_index(playerId)
  1117.         assert(playerIndex ~= 0, "invalid player id")
  1118.         local result = get_var(playerIndex, "$name")
  1119.         return result ~= 0 and result or nil
  1120.     end
  1121. )
  1122. getobject = getobject or ( -- Good
  1123.     function(objectId)
  1124.         local m_object = get_object_memory(objectId)
  1125.         return m_object ~= 0 and m_object or nil
  1126.     end
  1127. )
  1128. getobjectcoords = getobjectcoords or ( -- Good
  1129.     function(objectId)
  1130.         local m_object = get_object_memory(objectId)
  1131.         assert(m_object ~= 0, "invalid object id")
  1132.  
  1133.         local m_vehicleObj = get_object_memory(read_dword(m_object + 0x11C))
  1134.         if m_vehicleObj ~= 0 then
  1135.             m_object = m_vehicleObj
  1136.         end
  1137.  
  1138.         return read_vector3d(m_object + 0x5C)
  1139.     end
  1140. )
  1141. getplayer = getplayer or ( -- Good
  1142.     function(playerId)
  1143.         playerId = tonumber(playerId)
  1144.         if not playerId then
  1145.             return nil
  1146.         end
  1147.        
  1148.         local playerIndex = to_player_index(playerId)
  1149.         if prevent_join[playerIndex] then return nil end
  1150.         local result = get_player(to_player_index(playerId))
  1151.         return result ~= 0 and read_dword(result) ~= 0 and result or nil
  1152.     end
  1153. )
  1154. getplayerobjectid = getplayerobjectid or ( -- Good
  1155.     function(playerId)
  1156.         local playerIndex = to_player_index(playerId)
  1157.         assert(playerIndex ~= 0, "invalid player id")
  1158.         return read_dword(get_player(playerIndex) + 0x34)
  1159.     end
  1160. )
  1161. getport = getport or ( -- Good
  1162.     function(playerId)
  1163.         local playerIndex = to_player_index(playerId)
  1164.         assert(playerIndex ~= 0, "invalid player id")
  1165.         return read_word(read_dword(read_dword(read_dword(read_dword(_GAME == "PC" and 0x745BA0 or 0x6C7980) + 0xAA0 + read_byte(get_player(playerIndex) + 0x64)*4))) + 0x4)
  1166.     end
  1167. )
  1168. getprofilepath = getprofilepath or ( -- Good
  1169.     function()
  1170.         return (_GAME == "PC" and read_string(0x635610) or read_string(0x5B9630) or "") .. "\\"
  1171.     end
  1172. )
  1173. getrandomnumber = getrandomnumber or rand or math.randomseed(clock() + time()) and random(1,2) and random(3,5) and random(8,13) and ( -- Good
  1174.     function(min, max)
  1175.         if min > max then
  1176.             min, max = max, min
  1177.         end
  1178.         return random(min, max+1)
  1179.     end
  1180. )
  1181. gettagaddress = gettagaddress or ( -- Good
  1182.     function(a, b)
  1183.         local tag = lookup_tag(a, b)
  1184.         return tag ~= 0 and read_dword(tag + 0x14) or nil
  1185.     end
  1186. )
  1187. gettagid = gettagid or ( -- Good
  1188.     function(a, b)
  1189.         local tag = lookup_tag(a, b)
  1190.         return tag ~= 0 and read_dword(tag + 0xC) or nil
  1191.     end
  1192. )
  1193. gettaginfo = gettaginfo or ( -- Good
  1194.     function(a)
  1195.         local tag = lookup_tag(a, b)
  1196.         return tag ~= 0 and read_string(read_dword(tag + 0x10)), read_string(tag)
  1197.     end
  1198. )
  1199. getteam = getteam or ( -- Good
  1200.     function(playerId)
  1201.         local playerIndex = to_player_index(playerId)
  1202.         assert(playerIndex ~= 0, "invalid player id")
  1203.         local m_player = get_player(playerIndex)
  1204.         return read_byte(m_player + 0x20) or nil
  1205.     end
  1206. )
  1207. getteamsize = getteamsize or ( -- Good
  1208.     function(team)
  1209.         local counter = 0
  1210.         for playerIndex = 1,16 do
  1211.             if player_present(playerIndex) and get_var(playerIndex, "$team") == team then
  1212.                 counter = counter + 1
  1213.             end
  1214.         end
  1215.         return counter
  1216.     end
  1217. )
  1218. getticks = getticks or function() return clock() * 1000 end -- Good
  1219. halointersect = halointersect or ( -- Good
  1220.     function(dist, x, y, z, vx, vy, vz, objectId)
  1221.         return intersect(x, y, z, vx*dist, vy*dist, vz*dist, objectId)
  1222.     end
  1223. )
  1224. hprintf = hprintf or print -- Good
  1225. isinvehicle = isinvehicle or ( -- Good
  1226.     function(playerId)
  1227.         local playerIndex = to_player_index(playerId)
  1228.         assert(playerIndex ~= 0, "invalid player id")
  1229.        
  1230.         local m_playerObj = get_object_memory(read_dword(get_player(playerIndex) + 0x34))
  1231.         return m_playerObj ~= 0 and get_object_memory(read_dword(m_playerObj + 0x11C)) ~= 0
  1232.     end
  1233. )
  1234. phasorkill = _SERVERAPP == "Phasor" and kill or ( -- Annoying workaround.
  1235.     function(playerId)
  1236.         kill(to_player_index(playerId))
  1237.     end
  1238. )
  1239. log_msg = log_msg -- Not in Sapp.
  1240. lookuptag = lookuptag or ( -- Good
  1241.     function(a)
  1242.         local tag = lookup_tag(a)
  1243.         return tag ~= 0 and read_dword(tag+0x14) or nil
  1244.     end
  1245. )
  1246. movobjectcoords = movobjectcoords or moveobjcoords or moveobjectcoords or movobjcoords or ( -- Good
  1247.     function(objectId, x, y, z)
  1248.         local m_object = get_object_memory(objectId)
  1249.         assert(m_object ~= 0, "invalid object id")
  1250.        
  1251.         local m_vehicleObj = get_object_memory(read_dword(m_object + 0x11C))
  1252.         write_vector3d( (m_vehicleObj ~= 0 and m_vehicleObj or m_object) + 0x5C, x, y, z)
  1253.     end
  1254. )
  1255. objectidtoplayer = objectidtoplayer or ( -- Good
  1256.     function(objectId)
  1257.         local m_object = get_object_memory(objectId)
  1258.         assert(m_object ~= 0, "invalid object id")
  1259.        
  1260.         local playerId = read_word(m_object + 0xC0)
  1261.         return to_player_index(playerId) ~= 0 and playerId or nil
  1262.     end
  1263. )
  1264. odl_causer = odl_causer -- Not in sapp.
  1265. odl_flags = odl_flags -- Not in sapp.
  1266. odl_multiplier = odl_multiplier -- Not in sapp.
  1267. odl_receiver = odl_receiver -- Not in sapp.
  1268. odl_tag = odl_tag -- Not in sapp.
  1269. privatesay = privatesay or ( -- Good
  1270.     function(playerId, message)
  1271.         local playerIndex = to_player_index(playerId)
  1272.         assert(playerIndex ~= 0, "invalid player id")
  1273.        
  1274.         if not find(message, "\n") then
  1275.             return say(message, playerIndex)
  1276.         else
  1277.             local strTable = tokenizestring(message, "\n")
  1278.             for i = 1,#strTable do
  1279.                 say(strTable[i], playerIndex)
  1280.             end
  1281.         end
  1282.     end
  1283. )
  1284. raiseerror = error -- Good
  1285. readbit = readbit or read_bit or ( -- Good
  1286.     function(address, offset, bit)
  1287.         if bit then
  1288.             address = address + offset
  1289.         else
  1290.             bit = offset
  1291.         end
  1292.         return bit32.band(read_byte(address), bit) ~= 0
  1293.     end
  1294. )
  1295. readbyte = readbyte or ( -- Good
  1296.     function(address, offset)
  1297.         address = assert(tonumber(address), "bad argument #1 to 'readbyte' expected number, got " .. type(address))
  1298.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readbyte' expected number, got " .. type(offset))
  1299.         return read_byte(address + (offset == true and 0 or offset))
  1300.     end
  1301. )
  1302. readchar = readchar or ( -- Good
  1303.     function(address, offset)
  1304.         address = assert(tonumber(address), "bad argument #1 to 'readchar' expected number, got " .. type(address))
  1305.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readchar' expected number, got " .. type(offset))
  1306.         return read_char(address + (offset == true and 0 or offset))
  1307.     end
  1308. )
  1309. readword = readword or ( -- Good
  1310.     function(address, offset)
  1311.         address = assert(tonumber(address), "bad argument #1 to 'readword' expected number, got " .. type(address))
  1312.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readword' expected number, got " .. type(offset))
  1313.         return read_word(address + (offset == true and 0 or offset))
  1314.     end
  1315. )
  1316. readshort = readshort or ( -- Good
  1317.     function(address, offset)
  1318.         address = assert(tonumber(address), "bad argument #1 to 'readshort' expected number, got " .. type(address))
  1319.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readshort' expected number, got " .. type(offset))
  1320.         return read_short(address + (offset == true and 0 or offset))
  1321.     end
  1322. )
  1323. readdword = readdword or ( -- Good
  1324.     function(address, offset)
  1325.         address = assert(tonumber(address), "bad argument #1 to 'readdword' expected number, got " .. type(address))
  1326.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readdword' expected number, got " .. type(offset))
  1327.         return read_dword(address + (offset == true and 0 or offset))
  1328.     end
  1329. )
  1330. readint = readint or ( -- Good
  1331.     function(address, offset)
  1332.         address = assert(tonumber(address), "bad argument #1 to 'readint' expected number, got " .. type(address))
  1333.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readint' expected number, got " .. type(offset))
  1334.         return read_int(address + (offset == true and 0 or offset))
  1335.     end
  1336. )
  1337. readfloat = readfloat or ( -- Good
  1338.     function(address, offset)
  1339.         address = assert(tonumber(address), "bad argument #1 to 'readfloat' expected number, got " .. type(address))
  1340.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readfloat' expected number, got " .. type(offset))
  1341.         return read_float(address + (offset == true and 0 or offset))
  1342.     end
  1343. )
  1344. readdouble = readdouble or ( -- Good
  1345.     function(address, offset)
  1346.         address = assert(tonumber(address), "bad argument #1 to 'readdouble' expected number, got " .. type(address))
  1347.         offset = assert(not offset or tonumber(offset), "bad argument #2 to 'readdouble' expected number, got " .. type(offset))
  1348.         return read_double(address + (offset == true and 0 or offset))
  1349.     end
  1350. )
  1351. readstring = read_string and ( -- Good
  1352.     function(a, l)
  1353.         a = assert(tonumber(a), "bad argument #1 to 'readstring' expected number, got '" .. type(a) .. "'")
  1354.         l = assert(not l or tonumber(l), "bad argument #2 to 'readstring' expected number, got '" .. type(l) .. "'")
  1355.         local str = read_string(a)
  1356.         return str and sub(str, 1, l or #str)
  1357.     end
  1358. ) or (
  1359.     function(address, length)
  1360.         address = assert(tonumber(address), "bad argument #1 to 'readstring' expected number, got '" .. type(address) .. "'")
  1361.         length = assert(not length or tonumber(length), "bad argument #2 to 'readstring' expected number, got '" .. type(length) .. "'")
  1362.         local char_table = {}
  1363.         local newByte
  1364.         for i = 0,(length == true and 256 or length)-1 do
  1365.             newByte = read_byte(address + i)
  1366.             if newByte == 0 or newByte == 255 then break end
  1367.             char_table[#char_table+1] = char(newByte)
  1368.         end
  1369.         return concat(char_table)
  1370.     end
  1371. )
  1372. readwidestring = read_wide_string and ( -- Good
  1373.     function(a, l)
  1374.         a = assert(tonumber(a), "bad argument #1 to 'readstring' expected number, got '" .. type(a) .. "'")
  1375.         l = assert(not l or tonumber(l), "bad argument #2 to 'readstring' expected number, got '" .. type(l) .. "'")
  1376.         local str = read_wide_string(a)
  1377.         return str and sub(str, 1, l or #str)
  1378.     end
  1379. ) or (
  1380.     function(address, length)
  1381.         address = assert(tonumber(address), "bad argument #1 to 'readwidestring' expected number, got '" .. type(address) .. "'")
  1382.         length = assert(not length or tonumber(length), "bad argument #2 to 'readwidestring' expected number, got '" .. type(length) .. "'")
  1383.         local char_table = {}
  1384.         local newByte
  1385.         for i = 0,(length == true and 51001 or length)-1,2 do
  1386.             newByte = read_byte(address + i)
  1387.             if newByte == 0 or newByte == 255 or read_byte(address + i+1) ~= 0 then break end
  1388.             char_table[#char_table+1] = char(newByte)
  1389.         end
  1390.         return concat(char_table)
  1391.     end
  1392. )
  1393. registertimer = registertimer or ( -- Good
  1394.     function(delay, funcname, arg)
  1395.         local id = #timers+1
  1396.         timers[id] = funcname
  1397.         timer(delay, "__" ..funcname)
  1398.         local count = 0
  1399.         _G["__" .. funcname] = (
  1400.             function()
  1401.                 if not timers[id] then return false end
  1402.                 count = count + 1
  1403.                 local response = ypcall(_G[funcname], id, count, arg)
  1404.                 if response == false then
  1405.                     timers[id] = nil
  1406.                 end
  1407.                 return response
  1408.             end
  1409.         )
  1410.         return id
  1411.     end
  1412. )
  1413. resolveplayer = resolveplayer or ( -- Good
  1414.     function(playerId)
  1415.         local playerIndex = to_player_index(playerId)
  1416.         return playerIndex ~= 0 and playerIndex or nil
  1417.     end
  1418. )
  1419. rresolveplayer = rresolveplayer or ( -- Good
  1420.     function(playerIndex)
  1421.         local playerId = to_real_index(playerIndex)
  1422.         return playerId ~= 0 and playerId or nil
  1423.     end
  1424. )
  1425. removetimer = removetimer or ( -- Good
  1426.     function(id)
  1427.         if id then -- just ignore invalid timer ids
  1428.             timers[id] = nil
  1429.         end
  1430.     end
  1431. )
  1432. respond = respond or function() end -- Good. (real function in onservercommand event)
  1433. say = function(a, b) -- Good
  1434.     if tonumber(b) then
  1435.         if _SERVERAPP == "Phasor" then
  1436.             privatesay(a, rresolveplayer(b))
  1437.         else
  1438.             __say(b, a)
  1439.         end
  1440.     elseif b == false then
  1441.         if _SERVERAPP == "Sapp" then
  1442.             execute_command('say_prefix false')
  1443.             __say(a)
  1444.             execute_command('say_prefix true')
  1445.         else
  1446.             __say(a, false)
  1447.         end
  1448.     elseif b == true or b == nil then
  1449.         if _SERVERAPP == "Phasor" then
  1450.             __say(a)
  1451.         elseif not find(a, "\n") then
  1452.             say_all(a)
  1453.         else
  1454.             local strTable = tokenizestring(a, "\n")
  1455.             for i = 1,#strTable do
  1456.                 say_all(strTable[i])
  1457.             end
  1458.         end
  1459.     end
  1460. end
  1461. sendconsoletext = sendconsoletext or ( -- Good
  1462.     function(playerId, message)
  1463.         rprint(to_player_index(playerId), message)
  1464.     end
  1465. )
  1466. setspeed = setspeed or (
  1467.     function(playerId, speed)
  1468.         local playerIndex = to_player_index(playerId)
  1469.         assert(playerIndex ~= 0, "invalid player id")
  1470.         speed = assert(tonumber(speed), "bad argument #2 to 'setspeed' expected number, got " .. type(speed))
  1471.         write_float(get_player(playerIndex) + 0x6C, speed)
  1472.     end
  1473. )
  1474. svcmd = svcmd or ( -- Good
  1475.     function(a, bResult)
  1476.         if a ~= "reload" and a ~= "lua_unload" and a ~= "lua_load" then
  1477.             bResult = not not bResult
  1478.             svcmd_echo = bResult and ""
  1479.             execute_command(a, 0, bResult)
  1480.             bResult = type(svcmd_echo) == "string" and tokenizestring(svcmd_echo, "\n") or nil
  1481.             svcmd_echo = false
  1482.             return bResult
  1483.         end
  1484.     end
  1485. )
  1486. svcmdplayer = svcmdplayer or ( -- Good
  1487.     function(a, playerId, bResult)
  1488.         if a ~= "reload" and a ~= "lua_unload" and a ~= "lua_load" then
  1489.             svcmd_echo = bResult and ""
  1490.             execute_command(a, to_player_index(playerId), not not bResult)
  1491.             bResult = type(svcmd_echo) == "string" and tokenizestring(svcmd_echo, "\n") or nil
  1492.             svcmd_echo = false
  1493.             return bResult
  1494.         end
  1495.     end
  1496. )
  1497. tokenizestring = tokenizestring or ( -- Good
  1498.     function(str, ...)
  1499.        
  1500.         local subs = {}
  1501.         if (...) == "" then
  1502.             for i = 1,#str do
  1503.                 subs[#subs+1] = sub(str, i, i)
  1504.             end
  1505.             return subs
  1506.         end
  1507.  
  1508.         local strPart = ""
  1509.         local char, iter, delim
  1510.         for i = 1,#str do
  1511.             char = sub(str, i, i)
  1512.             iter = 1
  1513.             delim = select(iter, ...)
  1514.             repeat
  1515.                 if delim == char then
  1516.                     strPart = sub(strPart, 1, -1)
  1517.                     if strPart ~= "" then
  1518.                         subs[#subs+1] = strPart
  1519.                         strPart = ""
  1520.                         goto continue
  1521.                     end
  1522.                 end
  1523.                 iter = iter + 1
  1524.                 delim = select(iter, ...)
  1525.             until not delim or delim == select(-1, ...)
  1526.             strPart = strPart .. char
  1527.             ::continue::
  1528.         end
  1529.        
  1530.         if strPart ~= "" then
  1531.             subs[#subs+1] = strPart
  1532.         end
  1533.  
  1534.         return subs
  1535.     end
  1536. )
  1537. tokenizecmdstring = tokenizecmdstring or ( -- Good
  1538.     function(str)
  1539.         --remove spaces at beginning and end
  1540.         str = trim(str) .. " "
  1541.        
  1542.         local strParts = {}
  1543.         -- return if no delims found
  1544.         if not find(str, '[%s"]') then strParts[1] = str return strParts end
  1545.        
  1546.         local strPart, newPos, pos
  1547.         repeat
  1548.             strPart,newPos = match(str, '^"(.-)"%s+()', pos)
  1549.             if not strPart then
  1550.                 strPart,newPos = match(str, '([^%s]+)%s+()', pos)
  1551.             end
  1552.             pos = newPos
  1553.             strParts[#strParts+1] = strPart
  1554.         until not strPart
  1555.        
  1556.         ::returnSplits::
  1557.        
  1558.         return strParts
  1559.     end
  1560. )
  1561. updateammo = updateammo or ( -- Good
  1562.     function(objectId)
  1563.         assert(get_object_memory(objectId) ~= 0, "invalid object id")
  1564.         sync_ammo(objectId)
  1565.     end
  1566. )
  1567. writebit = writebit or write_bit or ( -- Good
  1568.     function(Address, BitOffset, NewValue) -- Thanks 002
  1569.         NewValue = (NewValue == false or NewValue == 0) and 0 or (NewValue == true or NewValue == 1) and 1 or error("Bad argument #3 to 'writebit' expected number/boolean, got " .. type(NewValue))
  1570.         local value = read_dword(Address)
  1571.         local and_val = 2^BitOffset
  1572.         local flag_set = bit32.band(value, and_val)
  1573.         if flag_set and NewValue == 0 then
  1574.             write_dword(Address, value-and_val)
  1575.         elseif not flag_set and NewValue == 1 then
  1576.             write_dword(Address, value+and_val)
  1577.         end
  1578.     end
  1579. )
  1580. writebyte = writebyte or ( -- Good
  1581.     function(address, offset, value)
  1582.         address = assert(tonumber(address), "bad argument #1 to 'writebyte' expected number, got " .. type(address))
  1583.         offset = assert(tonumber(offset), "bad argument #2 to 'writebyte' expected number, got " .. type(offset))
  1584.         if not value then
  1585.             value = offset
  1586.             offset = nil
  1587.         else
  1588.             value = assert(tonumber(value), "bad argument #3 to 'writebyte' expected number, got " .. type(value))
  1589.         end
  1590.        
  1591.         write_byte(address + (offset or 0), value)
  1592.     end
  1593. )
  1594. writechar = writechar or ( -- Good
  1595.     function(address, offset, value)
  1596.         address = assert(tonumber(address), "bad argument #1 to 'writechar' expected number, got " .. type(address))
  1597.         offset = assert(tonumber(offset), "bad argument #2 to 'writechar' expected number, got " .. type(offset))
  1598.         if not value then
  1599.             value = offset
  1600.             offset = nil
  1601.         else
  1602.             value = assert(tonumber(value), "bad argument #3 to 'writechar' expected number, got " .. type(value))
  1603.         end
  1604.        
  1605.         write_char(address + (offset or 0), value)
  1606.     end
  1607. )
  1608. writeword = writeword or ( -- Good
  1609.     function(address, offset, value)
  1610.         address = assert(tonumber(address), "bad argument #1 to 'writeword' expected number, got " .. type(address))
  1611.         offset = assert(tonumber(offset), "bad argument #2 to 'writeword' expected number, got " .. type(offset))
  1612.         if not value then
  1613.             value = offset
  1614.             offset = nil
  1615.         else
  1616.             value = assert(tonumber(value), "bad argument #3 to 'writeword' expected number, got " .. type(value))
  1617.         end
  1618.        
  1619.         write_word(address + (offset or 0), value)
  1620.     end
  1621. )
  1622. writeshort = writeshort or ( -- Good
  1623.     function(address, offset, value)
  1624.         address = assert(tonumber(address), "bad argument #1 to 'writeshort' expected number, got " .. type(address))
  1625.         offset = assert(tonumber(offset), "bad argument #2 to 'writeshort' expected number, got " .. type(offset))
  1626.         if not value then
  1627.             value = offset
  1628.             offset = nil
  1629.         else
  1630.             value = assert(tonumber(value), "bad argument #3 to 'writeshort' expected number, got " .. type(value))
  1631.         end
  1632.        
  1633.         write_short(address + (offset or 0), value)
  1634.     end
  1635. )
  1636. writedword = writedword or ( -- Good
  1637.     function(address, offset, value)
  1638.         address = assert(tonumber(address), "bad argument #1 to 'writedword' expected number, got " .. type(address))
  1639.         offset = assert(tonumber(offset), "bad argument #2 to 'writedword' expected number, got " .. type(offset))
  1640.         if not value then
  1641.             value = offset
  1642.             offset = nil
  1643.         else
  1644.             value = assert(tonumber(value), "bad argument #3 to 'writedword' expected number, got " .. type(value))
  1645.         end
  1646.        
  1647.         write_dword(address + (offset or 0), value)
  1648.     end
  1649. )
  1650. writeint = writeint or ( -- Good
  1651.     function(address, offset, value)
  1652.         address = assert(tonumber(address), "bad argument #1 to 'writeint' expected number, got " .. type(address))
  1653.         offset = assert(tonumber(offset), "bad argument #2 to 'writeint' expected number, got " .. type(offset))
  1654.         if not value then
  1655.             value = offset
  1656.             offset = nil
  1657.         else
  1658.             value = assert(tonumber(value), "bad argument #3 to 'writeint' expected number, got " .. type(value))
  1659.         end
  1660.        
  1661.         write_int(address + (offset or 0), value)
  1662.     end
  1663. )
  1664. writefloat = writefloat or ( -- Good
  1665.     function(address, offset, value)
  1666.         address = assert(tonumber(address), "bad argument #1 to 'writefloat' expected number, got " .. type(address))
  1667.         offset = assert(tonumber(offset), "bad argument #2 to 'writefloat' expected number, got " .. type(offset))
  1668.         if not value then
  1669.             value = offset
  1670.             offset = nil
  1671.         else
  1672.             value = assert(tonumber(value), "bad argument #3 to 'writefloat' expected number, got " .. type(value))
  1673.         end
  1674.        
  1675.         write_float(address + (offset or 0), value)
  1676.     end
  1677. )
  1678. writedouble = writedouble or ( -- Good
  1679.     function(address, offset, value)
  1680.         address = assert(tonumber(address), "bad argument #1 to 'writedouble' expected number, got " .. type(address))
  1681.         offset = assert(tonumber(offset), "bad argument #2 to 'writedouble' expected number, got " .. type(offset))
  1682.         if not value then
  1683.             value = offset
  1684.             offset = nil
  1685.         else
  1686.             value = assert(tonumber(value), "bad argument #3 to 'writedouble' expected number, got " .. type(value))
  1687.         end
  1688.        
  1689.         write_double(address + (offset or 0), value)
  1690.     end
  1691. )
  1692. writestring = write_string or ( -- Good
  1693.     function(address, offset, str)
  1694.         address = assert(type(address) == "number" and address, "bad argument #1 to 'writestring' expected number, got '" .. type(address) .. "'")
  1695.         if str then
  1696.             offset = assert(type(offset) == "number" and offset, "bad argument #2 to 'writestring' expected number, got '" .. type(offset) .. "'")
  1697.             str = assert(type(str) == "string" and str, "bad argument #3 to 'writestring' expected string, got '" .. type(str) .. "'")
  1698.         else
  1699.             str = assert(type(offset) == "string" and offset, "bad argument #2 to 'writestring' expected string, got '" .. type(offset) .. "'")
  1700.             offset = nil
  1701.         end
  1702.         address = address + (offset or 0x0)
  1703.         local byte_table = {}
  1704.         for char in gmatch(str, '.') do
  1705.             byte_table[#byte_table+1] = byte(char)
  1706.         end
  1707.         local length = #byte_table
  1708.         for i = 0,length-1 do
  1709.             writebyte(address + i, byte_table[i+1])
  1710.         end
  1711.     end
  1712. )
  1713. writewidestring = write_wide_string or ( -- Good
  1714.     function(address, offset, str)
  1715.         address = assert(type(address) == "number" and address, "bad argument #1 to 'writewidestring' expected number, got '" .. type(address) .. "'")
  1716.         if str then
  1717.             offset = assert(type(offset) == "number" and offset, "bad argument #2 to 'writewidestring' expected number, got '" .. type(offset) .. "'")
  1718.             str = assert(type(str) == "string" and str, "bad argument #3 to 'writewidestring' expected string, got '" .. type(str) .. "'")
  1719.         else
  1720.             str = assert(type(offset) == "string" and offset, "bad argument #2 to 'writewidestring' expected string, got '" .. type(offset) .. "'")
  1721.             offset = nil
  1722.         end
  1723.         address = address + (offset or 0x0)
  1724.         local byte_table = {}
  1725.         for char in gmatch(str, '.') do
  1726.             byte_table[#byte_table+1] = byte(char)
  1727.         end
  1728.         local length = #byte_table
  1729.         for i = 0,length*2 do
  1730.             writeword(address + i, 0)
  1731.         end
  1732.     end
  1733. )
  1734.  
  1735. -- Definitions for All Sapp Functions:
  1736. assign_weapon = assign_weapon or ( -- Good
  1737.     function(objectId, playerIndex)
  1738.         local playerId = rresolveplayer(playerIndex)
  1739.         return playerId and assignweapon(playerId, objectId)
  1740.     end
  1741. )
  1742. camo = camo or ( -- Good
  1743.     function(playerIndex, duration)
  1744.         local playerId = rresolveplayer(playerIndex)
  1745.         return playerId and applycamo(playerId, duration / 30)
  1746.     end
  1747. )
  1748. cprint = cprint or function(a) hprintf(a) end -- Good
  1749. destroy_object = destroy_object or ( -- Good
  1750.     function(objId)
  1751.         if getobject(objId) then destroyobject(objId) end
  1752.     end
  1753. )
  1754. drop_weapon = drop_weapon or ( -- Workaround
  1755.     function(playerIndex)
  1756.         local m_playerObj = getobject(getplayerobjectid(rresolveplayer(playerIndex)))
  1757.         if m_playerObj then
  1758.             destroyobject(readdword(m_playerObj + 0x118))
  1759.         end
  1760.     end
  1761. )
  1762. enter_vehicle = enter_vehicle or ( -- Good
  1763.     function(objectId, playerIndex, seat)
  1764.         local playerId = rresolveplayer(playerIndex)
  1765.         if playerId then entervehicle(playerId, objectId, seat) end
  1766.     end
  1767. )
  1768. execute_command = execute_command or ( -- Good
  1769.     function(command, playerIndex)
  1770.         local playerId = rresolveplayer(playerIndex)
  1771.         if events[cb.EVENT_ECHO][1] then
  1772.             local response = playerId and svcmdplayer(command, playerId, true) or svcmd(command, true)
  1773.             if type(response) == "table" then
  1774.                 for i = 1,#response do
  1775.                     ypcall(_G[events[cb.EVENT_ECHO][1]], 0, response[i])
  1776.                 end
  1777.             end
  1778.         elseif playerId then svcmdplayer(command, playerId, true)
  1779.         else svcmd(command, true)
  1780.         end
  1781.     end
  1782. )
  1783. exit_vehicle = exit_vehicle or ( -- Good
  1784.     function(playerIndex)
  1785.         local playerId = rresolveplayer(playerIndex)
  1786.         if playerId then exitvehicle(playerId) end
  1787.     end
  1788. )
  1789. get_dynamic_player = get_dynamic_player or ( -- Good
  1790.     function(playerIndex)
  1791.         local playerId = rresolveplayer(playerIndex)
  1792.         local playerObjId = playerId and getplayerobjectid(playerId)
  1793.         return playerObjId and getobject(playerObjId) or 0
  1794.     end
  1795. )
  1796. get_object_memory = get_object_memory or ( -- Good
  1797.     function(objectId)
  1798.         return objectId and getobject(objectId) or 0
  1799.     end
  1800. )
  1801. get_player = get_player or ( -- Good
  1802.     function(playerIndex)
  1803.         local playerId = rresolveplayer(playerIndex)
  1804.         return playerId and getplayer(playerId) or 0
  1805.     end
  1806. )
  1807. get_var = get_var or ( -- Some variables don't exist in Phasor.
  1808.     function(playerIndex, var)
  1809.         playerIndex = assert(tonumber(playerIndex), "bad argument #1 to 'get_var' expected number, got " .. type(playerIndex))
  1810.         var = lower(var)
  1811.         if var == "$n" then
  1812.             return playerIndex
  1813.         elseif var == "$name" then
  1814.             return getname(rresolveplayer(playerIndex))
  1815.         elseif var == "$hash" then
  1816.             return gethash(rresolveplayer(playerIndex))
  1817.         elseif var == "$ip" then
  1818.             local playerId = rresolveplayer(playerIndex)
  1819.             return getip(playerId) .. ":" .. getport(playerId)
  1820.         elseif var == "$tk" then
  1821.             local m_player = getplayer(rresolveplayer(playerIndex))
  1822.             return readshort(m_player + 0xAC) - readshort(m_player + 0xAE)
  1823.         elseif var == "$kills" then
  1824.             return readshort(getplayer(rresolveplayer(playerIndex)) + 0x9C)
  1825.         elseif var == "$assists" then
  1826.             return readshort(getplayer(rresolveplayer(playerIndex)) + 0xA4)
  1827.         elseif var == "$deaths" then
  1828.             return readshort(getplayer(rresolveplayer(playerIndex)) + 0xAE)
  1829.         elseif var == "$suicides" then
  1830.             return readshort(getplayer(rresolveplayer(playerIndex)) + 0xB0)
  1831.         elseif var == "$streak" then
  1832.             return readshort(getplayer(rresolveplayer(playerIndex)) + 0x96)
  1833.         elseif var == "$combo" then
  1834.             return readshort(getplayer(rresolveplayer(playerIndex)) + 0x98)
  1835.         elseif var == "$score" then
  1836.             return readshort(getplayer(rresolveplayer(playerIndex)) + 0xC8)
  1837.         elseif var == "$botscore" then
  1838.         elseif var == "$afk" then
  1839.         elseif var == "$ping" then
  1840.             return readdword(getplayer(rresolveplayer(playerIndex)) + 0xDC)
  1841.         elseif var == "$x" then
  1842.             return readfloat(getplayer(rresolveplayer(playerIndex)) + 0xF8)
  1843.         elseif var == "$y" then
  1844.             return readfloat(getplayer(rresolveplayer(playerIndex)) + 0xFC)
  1845.         elseif var == "$z" then
  1846.             return readfloat(getplayer(rresolveplayer(playerIndex)) + 0x100)
  1847.         elseif var == "$hp" then
  1848.             return readfloat(getplayer(rresolveplayer(playerIndex)) + 0xE0)
  1849.         elseif var == "$sh" then
  1850.             return readfloat(getplayer(rresolveplayer(playerIndex)) + 0xE4)
  1851.         elseif var == "$invis" then
  1852.             return readword(getplayer(rresolveplayer(playerIndex)) + 0x68) > 0 and 1 or 0
  1853.         elseif var == "$team" then
  1854.             return getteam(playerId)
  1855.         elseif var == "$oteam" then
  1856.             return abs(getteam(playerId)-1)
  1857.         elseif var == "$lvl" then
  1858.             return getadminlvl(playerId)
  1859.         elseif var == "$map" then
  1860.             return _GAME == "PC" and readstring(0x698F21) or readstring(0x61D151)
  1861.         elseif var == "$mode" then
  1862.             local gt = _GAME == "PC" and readbyte(0x671340 + 0x30) or readbyte(0x5F5498 + 0x30)
  1863.             return gt == 1 and "ctf" or gt == 2 and "slayer" or gt == 3 and "koth" or gt == 4 and "oddball" or gt == 5 and "race"
  1864.         elseif var == "$gt" then
  1865.             return _GAME == "PC" and readwidestring(0x671340 + 0x2C) or readwidestring(0x5F5498 + 0x2C)
  1866.         elseif var == "$ffa" then
  1867.             return _GAME == "PC" and readbyte(0x671340 + 0x34) or readbyte(0x5F5498 + 0x34)
  1868.         elseif var == "$svname" then
  1869.             return getservername()
  1870.         elseif var == "$pn" then
  1871.             local counter = 0
  1872.             for playerId = 0,15 do
  1873.                 if getplayer(playerId) then
  1874.                     counter = counter + 1
  1875.                 end
  1876.             end
  1877.             return counter
  1878.         elseif var == "$reds" then
  1879.             return getteamsize(0)
  1880.         elseif var == "$blues" then
  1881.             return getteamsize(1)
  1882.         elseif var == "$rand" then
  1883.             return getrandomnumber(1, 17)
  1884.         elseif var == "$game" then
  1885.             return _GAME
  1886.         end
  1887.         return "Variable doesn't exist on Phasor, sorry!"
  1888.     end
  1889. )
  1890. lookup_tag = lookup_tag or (
  1891.     function(a,b)
  1892.         for i=0,(tag_table_count - 1),0x20 do
  1893.             if a == readdword(0x40440034+i) or a == readstring(0x40440028+i, 4) and b == readstring(readdword(0x40440038+i)) then
  1894.                 return 0x40440028+i
  1895.             end
  1896.         end
  1897.     end
  1898. )
  1899. sappkill = _SERVERAPP == "Sapp" and kill or function(playerIndex) kill(to_real_index(playerIndex)) end -- Annoying.
  1900. intersect = intersect or ( -- Good
  1901.     function(x, y, z, vx, vy, vz, objectId)
  1902.         return halointersect(1, x, y, z, vx, vy, vz, objectId)
  1903.     end
  1904. )
  1905. player_present = player_present or function(playerIndex) return not not rresolveplayer(playerIndex) end -- Good
  1906. rand = rand or getrandomnumber -- Good
  1907. read_bit = read_bit or readbit -- Good
  1908. read_byte = read_byte or readbyte -- Good
  1909. read_char = read_char or readchar -- Good
  1910. read_word = read_word or readword -- Good
  1911. read_short = read_short or readshort -- Good
  1912. read_dword = read_dword or readdword -- Good
  1913. read_int = read_int or readint -- Good
  1914. read_float = read_float or readfloat -- Good
  1915. read_double = read_double or readdouble -- Good
  1916. read_string = read_string or ( -- Good
  1917.     function(address, length)
  1918.         address = type(address) == "number" and address or error("bad argument #1 to 'readstring' expected number, got '" .. type(address) .. "'")
  1919.         if length then
  1920.             length = type(length) == "number" and length or error("bad argument #2 to 'readstring' expected number, got '" .. type(length) .. "'")
  1921.         else
  1922.             length = length or 256
  1923.         end
  1924.         local char_table = {}
  1925.         local newByte
  1926.         for i = 0,length-1 do
  1927.             newByte = readbyte(address + i)
  1928.             if newByte == 0 or newByte == 255 then break end
  1929.             char_table[#char_table+1] = char(newByte)
  1930.         end
  1931.         return concat(char_table)
  1932.     end
  1933. )
  1934. read_vector3d = read_vector3d or ( -- Good
  1935.     function(address)
  1936.         return readfloat(address),readfloat(address+4),readfloat(address+8)
  1937.     end
  1938. )
  1939. read_wide_string = read_wide_string or ( -- Good
  1940.     function(address, length)
  1941.         address = type(address) == "number" and address or error("bad argument #1 to 'readwidestring' expected number, got '" .. type(address) .. "'")
  1942.         if length then
  1943.             length = type(length) == "number" and length or error("bad argument #2 to 'readwidestring' expected number, got '" .. type(length) .. "'")
  1944.         else
  1945.             length = length or 51001
  1946.         end
  1947.         local char_table = {}
  1948.         local newByte
  1949.         for i = 0,length-1,2 do
  1950.             newByte = readbyte(address + i)
  1951.             if newByte == 0 or newByte == 255 or readbyte(address + i+1) ~= 0 then break end
  1952.             char_table[#char_table+1] = char(newByte)
  1953.         end
  1954.         return concat(char_table)
  1955.     end
  1956. )
  1957. -- register_callback will ALWAYS take priority over functions that Phasor calls by default
  1958. -- This means that if you have a function named 'OnTeamChange' in your script, it will be treated as a Phasor function and will pass the default Phasor arguments because it is a phasor event function.
  1959. -- However, if you do 'register_callback(cb.EVENT_TEAM_SWITCH, "OnTeamChange"), now it will be treated like a Sapp event function, and will be called with a playerIndex only. So be careful.
  1960. register_callback = function(event, funcname)
  1961.     local internalEvent = phasorEvents[funcname]
  1962.     if internalEvent then
  1963.         if type(internalEvent) == "function" then
  1964.             _G["__" .. funcname] = internalEvent
  1965.             if internalEvent == _G[funcname] then
  1966.                 _G[funcname] = nil
  1967.             end
  1968.         end
  1969.         funcname = "__" .. funcname
  1970.     end
  1971.     local thisEvent = events[event]
  1972.     assert(thisEvent, "Invalid event passed to 'register_event'")
  1973.     events.Create(thisEvent, event, funcname)
  1974. end
  1975. rprint = rprint or ( -- Good
  1976.     function(playerIndex, message)
  1977.         sendconsoletext(rresolveplayer(playerIndex), message)
  1978.     end
  1979. )
  1980. safe_read = safe_read -- Phasor does not have this.
  1981. safe_write = safe_write -- Phasor does not have this.
  1982. say = say -- Good
  1983. say_all = say_all or __say -- Good
  1984. sig_scan = sig_scan -- Phasor does not have this.
  1985. spawn_object = spawn_object or ( -- Good
  1986.     function(tagtype, tagname, x, y, z, rot, mapId)
  1987.         mapId = tagtype and tagname and gettagid(tagtype, tagname) or mapId
  1988.         return createobject(mapId or gettagid(tagtype, tagname), 0, 0x7FFF, false, x, y, z) or 0
  1989.     end
  1990. )
  1991. sync_ammo = sync_ammo or function(objectId) if getobject(objectId) then updateammo(objectId) end end -- Good
  1992. timer = timer or ( -- Good
  1993.     function(delay, funcname, ...)
  1994.         local args = {...}
  1995.         for i = 1,#args do
  1996.             args[i] = tostring(args[i]) -- all sapp arguments are actually passed as strings
  1997.         end
  1998.         _G[funcname .. "_overhead"] = (
  1999.             function()
  2000.                 return ypcall(_G[funcname], unpack(args))
  2001.             end
  2002.         )
  2003.         registertimer(delay, funcname .. "_overhead", args)
  2004.     end
  2005. )
  2006. to_player_index = to_player_index or resolveplayer and ( -- Good
  2007.     function(playerId)
  2008.         return resolveplayer(playerId) or 0
  2009.     end
  2010. ) or error("Functions 'to_player_index' and 'resolveplayer' not found. What server app are you even using?")
  2011. to_real_index = to_real_index or rresolveplayer and ( -- Good
  2012.     function(playerIndex)
  2013.         return rresolveplayer(playerIndex) or -1
  2014.     end
  2015. ) or error("Functions 'to_real_index' and 'rresolveplayer' not found. What server app are you even using?")
  2016. write_bit = writebit -- Good
  2017. write_byte = write_byte or writebyte -- Good
  2018. write_char = write_char or writechar -- Good
  2019. write_word = write_word or writeword -- Good
  2020. write_short = write_short or writeshort -- Good
  2021. write_dword = write_dword or writedword -- Good
  2022. write_int = write_int or writeint -- Good
  2023. write_float = write_float or writefloat -- Good
  2024. write_double = write_double or writedouble -- Good
  2025. write_string = write_string or ( -- Good
  2026.     function(address, offset, str)
  2027.         address = type(address) == "number" and address or error("bad argument #1 to 'writestring' expected number, got '" .. type(address) .. "'")
  2028.         if str then
  2029.             offset = type(offset) == "number" and offset or error("bad argument #2 to 'writestring' expected number, got '" .. type(offset) .. "'")
  2030.             str = type(str) == "string" and str or error("bad argument #3 to 'writestring' expected string, got '" .. type(str) .. "'")
  2031.         else
  2032.             str = type(offset) == "string" and offset or error("bad argument #2 to 'writestring' expected string, got '" .. type(offset) .. "'")
  2033.             offset = nil
  2034.         end
  2035.         address = address + (offset or 0x0)
  2036.         local byte_table = {}
  2037.         for char in gmatch(str, '.') do
  2038.             byte_table[#byte_table+1] = byte(char)
  2039.         end
  2040.         local length = #byte_table
  2041.         for i = 0,length-1 do
  2042.             writebyte(address + i, byte_table[i+1])
  2043.         end
  2044.     end
  2045. )
  2046. write_vector3d = write_vector3d or (
  2047.     function(address, a, b, c)
  2048.         writefloat(address,   a)
  2049.         writefloat(address+4, b)
  2050.         writefloat(address+8, c)
  2051.     end
  2052. )
  2053. write_wide_string = write_wide_string or ( -- Good
  2054.     function(address, offset, str)
  2055.         address = type(address) == "number" and address or error("bad argument #1 to 'writewidestring' expected number, got '" .. type(address) .. "'")
  2056.         if str then
  2057.             offset = type(offset)  == "number" and offset or error("bad argument #2 to 'writewidestring' expected number, got '" .. type(offset) .. "'")
  2058.             str = type(str)  == "string" and str or error("bad argument #3 to 'writewidestring' expected string, got '" .. type(str) .. "'")
  2059.         else
  2060.             str = type(offset) == "string" and offset or error("bad argument #2 to 'writewidestring' expected string, got '" .. type(offset) .. "'")
  2061.             offset = nil
  2062.         end
  2063.         address = address + (offset or 0x0)
  2064.         local byte_table = {}
  2065.         for char in gmatch(str, '.') do
  2066.             byte_table[#byte_table+1] = byte(char)
  2067.         end
  2068.         local length = #byte_table
  2069.         for i = 0,length*2 do
  2070.             writeword(address + i, 0)
  2071.         end
  2072.     end
  2073. )
  2074.  
  2075. local OnScriptLoad2 = OnScriptLoad
  2076. function OnScriptLoad(process, game, persistent)
  2077.     if _SERVERAPP == "Sapp" then
  2078.         registerPhasorEvents()
  2079.     end
  2080.     ypcall(OnScriptLoad2, process or pid, game or halo_type or _GAME, persistent == nil or persistent)
  2081. end
  2082.  
  2083. collectgarbage() -- No doubt there's tons of functions and variables to be cleaned up since this script overrided most of them.
  2084. _G.kill = nil -- Been renamed, keep it out of the global table in case of accidents.
  2085.  
  2086. api_version = "1.7.0.0"
  2087.  
  2088. return _G
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement