koragg Posted May 28, 2017 Share Posted May 28, 2017 (edited) In short, when I press 3 on my keyboard my spawnpoint changes to the one which is closest to the first checkpoint of the map. But I want to compare if my current spawnpoint is actually the one which is closest to first checkpoint. As if I get auto-spawned in the closest spawnpoint by MTA itself there's no point in charging me with 7 coins to 'change' my spawnpoint (it won't change as the one I'm in is already the closest one). Any ideas? This is the whole script: ----------------- --- Spawns --- ----------------- local spawnIndex = {} local allSpawnpoints = {} ------------------------------------------------------------------------------------------------------------------------ function mapRestart(mapInfo, mapOptions, gameOptions) previousSpawn = {} spawnIndex = {} lshift, rshift = {}, {} allSpawnpoints = getElementsByType("spawnpoint", getResourceRootElement(exports.mapmanager:getRunningGamemodeMap())) if #getElementsByType("checkpoint") > 0 then table.sort(allSpawnpoints, function (spawnA, spawnB) local a_x, a_y, a_z, a_id = getSpawnpointPosition ( spawnA ) local b_x, b_y, b_z, b_id = getSpawnpointPosition ( spawnB ) local c_x, c_y, c_z = getElementPosition(getElementsByType("checkpoint")[1]) return getDistanceBetweenPoints3D( a_x, a_y, a_z, c_x, c_y, c_z) < getDistanceBetweenPoints3D( b_x, b_y, b_z, c_x, c_y, c_z) end) end if #allSpawnpoints == 0 then return false end for k,v in ipairs(getElementsByType("player")) do setElementData(v, "hasBoughtSpawn", false) end end addEventHandler("onMapStarting", root, mapRestart) ------------------------------------------------------------------------------------------------------------------------ function callSpawn(player) local spawnPrice = 7 local playeraccount = getPlayerAccount(player) local res = getResourceFromName("cw") if getResourceState(res) == "running" then return end local account = getPlayerAccount(player) if isGuestAccount(account) then outputChatBox("You need to register and login in order to buy spawnpoints!", player, 255, 153, 0, true) return end if #allSpawnpoints == 1 then outputChatBox("This map contains only one spawnpoint.", player, 255, 153, 0, true) return end if #allSpawnpoints == 0 then return false end local elementID local cash = tonumber(getAccountData(account, "knightcoins") or 0) if cash < spawnPrice or not cash then outputChatBox ( "You don't have enough KnightCoins to buy a spawn.", player, 255, 153, 0) return end if getElementData(player, "isOnSpawn") and getElementData(player, "isOnSpawn") == true then if not spawnIndex[player] then elementID, distance, index, rot = changeSpawn(player) outputChatBox("Use shift+3 to go back to a previous spawnpoint", player, 0, 255, 255) elseif getPedOccupiedVehicle(player) then elementID, distance, index, rot = changeSpawn(player) end local model = getElementModel(getPedOccupiedVehicle(player)) local rotation = rot if elementID then outputChatBox("Changed to spawnpoint: "..tostring(index).." / "..round(distance).." m / vehicle: "..tostring(getVehicleNameFromModel(model)).." ("..model..") / rotation: "..round(tonumber(rotation)), player, 0, 255, 255) end if getElementData(player, "hasBoughtSpawn") == true then return end local cash = tonumber(getAccountData(account, "knightcoins") or 0) if cash >= spawnPrice then local newCash = cash - spawnPrice setAccountData(account, "knightcoins", newCash) setElementData(player ,"data.knightcoins", newCash, true) triggerClientEvent(player, "addNotification", root, "#FF0000-"..spawnPrice.." #00FFFFKnightCoins #00FF00("..comma_value(newCash)..")", 2) local oldMoneySpentData = getAccountData(playeraccount, "moneySpent") or 0 local newMoneySpentData = oldMoneySpentData + spawnPrice setAccountData(playeraccount, "moneySpent", newMoneySpentData) setElementData(player, "moneySpent", newMoneySpentData) end else setElementData(player, "hasBoughtSpawn", false) end setElementData(player, "hasBoughtSpawn", true) end ------------------------------------------------------------------------------------------------------------------------ function changeSpawn(player) if not spawnIndex[player] then spawnIndex[player] = 1 else spawnIndex[player] = spawnIndex[player] + (getShiftState(player) and -1 or 1) end if spawnIndex[player] > #allSpawnpoints then spawnIndex[player] = 1 elseif spawnIndex[player] < 1 then spawnIndex[player] = #allSpawnpoints end local newSpawnpoint = allSpawnpoints[spawnIndex[player]] local veh = getPedOccupiedVehicle(player) if not veh then return end local x, y, z, id, vehID, rot = getSpawnpointPosition(newSpawnpoint) setElementPosition(veh, x,y,z) setElementRotation(veh, 0,0, rot) setElementModel(veh, vehID) setElementHealth(veh, 1000) local distance = getElementsByType("checkpoint")[1] and math.floor(100*getDistanceBetweenPoints3D(x,y,z,getElementPosition(getElementsByType("checkpoint")[1])))/100 or 0 return id, distance, spawnIndex[player], rot end ------------------------------------------------------------------------------------------------------------------------ function getSpawnpointPosition(element) local x = tonumber(getElementData(element, 'posX')) local y = tonumber(getElementData(element, 'posY')) local z = tonumber(getElementData(element, 'posZ')) local id = getElementID(element) local vehID = tonumber(getElementData(element, 'vehicle')) local rot = tonumber(getElementData(element, 'rotation') or getElementData(element, 'rotZ')) return x, y, z, id, vehID, rot end --------------------------- --- Shift detection --- --------------------------- local lshift, rshift = {}, {} function shift(player, key, state) if key == "lshift" then lshift[player] = state == "down" and true or nil elseif key == "rshift" then rshift[player] = state == "down" and true or nil end end ------------------------------------------------------------------------------------------------------------------------ function onResStart() for k,v in ipairs(getElementsByType("player")) do bindKey(v, "lshift", "both", shift) bindKey(v, "rshift", "both", shift) bindKey(v, "3", "down", callSpawn) end end addEventHandler("onResourseStart", resourceRoot, onResStart) ------------------------------------------------------------------------------------------------------------------------ function onPlayerJoin() bindKey(source, "lshift", "both", shift) bindKey(source, "rshift", "both", shift) bindKey(source, "3", "down", callSpawn) end addEventHandler("onPlayerJoin", root, onPlayerJoin) ------------------------------------------------------------------------------------------------------------------------ function onPlayerQuit() lshift[source] = nil rshift[source] = nil end addEventHandler("onPlayerQuit", root, onPlayerQuit) ------------------------------------------------------------------------------------------------------------------------ function getShiftState(player) return lshift[player] or rshift[player] end ------------------------------------------------------------------------------------------------------------------------ --http://lua-users.org/wiki/FormattingNumbers function round(val, decimal) if (decimal) then return math.floor( (val * 10^decimal) + 0.5) / (10^decimal) else return math.floor(val+0.5) end end ------------------------------------------------------------------------------------------------------------------------ --http://lua-users.org/wiki/FormattingNumbers function comma_value(amount) local formatted = amount while true do formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') if (k==0) then break end end return formatted end And a small command I made to get the coordinates of spawnpoint1 (NOT the closest one to 1st checkpoint) and those of my vehicle in hope to somehow see how to get spawnpoint coords out of my vehicle's coords but no luck so far : local allSpawnpoints = {} function onMapStart() allSpawnpoints = getElementsByType("spawnpoint", getResourceRootElement(exports.mapmanager:getRunningGamemodeMap())) end addEventHandler("onMapStarting", root, onMapStart) function test(player) local newSpawnpoint = allSpawnpoints[1] local x, y, z, id, vehID, rot = getSpawnpointPosition(newSpawnpoint) local xx, yy, zz = getElementPosition(getPedOccupiedVehicle(player)) outputChatBox(x..", "..y..", "..z) outputChatBox(xx..", "..yy..", "..zz) end addCommandHandler("go", test) function getSpawnpointPosition(element) local x = tonumber(getElementData(element, 'posX')) local y = tonumber(getElementData(element, 'posY')) local z = tonumber(getElementData(element, 'posZ')) local id = getElementID(element) local vehID = tonumber(getElementData(element, 'vehicle')) local rot = tonumber(getElementData(element, 'rotation') or getElementData(element, 'rotZ')) return x, y, z, id, vehID, rot end So if a player gets spawned in the closest to the first checkpoint spawn I want to just do 'return' and not take any coins from them as they already will be in the spawn that otherwise they have to buy. Edited May 28, 2017 by Dutchman101 Fix topic title for section requirements Link to comment
idarrr Posted May 28, 2017 Share Posted May 28, 2017 Not sure if it's gonna work. This function will return the closest spawn point coordinate from the player coordinate nearSP = {} function getSpawnpointPosition(player) -- The argument her is the player, cuz we need to get their coor local px, py, pz = getElementPosition(player) for i, v in ipairs(allSpawnpoints) do -- Loop all spawn point to get closest sp local x = tonumber(getElementData(v, 'posX')) local y = tonumber(getElementData(v, 'posY')) local z = tonumber(getElementData(v, 'posZ')) local dist = getDistanceBetweenPoints3D(x, y, z, px, py, pz) if not nearSP[player] then nearSP[player] == {v, dist} elseif nearSP[player][2] > dist then -- If the distance is closest then the other, store it here nearSP[player] == {v, dist} -- v = the spawn point element, dist = the distance end end local id = getElementID(nearSP[player][1]) local vehID = tonumber(getElementData(nearSP[player][1], 'vehicle')) local rot = tonumber(getElementData(nearSP[player][1], 'rotation') or getElementData(nearSP[player][1], 'rotZ')) nearSP[player] = nil return x, y, z, id, vehID, rot end -- Then call this getSpawnpointPosition(player) Link to comment
koragg Posted May 31, 2017 Author Share Posted May 31, 2017 I'll try it in a week or two. Literally buried in exams right now... Link to comment
koragg Posted June 3, 2017 Author Share Posted June 3, 2017 OK, fixed it by using element data logic. Works like a charm now, and yes I used the player's position to see if he's inside the closest spawnpoint. ----------------- --- Spawns --- ----------------- local spawnIndex = {} local allSpawnpoints = {} ------------------------------------------------------------------------------------------------------------------------ function mapRestart(mapInfo, mapOptions, gameOptions) previousSpawn = {} spawnIndex = {} lshift, rshift = {}, {} allSpawnpoints = getElementsByType("spawnpoint", getResourceRootElement(exports.mapmanager:getRunningGamemodeMap())) if #getElementsByType("checkpoint") > 0 then table.sort(allSpawnpoints, function (spawnA, spawnB) local a_x, a_y, a_z, a_id = getSpawnpointPosition ( spawnA ) local b_x, b_y, b_z, b_id = getSpawnpointPosition ( spawnB ) local c_x, c_y, c_z = getElementPosition(getElementsByType("checkpoint")[1]) return getDistanceBetweenPoints3D( a_x, a_y, a_z, c_x, c_y, c_z) < getDistanceBetweenPoints3D( b_x, b_y, b_z, c_x, c_y, c_z) end) end if #allSpawnpoints == 0 then return false end for k,v in ipairs(getElementsByType("player")) do setElementData(v, "hasBoughtSpawn", false) setElementData(v, "seenShiftCmd", false) setElementData(v, "pressed3", false) setElementData(v, "seenClosestMsg", false) end end addEventHandler("onMapStarting", root, mapRestart) ------------------------------------------------------------------------------------------------------------------------ function callSpawn(player) local spawnPrice = 7 local playeraccount = getPlayerAccount(player) local res = getResourceFromName("cw") if getResourceState(res) == "running" then return end local account = getPlayerAccount(player) if isGuestAccount(account) then outputChatBox("You need to register and login in order to buy spawnpoints!", player, 255, 153, 0, true) return end if #allSpawnpoints == 1 then outputChatBox("This map contains only one spawnpoint.", player, 255, 153, 0, true) return end if #allSpawnpoints == 0 then return false end local elementID local cash = tonumber(getAccountData(account, "knightcoins") or 0) if cash < spawnPrice or not cash then outputChatBox ( "You don't have enough KnightCoins to buy a spawn.", player, 255, 153, 0) return end local xx, yy, zz = getElementPosition(getPedOccupiedVehicle(player)) if getElementData(player, "isOnSpawn") and getElementData(player, "isOnSpawn") == true then if not spawnIndex[player] or getPedOccupiedVehicle(player) then elementID, distance, index, rot = changeSpawn(player) end local sx, sy, sz = getElementPosition(getPedOccupiedVehicle(player)) if round(sx) == round(xx) and round(sy) == round(yy) and round(sz) == round(zz) then if getElementData(player, "pressed3") == false then outputChatBox("You're already in the closest to the first checkpoint spawnpoint.", player, 255, 153, 0) setElementData(player, "seenClosestMsg", true) end end if getElementData(player, "seenClosestMsg") == true then setElementData(player, "seenClosestMsg", false) return end if getElementData(player, "seenShiftCmd") == false and getElementData(player, "seenClosestMsg") == false then outputChatBox("Use shift+3 to go back to a previous spawnpoint", player, 0, 255, 255) setElementData(player, "seenShiftCmd", true) end local model = getElementModel(getPedOccupiedVehicle(player)) local rotation = rot if elementID and getElementData(player, "seenClosestMsg") == false then outputChatBox("Changed to spawnpoint: "..tostring(index).." / "..round(distance).." m / vehicle: "..tostring(getVehicleNameFromModel(model)).." ("..model..") / rotation: "..round(tonumber(rotation)), player, 0, 255, 255) end if getElementData(player, "hasBoughtSpawn") == true then return end local cash = tonumber(getAccountData(account, "knightcoins") or 0) if cash >= spawnPrice and getElementData(player, "seenClosestMsg") == false then local newCash = cash - spawnPrice setAccountData(account, "knightcoins", newCash) setElementData(player ,"data.knightcoins", newCash, true) triggerClientEvent(player, "addNotification", root, "#FF0000-"..spawnPrice.." #00FFFFKnightCoins #00FF00("..comma_value(newCash)..")", 2) local oldMoneySpentData = getAccountData(playeraccount, "moneySpent") or 0 local newMoneySpentData = oldMoneySpentData + spawnPrice setAccountData(playeraccount, "moneySpent", newMoneySpentData) setElementData(player, "moneySpent", newMoneySpentData) end else setElementData(player, "hasBoughtSpawn", false) end setElementData(player, "hasBoughtSpawn", true) end ------------------------------------------------------------------------------------------------------------------------ function changeSpawn(player) if not spawnIndex[player] then spawnIndex[player] = 1 else spawnIndex[player] = spawnIndex[player] + (getShiftState(player) and -1 or 1) end if spawnIndex[player] > #allSpawnpoints then spawnIndex[player] = 1 elseif spawnIndex[player] < 1 then spawnIndex[player] = #allSpawnpoints end local newSpawnpoint = allSpawnpoints[spawnIndex[player]] local veh = getPedOccupiedVehicle(player) if not veh then return end local x, y, z, id, vehID, rot = getSpawnpointPosition(newSpawnpoint) setElementPosition(veh, x,y,z) setElementRotation(veh, 0,0, rot) setElementModel(veh, vehID) setElementHealth(veh, 1000) local distance = getElementsByType("checkpoint")[1] and math.floor(100*getDistanceBetweenPoints3D(x,y,z,getElementPosition(getElementsByType("checkpoint")[1])))/100 or 0 return id, distance, spawnIndex[player], rot end ------------------------------------------------------------------------------------------------------------------------ function getSpawnpointPosition(element) local x = tonumber(getElementData(element, 'posX')) local y = tonumber(getElementData(element, 'posY')) local z = tonumber(getElementData(element, 'posZ')) local id = getElementID(element) local vehID = tonumber(getElementData(element, 'vehicle')) local rot = tonumber(getElementData(element, 'rotation') or getElementData(element, 'rotZ')) return x, y, z, id, vehID, rot end --------------------------- --- Shift detection --- --------------------------- local lshift, rshift = {}, {} function shift(player, key, state) if key == "lshift" then lshift[player] = state == "down" and true or nil elseif key == "rshift" then rshift[player] = state == "down" and true or nil end end ------------------------------------------------------------------------------------------------------------------------ function onResStart() for k,v in ipairs(getElementsByType("player")) do bindKey(v, "lshift", "both", shift) bindKey(v, "rshift", "both", shift) bindKey(v, "3", "down", callSpawn) end end addEventHandler("onResourseStart", resourceRoot, onResStart) ------------------------------------------------------------------------------------------------------------------------ function onPlayerJoin() bindKey(source, "lshift", "both", shift) bindKey(source, "rshift", "both", shift) bindKey(source, "3", "down", callSpawn) end addEventHandler("onPlayerJoin", root, onPlayerJoin) ------------------------------------------------------------------------------------------------------------------------ function onPlayerQuit() lshift[source] = nil rshift[source] = nil end addEventHandler("onPlayerQuit", root, onPlayerQuit) ------------------------------------------------------------------------------------------------------------------------ function getShiftState(player) return lshift[player] or rshift[player] end ------------------------------------------------------------------------------------------------------------------------ --http://lua-users.org/wiki/FormattingNumbers function round(val, decimal) if (decimal) then return math.floor( (val * 10^decimal) + 0.5) / (10^decimal) else return math.floor(val+0.5) end end ------------------------------------------------------------------------------------------------------------------------ --http://lua-users.org/wiki/FormattingNumbers function comma_value(amount) local formatted = amount while true do formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') if (k==0) then break end end return formatted end ------------------------------------------------------------------------------------------------------------------------ function getAll(name) local result = {} for i,element in ipairs(getElementsByType(name)) do result[i] = {} result[i].id = getElementID(element) or i local position = { tonumber(getElementData(element,"posX")), tonumber(getElementData(element,"posY")), tonumber(getElementData(element,"posZ")) } result[i].position = position; end return result end Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now