From a5cdd23c00d502db63707937afd3d01adcaf8fe3 Mon Sep 17 00:00:00 2001 From: Rj Manhas <117674421+RjManhas@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:34:04 -0700 Subject: [PATCH] feat: added retaliate button (#2426) If this PR fixes an issue, link it below. If not, delete these two lines. Resolves #495 ## Description: Adds a button to quickly retaliate against a incoming attack image ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] 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: notifxy (1379678982676676639) --- resources/lang/en.json | 1 + src/client/graphics/layers/EventsDisplay.ts | 61 +++++++++++++++------ 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index 5f6dac416..6f941c61c 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -575,6 +575,7 @@ }, "events_display": { "retreating": "retreating", + "retaliate": "Retaliate", "boat": "Boat", "alliance_request_status": "{name} {status} your alliance request", "alliance_accepted": "accepted", diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index 803f81e3f..c8276491e 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -35,6 +35,7 @@ import { CancelBoatIntentEvent, SendAllianceExtensionIntentEvent, SendAllianceReplyIntentEvent, + SendAttackIntentEvent, } from "../../Transport"; import { Layer } from "./Layer"; @@ -736,28 +737,54 @@ export class EventsDisplay extends LitElement implements Layer { } } + private handleRetaliate(attack: AttackUpdate) { + const attacker = this.game.playerBySmallID(attack.attackerID) as PlayerView; + if (!attacker) return; + + const myPlayer = this.game.myPlayer(); + if (!myPlayer) return; + + // Launch counterattack with the same number of troops as the incoming attack + this.eventBus.emit(new SendAttackIntentEvent(attacker.id(), attack.troops)); + } + private renderIncomingAttacks() { return html` ${this.incomingAttacks.length > 0 ? html` - ${this.incomingAttacks.map( - (attack) => html` - ${this.renderButton({ - content: html` - ${renderTroops(attack.troops)} - ${( - this.game.playerBySmallID(attack.attackerID) as PlayerView - )?.name()} - ${attack.retreating - ? `(${translateText("events_display.retreating")}...)` +
+ ${this.incomingAttacks.map( + (attack) => html` +
+ ${this.renderButton({ + content: html` + ${renderTroops(attack.troops)} + ${( + this.game.playerBySmallID( + attack.attackerID, + ) as PlayerView + )?.name()} + ${attack.retreating + ? `(${translateText("events_display.retreating")}...)` + : ""} + `, + onClick: () => this.attackWarningOnClick(attack), + className: "text-left text-red-400", + translate: false, + })} + ${!attack.retreating + ? this.renderButton({ + content: translateText("events_display.retaliate"), + onClick: () => this.handleRetaliate(attack), + className: + "inline-block px-3 py-1 text-white rounded text-md md:text-sm cursor-pointer transition-colors duration-300 bg-red-600 hover:bg-red-700", + translate: true, + }) : ""} - `, - onClick: () => this.attackWarningOnClick(attack), - className: "text-left text-red-400", - translate: false, - })} - `, - )} +
+ `, + )} +
` : ""} `;