Jump to content

Dynamic race markers/checkpoints


Recommended Posts

So I'm trying to make a race with dynamic checkpoints (using markers). The basic logic is as such:

  • First two checkpoints are created at the start
  • When you hit Checkpoint_1...
    • Checkpoint_1 is destroyed
    • Checkpoint_3 is created
  • Keep going until the last checkpoint.

So basically just like the Race Resource checkpoints, except respawning isn't a concern because it's a deathmatch anyway so if you're dead you're out.

It works fine in the editor (in single player) but the issue I have is that when I test it with another player when either one of you hits a marker it is destroyed for both players.

Client

function markerHandler(hitElement)
   if(hitElement == localPlayer) then
      if(source == cp1) then
        --create/destroy markers and blips, etc
      end
      if(source == cp2) then
        --create/destroy markers and blips, etc
      end
      if(source == cp3) then
        --create/destroy markers and blips, etc
      	endGame()
      end
   end
end
addEventHandler("onClientMarkerHit", getRootElement(), markerHandler)

So is there any way to only see and affect the markers created on your own client? Or is this way more complicated than my nooby scripting skills will allow?

(I did initially try to do it serverside but it fried my brain so I figured clientside would be simpler)

Link to comment
  • Moderators
1 hour ago, [FOTL]Aphex said:

So is there any way to only see and affect the markers created on your own client?

Clientside is basically that.

Every client=player runs a copy of the same code on their own pc and the (variable) data is not shared.

 

Going for clientside?

As long as you do not mind the following, go for it!

  • Cheater can take advantage of this. (for example being able to win in an instance)
  • It is harder to maintain round management/win/lose etc.

Note: Remote players(other players than yourself) can also trigger some events in your copy of the code. So adding checks like this are important:

if(hitElement == localPlayer) then

 

Going for serverside?

  • Using tables is an essential for the serverside version of your current code. ⚠️ If you want to create bug free code on serverside, it is one of the things you have to master first. Tables are used to give every player their own piece of data, for example to keep track of the race/checkpoint progress for every player separately.

 

1 hour ago, [FOTL]Aphex said:

but it fried my brain so I figured clientside would be simple

Simple does not always equal better unfortunately. Give serverside a try if you are ready for it, but shouldn't be ignored completely. You are playing a multiplayer game after all.

Link to comment
45 minutes ago, IIYAMA said:

Going for serverside?

  • Using tables is an essential for the serverside version of your current code. ⚠️ If you want to create bug free code on serverside, it is one of the things you have to master first. Tables are used to give every player their own piece of data, for example to keep track of the race/checkpoint progress for every player separately.

 

Thanks a lot for the reply.

So I'm familiar with tables but I'm not sure I understand how such a table would be for keeping track of individual checkpoint progress, would it be something like this? With a `for` loop checking/dictating which markers are visible to which players?

c = {
	{player_1, checkpoint_reached},
	{player_2, checkpoint_reached},
	{player_3, checkpoint_reached},
  	...
}

Before I tried it with `set` and `getElementData` but i must have done something wrong because it didn't work as intended... So yeah, I think I'll leave serverside until I'm a bit more confident with my scripting abilities lol.

But for now you think my clientside script with ...

if(hitElement == localPlayer) then

...SHOULD work? Maybe??

(I haven't had the opportunity to test it with someone else since I changed to that)

Link to comment
  • Moderators

You could use for the markers:

local markers = {
	{	-- marker data
		otherProp = '????',
		element = '<marker element>'
	},
	{	-- marker data
		otherProp = '????',
		element = '<marker element>'
	},
}

 

20 hours ago, [FOTL]Aphex said:

With a `for` loop checking/dictating which markers are visible to which players?

Loops are not needed if you use the `player` as key.

 

And as for the players and their data:

---@type {[userdata]: {[string]: any}}
local playerData = {}

--- Give a player their own table/data
---@param player userdata
function initPlayerData(player)
	if playerData[player] then return end
	playerData[player] = {} -- < sub table
end

---@param player userdata
---@param key string
---@param data any
function setPlayerData(player, key, data)
	if not playerData[player] then return end
	playerData[player][key] = data
end

---@param player userdata
---@param key string
---@return unknown|nil
function getPlayerData(player, key)
	if not playerData[player] then return end
	return playerData[player][key]
end

Usage example:

--- SET
setPlayerData(player, "nextMarker", marker)

--- GET
local marker = getPlayerData(player, "nextMarker")

 

 

 

  • Like 1
Link to comment
47 minutes ago, IIYAMA said:

You could use for the markers:

local markers = {
	{	-- marker data
		otherProp = '????',
		element = '<marker element>'
	},
	{	-- marker data
		otherProp = '????',
		element = '<marker element>'
	},
}

 

Loops are not needed if you use the `player` as key.

 

And as for the players and their data:

---@type {[userdata]: {[string]: any}}
local playerData = {}

--- Give a player their own table/data
---@param player userdata
function initPlayerData(player)
	if playerData[player] then return end
	playerData[player] = {} -- < sub table
end

---@param player userdata
---@param key string
---@param data any
function setPlayerData(player, key, data)
	if not playerData[player] then return end
	playerData[player][key] = data
end

---@param player userdata
---@param key string
---@return unknown|nil
function getPlayerData(player, key)
	if not playerData[player] then return end
	return playerData[player][key]
end

Usage example:

--- SET
setPlayerData(player, "nextMarker", marker)

--- GET
local marker = getPlayerData(player, "nextMarker")

 

 

 

Thanks again, your knowledge and insight are very much appreciated.

I bit the bullet and installed a VM to test my map with more than one player and, miracle of miracles, it worked!

I'll definitely use your examples in future though... serverside stuff still scares me a bit lol

  • Like 1
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...