Ube4_1Calc::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 1
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
nc 1
nop 0
dl 0
loc 1
rs 10
c 1
b 0
f 0
ccs 0
cts 1
cp 0
crap 2
1
<?php
2
/**
3
 * Created by Gorlum 13.02.2018 7:53
4
 */
5
6
namespace Ube\Ube4_1;
7
8
use Universe\Universe;
9
10
class Ube4_1Calc {
11
  const BONUS_LIST = [
12
    UBE_ATTACK => UBE_ATTACK,
13
    UBE_ARMOR  => UBE_ARMOR,
14
    UBE_SHIELD => UBE_SHIELD,
15
  ];
16
17
  const HP_DESTRUCTION_LIMIT_PERCENT = 75; // How much ship structure should be damaged for instant destruction chance, %
18
  const DEFENSE_GIVEBACK_PERCENT = 75; // How much defence unit could be restored after destruction
19
  const DEFENSE_GIVEBACK_MIN_PERCENT = 80; // Minimum percent of defence to give back
20
  const DEFENSE_GIVEBACK_MAX_PERCENT = 120; // Maximum percent of defence to give back
21
  const DEBRIS_FROM_SHIPS_MIN_PERCENT = 20; // Minimum amount of debris from destroyed ships
22
  const DEBRIS_FROM_SHIPS_MAX_PERCENT = 40; // Maximum amount of debris from destroyed ships
23
  const DEBRIS_FROM_CARGO_MIN_PERCENT = 30; // Minimum amount of debris dropped from cargo bays of destroyed ships
24
  const DEBRIS_FROM_CARGO_MAX_PERCENT = 70; // Maximum amount of debris dropped from cargo bays of destroyed ships
25
26
27
  public function __construct() {
28
  }
29
30
  public function sn_ube_combat(&$combat_data) {
31
    // TODO: Сделать атаку по типам,  когда они будут
32
33
    $combat_data[UBE_TIME_SPENT] = microtime(true);
34
    $this->sn_ube_combat_round_prepare($combat_data, 0);
35
36
    for ($round = 1; $round <= 10; $round++) {
37
      // Готовим данные для раунда
38
      $this->sn_ube_combat_round_prepare($combat_data, $round);
39
40
      // Проводим раунд
41
      $this->sn_ube_combat_round_crossfire_fleet($combat_data, $round);
42
43
      // Анализируем итоги текущего раунда и готовим данные для следующего
44
      if ($this->sn_ube_combat_round_analyze($combat_data, $round) != UBE_COMBAT_RESULT_DRAW) {
45
        break;
46
      }
47
    }
48
    $combat_data[UBE_TIME_SPENT] = microtime(true) - $combat_data[UBE_TIME_SPENT];
49
50
    // Делать это всегда - нам нужны результаты боя: луна->обломки->количество осташихся юнитов
51
    $this->sn_ube_combat_analyze($combat_data);
52
  }
53
54
// ------------------------------------------------------------------------------------------------
55
// Вычисление дополнительной информации для расчета раунда
56
  protected function sn_ube_combat_round_prepare(&$combat_data, $round) {
57
    $isSimulatorStatic = $combat_data[UBE_OPTIONS][UBE_SIMULATOR_STATIC];
58
59
    $round_data = &$combat_data[UBE_ROUNDS][$round];
60
    foreach ($round_data[UBE_FLEETS] as $fleet_id => &$fleet_data) {
61
      // Кэшируем переменные для легкого доступа к подмассивам
62
      $fleet_info = &$combat_data[UBE_FLEETS][$fleet_id];
63
      $fleet_data[UBE_FLEET_INFO] = &$fleet_info;
64
      $fleet_type = $fleet_info[UBE_FLEET_TYPE];
65
66
      foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) {
67
        if ($unit_count <= 0) {
68
          continue;
69
        }
70
71
        // TODO:  Добавить процент регенерации щитов
72
73
        // Для не-симулятора - рандомизируем каждый раунд значения атаки и щитов
74
        $fleet_data[UBE_ATTACK_BASE][$unit_id] = floor($fleet_info[UBE_ATTACK][$unit_id] * ($isSimulatorStatic ? 1 : mt_rand(80, 120) / 100));
75
        $fleet_data[UBE_SHIELD_BASE][$unit_id] = floor($fleet_info[UBE_SHIELD][$unit_id] * ($isSimulatorStatic ? 1 : mt_rand(80, 120) / 100));
76
        $fleet_data[UBE_ARMOR_BASE][$unit_id] = floor($fleet_info[UBE_ARMOR][$unit_id]);// * ($is_simulator ? 1 : mt_rand(80, 120) / 100));
77
78
        $fleet_data[UBE_ATTACK][$unit_id] = $fleet_data[UBE_ATTACK_BASE][$unit_id] * $unit_count;
79
        $fleet_data[UBE_SHIELD][$unit_id] = $fleet_data[UBE_SHIELD_BASE][$unit_id] * $unit_count;
80
        $fleet_data[UBE_SHIELD_REST][$unit_id] = $fleet_data[UBE_SHIELD_BASE][$unit_id];
81
      }
82
83
      // Суммируем данные по флоту
84
      foreach (static::BONUS_LIST as $bonus_id) {
85
        $round_data[$fleet_type][$bonus_id][$fleet_id] += is_array($fleet_data[$bonus_id]) ? array_sum($fleet_data[$bonus_id]) : 0;
86
      }
87
    }
88
89
    // Суммируем данные по атакующим и защитникам
90
    foreach (static::BONUS_LIST as $bonus_id) {
91
      $round_data[UBE_TOTAL][UBE_DEFENDERS][$bonus_id] = array_sum($round_data[UBE_DEFENDERS][$bonus_id]);
92
      $round_data[UBE_TOTAL][UBE_ATTACKERS][$bonus_id] = array_sum($round_data[UBE_ATTACKERS][$bonus_id]);
93
    }
94
95
    // Высчитываем долю атаки, приходящейся на юнит равную отношению брони юнита к общей броне - крупные цели атакуют чаще
96
    foreach ($round_data[UBE_FLEETS] as &$fleet_data) {
97
      $fleet_type = $fleet_data[UBE_FLEET_INFO][UBE_FLEET_TYPE];
98
      foreach ($fleet_data[UBE_COUNT] as $unit_id => $unit_count) {
99
        $fleet_data[UBE_DAMAGE_PERCENT][$unit_id] = $fleet_data[UBE_ARMOR][$unit_id] / $round_data[UBE_TOTAL][$fleet_type][UBE_ARMOR];
100
      }
101
    }
102
  }
