-
Notifications
You must be signed in to change notification settings - Fork 200
/
Copy pathroom-list.lua
259 lines (222 loc) · 7.68 KB
/
room-list.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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
-- Browses rooms owned by a unit.
--[====[
gui/room-list
=============
To use, bind to a key (the example config uses :kbd:`Alt`:kbd:`R`) and activate in :kbd:`q` mode,
either immediately or after opening the assign owner page.
.. image:: /docs/images/room-list.png
The script lists other rooms owned by the same owner, or by the unit selected in the assign
list, and allows unassigning them.
]====]
local utils = require 'utils'
local gui = require 'gui'
local guidm = require 'gui.dwarfmode'
local room_type_table = {
[df.building_bedst] = { token = 'bed', qidx = 2, tile = 233 },
[df.building_tablest] = { token = 'table', qidx = 3, tile = 209 },
[df.building_chairst] = { token = 'chair', qidx = 4, tile = 210 },
[df.building_coffinst] = { token = 'coffin', qidx = 5, tile = 48 },
}
local room_quality_table = {
{ 1, 'Meager Quarters', 'Meager Dining Room', 'Meager Office', 'Grave' },
{ 100, 'Modest Quarters', 'Modest Dining Room', 'Modest Office', "Servant's Burial Chamber" },
{ 250, 'Quarters', 'Dining Room', 'Office', 'Burial Chamber' },
{ 500, 'Decent Quarters', 'Decent Dining Room', 'Decent Office', 'Tomb' },
{ 1000, 'Fine Quarters', 'Fine Dining Room', 'Splendid Office', 'Fine Tomb' },
{ 1500, 'Great Bedroom', 'Great Dining Room', 'Throne Room', 'Mausoleum' },
{ 2500, 'Grand Bedroom', 'Grand Dining Room', 'Opulent Throne Room', 'Grand Mausoleum' },
{ 10000, 'Royal Bedroom', 'Royal Dining Room', 'Royal Throne Room', 'Royal Mausoleum' }
}
function getRoomName(building, unit)
local info = room_type_table[building._type]
if not info or not building.is_room then
return utils.getBuildingName(building)
end
local quality = building:getRoomValue(unit)
local row = room_quality_table[1]
for _,v in ipairs(room_quality_table) do
if v[1] <= quality then
row = v
else
break
end
end
return row[info.qidx]
end
function makeRoomEntry(bld, unit, is_spouse)
local info = room_type_table[bld._type] or {}
return {
obj = bld,
token = info.token or '?',
tile = info.tile or '?',
caption = getRoomName(bld, unit),
can_use = (not is_spouse or bld:canUseSpouseRoom()),
owner = unit
}
end
function listRooms(unit, spouse)
local rv = {}
for _,v in pairs(unit.owned_buildings) do
if v.owner == unit then
rv[#rv+1] = makeRoomEntry(v, unit, spouse)
end
end
return rv
end
function concat_lists(...)
local rv = {}
for i = 1,select('#',...) do
local v = select(i,...)
if v then
for _,x in ipairs(v) do rv[#rv+1] = x end
end
end
return rv
end
RoomList = defclass(RoomList, guidm.MenuOverlay)
RoomList.focus_path = 'room-list'
RoomList.ATTRS{ unit = DEFAULT_NIL }
function RoomList:init(info)
local unit = info.unit
local base_bld = df.global.world.selected_building
self:assign{
base_building = base_bld,
items = {}, selected = 1,
own_rooms = {}, spouse_rooms = {}
}
self.old_viewport = self:getViewport()
self.old_cursor = guidm.getCursorPos()
if unit then
self.own_rooms = listRooms(unit)
self.spouse = df.unit.find(unit.relations.spouse_id)
if self.spouse then
self.spouse_rooms = listRooms(self.spouse, unit)
end
self.items = concat_lists(self.own_rooms, self.spouse_rooms)
end
if base_bld then
for i,v in ipairs(self.items) do
if v.obj == base_bld then
self.selected = i
v.tile = 26
goto found
end
end
self.base_item = makeRoomEntry(base_bld, unit)
self.base_item.owner = unit
self.base_item.old_owner = base_bld.owner
self.base_item.tile = 26
self.items = concat_lists({self.base_item}, self.items)
::found::
end
end
local sex_char = { [0] = 12, [1] = 11 }
function drawUnitName(dc, unit)
dc:pen(COLOR_GREY)
if unit then
local color = dfhack.units.getProfessionColor(unit)
dc:char(sex_char[unit.sex] or '?'):advance(1):pen(color)
local vname = dfhack.units.getVisibleName(unit)
if vname and vname.has_name then
dc:string(dfhack.TranslateName(vname)..', ')
end
dc:string(dfhack.units.getProfessionName(unit))
else
dc:string("No Owner Assigned")
end
end
function drawRoomEntry(dc, entry, selected)
local color = COLOR_GREEN
if not entry.can_use then
color = COLOR_RED
elseif entry.obj.owner ~= entry.owner or not entry.owner then
color = COLOR_CYAN
end
dc:pen{fg = color, bold = (selected == entry)}
dc:char(entry.tile):advance(1):string(entry.caption)
end
function can_modify(sel_item)
return sel_item and sel_item.owner
and sel_item.can_use and not sel_item.owner.flags1.dead
end
function RoomList:onRenderBody(dc)
local sel_item = self.items[self.selected]
dc:clear():seek(1,1)
drawUnitName(dc, self.unit)
if self.base_item then
dc:newline():newline(2)
drawRoomEntry(dc, self.base_item, sel_item)
end
if #self.own_rooms > 0 then
dc:newline()
for _,v in ipairs(self.own_rooms) do
dc:newline(2)
drawRoomEntry(dc, v, sel_item)
end
end
if #self.spouse_rooms > 0 then
dc:newline():newline(1)
drawUnitName(dc, self.spouse)
dc:newline()
for _,v in ipairs(self.spouse_rooms) do
dc:newline(2)
drawRoomEntry(dc, v, sel_item)
end
end
if self.unit and #self.own_rooms == 0 and #self.spouse_rooms == 0 then
dc:newline():newline(2):string("No already assigned rooms.", COLOR_LIGHTRED)
end
dc:newline():newline(1):pen(COLOR_WHITE)
dc:key('LEAVESCREEN'):string(": Back")
if can_modify(sel_item) then
dc:string(", "):key('SELECT')
if sel_item.obj.owner == sel_item.owner then
dc:string(": Unassign")
else
dc:string(": Assign")
end
end
end
function RoomList:changeSelected(delta)
if #self.items <= 1 then return end
self.selected = 1 + (self.selected + delta - 1) % #self.items
self:selectBuilding(self.items[self.selected].obj)
end
function RoomList:onInput(keys)
local sel_item = self.items[self.selected]
if keys.SECONDSCROLL_UP then
self:changeSelected(-1)
elseif keys.SECONDSCROLL_DOWN then
self:changeSelected(1)
elseif keys.LEAVESCREEN then
self:dismiss()
if self.base_building then
if not sel_item or self.base_building ~= sel_item.obj then
self:selectBuilding(self.base_building, self.old_cursor, self.old_view)
end
if self.unit and self.base_building.owner == self.unit then
df.global.ui_building_in_assign = false
end
end
elseif keys.SELECT then
if can_modify(sel_item) then
local owner = sel_item.owner
if sel_item.obj.owner == owner then
owner = sel_item.old_owner
end
dfhack.buildings.setOwner(sel_item.obj, owner)
end
elseif self:simulateViewScroll(keys) then
return
end
end
local focus = dfhack.gui.getCurFocus()
if focus == 'dwarfmode/QueryBuilding/Some/Assign/Unit' then
local unit = df.global.ui_building_assign_units[df.global.ui_building_item_cursor]
RoomList{ unit = unit }:show()
elseif string.match(dfhack.gui.getCurFocus(), '^dwarfmode/QueryBuilding/Some') then
local base = df.global.world.selected_building
RoomList{ unit = base.owner }:show()
else
qerror("This script requires the main dwarfmode view in 'q' mode")
end