Advertisement
Guest User

Untitled

a guest
Nov 15th, 2019
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.96 KB | None | 0 0
  1. -- in-memory spawnpoint array for this script execution instance
  2. local spawnPoints = {}
  3.  
  4. -- auto-spawn enabled flag
  5. local autoSpawnEnabled = false
  6. local autoSpawnCallback
  7.  
  8. -- support for mapmanager maps
  9. AddEventHandler('getMapDirectives', function(add)
  10.     -- call the remote callback
  11.     add('spawnpoint', function(state, model)
  12.         -- return another callback to pass coordinates and so on (as such syntax would be [spawnpoint 'model' { options/coords }])
  13.         return function(opts)
  14.             local x, y, z, heading
  15.  
  16.             local s, e = pcall(function()
  17.                 -- is this a map or an array?
  18.                 if opts.x then
  19.                     x = opts.x
  20.                     y = opts.y
  21.                     z = opts.z
  22.                 else
  23.                     x = opts[1]
  24.                     y = opts[2]
  25.                     z = opts[3]
  26.                 end
  27.  
  28.                 x = x + 0.0001
  29.                 y = y + 0.0001
  30.                 z = z + 0.0001
  31.  
  32.                 -- get a heading and force it to a float, or just default to null
  33.                 heading = opts.heading and (opts.heading + 0.01) or 0
  34.  
  35.                 -- add the spawnpoint
  36.                 addSpawnPoint({
  37.                     x = x, y = y, z = z,
  38.                     heading = heading,
  39.                     model = model
  40.                 })
  41.  
  42.                 -- recalculate the model for storage
  43.                 if not tonumber(model) then
  44.                     model = GetHashKey(model, _r)
  45.                 end
  46.  
  47.                 -- store the spawn data in the state so we can erase it later on
  48.                 state.add('xyz', { x, y, z })
  49.                 state.add('model', model)
  50.             end)
  51.  
  52.             if not s then
  53.                 Citizen.Trace(e .. "\n")
  54.             end
  55.         end
  56.         -- delete callback follows on the next line
  57.     end, function(state, arg)
  58.         -- loop through all spawn points to find one with our state
  59.         for i, sp in ipairs(spawnPoints) do
  60.             -- if it matches...
  61.             if sp.x == state.xyz[1] and sp.y == state.xyz[2] and sp.z == state.xyz[3] and sp.model == state.model then
  62.                 -- remove it.
  63.                 table.remove(spawnPoints, i)
  64.                 return
  65.             end
  66.         end
  67.     end)
  68. end)
  69.  
  70.  
  71. -- loads a set of spawn points from a JSON string
  72. function loadSpawns(spawnString)
  73.     -- decode the JSON string
  74.     local data = json.decode(spawnString)
  75.  
  76.     -- do we have a 'spawns' field?
  77.     if not data.spawns then
  78.         error("no 'spawns' in JSON data")
  79.     end
  80.  
  81.     -- loop through the spawns
  82.     for i, spawn in ipairs(data.spawns) do
  83.         -- and add it to the list (validating as we go)
  84.         addSpawnPoint(spawn)
  85.     end
  86. end
  87.  
  88. local spawnNum = 1
  89.  
  90. function addSpawnPoint(spawn)
  91.     -- validate the spawn (position)
  92.     if not tonumber(spawn.x) or not tonumber(spawn.y) or not tonumber(spawn.z) then
  93.         error("invalid spawn position")
  94.     end
  95.  
  96.     -- heading
  97.     if not tonumber(spawn.heading) then
  98.         error("invalid spawn heading")
  99.     end
  100.  
  101.     -- model (try integer first, if not, hash it)
  102.     local model = spawn.model
  103.  
  104.     if not tonumber(spawn.model) then
  105.         model = GetHashKey(spawn.model)
  106.     end
  107.  
  108.     -- is the model actually a model?
  109.     if not IsModelInCdimage(model) then
  110.         error("invalid spawn model")
  111.     end
  112.  
  113.     -- is is even a ped?
  114.     -- not in V?
  115.     --[[if not IsThisModelAPed(model) then
  116.         error("this model ain't a ped!")
  117.     end]]
  118.  
  119.     -- overwrite the model in case we hashed it
  120.     spawn.model = model
  121.  
  122.     -- add an index
  123.     spawn.idx = spawnNum
  124.     spawnNum = spawnNum + 1
  125.  
  126.     -- all OK, add the spawn entry to the list
  127.     table.insert(spawnPoints, spawn)
  128.  
  129.     return spawn.idx
  130. end
  131.  
  132. -- removes a spawn point
  133. function removeSpawnPoint(spawn)
  134.     for i = 1, #spawnPoints do
  135.         if spawnPoints[i].idx == spawn then
  136.             table.remove(spawnPoints, i)
  137.             return
  138.         end
  139.     end
  140. end
  141.  
  142. -- changes the auto-spawn flag
  143. function setAutoSpawn(enabled)
  144.     autoSpawnEnabled = enabled
  145. end
  146.  
  147. -- sets a callback to execute instead of 'native' spawning when trying to auto-spawn
  148. function setAutoSpawnCallback(cb)
  149.     autoSpawnCallback = cb
  150.     autoSpawnEnabled = true
  151. end
  152.  
  153. -- function as existing in original R* scripts
  154. local function freezePlayer(id, freeze)
  155.     local player = id
  156.     SetPlayerControl(player, not freeze, false)
  157.  
  158.     local ped = GetPlayerPed(player)
  159.  
  160.     if not freeze then
  161.         if not IsEntityVisible(ped) then
  162.             SetEntityVisible(ped, true)
  163.         end
  164.  
  165.         if not IsPedInAnyVehicle(ped) then
  166.             SetEntityCollision(ped, true)
  167.         end
  168.  
  169.         FreezeEntityPosition(ped, false)
  170.         --SetCharNeverTargetted(ped, false)
  171.         SetPlayerInvincible(player, false)
  172.     else
  173.         if IsEntityVisible(ped) then
  174.             SetEntityVisible(ped, false)
  175.         end
  176.  
  177.         SetEntityCollision(ped, false)
  178.         FreezeEntityPosition(ped, true)
  179.         --SetCharNeverTargetted(ped, true)
  180.         SetPlayerInvincible(player, true)
  181.         --RemovePtfxFromPed(ped)
  182.  
  183.         if not IsPedFatallyInjured(ped) then
  184.             ClearPedTasksImmediately(ped)
  185.         end
  186.     end
  187. end
  188.  
  189. function loadScene(x, y, z)
  190.     NewLoadSceneStart(x, y, z, 0.0, 0.0, 0.0, 20.0, 0)
  191.  
  192.     while IsNewLoadSceneActive() do
  193.         networkTimer = GetNetworkTimer()
  194.  
  195.         NetworkUpdateLoadScene()
  196.     end
  197. end
  198.  
  199. -- to prevent trying to spawn multiple times
  200. local spawnLock = false
  201.  
  202. -- spawns the current player at a certain spawn point index (or a random one, for that matter)
  203. function spawnPlayer(spawnIdx, cb)
  204.     if spawnLock then
  205.         return
  206.     end
  207.  
  208.     spawnLock = true
  209.  
  210.     Citizen.CreateThread(function()
  211.         -- if the spawn isn't set, select a random one
  212.         if not spawnIdx then
  213.             spawnIdx = GetRandomIntInRange(1, #spawnPoints + 1)
  214.         end
  215.  
  216.         -- get the spawn from the array
  217.         local spawn
  218.  
  219.         if type(spawnIdx) == 'table' then
  220.             spawn = spawnIdx
  221.         else
  222.             spawn = spawnPoints[spawnIdx]
  223.         end
  224.  
  225.         if not spawn.skipFade then
  226.             DoScreenFadeOut(500)
  227.  
  228.             while not IsScreenFadedOut() do
  229.                 Citizen.Wait(0)
  230.             end
  231.         end
  232.  
  233.         -- validate the index
  234.         if not spawn then
  235.             Citizen.Trace("tried to spawn at an invalid spawn index\n")
  236.  
  237.             spawnLock = false
  238.  
  239.             return
  240.         end
  241.  
  242.         -- freeze the local player
  243.         freezePlayer(PlayerId(), true)
  244.  
  245.         -- if the spawn has a model set
  246.         if spawn.model then
  247.             RequestModel(spawn.model)
  248.  
  249.             -- load the model for this spawn
  250.             while not HasModelLoaded(spawn.model) do
  251.                 RequestModel(spawn.model)
  252.  
  253.                 Wait(0)
  254.             end
  255.  
  256.             -- change the player model
  257.             SetPlayerModel(PlayerId(), spawn.model)
  258.  
  259.             -- release the player model
  260.             SetModelAsNoLongerNeeded(spawn.model)
  261.         end
  262.  
  263.         -- preload collisions for the spawnpoint
  264.         RequestCollisionAtCoord(spawn.x, spawn.y, spawn.z)
  265.  
  266.         -- spawn the player
  267.         --ResurrectNetworkPlayer(GetPlayerId(), spawn.x, spawn.y, spawn.z, spawn.heading)
  268.         local ped = GetPlayerPed(-1)
  269.  
  270.         -- V requires setting coords as well
  271.         SetEntityCoordsNoOffset(ped, spawn.x, spawn.y, spawn.z, false, false, false, true)
  272.  
  273.         NetworkResurrectLocalPlayer(spawn.x, spawn.y, spawn.z, spawn.heading, true, true, false)
  274.  
  275.         -- gamelogic-style cleanup stuff
  276.         ClearPedTasksImmediately(ped)
  277.         --SetEntityHealth(ped, 300) -- TODO: allow configuration of this?
  278.         RemoveAllPedWeapons(ped) -- TODO: make configurable (V behavior?)
  279.         ClearPlayerWantedLevel(PlayerId())
  280.  
  281.         -- why is this even a flag?
  282.         --SetCharWillFlyThroughWindscreen(ped, false)
  283.  
  284.         -- set primary camera heading
  285.         --SetGameCamHeading(spawn.heading)
  286.         --CamRestoreJumpcut(GetGameCam())
  287.  
  288.         -- load the scene; streaming expects us to do it
  289.         --ForceLoadingScreen(true)
  290.         --loadScene(spawn.x, spawn.y, spawn.z)
  291.         --ForceLoadingScreen(false)
  292.  
  293.         local time = GetGameTimer()
  294.  
  295.         while (not HasCollisionLoadedAroundEntity(ped) and (GetGameTimer() - time) < 5000) do
  296.             Citizen.Wait(0)
  297.         end
  298.  
  299.         ShutdownLoadingScreen()
  300.  
  301.         if IsScreenFadedOut() then
  302.             DoScreenFadeIn(500)
  303.  
  304.             while not IsScreenFadedIn() do
  305.                 Citizen.Wait(0)
  306.             end
  307.         end
  308.  
  309.         -- and unfreeze the player
  310.         freezePlayer(PlayerId(), false)
  311.  
  312.         TriggerEvent('playerSpawned', spawn)
  313.  
  314.         if cb then
  315.             cb(spawn)
  316.         end
  317.  
  318.         spawnLock = false
  319.     end)
  320. end
  321.  
  322. -- automatic spawning monitor thread, too
  323. local respawnForced
  324. local diedAt
  325.  
  326. Citizen.CreateThread(function()
  327.     -- main loop thing
  328.     while true do
  329.         Citizen.Wait(50)
  330.  
  331.         local playerPed = GetPlayerPed(-1)
  332.  
  333.         if playerPed and playerPed ~= -1 then
  334.             -- check if we want to autospawn
  335.             if autoSpawnEnabled then
  336.                 if NetworkIsPlayerActive(PlayerId()) then
  337.                     if (diedAt and (GetTimeDifference(GetGameTimer(), diedAt) > 2000)) or respawnForced then
  338.                         if autoSpawnCallback then
  339.                             autoSpawnCallback()
  340.                         else
  341.                             spawnPlayer()
  342.                         end
  343.  
  344.                         respawnForced = false
  345.                     end
  346.                 end
  347.             end
  348.  
  349.             if IsEntityDead(playerPed) then
  350.                 if not diedAt then
  351.                     diedAt = GetGameTimer()
  352.                 end
  353.             else
  354.                 diedAt = nil
  355.             end
  356.         end
  357.     end
  358. end)
  359.  
  360. function forceRespawn()
  361.     spawnLock = false
  362.     respawnForced = true
  363. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement