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

Merge pull request #112 from cogito123/planet_prison

Add planet prison 1.0.0
This commit is contained in:
MewMew 2020-01-07 01:38:36 +01:00 committed by GitHub
commit 86c37d173a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2457 additions and 3 deletions

View File

@ -111,6 +111,7 @@ require "modules.autostash"
--require "maps.rainbow_road"
--require "maps.cube"
--require "maps.forest_circle"
--require "maps.planet_prison"
-----------------------------
---- more modules here ----

868
maps/planet_prison.lua Normal file
View File

@ -0,0 +1,868 @@
global.this = {}
local _global = require("utils.global")
local _evt = require("utils.event")
local _map = require("tools.map_functions")
local _common = require("planet_prison.mod.common")
local _layers = require("planet_prison.mod.layers")
local _ai = require("planet_prison.mod.ai")
local _bp = require("planet_prison.mod.bp")
global.this._config = require("planet_prison.config")
global.this.maps = {
{
name = "Flooded metropolia",
height = 2000,
width = 2000,
water = 1,
terrain_segmentation = 8,
property_expression_names = {
moisture = 0,
temperature = 30.
},
starting_area = "none",
autoplace_controls = {
["iron-ore"] = {
frequency = 0,
},
["copper-ore"] = {
frequency = 0,
},
["stone"] = {
frequency = 0,
},
["coal"] = {
frequency = 0,
},
["crude-oil"] = {
frequency = 10,
size = 1,
},
["trees"] = {
frequency = 4,
},
["enemy-base"] = {
frequency = 0,
}
},
}
}
global.this.entities_cache = nil
global.this.surface = nil
global.this.last_friend = nil
local function pick_map()
return global.this.maps[_common.rand_range(1, #global.this.maps)]
end
local function find_force(name)
for _, f in pairs(game.forces) do
if f.name == name then
return f
end
end
return nil
end
local function init_player_ship_bp(entity, player)
entity.force = player.force
if entity.name == "crash-site-chest-1" then
for _, stack in pairs(global.this._config.player_ship_loot) do
entity.insert(stack)
end
end
if entity.name == "crash-site-generator" then
entity.electric_buffer_size = 2000
entity.power_production = 2000
end
end
global.this.events = {
merchant = {
alive = false,
moving = false,
spawn_tick = 0,
embark_tick = 0,
position = { x = 0, y = 0 },
offer = global.this._config.merchant_offer,
}
}
local function init_merchant_bp(entity, _)
entity.force = "merchant"
entity.rotatable = false
entity.minable = false
if entity.name ~= "market" then
entity.operable = false
else
for _, entry in pairs(global.this.events.merchant.offer) do
entity.add_market_item(entry)
end
end
end
local function noise_hostile_hook(ent)
ent.force = "enemy"
if ent.name == "character" then
ent.insert({name="pistol", count=1})
ent.insert({name="firearm-magazine", count=20})
else
ent.insert({name="firearm-magazine", count=200})
end
end
local function noise_set_neutral_hook(ent)
ent.force = "neutral"
end
global.this.bp = {
player_ship = require("planet_prison.bp.player_ship"),
merchant = require("planet_prison.bp.merchant")
}
local function init_game()
global.this.surface = game.create_surface("arena", pick_map())
global.this.surface.min_brightness = 0
global.this.surface.ticks_per_day = 25000 * 4
global.this.perks = {}
global.this.events.merchant.spawn_tick = game.tick + 5000
game.map_settings.pollution.enabled = false
game.map_settings.enemy_evolution.enabled = false
game.difficulty_settings.technology_price_multiplier = 0.1
game.difficulty_settings.research_queue_setting = "always"
_layers.init()
_layers.set_collision_mask({"water-tile"})
_layers.add_noise_layer("LuaTile", "concrete", {"concrete"}, 0.3, 0.2)
_layers.add_noise_layer("LuaTile", "stones", {"stone-path"}, 0.2, 0.4)
_layers.add_noise_layer("LuaTile", "shallows", {"water-shallow"}, 0.5, 0.005)
_layers.add_noise_layer("LuaEntity", "scrap", {"mineable-wreckage"}, 0.5, 0.1)
_layers.add_noise_layer("LuaEntity", "walls", {"stone-wall"}, 0.5, 0.09)
_layers.add_noise_layer("LuaEntity", "hostile", {"character",
"gun-turret"}, 0.92, 0.99)
_layers.add_noise_layer("LuaEntity", "structures", {"big-electric-pole",
"medium-electric-pole"}, 0.9, 0.9)
_layers.add_noise_layer_hook("structures", noise_set_neutral_hook)
_layers.add_noise_layer_hook("walls", noise_set_neutral_hook)
_layers.add_noise_layer_hook("hostile", noise_hostile_hook)
_bp.push_blueprint("player_ship", global.this.bp.player_ship)
_bp.set_blueprint_hook("player_ship", init_player_ship_bp)
_bp.push_blueprint("merchant", global.this.bp.merchant)
_bp.set_blueprint_hook("merchant", init_merchant_bp)
end
local function do_spawn_point(player)
local point = {
x = _common.get_axis(player.position, "x"),
y = _common.get_axis(player.position, "y") - 2
}
local instance = _bp.build(player.surface, "player_ship", point, player)
_layers.push_excluding_bounding_box(instance.bb)
end
local function get_non_obstructed_position(s, radius)
while true do
local chunk = s.get_random_chunk()
chunk.x = chunk.x * 32
chunk.y = chunk.y * 32
for x = 1, radius do
for y = 1, radius do
local tile = s.get_tile({chunk.x + x, chunk.y + y})
if not tile.collides_with("ground-tile") then
goto continue
end
end
end
local search_info = {
position = chunk,
radius = radius,
force = {"neutral", "enemy"},
invert = true
}
local ents = s.find_entities_filtered(search_info)
if not ents then
return chunk
end
if #ents == 0 then
return chunk
end
if ents[1].name == "character" then
return chunk
end
::continue::
end
end
local function redraw_gui(p)
p.gui.left.clear()
local merchant = global.this.events.merchant
local perks = global.this.perks[p.tag]
local chat_type = "Global chat"
if not perks.chat_global then
chat_type = "Buddies chat"
end
local button = {
type = "button",
name = "manual_toggle",
caption = "Manual"
}
p.gui.left.add(button)
button = {
type = "button",
name = "chat_toggle",
caption = chat_type,
}
p.gui.left.add(button)
if merchant.alive and not perks.minimap then
button = {
type = "button",
name = "merchant_find",
caption = "Merchant",
}
p.gui.left.add(button)
end
if perks.flashlight then
button = {
type = "button",
name = "flashlight_toggle",
caption = "Toggle flashlight"
}
p.gui.left.add(button)
end
end
local function print_merchant_position(player)
local position = global.this.events.merchant.position
local perks = global.this.perks[player.tag]
if not perks.minimap then
player.print(string.format(">> You were able to spot him %s from your location",
_common.get_readable_direction(player.position, position)))
else
player.print(string.format(">> You received a broadcast with [gps=%d,%d] coordinates", position.x, position.y))
end
end
local function on_gui_click(e)
local elem = e.element
local p = game.players[e.player_index]
local perks = global.this.perks[p.tag]
if elem.name == "chat_toggle" then
if perks.chat_global then
elem.caption = "Buddies chat"
perks.chat_global = false
else
elem.caption = "Global chat"
perks.chat_global = true
end
elseif elem.name == "flashlight_toggle" then
if perks.flashlight_enable then
perks.flashlight_enable = false
p.character.disable_flashlight()
else
perks.flashlight_enable = true
p.character.enable_flashlight()
end
elseif elem.name == "merchant_find" then
print_merchant_position(p)
elseif elem.name == "manual_toggle" then
local children = p.gui.center.children
if #children >= 1 then
p.gui.center.clear()
return
end
local text_box = {
type = "text-box",
text = global.this._config.manual
}
text_box = p.gui.center.add(text_box)
text_box.style.minimal_width = 512
text_box.read_only = true
text_box.word_wrap = true
end
end
local function init_player(p)
p.teleport({0, 0}, "arena")
local s = p.surface
local position = get_non_obstructed_position(s, 10)
p.teleport(position, "arena")
p.name = "inmate"
p.tag = string.format("[%d]", _common.rand_range(1000, 9999))
p.force = game.create_force(p.tag)
p.force.set_friend("neutral", true)
global.this.perks[p.tag] = {
flashlight = false,
flashlight_enabled = false,
minimap = false,
chat_global = true,
}
local merch = find_force("merchant")
if merch then
p.force.set_friend(merch, true)
merch.set_friend(p.force, true)
end
p.force.research_queue_enabled = true
for _, tech in pairs(p.force.technologies) do
for name, status in pairs(global.this._config.technologies) do
if tech.name == name then
tech.researched = status
tech.enabled = status
end
end
end
p.minimap_enabled = false
redraw_gui(p)
do_spawn_point(p)
end
local function on_player_joined_game(e)
local p = game.players[e.player_index]
init_player(p)
end
local function _build_merchant_bp(surf, position)
local instance = _bp.build(surf, "merchant", position, nil)
_layers.push_excluding_bounding_box(instance.bb)
end
local function _remove_merchant_bp(surf)
local refs = _bp.get_references("merchant")
local bb = _bp.reference_get_bounding_box(refs[1])
_layers.remove_excluding_bounding_box(bb)
_bp.destroy_references(surf, "merchant")
global.this.events.merchant.position = {
x = 0,
y = 0
}
end
local function spawn_merchant(s)
local merchant = global.this.events.merchant
local position = get_non_obstructed_position(s, 10)
local merch
if not merchant.moving then
merch = game.create_force("merchant")
else
merch = find_force("merchant")
end
merchant.position = position
merchant.alive = true
merchant.moving = false
merchant.embark_tick = game.tick + 90000
_build_merchant_bp(s, position)
s.print(">> Merchant appeared in the area")
for _, p in pairs(game.players) do
p.force.set_friend(merch, true)
merch.set_friend(p.force, true)
print_merchant_position(p)
redraw_gui(p)
end
end
local function embark_merchant(s)
global.this.events.merchant.alive = false
global.this.events.merchant.moving = true
global.this.events.merchant.spawn_tick = game.tick + 10000
s.print(">> Merchant is moving to new location")
_remove_merchant_bp(s)
for _, player in pairs(game.players) do
redraw_gui(player)
end
end
local function merchant_event(s)
local e = global.this.events
local m = e.merchant
if not m.alive and m.spawn_tick <= game.tick then
spawn_merchant(s)
end
if m.alive and not m.moving and m.embark_tick <= game.tick then
embark_merchant(s)
end
end
local function cause_event(s)
merchant_event(s)
end
local function unlink_old_blueprints(name)
local query = {
timestamp = game.tick,
}
local refs = _bp.unlink_references_filtered(name, query)
for _, ref in pairs(refs) do
local bb = _bp.reference_get_bounding_box(ref)
_layers.remove_excluding_bounding_box(bb)
end
end
-- global.this.profiler = nil
local function on_tick()
-- if not global.this.profiler then
-- global.this.profiler = game.create_profiler()
-- end
local s = global.this.surface
if not s then
log("on_tick: surface empty!")
return
end
if not s.is_chunk_generated then
log("on_tick: is_chunk_generated nil, map save?")
return
end
if not s.is_chunk_generated({0, 0}) then
return
end
local surf = global.this.surface
-- global.this.profiler.reset()
if game.tick % 4 == 0 then
_ai.do_job(surf, _ai.command.seek_and_destroy_player)
end
if game.tick % 10000 == 0 then
unlink_old_blueprints("player_ship")
end
_layers.do_job(surf, 64)
cause_event(s)
-- global.this.profiler.stop()
-- log(global.this.profiler)
end
local function make_ore_patch(e)
if _common.rand_range(1, 60) ~= 1 then
return
end
local surf = e.surface
local point = e.area.left_top
_map.draw_entity_circle(point, "stone", surf, 6, true, 1000000)
_map.draw_entity_circle(point, "coal", surf, 12, true, 1000000)
_map.draw_entity_circle(point, "copper-ore", surf, 18, true, 1000000)
_map.draw_entity_circle(point, "iron-ore", surf, 24, true, 1000000)
_map.draw_noise_tile_circle(point, "water", surf, 4)
end
local function on_chunk_generated(e)
make_ore_patch(e)
_layers.push_bounding_box(e.area)
end
local function on_player_mined_entity(e)
if e.entity.name ~= "mineable-wreckage" then
return
end
local candidates = {}
local chance = _common.rand_range(0, 1000)
for name, attrs in pairs(global.this._config.wreck_loot) do
local prob = attrs.rare * 100
if prob < chance then
local cand = {
name = name,
count = _common.rand_range(attrs.count[1], attrs.count[2]),
}
table.insert(candidates, cand)
end
end
local count = #candidates
if count == 0 then
return
end
local cand = candidates[_common.rand_range(1, count)]
e.buffer.insert(cand)
end
local function on_player_died(e)
local index = e.player_index
if not index then
return -- banned/kicked somewhere else
end
local p = game.players[index]
game.merge_forces(p.tag, "neutral")
global.this.perks[p.tag] = {
flashlight = false,
flashlight_enabled = false,
minimap = false,
chat_global = true,
}
end
local function on_player_respawned(e)
local p = game.players[e.player_index]
init_player(p)
end
local function on_player_dropped_item(e)
if not global.this.last_friend then
global.this.last_friend = {}
end
local p = game.players[e.player_index]
local ent = e.entity
if ent.stack.name == "raw-fish" then
local ent_list = p.surface.find_entities_filtered({
name = p.character.name,
position = ent.position,
limit = 1,
radius = 2,
})
if not ent_list or not #ent_list then
return
end
local peer = ent_list[1].player
if p.force.get_friend(peer.force) then
p.print(string.format("The %s %s is your buddy already", peer.name,
peer.tag))
return
end
if global.this.last_friend[peer.tag] == p.tag then
p.force.set_cease_fire(peer.force, true)
peer.force.set_cease_fire(p.force, true)
p.print(string.format("%s %s is now your buddy", peer.name, peer.tag))
peer.print(string.format("%s %s is now your buddy", p.name, p.tag))
global.this.last_friend[p.tag] = ""
return
end
global.this.last_friend[p.tag] = peer.tag
p.print(string.format("You want %s %s to be your buddy", peer.name, peer.tag))
peer.print(string.format("The %s %s wants to be your buddy", p.name, p.tag))
elseif ent.stack.name == "coal" then
local ent_list = p.surface.find_entities_filtered({
name = p.character.name,
position = ent.position,
limit = 1,
radius = 1,
})
if not ent_list or not #ent_list then
return
end
local peer = ent_list[1].player
if p.force.get_friend(peer.force) then
p.print(string.format("The %s %s is not your buddy", p.name, p.tag))
return
end
p.force.set_cease_fire(peer.force, false)
peer.force.set_cease_fire(p.force, false)
p.print(string.format("The %s %s is no longer your buddy", peer.name, peer.tag))
peer.print(string.format("The %s %s is no longer your buddy", p.name, p.tag))
end
end
local function on_chunk_charted(e)
local f_perks = global.this.perks[e.force.name]
if not f_perks then
return
end
if not f_perks.minimap then
e.force.clear_chart()
end
end
local function on_entity_damaged(e)
local ent = e.entity
if ent.force.name == "merchant" then
if not ent.force.get_friend(e.force) then
return
end
ent.force.set_friend(e.force, false)
e.force.set_friend(ent.force, false)
end
end
local function merchant_death(e)
local ent = e.entity
if ent.force.name ~= "merchant" then
return false
end
if ent.name ~= "character" and ent.name ~= "market" then
return false
end
local s = ent.surface
local explosion = {
name = "massive-explosion",
position = ent.position
}
s.create_entity(explosion)
_remove_merchant_bp(s)
global.this.events.merchant.alive = false
global.this.events.merchant.moving = false
global.this.events.merchant.spawn_tick = game.tick + 1000
game.merge_forces("merchant", "neutral")
s.print(">> Merchant died")
for _, player in pairs(game.players) do
redraw_gui(player)
end
return true
end
local function hostile_death(e)
local ent = e.entity
local loot = e.loot
if ent.name ~= "character" then
return false
end
if ent.player then
loot.insert({name = "coin", count = 70})
else
loot.insert({name = "coin", count = 10})
end
return true
end
local function on_entity_died(e)
if not e.entity.valid then
return
end
if merchant_death(e) then
return
end
hostile_death(e)
end
local function merchant_exploit_check(e)
local ent = e.created_entity
if ent.type ~= "electric-pole" then
return
end
local refs = _bp.get_references("merchant")
if not refs or #refs <= 0 then
return
end
local bp_ent = _bp.reference_get_entities(refs[1])[1]
local surf = bp_ent.surface
local query = {
type = "electric-pole",
position = bp_ent.position,
radius = 15
}
local ents = surf.find_entities_filtered(query)
for _, s_ent in pairs(ents) do
if s_ent.valid and s_ent.force.name ~= "merchant" then
s_ent.die()
end
end
end
local function on_built_entity(e)
merchant_exploit_check(e)
end
local function on_market_item_purchased(e)
local p = game.players[e.player_index]
local m = e.market
local o = m.get_market_items()[e.offer_index].offer
local perks = global.this.perks[p.tag]
if o.effect_description == "Construct a flashlight" then
perks.flashlight = true
perks.flashlight_enable = true
p.character.enable_flashlight()
redraw_gui(p)
elseif o.effect_description == "Construct a GPS receiver" then
perks.minimap = true
p.minimap_enabled = true
end
end
local function stringify_color(color)
local r, g, b = color.r, color.g, color.b
if r <= 1 then
r = math.floor(r * 255)
end
if g <= 1 then
g = math.floor(g * 255)
end
if b <= 1 then
b = math.floor(b * 255)
end
return string.format("%d,%d,%d", r, g, b)
end
local function create_console_message(p, message)
local prefix_fmt = "[color=%s]%s %s:[/color]"
local msg_fmt = "[color=%s]%s[/color]"
local color = stringify_color(p.chat_color)
local prefix = string.format(prefix_fmt, color, p.name, p.tag)
local p_msg = string.format(msg_fmt, color, message)
if global.this.perks[p.tag].chat_global then
msg_fmt = "[color=red]global:[/color] %s %s"
else
msg_fmt = "[color=green]buddies:[/color] %s %s"
end
return string.format(msg_fmt, prefix, p_msg)
end
local function create_speech_bubble_message(p, message)
local msg_fmt = "[color=%s]%s[/color]"
local color = stringify_color(p.chat_color)
return string.format(msg_fmt, color, message)
end
local function filter_out_gps(message)
local msg = string.gsub(message, '%[gps=%-?%d+%,?%s*%-?%d+%]', '[gps]')
return msg
end
local function on_console_chat(e)
local pid = e.player_index
if not pid then
return
end
local p = game.players[pid]
local msg = create_console_message(p, e.message)
if global.this.perks[p.tag].chat_global then
local bubble = {
name = "compi-speech-bubble",
position = p.position,
target = p.character,
text = create_speech_bubble_message(p, e.message),
lifetime = 100,
}
p.surface.create_entity(bubble)
for _, peer in pairs(game.players) do
local perks = global.this.perks[peer.tag]
if peer.tag ~= p.tag then
if perks.minimap then
peer.print(msg)
else
peer.print(filter_out_gps(msg))
end
end
end
else
for _, f in pairs(game.forces) do
if p.force.get_cease_fire(f) then
local peer = f.players[1]
local perks = global.this.perks[peer.tag]
if peer.tag ~= p.tag then
if perks.minimap then
peer.print(msg)
else
peer.print(filter_out_gps(msg))
end
end
end
end
end
end
local function on_research_finished(e)
local r = e.research
if not r.valid then
return
end
local reward = {
name = "coin",
count = math.ceil(r.research_unit_count * 3)
}
local f = r.force
for _, player in pairs(f.players) do
if player.can_insert(reward) then
player.insert(reward)
end
end
end
local function on_rocket_launched(e)
local surf = global.this.surface
local pid = e.player_index
surf.print(">> The rocket was launched")
if pid == nil then
surf.print(">> Nobody escaped by it")
else
local p = game.players[pid]
surf.print(string.format(">> The inmate %s was able to escape", p.tag))
on_player_died({player_index = pid})
p.character.die()
end
end
_evt.on_init(init_game)
_evt.add(defines.events.on_built_entity, on_built_entity)
_evt.add(defines.events.on_research_finished, on_research_finished)
_evt.add(defines.events.on_player_joined_game, on_player_joined_game)
_evt.add(defines.events.on_chunk_generated, on_chunk_generated)
_evt.add(defines.events.on_player_mined_entity, on_player_mined_entity)
_evt.add(defines.events.on_player_died, on_player_died)
_evt.add(defines.events.on_player_kicked, on_player_died)
_evt.add(defines.events.on_player_banned, on_player_died)
_evt.add(defines.events.on_player_respawned, on_player_respawned)
_evt.add(defines.events.on_player_dropped_item, on_player_dropped_item)
_evt.add(defines.events.on_pre_player_left_game, on_player_died)
_evt.add(defines.events.on_entity_damaged, on_entity_damaged)
_evt.add(defines.events.on_entity_died, on_entity_died)
_evt.add(defines.events.on_market_item_purchased, on_market_item_purchased)
_evt.add(defines.events.on_chunk_charted, on_chunk_charted)
_evt.add(defines.events.on_console_chat, on_console_chat)
_evt.add(defines.events.on_gui_click, on_gui_click)
_evt.add(defines.events.on_tick, on_tick)
_evt.add(defines.events.on_rocket_launched, on_rocket_launched)
_global.register_init({},
function(tbl)
tbl.this = global.this
end,
function(tbl)
global.this = tbl.this
end)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
return '{"blueprint":{"icons":[{"signal":{"type":"item","name":"crash-site-lab-repaired"},"index":1},{"signal":{"type":"item","name":"crash-site-generator"},"index":2}],"entities":[{"entity_number":1,"name":"crash-site-generator","position":{"x":3,"y":-3.5}},{"entity_number":2,"name":"crash-site-lab-repaired","position":{"x":-2,"y":-1}},{"entity_number":3,"name":"crash-site-chest-1","position":{"x":4,"y":-1}},{"entity_number":4,"name":"crash-site-chest-2","position":{"x":-3,"y":3}},{"entity_number":5,"name":"crash-site-assembling-machine-1-repaired","position":{"x":-2,"y":-5}}],"item":"blueprint","version":73019621376}}'

View File

@ -0,0 +1,556 @@
local public = {}
public.player_ship_loot = {
{
name = "firearm-magazine",
count = 60,
},
{
name = "submachine-gun",
count = 1,
},
{
name = "light-armor",
count = 1,
},
{
name = "iron-plate",
count = 30,
},
{
name = "copper-plate",
count = 10,
},
{
name = "raw-fish",
count = 2,
},
{
name = "small-lamp",
count = 1
}
}
public.wreck_loot = {
["iron-plate"] = {
rare = 0.1,
count = { 20, 40 },
},
["copper-plate"] = {
rare = 0.1,
count = { 10, 30 },
},
["empty-barrel"] = {
rare = 0.4,
count = { 1, 1},
},
["copper-cable"] = {
rare = 0.5,
count = { 5, 20 },
},
["electronic-circuit"] = {
rare = 0.6,
count = { 5, 20 },
},
["firearm-magazine"] = {
rare = 0.4,
count = { 1, 2 },
},
["steel-plate"] = {
rare = 0.8,
count = { 1, 5 },
},
["explosives"] = {
rare = 0.85,
count = { 1, 5 },
},
["advanced-circuit"] = {
rare = 0.9,
count = { 1, 5 },
},
["processing-unit"] = {
rare = 0.95,
count = { 1, 2 },
},
["electric-engine-unit"] = {
rare = 0.95,
count = { 1, 1 },
},
["battery"] = {
rare = 0.95,
count = { 1, 2 },
},
["piercing-rounds-magazine"] = {
rare = 0.99,
count = { 1, 2 },
},
}
public.technologies = {
["military"] = true,
["artillery"] = false,
["artillery-shell-range-1"] = false,
["artillery-shell-speed-1"] = false,
["automation-3"] = false,
["battery-equipment"] = false,
["battery-mk2-equipment"] = false,
["belt-immunity-equipment"] = false,
["combat-robotics-2"] = false,
["combat-robotics-3"] = false,
["discharge-defense-equipment"] = false,
["energy-shield-equipment"] = false,
["energy-shield-mk2-equipment"] = false,
["exoskeleton-equipment"] = false,
["explosive-rocketry"] = false,
["fast-inserter"] = false,
["flamethrower"] = false,
["fusion-reactor-equipment"] = false,
["inserter-capacity-bonus-1"] = false,
["inserter-capacity-bonus-2"] = false,
["inserter-capacity-bonus-3"] = false,
["inserter-capacity-bonus-4"] = false,
["inserter-capacity-bonus-5"] = false,
["inserter-capacity-bonus-6"] = false,
["inserter-capacity-bonus-7"] = false,
["kovarex-enrichment-process"] = false,
["land-mine"] = false,
["logistics-2"] = false,
["logistics-3"] = false,
["military-3"] = false,
["military-4"] = false,
["mining-productivity-2"] = false,
["mining-productivity-3"] = false,
["mining-productivity-4"] = false,
["modular-armor"] = false,
["night-vision-equipment"] = false,
["nuclear-fuel-reprocessing"] = false,
["nuclear-power"] = false,
["personal-laser-defense-equipment"] = false,
["personal-roboport-equipment"] = false,
["personal-roboport-mk2-equipment"] = false,
["power-armor"] = false,
["power-armor-mk2"] = false,
["refined-flammables-1"] = false,
["refined-flammables-2"] = false,
["refined-flammables-3"] = false,
["refined-flammables-4"] = false,
["refined-flammables-5"] = false,
["refined-flammables-6"] = false,
["refined-flammables-7"] = false,
["rocketry"] = false,
["solar-panel-equipment"] = false,
["stack-inserter"] = false,
["stronger-explosives-2"] = false,
["stronger-explosives-3"] = false,
["stronger-explosives-4"] = false,
["stronger-explosives-5"] = false,
["stronger-explosives-6"] = false,
["stronger-explosives-7"] = false,
["tanks"] = false,
["uranium-ammo"] = false,
["uranium-processing"] = false,
["atomic-bomb"] = false,
}
public.merchant_offer = {
{
price = {
{
type = "item",
name = "iron-plate",
amount = 5
},
{
type = "item",
name = "copper-cable",
amount = 2
},
{
type = "item",
name = "electronic-circuit",
amount = 1
},
{
type = "item",
name = "small-lamp",
amount = 1
}
},
offer = {
type = "nothing",
effect_description = "Construct a flashlight",
},
},
{
price = {
{
type = "item",
name = "iron-plate",
amount = 10
},
{
type = "item",
name = "advanced-circuit",
amount = 2
},
{
type = "item",
name = "battery",
amount = 2
},
{
type = "item",
name = "small-lamp",
amount = 2
},
{
type = "item",
name = "copper-cable",
amount = 5
},
{
type = "item",
name = "steel-plate",
amount = 1
},
},
offer = {
type = "nothing",
effect_description = "Construct a GPS receiver"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 500
}
},
offer = {
type = "unlock-recipe",
recipe = "modular-armor"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 5000
}
},
offer = {
type = "give-item",
item = "power-armor"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 10000
}
},
offer = {
type = "give-item",
item = "power-armor-mk2"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 100
}
},
offer = {
type = "give-item",
item = "night-vision-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 70
}
},
offer = {
type = "give-item",
item = "battery-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 300
}
},
offer = {
type = "give-item",
item = "battery-mk2-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 300
}
},
offer = {
type = "give-item",
item = "exoskeleton-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 2500
}
},
offer = {
type = "give-item",
item = "fusion-reactor-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 1000
}
},
offer = {
type = "give-item",
item = "personal-laser-defense-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 200
}
},
offer = {
type = "give-item",
item = "personal-roboport-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 400
}
},
offer = {
type = "give-item",
item = "personal-roboport-mk2-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 90
}
},
offer = {
type = "give-item",
item = "solar-panel-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 100
}
},
offer = {
type = "give-item",
item = "energy-shield-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 400
}
},
offer = {
type = "give-item",
item = "energy-shield-mk2-equipment"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 20
}
},
offer = {
type = "give-item",
item = "flamethrower-ammo"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 1000
}
},
offer = {
type = "unlock-recipe",
recipe = "flamethrower"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 100
}
},
offer = {
type = "give-item",
item = "defender-capsule"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 200
}
},
offer = {
type = "give-item",
item = "distractor-capsule"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 250
}
},
offer = {
type = "give-item",
item = "destroyer-capsule"
}
},
{
price = {
{
type = "item",
name = "coin",
amount = 50
}
},
offer = {
type = "unlock-recipe",
recipe = "fast-inserter"
},
},
{
price = {
{
type = "item",
name = "coin",
amount = 70
}
},
offer = {
type = "unlock-recipe",
recipe = "filter-inserter"
},
},
{
price = {
{
type = "item",
name = "coin",
amount = 100
}
},
offer = {
type = "unlock-recipe",
recipe = "stack-inserter"
},
},
{
price = {
{
type = "item",
name = "coin",
amount = 170
}
},
offer = {
type = "unlock-recipe",
recipe = "stack-filter-inserter"
},
},
{
price = {
{
type = "item",
name = "coin",
amount = 65000
}
},
offer = {
type = "give-item",
item = "computer"
}
},
}
public.manual = [[
[font=heading-1]Planet Prison (1.0.0) - Manual[/font]
[font=default-bold]You did naughty things and was sent to this planet with a one way ticket. Once an industrial site, turned into non-hospitable planet due to pollution and war. Among other inmates, there are still bandits scavenging through the junk looking for rare items.
This is an ultimate survival scenario with very hostile environment.
- You die, you lose everything.
- You leave, you lose everything.
- Technology cost is 10x lower.
- The merchant is a gateway to PvP.
- Flee by a rocket is a win. (Put a car into a rocket and enter the rocket).
- The light is your best friend.
[/font]
[font=heading-1]Buddies[/font]
[font=default-bold]Grab a raw fish [img=item/raw-fish] and drop it on someone with [virtual-signal=signal-Z] button (in default setting). This way you request an inmate to become your buddy.[/font]
[font=default-bold]Grab a coal piece [img=item/coal] and drop it on someone with [virtual-signal=signal-Z] button (in default setting). This way you discard buddy status with an inname.[/font]
[font=heading-1]Other[/font]
[font=default-bold]This scenario was made by cogito123. If you find any bugs/balancing issues, report it to getcomfy.eu/discord. Thanks for playing this map.[/font]
]]
return public

