This little code i wrote for my mod The Underground is a way for you to create for example ruins that you want to spawn randomly around the map.
The building can be created in singleplayer and then copied to a file by using a command.
Lisence: Free !
But don't claim it's yours. Ok ^_^?
What does it let you do?
--Copy tiles
--Copy entities
--Easily changable to have it set certain entities as part of the player's force so the player can use it
How to add this functionality to your mod?
add to your mod
Basically you have to put these two functions into your mod:
function uploadBuilding()
--Reseting all tables
global.names = {}
global.positions = {}
global.entPosition = {}
global.positionsX = {}
global.positionsY = {}
--tile tables
global.tileNames = {}
global.tilePosX = {}
global.tilePosY = {}
--find the top left corner(marked by a small electric pole(should prob be its own entity)
results = game.surfaces["nauvis"].find_entities_filtered{area = {{game.players[1].position.x -searchDist, game.players[1].position.y -searchDist}, {game.players[1].position.x +searchDist, game.players[1].position.y +searchDist}}, name = "small-electric-pole"}
for d,ent in pairs(results) do
topRightMarker = ent
end
--Find the bottom right corner(marked by a burner mining drill)
results = game.surfaces["nauvis"].find_entities_filtered{area = {{game.players[1].position.x -searchDist, game.players[1].position.y -searchDist}, {game.players[1].position.x +searchDist, game.players[1].position.y +searchDist}}, name = "stone-furnace"}
for d,ent in pairs(results) do
bottomLeftMarker = ent
end
areaWidth = topRightMarker.position.x - bottomLeftMarker.position.x
areaHeight = bottomLeftMarker.position.y - topRightMarker.position.y
searchX = bottomLeftMarker.position.x - areaWidth
searchY = bottomLeftMarker.position.y + areaHeight
results = game.surfaces["nauvis"].find_entities{{bottomLeftMarker.position.x, bottomLeftMarker.position.y-areaHeight}, {bottomLeftMarker.position.x+areaWidth, bottomLeftMarker.position.y}}
for d,ent in pairs(results) do
if ent.name ~= "player" then
global.positionsX[#global.positionsX+1] = ent.position.x - bottomLeftMarker.position.x
global.positionsY[#global.positionsY+1] = ent.position.y - topRightMarker.position.y
table.insert(global.names, ent.name)
end
end
game.makefile("buildings/names.lua", serpent.dump(global.names))
game.makefile("buildings/positionsx.lua", serpent.dump(global.positionsX))
game.makefile("buildings/positionsy.lua", serpent.dump(global.positionsY))
--Note down all the tiles
for w = 1, areaWidth do
for h = 1, areaHeight do
curTil = game.surfaces["nauvis"].get_tile(bottomLeftMarker.position.x+w, topRightMarker.position.y+h)
global.tilePosX[#global.tilePosX+1] = w
global.tilePosY[#global.tilePosY+1] = h
table.insert(global.tileNames, curTil.name)
end
end
game.makefile("buildings/tileNames.lua", serpent.dump(global.tileNames))
game.makefile("buildings/tilePositionsx.lua", serpent.dump(global.tilePosX))
game.makefile("buildings/tilePositionsy.lua", serpent.dump(global.tilePosY))
end
--Actually creating the building in game (remember to put the correct values at the correct places!
function downloadBuilding(modifierX, modifierY)
--The modifier valus are used to set the position of the building you want to place. So if both are zero the building will
--be spawned at spawn.
--Reading the values for tiles since i use some of them to find the height and with of the building:
tileNames = readTileNames
tilePosX = readTilePosX
tilePosY = readTilePosY
--Removal of entities near the structure you are spawning
areaWidth = tilePosX[#tilePosX]
areaHeight = tilePosY[#tilePosY]
toDestroy = game.surfaces["nauvis"].find_entities{{modifierX-10, modifierY-10}, {modifierX+areaWidth+10, modifierY+areaHeight+10}}
for d,ent in pairs(toDestroy) do
if ent.name ~= "player" then
ent.destroy()
end
end
--placing the entities
entPositionX = readPosX
entPositionY = readPosY
entName = readNames
for number = 1, #entName do
--Here it goes through the entities in the entName table and if it's a gate then use the first create_entity function
--as then the gate will be in the player's force!
if entName[number] == "gate" then
game.surfaces["nauvis"].create_entity({name = entName[number], position = {entPositionX[number]+modifierX, entPositionY[number]+modifierY}, force = game.forces.player})
else
game.surfaces["nauvis"].create_entity({name = entName[number], position = {entPositionX[number]+modifierX, entPositionY[number]+modifierY}})
end
end
--Placing of the tiles
tiles2 = {}
for numberT = 1, #tileNames do
table.insert(tiles2, {name = tileNames[numberT], position = {tilePosX[numberT]+modifierX, tilePosY[numberT]+modifierY}})
end
game.surfaces["nauvis"].set_tiles(tiles2)
end
The first step is what i call uploading the building. It is basically when you have created a building you want to have later be spawned in the world.
And you now want to turn it into files that can be later read!
uploading building
1. Create your building.
2. Put down a stone furnace on the bottom left corner of the building(can be changed in the uploadBuilding function)(one line change)
3. Put down a small power pole at the top right corner(can be changed in the uploadBuilding function)(one line change)
4. Run the command:
5. Go to: F:\Users\yourName\AppData\Roaming\Factorio\script-output\buildings
6. Copy those files into whatever folder you got in your mod. Prefferably a buildings folder. And in there each building got each of their folder. /buildings/lab1/ files here for example.
7. Notice how much information that 1 building is! To comparison a small 312 word big world doc is 14 KB!
8. Add this to the beginning of your control.lua file: (PS buildings.lab1 is an example location)
Upcoming
--Add in functionality for having more than one building. THough it is very easy to add, but time is running out and i can hint at it being a single extra if statement when downloading !)
--Add in possibility for adding random loot to it. Should be possible with not too much changes though. !
If ent.type == container then create entity, add loot code end
--Soon also i will trye and see if i can register the orientation of an object(i think i've seen that)
--Suggestions !