Page 1 of 1

Require location adjacent to water?

Posted: Sun Jan 29, 2017 6:26 pm
by Bizobinator
Is there a way to require an object to be next to water (similar to the offshore pumps)? Does that require:

Code: Select all

type = "offshore-pump"
?

Re: Require location adjacent to water?

Posted: Tue Jan 31, 2017 2:44 am
by Bizobinator
Anyone?

Re: Require location adjacent to water?

Posted: Tue Jan 31, 2017 5:02 am
by Adil
Yes.

Re: Require location adjacent to water?

Posted: Wed Feb 01, 2017 8:23 am
by Klonan
Bizobinator wrote:Is there a way to require an object to be next to water (similar to the offshore pumps)? Does that require:

Code: Select all

type = "offshore-pump"
?
Its not possible to set any limitations like this for now, and the only way to get the behavior is with the offshore-pump type entity

Re: Require location adjacent to water?

Posted: Thu Feb 02, 2017 12:03 am
by aubergine18
I've done something like this with my bridge mod (not yet released)...

I defined a custom offshore-pump entity, and then listen for the events when it's placed and then replace the offshore pump with the actual entity (in my case the ramp at the end of a bridge).

You can use the .orientation (or .rotation, can't quite remember) on the entity to work out which way it's facing and then if needs be map that to the opposite location for your replacement entity.

If you need any additional info let me know, I'll try and check the forums again in a few days.

Re: Require location adjacent to water?

Posted: Fri Feb 03, 2017 5:16 pm
by Bizobinator
aubergine18 wrote:I've done something like this with my bridge mod (not yet released)...

I defined a custom offshore-pump entity, and then listen for the events when it's placed and then replace the offshore pump with the actual entity (in my case the ramp at the end of a bridge).

You can use the .orientation (or .rotation, can't quite remember) on the entity to work out which way it's facing and then if needs be map that to the opposite location for your replacement entity.

If you need any additional info let me know, I'll try and check the forums again in a few days.
Oh wow, that's a neat approach to it. I think I'd definitely like to try that.

I'm also somewhat of a noob to programming, especially in Lua. How do I listen for an event?
Also, will that make my mod take up a bunch of UPS? :P

Thank you so much for your help! :D

Re: Require location adjacent to water?

Posted: Sat Feb 04, 2017 7:33 pm
by aubergine18
EDIT: Ignore this entire comment, I read your post above wrong. In answer to your question *will* it take up loads of UPS: No, it won't, because the events used will only be triggered when user tries to build something.

If your mod is causing UPS drop, it's most likely to be your on_tick handler. Easiest way to solve that is instead of running your code every tick (60 times per second), make it run every X ticks (60/X times per second).

Code: Select all

-- run our code once every X ticks:
local tick_throttle = 30 -- every 1/2 second, so our code runs twice per second

-- event handler function
local function handle_on_tick( event )
  if event.tick % update_throttle == 0 then
    -- your code goes here
  end
end

-- link above event handler to the event
script.on_event( defines.event.on_tick, handle_on_tick )
As for handling the other events and swapping entities, I'll need to go digging through my code - back in a bit...

Re: Require location adjacent to water?

Posted: Sat Feb 04, 2017 8:25 pm
by aubergine18
Rough sketch of code to swap a offshore-pump with some other entity:

Note: There's likely errors in this code, I've not tested it

Code: Select all

-- shortcut to defines.events table
local events = defines.events

-- event groups
-- Note: Some of the event names might change in Factorio 0.15
local built = { events.on_built_entity, events.on_robot_built_entity }
local died  = events.on_entity_died
local mined = { events.on_preplayer_mined_item, events.on_robot_pre_mined }

-- this is the entity that user will place on map
-- must be an offshore-pump type entity (restrict to water edge)
-- entity name is whatever you used in your prototype definition
local placement = "your-placement-entity-name"

-- when the entity above is placed, what does it get replaced with?
-- this can be any entity type, so long as it doesn't collide with water tiles
local replacement = "you-replacement-entity-name"

-- mandatory: handle creation of placement entity
-- and swap to replacement entity
local function handle_placement_built( event )

  -- get details of placed entity
  local placed = event.entity

  -- bail out if not placement entity
  if placed.name ~= placement then return end

  -- store key properties of placed entity
  local dir, pos, player, force, surface

  dir    = placed.direction
  pos    = placed.position
  player  = placed.last_user -- optional
  force  = placed.force
  surface = placed.surface

  -- note: For 'player', it won't be defined if robot built entity
  -- so if you plan on using it you have to check event.robot first
  -- (not included here for sake of brevity)

  -- optional: rotate direction by 180ยบ (depends on what you're trying to do)
  -- robbed from FARL oppositedirection() at
  -- https://github.com/Choumiko/FARL/blob/master/FARL.lua
  dir = (dir + 4) % 8

  -- delete the old entity
  placed.destroy()

  -- now create replacement entity in same location
  replace = surface.create_entity {
    name      = replacement;
    position  = pos;
    direction = dir;
    force     = force;
  }
end

-- optional: handle destruction of replacement entity
function handle_replacement_died( event )

  -- bail out if not relevant entity
  if event.entity.name ~= replacement then return end

  -- your code here
end

-- optional: handle entity mined
local function handle_replacement_mined( event )

  -- bail out if not relevant entity
  if event.entity.name ~= replacement then return end

  -- your code here
end

-- attach handlers to events
script.on_event( built, handle_placement_built )
script.on_event( died, handle_replacement_died )
script.on_event( mined, handle_replacement_mined )

That should hopefully be enough to get you started.

Re: Require location adjacent to water?

Posted: Mon Feb 13, 2017 9:42 pm
by Bizobinator
Thank you so much for that! It has indeed gotten me started, although now I've run into a bug.

Here is the code I've got right now...

Code: Select all

local events = defines.events

local robot_built = events.on_robot_built_entity
local built = events.on_built_entity
local died = events.on_entity_died

local placement = "sewage-pipe-placer"

local replacement = "sewage-pipe"

local function handle_placement_built( event )

	local placed = event.entity
	
	if placed.name ~= placement then return end
	
	local dir, pos, player, force, surface
	
	dir = placed.direction
	pos = place.position
	
	force = placed.force
	
	placed.destroy()
	
	replace = surface.create_entity {
		name = replacement,
		position = pos,
		direction = dir,
		force = force,
	}
end

script.on_event( built, handle_placement_built )

The game loads up fine, the save loads up fine. I can craft the placer item just fine (& it's only viable on the coast! ^_^). However, when I click to place it, I get an error that says:

Code: Select all

Error while running event on_built_entity (ID 6)
__sewage_pipe__/control.lua:15: attempt to index local 'placed' (a nil value)
So, I'm a bit confused (Lua is not my first language :P). Since, in the code that I have, it looks like it should have successfully created the local variable "placed", so that there wouldn't be an out-of-bounds error?

Re: Require location adjacent to water?

Posted: Mon Feb 13, 2017 9:46 pm
by Nexela
local placed = event.entity

should be

local placed = event.created_entity


--Because unfortunately consistency is not Factorios strong suit :)