View File

@ -0,0 +1,125 @@
local public, this = {}, {}
local _global = require("utils.global")
local _common = require(".common")
_global.register(this, function(t) this = t end)
public.command = {
--[[
@param args nil
--]]
noop = 0,
--[[
@param args nil
--]]
seek_and_destroy_player = 1,
}
local function _get_direction(src, dest)
local src_x = _common.get_axis(src, "x")
local src_y = _common.get_axis(src, "y")
local dest_x = _common.get_axis(dest, "x")
local dest_y = _common.get_axis(dest, "y")
local step = {
x = nil,
y = nil
}
local precision = _common.rand_range(1, 10)
if dest_x - precision > src_x then
step.x = 1
elseif dest_x < src_x - precision then
step.x = -1
else
step.x = 0
end
if dest_y - precision > src_y then
step.y = 1
elseif dest_y < src_y - precision then
step.y = -1
else
step.y = 0
end
return _common.direction_lookup[step.x][step.y]
end
local function _move_to(ent, trgt, min_distance)
local state = {
walking = false,
}
local distance = _common.get_distance(trgt.position, ent.position)
if min_distance < distance then
local dir = _get_direction(ent.position, trgt.position)
if dir then
state = {
walking = true,
direction = dir
}
end
end
ent.walking_state = state
return state.walking
end
local function _shoot_at(ent, trgt)
ent.shooting_state = {
state = defines.shooting.shooting_enemies,
position = trgt.position
}
end
local function _shoot_stop(ent)
ent.shooting_state = {
state = defines.shooting.not_shooting,
position = {0, 0}
}
end
local function _do_job_seek_and_destroy_player(surf)
for _, player in pairs(game.players) do
if player.character == nil then
goto continue
end
local search_info = {
name = "character",
position = player.character.position,
radius = 20,
force = "enemy",
}
local ents = surf.find_entities_filtered(search_info)
if not ents or #ents == 0 then
goto continue
end
for _, e in pairs(ents) do
if not _move_to(e, player.character, _common.rand_range(5, 10)) then
_shoot_at(e, player.character)
else
_shoot_stop(e)
end
end
::continue::
end
end
--[[
do_job - Perform non-stateful operation on all enemy "character" entities.
@param surf - LuaSurface, on which everything is happening.
@param command - Command to perform on all non-player controllable characters.
--]]
public.do_job = function(surf, command)
if command == public.command.seek_and_destroy_player then
_do_job_seek_and_destroy_player(surf)
end
end
return public

