1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Properties and methods for a ship instance. |
5
|
|
|
* Does not include the database layer (see SmrShip). |
6
|
|
|
*/ |
7
|
|
|
class AbstractSmrShip { |
8
|
|
|
|
9
|
|
|
// Player exp gained for each point of damage done |
10
|
|
|
const EXP_PER_DAMAGE_PLAYER = 0.375; |
11
|
|
|
const EXP_PER_DAMAGE_PLANET = 1.0; // note that planet damage is reduced |
12
|
|
|
const EXP_PER_DAMAGE_PORT = 0.15; |
13
|
|
|
const EXP_PER_DAMAGE_FORCE = 0.075; |
14
|
|
|
|
15
|
|
|
const STARTER_SHIPS = [ |
16
|
|
|
RACE_NEUTRAL => SHIP_TYPE_GALACTIC_SEMI, |
17
|
|
|
RACE_ALSKANT => SHIP_TYPE_SMALL_TIMER, |
18
|
|
|
RACE_CREONTI => SHIP_TYPE_MEDIUM_CARGO_HULK, |
19
|
|
|
RACE_HUMAN => SHIP_TYPE_LIGHT_FREIGHTER, |
20
|
|
|
RACE_IKTHORNE => SHIP_TYPE_TINY_DELIGHT, |
21
|
|
|
RACE_SALVENE => SHIP_TYPE_HATCHLINGS_DUE, |
22
|
|
|
RACE_THEVIAN => SHIP_TYPE_SWIFT_VENTURE, |
23
|
|
|
RACE_WQHUMAN => SHIP_TYPE_SLIP_FREIGHTER, |
24
|
|
|
RACE_NIJARIN => SHIP_TYPE_REDEEMER, |
25
|
|
|
]; |
26
|
|
|
|
27
|
|
|
protected AbstractSmrPlayer $player; |
28
|
|
|
|
29
|
|
|
protected int $gameID; |
30
|
|
|
protected SmrShipType $shipType; |
31
|
|
|
|
32
|
|
|
protected array $weapons = []; |
33
|
|
|
protected array $cargo = []; |
34
|
|
|
protected array $hardware = []; |
35
|
|
|
protected bool $isCloaked = false; |
36
|
|
|
protected array|false $illusionShip = false; |
37
|
|
|
|
38
|
|
|
protected bool $hasChangedWeapons = false; |
39
|
|
|
protected bool $hasChangedCargo = false; |
40
|
|
|
protected array $hasChangedHardware = []; |
41
|
|
|
protected bool $hasChangedCloak = false; |
42
|
|
|
protected bool $hasChangedIllusion = false; |
43
|
|
|
|
44
|
|
|
public function __construct(AbstractSmrPlayer $player) { |
45
|
|
|
$this->player = $player; |
46
|
|
|
$this->gameID = $player->getGameID(); |
47
|
|
|
$this->regenerateShipType(); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
protected function regenerateShipType() : void { |
51
|
|
|
$this->shipType = SmrShipType::get($this->player->getShipTypeID()); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
public function checkForExcess() : void { |
55
|
|
|
$this->checkForExcessHardware(); |
56
|
|
|
$this->checkForExcessWeapons(); |
57
|
|
|
$this->checkForExcessCargo(); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
public function checkForExcessWeapons() : void { |
61
|
|
|
while ($this->hasWeapons() && ($this->getPowerUsed() > $this->getType()->getMaxPower() || $this->getNumWeapons() > $this->getHardpoints())) { |
62
|
|
|
//erase the first weapon 1 at a time until we are okay |
63
|
|
|
$this->removeLastWeapon(); |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
public function checkForExcessCargo() : void { |
68
|
|
|
if ($this->hasCargo()) { |
69
|
|
|
$excess = array_sum($this->getCargo()) - $this->getCargoHolds(); |
70
|
|
|
foreach ($this->getCargo() as $goodID => $amount) { |
71
|
|
|
if ($excess > 0) { |
72
|
|
|
$decreaseAmount = min($amount, $excess); |
73
|
|
|
$this->decreaseCargo($goodID, $decreaseAmount); |
74
|
|
|
$excess -= $decreaseAmount; |
75
|
|
|
} else { |
76
|
|
|
// No more excess cargo |
77
|
|
|
break; |
78
|
|
|
} |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
public function checkForExcessHardware() : void { |
84
|
|
|
//check hardware to see if anything needs to be removed |
85
|
|
|
foreach ($this->getHardware() as $hardwareTypeID => $amount) { |
86
|
|
|
$max = $this->shipType->getMaxHardware($hardwareTypeID); |
87
|
|
|
$this->setHardware($hardwareTypeID, min($amount, $max)); |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Set all hardware to its maximum value for this ship. |
93
|
|
|
*/ |
94
|
|
|
public function setHardwareToMax() : void { |
95
|
|
|
foreach ($this->shipType->getAllMaxHardware() as $hardwareTypeID => $max) { |
96
|
|
|
$this->setHardware($hardwareTypeID, $max); |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
public function getPowerUsed() : int { |
101
|
|
|
$power = 0; |
102
|
|
|
foreach ($this->weapons as $weapon) { |
103
|
|
|
$power += $weapon->getPowerLevel(); |
104
|
|
|
} |
105
|
|
|
return $power; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
public function getRemainingPower() : int { |
109
|
|
|
return $this->getType()->getMaxPower() - $this->getPowerUsed(); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* given power level of new weapon, return whether there is enough power available to install it on this ship |
114
|
|
|
*/ |
115
|
|
|
public function checkPowerAvailable(int $powerLevel) : bool { |
116
|
|
|
return $this->getRemainingPower() >= $powerLevel; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
public function hasIllegalGoods() : bool { |
120
|
|
|
return $this->hasCargo(GOODS_SLAVES) || $this->hasCargo(GOODS_WEAPONS) || $this->hasCargo(GOODS_NARCOTICS); |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
public function getDisplayAttackRating() : int { |
124
|
|
|
if ($this->hasActiveIllusion()) { |
125
|
|
|
return $this->getIllusionAttack(); |
126
|
|
|
} else { |
127
|
|
|
return $this->getAttackRating(); |
128
|
|
|
} |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
public function getDisplayDefenseRating() : int { |
132
|
|
|
if ($this->hasActiveIllusion()) { |
133
|
|
|
return $this->getIllusionDefense(); |
134
|
|
|
} else { |
135
|
|
|
return $this->getDefenseRating(); |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
public function getDisplayName() : string { |
140
|
|
|
if ($this->hasActiveIllusion()) { |
141
|
|
|
return $this->getIllusionShipName(); |
142
|
|
|
} else { |
143
|
|
|
return $this->getName(); |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
public function getAttackRating() : int { |
148
|
|
|
return IRound(($this->getTotalShieldDamage() + $this->getTotalArmourDamage() + $this->getCDs() * 2) / 40); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
public function getAttackRatingWithMaxCDs() : int { |
152
|
|
|
return IRound(($this->getTotalShieldDamage() + $this->getTotalArmourDamage() + $this->getMaxCDs() * .7) / 40); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
public function getDefenseRating() : int { |
156
|
|
|
return IRound((($this->getShields() + $this->getArmour()) / 100) + (($this->getCDs() * 3) / 100)); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
public function getMaxDefenseRating() : int { |
160
|
|
|
return IRound((($this->getMaxShields() + $this->getMaxArmour()) / 100) + (($this->getMaxCDs() * 3) / 100)); |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
public function getShieldLow() : int { return IFloor($this->getShields() / 100) * 100; } |
164
|
|
|
public function getShieldHigh() : int { return $this->getShieldLow() + 100; } |
165
|
|
|
public function getArmourLow() : int { return IFloor($this->getArmour() / 100) * 100; } |
166
|
|
|
public function getArmourHigh() : int { return $this->getArmourLow() + 100; } |
167
|
|
|
public function getCDsLow() : int { return IFloor($this->getCDs() / 100) * 100; } |
168
|
|
|
public function getCDsHigh() : int { return $this->getCDsLow() + 100; } |
169
|
|
|
|
170
|
|
|
|
171
|
|
|
|
172
|
|
|
public function addWeapon(SmrWeapon $weapon) : SmrWeapon|false { |
173
|
|
|
if ($this->hasOpenWeaponSlots() && $this->checkPowerAvailable($weapon->getPowerLevel())) { |
174
|
|
|
array_push($this->weapons, $weapon); |
175
|
|
|
$this->hasChangedWeapons = true; |
176
|
|
|
return $weapon; |
177
|
|
|
} |
178
|
|
|
return false; |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
public function moveWeaponUp(int $orderID) : void { |
182
|
|
|
$replacement = $orderID - 1; |
183
|
|
|
if ($replacement < 0) { |
184
|
|
|
// Shift everything up by one and put the selected weapon at the bottom |
185
|
|
|
array_push($this->weapons, array_shift($this->weapons)); |
186
|
|
|
} else { |
187
|
|
|
// Swap the selected weapon with the one above it |
188
|
|
|
$temp = $this->weapons[$replacement]; |
189
|
|
|
$this->weapons[$replacement] = $this->weapons[$orderID]; |
190
|
|
|
$this->weapons[$orderID] = $temp; |
191
|
|
|
} |
192
|
|
|
$this->hasChangedWeapons = true; |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
public function moveWeaponDown(int $orderID) : void { |
196
|
|
|
$replacement = $orderID + 1; |
197
|
|
|
if ($replacement >= count($this->weapons)) { |
198
|
|
|
// Shift everything down by one and put the selected weapon at the top |
199
|
|
|
array_unshift($this->weapons, array_pop($this->weapons)); |
200
|
|
|
} else { |
201
|
|
|
// Swap the selected weapon with the one below it |
202
|
|
|
$temp = $this->weapons[$replacement]; |
203
|
|
|
$this->weapons[$replacement] = $this->weapons[$orderID]; |
204
|
|
|
$this->weapons[$orderID] = $temp; |
205
|
|
|
} |
206
|
|
|
$this->hasChangedWeapons = true; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
public function setWeaponLocations(array $orderArray) : void { |
210
|
|
|
$weapons = $this->weapons; |
211
|
|
|
foreach ($orderArray as $newOrder => $oldOrder) { |
212
|
|
|
$this->weapons[$newOrder] = $weapons[$oldOrder]; |
213
|
|
|
} |
214
|
|
|
$this->hasChangedWeapons = true; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
public function removeLastWeapon() : void { |
218
|
|
|
$this->removeWeapon($this->getNumWeapons() - 1); |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
public function removeWeapon(int $orderID) : void { |
222
|
|
|
// Remove the specified weapon, then reindex the array |
223
|
|
|
unset($this->weapons[$orderID]); |
224
|
|
|
$this->weapons = array_values($this->weapons); |
225
|
|
|
$this->hasChangedWeapons = true; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
public function removeAllWeapons() : void { |
229
|
|
|
$this->weapons = array(); |
230
|
|
|
$this->hasChangedWeapons = true; |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
public function removeAllCargo() : void { |
234
|
|
|
foreach ($this->cargo as $goodID => $amount) { |
235
|
|
|
$this->setCargo($goodID, 0); |
236
|
|
|
} |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
public function removeAllHardware() : void { |
240
|
|
|
foreach (array_keys($this->hardware) as $hardwareTypeID) { |
241
|
|
|
$this->hasChangedHardware[$hardwareTypeID] = true; |
242
|
|
|
} |
243
|
|
|
$this->hardware = []; |
244
|
|
|
$this->decloak(); |
245
|
|
|
$this->disableIllusion(); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
public function getPod(bool $isNewbie = false) : void { |
249
|
|
|
$this->removeAllWeapons(); |
250
|
|
|
$this->removeAllCargo(); |
251
|
|
|
$this->removeAllHardware(); |
252
|
|
|
|
253
|
|
|
if ($isNewbie) { |
254
|
|
|
$this->setShields(75); |
255
|
|
|
$this->setArmour(150); |
256
|
|
|
$this->setCargoHolds(40); |
257
|
|
|
$this->setTypeID(SHIP_TYPE_NEWBIE_MERCHANT_VESSEL); |
258
|
|
|
} else { |
259
|
|
|
$this->setShields(50); |
260
|
|
|
$this->setArmour(50); |
261
|
|
|
$this->setCargoHolds(5); |
262
|
|
|
$this->setTypeID(SHIP_TYPE_ESCAPE_POD); |
263
|
|
|
} |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
public function giveStarterShip() : void { |
267
|
|
|
if ($this->player->hasNewbieStatus()) { |
268
|
|
|
$shipID = SHIP_TYPE_NEWBIE_MERCHANT_VESSEL; |
269
|
|
|
$amount_shields = 75; |
270
|
|
|
$amount_armour = 150; |
271
|
|
|
} else { |
272
|
|
|
$shipID = self::STARTER_SHIPS[$this->player->getRaceID()]; |
273
|
|
|
$amount_shields = 50; |
274
|
|
|
$amount_armour = 50; |
275
|
|
|
} |
276
|
|
|
$this->setTypeID($shipID); |
277
|
|
|
$this->setShields($amount_shields); |
278
|
|
|
$this->setArmour($amount_armour); |
279
|
|
|
$this->setCargoHolds(40); |
280
|
|
|
$this->addWeapon(SmrWeapon::getWeapon(WEAPON_TYPE_LASER)); |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
public function hasJump() : bool { |
284
|
|
|
return $this->getHardware(HARDWARE_JUMP) > 0; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
public function hasDCS() : bool { |
288
|
|
|
return $this->getHardware(HARDWARE_DCS) > 0; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
public function hasScanner() : bool { |
292
|
|
|
return $this->getHardware(HARDWARE_SCANNER) > 0; |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
public function hasCloak() : bool { |
296
|
|
|
return $this->getHardware(HARDWARE_CLOAK) > 0; |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
public function isCloaked() : bool { |
300
|
|
|
return $this->isCloaked; |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
public function decloak() : void { |
304
|
|
|
if ($this->isCloaked === false) { |
305
|
|
|
return; |
306
|
|
|
} |
307
|
|
|
$this->isCloaked = false; |
308
|
|
|
$this->hasChangedCloak = true; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
public function enableCloak() : void { |
312
|
|
|
if ($this->hasCloak() === false) { |
313
|
|
|
throw new Exception('Ship does not have the supported hardware!'); |
314
|
|
|
} |
315
|
|
|
if ($this->isCloaked === true) { |
316
|
|
|
return; |
317
|
|
|
} |
318
|
|
|
$this->isCloaked = true; |
319
|
|
|
$this->hasChangedCloak = true; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
public function hasIllusion() : bool { |
323
|
|
|
return $this->getHardware(HARDWARE_ILLUSION) > 0; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
public function getIllusionShip() : array|false { |
327
|
|
|
return $this->illusionShip; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
public function hasActiveIllusion() : bool { |
331
|
|
|
return $this->getIllusionShip() !== false; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
public function setIllusion(int $shipTypeID, int $attack, int $defense) : void { |
335
|
|
|
if ($this->hasIllusion() === false) { |
336
|
|
|
throw new Exception('Ship does not have the supported hardware!'); |
337
|
|
|
} |
338
|
|
|
$newIllusionShip = [ |
339
|
|
|
'ID' => $shipTypeID, |
340
|
|
|
'Attack' => $attack, |
341
|
|
|
'Defense' => $defense, |
342
|
|
|
]; |
343
|
|
|
if ($this->getIllusionShip() === $newIllusionShip) { |
344
|
|
|
return; |
345
|
|
|
} |
346
|
|
|
$this->illusionShip = $newIllusionShip; |
347
|
|
|
$this->hasChangedIllusion = true; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
public function disableIllusion() : void { |
351
|
|
|
if ($this->getIllusionShip() === false) { |
352
|
|
|
return; |
353
|
|
|
} |
354
|
|
|
$this->illusionShip = false; |
355
|
|
|
$this->hasChangedIllusion = true; |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
public function getIllusionShipID() : int { |
359
|
|
|
return $this->getIllusionShip()['ID']; |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
public function getIllusionShipName() : string { |
363
|
|
|
return SmrShipType::get($this->getIllusionShip()['ID'])->getName(); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
public function getIllusionAttack() : int { |
367
|
|
|
return $this->getIllusionShip()['Attack']; |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
public function getIllusionDefense() : int { |
371
|
|
|
return $this->getIllusionShip()['Defense']; |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
public function getPlayer() : AbstractSmrPlayer { |
375
|
|
|
return $this->player; |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
public function getAccountID() : int { |
379
|
|
|
return $this->getPlayer()->getAccountID(); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
public function getGameID() : int { |
383
|
|
|
return $this->gameID; |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
public function getGame() : SmrGame { |
387
|
|
|
return SmrGame::getGame($this->gameID); |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
/** |
391
|
|
|
* Switch to a new ship, updating player turns accordingly. |
392
|
|
|
*/ |
393
|
|
|
public function setTypeID(int $shipTypeID) : void { |
394
|
|
|
$oldSpeed = $this->shipType->getSpeed(); |
395
|
|
|
$this->getPlayer()->setShipTypeID($shipTypeID); |
396
|
|
|
$this->regenerateShipType(); |
397
|
|
|
$this->checkForExcess(); |
398
|
|
|
|
399
|
|
|
// Update the player's turns to account for the speed change |
400
|
|
|
$newSpeed = $this->shipType->getSpeed(); |
401
|
|
|
$oldTurns = $this->getPlayer()->getTurns(); |
402
|
|
|
$this->getPlayer()->setTurns(IRound($oldTurns * $newSpeed / $oldSpeed)); |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
public function getType() : SmrShipType { |
406
|
|
|
return $this->shipType; |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
public function getTypeID() : int { |
410
|
|
|
return $this->shipType->getTypeID(); |
411
|
|
|
} |
412
|
|
|
|
413
|
|
|
public function getClassID() : int { |
414
|
|
|
return $this->shipType->getClassID(); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
public function getName() : string { |
418
|
|
|
return $this->shipType->getName(); |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
public function getCost() : int { |
422
|
|
|
return $this->shipType->getCost(); |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
public function getHardpoints() : int { |
426
|
|
|
return $this->shipType->getHardpoints(); |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
/** |
430
|
|
|
* Trade-in value of the ship |
431
|
|
|
*/ |
432
|
|
|
public function getRefundValue() : int { |
433
|
|
|
return IFloor($this->getCost() * SHIP_REFUND_PERCENT); |
434
|
|
|
} |
435
|
|
|
|
436
|
|
|
public function getCostToUpgrade(int $otherShipTypeID) : int { |
437
|
|
|
$otherShipType = SmrShipType::get($otherShipTypeID); |
438
|
|
|
return $otherShipType->getCost() - $this->getRefundValue(); |
439
|
|
|
} |
440
|
|
|
|
441
|
|
|
public function getCostToUpgradeAndUNO(int $otherShipTypeID) : int { |
442
|
|
|
return $this->getCostToUpgrade($otherShipTypeID) + $this->getCostToUNOAgainstShip($otherShipTypeID); |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
protected function getCostToUNOAgainstShip(int $otherShipTypeID) : int { |
446
|
|
|
$otherShipType = SmrShipType::get($otherShipTypeID); |
447
|
|
|
$cost = 0; |
448
|
|
|
$hardwareTypes = array(HARDWARE_SHIELDS, HARDWARE_ARMOUR, HARDWARE_CARGO); |
449
|
|
|
foreach ($hardwareTypes as $hardwareTypeID) { |
450
|
|
|
$cost += max(0, $otherShipType->getMaxHardware($hardwareTypeID) - $this->getHardware($hardwareTypeID)) * Globals::getHardwareCost($hardwareTypeID); |
451
|
|
|
} |
452
|
|
|
return $cost; |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
public function getCostToUNO() : int { |
456
|
|
|
return $this->getCostToUNOAgainstShip($this->getTypeID()); |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
/** |
460
|
|
|
* Returns the ship speed modified by the game speed. |
461
|
|
|
*/ |
462
|
|
|
public function getRealSpeed() : float { |
463
|
|
|
return $this->shipType->getSpeed() * $this->getGame()->getGameSpeed(); |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
public function getHardware(int $hardwareTypeID = null) : array|int { |
467
|
|
|
if ($hardwareTypeID === null) { |
468
|
|
|
return $this->hardware; |
469
|
|
|
} |
470
|
|
|
return $this->hardware[$hardwareTypeID] ?? 0; |
471
|
|
|
} |
472
|
|
|
|
473
|
|
|
public function setHardware(int $hardwareTypeID, int $amount) : void { |
474
|
|
|
if ($this->getHardware($hardwareTypeID) === $amount) { |
475
|
|
|
return; |
476
|
|
|
} |
477
|
|
|
$this->hardware[$hardwareTypeID] = $amount; |
478
|
|
|
$this->hasChangedHardware[$hardwareTypeID] = true; |
479
|
|
|
} |
480
|
|
|
|
481
|
|
|
public function increaseHardware(int $hardwareTypeID, int $amount) : void { |
482
|
|
|
$this->setHardware($hardwareTypeID, $this->getHardware($hardwareTypeID) + $amount); |
483
|
|
|
} |
484
|
|
|
|
485
|
|
|
public function hasMaxHardware(int $hardwareTypeID) : bool { |
486
|
|
|
return $this->getHardware($hardwareTypeID) == $this->shipType->getMaxHardware($hardwareTypeID); |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
public function getShields() : int { |
490
|
|
|
return $this->getHardware(HARDWARE_SHIELDS); |
491
|
|
|
} |
492
|
|
|
|
493
|
|
|
public function setShields(int $amount) : void { |
494
|
|
|
$this->setHardware(HARDWARE_SHIELDS, $amount); |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
public function decreaseShields(int $amount) : void { |
498
|
|
|
$this->setShields($this->getShields() - $amount); |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
public function increaseShields(int $amount) : void { |
502
|
|
|
$this->setShields($this->getShields() + $amount); |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
public function hasShields() : bool { |
506
|
|
|
return $this->getShields() > 0; |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
public function hasMaxShields() : bool { |
510
|
|
|
return $this->hasMaxHardware(HARDWARE_SHIELDS); |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
public function getMaxShields() : int { |
514
|
|
|
return $this->shipType->getMaxHardware(HARDWARE_SHIELDS); |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
public function getArmour() : int { |
518
|
|
|
return $this->getHardware(HARDWARE_ARMOUR); |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
public function setArmour(int $amount) : void { |
522
|
|
|
$this->setHardware(HARDWARE_ARMOUR, $amount); |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
public function decreaseArmour(int $amount) : void { |
526
|
|
|
$this->setArmour($this->getArmour() - $amount); |
527
|
|
|
} |
528
|
|
|
|
529
|
|
|
public function increaseArmour(int $amount) : void { |
530
|
|
|
$this->setArmour($this->getArmour() + $amount); |
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
public function hasArmour() : bool { |
534
|
|
|
return $this->getArmour() > 0; |
535
|
|
|
} |
536
|
|
|
|
537
|
|
|
public function hasMaxArmour() : bool { |
538
|
|
|
return $this->hasMaxHardware(HARDWARE_ARMOUR); |
539
|
|
|
} |
540
|
|
|
|
541
|
|
|
public function getMaxArmour() : int { |
542
|
|
|
return $this->shipType->getMaxHardware(HARDWARE_ARMOUR); |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
public function isDead() : bool { |
546
|
|
|
return !$this->hasArmour() && !$this->hasShields(); |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
public function hasMaxCDs() : bool { |
550
|
|
|
return $this->hasMaxHardware(HARDWARE_COMBAT); |
551
|
|
|
} |
552
|
|
|
|
553
|
|
|
public function hasMaxSDs() : bool { |
554
|
|
|
return $this->hasMaxHardware(HARDWARE_SCOUT); |
555
|
|
|
} |
556
|
|
|
|
557
|
|
|
public function hasMaxMines() : bool { |
558
|
|
|
return $this->hasMaxHardware(HARDWARE_MINE); |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
public function hasCDs() : bool { |
562
|
|
|
return $this->getCDs() > 0; |
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
public function hasSDs() : bool { |
566
|
|
|
return $this->getSDs() > 0; |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
public function hasMines() : bool { |
570
|
|
|
return $this->getMines() > 0; |
571
|
|
|
} |
572
|
|
|
|
573
|
|
|
public function getCDs() : int { |
574
|
|
|
return $this->getHardware(HARDWARE_COMBAT); |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
public function setCDs(int $amount) : void { |
578
|
|
|
$this->setHardware(HARDWARE_COMBAT, $amount); |
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
public function decreaseCDs(int $amount) : void { |
582
|
|
|
$this->setCDs($this->getCDs() - $amount); |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
public function increaseCDs(int $amount) : void { |
586
|
|
|
$this->setCDs($this->getCDs() + $amount); |
587
|
|
|
} |
588
|
|
|
|
589
|
|
|
public function getMaxCDs() : int { |
590
|
|
|
return $this->shipType->getMaxHardware(HARDWARE_COMBAT); |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
public function getSDs() : int { |
594
|
|
|
return $this->getHardware(HARDWARE_SCOUT); |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
public function setSDs(int $amount) : void { |
598
|
|
|
$this->setHardware(HARDWARE_SCOUT, $amount); |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
public function decreaseSDs(int $amount) : void { |
602
|
|
|
$this->setSDs($this->getSDs() - $amount); |
603
|
|
|
} |
604
|
|
|
|
605
|
|
|
public function increaseSDs(int $amount) : void { |
606
|
|
|
$this->setSDs($this->getSDs() + $amount); |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
public function getMaxSDs() : int { |
610
|
|
|
return $this->shipType->getMaxHardware(HARDWARE_SCOUT); |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
public function getMines() : int { |
614
|
|
|
return $this->getHardware(HARDWARE_MINE); |
615
|
|
|
} |
616
|
|
|
|
617
|
|
|
public function setMines(int $amount) : void { |
618
|
|
|
$this->setHardware(HARDWARE_MINE, $amount); |
619
|
|
|
} |
620
|
|
|
|
621
|
|
|
public function decreaseMines(int $amount) : void { |
622
|
|
|
$this->setMines($this->getMines() - $amount); |
623
|
|
|
} |
624
|
|
|
|
625
|
|
|
public function increaseMines(int $amount) : void { |
626
|
|
|
$this->setMines($this->getMines() + $amount); |
627
|
|
|
} |
628
|
|
|
|
629
|
|
|
public function getMaxMines() : int { |
630
|
|
|
return $this->shipType->getMaxHardware(HARDWARE_MINE); |
631
|
|
|
} |
632
|
|
|
|
633
|
|
|
public function getCargoHolds() : int { |
634
|
|
|
return $this->getHardware(HARDWARE_CARGO); |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
public function setCargoHolds(int $amount) : void { |
638
|
|
|
$this->setHardware(HARDWARE_CARGO, $amount); |
639
|
|
|
} |
640
|
|
|
|
641
|
|
|
public function getCargo(int $goodID = null) : int|array { |
642
|
|
|
if ($goodID === null) { |
643
|
|
|
return $this->cargo; |
644
|
|
|
} |
645
|
|
|
return $this->cargo[$goodID] ?? 0; |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
public function hasCargo(int $goodID = null) : bool { |
649
|
|
|
if ($goodID === null) { |
650
|
|
|
return $this->getUsedHolds() > 0; |
651
|
|
|
} |
652
|
|
|
return $this->getCargo($goodID) > 0; |
653
|
|
|
} |
654
|
|
|
|
655
|
|
|
public function setCargo(int $goodID, int $amount) : void { |
656
|
|
|
if ($this->getCargo($goodID) === $amount) { |
657
|
|
|
return; |
658
|
|
|
} |
659
|
|
|
$this->cargo[$goodID] = $amount; |
660
|
|
|
$this->hasChangedCargo = true; |
661
|
|
|
// Sort cargo by goodID to make sure it shows up in the correct order |
662
|
|
|
// before the next page is loaded. |
663
|
|
|
ksort($this->cargo); |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
public function decreaseCargo(int $goodID, int $amount) : void { |
667
|
|
|
if ($amount < 0) { |
668
|
|
|
throw new Exception('Trying to decrease negative cargo.'); |
669
|
|
|
} |
670
|
|
|
$this->setCargo($goodID, $this->getCargo($goodID) - $amount); |
671
|
|
|
} |
672
|
|
|
|
673
|
|
|
public function increaseCargo(int $goodID, int $amount) : void { |
674
|
|
|
if ($amount < 0) { |
675
|
|
|
throw new Exception('Trying to increase negative cargo.'); |
676
|
|
|
} |
677
|
|
|
$this->setCargo($goodID, $this->getCargo($goodID) + $amount); |
678
|
|
|
} |
679
|
|
|
|
680
|
|
|
public function getEmptyHolds() : int { |
681
|
|
|
return $this->getCargoHolds() - $this->getUsedHolds(); |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
public function getUsedHolds() : int { |
685
|
|
|
return array_sum($this->getCargo()); |
686
|
|
|
} |
687
|
|
|
|
688
|
|
|
public function hasMaxCargoHolds() : bool { |
689
|
|
|
return $this->hasMaxHardware(HARDWARE_CARGO); |
690
|
|
|
} |
691
|
|
|
|
692
|
|
|
public function getMaxCargoHolds() : int { |
693
|
|
|
return $this->shipType->getMaxHardware(HARDWARE_CARGO); |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
public function hasWeapons() : bool { |
697
|
|
|
return $this->getNumWeapons() > 0; |
698
|
|
|
} |
699
|
|
|
|
700
|
|
|
public function getWeapons() : array { |
701
|
|
|
return $this->weapons; |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
public function canAttack() : bool { |
705
|
|
|
return $this->hasWeapons() || $this->hasCDs(); |
706
|
|
|
} |
707
|
|
|
|
708
|
|
|
public function getNumWeapons() : int { |
709
|
|
|
return count($this->getWeapons()); |
710
|
|
|
} |
711
|
|
|
|
712
|
|
|
public function getOpenWeaponSlots() : int { |
713
|
|
|
return $this->getHardpoints() - $this->getNumWeapons(); |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
public function hasOpenWeaponSlots() : bool { |
717
|
|
|
return $this->getOpenWeaponSlots() > 0; |
718
|
|
|
} |
719
|
|
|
|
720
|
|
|
public function getTotalShieldDamage() : int { |
721
|
|
|
$shieldDamage = 0; |
722
|
|
|
foreach ($this->getWeapons() as $weapon) { |
723
|
|
|
$shieldDamage += $weapon->getShieldDamage(); |
724
|
|
|
} |
725
|
|
|
return $shieldDamage; |
726
|
|
|
} |
727
|
|
|
|
728
|
|
|
public function getTotalArmourDamage() : int { |
729
|
|
|
$armourDamage = 0; |
730
|
|
|
foreach ($this->getWeapons() as $weapon) { |
731
|
|
|
$armourDamage += $weapon->getArmourDamage(); |
732
|
|
|
} |
733
|
|
|
return $armourDamage; |
734
|
|
|
} |
735
|
|
|
|
736
|
|
|
public function isFederal() : bool { |
737
|
|
|
return $this->getTypeID() === SHIP_TYPE_FEDERAL_DISCOVERY || |
738
|
|
|
$this->getTypeID() === SHIP_TYPE_FEDERAL_WARRANT || |
739
|
|
|
$this->getTypeID() === SHIP_TYPE_FEDERAL_ULTIMATUM; |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
public function isUnderground() : bool { |
743
|
|
|
return $this->getTypeID() === SHIP_TYPE_THIEF || |
744
|
|
|
$this->getTypeID() === SHIP_TYPE_ASSASSIN || |
745
|
|
|
$this->getTypeID() === SHIP_TYPE_DEATH_CRUISER; |
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
public function shootPlayers(array $targetPlayers) : array { |
749
|
|
|
$thisPlayer = $this->getPlayer(); |
750
|
|
|
$results = array('Player' => $thisPlayer, 'TotalDamage' => 0, 'Weapons' => []); |
751
|
|
|
if ($thisPlayer->isDead()) { |
752
|
|
|
$results['DeadBeforeShot'] = true; |
753
|
|
|
return $results; |
754
|
|
|
} |
755
|
|
|
$results['DeadBeforeShot'] = false; |
756
|
|
|
foreach ($this->weapons as $orderID => $weapon) { |
757
|
|
|
$results['Weapons'][$orderID] = $weapon->shootPlayer($thisPlayer, array_rand_value($targetPlayers)); |
758
|
|
|
if ($results['Weapons'][$orderID]['Hit']) { |
759
|
|
|
$results['TotalDamage'] += $results['Weapons'][$orderID]['ActualDamage']['TotalDamage']; |
760
|
|
|
} |
761
|
|
|
} |
762
|
|
|
if ($this->hasCDs()) { |
763
|
|
|
$thisCDs = new SmrCombatDrones($this->getCDs()); |
764
|
|
|
$results['Drones'] = $thisCDs->shootPlayer($thisPlayer, array_rand_value($targetPlayers)); |
765
|
|
|
$results['TotalDamage'] += $results['Drones']['ActualDamage']['TotalDamage']; |
766
|
|
|
} |
767
|
|
|
$thisPlayer->increaseExperience(IRound($results['TotalDamage'] * self::EXP_PER_DAMAGE_PLAYER)); |
768
|
|
|
$thisPlayer->increaseHOF($results['TotalDamage'], array('Combat', 'Player', 'Damage Done'), HOF_PUBLIC); |
769
|
|
|
$thisPlayer->increaseHOF(1, array('Combat', 'Player', 'Shots'), HOF_PUBLIC); |
770
|
|
|
return $results; |
771
|
|
|
} |
772
|
|
|
|
773
|
|
|
public function shootForces(SmrForce $forces) : array { |
774
|
|
|
$thisPlayer = $this->getPlayer(); |
775
|
|
|
$results = array('Player' => $thisPlayer, 'TotalDamage' => 0, 'Weapons' => []); |
776
|
|
|
if ($thisPlayer->isDead()) { |
777
|
|
|
$results['DeadBeforeShot'] = true; |
778
|
|
|
return $results; |
779
|
|
|
} |
780
|
|
|
$results['DeadBeforeShot'] = false; |
781
|
|
|
foreach ($this->weapons as $orderID => $weapon) { |
782
|
|
|
$results['Weapons'][$orderID] = $weapon->shootForces($thisPlayer, $forces); |
783
|
|
|
if ($results['Weapons'][$orderID]['Hit']) { |
784
|
|
|
$results['TotalDamage'] += $results['Weapons'][$orderID]['ActualDamage']['TotalDamage']; |
785
|
|
|
$thisPlayer->increaseHOF($results['Weapons'][$orderID]['ActualDamage']['NumMines'], array('Combat', 'Forces', 'Mines', 'Killed'), HOF_PUBLIC); |
786
|
|
|
$thisPlayer->increaseHOF($results['Weapons'][$orderID]['ActualDamage']['Mines'], array('Combat', 'Forces', 'Mines', 'Damage Done'), HOF_PUBLIC); |
787
|
|
|
$thisPlayer->increaseHOF($results['Weapons'][$orderID]['ActualDamage']['NumCDs'], array('Combat', 'Forces', 'Combat Drones', 'Killed'), HOF_PUBLIC); |
788
|
|
|
$thisPlayer->increaseHOF($results['Weapons'][$orderID]['ActualDamage']['CDs'], array('Combat', 'Forces', 'Combat Drones', 'Damage Done'), HOF_PUBLIC); |
789
|
|
|
$thisPlayer->increaseHOF($results['Weapons'][$orderID]['ActualDamage']['NumSDs'], array('Combat', 'Forces', 'Scout Drones', 'Killed'), HOF_PUBLIC); |
790
|
|
|
$thisPlayer->increaseHOF($results['Weapons'][$orderID]['ActualDamage']['SDs'], array('Combat', 'Forces', 'Scout Drones', 'Damage Done'), HOF_PUBLIC); |
791
|
|
|
$thisPlayer->increaseHOF($results['Weapons'][$orderID]['ActualDamage']['NumMines'] + $results['Weapons'][$orderID]['ActualDamage']['NumCDs'] + $results['Weapons'][$orderID]['ActualDamage']['NumSDs'], array('Combat', 'Forces', 'Killed'), HOF_PUBLIC); |
792
|
|
|
} |
793
|
|
|
} |
794
|
|
|
if ($this->hasCDs()) { |
795
|
|
|
$thisCDs = new SmrCombatDrones($this->getCDs()); |
796
|
|
|
$results['Drones'] = $thisCDs->shootForces($thisPlayer, $forces); |
797
|
|
|
$results['TotalDamage'] += $results['Drones']['ActualDamage']['TotalDamage']; |
798
|
|
|
$thisPlayer->increaseHOF($results['Drones']['ActualDamage']['NumMines'], array('Combat', 'Forces', 'Mines', 'Killed'), HOF_PUBLIC); |
799
|
|
|
$thisPlayer->increaseHOF($results['Drones']['ActualDamage']['Mines'], array('Combat', 'Forces', 'Mines', 'Damage Done'), HOF_PUBLIC); |
800
|
|
|
$thisPlayer->increaseHOF($results['Drones']['ActualDamage']['NumCDs'], array('Combat', 'Forces', 'Combat Drones', 'Killed'), HOF_PUBLIC); |
801
|
|
|
$thisPlayer->increaseHOF($results['Drones']['ActualDamage']['CDs'], array('Combat', 'Forces', 'Combat Drones', 'Damage Done'), HOF_PUBLIC); |
802
|
|
|
$thisPlayer->increaseHOF($results['Drones']['ActualDamage']['NumSDs'], array('Combat', 'Forces', 'Scout Drones', 'Killed'), HOF_PUBLIC); |
803
|
|
|
$thisPlayer->increaseHOF($results['Drones']['ActualDamage']['SDs'], array('Combat', 'Forces', 'Scout Drones', 'Damage Done'), HOF_PUBLIC); |
804
|
|
|
$thisPlayer->increaseHOF($results['Drones']['ActualDamage']['NumMines'] + $results['Drones']['ActualDamage']['NumCDs'] + $results['Drones']['ActualDamage']['NumSDs'], array('Combat', 'Forces', 'Killed'), HOF_PUBLIC); |
805
|
|
|
} |
806
|
|
|
$thisPlayer->increaseExperience(IRound($results['TotalDamage'] * self::EXP_PER_DAMAGE_FORCE)); |
807
|
|
|
$thisPlayer->increaseHOF($results['TotalDamage'], array('Combat', 'Forces', 'Damage Done'), HOF_PUBLIC); |
808
|
|
|
$thisPlayer->increaseHOF(1, array('Combat', 'Forces', 'Shots'), HOF_PUBLIC); |
809
|
|
|
return $results; |
810
|
|
|
} |
811
|
|
|
|
812
|
|
|
public function shootPort(SmrPort $port) : array { |
813
|
|
|
$thisPlayer = $this->getPlayer(); |
814
|
|
|
$results = array('Player' => $thisPlayer, 'TotalDamage' => 0, 'Weapons' => []); |
815
|
|
|
if ($thisPlayer->isDead()) { |
816
|
|
|
$results['DeadBeforeShot'] = true; |
817
|
|
|
return $results; |
818
|
|
|
} |
819
|
|
|
$results['DeadBeforeShot'] = false; |
820
|
|
|
foreach ($this->weapons as $orderID => $weapon) { |
821
|
|
|
$results['Weapons'][$orderID] = $weapon->shootPort($thisPlayer, $port); |
822
|
|
|
if ($results['Weapons'][$orderID]['Hit']) { |
823
|
|
|
$results['TotalDamage'] += $results['Weapons'][$orderID]['ActualDamage']['TotalDamage']; |
824
|
|
|
} |
825
|
|
|
} |
826
|
|
|
if ($this->hasCDs()) { |
827
|
|
|
$thisCDs = new SmrCombatDrones($this->getCDs()); |
828
|
|
|
$results['Drones'] = $thisCDs->shootPort($thisPlayer, $port); |
829
|
|
|
$results['TotalDamage'] += $results['Drones']['ActualDamage']['TotalDamage']; |
830
|
|
|
} |
831
|
|
|
$thisPlayer->increaseExperience(IRound($results['TotalDamage'] * self::EXP_PER_DAMAGE_PORT)); |
832
|
|
|
$thisPlayer->increaseHOF($results['TotalDamage'], array('Combat', 'Port', 'Damage Done'), HOF_PUBLIC); |
833
|
|
|
// $thisPlayer->increaseHOF(1,array('Combat','Port','Shots')); //in SmrPortt::attackedBy() |
834
|
|
|
|
835
|
|
|
// Change alignment if we reach a damage threshold. |
836
|
|
|
// Increase if player and port races are at war; decrease otherwise. |
837
|
|
|
if ($results['TotalDamage'] >= SmrPort::DAMAGE_NEEDED_FOR_ALIGNMENT_CHANGE) { |
838
|
|
|
$relations = Globals::getRaceRelations($thisPlayer->getGameID(), $thisPlayer->getRaceID()); |
839
|
|
|
if ($relations[$port->getRaceID()] <= RELATIONS_WAR) { |
840
|
|
|
$thisPlayer->increaseAlignment(1); |
841
|
|
|
$thisPlayer->increaseHOF(1, array('Combat', 'Port', 'Alignment', 'Gain'), HOF_PUBLIC); |
842
|
|
|
} else { |
843
|
|
|
$thisPlayer->decreaseAlignment(1); |
844
|
|
|
$thisPlayer->increaseHOF(1, array('Combat', 'Port', 'Alignment', 'Loss'), HOF_PUBLIC); |
845
|
|
|
} |
846
|
|
|
} |
847
|
|
|
return $results; |
848
|
|
|
} |
849
|
|
|
|
850
|
|
|
public function shootPlanet(SmrPlanet $planet, bool $delayed) : array { |
851
|
|
|
$thisPlayer = $this->getPlayer(); |
852
|
|
|
$results = array('Player' => $thisPlayer, 'TotalDamage' => 0, 'Weapons' => []); |
853
|
|
|
if ($thisPlayer->isDead()) { |
854
|
|
|
$results['DeadBeforeShot'] = true; |
855
|
|
|
return $results; |
856
|
|
|
} |
857
|
|
|
$results['DeadBeforeShot'] = false; |
858
|
|
|
foreach ($this->weapons as $orderID => $weapon) { |
859
|
|
|
$results['Weapons'][$orderID] = $weapon->shootPlanet($thisPlayer, $planet, $delayed); |
860
|
|
|
if ($results['Weapons'][$orderID]['Hit']) { |
861
|
|
|
$results['TotalDamage'] += $results['Weapons'][$orderID]['ActualDamage']['TotalDamage']; |
862
|
|
|
} |
863
|
|
|
} |
864
|
|
|
if ($this->hasCDs()) { |
865
|
|
|
$thisCDs = new SmrCombatDrones($this->getCDs()); |
866
|
|
|
$results['Drones'] = $thisCDs->shootPlanet($thisPlayer, $planet, $delayed); |
867
|
|
|
$results['TotalDamage'] += $results['Drones']['ActualDamage']['TotalDamage']; |
868
|
|
|
} |
869
|
|
|
$thisPlayer->increaseExperience(IRound($results['TotalDamage'] * self::EXP_PER_DAMAGE_PLANET)); |
870
|
|
|
$thisPlayer->increaseHOF($results['TotalDamage'], array('Combat', 'Planet', 'Damage Done'), HOF_PUBLIC); |
871
|
|
|
// $thisPlayer->increaseHOF(1,array('Combat','Planet','Shots')); //in SmrPlanet::attackedBy() |
872
|
|
|
return $results; |
873
|
|
|
} |
874
|
|
|
|
875
|
|
|
public function doWeaponDamage(array $damage) : array { |
876
|
|
|
$alreadyDead = $this->getPlayer()->isDead(); |
877
|
|
|
$armourDamage = 0; |
878
|
|
|
$cdDamage = 0; |
879
|
|
|
$shieldDamage = 0; |
880
|
|
|
if (!$alreadyDead) { |
881
|
|
|
// Even if the weapon doesn't do any damage, it was fired at the |
882
|
|
|
// player, so alert them that they're under attack. |
883
|
|
|
$this->getPlayer()->setUnderAttack(true); |
884
|
|
|
|
885
|
|
|
$shieldDamage = $this->doShieldDamage(min($damage['MaxDamage'], $damage['Shield'])); |
886
|
|
|
$damage['MaxDamage'] -= $shieldDamage; |
887
|
|
|
if (!$this->hasShields() && ($shieldDamage == 0 || $damage['Rollover'])) { |
888
|
|
|
$cdDamage = $this->doCDDamage(min($damage['MaxDamage'], $damage['Armour'])); |
889
|
|
|
$damage['Armour'] -= $cdDamage; |
890
|
|
|
$damage['MaxDamage'] -= $cdDamage; |
891
|
|
|
if (!$this->hasCDs() && ($cdDamage == 0 || $damage['Rollover'])) { |
892
|
|
|
$armourDamage = $this->doArmourDamage(min($damage['MaxDamage'], $damage['Armour'])); |
893
|
|
|
} |
894
|
|
|
} |
895
|
|
|
} |
896
|
|
|
return array( |
897
|
|
|
'KillingShot' => !$alreadyDead && $this->isDead(), |
898
|
|
|
'TargetAlreadyDead' => $alreadyDead, |
899
|
|
|
'Shield' => $shieldDamage, |
900
|
|
|
'CDs' => $cdDamage, |
901
|
|
|
'NumCDs' => $cdDamage / CD_ARMOUR, |
902
|
|
|
'Armour' => $armourDamage, |
903
|
|
|
'HasCDs' => $this->hasCDs(), |
904
|
|
|
'TotalDamage' => $shieldDamage + $cdDamage + $armourDamage |
905
|
|
|
); |
906
|
|
|
} |
907
|
|
|
|
908
|
|
|
public function doMinesDamage(array $damage) : array { |
909
|
|
|
$alreadyDead = $this->getPlayer()->isDead(); |
910
|
|
|
$armourDamage = 0; |
911
|
|
|
$cdDamage = 0; |
912
|
|
|
$shieldDamage = 0; |
913
|
|
|
if (!$alreadyDead) { |
914
|
|
|
$shieldDamage = $this->doShieldDamage(min($damage['MaxDamage'], $damage['Shield'])); |
915
|
|
|
$damage['MaxDamage'] -= $shieldDamage; |
916
|
|
|
if (!$this->hasShields() && ($shieldDamage == 0 || $damage['Rollover'])) { //skip CDs if it's mines |
917
|
|
|
$armourDamage = $this->doArmourDamage(min($damage['MaxDamage'], $damage['Armour'])); |
918
|
|
|
} |
919
|
|
|
} |
920
|
|
|
return array( |
921
|
|
|
'KillingShot' => !$alreadyDead && $this->isDead(), |
922
|
|
|
'TargetAlreadyDead' => $alreadyDead, |
923
|
|
|
'Shield' => $shieldDamage, |
924
|
|
|
'CDs' => $cdDamage, |
925
|
|
|
'NumCDs' => $cdDamage / CD_ARMOUR, |
926
|
|
|
'Armour' => $armourDamage, |
927
|
|
|
'HasCDs' => $this->hasCDs(), |
928
|
|
|
'TotalDamage' => $shieldDamage + $cdDamage + $armourDamage |
929
|
|
|
); |
930
|
|
|
} |
931
|
|
|
|
932
|
|
|
protected function doShieldDamage(int $damage) : int { |
933
|
|
|
$actualDamage = min($this->getShields(), $damage); |
934
|
|
|
$this->decreaseShields($actualDamage); |
935
|
|
|
return $actualDamage; |
936
|
|
|
} |
937
|
|
|
|
938
|
|
|
protected function doCDDamage(int $damage) : int { |
939
|
|
|
$actualDamage = min($this->getCDs(), IFloor($damage / CD_ARMOUR)); |
940
|
|
|
$this->decreaseCDs($actualDamage); |
941
|
|
|
return $actualDamage * CD_ARMOUR; |
942
|
|
|
} |
943
|
|
|
|
944
|
|
|
protected function doArmourDamage(int $damage) : int { |
945
|
|
|
$actualDamage = min($this->getArmour(), $damage); |
946
|
|
|
$this->decreaseArmour($actualDamage); |
947
|
|
|
return $actualDamage; |
948
|
|
|
} |
949
|
|
|
|
950
|
|
|
/** |
951
|
|
|
* Returns the maneuverability rating for this ship. |
952
|
|
|
*/ |
953
|
|
|
public function getMR() : int { |
954
|
|
|
//700 - [ (ship hit points / 25) + (ship stat factors) ] |
955
|
|
|
//Minimum value of 0 because negative values cause issues with calculations calling this routine |
956
|
|
|
return max(0, IRound( |
957
|
|
|
700 - |
958
|
|
|
( |
959
|
|
|
( |
960
|
|
|
$this->getShields() |
961
|
|
|
+$this->getArmour() |
962
|
|
|
+$this->getCDs() * 3 |
963
|
|
|
) / 25 |
964
|
|
|
+( |
965
|
|
|
$this->getCargoHolds() / 100 |
966
|
|
|
-$this->shipType->getSpeed() * 5 |
967
|
|
|
+($this->getHardpoints()/*+$ship['Increases']['Ship Power']*/) * 5 |
968
|
|
|
/*+( |
969
|
|
|
$ship['Increases']['Mines'] |
970
|
|
|
+$ship['Increases']['Scout Drones'] |
971
|
|
|
)/12*/ |
972
|
|
|
+$this->getCDs() / 5 |
973
|
|
|
) |
974
|
|
|
) |
975
|
|
|
) |
976
|
|
|
); |
977
|
|
|
} |
978
|
|
|
|
979
|
|
|
} |
980
|
|
|
|