Files
OpenFrontIO/src/client/graphics/layers/PlayerActionHandler.ts
T
Mattia Migliorini 90204f6628 Add alliance renewal action to Radial Menu (#3148)
## Description:

The following PR replaces the (disabled) alliance request button with an
alliance extension/renewal button when the alliance with the target
player is expiring.

Agreeing to renewal via radial menu also hides the message in the
EventsDisplay.

<img width="369" height="364" alt="image"
src="https://github.com/user-attachments/assets/d8040f5c-ad7b-47d0-852f-925ecbf273a8"
/>


https://github.com/user-attachments/assets/aa589edf-6505-46bf-88a3-aa4c2df9137f

Icon size adjusted:

<img width="294" height="252" alt="image"
src="https://github.com/user-attachments/assets/7ca63500-b1fb-427b-965c-cf121a5213da"
/>

## 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:

deshack_82603

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-02-19 19:47:57 -06:00

97 lines
2.7 KiB
TypeScript

import { EventBus } from "../../../core/EventBus";
import { TileRef } from "../../../core/game/GameMap";
import { PlayerView } from "../../../core/game/GameView";
import {
SendAllianceExtensionIntentEvent,
SendAllianceRequestIntentEvent,
SendAttackIntentEvent,
SendBoatAttackIntentEvent,
SendBreakAllianceIntentEvent,
SendDeleteUnitIntentEvent,
SendDonateGoldIntentEvent,
SendDonateTroopsIntentEvent,
SendEmbargoIntentEvent,
SendEmojiIntentEvent,
SendSpawnIntentEvent,
SendTargetPlayerIntentEvent,
} from "../../Transport";
import { UIState } from "../UIState";
export class PlayerActionHandler {
constructor(
private eventBus: EventBus,
private uiState: UIState,
) {}
handleAttack(player: PlayerView, targetId: string | null) {
this.eventBus.emit(
new SendAttackIntentEvent(
targetId,
this.uiState.attackRatio * player.troops(),
),
);
}
handleBoatAttack(player: PlayerView, targetTile: TileRef) {
this.eventBus.emit(
new SendBoatAttackIntentEvent(
targetTile,
this.uiState.attackRatio * player.troops(),
),
);
}
async findBestTransportShipSpawn(
player: PlayerView,
tile: TileRef,
): Promise<TileRef | false> {
return await player.bestTransportShipSpawn(tile);
}
handleSpawn(tile: TileRef) {
this.eventBus.emit(new SendSpawnIntentEvent(tile));
}
handleAllianceRequest(player: PlayerView, recipient: PlayerView) {
this.eventBus.emit(new SendAllianceRequestIntentEvent(player, recipient));
}
handleExtendAlliance(recipient: PlayerView) {
this.eventBus.emit(new SendAllianceExtensionIntentEvent(recipient));
}
handleBreakAlliance(player: PlayerView, recipient: PlayerView) {
this.eventBus.emit(new SendBreakAllianceIntentEvent(player, recipient));
}
handleTargetPlayer(targetId: string | null) {
if (!targetId) return;
this.eventBus.emit(new SendTargetPlayerIntentEvent(targetId));
}
handleDonateGold(recipient: PlayerView) {
this.eventBus.emit(new SendDonateGoldIntentEvent(recipient, null));
}
handleDonateTroops(recipient: PlayerView, troops?: number) {
const amount = troops ?? null;
if (amount !== null && amount <= 0) {
return;
}
this.eventBus.emit(new SendDonateTroopsIntentEvent(recipient, amount));
}
handleEmbargo(recipient: PlayerView, action: "start" | "stop") {
this.eventBus.emit(new SendEmbargoIntentEvent(recipient, action));
}
handleEmoji(targetPlayer: PlayerView | "AllPlayers", emojiIndex: number) {
this.eventBus.emit(new SendEmojiIntentEvent(targetPlayer, emojiIndex));
}
handleDeleteUnit(unitId: number) {
this.eventBus.emit(new SendDeleteUnitIntentEvent(unitId));
}
}