Factorio-Paranoidal_mod/Natural_Evolution_Enemies/libs/collision-mask-util-extended.lua

197 lines
8.6 KiB
Lua

-- File Licence: You can copy and distribute this file regardless of the mod's general licence. This licence exception does not affect other files of this mod.
local collision_mask_util_extended = require("__core__/lualib/collision-mask-util")
--[[
Named collision masks allow a collision mask to be passed to the control phase.
The arrow object used to stor the mask is accessible under: game.entity_prototypes["collision-mask-flying-layer"]
The layer used is therefore: game.entity_prototypes["collision-mask-flying-layer"].collision_mask .. something
--------------------------------------------------------------------------------
-- INSTRUCTIONS
--------------------------------------------------------------------------------
-- flying-layer example:
-- data phase ------------------------------------------------------------------
(data.lua data-updates.lua data-final-fixes.lua etc) get/make a layer:
-- load the modified util
local collision_mask_util_extended = require("collision-mask-util-extended")
-- get a collision layer by name, if the name is not assigned to a layer it will assign one
local flying_layer = collision_mask_util_extended.get_make_named_collision_mask("flying-layer")
-- control phase ---------------------------------------------------------------
(conrtol.lua) Note: most mods don't need to know collision layers in control code.
local collision_mask_util_extended = require("collision-mask-util-control")
-- Example usage
local flying_layer = collision_mask_util_extended.get_named_collision_mask("flying-layer")
local entities = surface.find_entities_filtered{collision_mask={flying_layer}}
--------------------------------------------------------------------------------
-- Additional named layers
--------------------------------------------------------------------------------
"flying-layer"
-- local collision_mask_flying_layer = get_make_named_collision_mask("flying-layer")
Flying vehicles, units, and characters.
It is useful to also set the mask "not-colliding-with-itself" to prefent air-air collisions.
The mask can also be added to interior walls that are full height so can't be flown over.
"projectile-layer"
-- local collision_mask_projectile_layer = get_make_named_collision_mask("projectile-layer")
Projectiles. The the projectile should have the layers or most things it can hit (flying-layer).
Walls and shields can also use this layer to block the projectile.
Note: Projectiles use hit_collision_mask not collision_mask. force_condition = "not-friend" means it won't hit your stuff.
Note: Streams can't collide.
"vehicle-layer"
-- local collision_mask_vehicle_layer = get_make_named_collision_mask("vehicle-layer")
Car type vehicles and things that collide with them. Allows separation of vehicle-layer and player-layer in certain situations. Add to cars, trees, pipes
"space-tile"
-- local collision_mask_space_tile = get_make_named_collision_mask("space-tile")
All tiles in space zones (orbit/asteroid fields) including empty space and space platform.
"empty-space-tile"
-- local collision_mask_empty_space_tile = get_make_named_collision_mask("empty-space-tile")
tiles in space without flooring.
Different from void becuase there is no grravity and stuff can float there.
"interior-tile"
-- local collision_mask_interior_tile = get_make_named_collision_mask("interior-tile")
Tiles that represent interior spaces and don't have sky, like underground, factory building interiors, etc.
Rocket silos, artillery, telescopes, and space elevators may not be appropriate here.
"moving-tile"
-- local collision_mask_moving_tile = get_make_named_collision_mask("moving-tile")
Tiles that might change surface, such as spaceship tiles or warp structures.
"void-tile"
-- local collision_mask_void_tile = get_make_named_collision_mask("void-tile")
Tiles where there is a drop in to the ground (so you can't walk over or build on) but you can fly/jump over.
]]
local collision_flags =
{
"consider-tile-transitions",
"not-colliding-with-itself",
"colliding-with-tiles-only"
}
collision_mask_util_extended.collision_flags = table.deepcopy(collision_flags)
collision_mask_util_extended.vanilla_named_collision_masks = {
["ground-tile"] = "ground-tile",
["water-tile"] = "water-tile",
["resource-layer"] = "resource-layer",
["doodad-layer"] = "doodad-layer",
["floor-layer"] = "floor-layer",
["item-layer"] = "item-layer",
["ghost-layer"] = "ghost-layer",
["object-layer"] = "object-layer",
["player-layer"] = "player-layer",
["train-layer"] = "train-layer",
["rail-layer"] = "rail-layer",
["transport-belt-layer"] = "transport-belt-layer"
}
-- fix issue reported in F1.1.5
collision_mask_util_extended.get_default_mask_vanilla = collision_mask_util_extended.get_default_mask
collision_mask_util_extended.get_default_mask = function (type)
if type == "unit" then
return {"player-layer", "train-layer", "not-colliding-with-itself"}
else
return collision_mask_util_extended.get_default_mask_vanilla(type)
end
end
collision_mask_util_extended.get_default_hit_mask = function (type)
if type == "projectile" then
return {"player-layer", "train-layer", "object-layer",
collision_mask_util_extended.get_make_named_collision_mask("flying-layer"),
collision_mask_util_extended.get_make_named_collision_mask("projectile-layer"),
collision_mask_util_extended.get_make_named_collision_mask("vehicle-layer"),
"not-colliding-with-itself"}
else
return {}
end
end
_named_collision_masks = _named_collision_masks or table.deepcopy(collision_mask_util_extended.vanilla_named_collision_masks) -- do not modify directly
named_collision_masks = table.deepcopy(_named_collision_masks) -- readonly
collision_mask_util_extended.named_collision_masks = named_collision_masks
-- tracks mod layers only. format: named_collision_masks[mask_name] == "layer-"..x
function collision_mask_util_extended.get_named_collision_mask(mask_name)
return _named_collision_masks[mask_name]
end
function collision_mask_util_extended.get_make_named_collision_mask(mask_name)
local layer = collision_mask_util_extended.get_named_collision_mask(mask_name)
if not layer then
layer = collision_mask_util_extended.get_first_unused_layer()
--log("Named collision layer ["..mask_name .."] set to layer ["..layer.."]")
data:extend({
{
type = "arrow",
name = "collision-mask-"..mask_name,
collision_mask = {layer},
flags = {"placeable-off-grid", "not-on-map"},
circle_picture = { filename = "__core__/graphics/empty.png", priority = "low", width = 1, height = 1},
arrow_picture = { filename = "__core__/graphics/empty.png", priority = "low", width = 1, height = 1}
}
})
end
_named_collision_masks[mask_name] = layer
named_collision_masks = table.deepcopy(_named_collision_masks) -- readonly
collision_mask_util_extended.named_collision_masks = named_collision_masks
return layer
end
function collision_mask_util_extended.named_collision_mask_integrity_check()
-- This function will check that collision mask marker objects have 1 collision mask
for mask_name, layer_name in pairs(_named_collision_masks) do
if not collision_mask_util_extended.vanilla_named_collision_masks[mask_name] then
local mask_bearer = data.raw.arrow["collision-mask-"..mask_name]
local layer
if mask_bearer then
if mask_bearer.collision_mask then
for i, mask in pairs(mask_bearer.collision_mask) do
if i == 1 then
if mask == "not-colliding-with-itself"
or mask == "consider-tile-transitions"
or mask == "colliding-with-tiles-only" then
error("\n\n\nA reserved collision mask object "..mask_name.." has been compromised by 1 or more of your installed mods. Collision mask must be a collision layer, not a collision option.\n\n")
end
layer = mask
else
error("\n\n\nA reserved collision mask object "..mask_name.." has been compromised by 1 or more of your installed mods. Object must have only 1 collision mask.\n\n")
end
end
else
error("\n\n\nA reserved collision mask object "..mask_name.." has been compromised by 1 or more of your installed mods. Object is missing collision_mask.\n\n")
end
else
error("\n\n\nA reserved collision mask object "..mask_name.." has been removed.\n\n")
end
end
end
end
function collision_mask_util_extended.is_mask_empty(mask)
for _, layer in pairs(mask) do
local is_flag = false
for _, option in pairs(collision_flags) do
if layer == option then
is_flag = true
end
end
if not is_flag then
return false
end
end
return true
end
return collision_mask_util_extended