-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlayer-occupancy.lua
More file actions
110 lines (84 loc) · 3.1 KB
/
layer-occupancy.lua
File metadata and controls
110 lines (84 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
-- Fix occupancy flags at a given tile
--[====[
fix/tile-occupancy
==================
Clears bad occupancy flags at the selected tile. Useful for getting rid of
phantom "building present" messages. Currently only supports issues with
building and unit occupancy. Requires that a tile is selected with the in-game
cursor (``k``).
Can be used to fix problematic tiles caused by :issue:`1047`.
SWD Hacked to use current designation selection box if active, current layer if not.
]====]
if #{...} > 0 then
qerror('This script takes no arguments.')
end
-- local _, plotinfo = pcall(function() return df.global.ui; end)
-- if not _ then _, plotinfo = pcall(function() return df.global.plotinfo; end) end
local function xyz2str(x,y,z)
if not x or not y or not z then qerror('not enough parameters'); end
x = tonumber(x); y = tonumber(y); z = tonumber(z)
if not x or not y or not z then qerror('invalid number'); end
return(("%d,%d,%d"):format(x,y,z))
end
--[[
function findUnit(x, y, z)
for _, u in pairs(df.global.world.units.active) do
if u.pos.x == x and u.pos.y == y and u.pos.z == z
and u.flags1.inactive == false
-- SWD it can happen that .inactive is true, when the unit is immigrating
-- or returning from a mission.
-- SWD or leaving on a mission but not yet removed from .units.all .
-- SWD TODO did I mean units.active?
then
return true
end
end
return false
end
]]
function report(flag, x, y, z)
print(('Cleared occupancy flag %s at (%s).'):format(flag, xyz2str(x,y,z)))
changed = true
end
-- it's a table<strpos, true>. If the key exists, a unit is on that tile.
---@type table<string, boolean>[]
local occupied = {}
for _, u in pairs(df.global.world.units.active) do
if u.flags1.inactive and not u.flags2.killed then
print(('Unit %d inactive.'):format(u.id))
elseif dfhack.units.getGeneralRef(u, df.general_ref_type.CONTAINED_IN_ITEM) ~= nil then
-- in a cage; do nothing.
elseif u.pos.x == -30000 then
print(('Unit %d not on map.'):format(u.id))
else
occupied[xyz2str(pos2xyz(u.pos))] = true
end
end
local changed = false
local startx = 0; local endx = df.global.world.map.x_count-1
local starty = 0; local endy = df.global.world.map.y_count-1
local z = df.global.window_z
if df.global.selection_rect.start_x ~= -30000 then
startx = df.global.selection_rect.start_x
starty = df.global.selection_rect.start_y
endx = df.global.cursor.x
endy = df.global.cursor.y
if endx < startx then startx, endx = endx, startx; end
if endy < starty then starty, endy = endy, starty; end
end
for x = startx, endx do
for y = starty, endy do
-- TODO cache
local occ = dfhack.maps.getTileBlock(x, y, z).occupancy[x % 16][y % 16]
if occ.building ~= df.tile_building_occ.None and not dfhack.buildings.findAtTile(x, y, z) then
occ.building = df.tile_building_occ.None
report('building', x, y, z)
end
for _, flag in pairs{'unit', 'unit_grounded'} do
if occ[flag] and not occupied[xyz2str(x,y,z)] then
occ[flag] = false
report(flag, x, y, z)
end
end
end -- y
end -- x