myspace / Lua /BurningMaps.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
5.6 kB
MapVar("g_Fire", {})
MapVar("g_DistToFire", {})
local burn_active_terrain = "Dry_BurntGround_01"
local burn_inactive_terrain = "Dry_BurntGround_02"
local burn_terrain_radius = 3 * guim / 2
local toggledEnumFlags = const.efVisible + const.efWalkable + const.efCollision + const.efApplyToGrids
const.VoxelFireMaxDist = 5*guim
const.VoxelFireRange = MulDivRound(const.SlabSizeX, 200, 100)
const.BurnDamageMin = 1
const.BurnDamageMax = 5
local VoxelFireRange = const.VoxelFireRange
local VoxelFireMaxDist = const.VoxelFireMaxDist
function IsBurnActiveCollection(col)
return not not string.match(string.lower(col.Name), "col_burn_active")
end
function IsBurnInactiveCollection(col)
return not not string.match(string.lower(col.Name), "col_burn_inactive")
end
function UpdateMapBurningState(burning)
NetUpdateHash("UpdateMapBurningState")
local active_func = burning and CObject.SetEnumFlags or CObject.ClearEnumFlags
local inactive_func = burning and CObject.ClearEnumFlags or CObject.SetEnumFlags
local terrain_old = Presets.TerrainObj.Default[burning and burn_inactive_terrain or burn_active_terrain].idx
local terrain_new = Presets.TerrainObj.Default[burning and burn_active_terrain or burn_inactive_terrain].idx
g_Fire = {}
g_DistToFire = {}
local queue = {}
for _, col in pairs(Collections) do
if IsBurnActiveCollection(col) then
MapForEach("map", "collection", col.Index, true, function(obj)
active_func(obj, toggledEnumFlags)
if IsKindOf(obj, "ParSystem") and string.match(obj:GetParticlesName(), "Fire") then
local pos = obj:GetPos()
local vx, vy, vz = WorldToVoxel(pos)
local packed_pos = point_pack(vx, vy, vz)
g_Fire[packed_pos] = GameState.Burning or nil
g_DistToFire[packed_pos] = GameState.Burning and 0 or nil
queue[#queue+1] = packed_pos
terrain.ReplaceTypeCircle(pos, burn_terrain_radius, terrain_old, terrain_new)
end
end)
elseif IsBurnInactiveCollection(col) then
MapForEach("map", "collection", col.Index, true, function(obj)
inactive_func(obj, toggledEnumFlags)
end)
end
end
for _, area in ipairs(g_FireAreas) do
for _, pos in ipairs(area.fire_positions) do
local vx, vy, vz = WorldToVoxel(pos)
local packed_pos = point_pack(vx, vy, vz)
g_Fire[packed_pos] = true
g_DistToFire[packed_pos] = 0
queue[#queue+1] = packed_pos
end
end
-- precalc fire adjacency up to VoxelFireMaxDist
local qi = 1
while qi < #queue do
local ppos = queue[qi]
local dist = g_DistToFire[ppos]
local x, y, z = point_unpack(ppos)
local adj, adj_dist
if dist then
adj_dist = dist + const.SlabSizeX
if adj_dist < VoxelFireMaxDist then
adj = point_pack(x + 1, y, z)
if not g_DistToFire[adj] or g_DistToFire[adj] > adj_dist then
g_DistToFire[adj] = adj_dist
queue[#queue + 1] = adj
end
adj = point_pack(x - 1, y, z)
if not g_DistToFire[adj] or g_DistToFire[adj] > adj_dist then
g_DistToFire[adj] = adj_dist
queue[#queue + 1] = adj
end
end
adj_dist = dist + const.SlabSizeY
if adj_dist < VoxelFireMaxDist then
adj = point_pack(x, y + 1, z)
if not g_DistToFire[adj] or g_DistToFire[adj] > adj_dist then
g_DistToFire[adj] = adj_dist
queue[#queue + 1] = adj
end
adj = point_pack(x, y - 1, z)
if not g_DistToFire[adj] or g_DistToFire[adj] > adj_dist then
g_DistToFire[adj] = adj_dist
queue[#queue + 1] = adj
end
end
adj_dist = dist + const.SlabSizeZ
if adj_dist < VoxelFireMaxDist then
adj = point_pack(x, y, z + 1)
if not g_DistToFire[adj] or g_DistToFire[adj] > adj_dist then
g_DistToFire[adj] = adj_dist
queue[#queue + 1] = adj
end
adj = point_pack(x, y, z - 1)
if not g_DistToFire[adj] or g_DistToFire[adj] > adj_dist then
g_DistToFire[adj] = adj_dist
queue[#queue + 1] = adj
end
end
end
qi = qi + 1
end
UpdatePassType()
end
function OnMsg.GameStateChanged(changed)
if changed.FireStorm ~= nil then
UpdateMapBurningState(GameState.FireStorm)
end
end
function OnMsg.EnterSector()
UpdateMapBurningState(GameState.FireStorm)
end
function AreVoxelsInFireRange(voxels, range)
range = range or VoxelFireRange
-- check for fires in voxels around the unit, considering all voxels occupied by that unit
for _, voxel in ipairs(voxels) do
local dist = g_DistToFire[voxel]
if dist and dist < range then
return true, dist
end
end
end
MapVar("g_dbgFireVisuals", false)
function ToggleFiresDebug()
if g_dbgFireVisuals then
for _, obj in ipairs(g_dbgFireVisuals) do
DoneObject(obj)
end
g_dbgFireVisuals = false
return
end
g_dbgFireVisuals = {}
local voxel_box = box(point(-const.SlabSizeX/2, -const.SlabSizeY/2, 0), point(const.SlabSizeX/2, const.SlabSizeY/2, const.SlabSizeZ))
for ppos, _ in pairs(g_Fire) do
local pt = point(VoxelToWorld(point_unpack(ppos)))
if not pt:IsValidZ() then
pt = pt:SetTerrainZ()
end
local fire_box = voxel_box + pt
local mesh = PlaceBox(fire_box, const.clrOrange, nil, false)
table.insert(g_dbgFireVisuals, mesh)
end
for _, unit in ipairs(g_Units) do
local voxels = unit:GetVisualVoxels()
local adjacent, dist = AreVoxelsInFireRange(voxels)
for _, voxel in ipairs(voxels) do
local pt = point(VoxelToWorld(point_unpack(voxel)))
local unit_box = voxel_box + pt
local color = const.clrWhite
if adjacent and dist < const.SlabSizeX then
color = const.clrRed
elseif adjacent then
color = const.clrYellow
end
local mesh = PlaceBox(unit_box, color, nil, false)
table.insert(g_dbgFireVisuals, mesh)
end
end
end