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:
commit
86c37d173a
@ -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
868
maps/planet_prison.lua
Normal 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)
|
1
maps/planet_prison/bp/merchant.lua
Normal file
1
maps/planet_prison/bp/merchant.lua
Normal file
File diff suppressed because one or more lines are too long
1
maps/planet_prison/bp/player_ship.lua
Normal file
1
maps/planet_prison/bp/player_ship.lua
Normal 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}}'
|
556
maps/planet_prison/config.lua
Normal file
556
maps/planet_prison/config.lua
Normal 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
|
125
maps/planet_prison/mod/ai.lua
Normal file
125
maps/planet_prison/mod/ai.lua
Normal 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
|
329
maps/planet_prison/mod/bp.lua
Normal file
329
maps/planet_prison/mod/bp.lua
Normal 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
|
267
maps/planet_prison/mod/common.lua
Normal file
267
maps/planet_prison/mod/common.lua
Normal 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
|
181
maps/planet_prison/mod/layers.lua
Normal file
181
maps/planet_prison/mod/layers.lua
Normal 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
|
124
maps/planet_prison/mod/simplex_noise.lua
Normal file
124
maps/planet_prison/mod/simplex_noise.lua
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user