Jump to content

[QUESTION] Get current spawnpoint position after map starts.


koragg

Recommended Posts

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 xD:

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 by Dutchman101
Fix topic title for section requirements
Link to comment

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

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...