mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 04:40:41 +00:00
adding destroyer
This commit is contained in:
@@ -175,7 +175,7 @@
|
|||||||
* add gold DONE 11/4/2024
|
* add gold DONE 11/4/2024
|
||||||
* add troop/worker slider DONE 11/4/2024
|
* add troop/worker slider DONE 11/4/2024
|
||||||
* create Unit layer DONE 11/9/2024
|
* create Unit layer DONE 11/9/2024
|
||||||
* create Unit interface
|
* create Unit interface DONE 11/10/2024
|
||||||
* add destroyer
|
* add destroyer
|
||||||
* NPC has relations
|
* NPC has relations
|
||||||
* use twitter emojis
|
* use twitter emojis
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
shape-rendering="geometricPrecision"
|
||||||
|
text-rendering="geometricPrecision"
|
||||||
|
image-rendering="optimizeQuality"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
viewBox="0 0 500 499.99999"
|
||||||
|
version="1.1"
|
||||||
|
id="svg44"
|
||||||
|
sodipodi:docname="Destroyer.svg"
|
||||||
|
width="500"
|
||||||
|
height="500"
|
||||||
|
inkscape:export-filename="warship-icon.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs48" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview46"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.2877175"
|
||||||
|
inkscape:cx="86.587311"
|
||||||
|
inkscape:cy="266.36276"
|
||||||
|
inkscape:window-width="1536"
|
||||||
|
inkscape:window-height="987"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg44" />
|
||||||
|
<path
|
||||||
|
d="M 5.8295895,247.16089 C 65.39826,256.02013 106.88513,262.31167 162.00809,266.85556 l 14.35936,-93.47237 c 5.31364,0 10.70442,-0.0538 16.15307,-0.12099 v -59.97127 h 17.56104 V 172.953 l 12.17026,-0.25542 v -34.25394 h 17.56104 v 33.94474 c 19.59584,-0.26887 39.07597,-0.2151 57.44707,1.0217 11.50485,1.3309 21.51493,6.54696 29.54807,16.89843 7.85955,10.13636 13.56858,24.99139 16.59668,45.68087 l 0.10608,0.73939 0.0193,0.79316 0.58827,39.24146 c 21.23526,0.68562 28.57406,1.27713 50.74475,1.80142 l 97.12095,2.33917 c 1.9673,0.0403 4.58072,2.67524 3.57778,4.98752 l -29.90488,68.79018 c -0.99329,2.28538 -1.64906,4.98752 -3.57778,4.98752 H 50.305987 c -2.237321,0 -43.357737,-96.22828 -48.0541823,-107.50734 -0.7811336,-1.86864 0.5496866,-5.4446 3.5777848,-5.00097 z M 108.38954,189.01793 H 98.5434 l -1.330822,-16.25314 c -0.125367,-1.41156 -0.858282,-2.58114 -1.861219,-2.58114 H 71.531605 c -1.002937,0 -1.735852,1.16958 -1.851576,2.58114 l -1.340464,16.25314 H 59.4385 c -1.40797,0 -2.218034,1.72077 -2.594136,3.60285 l -0.829351,4.18092 -43.12629,-9.90783 -1.475475,10.29769 41.438656,15.6213 -6.422654,32.73482 c 25.989569,3.45497 51.352302,6.42597 76.38715,9.00712 l -11.84237,-61.93402 c -0.35681,-1.90897 -1.20545,-3.60285 -2.58449,-3.60285 z m 283.25255,37.11739 h 9.8365 l 1.34046,-16.25314 c 0.11572,-1.41156 0.839,-2.58114 1.85158,-2.58114 h 23.81975 c 1.02222,0 1.7455,1.16958 1.86122,2.58114 l 1.34046,16.25314 h 8.90107 c 1.42726,0 2.21803,1.72077 2.58449,3.60285 l 0.82935,4.18092 36.30825,-7.34013 1.47547,10.29769 -34.62061,13.0536 4.45536,22.65222 -56.76238,-1.35779 -13.67466,-0.33608 7.85955,-41.15043 c 0.36646,-1.90897 1.16688,-3.60285 2.59414,-3.60285 z m -121.095,-21.68429 h 52.28774 c 4.69644,9.86749 8.04278,19.95009 9.04572,30.28811 h -61.33346 z m -35.60426,-0.0135 h 22.49857 v 31.0275 h -22.49857 z"
|
||||||
|
id="path42"
|
||||||
|
style="stroke-width:1.13861" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
shape-rendering="geometricPrecision"
|
||||||
|
text-rendering="geometricPrecision"
|
||||||
|
image-rendering="optimizeQuality"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
viewBox="0 0 500 499.99999"
|
||||||
|
version="1.1"
|
||||||
|
id="svg44"
|
||||||
|
sodipodi:docname="DestroyerIconWhite.svg"
|
||||||
|
width="500"
|
||||||
|
height="500"
|
||||||
|
inkscape:export-filename="warship-icon.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs48" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview46"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.2877175"
|
||||||
|
inkscape:cx="86.587311"
|
||||||
|
inkscape:cy="266.36276"
|
||||||
|
inkscape:window-width="1536"
|
||||||
|
inkscape:window-height="987"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg44" />
|
||||||
|
<path
|
||||||
|
d="M 5.8295895,247.16089 C 65.39826,256.02013 106.88513,262.31167 162.00809,266.85556 l 14.35936,-93.47237 c 5.31364,0 10.70442,-0.0538 16.15307,-0.12099 v -59.97127 h 17.56104 V 172.953 l 12.17026,-0.25542 v -34.25394 h 17.56104 v 33.94474 c 19.59584,-0.26887 39.07597,-0.2151 57.44707,1.0217 11.50485,1.3309 21.51493,6.54696 29.54807,16.89843 7.85955,10.13636 13.56858,24.99139 16.59668,45.68087 l 0.10608,0.73939 0.0193,0.79316 0.58827,39.24146 c 21.23526,0.68562 28.57406,1.27713 50.74475,1.80142 l 97.12095,2.33917 c 1.9673,0.0403 4.58072,2.67524 3.57778,4.98752 l -29.90488,68.79018 c -0.99329,2.28538 -1.64906,4.98752 -3.57778,4.98752 H 50.305987 c -2.237321,0 -43.357737,-96.22828 -48.0541823,-107.50734 -0.7811336,-1.86864 0.5496866,-5.4446 3.5777848,-5.00097 z M 108.38954,189.01793 H 98.5434 l -1.330822,-16.25314 c -0.125367,-1.41156 -0.858282,-2.58114 -1.861219,-2.58114 H 71.531605 c -1.002937,0 -1.735852,1.16958 -1.851576,2.58114 l -1.340464,16.25314 H 59.4385 c -1.40797,0 -2.218034,1.72077 -2.594136,3.60285 l -0.829351,4.18092 -43.12629,-9.90783 -1.475475,10.29769 41.438656,15.6213 -6.422654,32.73482 c 25.989569,3.45497 51.352302,6.42597 76.38715,9.00712 l -11.84237,-61.93402 c -0.35681,-1.90897 -1.20545,-3.60285 -2.58449,-3.60285 z m 283.25255,37.11739 h 9.8365 l 1.34046,-16.25314 c 0.11572,-1.41156 0.839,-2.58114 1.85158,-2.58114 h 23.81975 c 1.02222,0 1.7455,1.16958 1.86122,2.58114 l 1.34046,16.25314 h 8.90107 c 1.42726,0 2.21803,1.72077 2.58449,3.60285 l 0.82935,4.18092 36.30825,-7.34013 1.47547,10.29769 -34.62061,13.0536 4.45536,22.65222 -56.76238,-1.35779 -13.67466,-0.33608 7.85955,-41.15043 c 0.36646,-1.90897 1.16688,-3.60285 2.59414,-3.60285 z m -121.095,-21.68429 h 52.28774 c 4.69644,9.86749 8.04278,19.95009 9.04572,30.28811 h -61.33346 z m -35.60426,-0.0135 h 22.49857 v 31.0275 h -22.49857 z"
|
||||||
|
id="path42"
|
||||||
|
style="stroke-width:1.13861" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;stroke-width:0.776568"
|
||||||
|
d="M 46.706349,351.9808 C 42.004196,342.57569 31.558258,319.09983 15.001906,280.72927 4.2738049,255.8661 2.3933801,250.94457 3.0592429,249.47241 c 0.4346644,-0.961 1.4320088,-1.74728 2.2163209,-1.74728 0.7843122,0 15.7310272,2.08277 33.2149232,4.62839 55.538666,8.08629 122.159113,15.92117 123.550193,14.53008 0.23554,-0.23552 3.6233,-21.24116 7.52837,-46.67918 l 7.10013,-46.25095 7.95982,-0.001 7.95982,-0.001 V 143.66505 113.3789 h 8.54224 8.54225 v 29.89786 29.89786 h 6.60083 6.60082 v -17.08449 -17.08449 h 8.15396 8.15397 v 16.69621 16.6962 l 13.39579,0.0102 c 21.89937,0.0167 46.22637,1.33987 51.05934,2.77709 18.87306,5.61245 30.73872,21.45768 37.4049,49.94994 1.26524,5.40782 1.67375,10.89917 2.15857,29.0159 0.32889,12.29014 0.73487,22.48072 0.90216,22.64572 0.54568,0.53819 41.93742,1.93217 95.43373,3.21399 54.05235,1.29515 55.99853,1.44928 55.87254,4.42493 -0.0222,0.52405 -7.2771,17.55195 -16.12202,37.83978 l -16.08168,36.88697 -206.35685,0.19558 -206.356855,0.19559 -3.786166,-7.57298 z M 257.82051,220.15698 V 204.23734 H 246.172 234.52348 v 15.91964 15.91964 h 11.64852 11.64851 z m 74.1798,11.84265 c -0.98753,-6.42557 -3.63791,-15.80032 -6.09246,-21.54975 l -2.48647,-5.82426 -26.58789,-0.20434 -26.58789,-0.20434 v 15.54156 15.54155 h 31.13097 31.13098 z"
|
||||||
|
id="path370" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;stroke-width:0.776568"
|
||||||
|
d="m 107.94293,252.66328 c -5.33891,-0.60164 -20.99574,-2.48304 -34.792965,-4.18087 -13.797226,-1.69784 -25.366829,-3.08698 -25.710229,-3.08698 -0.343401,0 0.8512,-7.35153 2.654669,-16.33673 2.940969,-14.65242 3.149735,-16.40042 2.02491,-16.95453 -0.689767,-0.3398 -10.071533,-3.90876 -20.848367,-7.93102 -14.89771,-5.56031 -19.520201,-7.59241 -19.285331,-8.47806 0.169902,-0.64067 0.525567,-2.76568 0.790368,-4.72225 l 0.481454,-3.5574 19.580444,4.50115 c 10.769244,2.47564 20.492947,4.70513 21.608227,4.95443 1.844631,0.41233 2.069192,0.19808 2.486266,-2.37205 0.70519,-4.34557 1.657226,-5.01642 7.119029,-5.01642 h 4.842078 l 0.550514,-8.70006 c 0.302782,-4.78504 0.722598,-8.9785 0.932924,-9.31882 0.210326,-0.34031 6.104255,-0.61875 13.097618,-0.61875 14.76188,0 13.249343,-1.15028 14.040604,10.67781 l 0.532477,7.95982 h 5.664 5.664 l 0.80464,2.52384 c 0.80804,2.53444 11.74089,59.3751 11.74089,61.04166 0,1.06925 -1.42288,1.03009 -13.97822,-0.38477 z"
|
||||||
|
id="path372" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;stroke-width:0.776568"
|
||||||
|
d="m 416.88697,271.41698 c -18.65086,-0.4307 -34.15559,-1.02828 -34.45497,-1.32794 -0.53305,-0.53356 6.25145,-38.17574 7.4887,-41.54929 0.55729,-1.51951 1.26654,-1.7384 6.29062,-1.94141 l 5.66252,-0.22882 0.77657,-8.54225 c 0.42711,-4.69823 1.05929,-8.97906 1.40483,-9.51295 0.45782,-0.70738 3.87376,-0.97071 12.5919,-0.97071 10.68101,0 12.04305,0.14836 12.70426,1.38384 0.40734,0.76112 0.9915,5.12931 1.29815,9.7071 l 0.55754,8.32325 h 5.2935 5.29349 l 0.80874,2.91213 c 0.44481,1.60167 0.81069,3.35561 0.81307,3.89764 0.003,0.6267 0.64048,0.83439 1.75161,0.57047 4.27407,-1.01523 32.80247,-6.60367 33.71102,-6.60367 1.00175,0 1.31418,0.90275 2.17005,6.26999 l 0.44256,2.77543 -17.28817,6.44808 c -9.5085,3.54644 -17.34584,6.49096 -17.4163,6.54338 -0.0705,0.0524 0.89062,5.1332 2.13575,11.29063 1.24513,6.15743 2.17643,11.22747 2.06954,11.26676 -0.10688,0.0393 -15.45412,-0.28096 -34.10498,-0.71166 z"
|
||||||
|
id="path374" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.5 KiB |
@@ -1,5 +1,5 @@
|
|||||||
import { Executor } from "../core/execution/ExecutionManager";
|
import { Executor } from "../core/execution/ExecutionManager";
|
||||||
import { Cell, MutableGame, PlayerEvent, PlayerID, MutablePlayer, TileEvent, Player, Game, BoatEvent, Tile, PlayerType, GameMap, Difficulty } from "../core/game/Game";
|
import { Cell, MutableGame, PlayerEvent, PlayerID, MutablePlayer, TileEvent, Player, Game, UnitEvent, Tile, PlayerType, GameMap, Difficulty } from "../core/game/Game";
|
||||||
import { createGame } from "../core/game/GameImpl";
|
import { createGame } from "../core/game/GameImpl";
|
||||||
import { EventBus } from "../core/EventBus";
|
import { EventBus } from "../core/EventBus";
|
||||||
import { Config, getConfig } from "../core/configuration/Config";
|
import { Config, getConfig } from "../core/configuration/Config";
|
||||||
|
|||||||
+19
-2
@@ -1,7 +1,7 @@
|
|||||||
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, Player, PlayerID, PlayerType } from "../core/game/Game"
|
import { AllianceRequest, AllPlayers, Cell, Player, PlayerID, PlayerType, Tile } from "../core/game/Game"
|
||||||
import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, GameID, Intent, ServerMessage, ServerMessageSchema } from "../core/Schemas"
|
import { ClientID, ClientIntentMessageSchema, ClientJoinMessageSchema, ClientLeaveMessageSchema, CreateDestroyerIntent, GameID, Intent, ServerMessage, ServerMessageSchema } from "../core/Schemas"
|
||||||
import { LocalServer } from "./LocalServer"
|
import { LocalServer } from "./LocalServer"
|
||||||
|
|
||||||
|
|
||||||
@@ -47,6 +47,12 @@ export class SendBoatAttackIntentEvent implements GameEvent {
|
|||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SendCreateDestroyerIntentEvent implements GameEvent {
|
||||||
|
constructor(
|
||||||
|
public readonly cell: Cell,
|
||||||
|
) { }
|
||||||
|
}
|
||||||
|
|
||||||
export class SendTargetPlayerIntentEvent implements GameEvent {
|
export class SendTargetPlayerIntentEvent implements GameEvent {
|
||||||
constructor(
|
constructor(
|
||||||
public readonly targetID: PlayerID,
|
public readonly targetID: PlayerID,
|
||||||
@@ -115,6 +121,7 @@ export class Transport {
|
|||||||
this.eventBus.on(SendDonateIntentEvent, (e) => this.onSendDonateIntent(e))
|
this.eventBus.on(SendDonateIntentEvent, (e) => this.onSendDonateIntent(e))
|
||||||
this.eventBus.on(SendNukeIntentEvent, (e) => this.onSendNukeIntent(e))
|
this.eventBus.on(SendNukeIntentEvent, (e) => this.onSendNukeIntent(e))
|
||||||
this.eventBus.on(SendSetTargetTroopRatioEvent, (e) => this.onSendSetTargetTroopRatioEvent(e))
|
this.eventBus.on(SendSetTargetTroopRatioEvent, (e) => this.onSendSetTargetTroopRatioEvent(e))
|
||||||
|
this.eventBus.on(SendCreateDestroyerIntentEvent, (e) => this.onCreateDestroyerIntent(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(onconnect: () => void, onmessage: (message: ServerMessage) => void) {
|
connect(onconnect: () => void, onmessage: (message: ServerMessage) => void) {
|
||||||
@@ -314,6 +321,16 @@ export class Transport {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onCreateDestroyerIntent(event: SendCreateDestroyerIntentEvent) {
|
||||||
|
this.sendIntent({
|
||||||
|
type: "create_destroyer",
|
||||||
|
clientID: this.clientID,
|
||||||
|
player: this.playerID,
|
||||||
|
x: event.cell.x,
|
||||||
|
y: event.cell.y,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private sendIntent(intent: Intent) {
|
private sendIntent(intent: Intent) {
|
||||||
if (this.isLocal || this.socket.readyState === WebSocket.OPEN) {
|
if (this.isLocal || this.socket.readyState === WebSocket.OPEN) {
|
||||||
const msg = ClientIntentMessageSchema.parse({
|
const msg = ClientIntentMessageSchema.parse({
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Colord } from "colord";
|
import { Colord } from "colord";
|
||||||
import { Theme } from "../../../core/configuration/Config";
|
import { Theme } from "../../../core/configuration/Config";
|
||||||
import { Unit, BoatEvent, Cell, Game, Tile } from "../../../core/game/Game";
|
import { Unit, UnitEvent, Cell, Game, Tile, UnitType } from "../../../core/game/Game";
|
||||||
import { bfs, dist } from "../../../core/Util";
|
import { bfs, dist } from "../../../core/Util";
|
||||||
import { Layer } from "./Layer";
|
import { Layer } from "./Layer";
|
||||||
import { EventBus } from "../../../core/EventBus";
|
import { EventBus } from "../../../core/EventBus";
|
||||||
@@ -35,7 +35,7 @@ export class UnitLayer implements Layer {
|
|||||||
this.context.putImageData(this.imageData, 0, 0);
|
this.context.putImageData(this.imageData, 0, 0);
|
||||||
this.initImageData()
|
this.initImageData()
|
||||||
|
|
||||||
this.eventBus.on(BoatEvent, e => this.onBoatEvent(e))
|
this.eventBus.on(UnitEvent, e => this.onUnitEvent(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
initImageData() {
|
initImageData() {
|
||||||
@@ -58,28 +58,47 @@ export class UnitLayer implements Layer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onBoatEvent(event: BoatEvent) {
|
onUnitEvent(event: UnitEvent) {
|
||||||
if (!this.boatToTrail.has(event.boat)) {
|
switch (event.unit.type()) {
|
||||||
this.boatToTrail.set(event.boat, new Set<Tile>())
|
case UnitType.TransportShip:
|
||||||
|
this.handleBoatEvent(event)
|
||||||
|
break
|
||||||
|
case UnitType.Destroyer:
|
||||||
|
this.handleDestroyerEvent(event)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw Error(`event for unit ${event.unit.type()} not supported`)
|
||||||
}
|
}
|
||||||
const trail = this.boatToTrail.get(event.boat)
|
}
|
||||||
|
|
||||||
|
private handleDestroyerEvent(event: UnitEvent) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleBoatEvent(event: UnitEvent) {
|
||||||
|
if (!this.boatToTrail.has(event.unit)) {
|
||||||
|
this.boatToTrail.set(event.unit, new Set<Tile>())
|
||||||
|
}
|
||||||
|
const trail = this.boatToTrail.get(event.unit)
|
||||||
trail.add(event.oldTile)
|
trail.add(event.oldTile)
|
||||||
bfs(event.oldTile, dist(event.oldTile, 3)).forEach(t => {
|
bfs(event.oldTile, dist(event.oldTile, 3)).forEach(t => {
|
||||||
this.clearCell(t.cell())
|
this.clearCell(t.cell())
|
||||||
})
|
})
|
||||||
if (event.boat.isActive()) {
|
if (event.unit.isActive()) {
|
||||||
bfs(event.boat.tile(), dist(event.boat.tile(), 4)).forEach(
|
bfs(event.unit.tile(), dist(event.unit.tile(), 4)).forEach(
|
||||||
t => {
|
t => {
|
||||||
if (trail.has(t)) {
|
if (trail.has(t)) {
|
||||||
this.paintCell(t.cell(), this.theme.territoryColor(event.boat.owner().info()), 150)
|
this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 150)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
bfs(event.boat.tile(), dist(event.boat.tile(), 2)).forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.boat.owner().info()), 255))
|
bfs(event.unit.tile(), dist(event.unit.tile(), 2))
|
||||||
bfs(event.boat.tile(), dist(event.boat.tile(), 1)).forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.boat.owner().info()), 180))
|
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255))
|
||||||
|
bfs(event.unit.tile(), dist(event.unit.tile(), 1))
|
||||||
|
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 180))
|
||||||
} else {
|
} else {
|
||||||
trail.forEach(t => this.clearCell(t.cell()))
|
trail.forEach(t => this.clearCell(t.cell()))
|
||||||
this.boatToTrail.delete(event.boat)
|
this.boatToTrail.delete(event.unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ 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, Items, Player } from '../../../../core/game/Game';
|
import { Cell, Game, Item, Items, Player } from '../../../../core/game/Game';
|
||||||
import { SendNukeIntentEvent } from '../../../Transport';
|
import { SendCreateDestroyerIntentEvent, 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 goldCoinIcon from '../../../../../resources/images/GoldCoinIcon.svg';
|
import goldCoinIcon from '../../../../../resources/images/GoldCoinIcon.svg';
|
||||||
import { renderNumber } from '../../Utils';
|
import { renderNumber } from '../../Utils';
|
||||||
import { ContextMenuEvent } from '../../../InputHandler';
|
import { ContextMenuEvent } from '../../../InputHandler';
|
||||||
@@ -16,6 +17,7 @@ interface BuildItem {
|
|||||||
const buildTable: BuildItem[][] = [
|
const buildTable: BuildItem[][] = [
|
||||||
[
|
[
|
||||||
{ item: Items.Nuke, icon: nukeIcon },
|
{ item: Items.Nuke, icon: nukeIcon },
|
||||||
|
{ item: Items.Destroyer, icon: destroyerIcon },
|
||||||
// { id: 'battleship', name: 'Battleship', icon: '🚢', cost: 500, buildTime: 20 }
|
// { id: 'battleship', name: 'Battleship', icon: '🚢', cost: 500, buildTime: 20 }
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
@@ -146,8 +148,15 @@ export class BuildMenu extends LitElement {
|
|||||||
return this.myPlayer && this.myPlayer.gold() >= item.item.cost;
|
return this.myPlayer && this.myPlayer.gold() >= item.item.cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onBuildSelected: (item: BuildItem) => void = () => {
|
public onBuildSelected = (item: BuildItem) => {
|
||||||
this.eventBus.emit(new SendNukeIntentEvent(this.myPlayer, this.clickedCell, null))
|
switch (item.item.name) {
|
||||||
|
case "Nuke":
|
||||||
|
this.eventBus.emit(new SendNukeIntentEvent(this.myPlayer, this.clickedCell, null))
|
||||||
|
break
|
||||||
|
case "Destroyer":
|
||||||
|
this.eventBus.emit(new SendCreateDestroyerIntentEvent(this.clickedCell))
|
||||||
|
|
||||||
|
}
|
||||||
this.hideMenu()
|
this.hideMenu()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+14
-4
@@ -15,6 +15,7 @@ export type Intent = SpawnIntent
|
|||||||
| DonateIntent
|
| DonateIntent
|
||||||
| NukeIntent
|
| NukeIntent
|
||||||
| TargetTroopRatioIntent
|
| TargetTroopRatioIntent
|
||||||
|
| CreateDestroyerIntent
|
||||||
|
|
||||||
export type AttackIntent = z.infer<typeof AttackIntentSchema>
|
export type AttackIntent = z.infer<typeof AttackIntentSchema>
|
||||||
export type SpawnIntent = z.infer<typeof SpawnIntentSchema>
|
export type SpawnIntent = z.infer<typeof SpawnIntentSchema>
|
||||||
@@ -26,7 +27,8 @@ export type TargetPlayerIntent = z.infer<typeof TargetPlayerIntentSchema>
|
|||||||
export type EmojiIntent = z.infer<typeof EmojiIntentSchema>
|
export type EmojiIntent = z.infer<typeof EmojiIntentSchema>
|
||||||
export type DonateIntent = z.infer<typeof DonateIntentSchema>
|
export type DonateIntent = z.infer<typeof DonateIntentSchema>
|
||||||
export type NukeIntent = z.infer<typeof NukeIntentSchema>
|
export type NukeIntent = z.infer<typeof NukeIntentSchema>
|
||||||
export type TargetTroopRatioIntent = z.infer<typeof TargetTroopRatioSchema>
|
export type TargetTroopRatioIntent = z.infer<typeof TargetTroopRatioIntentSchema>
|
||||||
|
export type CreateDestroyerIntent = z.infer<typeof CreateDestroyerIntentSchema>
|
||||||
|
|
||||||
export type Turn = z.infer<typeof TurnSchema>
|
export type Turn = z.infer<typeof TurnSchema>
|
||||||
export type GameConfig = z.infer<typeof GameConfigSchema>
|
export type GameConfig = z.infer<typeof GameConfigSchema>
|
||||||
@@ -67,7 +69,7 @@ const EmojiSchema = z.string().refine(
|
|||||||
);
|
);
|
||||||
// Zod schemas
|
// Zod schemas
|
||||||
const BaseIntentSchema = z.object({
|
const BaseIntentSchema = z.object({
|
||||||
type: z.enum(['attack', 'spawn', 'boat', 'name', 'targetPlayer', 'emoji', 'nuke', 'troop_ratio']),
|
type: z.enum(['attack', 'spawn', 'boat', 'name', 'targetPlayer', 'emoji', 'nuke', 'troop_ratio', 'create_destroyer']),
|
||||||
clientID: z.string(),
|
clientID: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -153,12 +155,19 @@ export const NukeIntentSchema = BaseIntentSchema.extend({
|
|||||||
magnitude: z.number().nullable(),
|
magnitude: z.number().nullable(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const TargetTroopRatioSchema = BaseIntentSchema.extend({
|
export const TargetTroopRatioIntentSchema = BaseIntentSchema.extend({
|
||||||
type: z.literal('troop_ratio'),
|
type: z.literal('troop_ratio'),
|
||||||
player: z.string(),
|
player: z.string(),
|
||||||
ratio: z.number().min(0).max(1),
|
ratio: z.number().min(0).max(1),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const CreateDestroyerIntentSchema = BaseIntentSchema.extend({
|
||||||
|
type: z.literal('create_destroyer'),
|
||||||
|
player: z.string(),
|
||||||
|
x: z.number(),
|
||||||
|
y: z.number(),
|
||||||
|
})
|
||||||
|
|
||||||
const IntentSchema = z.union([
|
const IntentSchema = z.union([
|
||||||
AttackIntentSchema,
|
AttackIntentSchema,
|
||||||
SpawnIntentSchema,
|
SpawnIntentSchema,
|
||||||
@@ -170,7 +179,8 @@ const IntentSchema = z.union([
|
|||||||
EmojiIntentSchema,
|
EmojiIntentSchema,
|
||||||
DonateIntentSchema,
|
DonateIntentSchema,
|
||||||
NukeIntentSchema,
|
NukeIntentSchema,
|
||||||
TargetTroopRatioSchema,
|
TargetTroopRatioIntentSchema,
|
||||||
|
CreateDestroyerIntentSchema,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const TurnSchema = z.object({
|
const TurnSchema = z.object({
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { AllPlayers, Cell, Execution, MutableGame, MutablePlayer, MutableUnit, PlayerID, UnitType } from "../game/Game";
|
||||||
|
|
||||||
|
export class DestroyerExecution implements Execution {
|
||||||
|
|
||||||
|
private _owner: MutablePlayer
|
||||||
|
private active = true
|
||||||
|
private destroyer: MutableUnit = null
|
||||||
|
private mg: MutableGame = null
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private playerID: PlayerID,
|
||||||
|
private cell: Cell,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
|
||||||
|
init(mg: MutableGame, ticks: number): void {
|
||||||
|
this._owner = mg.player(this.playerID)
|
||||||
|
this.mg = mg
|
||||||
|
}
|
||||||
|
|
||||||
|
tick(ticks: number): void {
|
||||||
|
if (this.destroyer == null) {
|
||||||
|
this.destroyer = this._owner.addUnit(UnitType.Destroyer, 0, this.mg.tile(this.cell))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
owner(): MutablePlayer {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
isActive(): boolean {
|
||||||
|
return this.active
|
||||||
|
}
|
||||||
|
|
||||||
|
activeDuringSpawnPhase(): boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import { AttackIntent, BoatAttackIntentSchema, GameID, Intent, Turn } from "../S
|
|||||||
import { AttackExecution } from "./AttackExecution";
|
import { AttackExecution } from "./AttackExecution";
|
||||||
import { SpawnExecution } from "./SpawnExecution";
|
import { SpawnExecution } from "./SpawnExecution";
|
||||||
import { BotSpawner } from "./BotSpawner";
|
import { BotSpawner } from "./BotSpawner";
|
||||||
import { BoatAttackExecution } from "./BoatAttackExecution";
|
import { TransportShipExecution } from "./TransportShipExecution";
|
||||||
import { PseudoRandom } from "../PseudoRandom";
|
import { PseudoRandom } from "../PseudoRandom";
|
||||||
import { FakeHumanExecution } from "./FakeHumanExecution";
|
import { FakeHumanExecution } from "./FakeHumanExecution";
|
||||||
import Usernames from '../../../resources/Usernames.txt'
|
import Usernames from '../../../resources/Usernames.txt'
|
||||||
@@ -52,7 +52,7 @@ export class Executor {
|
|||||||
new Cell(intent.x, intent.y)
|
new Cell(intent.x, intent.y)
|
||||||
)
|
)
|
||||||
} else if (intent.type == "boat") {
|
} else if (intent.type == "boat") {
|
||||||
return new BoatAttackExecution(
|
return new TransportShipExecution(
|
||||||
intent.attackerID,
|
intent.attackerID,
|
||||||
intent.targetID,
|
intent.targetID,
|
||||||
new Cell(intent.x, intent.y),
|
new Cell(intent.x, intent.y),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Cell, Execution, MutableGame, MutablePlayer, Player, PlayerInfo, Player
|
|||||||
import { PseudoRandom } from "../PseudoRandom"
|
import { PseudoRandom } from "../PseudoRandom"
|
||||||
import { and, bfs, dist, simpleHash } from "../Util";
|
import { and, bfs, dist, simpleHash } from "../Util";
|
||||||
import { AttackExecution } from "./AttackExecution";
|
import { AttackExecution } from "./AttackExecution";
|
||||||
import { BoatAttackExecution } from "./BoatAttackExecution";
|
import { TransportShipExecution } from "./TransportShipExecution";
|
||||||
import { SpawnExecution } from "./SpawnExecution";
|
import { SpawnExecution } from "./SpawnExecution";
|
||||||
|
|
||||||
export class FakeHumanExecution implements Execution {
|
export class FakeHumanExecution implements Execution {
|
||||||
@@ -194,7 +194,7 @@ export class FakeHumanExecution implements Execution {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mg.addExecution(new BoatAttackExecution(
|
this.mg.addExecution(new TransportShipExecution(
|
||||||
this.player.id(),
|
this.player.id(),
|
||||||
dst.hasOwner() ? dst.owner().id() : null,
|
dst.hasOwner() ? dst.owner().id() : null,
|
||||||
dst.cell(),
|
dst.cell(),
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ export class NukeExecution implements Execution {
|
|||||||
mp.removeTroops(mp.troops() / mp.numTilesOwned())
|
mp.removeTroops(mp.troops() / mp.numTilesOwned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.mg.boats().filter(b => euclideanDist(this.cell, b.tile().cell()) < this.magnitude + 50).forEach(b => b.delete())
|
this.mg.units()
|
||||||
|
.filter(b => euclideanDist(this.cell, b.tile().cell()) < this.magnitude + 50)
|
||||||
|
.forEach(b => b.delete())
|
||||||
this.active = false
|
this.active = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -4,7 +4,7 @@ import { and, bfs, manhattanDistWrapped, sourceDstOceanShore } from "../Util";
|
|||||||
import { AttackExecution } from "./AttackExecution";
|
import { AttackExecution } from "./AttackExecution";
|
||||||
import { DisplayMessageEvent, MessageType } from "../../client/graphics/layers/EventsDisplay";
|
import { DisplayMessageEvent, MessageType } from "../../client/graphics/layers/EventsDisplay";
|
||||||
|
|
||||||
export class BoatAttackExecution implements Execution {
|
export class TransportShipExecution implements Execution {
|
||||||
|
|
||||||
private lastMove: number
|
private lastMove: number
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ export class BoatAttackExecution implements Execution {
|
|||||||
this.aStarPre.compute(5)
|
this.aStarPre.compute(5)
|
||||||
this.path = this.aStarPre.reconstructPath()
|
this.path = this.aStarPre.reconstructPath()
|
||||||
if (this.path != null) {
|
if (this.path != null) {
|
||||||
this.boat = this.attacker.addBoat(this.troops, this.src, this.target)
|
this.boat = this.attacker.addUnit(UnitType.TransportShip, this.troops, this.src)
|
||||||
} else {
|
} else {
|
||||||
console.log('got null path')
|
console.log('got null path')
|
||||||
this.active = false
|
this.active = false
|
||||||
@@ -126,7 +126,9 @@ export class BoatAttackExecution implements Execution {
|
|||||||
this.target.addTroops(this.troops)
|
this.target.addTroops(this.troops)
|
||||||
} else {
|
} else {
|
||||||
this.attacker.conquer(this.dst)
|
this.attacker.conquer(this.dst)
|
||||||
this.mg.addExecution(new AttackExecution(this.troops, this.attacker.id(), this.targetID, this.dst.cell(), null, false))
|
this.mg.addExecution(
|
||||||
|
new AttackExecution(this.troops, this.attacker.id(), this.targetID, this.dst.cell(), null, false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
this.boat.delete()
|
this.boat.delete()
|
||||||
this.active = false
|
this.active = false
|
||||||
@@ -26,7 +26,8 @@ export enum GameMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum UnitType {
|
export enum UnitType {
|
||||||
TransportShip
|
TransportShip,
|
||||||
|
Destroyer
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Item {
|
export class Item {
|
||||||
@@ -35,6 +36,7 @@ export class Item {
|
|||||||
|
|
||||||
export const Items = {
|
export const Items = {
|
||||||
Nuke: new Item("Nuke", 1_000_000),
|
Nuke: new Item("Nuke", 1_000_000),
|
||||||
|
Destroyer: new Item("Destroyer", 100_000)
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export class Nation {
|
export class Nation {
|
||||||
@@ -226,7 +228,6 @@ export interface MutablePlayer extends Player {
|
|||||||
allianceWith(other: Player): MutableAlliance | null
|
allianceWith(other: Player): MutableAlliance | null
|
||||||
breakAlliance(alliance: Alliance): void
|
breakAlliance(alliance: Alliance): void
|
||||||
createAllianceRequest(recipient: Player): MutableAllianceRequest
|
createAllianceRequest(recipient: Player): MutableAllianceRequest
|
||||||
addBoat(troops: number, tile: Tile, target: Player | TerraNullius): MutableUnit
|
|
||||||
target(other: Player): void
|
target(other: Player): void
|
||||||
targets(): MutablePlayer[]
|
targets(): MutablePlayer[]
|
||||||
transitiveTargets(): MutablePlayer[]
|
transitiveTargets(): MutablePlayer[]
|
||||||
@@ -242,6 +243,8 @@ export interface MutablePlayer extends Player {
|
|||||||
setTroops(troops: number): void
|
setTroops(troops: number): void
|
||||||
addTroops(troops: number): void
|
addTroops(troops: number): void
|
||||||
removeTroops(troops: number): number
|
removeTroops(troops: number): number
|
||||||
|
|
||||||
|
addUnit(type: UnitType, troops: number, tile: Tile): MutableUnit
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Game {
|
export interface Game {
|
||||||
@@ -266,7 +269,7 @@ export interface Game {
|
|||||||
nations(): Nation[]
|
nations(): Nation[]
|
||||||
config(): Config
|
config(): Config
|
||||||
displayMessage(message: string, type: MessageType, playerID: PlayerID | null): void
|
displayMessage(message: string, type: MessageType, playerID: PlayerID | null): void
|
||||||
boats(): Unit[]
|
units(...types: UnitType[]): Unit[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MutableGame extends Game {
|
export interface MutableGame extends Game {
|
||||||
@@ -275,7 +278,7 @@ export interface MutableGame extends Game {
|
|||||||
players(): MutablePlayer[]
|
players(): MutablePlayer[]
|
||||||
addPlayer(playerInfo: PlayerInfo, manpower: number): MutablePlayer
|
addPlayer(playerInfo: PlayerInfo, manpower: number): MutablePlayer
|
||||||
executions(): Execution[]
|
executions(): Execution[]
|
||||||
boats(): MutableUnit[]
|
units(...types: UnitType[]): MutableUnit[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TileEvent implements GameEvent {
|
export class TileEvent implements GameEvent {
|
||||||
@@ -286,8 +289,8 @@ export class PlayerEvent implements GameEvent {
|
|||||||
constructor(public readonly player: Player) { }
|
constructor(public readonly player: Player) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BoatEvent implements GameEvent {
|
export class UnitEvent implements GameEvent {
|
||||||
constructor(public readonly boat: Unit, public oldTile: Tile) { }
|
constructor(public readonly unit: Unit, public oldTile: Tile) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AllianceRequestEvent implements GameEvent {
|
export class AllianceRequestEvent implements GameEvent {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { info } from "console";
|
import { info } from "console";
|
||||||
import { Config } from "../configuration/Config";
|
import { Config } from "../configuration/Config";
|
||||||
import { EventBus } from "../EventBus";
|
import { EventBus } from "../EventBus";
|
||||||
import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Unit, BoatEvent as UnitEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation } from "./Game";
|
import { Cell, Execution, MutableGame, Game, MutablePlayer, PlayerEvent, PlayerID, PlayerInfo, Player, TerraNullius, Tile, TileEvent, Unit, UnitEvent as UnitEvent, PlayerType, MutableAllianceRequest, AllianceRequestReplyEvent, AllianceRequestEvent, BrokeAllianceEvent, MutableAlliance, Alliance, AllianceExpiredEvent, Nation, UnitType } from "./Game";
|
||||||
import { TerrainMap } from "./TerrainMapLoader";
|
import { TerrainMap } from "./TerrainMapLoader";
|
||||||
import { PlayerImpl } from "./PlayerImpl";
|
import { PlayerImpl } from "./PlayerImpl";
|
||||||
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
import { TerraNulliusImpl } from "./TerraNulliusImpl";
|
||||||
@@ -58,8 +58,8 @@ export class GameImpl implements MutableGame {
|
|||||||
n.strength
|
n.strength
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
boats(): UnitImpl[] {
|
units(...types: UnitType[]): UnitImpl[] {
|
||||||
return Array.from(this._players.values()).flatMap(p => p._units)
|
return Array.from(this._players.values()).flatMap(p => p.units(...types))
|
||||||
}
|
}
|
||||||
nations(): Nation[] {
|
nations(): Nation[] {
|
||||||
return this.nations_
|
return this.nations_
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ export class PlayerImpl implements MutablePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
addBoat(troops: number, tile: Tile): UnitImpl {
|
addUnit(type: UnitType, troops: number, tile: Tile): UnitImpl {
|
||||||
const b = new UnitImpl(UnitType.TransportShip, this.gs, tile, troops, this);
|
const b = new UnitImpl(type, this.gs, tile, troops, this);
|
||||||
this._units.push(b);
|
this._units.push(b);
|
||||||
this.gs.fireUnitUpdateEvent(b, b.tile());
|
this.gs.fireUnitUpdateEvent(b, b.tile());
|
||||||
return b;
|
return b;
|
||||||
|
|||||||
Reference in New Issue
Block a user