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

AttackForcesProcessor   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 72
dl 0
loc 135
rs 10
c 1
b 0
f 0
wmc 23

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
F build() 0 128 22
1
<?php declare(strict_types=1);
2
3
namespace Smr\Pages\Player;
4
5
use AbstractSmrPlayer;
6
use Globals;
7
use Smr\Database;
8
use Smr\Epoch;
9
use Smr\Page\PlayerPageProcessor;
10
use Smr\SectorLock;
11
use SmrForce;
12
13
class AttackForcesProcessor extends PlayerPageProcessor {
14
15
	public function __construct(
16
		private readonly int $ownerAccountID,
17
		private readonly bool $bump = false
18
	) {}
19
20
	public function build(AbstractSmrPlayer $player): never {
21
		$ship = $player->getShip();
22
23
		$forces = SmrForce::getForce($player->getGameID(), $player->getSectorID(), $this->ownerAccountID);
24
		$forceOwner = $forces->getOwner();
25
26
		if ($player->hasNewbieTurns()) {
27
			create_error('You are under newbie protection!');
28
		}
29
		if ($player->hasFederalProtection()) {
30
			create_error('You are under federal protection.');
31
		}
32
		if ($player->isLandedOnPlanet()) {
33
			create_error('You cannot attack forces whilst on a planet!');
34
		}
35
		if (!$player->canFight()) {
36
			create_error('You are not allowed to fight!');
37
		}
38
		if ($player->forceNAPAlliance($forceOwner)) {
39
			create_error('You cannot attack allied forces!');
40
		}
41
42
		// The attack is processed slightly differently if the attacker bumped into mines
43
		// when moving into sector
44
		$bump = $this->bump;
45
46
		if ($bump) {
47
			if (!$forces->hasMines()) {
48
				create_error('No mines in sector!');
49
			}
50
		} else {
51
			if (!$forces->exists()) {
52
				create_error('These forces no longer exist.');
53
			}
54
			if ($player->getTurns() < $forces->getAttackTurnCost($ship)) {
55
				create_error('You do not have enough turns to attack these forces!');
56
			}
57
			if (!$ship->hasWeapons() && !$ship->hasCDs()) {
58
				create_error('You cannot attack without weapons!');
59
			}
60
		}
61
62
		// take the turns
63
		if ($bump) {
64
			$player->takeTurns($forces->getBumpTurnCost($ship));
65
		} else {
66
			$player->takeTurns($forces->getAttackTurnCost($ship), 1);
67
		}
68
69
		// delete plotted course
70
		$player->deletePlottedCourse();
71
72
		// A message will be sent if scouts are present before the attack.
73
		// Sending occurs after the attack so we can link the combat log.
74
		$sendMessage = $forces->hasSDs();
75
76
		// ********************************
77
		// *
78
		// * F o r c e s   a t t a c k
79
		// *
80
		// ********************************
81
82
		$results = ['Attackers' => ['TotalDamage' => 0],
83
						'Forces' => [],
84
						'Forced' => $bump];
85
86
		$attackers = $player->getSector()->getFightingTradersAgainstForces($player, $bump);
87
88
		//decloak all attackers
89
		foreach ($attackers as $attacker) {
90
			$attacker->getShip()->decloak();
91
			if (!$bump) {
92
				$attacker->setLastSectorID(0);
93
			}
94
		}
95
96
		// If mines are bumped, the forces shoot first. Otherwise player shoots first.
97
		if ($bump) {
98
			$results['Forces'] = $forces->shootPlayers($attackers, $bump);
99
		}
100
101
		$results['Attackers'] = ['TotalDamage' => 0];
102
		foreach ($attackers as $attacker) {
103
			$playerResults = $attacker->shootForces($forces);
104
			$results['Attackers']['Traders'][$attacker->getAccountID()] = $playerResults;
105
			$results['Attackers']['TotalDamage'] += $playerResults['TotalDamage'];
106
		}
107
108
		if (!$bump) {
109
			$results['Forces'] = $forces->shootPlayers($attackers, $bump);
110
			$forces->updateExpire();
111
		}
112
113
		// Add this log to the `combat_logs` database table
114
		$db = Database::getInstance();
115
		$logId = $db->insert('combat_logs', [
116
			'game_id' => $db->escapeNumber($player->getGameID()),
117
			'type' => $db->escapeString('FORCE'),
118
			'sector_id' => $db->escapeNumber($forces->getSectorID()),
119
			'timestamp' => $db->escapeNumber(Epoch::time()),
120
			'attacker_id' => $db->escapeNumber($player->getAccountID()),
121
			'attacker_alliance_id' => $db->escapeNumber($player->getAllianceID()),
122
			'defender_id' => $db->escapeNumber($forceOwner->getAccountID()),
123
			'defender_alliance_id' => $db->escapeNumber($forceOwner->getAllianceID()),
124
			'result' => $db->escapeObject($results, true),
125
		]);
126
127
		if ($sendMessage) {
128
			$message = 'Your forces in sector ' . Globals::getSectorBBLink($forces->getSectorID()) . ' are under <span class="red">attack</span> by ' . $player->getBBLink() . '! [combatlog=' . $logId . ']';
129
			$forces->ping($message, $player, true);
130
		}
131
132
		// If player died they are now in another sector, and thus locks need reset
133
		if ($player->isDead()) {
134
			saveAllAndReleaseLock(updateSession: false);
135
			// Grab the lock in the new sector to avoid reloading session
136
			SectorLock::getInstance()->acquireForPlayer($player);
137
		}
138
139
		// If player or target is dead there is no continue attack button
140
		if ($player->isDead() || !$forces->exists()) {
141
			$displayOwnerID = 0;
142
		} else {
143
			$displayOwnerID = $forces->getOwnerID();
144
		}
145
146
		$container = new AttackForces($displayOwnerID, $results, $player->isDead());
147
		$container->go();
148
	}
149
150
}
151