1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-05-13 21:56:29 +02:00

planet_prison: add claim system

Adds claim system to mark player bases.
This commit is contained in:
cogito 2020-01-18 19:59:34 +01:00
parent cfd35eb9bd
commit 284ed14b74
4 changed files with 463 additions and 1 deletions

View File

@ -8,6 +8,7 @@ local _layers = require("planet_prison.mod.layers")
local _ai = require("planet_prison.mod.ai")
local _bp = require("planet_prison.mod.bp")
local _afk = require("planet_prison.mod.afk")
local _claims = require("planet_prison.mod.claims")
global.this._config = require("planet_prison.config")
global.this.maps = {
@ -226,6 +227,8 @@ local function init_game()
_bp.init()
_ai.init()
_timers.init()
_claims.init(global.this._config.claim_markers,
global.this._config.claim_max_distance)
local map = pick_map()
local preset = global.this.presets[map.name]
@ -380,6 +383,14 @@ local function get_non_obstructed_position(s, radius)
return chunk
end
local function switchable_perk(caption, status)
if status then
return string.format("[color=0,80,0]%s[/color]", caption)
end
return string.format("[color=80,0,0]%s[/color]", caption)
end
local function redraw_gui(p)
p.gui.left.clear()
@ -649,7 +660,7 @@ local function on_chunk_generated(e)
_layers.push_chunk(e.position)
end
local function on_player_mined_entity(e)
local function mined_wreckage(e)
if e.entity.name ~= "mineable-wreckage" then
return
end
@ -676,6 +687,16 @@ local function on_player_mined_entity(e)
e.buffer.insert(cand)
end
local function on_player_mined_entity(e)
local ent = e.entity
if not ent.valid then
return
end
mined_wreckage(e)
_claims.on_player_mined_entity(ent)
end
local function on_player_died(e)
local index = e.player_index
if not index then
@ -894,6 +915,7 @@ local function on_entity_died(e)
hostile_death(e)
character_death(e)
_claims.on_entity_died(e.entity)
end
@ -929,6 +951,7 @@ local function on_built_entity(e)
return
end
_claims.on_built_entity(ent)
merchant_exploit_check(ent)
end

View File

@ -36,6 +36,11 @@ public.player_ship_loot = {
}
public.self_explode = 60 * 60 * 10
public.claim_markers = {
"gun-turret",
"laser-turret",
}
public.claim_max_distance = 15
public.wreck_loot = {
["iron-plate"] = {

View File

@ -0,0 +1,230 @@
local public = {}
local common = require(".common")
--[[
init - Initialize claim system.
@param names - Table of entity names that should be used as a marker.
@param max_distance - Maximal distance allowed between markers
--]]
public.init = function(names, max_distance)
if global.this == nil then
global.this = {}
end
if type(names) ~= "table" then
names = { names }
end
global.this._claims_info = {}
global.this._claims_visible_to = {}
global.this._claim_markers = names
global.this._claim_max_dist = max_distance
end
global.this._claim_new_claim = function(ent, deps)
local comm = deps.common
local point = {
{
x = comm.get_axis(ent.position, "x"),
y = comm.get_axis(ent.position, "y"),
}
}
local claims = global.this._claims_info
if claims[ent.force.name] == nil then
claims[ent.force.name] = {}
claims[ent.force.name].polygons = {}
claims[ent.force.name].claims = {}
claims[ent.force.name].collections = {}
end
table.insert(claims[ent.force.name].collections, point)
end
global.this._claim_on_build_entity = function(ent, deps)
local max_dist = global.this._claim_max_dist
local force = ent.force.name
local comm = deps.common
local data = global.this._claims_info[force]
if data == nil then
global.this._claim_new_claim(ent, deps)
return
end
local in_range = false
local collections = data.collections
for i = 1, #collections do
local points = collections[i]
for _, point in pairs(points) do
point = point
local dist = comm.get_distance(point, ent.position)
if max_dist < dist then
goto continue
end
in_range = true
point = {
x = comm.get_axis(ent.position, "x"),
y = comm.get_axis(ent.position, "y"),
}
table.insert(points, point)
data.claims[i] = comm.get_convex_hull(points)
break
::continue::
end
end
if not in_range then
global.this._claim_new_claim(ent, deps)
end
end
global.this._claims_in_markers = function(name)
for _, marker in pairs(global.this._claim_markers) do
if name == marker then
return true
end
end
return false
end
--[[
on_build_entity - Event processing function.
@param ent - Entity
--]]
public.on_built_entity = function(ent)
if not global.this._claims_in_markers(ent.name) then
return
end
local deps = {
common = common,
}
global.this._claim_on_build_entity(ent, deps)
end
global.this._claim_on_entity_died = function(ent, deps)
local comm = deps.common
local force = ent.force.name
local data = global.this._claims_info[force]
if data == nil then
return
end
for i = 1, #data.collections do
local points = data.collections[i]
for j = 1, #points do
local point = points[j]
if comm.positions_equal(point, ent.position) then
table.remove(points, j)
data.claims[i] = comm.get_convex_hull(points)
break
end
end
if #points == 0 then
table.remove(data.claims, i)
table.remove(data.collections, i)
break
end
end
if #data.claims == 0 then
global.this._claims_info[force] = nil
end
end
--[[
on_entity_died - Event processing function.
@param ent - Entity
--]]
public.on_entity_died = function(ent)
if not global.this._claims_in_markers(ent.name) then
return
end
local deps = {
common = common,
}
global.this._claim_on_entity_died(ent, deps)
end
--[[
on_player_mined_entity - Event processing function.
@param ent - Entity
--]]
public.on_player_mined_entity = function(ent)
public.on_entity_died(ent)
end
--[[
get_claims - Get all claims data points for given force.
@param f_name - Force name.
--]]
public.get_claims = function(f_name)
if global.this._claims_info[f_name] == nil then
return {}
end
return global.this._claims_info[f_name].claims
end
global.this._claims_update_visiblity = function()
if #global.this._claims_visible_to == 0 then
for _, info in pairs(global.this._claims_info) do
for _, id in pairs(info.polygons) do
if rendering.is_valid(id) then
rendering.set_visible(id, false)
end
end
end
return
end
for _, info in pairs(global.this._claims_info) do
for _, id in pairs(info.polygons) do
if rendering.is_valid(id) then
rendering.set_visible(id, true)
rendering.set_players(id, global.this._claims_visible_to)
end
end
end
end
--[[
set_visibility_to - Specifies who can see the claims and redraws.
@param name - Name of a player.
--]]
public.set_visibility_to = function(name)
for _, p in pairs(global.this._claims_visible_to) do
if p == name then
return
end
end
table.insert(global.this._claims_visible_to, name)
global.this._claims_update_visiblity()
end
--[[
remove_visibility_from - Remove the claim visibility from the player.
@param name - Name of a player.
--]]
public.remove_visibility_from = function(name)
for i = 1, #global.this._claims_visible_to do
local p = global.this._claims_visible_to[i]
if p == name then
table.remove(global.this._claims_visible_to, i)
global.this._claims_update_visiblity()
break
end
end
end
return public

View File

@ -39,6 +39,10 @@ get_axis - Extract axis value from any point format.
@param axis - Single character string describing the axis.
--]]
public.get_axis = function(point, axis)
if point.target then
return public.get_axis(point.target, axis)
end
if point[axis] then
return point[axis]
end
@ -289,4 +293,204 @@ public.get_time = function(ticks)
return time
end
--[[
polygon_insert - Append vertex in clockwise order.
@param vertex - Point to insert,
@param vertices - Tables of vertices.
--]]
public.polygon_append_vertex = function(vertices, vertex)
table.insert(vertices, vertex)
local x_avg, y_avg = 0, 0
for _, v in pairs(vertices) do
x_avg = x_avg + public.get_axis(v, "x")
y_avg = y_avg + public.get_axis(v, "y")
end
x_avg = x_avg / #vertices
y_avg = y_avg / #vertices
local delta_x, delta_y, rad1, rad2
for i = 1, #vertices, 1 do
for j = 1, #vertices - i do
local v = vertices[j]
delta_x = public.get_axis(v, "x") - x_avg
delta_y = public.get_axis(v, "y") - y_avg
rad1 = ((math.atan2(delta_x, delta_y) * (180 / 3.14)) + 360) % 360
v = vertices[j + 1]
delta_x = public.get_axis(v, "x") - x_avg
delta_y = public.get_axis(v, "y") - y_avg
rad2 = ((math.atan2(delta_x, delta_y) * (180 / 3.14)) + 360) % 360
if rad1 > rad2 then
vertices[j], vertices[j + 1] = vertices[j + 1], vertices[j]
end
end
end
end
--[[
positions_equal - Checks if given positions are equal.
@param a - Position a
@param b - Position b
--]]
public.positions_equal = function(a, b)
local p1 = public.get_axis(a, "x")
local p2 = public.get_axis(b, "x")
if p1 ~= p2 then
return false
end
p1 = public.get_axis(a, "y")
p2 = public.get_axis(b, "y")
if p1 ~= p2 then
return false
end
return true
end
local function rev(array, index)
if index == nil then
index = 0
end
index = #array - index
return array[index]
end
--[[
deepcopy - Makes a deep copy of an object.
@param orig - Object to copy.
--]]
public.deepcopy = function(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[public.deepcopy(orig_key)] = public.deepcopy(orig_value)
end
setmetatable(copy, public.deepcopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
local function convex_hull_turn(a, b, c)
local x1, x2, x3, y1, y2, y3
x1 = public.get_axis(a, "x")
x2 = public.get_axis(b, "x")
y1 = public.get_axis(a, "y")
y2 = public.get_axis(b, "y")
if c then
x3 = public.get_axis(c, "x")
y3 = public.get_axis(c, "y")
return (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)
end
return (x1 * y2) - (y1 * x2)
end
--[[
convex_hull - Generate convex hull out of given vertices.
@param vertices - Table of positions.
--]]
public.get_convex_hull = function(_vertices)
if #_vertices == 0 then
return {}
end
local vertices = public.deepcopy(_vertices)
-- Get the lowest point
local v, y1, y2, x1, x2, lowest_index
local lowest = vertices[1]
for i = 2, #vertices do
v = vertices[i]
y1 = public.get_axis(v, "y")
y2 = public.get_axis(lowest, "y")
if y1 < y2 then
lowest = v
lowest_index = i
elseif y1 == y2 then
x1 = public.get_axis(v, "x")
x2 = public.get_axis(lowest, "x")
if x1 < x2 then
lowest = v
lowest_index = i
end
end
end
table.remove(vertices, lowest_index)
x1 = public.get_axis(lowest, "x")
y1 = public.get_axis(lowest, "y")
-- Sort by angle to horizontal axis.
local rad1, rad2, dist1, dist2
local i, j = 1, 1
while i <= #vertices do
while j <= #vertices - i do
v = vertices[j]
x2 = public.get_axis(v, "x")
y2 = public.get_axis(v, "y")
rad1 = (math.atan2(y2 - y1, x2 - x1) * (180/3.14) + 320) % 360
v = vertices[j + 1]
x2 = public.get_axis(v, "x")
y2 = public.get_axis(v, "y")
rad2 = (math.atan2(y2 - y1, x2 - x1) * (180/3.14) + 320) % 360
if rad1 > rad2 then
vertices[j + 1], vertices[j] = vertices[j], vertices[j + 1]
elseif rad1 == rad2 then
dist1 = public.get_distance(lowest, vertices[j])
dist2 = public.get_distance(lowest, vertices[j + 1])
if dist1 > dist2 then
table.remove(vertices, j + 1)
else
table.remove(vertices, j)
end
end
j = j + 1
end
i = i + 1
end
if #vertices <= 3 then
return {}
end
-- Traverse points.
local stack = {
vertices[1],
vertices[2],
vertices[3],
}
local point
for i = 4, #vertices do
point = vertices[i]
while #stack > 1
and convex_hull_turn(point, rev(stack, 1), rev(stack)) >= 0 do
table.remove(stack)
end
table.insert(stack, point)
end
table.insert(stack, lowest)
return stack
end
return public