From 4f4b6adb80a883a4e4732ee55f0aa8545551cd50 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 8 Feb 2025 19:34:16 -0800 Subject: [PATCH] add 5 second player immunity to prevent spawn kills --- src/client/graphics/layers/RadialMenu.ts | 45 ------------------------ src/core/configuration/Config.ts | 5 +-- src/core/configuration/DefaultConfig.ts | 3 ++ src/core/execution/AttackExecution.ts | 31 +++++++++++----- src/core/game/PlayerImpl.ts | 9 +++++ 5 files changed, 37 insertions(+), 56 deletions(-) diff --git a/src/client/graphics/layers/RadialMenu.ts b/src/client/graphics/layers/RadialMenu.ts index 88b7bc216..b5818e790 100644 --- a/src/client/graphics/layers/RadialMenu.ts +++ b/src/client/graphics/layers/RadialMenu.ts @@ -331,26 +331,6 @@ export class RadialMenu implements Layer { }); } this.activateMenuElement(Slot.Close, "#DC2626", xIcon, () => {}); - // const canSendEmojiToPlayer = - // this.g.hasOwner(tile) && - // this.g.ownerID(tile) != myPlayer.smallID() && - // actions.interaction?.canSendEmoji; - // const canSendEmojiToAllPlayers = - // this.g.ownerID(tile) == myPlayer.smallID() && - // actions.canSendEmojiAllPlayers; - // if (canSendEmojiToPlayer || canSendEmojiToAllPlayers) { - // this.activateMenuElement(Slot.Emoji, "#00a6a4", emojiIcon, () => { - // const target = - // this.g.owner(tile) == myPlayer - // ? AllPlayers - // : (this.g.owner(tile) as PlayerView); - // this.emojiTable.onEmojiClicked = (emoji: string) => { - // this.emojiTable.hideTable(); - // this.eventBus.emit(new SendEmojiIntentEvent(target, emoji)); - // }; - // this.emojiTable.showTable(); - // }); - // } if (actions.canBoat) { this.activateMenuElement(Slot.Boat, "#3f6ab1", boatIcon, () => { @@ -370,31 +350,6 @@ export class RadialMenu implements Layer { if (!this.g.hasOwner(tile)) { return; } - const other = this.g.owner(tile) as PlayerView; - - // if (actions?.interaction.canDonate) { - // this.activateMenuElement(Slot.Target, "#53ac75", donateIcon, () => { - // this.eventBus.emit(new SendDonateIntentEvent(myPlayer, other, null)); - // }); - // } - - // if (actions?.interaction.canTarget) { - // this.activateMenuElement(Slot.Target, "#c74848", targetIcon, () => { - // this.eventBus.emit(new SendTargetPlayerIntentEvent(other.id())); - // }); - // } - - // if (actions?.interaction.canSendAllianceRequest) { - // this.activateMenuElement(Slot.Alliance, "#53ac75", allianceIcon, () => { - // this.eventBus.emit(new SendAllianceRequestIntentEvent(myPlayer, other)); - // }); - // } - - // if (actions?.interaction.canBreakAlliance) { - // this.activateMenuElement(Slot.Alliance, "#c74848", traitorIcon, () => { - // this.eventBus.emit(new SendBreakAllianceIntentEvent(myPlayer, other)); - // }); - // } } private onPointerUp(event: MouseUpEvent) { diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts index 6f1bae2dc..1b527c327 100644 --- a/src/core/configuration/Config.ts +++ b/src/core/configuration/Config.ts @@ -63,6 +63,7 @@ export interface ServerConfig { } export interface Config { + spawnImmunityDuration(): Tick; serverConfig(): ServerConfig; gameConfig(): GameConfig; theme(): Theme; @@ -79,14 +80,14 @@ export interface Config { attckTroops: number, attacker: Player, defender: Player | TerraNullius, - numAdjacentTilesWithEnemy: number, + numAdjacentTilesWithEnemy: number ): number; attackLogic( gm: Game, attackTroops: number, attacker: Player, defender: Player | TerraNullius, - tileToConquer: TileRef, + tileToConquer: TileRef ): { attackerTroopLoss: number; defenderTroopLoss: number; diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 5d7d75fe6..e697ac12b 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -36,6 +36,9 @@ export class DefaultConfig implements Config { private _serverConfig: ServerConfig, private _gameConfig: GameConfig ) {} + spawnImmunityDuration(): Tick { + return 5 * 10; + } gameConfig(): GameConfig { return this._gameConfig; diff --git a/src/core/execution/AttackExecution.ts b/src/core/execution/AttackExecution.ts index 1fe8b404e..d082784bb 100644 --- a/src/core/execution/AttackExecution.ts +++ b/src/core/execution/AttackExecution.ts @@ -42,7 +42,7 @@ export class AttackExecution implements Execution { private _ownerID: PlayerID, private _targetID: PlayerID | null, private sourceTile: TileRef | null, - private removeTroops: boolean = true, + private removeTroops: boolean = true ) {} public targetID(): PlayerID { @@ -69,6 +69,17 @@ export class AttackExecution implements Execution { throw new Error(`Player ${this._owner} cannot attack itself`); } + if ( + this.target.isPlayer() && + this.mg.config().numSpawnPhaseTurns() + + this.mg.config().spawnImmunityDuration() > + this.mg.ticks() + ) { + console.warn("cannot attack player during immunity phase"); + this.active = false; + return; + } + if (this.troops == null) { this.troops = this.mg.config().attackAmount(this._owner, this.target); } @@ -117,7 +128,7 @@ export class AttackExecution implements Execution { mg.displayMessage( `You are being attacked by ${this._owner.displayName()}`, MessageType.ERROR, - this._targetID, + this._targetID ); } if (this.sourceTile != null) { @@ -165,7 +176,7 @@ export class AttackExecution implements Execution { this.troops, this._owner, this.target, - this.border.size + this.random.nextInt(0, 5), + this.border.size + this.random.nextInt(0, 5) ); // consolex.log(`num tiles per tick: ${numTilesPerTick}`) // consolex.log(`num execs: ${this.mg.executions().length}`) @@ -201,7 +212,7 @@ export class AttackExecution implements Execution { this.troops, this._owner, this.target, - tileToConquer, + tileToConquer ); numTilesPerTick -= tilesPerTickUsed; this.troops -= attackerTroopLoss; @@ -242,8 +253,8 @@ export class AttackExecution implements Execution { new TileContainer( neighbor, dist / 100 + this.random.nextInt(0, 2) - numOwnedByMe + mag, - this.mg.ticks(), - ), + this.mg.ticks() + ) ); } } @@ -252,9 +263,11 @@ export class AttackExecution implements Execution { if (this.target.isPlayer() && this.target.numTilesOwned() < 100) { const gold = this.target.gold(); this.mg.displayMessage( - `Conquered ${this.target.displayName()} received ${renderNumber(gold)} gold`, + `Conquered ${this.target.displayName()} received ${renderNumber( + gold + )} gold`, MessageType.SUCCESS, - this._owner.id(), + this._owner.id() ); this.target.removeGold(gold); this._owner.addGold(gold); @@ -293,6 +306,6 @@ class TileContainer { constructor( public readonly tile: TileRef, public readonly priority: number, - public readonly tick: number, + public readonly tick: number ) {} } diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 42df4622d..2407dbef1 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -756,6 +756,15 @@ export class PlayerImpl implements Player { } public canAttack(tile: TileRef): boolean { + if ( + this.mg.hasOwner(tile) && + this.mg.config().numSpawnPhaseTurns() + + this.mg.config().spawnImmunityDuration() > + this.mg.ticks() + ) { + return false; + } + if (this.mg.owner(tile) == this) { return false; }