1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-20 03:29:47 +02:00

Expanse fixes + updates.

This commit is contained in:
hanakocz 2022-08-08 02:50:40 +02:00
parent 65908c5331
commit 8647526ce0
3 changed files with 295 additions and 20 deletions

View File

@ -16,7 +16,8 @@ map_info_text=This is a harsh world, the heat is unbearable and the sand is shar
[expanse]
map_info_main_caption=-- E x p a n s e --
map_info_sub_caption=
map_info_text=The blue chests are hungry.\nFeed them and they will reward you with more land.\n\nThe friendly infini tree will provide you with all the wood you ever wanted.\nThe everlasting rock with be happy to provide resources for you.\n\nIf you find yourself stuck, put a reroll token, the small plane toy, in the chest to get a new offer.\nUnlocking chests may drop additional tokens.
map_info_text=The blue chests are hungry.\nFeed them and they will reward you with more land.\n\nThe friendly infini tree will provide you with all the wood you ever wanted.\nThe everlasting rock with be happy to provide resources for you.\n\nIf you find yourself stuck, put a reroll token, the COIN, in the chest to get a new offer.\nUnlocking chests may drop additional tokens.\nBiters might invade your lands, we managed to mark the danger sites, but biters might choose some of them randomly.\nMining research now increases inventory size.
biters_invasion_warning=Warning! Biters are aproaching your positions and will attack in about __1__ seconds! We detected __2__ groups aproaching some of the marked positions!
[fish_defender]
map_info_main_caption=--Fish Defender--

View File