View File

@ -0,0 +1,329 @@
local this, public = {}, {}
local _global = require("utils.global")
local _common = require(".common")
_global.register(this, function(t) this = t end)
this._bps = {}
--[[
push_blueprint - Pushes blueprint into a list.
@param name - Handle of a blueprint.
@param bp - Blueprint in JSON format.
--]]
public.push_blueprint = function(name, bp)
local entry = {
bp = game.json_to_table(bp).blueprint,
hook = nil,
refs = {}
}
this._bps[name] = entry
end
--[[
set_blueprint_hook - Set callback to a blueprint.
@param name - Handle of a blueprint
@param hook - Callback that will be called after blueprint is placed.
--]]
public.set_blueprint_hook = function(name, hook)
if name == nil then
log("bp.set_blueprint_hook: name is nil")
return
end
if this._bps[name] == nil then
log("bp.set_blueprint_hook: unrecognized blueprint")
return
end
this._bps[name].hook = hook
end
--[[
get_references - Get all references of the blueprint on the map.
@param name - Blueprint handle.
--]]
public.get_references = function(name)
if name == nil then
log("bp.get_references: name is nil")
return {}
end
local object = this._bps[name]
if object == nil then
log("bp.get_references: unrecognized blueprint")
return {}
end
return object.refs
end
--[[
get_references - Gets opaque object representing bp references.
@param name - Blueprint handle.
--]]
public.get_references = function(name)
if name == nil then
log("bp.get_references: name is nil")
return
end
local object = this._bps[name]
if object == nil then
log("bp.get_references: unrecognized blueprint")
return
end
return object.refs
end
--[[
reference_get_bounding_box - Return bounding box from the reference.
@param reference - Valid reference object fetched from get_references.
--]]
public.reference_get_bounding_box = function(reference)
return reference.bb
end
--[[
reference_get_entities - Return references to entities.
@param reference - Valid reference object fetched from get_references.
--]]
public.reference_get_entities = function(reference)
return reference.entities
end
--[[
reference_get_timestamp - Return timestamp of a reference
@param reference - Valid reference object fetched from get_references.
--]]
public.reference_get_timestamp = function(reference)
return reference.timestamp
end
--[[
unlink_references_filtered - Unlinks all references of blueprint on the map if they
meet the query rules.
@param name - Blueprint handle.
@param query - Additional parameter by which unlinking is guided
@param query.timestamp - If reference is older that submitted timestamp, it will be
unlinked.
@return An array of unlinked references.
--]]
public.unlink_references_filtered = function(name, query)
if name == nil then
log("bp.get_references: name is nil")
return
end
local object = this._bps[name]
if object == nil then
log("bp.get_references: unrecognized blueprint")
return
end
local refs = {}
for i = 1, #object.refs do
local ref = object.refs[i]
if query and query.timestamp then
if ref.timestamp > query.timestamp then
goto continue
end
end
table.insert(refs, ref)
table.remove(object.refs, i)
::continue::
end
return refs
end
--[[
destroy_references_filtered - Destroys all references of blueprint on the map if they
meet the query rules.
@param surf - Surface on which blueprints are placed.
@param name - Blueprint handle.
@param query - Additional parameter by which removal is guided
@param query.timestamp - If reference is older that submitted timestamp, it will be
removed.
--]]
public.destroy_references_filtered = function(surf, name, query)
if name == nil then
log("bp.get_references: name is nil")
return
end
local object = this._bps[name]
if object == nil then
log("bp.get_references: unrecognized blueprint")
return
end
for i = 1, #object.refs do
local ref = object.refs[i]
if query and query.timestamp then
if ref.timestamp > query.timestamp then
goto continue
end
end
for _, ent in pairs(ref.entities) do
if ent.valid then
ent.destroy()
end
end
local tiles = {}
for _, tile in pairs(ref.tiles) do
tile.name = "concrete"
table.insert(tiles, tile)
end
surf.set_tiles(tiles)
table.remove(object.refs, i)
::continue::
end
end
--[[
destroy_references - Destroys all references of blueprint on the map
@param surf - Surface on which blueprints are placed.
@param name - Blueprint handle.
--]]
public.destroy_references = function(surf, name)
public.destroy_references_filtered(surf, name, {})
end
local function _build_tiles(surf, point, tiles)
local _tiles = {}
local get_axis = _common.get_axis
for _, tile in pairs(tiles) do
local _tile = {
name = tile.name,
position = {
x = get_axis(tile.position, "x") + get_axis(point, "x"),
y = get_axis(tile.position, "y") + get_axis(point, "y")
}
}
table.insert(_tiles, _tile)
end
surf.set_tiles(_tiles)
return _tiles
end
local function _build_entities(surf, point, entities, hook, args)
local _entities = {}
local get_axis = _common.get_axis
for _, ent in pairs(entities) do
local ent_info = {
position = {
x = get_axis(ent.position, "x") + get_axis(point, "x"),
y = get_axis(ent.position, "y") + get_axis(point, "y")
},
name = ent.name,
}
local e = surf.create_entity(ent_info)
if not e or not e.valid then
goto continue
end
if hook then
hook(e, args)
end
table.insert(_entities, e)
::continue::
end
return _entities
end
--[[
build - Place blueprint at given point.
@param surf - LuaSurface on which action will be taken.
@param name - Blueprint handle.
@param point - Position at which place blueprint.
@param args - If hook was set, this will be argument passed.
--]]
public.build = function(surf, name, point, args)
if surf == nil then
log("bp.build: surf is nil")
return
end
if name == nil then
log("bp.build: name is nil")
return
end
local object = this._bps[name]
if object == nil then
log("bp.set_blueprint_hook: unrecognized blueprint")
return
end
local instance = {
entities = {},
tiles = {},
bb = nil,
timestamp = game.tick,
}
local bbs = {}
local tiles = object.bp.tiles
if tiles and #tiles > 0 then
instance.tiles = _build_tiles(surf, point, tiles)
local bb = _common.create_bounding_box_by_points(instance.tiles)
table.insert(bbs, bb)
local query = {
name = "character",
area = bb,
invert = true,
}
for _, ent in pairs(surf.find_entities_filtered(query)) do
if ent.valid then
ent.destroy()
end
end
end
local entities = object.bp.entities
if entities and #entities > 0 then
instance.entities = _build_entities(surf, point, entities, object.hook, args)
local bb = _common.create_bounding_box_by_points(instance.entities)
table.insert(bbs, bb)
local query = {
name = "character",
area = bb,
invert = true,
}
for _, ent_found in pairs(surf.find_entities_filtered(query)) do
if not ent_found.valid then
goto continue
end
for _, ent_spawned in pairs(instance.entities) do
if ent_found == ent_spawned then
goto continue
end
end
ent_found.die()
::continue::
end
end
instance.bb = _common.merge_bounding_boxes(bbs)
table.insert(object.refs, instance)
return instance
end
return public

