Require location adjacent to water?

Place to get help with not working mods / modding interface.
Post Reply
Bizobinator
Fast Inserter
Fast Inserter
Posts: 193
Joined: Fri May 06, 2016 10:35 pm
Contact:

Require location adjacent to water?

Post 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"
?

Bizobinator
Fast Inserter
Fast Inserter
Posts: 193
Joined: Fri May 06, 2016 10:35 pm
Contact:

Re: Require location adjacent to water?

Post by Bizobinator »

Anyone?

User avatar
Adil
Filter Inserter
Filter Inserter
Posts: 945
Joined: Fri Aug 15, 2014 8:36 pm
Contact:

Re: Require location adjacent to water?

Post by Adil »

Yes.
I do mods. Modding wiki is friend, it teaches how to mod. Api docs is friend too...
I also update mods, some of them even work.
Recently I did a mod tutorial.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5150
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Require location adjacent to water?

Post 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

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: Require location adjacent to water?

Post 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.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

Bizobinator
Fast Inserter
Fast Inserter
Posts: 193
Joined: Fri May 06, 2016 10:35 pm
Contact:

Re: Require location adjacent to water?

Post 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

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: Require location adjacent to water?

Post 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...
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: Require location adjacent to water?

Post 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.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.

Bizobinator
Fast Inserter
Fast Inserter
Posts: 193
Joined: Fri May 06, 2016 10:35 pm
Contact:

Re: Require location adjacent to water?

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

Nexela
Smart Inserter
Smart Inserter
Posts: 1828
Joined: Wed May 25, 2016 11:09 am
Contact:

Re: Require location adjacent to water?

Post by Nexela »

local placed = event.entity

should be

local placed = event.created_entity


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

Post Reply

Return to “Modding help”