Fix border color changes edge cases (#754)

## Description:

Fixes a couple of bugs with the defended border color:
- When a defense post is destroyed it doesnt redraw defended border to
normal ones
- The distance to draw borders at unit update is not the same as
territory update
- When a defense post changes owner, only the directly touching borders
were redrawn. Had to refactor units a bit so it keeps track of the last
owner

## Gifs:
Before fix:

![image](https://github.com/user-attachments/assets/99b2763c-9c49-4d5d-8059-a9f938e8cef8)


After fix:

![capture](https://github.com/user-attachments/assets/4ebf388d-91e4-4e9e-bc96-9fe6e02cd9ea)

![destruct](https://github.com/user-attachments/assets/5a1204a8-d5c4-473f-8f4d-5cc46cd19080)



## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

## Please put your Discord username so you can be contacted if a bug or
regression is found:

VivaciousBox
This commit is contained in:
Vivacious Box
2025-05-15 20:48:18 +02:00
committed by GitHub
parent 3b9e94ddb9
commit c65c9a6ca8
5 changed files with 21 additions and 35 deletions
+5 -11
View File
@@ -3,11 +3,7 @@ import { Colord } from "colord";
import { Theme } from "../../../core/configuration/Config";
import { EventBus } from "../../../core/EventBus";
import { Cell, PlayerType, UnitType } from "../../../core/game/Game";
import {
euclDistFN,
manhattanDistFN,
TileRef,
} from "../../../core/game/GameMap";
import { euclDistFN, TileRef } from "../../../core/game/GameMap";
import { GameUpdateType, UnitUpdate } from "../../../core/game/GameUpdates";
import { GameView, PlayerView } from "../../../core/game/GameView";
import { PseudoRandom } from "../../../core/PseudoRandom";
@@ -64,17 +60,15 @@ export class TerritoryLayer implements Layer {
this.game.recentlyUpdatedTiles().forEach((t) => this.enqueueTile(t));
this.game.updatesSinceLastTick()[GameUpdateType.Unit].forEach((u) => {
const update = u as UnitUpdate;
if (update.unitType == UnitType.DefensePost && update.isActive) {
if (update.unitType == UnitType.DefensePost) {
const tile = update.pos;
this.game
.bfs(
tile,
manhattanDistFN(tile, this.game.config().defensePostRange()),
)
.bfs(tile, euclDistFN(tile, this.game.config().defensePostRange()))
.forEach((t) => {
if (
this.game.isBorder(t) &&
this.game.ownerID(t) == update.ownerID
(this.game.ownerID(t) == update.ownerID ||
this.game.ownerID(t) == update.lastOwnerID)
) {
this.enqueueTile(t);
}
+1
View File
@@ -344,6 +344,7 @@ export interface Unit {
setWarshipTarget(target: Unit): void; // warship only
warshipTarget(): Unit;
setOwner(owner: Player): void;
setCooldown(triggerCooldown: boolean): void;
ticksLeftInCooldown(cooldownDuration: number): Tick;
isCooldown(): boolean;
+1
View File
@@ -68,6 +68,7 @@ export interface UnitUpdate {
troops: number;
id: number;
ownerID: number;
lastOwnerID?: number;
// TODO: make these tilerefs
pos: TileRef;
lastPos: TileRef;
+1 -17
View File
@@ -703,23 +703,7 @@ export class PlayerImpl implements Player {
if (unit.owner() == this) {
throw new Error(`Cannot capture unit, ${this} already owns ${unit}`);
}
const prev = unit.owner();
(prev as PlayerImpl)._units = (prev as PlayerImpl)._units.filter(
(u) => u != unit,
);
(unit as UnitImpl)._owner = this;
this._units.push(unit as UnitImpl);
this.mg.addUpdate(unit.toUpdate());
this.mg.displayMessage(
`${unit.type()} captured by ${this.displayName()}`,
MessageType.ERROR,
prev.id(),
);
this.mg.displayMessage(
`Captured ${unit.type()} from ${prev.displayName()}`,
MessageType.SUCCESS,
this.id(),
);
unit.setOwner(this);
}
buildUnit<T extends UnitType>(
+13 -7
View File
@@ -2,7 +2,6 @@ import { simpleHash, toInt, withinInt } from "../Util";
import {
AllUnitParams,
MessageType,
Player,
Tick,
Unit,
UnitInfo,
@@ -23,7 +22,7 @@ export class UnitImpl implements Unit {
private _safeFromPiratesCooldown: number; // Only for trade ships
private _lastSetSafeFromPirates: number; // Only for trade ships
private _constructionType: UnitType = undefined;
private _lastOwner: PlayerImpl | null = null;
private _troops: number;
private _cooldownTick: Tick | null = null;
private _dstPort: Unit | null = null; // Only for trade ships
@@ -66,6 +65,7 @@ export class UnitImpl implements Unit {
id: this._id,
troops: this._troops,
ownerID: this._owner.smallID(),
lastOwnerID: this._lastOwner?.smallID(),
isActive: this._active,
pos: this._tile,
lastPos: this._lastTile,
@@ -119,15 +119,21 @@ export class UnitImpl implements Unit {
return this.mg.unitInfo(this._type);
}
setOwner(newOwner: Player): void {
const oldOwner = this._owner;
oldOwner._units = oldOwner._units.filter((u) => u != this);
this._owner = newOwner as PlayerImpl;
setOwner(newOwner: PlayerImpl): void {
this._lastOwner = this._owner;
this._lastOwner._units = this._lastOwner._units.filter((u) => u != this);
this._owner = newOwner;
this._owner._units.push(this);
this.mg.addUpdate(this.toUpdate());
this.mg.displayMessage(
`Your ${this.type()} was captured by ${newOwner.displayName()}`,
MessageType.ERROR,
oldOwner.id(),
this._lastOwner.id(),
);
this.mg.displayMessage(
`Captured ${this.type()} from ${this._lastOwner.displayName()}`,
MessageType.SUCCESS,
newOwner.id(),
);
}