Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Failed Conditions
Pull Request — main (#1494)
by Dan
08:06 queued 03:15
created

AttackPlayerProcessor   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 121
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 71
dl 0
loc 121
rs 10
c 1
b 0
f 0
wmc 24

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
F build() 0 115 23
1
<?php declare(strict_types=1);
2
3
namespace Smr\Pages\Player;
4
5
use AbstractSmrPlayer;
6
use Smr\Database;
7
use Smr\Epoch;
8
use Smr\Page\PlayerPageProcessor;
9
use Smr\SectorLock;
10
use SmrPlayer;
11
12
class AttackPlayerProcessor extends PlayerPageProcessor {
13
14
	public function __construct(
15
		private readonly int $targetAccountID
16
	) {}
17
18
	public function build(AbstractSmrPlayer $player): never {
19
		$account = $player->getAccount();
20
		$sector = $player->getSector();
21
22
		if ($player->hasNewbieTurns()) {
23
			create_error('You are under newbie protection.');
24
		}
25
		if ($player->hasFederalProtection()) {
26
			create_error('You are under federal protection.');
27
		}
28
		if ($player->isLandedOnPlanet()) {
29
			create_error('You cannot attack whilst on a planet!');
30
		}
31
		if ($player->getTurns() < TURNS_TO_SHOOT_SHIP) {
32
			create_error('You have insufficient turns to perform that action.');
33
		}
34
		if (!$player->canFight()) {
35
			create_error('You are not allowed to fight!');
36
		}
37
38
		$targetPlayer = SmrPlayer::getPlayer($this->targetAccountID, $player->getGameID());
39
40
		if ($player->traderNAPAlliance($targetPlayer)) {
41
			create_error('Your alliance does not allow you to attack this trader.');
42
		} elseif ($targetPlayer->isDead()) {
43
			create_error('Target is already dead.');
44
		} elseif ($targetPlayer->getSectorID() != $player->getSectorID()) {
45
			create_error('Target is no longer in this sector.');
46
		} elseif ($targetPlayer->hasNewbieTurns()) {
47
			create_error('Target is under newbie protection.');
48
		} elseif ($targetPlayer->isLandedOnPlanet()) {
49
			create_error('Target is protected by planetary shields.');
50
		} elseif ($targetPlayer->hasFederalProtection()) {
51
			create_error('Target is under federal protection.');
52
		}
53
54
		$fightingPlayers = $sector->getFightingTraders($player, $targetPlayer);
55
56
		// Randomize players so that the attack order is always different
57
		shuffle($fightingPlayers['Attackers']);
58
		shuffle($fightingPlayers['Defenders']);
59
60
		//decloak all fighters
61
		foreach ($fightingPlayers as $teamPlayers) {
62
			foreach ($teamPlayers as $teamPlayer) {
63
				$teamPlayer->getShip()->decloak();
64
			}
65
		}
66
67
		// Take off the 3 turns for attacking
68
		$player->takeTurns(TURNS_TO_SHOOT_SHIP);
69
		$player->update();
70
71
		/**
72
		 * @param array<string, array<int, AbstractSmrPlayer>> $fightingPlayers
73
		 * @return array<string, mixed>
74
		 */
75
		$teamAttack = function(array $fightingPlayers, string $attack, string $defend): array {
76
			$results = ['Traders' => [], 'TotalDamage' => 0];
77
			foreach ($fightingPlayers[$attack] as $accountID => $teamPlayer) {
78
				$playerResults = $teamPlayer->shootPlayers($fightingPlayers[$defend]);
79
				$results['Traders'][$teamPlayer->getAccountID()] = $playerResults;
80
				$results['TotalDamage'] += $playerResults['TotalDamage'];
81
82
				// Award assists (if there are multiple attackers)
83
				if (count($fightingPlayers[$attack]) > 1) {
84
					foreach ($playerResults['Weapons'] as $weaponResults) {
85
						if (isset($weaponResults['KillResults'])) {
86
							foreach ($fightingPlayers[$attack] as $assistPlayer) {
87
								if (!$assistPlayer->equals($teamPlayer)) {
88
									$assistPlayer->increaseAssists(1);
89
								}
90
							}
91
						}
92
					}
93
				}
94
			}
95
			return $results;
96
		};
97
98
		$results = [
99
			'Attackers' => $teamAttack($fightingPlayers, 'Attackers', 'Defenders'),
100
			'Defenders' => $teamAttack($fightingPlayers, 'Defenders', 'Attackers'),
101
		];
102
103
		$account->log(LOG_TYPE_TRADER_COMBAT, 'Player attacks player, their team does ' . $results['Attackers']['TotalDamage'] . ' and the other team does ' . $results['Defenders']['TotalDamage'], $sector->getSectorID());
104
105
		$db = Database::getInstance();
106
		$db->insert('combat_logs', [
107
			'game_id' => $db->escapeNumber($player->getGameID()),
108
			'type' => $db->escapeString('PLAYER'),
109
			'sector_id' => $db->escapeNumber($sector->getSectorID()),
110
			'timestamp' => $db->escapeNumber(Epoch::time()),
111
			'attacker_id' => $db->escapeNumber($player->getAccountID()),
112
			'attacker_alliance_id' => $db->escapeNumber($player->getAllianceID()),
113
			'defender_id' => $db->escapeNumber($this->targetAccountID),
114
			'defender_alliance_id' => $db->escapeNumber($targetPlayer->getAllianceID()),
115
			'result' => $db->escapeObject($results, true),
116
		]);
117
118
		// If player died they are now in another sector, and thus locks need reset
119
		if ($player->isDead()) {
120
			saveAllAndReleaseLock(updateSession: false);
121
			// Grab the lock in the new sector to avoid reloading session
122
			SectorLock::getInstance()->acquireForPlayer($player);
123
		}
124
125
		// If player or target is dead there is no continue attack button
126
		if ($player->isDead() || $targetPlayer->isDead()) {
127
			$targetAccountID = null;
128
		} else {
129
			$targetAccountID = $this->targetAccountID;
130
		}
131
		$container = new AttackPlayer($results, $targetAccountID, $player->isDead());
132
		$container->go();
133
	}
134
135
}
136