2022-02-02 13:30:49 +01:00
|
|
|
import { isOutlineable } from "../../Utils/CustomTypeGuards";
|
|
|
|
import { MathUtils } from "../../Utils/MathUtils";
|
|
|
|
import type { Player } from "../Player/Player";
|
|
|
|
import type { ActivatableInterface } from "./ActivatableInterface";
|
2022-01-27 15:15:18 +01:00
|
|
|
|
|
|
|
export class ActivatablesManager {
|
|
|
|
// The item that can be selected by pressing the space key.
|
|
|
|
private selectedActivatableObjectByDistance?: ActivatableInterface;
|
|
|
|
private selectedActivatableObjectByPointer?: ActivatableInterface;
|
|
|
|
private activatableObjectsDistances: Map<ActivatableInterface, number> = new Map<ActivatableInterface, number>();
|
|
|
|
|
|
|
|
private currentPlayer: Player;
|
2022-02-02 13:30:49 +01:00
|
|
|
|
2022-02-07 12:36:33 +01:00
|
|
|
private canSelectByDistance: boolean = true;
|
|
|
|
|
2022-02-07 10:39:03 +01:00
|
|
|
private readonly outlineColor = 0xffff00;
|
2022-02-07 11:08:52 +01:00
|
|
|
private readonly directionalActivationPositionShift = 50;
|
2022-02-07 10:39:03 +01:00
|
|
|
|
2022-01-27 15:15:18 +01:00
|
|
|
constructor(currentPlayer: Player) {
|
|
|
|
this.currentPlayer = currentPlayer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public handlePointerOverActivatableObject(object: ActivatableInterface): void {
|
|
|
|
if (this.selectedActivatableObjectByPointer === object) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByDistance)) {
|
|
|
|
this.selectedActivatableObjectByDistance?.characterFarAwayOutline();
|
|
|
|
}
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByPointer)) {
|
|
|
|
this.selectedActivatableObjectByPointer?.pointerOutOutline();
|
|
|
|
}
|
|
|
|
this.selectedActivatableObjectByPointer = object;
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByPointer)) {
|
2022-02-07 10:39:03 +01:00
|
|
|
this.selectedActivatableObjectByPointer?.pointerOverOutline(this.outlineColor);
|
2022-01-27 15:15:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public handlePointerOutActivatableObject(): void {
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByPointer)) {
|
|
|
|
this.selectedActivatableObjectByPointer?.pointerOutOutline();
|
|
|
|
}
|
|
|
|
this.selectedActivatableObjectByPointer = undefined;
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByDistance)) {
|
2022-02-07 10:39:03 +01:00
|
|
|
this.selectedActivatableObjectByDistance?.characterCloseByOutline(this.outlineColor);
|
2022-01-27 15:15:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public getSelectedActivatableObject(): ActivatableInterface | undefined {
|
|
|
|
return this.selectedActivatableObjectByPointer ?? this.selectedActivatableObjectByDistance;
|
|
|
|
}
|
|
|
|
|
|
|
|
public deduceSelectedActivatableObjectByDistance(): void {
|
2022-02-07 12:36:33 +01:00
|
|
|
if (!this.canSelectByDistance) {
|
|
|
|
return;
|
|
|
|
}
|
2022-01-27 15:15:18 +01:00
|
|
|
const newNearestObject = this.findNearestActivatableObject();
|
|
|
|
if (this.selectedActivatableObjectByDistance === newNearestObject) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// update value but do not change the outline
|
|
|
|
if (this.selectedActivatableObjectByPointer) {
|
|
|
|
this.selectedActivatableObjectByDistance = newNearestObject;
|
2022-02-02 13:30:49 +01:00
|
|
|
return;
|
2022-01-27 15:15:18 +01:00
|
|
|
}
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByDistance)) {
|
|
|
|
this.selectedActivatableObjectByDistance?.characterFarAwayOutline();
|
|
|
|
}
|
|
|
|
this.selectedActivatableObjectByDistance = newNearestObject;
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByDistance)) {
|
2022-02-07 10:39:03 +01:00
|
|
|
this.selectedActivatableObjectByDistance?.characterCloseByOutline(this.outlineColor);
|
2022-01-27 15:15:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public updateActivatableObjectsDistances(objects: ActivatableInterface[]): void {
|
2022-02-07 14:23:34 +01:00
|
|
|
const currentPlayerPos = this.currentPlayer.getDirectionalActivationPosition(
|
|
|
|
this.directionalActivationPositionShift
|
|
|
|
);
|
2022-01-27 15:15:18 +01:00
|
|
|
for (const object of objects) {
|
|
|
|
const distance = MathUtils.distanceBetween(currentPlayerPos, object.getPosition());
|
|
|
|
this.activatableObjectsDistances.set(object, distance);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public updateDistanceForSingleActivatableObject(object: ActivatableInterface): void {
|
|
|
|
this.activatableObjectsDistances.set(
|
|
|
|
object,
|
2022-02-07 11:08:52 +01:00
|
|
|
MathUtils.distanceBetween(
|
|
|
|
this.currentPlayer.getDirectionalActivationPosition(this.directionalActivationPositionShift),
|
2022-02-07 14:23:34 +01:00
|
|
|
object.getPosition()
|
2022-02-07 11:08:52 +01:00
|
|
|
)
|
2022-01-27 15:15:18 +01:00
|
|
|
);
|
|
|
|
}
|
2022-02-07 12:36:33 +01:00
|
|
|
|
|
|
|
public disableSelectingByDistance(): void {
|
|
|
|
this.canSelectByDistance = false;
|
|
|
|
if (isOutlineable(this.selectedActivatableObjectByDistance)) {
|
|
|
|
this.selectedActivatableObjectByDistance?.characterFarAwayOutline();
|
|
|
|
}
|
|
|
|
this.selectedActivatableObjectByDistance = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
public enableSelectingByDistance(): void {
|
|
|
|
this.canSelectByDistance = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private findNearestActivatableObject(): ActivatableInterface | undefined {
|
|
|
|
let shortestDistance: number = Infinity;
|
|
|
|
let closestObject: ActivatableInterface | undefined = undefined;
|
|
|
|
|
|
|
|
for (const [object, distance] of this.activatableObjectsDistances.entries()) {
|
|
|
|
if (object.isActivatable() && object.activationRadius > distance && shortestDistance > distance) {
|
|
|
|
shortestDistance = distance;
|
|
|
|
closestObject = object;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return closestObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
public isSelectingByDistanceEnabled(): boolean {
|
|
|
|
return this.canSelectByDistance;
|
|
|
|
}
|
2022-01-27 16:50:25 +01:00
|
|
|
}
|