Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require "World_large"
- require "World_small"
- require "spawns"
- --Terrain codes should be in sync with the ConvertMap code
- local terrain_codes = {
- ["_"] = "out-of-map",
- ["o"] = "deepwater",--ocean
- ["O"] = "deepwater-green",
- ["w"] = "water",
- ["W"] = "water-green",
- ["g"] = "grass-1",
- ["m"] = "grass-3",
- ["G"] = "grass-2",
- ["d"] = "dirt-3",
- ["D"] = "dirt-6",
- ["s"] = "sand-1",
- ["S"] = "sand-3"
- }
- ----
- --Don't touch anything under this, unless you know what you're doing
- ----
- --Load settings
- local use_large_map = settings.global["use-large-map"].value
- local scale = settings.global["map-gen-scale"].value
- local spawn_settings = {
- position = settings.global["spawn-position"].value,
- x = settings.global["spawn-x"].value,
- y = settings.global["spawn-y"].value
- }
- local safe_zone_size = settings.global["safe-zone-size"].value
- local repeat_map = settings.global["repeat-map"].value
- local out_of_map_code = "_" -- The terrain to use for everything outside the map
- script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
- game.print("You shouldn't change the world-gen settings after you started a savegame. This will break the generating for new parts of the map.")
- game.print("The change is ignored for now, but will take effect when restarting the game.")
- game.print("Return them to what they were, or risk smegging up your save!")
- game.print("Your settings were: ")
- game.print("Scale = " .. scale)
- game.print("spawn: " .. spawn_settings.position .. "; x = " .. spawn_settings.x .. ", y = " .. spawn_settings.y)
- game.print("Use large map = " .. (use_large_map and "true" or "false"))
- game.print("Repeat map = " .. (repeat_map and "true" or "false"))
- end)
- --Get correct world
- local terrain_types = nil
- if use_large_map then
- terrain_types = map_data_large
- else
- terrain_types = map_data_small
- end
- --Get spawn
- local spawn = spawns[spawn_settings.position]
- local function scale_position(position)
- position = {
- x = scale * position.x * (use_large_map and 2 or 1),
- y = scale * position.y * (use_large_map and 2 or 1)
- }
- return position
- end
- --If x and y are not set (for custom) use the x and y settings
- spawn = {
- x = spawn.x or spawn_settings.x,
- y = spawn.y or spawn_settings.y
- }
- --Scale spawn so it is roughly the same position on the map regardless of scale and wether you use large map or not
- spawn = scale_position(spawn)
- --The variable that will store the decompressed map
- local decompressed_map_data = {}
- local width = nil
- local height = #terrain_types
- for y = 0, #terrain_types-1 do
- decompressed_map_data[y] = {}
- end
- --Function to actually do the decompressing
- local function decrompress_line(y)
- local decompressed_line = decompressed_map_data[y]
- if(#decompressed_line == 0) then
- --do decompression of this line
- local total_count = 0
- local line = terrain_types[y+1]
- for letter, count in string.gmatch(line, "(%a+)(%d+)") do
- for x = total_count, total_count + count do
- decompressed_line[x] = letter
- end
- total_count = total_count + count
- end
- --check width (all lines must the equal in length)
- if width == nil then
- width = total_count
- elseif width ~= total_count then
- error("Mismatching width: " .. width .. " vs " .. total_count)
- end
- end
- end
- --Decompress one line to we know the width
- decrompress_line(0)
- function vecLengthPow(vector)
- return (math.pow(vector.x,2)+math.pow(vector.y,2))
- end
- function randOre( proximity )
- local randMax = 2.45 --higher = more resources (but randomly)
- local amount = 5 --multiplier
- local resType = math.random(0,10)
- if (resType==0) then
- resType = "stone"
- elseif (resType<=2) then
- resType = "coal"
- elseif (resType<=6) then
- resType = "iron-ore"
- else
- resType = "copper-ore"
- end
- randomFactor = (math.random(1,randMax*100)/100)
- amount = amount*randomFactor*proximity
- if(amount>=1) then
- return {name=resType, amount=amount}
- else
- return nil
- end
- end
- function generateOres( surface, position )
- local cutoff = 150
- for y=-12,12 do
- for x=-12,12 do
- distPow = vecLengthPow({x=x,y=y})
- if ( distPow < cutoff ) then
- local temp = randOre(cutoff-distPow)
- if (temp ~= nil) then
- temp["position"] = {x=position.x+x,y=position.y+y}
- surface.create_entity(temp)
- end
- end
- end
- end
- end
- --Helper functions
- local function add_to_total(totals, weight, code)
- if totals[code] == nil then
- totals[code] = {code=code, weight=weight}
- else
- totals[code].weight = totals[code].weight + weight
- end
- end
- local function get_world_tile_code_raw(x, y)
- y_wrap = y % height
- x_wrap = x % width
- if not repeat_map and (x ~= x_wrap or y ~= y_wrap)then
- return out_of_map_code
- end
- decrompress_line(y_wrap)
- return decompressed_map_data[y_wrap][x_wrap]
- end
- local function get_world_tile_name(x, y)
- --[[
- --spawn
- x = x + spawn.x
- y = y + spawn.y
- --scaling
- x = x / scale
- y = y / scale
- --]]
- --spawn & scaling
- x = (x + spawn.x) / scale
- y = (y + spawn.y)/ scale
- --get cells you're between
- local top = math.floor(y)
- local bottom = (top + 1)
- local left = math.floor(x)
- local right = (left + 1)
- --get codes
- local c_top_left = get_world_tile_code_raw(left, top)
- local c_top_right = get_world_tile_code_raw(right, top)
- local c_bottom_left = get_world_tile_code_raw(left, bottom)
- local c_bottom_right = get_world_tile_code_raw(right, bottom)
- if(c_top_left == c_top_right == c_bottom_left == c_bottom_right) then
- --shortcut before heavy operations it's applied often enough, that it's worth of additional if.
- return terrain_codes[c_top_left]
- end
- --calc weights
- local sqrt2 = math.sqrt(2)
- local w_top_left = 1 - math.sqrt((top - y)*(top - y) + (left - x)*(left - x)) / sqrt2
- local w_top_right = 1 - math.sqrt((top - y)*(top - y) + (right - x)*(right - x)) / sqrt2
- local w_bottom_left = 1 - math.sqrt((bottom - y)*(bottom - y) + (left - x)*(left - x)) / sqrt2
- local w_bottom_right = 1 - math.sqrt((bottom - y)*(bottom - y) + (right - x)*(right - x)) / sqrt2
- w_top_left = w_top_left * w_top_left + math.random() / math.max(scale / 2, 10)
- w_top_right = w_top_right * w_top_right + math.random() / math.max(scale / 2, 10)
- w_bottom_left = w_bottom_left * w_bottom_left + math.random() / math.max(scale / 2, 10)
- w_bottom_right = w_bottom_right * w_bottom_right + math.random() / math.max(scale / 2, 10)
- --calculate total weights for codes
- local totals = {}
- add_to_total(totals, w_top_left, c_top_left)
- add_to_total(totals, w_top_right, c_top_right)
- add_to_total(totals, w_bottom_left, c_bottom_left)
- add_to_total(totals, w_bottom_right, c_bottom_right)
- --choose final code
- local code = nil
- local weight = 0
- for _, total in pairs(totals) do
- if total.weight > weight then
- code = total.code
- weight = total.weight
- end
- end
- local terrain_name = terrain_codes[code]
- --safezone
- return terrain_name
- end
- local function init_modData()
- if (global["worldMP playerData"] == nil) then
- global["worldMP playerData"] = {}
- end
- if (global["worldMP bindings"] == nil) then
- global["worldMP bindings"] = {
- ["California"]=spawns["United States, Los Angeles"],
- ["NYC"]=spawns["United States, New York"],
- ["Venesuela"]={ x = 1210, y = 860 },
- ["Mexico"]=spawns["Central America, Mexico City"],
- ["Rio de Janeiro"]={ x = 1533, y = 1233 },
- ["London"]=spawns["Europe, London"],
- ["Warsaw"]={ x = 2250, y = 390 },
- ["Rome"]={ x = 2155, y = 510 },
- ["Cairo"]=spawns["Africa, Cairo"],
- ["Baghdad"]={ x = 2511, y = 607 },
- ["Delhi"]=spawns["Asia, Delhi"],
- ["Beijing"]=spawns["Asia, Beijing"],
- ["Omsk"]={ x = 2820, y = 385 },
- ["Sydney"]=spawns["Oceana, Sydney"]
- }
- end
- end
- -- Get an area given a position and distance.
- -- Square length = 2x distance
- function GetAreaAroundPos(pos, dist)
- return {left_top=
- {x=pos.x-dist,
- y=pos.y-dist},
- right_bottom=
- {x=pos.x+dist,
- y=pos.y+dist}}
- end
- -- Convenient way to remove aliens, just provide an area
- function RemoveAliensInArea(surface, area)
- for _, entity in pairs(surface.find_entities_filtered{area = area, force = "enemy"}) do
- entity.destroy()
- end
- end
- -- Make an area safer
- -- Reduction factor divides the enemy spawns by that number. 2 = half, 3 = third, etc...
- -- Also removes all big and huge worms in that area
- function ReduceAliensInArea(surface, area, reductionFactor, evolution)
- for _, entity in pairs(surface.find_entities_filtered{area = area, force = "enemy"}) do
- if (math.random(0,reductionFactor) > 0) then
- entity.destroy()
- end
- end
- -- Downgrade all huge worms
- if (evolution<0.75) then
- for _, entity in pairs(surface.find_entities_filtered{area = area, name = "behemoth-worm-turret"}) do
- surface.create_entity({
- name="big-worm-turret",
- position=entity.position
- })
- entity.destroy()
- end
- end
- -- Downgrade all big worms
- if (evolution<0.5) then
- for _, entity in pairs(surface.find_entities_filtered{area = area, name = "big-worm-turret"}) do
- surface.create_entity({
- name="medium-worm-turret",
- position=entity.position
- })
- entity.destroy()
- end
- end
- -- Downgrade all medium worms
- if (evolution<0.25) then
- for _, entity in pairs(surface.find_entities_filtered{area = area, name = "medium-worm-turret"}) do
- surface.create_entity({
- name="small-worm-turret",
- position=entity.position
- })
- entity.destroy()
- end
- end
- end
- local function removeAlienDecoratives(surface,area)
- surface.destroy_decoratives( { area=area, name= {"shroom-decal","worms-decal","enemy-decal","enemy-decal-transparent"} } )
- end
- local function scaleDownBiters(surface,area,evolution)
- local reduction = 80
- if (evolution>=0.1) then
- reduction = 40
- end
- if (evolution>=0.2) then
- reduction = 20
- end
- if (evolution>=0.35) then
- reduction = 10
- end
- if (evolution>=0.5) then
- reduction = 5
- end
- if (evolution>=0.65) then
- reduction = 3
- end
- if (evolution>0.8) then
- reduction = 1
- end
- local dice_roll = math.random(0,reduction)
- if ( dice_roll > 2) then
- RemoveAliensInArea(surface,area) -- kill all "enemy" objects in this chunk
- removeAlienDecoratives(surface,area)
- elseif (dice_roll > 0)then
- ReduceAliensInArea(surface,area,2,evolution) --downgrade worms and kill some nests
- else
- ReduceAliensInArea(surface,area,0,evolution) --only downgrade worms
- end
- end
- local resourceSpawnPlace = {
- ["California"]={pos=spawns["United States, Los Angeles"]},
- ["NYC"]={pos=spawns["United States, New York"]},
- ["Venesuela"]={pos={ x = 1210, y = 860 }},
- ["Mexico"]={pos=spawns["Central America, Mexico City"]},
- ["Rio de Janeiro"]={pos={ x = 1533, y = 1233 }},
- ["London"]={pos=spawns["Europe, London"]},
- ["Warsaw"]={pos={ x = 2250, y = 390 }},
- ["Rome"]={pos={ x = 2155, y = 510 }},
- ["Cairo"]={pos=spawns["Africa, Cairo"]},
- ["Baghdad"]={pos={ x = 2511, y = 607 }},
- ["Delhi"]={pos=spawns["Asia, Delhi"]},
- ["Beijing"]={pos=spawns["Asia, Beijing"]},
- ["Omsk"]={pos={ x = 2820, y = 385 }},
- ["Sydney"]={pos=spawns["Oceana, Sydney"]}
- }
- --Chunk generation code
- local function on_chunk_generated(event)
- if (event.surface.name ~= "nauvis") then
- return
- end
- local surface = event.surface
- local lt = event.area.left_top
- local rb = event.area.right_bottom
- local w = rb.x - lt.x
- local h = rb.y - lt.y
- local tiles = {}
- for y = lt.y-1, rb.y do
- for x = lt.x-1, rb.x do
- tiles[#tiles+1]={name=get_world_tile_name(x, y), position={x,y}}
- -- table.insert(tiles, {name=get_world_tile_name(x, y), position={x,y}})
- end
- end
- surface.set_tiles(tiles)
- local positions = {event.position}
- surface.regenerate_entity(nil, positions)
- surface.destroy_decoratives({area = event.area})
- surface.regenerate_decorative(nil, positions)
- scaleDownBiters(surface,event.area,game.forces["enemy"].evolution_factor)
- for spawnName,spawnData in pairs(resourceSpawnPlace) do
- spawnPlace = scale_position(spawnData.pos)
- spawnPlace = {x=spawnPlace.x-spawn.x,y=spawnPlace.y-spawn.y}
- local midX = rb.x-16
- local midY = rb.y-16
- if (math.sqrt(vecLengthPow({x=spawnPlace.x-midX,y=spawnPlace.y-midY}))<60) then
- if (spawnData["nearby"]==nil) then
- spawnData["nearby"]=1
- else
- spawnData["nearby"] = spawnData["nearby"]+1
- end
- if (spawnData["nearby"]>5) then
- generateOres(surface, {x=spawnPlace.x,y=spawnPlace.y})
- resourceSpawnPlace[spawnName]=nil
- end
- end
- end
- end
- local function getSpawnList()
- local spawnList = {}
- table.insert(spawnList,"CHOOSE SPAWN (ONLY ONCE!)")
- for name,elem in pairs(global["worldMP bindings"]) do
- table.insert(spawnList,name)
- end
- return spawnList
- end
- local function hide_gui( player )
- if (player.gui.top["spawnPicker"] ~= nil) then
- player.gui.top["spawnPicker"].destroy()
- end
- end
- local function update_gui(player)
- hide_gui(player)
- player.gui.top.add{name = "spawnPicker", type = "drop-down", items = getSpawnList(), selected_index=1}
- end
- local function has_gui(player)
- if (player.gui.top["spawnPicker"] ~= nil) then
- return true
- end
- return false
- end
- local function sendToSpawn(player,playerSpawn)
- if(playerSpawn ~= nil) then
- player.teleport({x=playerSpawn.position.x,y=playerSpawn.position.y}, playerSpawn.surface)
- player.surface.create_entity{name="cliff-explosives", position=player.position, speed=0, max_range=0, target=player.character}
- else
- player.teleport({x=0,y=0}, player.surface)
- update_gui(player,false)
- end
- end
- local function pickSpawn( player,spawnName )
- local newSpawn = global["worldMP bindings"][spawnName]
- newSpawn = scale_position(newSpawn)
- newSpawn = {x=newSpawn.x-spawn.x,y=newSpawn.y-spawn.y}
- newSpawn = {name = spawnName, bind = global["worldMP bindings"][spawnName], position = newSpawn, lock = true, tries = 0, surface = player.surface}
- global["worldMP playerData"][player.name]["spawn"] = newSpawn
- game.print("Setting " .. player.name .. "'s spawn point to " .. spawnName)
- if (player.character ~= nil ) then
- sendToSpawn(player,newSpawn)
- end
- end
- local function on_player_joined(event)
- local player = game.players[event.player_index]
- if (global["worldMP playerData"] == nil) then
- init_modData()
- end
- if global["worldMP playerData"][player.name] == nil then
- global["worldMP playerData"][player.name] = {}
- global["worldMP playerData"][player.name]["spawn"]=nil
- global["worldMP playerData"][player.name]["joinTime"]=game.tick
- sendToSpawn(player,nil)
- end
- if global["worldMP playerData"][player.name]["spawn"] == nil then
- if player.gui.top.spawnPicker == nil then
- update_gui(player)
- end
- end
- end
- local function on_gui_selection_state_changed(event)
- if event.element.name == "spawnPicker" then
- local index = event.element.selected_index
- if index~=1 then
- local player = game.players[event.player_index]
- local spawnName = event.element.items[index]
- pickSpawn(player,spawnName)
- global["worldMP bindings"][spawnName]=nil
- hide_gui(player)
- end
- for _,player in pairs(game.players) do
- if (has_gui(player)) then
- update_gui(player)
- end
- end
- end
- end
- local deleteSeconds=60*15 --15 minutes
- local function deletePlayerData( player )
- if (global["worldMP playerData"] == nil) then
- init_modData()
- end
- if (global["worldMP playerData"][player.name] ~= nil) then
- if (global["worldMP playerData"][player.name]["joinTime"]+(60*deleteSeconds)>game.tick) then
- if (global["worldMP playerData"][player.name]["spawn"]~=nil) then
- local spawn = global["worldMP playerData"][player.name]["spawn"]
- global["worldMP bindings"][spawn.name] = spawn.bind
- end
- global["worldMP playerData"][player.name] = nil
- end
- end
- end
- local function on_player_left_game(event)
- local player = game.players[event.player_index]
- deletePlayerData(player)
- end
- local function on_player_removed(event)
- local player = game.players[event.player_index]
- deletePlayerData(player)
- end
- local function on_player_respawned (event)
- -- Get Current Player
- local player = game.players[event.player_index]
- sendToSpawn(player,global["worldMP playerData"].spawn)
- RemoveAliensInArea(player.surface, GetAreaAroundPos(player.position,40) ) -- kill 100% of enemy entities
- ReduceAliensInArea(player.surface, GetAreaAroundPos(player.position,100), 1, 0.4) --max medium worms, kill 50% of enemy entities
- end
- local function on_init(event)
- if (remote.interfaces["freeplay"] ~= nil) then
- remote.call("freeplay", "set_disable_crashsite", true)
- end
- init_modData()
- end
- script.on_event(defines.events.on_chunk_generated, on_chunk_generated)
- script.on_event(defines.events.on_player_joined_game, on_player_joined)
- script.on_event(defines.events.on_gui_selection_state_changed, on_gui_selection_state_changed)
- script.on_event(defines.events.on_player_respawned, on_player_respawned)
- script.on_event(defines.events.on_player_left_game, on_player_left_game)
- script.on_event(defines.events.on_player_removed, on_player_removed)
- script.on_init(on_init)
Advertisement
Add Comment
Please, Sign In to add comment