forked from DFHack/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeathcause.lua
More file actions
182 lines (156 loc) · 5.91 KB
/
deathcause.lua
File metadata and controls
182 lines (156 loc) · 5.91 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
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
-- show death cause of a creature
local guidm = require('gui.dwarfmode')
local DEATH_TYPES = reqscript('gui/unit-info-viewer').DEATH_TYPES
-- Gets the first corpse item at the given location
function getItemAtPosition(pos)
for _, item in ipairs(df.global.world.items.other.ANY_CORPSE) do
if item.pos.x == pos.x and item.pos.y == pos.y and item.pos.z == pos.z then
print("Automatically chose first corpse at the selected location.")
return item
end
end
end
function getRaceNameSingular(race_id)
return df.creature_raw.find(race_id).name[0]
end
function getDeathStringFromCause(cause)
if cause == -1 then
return "died"
else
return DEATH_TYPES[cause]:trim()
end
end
function displayDeathUnit(unit)
local str = ("The %s"):format(getRaceNameSingular(unit.race))
if unit.name.has_name then
str = str .. (" %s"):format(dfhack.TranslateName(unit.name))
end
if not dfhack.units.isDead(unit) then
print(str .. " is not dead yet!")
return
end
str = str .. (" %s"):format(getDeathStringFromCause(unit.counters.death_cause))
local incident = df.incident.find(unit.counters.death_id)
if incident then
str = str .. (" in year %d"):format(incident.event_year)
if incident.criminal then
local killer = df.unit.find(incident.criminal)
if killer then
str = str .. (" killed by the %s"):format(getRaceNameSingular(killer.race))
if killer.name.has_name then
str = str .. (" %s"):format(dfhack.TranslateName(killer.name))
end
end
end
end
print(str .. '.')
end
-- returns the item description if the item still exists; otherwise
-- returns the weapon name
function getWeaponName(item_id, subtype)
local item = df.item.find(item_id)
if not item then
return df.global.world.raws.itemdefs.weapons[subtype].name
end
return dfhack.items.getDescription(item, 0, false)
end
function displayDeathEventHistFigUnit(histfig_unit, event)
local str = ("The %s %s %s in year %d"):format(
getRaceNameSingular(histfig_unit.race),
dfhack.TranslateName(histfig_unit.name),
getDeathStringFromCause(event.death_cause),
event.year
)
local slayer_histfig = df.historical_figure.find(event.slayer_hf)
if slayer_histfig then
str = str .. (", killed by the %s %s"):format(
getRaceNameSingular(slayer_histfig.race),
dfhack.TranslateName(slayer_histfig.name)
)
end
if event.weapon then
if event.weapon.item_type == df.item_type.WEAPON then
str = str .. (", using a %s"):format(getWeaponName(event.weapon.item, event.weapon.item_subtype))
elseif event.weapon.shooter_item_type == df.item_type.WEAPON then
str = str .. (", shot by a %s"):format(getWeaponName(event.weapon.shooter_item, event.weapon.shooter_item_subtype))
end
end
print(str .. '.')
end
-- Returns the death event for the given histfig or nil if not found
function getDeathEventForHistFig(histfig_id)
for i = #df.global.world.history.events - 1, 0, -1 do
local event = df.global.world.history.events[i]
if event:getType() == df.history_event_type.HIST_FIGURE_DIED then
if event.victim_hf == histfig_id then
return event
end
end
end
return nil
end
function displayDeathHistFig(histfig)
local histfig_unit = df.unit.find(histfig.unit_id)
if not histfig_unit then
qerror("Cause of death not available")
end
if not dfhack.units.isDead(histfig_unit) then
print(("%s is not dead yet!"):format(dfhack.TranslateName(histfig_unit.name)))
else
local death_event = getDeathEventForHistFig(histfig.id)
displayDeathEventHistFigUnit(histfig_unit, death_event)
end
end
local function is_corpse_item(item)
if not item then return false end
local itype = item:getType()
return itype == df.item_type.CORPSE or itype == df.item_type.CORPSEPIECE
end
local selected_item = dfhack.gui.getSelectedItem(true)
local selected_unit = dfhack.gui.getSelectedUnit(true)
if not selected_unit and not selected_item then
local pos
if not selected_item and
dfhack.gui.matchFocusString('dwarfmode/ViewSheets/ITEM_LIST', dfhack.gui.getDFViewscreen(true)) and
#df.global.game.main_interface.view_sheets.viewing_itid > 0
then
selected_item = df.item.find(df.global.game.main_interface.view_sheets.viewing_itid[0])
elseif selected_item then
pos = xyz2pos(dfhack.items.getPosition(selected_item))
end
if not selected_item then
pos = guidm.getCursorPos()
end
if pos then
-- if there isn't a selected unit and we don't have a selected item or the selected item is not a corpse
-- let's try to look for corpses at the same location because it's probably what the user wants
-- we will just grab the first one as it's the best we can do
selected_item = getItemAtPosition(pos)
end
end
if not selected_unit and not is_corpse_item(selected_item) then
if df.item_remainsst:is_instance(selected_item) then
print(("The %s died."):format(getRaceNameSingular(selected_item.race)))
return
end
qerror("Please select a corpse")
end
local hist_figure_id
if selected_item then
hist_figure_id = selected_item.hist_figure_id
elseif selected_unit then
hist_figure_id = selected_unit.hist_figure_id
end
if not hist_figure_id then
qerror("Cause of death not available")
elseif hist_figure_id == -1 then
if not selected_unit then
selected_unit = df.unit.find(selected_item.unit_id)
if not selected_unit then
qerror("Cause of death not available")
end
end
displayDeathUnit(selected_unit)
else
displayDeathHistFig(df.historical_figure.find(hist_figure_id))
end