diff --git a/TODO.txt b/TODO.txt index e0eafe659..320af0ca5 100644 --- a/TODO.txt +++ b/TODO.txt @@ -151,8 +151,8 @@ * BUG: alliance expire message after player dies DONE 9/30/2024 * BUG: alliance cooldown request DONE 9/30/2024 * make create/break alliance single button DONE 10/1/2024 +* add request attack other players DONE 10/2/2024 * Improve alliance icon -* add request attack other players * BUG: double tap zooms on mobile * BUG: center button should be disabled select island * BUG: boat icon appears when click inland diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index b88b1bde7..198769760 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -1,6 +1,6 @@ import {nullable} from "zod"; import {EventBus, GameEvent} from "../../../core/EventBus"; -import {AllianceExpiredEvent, AllianceRequestEvent, AllianceRequestReplyEvent, BrokeAllianceEvent, Game, Player, PlayerID} from "../../../core/game/Game"; +import {AllianceExpiredEvent, AllianceRequestEvent, AllianceRequestReplyEvent, BrokeAllianceEvent, Game, Player, PlayerID, TargetPlayerEvent} from "../../../core/game/Game"; import {ClientID} from "../../../core/Schemas"; import {Layer} from "./Layer"; import {SendAllianceReplyIntentEvent} from "../../Transport"; @@ -52,6 +52,7 @@ export class EventsDisplay implements Layer { this.eventBus.on(DisplayMessageEvent, e => this.onDisplayMessageEvent(e)) this.eventBus.on(BrokeAllianceEvent, e => this.onBrokeAllianceEvent(e)) this.eventBus.on(AllianceExpiredEvent, e => this.onAllianceExpiredEvent(e)) + this.eventBus.on(TargetPlayerEvent, e => this.onTargetPlayerEvent(e)) this.renderTable() } @@ -210,6 +211,21 @@ export class EventsDisplay implements Layer { }) } + onTargetPlayerEvent(event: TargetPlayerEvent) { + const myPlayer = this.game.playerByClientID(this.clientID) + if (myPlayer == null) { + return + } + if (myPlayer.isAlliedWith(event.player)) { + this.addEvent({ + description: `${event.player.name()} requests you attack ${event.target.name()}`, + type: MessageType.INFO, + highlight: true, + createdAt: this.game.ticks(), + }) + } + } + addEvent(event: Event): void { this.events.push(event); this.renderTable() diff --git a/src/client/graphics/layers/NameLayer.ts b/src/client/graphics/layers/NameLayer.ts index 4025a901c..dbc62c988 100644 --- a/src/client/graphics/layers/NameLayer.ts +++ b/src/client/graphics/layers/NameLayer.ts @@ -178,7 +178,7 @@ export class NameLayer implements Layer { ); } - if (new Set(myPlayer.transitiveTargets()).has(render.player)) { + if (myPlayer != null && new Set(myPlayer.transitiveTargets()).has(render.player)) { context.drawImage( this.targetIconImage, nameCenterX - iconSize / 2, diff --git a/src/client/graphics/layers/RadialMenu.ts b/src/client/graphics/layers/RadialMenu.ts index 9f346531e..a0b7c046e 100644 --- a/src/client/graphics/layers/RadialMenu.ts +++ b/src/client/graphics/layers/RadialMenu.ts @@ -254,6 +254,8 @@ export class RadialMenu implements Layer { new SendAllianceRequestIntentEvent(myPlayer, other) ) }) + } + if (myPlayer.canTarget(other)) { this.activateMenuElement(Slot.Target, "#c74848", targetIcon, () => { this.eventBus.emit( new SendTargetPlayerIntentEvent(other.id()) diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 6d17c24bb..7e2c86e71 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -11,7 +11,7 @@ export class DefaultConfig implements Config { return 10 * 10 } targetCooldown(): Tick { - return 30 * 10 + return 15 * 10 } allianceRequestCooldown(): Tick { return 30 * 10 diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index bb54a4178..0061058af 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -237,4 +237,8 @@ export class BrokeAllianceEvent implements GameEvent { export class AllianceExpiredEvent implements GameEvent { constructor(public readonly player1: Player, public readonly player2: Player) { } +} + +export class TargetPlayerEvent implements GameEvent { + constructor(public readonly player: Player, public readonly target: Player) { } } \ No newline at end of file diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 89d762fc3..bd24fa019 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -34,7 +34,7 @@ export class GameImpl implements MutableGame { allianceRequests: AllianceRequestImpl[] = [] alliances_: AllianceImpl[] = [] - constructor(terrainMap: TerrainMap, private eventBus: EventBus, private _config: Config) { + constructor(terrainMap: TerrainMap, public eventBus: EventBus, private _config: Config) { this._terraNullius = new TerraNulliusImpl(this) this._width = terrainMap.width(); this._height = terrainMap.height(); diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 4e2543604..13483f085 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -1,4 +1,4 @@ -import {MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, MutableGame, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick} from "./Game"; +import {MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, MutableGame, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick, TargetPlayerEvent} from "./Game"; import {ClientID} from "../Schemas"; import {simpleHash} from "../Util"; import {CellString, GameImpl} from "./GameImpl"; @@ -179,11 +179,12 @@ export class PlayerImpl implements MutablePlayer { } canTarget(other: Player): boolean { + if (this.isAlliedWith(other)) { + return false + } for (const t of this.targets_) { - if (t.target == other) { - if (this.gs.ticks() - t.tick < this.gs.config().targetCooldown()) { - return false - } + if (this.gs.ticks() - t.tick < this.gs.config().targetCooldown()) { + return false } } return true @@ -191,6 +192,7 @@ export class PlayerImpl implements MutablePlayer { target(other: Player): void { this.targets_.push({tick: this.gs.ticks(), target: other}) + this.gs.eventBus.emit(new TargetPlayerEvent(this, other)) } targets(): PlayerImpl[] {