mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:30:45 +00:00
Fix transport ship src and dst to always be water (#2832)
## Description: Issue discovered by @DevelopingTom, posted on Discord. After merging pathfinding PR, transport ships lost the ability to navigate between land tiles. For now, the quick fix is to select adjacent water tile and select it for pathing. Conquer logic still applies to original destination on the shore. ## Please complete the following: - [ ] I have added screenshots for all UI updates - [ ] I process any text displayed to the user through translateText() and I've added it to the en.json file - [ ] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: moleole
This commit is contained in:
committed by
GitHub
parent
cf1e67cd9c
commit
d8762b1317
@@ -29,6 +29,7 @@ export class TransportShipExecution implements Execution {
|
||||
// TODO make private
|
||||
public path: TileRef[];
|
||||
private dst: TileRef | null;
|
||||
private dstShore: TileRef | null;
|
||||
|
||||
private boat: Unit;
|
||||
|
||||
@@ -103,8 +104,8 @@ export class TransportShipExecution implements Execution {
|
||||
|
||||
this.startTroops = Math.min(this.startTroops, this.attacker.troops());
|
||||
|
||||
this.dst = targetTransportTile(this.mg, this.ref);
|
||||
if (this.dst === null) {
|
||||
this.dstShore = targetTransportTile(this.mg, this.ref);
|
||||
if (this.dstShore === null) {
|
||||
console.warn(
|
||||
`${this.attacker} cannot send ship to ${this.target}, cannot find attack tile`,
|
||||
);
|
||||
@@ -112,9 +113,18 @@ export class TransportShipExecution implements Execution {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dst = this.adjacentWater(this.dstShore);
|
||||
if (this.dst === null) {
|
||||
console.warn(
|
||||
`${this.attacker} cannot find water tile adjacent to destination`,
|
||||
);
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const closestTileSrc = this.attacker.canBuild(
|
||||
UnitType.TransportShip,
|
||||
this.dst,
|
||||
this.dstShore,
|
||||
);
|
||||
if (closestTileSrc === false) {
|
||||
console.warn(`can't build transport ship`);
|
||||
@@ -143,6 +153,22 @@ export class TransportShipExecution implements Execution {
|
||||
targetTile: this.dst ?? undefined,
|
||||
});
|
||||
|
||||
// Move boat from shore to adjacent water for pathfinding
|
||||
const spawnWater = this.adjacentWater(this.src);
|
||||
if (spawnWater === null) {
|
||||
console.warn(`No adjacent water for transport ship spawn`);
|
||||
this.boat.delete(false);
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
this.boat.move(spawnWater);
|
||||
|
||||
if (this.dstShore !== null) {
|
||||
this.boat.setTargetTile(this.dstShore);
|
||||
} else {
|
||||
this.boat.setTargetTile(undefined);
|
||||
}
|
||||
|
||||
// Notify the target player about the incoming naval invasion
|
||||
if (this.targetID && this.targetID !== mg.terraNullius().id()) {
|
||||
mg.displayIncomingUnit(
|
||||
@@ -194,6 +220,7 @@ export class TransportShipExecution implements Execution {
|
||||
if (this.mg.owner(this.src!) !== this.attacker) {
|
||||
// Use bestTransportShipSpawn, not canBuild because of its max boats check etc
|
||||
const newSrc = this.attacker.bestTransportShipSpawn(this.dst);
|
||||
|
||||
if (newSrc === false) {
|
||||
this.src = null;
|
||||
} else {
|
||||
@@ -210,10 +237,19 @@ export class TransportShipExecution implements Execution {
|
||||
this.active = false;
|
||||
return;
|
||||
} else {
|
||||
this.dst = this.src;
|
||||
this.dstShore = this.src;
|
||||
const retreatWater = this.adjacentWater(this.src);
|
||||
if (retreatWater === null) {
|
||||
console.warn(`No adjacent water for retreat destination`);
|
||||
this.attacker.addTroops(this.boat.troops());
|
||||
this.boat.delete(false);
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
this.dst = retreatWater;
|
||||
|
||||
if (this.boat.targetTile() !== this.dst) {
|
||||
this.boat.setTargetTile(this.dst);
|
||||
if (this.boat.targetTile() !== this.dstShore) {
|
||||
this.boat.setTargetTile(this.dstShore!);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,7 +257,7 @@ export class TransportShipExecution implements Execution {
|
||||
const result = this.pathFinder.next(this.boat.tile(), this.dst);
|
||||
switch (result.status) {
|
||||
case PathStatus.COMPLETE:
|
||||
if (this.mg.owner(this.dst) === this.attacker) {
|
||||
if (this.mg.owner(this.dstShore!) === this.attacker) {
|
||||
const deaths = this.boat.troops() * (malusForRetreat / 100);
|
||||
const survivors = this.boat.troops() - deaths;
|
||||
this.attacker.addTroops(survivors);
|
||||
@@ -241,7 +277,7 @@ export class TransportShipExecution implements Execution {
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.attacker.conquer(this.dst);
|
||||
this.attacker.conquer(this.dstShore!);
|
||||
if (this.target.isPlayer() && this.attacker.isFriendly(this.target)) {
|
||||
this.attacker.addTroops(this.boat.troops());
|
||||
} else {
|
||||
@@ -250,7 +286,7 @@ export class TransportShipExecution implements Execution {
|
||||
this.boat.troops(),
|
||||
this.attacker,
|
||||
this.targetID,
|
||||
this.dst,
|
||||
this.dstShore!,
|
||||
false,
|
||||
),
|
||||
);
|
||||
@@ -285,4 +321,17 @@ export class TransportShipExecution implements Execution {
|
||||
isActive(): boolean {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
private adjacentWater(tile: TileRef): TileRef | null {
|
||||
if (this.mg.isWater(tile)) {
|
||||
return tile;
|
||||
}
|
||||
|
||||
for (const neighbor of this.mg.neighbors(tile)) {
|
||||
if (this.mg.isWater(neighbor)) {
|
||||
return neighbor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ describe("Disconnected", () => {
|
||||
player1.conquer(game.map().ref(coastX, 4));
|
||||
player2.conquer(game.map().ref(coastX, 1));
|
||||
|
||||
const enemyShoreTile = game.map().ref(coastX, 8);
|
||||
const enemyShoreTile = game.map().ref(coastX, 15);
|
||||
|
||||
game.addExecution(
|
||||
new TransportShipExecution(
|
||||
|
||||
Reference in New Issue
Block a user