-
Notifications
You must be signed in to change notification settings - Fork 0
/
groupaistatebesiege.lua
164 lines (130 loc) · 4.39 KB
/
groupaistatebesiege.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
local function make_dis_id(from, to)
local f = from < to and from or to
local t = to < from and from or to
return tostring(f) .. "-" .. tostring(t)
end
local function spawn_group_id(spawn_group)
return spawn_group.mission_element:id()
end
function GroupAIStateBesiege:_choose_best_group(best_groups, total_weight)
local rand_wgt = total_weight * math.random()
local best_grp, best_grp_type = nil
for i, candidate in ipairs(best_groups) do
rand_wgt = rand_wgt - candidate.wght
if rand_wgt <= 0 then
-- what the fuck were you thinking???? https://imgur.com/a/v9T4mwq
self._spawn_group_timers[spawn_group_id(candidate.group)] = TimerManager:game():time() + math.random(15, 20)
best_grp = candidate.group
best_grp_type = candidate.group_type
best_grp.delay_t = self._t + best_grp.interval
break
end
end
return best_grp, best_grp_type
end
function GroupAIStateBesiege:_find_spawn_group_near_area(target_area, allowed_groups, target_pos, max_dis, verify_clbk)
local all_areas = self._area_data
local mvec3_dis = mvector3.distance_sq
max_dis = max_dis and max_dis * max_dis
local t = self._t
local valid_spawn_groups = {}
local valid_spawn_group_distances = {}
local total_dis = 0
target_pos = target_pos or target_area.pos
local to_search_areas = {
target_area
}
local found_areas = {
[target_area.id] = true
}
repeat
local search_area = table.remove(to_search_areas, 1)
local spawn_groups = search_area.spawn_groups
if spawn_groups then
for _, spawn_group in ipairs(spawn_groups) do
if spawn_group.delay_t <= t and (not verify_clbk or verify_clbk(spawn_group)) then
local dis_id = make_dis_id(spawn_group.nav_seg, target_area.pos_nav_seg)
if not self._graph_distance_cache[dis_id] then
local coarse_params = {
access_pos = "swat",
from_seg = spawn_group.nav_seg,
to_seg = target_area.pos_nav_seg,
id = dis_id
}
local path = managers.navigation:search_coarse(coarse_params)
if path and #path >= 2 then
local dis = 0
local current = spawn_group.pos
for i = 2, #path do
local nxt = path[i][2]
if current and nxt then
dis = dis + mvector3.distance(current, nxt)
end
current = nxt
end
self._graph_distance_cache[dis_id] = dis
end
end
if self._graph_distance_cache[dis_id] then
local my_dis = self._graph_distance_cache[dis_id]
if not max_dis or my_dis < max_dis then
total_dis = total_dis + my_dis
valid_spawn_groups[spawn_group_id(spawn_group)] = spawn_group
valid_spawn_group_distances[spawn_group_id(spawn_group)] = my_dis
end
end
end
end
end
for other_area_id, other_area in pairs(all_areas) do
if not found_areas[other_area_id] and other_area.neighbours[search_area.id] then
table.insert(to_search_areas, other_area)
found_areas[other_area_id] = true
end
end
until #to_search_areas == 0
if not next(valid_spawn_group_distances) then
return
end
local time = TimerManager:game():time()
-- bring back the resetting of all spawnpoint cooldowns when all of them are on cooldown
-- removed part starts here
local timer_can_spawn = false
for id in pairs(valid_spawn_groups) do
if not self._spawn_group_timers[id] or self._spawn_group_timers[id] <= time then
timer_can_spawn = true
break
end
end
if not timer_can_spawn then
self._spawn_group_timers = {}
end
-- removed part ends here
for id in pairs(valid_spawn_groups) do
if self._spawn_group_timers[id] and time < self._spawn_group_timers[id] then
valid_spawn_groups[id] = nil
valid_spawn_group_distances[id] = nil
end
end
if total_dis == 0 then
total_dis = 1
end
local total_weight = 0
local candidate_groups = {}
self._debug_weights = {}
local dis_limit = 5000
for i, dis in pairs(valid_spawn_group_distances) do
local my_wgt = math.lerp(1, 0.2, math.min(1, dis / dis_limit)) * 5
local my_spawn_group = valid_spawn_groups[i]
local my_group_types = my_spawn_group.mission_element:spawn_groups()
my_spawn_group.distance = dis
total_weight = total_weight + self:_choose_best_groups(candidate_groups, my_spawn_group, my_group_types, allowed_groups, my_wgt)
end
if total_weight == 0 then
return
end
for _, group in ipairs(candidate_groups) do
table.insert(self._debug_weights, clone(group))
end
return self:_choose_best_group(candidate_groups, total_weight)
end