1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-04 00:15:45 +02:00

Merge branch 'ComfyFactory:develop' into develop

This commit is contained in:
danielmartin0 2022-03-07 22:13:21 +00:00 committed by GitHub
commit 960b234807
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 5416 additions and 2762 deletions

File diff suppressed because it is too large Load Diff

View File

@ -121,13 +121,13 @@ local function build_group_gui(data)
b.style.minimal_width = actions_width
b.style.maximal_width = actions_width
else
local b = tt.add({type = 'button', caption = 'Leave'})
local b = tt.add({type = 'button', caption = {'gui.leave'}})
b.style.font = 'default-bold'
b.style.minimal_width = actions_width
b.style.maximal_width = actions_width
end
if player.admin == true or group.founder == player.name then
local b = tt.add({type = 'button', caption = 'Delete'})
local b = tt.add({type = 'button', caption = {'gui.delete'}})
b.style.font = 'default-bold'
b.style.minimal_width = actions_width
b.style.maximal_width = actions_width
@ -233,13 +233,9 @@ local function on_gui_click(event)
end
local player = game.get_player(event.player_index)
local name = event.element.name
local name = element.name
if not name then
return
end
if name == 'tab_' .. module_name then
if name and name == 'tab_' .. module_name then
local is_spamming = SpamProtection.is_spamming(player, nil, 'Groups tab_Groups')
if is_spamming then
return
@ -320,7 +316,9 @@ local function on_gui_click(event)
return
end
if element.type == 'button' and element.caption == 'Join' then
local caption = element.caption and element.caption[1]
if element.type == 'button' and caption == 'gui.join' then
this.player_group[player.name] = element.parent.name
local str = '[' .. element.parent.name
str = str .. ']'
@ -339,7 +337,7 @@ local function on_gui_click(event)
return
end
if element.type == 'button' and element.caption == 'Delete' then
if element.type == 'button' and caption == 'gui.delete' then
for _, players in pairs(game.players) do
if this.player_group[players.name] then
if this.player_group[players.name] == element.parent.name then
@ -354,7 +352,7 @@ local function on_gui_click(event)
return
end
if element.type == 'button' and element.caption == 'Leave' then
if element.type == 'button' and caption == 'gui.leave' then
this.player_group[player.name] = '[Group]'
player.tag = ''
refresh_gui()

View File

@ -160,6 +160,9 @@ require 'maps.pirates.main'
--![[Territorial Control - reveal the map as you walk through the mist]]--
--require 'maps.territorial_control'
--![[Deep Jungle - dangerous map]]--
--require 'maps.deep_jungle.main'
--![[You fell in a dark cave, will you survive?]]--
--require 'maps.cave_choppy.main'
--require 'maps.cave_miner'
@ -215,7 +218,6 @@ require 'maps.pirates.main'
--![[Misc / WIP]]--
--require 'maps.rainbow_road'
--require 'maps.deep_jungle'
--require 'maps.cratewood_forest'
--require 'maps.maze_challenge'
--require 'maps.lost_desert'

View File

@ -5,6 +5,8 @@ description=Description
members=Members
create=Create
join=Join
leave=Leave
delete=Delete
gui_data_cleaning=Gui Data Cleaning
spaghett_mode=Spaghett Mode
notify_on_polls=Notify on polls

View File

