-
Notifications
You must be signed in to change notification settings - Fork 199
/
markdown.lua
142 lines (115 loc) · 5.07 KB
/
markdown.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
-- Save the description of a selected unit or item in Markdown file in UTF-8
-- This script extracts the description of a selected unit or item and saves it
-- as a Markdown file encoded in UTF-8 in the root game directory.
local gui = require('gui')
local argparse = require('argparse')
-- Get world name for default filename
local worldName = dfhack.df2utf(dfhack.TranslateName(df.global.world.world_data.name)):gsub(" ", "_")
local help, overwrite, filenameArg = false, false, nil
local positionals = argparse.processArgsGetopt({ ... }, {
{'o', 'overwrite', handler=function() overwrite = true end},
{'h', 'help', handler=function() help = true end},
})
-- Extract non-option arguments (filename)
filenameArg = positionals[1]
if help then
print(dfhack.script_help())
return
end
-- Determine write mode and filename
local writemode = overwrite and 'w' or 'a'
local filename = 'markdown_' .. (filenameArg or worldName) .. '.md'
-- Utility functions
local function getFileHandle()
local handle, error = io.open(filename, writemode)
if not handle then
qerror("Error opening file: " .. filename .. ". " .. error)
end
return handle
end
local function closeFileHandle(handle)
handle:write('\n---\n\n')
handle:close()
if writemode == 'a' then
print('\nData appended to "' .. 'Dwarf Fortress/' .. filename .. '"')
elseif writemode == 'w' then
print('\nData overwritten in "' .. 'Dwarf Fortress/' .. filename .. '"')
end
end
local function reformat(str)
-- [B] tags seem to indicate a new paragraph
-- [R] tags seem to indicate a sub-blocks of text.Treat them as paragraphs.
-- [P] tags seem to be redundant
-- [C] tags indicate color. Remove all color information
return str:gsub('%[B%]', '\n\n')
:gsub('%[R%]', '\n\n')
:gsub('%[P%]', '')
:gsub('%[C:%d+:%d+:%d+%]', '')
:gsub('\n\n+', '\n\n')
end
local function getNameRaceAgeProf(unit)
--%s is a placeholder for a string, and %d is a placeholder for a number.
return string.format("%s, %d years old %s.", dfhack.units.getReadableName(unit), df.global.cur_year - unit
.birth_year, dfhack.units.getProfessionName(unit))
end
-- Main logic for item and unit processing
local item = dfhack.gui.getSelectedItem(true)
local unit = dfhack.gui.getSelectedUnit(true)
if not item and not unit then
dfhack.printerr([[
Error: No unit or item is currently selected.
- To select a unit, click on it.
- For items that are installed as buildings (like statues or beds),
open the building's interface and click the magnifying glass icon.
Please select a valid target and try running the script again.]])
-- Early return to avoid proceeding further if no unit or item is selected
return
end
local log = getFileHandle()
local gps = df.global.gps
local mi = df.global.game.main_interface
if item then
-- Item processing
local itemRawName = dfhack.items.getDescription(item, 0, true)
local itemRawDescription = mi.view_sheets.raw_description
log:write('### ' ..
dfhack.df2utf(itemRawName) .. '\n\n#### Description: \n' .. reformat(dfhack.df2utf(itemRawDescription)) .. '\n')
print('Exporting description of the ' .. itemRawName)
elseif unit then
-- Unit processing
-- Simulate UI interactions to load data into memory (click through tabs). Note: Constant might change with DF updates/patches
local is_adv = dfhack.world.isAdventureMode()
local screen = dfhack.gui.getDFViewscreen()
local windowSize = dfhack.screen.getWindowSize()
-- Click "Personality"
local personalityWidthConstant = is_adv and 68 or 48
local personalityHeightConstant = is_adv and 13 or 11
gps.mouse_x = windowSize - personalityWidthConstant
gps.mouse_y = personalityHeightConstant
gui.simulateInput(screen, '_MOUSE_L')
-- Click "Health"
local healthWidthConstant = 74
local healthHeightConstant = is_adv and 15 or 13
gps.mouse_x = windowSize - healthWidthConstant
gps.mouse_y = healthHeightConstant
gui.simulateInput(screen, '_MOUSE_L')
-- Click "Health/Description"
local healthDescriptionWidthConstant = is_adv and 74 or 51
local healthDescriptionHeightConstant = is_adv and 17 or 15
gps.mouse_x = windowSize - healthDescriptionWidthConstant
gps.mouse_y = healthDescriptionHeightConstant
gui.simulateInput(screen, '_MOUSE_L')
local unit_description_raw = #mi.view_sheets.unit_health_raw_str > 0 and mi.view_sheets.unit_health_raw_str[0].value or ''
local unit_personality_raw = mi.view_sheets.personality_raw_str
log:write('### ' ..
dfhack.df2utf(getNameRaceAgeProf(unit)) ..
'\n\n#### Description: \n' .. reformat(dfhack.df2utf(unit_description_raw)) .. '\n')
if #unit_personality_raw > 0 then
log:write('\n#### Personality: \n')
for _, unit_personality in ipairs(unit_personality_raw) do
log:write(reformat(dfhack.df2utf(unit_personality.value)) .. '\n')
end
end
print('Exporting Health/Description & Personality/Traits data for: \n' .. dfhack.df2console(getNameRaceAgeProf(unit)))
end
closeFileHandle(log)