198 lines
8.7 KiB
Lua
198 lines
8.7 KiB
Lua
-- source: combat-mechanics-overhaul mod
|
|
-- 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
|