@ -1,414 +0,0 @@
--luacheck: ignore
--deep jungle-- mewmew made this --
require 'modules.no_deconstruction_of_neutral_entities'
require 'modules.spawners_contain_biters'
require 'modules.biters_yield_coins'
require 'modules.rocks_yield_coins'
require 'modules.flashlight_toggle_button'
local map_functions = require 'tools.map_functions'
local simplex_noise = require 'utils.simplex_noise'
simplex_noise = simplex_noise.d2
local event = require 'utils.event'
local math_random = math.random
local function shuffle(tbl)
local size = #tbl
for i = size, 1, -1 do
local rand = math.random(size)
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
end
local function secret_shop(pos, surface)
local secret_market_items = {
{price = {{'coin', math_random(300, 600)}}, offer = {type = 'give-item', item = 'combat-shotgun'}},
{price = {{'coin', math_random(200, 400)}}, offer = {type = 'give-item', item = 'rocket-launcher'}},
{price = {{'coin', math_random(5, 10)}}, offer = {type = 'give-item', item = 'piercing-rounds-magazine'}},
--{price = {{"coin", math_random(150,250)}}, offer = {type = 'give-item', item = 'uranium-rounds-magazine'}},
{price = {{'coin', math_random(15, 30)}}, offer = {type = 'give-item', item = 'piercing-shotgun-shell'}},
{price = {{'coin', math_random(10, 20)}}, offer = {type = 'give-item', item = 'rocket'}},
{price = {{'coin', math_random(20, 30)}}, offer = {type = 'give-item', item = 'explosive-rocket'}},
{price = {{'coin', math_random(30, 60)}}, offer = {type = 'give-item', item = 'cluster-grenade'}},
{price = {{'coin', math_random(8, 16)}}, offer = {type = 'give-item', item = 'land-mine'}},
{price = {{'coin', math_random(200, 300)}}, offer = {type = 'give-item', item = 'heavy-armor'}},
{price = {{'coin', math_random(400, 800)}}, offer = {type = 'give-item', item = 'modular-armor'}},
{price = {{'coin', math_random(1000, 2000)}}, offer = {type = 'give-item', item = 'power-armor'}},
{price = {{'coin', math_random(2500, 5000)}}, offer = {type = 'give-item', item = 'fusion-reactor-equipment'}},
{price = {{'coin', math_random(200, 400)}}, offer = {type = 'give-item', item = 'battery-equipment'}},
{price = {{'coin', math_random(150, 250)}}, offer = {type = 'give-item', item = 'belt-immunity-equipment'}},
{price = {{'coin', math_random(100, 200)}}, offer = {type = 'give-item', item = 'night-vision-equipment'}},
{price = {{'coin', math_random(400, 800)}}, offer = {type = 'give-item', item = 'exoskeleton-equipment'}},
{price = {{'coin', math_random(200, 300)}}, offer = {type = 'give-item', item = 'personal-roboport-equipment'}},
{price = {{'coin', math_random(25, 50)}}, offer = {type = 'give-item', item = 'construction-robot'}},
-- {price = {{"coin", math_random(10000,20000)}}, offer = {type = 'give-item', item = 'energy-shield-equipment'}},
-- {price = {{"coin", math_random(5000,15000)}}, offer = {type = 'give-item', item = 'personal-laser-defense-equipment'}},
{price = {{'coin', math_random(100, 300)}}, offer = {type = 'give-item', item = 'loader'}},
{price = {{'coin', math_random(200, 400)}}, offer = {type = 'give-item', item = 'fast-loader'}},
{price = {{'coin', math_random(300, 500)}}, offer = {type = 'give-item', item = 'express-loader'}},
{price = {{'coin', math_random(150, 300)}}, offer = {type = 'give-item', item = 'locomotive'}},
{price = {{'coin', math_random(100, 200)}}, offer = {type = 'give-item', item = 'cargo-wagon'}},
{price = {{'coin', math_random(5, 15)}}, offer = {type = 'give-item', item = 'grenade'}},
{price = {{'coin', math_random(80, 160)}}, offer = {type = 'give-item', item = 'cliff-explosives'}},
{price = {{'coin', math_random(10, 20)}}, offer = {type = 'give-item', item = 'explosives', count = 50}},
{price = {{'coin', math_random(4, 8)}}, offer = {type = 'give-item', item = 'rail', count = 4}},
{price = {{'coin', math_random(20, 30)}}, offer = {type = 'give-item', item = 'train-stop'}},
{price = {{'coin', math_random(4, 12)}}, offer = {type = 'give-item', item = 'small-lamp'}},
{price = {{'coin', math_random(1, 4)}}, offer = {type = 'give-item', item = 'firearm-magazine'}},
{price = {{'coin', math_random(60, 150)}}, offer = {type = 'give-item', item = 'car', count = 1}},
{price = {{'coin', math_random(75, 150)}}, offer = {type = 'give-item', item = 'gun-turret', count = 1}},
{price = {{'coin', math_random(500, 750)}}, offer = {type = 'give-item', item = 'laser-turret', count = 1}},
{price = {{'coin', math_random(1000, 2000)}}, offer = {type = 'give-item', item = 'artillery-turret', count = 1}},
{price = {{'coin', math_random(100, 200)}}, offer = {type = 'give-item', item = 'artillery-shell', count = 1}},
{price = {{'coin', math_random(50, 150)}}, offer = {type = 'give-item', item = 'artillery-targeting-remote', count = 1}},
{price = {{'coin', math_random(5, 15)}}, offer = {type = 'give-item', item = 'shotgun-shell', count = 1}},
{price = {{'coin', math_random(8000, 16000)}}, offer = {type = 'give-item', item = 'power-armor-mk2', count = 1}},
{price = {{'coin', math_random(80, 160)}}, offer = {type = 'give-item', item = 'solar-panel-equipment', count = 1}},
{price = {{'coin', math_random(4, 8)}}, offer = {type = 'give-item', item = 'wood', count = 50}},
{price = {{'coin', math_random(4, 8)}}, offer = {type = 'give-item', item = 'iron-ore', count = 50}},
{price = {{'coin', math_random(4, 8)}}, offer = {type = 'give-item', item = 'copper-ore', count = 50}},
{price = {{'coin', math_random(4, 8)}}, offer = {type = 'give-item', item = 'stone', count = 50}},
{price = {{'coin', math_random(4, 8)}}, offer = {type = 'give-item', item = 'coal', count = 50}}
--{price = {{"coin", math_random(4,8)}}, offer = {type = 'give-item', item = 'uranium-ore', count = 50}}
}
secret_market_items = shuffle(secret_market_items)
local market = surface.create_entity {name = 'market', position = pos}
market.destructible = false
for i = 1, math.random(6, 10), 1 do
market.add_market_item(secret_market_items[i])
end
end
local function treasure_chest(position)
if not game.surfaces['deep_jungle'].can_place_entity({name = 'steel-chest', position = position, force = 'player'}) then
return
end
treasure_chest_raffle_table = {}
treasure_chest_loot_weights = {}
table.insert(treasure_chest_loot_weights, {{name = 'landfill', count = math_random(8, 16)}, 16})
table.insert(treasure_chest_loot_weights, {{name = 'iron-gear-wheel', count = math_random(16, 48)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'coal', count = math_random(16, 48)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'copper-cable', count = math_random(64, 128)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'inserter', count = math_random(4, 8)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'fast-inserter', count = math_random(4, 8)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'burner-inserter', count = math_random(4, 8)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'rocket-fuel', count = math_random(1, 5)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'small-electric-pole', count = math_random(4, 8)}, 7})
table.insert(treasure_chest_loot_weights, {{name = 'firearm-magazine', count = math_random(16, 48)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'submachine-gun', count = 1}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'grenade', count = math_random(6, 12)}, 5})
table.insert(treasure_chest_loot_weights, {{name = 'land-mine', count = math_random(8, 16)}, 5})
table.insert(treasure_chest_loot_weights, {{name = 'light-armor', count = 1}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'heavy-armor', count = 1}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'pipe', count = math_random(10, 100)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'explosives', count = math_random(40, 50)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'shotgun', count = 1}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'shotgun-shell', count = math_random(8, 16)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'stone-brick', count = math_random(80, 100)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'small-lamp', count = math_random(2, 4)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'rail', count = math_random(16, 48)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'coin', count = math_random(32, 320)}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-1', count = math_random(1, 3)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-2', count = math_random(1, 3)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-3', count = math_random(1, 2)}, 1})
for _, t in pairs(treasure_chest_loot_weights) do
for x = 1, t[2], 1 do
table.insert(treasure_chest_raffle_table, t[1])
end
end
local e = game.surfaces['deep_jungle'].create_entity {name = 'wooden-chest', position = position, force = 'player'}
e.minable = false
local i = e.get_inventory(defines.inventory.chest)
for x = 1, math_random(3, 7), 1 do
local loot = treasure_chest_raffle_table[math_random(1, #treasure_chest_raffle_table)]
i.insert(loot)
end
end
local function rare_treasure_chest(position)
if not game.surfaces['deep_jungle'].can_place_entity({name = 'steel-chest', position = position, force = 'player'}) then
return
end
local rare_treasure_chest_raffle_table = {}
local rare_treasure_chest_loot_weights = {}
table.insert(rare_treasure_chest_loot_weights, {{name = 'combat-shotgun', count = 1}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'piercing-shotgun-shell', count = math_random(8, 16)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'rocket-launcher', count = 1}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'rocket', count = math_random(4, 8)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'explosive-rocket', count = math_random(4, 8)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'modular-armor', count = 1}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'piercing-rounds-magazine', count = math_random(32, 64)}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'defender-capsule', count = math_random(4, 8)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'distractor-capsule', count = math_random(3, 5)}, 4})
table.insert(rare_treasure_chest_loot_weights, {{name = 'destroyer-capsule', count = math_random(2, 3)}, 3})
for _, t in pairs(rare_treasure_chest_loot_weights) do
for x = 1, t[2], 1 do
table.insert(rare_treasure_chest_raffle_table, t[1])
end
end
local e = game.surfaces['deep_jungle'].create_entity {name = 'steel-chest', position = position, force = 'player'}
e.minable = false
local i = e.get_inventory(defines.inventory.chest)
for x = 1, math_random(2, 3), 1 do
local loot = rare_treasure_chest_raffle_table[math_random(1, #rare_treasure_chest_raffle_table)]
i.insert(loot)
end
end
local function get_noise(name, pos)
local seed = game.surfaces[1].map_gen_settings.seed
local noise_seed_add = 25000
if name == 1 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.001, pos.y * 0.001, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.01, pos.y * 0.01, seed + noise_seed_add)
local noise = noise[1] + noise[2] * 0.1
return noise
end
if name == 2 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.015, pos.y * 0.015, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.15, pos.y * 0.15, seed + noise_seed_add)
local noise = noise[1] + noise[2] * 0.2
return noise
end
if name == 3 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.025, pos.y * 0.025, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.2, pos.y * 0.2, seed + noise_seed_add)
local noise = noise[1] + noise[2] * 0.2
return noise
end
if name == 'greenwater' then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.003, pos.y * 0.003, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.03, pos.y * 0.03, seed + noise_seed_add)
local noise = noise[1] + noise[2] * 0.1
return noise
end
end
local rock_raffle = {'sand-rock-big', 'sand-rock-big', 'rock-big', 'rock-big', 'rock-big', 'rock-big', 'rock-huge'}
local tree_raffle = {'tree-04', 'tree-07', 'tree-09', 'tree-06', 'tree-04', 'tree-07', 'tree-09', 'tree-04'}
local function process_tile(pos)
local noise_1 = get_noise(1, pos)
if noise_1 > -0.03 and noise_1 < 0.03 then
return 'deepwater'
end
if noise_1 > -0.05 and noise_1 < 0.05 then
return 'water'
end
local noise_greenwater = get_noise('greenwater', pos)
if noise_greenwater > -0.035 and noise_greenwater < 0.035 then
return 'water-green'
end
if noise_1 > -0.08 and noise_1 < 0.08 then
return false
end
local noise_2 = get_noise(2, pos)
if noise_2 > 0.37 or noise_2 < -0.37 then
if math_random(1, 4) == 1 then
return false, tree_raffle[math.ceil(math.abs(noise_1 * 8))]
end
end
local noise_3 = get_noise(3, pos)
if noise_3 > 0.5 then
if math_random(1, 3) == 1 then
return false, rock_raffle[math_random(1, #rock_raffle)]
end
end
return false
end
local function on_chunk_generated(event)
local surface = game.surfaces['deep_jungle']
if event.surface.name ~= surface.name then
return
end
local chunk_pos_x = event.area.left_top.x
local chunk_pos_y = event.area.left_top.y
local tiles = {}
local entities_to_place = {}
local treasure_chests = {}
local rare_treasure_chests = {}
local secret_shops = {}
local tile_to_insert = false
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local pos = {x = chunk_pos_x + x, y = chunk_pos_y + y}
tile_to_insert, entity_to_place = process_tile(pos)
if entity_to_place then
table.insert(entities_to_place, {name = entity_to_place, position = pos, force = 'player'})
end
if tile_to_insert then
table.insert(tiles, {name = tile_to_insert, position = pos})
if math_random(1, 40) == 1 and tile_to_insert == 'deepwater' then
surface.create_entity({name = 'fish', position = pos})
end
end
if math_random(1, 1500) == 1 then
table.insert(treasure_chests, pos)
end
if math_random(1, 16000) == 1 then
table.insert(rare_treasure_chests, pos)
end
if math_random(1, 8000) == 1 then
table.insert(secret_shops, pos)
end
end
end
surface.set_tiles(tiles, true)
for _, e in pairs(entities_to_place) do
if not surface.get_tile(e.position).collides_with('player-layer') then
surface.create_entity(e)
end
end
for _, p in pairs(treasure_chests) do
treasure_chest(p)
end
for _, p in pairs(rare_treasure_chests) do
rare_treasure_chest(p)
end
for _, p in pairs(secret_shops) do
if not surface.get_tile(p).collides_with('player-layer') then
local area = {{p.x - 128, p.y - 128}, {p.x + 128, p.y + 128}}
if surface.count_entities_filtered({name = 'market', area = area}) == 0 then
secret_shop(p, surface)
end
end
end
end
local function on_chunk_charted(event)
if not global.chunks_charted then
global.chunks_charted = {}
end
local surface = game.surfaces[event.surface_index]
local position = event.position
if global.chunks_charted[tostring(position.x) .. tostring(position.y)] then
return
end
global.chunks_charted[tostring(position.x) .. tostring(position.y)] = true
local decorative_names = {}
for k, v in pairs(game.decorative_prototypes) do
if v.autoplace_specification then
decorative_names[#decorative_names + 1] = k
end
end
surface.regenerate_decorative(decorative_names, {position})
if math_random(1, 14) ~= 1 then
return
end
map_functions.draw_rainbow_patch({x = position.x * 32 + math_random(1, 32), y = position.y * 32 + math_random(1, 32)}, surface, math_random(14, 26), 2000)
end
local function on_player_joined_game(event)
local player = game.players[event.player_index]
local surface = game.surfaces['deep_jungle']
if player.online_time < 5 and surface.is_chunk_generated({0, 0}) then
player.teleport(surface.find_non_colliding_position('character', {0, 0}, 2, 1), 'deep_jungle')
else
if player.online_time < 5 then
player.teleport({0, 0}, 'deep_jungle')
end
end
if player.online_time < 2 then
player.insert {name = 'iron-plate', count = 32}
end
end
local function on_entity_died(event)
local surface = event.entity.surface
if event.entity.type == 'tree' then
if math_random(1, 8) == 1 then
local p = surface.find_non_colliding_position('small-biter', event.entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'small-biter', position = event.entity.position}
end
return
end
if math_random(1, 16) == 1 then
local p = surface.find_non_colliding_position('medium-biter', event.entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'medium-biter', position = event.entity.position}
end
return
end
if math_random(1, 32) == 1 then
local p = surface.find_non_colliding_position('big-biter', event.entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'big-biter', position = event.entity.position}
end
return
end
if math_random(1, 512) == 1 then
local p = surface.find_non_colliding_position('behemoth-biter', event.entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'behemoth-biter', position = event.entity.position}
end
return
end
end
if event.entity.type == 'simple-entity' then
if math_random(1, 8) == 1 then
surface.create_entity {name = 'small-worm-turret', position = event.entity.position}
return
end
if math_random(1, 16) == 1 then
surface.create_entity {name = 'medium-worm-turret', position = event.entity.position}
return
end
if math_random(1, 32) == 1 then
surface.create_entity {name = 'big-worm-turret', position = event.entity.position}
return
end
end
end
local function on_init()
local map_gen_settings = {}
map_gen_settings.moisture = 0.99
map_gen_settings.water = 'none'
map_gen_settings.starting_area = 'normal'
map_gen_settings.cliff_settings = {cliff_elevation_interval = 4, cliff_elevation_0 = 0.1}
map_gen_settings.autoplace_controls = {
['coal'] = {frequency = 'none', size = 'none', richness = 'none'},
['stone'] = {frequency = 'none', size = 'none', richness = 'none'},
['copper-ore'] = {frequency = 'none', size = 'none', richness = 'none'},
['iron-ore'] = {frequency = 'none', size = 'none', richness = 'none'},
['crude-oil'] = {frequency = 'very-high', size = 'big', richness = 'normal'},
['trees'] = {frequency = 'none', size = 'none', richness = 'none'},
['enemy-base'] = {frequency = 'high', size = 'big', richness = 'good'}
}
game.create_surface('deep_jungle', map_gen_settings)
game.forces['player'].set_spawn_position({0, 0}, game.surfaces['deep_jungle'])
end
event.on_init(on_init)
event.add(defines.events.on_chunk_generated, on_chunk_generated)
event.add(defines.events.on_chunk_charted, on_chunk_charted)
event.add(defines.events.on_entity_died, on_entity_died)
event.add(defines.events.on_player_joined_game, on_player_joined_game)
require 'modules.rocks_yield_ore'

View File

@ -0,0 +1,508 @@
local Task = require 'utils.task'
local Token = require 'utils.token'
local Event = require 'utils.event'
local Terrain = require 'maps.deep_jungle.terrain'
local Public = {}
local force_chunk = false
local ceil = math.ceil
local queue_task = Task.queue_task
local tiles_per_call = 12
local total_calls = ceil(1024 / tiles_per_call)
local regen_decoratives = false
local generate_map = Terrain.heavy_functions
-- Set to false by modules that want to control the on_chunk_generated event themselves.
Public.enable_register_events = true
-- Simple "loop" that is UPS friendly.
local function get_position(data)
data.yv = data.yv + 1
if data.yv == 32 then
if data.xv == 32 then
data.xv = 0
end
if data.yv == 32 then
data.yv = 0
end
data.xv = data.xv + 1
end
data.position = {x = data.top_x + data.xv, y = data.top_y + data.yv}
end
local function do_tile_inner(tiles, tile, pos)
if type(tile) == 'string' then
tiles[#tiles + 1] = {name = tile, position = pos}
end
end
local function do_tile(x, y, data, shape)
local pos = {x, y}
-- local coords need to be 'centered' to allow for correct rotation and scaling.
local tile = shape(data)
if type(tile) == 'table' then
do_tile_inner(data.tiles, tile.tile, pos)
local hidden_tile = tile.hidden_tile
if hidden_tile then
data.hidden_tiles[#data.hidden_tiles + 1] = {tile = hidden_tile, position = pos}
end
local entities = tile.entities
if entities then
for _, entity in ipairs(entities) do
if not entity.position then
entity.position = pos
end
data.entities[#data.entities + 1] = entity
end
end
local buildings = tile.buildings
if buildings then
for _, entity in ipairs(buildings) do
if not entity.position then
entity.position = pos
end
data.buildings[#data.buildings + 1] = entity
end
end
local decoratives = tile.decoratives
if decoratives then
for _, decorative in ipairs(decoratives) do
data.decoratives[#data.decoratives + 1] = decorative
end
end
local markets = tile.markets
if markets then
for _, t in ipairs(markets) do
if not t.position then
t.position = pos
end
data.markets[#data.markets + 1] = t
end
end
local treasure = tile.treasure
if treasure then
for _, t in ipairs(treasure) do
if not t.position then
t.position = pos
end
data.treasure[#data.treasure + 1] = t
end
end
else
do_tile_inner(data.tiles, tile, pos)
end
end
local function do_row(row, data, shape)
local y = data.top_y + row
local top_x = data.top_x
local tiles = data.tiles
data.y = y
for x = top_x, top_x + 31 do
data.x = x
local pos = {data.x, data.y}
get_position(data)
-- local coords need to be 'centered' to allow for correct rotation and scaling.
local tile = shape(data)
if type(tile) == 'table' then
do_tile_inner(tiles, tile.tile, pos)
local hidden_tile = tile.hidden_tile
if hidden_tile then
data.hidden_tiles[#data.hidden_tiles + 1] = {tile = hidden_tile, position = pos}
end
local entities = tile.entities
if entities then
for _, entity in ipairs(entities) do
if not entity.position then
entity.position = pos
end
data.entities[#data.entities + 1] = entity
end
end
local buildings = tile.buildings
if buildings then
for _, entity in ipairs(buildings) do
if not entity.position then
entity.position = pos
end
data.buildings[#data.buildings + 1] = entity
end
end
local decoratives = tile.decoratives
if decoratives then
for _, decorative in ipairs(decoratives) do
if not decorative.position then
decorative.position = pos
end
data.decoratives[#data.decoratives + 1] = decorative
end
end
local markets = tile.markets
if markets then
for _, t in ipairs(markets) do
if not t.position then
t.position = pos
end
data.markets[#data.markets + 1] = t
end
end
local treasure = tile.treasure
if treasure then
for _, t in ipairs(treasure) do
if not t.position then
t.position = pos
end
data.treasure[#data.treasure + 1] = t
end
end
else
do_tile_inner(tiles, tile, pos)
end
end
end
local function do_place_tiles(data)
local surface = data.surface
surface.set_tiles(data.tiles, true)
end
local function do_place_hidden_tiles(data)
local surface = data.surface
surface.set_tiles(data.hidden_tiles, true)
end
local function do_place_decoratives(data)
local surface = data.surface
if regen_decoratives then
surface.regenerate_decorative(nil, {{data.top_x / 32, data.top_y / 32}})
end
local dec = data.decoratives
if #dec > 0 then
surface.create_decoratives({check_collision = true, decoratives = dec})
end
end
local function do_place_buildings(data)
local surface = data.surface
local entity
local callback
for _, e in ipairs(data.buildings) do
if e.e_type then
local p = e.position
if
surface.count_entities_filtered {
area = {{p.x - 32, p.y - 32}, {p.x + 32, p.y + 32}},
type = e.e_type,
limit = 1
} == 0
then
entity = surface.create_entity(e)
if entity and entity.valid then
if e.direction then
entity.direction = e.direction
end
if e.force then
entity.force = e.force
end
if e.callback then
local c = e.callback.callback
if c then
local d = {callback_data = e.callback.data}
if not d then
callback = Token.get(c)
callback(entity)
else
callback = Token.get(c)
callback(entity, d)
end
end
end
end
end
end
end
end
local function do_place_entities(data)
local surface = data.surface
local entity
local callback
for _, e in ipairs(data.entities) do
if e.collision then
if surface.can_place_entity(e) then
entity = surface.create_entity(e)
if entity then
if e.direction then
entity.direction = e.direction
end
if e.force then
entity.force = e.force
end
if e.amount then
entity.amount = e.amount
end
if e.callback then
local c = e.callback.callback
if not c then
return
end
local d = {callback_data = e.callback.data}
if not d then
callback = Token.get(c)
callback(entity)
else
callback = Token.get(c)
callback(entity, d)
end
end
end
end
else
entity = surface.create_entity(e)
if entity then
if e.direction then
entity.direction = e.direction
end
if e.force then
entity.force = e.force
end
if e.amount then
entity.amount = e.amount
end
if e.callback then
local c = e.callback.callback
if c then
local d = {callback_data = e.callback.data}
if not d then
callback = Token.get(c)
callback(entity)
else
callback = Token.get(c)
callback(entity, d)
end
end
end
end
end
end
end
local function run_chart_update(data)
local x = data.top_x / 32
local y = data.top_y / 32
local surface = data.surface
if not surface or not surface.valid then
return
end
if game.forces.player.is_chunk_charted(surface, {x, y}) then
-- Don't use full area, otherwise adjacent chunks get charted
game.forces.player.chart(
surface,
{
{data.top_x, data.top_y},
{data.top_x + 1, data.top_y + 1}
}
)
end
end
local function map_gen_action(data)
local state = data.y
if state < 32 then
local shape = generate_map
if shape == nil then
return false
end
if not data.surface.valid then
return
end
local count = tiles_per_call
local y = state + data.top_y
local x = data.x
local max_x = data.top_x + 32
data.y = y
repeat
count = count - 1
get_position(data)
do_tile(x, y, data, shape)
x = x + 1
if x == max_x then
y = y + 1
if y == data.top_y + 32 then
break
end
x = data.top_x
data.y = y
end
data.x = x
until count == 0
data.y = y - data.top_y
return true
elseif state == 32 then
do_place_tiles(data)
data.y = 33
return true
elseif state == 33 then
do_place_hidden_tiles(data)
data.y = 34
return true
elseif state == 34 then
do_place_entities(data)
data.y = 35
return true
elseif state == 35 then
do_place_buildings(data)
data.y = 36
return true
elseif state == 36 then
do_place_decoratives(data)
data.y = 37
return true
elseif state == 37 then
run_chart_update(data)
return false
end
end
local map_gen_action_token = Token.register(map_gen_action)
--- Adds generation of a Chunk of the map to the queue
-- @param event <table> the event table from on_chunk_generated
function Public.schedule_chunk(event)
local surface = event.surface
local shape = generate_map
if event.tick < 1 then
return
end
if not surface.valid then
return
end
if not shape then
return
end
local area = event.area
local data = {
yv = -0,
xv = 0,
y = 0,
x = area.left_top.x,
area = area,
top_x = area.left_top.x,
top_y = area.left_top.y,
surface = surface,
tiles = {},
hidden_tiles = {},
entities = {},
buildings = {},
decoratives = {},
markets = {},
treasure = {}
}
if not data.surface or not data.surface.valid then
return
end
queue_task(map_gen_action_token, data, total_calls)
end
--- Generates a Chunk of map when called
-- @param event <table> the event table from on_chunk_generated
function Public.do_chunk(event)
local surface = event.surface
local shape = generate_map
if not surface.valid then
return
end
if not shape then
return
end
local area = event.area
local data = {
yv = -0,
xv = 0,
area = area,
top_x = area.left_top.x,
top_y = area.left_top.y,
surface = surface,
tiles = {},
hidden_tiles = {},
entities = {},
buildings = {},
decoratives = {},
markets = {},
treasure = {}
}
if not data.surface.valid then
return
end
for row = 0, 31 do
do_row(row, data, shape)
end
do_place_tiles(data)
do_place_hidden_tiles(data)
do_place_entities(data)
do_place_buildings(data)
do_place_decoratives(data)
end
local do_chunk = Public.do_chunk
local schedule_chunk = Public.schedule_chunk
local function on_chunk(event)
if force_chunk then
do_chunk(event)
else
schedule_chunk(event)
end
end
Event.add(defines.events.on_chunk_generated, on_chunk)
return Public

142
maps/deep_jungle/main.lua Normal file
View File

@ -0,0 +1,142 @@
require 'modules.no_deconstruction_of_neutral_entities'
require 'modules.spawners_contain_biters'
require 'modules.biters_yield_coins'
require 'modules.rocks_yield_coins'
require 'modules.flashlight_toggle_button'
require 'maps.deep_jungle.generate'
local Global = require 'utils.global'
local Event = require 'utils.event'
local map_functions = require 'tools.map_functions'
local random = math.random
local this = {
chunks_charted = {}
}
Global.register(
this,
function(tbl)
this = tbl
end
)
local Public = {}
local function on_chunk_charted(event)
local surface = game.get_surface(event.surface_index)
local deco = game.decorative_prototypes
local position = event.position
if this.chunks_charted[tostring(position.x) .. tostring(position.y)] then
return
end
this.chunks_charted[tostring(position.x) .. tostring(position.y)] = true
local decorative_names = {}
for k, v in pairs(deco) do
if v.autoplace_specification then
decorative_names[#decorative_names + 1] = k
end
end
surface.regenerate_decorative(decorative_names, {position})
if random(1, 14) ~= 1 then
return
end
map_functions.draw_rainbow_patch({x = position.x * 32 + random(1, 32), y = position.y * 32 + random(1, 32)}, surface, random(14, 26), 2000)
end
local function on_player_joined_game(event)
local player = game.get_player(event.player_index)
local surface = game.get_surface('deep_jungle')
if player.online_time < 5 and surface.is_chunk_generated({0, 0}) then
player.teleport(surface.find_non_colliding_position('character', {0, 0}, 2, 1), 'deep_jungle')
else
if player.online_time < 5 then
player.teleport({0, 0}, 'deep_jungle')
end
end
if player.online_time < 2 then
player.insert {name = 'iron-plate', count = 32}
end
end
local function on_entity_died(event)
local entity = event.entity
if not entity or not entity.valid then
return
end
local surface = entity.surface
if entity.type == 'tree' then
if random(1, 8) == 1 then
local p = surface.find_non_colliding_position('small-biter', entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'small-biter', position = entity.position}
end
return
end
if random(1, 16) == 1 then
local p = surface.find_non_colliding_position('medium-biter', entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'medium-biter', position = entity.position}
end
return
end
if random(1, 32) == 1 then
local p = surface.find_non_colliding_position('big-biter', entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'big-biter', position = entity.position}
end
return
end
if random(1, 512) == 1 then
local p = surface.find_non_colliding_position('behemoth-biter', entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'behemoth-biter', position = entity.position}
end
return
end
end
if entity.type == 'simple-entity' then
if random(1, 8) == 1 then
surface.create_entity {name = 'small-worm-turret', position = entity.position}
return
end
if random(1, 16) == 1 then
surface.create_entity {name = 'medium-worm-turret', position = entity.position}
return
end
if random(1, 32) == 1 then
surface.create_entity {name = 'big-worm-turret', position = entity.position}
return
end
end
end
local function on_init()
local map_gen_settings = {}
map_gen_settings.moisture = 0.99
map_gen_settings.water = 'none'
map_gen_settings.starting_area = 'normal'
map_gen_settings.cliff_settings = {cliff_elevation_interval = 4, cliff_elevation_0 = 0.1}
map_gen_settings.autoplace_controls = {
['coal'] = {frequency = 'none', size = 'none', richness = 'none'},
['stone'] = {frequency = 'none', size = 'none', richness = 'none'},
['copper-ore'] = {frequency = 'none', size = 'none', richness = 'none'},
['iron-ore'] = {frequency = 'none', size = 'none', richness = 'none'},
['crude-oil'] = {frequency = 'very-high', size = 'big', richness = 'normal'},
['trees'] = {frequency = 'none', size = 'none', richness = 'none'},
['enemy-base'] = {frequency = 'high', size = 'big', richness = 'good'}
}
game.create_surface('deep_jungle', map_gen_settings)
game.forces.player.set_spawn_position({0, 0}, game.surfaces['deep_jungle'])
end
Event.on_init(on_init)
Event.add(defines.events.on_chunk_charted, on_chunk_charted)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
require 'modules.rocks_yield_ore'
return Public

View File

@ -0,0 +1,291 @@
local simplex_noise = require 'utils.simplex_noise'
local random = math.random
local Public = {}
local function shuffle(tbl)
local size = #tbl
for i = size, 1, -1 do
local rand = math.random(size)
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
end
local function secret_shop(pos, surface)
local secret_market_items = {
{price = {{'coin', random(300, 600)}}, offer = {type = 'give-item', item = 'combat-shotgun'}},
{price = {{'coin', random(200, 400)}}, offer = {type = 'give-item', item = 'rocket-launcher'}},
{price = {{'coin', random(5, 10)}}, offer = {type = 'give-item', item = 'piercing-rounds-magazine'}},
--{price = {{"coin", random(150,250)}}, offer = {type = 'give-item', item = 'uranium-rounds-magazine'}},
{price = {{'coin', random(15, 30)}}, offer = {type = 'give-item', item = 'piercing-shotgun-shell'}},
{price = {{'coin', random(10, 20)}}, offer = {type = 'give-item', item = 'rocket'}},
{price = {{'coin', random(20, 30)}}, offer = {type = 'give-item', item = 'explosive-rocket'}},
{price = {{'coin', random(30, 60)}}, offer = {type = 'give-item', item = 'cluster-grenade'}},
{price = {{'coin', random(8, 16)}}, offer = {type = 'give-item', item = 'land-mine'}},
{price = {{'coin', random(200, 300)}}, offer = {type = 'give-item', item = 'heavy-armor'}},
{price = {{'coin', random(400, 800)}}, offer = {type = 'give-item', item = 'modular-armor'}},
{price = {{'coin', random(1000, 2000)}}, offer = {type = 'give-item', item = 'power-armor'}},
{price = {{'coin', random(2500, 5000)}}, offer = {type = 'give-item', item = 'fusion-reactor-equipment'}},
{price = {{'coin', random(200, 400)}}, offer = {type = 'give-item', item = 'battery-equipment'}},
{price = {{'coin', random(150, 250)}}, offer = {type = 'give-item', item = 'belt-immunity-equipment'}},
{price = {{'coin', random(100, 200)}}, offer = {type = 'give-item', item = 'night-vision-equipment'}},
{price = {{'coin', random(400, 800)}}, offer = {type = 'give-item', item = 'exoskeleton-equipment'}},
{price = {{'coin', random(200, 300)}}, offer = {type = 'give-item', item = 'personal-roboport-equipment'}},
{price = {{'coin', random(25, 50)}}, offer = {type = 'give-item', item = 'construction-robot'}},
-- {price = {{"coin", random(10000,20000)}}, offer = {type = 'give-item', item = 'energy-shield-equipment'}},
-- {price = {{"coin", random(5000,15000)}}, offer = {type = 'give-item', item = 'personal-laser-defense-equipment'}},
{price = {{'coin', random(100, 300)}}, offer = {type = 'give-item', item = 'loader'}},
{price = {{'coin', random(200, 400)}}, offer = {type = 'give-item', item = 'fast-loader'}},
{price = {{'coin', random(300, 500)}}, offer = {type = 'give-item', item = 'express-loader'}},
{price = {{'coin', random(150, 300)}}, offer = {type = 'give-item', item = 'locomotive'}},
{price = {{'coin', random(100, 200)}}, offer = {type = 'give-item', item = 'cargo-wagon'}},
{price = {{'coin', random(5, 15)}}, offer = {type = 'give-item', item = 'grenade'}},
{price = {{'coin', random(80, 160)}}, offer = {type = 'give-item', item = 'cliff-explosives'}},
{price = {{'coin', random(10, 20)}}, offer = {type = 'give-item', item = 'explosives', count = 50}},
{price = {{'coin', random(4, 8)}}, offer = {type = 'give-item', item = 'rail', count = 4}},
{price = {{'coin', random(20, 30)}}, offer = {type = 'give-item', item = 'train-stop'}},
{price = {{'coin', random(4, 12)}}, offer = {type = 'give-item', item = 'small-lamp'}},
{price = {{'coin', random(1, 4)}}, offer = {type = 'give-item', item = 'firearm-magazine'}},
{price = {{'coin', random(60, 150)}}, offer = {type = 'give-item', item = 'car', count = 1}},
{price = {{'coin', random(75, 150)}}, offer = {type = 'give-item', item = 'gun-turret', count = 1}},
{price = {{'coin', random(500, 750)}}, offer = {type = 'give-item', item = 'laser-turret', count = 1}},
{price = {{'coin', random(1000, 2000)}}, offer = {type = 'give-item', item = 'artillery-turret', count = 1}},
{price = {{'coin', random(100, 200)}}, offer = {type = 'give-item', item = 'artillery-shell', count = 1}},
{price = {{'coin', random(50, 150)}}, offer = {type = 'give-item', item = 'artillery-targeting-remote', count = 1}},
{price = {{'coin', random(5, 15)}}, offer = {type = 'give-item', item = 'shotgun-shell', count = 1}},
{price = {{'coin', random(8000, 16000)}}, offer = {type = 'give-item', item = 'power-armor-mk2', count = 1}},
{price = {{'coin', random(80, 160)}}, offer = {type = 'give-item', item = 'solar-panel-equipment', count = 1}},
{price = {{'coin', random(4, 8)}}, offer = {type = 'give-item', item = 'wood', count = 50}},
{price = {{'coin', random(4, 8)}}, offer = {type = 'give-item', item = 'iron-ore', count = 50}},
{price = {{'coin', random(4, 8)}}, offer = {type = 'give-item', item = 'copper-ore', count = 50}},
{price = {{'coin', random(4, 8)}}, offer = {type = 'give-item', item = 'stone', count = 50}},
{price = {{'coin', random(4, 8)}}, offer = {type = 'give-item', item = 'coal', count = 50}}
--{price = {{"coin", random(4,8)}}, offer = {type = 'give-item', item = 'uranium-ore', count = 50}}
}
secret_market_items = shuffle(secret_market_items)
local market = surface.create_entity {name = 'market', position = pos}
market.destructible = false
for i = 1, math.random(6, 10), 1 do
market.add_market_item(secret_market_items[i])
end
end
local function treasure_chest(position)
if not game.surfaces['deep_jungle'].can_place_entity({name = 'steel-chest', position = position, force = 'player'}) then
return
end
local treasure_chest_raffle_table = {}
local treasure_chest_loot_weights = {}
table.insert(treasure_chest_loot_weights, {{name = 'landfill', count = random(8, 16)}, 16})
table.insert(treasure_chest_loot_weights, {{name = 'iron-gear-wheel', count = random(16, 48)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'coal', count = random(16, 48)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'copper-cable', count = random(64, 128)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'inserter', count = random(4, 8)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'fast-inserter', count = random(4, 8)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'burner-inserter', count = random(4, 8)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'rocket-fuel', count = random(1, 5)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'small-electric-pole', count = random(4, 8)}, 7})
table.insert(treasure_chest_loot_weights, {{name = 'firearm-magazine', count = random(16, 48)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'submachine-gun', count = 1}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'grenade', count = random(6, 12)}, 5})
table.insert(treasure_chest_loot_weights, {{name = 'land-mine', count = random(8, 16)}, 5})
table.insert(treasure_chest_loot_weights, {{name = 'light-armor', count = 1}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'heavy-armor', count = 1}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'pipe', count = random(10, 100)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'explosives', count = random(40, 50)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'shotgun', count = 1}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'shotgun-shell', count = random(8, 16)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'stone-brick', count = random(80, 100)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'small-lamp', count = random(2, 4)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'rail', count = random(16, 48)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'coin', count = random(32, 320)}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-1', count = random(1, 3)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-2', count = random(1, 3)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-3', count = random(1, 2)}, 1})
for _, t in pairs(treasure_chest_loot_weights) do
for _ = 1, t[2], 1 do
table.insert(treasure_chest_raffle_table, t[1])
end
end
local e = game.surfaces['deep_jungle'].create_entity {name = 'wooden-chest', position = position, force = 'player'}
e.minable = false
local i = e.get_inventory(defines.inventory.chest)
for _ = 1, random(3, 7), 1 do
local loot = treasure_chest_raffle_table[random(1, #treasure_chest_raffle_table)]
i.insert(loot)
end
end
local function rare_treasure_chest(position)
if not game.surfaces['deep_jungle'].can_place_entity({name = 'steel-chest', position = position, force = 'player'}) then
return
end
local rare_treasure_chest_raffle_table = {}
local rare_treasure_chest_loot_weights = {}
table.insert(rare_treasure_chest_loot_weights, {{name = 'combat-shotgun', count = 1}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'piercing-shotgun-shell', count = random(8, 16)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'rocket-launcher', count = 1}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'rocket', count = random(4, 8)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'explosive-rocket', count = random(4, 8)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'modular-armor', count = 1}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'piercing-rounds-magazine', count = random(32, 64)}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'defender-capsule', count = random(4, 8)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'distractor-capsule', count = random(3, 5)}, 4})
table.insert(rare_treasure_chest_loot_weights, {{name = 'destroyer-capsule', count = random(2, 3)}, 3})
for _, t in pairs(rare_treasure_chest_loot_weights) do
for _ = 1, t[2], 1 do
table.insert(rare_treasure_chest_raffle_table, t[1])
end
end
local e = game.surfaces['deep_jungle'].create_entity {name = 'steel-chest', position = position, force = 'player'}
e.minable = false
local i = e.get_inventory(defines.inventory.chest)
for _ = 1, random(2, 3), 1 do
local loot = rare_treasure_chest_raffle_table[random(1, #rare_treasure_chest_raffle_table)]
i.insert(loot)
end
end
local function get_noise(name, pos)
local seed = game.surfaces[1].map_gen_settings.seed
local d2 = simplex_noise.d2
local noise_seed_add = 25000
if name == 1 then
local noise = {}
noise[1] = d2(pos.x * 0.001, pos.y * 0.001, seed)
seed = seed + noise_seed_add
noise[2] = d2(pos.x * 0.01, pos.y * 0.01, seed + noise_seed_add)
noise = noise[1] + noise[2] * 0.1
return noise
end
if name == 2 then
local noise = {}
noise[1] = d2(pos.x * 0.015, pos.y * 0.015, seed)
seed = seed + noise_seed_add
noise[2] = d2(pos.x * 0.15, pos.y * 0.15, seed + noise_seed_add)
noise = noise[1] + noise[2] * 0.2
return noise
end
if name == 3 then
local noise = {}
noise[1] = d2(pos.x * 0.025, pos.y * 0.025, seed)
seed = seed + noise_seed_add
noise[2] = d2(pos.x * 0.2, pos.y * 0.2, seed + noise_seed_add)
noise = noise[1] + noise[2] * 0.2
return noise
end
if name == 'greenwater' then
local noise = {}
noise[1] = d2(pos.x * 0.003, pos.y * 0.003, seed)
seed = seed + noise_seed_add
noise[2] = d2(pos.x * 0.03, pos.y * 0.03, seed + noise_seed_add)
noise = noise[1] + noise[2] * 0.1
return noise
end
end
local rock_raffle = {'sand-rock-big', 'sand-rock-big', 'rock-big', 'rock-big', 'rock-big', 'rock-big', 'rock-huge'}
local tree_raffle = {'tree-04', 'tree-07', 'tree-09', 'tree-06', 'tree-04', 'tree-07', 'tree-09', 'tree-04'}
local function process_tile(pos)
local noise_1 = get_noise(1, pos)
if noise_1 > -0.03 and noise_1 < 0.03 then
return 'deepwater'
end
if noise_1 > -0.05 and noise_1 < 0.05 then
return 'water'
end
local noise_greenwater = get_noise('greenwater', pos)
if noise_greenwater > -0.035 and noise_greenwater < 0.035 then
return 'water-green'
end
if noise_1 > -0.08 and noise_1 < 0.08 then
return false
end
local noise_2 = get_noise(2, pos)
if noise_2 > 0.37 or noise_2 < -0.37 then
if random(1, 4) == 1 then
return false, tree_raffle[math.ceil(math.abs(noise_1 * 8))]
end
end
local noise_3 = get_noise(3, pos)
if noise_3 > 0.5 then
if random(1, 3) == 1 then
return false, rock_raffle[random(1, #rock_raffle)]
end
end
return false
end
local function process_bits(data)
local pos = data.position
local tiles = data.tiles
local entities = data.entities
local surface = game.surfaces['deep_jungle']
local treasure_chests = {}
local rare_treasure_chests = {}
local secret_shops = {}
local tile_to_insert, entity_to_place = process_tile(pos)
if entity_to_place then
entities[#entities + 1] = {name = entity_to_place, position = pos, force = 'player'}
end
if tile_to_insert then
tiles[#tiles + 1] = {name = tile_to_insert, position = pos}
if random(1, 40) == 1 and tile_to_insert == 'deepwater' then
entities[#entities + 1] = {name = 'fish', position = pos}
end
end
if random(1, 1500) == 1 then
table.insert(treasure_chests, pos)
end
if random(1, 16000) == 1 then
table.insert(rare_treasure_chests, pos)
end
if random(1, 8000) == 1 then
table.insert(secret_shops, pos)
end
for _, v in pairs(treasure_chests) do
treasure_chest(v)
end
for _, v in pairs(rare_treasure_chests) do
rare_treasure_chest(v)
end
for _, v in pairs(secret_shops) do
if not surface.get_tile(v).collides_with('player-layer') then
local area = {{v.x - 128, v.y - 128}, {v.x + 128, v.y + 128}}
if surface.count_entities_filtered({name = 'market', area = area}) == 0 then
secret_shop(v, surface)
end
end
end
end
function Public.heavy_functions(data)
local surface = data.surface
local map_name = 'deep_jungle'
if string.sub(surface.name, 0, #map_name) ~= map_name then
return
end
if not data.seed then
data.seed = surface.map_gen_settings.seed
end
process_bits(data)
end
return Public

View File

@ -1,477 +0,0 @@
--luacheck: ignore
--deep jungle-- mewmew made this --
local map_functions = require 'tools.map_functions'
local simplex_noise = require 'utils.simplex_noise'
simplex_noise = simplex_noise.d2
local event = require 'utils.event'
local math_random = math.random
local function treasure_chest(position)
local p = game.surfaces['deep_jungle'].find_non_colliding_position('wooden-chest', position, 2, 0.5)
if not p then
return
end
treasure_chest_raffle_table = {}
treasure_chest_loot_weights = {}
table.insert(treasure_chest_loot_weights, {{name = 'iron-gear-wheel', count = math_random(16, 48)}, 10})
table.insert(treasure_chest_loot_weights, {{name = 'coal', count = math_random(16, 48)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'copper-cable', count = math_random(64, 128)}, 10})
table.insert(treasure_chest_loot_weights, {{name = 'inserter', count = math_random(8, 16)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'fast-inserter', count = math_random(4, 8)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'stack-filter-inserter', count = math_random(2, 4)}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'stack-inserter', count = math_random(2, 4)}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'burner-inserter', count = math_random(16, 32)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'electric-engine-unit', count = math_random(1, 16)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'engine-unit', count = math_random(1, 16)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'rocket-fuel', count = math_random(1, 5)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'empty-barrel', count = math_random(1, 10)}, 7})
table.insert(treasure_chest_loot_weights, {{name = 'lubricant-barrel', count = math_random(1, 10)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'crude-oil-barrel', count = math_random(1, 10)}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'iron-stick', count = math_random(1, 100)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'small-electric-pole', count = math_random(8, 32)}, 9})
table.insert(treasure_chest_loot_weights, {{name = 'firearm-magazine', count = math_random(16, 48)}, 8})
table.insert(treasure_chest_loot_weights, {{name = 'grenade', count = math_random(16, 32)}, 5})
table.insert(treasure_chest_loot_weights, {{name = 'land-mine', count = math_random(24, 48)}, 5})
table.insert(treasure_chest_loot_weights, {{name = 'light-armor', count = 1}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'heavy-armor', count = 1}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'pipe', count = math_random(10, 100)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'wooden-chest', count = 1}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'burner-mining-drill', count = 1}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'iron-axe', count = 1}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'steel-axe', count = 1}, 3})
table.insert(treasure_chest_loot_weights, {{name = 'raw-wood', count = math_random(5, 50)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'sulfur', count = math_random(20, 50)}, 7})
table.insert(treasure_chest_loot_weights, {{name = 'explosives', count = math_random(20, 50)}, 6})
table.insert(treasure_chest_loot_weights, {{name = 'shotgun', count = 1}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'stone-brick', count = math_random(80, 100)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'small-lamp', count = math_random(3, 10)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'rail', count = math_random(32, 100)}, 4})
table.insert(treasure_chest_loot_weights, {{name = 'coin', count = math_random(32, 100)}, 1})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-1', count = math_random(1, 4)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-2', count = math_random(1, 3)}, 2})
table.insert(treasure_chest_loot_weights, {{name = 'assembling-machine-3', count = math_random(1, 2)}, 1})
for _, t in pairs(treasure_chest_loot_weights) do
for x = 1, t[2], 1 do
table.insert(treasure_chest_raffle_table, t[1])
end
end
local e = game.surfaces['deep_jungle'].create_entity {name = 'wooden-chest', position = p, force = 'player'}
e.minable = false
local i = e.get_inventory(defines.inventory.chest)
for x = 1, math_random(3, 7), 1 do
local loot = treasure_chest_raffle_table[math_random(1, #treasure_chest_raffle_table)]
i.insert(loot)
end
end
local function rare_treasure_chest(position)
local p = game.surfaces['deep_jungle'].find_non_colliding_position('steel-chest', position, 2, 0.5)
if not p then
return
end
local rare_treasure_chest_raffle_table = {}
local rare_treasure_chest_loot_weights = {}
table.insert(rare_treasure_chest_loot_weights, {{name = 'combat-shotgun', count = 1}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'piercing-shotgun-shell', count = math_random(16, 48)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'rocket-launcher', count = 1}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'rocket', count = math_random(16, 48)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'explosive-rocket', count = math_random(16, 48)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'modular-armor', count = 1}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'power-armor', count = 1}, 1})
table.insert(rare_treasure_chest_loot_weights, {{name = 'uranium-rounds-magazine', count = math_random(16, 48)}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'piercing-rounds-magazine', count = math_random(64, 128)}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'exoskeleton-equipment', count = 1}, 2})
table.insert(rare_treasure_chest_loot_weights, {{name = 'defender-capsule', count = math_random(8, 16)}, 5})
table.insert(rare_treasure_chest_loot_weights, {{name = 'distractor-capsule', count = math_random(4, 8)}, 4})
table.insert(rare_treasure_chest_loot_weights, {{name = 'destroyer-capsule', count = math_random(4, 8)}, 3})
table.insert(rare_treasure_chest_loot_weights, {{name = 'atomic-bomb', count = 1}, 1})
for _, t in pairs(rare_treasure_chest_loot_weights) do
for x = 1, t[2], 1 do
table.insert(rare_treasure_chest_raffle_table, t[1])
end
end
local e = game.surfaces['deep_jungle'].create_entity {name = 'steel-chest', position = p, force = 'player'}
e.minable = false
local i = e.get_inventory(defines.inventory.chest)
for x = 1, math_random(2, 3), 1 do
local loot = rare_treasure_chest_raffle_table[math_random(1, #rare_treasure_chest_raffle_table)]
i.insert(loot)
end
end
local function get_noise(name, pos)
local seed = game.surfaces[1].map_gen_settings.seed
local noise_seed_add = 25000
seed = seed + noise_seed_add
if name == 1 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.01, pos.y * 0.01, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed)
local noise = noise[1] + noise[2] * 0.1
return noise
end
seed = seed + noise_seed_add
seed = seed + noise_seed_add
if name == 2 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.01, pos.y * 0.01, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed)
local noise = noise[1] + noise[2] * 0.1
return noise
end
seed = seed + noise_seed_add
seed = seed + noise_seed_add
if name == 3 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.001, pos.y * 0.001, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.01, pos.y * 0.01, seed)
local noise = noise[1] + noise[2] * 0.1
return noise
end
seed = seed + noise_seed_add
seed = seed + noise_seed_add
if name == 4 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.01, pos.y * 0.01, seed)
seed = seed + noise_seed_add
noise[2] = simplex_noise(pos.x * 0.1, pos.y * 0.1, seed)
local noise = noise[1] + noise[2] * 0.2
return noise
end
seed = seed + noise_seed_add
seed = seed + noise_seed_add
if name == 5 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.05, pos.y * 0.05, seed)
local noise = noise[1]
return noise
end
seed = seed + noise_seed_add
seed = seed + noise_seed_add
if name == 6 then
local noise = {}
noise[1] = simplex_noise(pos.x * 0.05, pos.y * 0.05, seed)
local noise = noise[1]
return noise
end
end
local worm_raffle = {'small-worm-turret', 'small-worm-turret', 'small-worm-turret', 'medium-worm-turret', 'medium-worm-turret', 'big-worm-turret'}
local rock_raffle = {'sand-rock-big', 'sand-rock-big', 'rock-big', 'rock-big', 'rock-big', 'rock-big', 'rock-huge'}
local function on_chunk_generated(event)
local surface = game.surfaces['deep_jungle']
if event.surface.name ~= surface.name then
return
end
local chunk_pos_x = event.area.left_top.x
local chunk_pos_y = event.area.left_top.y
local tiles = {}
local entities_to_place = {
rocks = {},
worms = {},
enemy_buildings = {},
trees = {},
fish = {},
treasure_chests = {},
rare_treasure_chests = {}
}
local decoratives = {}
local entities = surface.find_entities(event.area)
for _, e in pairs(entities) do
if e.type == 'tree' or e.force.name == 'enemy' then
e.destroy()
end
end
local tile_to_insert = false
for x = 0, 31, 1 do
for y = 0, 31, 1 do
local pos_x = chunk_pos_x + x
local pos_y = chunk_pos_y + y
local pos = {x = pos_x, y = pos_y}
tile_to_insert = false
local noise_3 = get_noise(3, pos)
if noise_3 > -0.1 and noise_3 < 0.1 then
if noise_3 > -0.05 and noise_3 < 0.05 then
tile_to_insert = 'water'
if math_random(1, 40) == 1 then
table.insert(entities_to_place.fish, pos)
end
end
if noise_3 > -0.03 and noise_3 < 0.03 then
tile_to_insert = 'deepwater'
if math_random(1, 40) == 1 then
table.insert(entities_to_place.fish, pos)
end
end
else
local tile_distance_to_center = pos_x ^ 2 + pos_y ^ 2
local noise_1 = get_noise(1, pos)
local noise_2 = get_noise(2, pos)
local noise_4 = get_noise(4, pos)
if tile_distance_to_center > 10000 then
if math_random(1, 500) == 1 then
table.insert(entities_to_place.worms, pos)
end
if noise_4 > -0.1 and noise_4 < 0.1 and noise_1 > 0.3 and noise_2 > 0.3 then
if math_random(1, 8) == 1 then
table.insert(entities_to_place.rocks, pos)
end
end
end
if noise_4 < -0.8 or noise_4 > 0.8 then
tile_to_insert = 'dirt-6'
end
if noise_3 < -0.1 then
if noise_1 > 0.2 then
if math_random(1, 4) == 1 then
table.insert(entities_to_place.trees, {'tree-02', pos})
end
if math_random(1, 7500) == 1 then
table.insert(entities_to_place.rare_treasure_chests, pos)
end
if math_random(1, 1250) == 1 then
table.insert(entities_to_place.treasure_chests, pos)
end
if noise_1 > 0.8 and tile_distance_to_center > 8000 then
tile_to_insert = 'water-green'
if math_random(1, 24) == 1 then
table.insert(entities_to_place.fish, pos)
end
end
end
if noise_1 < -0.2 then
if math_random(1, 4) == 1 then
table.insert(entities_to_place.trees, {'tree-04', pos})
end
if math_random(1, 7500) == 1 then
table.insert(entities_to_place.rare_treasure_chests, pos)
end
if math_random(1, 1250) == 1 then
table.insert(entities_to_place.treasure_chests, pos)
end
if noise_1 < -0.75 and tile_distance_to_center > 8000 then
if math_random(1, 36) == 1 then
table.insert(entities_to_place.enemy_buildings, pos)
end
end
end
else
if noise_2 > 0.2 then
if math_random(1, 4) == 1 then
table.insert(entities_to_place.trees, {'tree-07', pos})
end
if math_random(1, 7500) == 1 then
table.insert(entities_to_place.rare_treasure_chests, pos)
end
if math_random(1, 1250) == 1 then
table.insert(entities_to_place.treasure_chests, pos)
end
if noise_2 > 0.75 and tile_distance_to_center > 8000 then
if math_random(1, 36) == 1 then
table.insert(entities_to_place.enemy_buildings, pos)
end
end
end
if noise_2 < -0.2 then
if math_random(1, 4) == 1 then
table.insert(entities_to_place.trees, {'tree-09', pos})
end
if math_random(1, 7500) == 1 then
table.insert(entities_to_place.rare_treasure_chests, pos)
end
if math_random(1, 1250) == 1 then
table.insert(entities_to_place.treasure_chests, pos)
end
if noise_2 < -0.8 and tile_distance_to_center > 8000 then
tile_to_insert = 'water-green'
if math_random(1, 24) == 1 then
table.insert(entities_to_place.fish, pos)
end
end
end
end
end
if tile_to_insert ~= 'deepwater' and tile_to_insert ~= 'water' and tile_to_insert ~= 'water-green' then
if math_random(1, 3) == 1 then
local noise = get_noise(5, pos)
if noise > 0.2 then
table.insert(decoratives, {name = 'green-hairy-grass', position = pos, amount = 2})
end
if noise < -0.7 then
table.insert(decoratives, {name = 'green-pita', position = pos, amount = 2})
end
local noise = get_noise(6, pos)
if noise > 0.7 then
table.insert(decoratives, {name = 'green-croton', position = pos, amount = 3})
end
if noise < -0.2 then
table.insert(decoratives, {name = 'green-asterisk', position = pos, amount = 2})
end
end
end
if tile_to_insert == false then
table.insert(tiles, {name = 'grass-1', position = {pos_x, pos_y}})
else
table.insert(tiles, {name = tile_to_insert, position = {pos_x, pos_y}})
end
end
end
surface.set_tiles(tiles, true)
surface.create_decoratives {check_collision = false, decoratives = decoratives}
for _, p in pairs(entities_to_place.enemy_buildings) do
if math_random(1, 3) == 1 then
if surface.can_place_entity({name = 'spitter-spawner', position = p}) then
surface.create_entity {name = 'spitter-spawner', position = p}
end
else
if surface.can_place_entity({name = 'biter-spawner', position = p}) then
surface.create_entity {name = 'biter-spawner', position = p}
end
end
end
for _, p in pairs(entities_to_place.worms) do
local e = worm_raffle[math_random(1, #worm_raffle)]
if surface.can_place_entity({name = e, position = p}) then
surface.create_entity {name = e, position = p}
end
end
for _, p in pairs(entities_to_place.rocks) do
local e = rock_raffle[math_random(1, #rock_raffle)]
surface.create_entity {name = e, position = p}
end
for _, p in pairs(entities_to_place.trees) do
if surface.can_place_entity({name = p[1], position = p[2]}) then
surface.create_entity {name = p[1], position = p[2]}
end
end
for _, p in pairs(entities_to_place.treasure_chests) do
treasure_chest(p)
end
for _, p in pairs(entities_to_place.rare_treasure_chests) do
rare_treasure_chest(p)
end
for _, p in pairs(entities_to_place.fish) do
surface.create_entity {name = 'fish', position = p}
end
end
local function on_chunk_charted(event)
if not global.chunks_charted then
global.chunks_charted = {}
end
local surface = game.surfaces[event.surface_index]
local position = event.position
if global.chunks_charted[tostring(position.x) .. tostring(position.y)] then
return
end
global.chunks_charted[tostring(position.x) .. tostring(position.y)] = true
local force = event.force
if math_random(1, 12) ~= 1 then
return
end
map_functions.draw_rainbow_patch({x = position.x * 32 + math_random(1, 32), y = position.y * 32 + math_random(1, 32)}, surface, math_random(14, 26), 2000)
end
local function on_player_joined_game(event)
local player = game.players[event.player_index]
if not global.map_init_done then
game.forces['player'].technologies['flamethrower'].enabled = false
local map_gen_settings = {}
map_gen_settings.water = 'none'
map_gen_settings.cliff_settings = {cliff_elevation_interval = 4, cliff_elevation_0 = 0.1}
map_gen_settings.autoplace_controls = {
['coal'] = {frequency = 'high', size = 'big', richness = 'normal'},
['stone'] = {frequency = 'high', size = 'big', richness = 'normal'},
['copper-ore'] = {frequency = 'high', size = 'big', richness = 'normal'},
['iron-ore'] = {frequency = 'high', size = 'big', richness = 'normal'},
['crude-oil'] = {frequency = 'high', size = 'big', richness = 'normal'},
['trees'] = {frequency = 'none', size = 'none', richness = 'none'},
['enemy-base'] = {frequency = 'none', size = 'none', richness = 'none'},
--["grass"] = {frequency = "none", size = "none", richness = "none"},
['sand'] = {frequency = 'none', size = 'none', richness = 'none'},
['desert'] = {frequency = 'none', size = 'none', richness = 'none'},
['dirt'] = {frequency = 'none', size = 'none', richness = 'none'}
}
game.map_settings.pollution.pollution_restored_per_tree_damage = 0
game.create_surface('deep_jungle', map_gen_settings)
game.forces['player'].set_spawn_position({0, 0}, game.surfaces['deep_jungle'])
global.map_init_done = true
end
local surface = game.surfaces['deep_jungle']
if player.online_time < 5 and surface.is_chunk_generated({0, 0}) then
player.teleport(surface.find_non_colliding_position('character', {0, 0}, 2, 1), 'deep_jungle')
else
if player.online_time < 5 then
player.teleport({0, 0}, 'deep_jungle')
end
end
if player.online_time < 10 then
player.insert {name = 'submachine-gun', count = 1}
player.insert {name = 'raw-fish', count = 12}
player.insert {name = 'firearm-magazine', count = 32}
player.insert {name = 'steel-axe', count = 1}
player.insert {name = 'light-armor', count = 1}
end
end
local function on_marked_for_deconstruction(event)
if event.entity.name == 'rock-huge' or event.entity.name == 'rock-big' or event.entity.name == 'sand-rock-big' or event.entity.name == 'fish' or event.entity.type == 'tree' then
event.entity.cancel_deconstruction(game.players[event.player_index].force.name)
end
end
local function on_entity_died(event)
if event.entity.type == 'tree' then
if math_random(1, 6) == 1 then
local surface = game.surfaces['deep_jungle']
local p = surface.find_non_colliding_position('small-biter', event.entity.position, 2, 0.5)
if p then
surface.create_entity {name = 'small-biter', position = event.entity.position}
end
end
end
end
function cheat_mode()
local cheat_mode_enabed = true
if cheat_mode_enabed == true then
local surface = game.surfaces['deep_jungle']
game.player.cheat_mode = true
game.players[1].insert({name = 'power-armor-mk2'})
game.players[1].insert({name = 'fusion-reactor-equipment', count = 4})
game.players[1].insert({name = 'personal-laser-defense-equipment', count = 8})
game.players[1].insert({name = 'rocket-launcher'})
game.players[1].insert({name = 'explosive-rocket', count = 200})
game.speed = 2
surface.daytime = 1
game.player.force.research_all_technologies()
game.forces['enemy'].evolution_factor = 0.2
local chart = 300
local surface = game.surfaces['deep_jungle']
game.forces['player'].chart(surface, {lefttop = {x = chart * -1, y = chart * -1}, rightbottom = {x = chart, y = chart}})
end
end
event.add(defines.events.on_chunk_generated, on_chunk_generated)
event.add(defines.events.on_chunk_charted, on_chunk_charted)
event.add(defines.events.on_entity_died, on_entity_died)
event.add(defines.events.on_marked_for_deconstruction, on_marked_for_deconstruction)
event.add(defines.events.on_player_joined_game, on_player_joined_game)

View File

@ -53,6 +53,9 @@ function Public.bouncy_shells(event)
return false
end
local cause = event.cause
if not cause and not cause.valid then
return
end
if cause.shooting_state.state == defines.shooting.not_shooting then
return false
end

View File

@ -101,7 +101,7 @@ function Public.get_replacement_tile(surface, position)
shuffle(vectors)
for k, v in pairs(vectors) do
local tile = surface.get_tile(position.x + v[1], position.y + v[2])
if tile and not tile.collides_with('resource-layer') then
if tile and tile.valid and not tile.collides_with('resource-layer') then
return tile.name
end
end

View File

@ -711,6 +711,7 @@ function Public.remove_offline_players()
return
end
local offline_players = WPT.get('offline_players')
local offline_players_surface_removal = WPT.get('offline_players_surface_removal')
local active_surface_index = WPT.get('active_surface_index')
local surface = game.surfaces[active_surface_index]
local player_inv = {}
@ -729,7 +730,9 @@ function Public.remove_offline_players()
player_inv[3] = target.get_inventory(defines.inventory.character_guns)
player_inv[4] = target.get_inventory(defines.inventory.character_ammo)
player_inv[5] = target.get_inventory(defines.inventory.character_trash)
ICT_Functions.remove_surface(target) -- remove empty surface
if offline_players_surface_removal then
ICT_Functions.remove_surface(target) -- remove empty surface
end
if target.get_item_count() == 0 then -- if the player has zero items, don't do anything
offline_players[i] = nil

View File

@ -742,42 +742,43 @@ function Public.remove_surface(player)
kick_players_from_surface(car)
local trust_system = IC.get('trust_system')
local owner = car.owner
if owner then
owner = game.get_player(owner)
if owner and owner.valid then
if trust_system[owner.index] then
trust_system[owner.index] = nil
end
end
if trust_system[player.index] then
trust_system[player.index] = nil
end
local renders = IC.get('renders')
if renders[owner.index] then
rendering.destroy(renders[owner.index])
renders[owner.index] = nil
if renders[player.index] then
rendering.destroy(renders[player.index])
renders[player.index] = nil
end
local player_gui_data = IC.get('player_gui_data')
if player_gui_data[owner.name] then
player_gui_data[owner.name] = nil
if player_gui_data[player.name] then
player_gui_data[player.name] = nil
end
local players = IC.get('players')
if players[owner.index] then
players[owner.index] = nil
if players[player.index] then
players[player.index] = nil
end
local misc_settings = IC.get('misc_settings')
if misc_settings[owner.index] then
misc_settings[owner.index] = nil
if misc_settings[player.index] then
misc_settings[player.index] = nil
end
kill_doors(car)
surfaces[car.saved_entity] = nil
cars[car.saved_entity] = nil
local surface_index = car.surface
local surface = game.surfaces[surface_index]
kill_doors(car)
if not surface or not surface.valid then
return
end
for _, tile in pairs(surface.find_tiles_filtered({area = car.area})) do
surface.set_tiles({{name = 'out-of-map', position = tile.position}}, true)
end
@ -787,8 +788,6 @@ function Public.remove_surface(player)
surface.set_tiles({{name = 'out-of-map', position = {x = p.x - 1, y = p.y}}}, true)
end
game.delete_surface(surface)
surfaces[car.saved_entity] = nil
cars[car.saved_entity] = nil
end
function Public.kill_car(entity)
@ -1195,6 +1194,9 @@ function Public.remove_invalid_cars()
end
for k, index in pairs(surfaces) do
local surface = game.surfaces[index]
if not validate_entity(surface) then
return
end
if not cars[tonumber(surface.name)] then
game.delete_surface(surface)
surfaces[k] = nil

View File

@ -190,6 +190,7 @@ function Public.reset_table()
this.disconnect_wagon = false
this.offline_players_enabled = true
this.offline_players = {}
this.offline_players_surface_removal = false
this.collapse_amount = false
this.collapse_speed = false
this.y_value_position = 20

View File

@ -4,6 +4,7 @@
local Global = require 'utils.global'
local Session = require 'utils.datastore.session_data'
local Event = require 'utils.event'
local Freeplay = require 'utils.freeplay'
local Server = require 'utils.server'
local MapFuntions = require 'tools.map_functions'
local CommonFunctions = require 'utils.common'
@ -19,6 +20,9 @@ local Color = require 'utils.color_presets'
-- require 'modules.thirst'
local this = {
entities_cache = nil,
active_surface = nil,
last_friend = nil,
remove_offline_players = {
players = {},
time = 216000, -- 1h
@ -270,6 +274,88 @@ local industrial_zone_layers = {
}
}
local industrial_zone_layers_modded = {
{
type = 'LuaTile',
name = 'concrete',
objects = {
'concrete'
},
elevation = 0.3,
resolution = 0.2,
hook = nil,
deps = nil
},
{
type = 'LuaTile',
name = 'stones',
objects = {
'stone-path'
},
elevation = 0.2,
resolution = 0.4,
hook = nil,
deps = nil
},
{
type = 'LuaTile',
name = 'shallows',
objects = {
'water-shallow'
},
elevation = 0.7,
resolution = 0.01,
hook = nil,
deps = nil
},
{
type = 'LuaEntity',
name = 'scrap',
objects = {
'mineable-wreckage'
},
elevation = 0.5,
resolution = 0.1,
hook = set_neutral_to_entity,
deps = nil
},
{
type = 'LuaEntity',
name = 'walls',
objects = {
'stone-wall'
},
elevation = 0.5,
resolution = 0.09,
hook = set_neutral_to_entity,
deps = nil
},
{
type = 'LuaEntity',
name = 'hostile',
objects = {
'character',
'gun-turret'
},
elevation = 0.92,
resolution = 0.99,
hook = set_noise_hostile_hook,
deps = fetch_common
},
{
type = 'LuaEntity',
name = 'structures',
objects = {
'big-electric-pole',
'medium-electric-pole'
},
elevation = 0.9,
resolution = 0.9,
hook = set_neutral_to_entity,
deps = nil
}
}
local swampy_rivers_layers = {
{
type = 'LuaTile',
@ -359,9 +445,11 @@ this.presets = {
['swampy-rivers'] = swampy_rivers_layers
}
this.entities_cache = nil
this.surface = nil
this.last_friend = nil
this.presets_modded = {
['flooded-metropolia'] = industrial_zone_layers_modded,
['swampy-rivers'] = swampy_rivers_layers
}
local function pick_map()
return this.maps[CommonFunctions.rand_range(1, #this.maps)]
end
@ -430,18 +518,25 @@ this.bp = {
merchant = require('planet_prison.bp.merchant')
}
local function init_game()
Freeplay.set('disabled', true)
LayersFunctions.init()
ClaimsFunctions.init(MapConfig.claim_markers, MapConfig.claim_max_distance)
local map = pick_map()
local preset = this.presets[map.name]
this.surface = game.create_surface('arena', map)
this.surface.brightness_visual_weights = {
local preset
if is_game_modded() then
preset = this.presets_modded[map.name]
else
preset = this.presets[map.name]
end
local surface = game.create_surface('arena', map)
surface.brightness_visual_weights = {
1 / 0.85,
1 / 0.85,
1 / 0.85
}
this.surface.ticks_per_day = 25000 * 4
surface.ticks_per_day = 25000 * 4
this.active_surface = surface.index
this.perks = {}
this.events.merchant.spawn_tick = game.tick + 5000
this.events.raid_groups = {}
@ -507,7 +602,12 @@ local explode_ship =
function(data)
local ship = data.ship
local id = data.id
local surface = data.surface
local active_surface = data.active_surface
local surface = game.get_surface(active_surface)
if not surface or not surface.valid then
return
end
for _, ent in pairs(Blueprints.reference_get_entities(ship)) do
if not ent.valid then
goto continue
@ -554,7 +654,7 @@ local function do_spawn_point(player)
}
local id = rendering.draw_text(object)
local data = {id = id, time_left = time_left, ship = instance, surface = player.surface}
local data = {id = id, time_left = time_left, ship = instance, active_surface = player.surface.index}
local timer = Timers.set_timer(time_left, explode_ship)
Timers.set_timer_on_update(timer, explode_ship_update)
@ -824,7 +924,8 @@ local function init_player(p)
this.perks[p.name] = {
flashlight_enable = true,
minimap = false,
chat_global = true
chat_global = true,
init = true
}
for i = 1, 7 do
@ -881,8 +982,9 @@ end
local function on_player_joined_game(e)
local p = game.players[e.player_index]
player_reconnected(p)
redraw_gui(p)
if this.perks and this.perks[p.name] then
if this.perks and this.perks[p.name] and this.perks[p.name].init then
return
end
init_player(p)
@ -986,7 +1088,6 @@ local function _calculate_attack_costs(surf, bb)
}
local objects = surf.find_entities_filtered(query)
if next(objects) == nil then
log('B')
return 0
end
@ -1230,7 +1331,7 @@ local function cause_event(s)
end
local function on_tick()
local s = this.surface
local s = this.active_surface
if not s then
log('on_tick: surface empty!')
return
@ -1238,7 +1339,7 @@ local function on_tick()
local tick = game.tick
local surf = this.surface
local surf = game.get_surface(this.active_surface)
if not surf or not surf.valid then
return
end
@ -1248,7 +1349,7 @@ local function on_tick()
end
LayersFunctions.do_job(surf)
cause_event(s)
cause_event(surf)
if (tick + 1) % 60 == 0 then
Timers.do_job()
@ -1291,6 +1392,7 @@ local valid_ents = {
['crash-site-spaceship-wreck-small-4'] = true,
['crash-site-spaceship-wreck-small-5'] = true,
['crash-site-spaceship-wreck-small-6'] = true,
['mineable-wreckage'] = true,
['sand-rock-big'] = true,
['rock-big'] = true,
['rock-huge'] = true
@ -1753,8 +1855,20 @@ local function move_to_orbit(player)
orbit_perms.add_player(player)
end
local function on_marked_for_deconstruction(event)
local entity = event.entity
local player = game.get_player(event.player_index)
if entity and entity.valid and player and player.valid then
entity.cancel_deconstruction(player.force.name)
end
end
local function on_rocket_launched(e)
local surf = this.surface
local surf = game.get_surface(this.active_surface)
if not surf or not surf.valid then
return
end
local pid = e.player_index
surf.print('>> The rocket was launched')
if pid == nil then
@ -1781,6 +1895,7 @@ Event.add(defines.events.on_player_banned, on_player_died)
Event.add(defines.events.on_pre_player_left_game, on_pre_player_left_game)
Event.add(defines.events.on_player_respawned, on_player_respawned)
Event.add(defines.events.on_player_dropped_item, on_player_dropped_item)
Event.add(defines.events.on_marked_for_deconstruction, on_marked_for_deconstruction)
Event.add(defines.events.on_entity_damaged, on_entity_damaged)
Event.add(defines.events.on_entity_died, on_entity_died)
Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)

View File

@ -1,4 +1,4 @@
local CommonFunctions = require 'maps.planet_prison.mod.common'
local CommonFunctions = require 'utils.common'
local Global = require 'utils.global'
local Token = require 'utils.token'

View File

@ -1,4 +1,4 @@
local CommonFunctions = require 'maps.planet_prison.mod.common'
local CommonFunctions = require 'utils.common'
local Global = require 'utils.global'
local Public = {}

View File

@ -1,4 +1,4 @@
local CommonFunctions = require 'maps.planet_prison.mod.common'
local CommonFunctions = require 'utils.common'
local SimplexFunctions = require 'maps.planet_prison.mod.simplex_noise'
local Token = require 'utils.token'
local Global = require 'utils.global'

View File

@ -1,7 +1,7 @@
-- Original implementation taken from here https://github.com/thenumbernine/lua-simplexnoise/blob/master/2d.lua
local Global = require 'utils.global'
local CommonFunctions = require 'maps.planet_prison.mod.common'
local CommonFunctions = require 'utils.common'
local Public = {}
local this = {}

View File

@ -6,6 +6,7 @@ require 'modules.biters_yield_coins'
require 'modules.scrap_towny_ffa.mining'
require 'modules.scrap_towny_ffa.on_tick_schedule'
require 'modules.scrap_towny_ffa.building'
require 'modules.scrap_towny_ffa.spaceship'
require 'modules.scrap_towny_ffa.town_center'
require 'modules.scrap_towny_ffa.market'
require 'modules.scrap_towny_ffa.slots'
@ -18,6 +19,8 @@ require 'modules.scrap_towny_ffa.trap'
require 'modules.scrap_towny_ffa.turrets_drop_ammo'
require 'modules.scrap_towny_ffa.combat_balance'
local Autostash = require 'modules.autostash'
local BottomFrame = require 'comfy_panel.bottom_frame'
local Table = require 'modules.scrap_towny_ffa.table'
local Nauvis = require 'modules.scrap_towny_ffa.nauvis'
local Biters = require 'modules.scrap_towny_ffa.biters'
@ -28,43 +31,91 @@ local Team = require 'modules.scrap_towny_ffa.team'
local Spawn = require 'modules.scrap_towny_ffa.spawn'
local Radar = require 'modules.scrap_towny_ffa.limited_radar'
local default_surface = 'nauvis'
-- for testing purposes only!!!
local testing_mode = false
-- how long in ticks between spawn and death will be considered spawn kill (10 seconds)
local max_ticks_between_spawns = 60 * 10
-- how many players must login before teams are teams_enabled
local min_players_for_enabling_towns = 0
local function load_buffs(player)
if player.force.name ~= 'player' and player.force.name ~= 'rogue' then return end
local ffatable = Table.get_table()
local player_index = player.index
if player.character == nil then return end
if ffatable.buffs[player_index] == nil then ffatable.buffs[player_index] = {} end
if ffatable.buffs[player_index].character_inventory_slots_bonus ~= nil then
player.character.character_inventory_slots_bonus = ffatable.buffs[player_index].character_inventory_slots_bonus
end
if ffatable.buffs[player_index].character_mining_speed_modifier ~= nil then
player.character.character_mining_speed_modifier = ffatable.buffs[player_index].character_mining_speed_modifier
end
if ffatable.buffs[player_index].character_crafting_speed_modifier ~= nil then
player.character.character_crafting_speed_modifier = ffatable.buffs[player_index].character_crafting_speed_modifier
end
end
local function on_player_joined_game(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local surface = game.surfaces[default_surface]
local surface = game.surfaces['nauvis']
player.game_view_settings.show_minimap = false
player.game_view_settings.show_map_view_options = false
player.game_view_settings.show_entity_info = true
player.map_view_settings = {
["show-logistic-network"] = false,
["show-electric-network"] = false,
["show-turret-range"] = false,
["show-pollution"] = false,
["show-train-station-names"] = false,
["show-player-names"] = false,
["show-networkless-logistic-members"] = false,
["show-non-standard-map-info"] = false
}
player.show_on_map = false
--player.game_view_settings.show_side_menu = false
Info.toggle_button(player)
Info.show(player)
Team.set_player_color(player)
if player.force ~= game.forces.player then
return
end
-- setup outlanders
Team.set_player_to_outlander(player)
if player.online_time == 0 then
Info.show(player)
if testing_mode then
ffatable.towns_enabled = true
else
ffatable.players = ffatable.players + 1
if ffatable.players >= min_players_for_enabling_towns then ffatable.towns_enabled = true end
end
player.teleport({0, 0}, game.surfaces['limbo'])
Team.give_outlander_items(player)
Team.give_key(player)
Team.set_player_to_outlander(player)
Team.give_player_items(player)
player.insert{name="coin", count="100"}
player.insert{name="stone-furnace", count="1"}
Team.give_key(player.index)
if (testing_mode == true) then
player.cheat_mode = true
player.force.research_all_technologies()
player.insert{name="coin", count="9900"}
end
-- first time spawn point
local spawn_point = Spawn.get_spawn_point(player, surface)
local spawn_point = Spawn.get_new_spawn_point(player, surface)
ffatable.strikes[player.name] = 0
Spawn.clear_spawn_point(spawn_point, surface)
-- reset cooldown
ffatable.cooldowns_town_placement[player.index] = 0
ffatable.last_respawn[player.name] = 0
player.teleport(spawn_point, surface)
return
end
load_buffs(player)
if not ffatable.requests[player.index] then
return
end
if ffatable.requests[player.index] ~= 'kill-character' then
if not ffatable.requests[player.index] or ffatable.requests[player.index] ~= 'kill-character' then
return
end
if player.character then
@ -79,39 +130,57 @@ local function on_player_respawned(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local surface = player.surface
Team.give_player_items(player)
if player.force == game.forces['rogue'] then
Team.set_player_to_outlander(player)
end
if player.force == game.forces['player'] then
Team.give_key(player)
Team.give_key(player.index)
end
-- TODO: this needs fixing!
-- 5 second cooldown
--local last_respawn = ffatable.cooldowns_last_respawn[player.name]
--if last_respawn == nil then last_respawn = 0 end
-- get_spawn_point will always return a valid spawn
local spawn_point = Spawn.get_spawn_point(player, surface)
-- reset cooldown
ffatable.cooldowns_last_respawn[player.name] = game.tick
player.teleport(surface.find_non_colliding_position('character', spawn_point, 0, 0.5, false), surface)
-- reset cooldown
ffatable.last_respawn[player.name] = game.tick
player.teleport(spawn_point, surface)
load_buffs(player)
end
local function on_player_died(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
ffatable.cooldowns_last_death[player.name] = game.tick
if ffatable.strikes[player.name] == nil then ffatable.strikes[player.name] = 0 end
local ticks_elapsed = game.tick - ffatable.last_respawn[player.name]
if ticks_elapsed < max_ticks_between_spawns then
ffatable.strikes[player.name] = ffatable.strikes[player.name] + 1
else
ffatable.strikes[player.name] = 0
end
end
local function on_init()
local ffatable = Table.get_table()
Autostash.insert_into_furnace(true)
Autostash.insert_into_wagon(true)
Autostash.bottom_button(true)
BottomFrame.reset()
BottomFrame.activate_custom_buttons(true)
--log("on_init")
game.enemy_has_vision_on_land_mines = false
game.draw_resource_selection = true
game.disable_tutorial_triggers()
ffatable.cooldowns_last_respawn = {}
ffatable.cooldowns_last_death = {}
local ffatable = Table.get_table()
ffatable.last_respawn = {}
ffatable.last_death = {}
ffatable.strikes = {}
ffatable.testing_mode = testing_mode
ffatable.spawn_point = {}
ffatable.buffs = {}
ffatable.players = 0
ffatable.towns_enabled = true
Nauvis.initialize()
Team.initialize()
@ -136,6 +205,8 @@ local function on_nth_tick(event)
if not tick_actions[seconds] then
return
end
--game.surfaces['nauvis'].play_sound({path = 'utility/alert_destroyed', volume_modifier = 1})
--log('seconds = ' .. seconds)
tick_actions[seconds]()
end

View File

@ -41,7 +41,12 @@ local function anarchy_gui(player)
frame.style.minimal_height = total_height
local t = frame.add({type = 'table', column_count = 5})
local headings = {{'Title', group_name_width}, {'Description', description_width}, {'Members', members_width * member_columns}, {'', actions_width * 2 - 30}}
local headings = {
{'Title', group_name_width},
{'Description', description_width},
{'Members', members_width * member_columns},
{'', actions_width * 2 - 30}
}
for _, h in pairs(headings) do
local l = t.add({type = 'label', caption = h[1]})
l.style.font_color = {r = 0.98, g = 0.66, b = 0.22}
@ -60,7 +65,8 @@ local function anarchy_gui(player)
b.style.right_padding = 4
b.style.bottom_padding = 2
local scroll_pane = frame.add({type = 'scroll-pane', name = 'scroll_pane', direction = 'vertical', horizontal_scroll_policy = 'never', vertical_scroll_policy = 'auto'})
local scroll_pane =
frame.add({type = 'scroll-pane', name = 'scroll_pane', direction = 'vertical', horizontal_scroll_policy = 'never', vertical_scroll_policy = 'auto'})
scroll_pane.style.maximal_height = total_height - 50
scroll_pane.style.minimal_height = total_height - 50
@ -268,7 +274,12 @@ local function new_group(frame, player)
local color = player.color
color = {r = color.r * 0.6 + 0.4, g = color.g * 0.6 + 0.4, b = color.b * 0.6 + 0.4, a = 1}
global.alliance_groups[new_group_name] = {name = new_group_name, color = color, description = new_group_description, members = {[tostring(player.name)] = player.index}}
global.alliance_groups[new_group_name] = {
name = new_group_name,
color = color,
description = new_group_description,
members = {[tostring(player.name)] = player.index}
}
color = {r = player.color.r * 0.7 + 0.3, g = player.color.g * 0.7 + 0.3, b = player.color.b * 0.7 + 0.3, a = 1}
game.print(tostring(player.name) .. ' has founded a new group!', color)
game.print('>> ' .. new_group_name, {r = 0.98, g = 0.66, b = 0.22})
@ -368,7 +379,8 @@ local function on_gui_click(event)
if event.element.type == 'button' and event.element.caption == 'Join' then
if global.spam_protection[tostring(player.name)] > game.tick then
player.print(
'Please wait ' .. math.ceil((global.spam_protection[tostring(player.name)] - game.tick) / 60) .. ' seconds before sending another request.',
'Please wait ' ..
math.ceil((global.spam_protection[tostring(player.name)] - game.tick) / 60) .. ' seconds before sending another request.',
message_color
)
return
@ -429,7 +441,6 @@ local function on_player_joined_game(event)
permission_group.set_allows_action(defines.input_action.gui_value_changed, true)
permission_group.set_allows_action(defines.input_action.gui_click, true)
permission_group.set_allows_action(defines.input_action.gui_selection_state_changed, true)
permission_group.set_allows_action(defines.input_action.open_kills_gui, true)
permission_group.set_allows_action(defines.input_action.open_character_gui, true)
permission_group.set_allows_action(defines.input_action.edit_permission_group, true)
permission_group.set_allows_action(defines.input_action.toggle_show_entity_info, true)

View File

@ -1,4 +1,3 @@
--luacheck: ignore
local Public = {}
local math_random = math.random
local math_floor = math.floor
@ -10,6 +9,7 @@ local table_remove = table.remove
local table_shuffle = table.shuffle_table
local Global = require 'utils.global'
local BiterHealthBooster = require 'modules.biter_health_booster_v2'
local tick_schedule = {}
Global.register(
@ -29,7 +29,7 @@ local function get_commmands(target, group)
local target_position = target.position
local distance_to_target = math_floor(math_sqrt((target_position.x - group_position.x) ^ 2 + (target_position.y - group_position.y) ^ 2))
local steps = math_floor(distance_to_target / step_length) + 1
local steps = math_floor((distance_to_target - 27) / step_length) + 1
local vector = {math_round((target_position.x - group_position.x) / steps, 3), math_round((target_position.y - group_position.y) / steps, 3)}
for _ = 1, steps, 1 do
@ -38,7 +38,7 @@ local function get_commmands(target, group)
local position = group.surface.find_non_colliding_position('small-biter', group_position, step_length, 2)
if position then
commands[#commands + 1] = {
type = defines.command.attack_area,
type = defines.command.go_to_location,
destination = {x = position.x, y = position.y},
radius = 16,
distraction = defines.distraction.by_damage
@ -46,17 +46,22 @@ local function get_commmands(target, group)
end
end
commands[#commands + 1] = {
type = defines.command.attack_area,
destination = target.position,
radius = 12,
distraction = defines.distraction.by_enemy
}
commands[#commands + 1] = {
type = defines.command.attack,
target = target,
distraction = defines.distraction.by_damage
}
commands[#commands + 1] = {
type = defines.command.attack_area,
destination = target.position,
radius = 27,
distraction = defines.distraction.by_anything
}
commands[#commands + 1] = {
type = defines.command.build_base,
destination = target.position,
distraction = defines.distraction.by_damage
}
return commands
end
@ -68,8 +73,13 @@ local function roll_market()
return
end
local keyset = {}
for town_name, _ in pairs(town_centers) do
table_insert(keyset, town_name)
for town_name, town_center in pairs(town_centers) do
local evolution = Evolution.get_biter_evolution(town_center.market.position)
local tries = math_floor(evolution * 20)
-- 1 try for each 5% of evolution
for _ = 1, tries, 1 do
table_insert(keyset, town_name)
end
end
local tc = math_random(1, #keyset)
return town_centers[keyset[tc]]
@ -107,6 +117,9 @@ end
function Public.validate_swarms()
local ffatable = Table.get_table()
if ffatable.testing_mode then
return
end
for k, swarm in pairs(ffatable.swarms) do
if not is_swarm_valid(swarm) then
table_remove(ffatable.swarms, k)
@ -116,6 +129,9 @@ end
function Public.unit_groups_start_moving()
local ffatable = Table.get_table()
if ffatable.testing_mode then
return
end
for _, swarm in pairs(ffatable.swarms) do
if swarm.group then
if swarm.group.valid then
@ -125,22 +141,34 @@ function Public.unit_groups_start_moving()
end
end
local function new_town(town_center)
-- cooldown for swarms on new towns is 15 minutes
local cooldown_ticks = 15 * 3600
local elapsed_ticks = game.tick - town_center.creation_tick
-- skip if within first 30 minutes and town evolution < 0.25
if elapsed_ticks < cooldown_ticks and town_center.evolution.biters < 0.15 then
return true
end
return false
end
function Public.swarm(town_center, radius)
if town_center == nil then
return
end
local ffatable = Table.get_table()
if ffatable.testing_mode then
return
end
local r = radius or 32
local tc = town_center or roll_market()
if not tc or r > 512 then
return
end
-- skip if town evolution < 0.25
if town_center.get_biter_evolution < 0.25 then
-- cancel if relatively new town
if new_town(tc) then
return
end
-- skip if we have to many swarms already
local count = table_size(ffatable.swarms)
local towns = table_size(ffatable.town_centers)
@ -167,15 +195,18 @@ function Public.swarm(town_center, radius)
return
end
-- get our evolution
local evolution = 0
-- get our evolution at the spawner location
local evolution
if spawner.name == 'spitter-spawner' then
evolution = Evolution.get_biter_evolution(spawner)
else
evolution = Evolution.get_spitter_evolution(spawner)
end
-- get our target amount of enemies
-- get the evolution at the market location
local market_evolution = Evolution.get_evolution(market.position)
-- get our target amount of enemies based on relative evolution
local count2 = (evolution * 124) + 4
local units = spawner.surface.find_enemy_units(spawner.position, 16, market.force)
@ -192,6 +223,18 @@ function Public.swarm(town_center, radius)
return
end
-- try up to 10 times to throw in a boss based on market evolution
-- evolution = 0%, chances 0 in 10
-- evoution = 10%, chances 1 in 10
-- evolution = 20%, chances 2 in 10
-- evolution = 100%, chances 10 in 10
local health_multiplier = 40 * market_evolution + 10
for _ = 1, math_floor(market_evolution * 10), 1 do
if math_random(1, 2) == 1 then
BiterHealthBooster.add_boss_unit(units[1], health_multiplier)
end
end
local unit_group_position = surface.find_non_colliding_position('biter-spawner', units[1].position, 256, 1)
if not unit_group_position then
return
@ -215,6 +258,30 @@ function Public.swarm(town_center, radius)
table_insert(ffatable.swarms, {group = unit_group, timeout = game.tick + 36000})
end
local function on_unit_group_finished_gathering(event)
local unit_group = event.group
local position = unit_group.position
local entities = unit_group.surface.find_entities_filtered({position = position, radius = 256, name = 'market'})
local target = entities[1]
if target ~= nil then
local force = target.force
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
local town_center = town_centers[force.name]
-- cancel if relatively new town
if new_town(town_center) then
return
end
unit_group.set_command(
{
type = defines.command.compound,
structure_type = defines.compound_command.return_last,
commands = get_commmands(target, unit_group)
}
)
end
end
local function on_tick()
if not tick_schedule[game.tick] then
return
@ -232,10 +299,13 @@ end
local on_init = function()
local ffatable = Table.get_table()
ffatable.swarms = {}
BiterHealthBooster.acid_nova(true)
BiterHealthBooster.check_on_entity_died(true)
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_unit_group_finished_gathering, on_unit_group_finished_gathering)
return Public

View File

@ -1,29 +1,89 @@
--luacheck: ignore
local Public = {}
local math_floor = math.floor
local table_insert = table.insert
local table_size = table.size
local Table = require 'modules.scrap_towny_ffa.table'
local town_radius = 27
local connection_radius = 7
local blacklist_entity_types = {
['car'] = true,
['character'] = true,
['combat-robot'] = true,
['construction-robot'] = true,
['logistic-robot'] = true,
['entity-ghost'] = true,
['character-corpse'] = true,
['corpse'] = true
}
-- these should be allowed to place inside any base by outlanders as neutral
local neutral_whitelist = {
['wooden-chest'] = true,
['burner-inserter'] = true,
['car'] = true,
['coin'] = true,
['express-loader'] = true,
['fast-inserter'] = true,
['fast-loader'] = true,
['filter-inserter'] = true,
['inserter'] = true,
['iron-chest'] = true,
['loader'] = true,
['long-handed-inserter'] = true,
['raw-fish'] = true,
['stack-filter-inserter'] = true,
['stack-inserter'] = true,
['steel-chest'] = true,
['raw-fish'] = true
['tank'] = true,
['wooden-chest'] = true
}
local entity_type_whitelist = {
-- these should be allowed to place outside any base by town players
local team_whitelist = {
['burner-inserter'] = true,
['car'] = true,
['cargo-wagon'] = true,
['coin'] = true,
['curved-rail'] = true,
['electric-pole'] = true,
['express-loader'] = true,
['fast-inserter'] = true,
['fast-loader'] = true,
['filter-inserter'] = true,
['inserter'] = true,
['fluid-wagon'] = true,
['iron-chest'] = true,
['loader'] = true,
['long-handed-inserter'] = true,
['locomotive'] = true,
['rail'] = true,
['rail-chain-signal'] = true,
['rail-signal'] = true,
['raw-fish'] = true,
['stack-filter-inserter'] = true,
['stack-inserter'] = true,
['steel-chest'] = true,
['straight-rail'] = true,
['tank'] = true,
['train-stop'] = true,
['wooden-chest'] = true
}
-- these need to be prototypes
local team_entities = {
['accumulator'] = true,
['ammo-turret'] = true,
['arithmetic-combinator'] = true,
['artillery-turret'] = true,
['assembling-machine'] = true,
['beacon'] = true,
['boiler'] = true,
['burner-generator'] = true,
['constant-combinator'] = true,
['container'] = true,
['curved-rail'] = true,
['decider-combinator'] = true,
['electric-energy-interface'] = true,
['electric-pole'] = true,
['electric-turret'] = true,
['fluid-turret'] = true,
@ -38,26 +98,27 @@ local entity_type_whitelist = {
['lab'] = true,
['lamp'] = true,
['land-mine'] = true,
['linked-belt'] = true,
['linked-container'] = true,
['loader'] = true,
['loader-1x1'] = true,
['logistic-container'] = true,
['market'] = true,
['mining-drill'] = true,
['offshore-pump'] = true,
['pipe'] = true,
['pipe-to-ground'] = true,
['player-port'] = true,
['power-switch'] = true,
['programmable-speaker'] = true,
['pump'] = true,
['radar'] = true,
['rail-chain-signal'] = true,
['rail-signal'] = true,
['reactor'] = true,
['roboport'] = true,
['rocket-silo'] = true,
['solar-panel'] = true,
['splitter'] = true,
['storage-tank'] = true,
['straight-rail'] = true,
['train-stop'] = true,
['transport-belt'] = true,
['underground-belt'] = true,
['wall'] = true
@ -70,7 +131,7 @@ local function isolated(surface, force, position)
local count = 0
for _, e in pairs(surface.find_entities_filtered({area = area, force = force.name})) do
if entity_type_whitelist[e.type] then
if team_entities[e.type] then
count = count + 1
if count > 1 then
return false
@ -85,12 +146,13 @@ local function refund_item(event, item_name)
if item_name == 'blueprint' then
return
end
if event.player_index then
if event.player_index ~= nil then
game.players[event.player_index].insert({name = item_name, count = 1})
return
end
if event.robot then
-- return item to robot, but don't replace ghost (otherwise might loop)
if event.robot ~= nil then
local inventory = event.robot.get_inventory(defines.inventory.robot_cargo)
inventory.insert({name = item_name, count = 1})
return
@ -108,7 +170,7 @@ local function error_floaty(surface, position, msg)
)
end
local function in_range(pos1, pos2, radius)
function Public.in_range(pos1, pos2, radius)
if pos1 == nil then
return false
end
@ -126,170 +188,399 @@ local function in_range(pos1, pos2, radius)
return false
end
-- is the position near a town?
function Public.near_town(position, surface, radius)
local ffatable = Table.get_table()
for _, town_center in pairs(ffatable.town_centers) do
if town_center ~= nil then
local market = town_center.market
if in_range(position, market.position, radius) and market.surface == surface then
return true
end
function Public.in_area(position, area_center, area_radius)
if position == nil then
return false
end
if area_center == nil then
return false
end
if area_radius < 1 then
return true
end
if position.x >= area_center.x - area_radius and position.x <= area_center.x + area_radius then
if position.y >= area_center.y - area_radius and position.y <= area_center.y + area_radius then
return true
end
end
return false
end
local function in_town(force, position)
-- is the position near another town?
function Public.near_another_town(force_name, position, surface, radius)
-- check for nearby town centers
if force_name == nil then
return false
end
local ffatable = Table.get_table()
local forces = {}
-- check for nearby town centers
local fail = false
if table_size(ffatable.town_centers) > 0 then
for _, town_center in pairs(ffatable.town_centers) do
if town_center ~= nil then
local market = town_center.market
if market ~= nil and market.valid then
local market_force = market.force
if market_force ~= nil then
if market_force.name ~= nil then
table_insert(forces, market_force.name)
if force_name ~= market_force.name then
if Public.in_range(position, market.position, radius) == true then
fail = true
break
end
end
end
end
end
end
end
if fail == true then
return true
end
end
-- check for nearby town entities
if table.size(forces) > 0 then
local entities = surface.find_entities_filtered({position = position, radius = radius, force = forces})
for _, e in pairs(entities) do
if e.valid and e.force ~= nil then
local entity_force_name = e.force.name
--if force_name ~= force.name and force_name ~= 'enemy' and force_name ~= 'neutral' and force_name ~= 'player' and force_name ~= 'rogue' then
if entity_force_name ~= nil then
if entity_force_name ~= force_name then
if blacklist_entity_types[e.type] ~= true then
fail = true
break
end
end
end
end
end
if fail == true then
return true
end
end
return false
end
local function in_own_town(force, position)
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force.name]
if town_center ~= nil then
local center = town_center.market.position
if position.x >= center.x - town_radius and position.x <= center.x + town_radius then
if position.y >= center.y - town_radius and position.y <= center.y + town_radius then
return true
local market = town_center.market
if market ~= nil then
local center = market.position
if position.x >= center.x - town_radius and position.x <= center.x + town_radius then
if position.y >= center.y - town_radius and position.y <= center.y + town_radius then
return true
end
end
end
end
return false
end
local function prevent_isolation_entity(event, player)
local p = player or nil
function Public.in_restricted_zone(surface, position)
if surface.name ~= 'nauvis' then
return false
end
local chunk_position = {}
chunk_position.x = math_floor(position.x / 32)
chunk_position.y = math_floor(position.y / 32)
if chunk_position.x <= -33 or chunk_position.x >= 32 or chunk_position.y <= -33 or chunk_position.y >= 32 then
return true
end
return false
end
local function prevent_entity_in_restricted_zone(event)
local player_index = event.player_index or nil
local entity = event.created_entity
local position = entity.position
if not entity.valid then
return
end
local entity_name = entity.name
local item = event.item
if item == nil then
return
end
local item_name = item.name
local force = entity.force
if force == game.forces.player then
return
end
if force == game.forces['rogue'] then
if entity == nil or not entity.valid then
return
end
local name = entity.name
local surface = entity.surface
local position = entity.position
local error = false
if not in_town(force, position) and isolated(surface, force, position) then
if Public.in_restricted_zone(surface, position) then
error = true
entity.destroy()
if entity_name ~= 'entity-ghost' and entity_name ~= 'tile-ghost' then
refund_item(event, item_name)
local item = event.item
if name ~= 'entity-ghost' and name ~= 'tile-ghost' and item ~= nil then
refund_item(event, item.name)
end
--return true
end
if error == true then
if p ~= nil then
p.play_sound({path = 'utility/cannot_build', position = p.position, volume_modifier = 0.75})
if player_index ~= nil then
local player = game.players[player_index]
player.play_sound({path = 'utility/cannot_build', position = player.position, volume_modifier = 0.75})
end
error_floaty(surface, position, 'Building is not connected to town!')
error_floaty(surface, position, 'Can not build in restricted zone!')
end
end
local function prevent_isolation_tile(event, player)
local p = player or nil
local tile = event.tile
if not tile.valid then
local function prevent_unconnected_town_entities(event)
local player_index = event.player_index or nil
local entity = event.created_entity
if entity == nil or not entity.valid then
return
end
local name = entity.name
local surface = entity.surface
local position = entity.position
local force = entity.force
if force.index == game.forces.player.index or force.index == game.forces['rogue'].index then
-- no town restrictions if outlander or rogue
return
end
local error = false
if name ~= 'entity-ghost' then
if not in_own_town(force, position) and isolated(surface, force, position) and not team_whitelist[name] then
error = true
entity.destroy()
local item = event.item
if item ~= nil then
refund_item(event, item.name)
end
end
end
if error == true then
if player_index ~= nil then
local player = game.players[player_index]
player.play_sound({path = 'utility/cannot_build', position = player.position, volume_modifier = 0.75})
end
error_floaty(surface, position, 'Building is not connected to your town!')
end
end
local function prevent_landfill_in_restricted_zone(event)
local player_index = event.player_index or nil
local tile = event.tile
if tile == nil or not tile.valid then
return
end
local surface = game.surfaces[event.surface_index]
local fail = false
local position
for _, t in pairs(event.tiles) do
local old_tile = t.old_tile
position = t.position
if Public.in_restricted_zone(surface, position) then
fail = true
surface.set_tiles({{name = old_tile.name, position = position}}, true)
refund_item(event, tile.name)
end
end
if fail == true then
if player_index ~= nil then
local player = game.players[player_index]
player.play_sound({path = 'utility/cannot_build', position = player.position, volume_modifier = 0.75})
end
error_floaty(surface, position, 'Can not build in restricted zone!')
end
return fail
end
local function prevent_unconnected_town_tiles(event)
local player_index = event.player_index or nil
local tile = event.tile
if tile == nil or not tile.valid then
return
end
local tile_name = tile.name
local surface = game.surfaces[event.surface_index]
local tiles = event.tiles
local force
if event.player_index then
force = game.players[event.player_index].force
if player_index ~= nil then
force = game.players[player_index].force
else
force = event.robot.force
end
local error = false
local fail = false
local position
for _, t in pairs(tiles) do
local old_tile = t.old_tile
position = t.position
if not in_town(force, position) and isolated(surface, force, position) then
error = true
surface.set_tiles({{name = old_tile.name, position = position}}, true)
if tile_name ~= 'tile-ghost' then
if tile_name == 'stone-path' then
tile_name = 'stone-brick'
if tile.name ~= 'tile-ghost' then
if not in_own_town(force, position) and isolated(surface, force, position) then
fail = true
surface.set_tiles({{name = old_tile.name, position = position}}, true)
if tile.name == 'stone-path' then
tile.name = 'stone-brick'
end
refund_item(event, tile_name)
refund_item(event, tile.name)
end
end
end
if error == true then
if p ~= nil then
p.play_sound({path = 'utility/cannot_build', position = p.position, volume_modifier = 0.75})
if fail == true then
if player_index ~= nil then
local player = game.players[player_index]
player.play_sound({path = 'utility/cannot_build', position = player.position, volume_modifier = 0.75})
end
error_floaty(surface, position, 'Tile is not connected to town!')
end
end
local function restrictions(event, player)
local p = player or nil
local function prevent_entities_near_towns(event)
local player_index = event.player_index or nil
local entity = event.created_entity
if not entity.valid then
if entity == nil or not entity.valid then
return
end
local entity_name = entity.name
local name = entity.name
local surface = entity.surface
local position = entity.position
local error = false
if entity.force == game.forces['player'] or entity.force == game.forces['rogue'] then
if Public.near_town(position, surface, 32) then
error = true
local force_name
if player_index ~= nil then
local player = game.players[player_index]
if player ~= nil then
local force = player.force
if force ~= nil then
force_name = force.name
end
end
else
local robot = event.robot
if robot ~= nil then
local force = robot.force
if force ~= nil then
force_name = force.name
end
end
end
if Public.near_another_town(force_name, position, surface, 32) == true then
if neutral_whitelist[name] then
entity.force = game.forces['neutral']
else
entity.destroy()
if entity_name ~= 'entity-ghost' then
if player_index ~= nil then
local player = game.players[player_index]
player.play_sound({path = 'utility/cannot_build', position = player.position, volume_modifier = 0.75})
end
error_floaty(surface, position, "Can't build near town!")
if name ~= 'entity-ghost' then
refund_item(event, event.stack.name)
end
else
entity.force = game.forces['neutral']
return
end
end
end
local function prevent_tiles_near_towns(event)
local player_index = event.player_index or nil
local tile = event.tile
if tile == nil or not tile.valid then
return
end
if error == true then
if p ~= nil then
p.play_sound({path = 'utility/cannot_build', position = p.position, volume_modifier = 0.75})
local surface = game.surfaces[event.surface_index]
local force_name
if player_index ~= nil then
local player = game.players[player_index]
if player ~= nil then
local force = player.force
if force ~= nil then
force_name = force.name
end
end
else
local robot = event.robot
if robot ~= nil then
local force = robot.force
if force ~= nil then
force_name = force.name
end
end
end
local fail = false
local position
for _, t in pairs(event.tiles) do
local old_tile = t.old_tile
position = t.position
if Public.near_another_town(force_name, position, surface, 32) == true then
fail = true
surface.set_tiles({{name = old_tile.name, position = position}}, true)
refund_item(event, tile.name)
end
end
if fail == true then
if player_index ~= nil then
local player = game.players[player_index]
player.play_sound({path = 'utility/cannot_build', position = player.position, volume_modifier = 0.75})
end
error_floaty(surface, position, "Can't build near town!")
end
return fail
end
if not neutral_whitelist[entity.type] then
return
local function prevent_neutral_deconstruct(event)
local player = game.players[event.player_index] or nil
local entity = event.entity
if entity.to_be_deconstructed() and entity.force.name == 'neutral' then
for _, f in pairs(game.forces) do
if entity.is_registered_for_deconstruction(f) then
entity.cancel_deconstruction(f, player)
end
end
end
entity.force = game.forces['neutral']
end
-- called when a player places an item, or a ghost
local function on_built_entity(event)
local player = game.players[event.player_index]
if prevent_isolation_entity(event, player) then
if prevent_entity_in_restricted_zone(event) then
return
end
restrictions(event, player)
if prevent_entities_near_towns(event) then
return
end
if player.force.index ~= game.forces['player'].index and player.force.index ~= game.forces['rogue'].index then
prevent_unconnected_town_entities(event)
end
end
local function on_robot_built_entity(event)
if prevent_isolation_entity(event) then
local robot = event.robot
if prevent_entity_in_restricted_zone(event) then
return
end
restrictions(event)
if prevent_entities_near_towns(event) then
return
end
if robot.force.index ~= game.forces['player'].index and robot.force.index ~= game.forces['rogue'].index then
prevent_unconnected_town_entities(event)
end
end
-- called when a player places landfill
local function on_player_built_tile(event)
local player = game.players[event.player_index]
prevent_isolation_tile(event, player)
if prevent_landfill_in_restricted_zone(event) then
return
end
if prevent_tiles_near_towns(event) then
return
end
if player.force.index ~= game.forces['player'].index and player.force.index ~= game.forces['rogue'].index then
prevent_unconnected_town_tiles(event)
end
end
local function on_robot_built_tile(event)
prevent_isolation_tile(event)
local robot = event.robot
if prevent_landfill_in_restricted_zone(event) then
return
end
if prevent_tiles_near_towns(event) then
return
end
if robot.force.index ~= game.forces['player'].index and robot.force.index ~= game.forces['rogue'].index then
prevent_unconnected_town_tiles(event)
end
end
local function on_marked_for_deconstruction(event)
prevent_neutral_deconstruct(event)
end
local Event = require 'utils.event'
@ -297,5 +588,6 @@ Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_player_built_tile, on_player_built_tile)
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
Event.add(defines.events.on_robot_built_tile, on_robot_built_tile)
Event.add(defines.events.on_marked_for_deconstruction, on_marked_for_deconstruction)
return Public

View File

@ -0,0 +1,216 @@
local Public = {}
local table_shuffle = table.shuffle_table
local Table = require 'modules.scrap_towny_ffa.table'
local Color = require 'utils.color_presets'
local colors = {}
colors[1] = {name = 'Almond', rgb = {239, 222, 205}}
colors[2] = {name = 'Antique Brass', rgb = {205, 149, 117}}
colors[3] = {name = 'Apricot', rgb = {253, 217, 181}}
colors[4] = {name = 'Aquamarine', rgb = {120, 219, 226}}
colors[5] = {name = 'Asparagus', rgb = {135, 169, 107}}
colors[6] = {name = 'Atomic Tangerine', rgb = {255, 164, 116}}
colors[7] = {name = 'Banana Mania', rgb = {250, 231, 181}}
colors[8] = {name = 'Beaver', rgb = {159, 129, 112}}
colors[9] = {name = 'Bittersweet', rgb = {253, 124, 110}}
colors[10] = {name = 'Black', rgb = {0, 0, 0}}
colors[11] = {name = 'Blizzard Blue', rgb = {172, 229, 238}}
colors[12] = {name = 'Blue', rgb = {31, 117, 254}}
colors[13] = {name = 'Blue Bell', rgb = {162, 162, 208}}
colors[14] = {name = 'Blue Gray', rgb = {102, 153, 204}}
colors[15] = {name = 'Blue Green', rgb = {13, 152, 186}}
colors[16] = {name = 'Blue Violet', rgb = {115, 102, 189}}
colors[17] = {name = 'Blush', rgb = {222, 93, 131}}
colors[18] = {name = 'Brick Red', rgb = {203, 65, 84}}
colors[19] = {name = 'Brown', rgb = {180, 103, 77}}
colors[20] = {name = 'Burnt Orange', rgb = {255, 127, 73}}
colors[21] = {name = 'Burnt Sienna', rgb = {234, 126, 93}}
colors[22] = {name = 'Cadet Blue', rgb = {176, 183, 198}}
colors[23] = {name = 'Canary', rgb = {255, 255, 153}}
colors[24] = {name = 'Caribbean Green', rgb = {28, 211, 162}}
colors[25] = {name = 'Carnation Pink', rgb = {255, 170, 204}}
colors[26] = {name = 'Cerise', rgb = {221, 68, 146}}
colors[27] = {name = 'Cerulean', rgb = {29, 172, 214}}
colors[28] = {name = 'Chestnut', rgb = {188, 93, 88}}
colors[29] = {name = 'Copper', rgb = {221, 148, 117}}
colors[30] = {name = 'Cornflower', rgb = {154, 206, 235}}
colors[31] = {name = 'Cotton Candy', rgb = {255, 188, 217}}
colors[32] = {name = 'Dandelion', rgb = {253, 219, 109}}
colors[33] = {name = 'Denim', rgb = {43, 108, 196}}
colors[34] = {name = 'Desert Sand', rgb = {239, 205, 184}}
colors[35] = {name = 'Eggplant', rgb = {110, 81, 96}}
colors[36] = {name = 'Electric Lime', rgb = {206, 255, 29}}
colors[37] = {name = 'Fern', rgb = {113, 188, 120}}
colors[38] = {name = 'Forest Green', rgb = {109, 174, 129}}
colors[39] = {name = 'Fuchsia', rgb = {195, 100, 197}}
colors[40] = {name = 'Fuzzy Wuzzy', rgb = {204, 102, 102}}
colors[41] = {name = 'Gold', rgb = {231, 198, 151}}
colors[42] = {name = 'Goldenrod', rgb = {252, 217, 117}}
colors[43] = {name = 'Granny Smith Apple', rgb = {168, 228, 160}}
colors[44] = {name = 'Gray', rgb = {149, 145, 140}}
colors[45] = {name = 'Green', rgb = {28, 172, 120}}
colors[46] = {name = 'Green Blue', rgb = {17, 100, 180}}
colors[47] = {name = 'Green Yellow', rgb = {240, 232, 145}}
colors[48] = {name = 'Hot Magenta', rgb = {255, 29, 206}}
colors[49] = {name = 'Inchworm', rgb = {178, 236, 93}}
colors[50] = {name = 'Indigo', rgb = {93, 118, 203}}
colors[51] = {name = 'Jazzberry Jam', rgb = {202, 55, 103}}
colors[52] = {name = 'Jungle Green', rgb = {59, 176, 143}}
colors[53] = {name = 'Laser Lemon', rgb = {254, 254, 34}}
colors[54] = {name = 'Lavender', rgb = {252, 180, 213}}
colors[55] = {name = 'Lemon Yellow', rgb = {255, 244, 79}}
colors[56] = {name = 'Macaroni and Cheese', rgb = {255, 189, 136}}
colors[57] = {name = 'Magenta', rgb = {246, 100, 175}}
colors[58] = {name = 'Magic Mint', rgb = {170, 240, 209}}
colors[59] = {name = 'Mahogany', rgb = {205, 74, 76}}
colors[60] = {name = 'Maize', rgb = {237, 209, 156}}
colors[61] = {name = 'Manatee', rgb = {151, 154, 170}}
colors[62] = {name = 'Mango Tango', rgb = {255, 130, 67}}
colors[63] = {name = 'Maroon', rgb = {200, 56, 90}}
colors[64] = {name = 'Mauvelous', rgb = {239, 152, 170}}
colors[65] = {name = 'Melon', rgb = {253, 188, 180}}
colors[66] = {name = 'Midnight Blue', rgb = {26, 72, 118}}
colors[67] = {name = 'Mountain Meadow', rgb = {48, 186, 143}}
colors[68] = {name = 'Mulberry', rgb = {197, 75, 140}}
colors[69] = {name = 'Navy Blue', rgb = {25, 116, 210}}
colors[70] = {name = 'Neon Carrot', rgb = {255, 163, 67}}
colors[71] = {name = 'Olive Green', rgb = {186, 184, 108}}
colors[72] = {name = 'Orange', rgb = {255, 117, 56}}
colors[73] = {name = 'Orange Red', rgb = {255, 43, 43}}
colors[74] = {name = 'Orange Yellow', rgb = {248, 213, 104}}
colors[75] = {name = 'Orchid', rgb = {230, 168, 215}}
colors[76] = {name = 'Outer Space', rgb = {65, 74, 76}}
colors[77] = {name = 'Outrageous Orange', rgb = {255, 110, 74}}
colors[78] = {name = 'Pacific Blue', rgb = {28, 169, 201}}
colors[79] = {name = 'Peach', rgb = {255, 207, 171}}
colors[80] = {name = 'Periwinkle', rgb = {197, 208, 230}}
colors[81] = {name = 'Piggy Pink', rgb = {253, 221, 230}}
colors[82] = {name = 'Pine Green', rgb = {21, 128, 120}}
colors[83] = {name = 'Pink Flamingo', rgb = {252, 116, 253}}
colors[84] = {name = 'Pink Sherbert', rgb = {247, 143, 167}}
colors[85] = {name = 'Plum', rgb = {142, 69, 133}}
colors[86] = {name = 'Purple Heart', rgb = {116, 66, 200}}
colors[87] = {name = "Purple Mountain's Majesty", rgb = {157, 129, 186}}
colors[88] = {name = 'Purple Pizzazz', rgb = {254, 78, 218}}
colors[89] = {name = 'Radical Red', rgb = {255, 73, 108}}
colors[90] = {name = 'Raw Sienna', rgb = {214, 138, 89}}
colors[91] = {name = 'Raw Umber', rgb = {113, 75, 35}}
colors[92] = {name = 'Razzle Dazzle Rose', rgb = {255, 72, 208}}
colors[93] = {name = 'Razzmatazz', rgb = {227, 37, 107}}
colors[94] = {name = 'Red', rgb = {238, 32, 77}}
colors[95] = {name = 'Red Orange', rgb = {255, 83, 73}}
colors[96] = {name = 'Red Violet', rgb = {192, 68, 143}}
colors[97] = {name = "Robin's Egg Blue", rgb = {31, 206, 203}}
colors[98] = {name = 'Royal Purple', rgb = {120, 81, 169}}
colors[99] = {name = 'Salmon', rgb = {255, 155, 170}}
colors[100] = {name = 'Scarlet', rgb = {252, 40, 71}}
colors[101] = {name = "Screamin' Green", rgb = {118, 255, 122}}
colors[102] = {name = 'Sea Green', rgb = {159, 226, 191}}
colors[103] = {name = 'Sepia', rgb = {165, 105, 79}}
colors[104] = {name = 'Shadow', rgb = {138, 121, 93}}
colors[105] = {name = 'Shamrock', rgb = {69, 206, 162}}
colors[106] = {name = 'Shocking Pink', rgb = {251, 126, 253}}
colors[107] = {name = 'Silver', rgb = {205, 197, 194}}
colors[108] = {name = 'Sky Blue', rgb = {128, 218, 235}}
colors[109] = {name = 'Spring Green', rgb = {236, 234, 190}}
colors[110] = {name = 'Sunglow', rgb = {255, 207, 72}}
colors[111] = {name = 'Sunset Orange', rgb = {253, 94, 83}}
colors[112] = {name = 'Tan', rgb = {250, 167, 108}}
colors[113] = {name = 'Teal Blue', rgb = {24, 167, 181}}
colors[114] = {name = 'Thistle', rgb = {235, 199, 223}}
colors[115] = {name = 'Tickle Me Pink', rgb = {252, 137, 172}}
colors[116] = {name = 'Timberwolf', rgb = {219, 215, 210}}
colors[117] = {name = 'Tropical Rain Forest', rgb = {23, 128, 109}}
colors[118] = {name = 'Tumbleweed', rgb = {222, 170, 136}}
colors[119] = {name = 'Turquoise Blue', rgb = {119, 221, 231}}
colors[120] = {name = 'Unmellow Yellow', rgb = {255, 255, 102}}
colors[121] = {name = 'Violet (Purple)', rgb = {146, 110, 174}}
colors[122] = {name = 'Violet Blue', rgb = {50, 74, 178}}
colors[123] = {name = 'Violet Red', rgb = {247, 83, 148}}
colors[124] = {name = 'Vivid Tangerine', rgb = {255, 160, 137}}
colors[125] = {name = 'Vivid Violet', rgb = {143, 80, 157}}
colors[126] = {name = 'White', rgb = {255, 255, 255}}
colors[127] = {name = 'Wild Blue Yonder', rgb = {162, 173, 208}}
colors[128] = {name = 'Wild Strawberry', rgb = {255, 67, 164}}
colors[129] = {name = 'Wild Watermelon', rgb = {252, 108, 133}}
colors[130] = {name = 'Wisteria', rgb = {205, 164, 222}}
colors[131] = {name = 'Yellow', rgb = {252, 232, 131}}
colors[132] = {name = 'Yellow Green', rgb = {197, 227, 132}}
colors[133] = {name = 'Yellow Orange', rgb = {255, 174, 66}}
local function is_color_used(color, town_centers)
for _, center in pairs(town_centers) do
if center.color then
if center.color.r == color.r and center.color.g == color.g and center.color.b == color.b then
return true
end
end
end
end
function Public.get_random_color()
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
local rgb
local color = {}
local name
local shuffle_index = {}
for i = 1, #colors, 1 do
shuffle_index[i] = i
end
table_shuffle(shuffle_index)
for i = 1, #colors, 1 do
rgb = colors[shuffle_index[i]].rgb
name = colors[shuffle_index[i]].name
local red = rgb[1] / 255
local green = rgb[2] / 255
local blue = rgb[3] / 255
color.r = red
color.g = green
color.b = blue
if not is_color_used(color, town_centers) then
--log("color = " .. name)
return {name = name, color = color}
end
end
end
local function random_color(cmd)
local player = game.players[cmd.player_index]
if not player or not player.valid then
return
end
local force = player.force
if force.name == 'player' or force.name == 'rogue' then
player.print('You are not member of a town!', Color.fail)
return
end
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force.name]
local crayon = Public.get_random_color()
town_center.color = crayon.color
rendering.set_color(town_center.town_caption, town_center.color)
for _, p in pairs(force.players) do
if p.index == player.index then
player.print('Your town color is now ' .. crayon.name, crayon.color)
else
player.print(player.name .. ' has set the town color to ' .. crayon.name, crayon.color)
end
p.color = crayon.color
p.chat_color = crayon.color
end
end
commands.add_command(
'random-color',
'Randomly color your town..',
function(cmd)
random_color(cmd)
end
)
return Public

View File

@ -35,9 +35,8 @@ local balance_functions = {
local function on_research_finished(event)
local research_name = event.research.name
local force_name = event.research.force.name
local key
for b = 1, string_len(research_name), 1 do
key = string_sub(research_name, 0, b)
local key = string_sub(research_name, 0, b)
if balance_functions[key] then
balance_functions[key](force_name)
return

View File

@ -1,5 +1,6 @@
local Public = {}
local math_floor = math.floor
local math_log10 = math.log10
local Table = require 'modules.scrap_towny_ffa.table'
@ -29,6 +30,7 @@ local max_evolution_distance = 1024
local max_pollution_behemoth = 256
local max_pollution_big = 64
local max_pollution_medium = 16
-- max_factor < 1.0 means technology sum of weights will be greater than 1.0
local max_factor = 0.8
-- technology weights (biter, spitter, worm)
@ -106,7 +108,6 @@ local technology_weights = {
['gate'] = {biter = 1, spitter = 1, worm = 1},
['gun-turret'] = {biter = 1, spitter = 1, worm = 1},
['heavy-armor'] = {biter = 5, spitter = 5, worm = 5},
['improved-equipment'] = {biter = 1, spitter = 1, worm = 1},
['inserter-capacity-bonus-1'] = {biter = 1, spitter = 1, worm = 1},
['inserter-capacity-bonus-3'] = {biter = 1, spitter = 1, worm = 1},
['inserter-capacity-bonus-4'] = {biter = 1, spitter = 1, worm = 1},
@ -117,13 +118,13 @@ local technology_weights = {
['land-mine'] = {biter = 5, spitter = 5, worm = 5},
['landfill'] = {biter = 1, spitter = 1, worm = 1},
['laser'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret-speed-1'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret-speed-2'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret-speed-3'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret-speed-4'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret-speed-5'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret-speed-6'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret-speed-7'] = {biter = 5, spitter = 5, worm = 5},
['laser-shooting-speed-1'] = {biter = 5, spitter = 5, worm = 5},
['laser-shooting-speed-2'] = {biter = 5, spitter = 5, worm = 5},
['laser-shooting-speed-3'] = {biter = 5, spitter = 5, worm = 5},
['laser-shooting-speed-4'] = {biter = 5, spitter = 5, worm = 5},
['laser-shooting-speed-5'] = {biter = 5, spitter = 5, worm = 5},
['laser-shooting-speed-6'] = {biter = 5, spitter = 5, worm = 5},
['laser-shooting-speed-7'] = {biter = 5, spitter = 5, worm = 5},
['laser-turret'] = {biter = 5, spitter = 5, worm = 5},
['logistic-robotics'] = {biter = 1, spitter = 1, worm = 1},
['logistic-science-pack'] = {biter = 25, spitter = 25, worm = 25},
@ -240,89 +241,128 @@ max_spitter_weight = max_spitter_weight * max_factor
max_worm_weight = max_worm_weight * max_factor
local function get_unit_size(evolution)
-- returns a value 0-3 that represents the unit size
-- returns a value 1-4 that represents the unit size
-- basically evo values of: 0%, 10%, 30%, 60%, 80%, 100%
-- small unit chances are 100%, 100%, 50%, 25%, 12.5%, 0%
-- medium unit chances are 0%, 0%, 50%, 25%, 12.5%, 0%
-- big unit chances are 0%, 0%, 0%, 50%, 25%, 0%
-- behemoth unit chances are 0%, 0%, 0%, 0%, 50%, 100%
-- basically evo values of: 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%
-- -----------------------------------------------------------------------------------
-- small unit chances are 100% 60% 40% 30% 20% 15% 7.5% 0% 0% 0% 0%
-- medium unit chances are 0% 40% 40% 30% 20% 15% 7.5% 12.5% 25% 0% 0%
-- big unit chances are 0% 0% 20% 40% 60% 60% 75% 75% 50% 50% 0%
-- behemoth unit chances are 0% 0% 0% 0% 0% 10% 10% 12.5% 25% 50% 100%
-- and curve accordingly in between evo values
-- magic stuff happens here
if (evolution < 0.10) then
-- 0%
if (evolution < 0.1) then
return 1
end
if (evolution >= 0.10 and evolution < 0.40) then
local r = (evolution - 0.10) * 5
if math.random() < 0.5 then
return 1
end
if math.random() < r then
-- 10%
if (evolution >= 0.1 and evolution < 0.2) then
local r = math.random()
if r < 0.6 then
return 1
end
return 2
end
if (evolution >= 0.30 and evolution < 0.60) then
local r = (evolution - 0.30) * 3.3333
if math.random() < 0.5 then
if math.random() < 0.5 then
-- 20%
if (evolution >= 0.2 and evolution < 0.3) then
local r = math.random()
if r < 0.8 then
if r < 0.4 then
return 1
else
if math.random() < r then
return 2
end
end
return 3
end
-- 30%
if (evolution >= 0.3 and evolution < 0.4) then
local r = math.random()
if r < 0.6 then
if r < 0.3 then
return 1
else
return 2
end
end
return 3
end
-- 40%
if (evolution >= 0.4 and evolution < 0.5) then
local r = math.random()
if r < 0.4 then
if r < 0.2 then
return 1
else
return 2
end
end
return 3
end
-- 50%
if (evolution >= 0.5 and evolution < 0.6) then
local r = math.random()
if r < 0.9 then
if r < 0.3 then
if r < 0.15 then
return 1
else
return 2
end
end
else
if math.random() < r then
return 3
end
return 4
end
-- 60%
if (evolution >= 0.60 and evolution < 0.70) then
local r = math.random()
if r < 0.9 then
if r < 0.15 then
if r < 0.075 then
return 1
else
return 2
end
end
return 3
end
return 4
end
-- 70%
if (evolution >= 0.70 and evolution < 0.80) then
local r = math.random()
if r < 0.985 then
if r < 0.125 then
return 2
else
return 3
end
end
return 4
end
if (evolution >= 0.60 and evolution < 0.80) then
local r = (evolution - 0.60) * 5
if math.random() < 0.5 then
if math.random() < 0.5 then
if math.random() < r then
return 1
else
return 2
end
else
if math.random() < r then
return 2
else
return 3
end
end
else
if math.random() < r then
return 3
else
return 4
end
end
end
if (evolution >= 0.80 and evolution < 1.0) then
local r = (evolution - 0.80) * 5
if math.random() < 0.5 then
if math.random() < r then
if math.random() < r then
return 1
else
return 2
end
-- 80%
if (evolution >= 0.80 and evolution < 0.90) then
local r = math.random()
if r < 0.75 then
if r < 0.25 then
return 2
else
return 3
end
else
return 4
end
return 4
end
-- 90%
if (evolution >= 0.90 and evolution < 1) then
local r = math.random()
if r < 0.5 then
return 3
end
return 4
end
-- 100%
if (evolution >= 1.0) then
return 4
end
@ -336,6 +376,16 @@ local function distance_squared(pos1, pos2)
return d2
end
-- calculate the relative evolution based on evolution factor (0.0-1.0) and distance factor (0.0-1.0)
local function calculate_relative_evolution(evolution_factor, distance_factor)
-- distance factor will be from 0.0 to 1.0 but drop off dramatically towards zero
local log_distance_factor = math_log10(distance_factor * 10 + 1)
local evo = log_distance_factor * evolution_factor
if evo < 0.0 then evo = 0.0 end
if evo > 1.0 then evo = 1.0 end
return evo
end
local function get_relative_biter_evolution(position)
local ffatable = Table.get_table()
local relative_evolution = 0.0
@ -343,9 +393,10 @@ local function get_relative_biter_evolution(position)
-- for all of the teams
local teams = ffatable.town_centers
for _, town_center in pairs(teams) do
local market_position = town_center.market.position
local market = town_center.market
if market == nil or not market.valid then return relative_evolution end
-- calculate the distance squared
local d2 = distance_squared(position, market_position)
local d2 = distance_squared(position, market.position)
if d2 < max_d2 then
-- get the distance factor (0.0-1.0)
local distance_factor = 1.0 - d2 / max_d2
@ -356,8 +407,8 @@ local function get_relative_biter_evolution(position)
if town_center.evolution.biters == nil then
town_center.evolution.biters = 0.0
end
local evolution_factor = town_center.evolution.biters
local evo = distance_factor * evolution_factor
local evo = calculate_relative_evolution(town_center.evolution.biters, distance_factor)
-- get the highest of the relative evolutions of each town
relative_evolution = math.max(relative_evolution, evo)
end
end
@ -371,9 +422,10 @@ local function get_relative_spitter_evolution(position)
-- for all of the teams
local teams = ffatable.town_centers
for _, town_center in pairs(teams) do
local market_position = town_center.market.position
local market = town_center.market
if market == nil or not market.valid then return relative_evolution end
-- calculate the distance squared
local d2 = distance_squared(position, market_position)
local d2 = distance_squared(position, market.position)
if d2 < max_d2 then
-- get the distance factor (0.0-1.0)
local distance_factor = 1.0 - d2 / max_d2
@ -384,8 +436,8 @@ local function get_relative_spitter_evolution(position)
if town_center.evolution.spitters == nil then
town_center.evolution.spitters = 0.0
end
local evolution_factor = town_center.evolution.spitters
local evo = distance_factor * evolution_factor
local evo = calculate_relative_evolution(town_center.evolution.spitters, distance_factor)
-- get the highest of the relative evolutions of each town
relative_evolution = math.max(relative_evolution, evo)
end
end
@ -399,9 +451,10 @@ local function get_relative_worm_evolution(position)
-- for all of the teams
local teams = ffatable.town_centers
for _, town_center in pairs(teams) do
local market_position = town_center.market.position
local market = town_center.market
if market == nil or not market.valid then return relative_evolution end
-- calculate the distance squared
local d2 = distance_squared(position, market_position)
local d2 = distance_squared(position, market.position)
if d2 < max_d2 then
-- get the distance factor (0.0-1.0)
local distance_factor = 1.0 - d2 / max_d2
@ -412,8 +465,8 @@ local function get_relative_worm_evolution(position)
if town_center.evolution.worms == nil then
town_center.evolution.worms = 0.0
end
local evolution_factor = town_center.evolution.worms
local evo = distance_factor * evolution_factor
local evo = calculate_relative_evolution(town_center.evolution.worms, distance_factor)
-- get the highest of the relative evolutions of each town
relative_evolution = math.max(relative_evolution, evo)
end
end
@ -577,12 +630,13 @@ local function is_worm(entity)
return false
end
-- update evolution based on research completed (weighted)
-- sets the evolution to a value from 0.0 to 1.0 based on research progress
local function update_evolution(force_name, technology)
if technology == nil then
return
end
local ffatable = Table.get_table()
-- update evolution based on research completed (weighted)
local town_center = ffatable.town_centers[force_name]
-- town_center is a reference to a global table
if not town_center then
@ -600,6 +654,7 @@ local function update_evolution(force_name, technology)
local spitter_weight = weight.spitter
local worm_weight = weight.worm
-- update the evolution values (0.0 to 1.0)
-- max weights might be less than 1.0, to allow for evo > 1.0
local b = (biter_weight / max_biter_weight)
local s = (spitter_weight / max_spitter_weight)
local w = (worm_weight / max_worm_weight)
@ -613,9 +668,9 @@ end
local function on_research_finished(event)
local research = event.research
local force_name = research.force.name
local force = research.force
local technology = research.name
update_evolution(force_name, technology)
update_evolution(force.name, technology)
end
local function on_entity_spawned(event)

View File

@ -13,7 +13,7 @@ function Public.reproduce()
if #fishes == 0 then
return
end
if #fishes >= 100 then
if #fishes >= 128 then
return
end
-- pick a random fish
@ -52,15 +52,18 @@ local function on_player_used_capsule(event)
end
-- if using fish on water
if tile.name == 'water' and tile.name == 'water-green' and tile.name == 'deepwater' and tile.name == 'deepwater-green' then
if tile.name == 'water'
or tile.name == 'water-green'
or tile.name == 'water-mud'
or tile.name == 'water-shallow'
or tile.name == 'deepwater'
or tile.name == 'deepwater-green'
then
-- get the count of fish in the water nearby and test if can be repopulated
local fishes = surface.find_entities_filtered({name = 'fish', position = position, radius = 27})
if #fishes < 12 then
surface.create_entity({name = 'water-splash', position = position})
surface.create_entity({name = 'fish', position = position})
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return
end
surface.create_entity({name = 'water-splash', position = position})
surface.create_entity({name = 'fish', position = position})
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return
end
-- otherwise return the fish and make no sound
player.insert({name = 'raw-fish', count = 1})

View File

@ -10,17 +10,17 @@ The local inhabitants are indifferent to you at first, so long as you don't buil
by foreign technology. In fact, they get quite aggressive at the scent of it. If you were to hurt any of the natives you will be
brandished a rogue until your untimely death or until you find better digs.
To create a new town or outpost simply place a furnace down in a suitable spot that is not near any other towns or obstructed.
To create a new town simply place a furnace down in a suitable spot that is not near any other towns or obstructed.
The world seems to be limited in size with uninhabitable zones on four sides. News towns can only be built within these
borders and you must leave room for the town's size (radius of 27) when placing a new town.
borders and you must leave room for the town's size (radius of 27) when placing a new town. Each town costs 100 coins.
TIP: It's best to find a spot far from existing towns and pollution, as enemies will become aggressive once you form a town.
Once a town is formed, members may invite other players and teams using a raw fish. To invite another player, drop a fish
on that player (with the Z key). To accept an invite, offer a fish in return to the member. To leave a town, simply drop coal
Once a town is formed, members may invite other players and teams using a coin. To invite another player, drop a coin
on that player (with the Z key). To accept an invite, offer a coin in return to the member. To leave a town, simply drop coal
on the market. As a member of a town, your respawn point will change to that of the town.
To form any alliance with another town, drop a fish on a member or their market. If they agree they can reciprocate with a
fish offering.
To form any alliance with another town, drop a coin on a member or their market. If they agree they can reciprocate with a
coin offering.
The town market is the heart of your town. If it is destroyed, your town is destroyed and you will lose all research. So
protect it well, repair it whenever possible, and if you can afford, increase its health by purchasing upgrades. If your
@ -67,14 +67,14 @@ function Public.show(player)
t = t.add {type = 'table', column_count = 4}
local label2 = t.add {type = 'label', caption = 'Outlander' .. '(' .. #game.forces.player.connected_players .. ')'}
local label2 = t.add {type = 'label', caption = 'Outlander' .. ':' .. #game.forces.player.connected_players .. ' '}
label2.style.font_color = {170, 170, 170}
label2.style.font = 'heading-3'
label2.style.minimal_width = 80
for _, town_center in pairs(ffatable.town_centers) do
local force = town_center.market.force
local label3 = t.add {type = 'label', caption = force.name .. '(' .. #force.connected_players .. ')'}
local label3 = t.add {type = 'label', caption = force.name .. ':' .. #force.connected_players .. ' '}
label3.style.font = 'heading-3'
label3.style.minimal_width = 80
label3.style.font_color = town_center.color

View File

@ -1,6 +1,10 @@
local Public = {}
local Table = require 'modules.scrap_towny_ffa.table'
function Public.reset()
local ffatable = Table.get_table()
if ffatable.testing_mode then return end
for index = 1, table.size(game.forces), 1 do
local force = game.forces[index]
if force ~= nil then
@ -9,7 +13,47 @@ function Public.reset()
end
end
--local Event = require 'utils.event'
--Event.add(defines.events.on_chunk_charted, on_chunk_charted)
local function add_force(id, force_name)
local forces = rendering.get_forces(id)
for _, force in ipairs(forces) do
if force.name == force_name or force == force_name then return end
end
forces[#forces + 1] = force_name
rendering.set_forces(id, forces)
end
local function update_forces(id)
local forces = rendering.get_forces(id)
local new_forces = {}
for _, force in ipairs(forces) do
if force ~= nil and force.valid then
new_forces[#new_forces + 1] = force.name
end
end
rendering.set_forces(id, new_forces)
end
local function on_chunk_charted(event)
local surface = game.surfaces[event.surface_index]
local force = event.force
local area = event.area
local markets = surface.find_entities_filtered({area = area, name = 'market'})
for _, market in pairs(markets) do
local force_name = market.force.name
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force_name]
-- town caption
local town_caption = town_center.town_caption
update_forces(town_caption)
add_force(town_caption, force.name)
-- health text
local health_text = town_center.health_text
update_forces(health_text)
add_force(health_text, force.name)
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_chunk_charted, on_chunk_charted)
return Public

View File

@ -0,0 +1,19 @@
local Public = {}
function Public.disable_world_map(player)
player.map_view_settings = {
["show-player-names"] = false,
}
player.show_on_map = false
player.game_view_settings.show_minimap = false
end
function Public.enable_world_map(player)
player.map_view_settings = {
["show-player-names"] = true,
}
player.show_on_map = true
player.game_view_settings.show_minimap = true
end
return Public

View File

@ -9,45 +9,75 @@ local upgrade_functions = {
local market = town_center.market
local surface = market.surface
if town_center.max_health > 500000 then
return
return false
end
town_center.health = town_center.health + town_center.max_health
town_center.max_health = town_center.max_health * 2
Town_center.set_market_health(market, 0)
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Upgrade Backpack
[2] = function(town_center, player)
local market = town_center.market
local force = market.force
local surface = market.surface
if force.character_inventory_slots_bonus > 100 then
return
if force.character_inventory_slots_bonus + 5 > 100 then
return false
end
force.character_inventory_slots_bonus = force.character_inventory_slots_bonus + 5
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Upgrade Mining Productivity
[3] = function(town_center, player)
local market = town_center.market
local force = market.force
local surface = market.surface
if town_center.upgrades.mining_prod >= 10 then
return
if town_center.upgrades.mining_prod + 1 > 10 then
return false
end
town_center.upgrades.mining_prod = town_center.upgrades.mining_prod + 1
force.mining_drill_productivity_bonus = force.mining_drill_productivity_bonus + 0.1
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Upgrade Pickaxe Speed
[4] = function(town_center, player)
local market = town_center.market
local force = market.force
local surface = market.surface
if town_center.upgrades.mining_speed + 1 > 10 then
return false
end
town_center.upgrades.mining_speed = town_center.upgrades.mining_speed + 1
force.manual_mining_speed_modifier = force.manual_mining_speed_modifier + 0.1
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Upgrade Crafting Speed
[5] = function(town_center, player)
local market = town_center.market
local force = market.force
local surface = market.surface
if town_center.upgrades.crafting_speed + 1 > 10 then
return false
end
town_center.upgrades.crafting_speed = town_center.upgrades.crafting_speed + 1
force.manual_crafting_speed_modifier = force.manual_crafting_speed_modifier + 0.1
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Laser Turret Slot
[4] = function(town_center, player)
[6] = function(town_center, player)
local market = town_center.market
local surface = market.surface
town_center.upgrades.laser_turret.slots = town_center.upgrades.laser_turret.slots + 1
surface.play_sound({path = 'utility/new_objective', position = player.position, volume_modifier = 1})
return true
end,
-- Set Spawn Point
[5] = function(town_center, player)
[7] = function(town_center, player)
local ffatable = Table.get_table()
local market = town_center.market
local force = market.force
@ -55,6 +85,7 @@ local upgrade_functions = {
local spawn_point = force.get_spawn_position(surface)
ffatable.spawn_point[player.name] = spawn_point
surface.play_sound({path = 'utility/scenario_message', position = player.position, volume_modifier = 1})
return false
end
}
@ -70,31 +101,39 @@ end
local function set_offers(town_center)
local market = town_center.market
local force = market.force
local market_items = {}
-- special offers
local special_offers = {}
if town_center.max_health < 500000 then
special_offers[1] = {{{'coin', town_center.max_health * 0.1}}, 'Upgrade Town Center Health'}
else
special_offers[1] = {{{'coin', 1}}, 'Maximum Health upgrades reached!'}
special_offers[1] = {{}, 'Maximum Health upgrades reached!'}
end
if force.character_inventory_slots_bonus <= 100 then
if force.character_inventory_slots_bonus + 5 <= 100 then
special_offers[2] = {{{'coin', (force.character_inventory_slots_bonus / 5 + 1) * 50}}, 'Upgrade Backpack +5 Slot'}
else
special_offers[2] = {{{'coin', 1}}, 'Maximum Backpack upgrades reached!'}
special_offers[2] = {{}, 'Maximum Backpack upgrades reached!'}
end
if town_center.upgrades.mining_prod < 10 then
if town_center.upgrades.mining_prod + 1 <= 10 then
special_offers[3] = {{{'coin', (town_center.upgrades.mining_prod + 1) * 400}}, 'Upgrade Mining Productivity +10%'}
else
special_offers[3] = {{{'coin', 1}}, 'Maximum Mining upgrades reached!'}
special_offers[3] = {{}, 'Maximum Productivity upgrades reached!'}
end
if town_center.upgrades.mining_speed + 1 <= 10 then
special_offers[4] = {{{'coin', (town_center.upgrades.mining_speed + 1) * 400}}, 'Upgrade Mining Speed +10%'}
else
special_offers[4] = {{}, 'Maximum Mining Speed upgrades reached!'}
end
if town_center.upgrades.crafting_speed + 1 <= 10 then
special_offers[5] = {{{'coin', (town_center.upgrades.crafting_speed + 1) * 400}}, 'Upgrade Crafting Speed +10%'}
else
special_offers[5] = {{}, 'Maximum Crafting Speed upgrades reached!'}
end
local laser_turret = 'Laser Turret Slot [#' .. tostring(town_center.upgrades.laser_turret.slots + 1) .. ']'
special_offers[4] = {{{'coin', 1000 + (town_center.upgrades.laser_turret.slots * 50)}}, laser_turret}
special_offers[6] = {{{'coin', 1000 + (town_center.upgrades.laser_turret.slots * 50)}}, laser_turret}
local spawn_point = 'Set Spawn Point'
special_offers[5] = {{{'coin', 1}}, spawn_point}
local market_items = {}
special_offers[7] = {{}, spawn_point}
for _, v in pairs(special_offers) do
table_insert(market_items, {price = v[1], offer = {type = 'nothing', effect_description = v[2]}})
end
@ -111,6 +150,7 @@ local function set_offers(town_center)
table_insert(market_items, {price = {{'coin', 600}}, offer = {type = 'give-item', item = 'fast-loader', count = 1}})
table_insert(market_items, {price = {{'coin', 900}}, offer = {type = 'give-item', item = 'express-loader', count = 1}})
-- scrap selling
table_insert(market_items, {price = {{'raw-fish', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'wood', 7}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'iron-ore', 7}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'copper-ore', 7}}, offer = {type = 'give-item', item = 'coin', count = 1}})
@ -129,6 +169,7 @@ end
local function refresh_offers(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local market = event.entity or event.market
if not market then
return
@ -143,8 +184,22 @@ local function refresh_offers(event)
if not town_center then
return
end
clear_offers(market)
set_offers(town_center)
if player.force == market.force then
clear_offers(market)
set_offers(town_center)
else
if player.opened ~= nil then
player.opened = nil
player.surface.create_entity(
{
name = 'flying-text',
position = {market.position.x - 1.75, market.position.y},
text = 'Sorry, we are closed.',
color = {r = 1, g = 0.68, b = 0.26}
}
)
end
end
end
local function offer_purchased(event)
@ -156,21 +211,30 @@ local function offer_purchased(event)
if not upgrade_functions[offer_index] then
return
end
local town_center = ffatable.town_centers[market.force.name]
if not town_center then
return
end
upgrade_functions[offer_index](town_center, player)
if count > 1 then
if upgrade_functions[offer_index](town_center, player) then
-- reimburse extra purchased
if count > 1 then
local offers = market.get_market_items()
if offers[offer_index].price ~= nil then
local price = offers[offer_index].price[1].amount
player.insert({name = 'coin', count = price * (count - 1)})
end
end
else
-- reimburse purchase
local offers = market.get_market_items()
local price = offers[offer_index].price[1].amount
player.insert({name = 'coin', count = price * (count - 1)})
if offers[offer_index].price ~= nil then
local price = offers[offer_index].price[1].amount
player.insert({name = 'coin', count = price * (count)})
end
end
end
-- called for all gui events
local function on_gui_opened(event)
local gui_type = event.gui_type
if gui_type ~= defines.gui_type.entity then
@ -180,25 +244,53 @@ local function on_gui_opened(event)
if entity == nil or not entity.valid then
return
end
if entity.type == 'market' then
if entity.name == 'market' then
refresh_offers(event)
end
end
-- called for all market events
local function on_market_item_purchased(event)
offer_purchased(event)
refresh_offers(event)
local market = event.market
if market.name == 'market' then
offer_purchased(event)
refresh_offers(event)
end
end
local function inside(pos, area)
return pos.x >= area.left_top.x and pos.x <= area.right_bottom.x and pos.y >= area.left_top.y and pos.y <= area.right_bottom.y
end
local function on_tick(_)
local ffatable = Table.get_table()
if not ffatable.town_centers then
return
local function equal(pos1, pos2)
return pos1.x == pos2.x and pos1.y == pos2.y
end
local function is_loader(entity)
return entity.name == 'loader' or entity.name == 'fast-loader' or entity.name == 'express-loader'
end
local function is_filtered_inserter(entity)
return entity.name == 'filter-inserter' or entity.name == "stack-filter-inserter"
end
local function max_stack_size(entity)
if is_loader(entity) then return 1 end
if (entity.name == "stack-inserter" or entity.name == "stack-filter-inserter") then
local override = entity.inserter_stack_size_override
if override > 0 then return override end
local capacity = entity.force.stack_inserter_capacity_bonus
return 1 + capacity
else
local override = entity.inserter_stack_size_override
if override > 0 then return override end
local bonus = entity.force.inserter_stack_size_bonus
return 1 + bonus
end
end
local function get_connected_entities(market)
if not market.valid then return {} end
local items = {
'burner-inserter',
'inserter',
@ -211,117 +303,211 @@ local function on_tick(_)
'fast-loader',
'express-loader'
}
for _, town_center in pairs(ffatable.town_centers) do
local market = town_center.market
local items2 = {
'long-handed-inserter',
}
local bb = market.bounding_box
local s = market.surface
local area = {left_top = {bb.left_top.x - 1, bb.left_top.y - 1}, right_bottom = {bb.right_bottom.x + 1, bb.right_bottom.y + 1}}
local entities = s.find_entities_filtered({area = area, name = items})
local area2 = {left_top = {bb.left_top.x - 2, bb.left_top.y - 2}, right_bottom = {bb.right_bottom.x + 2, bb.right_bottom.y + 2}}
local entities2 = s.find_entities_filtered({area = area2, name = items2})
for k,v in pairs(entities2) do
entities[k] = v
end
return entities
end
local function get_inserter_filter(entity)
-- return the first filter
local filter_mode = entity.inserter_filter_mode
if filter_mode == 'whitelist' then
return entity.get_filter(1)
end
return nil
end
local function get_loader_filter(entity, index)
-- return first two filter types
return entity.get_filter(index)
end
local function get_loader_market_position(entity)
-- gets the position of the market relative to the loader
local position = {x=entity.position.x, y=entity.position.y}
local orientation = entity.orientation
local type = entity.loader_type
if (orientation == 0.0 and type == "input") or (orientation == 0.5 and type == "output") then
position.y = position.y - 1.5
end
if (orientation == 0.25 and type == "input") or (orientation == 0.75 and type == "output") then
position.x = position.x + 1.5
end
if (orientation == 0.5 and type == "input") or (orientation == 0.0 and type == "output") then
position.y = position.y + 1.5
end
if (orientation == 0.75 and type == "input") or (orientation == 0.25 and type == "output") then
position.x = position.x - 1.5
end
return position
end
local function output_loader_items(town_center, trade, entity, index)
local item = trade.offer.item
local line = entity.get_transport_line(index)
if line.can_insert_at_back() and town_center.output_buffer[item] > 0 then
local stack = {name = item, count = 1}
town_center.output_buffer[item] = town_center.output_buffer[item] - 1
line.insert_at_back(stack)
end
end
local function output_inserter_items(town_center, trade, entity)
local item = trade.offer.item
local stack_size = max_stack_size(entity)
local count = 0
while town_center.output_buffer[item] > 0 and count < stack_size do
town_center.output_buffer[item] = town_center.output_buffer[item] - 1
count = count + 1
end
if count > 0 then
local stack = {name = item, count = count}
entity.held_stack.set_stack(stack)
end
end
local function trade_scrap_for_coin(town_center, market, trade, stack)
local item = stack.name
local amount = stack.count
-- buffer the input in an item buffer that can be sold for coin
if town_center.input_buffer[item] == nil then
town_center.input_buffer[item] = 0
end
town_center.input_buffer[item] = town_center.input_buffer[item] + amount
--log("input_buffer[" .. item .. "] = " .. town_center.input_buffer[item])
local price = trade.price[1].amount
local count = trade.offer.count
while town_center.input_buffer[item] >= price do
town_center.input_buffer[item] = town_center.input_buffer[item] - price
town_center.coin_balance = town_center.coin_balance + count
end
Town_center.update_coin_balance(market.force)
--log("input_buffer[" .. item .. "] = " .. town_center.input_buffer[item])
end
local function trade_coin_for_items(town_center, market, trade)
local item = trade.offer.item
local count = trade.offer.count
local price = trade.price[1].amount
if town_center.output_buffer[item] == nil then
town_center.output_buffer[item] = 0
end
while town_center.coin_balance - price >= 0 do
if town_center.output_buffer[item] == 0 then
town_center.coin_balance = town_center.coin_balance - price
town_center.output_buffer[item] = town_center.output_buffer[item] + count
else
break
end
end
Town_center.update_coin_balance(market.force)
end
local function handle_loader_output(town_center, market, entity, index)
local line = entity.get_transport_line(index)
-- get loader filters
local filter = get_loader_filter(entity, index)
if filter == nil then return end
if filter == 'coin' then
-- output for coins
while town_center.coin_balance > 0 and line.can_insert_at_back() do
town_center.coin_balance = town_center.coin_balance - 1
local stack = {name = 'coin', count = 1}
line.insert_at_back(stack)
end
Town_center.update_coin_balance(market.force)
else
-- output for matching purchases
local offers = market.get_market_items()
if offers == nil then
set_offers(town_center)
end
local s = market.surface
local force = market.force
-- get the bounding box for the market
local bb = market.bounding_box
local area = {left_top = {bb.left_top.x - 2, bb.left_top.y - 2}, right_bottom = {bb.right_bottom.x + 2, bb.right_bottom.y + 2}}
local entities = s.find_entities_filtered({area = area, name = items})
for _, e in pairs(entities) do
if e.name ~= 'loader' and e.name ~= 'fast-loader' and e.name ~= 'express-loader' then
local ppos = e.pickup_position
local dpos = e.drop_position
-- pulling an item from the market
if inside(ppos, bb) and e.drop_target then
local stack = e.held_stack
local spos = e.held_stack_position
if inside(spos, bb) then
local filter
local filter_mode = e.inserter_filter_mode
if filter_mode ~= nil then
for i = 1, e.filter_slot_count do
if e.get_filter(i) ~= nil then
filter = e.get_filter(i)
break
end
end
end
if (filter_mode == 'whitelist' and filter == 'coin') or (filter_mode == 'blacklist' and filter == nil) or (filter_mode == nil) then
if stack.valid and town_center.coin_balance > 0 then
-- pull coins
stack.set_stack({name = 'coin', count = 1})
town_center.coin_balance = town_center.coin_balance - 1
Town_center.update_coin_balance(force)
end
else
if filter_mode == 'whitelist' and filter ~= nil and stack.valid then
-- purchased and pull items if output buffer is empty
-- buffer the output in a item buffer since the stack might be too small
-- output items are shared among the output
for _, trade in ipairs(offers) do
local type = trade.offer.type
local item = trade.offer.item
local count = trade.offer.count or 1
local cost = trade.price[1].amount
if type == 'give-item' and item == filter then
if town_center.output_buffer[item] == nil then
town_center.output_buffer[item] = 0
end
if town_center.output_buffer[item] == 0 then
-- fill buffer
if town_center.coin_balance >= cost then
town_center.coin_balance = town_center.coin_balance - cost
Town_center.update_coin_balance(force)
town_center.output_buffer[item] = town_center.output_buffer[item] + count
--log("output_buffer[" .. item .. "] = " .. town_center.output_buffer[item])
end
end
if town_center.output_buffer[item] > 0 and not stack.valid_for_read then
-- output the item
local amount = 1
if stack.can_set_stack({name = item, count = amount}) then
town_center.output_buffer[item] = town_center.output_buffer[item] - amount
stack.set_stack({name = item, count = amount})
--log("output_buffer[" .. item .. "] = " .. town_center.output_buffer[item])
end
end
break
end
end
end
end
if offers ~= nil then
for _, trade in ipairs(offers) do
if trade.offer.type == 'give-item' then
local item = trade.price[1].name
if item == 'coin' and trade.offer.item == filter then
trade_coin_for_items(town_center, market, trade)
output_loader_items(town_center, trade, entity, index)
end
end
-- pushing an item to the market (coins or scrap)
if e.pickup_target and inside(dpos, bb) then
local stack = e.held_stack
local spos = e.held_stack_position
if stack.valid_for_read and inside(spos, bb) then
local name = stack.name
local amount = stack.count
if name == 'coin' then
-- push coins
e.remove_item(stack)
town_center.coin_balance = town_center.coin_balance + amount
Town_center.update_coin_balance(force)
else
-- push items to turn into coin
for _, trade in ipairs(offers) do
local type = trade.offer.type
local item = trade.price[1].name
local count = trade.price[1].amount
local cost = trade.offer.count
if type == 'give-item' and name == item and item ~= 'coin' then
e.remove_item(stack)
-- buffer the input in an item buffer that can be sold
if town_center.input_buffer[item] == nil then
town_center.input_buffer[item] = 0
end
town_center.input_buffer[item] = town_center.input_buffer[item] + amount
--log("input_buffer[" .. item .. "] = " .. town_center.input_buffer[item])
if town_center.input_buffer[item] >= count then
town_center.input_buffer[item] = town_center.input_buffer[item] - count
town_center.coin_balance = town_center.coin_balance + cost
Town_center.update_coin_balance(force)
--log("input_buffer[" .. item .. "] = " .. town_center.input_buffer[item])
end
end
end
end
end
end
local function handle_inserter_output(town_center, market, entity)
-- get inserter filter
local filter = get_inserter_filter(entity)
if filter == nil then return end
local amount = max_stack_size(entity)
local stack = {name = 'coin', count = amount}
if filter == 'coin' then
-- output coins
if amount > town_center.coin_balance then amount = town_center.coin_balance end
stack.count = amount
if town_center.coin_balance > 0 then
town_center.coin_balance = town_center.coin_balance - amount
entity.held_stack.set_stack(stack)
end
Town_center.update_coin_balance(market.force)
else
-- for matching coin purchases
local offers = market.get_market_items()
if offers == nil then
set_offers(town_center)
end
if offers ~= nil then
for _, trade in ipairs(offers) do
if trade.offer.type == 'give-item' and trade.offer.item == filter then
local item = trade.price[1].name
if item == 'coin' then
trade_coin_for_items(town_center, market, trade)
output_inserter_items(town_center, trade, entity)
end
end
end
end
end
end
local function handle_loader_input(town_center, market, entity, index)
local line = entity.get_transport_line(index)
-- check for a line item at the back where we can pull
if line.valid then
local length = #line
if length > 1 or (length == 1 and line.can_insert_at_back()) then
local line_item = line[length].name
local stack = {name = line_item, count = 1}
if line_item == 'coin' then
-- insert coins
line.remove_item(stack)
town_center.coin_balance = town_center.coin_balance + stack.count
Town_center.update_coin_balance(market.force)
else
local offers = market.get_market_items()
if offers == nil then
set_offers(town_center)
end
if offers ~= nil then
for _, trade in ipairs(offers) do
if trade.offer.type == 'give-item' then
local item = trade.price[1].name
if item == stack.name and trade.offer.item == 'coin' then
-- trade scrap for coin
line.remove_item(stack)
trade_scrap_for_coin(town_center, market, trade, stack)
end
end
end
@ -331,6 +517,142 @@ local function on_tick(_)
end
end
local function handle_inserter_input(town_center, market, entity)
-- check if stack is coin or resource
local stack = {name = entity.held_stack.name, count = entity.held_stack.count}
if stack.name == 'coin' and stack.count > 0 then
-- insert coins
entity.remove_item(stack)
town_center.coin_balance = town_center.coin_balance + stack.count
Town_center.update_coin_balance(market.force)
else
local offers = market.get_market_items()
if offers == nil then
set_offers(town_center)
end
if offers ~= nil then
for _, trade in ipairs(offers) do
if trade.offer.type == 'give-item' and trade.offer.item == 'coin' then
local item = trade.price[1].name
if item == stack.name and trade.offer.item == 'coin' then
-- trade scrap for coin
entity.remove_item(stack)
trade_scrap_for_coin(town_center, market, trade, stack)
end
end
end
end
end
end
local function handle_market_input(town_center, market, entity)
if is_loader(entity) then
-- handle loader input
-- we don't care about filters
local max_index = entity.get_max_transport_line_index()
for index = 1, max_index, 1 do
handle_loader_input(town_center, market, entity, index)
end
else
-- handle inserter input
-- we don't care about filters
local stack = entity.held_stack
if stack ~= nil then
-- if there is a pickup target
local spos = entity.held_stack_position
local dpos = entity.drop_position
if equal(spos, dpos) then
if stack.valid_for_read and stack.count > 0 then
-- if there is a stack
-- insert an item into the market
handle_inserter_input(town_center, market, entity)
end
end
end
end
end
local function handle_market_output(town_center, market, entity)
if is_loader(entity) then
-- handle loader output
local max_index = entity.get_max_transport_line_index()
for index = 1, max_index, 1 do
if get_loader_filter(entity, index) ~= nil then
handle_loader_output(town_center, market, entity, index)
end
end
else
if is_filtered_inserter(entity) then
-- handle inserter output
if entity.drop_target ~= nil then
-- if the pickup position is inside the market
--log("inside pickup position and there is a drop target")
local stack = entity.held_stack
local spos = entity.held_stack_position
local ppos = entity.pickup_position
if equal(spos, ppos) then
-- if the stack position is inside the market
if stack == nil or stack.count == 0 then
-- if there is space on the stack
-- pull an item from the market
handle_inserter_output(town_center, market, entity, stack)
end
end
end
end
end
end
local function get_entity_mode(market, entity)
local bb = market.bounding_box
if is_loader(entity) then
local mpos = get_loader_market_position(entity)
if inside(mpos, bb) then
return entity.loader_type
else
return 'none'
end
else
local dpos = entity.drop_position
local ppos = entity.pickup_position
if inside(dpos, bb) then
return 'input'
end
if inside(ppos, bb) then
return 'output'
end
return "none"
end
end
local function handle_connected_entity(town_center, market, entity)
local mode = get_entity_mode(market, entity)
if mode == "input" then
handle_market_input(town_center, market, entity)
end
if mode == "output" then
handle_market_output(town_center, market, entity)
end
end
local function on_tick(_)
local ffatable = Table.get_table()
if not ffatable.town_centers then
return
end
for _, town_center in pairs(ffatable.town_centers) do
-- get connected entities on markets
local market = town_center.market
local entities = get_connected_entities(market)
-- handle connected entity
for _, entity in pairs(entities) do
if entity.force == market.force then
handle_connected_entity(town_center, market, entity)
end
end
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_tick, on_tick)
Event.add(defines.events.on_gui_opened, on_gui_opened)

View File

@ -1,5 +1,6 @@
local Public = {}
local math_random = math.random
--local Server = require 'utils.server'
local function create_limbo()
game.create_surface('limbo')
@ -17,14 +18,14 @@ local function initialize_nauvis()
['copper-ore'] = {frequency = 'none', size = 1, richness = 'normal'},
['iron-ore'] = {frequency = 'none', size = 1, richness = 'normal'},
['uranium-ore'] = {frequency = 'none', size = 1, richness = 'normal'},
['crude-oil'] = {frequency = 'none', size = 1, richness = 'normal'},
['crude-oil'] = {frequency = 'very-low', size = 'very-small', richness = 'normal'},
trees = {frequency = 2, size = 'normal', richness = 'normal'},
['enemy-base'] = {frequency = 8, size = 1, richness = 'normal'}
['enemy-base'] = {frequency = 'very-high', size = 2, richness = 'normal'}
}
mgs.autoplace_settings = {
entity = {
settings = {
['rock-huge'] = {frequency = 3, size = 12, richness = 'very-high'},
['rock-huge'] = {frequency = 2, size = 12, richness = 'very-high'},
['rock-big'] = {frequency = 3, size = 12, richness = 'very-high'},
['sand-rock-big'] = {frequency = 3, size = 12, richness = 1, 'very-high'}
}
@ -53,8 +54,9 @@ local function initialize_nauvis()
mgs.peaceful_mode = false
mgs.starting_area = 'none'
mgs.terrain_segmentation = 8
mgs.width = 2048
mgs.height = 2048
-- terrain size is 64 x 64 chunks, water size is 80 x 80
mgs.width = 2560
mgs.height = 2560
--mgs.starting_points = {
-- {x = 0, y = 0}
--}
@ -67,7 +69,7 @@ local function initialize_nauvis()
--moisture = 0,
-- here we are overriding the aux noise-layer with a fixed value to keep aux consistent across the map
-- it allows to free up the aux noise expression
-- it allows to free up the aux noise expression
-- aux should be not sand, nor red sand
--aux = 0.5,
@ -111,11 +113,11 @@ local function initialize_nauvis()
-- a constant intensity means base distribution will be consistent with regard to distance
['enemy-base-intensity'] = 1,
-- adjust this value to set how many nests spawn per tile
['enemy-base-frequency'] = 0.2,
['enemy-base-frequency'] = 0.4,
-- this will make and average base radius around 12 tiles
['enemy-base-radius'] = 12
}
mgs.seed = math_random(10000, 99999)
mgs.seed = game.surfaces[1].map_gen_settings.seed
surface.map_gen_settings = mgs
surface.peaceful_mode = false
surface.always_day = false
@ -123,6 +125,20 @@ local function initialize_nauvis()
surface.clear(true)
surface.regenerate_entity({'rock-huge', 'rock-big', 'sand-rock-big'})
surface.regenerate_decorative()
-- this will force generate the entire map
--Server.to_discord_embed('ScrapTownyFFA Map Regeneration in Progress')
--surface.request_to_generate_chunks({x=0,y=0},64)
--surface.force_generate_chunk_requests()
--Server.to_discord_embed('Regeneration Complete')
end
local function initialize_limbo()
local surface = game.surfaces['limbo']
surface.generate_with_lab_tiles = true
surface.peaceful_mode = true
surface.always_day = true
surface.freeze_daytime = true
surface.clear(true)
end
function Public.initialize()
@ -167,8 +183,8 @@ function Public.initialize()
game.map_settings.enemy_expansion.max_expansion_cooldown = 3600 -- maximum time before next expansion
-- unit group settings
game.map_settings.unit_group.min_group_gathering_time = 600
game.map_settings.unit_group.max_group_gathering_time = 3600
game.map_settings.unit_group.min_group_gathering_time = 400
game.map_settings.unit_group.max_group_gathering_time = 2400
game.map_settings.unit_group.max_wait_time_for_late_members = 3600
game.map_settings.unit_group.max_group_radius = 30.0
game.map_settings.unit_group.min_group_radius = 5.0
@ -192,6 +208,7 @@ function Public.initialize()
--game.map_settings.steering.moving.force_unit_fuzzy_goto_behavior = false
create_limbo()
initialize_limbo()
initialize_nauvis()
end

View File

@ -47,15 +47,21 @@ local pollution_index = {
function Public.market_scent()
local ffatable = Table.get_table()
if ffatable.testing_mode then
return
end
local town_centers = ffatable.town_centers
if town_centers == nil then
return
end
for _, town_center in pairs(town_centers) do
local market = town_center.market
local pollution = pollution_index['market']
local amount = math_random(pollution.min, pollution.max)
market.surface.pollute(market.position, amount)
if market ~= nil and market.valid then
local pollution = pollution_index['market']
local amount = math_random(pollution.min, pollution.max)
local evolution = town_center.evolution.biters
market.surface.pollute(market.position, amount + evolution * 500)
end
end
end

View File

@ -4,7 +4,6 @@ local table_insert = table.insert
local table_shuffle = table.shuffle_table
local Table = require 'modules.scrap_towny_ffa.table'
local Evolution = require 'modules.scrap_towny_ffa.evolution'
local valid_entities = {
['rock-big'] = true,
@ -13,21 +12,21 @@ local valid_entities = {
}
local size_raffle = {
{'giant', 128, 256},
{'huge', 64, 128},
{'big', 32, 64},
{'small', 16, 32},
{'tiny', 8, 16}
{'giant', 1024, 2048},
{'huge', 512, 1024},
{'big', 256, 510},
{'small', 126, 256},
{'tiny', 64, 128}
}
local function get_chances()
local chances = {}
table_insert(chances, {'iron-ore', 25})
table_insert(chances, {'iron-ore', 24})
table_insert(chances, {'copper-ore', 18})
table_insert(chances, {'mixed', 15})
table_insert(chances, {'mixed', 12})
table_insert(chances, {'coal', 14})
table_insert(chances, {'stone', 8})
table_insert(chances, {'uranium-ore', 3})
table_insert(chances, {'stone', 12})
table_insert(chances, {'uranium-ore', 8})
return chances
end
@ -42,42 +41,52 @@ local function set_raffle()
ffatable.rocks_yield_ore_veins.mixed_ores = {'iron-ore', 'copper-ore', 'stone', 'coal'}
end
local function get_amount(position)
local base = 256
local relative_evolution = Evolution.get_evolution(position)
local tier = 4 + math_floor(relative_evolution * 16)
return (math_random(1, base) + math_random(1, 2 ^ tier))
local function get_amount()
local base = 256 + 2 ^ 8
local max = 2 ^ 12
return math_random(math_random(256, base), math_random(base, max))
end
local function draw_chain(surface, count, ore, ore_entities, ore_positions)
local ffatable = Table.get_table()
local vectors = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}}
local vectors = {{0, -0.75}, {-0.75, 0}, {0.75, 0}, {0, 0.75}}
local r = math_random(1, #ore_entities)
local position = {x = ore_entities[r].position.x, y = ore_entities[r].position.y}
local position = {x = ore_entities[r].ore.position.x, y = ore_entities[r].ore.position.y}
for _ = 1, count, 1 do
table_shuffle(vectors)
for i = 1, 4, 1 do
local p = {x = position.x + vectors[i][1], y = position.y + vectors[i][2]}
-- dispersion will make patches more round
local dx = (math_random(0, 100) - 50) / 100
local dy = (math_random(0, 100) - 50) / 100
local dp = {x = p.x + dx, y = p.y + dy}
local name = ore
if ore == 'mixed' then
name = ffatable.rocks_yield_ore_veins.mixed_ores[math_random(1, #ffatable.rocks_yield_ore_veins.mixed_ores)]
end
if surface.can_place_entity({name = name, position = p, amount = 1}) then
if not ore_positions[p.x .. '_' .. p.y] then
position.x = p.x
position.y = p.y
ore_positions[p.x .. '_' .. p.y] = true
ore_entities[#ore_entities + 1] = {name = name, position = p, amount = get_amount(p)}
break
if surface.can_place_entity({name = name, position = p, force = 'neutral'}) then
if math_random(1, 2) == 1 then
if not ore_positions[p.x .. '_' .. p.y] then
position.x = p.x
position.y = p.y
ore_positions[p.x .. '_' .. p.y] = true
ore_entities[#ore_entities + 1] = {ore = {name = name, position = dp}, amount = get_amount()}
break
end
end
else
if surface.can_fast_replace({name = name, position = p}) then
if math_random(1, 2) == 1 then
-- existing ore of same name
if surface.can_fast_replace({name = name, position = p, force = 'neutral'}) then
local amount = get_amount()
local deposit = surface.find_entity(name, p)
if deposit ~= nil then
amount = amount + deposit
if not ore_positions[p.x .. '_' .. p.y] then
position.x = p.x
position.y = p.y
ore_positions[p.x .. '_' .. p.y] = true
ore_entities[#ore_entities + 1] = {name = name, position = p, amount = get_amount(p), fast_replace = true}
ore_entities[#ore_entities + 1] = {ore = {name = name, position = dp}, amount = amount, fast_replace = true}
break
end
end
@ -129,13 +138,15 @@ local function ore_vein(event)
end
local position = event.entity.position
local ore_entities = {{name = ore, position = {x = position.x, y = position.y}, amount = get_amount(position)}}
local ore_entities = {{ore = {name = ore, position = {x = position.x, y = position.y}}, amount = get_amount()}}
if ore == 'mixed' then
ore_entities = {
{
name = ffatable.rocks_yield_ore_veins.mixed_ores[math_random(1, #ffatable.rocks_yield_ore_veins.mixed_ores)],
position = {x = position.x, y = position.y},
amount = get_amount(position)
ore = {
name = ffatable.rocks_yield_ore_veins.mixed_ores[math_random(1, #ffatable.rocks_yield_ore_veins.mixed_ores)],
position = {x = position.x, y = position.y}
},
amount = get_amount()
}
}
end
@ -148,32 +159,43 @@ local function ore_vein(event)
if count < c then
c = count
end
local placed_ore_count = #ore_entities
draw_chain(surface, c, ore, ore_entities, ore_positions)
count = count - (#ore_entities - placed_ore_count)
if count <= 0 then
break
end
end
for _, e in pairs(ore_entities) do
surface.create_entity(e)
-- place the ore
for _, ore_entity in pairs(ore_entities) do
if ore_entity.fast_replace then
local e = surface.find_entity(ore_entity.ore.name, ore_entity.ore.position)
e.amount = ore_entity.amount
else
local e = surface.create_entity(ore_entity.ore)
e.amount = ore_entity.amount
end
end
end
local function on_player_mined_entity(event)
local ffatable = Table.get_table()
local rocks_yield_ore_veins = Table.get('rocks_yield_ore_veins')
if not rocks_yield_ore_veins then
return
end
local player = game.players[event.player_index]
if player.force.technologies['steel-processing'].researched == false then
return
end
if not event.entity.valid then
return
end
if not valid_entities[event.entity.name] then
return
end
if math_random(1, ffatable.rocks_yield_ore_veins.chance) ~= 1 then
if math_random(1, rocks_yield_ore_veins.chance) ~= 1 then
return
end
ore_vein(event)
@ -184,7 +206,7 @@ local function on_init()
ffatable.rocks_yield_ore_veins = {}
ffatable.rocks_yield_ore_veins.raffle = {}
ffatable.rocks_yield_ore_veins.mixed_ores = {}
ffatable.rocks_yield_ore_veins.chance = 4
ffatable.rocks_yield_ore_veins.chance = 10
set_raffle()
end

View File

@ -1,5 +1,3 @@
local table_size = table.size
local Table = require 'modules.scrap_towny_ffa.table'
-- called whenever a player places an item
@ -16,7 +14,7 @@ local function on_built_entity(event)
local force = player.force
local town_center = ffatable.town_centers[force.name]
local surface = entity.surface
if force == game.forces['player'] or force == game.forces['rogue'] or town_center == nil then
if force.index == game.forces['player'].index or force.index == game.forces['rogue'].index or town_center == nil then
surface.create_entity(
{
name = 'flying-text',
@ -31,7 +29,8 @@ local function on_built_entity(event)
end
local slots = town_center.upgrades.laser_turret.slots
local locations = town_center.upgrades.laser_turret.locations
if table_size(locations) >= slots then
if locations >= slots then
surface.create_entity(
{
name = 'flying-text',
@ -44,12 +43,24 @@ local function on_built_entity(event)
entity.destroy()
return
end
local position = entity.position
local key = tostring('{' .. position.x .. ',' .. position.y .. '}')
locations[key] = true
local key = script.register_on_entity_destroyed(entity)
if (ffatable.laser_turrets == nil) then
ffatable.laser_turrets = {}
end
ffatable.laser_turrets[key] = force.index
locations = locations + 1
town_center.upgrades.laser_turret.locations = locations
surface.create_entity(
{
name = 'flying-text',
position = entity.position,
text = 'Using ' .. locations .. '/' .. slots .. ' slots',
color = {r = 1.0, g = 1.0, b = 1.0}
}
)
end
-- called whenever a player places an item
-- called whenever a robot places an item
local function on_robot_built_entity(event)
local ffatable = Table.get_table()
local entity = event.created_entity
@ -63,7 +74,7 @@ local function on_robot_built_entity(event)
local force = robot.force
local town_center = ffatable.town_centers[force.name]
local surface = entity.surface
if force == game.forces['player'] or force == game.forces['rogue'] or town_center == nil then
if force.index == game.forces['player'].index or force.index == game.forces['rogue'].index or town_center == nil then
surface.create_entity(
{
name = 'flying-text',
@ -78,7 +89,7 @@ local function on_robot_built_entity(event)
end
local slots = town_center.upgrades.laser_turret.slots
local locations = town_center.upgrades.laser_turret.locations
if table_size(locations) >= slots then
if locations >= slots then
surface.create_entity(
{
name = 'flying-text',
@ -91,31 +102,51 @@ local function on_robot_built_entity(event)
entity.destroy()
return
end
local position = entity.position
local key = tostring('{' .. position.x .. ',' .. position.y .. '}')
locations[key] = true
local key = script.register_on_entity_destroyed(entity)
if (ffatable.laser_turrets == nil) then
ffatable.laser_turrets = {}
end
ffatable.laser_turrets[key] = force.index
locations = locations + 1
town_center.upgrades.laser_turret.locations = locations
surface.create_entity(
{
name = 'flying-text',
position = entity.position,
text = 'Using ' .. locations .. '/' .. slots .. ' slots',
color = {r = 1.0, g = 1.0, b = 1.0}
}
)
end
-- called whenever a player mines an entity but before it is removed from the map
-- will have the contents of the drops
local function on_player_mined_entity(event)
-- called whenever a laser-turret is removed from the map
local function on_entity_destroyed(event)
local key = event.registration_number
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local force = player.force
local entity = event.entity
if entity.name == 'laser-turret' then
local town_center = ffatable.town_centers[force.name]
if force == game.forces['player'] or force == game.forces['rogue'] or town_center == nil then
return
if (ffatable.laser_turrets == nil) then
return
end
if (ffatable.laser_turrets[key] ~= nil) then
local index = ffatable.laser_turrets[key]
local force = game.forces[index]
if force ~= nil then
local town_center = ffatable.town_centers[force.name]
if town_center ~= nil then
if force.index == game.forces['player'].index or force.index == game.forces['rogue'].index or town_center == nil then
return
end
local locations = town_center.upgrades.laser_turret.locations
locations = locations - 1
if (locations < 0) then
locations = 0
end
town_center.upgrades.laser_turret.locations = locations
end
end
local locations = town_center.upgrades.laser_turret.locations
local position = entity.position
local key = tostring('{' .. position.x .. ',' .. position.y .. '}')
locations[key] = nil
end
end
local Event = require 'utils.event'
Event.add(defines.events.on_built_entity, on_built_entity)
Event.add(defines.events.on_robot_built_entity, on_robot_built_entity)
Event.add(defines.events.on_player_mined_entity, on_player_mined_entity)
Event.add(defines.events.on_entity_destroyed, on_entity_destroyed)

View File

@ -0,0 +1,268 @@
local table_insert = table.insert
local Table = require 'modules.scrap_towny_ffa.table'
local upgrade_functions = {
-- Upgrade Backpack
[1] = function(player)
local ffatable = Table.get_table()
local surface = player.surface
if player.character.character_inventory_slots_bonus + 5 > 100 then
return false
end
player.character.character_inventory_slots_bonus = player.character.character_inventory_slots_bonus + 5
if not ffatable.buffs[player.index] then
ffatable.buffs[player.index] = {}
end
if not ffatable.buffs[player.index].character_inventory_slots_bonus then
ffatable.buffs[player.index].character_inventory_slots_bonus = 0
end
ffatable.buffs[player.index].character_inventory_slots_bonus = player.character.character_inventory_slots_bonus
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Upgrade Pickaxe Speed
[2] = function(player)
local ffatable = Table.get_table()
local surface = player.surface
if player.character.character_mining_speed_modifier + 0.1 > 1 then
return false
end
player.character.character_mining_speed_modifier = player.character.character_mining_speed_modifier + 0.1
if not ffatable.buffs[player.index] then
ffatable.buffs[player.index] = {}
end
if not ffatable.buffs[player.index].character_mining_speed_modifier then
ffatable.buffs[player.index].character_mining_speed_modifier = 0
end
ffatable.buffs[player.index].character_mining_speed_modifier = player.character.character_mining_speed_modifier
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Upgrade Crafting Speed
[3] = function(player)
local ffatable = Table.get_table()
local surface = player.surface
if player.character.character_crafting_speed_modifier + 0.1 > 1 then
return false
end
player.character.character_crafting_speed_modifier = player.character.character_crafting_speed_modifier + 0.1
if not ffatable.buffs[player.index] then
ffatable.buffs[player.index] = {}
end
if not ffatable.buffs[player.index].character_crafting_speed_modifier then
ffatable.buffs[player.index].character_crafting_speed_modifier = 0
end
ffatable.buffs[player.index].character_crafting_speed_modifier = player.character.character_crafting_speed_modifier
surface.play_sound({path = 'utility/achievement_unlocked', position = player.position, volume_modifier = 1})
return true
end,
-- Set Spawn Point
[4] = function(player)
local ffatable = Table.get_table()
local surface = player.surface
local position = player.position
position = surface.find_non_colliding_position('character', position, 0, 0.25)
if position ~= nil and player ~= nil then
ffatable.spawn_point[player.name] = {x = position.x, y = position.y}
surface.play_sound({path = 'utility/scenario_message', position = player.position, volume_modifier = 1})
else
surface.create_entity(
{
name = 'flying-text',
position = position,
text = 'Could not find open space for spawnpoint!',
color = {r = 0.77, g = 0.0, b = 0.0}
}
)
end
return false
end
}
local function clear_offers(market)
for _ = 1, 256, 1 do
local a = market.remove_market_item(1)
if a == false then
return
end
end
end
local function set_offers(market, player)
local market_items = {}
-- special offers are only for outlanders and rogues
local special_offers = {}
local force = player.force
if force.index == game.forces['player'].index or force.index == game.forces['rogue'].index then
if player.character.character_inventory_slots_bonus + 5 <= 100 then
special_offers[1] = {{{'coin', (player.character.character_inventory_slots_bonus / 5 + 1) * 50}}, 'Upgrade Backpack +5 Slot'}
else
special_offers[1] = {{}, 'Maximum Backpack upgrades reached!'}
end
if player.character.character_mining_speed_modifier + 0.1 <= 1 then
special_offers[2] = {{{'coin', (player.character.character_mining_speed_modifier * 10 + 1) * 400}}, 'Upgrade Mining Speed +10%'}
else
special_offers[2] = {{}, 'Maximum Mining Speed upgrades reached!'}
end
if player.character.character_crafting_speed_modifier + 0.1 <= 1 then
special_offers[3] = {{{'coin', (player.character.character_crafting_speed_modifier * 10 + 1) * 400}}, 'Upgrade Crafting Speed +10%'}
else
special_offers[3] = {{}, 'Maximum Crafting Speed upgrades reached!'}
end
local spawn_point = 'Set Spawn Point'
special_offers[4] = {{}, spawn_point}
else
local spawn_point = 'Set Spawn Point'
special_offers[1] = {{}, spawn_point}
end
for _, v in pairs(special_offers) do
table_insert(market_items, {price = v[1], offer = {type = 'nothing', effect_description = v[2]}})
end
-- coin purchases
table_insert(market_items, {price = {{'coin', 1}}, offer = {type = 'give-item', item = 'raw-fish', count = 1}})
table_insert(market_items, {price = {{'coin', 4}}, offer = {type = 'give-item', item = 'firearm-magazine', count = 5}})
table_insert(market_items, {price = {{'coin', 10}}, offer = {type = 'give-item', item = 'grenade', count = 6}})
table_insert(market_items, {price = {{'coin', 40}}, offer = {type = 'give-item', item = 'piercing-rounds-magazine', count = 10}})
table_insert(market_items, {price = {{'coin', 75}}, offer = {type = 'give-item', item = 'heavy-armor', count = 1}})
table_insert(market_items, {price = {{'coin', 150}}, offer = {type = 'give-item', item = 'modular-armor', count = 1}})
-- scrap selling
table_insert(market_items, {price = {{'raw-fish', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'wood', 7}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'copper-cable', 12}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'copper-plate', 5}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'iron-stick', 12}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'iron-gear-wheel', 3}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'iron-plate', 5}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'steel-plate', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'empty-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'crude-oil-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'heavy-oil-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'light-oil-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'lubricant-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'petroleum-gas-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'sulfuric-acid-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'water-barrel', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'electronic-circuit', 5}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'advanced-circuit', 1}}, offer = {type = 'give-item', item = 'coin', count = 5}})
table_insert(market_items, {price = {{'processing-unit', 1}}, offer = {type = 'give-item', item = 'coin', count = 10}})
table_insert(market_items, {price = {{'plastic-bar', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'green-wire', 5}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'red-wire', 5}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'battery', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'heat-pipe', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'pipe', 8}}, offer = {type = 'give-item', item = 'coin', count = 1}})
table_insert(market_items, {price = {{'pipe-to-ground', 1}}, offer = {type = 'give-item', item = 'coin', count = 1}})
for _, item in pairs(market_items) do
market.add_market_item(item)
end
end
local function refresh_offers(event)
local player_index = event.player_index
if player_index == nil then
return
end
local player = game.players[event.player_index]
local ffatable = Table.get_table()
local market = event.entity or event.market
if not market then
return
end
if not market.valid then
return
end
if market.name ~= 'crash-site-spaceship-market' then
return
end
local position = market.position
local spaceship = ffatable.spaceships[position.x][position.y]
if not spaceship then
return
end
clear_offers(market)
set_offers(market, player)
end
local function offer_purchased(event)
local ffatable = Table.get_table()
local player = game.players[event.player_index]
local market = event.market
local offer_index = event.offer_index
local count = event.count
if not upgrade_functions[offer_index] then
return
end
local spaceship = ffatable.spaceships[market.position.x][market.position.y]
if not spaceship then
return
end
if upgrade_functions[offer_index](player) then
-- reimburse extra purchased
if count > 1 then
local offers = market.get_market_items()
if offers[offer_index].price ~= nil then
local price = offers[offer_index].price[1].amount
player.insert({name = 'coin', count = price * (count - 1)})
end
end
else
-- reimburse purchase
local offers = market.get_market_items()
if offers[offer_index].price ~= nil then
local price = offers[offer_index].price[1].amount
player.insert({name = 'coin', count = price * (count)})
end
end
end
local function on_gui_opened(event)
local gui_type = event.gui_type
if gui_type == defines.gui_type.entity then
local entity = event.entity
if entity ~= nil or entity.valid then
-- crash-site-spaceship
if entity.name == 'crash-site-spaceship-market' then
refresh_offers(event)
end
end
end
end
local function on_market_item_purchased(event)
local market = event.market
if market.name == 'crash-site-spaceship-market' then
offer_purchased(event)
refresh_offers(event)
end
end
local function kill_spaceship(entity)
local ffatable = Table.get_table()
local spaceship = ffatable.spaceships[entity.position.x][entity.position.y]
if spaceship ~= nil then
ffatable.spaceships[entity.position.x][entity.position.y] = nil
end
end
local function on_entity_died(event)
local entity = event.entity
if entity.name == 'crash-site-spaceship-market' then
kill_spaceship(entity)
end
end
local on_init = function()
local ffatable = Table.get_table()
ffatable.spaceships = {}
end
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_gui_opened, on_gui_opened)
Event.add(defines.events.on_market_item_purchased, on_market_item_purchased)
Event.add(defines.events.on_entity_died, on_entity_died)

View File

@ -1,4 +1,3 @@
--luacheck: ignore
local Public = {}
local table_size = table.size
@ -69,11 +68,19 @@ end
-- is the position empty
local function is_empty(position, surface)
local entity_radius = 1
local tile_radius = 1
local entities = surface.count_entities_filtered({position = position, radius = entity_radius, collision_mask = {'object-layer', 'player-layer'}})
--log("entities = " .. entities)
if entities > 0 then
local chunk_position = {}
chunk_position.x = math_floor(position.x / 32)
chunk_position.y = math_floor(position.y / 32)
if not surface.is_chunk_generated(chunk_position) then
-- force load the chunk
surface.request_to_generate_chunks(position, 0)
surface.force_generate_chunk_requests()
end
local entity_radius = 3
local tile_radius = 2
local entities = surface.find_entities_filtered({position = position, radius = entity_radius})
--log("entities = " .. #entities)
if #entities > 0 then
return false
end
local tiles = surface.count_tiles_filtered({position = position, radius = tile_radius, collision_mask = 'water-tile'})
@ -87,14 +94,17 @@ local function is_empty(position, surface)
end
-- finds a valid spawn point that is not near a town and not in a polluted area
local function find_valid_spawn_point(surface)
local function find_valid_spawn_point(force_name, surface)
local ffatable = Table.get_table()
-- check center of map first if valid
local position = {x = 0, y = 0}
--log("testing {" .. position.x .. "," .. position.y .. "}")
force_load(position, surface, 1)
-- is the point near any buildings
if in_use(position) == false then
if Building.near_town(position, surface, spawn_point_town_buffer) == false then
if Building.near_another_town(force_name, position, surface, spawn_point_town_buffer) == false then
-- force load the position
if is_empty(position, surface) == true then
--log("found valid spawn point at {" .. position.x .. "," .. position.y .. "}")
@ -133,7 +143,7 @@ local function find_valid_spawn_point(surface)
force_load(position, surface, 1)
if in_use(target) == false then
if has_pollution(target, surface) == false then
if Building.near_town(target, surface, spawn_point_town_buffer) == false then
if Building.near_another_town(force_name, target, surface, spawn_point_town_buffer) == false then
if is_empty(target, surface) == true then
--log("found valid spawn point at {" .. target.x .. "," .. target.y .. "}")
position = target
@ -145,7 +155,6 @@ local function find_valid_spawn_point(surface)
end
-- near a town, increment the radius and select another angle
radius = radius + math_random(1, spawn_point_incremental_distance)
angle = math_random(0, 360)
tries = tries + 1
end
return {x = 0, y = 0}
@ -154,7 +163,14 @@ end
function Public.get_new_spawn_point(player, surface)
local ffatable = Table.get_table()
-- get a new spawn point
local position = find_valid_spawn_point(surface)
local position = {0, 0}
if player ~= nil then
local force = player.force
if force ~= nil then
local force_name = force.name
position = find_valid_spawn_point(force_name, surface)
end
end
-- should never be invalid or blocked
ffatable.spawn_point[player.name] = position
--log("player " .. player.name .. " assigned new spawn point at {" .. position.x .. "," .. position.y .. "}")
@ -164,21 +180,16 @@ end
-- gets a new or existing spawn point for the player
function Public.get_spawn_point(player, surface)
local ffatable = Table.get_table()
if ffatable.spawn_point == nil then
ffatable.spawn_point = {}
end
-- test the existing spawn point
local position = ffatable.spawn_point[player.name]
if position ~= nil then
-- if there is a spawn point and less than three strikes
if position ~= nil and ffatable.strikes[player.name] < 3 then
-- check that the spawn point is not blocked
if surface.can_place_entity({name = 'character', position = position}) then
--log("player " .. player.name .. "using existing spawn point at {" .. position.x .. "," .. position.y .. "}")
return position
else
position = surface.find_non_colliding_position('character', position, 16, 0.25)
if (position ~= nil) then
return position
end
position = surface.find_non_colliding_position('character', position, 0, 0.25)
return position
end
end
-- otherwise get a new spawn point

View File

@ -20,6 +20,25 @@ function Public.get_table()
return ffatable
end
function Public.get(key)
if key then
return ffatable[key]
else
return ffatable
end
end
function Public.set(key, value)
if key and (value or value == false) then
ffatable[key] = value
return ffatable[key]
elseif key then
return ffatable[key]
else
return ffatable
end
end
local on_init = function()
Public.reset_table()
end

View File

@ -1,10 +1,12 @@
--luacheck: ignore
local Public = {}
local math_random = math.random
local table_size = table.size
local string_match = string.match
local string_lower = string.lower
local Server = require 'utils.server'
local Map = require 'modules.scrap_towny_ffa.map'
local Table = require 'modules.scrap_towny_ffa.table'
local outlander_color = {150, 150, 150}
@ -13,70 +15,118 @@ local rogue_color = {150, 150, 150}
local rogue_chat_color = {170, 170, 170}
local item_drop_radius = 1.65
local destroy_wall_types = {
['gate'] = true,
['wall'] = true
}
local destroy_military_types = {
['ammo-turret'] = true,
['artillery-turret'] = true,
['artillery-wagon'] = true,
['electric-turret'] = true,
['fluid-turret'] = true,
['lab'] = true,
['land-mine'] = true,
['logistic-robot'] = true,
['radar'] = true,
['reactor'] = true,
['roboport'] = true,
['rocket-silo'] = true
}
local destroy_robot_types = {
['combat-robot'] = true,
['construction-robot'] = true,
['logistic-robot'] = true
}
local function min_slots(slots)
local min = 0
for i = 1, 3, 1 do
if slots[i] > min then
min = slots[i]
end
end
return min
end
local function can_force_accept_member(force)
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
local size_of_town_centers = ffatable.size_of_town_centers
local member_limit = 0
if size_of_town_centers <= 1 then
return true
if ffatable.member_limit == nil then
ffatable.member_limit = 1
end
for _, town in pairs(town_centers) do
member_limit = member_limit + table_size(town.market.force.connected_players)
-- get the members of each force name into a table
local slots = {0, 0, 0}
for _, town_center in pairs(town_centers) do
local players = table_size(town_center.market.force.players)
-- get min value for all slots
local min = min_slots(slots)
-- if our value greater than min of all three replace that slot
if players > min then
for i = 1, 3, 1 do
if slots[i] == min then
slots[i] = players
break
end
end
end
end
member_limit = math.floor(member_limit / size_of_town_centers) + 4
-- get the min of all slots
local member_limit = min_slots(slots) + 1
ffatable.member_limit = member_limit
if #force.connected_players >= member_limit then
game.print('>> Town ' .. force.name .. ' has too many settlers! Current limit (' .. member_limit .. ')', {255, 255, 0})
return
end
return true
end
local function is_towny(force)
if force == game.forces['player'] or force == game.forces['rogue'] then
return false
end
return true
end
function Public.has_key(player)
if not (player and player.valid) then
return
local function is_towny(force)
if force.index == game.forces['player'].index or force.index == game.forces['rogue'].index then
return false
end
local ffatable = Table.get_table()
return ffatable.key[player.index]
return true
end
function Public.give_key(player)
if not (player and player.valid) then
return
end
function Public.has_key(index)
local ffatable = Table.get_table()
ffatable.key[player.index] = true
if ffatable.key == nil then
ffatable.key = {}
end
if ffatable.key[index] ~= nil then
return ffatable.key[index]
end
return false
end
function Public.remove_key(player)
if not (player and player.valid) then
return
end
function Public.give_key(index)
local ffatable = Table.get_table()
if ffatable.key == nil then
ffatable.key = {}
end
ffatable.key[index] = true
end
ffatable.key[player.index] = false
function Public.remove_key(index)
local ffatable = Table.get_table()
if ffatable.key == nil then
ffatable.key = {}
end
ffatable.key[index] = false
end
function Public.set_player_color(player)
local ffatable = Table.get_table()
if player.force == game.forces['player'] then
if player.force.index == game.forces['player'].index then
player.color = outlander_color
player.chat_color = outlander_chat_color
return
end
if player.force == game.forces['rogue'] then
if player.force.index == game.forces['rogue'].index then
player.color = rogue_color
player.chat_color = rogue_chat_color
return
@ -114,51 +164,62 @@ function Public.set_all_player_colors()
end
end
local function reset_player(player)
if player.character ~= nil then
local character = player.character
character.character_crafting_speed_modifier = 0.0
character.character_mining_speed_modifier = 0.0
character.character_inventory_slots_bonus = 0
end
end
function Public.add_player_to_town(player, town_center)
local ffatable = Table.get_table()
local market = town_center.market
local force = market.force
local surface = market.surface
reset_player(player)
player.force = market.force
Public.remove_key(player)
Public.remove_key(player.index)
ffatable.spawn_point[player.name] = force.get_spawn_position(surface)
game.permissions.get_group(force.name).add_player(player)
player.tag = ''
Map.enable_world_map(player)
Public.set_player_color(player)
end
function Public.give_outlander_items(player)
player.insert({name = 'stone-furnace', count = 1})
-- given to player upon respawn
function Public.give_player_items(player)
player.clear_items_inside()
player.insert({name = 'raw-fish', count = 3})
player.insert({name = 'coal', count = 3})
end
function Public.set_player_to_outlander(player)
local ffatable = Table.get_table()
player.force = game.forces.player
if ffatable.spawn_point[player.name] then
ffatable.spawn_point[player.name] = nil
if player == nil then
return
end
player.force = game.forces.player
if game.permissions.get_group('outlander') == nil then
game.permissions.create_group('outlander')
end
game.permissions.get_group('outlander').add_player(player)
player.tag = '[Outlander]'
Map.disable_world_map(player)
Public.set_player_color(player)
Public.give_key(player)
Public.give_key(player.index)
end
local function set_player_to_rogue(player)
local ffatable = Table.get_table()
player.force = game.forces['rogue']
if ffatable.spawn_point[player.name] then
ffatable.spawn_point[player.name] = nil
if player == nil then
return
end
player.force = 'rogue'
if game.permissions.get_group('rogue') == nil then
game.permissions.create_group('rogue')
end
game.permissions.get_group('rogue').add_player(player)
player.tag = '[Rogue]'
Map.disable_world_map(player)
Public.set_player_color(player)
end
@ -167,6 +228,11 @@ local function ally_outlander(player, target)
local requesting_force = player.force
local target_force = target.force
-- don't handle if towns not yet enabled
if not ffatable.towns_enabled then
player.print('You must wait for more players to join!', {255, 255, 0})
return false
end
-- don't handle request if target is not a town
if not is_towny(requesting_force) and not is_towny(target_force) then
return false
@ -181,7 +247,7 @@ local function ally_outlander(player, target)
if not is_towny(requesting_force) and is_towny(target_force) then
ffatable.requests[player.index] = target_force.name
local target_player = false
local target_player
if target.type == 'character' then
target_player = target.player
else
@ -333,7 +399,10 @@ local function declare_war(player, item)
requesting_force.set_friend(target_force, false)
target_force.set_friend(requesting_force, false)
game.print('>> ' .. player.name .. ' has dropped the coal! Town ' .. target_force.name .. ' and ' .. requesting_force.name .. ' are now at war!', {255, 255, 0})
game.print(
'>> ' .. player.name .. ' has dropped the coal! Town ' .. target_force.name .. ' and ' .. requesting_force.name .. ' are now at war!',
{255, 255, 0}
)
end
local function delete_chart_tag_for_all_forces(market)
@ -351,13 +420,15 @@ local function delete_chart_tag_for_all_forces(market)
end
end
function Public.add_chart_tag(force, market)
function Public.add_chart_tag(town_center)
local market = town_center.market
local force = market.force
local position = market.position
local tags = force.find_chart_tags(market.surface, {{position.x - 0.1, position.y - 0.1}, {position.x + 0.1, position.y + 0.1}})
if tags[1] then
return
end
force.add_chart_tag(market.surface, {icon = {type = 'item', name = 'stone-furnace'}, position = position, text = market.force.name .. "'s Town"})
force.add_chart_tag(market.surface, {icon = {type = 'item', name = 'stone-furnace'}, position = position, text = town_center.town_name})
end
function Public.update_town_chart_tags()
@ -366,9 +437,11 @@ function Public.update_town_chart_tags()
local forces = game.forces
for _, town_center in pairs(town_centers) do
local market = town_center.market
for _, force in pairs(forces) do
if force.is_chunk_visible(market.surface, town_center.chunk_position) then
Public.add_chart_tag(force, market)
if market ~= nil and market.valid then
for _, force in pairs(forces) do
if force.is_chunk_visible(market.surface, town_center.chunk_position) then
Public.add_chart_tag(town_center)
end
end
end
end
@ -386,6 +459,35 @@ local function reset_permissions(permission_group)
end
end
local function enable_blueprints(permission_group)
local defs = {
defines.input_action.alt_select_blueprint_entities,
defines.input_action.cancel_new_blueprint,
defines.input_action.change_blueprint_record_label,
defines.input_action.clear_selected_blueprint,
defines.input_action.create_blueprint_like,
defines.input_action.cycle_blueprint_backwards,
defines.input_action.cycle_blueprint_forwards,
defines.input_action.delete_blueprint_library,
defines.input_action.delete_blueprint_record,
defines.input_action.drop_blueprint_record,
defines.input_action.drop_to_blueprint_book,
defines.input_action.export_blueprint,
defines.input_action.grab_blueprint_record,
defines.input_action.import_blueprint,
defines.input_action.import_blueprint_string,
defines.input_action.open_blueprint_library_gui,
defines.input_action.open_blueprint_record,
defines.input_action.select_blueprint_entities,
defines.input_action.setup_blueprint,
defines.input_action.setup_single_blueprint_record,
defines.input_action.upgrade_open_blueprint
}
for _, d in pairs(defs) do
permission_group.set_allows_action(d, true)
end
end
local function disable_blueprints(permission_group)
local defs = {
defines.input_action.alt_select_blueprint_entities,
@ -408,7 +510,30 @@ local function disable_blueprints(permission_group)
defines.input_action.select_blueprint_entities,
defines.input_action.setup_blueprint,
defines.input_action.setup_single_blueprint_record,
defines.input_action.upgrade_open_blueprint,
defines.input_action.upgrade_open_blueprint
}
for _, d in pairs(defs) do
permission_group.set_allows_action(d, false)
end
end
local function enable_deconstruct(permission_group)
local defs = {
defines.input_action.deconstruct,
defines.input_action.clear_selected_deconstruction_item,
defines.input_action.cancel_deconstruct,
defines.input_action.toggle_deconstruction_item_entity_filter_mode,
defines.input_action.toggle_deconstruction_item_tile_filter_mode,
defines.input_action.set_deconstruction_item_tile_selection_mode,
defines.input_action.set_deconstruction_item_trees_and_rocks_only
}
for _, d in pairs(defs) do
permission_group.set_allows_action(d, true)
end
end
local function disable_deconstruct(permission_group)
local defs = {
defines.input_action.deconstruct,
defines.input_action.clear_selected_deconstruction_item,
defines.input_action.cancel_deconstruct,
@ -425,12 +550,12 @@ end
local function enable_artillery(force, permission_group)
permission_group.set_allows_action(defines.input_action.use_artillery_remote, true)
force.technologies['artillery'].enabled = true
force.technologies['artillery-shell-range-1'].enabled = false
force.technologies['artillery-shell-speed-1'].enabled = false
force.recipes['artillery-turret'].enabled = true
force.recipes['artillery-wagon'].enabled = true
force.recipes['artillery-targeting-remote'].enabled = true
force.recipes['artillery-shell'].enabled = true
force.technologies['artillery-shell-range-1'].enabled = true
force.technologies['artillery-shell-speed-1'].enabled = true
force.recipes['artillery-turret'].enabled = false
force.recipes['artillery-wagon'].enabled = false
force.recipes['artillery-targeting-remote'].enabled = false
force.recipes['artillery-shell'].enabled = false
end
local function disable_artillery(force, permission_group)
@ -490,11 +615,13 @@ end
-- setup a team force
function Public.add_new_force(force_name)
local ffatable = Table.get_table()
-- disable permissions
local force = game.create_force(force_name)
local permission_group = game.permissions.create_group(force_name)
reset_permissions(permission_group)
disable_blueprints(permission_group)
enable_blueprints(permission_group)
enable_deconstruct(permission_group)
enable_artillery(force, permission_group)
disable_spidertron(force, permission_group)
disable_rockets(force)
@ -510,15 +637,29 @@ function Public.add_new_force(force_name)
-- balance initial combat
force.set_ammo_damage_modifier('landmine', -0.75)
force.set_ammo_damage_modifier('grenade', -0.5)
if (ffatable.testing_mode == true) then
local e_force = game.forces['enemy']
e_force.set_friend(force, true) -- team force should not be attacked by turrets
e_force.set_cease_fire(force, true) -- team force should not be attacked by units
force.enable_all_prototypes()
force.research_all_technologies()
end
return force
end
local function kill_force(force_name)
local function kill_force(force_name, cause)
local ffatable = Table.get_table()
local force = game.forces[force_name]
local market = ffatable.town_centers[force_name].market
local town_center = ffatable.town_centers[force_name]
local market = town_center.market
local position = market.position
local surface = market.surface
surface.create_entity({name = 'big-artillery-explosion', position = market.position})
local balance = town_center.coin_balance
local town_name = town_center.town_name
surface.create_entity({name = 'big-artillery-explosion', position = position})
for _, player in pairs(force.players) do
ffatable.spawn_point[player.name] = nil
ffatable.cooldowns_town_placement[player.index] = game.tick + 3600 * 15
if player.character then
player.character.die()
else
@ -526,22 +667,108 @@ local function kill_force(force_name)
end
player.force = game.forces.player
Public.set_player_color(player)
Public.give_key(player.index)
end
for _, e in pairs(surface.find_entities_filtered({force = force_name})) do
if e.valid then
if e.type == 'wall' or e.type == 'gate' then
if destroy_military_types[e.type] == true then
surface.create_entity({name = 'big-artillery-explosion', position = position})
e.die()
else
if destroy_robot_types[e.type] == true then
surface.create_entity({name = 'explosion', position = position})
e.die()
else
if destroy_wall_types[e.type] == true then
e.die()
end
end
end
end
end
for _, e in pairs(surface.find_entities_filtered({force = force_name})) do
if e.valid then
e.force = game.forces['neutral']
local damage = math_random() * 2.5 - 0.5
if damage > 0 then
if damage >= 1 or e.health == nil then
e.die()
else
local health = e.health
e.health = health * damage
end
end
end
end
local r = 27
for _, e in pairs(
surface.find_entities_filtered({area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}}, force = 'neutral', type = 'resource'})
) do
if e.name ~= 'crude-oil' then
e.destroy()
end
end
game.merge_forces(force_name, 'neutral')
ffatable.town_centers[force_name] = nil
ffatable.size_of_town_centers = ffatable.size_of_town_centers - 1
ffatable.number_of_towns = ffatable.number_of_towns - 1
delete_chart_tag_for_all_forces(market)
game.print('>> ' .. force_name .. "'s town has fallen! [gps=" .. math.floor(market.position.x) .. ',' .. math.floor(market.position.y) .. ']', {255, 255, 0})
-- reward the killer
if cause == nil or not cause.valid then
Server.to_discord_embed(town_name .. ' has fallen!')
game.print('>> ' .. town_name .. ' has fallen!', {255, 255, 0})
return
end
if cause.force == nil then
Server.to_discord_embed(town_name .. ' has fallen!')
game.print('>> ' .. town_name .. ' has fallen!', {255, 255, 0})
return
end
if cause.force.name == 'player' or cause.force.name == 'rogue' then
local items = {name = 'coin', count = balance}
town_center.coin_balance = 0
if balance > 0 then
if cause.can_insert(items) then
cause.insert(items)
else
local chest = surface.create_entity({name = 'steel-chest', position = position, force = 'neutral'})
chest.insert(items)
end
end
if cause.force.name == 'player' then
Server.to_discord_embed(town_name .. ' has fallen to outlanders!')
game.print('>> ' .. town_name .. ' has fallen to outlanders!', {255, 255, 0})
else
Server.to_discord_embed(town_name .. ' has fallen to rogues!')
game.print('>> ' .. town_name .. ' has fallen to rogues!', {255, 255, 0})
end
else
if cause.force.name ~= 'enemy' then
if ffatable.town_centers[cause.force.name] ~= nil then
local killer_town_center = ffatable.town_centers[cause.force.name]
if balance > 0 then
killer_town_center.coin_balance = killer_town_center.coin_balance + balance
end
Server.to_discord_embed(town_name .. ' has fallen to ' .. killer_town_center.town_name .. '!')
game.print('>> ' .. town_name .. ' has fallen to ' .. killer_town_center.town_name .. '!', {255, 255, 0})
end
else
Server.to_discord_embed(town_name .. ' has fallen!')
game.print('>> ' .. town_name .. ' has fallen!', {255, 255, 0})
end
end
end
local player_force_disabled_recipes = {'lab', 'automation-science-pack', 'stone-brick', 'radar'}
-- hand craftable
local player_force_disabled_recipes = {
'lab',
'automation-science-pack',
'steel-furnace',
'electric-furnace',
'stone-wall',
'stone-brick',
'radar'
}
local player_force_enabled_recipes = {
'submachine-gun',
'assembling-machine-1',
@ -552,24 +779,40 @@ local player_force_enabled_recipes = {
'splitter',
'steel-plate',
'car',
'cargo-wagon',
'constant-combinator',
'tank',
'engine-unit',
'constant-combinator',
'green-wire',
'locomotive',
'rail',
'train-stop',
'red-wire',
'arithmetic-combinator',
'decider-combinator'
}
local function setup_neutral_force()
local force = game.forces['neutral']
force.technologies['military'].researched = true
force.technologies['automation'].researched = true
force.technologies['logistic-science-pack'].researched = true
force.technologies['steel-processing'].researched = true
force.technologies['engine'].researched = true
force.recipes['submachine-gun'].enabled = true
force.recipes['engine-unit'].enabled = true
force.recipes['stone-brick'].enabled = false
force.recipes['radar'].enabled = false
force.recipes['lab'].enabled = false
force.recipes['automation-science-pack'].enabled = false
force.recipes['logistic-science-pack'].enabled = false
end
-- setup the player force (this is the default for Outlanders)
local function setup_player_force()
local ffatable = Table.get_table()
local force = game.forces.player
local permission_group = game.permissions.create_group('outlander')
-- disable permissions
reset_permissions(permission_group)
disable_blueprints(permission_group)
disable_deconstruct(permission_group)
disable_artillery(force, permission_group)
disable_spidertron(force, permission_group)
disable_rockets(force)
@ -593,15 +836,20 @@ local function setup_player_force()
end
force.set_ammo_damage_modifier('landmine', -0.75)
force.set_ammo_damage_modifier('grenade', -0.5)
if (ffatable.testing_mode == true) then
force.enable_all_prototypes()
end
end
local function setup_rogue_force()
local ffatable = Table.get_table()
local force_name = 'rogue'
local force = game.create_force(force_name)
local permission_group = game.permissions.create_group(force_name)
-- disable permissions
reset_permissions(permission_group)
disable_blueprints(permission_group)
disable_deconstruct(permission_group)
disable_artillery(force, permission_group)
disable_spidertron(force, permission_group)
disable_rockets(force)
@ -625,22 +873,31 @@ local function setup_rogue_force()
end
force.set_ammo_damage_modifier('landmine', -0.75)
force.set_ammo_damage_modifier('grenade', -0.5)
if (ffatable.testing_mode == true) then
force.enable_all_prototypes()
end
end
local function setup_enemy_force()
local ffatable = Table.get_table()
local e_force = game.forces['enemy']
e_force.evolution_factor = 1 -- this should never change since we are changing biter types on spawn
e_force.set_friend(game.forces.player, true) -- outlander force (player) should not be attacked by turrets
e_force.set_cease_fire(game.forces.player, true) -- outlander force (player) should not be attacked by units
e_force.set_friend(game.forces['rogue'], false) -- rogue force (rogue) should be attacked by turrets
e_force.set_cease_fire(game.forces['rogue'], false) -- rogue force (rogue) should be attacked by units
-- note, these don't prevent an outlander or rogue from attacking a unit or spawner, we need to handle separately
if (ffatable.testing_mode == true) then
e_force.set_friend(game.forces['rogue'], true) -- rogue force (rogue) should not be attacked by turrets
e_force.set_cease_fire(game.forces['rogue'], true) -- rogue force (rogue) should not be attacked by units
else
-- note, these don't prevent an outlander or rogue from attacking a unit or spawner, we need to handle separately
e_force.set_friend(game.forces['rogue'], false) -- rogue force (rogue) should be attacked by turrets
e_force.set_cease_fire(game.forces['rogue'], false) -- rogue force (rogue) should be attacked by units
end
end
local function on_player_dropped_item(event)
local player = game.players[event.player_index]
local entity = event.entity
if entity.stack.name == 'raw-fish' then
if entity.stack.name == 'coin' then
ally_town(player, entity)
return
end
@ -669,9 +926,9 @@ local function on_entity_damaged(event)
-- special case to handle enemies attacked by outlanders
if entity.force == game.forces['enemy'] then
if cause ~= nil then
if cause.type == 'character' and force == game.forces['player'] then
if cause.type == 'character' and force.index == game.forces['player'].index then
local player = cause.player
if force == game.forces['player'] then
if player ~= nil and force.index == game.forces['player'].index then
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(player)
end
@ -679,12 +936,12 @@ local function on_entity_damaged(event)
-- cars and tanks
if cause.type == 'car' or cause.type == 'tank' then
local driver = cause.get_driver()
if driver ~= nil and driver.force == game.forces['player'] then
if driver ~= nil and driver.force.index == game.forces['player'].index then
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(driver)
end
local passenger = cause.get_passenger()
if passenger ~= nil and passenger.force == game.forces['player'] then
if passenger ~= nil and passenger.force.index == game.forces['player'].index then
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(passenger)
end
@ -693,16 +950,18 @@ local function on_entity_damaged(event)
if cause.type == 'locomotive' or cause.type == 'cargo-wagon' or cause.type == 'fluid-wagon' or cause.type == 'artillery-wagon' then
local train = cause.train
for _, passenger in pairs(train.passengers) do
if passenger ~= nil and passenger.force == game.forces['player'] then
if passenger ~= nil and passenger.force.index == game.forces['player'].index then
set_player_to_rogue(passenger)
end
end
end
-- combat robots
if cause.type == 'combat-robot' and force == game.forces['player'] then
if cause.type == 'combat-robot' then
local owner = cause.last_user
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(owner)
if owner ~= nil and owner.force == game.forces['player]'] then
-- set the force of the player to rogue until they die or create a town
set_player_to_rogue(owner)
end
end
end
end
@ -710,8 +969,9 @@ end
local function on_entity_died(event)
local entity = event.entity
if entity.name == 'market' then
kill_force(entity.force.name)
local cause = event.cause
if entity ~= nil and entity.valid and entity.name == 'market' then
kill_force(entity.force.name, cause)
end
end
@ -723,7 +983,7 @@ local function on_post_entity_died(event)
local entities = game.surfaces[event.surface_index].find_entities_filtered({position = event.position, radius = 1})
for _, e in pairs(entities) do
if e.type == 'character-corpse' then
Public.remove_key(e)
Public.remove_key(e.character_corpse_player_index)
end
end
end
@ -735,12 +995,16 @@ end
local function on_console_chat(event)
local player = game.players[event.player_index]
if string_match(string_lower(event.message), '%[armor%=') then
if string_match(event.message, player.name) then
return
end
player.clear_console()
game.print('>> ' .. player.name .. ' is trying to gain an unfair advantage!')
end
end
function Public.initialize()
setup_neutral_force()
setup_player_force()
setup_rogue_force()
setup_enemy_force()

View File

@ -5,13 +5,17 @@ local table_insert = table.insert
local math_floor = math.floor
local table_shuffle = table.shuffle_table
local Server = require 'utils.server'
local Table = require 'modules.scrap_towny_ffa.table'
local Team = require 'modules.scrap_towny_ffa.team'
local Building = require 'modules.scrap_towny_ffa.building'
local Colors = require 'modules.scrap_towny_ffa.colors'
local Enemy = require 'modules.scrap_towny_ffa.enemy'
local Color = require 'utils.color_presets'
local town_radius = 27
local radius_between_towns = 160
local ore_amount = 250
local radius_between_towns = 64
local ore_amount = 1000 * (200 / 168.5)
local colors = {}
local c1 = 250
@ -63,8 +67,8 @@ end
local resource_vectors = {}
resource_vectors[1] = {}
for x = 7, 24, 1 do
for y = 7, 24, 1 do
for x = 10, 22, 1 do
for y = 10, 22, 1 do
table_insert(resource_vectors[1], {x, y})
end
end
@ -103,12 +107,17 @@ for _, vector in pairs(additional_resource_vectors[3]) do
table_insert(additional_resource_vectors[4], {vector[1], vector[2] * -1})
end
local clear_whitelist_types = {
['simple-entity'] = true,
['resource'] = true,
['cliff'] = true,
['tree'] = true
}
--local clear_whitelist_types = {
-- ['character'] = true,
-- ['market'] = true,
-- ['simple-entity'] = true,
-- ['simple-entity-with-owner'] = true,
-- ['container'] = true,
-- ['car'] = true,
-- ['resource'] = true,
-- ['cliff'] = true,
-- ['tree'] = true
--}
local starter_supplies = {
{name = 'raw-fish', count = 3},
@ -121,14 +130,15 @@ local starter_supplies = {
{name = 'shotgun', count = 1},
{name = 'shotgun-shell', count = 8},
{name = 'firearm-magazine', count = 16},
{name = 'firearm-magazine', count = 16},
{name = 'gun-turret', count = 2}
}
local function count_nearby_ore(surface, position, ore_name)
local count = 0
local r = town_radius + 8
for _, e in pairs(surface.find_entities_filtered({area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}}, force = 'neutral', name = ore_name})) do
for _, e in pairs(
surface.find_entities_filtered({area = {{position.x - r, position.y - r}, {position.x + r, position.y + r}}, force = 'neutral', name = ore_name})
) do
count = count + e.amount
end
return count
@ -140,14 +150,14 @@ local function draw_town_spawn(player_name)
local position = market.position
local surface = market.surface
local area = {{position.x - (town_radius + 1), position.y - (town_radius + 1)}, {position.x + (town_radius + 1), position.y + (town_radius + 1)}}
--local area = {{position.x - (town_radius + 1), position.y - (town_radius + 1)}, {position.x + (town_radius + 1), position.y + (town_radius + 1)}}
-- remove other than cliffs, rocks and ores and trees
for _, e in pairs(surface.find_entities_filtered({area = area, force = 'neutral'})) do
if not clear_whitelist_types[e.type] then
e.destroy()
end
end
--for _, e in pairs(surface.find_entities_filtered({area = area, force = 'neutral'})) do
-- if not clear_whitelist_types[e.type] then
-- e.destroy()
-- end
--end
-- create walls
for _, vector in pairs(gate_vectors_horizontal) do
@ -196,7 +206,7 @@ local function draw_town_spawn(player_name)
local p = {position.x + m1, position.y + m2}
p = surface.find_non_colliding_position('wooden-chest', p, 64, 1)
if p then
local e = surface.create_entity({name = 'wooden-chest', position = p, force = player_name})
local e = surface.create_entity({name = 'iron-chest', position = p, force = player_name})
local inventory = e.get_inventory(defines.inventory.chest)
inventory.insert(item_stack)
end
@ -225,7 +235,7 @@ local function draw_town_spawn(player_name)
local y = position.y + vector[2]
local p = {x = x, y = y}
if surface.get_tile(p).name ~= 'out-of-map' then
surface.set_tiles({{name = 'water-green', position = p}})
surface.set_tiles({{name = 'water-shallow', position = p}})
end
end
@ -265,9 +275,8 @@ local function draw_town_spawn(player_name)
--end
end
local function is_valid_location(surface, position)
local function is_valid_location(force_name, surface, position)
local ffatable = Table.get_table()
if not surface.can_place_entity({name = 'market', position = position}) then
surface.create_entity(
{
@ -282,13 +291,12 @@ local function is_valid_location(surface, position)
for _, vector in pairs(town_wall_vectors) do
local p = {x = math_floor(position.x + vector[1]), y = math_floor(position.y + vector[2])}
local tile = surface.get_tile(p.x, p.y)
if tile.name == 'out-of-map' then
if Building.in_restricted_zone(surface, p) then
surface.create_entity(
{
name = 'flying-text',
position = position,
text = 'Town would be off-map!',
text = 'Can not build in restricted zone!',
color = {r = 0.77, g = 0.0, b = 0.0}
}
)
@ -296,52 +304,53 @@ local function is_valid_location(surface, position)
end
end
if ffatable.size_of_town_centers > 48 then
if ffatable.number_of_towns > 48 then
surface.create_entity(
{
name = 'flying-text',
position = position,
text = 'Too many town centers on the map!',
text = 'Too many towns on the map!',
color = {r = 0.77, g = 0.0, b = 0.0}
}
)
return false
end
if Building.near_town(position, surface, radius_between_towns) then
if Building.near_another_town(force_name, position, surface, radius_between_towns) == true then
surface.create_entity(
{
name = 'flying-text',
position = position,
text = 'Town location is too close to another town center!',
text = 'Town location is too close to others!',
color = {r = 0.77, g = 0.0, b = 0.0}
}
)
return false
end
local area = {{position.x - town_radius, position.y - town_radius}, {position.x + town_radius, position.y + town_radius}}
local count = 0
for _, e in pairs(surface.find_entities_filtered({area = area})) do
if e.force.name == 'enemy' then
count = count + 1
end
end
if count > 1 then
surface.create_entity(
{
name = 'flying-text',
position = position,
text = 'I got a bad feeling about this! There are enemies nearby.',
color = {r = 0.77, g = 0.0, b = 0.0}
}
)
end
return true
end
function Public.in_any_town(position)
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
for _, town_center in pairs(town_centers) do
local market = town_center.market
if market ~= nil then
if Building.in_area(position, market.position, town_radius) == true then
return true
end
end
end
return false
end
function Public.update_town_name(force)
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force.name]
rendering.set_text(town_center.town_caption, town_center.town_name)
end
function Public.set_market_health(entity, final_damage_amount)
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[entity.force.name]
@ -360,137 +369,125 @@ function Public.update_coin_balance(force)
rendering.set_text(town_center.coins_text, 'Coins: ' .. town_center.coin_balance)
end
local function is_color_used(color, town_centers)
for _, center in pairs(town_centers) do
if center.color then
if center.color.r == color.r and center.color.g == color.g and center.color.b == color.b then
return true
end
end
end
end
local function get_color()
local ffatable = Table.get_table()
local town_centers = ffatable.town_centers
local c
local shuffle_index = {}
for i = 1, #colors, 1 do
shuffle_index[i] = i
end
table_shuffle(shuffle_index)
for i = 1, #colors, 1 do
c = {r = colors[shuffle_index[i]][1], g = colors[shuffle_index[i]][2], b = colors[shuffle_index[i]][3]}
if not is_color_used(c, town_centers) then
return c
end
end
return c
end
local function found_town(event)
local entity = event.created_entity
-- is a valid entity placed?
if entity == nil or not entity.valid then
return true
end -- cancel, not a valid entity placed
if entity.name ~= 'stone-furnace' then
return false
end -- cancel, player did not place a stone-furnace
local player = game.players[event.player_index]
if player.force ~= game.forces.player and player.force ~= game.forces['rogue'] then
return false
end -- cancel, player is in a team already
local force_name = tostring(player.name)
if game.forces[force_name] then
return
end -- cancel, player is mayor of town
if Team.has_key(player) == false then
return false
end -- cancel, player has already placed a town
end
local player = game.players[event.player_index]
-- is player not a character?
local character = player.character
if character == nil then
return
end
-- is it a stone-furnace?
if entity.name ~= 'stone-furnace' then
return
end
-- is player in a town already?
if player.force.index ~= game.forces.player.index and player.force.index ~= game.forces['rogue'].index then
return
end
-- try to place the town
local force_name = tostring(player.name)
local surface = entity.surface
local ffatable = Table.get_table()
local position = entity.position
entity.destroy()
-- are towns enabled?
local ffatable = Table.get_table()
if not ffatable.towns_enabled then
player.print('You must wait for more players to join!', {255, 255, 0})
player.insert({name = 'stone-furnace', count = 1})
return
end
-- is player mayor of town that still exists?
if game.forces[force_name] then
player.insert({name = 'stone-furnace', count = 1})
return
end
-- has player placed a town already?
if Team.has_key(player.index) == false then
player.insert({name = 'stone-furnace', count = 1})
return
end
-- is town placement on cooldown?
if ffatable.cooldowns_town_placement[player.index] then
if game.tick < ffatable.cooldowns_town_placement[player.index] then
surface.create_entity(
{
name = 'flying-text',
position = entity.position,
position = position,
text = 'Town founding is on cooldown for ' .. math.ceil((ffatable.cooldowns_town_placement[player.index] - game.tick) / 3600) .. ' minutes.',
color = {r = 0.77, g = 0.0, b = 0.0}
}
)
player.insert({name = 'stone-furnace', count = 1})
entity.destroy()
return true
return
end
end
local position = entity.position
entity.destroy()
if not is_valid_location(surface, position) then
-- is it a valid location to place a town?
if not is_valid_location(force_name, surface, position) then
player.insert({name = 'stone-furnace', count = 1})
return true
return
end
Team.add_new_force(force_name)
-- does player have 100 coins?
local inventory = character.get_main_inventory()
if inventory == nil or inventory.get_item_count('coin') < 100 then
player.print('Towns cost 100 coins!', {255, 255, 0})
player.insert({name = 'stone-furnace', count = 1})
return
else
inventory.remove({name = 'coin', count = 100})
end
local force = Team.add_new_force(force_name)
ffatable.town_centers[force_name] = {}
local town_center = ffatable.town_centers[force_name]
town_center.town_name = player.name .. "'s Town"
town_center.market = surface.create_entity({name = 'market', position = position, force = force_name})
town_center.chunk_position = {math.floor(town_center.market.position.x / 32), math.floor(town_center.market.position.y / 32)}
town_center.max_health = 1000
town_center.max_health = 100
town_center.coin_balance = 0
town_center.input_buffer = {}
town_center.output_buffer = {}
town_center.health = town_center.max_health
town_center.color = get_color()
local crayola = Colors.get_random_color()
town_center.color = crayola.color
town_center.research_counter = 1
town_center.upgrades = {}
town_center.upgrades.mining_prod = 0
town_center.upgrades.mining_speed = 0
town_center.upgrades.crafting_speed = 0
town_center.upgrades.laser_turret = {}
town_center.upgrades.laser_turret.slots = 0
town_center.upgrades.laser_turret.locations = {}
town_center.upgrades.laser_turret.locations = 0
town_center.evolution = {}
town_center.evolution.biters = 0
town_center.evolution.spitters = 0
town_center.evolution.worms = 0
town_center.coins_text =
rendering.draw_text {
text = 'Coins: ' .. town_center.coin_balance,
surface = surface,
target = town_center.market,
target_offset = {0, -2.75},
color = {200, 200, 200},
scale = 1.00,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
town_center.health_text =
rendering.draw_text {
text = 'HP: ' .. town_center.health .. ' / ' .. town_center.max_health,
surface = surface,
target = town_center.market,
target_offset = {0, -3.25},
color = {200, 200, 200},
scale = 1.00,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
town_center.creation_tick = game.tick
town_center.town_caption =
rendering.draw_text {
text = player.name .. "'s Town",
text = town_center.town_name,
surface = surface,
forces = {force_name},
target = town_center.market,
target_offset = {0, -4.25},
color = town_center.color,
@ -500,27 +497,51 @@ local function found_town(event)
scale_with_zoom = false
}
ffatable.size_of_town_centers = ffatable.size_of_town_centers + 1
town_center.health_text =
rendering.draw_text {
text = 'HP: ' .. town_center.health .. ' / ' .. town_center.max_health,
surface = surface,
forces = {force_name},
target = town_center.market,
target_offset = {0, -3.25},
color = {200, 200, 200},
scale = 1.00,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
town_center.coins_text =
rendering.draw_text {
text = 'Coins: ' .. town_center.coin_balance,
surface = surface,
forces = {force_name},
target = town_center.market,
target_offset = {0, -2.75},
color = {200, 200, 200},
scale = 1.00,
font = 'default-game',
alignment = 'center',
scale_with_zoom = false
}
ffatable.number_of_towns = ffatable.number_of_towns + 1
Enemy.clear_enemies(position, surface, town_radius * 2)
draw_town_spawn(force_name)
Team.add_player_to_town(player, town_center)
Team.add_chart_tag(game.forces.player, town_center.market)
local force = player.force
-- set the spawn point
local pos = {x = town_center.market.position.x, y = town_center.market.position.y + 4}
--log("setting spawn point = {" .. spawn_point.x .. "," .. spawn_point.y .. "}")
force.set_spawn_position(pos, surface)
ffatable.spawn_point[player.name] = pos
ffatable.cooldowns_town_placement[player.index] = game.tick + 3600 * 15
Team.remove_key(player)
Team.add_player_to_town(player, town_center)
Team.remove_key(player.index)
Team.add_chart_tag(town_center)
game.print('>> ' .. player.name .. ' has founded a new town!', {255, 255, 0})
return true
Server.to_discord_embed(player.name .. ' has founded a new town!')
player.print('Your town color is ' .. crayola.name, crayola.color)
end
local function on_built_entity(event)
@ -554,10 +575,52 @@ end
local on_init = function()
local ffatable = Table.get_table()
ffatable.town_centers = {}
ffatable.size_of_town_centers = 0
ffatable.number_of_towns = 0
ffatable.cooldowns_town_placement = {}
end
local function rename_town(cmd)
local player = game.players[cmd.player_index]
if not player or not player.valid then
return
end
local force = player.force
if force.name == 'player' or force.name == 'rogue' then
player.print('You are not member of a town!', Color.fail)
return
end
local name = cmd.parameter
if name == nil then
player.print('Must specify new town name!', Color.fail)
return
end
local ffatable = Table.get_table()
local town_center = ffatable.town_centers[force.name]
local old_name = town_center.town_name
town_center.town_name = name
Public.update_town_name(force)
for _, p in pairs(force.players) do
if p == player then
player.print('Your town name is now ' .. name, town_center.color)
else
player.print(player.name .. ' has renamed the town to ' .. name, town_center.color)
end
Team.set_player_color(p)
end
game.print('>> ' .. old_name .. ' is now known as ' .. '"' .. name .. '"', {255, 255, 0})
Server.to_discord_embed(old_name .. ' is now known as ' .. '"' .. name .. '"')
end
commands.add_command(
'rename-town',
'Renames your town..',
function(cmd)
rename_town(cmd)
end
)
local Event = require 'utils.event'
Event.on_init(on_init)
Event.add(defines.events.on_built_entity, on_built_entity)

View File

@ -1,7 +1,6 @@
--luacheck: ignore
--Towny balance things by Gerkiz --
local player_ammo_starting_modifiers = {
--[[ local player_ammo_starting_modifiers = {
['artillery-shell'] = -0.75,
['biological'] = -0.5,
['bullet'] = -0.25,
@ -18,8 +17,7 @@ local player_ammo_starting_modifiers = {
['railgun'] = 1,
['rocket'] = -0.75,
['shotgun-shell'] = -0.20
}
} ]]
local player_gun_speed_modifiers = {
['artillery-shell'] = -0.75,
['biological'] = -0.5,
@ -101,7 +99,7 @@ local enemy_ammo_evolution_modifiers = {
--['rocket'] = 1,
--['shotgun-shell'] = 1
}
--[[
function init_player_weapon_damage(force)
for k, v in pairs(player_ammo_starting_modifiers) do
force.set_ammo_damage_modifier(k, v)
@ -111,8 +109,8 @@ function init_player_weapon_damage(force)
force.set_gun_speed_modifier(k, v)
end
end
function init_enemy_weapon_damage()
]]
local function init_enemy_weapon_damage()
local e_force = game.forces['enemy']
for k, v in pairs(enemy_ammo_starting_modifiers) do

View File

@ -1,6 +1,6 @@
local math_random = math.random
local Evolution = require 'modules.scrap_towny_ffa.evolution'
local Building = require 'modules.scrap_towny_ffa.building'
local Town_center = require 'modules.scrap_towny_ffa.town_center'
local Scrap = require 'modules.scrap_towny_ffa.scrap'
local unearthing_worm = require 'modules.scrap_towny_ffa.unearthing_worm'
local unearthing_biters = require 'modules.scrap_towny_ffa.unearthing_biters'
@ -8,29 +8,24 @@ local tick_tack_trap = require 'modules.scrap_towny_ffa.tick_tack_trap'
local function trap(entity)
-- check if within 32 blocks of market
if entity.type == 'tree' or Scrap.is_scrap(entity) then
if entity.type == 'tree' or Scrap.is_scrap(entity) and not Town_center.in_any_town(entity.position) then
if math_random(1, 1024) == 1 then
if not Building.near_town(entity.position, entity.surface, 32) then
tick_tack_trap(entity.surface, entity.position)
return
end
tick_tack_trap(entity.surface, entity.position)
end
if math_random(1, 256) == 1 then
if not Building.near_town(entity.position, entity.surface, 32) then
unearthing_worm(entity.surface, entity.position, Evolution.get_worm_evolution(entity))
end
unearthing_worm(entity.surface, entity.position, Evolution.get_worm_evolution(entity))
end
if math_random(1, 128) == 1 then
if not Building.near_town(entity.position, entity.surface, 32) then
unearthing_biters(entity.surface, entity.position, math_random(4, 8), Evolution.get_biter_evolution(entity))
end
unearthing_biters(entity.surface, entity.position, math_random(4, 8), Evolution.get_biter_evolution(entity))
end
end
end
local function on_player_mined_entity(event)
local entity = event.entity
trap(entity)
if entity and entity.valid then
trap(entity)
end
end
local Event = require 'utils.event'

View File

@ -6,10 +6,10 @@ local Scrap = require 'modules.scrap_towny_ffa.scrap'
-- loot chances and amounts for scrap entities
local entity_loot_chance = {
{name = 'advanced-circuit', chance = 5},
{name = 'advanced-circuit', chance = 15},
--{name = "artillery-shell", chance = 1},
{name = 'battery', chance = 20},
{name = 'cannon-shell', chance = 2},
{name = 'battery', chance = 15},
{name = 'cannon-shell', chance = 4},
--{name = "cluster-grenade", chance = 2},
{name = 'construction-robot', chance = 1},
{name = 'copper-cable', chance = 250},
@ -19,9 +19,9 @@ local entity_loot_chance = {
{name = 'destroyer-capsule', chance = 1},
{name = 'distractor-capsule', chance = 2},
{name = 'electric-engine-unit', chance = 2},
{name = 'electronic-circuit', chance = 200},
{name = 'electronic-circuit', chance = 150},
{name = 'empty-barrel', chance = 10},
{name = 'engine-unit', chance = 4},
{name = 'engine-unit', chance = 5},
{name = 'explosive-cannon-shell', chance = 2},
--{name = "explosive-rocket", chance = 3},
--{name = "explosive-uranium-cannon-shell", chance = 1},
@ -55,15 +55,16 @@ local entity_loot_chance = {
--{name = "uranium-fuel-cell", chance = 1},
--{name = "used-up-uranium-fuel-cell", chance = 1},
{name = 'water-barrel', chance = 10},
{name = 'tank', chance = 1},
{name = 'car', chance = 1}
{name = 'tank', chance = 2},
{name = 'car', chance = 3}
}
-- positive numbers can scale, 0 is disabled, and negative numbers are fixed absolute values
local entity_loot_amounts = {
['advanced-circuit'] = 2,
['advanced-circuit'] = 6,
--["artillery-shell"] = 0.3,
['battery'] = 2,
['cannon-shell'] = 2,
['cannon-shell'] = 4,
--["cluster-grenade"] = 0.3,
['construction-robot'] = 0.3,
['copper-cable'] = 24,
@ -81,13 +82,13 @@ local entity_loot_amounts = {
--["explosive-uranium-cannon-shell"] = 2,
['explosives'] = 4,
['green-wire'] = 8,
['grenade'] = 2,
['grenade'] = 6,
['heat-pipe'] = 1,
['heavy-oil-barrel'] = 3,
['iron-gear-wheel'] = 8,
['iron-plate'] = 16,
['iron-stick'] = 16,
['land-mine'] = 1,
['land-mine'] = 6,
['light-oil-barrel'] = 3,
['logistic-robot'] = 0.3,
['low-density-structure'] = 0.3,
@ -97,7 +98,7 @@ local entity_loot_amounts = {
['pipe'] = 8,
['pipe-to-ground'] = 1,
['plastic-bar'] = 4,
['processing-unit'] = 1,
['processing-unit'] = 2,
['red-wire'] = 8,
--["rocket"] = 2,
--["rocket-control-unit"] = 0.3,
@ -109,8 +110,8 @@ local entity_loot_amounts = {
--["uranium-fuel-cell"] = 0.3,
--["used-up-uranium-fuel-cell"] = 1,
['water-barrel'] = 3,
['tank'] = 1,
['car'] = 1
['tank'] = -1,
['car'] = -1
}
local scrap_raffle = {}
@ -141,9 +142,16 @@ local function on_player_mined_entity(event)
local scrap = scrap_raffle[math.random(1, size_of_scrap_raffle)]
local amount_bonus = (game.forces.enemy.evolution_factor * 2) + (game.forces.player.mining_drill_productivity_bonus * 2)
local r1 = math.ceil(entity_loot_amounts[scrap] * (0.3 + (amount_bonus * 0.3)))
local r2 = math.ceil(entity_loot_amounts[scrap] * (1.7 + (amount_bonus * 1.7)))
local amount = math.random(r1, r2)
local amount
if entity_loot_amounts[scrap] <= 0 then
amount = math.abs(entity_loot_amounts[scrap])
else
local m1 = 0.3 + (amount_bonus * 0.3)
local m2 = 1.7 + (amount_bonus * 1.7)
local r1 = math.ceil(entity_loot_amounts[scrap] * m1)
local r2 = math.ceil(entity_loot_amounts[scrap] * m2)
amount = math.random(r1, r2)
end
local player = game.players[event.player_index]
local inserted_count = player.insert({name = scrap, count = amount})

View File

@ -1048,7 +1048,7 @@ local function check_group_positions()
fill_tiles(group, 30)
remove_rocks(group)
remove_trees(group)
if ugp[group.group_number].index >= 4 then
if valid(group) and ugp[group.group_number].index >= 4 then
generated_units.unit_group_pos.positions[group.group_number] = nil
reform_group(group)
end

View File

@ -4,6 +4,7 @@ local math_floor = math.floor
local math_abs = math.abs
local get_noise = require 'utils.get_noise'
local Table = require 'modules.scrap_towny_ffa.table'
local Scrap = require 'modules.scrap_towny_ffa.scrap'
require 'modules.no_deconstruction_of_neutral_entities'
@ -75,6 +76,7 @@ local container_loot_chance = {
{name = 'cannon-shell', chance = 2},
{name = 'cliff-explosives', chance = 5},
--{name = "cluster-grenade", chance = 2},
{name = 'coin', chance = 1},
{name = 'construction-robot', chance = 1},
{name = 'copper-cable', chance = 250},
{name = 'copper-plate', chance = 500},
@ -128,6 +130,7 @@ local container_loot_amounts = {
['cannon-shell'] = 2,
['cliff-explosives'] = 2,
--["cluster-grenade"] = 0.3,
['coin'] = 2,
['construction-robot'] = 0.3,
['copper-cable'] = 24,
['copper-plate'] = 16,
@ -184,6 +187,10 @@ end
local size_of_scrap_raffle = #scrap_raffle
local function place_scrap(surface, position)
local ffatable = Table.get_table()
if ffatable.spaceships == nil then
ffatable.spaceships = {}
end
-- place turrets
if math_random(1, 700) == 1 then
if position.x ^ 2 + position.x ^ 2 > 4096 then
@ -195,17 +202,19 @@ local function place_scrap(surface, position)
end
end
-- place spaceship with loot
if math_random(1, 8192) == 1 then
local e = surface.create_entity({name = 'crash-site-spaceship', position = position, force = 'neutral'})
e.minable = true
local i = e.get_inventory(defines.inventory.chest)
if i then
for _ = 1, math_random(1, 5), 1 do
local loot = scrap_raffle[math_random(1, size_of_scrap_raffle)]
local amount = container_loot_amounts[loot]
local count = math_floor(amount * math_random(5, 35) * 0.1) + 1
i.insert({name = loot, count = count})
-- place market spaceship
if math_random(1, 4096) == 1 then
local spaceship = {}
if surface.can_place_entity({name = 'crash-site-spaceship-market', position = position, force = 'neutral'}) then
spaceship.market = surface.create_entity({name = 'crash-site-spaceship-market', position = position, force = 'neutral'})
spaceship.market.minable = false
spaceship.max_health = 300
spaceship.health = spaceship.max_health
if spaceship.market and spaceship.market.valid then
if ffatable.spaceships[position.x] == nil then
ffatable.spaceships[position.x] = {}
end
ffatable.spaceships[position.x][position.y] = spaceship
end
end
return
@ -294,12 +303,51 @@ end
local function on_chunk_generated(event)
--log("scrap_towny_ffa::on_chunk_generated")
local surface = event.surface
if (surface.name ~= 'nauvis') then
return
end
local seed = surface.map_gen_settings.seed
local left_top_x = event.area.left_top.x
local left_top_y = event.area.left_top.y
--log(" chunk = {" .. left_top_x/32 .. ", " .. left_top_y/32 .. "}")
local position
local noise
local chunk_position = event.position
--log('chunk_position = {' .. chunk_position.x .. ',' .. chunk_position.y .. '}')
if chunk_position.x >= -33 and chunk_position.x <= 32 and chunk_position.y >= -33 and chunk_position.y <= 32 then
if chunk_position.x == -33 or chunk_position.x == 32 or chunk_position.y == -33 or chunk_position.y == 32 then
local area = {{x = left_top_x, y = left_top_y}, {x = left_top_x + 31, y = left_top_y + 31}}
local entities = surface.find_entities(area)
for _, e in pairs(entities) do
e.destroy()
end
for x = 0, 31, 1 do
for y = 0, 31, 1 do
position = {x = left_top_x + x, y = left_top_y + y}
if not surface.get_tile(position).collides_with('water-tile') then
surface.set_tiles({{name = 'water-shallow', position = position}}, true)
end
end
end
return
end
end
if chunk_position.x < -33 or chunk_position.x > 32 or chunk_position.y < -33 or chunk_position.y > 32 then
local area = {{x = left_top_x, y = left_top_y}, {x = left_top_x + 31, y = left_top_y + 31}}
local entities = surface.find_entities(area)
for _, e in pairs(entities) do
e.destroy()
end
for x = 0, 31, 1 do
for y = 0, 31, 1 do
position = {x = left_top_x + x, y = left_top_y + y}
surface.set_tiles({{name = 'deepwater', position = position}}, true)
end
end
return
end
for x = 0, 31, 1 do
for y = 0, 31, 1 do
if math_random(1, 3) > 1 then

View File

@ -109,7 +109,7 @@ end
local function _shoot_at(ent, trgt)
ent.shooting_state = {
state = defines.shooting.shooting_selected,
state = defines.shooting.shooting_enemies,
position = trgt.position
}
end
@ -137,7 +137,11 @@ local function set_noise_hostile_hook(ent)
end
local function _do_job_seek_and_destroy_player(data)
local surf = data.surface
local active_surface = data.active_surface
local surf = game.get_surface(active_surface)
if not surf or not surf.valid then
return
end
local force = data.force
local players = game.connected_players
@ -188,8 +192,13 @@ local function _do_job_seek_and_destroy_player(data)
end
local function _do_job_attack_objects(data)
local surf = data.surface
local active_surface = data.active_surface
local surf = game.get_surface(active_surface)
if not surf or not surf.valid then
return
end
local force = data.force
local args = data.args
local position = data.position
if type(surf) == 'number' then
@ -241,7 +250,16 @@ local function _do_job_attack_objects(data)
if #closest ~= 0 then
target = CommonFunctions.get_closest_neighbour(agent.position, closest)
else
goto continue
if not args or not args.objects then
goto continue
end
if #args.objects == 0 then
_shoot_stop(agent)
goto continue
end
target = CommonFunctions.get_closest_neighbour(agent.position, args.objects)
end
if target == nil or not target.valid then
@ -311,10 +329,22 @@ Public.do_job = function(surf, command, args, force)
args = {}
end
if not surf and not surf.valid then
return
end
if command == Public.command.seek_and_destroy_player then
_do_job_seek_and_destroy_player(surf, force)
local data = {
active_surface = surf.index,
force = force
}
_do_job_seek_and_destroy_player(data)
elseif command == Public.command.attack_objects then
_do_job_attack_objects(surf, args)
local data = {
active_surface = surf.index,
args = args
}
_do_job_attack_objects(data)
end
end

View File

@ -25,7 +25,7 @@ function get_game_version()
end
function is_loaded(module)
local res = package.loaded[module]
local res = _G.package.loaded[module]
if res then
return res
else

View File

@ -1,9 +1,12 @@
local Global = require 'utils.global'
local Event = require 'utils.event'
local Public = {}
local this = {
created_items = {},
respawn_items = {},
disabled = false,
skip_intro = true,
chart_distance = 0,
disable_crashsite = true,
@ -74,6 +77,9 @@ local on_player_created = function(event)
if not this.modded then
return
end
if this.disabled then
return
end
local player = game.get_player(event.player_index)
util.insert_safe(player, this.created_items)
@ -103,6 +109,9 @@ local on_player_respawned = function(event)
if not this.modded then
return
end
if this.disabled then
return
end
local player = game.players[event.player_index]
util.insert_safe(player, this.respawn_items)
end
@ -111,6 +120,9 @@ local on_cutscene_waypoint_reached = function(event)
if not this.modded then
return
end
if this.disabled then
return
end
if not crash_site.is_crash_site_cutscene(event) then
return
end
@ -131,6 +143,10 @@ local skip_crash_site_cutscene = function(event)
return
end
if this.disabled then
return
end
if event.player_index ~= 1 then
return
end
@ -154,6 +170,10 @@ local on_cutscene_cancelled = function(event)
return
end
if this.disabled then
return
end
local player = game.get_player(event.player_index)
if player.gui.screen.skip_cutscene_label then
player.gui.screen.skip_cutscene_label.destroy()
@ -208,6 +228,25 @@ if not remote.interfaces['freeplay'] then
remote.add_interface('freeplay', freeplay_interface)
end
function Public.get(key)
if key then
return this[key]
else
return this
end
end
function Public.set(key, value)
if key and (value or value == false) then
this[key] = value
return this[key]
elseif key then
return this[key]
else
return this
end
end
Event.on_init(
function()
local game_has_mods = is_game_modded()
@ -240,3 +279,5 @@ Event.add(defines.events.on_player_respawned, on_player_respawned)
Event.add(defines.events.on_cutscene_waypoint_reached, on_cutscene_waypoint_reached)
Event.add('crash-site-skip-cutscene', skip_crash_site_cutscene)
Event.add(defines.events.on_cutscene_cancelled, on_cutscene_cancelled)
return Public

View File

@ -116,7 +116,13 @@ local noises = {
{modifier = 0.004, weight = 1},
{modifier = 0.02, weight = 0.05}
},
['journey_swamps'] = {{modifier = 0.02, weight = 1}, {modifier = 0.04, weight = 0.35}, {modifier = 0.1, weight = 0.08}},
['scrap_towny_ffa'] = {
{modifier = 0.005, weight = 1},
{modifier = 0.025, weight = 0.25},
{modifier = 0.1, weight = 0.125},
{modifier = 0.01, weight = 0.025}
},
['journey_swamps'] = {{modifier = 0.02, weight = 1}, {modifier = 0.04, weight = 0.35}, {modifier = 0.1, weight = 0.08}}
}
--returns a float number between -1 and 1

View File

@ -6,7 +6,7 @@ local this = {
prevent_spam = {}, -- the default table where all player indexes will be stored
default_tick = 10, -- this defines the default tick to check whether or not a user is spamming a button.
debug_text = false,
debug_spam = true
debug_spam = false
}
local main_text = '[Spam Info] '