FFA mode - Random Spawn and own faction

Place to get help with not working mods / modding interface.
Scerchy
Manual Inserter
Manual Inserter
Posts: 4
Joined: Sun Mar 27, 2016 11:09 pm
Contact:

FFA mode - Random Spawn and own faction

Post 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).
User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5410
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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
User avatar
prg
Filter Inserter
Filter Inserter
Posts: 947
Joined: Mon Jan 19, 2015 12:39 am
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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.
Automatic Belt (and pipe) Planner—Automate yet another aspect of constructing your factory!
Scerchy
Manual Inserter
Manual Inserter
Posts: 4
Joined: Sun Mar 27, 2016 11:09 pm
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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
orzelek
Smart Inserter
Smart Inserter
Posts: 3928
Joined: Fri Apr 03, 2015 10:20 am
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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).
Scerchy
Manual Inserter
Manual Inserter
Posts: 4
Joined: Sun Mar 27, 2016 11:09 pm
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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. :)
User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5410
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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}
Scerchy
Manual Inserter
Manual Inserter
Posts: 4
Joined: Sun Mar 27, 2016 11:09 pm
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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 ;(
User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5410
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: FFA mode - Random Spawn and own faction

Post 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
Post Reply

Return to “Modding help”