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::build()   F

Complexity

Conditions 23
Paths 2688

Size

Total Lines 115
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 23
eloc 70
nc 2688
nop 1
dl 0
loc 115
rs 0
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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