forked from DFHack/scripts
-
Notifications
You must be signed in to change notification settings - Fork 1
/
assign-goals.lua
173 lines (142 loc) · 5.68 KB
/
assign-goals.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
-- Change the goals of a unit.
--@ module = true
local help = [====[
assign-goals
============
A script to change the goals (dreams) of a unit.
Goals are defined with the goal token and a true/false value
that describes whether or not the goal has been accomplished. Be
advised that this last feature has not been properly tested and
might be potentially destructive: I suggest leaving it at false.
For a list of possible goals:
https://dwarffortresswiki.org/index.php/DF2014:Personality_trait#Goals
Bear in mind that nothing will stop you from assigning zero or
more than one goal, but it's not clear how it will affect the game.
Usage:
``-help``:
print the help page.
``-unit <UNIT_ID>``:
set the target unit ID. If not present, the
currently selected unit will be the target.
``-goals [ <GOAL> <REALIZED_FLAG> <GOAL> <REALIZED_FLAG> <...> ]``:
the goals to modify/add and whether they have
been realized or not. The valid goal tokens
can be found in the wiki page linked above.
The flag must be a true/false value.
There must be a space before and after each square
bracket.
``-reset``:
clear all goals. If the script is called with
both this option and a list of goals, first all
the unit goals will be erased and then those
goals listed after ``-goals`` will be added.
Example::
assign-goals -reset -goals [ MASTER_A_SKILL false ]
Clears all the unit goals, then sets the "master a skill" goal. The final result
will be: "dreams of mastering a skill".
]====]
local utils = require("utils")
local valid_args = utils.invert({
'help',
'unit',
'goals',
'reset',
})
-- ----------------------------------------------- UTILITY FUNCTIONS ------------------------------------------------ --
local function print_yellow(text)
dfhack.color(COLOR_YELLOW)
print(text)
dfhack.color(-1)
end
-- ------------------------------------------------- ASSIGN GOALS ------------------------------------------------- --
-- NOTE: in the game data, goals are called both dreams and goals.
--- Assign the given goals to a unit, clearing all the other goals if requested.
--- :goals: nil, or a table. The fields have the goal name as key and true/false as value.
--- :unit: a valid unit id, a df.unit object, or nil. If nil, the currently selected unit will be targeted.
--- :reset: boolean, or nil.
function assign(goals, unit, reset)
assert(not goals or type(goals) == "table")
assert(not unit or type(unit) == "number" or type(unit) == "userdata")
assert(not reset or type(reset) == "boolean")
goals = goals or {}
reset = reset or false
if type(unit) == "number" then
unit = df.unit.find(tonumber(unit)) --luacheck:retype
end
unit = unit or dfhack.gui.getSelectedUnit(true)
if not unit then
qerror("No unit found.")
end
-- erase goals
if reset then
unit.status.current_soul.personality.dreams = {}
end
--assign goals
for goal, realized in pairs(goals) do
assert(type(realized) == "boolean")
goal = goal:upper()
if df.goal_type[goal] then
utils.insert_or_update(unit.status.current_soul.personality.dreams,
{ new = true, type = df.goal_type[goal], unk8 = realized and 1 or 0 },
"type")
else
print_yellow("WARNING: '" .. goal .. "' is not a valid goal token. Skipping...")
end
end
end
-- ------------------------------------------------------ MAIN ------------------------------------------------------ --
local function main(...)
local function is_flag(string)
return string:upper() == "TRUE" or string:upper() == "FALSE"
end
local args = utils.processArgs({ ... }, valid_args)
if args.help then
print(help)
return
end
local unit
if args.unit then
unit = tonumber(args.unit)
if not unit then
qerror("'" .. args.unit .. "' is not a valid unit ID.")
end
end
local reset = false
if args.reset then
reset = true
end
-- parse goals list
local goals = {}
if args.goals then
local i = 1
while i <= #args.goals do
local v = args.goals[i]
-- v can be a goal name but it can also be a boolean flag, so we have to check
if not is_flag(v) then
-- assume it's a valid goal name, for now
local goal_name = tostring(v):upper()
-- then try to get the boolean flag
local flag_str = args.goals[i + 1]
if not flag_str then
-- we reached the end of the goals list
qerror("Missing realized flag after '" .. v .. "'.")
end
local flag_bool
if flag_str:upper() == "TRUE" then
flag_bool = true
elseif flag_str:upper() == "FALSE" then
flag_bool = false
end
if flag_bool == nil then
qerror("'" .. flag_str .. "' is not a true or false value.")
end
goals[goal_name] = flag_bool
end
i = i + 1 -- skip next arg because we already consumed it
end
end
assign(goals, unit, reset)
end
if not dfhack_flags.module then
main(...)
end