View File

@ -0,0 +1,267 @@
local public, this = {}, {}
local _global = require("utils.global")
_global.register(this, function(t) this = t end)
--[[
rand_range - Return random integer within the range.
@param start - Start range.
@param stop - Stop range.
--]]
public.rand_range = function(start, stop)
if not this.rng then
this.rng = game.create_random_generator()
end
return this.rng(start, stop)
end
--[[
for_bounding_box - Execute function per every position within bb.
@param surf - LuaSurface, that will be given into func.
@param bb - BoundingBox
@param func - User supplied callback that will be executed.
--]]
public.for_bounding_box = function(surf, bb, func)
for x = bb.left_top.x, bb.right_bottom.x do
for y = bb.left_top.y, bb.right_bottom.y do
func(surf, x, y)
end
end
end
--[[
get_axis - Extract axis value from any point format.
@param point - Table with or without explicity axis members.
@param axis - Single character string describing the axis.
--]]
public.get_axis = function(point, axis)
if point[axis] then
return point[axis]
end
if #point ~= 2 then
log("get_axis: invalid point format")
return nil
end
if axis == "x" then
return point[1]
end
return point[2]
end
--[[
get_close_random_position - Gets randomized close position to origin,
@param origin - Position that will be taken as relative
point for calculation.
@param radius - Radius space.
--]]
public.get_close_random_position = function(origin, radius)
local x = public.get_axis(origin, "x")
local y = public.get_axis(origin, "y")
x = public.rand_range(x - radius, x + radius)
y = public.rand_range(y - radius, y + radius)
return { x = x, y = y }
end
--[[
get_distance - Returns distance in tiles between 2 points.
@param a - Position, first point.
@param b - Position, second point.
--]]
public.get_distance = function(a, b)
local h = (public.get_axis(a, "x") - public.get_axis(b, "x")) ^ 2
local v = (public.get_axis(a, "y") - public.get_axis(b, "y")) ^ 2
return math.sqrt(h + v)
end
--[[
point_in_bounding_box - Check whatever point is within bb.
@param point - Position
@param bb - BoundingBox
--]]
public.point_in_bounding_box = function(point, bb)
local x = public.get_axis(point, "x")
local y = public.get_axis(point, "y")
if bb.left_top.x <= x and bb.right_bottom.x >= x and
bb.left_top.y <= y and bb.right_bottom.y >= y then
return true
end
return false
end
public.direction_lookup = {
[-1] = {
[1] = defines.direction.southwest,
[0] = defines.direction.west,
[-1] = defines.direction.northwest,
},
[0] = {
[1] = defines.direction.south,
[-1] = defines.direction.north
},
[1] = {
[1] = defines.direction.southeast,
[0] = defines.direction.east,
[-1] = defines.direction.northeast,
},
}
--[[
get_readable_direction - Return readable direction from point a to b.
@param a - Position A
@param b - Position B
--]]
public.get_readable_direction = function(a, b)
local a_x = public.get_axis(a, "x")
local a_y = public.get_axis(a, "y")
local b_x = public.get_axis(b, "x")
local b_y = public.get_axis(b, "y")
local h, v
if a_x < b_x then
h = 1
elseif a_x > b_x then
h = -1
else
h = 0
end
if a_y < b_y then
v = 1
elseif a_y > b_y then
v = -1
else
v = 0
end
local mapping = {
[defines.direction.southwest] = "south-west",
[defines.direction.west] = "west",
[defines.direction.northwest] = "north-west",
[defines.direction.south] = "south",
[defines.direction.north] = "north",
[defines.direction.southeast] = "south-east",
[defines.direction.east] = "east",
[defines.direction.northeast] = "north-east",
}
return mapping[public.direction_lookup[h][v]]
end
--[[
create_bounding_box_by_points - Construct a BoundingBox using points
from any array of objects with "position" or "bounding_box" datafield.
@param objects - Array of objects that have "position" datafield.
--]]
public.create_bounding_box_by_points = function(objects)
local box = {
left_top = {
x = public.get_axis(objects[1].position, "x"),
y = public.get_axis(objects[1].position, "y")
},
right_bottom = {
x = public.get_axis(objects[1].position, "x"),
y = public.get_axis(objects[1].position, "y")
}
}
for i = 2, #objects do
local object = objects[i]
if object.bounding_box then
local bb = object.bounding_box
if box.left_top.x > bb.left_top.x then
box.left_top.x = bb.left_top.x
end
if box.right_bottom.x < bb.right_bottom.x then
box.right_bottom.x = bb.right_bottom.x
end
if box.left_top.y > bb.left_top.y then
box.left_top.y = bb.left_top.y
end
if box.right_bottom.y < bb.right_bottom.y then
box.right_bottom.y = bb.right_bottom.y
end
else
local point = objects[i].position
local x = public.get_axis(point, "x")
local y = public.get_axis(point, "y")
if box.left_top.x > x then
box.left_top.x = x
elseif box.right_bottom.x < x then
box.right_bottom.x = x
end
if box.left_top.y > y then
box.left_top.y = y
elseif box.right_bottom.y < y then
box.right_bottom.y = y
end
end
end
box.left_top.x = box.left_top.x - 1
box.left_top.y = box.left_top.y - 1
box.right_bottom.x = box.right_bottom.x + 1
box.right_bottom.y = box.right_bottom.y + 1
return box
end
--[[
merge_bounding_boxes - Merge array of BoundingBox objects into a single
object.
@param bbs - Array of BoundingBox objects.
--]]
public.merge_bounding_boxes = function(bbs)
if bbs == nil then
log("common.merge_bounding_boxes: bbs is nil")
return
end
if #bbs <= 0 then
log("common.merge_bounding_boxes: bbs is empty")
return
end
local box = {
left_top = {
x = bbs[1].left_top.x,
y = bbs[1].left_top.y,
},
right_bottom = {
x = bbs[1].right_bottom.x,
y = bbs[1].right_bottom.y,
}
}
for i = 2, #bbs do
local bb = bbs[i]
if box.left_top.x > bb.left_top.x then
box.left_top.x = bb.left_top.x
end
if box.right_bottom.x < bb.right_bottom.x then
box.right_bottom.x = bb.right_bottom.x
end
if box.left_top.y > bb.left_top.y then
box.left_top.y = bb.left_top.y
end
if box.right_bottom.y < bb.right_bottom.y then
box.right_bottom.y = bb.right_bottom.y
end
end
return box
end
return public

