From a81dbda0716cd60008c45d047bcfc4dd86f1cf8a Mon Sep 17 00:00:00 2001 From: evanpelle Date: Sat, 19 Oct 2024 10:04:40 -0700 Subject: [PATCH] add nuke button --- resources/images/NukeIconWhite.png | Bin 0 -> 17503 bytes src/client/Transport.ts | 20 ++++++++++++++++++ .../graphics/layers/radial/RadialMenu.ts | 13 +++++++++--- src/client/index.html | 2 +- src/core/Util.ts | 4 ++++ src/core/execution/NukeExecution.ts | 12 ++++++++--- 6 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 resources/images/NukeIconWhite.png diff --git a/resources/images/NukeIconWhite.png b/resources/images/NukeIconWhite.png new file mode 100644 index 0000000000000000000000000000000000000000..625e7768e2d89b20663ad2aaa31e451378130e9d GIT binary patch literal 17503 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 literal 0 HcmV?d00001 diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 8ac43e989..dfaa72d5f 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -67,6 +67,14 @@ export class SendDonateIntentEvent implements GameEvent { ) { } } +export class SendNukeIntentEvent implements GameEvent { + constructor( + public readonly sender: Player, + public readonly cell: Cell, + public readonly magnitude: number | null, + ) { } +} + export class Transport { private socket: WebSocket @@ -97,6 +105,7 @@ export class Transport { this.eventBus.on(SendTargetPlayerIntentEvent, (e) => this.onSendTargetPlayerIntent(e)) this.eventBus.on(SendEmojiIntentEvent, (e) => this.onSendEmojiIntent(e)) this.eventBus.on(SendDonateIntentEvent, (e) => this.onSendDonateIntent(e)) + this.eventBus.on(SendNukeIntentEvent, (e) => this.onSendNukeIntent(e)) } connect(onconnect: () => void, onmessage: (message: ServerMessage) => void) { @@ -276,6 +285,17 @@ export class Transport { }) } + private onSendNukeIntent(event: SendNukeIntentEvent) { + this.sendIntent({ + type: "nuke", + clientID: this.clientID, + sender: event.sender.id(), + x: event.cell.x, + y: event.cell.y, + magnitude: event.magnitude, + }) + } + private sendIntent(intent: Intent) { if (this.isLocal || this.socket.readyState === WebSocket.OPEN) { const msg = ClientIntentMessageSchema.parse({ diff --git a/src/client/graphics/layers/radial/RadialMenu.ts b/src/client/graphics/layers/radial/RadialMenu.ts index a2d373192..3edcbcd47 100644 --- a/src/client/graphics/layers/radial/RadialMenu.ts +++ b/src/client/graphics/layers/radial/RadialMenu.ts @@ -3,7 +3,7 @@ import {AllPlayers, Cell, Game, Player} from "../../../../core/game/Game"; import {ClientID} from "../../../../core/Schemas"; import {and, bfs, dist, manhattanDist, manhattanDistWrapped, sourceDstOceanShore} from "../../../../core/Util"; import {ContextMenuEvent, MouseUpEvent} from "../../../InputHandler"; -import {SendAllianceRequestIntentEvent, SendAttackIntentEvent, SendBoatAttackIntentEvent, SendBreakAllianceIntentEvent, SendDonateIntentEvent, SendEmojiIntentEvent, SendSpawnIntentEvent, SendTargetPlayerIntentEvent} from "../../../Transport"; +import {SendAllianceRequestIntentEvent, SendAttackIntentEvent, SendBoatAttackIntentEvent, SendBreakAllianceIntentEvent, SendDonateIntentEvent, SendEmojiIntentEvent, SendNukeIntentEvent, SendSpawnIntentEvent, SendTargetPlayerIntentEvent} from "../../../Transport"; import {TransformHandler} from "../../TransformHandler"; import {Layer} from "../Layer"; import * as d3 from 'd3'; @@ -15,6 +15,7 @@ import targetIcon from '../../../../../resources/images/TargetIconWhite.png'; import emojiIcon from '../../../../../resources/images/EmojiIconWhite.png'; import disabledIcon from '../../../../../resources/images/DisabledIcon.png'; import donateIcon from '../../../../../resources/images/DonateIconWhite.png'; +import nukeIcon from '../../../../../resources/images/NukeIconWhite.png'; import {EmojiTable} from "./EmojiTable"; @@ -22,7 +23,8 @@ enum Slot { Alliance, Boat, Target, - Emoji + Emoji, + Nuke, } export class RadialMenu implements Layer { @@ -35,6 +37,7 @@ export class RadialMenu implements Layer { [Slot.Boat, {name: "boat", disabled: true, action: () => { }, color: null, icon: null}], [Slot.Target, {name: "target", disabled: true, action: () => { }}], [Slot.Emoji, {name: "emoji", disabled: true, action: () => { }}], + [Slot.Nuke, {name: "nuke", disabled: true, action: () => { }}], ]); private readonly menuSize = 190; @@ -225,10 +228,14 @@ export class RadialMenu implements Layer { return } + this.activateMenuElement(Slot.Nuke, "#ebe250", nukeIcon, () => { + this.eventBus.emit(new SendNukeIntentEvent(myPlayer, this.clickedCell, null)) + }) + if (tile.hasOwner()) { const target = tile.owner() == myPlayer ? AllPlayers : (tile.owner() as Player) if (myPlayer.canSendEmoji(target)) { - this.activateMenuElement(Slot.Emoji, "#ebe250", emojiIcon, () => { + this.activateMenuElement(Slot.Emoji, "#00a6a4", emojiIcon, () => { this.emojiTable.onEmojiClicked = (emoji: string) => { this.emojiTable.hideTable() this.eventBus.emit(new SendEmojiIntentEvent(target, emoji)) diff --git a/src/client/index.html b/src/client/index.html index d77aea1ba..eafa93a49 100644 --- a/src/client/index.html +++ b/src/client/index.html @@ -28,7 +28,7 @@

OpenFront.io

-

(v0.7.0)

+

(v0.7.1)

diff --git a/src/core/Util.ts b/src/core/Util.ts index 7e8f2cf9f..7d353c867 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -7,6 +7,10 @@ export function manhattanDist(c1: Cell, c2: Cell): number { return Math.abs(c1.x - c2.x) + Math.abs(c1.y - c2.y); } +export function euclideanDist(c1: Cell, c2: Cell): number { + return Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2)); +} + export function manhattanDistWrapped(c1: Cell, c2: Cell, width: number): number { // Calculate x distance let dx = Math.abs(c1.x - c2.x); diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts index 424e095ad..5f9463528 100644 --- a/src/core/execution/NukeExecution.ts +++ b/src/core/execution/NukeExecution.ts @@ -1,5 +1,6 @@ import {Cell, Execution, MutableGame, MutablePlayer, PlayerID, Tile} from "../game/Game"; -import {bfs, dist} from "../Util"; +import {PseudoRandom} from "../PseudoRandom"; +import {bfs, dist, euclideanDist, manhattanDist} from "../Util"; export class NukeExecution implements Execution { @@ -22,12 +23,17 @@ export class NukeExecution implements Execution { this.mg = mg this.sender = mg.player(this.senderID) if (this.magnitude == null) { - this.magnitude = 50 + this.magnitude = 70 } + const rand = new PseudoRandom(mg.ticks()) const tile = mg.tile(this.cell) - this.toDestroy = bfs(tile, dist(tile, this.magnitude)) + this.toDestroy = bfs(tile, (n: Tile) => { + const d = euclideanDist(tile.cell(), n.cell()) + return (d <= this.magnitude || rand.chance(2)) && d <= this.magnitude + 30 + }) } + tick(ticks: number): void { for (const tile of this.toDestroy) { const owner = tile.owner()