Page 1 of 1

FFA mode - Random Spawn and own faction

Posted: Sun Mar 27, 2016 11:15 pm
by Scerchy
Hello

I'm trying to create a FFA scenario to play with my friends. This mode will allow us to have our own bases, our own research all seperatly but a non-hostile faction treatie.
For this mode I'd like to have the following setup:
-Random Faction (based on player name - works)
-Random Spawn (doesn't work)

Here's the current code that I use:

Code: Select all

script.on_event(defines.events.on_player_created, function(event)
  local player = game.get_player(event.player_index)
  player.insert{name="iron-plate", count=8}
  player.insert{name="pistol", count=1}
  player.insert{name="basic-bullet-magazine", count=10}
  player.insert{name="burner-mining-drill", count = 1}
  player.insert{name="stone-furnace", count = 1}
  setForce(player)
end)
d = 32*3
bd = d*3
function setForce(player)
   pforces = {}; 
   for _, player in ipairs(game.players) do
	local fname = "player_" .. player.name; 
	local force = game.forces[fname] or game.create_force(fname); 
	player.force = force; 
	for _, pforce in ipairs(pforces) do 
	pforce.set_cease_fire(force.name, true);
	force.set_cease_fire(pforce.name, true)
   end;
   pforces[#pforces+1] = force 
   end
   setForcespawn(force,player)
end
function setForcespawn(force,player)
   s = game.surfaces.nauvis
   local x = math.random(320,960)
   local y = math.random(320,960)
   local pos ={x, y}
   game.forces["player"].chart(s,{{ x - bd,  y -bd}, { x + bd,  y + bd}} )
   local position = s.find_non_colliding_position("player",pos, 64,4)
   player.teleport(pos,s)
   if position ~= nil then
   for k, p in pairs (game.players) do
	p.print(position.x.." "..position.y)
   end
   force.set_spawn_position({position.x,position.y},s)
   player.teleport(position,s)
   for k, entity in pairs(s.find_entities_filtered({area={{position.x - bd, position.y -bd}, {position.x + bd, position.y + bd}}, force= "enemy"})) do
        entity.destroy()
   end
	else for k, p in pairs (game.players) do 
      p.print("Map unsutitable, please restart")
    end
	end
end
The issue is that I always get the 'map unsuitable' error when I make the game. This means that local position = s.find_non_colliding_position("player",pos, 64,4) is always nil (I've tested this over 50x, even nill when in some cases I get teleported to a suitable spot).

I hope that you know why the method returns nil and how I can solve this issue.
Thanks in advance
Also I'd like to have some general tips on how to debug in LUA. I'm a java developper myself and I can't seem to log any data anywhere (except for messaging players, but when nill, it terminates the game).

Re: FFA mode - Random Spawn and own faction

Posted: Sun Mar 27, 2016 11:45 pm
by Klonan
The reason the position might be nil, even if its suitable, is because it hasn't been charted before the player is teleported there,
Thus the game is trying to find a position on some place which there are no tiles generated yet

Re: FFA mode - Random Spawn and own faction

Posted: Mon Mar 28, 2016 8:07 am
by prg
Scerchy wrote:Also I'd like to have some general tips on how to debug in LUA. I'm a java developper myself and I can't seem to log any data anywhere (except for messaging players, but when nill, it terminates the game).
log() writes to the log file. print() writes to stdout. debug.traceback() returns a string that might be useful to figure out how you got somewhere.

Re: FFA mode - Random Spawn and own faction

Posted: Mon Mar 28, 2016 8:44 am
by Scerchy
Klonan wrote:The reason the position might be nil, even if its suitable, is because it hasn't been charted before the player is teleported there,
Thus the game is trying to find a position on some place which there are no tiles generated yet
How should I chart this?

Code: Select all

game.forces["player"].chart(s,{{ x - bd,  y -bd}, { x + bd,  y + bd}} )
   local position = s.find_non_colliding_position("player",pos, 64,4)

nor

Code: Select all

player.force.chart(s,{{ x - bd,  y -bd}, { x + bd,  y + bd}} )
   local position = s.find_non_colliding_position("player",pos, 64,4)
seems to help

Re: FFA mode - Random Spawn and own faction

Posted: Mon Mar 28, 2016 10:57 am
by orzelek
I'm guessing a bit here: chart command is not instant. You need to call chart and then wait a bit before trying to place player there. By waiting I mean your script needs to exit and schedule this on later tick(or few ticks after).

Re: FFA mode - Random Spawn and own faction

Posted: Mon Mar 28, 2016 5:04 pm
by Scerchy
After some testing I'm still unable to resolve the issue.

I've updated my code to work with the game ticks (for a delay of 30s to chart)
However, I've let my code run for over 20 mins with the is_chunk_charted check and it kept returning false so I still don't know how to teleport the player safely...
If you have any experience using the charting function, all feedback is welcome.

Current code:

Code: Select all

d = 32*3
bd = d*3
script.on_event(defines.events.on_player_created, function(event)
  global.player = game.get_player(event.player_index)
  global.player.insert{name="iron-plate", count=8}
  global.player.insert{name="pistol", count=1}
  global.player.insert{name="basic-bullet-magazine", count=10}
  global.player.insert{name="burner-mining-drill", count = 1}
  global.player.insert{name="stone-furnace", count = 1}
  global.force_x = math.random(320,960)
  global.force_y = math.random(320,960)
  global.force_pos = {global.force_x .. global.force_y}
  global.player.print("X"..global.force_x .."Y"..global.force_y)
  global.force_area={{global.force_x - d,global.force_y - d},{global.force_x + d,global.force_y + d}}
  make_force(global.player)
end)

function make_force(player)
	game.forces.player.chart(game.player.surface,{{global.force_x - bd,  global.force_y -bd},{global.force_x + bd,global.force_y + bd}})
	global.pforces = {}; 
	local fname = "player_" .. player.name; 
	global.force = game.forces[fname] or game.create_force(fname); 
	player.force = global.force; 
	for _, pforce in ipairs(global.pforces) do 
		pforce.set_cease_fire(global.force.name, true);
		global.force.set_cease_fire(pforce.name, true)
	end;
   global.pforces[#global.pforces+1] = force 
   
	global.now = game.tick
	
end
script.on_event(defines.events.on_tick, function(event)
	local i = 0;
	if global.now == game.tick then
		i = 0;
		global.player.print("Your spawn will be set in 30s. You'll be teleported to this location aswell")
	end
	if game.tick == global.now + ((25+i)*60)then
		global.player.print(5-i .." secs remaining")
		i = i + 1
	end
	if i == 5 then
		set_spawn()
		global.now = 0;
	end
	local chunkX = math.floor(global.force_x / 32)
	local chunkY = math.floor(global.force_y / 32)
	global.player.print("X"..chunkX .. "Y"..chunkY)
	global.player.print(tostring(game.player.force.is_chunk_charted(game.player.surface, {chunkX, chunkY})))
end)
function set_spawn(force)
	s = game.surfaces.nauvis
	local position = s.find_non_colliding_position("player",  global.force_pos, 64,4)
	if position ~= nil then
		for k, p in pairs (game.players) do
		p.print(position.x.." "..position.y)
		end
		global.force.set_spawn_position({position.x,position.y},s)
		player.teleport(position,s)
		for k, entity in pairs(s.find_entities_filtered({area={{position.x - bd, position.y -bd}, {position.x + bd, position.y + bd}}, force= "enemy"})) do
		entity.destroy()
		end
	else for k, p in pairs (game.players) do 
		p.print("Map unsuitable, please restart")
		end
	end
end
Another issue is that the game ticks check with i is only firing once with i = 0...
If anyone has a fix for this, that would be great. :)

Re: FFA mode - Random Spawn and own faction

Posted: Mon Mar 28, 2016 7:53 pm
by Klonan
I think i foudn the issue:

Code: Select all

global.force_pos = {global.force_x .. global.force_y}
You concatenated the values, where they should be like

Code: Select all

global.force_pos = {global.force_x , global.force_y}

Re: FFA mode - Random Spawn and own faction

Posted: Mon Mar 28, 2016 8:25 pm
by Scerchy
Klonan wrote:I think i foudn the issue:

Code: Select all

global.force_pos = {global.force_x .. global.force_y}
You concatenated the values, where they should be like

Code: Select all

global.force_pos = {global.force_x , global.force_y}
That could have been the issue indeed but sadly, this getting the nil as answer ;(

Re: FFA mode - Random Spawn and own faction

Posted: Mon Mar 28, 2016 8:36 pm
by Klonan
I don't like the way you set the global values,
I'd do it like this,

>New player joins

Code: Select all

local i = event.entity.index
local f = game.create_force(game.players[i].name) --call the force the players name
f.set_spawn_position(game.players[i].surface, {math.random(10,100), math.random(10,100)})
local p = f.get_spawn_position
local a = {{p.x - 100, p.y - 100},{p.x + 100, p.y +100}}
And so on, calling all teh value now around the spawn location,
With your way, if another player joins, all the global values will be remade