You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
6.2 KiB

local Beacon = {}
-- Note: supply_area_distance -- extends from edge of collision box
Beacon.affected_types = {"assembling-machine", "furnace", "lab", "mining-drill", "rocket-silo"}
function Beacon.get_beacon_prototypes()
if not Beacon.list_beacon_prototypes then
Beacon.list_beacon_prototypes = {}
for name, prototype in pairs(game.entity_prototypes) do
if prototype.type == "beacon" and prototype.supply_area_distance then
table.insert(Beacon.list_beacon_prototypes, prototype)
end
end
end
return Beacon.list_beacon_prototypes
end
function Beacon.get_max_beacon_range()
if not Beacon.max_beacon_range then
Beacon.max_beacon_range = 0
for _, prototype in pairs(Beacon.list_beacon_prototypes()) do
if prototype.supply_area_distance > Beacon.max_beacon_range then
Beacon.max_beacon_range = prototype.supply_area_distance
end
end
end
return Beacon.max_beacon_range
end
function Beacon.validate_entity(entity, ignore_count)
-- make sure not affected by more than 1 beacon
if (not entity.prototype.allowed_effects) or table_size(entity.prototype.allowed_effects) == 0
or (not entity.prototype.module_inventory_size) or entity.prototype.module_inventory_size == 0 then return end
local ignore = ignore_count and ignore_count or 0
local bounding_box = entity.bounding_box
local beacons = 0
for _, prototype in pairs(Beacon.get_beacon_prototypes()) do
local area = util.area_extend(bounding_box, prototype.supply_area_distance)
beacons = beacons + entity.surface.count_entities_filtered{type="beacon", name=prototype.name, area = area}
end
if beacons > 1 + ignore then
if entity.active == true then
entity.active = false
entity.surface.create_entity{
name = "flying-text",
position = entity.position,
text = {"space-exploration.beacon-overload"}
}
global.beacon_overloaded_entities = global.beacon_overloaded_entities or {}
global.beacon_overloaded_entities[entity.unit_number] = entity
global.beacon_overloaded_shapes = global.beacon_overloaded_shapes or {}
local shape_id = global.beacon_overloaded_shapes[entity.unit_number]
if shape_id and rendering.is_valid(shape_id) then rendering.destroy(shape_id) end -- shouldn't happen but best to check if other mods broke something
shape_id = rendering.draw_sprite{
sprite = "virtual-signal/"..mod_prefix.."beacon-overload",
surface = entity.surface,
target = entity,
x_scale = 1,
y_scale = 1,
target_offset = entity.prototype.alert_icon_shift
}
global.beacon_overloaded_shapes[entity.unit_number] = shape_id
end
else
-- TODO: add hook here so other things can cancel
if not entity.active then
global.beacon_overloaded_entities = global.beacon_overloaded_entities or {}
global.beacon_overloaded_shapes = global.beacon_overloaded_shapes or {}
local deactivated_by_beacons = false
for unit_number, overloaed_entity in pairs(global.beacon_overloaded_entities) do
if not overloaed_entity.valid then
global.beacon_overloaded_entities[unit_number] = nil
if global.beacon_overloaded_shapes[unit_number] then
local shape_id = global.beacon_overloaded_shapes[unit_number]
if rendering.is_valid(shape_id) then rendering.destroy(shape_id) end
global.beacon_overloaded_shapes[unit_number] = nil
end
elseif entity == overloaed_entity then
global.beacon_overloaded_entities[unit_number] = nil
if global.beacon_overloaded_shapes[unit_number] then
local shape_id = global.beacon_overloaded_shapes[unit_number]
if rendering.is_valid(shape_id) then rendering.destroy(shape_id) end
global.beacon_overloaded_shapes[unit_number] = nil
end
deactivated_by_beacons = true
end
end
if deactivated_by_beacons then
entity.active = true
entity.surface.create_entity{
name = "flying-text",
position = entity.position,
text = {"space-exploration.beacon-overload-ended"}
}
for interface, functions in pairs(remote.interfaces) do -- allow other mods to deactivate after
if interface ~= "space-exploration" and functions["on_entity_activated"] then
remote.call(interface, "on_entity_activated", {entity = entity, mod = "space-exploration"})
end
end
end
end
end
end
function Beacon.validate_beacon(entity, is_deconstructing)
local prototype = entity.prototype
local area = util.area_extend(entity.bounding_box, prototype.supply_area_distance)
local structures = entity.surface.find_entities_filtered{type = Beacon.affected_types, area = area}
local ignore = is_deconstructing and 1 or 0
for _, structure in pairs(structures) do
Beacon.validate_entity(structure, ignore)
end
end
function Beacon.on_entity_created(event)
local entity
if event.entity and event.entity.valid then
entity = event.entity
end
if event.created_entity and event.created_entity.valid then
entity = event.created_entity
end
if not entity then return end
if entity.type == "beacon" then
Beacon.validate_beacon(entity)
elseif util.table_contains(Beacon.affected_types, entity.type) then
Beacon.validate_entity(entity)
end
end
Event.addListener(defines.events.on_built_entity, Beacon.on_entity_created)
Event.addListener(defines.events.on_robot_built_entity, Beacon.on_entity_created)
Event.addListener(defines.events.script_raised_built, Beacon.on_entity_created)
Event.addListener(defines.events.script_raised_revive, Beacon.on_entity_created)
function Beacon.on_entity_removed(event)
if event.entity and event.entity.valid then
if event.entity.type == "beacon" then
-- do validation but counting 1 beacon fewer
Beacon.validate_beacon(event.entity, true)
end
end
end
Event.addListener(defines.events.on_player_mined_entity, Beacon.on_entity_removed)
Event.addListener(defines.events.on_robot_mined_entity, Beacon.on_entity_removed)
Event.addListener(defines.events.on_entity_died, Beacon.on_entity_removed)
Event.addListener(defines.events.script_raised_destroy, Beacon.on_entity_removed)
return Beacon