Completed
Push — trunk ( 5a98ee...c2d255 )
by SuperNova.WS
04:09
created

Ube4_1Calc::defenceGiveBack()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 3
nop 3
dl 0
loc 26
rs 8.439
c 0
b 0
f 0
ccs 0
cts 19
cp 0
crap 30
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));
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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);
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 can never be false.
Loading history...
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
406
      // sn_ube_combat_helper_round_header($round);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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: Это пока нельзя включать - вот если будут "боевые порядки юнитов..."
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

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.

Loading history...
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 can never be false.
Loading history...
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

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::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