forked from FAForever/fa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
WeaponPriorities.lua
225 lines (178 loc) · 7.3 KB
/
WeaponPriorities.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
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
local parsedPriorities
local ParseEntityCategoryProperly = import("/lua/sim/categoryutils.lua").ParseEntityCategoryProperly
local cachedTablePriorities = { }
local cachedLimitedTablePriorities = { }
--- We can't serialize categories, therefore the UI sends us a string of categories. We manually
--- parse the string here into categories.
---@param inputString string
---@return EntityCategory[] | nil
---@return EntityCategory[] | nil
function ParseTableOfCategories(inputString)
local full, limited = nil, nil
local ok, msg = pcall(
function()
local categories = StringSplit(inputString, ',')
for k, category in categories do
local clean = category
clean = string.gsub(clean, '{', '')
clean = string.gsub(clean, '}', '')
clean = string.gsub(clean, ' ', '')
clean = string.gsub(clean, 'categories.', '')
categories[k] = clean
end
full = { }
for k, category in categories do
if not (category == '') then
local parsed = cachedTablePriorities[category] or ParseEntityCategoryProperly(category)
cachedTablePriorities[category] = parsed
if parsed then
table.insert(full, parsed)
end
end
end
-- excludes the use of the COMMAND category, to prevent sniping with Mantis
limited = { }
for k, category in categories do
if not (category == '' or string.find(category, 'COMMAND')) then
local parsed = cachedLimitedTablePriorities[category] or ParseEntityCategoryProperly(string.format('(%s) - COMMAND', category))
cachedLimitedTablePriorities[category] = parsed
if parsed then
table.insert(limited, parsed)
end
end
end
end
)
if not ok then
WARN(msg)
WARN(inputString)
end
return full, limited
end
function SetWeaponPriorities(data)
local selectedUnits = data.SelectedUnits
local prioritiesTable
local prioritiesTableLimited
local editedPriorities = {}
local editedPrioritiesLimited = {}
local default
local name
-- parse and save all default priorities (we do it only once)
if not parsedPriorities then
parsedPriorities = parseDefaultPriorities()
end
if not selectedUnits[1] then return end
if data.prioritiesTable then
prioritiesTable, prioritiesTableLimited = ParseTableOfCategories(data.prioritiesTable)
--this is needed to prevent crashes when there is a mistake in the middle of input string
--and priTable has such structure: {[1] = userdata: EntityCategory, [2] = empty!, [3] = userdata: EntityCategory}
for key,cat in prioritiesTable or {} do
table.insert(editedPriorities, cat)
end
for key,cat in prioritiesTableLimited or {} do
table.insert(editedPrioritiesLimited, cat)
end
end
if not editedPriorities[1] then
default = true
end
--work out what message to send to the player for changing their priority list
if default then
name = "Default"
elseif type(data.name) == "string" then
name = data.name
end
if GetEntityById(selectedUnits[1]).Army == GetFocusArmy() and not data.hideMsg then
--send the message to the owner of the army
print('Target Priority:', name)
end
local units = {}
-- prevent tampering
for _, unitId in selectedUnits do
local unit = GetEntityById(unitId)
if unit and OkayToMessWithArmy(unit.Army) then
table.insert(units, unit)
end
end
local preparedPrioTables = {}
for _, unit in units do
local bp = unit:GetBlueprint()
local blueprintId = bp.BlueprintId
local weaponCount = unit:GetWeaponCount()
local finalPriorities = editedPrioritiesLimited
if bp.CategoriesHash.SNIPEMODE then
finalPriorities = editedPriorities
end
--checks if unit is already in requested mode
if weaponCount > 0 and unit.Sync.WepPriority ~= name then
unit.Sync.WepPriority = name or "?????"
if default then
for i = 1, weaponCount do
local weapon = unit:GetWeapon(i)
weapon:SetTargetingPriorities(parsedPriorities[blueprintId][i])
weapon:ResetTarget()
end
elseif data.exclusive then
for i = 1, weaponCount do
local weapon = unit:GetWeapon(i)
weapon:SetTargetingPriorities(finalPriorities)
weapon:ResetTarget()
end
elseif preparedPrioTables[blueprintId] then
for i = 1, weaponCount do
local weapon = unit:GetWeapon(i)
weapon:SetTargetingPriorities(preparedPrioTables[blueprintId][i])
weapon:ResetTarget()
end
else
preparedPrioTables[blueprintId] = {}
for i = 1, weaponCount do
local weapon = unit:GetWeapon(i)
local defaultPriorities = parsedPriorities[blueprintId][i]
local mergedPriorities = table.copy(finalPriorities) or {}
for k,v in defaultPriorities do
table.insert(mergedPriorities, v)
end
preparedPrioTables[blueprintId][i] = mergedPriorities
weapon:SetTargetingPriorities(mergedPriorities)
weapon:ResetTarget()
end
end
end
end
end
-- Parse and caching all TargetPriorities tables for every unit
function parseDefaultPriorities()
local idlist = EntityCategoryGetUnitList(categories.ALLUNITS)
local finalPriorities = {}
local parsedTemp = {}
for _, id in idlist do
local weapons = GetUnitBlueprintByName(id).Weapon
local priorities = {}
for weaponNum, weapon in weapons or {} do
if weapon.TargetPriorities then
priorities[weaponNum] = weapon.TargetPriorities
else
priorities[weaponNum] = {}
end
end
for weaponNum, tbl in priorities do
if not finalPriorities[id] then finalPriorities[id] = {} end
if not finalPriorities[id][weaponNum] then finalPriorities[id][weaponNum] = {} end
for line, categories in tbl or {} do
if parsedTemp[categories] then
finalPriorities[id][weaponNum][line] = parsedTemp[categories]
elseif string.find(categories, '%(') then
local parsed = ParseEntityCategoryProperly(categories)
finalPriorities[id][weaponNum][line] = parsed
parsedTemp[categories] = parsed
else
local parsed = ParseEntityCategory(categories)
finalPriorities[id][weaponNum][line] = parsed
parsedTemp[categories] = parsed
end
end
end
end
return finalPriorities
end