1 | <?php /** @noinspection PhpDeprecationInspection */ |
||||||
2 | |||||||
3 | /** Created by Gorlum 09.05.2025 18:56 */ |
||||||
4 | |||||||
5 | namespace Fleet; |
||||||
6 | |||||||
7 | use SN; |
||||||
8 | |||||||
9 | class MissionExploreResult { |
||||||
10 | /** @var string Key in outcome config for roll value */ |
||||||
11 | const K_ROLL_VALUE = 'value'; |
||||||
12 | |||||||
13 | /** @var int Max DM can be found in 1 expedition */ |
||||||
14 | const MAX_DM = CONST_10K; |
||||||
15 | |||||||
16 | /** @var int $valueRolled mt_rand() value rolled [0,max_chance] that determine current expedition outcome */ |
||||||
17 | public $valueRolled = Constants::OUTCOME_NOT_CALCULATED; |
||||||
18 | /** @var int $outcome Expedition outcome */ |
||||||
19 | public $outcome = Constants::OUTCOME_NOT_CALCULATED; |
||||||
20 | /**@var array $currentOutcomeConfig Current outcome config */ |
||||||
21 | public $currentOutcomeConfig = []; |
||||||
22 | |||||||
23 | // Outcomes with variants - sub-outcomes |
||||||
24 | /** @var float $subOutcomeProbability Normalized probability [0,1] of sub-outcome */ |
||||||
25 | public $subOutcomeProbability = Constants::OUTCOME_NOT_CALCULATED; |
||||||
26 | /** @var int $subOutcome Secondary outcome (sub-outcome) for variable outcomes */ |
||||||
27 | public $subOutcome = Constants::OUTCOME_NOT_CALCULATED; |
||||||
28 | /** @var float $gainShare Share of total resources to gain - depends on sub-outcome */ |
||||||
29 | public $gainShare = 0; |
||||||
30 | |||||||
31 | // Units/Resources changes |
||||||
32 | /** @var int[] $shipsFound Ships found during current expedition */ |
||||||
33 | public $shipsFound = []; |
||||||
34 | /** @var int[] $shipsLost Ships lost during current expedition */ |
||||||
35 | public $shipsLost = []; |
||||||
36 | /** @var float[] $resourcesFound Resource amounts found during current expedition */ |
||||||
37 | public $resourcesFound = []; |
||||||
38 | /** @var int $darkMatterFound Dark Matter found during current expedition */ |
||||||
39 | public $darkMatterFound = 0; |
||||||
40 | |||||||
41 | // Other variables |
||||||
42 | /** @var array $ships Current list of ships within mission. CAN be changed by outcomes and SHOULD be changed if ships lost/found */ |
||||||
43 | public $ships = []; |
||||||
44 | /** @var int $fleetCapacityFree Free fleet capacity left */ |
||||||
45 | public $fleetCapacityFree = 0; |
||||||
46 | /** @var int $shipsCostInMetal Total ships cost in metal */ |
||||||
47 | public $shipsCostInMetal = 0; |
||||||
48 | |||||||
49 | /** @var ?FleetDispatchEvent $fleetEvent Event currently processed */ |
||||||
50 | public $fleetEvent = null; |
||||||
51 | |||||||
52 | /** @var float $timeStart Timestamp with ms when started expedition processing */ |
||||||
53 | protected $timeStart = 0; |
||||||
54 | |||||||
55 | /** @var array[] $configs */ |
||||||
56 | public static $configs = [ |
||||||
57 | Constants::OUTCOME_NONE => [ |
||||||
58 | Constants::K_OUTCOME => Constants::OUTCOME_NONE, |
||||||
59 | Constants::K_OUTCOME_TYPE => Constants::OUTCOME_TYPE_NEUTRAL, |
||||||
60 | P_CHANCE => Constants::OUTCOME_EXPEDITION_NOTHING_DEFAULT_CHANCE, |
||||||
61 | ], |
||||||
62 | Constants::EXPEDITION_OUTCOME_LOST_FLEET => [ |
||||||
63 | Constants::K_OUTCOME => Constants::EXPEDITION_OUTCOME_LOST_FLEET, |
||||||
64 | Constants::K_OUTCOME_TYPE => Constants::OUTCOME_TYPE_BAD, |
||||||
65 | P_CHANCE => 9, |
||||||
66 | ], |
||||||
67 | Constants::EXPEDITION_OUTCOME_LOST_FLEET_ALL => [ |
||||||
68 | Constants::K_OUTCOME => Constants::EXPEDITION_OUTCOME_LOST_FLEET_ALL, |
||||||
69 | Constants::K_OUTCOME_TYPE => Constants::OUTCOME_TYPE_BAD, |
||||||
70 | P_CHANCE => 3, |
||||||
71 | ], |
||||||
72 | Constants::EXPEDITION_OUTCOME_FOUND_FLEET => [ |
||||||
73 | Constants::K_OUTCOME => Constants::EXPEDITION_OUTCOME_FOUND_FLEET, |
||||||
74 | Constants::K_OUTCOME_TYPE => Constants::OUTCOME_TYPE_GOOD, |
||||||
75 | P_CHANCE => 200, |
||||||
76 | 'percent' => [0 => 0.1, 1 => 0.02, 2 => 0.01,], |
||||||
77 | Constants::K_OUTCOME_SECONDARY => [ |
||||||
78 | [P_CHANCE => 90, P_MULTIPLIER => 0.01, P_MESSAGE_ID => 2,], |
||||||
79 | [P_CHANCE => 9, P_MULTIPLIER => 0.02, P_MESSAGE_ID => 1,], |
||||||
80 | [P_CHANCE => 1, P_MULTIPLIER => 0.10, P_MESSAGE_ID => 0,], |
||||||
81 | ], |
||||||
82 | ], |
||||||
83 | Constants::EXPEDITION_OUTCOME_FOUND_RESOURCES => [ |
||||||
84 | Constants::K_OUTCOME => Constants::EXPEDITION_OUTCOME_FOUND_RESOURCES, |
||||||
85 | Constants::K_OUTCOME_TYPE => Constants::OUTCOME_TYPE_GOOD, |
||||||
86 | P_CHANCE => 300, |
||||||
87 | 'percent' => [0 => 0.1, 1 => 0.050, 2 => 0.025,], |
||||||
88 | Constants::K_OUTCOME_SECONDARY => [ |
||||||
89 | [P_CHANCE => 90, P_MULTIPLIER => 0.025, P_MESSAGE_ID => 2,], |
||||||
90 | [P_CHANCE => 9, P_MULTIPLIER => 0.050, P_MESSAGE_ID => 1,], |
||||||
91 | [P_CHANCE => 1, P_MULTIPLIER => 0.100, P_MESSAGE_ID => 0,], |
||||||
92 | ], |
||||||
93 | ], |
||||||
94 | Constants::EXPEDITION_OUTCOME_FOUND_DM => [ |
||||||
95 | Constants::K_OUTCOME => Constants::EXPEDITION_OUTCOME_FOUND_DM, |
||||||
96 | Constants::K_OUTCOME_TYPE => Constants::OUTCOME_TYPE_GOOD, |
||||||
97 | P_CHANCE => 100, |
||||||
98 | 'percent' => [0 => 0.0100, 1 => 0.0040, 2 => 0.0010,], |
||||||
99 | Constants::K_OUTCOME_SECONDARY => [ |
||||||
100 | [P_CHANCE => 90, P_MULTIPLIER => 0.0010, /*P_MESSAGE_ID => 2,*/], |
||||||
101 | [P_CHANCE => 9, P_MULTIPLIER => 0.0040, /*P_MESSAGE_ID => 1,*/], |
||||||
102 | [P_CHANCE => 1, P_MULTIPLIER => 0.0100, /*P_MESSAGE_ID => 0,*/], |
||||||
103 | ], |
||||||
104 | ], |
||||||
105 | /* |
||||||
106 | FLT_EXPEDITION_OUTCOME_FOUND_ARTIFACT => array( |
||||||
107 | 'outcome' => FLT_EXPEDITION_OUTCOME_FOUND_ARTIFACT, |
||||||
108 | P_CHANCE => 10, |
||||||
109 | ), |
||||||
110 | */ |
||||||
111 | ]; |
||||||
112 | |||||||
113 | /** @var array[] $shipData */ |
||||||
114 | public static $shipData = []; |
||||||
115 | /** @var float[] $rates Resources exchange rates */ |
||||||
116 | public static $rates = []; |
||||||
117 | |||||||
118 | public function __construct() { |
||||||
119 | self::getShipData(); |
||||||
120 | self::getExchangeRates(); |
||||||
121 | } |
||||||
122 | |||||||
123 | /** |
||||||
124 | * @return int |
||||||
125 | */ |
||||||
126 | public function flt_mission_explore(FleetDispatchEvent $fleetEvent) { |
||||||
127 | if ($fleetEvent->event != EVENT_FLT_ACCOMPLISH) { |
||||||
128 | return CACHE_NONE; |
||||||
129 | } |
||||||
130 | |||||||
131 | // Preparing for expedition |
||||||
132 | $this->timeStart = microtime(true); |
||||||
0 ignored issues
–
show
|
|||||||
133 | |||||||
134 | $this->resetExpedition($fleetEvent); |
||||||
135 | |||||||
136 | $this->calcSecondaryData(); |
||||||
137 | |||||||
138 | // Calculating mission outcome |
||||||
139 | |||||||
140 | // Making a copy of outcome configs to tamper with |
||||||
141 | $outcomeConfigs = static::$configs; |
||||||
142 | |||||||
143 | $outcomeConfigs = $this->adjustNoneChance($outcomeConfigs); |
||||||
144 | |||||||
145 | list($outcomeConfigs, $chance_max) = $this->calculateRollValues($outcomeConfigs); |
||||||
146 | |||||||
147 | |||||||
148 | // Rolling value which wil determine outcome |
||||||
149 | $this->valueRolled = mt_rand(0, ceil($chance_max)); |
||||||
0 ignored issues
–
show
ceil($chance_max) of type double is incompatible with the type integer expected by parameter $max of mt_rand() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() $chance_max of type array is incompatible with the type double|integer expected by parameter $num of ceil() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
150 | // NOTHING => 200, LOST_FLEET => 209, LOST_FLEET_ALL => 212, FOUND_FLEET => 412, RESOURCES => 712, FOUND_DM => 812 |
||||||
151 | // $this->valueRolled = 409; // DEBUG comment! |
||||||
152 | // Determining outcome |
||||||
153 | foreach ($outcomeConfigs as $key1 => $config) { |
||||||
0 ignored issues
–
show
|
|||||||
154 | if (!$config[P_CHANCE]) { |
||||||
155 | continue; |
||||||
156 | } |
||||||
157 | $this->outcome = $key1; |
||||||
158 | if ($this->valueRolled <= $config [self::K_ROLL_VALUE]) { |
||||||
159 | break; |
||||||
160 | } |
||||||
161 | } |
||||||
162 | // Fallback in case something went wrong |
||||||
163 | if ($this->outcome == Constants::OUTCOME_NOT_CALCULATED) { |
||||||
164 | $this->outcome = Constants::OUTCOME_NONE; |
||||||
165 | } |
||||||
166 | $this->currentOutcomeConfig = $outcomeConfigs[$this->outcome]; |
||||||
167 | |||||||
168 | // Вычисляем вероятность выпадения данного числа в общем пуле |
||||||
169 | $this->subOutcomeProbability = ($this->currentOutcomeConfig[self::K_ROLL_VALUE] - $this->valueRolled) / $this->currentOutcomeConfig[P_CHANCE]; |
||||||
170 | $this->subOutcome = $this->subOutcomeProbability >= 0.99 ? 0 : ($this->subOutcomeProbability >= 0.90 ? 1 : 2); |
||||||
171 | $this->gainShare = !empty($this->currentOutcomeConfig['percent'][$this->subOutcome]) |
||||||
172 | ? $this->currentOutcomeConfig['percent'][$this->subOutcome] |
||||||
173 | : Constants::OUTCOME_NOT_CALCULATED; |
||||||
174 | |||||||
175 | // Outcome CAN change ONLY object properties and SHOULD NOT mess with real fleet values |
||||||
176 | switch ($this->outcome) { |
||||||
177 | case Constants::OUTCOME_NONE: |
||||||
178 | $this->subOutcome = Constants::OUTCOME_NOT_CALCULATED; |
||||||
179 | break; |
||||||
180 | |||||||
181 | case Constants::EXPEDITION_OUTCOME_LOST_FLEET: |
||||||
182 | $this->outcomeShipsLostPartially(); |
||||||
183 | $this->subOutcome = Constants::OUTCOME_NOT_CALCULATED; |
||||||
184 | break; |
||||||
185 | |||||||
186 | case Constants::EXPEDITION_OUTCOME_LOST_FLEET_ALL: |
||||||
187 | $this->outcomeLostFleetAll(); |
||||||
188 | $this->subOutcome = Constants::OUTCOME_NOT_CALCULATED; |
||||||
189 | break; |
||||||
190 | |||||||
191 | case Constants::EXPEDITION_OUTCOME_FOUND_FLEET: |
||||||
192 | $this->outcomeFoundShips(); |
||||||
193 | break; |
||||||
194 | |||||||
195 | case Constants::EXPEDITION_OUTCOME_FOUND_RESOURCES: |
||||||
196 | $this->outcomeFoundResources(); |
||||||
197 | break; |
||||||
198 | |||||||
199 | case Constants::EXPEDITION_OUTCOME_FOUND_DM: |
||||||
200 | $this->outcomeFoundDm(); |
||||||
201 | break; |
||||||
202 | |||||||
203 | //case FLT_EXPEDITION_OUTCOME_FOUND_ARTIFACT: |
||||||
204 | //break; |
||||||
205 | |||||||
206 | default: |
||||||
207 | break; |
||||||
208 | } |
||||||
209 | |||||||
210 | // Calling extra |
||||||
211 | $this->flt_mission_explore_addon($this); |
||||||
212 | |||||||
213 | // Applying expedition changes to real fleet data |
||||||
214 | $this->applyFleetChanges(); |
||||||
215 | |||||||
216 | // Saving expedition result to DB |
||||||
217 | $this->saveResult(); |
||||||
218 | |||||||
219 | // Sending expedition report to player |
||||||
220 | $this->sendReport($this->fleetEvent->fleet); |
||||||
221 | |||||||
222 | return CACHE_FLEET | CACHE_USER_SRC; |
||||||
223 | } |
||||||
224 | |||||||
225 | /** |
||||||
226 | * @param array $theFleet |
||||||
227 | * |
||||||
228 | * @return string |
||||||
229 | */ |
||||||
230 | protected function renderUnits(array $theFleet) { |
||||||
231 | $add = ''; |
||||||
232 | foreach ($theFleet as $ship_id => $ship_amount) { |
||||||
233 | $add .= SN::$lang['tech'][$ship_id] . ' - ' . $ship_amount . "\r\n"; |
||||||
234 | } |
||||||
235 | |||||||
236 | return $add; |
||||||
237 | } |
||||||
238 | |||||||
239 | /** |
||||||
240 | * @param static $outcome |
||||||
241 | * |
||||||
242 | * @return static |
||||||
243 | */ |
||||||
244 | protected function flt_mission_explore_addon(MissionExploreResult $outcome) { |
||||||
245 | /** @see core_festival::expedition_result_adjust(), FestivalActivityPuzzleExpedition::fleet_explore_adjust_result() */ |
||||||
246 | return sn_function_call(Constants::HOOK_MISSION_EXPLORE_ADDON, [$outcome]); |
||||||
247 | } |
||||||
248 | |||||||
249 | /** |
||||||
250 | * Reset current expedition state |
||||||
251 | * |
||||||
252 | * @param ?FleetDispatchEvent $fleetEvent |
||||||
253 | * |
||||||
254 | * @return void |
||||||
255 | */ |
||||||
256 | protected function resetExpedition(FleetDispatchEvent $fleetEvent = null) { |
||||||
257 | $this->fleetEvent = $fleetEvent; |
||||||
258 | |||||||
259 | // Fleet's ship list |
||||||
260 | $this->ships = !empty($this->fleetEvent->fleet['fleet_array']) |
||||||
261 | ? sys_unit_str2arr($this->fleetEvent->fleet['fleet_array']) |
||||||
262 | : []; |
||||||
263 | |||||||
264 | $this->shipsLost = []; |
||||||
265 | $this->shipsFound = []; |
||||||
266 | $this->resourcesFound = []; |
||||||
267 | $this->darkMatterFound = 0; |
||||||
268 | |||||||
269 | $this->valueRolled = -1; |
||||||
270 | $this->outcome = Constants::OUTCOME_NOT_CALCULATED; |
||||||
271 | $this->subOutcomeProbability = -1; |
||||||
272 | $this->subOutcome = Constants::OUTCOME_NOT_CALCULATED; |
||||||
273 | $this->gainShare = 0; |
||||||
274 | |||||||
275 | $this->fleetCapacityFree = 0; |
||||||
276 | $this->shipsCostInMetal = 0; |
||||||
277 | } |
||||||
278 | |||||||
279 | /** |
||||||
280 | * Get data for ships |
||||||
281 | * |
||||||
282 | * @return array[] |
||||||
283 | */ |
||||||
284 | protected static function getShipData() { |
||||||
285 | if (empty(static::$shipData)) { |
||||||
286 | foreach (sn_get_groups('fleet') as $unit_id) { |
||||||
287 | $unit_info = get_unit_param($unit_id); |
||||||
288 | if ($unit_info[P_UNIT_TYPE] != UNIT_SHIPS || empty($unit_info['engine'][0]['speed'])) { |
||||||
289 | continue; |
||||||
290 | } |
||||||
291 | $unit_info[P_COST_METAL] = get_unit_cost_in($unit_info[P_COST]); |
||||||
292 | |||||||
293 | static::$shipData[$unit_id] = $unit_info; |
||||||
294 | } |
||||||
295 | } |
||||||
296 | |||||||
297 | return static::$shipData; |
||||||
298 | } |
||||||
299 | |||||||
300 | /** |
||||||
301 | * Get resource exchange rates |
||||||
302 | * |
||||||
303 | * @return float[] |
||||||
304 | */ |
||||||
305 | protected static function getExchangeRates() { |
||||||
306 | if (empty(static::$rates)) { |
||||||
307 | static::$rates = SN::$gc->economicHelper->getResourcesExchange(); |
||||||
308 | } |
||||||
309 | |||||||
310 | return static::$rates; |
||||||
311 | } |
||||||
312 | |||||||
313 | /** |
||||||
314 | * Saving expedition results to DB |
||||||
315 | * |
||||||
316 | * @return void |
||||||
317 | */ |
||||||
318 | protected function saveResult() { |
||||||
319 | // Increasing expedition XP - 1 point per Expedition |
||||||
320 | db_user_set_by_id($this->fleetEvent->fleetOwnerId, "`player_rpg_explore_xp` = `player_rpg_explore_xp` + 1"); |
||||||
0 ignored issues
–
show
The function
db_user_set_by_id() has been deprecated.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
321 | // Saving changed data to DB |
||||||
322 | if ($this->darkMatterFound >= 1) { |
||||||
323 | rpg_points_change($this->fleetEvent->fleetOwnerId, RPG_EXPEDITION, $this->darkMatterFound, 'Expedition Bonus'); |
||||||
0 ignored issues
–
show
'Expedition Bonus' of type string is incompatible with the type boolean expected by parameter $comment of rpg_points_change() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
324 | } |
||||||
325 | |||||||
326 | // Checking if the fleet was destroyed entirely |
||||||
327 | if (($fleetAmount = array_sum($this->ships)) >= 1) { |
||||||
328 | // No - some ships left |
||||||
329 | $query_data = |
||||||
330 | // Routing fleet to return path |
||||||
331 | ['fleet_mess' => FLEET_STATUS_RETURNING] |
||||||
332 | // If there were some changes to the fleet - propagating them to DB |
||||||
333 | + (!empty($this->shipsLost) || !empty($this->shipsFound) |
||||||
334 | ? [ |
||||||
335 | 'fleet_amount' => $fleetAmount, |
||||||
336 | 'fleet_array' => sys_unit_arr2str($this->ships), |
||||||
337 | ] |
||||||
338 | : [] |
||||||
339 | ); |
||||||
340 | |||||||
341 | $query_delta = []; |
||||||
342 | // If we found some resources - adding them to cargo bays |
||||||
343 | if (!empty($this->resourcesFound) && array_sum($this->resourcesFound) > 0) { |
||||||
344 | $query_delta = [ |
||||||
345 | 'fleet_resource_metal' => $this->resourcesFound[RES_METAL], |
||||||
346 | 'fleet_resource_crystal' => $this->resourcesFound[RES_CRYSTAL], |
||||||
347 | 'fleet_resource_deuterium' => $this->resourcesFound[RES_DEUTERIUM], |
||||||
348 | ]; |
||||||
349 | } |
||||||
350 | |||||||
351 | DbFleetStatic::fleet_update_set($this->fleetEvent->fleetId, $query_data, $query_delta); |
||||||
352 | } else { |
||||||
353 | // Fleet empty? Removing fleet from DB |
||||||
354 | DbFleetStatic::db_fleet_delete($this->fleetEvent->fleetId); |
||||||
355 | } |
||||||
356 | } |
||||||
357 | |||||||
358 | /** |
||||||
359 | * Compile and send expedition report |
||||||
360 | * |
||||||
361 | * @param array $fleetRow |
||||||
362 | * |
||||||
363 | * @return void |
||||||
364 | */ |
||||||
365 | protected function sendReport(array $fleetRow) { |
||||||
366 | // Generating PM for user |
||||||
367 | $langExpeditions = SN::$lang['flt_mission_expedition']; |
||||||
368 | // Generating outcome-specific details |
||||||
369 | $msg_text_addon = ''; |
||||||
370 | if ($this->outcome == Constants::EXPEDITION_OUTCOME_FOUND_DM) { |
||||||
371 | $msg_text_addon = $this->darkMatterFound >= 1 |
||||||
372 | ? sprintf($langExpeditions['found_dark_matter'], $this->darkMatterFound) |
||||||
373 | : $langExpeditions['outcomes'][$this->outcome]['no_result']; |
||||||
374 | } |
||||||
375 | |||||||
376 | if ($this->outcome == Constants::EXPEDITION_OUTCOME_FOUND_RESOURCES) { |
||||||
377 | if (array_sum($this->resourcesFound) >= 1) { |
||||||
378 | $msg_text_addon = $langExpeditions['found_resources']; |
||||||
379 | $msg_text_addon .= $this->renderUnits($this->resourcesFound); |
||||||
380 | } else { |
||||||
381 | $msg_text_addon = $langExpeditions['outcomes'][$this->outcome]['no_result']; |
||||||
382 | } |
||||||
383 | } |
||||||
384 | |||||||
385 | if (!empty($this->shipsLost)) { |
||||||
386 | $msg_text_addon = $langExpeditions['lost_fleet']; |
||||||
387 | $msg_text_addon .= $this->renderUnits($this->shipsLost); |
||||||
388 | } |
||||||
389 | |||||||
390 | if ($this->outcome == Constants::EXPEDITION_OUTCOME_FOUND_FLEET) { |
||||||
391 | if (empty($this->shipsFound)) { |
||||||
392 | $msg_text_addon = $langExpeditions['outcomes'][$this->outcome]['no_result']; |
||||||
393 | } |
||||||
394 | } |
||||||
395 | |||||||
396 | if (!empty($this->ships) && array_sum($this->ships) >= 1) { |
||||||
397 | if (!empty($this->shipsFound)) { |
||||||
398 | $msg_text_addon = $langExpeditions['found_fleet'] . $this->renderUnits($this->shipsFound); |
||||||
399 | } |
||||||
400 | } |
||||||
401 | |||||||
402 | $messages = $langExpeditions['outcomes'][$this->outcome]['messages']; |
||||||
403 | if ( |
||||||
404 | // Outcome have sub-outcomes |
||||||
405 | !empty($this->currentOutcomeConfig['percent']) |
||||||
406 | // Some outcome rolled |
||||||
407 | && $this->subOutcome >= 0 |
||||||
408 | // Messages are different for different outcomes |
||||||
409 | && is_array($messages) |
||||||
410 | ) { |
||||||
411 | // Selecting messages for specific outcome |
||||||
412 | $messages = &$messages[$this->subOutcome]; |
||||||
413 | } |
||||||
414 | |||||||
415 | $msg_text = is_string($messages) |
||||||
416 | // If we have only one variant for message - using it |
||||||
417 | ? $messages |
||||||
418 | // If we have several message variations - selecting one randomly |
||||||
419 | : (is_array($messages) ? $messages[mt_rand(0, count($messages) - 1)] : ''); |
||||||
420 | |||||||
421 | $msg_text = sprintf( |
||||||
422 | $msg_text, |
||||||
423 | $this->fleetEvent->fleetId, |
||||||
424 | uni_render_coordinates($fleetRow, 'fleet_end_') |
||||||
425 | ) . ($msg_text_addon ? "\r\n" . $msg_text_addon : ''); |
||||||
426 | |||||||
427 | msg_send_simple_message( |
||||||
428 | $this->fleetEvent->fleetOwnerId, |
||||||
429 | '', |
||||||
430 | $fleetRow['fleet_end_stay'], |
||||||
431 | MSG_TYPE_EXPLORE, |
||||||
432 | $langExpeditions['msg_sender'], |
||||||
433 | $langExpeditions['msg_title'], |
||||||
434 | $msg_text |
||||||
435 | ); |
||||||
436 | } |
||||||
437 | |||||||
438 | /** |
||||||
439 | * @return void |
||||||
440 | */ |
||||||
441 | protected function applyFleetChanges() { |
||||||
442 | // Shortcut to access and change fleet data in event |
||||||
443 | $fleetRow = &$this->fleetEvent->fleet; |
||||||
444 | |||||||
445 | // Adding found ships |
||||||
446 | foreach (!empty($this->shipsFound) ? $this->shipsFound : [] as $unit_id => $unit_amount) { |
||||||
447 | $this->ships[$unit_id] += $unit_amount; |
||||||
448 | } |
||||||
449 | // Removing lost ships |
||||||
450 | foreach (!empty($this->shipsLost) ? $this->shipsLost : [] as $shipLostId => $shipLostCount) { |
||||||
451 | $this->ships[$shipLostId] -= $shipLostCount; |
||||||
452 | if ($this->ships[$shipLostId] < 1) { |
||||||
453 | unset($this->ships[$shipLostId]); |
||||||
454 | } |
||||||
455 | } |
||||||
456 | // Adjusting ship data in real fleet record |
||||||
457 | $fleetRow['fleet_amount'] = array_sum($this->ships); |
||||||
458 | $fleetRow['fleet_array'] = sys_unit_arr2str($this->ships); |
||||||
459 | |||||||
460 | // Adjusting resources data in real fleet record |
||||||
461 | if (array_sum($this->resourcesFound) >= 1) { |
||||||
462 | $fleetRow['fleet_resource_metal'] += $this->resourcesFound[RES_METAL]; |
||||||
463 | $fleetRow['fleet_resource_crystal'] += $this->resourcesFound[RES_CRYSTAL]; |
||||||
464 | $fleetRow['fleet_resource_deuterium'] += $this->resourcesFound[RES_DEUTERIUM]; |
||||||
465 | } |
||||||
466 | |||||||
467 | // Setting fleet to return route |
||||||
468 | $fleetRow['fleet_mess'] = FLEET_STATUS_RETURNING; |
||||||
469 | } |
||||||
470 | |||||||
471 | /** |
||||||
472 | * Calculating fleet cost in metal and free capacity |
||||||
473 | * |
||||||
474 | * @return void |
||||||
475 | */ |
||||||
476 | protected function calcSecondaryData() { |
||||||
477 | // Calculating ship's free capacity and fleet cost in metal |
||||||
478 | foreach ($this->ships as $ship_id => $ship_amount) { |
||||||
479 | $this->fleetCapacityFree += $ship_amount * static::$shipData[$ship_id][P_CAPACITY]; |
||||||
480 | $this->shipsCostInMetal += $ship_amount * static::$shipData[$ship_id][P_COST_METAL]; |
||||||
481 | } |
||||||
482 | // Calculating rest of fleet capacity - room which not occupied with resources |
||||||
483 | $this->fleetCapacityFree = max( |
||||||
484 | 0, |
||||||
485 | $this->fleetCapacityFree |
||||||
486 | - $this->fleetEvent->fleet['fleet_resource_metal'] |
||||||
487 | - $this->fleetEvent->fleet['fleet_resource_crystal'] |
||||||
488 | - $this->fleetEvent->fleet['fleet_resource_deuterium'] |
||||||
489 | ); |
||||||
490 | } |
||||||
491 | |||||||
492 | /** |
||||||
493 | * @param array $outcomeConfigs |
||||||
494 | * |
||||||
495 | * @return array |
||||||
496 | */ |
||||||
497 | protected function adjustNoneChance(array $outcomeConfigs) { |
||||||
498 | // Calculating how many hours spent in expedition |
||||||
499 | $flt_stay_hours = |
||||||
500 | ($this->fleetEvent->fleet['fleet_end_stay'] - $this->fleetEvent->fleet['fleet_start_time']) / 3600 |
||||||
501 | * (SN::$config->game_speed_expedition ?: 1); |
||||||
502 | // Adjusting chance for empty outcome - expedition found nothing |
||||||
503 | $outcomeConfigs[Constants::OUTCOME_NONE][P_CHANCE] = ceil(Constants::OUTCOME_EXPEDITION_NOTHING_DEFAULT_CHANCE / max(0.1, pow($flt_stay_hours, 1 / 1.7))); |
||||||
504 | |||||||
505 | return $outcomeConfigs; |
||||||
506 | } |
||||||
507 | |||||||
508 | /** |
||||||
509 | * @param array $outcomeConfigs |
||||||
510 | * |
||||||
511 | * @return array{0: int, 1: array} |
||||||
512 | */ |
||||||
513 | protected function calculateRollValues(array $outcomeConfigs) { |
||||||
514 | // Calculating max chance can be rolled for current expedition |
||||||
515 | $chance_max = 0; |
||||||
516 | foreach ($outcomeConfigs as $key => &$outcomeConfig) { |
||||||
517 | // Removing invalid outcomes - with no chances set or zero chances |
||||||
518 | if (empty($outcomeConfig[P_CHANCE])) { |
||||||
519 | unset($outcomeConfigs[$key]); |
||||||
520 | continue; |
||||||
521 | } |
||||||
522 | $outcomeConfig[self::K_ROLL_VALUE] = $chance_max = $outcomeConfig[P_CHANCE] + $chance_max; |
||||||
523 | } |
||||||
524 | |||||||
525 | return [$outcomeConfigs, $chance_max]; |
||||||
526 | } |
||||||
527 | |||||||
528 | /** |
||||||
529 | * Outcome - ships partially lost |
||||||
530 | * |
||||||
531 | * @return void |
||||||
532 | */ |
||||||
533 | protected function outcomeShipsLostPartially() { |
||||||
534 | // 1-3 pack of 20-30%% -> 20-90%% lost totally |
||||||
535 | // Calculating lost share per fleet to maintain mathematical consistency for math model |
||||||
536 | $lostShare = mt_rand(1, 3) * (mt_rand(200000, 300000) / CONST_1M); |
||||||
537 | foreach ($this->ships as $shipId => $shipCount) { |
||||||
538 | $this->shipsLost[$shipId] = ceil($shipCount * $lostShare); |
||||||
539 | } |
||||||
540 | } |
||||||
541 | |||||||
542 | /** |
||||||
543 | * Outcome - lost all fleet |
||||||
544 | * |
||||||
545 | * @return void |
||||||
546 | */ |
||||||
547 | protected function outcomeLostFleetAll() { |
||||||
548 | foreach ($this->ships as $shipsId => $shipCount) { |
||||||
549 | $this->shipsLost[$shipsId] += $this->ships[$shipsId]; |
||||||
550 | } |
||||||
551 | } |
||||||
552 | |||||||
553 | /** |
||||||
554 | * @return void |
||||||
555 | */ |
||||||
556 | protected function outcomeFoundResources() { |
||||||
557 | // Calculating found resources amount in metal |
||||||
558 | $found_in_metal = ceil( |
||||||
559 | min($this->gainShare * $this->shipsCostInMetal, game_resource_multiplier(true) * CONST_10M, $this->fleetCapacityFree) |
||||||
560 | // 95-105%% [0.95 - 1.05] |
||||||
561 | * (mt_rand(95 * 10000, 105 * 10000) / CONST_1M) |
||||||
562 | ); // game_speed |
||||||
563 | |||||||
564 | // 30-70%% of resources found are found in metal. Large numbers used to add more variability |
||||||
565 | $this->resourcesFound[RES_METAL] = floor($found_in_metal * mt_rand(3 * CONST_100K, 7 * CONST_100K) / CONST_1M); |
||||||
566 | // Deducing found metal from pool |
||||||
567 | $found_in_metal -= $this->resourcesFound[RES_METAL]; |
||||||
568 | |||||||
569 | // Converting rest of found metal to crystals. Large numbers used to add more variability |
||||||
570 | $found_in_metal = floor($found_in_metal * static::$rates[RES_METAL] / static::$rates[RES_CRYSTAL]); |
||||||
571 | // 50-100%% of rest resources are found in crystals |
||||||
572 | $this->resourcesFound[RES_CRYSTAL] = floor($found_in_metal * mt_rand(5 * CONST_100K, 10 * CONST_100K) / CONST_1M); |
||||||
573 | // Deducing found crystals from pool |
||||||
574 | $found_in_metal -= $this->resourcesFound[RES_CRYSTAL]; |
||||||
575 | |||||||
576 | // Converting rest of found crystals to deuterium |
||||||
577 | $found_in_metal = floor($found_in_metal * static::$rates[RES_CRYSTAL] / static::$rates[RES_DEUTERIUM]); |
||||||
578 | // 100% of resources rest are in deuterium |
||||||
579 | $this->resourcesFound[RES_DEUTERIUM] = $found_in_metal; |
||||||
580 | } |
||||||
581 | |||||||
582 | /** |
||||||
583 | * |
||||||
584 | * @return void |
||||||
585 | */ |
||||||
586 | protected function outcomeFoundShips() { |
||||||
587 | // Рассчитываем эквивалент найденного флота в метале |
||||||
588 | $found_in_metal = min($this->gainShare * $this->shipsCostInMetal, game_resource_multiplier(true) * CONST_10M); |
||||||
589 | // 13 243 754 000 g x1 |
||||||
590 | // 60 762 247 000 a x10 |
||||||
591 | // 308 389 499 488 000 b x500 |
||||||
592 | |||||||
593 | // Рассчитываем стоимость самого дорого корабля в металле |
||||||
594 | $shipMaxCostInMetal = 0; |
||||||
595 | foreach ($this->ships as $ship_id => $ship_amount) { |
||||||
596 | $shipMaxCostInMetal = max($shipMaxCostInMetal, static::$shipData[$ship_id][P_COST_METAL]); |
||||||
597 | } |
||||||
598 | |||||||
599 | // Ограничиваем корабли только теми, чья стоимость в металле меньше или равно стоимости самого дорогого корабля |
||||||
600 | $can_be_found = []; |
||||||
601 | |||||||
602 | foreach (static::$shipData as $ship_id => $ship_info) { |
||||||
603 | if ( |
||||||
604 | $ship_info[P_COST_METAL] <= $shipMaxCostInMetal |
||||||
605 | // and not race ship |
||||||
606 | && empty($ship_info[P_RACE_SHIP]) |
||||||
607 | // and not event-related ship |
||||||
608 | && empty($ship_info[P_REQUIRE_HIGHSPOT]) |
||||||
609 | ) { |
||||||
610 | $can_be_found[$ship_id] = $ship_info[P_COST_METAL]; |
||||||
611 | } |
||||||
612 | } |
||||||
613 | |||||||
614 | // Убираем колонизаторы и шпионов - миллиарды шпионов и колонизаторов нам не нужны |
||||||
615 | unset($can_be_found[SHIP_COLONIZER]); |
||||||
616 | unset($can_be_found[SHIP_SPY]); |
||||||
617 | |||||||
618 | while (count($can_be_found) && $found_in_metal >= max($can_be_found)) { |
||||||
619 | $found_index = mt_rand(1, count($can_be_found)) - 1; |
||||||
620 | $found_ship = array_slice($can_be_found, $found_index, 1, true); |
||||||
621 | $found_ship_cost = reset($found_ship); |
||||||
622 | $found_ship_id = key($found_ship); |
||||||
623 | |||||||
624 | if ($found_ship_cost > $found_in_metal) { |
||||||
625 | unset($can_be_found[$found_ship_id]); |
||||||
626 | } else { |
||||||
627 | $found_ship_count = mt_rand(1, floor($found_in_metal / $found_ship_cost)); |
||||||
0 ignored issues
–
show
floor($found_in_metal / $found_ship_cost) of type double is incompatible with the type integer expected by parameter $max of mt_rand() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
628 | $this->shipsFound[$found_ship_id] += $found_ship_count; |
||||||
629 | $found_in_metal -= $found_ship_count * $found_ship_cost; |
||||||
630 | } |
||||||
631 | } |
||||||
632 | } |
||||||
633 | |||||||
634 | /** |
||||||
635 | * @return void |
||||||
636 | */ |
||||||
637 | protected function outcomeFoundDm() { |
||||||
638 | // Рассчитываем количество найденной ТМ |
||||||
639 | $this->darkMatterFound = floor( |
||||||
640 | min( |
||||||
641 | $this->gainShare * $this->shipsCostInMetal / static::$rates[RES_DARK_MATTER], |
||||||
642 | self::MAX_DM |
||||||
643 | ) |
||||||
644 | // 75-100%% of calculated value |
||||||
645 | * mt_rand(750000, CONST_1M) / CONST_1M |
||||||
646 | ); |
||||||
647 | } |
||||||
648 | |||||||
649 | } |
||||||
650 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.