Repository navigation
Expand file tree
/
Copy pathuTextToMods.lua
More file actions
234 lines (227 loc) · 7.78 KB
/
Copy pathuTextToMods.lua
File metadata and controls
234 lines (227 loc) · 7.78 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
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
if not table.containsId then
dofile("Scripts/mods.lua")
end
-- Note that these will be normally commented out to prevent accidental legacy mod wording loss on export
-- (before legacy mods have been added to the uniques in src/Data)
local itemTypes = {
-- "axe",
-- "bow",
-- "claw",
-- "dagger",
-- "fishing",
-- "mace",
-- "staff",
-- "sword",
-- "wand",
-- "helmet",
-- "body",
-- "gloves",
-- "boots",
-- "shield",
-- "quiver",
-- "amulet",
-- "ring",
-- "belt",
-- "jewel",
-- "flask",
-- "tincture",
}
-- TODO: Remove this once we are exporting all item types
local itemTypesTemp = {
"axe",
"bow",
"claw",
"dagger",
"fishing",
"mace",
"staff",
"sword",
"wand",
"helmet",
"body",
"gloves",
"boots",
"shield",
"quiver",
"amulet",
"ring",
"belt",
"jewel",
"flask",
"tincture",
}
function io.linesBackward(filename)
local file = assert(io.open(filename, "rb"))
local content = file:read("*a")
file:close()
content = content:gsub("\r\n", "\n"):gsub("\r", "\n")
local lines = {}
for line in content:gmatch("([^\n]*)\n?") do
lines[#lines + 1] = line
end
-- Trailing empty entry from final newline
if lines[#lines] == "" then
lines[#lines] = nil
end
local i = #lines + 1
return function()
i = i - 1
if i > 0 then
return lines[i]
end
end
end
local usedMods = {}
local itemUsedMods = {}
local modTextMap = LoadModule("Uniques/ModTextMap.lua")
local uniqueMods = LoadModule("../Data/ModItemExclusive.lua")
for _, name in pairs(itemTypes) do
-- Reading the file backward lets us see the most current variant lines first
-- This way legacy mods can prefer existing mods and be more likely to match up automatically
-- Note this ONLY works because conventionally we have the most current variant mod listed last
-- if that ever changes due to modOrder, a lot of the `itemUsedMods` logic won't work (and might make things worse in some cases)
local outTbl = {}
for line in io.linesBackward("../Data/Uniques/"..name..".lua") do
if line == "]],[[" then
itemUsedMods = {} -- Reset mod list for trying to keep variants using the same mod
end
local specName, specVal = line:match("^([%a ]+): (.+)$")
if not specName and line ~= "]],[[" then
local versions = line:match("{version:([%d,.]+)}")
local variants = line:match("{[vV]ariant:([%d,.]+)}")
local groups = line:match("{group:([%d,.]+)}")
local fractured = line:match("({fractured})") or ""
local modText = line:gsub("{.-}", ""):gsub("\xe2\x80\x93", "-") -- Clean tag prefixes and EM dash
local possibleMods = modTextMap[modText:lower()] or {}
local genericText
local genericValues = {}
if variants then
-- Replace numbers with placeholder. Covers 5, -5--10, -5.5-10.5, etc. Ranges are handled later when printing
local genericMatchText = modText:gsub('(%-*%d*%.*%d+%-*%-*%d*%.*%d*)', '#')
local genericMatchMods = modTextMap[genericMatchText:lower()] or {}
local newPossibleMods = {}
for _, mod in ipairs(genericMatchMods) do
if itemUsedMods[mod] then
-- Found previously used mod that matches the generic version, so it's likely just a variant of the other
-- Don't use the found possibleMod, as it might match exactly, but for a different item
table.insert(newPossibleMods, mod)
end
end
if newPossibleMods[1] or #possibleMods == 0 then
genericText = genericMatchText
for val in modText:gmatch('(%-*%d*%.*%d+%-*%-*%d*%.*%d*)') do
table.insert(genericValues, val)
end
possibleMods = #newPossibleMods == 0 and genericMatchMods or newPossibleMods
end
end
local gggMod
if possibleMods[1] then
table.sort(possibleMods, function(a, b)
-- Strongly prefer already used mods for variant purposes
if itemUsedMods[a] == itemUsedMods[b] then
-- Used or not, prefer the mod with the item type
-- This doesn't really work for energy shield mods on shields, but it's a start
if a:lower():match(name) == b:lower():match(name) then
-- Sort types that aren't this one lower
for _, itemType in ipairs(itemTypesTemp) do
if a:lower():match(itemType) and not b:lower():match(itemType) then
return false
end
end
-- No item types in the names, or they had identical item types
-- Implicits preferred
if (a:match("Implicit") and a:lower():match(name)) and not (b:match("Implicit") and b:lower():match(name)) then
return true
elseif (b:match("Implicit") and b:lower():match(name)) and not (a:match("Implicit") and a:lower():match(name)) then
return false
end
-- No implicits, so prefer unused
if usedMods[a] == usedMods[b] then
return a:lower() < b:lower()
else
return not usedMods[a]
end
else
return a:lower():match(name) ~= nil
end
else
return itemUsedMods[a] ~= nil
end
end)
-- Sorted already, so just pick the top one
gggMod = possibleMods[1]
usedMods[gggMod] = true
itemUsedMods[gggMod] = true
local outLine = (versions and "{version:" .. versions:gsub("%.", ",") .. "}" or "")
.. (variants and "{variant:" .. variants:gsub("%.", ",") .. "}" or "")
.. (groups and "{group:" .. groups:gsub("%.", ",") .. "}" or "") .. fractured
outLine = outLine .. gggMod
if genericText then
-- Figure out where to put [,]
for _, val in ipairs(genericValues) do
local min, max = val:match("(%-*%d*%.*%d+)-*(%-*%d*%.*%d*)")
if not max or max == "" then max = min end
-- Decimals mean it's not an exact value
-- There are more that should be multiplied, but they're near-impossible to detect this way
local multiplier = genericText:match("critical strike chance") and 1000 or genericText:match("per second") and 60 or 1
min = tonumber(min) * multiplier
max = tonumber(max) * multiplier
outLine = outLine .. "[" .. min .. "," .. max .. "]"
end
end
table.insert(outTbl, 1, outLine .. "\n")
-- Multi-line mods: remove stale continuation lines from outTbl.
-- Since we read backward, continuation lines (2nd, 3rd, etc.) were
-- processed before the first line and are already in outTbl as raw
-- text. The mod ID we just inserted resolves to ALL lines, so the
-- raw continuation entries are duplicates.
-- Also collect continuations from sibling mods that share the same
-- first line (e.g. Dream/Nightmare jewels have 4 mods with identical
-- first lines but different continuations).
local modData = uniqueMods[gggMod]
if modData and #modData > 1 then
local continuations = {}
-- Find all mods sharing this first line
local firstLine = modData[1]:lower()
local siblingMods = modTextMap[firstLine] or { gggMod }
for _, siblingId in ipairs(siblingMods) do
local siblingData = uniqueMods[siblingId]
if siblingData then
for i = 2, #siblingData do
continuations[siblingData[i]:lower()] = true
end
end
end
-- Find boundary of current item (stop at ]],[[ separator)
local boundary = #outTbl
for j = 2, #outTbl do
local stripped = outTbl[j]:gsub("\n$", "")
if stripped == "]],[[" or stripped == "]]," then
boundary = j - 1
break
end
end
-- Scan backward within current item, remove matching entries
for j = boundary, 2, -1 do
local cleanLine = outTbl[j]:gsub("{.-}", ""):gsub("%s+$", ""):gsub("\n$", "")
if continuations[cleanLine:lower()] then
table.remove(outTbl, j)
end
end
end
else
ConPrintf("Warning: No mod found for line '%s' in %s", modText, name)
table.insert(outTbl, 1, line .."\n")
end
else
table.insert(outTbl, 1, line .. "\n")
end
end
local out = io.open("Uniques/"..name..".lua", "w")
for _, line in ipairs(outTbl) do
out:write(line)
end
out:close()
end
print("Unique mods exported.")