Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions resources/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
"gold": "Gold",
"troops": "Troops",
"traitor": "Traitor",
"alliance_time_remaining": "Time Remaining",
"embargo": "Stopped trading with you",
"nuke": "Nukes sent by them to you",
"start_trade": "Start trading",
Expand Down
44 changes: 44 additions & 0 deletions src/client/graphics/layers/PlayerPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export class PlayerPanel extends LitElement implements Layer {
@state()
private isVisible: boolean = false;

@state()
private allianceExpiryText: string | null = null;

public show(actions: PlayerActions, tile: TileRef) {
this.actions = actions;
this.tile = tile;
Expand Down Expand Up @@ -170,11 +173,38 @@ export class PlayerPanel extends LitElement implements Layer {
const myPlayer = this.g.myPlayer();
if (myPlayer !== null && myPlayer.isAlive()) {
this.actions = await myPlayer.actions(this.tile);

if (this.actions?.interaction?.allianceCreatedAtTick !== undefined) {
const createdAt = this.actions.interaction.allianceCreatedAtTick;
const durationTicks = this.g.config().allianceDuration();
const expiryTick = createdAt + durationTicks;
const remainingTicks = expiryTick - this.g.ticks();

if (remainingTicks > 0) {
const remainingSeconds = Math.max(
0,
Math.floor(remainingTicks / 10),
); // 10 ticks per second
this.allianceExpiryText = this.formatDuration(remainingSeconds);
}
} else {
this.allianceExpiryText = null;
}
this.requestUpdate();
}
}
}

private formatDuration(totalSeconds: number): string {
if (totalSeconds <= 0) return "0s";
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
let time = "";
if (minutes > 0) time += `${minutes}m `;
time += `${seconds}s`;
return time.trim();
}

getTotalNukesSent(otherId: PlayerID): number {
const stats = this.g.player(otherId).stats();
if (!stats) {
Expand Down Expand Up @@ -309,6 +339,20 @@ export class PlayerPanel extends LitElement implements Layer {
</div>
</div>

${this.allianceExpiryText !== null
? html`
<div class="flex flex-col gap-1">
<div class="text-white text-opacity-80 text-sm px-2">
${translateText("player_panel.alliance_time_remaining")}
</div>
<div
class="bg-opacity-50 bg-gray-700 rounded p-2 text-white"
>
${this.allianceExpiryText}
</div>
</div>
`
: ""}
<!-- Stats -->
<div class="flex flex-col gap-1">
<div class="text-white text-opacity-80 text-sm px-2">
Expand Down
4 changes: 4 additions & 0 deletions src/core/GameRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ export class GameRunner {
canDonate: player.canDonate(other),
canEmbargo: !player.hasEmbargoAgainst(other),
};
const alliance = player.allianceWith(other as Player);
if (alliance) {
actions.interaction.allianceCreatedAtTick = alliance.createdAt();
}
}

return actions;
Expand Down
1 change: 1 addition & 0 deletions src/core/game/Game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ export interface PlayerInteraction {
canTarget: boolean;
canDonate: boolean;
canEmbargo: boolean;
allianceCreatedAtTick?: Tick;
}

export interface EmojiMessage {
Expand Down
Loading