mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-22 11:37:12 +00:00
Target player creates target icon
This commit is contained in:
+10
-1
@@ -11,6 +11,7 @@ export type Intent = SpawnIntent
|
||||
| AllianceRequestIntent
|
||||
| AllianceRequestReplyIntent
|
||||
| BreakAllianceIntent
|
||||
| TargetPlayerIntent
|
||||
|
||||
export type AttackIntent = z.infer<typeof AttackIntentSchema>
|
||||
export type SpawnIntent = z.infer<typeof SpawnIntentSchema>
|
||||
@@ -19,6 +20,7 @@ export type UpdateNameIntent = z.infer<typeof UpdateNameIntentSchema>
|
||||
export type AllianceRequestIntent = z.infer<typeof AllianceRequestIntentSchema>
|
||||
export type AllianceRequestReplyIntent = z.infer<typeof AllianceRequestReplyIntentSchema>
|
||||
export type BreakAllianceIntent = z.infer<typeof BreakAllianceIntentSchema>
|
||||
export type TargetPlayerIntent = z.infer<typeof TargetPlayerIntentSchema>
|
||||
|
||||
|
||||
export type Turn = z.infer<typeof TurnSchema>
|
||||
@@ -104,6 +106,12 @@ export const BreakAllianceIntentSchema = BaseIntentSchema.extend({
|
||||
recipient: z.string(),
|
||||
})
|
||||
|
||||
export const TargetPlayerIntentSchema = BaseIntentSchema.extend({
|
||||
type: z.literal('targetPlayer'),
|
||||
requestor: z.string(),
|
||||
target: z.string(),
|
||||
})
|
||||
|
||||
const IntentSchema = z.union([
|
||||
AttackIntentSchema,
|
||||
SpawnIntentSchema,
|
||||
@@ -111,7 +119,8 @@ const IntentSchema = z.union([
|
||||
UpdateNameIntentSchema,
|
||||
AllianceRequestIntentSchema,
|
||||
AllianceRequestReplyIntentSchema,
|
||||
BreakAllianceIntentSchema
|
||||
BreakAllianceIntentSchema,
|
||||
TargetPlayerIntentSchema,
|
||||
]);
|
||||
|
||||
const TurnSchema = z.object({
|
||||
|
||||
@@ -49,6 +49,8 @@ export interface Config {
|
||||
boatMaxNumber(): number
|
||||
allianceDuration(): Tick
|
||||
allianceRequestCooldown(): Tick
|
||||
targetDuration(): Tick
|
||||
targetCooldown(): Tick
|
||||
}
|
||||
|
||||
export interface Theme {
|
||||
|
||||
@@ -7,6 +7,12 @@ import {pastelTheme} from "./PastelTheme";
|
||||
|
||||
|
||||
export class DefaultConfig implements Config {
|
||||
targetDuration(): Tick {
|
||||
return 10 * 10
|
||||
}
|
||||
targetCooldown(): Tick {
|
||||
return 30 * 10
|
||||
}
|
||||
allianceRequestCooldown(): Tick {
|
||||
return 30 * 10
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import {Tick} from "../game/Game";
|
||||
import {GameID} from "../Schemas";
|
||||
import {DefaultConfig} from "./DefaultConfig";
|
||||
|
||||
export const devConfig = new class extends DefaultConfig {
|
||||
percentageTilesOwnedToWin(): number {
|
||||
return 95
|
||||
}
|
||||
numSpawnPhaseTurns(): number {
|
||||
return 40
|
||||
}
|
||||
gameCreationRate(): number {
|
||||
return 2 * 1000
|
||||
}
|
||||
lobbyLifetime(): number {
|
||||
return 2 * 1000
|
||||
}
|
||||
// numSpawnPhaseTurns(): number {
|
||||
// return 40
|
||||
// }
|
||||
// gameCreationRate(): number {
|
||||
// return 2 * 1000
|
||||
// }
|
||||
// lobbyLifetime(): number {
|
||||
// return 2 * 1000
|
||||
// }
|
||||
turnIntervalMs(): number {
|
||||
return 100
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {simpleHash} from "../Util";
|
||||
import {AllianceRequestExecution} from "./alliance/AllianceRequestExecution";
|
||||
import {AllianceRequestReplyExecution} from "./alliance/AllianceRequestReplyExecution";
|
||||
import {BreakAllianceExecution} from "./alliance/BreakAllianceExecution";
|
||||
import {TargetPlayerExecution} from "./TargetPlayerExecution";
|
||||
|
||||
|
||||
|
||||
@@ -64,6 +65,8 @@ export class Executor {
|
||||
return new AllianceRequestReplyExecution(intent.requestor, intent.recipient, intent.accept)
|
||||
} else if (intent.type == "breakAlliance") {
|
||||
return new BreakAllianceExecution(intent.requestor, intent.recipient)
|
||||
} else if (intent.type == "targetPlayer") {
|
||||
return new TargetPlayerExecution(intent.requestor, intent.target)
|
||||
}
|
||||
else {
|
||||
throw new Error(`intent type ${intent} not found`)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import {Execution, MutableGame, MutablePlayer, PlayerID} from "../game/Game";
|
||||
|
||||
export class TargetPlayerExecution implements Execution {
|
||||
|
||||
private requestor: MutablePlayer
|
||||
private target: MutablePlayer
|
||||
|
||||
private active = true
|
||||
|
||||
constructor(private requestorID: PlayerID, private targetID: PlayerID) { }
|
||||
|
||||
|
||||
init(mg: MutableGame, ticks: number): void {
|
||||
this.requestor = mg.player(this.requestorID)
|
||||
this.target = mg.player(this.targetID)
|
||||
}
|
||||
|
||||
tick(ticks: number): void {
|
||||
if (this.requestor.canTarget(this.target)) {
|
||||
this.requestor.target(this.target)
|
||||
}
|
||||
this.active = false
|
||||
}
|
||||
|
||||
owner(): MutablePlayer {
|
||||
return null
|
||||
}
|
||||
|
||||
isActive(): boolean {
|
||||
return this.active
|
||||
}
|
||||
|
||||
activeDuringSpawnPhase(): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,13 @@ export class AllianceImpl implements MutableAlliance {
|
||||
readonly createdAtTick_: Tick,
|
||||
) { }
|
||||
|
||||
other(player: Player): PlayerImpl {
|
||||
if (this.requestor_ == player) {
|
||||
return this.recipient_
|
||||
}
|
||||
return this.requestor_
|
||||
}
|
||||
|
||||
requestor(): MutablePlayer {
|
||||
return this.requestor_
|
||||
}
|
||||
|
||||
@@ -64,10 +64,12 @@ export interface Alliance {
|
||||
requestor(): Player
|
||||
recipient(): Player
|
||||
createdAt(): Tick
|
||||
other(player: Player): Player
|
||||
}
|
||||
|
||||
export interface MutableAlliance extends Alliance {
|
||||
expire(): void
|
||||
other(player: Player): MutablePlayer
|
||||
}
|
||||
|
||||
export class PlayerInfo {
|
||||
@@ -148,6 +150,11 @@ export interface Player {
|
||||
// Includes recent requests that are in cooldown
|
||||
recentOrPendingAllianceRequestWith(other: Player): boolean
|
||||
isTraitor(): boolean
|
||||
canTarget(other: Player): boolean
|
||||
// Targets for this player
|
||||
targets(): Player[]
|
||||
// Targets of player and all allies.
|
||||
transitiveTargets(): Player[]
|
||||
toString(): string
|
||||
}
|
||||
|
||||
@@ -168,6 +175,9 @@ export interface MutablePlayer extends Player {
|
||||
breakAlliance(alliance: Alliance): void
|
||||
createAllianceRequest(recipient: Player): MutableAllianceRequest
|
||||
addBoat(troops: number, tile: Tile, target: Player | TerraNullius): MutableBoat
|
||||
target(other: Player): void
|
||||
targets(): MutablePlayer[]
|
||||
transitiveTargets(): MutablePlayer[]
|
||||
}
|
||||
|
||||
export interface Game {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, MutableGame, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance} from "./Game";
|
||||
import {MutablePlayer, Tile, PlayerInfo, PlayerID, PlayerType, Player, TerraNullius, Cell, MutableGame, Execution, AllianceRequest, MutableAllianceRequest, MutableAlliance, Alliance, Tick} from "./Game";
|
||||
import {ClientID} from "../Schemas";
|
||||
import {simpleHash} from "../Util";
|
||||
import {CellString, GameImpl} from "./GameImpl";
|
||||
@@ -7,6 +7,10 @@ import {TileImpl} from "./TileImpl";
|
||||
import {TerraNulliusImpl} from "./TerraNulliusImpl";
|
||||
import {threadId} from "worker_threads";
|
||||
|
||||
interface Target {
|
||||
tick: Tick
|
||||
target: Player
|
||||
}
|
||||
|
||||
export class PlayerImpl implements MutablePlayer {
|
||||
isTraitor_ = false
|
||||
@@ -20,6 +24,8 @@ export class PlayerImpl implements MutablePlayer {
|
||||
|
||||
public pastOutgoingAllianceRequests: AllianceRequest[] = []
|
||||
|
||||
private targets_: Target[] = []
|
||||
|
||||
constructor(private gs: GameImpl, private readonly playerInfo: PlayerInfo, private _troops) {
|
||||
this._name = playerInfo.name;
|
||||
}
|
||||
@@ -172,6 +178,33 @@ export class PlayerImpl implements MutablePlayer {
|
||||
return this.gs.createAllianceRequest(this, recipient)
|
||||
}
|
||||
|
||||
canTarget(other: Player): boolean {
|
||||
for (const t of this.targets_) {
|
||||
if (t.target == other) {
|
||||
if (this.gs.ticks() - t.tick < this.gs.config().targetCooldown()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
target(other: Player): void {
|
||||
this.targets_.push({tick: this.gs.ticks(), target: other})
|
||||
}
|
||||
|
||||
targets(): PlayerImpl[] {
|
||||
return this.targets_
|
||||
.filter(t => this.gs.ticks() - t.tick < this.gs.config().targetDuration())
|
||||
.map(t => t.target as PlayerImpl)
|
||||
}
|
||||
|
||||
transitiveTargets(): MutablePlayer[] {
|
||||
const ts = this.alliances().map(a => a.other(this)).flatMap(ally => ally.targets())
|
||||
ts.push(...this.targets())
|
||||
return [...new Set(ts)]
|
||||
}
|
||||
|
||||
hash(): number {
|
||||
return simpleHash(this.id()) * (this.troops() + this.numTilesOwned());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user