-
Notifications
You must be signed in to change notification settings - Fork 199
/
unit-path.lua
227 lines (185 loc) · 6.58 KB
/
unit-path.lua
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
-- Show the internal path a unit is currently following.
--[====[
devel/unit-path
===============
Show the internal path a unit is currently following.
]====]
local utils = require 'utils'
local gui = require 'gui'
local guidm = require 'gui.dwarfmode'
local dlg = require 'gui.dialogs'
local tile_attrs = df.tiletype.attrs
UnitPathUI = defclass(UnitPathUI, guidm.MenuOverlay)
UnitPathUI.focus_path = 'unit-path'
local default_nil_unit = DEFAULT_NIL --as:df.unit
UnitPathUI.ATTRS {
unit = default_nil_unit,
has_path = false,
has_goal = false,
}
function UnitPathUI:init()
self.saved_mode = df.global.ui.main.mode
if self.unit then
self.has_path = #self.unit.path.path.x > 0
self.has_goal = self.unit.path.dest.x >= 0
end
end
function UnitPathUI:onShow()
-- with cursor, but without those ugly lines from native hauling mode
df.global.ui.main.mode = df.ui_sidebar_mode.Stockpiles
end
function UnitPathUI:onDestroy()
self:moveCursorTo(copyall(self.unit.pos))
df.global.ui.main.mode = self.saved_mode
end
local function getTileType(cursor)
local block = dfhack.maps.getTileBlock(cursor)
if block then
return block.tiletype[cursor.x%16][cursor.y%16]
else
return 0
end
end
local function getTileWalkable(cursor)
local block = dfhack.maps.getTileBlock(cursor)
if block then
return block.walkable[cursor.x%16][cursor.y%16]
else
return 0
end
end
local function paintMapTile(dc, vp, cursor, pos, ...)
if not same_xyz(cursor, pos) then
local stile = vp:tileToScreen(pos)
if stile.z == 0 then
dc:map(true):seek(stile.x,stile.y):char(...):map(false)
end
end
end
local function get_path_point(gpath,i)
return xyz2pos(gpath.x[i], gpath.y[i], gpath.z[i])
end
function UnitPathUI:renderPath(dc,vp,cursor)
local gpath = self.unit.path.path
local startp = self.unit.pos
local endp = self.unit.path.dest
local visible = gui.blink_visible(500)
if visible then
paintMapTile(dc, vp, cursor, endp, '+', COLOR_LIGHTGREEN)
end
local ok = nil
local pcnt = #gpath.x
if pcnt > 0 then
ok = true
for i = 0,pcnt-1 do
local pt = get_path_point(gpath, i)
if i == 0 and not same_xyz(startp,pt) then
ok = false
end
if i == pcnt-1 and not same_xyz(endp,pt) then
ok = false
end
--[[local tile = getTileType(pt)
if not isTrackTile(tile) then
ok = false
end]]
if visible then
local char = '+'
if i < pcnt-1 then
local npt = get_path_point(gpath, i+1)
if npt.z == pt.z+1 then
char = 30 --luacheck: retype
elseif npt.z == pt.z-1 then
char = 31 --luacheck: retype
elseif npt.x == pt.x+1 then
char = 26 --luacheck: retype
elseif npt.x == pt.x-1 then
char = 27 --luacheck: retype
elseif npt.y == pt.y+1 then
char = 25 --luacheck: retype
elseif npt.y == pt.y-1 then
char = 24 --luacheck: retype
end
end
local color = COLOR_LIGHTGREEN
if getTileWalkable(pt) == 0 then color = COLOR_LIGHTRED end
paintMapTile(dc, vp, cursor, pt, char, color)
end
end
end
if gui.blink_visible(120) then
paintMapTile(dc, vp, cursor, startp, 240, COLOR_LIGHTGREEN, COLOR_GREEN)
end
return ok
end
function UnitPathUI:onRenderBody(dc)
dc:clear():seek(1,1):pen(COLOR_WHITE):string("Unit Path")
local prof = dfhack.units.getProfessionName(self.unit)
local name = dfhack.units.getVisibleName(self.unit)
dc:seek(2,3):pen(COLOR_BLUE):string(prof)
if name and name.has_name then
dc:seek(2,4):pen(COLOR_BLUE):string(dfhack.TranslateName(name))
end
local cursor = guidm.getCursorPos()
local vp = self:getViewport()
local mdc = gui.Painter.new(self.df_layout.map)
if not self.has_path then
if gui.blink_visible(120) then
paintMapTile(mdc, vp, cursor, self.unit.pos, 15, COLOR_LIGHTRED, COLOR_RED)
end
dc:seek(1,6):pen(COLOR_RED):string('Not following path')
else
self:renderPath(mdc,vp,cursor)
dc:seek(1,6):pen(COLOR_GREEN):string(df.unit_path_goal[self.unit.path.goal] or '?')
end
dc:newline():pen(COLOR_GREY)
dc:newline(2):string('Speed: '..dfhack.units.computeMovementSpeed(self.unit))
dc:newline(2):string('Slowdown: '..dfhack.units.computeSlowdownFactor(self.unit))
dc:newline():newline(1)
local has_station = self.unit.idle_area_type >= 0
if has_station then
if gui.blink_visible(250) then
paintMapTile(mdc, vp, cursor, self.unit.idle_area, 21, COLOR_LIGHTCYAN)
end
dc:pen(COLOR_GREEN):string(df.unit_station_type[self.unit.idle_area_type])
dc:newline():newline(2):pen(COLOR_GREY):string('Threshold: '..self.unit.idle_area_threshold)
else
dc:pen(COLOR_RED):string('No station'):newline():newline(2)
end
dc:newline():newline(1):string('At cursor:')
dc:newline():newline(2)
local tile = getTileType(cursor)
dc:string(df.tiletype[tile],COLOR_CYAN)
dc:newline():newline(1):pen(COLOR_WHITE)
dc:key('CUSTOM_Z'):string(": Zoom unit, ")
dc:key('CUSTOM_G'):string(": Zoom goal",COLOR_GREY,nil,self.has_goal)
dc:newline(1)
dc:key('CUSTOM_N'):string(": Zoom station",COLOR_GREY,nil,has_station)
dc:newline():newline(1)
dc:key('LEAVESCREEN'):string(": Back")
end
function UnitPathUI:onInput(keys)
if keys.CUSTOM_Z then
self:moveCursorTo(copyall(self.unit.pos))
elseif keys.CUSTOM_G then
if self.has_goal then
self:moveCursorTo(copyall(self.unit.path.dest))
end
elseif keys.CUSTOM_N then
if self.unit.idle_area_type > 0 then
self:moveCursorTo(copyall(self.unit.idle_area))
end
elseif keys.LEAVESCREEN then
self:dismiss()
elseif self:propagateMoveKeys(keys) then
return
end
end
function UnitPathUI:onGetSelectedUnit()
return self.unit
end
local unit = dfhack.gui.getSelectedUnit(true)
if not unit or not string.match(dfhack.gui.getCurFocus(), '^dwarfmode/ViewUnits/Some/') then
qerror("This script requires the main dwarfmode view in 'v' mode with a unit selected")
end
UnitPathUI{ unit = unit }:show()