View File

@ -0,0 +1,181 @@
local this, public = {}, {}
local _global = require("utils.global")
local _common = require(".common")
local _simplex = require(".simplex_noise")
_global.register(this, function(t) this = t end)
this._grid = {}
this._exclusions = {}
this._layers = {}
this._collision_mask = {}
public.init = function()
_simplex.init()
end
local function _push_bounding_box(_, x, y)
table.insert(this._grid, { x, y })
end
--[[
push_bounding_box - Pushes bounding box into a grid for later processing.
@param bb - BoundingBox.
--]]
public.push_bounding_box = function(bb)
_common.for_bounding_box(nil, bb, _push_bounding_box)
end
--[[
add_excluding_bounding_box - Pushes bounding box into exclusion list.
@param bb - BoundindBox.
--]]
public.push_excluding_bounding_box = function(bb)
table.insert(this._exclusions, bb)
end
--[[
remove_ecluding_bounding_box - Removes bounding box from exclusion list.
@param bb - BoundingBox to get rid of.
--]]
public.remove_excluding_bounding_box = function(bb)
for i = 1, #this._exclusions do
local box = this._exclusions[i]
if box == bb then
table.remove(this._exclusions, i)
break
end
end
end
--[[
add_noise_layer - Add noise layer that will be applied onto the grid.
@param type - Type of an object that will be placed onto layer.
@param name - Name of the layer
@param objects - Names of the objects that will be placed.
@param resolution - Resolution of a layer [0f - 1f]
@param elevation - Layer visibility [0f - 1f)
--]]
public.add_noise_layer = function(type, name, objects, elevation, resolution)
local layer = {
type = type,
name = name,
objects = objects,
elevation = elevation,
resolution = resolution,
cache = {},
hook = nil,
}
table.insert(this._layers, layer)
end
--[[
add_noise_layer_hook - Execute callback on created object.
@param name - Name of the layer.
@param hook - Callback that will be called with an object argument.
--]]
public.add_noise_layer_hook = function(name, hook)
for _, layer in pairs(this._layers) do
if layer.name == name then
layer.hook = hook
break
end
end
end
--[[
set_collision_mask - Set which tiles should be ignored.
@param mask - Table of collision masks.
--]]
public.set_collision_mask = function(mask)
this._collision_mask = mask
end
local function _do_job_tile(surf, layer)
surf.set_tiles(layer.cache)
end
local function _do_job_entity(surf, layer)
local hook = layer.hook
for _, object in pairs(layer.cache) do
if object.name == "character" or object.name == "gun-turret" then
if not surf.can_place_entity(object) then
goto continue
end
end
local ent = surf.create_entity(object)
if not ent or not ent.valid then
goto continue
end
if hook then
hook(ent)
end
::continue::
end
end
--[[
do_job - Do a single step propagation of a layers.
@param surf - LuaSurface, onto which action is taken.
@param limit - How many requests to process.
--]]
public.do_job = function(surf, limit)
for i = 1, #this._grid do
local point = table.remove(this._grid)
for _, box in pairs(this._exclusions) do
if _common.point_in_bounding_box(point, box) then
goto next_point
end
end
for _, layer in pairs(this._layers) do
local ret = _simplex.get(point, layer.resolution)
if ret >= layer.elevation then
local tile = surf.get_tile(point)
for _, mask in pairs(this._collision_mask) do
if tile.collides_with(mask) then
goto continue
end
end
local object_name = layer.objects[1]
if #layer.objects > 1 then
local index = _common.rand_range(1, #layer.objects)
object_name = layer.objects[index]
end
local object = {
name = object_name,
position = point,
}
table.insert(layer.cache, object)
break
::continue::
end
end
::next_point::
if i >= limit then
break
end
end
for _, layer in pairs(this._layers) do
local cache = layer.cache
if #cache >= 1 then
if layer.type == "LuaTile" then
_do_job_tile(surf, layer)
elseif layer.type == "LuaEntity" then
_do_job_entity(surf, layer)
end
layer.cache = {}
end
end
end
return public

View File

@ -0,0 +1,124 @@
-- Original implementation taken from here https://github.com/thenumbernine/lua-simplexnoise/blob/master/2d.lua
local public, this = {}, {}
local _global = require("utils.global")
local _common = require(".common")
_global.register(this, function(t) this = t end)
this.perm = {}
this.seed = 0
this.grad3 = {
{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1 ,0},
{1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1},
{0, 1, 1}, {0, -1, 1}, {0, 1, -1}, {0, -1, -1}
}
this.p = {
151, 160, 137, 91, 90, 15, 131, 13, 201,
95, 96, 53, 194, 233, 7, 225, 140, 36,
103, 30, 69, 142, 8, 99, 37, 240, 21, 10,
23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
197, 62, 94, 252, 219, 203, 117, 35, 11,
32, 57, 177, 33, 88, 237, 149, 56, 87,
174, 20, 125, 136, 171, 168, 68, 175, 74,
165, 71, 134, 139, 48, 27, 166, 77, 146,
158, 231, 83, 111, 229, 122, 60, 211, 133,
230, 220, 105, 92, 41, 55, 46, 245, 40,
244, 102, 143, 54, 65, 25, 63, 161, 1,
216, 80, 73, 209, 76, 132, 187, 208, 89,
18, 169, 200, 196, 135, 130, 116, 188,
159, 86, 164, 100, 109, 198, 173, 186,
3, 64, 52, 217, 226, 250, 124, 123, 5, 202,
38, 147, 118, 126, 255, 82, 85, 212, 207,
206, 59, 227, 47, 16, 58, 17, 182, 189,
28, 42, 223, 183, 170, 213, 119, 248, 152,
2, 44, 154, 163, 70, 221, 153, 101, 155,
167, 43, 172, 9, 129, 22, 39, 253, 19,
98, 108, 110, 79, 113, 224, 232, 178, 185,
112, 104, 218, 246, 97, 228, 251, 34, 242,
193, 238, 210, 144, 12, 191, 179, 162, 241,
81, 51, 145, 235, 249, 14, 239, 107, 49, 192,
214, 31, 181, 199, 106, 157, 184, 84, 204,
176, 115, 121, 50, 45, 127, 4, 150, 254,
138, 236, 205, 93, 222, 114, 67, 29, 24, 72,
243, 141, 128, 195, 78, 66, 215, 61, 156, 180
}
local function dot(a, b)
local sum = 0
for i = 1, #b do
sum = sum + (a[i] * b[i])
end
return sum
end
public.init = function()
local rng = game.create_random_generator()
this.seed = rng(1, 4294967295)
for i = 0, 511 do
this.perm[i + 1] = this.p[bit32.band(i, 255) + 1]
end
end
public.get = function(pos, resolution)
local x = (_common.get_axis(pos, 'x') + this.seed) * resolution
local y = (_common.get_axis(pos, 'y') + this.seed) * resolution
local n0, n1, n2
local F2 = 0.5*(math.sqrt(3.0)-1.0)
local s = (x + y) * F2;
local i = math.floor(x + s)
local j = math.floor(y + s)
local G2 = (3.0-math.sqrt(3.0))/6.0
local t = (i+j)*G2
local X0 = i-t
local Y0 = j-t
local x0 = x - X0
local y0 = y -Y0
local i1, j1
if x0 > y0 then
i1 = 1
j1 = 0
else
i1 = 0
j1 = 1
end
local x1 = x0 - i1 + G2
local y1 = y0 - j1 + G2
local x2 = x0 - 1 + 2 * G2
local y2 = y0 - 1 + 2 * G2
local ii = bit32.band(i, 255)
local jj = bit32.band(j, 255)
local gi0 = this.perm[ii + this.perm[jj+1]+1] % 12
local gi1 = this.perm[ii + i1 + this.perm[jj + j1+1]+1] % 12
local gi2 = this.perm[ii + 1 + this.perm[jj + 1+1]+1] % 12
-- Calculate the contribution from the three corners
local t0 = 0.5 - x0 * x0 - y0 * y0
if t0 < 0 then
n0 = 0.0
else
t0 = t0 * t0
n0 = t0 * t0 * dot(this.grad3[gi0+1], {x0, y0})
end
local t1 = 0.5 - x1 * x1 - y1 * y1
if t1 < 0 then
n1 = 0.0
else
t1 = t1 * t1
n1 = t1 * t1 * dot(this.grad3[gi1+1], {x1, y1})
end
local t2 = 0.5 - x2 * x2 - y2 * y2
if t2 < 0 then
n2 = 0.0
else
t2 = t2 * t2
n2 = t2 * t2 * dot(this.grad3[gi2+1], {x2, y2})
end
return 70.0 * (n0 + n1 + n2)
end
return public

View File

@ -41,7 +41,7 @@ end
local function on_player_joined_game(event)
if this[event.player_index] then
Public.update_player_modifiers(player)
Public.update_player_modifiers(game.players[event.player_index])
return
end
this[event.player_index] = {}
@ -58,4 +58,5 @@ local Event = require 'utils.event'
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
Event.add(defines.events.on_player_respawned, on_player_respawned)
return Public
return Public

View File

@ -730,7 +730,7 @@ Event.add(
message[#message + 1] = ' was killed by '
local name = cause.name
if name == 'character' then
if name == 'character' and cause.player then
name = cause.player.name
end