rafizzzz

Untitled

Feb 8th, 2021
530
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 18.54 KB | None | 0 0
  1. require "World_large"
  2. require "World_small"
  3. require "spawns"
  4.  
  5. --Terrain codes should be in sync with the ConvertMap code
  6. local terrain_codes = {
  7.     ["_"] = "out-of-map",
  8.     ["o"] = "deepwater",--ocean
  9.     ["O"] = "deepwater-green",
  10.     ["w"] = "water",
  11.     ["W"] = "water-green",
  12.     ["g"] = "grass-1",
  13.     ["m"] = "grass-3",
  14.     ["G"] = "grass-2",
  15.     ["d"] = "dirt-3",
  16.     ["D"] = "dirt-6",
  17.     ["s"] = "sand-1",
  18.     ["S"] = "sand-3"
  19. }
  20.  
  21. ----
  22. --Don't touch anything under this, unless you know what you're doing
  23. ----
  24. --Load settings
  25. local use_large_map = settings.global["use-large-map"].value
  26. local scale = settings.global["map-gen-scale"].value
  27. local spawn_settings = {
  28.     position = settings.global["spawn-position"].value,
  29.     x = settings.global["spawn-x"].value,
  30.     y = settings.global["spawn-y"].value
  31. }
  32. local safe_zone_size = settings.global["safe-zone-size"].value
  33. local repeat_map = settings.global["repeat-map"].value
  34. local out_of_map_code = "_" -- The terrain to use for everything outside the map
  35.  
  36. script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
  37.     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.")
  38.     game.print("The change is ignored for now, but will take effect when restarting the game.")
  39.     game.print("Return them to what they were, or risk smegging up your save!")
  40.     game.print("Your settings were: ")
  41.     game.print("Scale = " .. scale)
  42.     game.print("spawn: " .. spawn_settings.position .. "; x = " .. spawn_settings.x .. ", y = " .. spawn_settings.y)
  43.     game.print("Use large map = " .. (use_large_map and "true" or "false"))
  44.     game.print("Repeat map = " .. (repeat_map and "true" or "false"))
  45. end)
  46.  
  47. --Get correct world
  48. local terrain_types = nil
  49. if use_large_map then
  50.     terrain_types = map_data_large
  51. else
  52.     terrain_types = map_data_small
  53. end
  54.  
  55. --Get spawn
  56. local spawn = spawns[spawn_settings.position]
  57.  
  58. local function scale_position(position)
  59.     position = {
  60.         x = scale * position.x * (use_large_map and 2 or 1),
  61.         y = scale * position.y * (use_large_map and 2 or 1)
  62.     }
  63.     return position
  64. end
  65.  
  66. --If x and y are not set (for custom) use the x and y settings
  67. spawn = {
  68.     x = spawn.x or spawn_settings.x,
  69.     y = spawn.y or spawn_settings.y
  70. }
  71.  
  72. --Scale spawn so it is roughly the same position on the map regardless of scale and wether you use large map or not
  73.  
  74. spawn = scale_position(spawn)
  75.  
  76. --The variable that will store the decompressed map
  77. local decompressed_map_data = {}
  78. local width = nil
  79. local height = #terrain_types
  80. for y = 0, #terrain_types-1 do
  81.     decompressed_map_data[y] = {}
  82. end
  83.  
  84. --Function to actually do the decompressing
  85. local function decrompress_line(y)
  86.     local decompressed_line = decompressed_map_data[y]
  87.     if(#decompressed_line == 0) then
  88.         --do decompression of this line
  89.         local total_count = 0
  90.         local line = terrain_types[y+1]
  91.         for letter, count in string.gmatch(line, "(%a+)(%d+)") do
  92.             for x = total_count, total_count + count do
  93.                 decompressed_line[x] = letter
  94.             end
  95.             total_count = total_count + count
  96.         end
  97.         --check width (all lines must the equal in length)
  98.         if width == nil then
  99.             width = total_count
  100.         elseif width ~= total_count then
  101.             error("Mismatching width: " .. width .. " vs " .. total_count)
  102.         end
  103.     end
  104. end
  105.  
  106. --Decompress one line to we know the width
  107. decrompress_line(0)
  108.  
  109. function vecLengthPow(vector)
  110.     return (math.pow(vector.x,2)+math.pow(vector.y,2))
  111. end
  112.  
  113. function randOre( proximity )
  114.     local randMax = 2.45 --higher = more resources (but randomly)
  115.     local amount = 5 --multiplier
  116.  
  117.     local resType = math.random(0,10)
  118.     if (resType==0) then
  119.         resType = "stone"
  120.     elseif (resType<=2) then
  121.         resType = "coal"
  122.     elseif (resType<=6) then
  123.         resType = "iron-ore"
  124.     else
  125.         resType = "copper-ore"
  126.     end
  127.     randomFactor = (math.random(1,randMax*100)/100)
  128.     amount = amount*randomFactor*proximity
  129.     if(amount>=1) then
  130.         return {name=resType, amount=amount}
  131.     else
  132.         return nil
  133.     end
  134. end
  135.  
  136. function generateOres( surface, position )
  137.     local cutoff = 150
  138.     for y=-12,12 do
  139.         for x=-12,12 do
  140.             distPow = vecLengthPow({x=x,y=y})
  141.             if ( distPow < cutoff ) then
  142.                 local temp = randOre(cutoff-distPow)
  143.                 if (temp ~= nil) then
  144.                     temp["position"] = {x=position.x+x,y=position.y+y}
  145.                     surface.create_entity(temp)
  146.                 end
  147.             end
  148.         end
  149.     end
  150. end
  151. --Helper functions
  152. local function add_to_total(totals, weight, code)
  153.     if totals[code] == nil then
  154.         totals[code] = {code=code, weight=weight}
  155.     else
  156.         totals[code].weight = totals[code].weight + weight
  157.     end
  158. end
  159.  
  160. local function get_world_tile_code_raw(x, y)
  161.     y_wrap = y % height
  162.     x_wrap = x % width
  163.  
  164.     if not repeat_map and (x ~= x_wrap or y ~= y_wrap)then
  165.         return out_of_map_code
  166.     end
  167.  
  168.     decrompress_line(y_wrap)
  169.     return decompressed_map_data[y_wrap][x_wrap]
  170. end
  171.  
  172. local function get_world_tile_name(x, y)
  173. --[[
  174.     --spawn
  175.     x = x + spawn.x
  176.     y = y + spawn.y
  177.     --scaling
  178.     x = x / scale
  179.     y = y / scale
  180. --]]
  181.     --spawn & scaling
  182.     x = (x + spawn.x) / scale
  183.     y = (y + spawn.y)/ scale
  184.  
  185.     --get cells you're between
  186.     local top = math.floor(y)
  187.     local bottom = (top + 1)
  188.     local left = math.floor(x)
  189.     local right = (left + 1)
  190.     --get codes
  191.     local c_top_left = get_world_tile_code_raw(left, top)
  192.     local c_top_right = get_world_tile_code_raw(right, top)
  193.     local c_bottom_left = get_world_tile_code_raw(left, bottom)
  194.     local c_bottom_right = get_world_tile_code_raw(right, bottom)
  195.     if(c_top_left == c_top_right == c_bottom_left == c_bottom_right) then
  196.         --shortcut before heavy operations it's applied often enough, that it's worth of additional if.
  197.         return terrain_codes[c_top_left]
  198.     end
  199.     --calc weights
  200.     local sqrt2 = math.sqrt(2)
  201.     local w_top_left = 1 - math.sqrt((top - y)*(top - y) + (left - x)*(left - x)) / sqrt2
  202.     local w_top_right = 1 - math.sqrt((top - y)*(top - y) + (right - x)*(right - x)) / sqrt2
  203.     local w_bottom_left = 1 - math.sqrt((bottom - y)*(bottom - y) + (left - x)*(left - x)) / sqrt2
  204.     local w_bottom_right = 1 - math.sqrt((bottom - y)*(bottom - y) + (right - x)*(right - x)) / sqrt2
  205.     w_top_left = w_top_left * w_top_left + math.random() / math.max(scale / 2, 10)
  206.     w_top_right = w_top_right * w_top_right + math.random() / math.max(scale / 2, 10)
  207.     w_bottom_left = w_bottom_left * w_bottom_left + math.random() / math.max(scale / 2, 10)
  208.     w_bottom_right = w_bottom_right * w_bottom_right + math.random() / math.max(scale / 2, 10)
  209.     --calculate total weights for codes
  210.     local totals = {}
  211.     add_to_total(totals, w_top_left, c_top_left)
  212.     add_to_total(totals, w_top_right, c_top_right)
  213.     add_to_total(totals, w_bottom_left, c_bottom_left)
  214.     add_to_total(totals, w_bottom_right, c_bottom_right)
  215.     --choose final code
  216.     local code = nil
  217.     local weight = 0
  218.     for _, total in pairs(totals) do
  219.         if total.weight > weight then
  220.             code = total.code
  221.             weight = total.weight
  222.         end
  223.     end
  224.     local terrain_name = terrain_codes[code]
  225.     --safezone
  226.     return terrain_name
  227. end
  228.  
  229. local function init_modData()
  230.     if (global["worldMP playerData"] == nil) then
  231.         global["worldMP playerData"] = {}
  232.     end
  233.     if (global["worldMP bindings"] == nil) then
  234.         global["worldMP bindings"] = {
  235.         ["California"]=spawns["United States, Los Angeles"],
  236.         ["NYC"]=spawns["United States, New York"],
  237.         ["Venesuela"]={ x = 1210, y = 860 },
  238.         ["Mexico"]=spawns["Central America, Mexico City"],
  239.         ["Rio de Janeiro"]={ x = 1533, y = 1233 },
  240.         ["London"]=spawns["Europe, London"],
  241.         ["Warsaw"]={ x = 2250, y = 390 },
  242.         ["Rome"]={ x = 2155, y = 510 },
  243.         ["Cairo"]=spawns["Africa, Cairo"],
  244.         ["Baghdad"]={ x = 2511, y = 607 },
  245.         ["Delhi"]=spawns["Asia, Delhi"],
  246.         ["Beijing"]=spawns["Asia, Beijing"],
  247.         ["Omsk"]={ x = 2820, y = 385 },
  248.         ["Sydney"]=spawns["Oceana, Sydney"]
  249.         }
  250.     end
  251. end
  252.  
  253. -- Get an area given a position and distance.
  254. -- Square length = 2x distance
  255. function GetAreaAroundPos(pos, dist)
  256.     return {left_top=
  257.                     {x=pos.x-dist,
  258.                      y=pos.y-dist},
  259.             right_bottom=
  260.                     {x=pos.x+dist,
  261.                      y=pos.y+dist}}
  262. end
  263. -- Convenient way to remove aliens, just provide an area
  264. function RemoveAliensInArea(surface, area)
  265.     for _, entity in pairs(surface.find_entities_filtered{area = area, force = "enemy"}) do
  266.         entity.destroy()
  267.     end
  268. end
  269.  
  270. -- Make an area safer
  271. -- Reduction factor divides the enemy spawns by that number. 2 = half, 3 = third, etc...
  272. -- Also removes all big and huge worms in that area
  273. function ReduceAliensInArea(surface, area, reductionFactor, evolution)
  274.     for _, entity in pairs(surface.find_entities_filtered{area = area, force = "enemy"}) do
  275.         if (math.random(0,reductionFactor) > 0) then
  276.             entity.destroy()
  277.         end
  278.     end
  279.     -- Downgrade all huge worms
  280.     if (evolution<0.75) then
  281.         for _, entity in pairs(surface.find_entities_filtered{area = area, name = "behemoth-worm-turret"}) do
  282.                 surface.create_entity({
  283.                     name="big-worm-turret",
  284.                     position=entity.position
  285.                 })
  286.                 entity.destroy()
  287.         end
  288.     end
  289.     -- Downgrade all big worms
  290.     if (evolution<0.5) then
  291.         for _, entity in pairs(surface.find_entities_filtered{area = area, name = "big-worm-turret"}) do
  292.                 surface.create_entity({
  293.                     name="medium-worm-turret",
  294.                     position=entity.position
  295.                 })
  296.                 entity.destroy()
  297.         end
  298.     end
  299.     -- Downgrade all medium worms
  300.     if (evolution<0.25) then
  301.         for _, entity in pairs(surface.find_entities_filtered{area = area, name = "medium-worm-turret"}) do
  302.                 surface.create_entity({
  303.                     name="small-worm-turret",
  304.                     position=entity.position
  305.                 })
  306.                 entity.destroy()
  307.         end
  308.     end
  309. end
  310.  
  311. local function removeAlienDecoratives(surface,area)
  312.     surface.destroy_decoratives( { area=area, name= {"shroom-decal","worms-decal","enemy-decal","enemy-decal-transparent"} } )
  313. end
  314.  
  315. local function scaleDownBiters(surface,area,evolution)
  316.     local reduction = 80
  317.     if (evolution>=0.1) then
  318.         reduction = 40
  319.     end
  320.     if (evolution>=0.2) then
  321.         reduction = 20
  322.     end
  323.     if (evolution>=0.35) then
  324.         reduction = 10
  325.     end
  326.     if (evolution>=0.5) then
  327.         reduction = 5
  328.     end
  329.     if (evolution>=0.65) then
  330.         reduction = 3
  331.     end
  332.     if (evolution>0.8) then
  333.         reduction = 1
  334.     end
  335.  
  336.     local dice_roll = math.random(0,reduction)
  337.     if ( dice_roll > 2) then
  338.         RemoveAliensInArea(surface,area)            -- kill all "enemy" objects in this chunk
  339.         removeAlienDecoratives(surface,area)
  340.     elseif (dice_roll > 0)then
  341.         ReduceAliensInArea(surface,area,2,evolution) --downgrade worms and kill some nests
  342.     else
  343.         ReduceAliensInArea(surface,area,0,evolution) --only downgrade worms
  344.     end
  345. end
  346.  
  347.  
  348.  
  349. local resourceSpawnPlace = {
  350.         ["California"]={pos=spawns["United States, Los Angeles"]},
  351.         ["NYC"]={pos=spawns["United States, New York"]},
  352.         ["Venesuela"]={pos={ x = 1210, y = 860 }},
  353.         ["Mexico"]={pos=spawns["Central America, Mexico City"]},
  354.         ["Rio de Janeiro"]={pos={ x = 1533, y = 1233 }},
  355.         ["London"]={pos=spawns["Europe, London"]},
  356.         ["Warsaw"]={pos={ x = 2250, y = 390 }},
  357.         ["Rome"]={pos={ x = 2155, y = 510 }},
  358.         ["Cairo"]={pos=spawns["Africa, Cairo"]},
  359.         ["Baghdad"]={pos={ x = 2511, y = 607 }},
  360.         ["Delhi"]={pos=spawns["Asia, Delhi"]},
  361.         ["Beijing"]={pos=spawns["Asia, Beijing"]},
  362.         ["Omsk"]={pos={ x = 2820, y = 385 }},
  363.         ["Sydney"]={pos=spawns["Oceana, Sydney"]}
  364.         }
  365.  
  366. --Chunk generation code
  367. local function on_chunk_generated(event)
  368.     if (event.surface.name ~= "nauvis") then
  369.         return
  370.     end
  371.  
  372.     local surface = event.surface
  373.     local lt = event.area.left_top
  374.     local rb = event.area.right_bottom
  375.  
  376.     local w = rb.x - lt.x
  377.     local h = rb.y - lt.y
  378.  
  379.     local tiles = {}
  380.     for y = lt.y-1, rb.y do
  381.         for x = lt.x-1, rb.x do
  382.             tiles[#tiles+1]={name=get_world_tile_name(x, y), position={x,y}}
  383. --            table.insert(tiles, {name=get_world_tile_name(x, y), position={x,y}})
  384.         end
  385.     end
  386.     surface.set_tiles(tiles)
  387.     local positions = {event.position}
  388.     surface.regenerate_entity(nil, positions)
  389.    
  390.     surface.destroy_decoratives({area = event.area})
  391.     surface.regenerate_decorative(nil, positions)
  392.     scaleDownBiters(surface,event.area,game.forces["enemy"].evolution_factor)
  393.  
  394.     for spawnName,spawnData in pairs(resourceSpawnPlace) do
  395.         spawnPlace = scale_position(spawnData.pos)
  396.         spawnPlace = {x=spawnPlace.x-spawn.x,y=spawnPlace.y-spawn.y}
  397.  
  398.         local midX = rb.x-16
  399.         local midY = rb.y-16
  400.  
  401.         if (math.sqrt(vecLengthPow({x=spawnPlace.x-midX,y=spawnPlace.y-midY}))<60) then
  402.             if (spawnData["nearby"]==nil) then
  403.                 spawnData["nearby"]=1
  404.             else
  405.                 spawnData["nearby"] = spawnData["nearby"]+1
  406.             end
  407.             if (spawnData["nearby"]>5) then
  408.                 generateOres(surface, {x=spawnPlace.x,y=spawnPlace.y})
  409.                 resourceSpawnPlace[spawnName]=nil
  410.             end
  411.         end
  412.     end
  413.  
  414. end
  415.  
  416. local function getSpawnList()
  417.     local spawnList = {}
  418.     table.insert(spawnList,"CHOOSE SPAWN (ONLY ONCE!)")
  419.     for name,elem in pairs(global["worldMP bindings"]) do
  420.         table.insert(spawnList,name)
  421.     end
  422.     return spawnList
  423. end
  424.  
  425. local function hide_gui( player )
  426.     if (player.gui.top["spawnPicker"] ~= nil) then
  427.         player.gui.top["spawnPicker"].destroy()
  428.     end
  429. end
  430.  
  431. local function update_gui(player)
  432.     hide_gui(player)
  433.     player.gui.top.add{name = "spawnPicker", type = "drop-down", items = getSpawnList(), selected_index=1}
  434. end
  435.  
  436. local function has_gui(player)
  437.     if (player.gui.top["spawnPicker"] ~= nil) then
  438.         return true
  439.     end
  440.     return false
  441. end
  442.  
  443. local function sendToSpawn(player,playerSpawn)
  444.     if(playerSpawn ~= nil) then
  445.         player.teleport({x=playerSpawn.position.x,y=playerSpawn.position.y}, playerSpawn.surface)
  446.         player.surface.create_entity{name="cliff-explosives", position=player.position, speed=0, max_range=0, target=player.character}
  447.     else
  448.         player.teleport({x=0,y=0}, player.surface)
  449.         update_gui(player,false)
  450.     end
  451. end
  452.  
  453. local function pickSpawn( player,spawnName )
  454.     local newSpawn = global["worldMP bindings"][spawnName]
  455.     newSpawn = scale_position(newSpawn)
  456.     newSpawn = {x=newSpawn.x-spawn.x,y=newSpawn.y-spawn.y}
  457.     newSpawn = {name = spawnName, bind = global["worldMP bindings"][spawnName], position = newSpawn, lock = true, tries = 0, surface = player.surface}
  458.     global["worldMP playerData"][player.name]["spawn"] = newSpawn
  459.     game.print("Setting " .. player.name .. "'s spawn point to " .. spawnName)
  460.     if (player.character ~= nil ) then
  461.         sendToSpawn(player,newSpawn)
  462.     end
  463. end
  464.  
  465. local function on_player_joined(event)
  466.     local player = game.players[event.player_index]
  467.     if (global["worldMP playerData"] == nil) then
  468.         init_modData()
  469.     end
  470.    
  471.     if global["worldMP playerData"][player.name] == nil then
  472.         global["worldMP playerData"][player.name] = {}
  473.         global["worldMP playerData"][player.name]["spawn"]=nil
  474.         global["worldMP playerData"][player.name]["joinTime"]=game.tick
  475.         sendToSpawn(player,nil)
  476.     end
  477.  
  478.     if global["worldMP playerData"][player.name]["spawn"] == nil then
  479.         if player.gui.top.spawnPicker == nil then
  480.             update_gui(player)
  481.         end
  482.     end
  483. end
  484.  
  485. local function on_gui_selection_state_changed(event)
  486.     if event.element.name == "spawnPicker" then
  487.         local index = event.element.selected_index
  488.         if index~=1 then
  489.             local player = game.players[event.player_index]
  490.             local spawnName = event.element.items[index]
  491.             pickSpawn(player,spawnName)
  492.             global["worldMP bindings"][spawnName]=nil
  493.             hide_gui(player)
  494.         end
  495.         for _,player in pairs(game.players) do
  496.             if (has_gui(player)) then
  497.                 update_gui(player)
  498.             end
  499.         end
  500.     end
  501. end
  502.  
  503. local deleteSeconds=60*15 --15 minutes
  504.  
  505. local function  deletePlayerData( player )
  506.     if (global["worldMP playerData"] == nil) then
  507.         init_modData()
  508.     end
  509.     if (global["worldMP playerData"][player.name] ~= nil) then
  510.         if (global["worldMP playerData"][player.name]["joinTime"]+(60*deleteSeconds)>game.tick) then
  511.             if (global["worldMP playerData"][player.name]["spawn"]~=nil) then
  512.                 local spawn = global["worldMP playerData"][player.name]["spawn"]
  513.                 global["worldMP bindings"][spawn.name] = spawn.bind
  514.             end
  515.             global["worldMP playerData"][player.name] = nil
  516.         end
  517.     end
  518. end
  519.  
  520. local function on_player_left_game(event)
  521.     local player = game.players[event.player_index]
  522.     deletePlayerData(player)
  523. end
  524.  
  525. local function on_player_removed(event)
  526.     local player = game.players[event.player_index]
  527.     deletePlayerData(player)
  528. end
  529.  
  530. local function on_player_respawned (event)
  531.     -- Get Current Player
  532.     local player = game.players[event.player_index]
  533.     sendToSpawn(player,global["worldMP playerData"].spawn)
  534.     RemoveAliensInArea(player.surface, GetAreaAroundPos(player.position,40) )   -- kill 100% of enemy entities
  535.     ReduceAliensInArea(player.surface, GetAreaAroundPos(player.position,100), 1, 0.4) --max medium worms, kill 50% of enemy entities
  536. end
  537.  
  538. local function on_init(event)
  539.     if (remote.interfaces["freeplay"] ~= nil) then
  540.         remote.call("freeplay", "set_disable_crashsite", true)
  541.     end
  542.     init_modData()
  543. end
  544.  
  545. script.on_event(defines.events.on_chunk_generated, on_chunk_generated)
  546.  
  547. script.on_event(defines.events.on_player_joined_game, on_player_joined)
  548.  
  549. script.on_event(defines.events.on_gui_selection_state_changed, on_gui_selection_state_changed)
  550.  
  551. script.on_event(defines.events.on_player_respawned, on_player_respawned)
  552.  
  553. script.on_event(defines.events.on_player_left_game, on_player_left_game)
  554.  
  555. script.on_event(defines.events.on_player_removed, on_player_removed)
  556.  
  557. script.on_init(on_init)
Advertisement
Add Comment
Please, Sign In to add comment