103
104
// ------------------------------------------------------------------------------------------------
105
// Разбирает данные боя для генерации отчета
106
  protected function sn_ube_combat_analyze(&$combat_data) {
107
    global $config;
108
109
    $isSimulatorStatic = $combat_data[UBE_OPTIONS][UBE_SIMULATOR_STATIC];
110
    $combat_data[UBE_OPTIONS][UBE_EXCHANGE] = array(RES_METAL => $config->rpg_exchange_metal);
111
112
    $exchange = &$combat_data[UBE_OPTIONS][UBE_EXCHANGE];
113
    foreach (array(RES_CRYSTAL => 'rpg_exchange_crystal', RES_DEUTERIUM => 'rpg_exchange_deuterium', RES_DARK_MATTER => 'rpg_exchange_darkMatter') as $resource_id => $resource_name) {
114
      $exchange[$resource_id] = $config->$resource_name * $exchange[RES_METAL];
115
    }
116
117
    // Переменные для быстрого доступа к подмассивам
118
    $outcome = &$combat_data[UBE_OUTCOME];
119
    $fleets_info = &$combat_data[UBE_FLEETS];
120
    $last_round_data = &$combat_data[UBE_ROUNDS][count($combat_data[UBE_ROUNDS]) - 1];
121
122
    $outcome[UBE_DEBRIS] = array();
123
124
    // Генерируем результат боя
125
    foreach ($fleets_info as $fleet_id => &$fleet_info) {
126
      $fleet_type = $fleet_info[UBE_FLEET_TYPE];
127
      // Инициализируем массив результатов для флота
128
      $outcome[UBE_FLEETS][$fleet_id] = array(UBE_UNITS_LOST => array());
129
      $outcome[$fleet_type][UBE_FLEETS][$fleet_id] = &$outcome[UBE_FLEETS][$fleet_id];
130
131
      // Переменные для быстрого доступа к подмассивам
132
      $fleet_outcome = &$outcome[UBE_FLEETS][$fleet_id];
133
      $fleet_data = &$last_round_data[UBE_FLEETS][$fleet_id];
134
135
      foreach ($fleet_info[UBE_COUNT] as $unit_id => $unit_count) {
136
        // Вычисляем сколько юнитов осталось и сколько потеряно
137
        $units_left = $fleet_data[UBE_COUNT][$unit_id];
138
139
        // Восстановление обороны - 75% от уничтоженной
140
        if ($fleet_info[UBE_TYPE][$unit_id] == UNIT_DEFENCE) {
141
          $units_giveback = $this->defenceGiveBack($unit_count, $units_left, $isSimulatorStatic);
142
143
          $units_left += $units_giveback;
144
          $fleet_outcome[UBE_DEFENCE_RESTORE][$unit_id] = $units_giveback;
145
        }
146
147
        // TODO: Сбор металла/кристалла от обороны
148
149
        $units_lost = $unit_count - $units_left;
150
151
        // Вычисляем емкость трюмов оставшихся кораблей
152
        $outcome[$fleet_type][UBE_CAPACITY][$fleet_id] += $fleet_info[UBE_CAPACITY][$unit_id] * $units_left;
153
154
        // Вычисляем потери в ресурсах
155
        if ($units_lost) {
156
          $fleet_outcome[UBE_UNITS_LOST][$unit_id] = $units_lost;
157
158
          foreach ($fleet_info[UBE_PRICE] as $resource_id => $unit_prices) {
159
            if (!$unit_prices[$unit_id]) {
160
              continue;
161
            }
162
163
            // ...чистыми
164
            $resources_lost = $units_lost * $unit_prices[$unit_id];
165
            $fleet_outcome[UBE_RESOURCES_LOST][$resource_id] += $resources_lost;
166
167
            // Если это корабль - прибавляем потери к обломкам на орбите
168
            if ($fleet_info[UBE_TYPE][$unit_id] == UNIT_SHIPS) {
169
              $debrisFraction = (
170
                $isSimulatorStatic
171
                  ? (
172
                    static::DEBRIS_FROM_SHIPS_MIN_PERCENT +
173
                    static::DEBRIS_FROM_SHIPS_MAX_PERCENT) / 2
174
                  : mt_rand(
175
                  static::DEBRIS_FROM_SHIPS_MIN_PERCENT,
176
                  static::DEBRIS_FROM_SHIPS_MAX_PERCENT)
177
                ) / 100;
178
              $outcome[UBE_DEBRIS][$resource_id] += floor($resources_lost * $debrisFraction);
179
            }
180
181
            // ...в металле
182
            $resources_lost_in_metal = $resources_lost * $exchange[$resource_id];
183
            $fleet_outcome[UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $resources_lost_in_metal;
184
          }
185
        }
186
      }
187
188
      // На планете ($fleet_id = 0) ресурсы в космос не выбрасываются
189
      if ($fleet_id == 0) {
190
        continue;
191
      }
192
193
      // Количество ресурсов флота
194
      $fleet_total_resources = empty($fleet_info[UBE_RESOURCES]) ? 0 : array_sum($fleet_info[UBE_RESOURCES]);
195
      // Если на борту нет ресурсов - зачем нам все это?
196
      if ($fleet_total_resources == 0) {
197
        continue;
198
      }
199
200
      // Емкость трюмов флота
201
      $fleet_capacity = $outcome[$fleet_type][UBE_CAPACITY][$fleet_id];
202
      // Если емкость трюмов меньше количество ресурсов - часть ресов выбрасываем нахуй
203
      if ($fleet_capacity < $fleet_total_resources) {
204
        $left_percent = $fleet_capacity / $fleet_total_resources; // Сколько ресурсов будет оставлено
205
        foreach ($fleet_info[UBE_RESOURCES] as $resource_id => $resource_amount) {
206
          // Не просчитываем ресурсы, которых нет на борту кораблей флота
207
          if (!$resource_amount) {
208
            continue;
209
          }
210
211
          // TODO Восстанавливаем ошибку округления - придумать нормальный алгоритм - вроде round() должно быть достаточно. Проверить
212
          $fleet_outcome[UBE_RESOURCES][$resource_id] = round($left_percent * $resource_amount);
213
          $resource_dropped = $resource_amount - $fleet_outcome[UBE_RESOURCES][$resource_id];
214
          $fleet_outcome[UBE_CARGO_DROPPED][$resource_id] = $resource_dropped;
215
216
          $cargoDroppedFraction = (
217
            $isSimulatorStatic
218
              ? (static::DEBRIS_FROM_CARGO_MIN_PERCENT +
219
                static::DEBRIS_FROM_CARGO_MAX_PERCENT) / 2
220
              : mt_rand(
221
              static::DEBRIS_FROM_CARGO_MIN_PERCENT,
222
              static::DEBRIS_FROM_CARGO_MAX_PERCENT)
223
            ) / 100;
224
          $outcome[UBE_DEBRIS][$resource_id] += round($resource_dropped * $cargoDroppedFraction); // TODO: Configurize
225
          $fleet_outcome[UBE_RESOURCES_LOST_IN_METAL][RES_METAL] += $resource_dropped * $exchange[$resource_id];
226
        }
227
        $fleet_total_resources = array_sum($fleet_outcome[UBE_RESOURCES]);
228
      }
229
230
      $outcome[$fleet_type][UBE_CAPACITY][$fleet_id] = $fleet_capacity - $fleet_total_resources;
231
    }
232
233
    $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];
234
    // SFR - Small Fleet Reconnaissance ака РМФ
235
    $outcome[UBE_SFR] = count($combat_data[UBE_ROUNDS]) == 2 && $outcome[UBE_COMBAT_RESULT] == UBE_COMBAT_RESULT_LOSS;
236
237
    if (!$combat_data[UBE_OPTIONS][UBE_LOADED]) {
238
      if ($combat_data[UBE_OPTIONS][UBE_MOON_WAS]) {
239
        $outcome[UBE_MOON] = UBE_MOON_WAS;
240
      } else {
241
        $this->sn_ube_combat_analyze_moon($outcome, $isSimulatorStatic);
242
      }
243
244
      // Лутаем ресурсы - если аттакер выиграл
245
      if ($outcome[UBE_COMBAT_RESULT] == UBE_COMBAT_RESULT_WIN) {
246
        $this->sn_ube_combat_analyze_loot($combat_data);
247
        if ($combat_data[UBE_OPTIONS][UBE_MOON_WAS] && $combat_data[UBE_OPTIONS][UBE_MISSION_TYPE] == MT_DESTROY) {
248
          $this->sn_ube_combat_analyze_moon_destroy($combat_data);
249
        }
250
      }
251
    }
252
253
  }
254
255
// ------------------------------------------------------------------------------------------------
256
  protected function sn_ube_combat_analyze_moon(&$outcome, $is_simulator) {
257
    $outcome[UBE_DEBRIS_TOTAL] = 0;
258
    foreach ([RES_METAL, RES_CRYSTAL] as $resource_id) {
259
      $outcome[UBE_DEBRIS_TOTAL] += $outcome[UBE_DEBRIS][$resource_id];
260
    }
261
262
    $outcome[UBE_DEBRIS_ORIGINAL] = $outcome[UBE_DEBRIS];
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_SIZE]) {
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);
0 ignored issues
show
Unused Code introduced by
The assignment to $total_lootable is dead and can be removed.
Loading history...
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) {
0 ignored issues
show
introduced by
The condition Ube\Ube4_1\BE_DEBUG === true is always true.
Loading history...
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) {
0 ignored issues
show
introduced by
The condition Ube\Ube4_1\BE_DEBUG === true is always true.
Loading history...
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] ? 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