-
Notifications
You must be signed in to change notification settings - Fork 200
/
Copy pathchoose-weapons.lua
169 lines (149 loc) · 5.23 KB
/
choose-weapons.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
-- Rewrite individual choice weapons to specific types
--[====[
gui/choose-weapons
==================
Bind to a key (the example config uses :kbd:`Ctrl`:kbd:`W`), and activate in the Equip->View/Customize
page of the military screen.
Depending on the cursor location, it rewrites all 'individual choice weapon' entries
in the selected squad or position to use a specific weapon type matching the assigned
unit's top skill. If the cursor is in the rightmost list over a weapon entry, it rewrites
only that entry, and does it even if it is not 'individual choice'.
Rationale: individual choice seems to be unreliable when there is a weapon shortage,
and may lead to inappropriate weapons being selected.
]====]
local utils = require 'utils'
local dlg = require 'gui.dialogs'
local defs = df.global.world.raws.itemdefs
local entity = df.global.ui.main.fortress_entity
local tasks = df.global.ui.tasks
local equipment = df.global.ui.equipment
function find_best_weapon(unit,mode)
local best = nil
local skill = nil
local skill_level = nil
local count = 0
local function try(id,iskill)
local slevel = dfhack.units.getNominalSkill(unit,iskill)
-- Choose most skill
if (skill ~= nil and slevel > skill_level)
or (skill == nil and slevel > 0) then
best,skill,skill_level,count = id,iskill,slevel,0
end
-- Then most produced within same skill
if skill == iskill then
local cnt = tasks.created_weapons[id]
if cnt > count then
best,count = id,cnt
end
end
end
for _,id in ipairs(entity.resources.weapon_type) do
local def = defs.weapons[id]
if def.skill_ranged >= 0 then
if mode == nil or mode == 'ranged' then
try(id, def.skill_ranged)
end
else
if mode == nil or mode == 'melee' then
try(id, def.skill_melee)
end
end
end
return best
end
function unassign_wrong_items(unit,position,spec,subtype)
for i=#spec.assigned-1,0,-1 do
local id = spec.assigned[i]
local item = df.item.find(id)
if item.subtype.subtype ~= subtype then
spec.assigned:erase(i)
-- TODO: somewhat unexplored area; maybe missing some steps
utils.erase_sorted(position.assigned_items,id)
if utils.erase_sorted(equipment.items_assigned.WEAPON,item,'id') then
utils.insert_sorted(equipment.items_unassigned.WEAPON,item,'id')
end
equipment.update.weapon = true
unit.military.pickup_flags.update = true
end
end
end
local count = 0
function adjust_uniform_spec(unit,position,spec,force)
if not unit then return end
local best
if spec.indiv_choice.melee then
best = find_best_weapon(unit, 'melee')
elseif spec.indiv_choice.ranged then
best = find_best_weapon(unit, 'ranged')
elseif spec.indiv_choice.any or force then
best = find_best_weapon(unit, nil)
end
if best then
count = count + 1
spec.item_filter.item_subtype = best
spec.indiv_choice.any = false
spec.indiv_choice.melee = false
spec.indiv_choice.ranged = false
unassign_wrong_items(unit, position, spec, best)
end
end
function adjust_position(unit,position,force)
if not unit then
local fig = df.historical_figure.find(position.occupant)
if not fig then return end
unit = df.unit.find(fig.unit_id)
end
for _,v in ipairs(position.uniform.weapon) do
adjust_uniform_spec(unit, position, v, force)
end
end
function adjust_squad(squad, force)
for _,pos in ipairs(squad.positions) do
adjust_position(nil, pos, force)
end
end
local args = {...}
local vs = dfhack.gui.getCurViewscreen()
local vstype = df.viewscreen_layer_militaryst
if not vstype:is_instance(vs) then
qerror('Call this from the military screen')
end
if vs.page == vstype.T_page.Equip
and vs.equip.mode == vstype.T_equip.T_mode.Customize then
local slist = vs.layer_objects[0]
local squad = vs.equip.squads[slist:getListCursor()]
if slist.active then
print('Adjusting squad.')
adjust_squad(squad)
else
local plist = vs.layer_objects[1]
local pidx = plist:getListCursor()
local pos = squad.positions[pidx]
local unit = vs.equip.units[pidx]
if plist.active then
print('Adjusting position.')
adjust_position(unit, pos)
elseif unit and vs.equip.edit_mode < 0 then
local wlist = vs.layer_objects[2]
local idx = wlist:getListCursor()
local cat = vs.equip.assigned.category[idx]
if wlist.active and cat == df.uniform_category.weapon then
print('Adjusting spec.')
adjust_uniform_spec(unit, pos, vs.equip.assigned.spec[idx], true)
end
end
end
else
qerror('Call this from the Equip page of military screen')
end
if count > 1 then
dlg.showMessage(
'Choose Weapons',
'Updated '..count..' uniform entries.', COLOR_GREEN
)
elseif count == 0 then
dlg.showMessage(
'Choose Weapons',
'Did not find any entries to update.', COLOR_YELLOW
)
end