@ -1,4 +1,5 @@
local Price_raffle = require 'maps.expanse.price_raffle'
local BiterRaffle = require 'functions.biter_raffle'
local Public = {}
local ores = {'copper-ore', 'iron-ore', 'stone', 'coal'}
@ -24,12 +25,12 @@ local function reward_tokens(expanse, entity)
if chance > 0 then
chance = math.floor(chance * 1000)
if math.random(1, 1000) <= chance then
entity.surface.spill_item_stack(entity.position, {name = 'small-plane', count = 1}, true, nil, false)
entity.surface.spill_item_stack(entity.position, {name = 'coin', count = 1}, true, nil, false)
end
end
if count > 0 then
for _ = 1, count, 1 do
entity.surface.spill_item_stack(entity.position, {name = 'small-plane', count = 1}, true, nil, false)
entity.surface.spill_item_stack(entity.position, {name = 'coin', count = 1}, true, nil, false)
end
end
end
@ -56,7 +57,7 @@ local function get_cell_value(expanse, left_top)
end
local distance = math.sqrt(left_top.x ^ 2 + left_top.y ^ 2)
value = value * (distance * expanse.price_distance_modifier)
value = value * ((distance ^ 1.1) * expanse.price_distance_modifier)
local ore_modifier = distance * (expanse.price_distance_modifier / 20)
if ore_modifier > expanse.max_ore_price_modifier then
ore_modifier = expanse.max_ore_price_modifier
@ -126,6 +127,142 @@ local function is_container_position_valid(expanse, position)
return true
end
local function create_costs_render(entity, name, offset)
local id = rendering.draw_sprite{
sprite = 'virtual-signal/signal-grey',
surface = entity.surface,
target = entity,
x_scale = 1.1,
y_scale = 1.1,
render_layer = '190',
target_offset = {offset, -1.5},
only_in_alt_mode = true
}
local id2 = rendering.draw_sprite{
sprite = 'item/' ..name,
surface = entity.surface,
target = entity,
x_scale = 0.75,
y_scale = 0.75,
render_layer = '191',
target_offset = {offset, -1.5},
only_in_alt_mode = true
}
return {id, id2}
end
local function remove_one_render(container, key)
if rendering.is_valid(container.price[key].render[1]) then
rendering.destroy(container.price[key].render[1])
end
if rendering.is_valid(container.price[key].render[2]) then
rendering.destroy(container.price[key].render[2])
end
end
local function remove_old_renders(container)
for key, _ in pairs(container.price) do
remove_one_render(container, key)
end
end
function Public.invasion_warn(event)
local seconds = (120 * 60 - event.delay) / 60
game.print({'expanse.biters_invasion_warning', seconds, event.size}, {r = 0.88, g = 0.22, b = 0.22})
end
function Public.invasion_detonate(event)
local surface = event.surface
local position = event.position
local entities_close = surface.find_entities_filtered{position = position, radius = 8}
for _, entity in pairs(entities_close) do
if entity.valid then
entity.die('enemy')
end
end
local entities_nearby = surface.find_entities_filtered{position = position, radius = 16}
for _, entity in pairs(entities_nearby) do
if entity.valid and entity.is_entity_with_health then
entity.damage(entity.prototype.max_health * 0.75, 'enemy')
end
end
surface.create_entity({name = 'nuke-explosion', position = position})
end
function Public.invasion_trigger(event)
local surface = event.surface
local position = event.position
local round = event.round
local evolution = game.forces.enemy.evolution_factor
local biters = {}
for i = 1, 5 + math.floor(30 * evolution) + round * 5, 1 do
local biter_roll = BiterRaffle.roll('mixed', evolution)
local free_pos = surface.find_non_colliding_position(biter_roll, position, 12, 0.05)
biters[#biters + 1] = surface.create_entity({name = biter_roll, position = free_pos or position, force = 'enemy'})
end
local group = surface.create_unit_group{position = position, force = 'enemy'}
for _, biter in pairs(biters) do
group.add_member(biter)
end
group.set_command({type = defines.command.attack_area, destination = position, radius = 80, distraction = defines.distraction.by_anything})
group.start_moving()
local worm_roll = BiterRaffle.roll('worm', evolution)
for i = 1, 3 + math.floor(7 * evolution), 1 do
local worm_pos = surface.find_non_colliding_position(worm_roll, {x = position.x + math.random(-6,6), y = position.y + math.random(-6,6)}, 12, 0.1)
if worm_pos then
surface.create_entity({name = worm_roll, position = worm_pos, force = 'enemy'})
end
end
local nest = {'biter-spawner', 'biter-spawner', 'biter-spawner', 'spitter-spawner'}
local nest_roll = nest[math.random(1, 4)]
local nest_pos = surface.find_non_colliding_position(nest_roll, position, 12, 0.1)
if nest_pos then
surface.create_entity({name = nest_roll, position = nest_pos, force = 'enemy'})
end
end
local function schedule_detonation(expanse, surface, position)
table.insert(expanse.schedule, {tick = game.tick + 120 * 60, event = 'invasion_detonate', parameters = {surface = surface, position = position}})
end
local function schedule_warning(expanse, size, delay)
table.insert(expanse.schedule, {tick = game.tick + 2 * 60 + delay, event = 'invasion_warn', parameters = {size = size, delay = delay}})
end
local function schedule_biters(expanse, surface, position, delay, round)
table.insert(expanse.schedule, {tick = game.tick + delay + 120 * 60, event = 'invasion_trigger', parameters = {surface = surface, position = position, round = round}})
end
local function plan_invasion(expanse, evolution)
local candidates = expanse.invasion_candidates
table.shuffle_table(candidates)
local size = 1 + math.floor(evolution * 4)
schedule_warning(expanse, size, 0)
schedule_warning(expanse, size, 60 * 60)
schedule_warning(expanse, size, 90 * 60)
local rounds = 4 + math.random(1, 4)
for i = 1, size, 1 do
local surface = candidates[i].surface
local position = candidates[i].position
schedule_detonation(expanse, surface, position)
for ii = 1, rounds, 1 do
schedule_biters(expanse, surface, position, 120 + (ii - 1) * 300, ii)
end
rendering.set_time_to_live(candidates[i].render, 122 * 60 + rounds * 300)
end
for j = size + 1, #candidates, 1 do
rendering.set_time_to_live(candidates[j].render, 122 * 60)
end
expanse.invasion_candidates = {}
end
function Public.check_invasion(expanse)
local evolution = game.forces.enemy.evolution_factor
if #expanse.invasion_candidates >= 3 + math.floor(evolution * 10) then
plan_invasion(expanse, evolution)
end
end
function Public.expand(expanse, left_top)
expanse.grid[tostring(left_top.x .. '_' .. left_top.y)] = true
@ -177,15 +314,15 @@ function Public.expand(expanse, left_top)
local a = math.floor(expanse.square_size * 0.5)
for x = 1, 3, 1 do
for y = 1, 3, 1 do
surface.set_tiles({{name = 'water', position = {a + x, a + y - 2}}}, true)
surface.set_tiles({{name = 'water', position = {a + x + 2, a + y - 2}}}, true)
end
end
surface.create_entity({name = 'crude-oil', position = {a - 3, a}, amount = 1500000})
surface.create_entity({name = 'crude-oil', position = {a - 5, a}, amount = 1500000})
surface.create_entity({name = 'rock-big', position = {a, a}})
surface.create_entity({name = 'tree-0' .. math.random(1, 9), position = {a, a - 1}})
surface.spill_item_stack({a, a + 2}, {name = 'small-plane', count = 1}, false, nil, false)
surface.spill_item_stack({a + 0.5, a + 2.5}, {name = 'small-plane', count = 1}, false, nil, false)
surface.spill_item_stack({a - 0.5, a + 2.5}, {name = 'small-plane', count = 1}, false, nil, false)
surface.create_entity({name = 'tree-0' .. math.random(1, 9), position = {a, a - 3}})
surface.spill_item_stack({a, a + 2}, {name = 'coin', count = 1}, false, nil, false)
surface.spill_item_stack({a + 0.5, a + 2.5}, {name = 'coin', count = 1}, false, nil, false)
surface.spill_item_stack({a - 0.5, a + 2.5}, {name = 'coin', count = 1}, false, nil, false)
for x = 0, square_size, 1 do
for y = 0, square_size, 1 do
@ -218,8 +355,10 @@ local function init_container(expanse, entity)
end
local price = {}
local offset = -2
for k, v in pairs(item_stacks) do
table.insert(price, {name = k, count = v})
table.insert(price, {name = k, count = v, render = create_costs_render(entity, k, offset)})
offset = offset + 1
end
local containers = expanse.containers
@ -235,14 +374,21 @@ function Public.set_container(expanse, entity)
end
local container = expanse.containers[entity.unit_number]
if not container or not container.entity or not container.entity.valid then
expanse.containers[entity.unit_number] = nil
return
end
local inventory = container.entity.get_inventory(defines.inventory.chest)
if not inventory.is_empty() then
local contents = inventory.get_contents()
if contents['small-plane'] then
local count_removed = inventory.remove({name = 'small-plane', count = 1})
if contents['coin'] then
local count_removed = inventory.remove({name = 'coin', count = 1})
if count_removed > 0 then
expanse.cost_stats['coin'] = (expanse.cost_stats['coin'] or 0) + count_removed
script.raise_event(expanse.events.gui_update, {item = 'coin'})
remove_old_renders(container)
init_container(expanse, entity)
container = expanse.containers[entity.unit_number]
game.print("The hungry chest has renewed it's offer! [gps=" .. math.floor(entity.position.x) .. ',' .. math.floor(entity.position.y) .. ',expanse]')
@ -251,9 +397,13 @@ function Public.set_container(expanse, entity)
end
for key, item_stack in pairs(container.price) do
local count_removed = inventory.remove(item_stack)
local name = item_stack.name
local count_removed = inventory.remove({name = name, count = item_stack.count})
container.price[key].count = container.price[key].count - count_removed
expanse.cost_stats[name] = (expanse.cost_stats[name] or 0) + count_removed
script.raise_event(expanse.events.gui_update, {item = name})
if container.price[key].count <= 0 then
remove_one_render(container, key)
table.remove(container.price, key)
end
end

View File

@ -5,12 +5,17 @@ local cell_size = 15 -- size of each territory to unlock
local chance_to_receive_token = 0.35 -- chance of a hungry chest, dropping a token after unlocking, can be above 1 for multiple
require 'modules.satellite_score'
require 'modules.backpack_research'
local Event = require 'utils.event'
local Functions = require 'maps.expanse.functions'
local GetNoise = require 'utils.get_noise'
local Global = require 'utils.global'
local Map_info = require 'modules.map_info'
local Gui = require 'utils.gui'
local format_number = require 'util'.format_number
local Random = require 'maps.chronosphere.random'
local Autostash = require 'modules.autostash'
local expanse = {}
Global.register(
@ -19,6 +24,31 @@ Global.register(
expanse = tbl
end
)
expanse.events = {
gui_update = Event.generate_event_name('expanse_gui_update'),
invasion_warn = Event.generate_event_name('invasion_warn'),
invasion_detonate = Event.generate_event_name('invasion_detonate'),
invasion_trigger = Event.generate_event_name('invasion_trigger'),
}
local main_button_name = Gui.uid_name()
local main_frame_name = Gui.uid_name()
local function create_button(player)
if not player.gui.top[main_button_name] then
local b =
player.gui.top.add(
{
type = 'sprite-button',
name = main_button_name,
sprite = 'item/logistic-chest-requester',
tooltip = 'Show Expanse statistics!'
}
)
b.style.minimal_height = 38
b.style.maximal_height = 38
end
end
local function set_nauvis()
local surface = game.surfaces[1]
@ -43,6 +73,11 @@ end
local function reset()
expanse.grid = {}
expanse.containers = {}
expanse.cost_stats = {}
expanse.invasion_candidates = {}
expanse.schedule = {}
expanse.size = 1
Autostash.insert_into_furnace(true)
local map_gen_settings = {
['water'] = 0,
@ -171,6 +206,21 @@ local function container_opened(event)
local colored_player_name =
table.concat({'[color=', player.color.r * 0.6 + 0.35, ',', player.color.g * 0.6 + 0.35, ',', player.color.b * 0.6 + 0.35, ']', player.name, '[/color]'})
game.print(colored_player_name .. ' unlocked new grounds! [gps=' .. math.floor(expansion_position.x) .. ',' .. math.floor(expansion_position.y) .. ',expanse]')
expanse.size = (expanse.size or 1) + 1
if math.random(1, 4) == 1 then
if player.surface.count_tiles_filtered({position = expansion_position, radius = 6, collision_mask = 'water-tile'}) > 40 then
return
end
local render = rendering.draw_sprite{
sprite = 'utility/danger_icon',
surface = player.surface,
target = expansion_position,
x_scale = 2,
y_scale = 2
}
table.insert(expanse.invasion_candidates, {surface = player.surface, position = expansion_position, render = render})
Functions.check_invasion(expanse)
end
end
end
@ -200,8 +250,8 @@ local function infini_tree(entity)
return
end
local a = math.floor(expanse.square_size * 0.5)
if entity.position.x == a and entity.position.y == a - 1 then
entity.surface.create_entity({name = 'tree-0' .. math.random(1, 9), position = {a, a - 1}})
if entity.position.x == a and entity.position.y == a - 3 then
entity.surface.create_entity({name = 'tree-0' .. math.random(1, 9), position = {a, a - 3}})
end
end
@ -220,9 +270,10 @@ local function on_player_joined_game(event)
local surface = game.surfaces.expanse
player.teleport(surface.find_non_colliding_position('character', {expanse.square_size * 0.5, expanse.square_size * 0.5}, 32, 0.5), surface)
end
create_button(player)
end
local function on_player_left_game(event)
local function on_pre_player_left_game(event)
local player = game.players[event.player_index]
if not player.character then
return
@ -234,10 +285,10 @@ local function on_player_left_game(event)
if not inventory then
return
end
local removed_count = inventory.remove({name = 'small-plane', count = 999})
local removed_count = inventory.remove({name = 'coin', count = 999999})
if removed_count > 0 then
for _ = 1, removed_count, 1 do
player.surface.spill_item_stack(player.position, {name = 'small-plane', count = 1}, false, nil, false)
player.surface.spill_item_stack(player.position, {name = 'coin', count = 1}, false, nil, false)
end
game.print(player.name .. ' dropped their tokens! [gps=' .. math.floor(player.position.x) .. ',' .. math.floor(player.position.y) .. ',' .. player.surface.name .. ']')
end
@ -285,12 +336,85 @@ local function on_init()
reset()
end
local function on_tick()
if not next(expanse.schedule) then return end
for index, stuff in pairs(expanse.schedule) do
if game.tick >= stuff.tick then
script.raise_event(expanse.events[stuff.event], stuff.parameters)
expanse.schedule[index] = nil
end
end
end
local function resource_stats(parent, name, count)
local button = parent.add({type = 'sprite-button', name = name .. '_sprite', sprite = 'item/' .. name, enabled = false})
local label = parent.add({type = 'label', name = name .. '_label', caption = format_number(tonumber(count), true), tooltip = count})
label.style.width = 40
return button, label
end
local function create_main_frame(player)
local frame = player.gui.screen.add({type = 'frame', name = main_frame_name, caption = 'Expanse hungry chest stats', direction = 'vertical'})
frame.location = {x = 10, y = 40}
frame.style.maximal_height = 600
local evo = game.forces.enemy.evolution_factor
frame.add({type = 'label', name = 'size', caption = 'Total size unlocked: ' .. expanse.size or 1})
frame.add({type = 'label', name = 'biters', caption = 'Biter attack: ' .. 3 + math.floor(7 * evo) .. ' positions, ' .. 1 + math.floor(evo * 4) .. ' armies'})
local scroll = frame.add({type = 'scroll-pane', name = 'scroll_pane', horizontal_scroll_policy = 'never', vertical_scroll_policy = 'auto-and-reserve-space'})
local frame_table = scroll.add({type = 'table', name = 'resource_stats', column_count = 8})
for name, count in Random.spairs(expanse.cost_stats, function(t,a,b) return t[a] > t[b] end) do
resource_stats(frame_table, name, count)
end
end
local function update_resource_gui(event)
for _, player in pairs(game.connected_players) do
if player.gui.screen[main_frame_name] then
local frame = player.gui.screen[main_frame_name]
local evo = game.forces.enemy.evolution_factor
frame['size'].caption = 'Total size unlocked: ' .. expanse.size or 1
frame['biters'].caption = 'Biter attack: ' .. 3 + math.floor(evo * 10) .. ' positions, ' .. 1 + math.floor(evo * 4) .. ' armies'
local frame_table = frame['scroll_pane']['resource_stats']
local count = expanse.cost_stats[event.item] or 0
if not frame_table[event.item .. '_label'] then
resource_stats(frame_table, event.item, count)
else
frame_table[event.item .. '_label'].caption = format_number(tonumber(count), true)
frame_table[event.item .. '_label'].tooltip = count
end
end
end
end
local function on_gui_click(event)
local element = event.element
if not element.valid then
return
end
local name = element.name
if name == main_button_name then
local player = game.players[event.player_index]
if player.gui.screen[main_frame_name] then
player.gui.screen[main_frame_name].destroy()
else
create_main_frame(player)
end
end
end
Event.on_init(on_init)
Event.on_nth_tick(60, on_tick)
Event.add(defines.events.on_chunk_generated, on_chunk_generated)
Event.add(defines.events.on_entity_died, infini_resource)
Event.add(defines.events.on_gui_closed, on_gui_closed)
Event.add(defines.events.on_gui_opened, on_gui_opened)
Event.add(defines.events.on_gui_click, on_gui_click)
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_left_game, on_player_left_game)
Event.add(defines.events.on_pre_player_left_game, on_pre_player_left_game)
Event.add(defines.events.on_pre_player_mined_item, infini_resource)
Event.add(defines.events.on_robot_pre_mined, infini_resource)
Event.add(expanse.events.gui_update, update_resource_gui)
Event.add(expanse.events.invasion_warn, Functions.invasion_warn)
Event.add(expanse.events.invasion_detonate, Functions.invasion_detonate)
Event.add(expanse.events.invasion_trigger, Functions.invasion_trigger)