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.
127 lines
3.8 KiB
127 lines
3.8 KiB
import {BallState, Player, 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: Player | PlayerPhantom,
|
|
b: Player | PlayerPhantom,
|
|
) {
|
|
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: Player | PlayerPhantom, other: Player | PlayerPhantom, 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: Player | PlayerPhantom,
|
|
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 (Player | PlayerPhantom)
|
|
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: Player | PlayerPhantom, newState: BallState, content: TacticContent): TacticContent {
|
|
return spreadNewStateFromOriginStateChange(player, newState, content)
|
|
} |