mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 03:00:43 +00:00
port spawns on coast
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { Config } from "../core/configuration/Config"
|
import { Config } from "../core/configuration/Config"
|
||||||
import { EventBus, GameEvent } from "../core/EventBus"
|
import { EventBus, GameEvent } from "../core/EventBus"
|
||||||
import { AllianceRequest, AllPlayers, Cell, Item, Player, PlayerID, PlayerType, Tile, UnitType } from "../core/game/Game"
|
import { AllianceRequest, AllPlayers, Cell, BuildItem, Player, PlayerID, PlayerType, Tile, UnitType } from "../core/game/Game"
|
||||||
import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, BuildUnitIntentSchema, GameID, Intent, ServerMessage, ServerMessageSchema } from "../core/Schemas"
|
import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, BuildUnitIntentSchema, GameID, Intent, ServerMessage, ServerMessageSchema } from "../core/Schemas"
|
||||||
import { LocalServer } from "./LocalServer"
|
import { LocalServer } from "./LocalServer"
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { ControlPanel } from "./layers/ControlPanel";
|
|||||||
import { UIState } from "./UIState";
|
import { UIState } from "./UIState";
|
||||||
import { BuildMenu } from "./layers/radial/BuildMenu";
|
import { BuildMenu } from "./layers/radial/BuildMenu";
|
||||||
import { UnitLayer } from "./layers/UnitLayer";
|
import { UnitLayer } from "./layers/UnitLayer";
|
||||||
|
import { BuildValidator } from "../../core/game/BuildValidator";
|
||||||
|
|
||||||
|
|
||||||
export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus: EventBus, clientID: ClientID): GameRenderer {
|
export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus: EventBus, clientID: ClientID): GameRenderer {
|
||||||
@@ -33,7 +34,7 @@ export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus:
|
|||||||
}
|
}
|
||||||
buildMenu.game = game
|
buildMenu.game = game
|
||||||
buildMenu.eventBus = eventBus
|
buildMenu.eventBus = eventBus
|
||||||
buildMenu.init()
|
buildMenu.buildValidator = new BuildValidator(game)
|
||||||
|
|
||||||
const leaderboard = document.querySelector('leader-board') as Leaderboard;
|
const leaderboard = document.querySelector('leader-board') as Leaderboard;
|
||||||
if (!emojiTable || !(leaderboard instanceof Leaderboard)) {
|
if (!emojiTable || !(leaderboard instanceof Leaderboard)) {
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import { LitElement, html, css } from 'lit';
|
import { LitElement, html, css } from 'lit';
|
||||||
import { customElement, state } from 'lit/decorators.js';
|
import { customElement, state } from 'lit/decorators.js';
|
||||||
import { EventBus } from '../../../../core/EventBus';
|
import { EventBus } from '../../../../core/EventBus';
|
||||||
import { Cell, Game, Item, BuildItems, Player, UnitType } from '../../../../core/game/Game';
|
import { Cell, Game, BuildItem, BuildItems, Player, UnitType } from '../../../../core/game/Game';
|
||||||
import { BuildUnitIntentEvent as BuildItemIntentEvent, BuildUnitIntentEvent, SendNukeIntentEvent } from '../../../Transport';
|
import { BuildUnitIntentEvent, SendNukeIntentEvent } from '../../../Transport';
|
||||||
import nukeIcon from '../../../../../resources/images/NukeIconWhite.svg';
|
import nukeIcon from '../../../../../resources/images/NukeIconWhite.svg';
|
||||||
import destroyerIcon from '../../../../../resources/images/DestroyerIconWhite.svg';
|
import destroyerIcon from '../../../../../resources/images/DestroyerIconWhite.svg';
|
||||||
import goldCoinIcon from '../../../../../resources/images/GoldCoinIcon.svg';
|
import goldCoinIcon from '../../../../../resources/images/GoldCoinIcon.svg';
|
||||||
import portIcon from '../../../../../resources/images/PortIcon.svg';
|
import portIcon from '../../../../../resources/images/PortIcon.svg';
|
||||||
import { renderNumber } from '../../Utils';
|
import { renderNumber } from '../../Utils';
|
||||||
import { ContextMenuEvent } from '../../../InputHandler';
|
import { BuildValidator } from '../../../../core/game/BuildValidator';
|
||||||
|
|
||||||
interface BuildItem {
|
interface BuildItemDisplay {
|
||||||
item: Item
|
item: BuildItem
|
||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildTable: BuildItem[][] = [
|
const buildTable: BuildItemDisplay[][] = [
|
||||||
[
|
[
|
||||||
{ item: BuildItems.Nuke, icon: nukeIcon },
|
{ item: BuildItems.Nuke, icon: nukeIcon },
|
||||||
{ item: BuildItems.Destroyer, icon: destroyerIcon },
|
{ item: BuildItems.Destroyer, icon: destroyerIcon },
|
||||||
@@ -27,6 +27,7 @@ const buildTable: BuildItem[][] = [
|
|||||||
export class BuildMenu extends LitElement {
|
export class BuildMenu extends LitElement {
|
||||||
public game: Game;
|
public game: Game;
|
||||||
public eventBus: EventBus;
|
public eventBus: EventBus;
|
||||||
|
public buildValidator: BuildValidator;
|
||||||
|
|
||||||
private myPlayer: Player;
|
private myPlayer: Player;
|
||||||
private clickedCell: Cell;
|
private clickedCell: Cell;
|
||||||
@@ -145,19 +146,14 @@ export class BuildMenu extends LitElement {
|
|||||||
@state()
|
@state()
|
||||||
private _hidden = true;
|
private _hidden = true;
|
||||||
|
|
||||||
private canBuild(item: BuildItem): boolean {
|
private canBuild(item: BuildItemDisplay): boolean {
|
||||||
if (!this.myPlayer || this.myPlayer.gold() < item.item.cost) {
|
if(this.myPlayer == null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
switch (item.item) {
|
return this.buildValidator.canBuild(this.myPlayer, this.game.tile(this.clickedCell), item.item)
|
||||||
case BuildItems.Destroyer:
|
|
||||||
return this.myPlayer.units(UnitType.Port).length > 0
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onBuildSelected = (item: BuildItem) => {
|
public onBuildSelected = (item: BuildItemDisplay) => {
|
||||||
switch (item.item) {
|
switch (item.item) {
|
||||||
case BuildItems.Nuke:
|
case BuildItems.Nuke:
|
||||||
this.eventBus.emit(new SendNukeIntentEvent(this.myPlayer, this.clickedCell, null))
|
this.eventBus.emit(new SendNukeIntentEvent(this.myPlayer, this.clickedCell, null))
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { AllPlayers, Cell, Execution, MutableGame, MutablePlayer, PlayerID, UnitType } from "../game/Game";
|
import { BuildValidator } from "../game/BuildValidator";
|
||||||
|
import { AllPlayers, BuildItem, BuildItems, Cell, Execution, MutableGame, MutablePlayer, PlayerID, UnitType } from "../game/Game";
|
||||||
|
import { bfs, dist, manhattanDist } from "../Util";
|
||||||
|
|
||||||
export class PortExecution implements Execution {
|
export class PortExecution implements Execution {
|
||||||
|
|
||||||
@@ -18,7 +20,23 @@ export class PortExecution implements Execution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tick(ticks: number): void {
|
tick(ticks: number): void {
|
||||||
this.player.addUnit(UnitType.Port, 0, this.mg.tile(this.cell))
|
const tile = this.mg.tile(this.cell)
|
||||||
|
if (!new BuildValidator(this.mg).canBuild(this.player, tile, BuildItems.Port)) {
|
||||||
|
console.warn(`player ${this.player} cannot build port at ${this.cell}`)
|
||||||
|
this.active = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const spawns = Array.from(bfs(tile, dist(tile, 20)))
|
||||||
|
.filter(t => t.isOceanShore() && t.owner() == this.player)
|
||||||
|
.sort((a, b) => manhattanDist(a.cell(), tile.cell()) - manhattanDist(b.cell(), tile.cell()))
|
||||||
|
|
||||||
|
if (spawns.length == 0) {
|
||||||
|
console.warn(`cannot find spawn for port`)
|
||||||
|
this.active = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.player.addUnit(UnitType.Port, 0, spawns[0])
|
||||||
this.active = false
|
this.active = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { bfs, dist, manhattanDist } from "../Util";
|
||||||
|
import { BuildItem, BuildItems, Game, Player, Tile, UnitType } from "./Game";
|
||||||
|
|
||||||
|
export class BuildValidator {
|
||||||
|
constructor(private game: Game) { }
|
||||||
|
|
||||||
|
canBuild(player: Player, tile: Tile, item: BuildItem): boolean {
|
||||||
|
if (!player.isAlive() || player.gold() < item.cost) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch (item) {
|
||||||
|
case BuildItems.Nuke:
|
||||||
|
return true
|
||||||
|
case BuildItems.Port:
|
||||||
|
return this.canBuildPort(player, tile)
|
||||||
|
case BuildItems.Destroyer:
|
||||||
|
return this.canBuildDestroyer(player, tile)
|
||||||
|
default:
|
||||||
|
throw Error(`item ${item.type} not supported`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canBuildPort(player: Player, tile: Tile): boolean {
|
||||||
|
return Array.from(bfs(tile, dist(tile, 20)))
|
||||||
|
.filter(t => t.owner() == player && t.isOceanShore()).length > 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
canBuildDestroyer(player: Player, tile: Tile): boolean {
|
||||||
|
return player.units(UnitType.Port)
|
||||||
|
.filter(u => manhattanDist(u.tile().cell(), tile.cell()) < this.game.config().boatMaxDistance()).length > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,16 +32,17 @@ export enum UnitType {
|
|||||||
Nuke = "Nuke",
|
Nuke = "Nuke",
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Item {
|
export class BuildItem {
|
||||||
constructor(public readonly type: UnitType,
|
constructor(
|
||||||
|
public readonly type: UnitType,
|
||||||
public readonly cost: Gold
|
public readonly cost: Gold
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BuildItems = {
|
export const BuildItems = {
|
||||||
Nuke: new Item(UnitType.Nuke, 1_000_000),
|
Nuke: new BuildItem(UnitType.Nuke, 1_000_000),
|
||||||
Destroyer: new Item(UnitType.Destroyer, 10),
|
Destroyer: new BuildItem(UnitType.Destroyer, 10),
|
||||||
Port: new Item(UnitType.Port, 0)
|
Port: new BuildItem(UnitType.Port, 0)
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export class Nation {
|
export class Nation {
|
||||||
|
|||||||
Reference in New Issue
Block a user