-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #105 from lanedirt/100-add-fleet-mission-transport…
…-return-logic Add fleet mission transport return logic
- Loading branch information
Showing
25 changed files
with
1,280 additions
and
269 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,247 @@ | ||
<?php | ||
|
||
namespace OGame\GameMissions\Abstracts; | ||
|
||
use Illuminate\Contracts\Container\BindingResolutionException; | ||
use Illuminate\Support\Carbon; | ||
use OGame\Factories\PlanetServiceFactory; | ||
use OGame\GameObjects\Models\UnitCollection; | ||
use OGame\Models\FleetMission; | ||
use OGame\Models\Resources; | ||
use OGame\Services\FleetMissionService; | ||
use OGame\Services\MessageService; | ||
use OGame\Services\PlanetService; | ||
|
||
abstract class GameMission | ||
{ | ||
/** | ||
* @var string The name of the mission shown in the GUI. | ||
*/ | ||
protected static string $name; | ||
|
||
/** | ||
* @var int The type ID of the mission. | ||
*/ | ||
protected static int $typeId; | ||
|
||
/** | ||
* @var bool Whether this mission has a return mission by default. | ||
*/ | ||
protected static bool $hasReturnMission; | ||
|
||
protected FleetMissionService $fleetMissionService; | ||
|
||
protected MessageService $messageService; | ||
|
||
public function __construct(FleetMissionService $fleetMissionService, MessageService $messageService) | ||
{ | ||
$this->fleetMissionService = $fleetMissionService; | ||
$this->messageService = $messageService; | ||
} | ||
|
||
public static function getName(): string | ||
{ | ||
return static::$name; | ||
} | ||
|
||
public static function hasReturnMission(): bool | ||
{ | ||
return static::$hasReturnMission; | ||
} | ||
|
||
/** | ||
* Cancel an already started mission. | ||
* | ||
* @param FleetMission $mission | ||
* @return void | ||
* @throws BindingResolutionException | ||
*/ | ||
public function cancel(FleetMission $mission): void | ||
{ | ||
// Mark parent mission as canceled. | ||
$mission->canceled = 1; | ||
$mission->processed = 1; | ||
$mission->save(); | ||
|
||
// Start the return mission. | ||
$this->startReturn($mission); | ||
} | ||
|
||
/** | ||
* Generic sanity checks before starting a mission to make sure the planet has enough resources and units. | ||
* | ||
* @param PlanetService $planet | ||
* @param UnitCollection $units | ||
* @param Resources $resources | ||
* @return void | ||
* @throws \Exception | ||
*/ | ||
public function startMissionSanityChecks(PlanetService $planet, UnitCollection $units, Resources $resources): void | ||
{ | ||
if (!$planet->hasResources($resources)) { | ||
throw new \Exception('Not enough resources on the planet to send the fleet.'); | ||
} | ||
if (!$planet->hasUnits($units)) { | ||
throw new \Exception('Not enough units on the planet to send the fleet.'); | ||
} | ||
} | ||
|
||
/** | ||
* Deduct mission resources from the planet (when starting mission). | ||
* | ||
* @throws \Exception | ||
*/ | ||
public function deductMissionResources(PlanetService $planet, Resources $resources, UnitCollection $units): void | ||
{ | ||
$planet->deductResources($resources, false); | ||
$planet->removeUnits($units, false); | ||
} | ||
|
||
/** | ||
* Start a new mission. | ||
* | ||
* @param PlanetService $planet | ||
* @param PlanetService $targetPlanet | ||
* @param UnitCollection $units | ||
* @param Resources $resources | ||
* @param int $parent_id | ||
* @return void | ||
* @throws \Exception | ||
*/ | ||
public function start(PlanetService $planet, PlanetService $targetPlanet, UnitCollection $units, Resources $resources, int $parent_id = 0): void | ||
{ | ||
$this->startMissionSanityChecks($planet, $units, $resources); | ||
|
||
// Time this fleet mission will depart (now) | ||
$time_start = (int)Carbon::now()->timestamp; | ||
|
||
// Time fleet mission will arrive | ||
//TODO: refactor calculate to gamemission base class? | ||
$time_end = $time_start + $this->fleetMissionService->calculateFleetMissionDuration(); | ||
|
||
$mission = new FleetMission(); | ||
|
||
// Set the parent mission if it exists. This indicates that this mission is a follow-up (return) | ||
// mission linked to a previous mission. | ||
if (!empty($parent_id)) { | ||
$parentMission = $this->fleetMissionService->getFleetMissionById($parent_id); | ||
$mission->parent_id = $parentMission->id; | ||
} | ||
|
||
$mission->user_id = $planet->getPlayer()->getId(); | ||
$mission->planet_id_from = $planet->getPlanetId(); | ||
$mission->mission_type = static::$typeId; | ||
$mission->time_departure = $time_start; | ||
$mission->time_arrival = $time_end; | ||
|
||
$mission->planet_id_to = $targetPlanet->getPlanetId(); | ||
// Coordinates | ||
$coords = $targetPlanet->getPlanetCoordinates(); | ||
$mission->galaxy_to = $coords->galaxy; | ||
$mission->system_to = $coords->system; | ||
$mission->position_to = $coords->position; | ||
|
||
// Define units | ||
foreach ($units->units as $unit) { | ||
$mission->{$unit->unitObject->machine_name} = $unit->amount; | ||
} | ||
// Define resources | ||
$mission->metal = $resources->metal->getRounded(); | ||
$mission->crystal = $resources->crystal->getRounded(); | ||
$mission->deuterium = $resources->deuterium->getRounded(); | ||
|
||
// Deduct mission resources from the planet. | ||
$this->deductMissionResources($planet, $resources, $units); | ||
|
||
// Save the new fleet mission. | ||
$mission->save(); | ||
} | ||
|
||
/** | ||
* Start the return mission. | ||
* | ||
* @param FleetMission $parentMission | ||
* @return void | ||
* @throws \Illuminate\Contracts\Container\BindingResolutionException | ||
*/ | ||
protected function startReturn(FleetMission $parentMission): void { | ||
// No need to check for resources and units, as the return mission takes the units from the original | ||
// mission and the resources are already delivered. Nothing is deducted from the planet. | ||
// Time this fleet mission will depart (arrival time of the parent mission) | ||
$time_start = $parentMission->time_arrival; | ||
|
||
// Time fleet mission will arrive (arrival time of the parent mission + duration of the parent mission) | ||
// Return mission duration is always the same as the parent mission duration. | ||
$time_end = $time_start + ($parentMission->time_arrival - $parentMission->time_departure); | ||
|
||
// Create new return mission object | ||
$mission = new FleetMission(); | ||
$mission->parent_id = $parentMission->id; | ||
$mission->user_id = $parentMission->user_id; | ||
$mission->planet_id_from = $parentMission->planet_id_to; | ||
$mission->mission_type = $parentMission->mission_type; | ||
$mission->time_departure = $time_start; | ||
$mission->time_arrival = $time_end; | ||
$mission->planet_id_to = $parentMission->planet_id_from; | ||
|
||
// Planet from service | ||
$planetServiceFactory = app()->make(PlanetServiceFactory::class); | ||
$planetFromService = $planetServiceFactory->make($mission->planet_id_from); | ||
$planetToService = $planetServiceFactory->make($mission->planet_id_to); | ||
|
||
// Coordinates | ||
$coords = $planetToService->getPlanetCoordinates(); | ||
$mission->galaxy_to = $coords->galaxy; | ||
$mission->system_to = $coords->system; | ||
$mission->position_to = $coords->position; | ||
|
||
// Fill in the units | ||
foreach ($this->fleetMissionService->getFleetUnits($parentMission)->units as $unit) { | ||
$mission->{$unit->unitObject->machine_name} = $unit->amount; | ||
} | ||
|
||
// Fill in the resources. Return missions do not carry resources as they have been | ||
// offloaded at the target planet. | ||
$mission->metal = 0; | ||
$mission->crystal = 0; | ||
$mission->deuterium = 0; | ||
|
||
// Save the new fleet return mission. | ||
$mission->save(); | ||
} | ||
|
||
/** | ||
* Process the mission. | ||
* | ||
* @param FleetMission $mission | ||
* @return void | ||
*/ | ||
public function process(FleetMission $mission): void { | ||
if (!empty($mission->parent_id)) { | ||
// This is a return mission as it has a parent mission. | ||
$this->processReturn($mission); | ||
return; | ||
} | ||
else { | ||
// This is an arrival mission as it has no parent mission. | ||
// Process arrival. | ||
$this->processArrival($mission); | ||
} | ||
} | ||
|
||
/** | ||
* Process the mission arrival (first stage, required). | ||
* | ||
* @param FleetMission $mission | ||
* @return void | ||
*/ | ||
protected abstract function processArrival(FleetMission $mission): void; | ||
|
||
/** | ||
* Process the mission return (second stage, optional). | ||
* | ||
* @param FleetMission $mission | ||
* @return void | ||
*/ | ||
protected abstract function processReturn(FleetMission $mission): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
namespace OGame\GameMissions; | ||
|
||
use Illuminate\Contracts\Container\BindingResolutionException; | ||
use OGame\Factories\PlanetServiceFactory; | ||
use OGame\GameMissions\Abstracts\GameMission; | ||
use OGame\Models\FleetMission; | ||
|
||
class DeploymentMission extends GameMission | ||
{ | ||
protected static string $name = 'Deployment'; | ||
protected static int $typeId = 4; | ||
protected static bool $hasReturnMission = false; | ||
|
||
/** | ||
* @throws BindingResolutionException | ||
*/ | ||
protected function processArrival(FleetMission $mission): void | ||
{ | ||
// Load the target planet | ||
$planetServiceFactory = app()->make(PlanetServiceFactory::class); | ||
$target_planet = $planetServiceFactory->make($mission->planet_id_to); | ||
|
||
// Add resources to the target planet | ||
$resources = $this->fleetMissionService->getResources($mission); | ||
$target_planet->addResources($resources); | ||
|
||
// Send a message to the player that the mission has arrived | ||
// TODO: make message content translatable by using tokens instead of directly inserting dynamic content. | ||
if ($resources->sum() > 0) { | ||
$this->messageService->sendMessageToPlayer($target_planet->getPlayer(), 'Fleet deployment', 'One of your fleets from [planet]' . $mission->planet_id_from . '[/planet] has reached [planet]' . $mission->planet_id_to . '[/planet] and delivered its goods: | ||
Metal: ' . $mission->metal . ' | ||
Crystal: ' . $mission->crystal . ' | ||
Deuterium: ' . $mission->deuterium, 'fleet_deployment'); | ||
} | ||
else { | ||
$this->messageService->sendMessageToPlayer($target_planet->getPlayer(), 'Fleet deployment', 'One of your fleets from [planet]' . $mission->planet_id_from . '[/planet] has reached [planet]' . $mission->planet_id_to . '[/planet]. The fleet doesn`t deliver goods.', 'fleet_deployment'); | ||
} | ||
|
||
// Mark the arrival mission as processed | ||
$mission->processed = 1; | ||
$mission->save(); | ||
} | ||
|
||
protected function processReturn(FleetMission $mission): void | ||
{ | ||
// Load the target planet | ||
$planetServiceFactory = app()->make(PlanetServiceFactory::class); | ||
$target_planet = $planetServiceFactory->make($mission->planet_id_to); | ||
|
||
// Transport return trip: add back the units to the source planet. Then we're done. | ||
$target_planet->addUnits($this->fleetMissionService->getFleetUnits($mission)); | ||
|
||
// Send message to player that the return mission has arrived | ||
$this->messageService->sendMessageToPlayer($target_planet->getPlayer(), 'Return of a fleet', 'Your fleet is returning from planet [planet]' . $mission->planet_id_from . '[/planet] to planet [planet]' . $mission->planet_id_to . '[/planet]. | ||
The fleet doesn\'t deliver goods.', 'return_of_fleet'); | ||
|
||
// Mark the return mission as processed | ||
$mission->processed = 1; | ||
$mission->save(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
|
||
namespace OGame\GameMissions; | ||
|
||
use Illuminate\Contracts\Container\BindingResolutionException; | ||
use OGame\Factories\PlanetServiceFactory; | ||
use OGame\GameMissions\Abstracts\GameMission; | ||
use OGame\Models\FleetMission; | ||
|
||
class TransportMission extends GameMission | ||
{ | ||
protected static string $name = 'Transport'; | ||
protected static int $typeId = 3; | ||
protected static bool $hasReturnMission = true; | ||
|
||
/** | ||
* @throws BindingResolutionException | ||
*/ | ||
protected function processArrival(FleetMission $mission): void | ||
{ | ||
$planetServiceFactory = app()->make(PlanetServiceFactory::class); | ||
// Load origin planet | ||
$origin_planet = $planetServiceFactory->make($mission->planet_id_from); | ||
// Load the target planet | ||
$target_planet = $planetServiceFactory->make($mission->planet_id_to); | ||
|
||
// Add resources to the target planet | ||
$target_planet->addResources($this->fleetMissionService->getResources($mission)); | ||
|
||
// Send a message to the origin player that the mission has arrived | ||
// TODO: make message content translatable by using tokens instead of directly inserting dynamic content. | ||
$this->messageService->sendMessageToPlayer($origin_planet->getPlayer(), 'Reaching a planet', 'Your fleet from planet [planet]' . $mission->planet_id_from . '[/planet] reaches the planet [planet]' . $mission->planet_id_to . '[/planet] and delivers its goods: | ||
Metal: ' . $mission->metal . ' Crystal: ' . $mission->crystal . ' Deuterium: ' . $mission->deuterium, 'transport_arrived'); | ||
|
||
if ($origin_planet->getPlayer()->getId() !== $target_planet->getPlayer()->getId()) { | ||
// Send a message to the target player that the mission has arrived | ||
$this->messageService->sendMessageToPlayer($target_planet->getPlayer(), 'Incoming fleet', 'An incoming fleet from planet [planet]' . $mission->planet_id_from . '[/planet] has reached your planet [planet]' . $mission->planet_id_to . '[/planet] and delivered its goods: | ||
Metal: ' . $mission->metal . ' Crystal: ' . $mission->crystal . ' Deuterium: ' . $mission->deuterium, 'transport_received'); | ||
} | ||
|
||
// Create and start the return mission. | ||
$this->startReturn($mission); | ||
|
||
// Mark the arrival mission as processed | ||
$mission->processed = 1; | ||
$mission->save(); | ||
} | ||
|
||
protected function processReturn(FleetMission $mission): void | ||
{ | ||
// Load the target planet | ||
$planetServiceFactory = app()->make(PlanetServiceFactory::class); | ||
$target_planet = $planetServiceFactory->make($mission->planet_id_to); | ||
|
||
// Transport return trip: add back the units to the source planet. | ||
$target_planet->addUnits($this->fleetMissionService->getFleetUnits($mission)); | ||
|
||
// Send message to player that the return mission has arrived | ||
$this->messageService->sendMessageToPlayer($target_planet->getPlayer(), 'Return of a fleet', 'Your fleet is returning from planet [planet]' . $mission->planet_id_from . '[/planet] to planet [planet]' . $mission->planet_id_to . '[/planet]. | ||
The fleet doesn\'t deliver goods.', 'return_of_fleet'); | ||
|
||
// Mark the return mission as processed | ||
$mission->processed = 1; | ||
$mission->save(); | ||
} | ||
} |
Oops, something went wrong.