1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by Gorlum 13.02.2018 7:53 |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace Ube\Ube4_1; |
7
|
|
|
|
8
|
|
|
|
9
|
|
|
class Ube4_1Calc { |
10
|
|
|
const BONUS_LIST = [ |
11
|
|
|
UBE_ATTACK => UBE_ATTACK, |
12
|
|
|
UBE_ARMOR => UBE_ARMOR, |
13
|
|
|
UBE_SHIELD => UBE_SHIELD, |
14
|
|
|
]; |
15
|
|
|
|
16
|
|
|
const HP_DESTRUCTION_LIMIT_PERCENT = 75; // How much ship structure should be damaged for instant destruction chance, % |
17
|
|
|
const DEFENSE_GIVEBACK_PERCENT = 75; // How much defence unit could be restored after destruction |
18
|
|
|
const DEFENSE_GIVEBACK_MIN_PERCENT = 80; // Minimum percent of defence to give back |
19
|
|
|
const DEFENSE_GIVEBACK_MAX_PERCENT = 120; // Maximum percent of defence to give back |
20
|
|
|
const DEBRIS_FROM_SHIPS_MIN_PERCENT = 20; // Minimum amount of debris from destroyed ships |
21
|
|
|
const DEBRIS_FROM_SHIPS_MAX_PERCENT = 40; // Maximum amount of debris from destroyed ships |
22
|
|
|
const DEBRIS_FROM_CARGO_MIN_PERCENT = 30; // Minimum amount of debris dropped from cargo bays of destroyed ships |
23
|
|
|
const DEBRIS_FROM_CARGO_MAX_PERCENT = 70; // Maximum amount of debris dropped from cargo bays of destroyed ships |
24
|
|
|
|
25
|
|
|
const MOON_DEBRIS_MIN = 1000000; // Minimum amount of debris to span a moon |
26
|
|
|
const MOON_CHANCE_MAX_PERCENT = 30; // Maximum chance to span a moon |
27
|
|
|
|
28
|
|
|
|
29
|
|
|
public function __construct() { |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
public function sn_ube_combat(&$combat_data) { |
33
|
|
|
// TODO: Сделать атаку по типам, когда они будут |
34
|
|
|
|
35
|
|
|
$combat_data[UBE_TIME_SPENT] = microtime(true); |
36
|
|
|
$this->sn_ube_combat_round_prepare($combat_data, 0); |
37
|
|
|
|
38
|
|
|
for ($round = 1; $round <= 10; $round++) { |
39
|
|
|
// Готовим данные для раунда |
40
|
|
|
$this->sn_ube_combat_round_prepare($combat_data, $round); |
41
|
|
|
|
42
|
|
|
// Проводим раунд |
43
|
|
|
$this->sn_ube_combat_round_crossfire_fleet($combat_data, $round); |
44
|
|
|
|
45
|
|
|
// Анализируем итоги текущего раунда и готовим данные для следующего |
46
|
|
|
if ($this->sn_ube_combat_round_analyze($combat_data, $round) != UBE_COMBAT_RESULT_DRAW) { |
47
|
|
|
break; |
48
|
|
|
} |
49
|
|
|
} |
50
|
|
|
$combat_data[UBE_TIME_SPENT] = microtime(true) - $combat_data[UBE_TIME_SPENT]; |
51
|
|
|
|
52
|
|
|
// Делать это всегда - нам нужны результаты боя: луна->обломки->количество осташихся юнитов |
53
|
|
|
$this->sn_ube_combat_analyze($combat_data); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
// ------------------------------------------------------------------------------------------------ |
57
|
|
|
// Вычисление дополнительной информации для расчета раунда |
58
|
|
|
protected function sn_ube_combat_round_prepare(&$combat_data, $round) { |
59
|
|
|
$is_simulator = $combat_data[UBE_OPTIONS][UBE_SIMULATOR]; |
60
|
|
|
|
61
|
|
|
$round_data = &$combat_data[UBE_ROUNDS][$round]; |
62
|
|
|
foreach ($round_data[UBE_FLEETS] as $fleet_id => &$fleet_data) { |
63
|
|
|
// Кэшируем переменные для легкого доступа к подмассивам |
64
|
|
|
$fleet_info = &$combat_data[UBE_FLEETS][$fleet_id]; |
65
|
|
|
$fleet_data[UBE_FLEET_INFO] = &$fleet_info; |
66
|
|
|
$fleet_type = $fleet_info[UBE_FLEET_TYPE]; |
67
|
|
|
|
68
|
|
|
foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) { |
69
|
|
|
if ($unit_count <= 0) { |
70
|
|
|
continue; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
// TODO: Добавить процент регенерации щитов |
74
|
|
|
|
75
|
|
|
// Для не-симулятора - рандомизируем каждый раунд значения атаки и щитов |
76
|
|
|
$fleet_data[UBE_ATTACK_BASE][$unit_id] = floor($fleet_info[UBE_ATTACK][$unit_id] * ($is_simulator ? 1 : mt_rand(80, 120) / 100)); |
77
|
|
|
$fleet_data[UBE_SHIELD_BASE][$unit_id] = floor($fleet_info[UBE_SHIELD][$unit_id] * ($is_simulator ? 1 : mt_rand(80, 120) / 100)); |
78
|
|
|
$fleet_data[UBE_ARMOR_BASE][$unit_id] = floor($fleet_info[UBE_ARMOR][$unit_id]);// * ($is_simulator ? 1 : mt_rand(80, 120) / 100)); |
|
|
|
|
79
|
|
|
|
80
|
|
|
$fleet_data[UBE_ATTACK][$unit_id] = $fleet_data[UBE_ATTACK_BASE][$unit_id] * $unit_count; |
81
|
|
|
$fleet_data[UBE_SHIELD][$unit_id] = $fleet_data[UBE_SHIELD_BASE][$unit_id] * $unit_count; |
82
|
|
|
$fleet_data[UBE_SHIELD_REST][$unit_id] = $fleet_data[UBE_SHIELD_BASE][$unit_id]; |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
// Суммируем данные по флоту |
86
|
|
|
foreach (static::BONUS_LIST as $bonus_id) { |
87
|
|
|
$round_data[$fleet_type][$bonus_id][$fleet_id] += is_array($fleet_data[$bonus_id]) ? array_sum($fleet_data[$bonus_id]) : 0; |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
// Суммируем данные по атакующим и защитникам |
92
|
|
|
foreach (static::BONUS_LIST as $bonus_id) { |
93
|
|
|
$round_data[UBE_TOTAL][UBE_DEFENDERS][$bonus_id] = array_sum($round_data[UBE_DEFENDERS][$bonus_id]); |
94
|
|
|
$round_data[UBE_TOTAL][UBE_ATTACKERS][$bonus_id] = array_sum($round_data[UBE_ATTACKERS][$bonus_id]); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
// Высчитываем долю атаки, приходящейся на юнит равную отношению брони юнита к общей броне - крупные цели атакуют чаще |
98
|
|
|
foreach ($round_data[UBE_FLEETS] as &$fleet_data) { |
99
|
|
|
$fleet_type = $fleet_data[UBE_FLEET_INFO][UBE_FLEET_TYPE]; |
100
|
|
|
foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) { |
101
|
|
|
$fleet_data[UBE_DAMAGE_PERCENT][$unit_id] = $fleet_data[UBE_ARMOR][$unit_id] / $round_data[UBE_TOTAL][$fleet_type][UBE_ARMOR]; |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
// ------------------------------------------------------------------------------------------------ |
107
|
|
|
// Разбирает данные боя для генерации отчета |
108
|
|
|
protected function sn_ube_combat_analyze(&$combat_data) { |
109
|
|
|
global $config; |
|
|
|
|
110
|
|
|
|
111
|
|
|
$isSimulator = $combat_data[UBE_OPTIONS][UBE_SIMULATOR]; |
112
|
|
|
$combat_data[UBE_OPTIONS][UBE_EXCHANGE] = array(RES_METAL => $config->rpg_exchange_metal); |
113
|
|
|
|
114
|
|
|
$exchange = &$combat_data[UBE_OPTIONS][UBE_EXCHANGE]; |
115
|
|
|
foreach (array(RES_CRYSTAL => 'rpg_exchange_crystal', RES_DEUTERIUM => 'rpg_exchange_deuterium', RES_DARK_MATTER => 'rpg_exchange_darkMatter') as $resource_id => $resource_name) { |
116
|
|
|
$exchange[$resource_id] = $config->$resource_name * $exchange[RES_METAL]; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
// Переменные для быстрого доступа к подмассивам |
120
|
|
|
$outcome = &$combat_data[UBE_OUTCOME]; |
121
|
|
|
$fleets_info = &$combat_data[UBE_FLEETS]; |
122
|
|
|
$last_round_data = &$combat_data[UBE_ROUNDS][count($combat_data[UBE_ROUNDS]) - 1]; |
123
|
|
|
|
124
|
|
|
$outcome[UBE_DEBRIS] = array(); |
125
|
|
|
|
126
|
|
|
// Генерируем результат боя |
127
|
|
|
foreach ($fleets_info as $fleet_id => &$fleet_info) { |
128
|
|
|
$fleet_type = $fleet_info[UBE_FLEET_TYPE]; |
129
|
|
|
// Инициализируем массив результатов для флота |
130
|
|
|
$outcome[UBE_FLEETS][$fleet_id] = array(UBE_UNITS_LOST => array()); |
131
|
|
|
$outcome[$fleet_type][UBE_FLEETS][$fleet_id] = &$outcome[UBE_FLEETS][$fleet_id]; |
132
|
|
|
|
133
|
|
|
// Переменные для быстрого доступа к подмассивам |
134
|
|
|
$fleet_outcome = &$outcome[UBE_FLEETS][$fleet_id]; |
135
|
|
|
$fleet_data = &$last_round_data[UBE_FLEETS][$fleet_id]; |
136
|
|
|
|
137
|
|
|
foreach ($fleet_info[UBE_COUNT] as $unit_id => $unit_count) { |
138
|
|
|
// Вычисляем сколько юнитов осталось и сколько потеряно |
139
|
|
|
$units_left = $fleet_data[UBE_COUNT][$unit_id]; |
140
|
|
|
|
141
|
|
|
// Восстановление обороны - 75% от уничтоженной |
142
|
|
|
if ($fleet_info[UBE_TYPE][$unit_id] == UNIT_DEFENCE) { |
143
|
|
|
$units_giveback = $this->defenceGiveBack($unit_count, $units_left, $isSimulator); |
144
|
|
|
|
145
|
|
|
$units_left += $units_giveback; |
146
|
|
|
$fleet_outcome[UBE_DEFENCE_RESTORE][$unit_id] = $units_giveback; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
// TODO: Сбор металла/кристалла от обороны |
150
|
|
|
|
151
|
|
|
$units_lost = $unit_count - $units_left; |
152
|
|
|
|
153
|
|
|
// Вычисляем емкость трюмов оставшихся кораблей |
154
|
|
|
$outcome[$fleet_type][UBE_CAPACITY][$fleet_id] += $fleet_info[UBE_CAPACITY][$unit_id] * $units_left; |
155
|
|
|
|
156
|
|
|
// Вычисляем потери в ресурсах |
157
|
|
|
if ($units_lost) { |
158
|
|
|
$fleet_outcome[UBE_UNITS_LOST][$unit_id] = $units_lost; |
159
|
|
|
|
160
|
|
|
foreach ($fleet_info[UBE_PRICE] as $resource_id => $unit_prices) { |
161
|
|
|
if (!$unit_prices[$unit_id]) { |
162
|
|
|
continue; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
// ...чистыми |
166
|
|
|
$resources_lost = $units_lost * $unit_prices[$unit_id]; |
167
|
|
|
$fleet_outcome[UBE_RESOURCES_LOST][$resource_id] += $resources_lost; |
168
|
|
|
|
169
|
|
|
// Если это корабль - прибавляем потери к обломкам на орбите |
170
|
|
|
if ($fleet_info[UBE_TYPE][$unit_id] == UNIT_SHIPS) { |
171
|
|
|
$debrisFraction = ( |
172
|
|
|
$isSimulator |
173
|
|
|
? ( |
174
|
|
|
static::DEBRIS_FROM_SHIPS_MIN_PERCENT + |
175
|
|
|
static::DEBRIS_FROM_SHIPS_MAX_PERCENT) / 2 |
176
|
|
|
: mt_rand( |
177
|
|
|
static::DEBRIS_FROM_SHIPS_MIN_PERCENT, |
178
|
|
|
static::DEBRIS_FROM_SHIPS_MAX_PERCENT) |
179
|
|
|
) / 100; |
180
|
|
|
$outcome[UBE_DEBRIS][$resource_id] += floor($resources_lost * $debrisFraction); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
// ...в металле |
184
|
|
|
$resources_lost_in_metal = $resources_lost * $exchange[$resource_id]; |
185
|
|
|
$fleet_outcome[UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $resources_lost_in_metal; |
186
|
|
|
} |
187
|
|
|
} |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
// На планете ($fleet_id = 0) ресурсы в космос не выбрасываются |
191
|
|
|
if ($fleet_id == 0) { |
192
|
|
|
continue; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
// Количество ресурсов флота |
196
|
|
|
$fleet_total_resources = empty($fleet_info[UBE_RESOURCES]) ? 0 : array_sum($fleet_info[UBE_RESOURCES]); |
197
|
|
|
// Если на борту нет ресурсов - зачем нам все это? |
198
|
|
|
if ($fleet_total_resources == 0) { |
199
|
|
|
continue; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
// Емкость трюмов флота |
203
|
|
|
$fleet_capacity = $outcome[$fleet_type][UBE_CAPACITY][$fleet_id]; |
204
|
|
|
// Если емкость трюмов меньше количество ресурсов - часть ресов выбрасываем нахуй |
205
|
|
|
if ($fleet_capacity < $fleet_total_resources) { |
206
|
|
|
$left_percent = $fleet_capacity / $fleet_total_resources; // Сколько ресурсов будет оставлено |
207
|
|
|
foreach ($fleet_info[UBE_RESOURCES] as $resource_id => $resource_amount) { |
208
|
|
|
// Не просчитываем ресурсы, которых нет на борту кораблей флота |
209
|
|
|
if (!$resource_amount) { |
210
|
|
|
continue; |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
// TODO Восстанавливаем ошибку округления - придумать нормальный алгоритм - вроде round() должно быть достаточно. Проверить |
214
|
|
|
$fleet_outcome[UBE_RESOURCES][$resource_id] = round($left_percent * $resource_amount); |
215
|
|
|
$resource_dropped = $resource_amount - $fleet_outcome[UBE_RESOURCES][$resource_id]; |
216
|
|
|
$fleet_outcome[UBE_CARGO_DROPPED][$resource_id] = $resource_dropped; |
217
|
|
|
|
218
|
|
|
$cargoDroppedFraction = ( |
219
|
|
|
$isSimulator |
220
|
|
|
? (static::DEBRIS_FROM_CARGO_MIN_PERCENT + |
221
|
|
|
static::DEBRIS_FROM_CARGO_MAX_PERCENT) / 2 |
222
|
|
|
: mt_rand( |
223
|
|
|
static::DEBRIS_FROM_CARGO_MIN_PERCENT, |
224
|
|
|
static::DEBRIS_FROM_CARGO_MAX_PERCENT) |
225
|
|
|
) / 100; |
226
|
|
|
$outcome[UBE_DEBRIS][$resource_id] += round($resource_dropped * $cargoDroppedFraction); // TODO: Configurize |
227
|
|
|
$fleet_outcome[UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $resource_dropped * $exchange[$resource_id]; |
228
|
|
|
} |
229
|
|
|
$fleet_total_resources = array_sum($fleet_outcome[UBE_RESOURCES]); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
$outcome[$fleet_type][UBE_CAPACITY][$fleet_id] = $fleet_capacity - $fleet_total_resources; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
$outcome[UBE_COMBAT_RESULT] = !isset($last_round_data[UBE_OUTCOME]) || $last_round_data[UBE_OUTCOME] == UBE_COMBAT_RESULT_DRAW_END ? UBE_COMBAT_RESULT_DRAW : $last_round_data[UBE_OUTCOME]; |
236
|
|
|
// SFR - Small Fleet Reconnaissance ака РМФ |
237
|
|
|
$outcome[UBE_SFR] = count($combat_data[UBE_ROUNDS]) == 2 && $outcome[UBE_COMBAT_RESULT] == UBE_COMBAT_RESULT_LOSS; |
238
|
|
|
|
239
|
|
|
if (!$combat_data[UBE_OPTIONS][UBE_LOADED]) { |
240
|
|
|
if ($combat_data[UBE_OPTIONS][UBE_MOON_WAS]) { |
241
|
|
|
$outcome[UBE_MOON] = UBE_MOON_WAS; |
242
|
|
|
} else { |
243
|
|
|
$this->sn_ube_combat_analyze_moon($outcome, $combat_data[UBE_OPTIONS][UBE_SIMULATOR]); |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
// Лутаем ресурсы - если аттакер выиграл |
247
|
|
|
if ($outcome[UBE_COMBAT_RESULT] == UBE_COMBAT_RESULT_WIN) { |
248
|
|
|
$this->sn_ube_combat_analyze_loot($combat_data); |
249
|
|
|
if ($combat_data[UBE_OPTIONS][UBE_MOON_WAS] && $combat_data[UBE_OPTIONS][UBE_MISSION_TYPE] == MT_DESTROY) { |
250
|
|
|
$this->sn_ube_combat_analyze_moon_destroy($combat_data); |
251
|
|
|
} |
252
|
|
|
} |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
} |
256
|
|
|
|
257
|
|
|
// ------------------------------------------------------------------------------------------------ |
258
|
|
|
protected function sn_ube_combat_analyze_moon(&$outcome, $is_simulator) { |
259
|
|
|
$outcome[UBE_DEBRIS_TOTAL] = 0; |
260
|
|
|
foreach ([RES_METAL, RES_CRYSTAL] as $resource_id) { |
261
|
|
|
$outcome[UBE_DEBRIS_TOTAL] += $outcome[UBE_DEBRIS][$resource_id]; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
if ($outcome[UBE_DEBRIS_TOTAL]) { |
265
|
|
|
if ($outcome[UBE_MOON_CHANCE] = \Universe::moonCalcChanceFromDebris($outcome[UBE_DEBRIS_TOTAL])) { |
266
|
|
|
$outcome[UBE_MOON_SIZE] = $is_simulator |
267
|
|
|
// On simulator moon always will be average size |
268
|
|
|
? round(max(1, $outcome[UBE_MOON_CHANCE] / 2) * 150 + 2000) |
269
|
|
|
: \Universe::moonRollSize($outcome[UBE_DEBRIS_TOTAL]); |
270
|
|
|
if ($outcome[UBE_MOON_CHANCE]) { |
271
|
|
|
// Got moon |
272
|
|
|
$outcome[UBE_MOON] = UBE_MOON_CREATE_SUCCESS; |
273
|
|
|
|
274
|
|
|
if ($outcome[UBE_DEBRIS_TOTAL] <= \Universe::moonMaxDebris()) { |
275
|
|
|
$outcome[UBE_DEBRIS_TOTAL] = 0; |
276
|
|
|
$outcome[UBE_DEBRIS] = []; |
277
|
|
|
} else { |
278
|
|
|
$moon_debris_spent = \Universe::moonMaxDebris(); |
279
|
|
|
$moon_debris_left_percent = ($outcome[UBE_DEBRIS_TOTAL] - $moon_debris_spent) / $outcome[UBE_DEBRIS_TOTAL]; |
280
|
|
|
|
281
|
|
|
$outcome[UBE_DEBRIS_TOTAL] = 0; |
282
|
|
|
foreach ([RES_METAL, RES_CRYSTAL] as $resource_id) { |
283
|
|
|
$outcome[UBE_DEBRIS][$resource_id] = floor($outcome[UBE_DEBRIS][$resource_id] * $moon_debris_left_percent); |
284
|
|
|
$outcome[UBE_DEBRIS_TOTAL] += $outcome[UBE_DEBRIS][$resource_id]; |
285
|
|
|
} |
286
|
|
|
} |
287
|
|
|
} else { |
288
|
|
|
$outcome[UBE_MOON] = UBE_MOON_CREATE_FAILED; |
289
|
|
|
} |
290
|
|
|
} |
291
|
|
|
} else { |
292
|
|
|
$outcome[UBE_MOON] = UBE_MOON_NONE; |
293
|
|
|
} |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
// ------------------------------------------------------------------------------------------------ |
297
|
|
|
protected function sn_ube_combat_analyze_moon_destroy(&$combat_data) { |
298
|
|
|
// TODO: $is_simulator |
299
|
|
|
$reapers = 0; |
300
|
|
|
foreach ($combat_data[UBE_ROUNDS][count($combat_data[UBE_ROUNDS]) - 1][UBE_FLEETS] as $fleet_data) { |
301
|
|
|
if ($fleet_data[UBE_FLEET_INFO][UBE_FLEET_TYPE] == UBE_ATTACKERS) { |
302
|
|
|
foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) { |
303
|
|
|
// TODO: Работа по группам - группа "Уничтожители лун" |
304
|
|
|
$reapers += ($unit_id == SHIP_HUGE_DEATH_STAR) ? $unit_count : 0; |
305
|
|
|
} |
306
|
|
|
} |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
$moon_size = $combat_data[UBE_OUTCOME][UBE_PLANET][PLANET_SIZE]; |
310
|
|
|
if ($reapers) { |
311
|
|
|
$random = mt_rand(1, 100); |
312
|
|
|
$combat_data[UBE_OUTCOME][UBE_MOON_DESTROY_CHANCE] = max(1, min(99, round((100 - sqrt($moon_size)) * sqrt($reapers)))); |
313
|
|
|
$combat_data[UBE_OUTCOME][UBE_MOON_REAPERS_DIE_CHANCE] = round(sqrt($moon_size) / 2 + sqrt($reapers)); |
314
|
|
|
$combat_data[UBE_OUTCOME][UBE_MOON] = $random <= $combat_data[UBE_OUTCOME][UBE_MOON_DESTROY_CHANCE] ? UBE_MOON_DESTROY_SUCCESS : UBE_MOON_DESTROY_FAILED; |
315
|
|
|
$random = mt_rand(1, 100); |
316
|
|
|
$combat_data[UBE_OUTCOME][UBE_MOON_REAPERS] = $random <= $combat_data[UBE_OUTCOME][UBE_MOON_REAPERS_DIE_CHANCE] ? UBE_MOON_REAPERS_DIED : UBE_MOON_REAPERS_RETURNED; |
317
|
|
|
} else { |
318
|
|
|
$combat_data[UBE_OUTCOME][UBE_MOON_REAPERS] = UBE_MOON_REAPERS_NONE; |
319
|
|
|
} |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
// ------------------------------------------------------------------------------------------------ |
323
|
|
|
protected function sn_ube_combat_analyze_loot(&$combat_data) { |
324
|
|
|
$exchange = &$combat_data[UBE_OPTIONS][UBE_EXCHANGE]; |
325
|
|
|
$planet_resource_list = &$combat_data[UBE_FLEETS][0][UBE_RESOURCES]; |
326
|
|
|
$outcome = &$combat_data[UBE_OUTCOME]; |
327
|
|
|
|
328
|
|
|
$planet_looted_in_metal = 0; |
329
|
|
|
$planet_resource_looted = array(); |
330
|
|
|
$planet_resource_total = is_array($planet_resource_list) ? array_sum($planet_resource_list) : 0; |
331
|
|
|
if ($planet_resource_total && ($total_capacity = array_sum($outcome[UBE_ATTACKERS][UBE_CAPACITY]))) { |
332
|
|
|
// Можно вывести только половину ресурсов, но не больше, чем общая вместимость флотов атакующих |
333
|
|
|
$planet_lootable = min($planet_resource_total / 2, $total_capacity); |
334
|
|
|
// Вычисляем процент вывоза. Каждого ресурса будет вывезено в одинаковых пропорциях |
335
|
|
|
$planet_lootable_percent = $planet_lootable / $planet_resource_total; |
336
|
|
|
|
337
|
|
|
// Вычисляем какой процент общей емкости трюмов атакующих будет задействован |
338
|
|
|
$total_lootable = min($planet_lootable, $total_capacity); |
|
|
|
|
339
|
|
|
|
340
|
|
|
// Вычисляем сколько ресурсов вывезено |
341
|
|
|
foreach ($outcome[UBE_ATTACKERS][UBE_CAPACITY] as $fleet_id => $fleet_capacity) { |
342
|
|
|
$looted_in_metal = 0; |
343
|
|
|
$fleet_loot_data = array(); |
344
|
|
|
foreach ($planet_resource_list as $resource_id => $resource_amount) { |
345
|
|
|
// TODO Восстанавливаем ошибку округления - придумать нормальный алгоритм - вроде round() должно быть достаточно. Проверить |
346
|
|
|
$fleet_lootable_percent = $fleet_capacity / $total_capacity; |
347
|
|
|
$looted = round($resource_amount * $planet_lootable_percent * $fleet_lootable_percent); |
348
|
|
|
$fleet_loot_data[$resource_id] = -$looted; |
349
|
|
|
$planet_resource_looted[$resource_id] += $looted; |
350
|
|
|
$looted_in_metal -= $looted * $exchange[$resource_id]; |
351
|
|
|
} |
352
|
|
|
$outcome[UBE_FLEETS][$fleet_id][UBE_RESOURCES_LOOTED] = $fleet_loot_data; |
353
|
|
|
$outcome[UBE_FLEETS][$fleet_id][UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $looted_in_metal; |
354
|
|
|
$planet_looted_in_metal += $looted_in_metal; |
355
|
|
|
} |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
$outcome[UBE_FLEETS][0][UBE_RESOURCES_LOST_IN_METAL][RES_METAL] -= $planet_looted_in_metal; |
359
|
|
|
$outcome[UBE_FLEETS][0][UBE_RESOURCES_LOOTED] = $planet_resource_looted; |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
|
363
|
|
|
// ------------------------------------------------------------------------------------------------ |
364
|
|
|
// Анализирует результаты раунда и генерирует данные для следующего раунда |
365
|
|
|
protected function sn_ube_combat_round_analyze(&$combat_data, $round) { |
366
|
|
|
$round_data = &$combat_data[UBE_ROUNDS][$round]; |
367
|
|
|
$round_data[UBE_OUTCOME] = UBE_COMBAT_RESULT_DRAW; |
368
|
|
|
|
369
|
|
|
$outcome = array(); |
370
|
|
|
$next_round_fleet = array(); |
371
|
|
|
foreach ($round_data[UBE_FLEETS] as $fleet_id => &$fleet_data) { |
372
|
|
|
if (array_sum($fleet_data[UBE_COUNT]) <= 0) { |
373
|
|
|
continue; |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) { |
377
|
|
|
if ($unit_count <= 0) { |
378
|
|
|
continue; |
379
|
|
|
} |
380
|
|
|
$next_round_fleet[$fleet_id][UBE_COUNT][$unit_id] = $unit_count; |
381
|
|
|
$next_round_fleet[$fleet_id][UBE_ARMOR][$unit_id] = $fleet_data[UBE_ARMOR][$unit_id]; |
382
|
|
|
$next_round_fleet[$fleet_id][UBE_ARMOR_REST][$unit_id] = $fleet_data[UBE_ARMOR_REST][$unit_id]; |
383
|
|
|
$outcome[$fleet_data[UBE_FLEET_INFO][UBE_FLEET_TYPE]] = 1; |
384
|
|
|
} |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
// Проверяем - если кого-то не осталось или не осталось обоих - заканчиваем цикл |
388
|
|
|
if (count($outcome) == 0 || $round == 10) { |
389
|
|
|
$round_data[UBE_OUTCOME] = UBE_COMBAT_RESULT_DRAW_END; |
390
|
|
|
} elseif (count($outcome) == 1) { |
391
|
|
|
$round_data[UBE_OUTCOME] = isset($outcome[UBE_ATTACKERS]) ? UBE_COMBAT_RESULT_WIN : UBE_COMBAT_RESULT_LOSS; |
392
|
|
|
} elseif (count($outcome) == 2) { |
393
|
|
|
if ($round < 10) { |
394
|
|
|
$combat_data[UBE_ROUNDS][$round + 1][UBE_FLEETS] = $next_round_fleet; |
395
|
|
|
} |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
return ($round_data[UBE_OUTCOME]); |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
|
402
|
|
|
// ------------------------------------------------------------------------------------------------ |
403
|
|
|
// Рассчитывает результат столкновения флотов ака раунд |
404
|
|
|
protected function sn_ube_combat_round_crossfire_fleet(&$combat_data, $round) { |
405
|
|
|
if (BE_DEBUG === true) { |
|
|
|
|
406
|
|
|
// sn_ube_combat_helper_round_header($round); |
|
|
|
|
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
$round_data = &$combat_data[UBE_ROUNDS][$round]; |
410
|
|
|
// Проводим бой. Сталкиваем каждый корабль атакующего с каждым кораблем атакуемого |
411
|
|
|
foreach ($round_data[UBE_ATTACKERS][UBE_ATTACK] as $attack_fleet_id => $temp) { |
412
|
|
|
$attack_fleet_data = &$round_data[UBE_FLEETS][$attack_fleet_id]; |
413
|
|
|
foreach ($round_data[UBE_DEFENDERS][UBE_ATTACK] as $defend_fleet_id => $temp2) { |
414
|
|
|
$defend_fleet_data = &$round_data[UBE_FLEETS][$defend_fleet_id]; |
415
|
|
|
|
416
|
|
|
foreach ($attack_fleet_data[UBE_COUNT] as $attack_unit_id => $attack_unit_count) { |
417
|
|
|
// if($attack_unit_count <= 0) continue; // TODO: Это пока нельзя включать - вот если будут "боевые порядки юнитов..." |
|
|
|
|
418
|
|
|
foreach ($defend_fleet_data[UBE_COUNT] as $defend_unit_id => $defend_unit_count) { |
419
|
|
|
$this->sn_ube_combat_round_crossfire_unit2($attack_fleet_data, $defend_fleet_data, $attack_unit_id, $defend_unit_id, $combat_data[UBE_OPTIONS]); |
420
|
|
|
$this->sn_ube_combat_round_crossfire_unit2($defend_fleet_data, $attack_fleet_data, $defend_unit_id, $attack_unit_id, $combat_data[UBE_OPTIONS]); |
421
|
|
|
} |
422
|
|
|
} |
423
|
|
|
} |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
if (BE_DEBUG === true) { |
|
|
|
|
427
|
|
|
// sn_ube_combat_helper_round_footer(); |
428
|
|
|
} |
429
|
|
|
} |
430
|
|
|
|
431
|
|
|
|
432
|
|
|
// ------------------------------------------------------------------------------------------------ |
433
|
|
|
// Рассчитывает результат столкновения двух юнитов ака ход |
434
|
|
|
protected function sn_ube_combat_round_crossfire_unit2(&$attack_fleet_data, &$defend_fleet_data, $attack_unit_id, $defend_unit_id, &$combat_options) { |
435
|
|
|
if ($defend_fleet_data[UBE_COUNT][$defend_unit_id] <= 0) { |
436
|
|
|
return; |
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
// Вычисляем прямой дамадж от атакующего юнита с учетом размера атакуемого |
440
|
|
|
$direct_damage = floor($attack_fleet_data[UBE_ATTACK][$attack_unit_id] * $defend_fleet_data[UBE_DAMAGE_PERCENT][$defend_unit_id]); |
441
|
|
|
|
442
|
|
|
// Применяем амплифай, если есть |
443
|
|
|
$amplify = $attack_fleet_data[UBE_FLEET_INFO][UBE_AMPLIFY][$attack_unit_id][$defend_unit_id]; |
444
|
|
|
$amplify = $amplify ? $amplify : 1; |
445
|
|
|
$amplified_damage = floor($direct_damage * $amplify); |
446
|
|
|
|
447
|
|
|
// Проверяем - не взорвался ли текущий раненный юнит |
448
|
|
|
$this->sn_ube_combat_round_crossfire_unit_damage_current($defend_fleet_data, $defend_unit_id, $amplified_damage, $units_lost, $units_boomed, $combat_options); |
449
|
|
|
|
450
|
|
|
$defend_unit_base_defence = $defend_fleet_data[UBE_SHIELD_BASE][$defend_unit_id] + $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id]; |
451
|
|
|
|
452
|
|
|
// todo Добавить взрывы от полуповрежденных юнитов - т.е. заранее вычислить из убитых юнитов еще количество убитых умножить на вероятность от структуры |
453
|
|
|
|
454
|
|
|
// Вычисляем, сколько юнитов взорвалось полностью |
455
|
|
|
$units_lost_full = floor($amplified_damage / $defend_unit_base_defence); |
456
|
|
|
// Уменьшаем дамадж на ту же сумму |
457
|
|
|
$amplified_damage -= $units_lost_full * $defend_unit_base_defence; |
458
|
|
|
// Вычисляем, сколько юнитов осталось |
459
|
|
|
$defend_fleet_data[UBE_COUNT][$defend_unit_id] = max(0, $defend_fleet_data[UBE_COUNT][$defend_unit_id] - $units_lost_full); |
460
|
|
|
// Уменьшаем броню подразделения на броню потерянных юнитов |
461
|
|
|
$defend_fleet_data[UBE_ARMOR][$defend_unit_id] -= $units_lost_full * $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id]; |
462
|
|
|
$defend_fleet_data[UBE_SHIELD][$defend_unit_id] -= $units_lost_full * $defend_fleet_data[UBE_SHIELD_BASE][$defend_unit_id]; |
463
|
|
|
|
464
|
|
|
// Проверяем - не взорвался ли текущий юнит |
465
|
|
|
$this->sn_ube_combat_round_crossfire_unit_damage_current($defend_fleet_data, $defend_unit_id, $amplified_damage, $units_lost, $units_boomed, $combat_options); |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* @param $defend_fleet_data |
470
|
|
|
* @param $defend_unit_id |
471
|
|
|
* @param $amplified_damage |
472
|
|
|
* @param $units_lost |
473
|
|
|
* @param $units_boomed |
474
|
|
|
* @param $combat_options |
475
|
|
|
* |
476
|
|
|
* @return bool |
477
|
|
|
*/ |
478
|
|
|
protected function sn_ube_combat_round_crossfire_unit_damage_current(&$defend_fleet_data, $defend_unit_id, &$amplified_damage, &$units_lost, &$units_boomed, &$combat_options) { |
479
|
|
|
$unit_is_lost = false; |
480
|
|
|
|
481
|
|
|
$units_boomed = $units_boomed ? $units_boomed : 0; |
482
|
|
|
$units_lost = $units_lost ? $units_lost : 0; |
483
|
|
|
|
484
|
|
|
if ($defend_fleet_data[UBE_COUNT][$defend_unit_id] > 0 && $amplified_damage) { |
485
|
|
|
$damage_to_shield = min($amplified_damage, $defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id]); |
486
|
|
|
$amplified_damage -= $damage_to_shield; |
487
|
|
|
$defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id] -= $damage_to_shield; |
488
|
|
|
|
489
|
|
|
$damage_to_armor = min($amplified_damage, $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id]); |
490
|
|
|
$amplified_damage -= $damage_to_armor; |
491
|
|
|
$defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] -= $damage_to_armor; |
492
|
|
|
|
493
|
|
|
// Если брони не осталось - юнит потерян |
494
|
|
|
if ($defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] <= 0) { |
495
|
|
|
$unit_is_lost = true; |
496
|
|
|
} elseif ($defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id] <= 0) { |
497
|
|
|
// Если броня осталось, но не осталось щитов - прошел дамадж по броне и надо проверить - не взорвался ли корабль |
498
|
|
|
$last_unit_hp = $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id]; |
499
|
|
|
$last_unit_percent = $last_unit_hp / $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id] * 100; |
500
|
|
|
|
501
|
|
|
$random = $combat_options[UBE_SIMULATOR] ? static::HP_DESTRUCTION_LIMIT_PERCENT / 2 : mt_rand(0, 100); |
502
|
|
|
if ($last_unit_percent <= static::HP_DESTRUCTION_LIMIT_PERCENT && $last_unit_percent <= $random) { |
503
|
|
|
$unit_is_lost = true; |
504
|
|
|
$units_boomed++; |
505
|
|
|
$damage_to_armor += $defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id]; |
506
|
|
|
$defend_fleet_data[UBE_UNITS_BOOM][$defend_unit_id]++; |
507
|
|
|
$defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] = 0; |
508
|
|
|
} |
509
|
|
|
} |
510
|
|
|
|
511
|
|
|
$defend_fleet_data[UBE_ARMOR][$defend_unit_id] -= $damage_to_armor; |
512
|
|
|
$defend_fleet_data[UBE_SHIELD][$defend_unit_id] -= $damage_to_shield; |
513
|
|
|
|
514
|
|
|
if ($unit_is_lost) { |
515
|
|
|
$units_lost++; |
516
|
|
|
$defend_fleet_data[UBE_COUNT][$defend_unit_id]--; |
517
|
|
|
if ($defend_fleet_data[UBE_COUNT][$defend_unit_id]) { |
518
|
|
|
$defend_fleet_data[UBE_ARMOR_REST][$defend_unit_id] = $defend_fleet_data[UBE_ARMOR_BASE][$defend_unit_id]; |
519
|
|
|
$defend_fleet_data[UBE_SHIELD_REST][$defend_unit_id] = $defend_fleet_data[UBE_SHIELD_BASE][$defend_unit_id]; |
520
|
|
|
} |
521
|
|
|
} |
522
|
|
|
} |
523
|
|
|
|
524
|
|
|
return $unit_is_lost; |
525
|
|
|
} |
526
|
|
|
|
527
|
|
|
/** |
528
|
|
|
* @param $unit_count |
529
|
|
|
* @param $units_left |
530
|
|
|
* @param $isSimulator |
531
|
|
|
* |
532
|
|
|
* @return int |
533
|
|
|
*/ |
534
|
|
|
protected function defenceGiveBack($unit_count, $units_left, $isSimulator) { |
535
|
|
|
$units_lost = $unit_count - $units_left; |
536
|
|
|
if ($isSimulator) { |
537
|
|
|
// for simulation just return 75% of loss |
538
|
|
|
$units_giveback = round($units_lost * static::DEFENSE_GIVEBACK_PERCENT / 100); |
539
|
|
|
} else { |
540
|
|
|
if ($unit_count > 10) { |
541
|
|
|
// if there were more then 10 defense elements - mass-calculating giveback |
542
|
|
|
|
543
|
|
|
// Calculating random part of return - it would be a decimal |
544
|
|
|
$random = mt_rand(static::DEFENSE_GIVEBACK_MIN_PERCENT * 1000, static::DEFENSE_GIVEBACK_MAX_PERCENT * 1000) / (100 * 1000); // Trick to get random with high precision |
545
|
|
|
// Limiting max return to 100% - in case if we messed with min/max chance and/or giveback |
546
|
|
|
$random = min($random * static::DEFENSE_GIVEBACK_PERCENT, 100); |
547
|
|
|
$units_giveback = round($units_lost * $random / 100); |
548
|
|
|
} else { |
549
|
|
|
// if there were less then 10 defense elements - calculating giveback per element |
550
|
|
|
$units_giveback = 0; |
551
|
|
|
for ($i = 1; $i <= $units_lost; $i++) { |
552
|
|
|
if (mt_rand(1, 100) <= static::DEFENSE_GIVEBACK_PERCENT) { |
553
|
|
|
$units_giveback++; |
554
|
|
|
} |
555
|
|
|
} |
556
|
|
|
} |
557
|
|
|
} |
558
|
|
|
|
559
|
|
|
return $units_giveback; |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
} |
563
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.