You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.9 KiB
150 lines
3.9 KiB
import {
|
|
BallState,
|
|
Player,
|
|
PlayerLike,
|
|
PlayerPhantom,
|
|
} from "../model/tactic/Player"
|
|
import { TacticComponent, TacticContent } from "../model/tactic/Tactic"
|
|
import { removeComponent, updateComponent } from "./TacticContentDomains"
|
|
import {
|
|
removeAllActionsTargeting,
|
|
spreadNewStateFromOriginStateChange,
|
|
} from "./ActionsDomains"
|
|
import { ActionKind } from "../model/tactic/Action"
|
|
|
|
export function getOrigin(
|
|
pathItem: PlayerPhantom,
|
|
components: TacticComponent[],
|
|
): Player {
|
|
// Trust the components to contains only phantoms with valid player origin identifiers
|
|
return components.find((c) => c.id == pathItem.originPlayerId)! as Player
|
|
}
|
|
|
|
export function areInSamePath(a: PlayerLike, b: PlayerLike) {
|
|
if (a.type === "phantom" && b.type === "phantom") {
|
|
return a.originPlayerId === b.originPlayerId
|
|
}
|
|
if (a.type === "phantom") {
|
|
return b.id === a.originPlayerId
|
|
}
|
|
if (b.type === "phantom") {
|
|
return a.id === b.originPlayerId
|
|
}
|
|
return false
|
|
}
|
|
|
|
/**
|
|
* @param origin
|
|
* @param other
|
|
* @param components
|
|
* @returns true if the `other` player is the phantom next-to the origin's path.
|
|
*/
|
|
export function isNextInPath(
|
|
origin: PlayerLike,
|
|
other: PlayerLike,
|
|
components: TacticComponent[],
|
|
): boolean {
|
|
if (origin.type === "player") {
|
|
return origin.path?.items[0] === other.id
|
|
}
|
|
const originPath = getOrigin(origin, components).path!
|
|
return (
|
|
originPath.items!.indexOf(origin.id) ===
|
|
originPath.items!.indexOf(other.id) - 1
|
|
)
|
|
}
|
|
|
|
export function removePlayerPath(
|
|
player: Player,
|
|
content: TacticContent,
|
|
): TacticContent {
|
|
if (player.path == null) {
|
|
return content
|
|
}
|
|
|
|
for (const pathElement of player.path.items) {
|
|
content = removeComponent(pathElement, content)
|
|
content = removeAllActionsTargeting(pathElement, content)
|
|
}
|
|
return updateComponent(
|
|
{
|
|
...player,
|
|
path: null,
|
|
},
|
|
content,
|
|
)
|
|
}
|
|
|
|
export function removePlayer(
|
|
player: PlayerLike,
|
|
content: TacticContent,
|
|
): TacticContent {
|
|
content = removeAllActionsTargeting(player.id, content)
|
|
|
|
if (player.type == "phantom") {
|
|
const origin = getOrigin(player, content.components)
|
|
return truncatePlayerPath(origin, player, content)
|
|
}
|
|
|
|
content = removePlayerPath(player, content)
|
|
content = removeComponent(player.id, content)
|
|
|
|
for (const action of player.actions) {
|
|
if (action.type !== ActionKind.SHOOT) {
|
|
continue
|
|
}
|
|
const actionTarget = content.components.find(
|
|
(c) => c.id === action.target,
|
|
)! as PlayerLike
|
|
return spreadNewStateFromOriginStateChange(
|
|
actionTarget,
|
|
BallState.NONE,
|
|
content,
|
|
)
|
|
}
|
|
|
|
return content
|
|
}
|
|
|
|
export function truncatePlayerPath(
|
|
player: Player,
|
|
phantom: PlayerPhantom,
|
|
content: TacticContent,
|
|
): TacticContent {
|
|
if (player.path == null) return content
|
|
|
|
const path = player.path!
|
|
|
|
const truncateStartIdx = path.items.indexOf(phantom.id)
|
|
|
|
for (let i = truncateStartIdx; i < path.items.length; i++) {
|
|
const pathPhantomId = path.items[i]
|
|
|
|
//remove the phantom from the tactic
|
|
content = removeComponent(pathPhantomId, content)
|
|
content = removeAllActionsTargeting(pathPhantomId, content)
|
|
}
|
|
|
|
return updateComponent(
|
|
{
|
|
...player,
|
|
path:
|
|
truncateStartIdx == 0
|
|
? null
|
|
: {
|
|
...path,
|
|
items: path.items.toSpliced(truncateStartIdx),
|
|
},
|
|
},
|
|
content,
|
|
)
|
|
}
|
|
|
|
export function changePlayerBallState(
|
|
player: PlayerLike,
|
|
newState: BallState,
|
|
content: TacticContent,
|
|
): TacticContent {
|
|
return spreadNewStateFromOriginStateChange(player, newState, content)
|
|
}
|