nitro/libs/renderer/src/nitro/room/object/logic/avatar/AvatarLogic.ts

459 lines
15 KiB
TypeScript

import {AvatarAction, IRoomGeometry, IRoomObjectModel, MouseEventType, RoomObjectVariable, Vector3d} from "../../../../../api";
import {RoomObjectFurnitureActionEvent, RoomObjectMouseEvent, RoomObjectMoveEvent, RoomSpriteMouseEvent} from "../../../../../events";
import {GetTickerTime} from "../../../../../pixi-proxy";
import {RoomObjectUpdateMessage} from "../../../../../room";
import {
ObjectAvatarCarryObjectUpdateMessage,
ObjectAvatarChatUpdateMessage,
ObjectAvatarDanceUpdateMessage,
ObjectAvatarEffectUpdateMessage,
ObjectAvatarExpressionUpdateMessage,
ObjectAvatarFigureUpdateMessage,
ObjectAvatarFlatControlUpdateMessage,
ObjectAvatarGestureUpdateMessage,
ObjectAvatarMutedUpdateMessage,
ObjectAvatarOwnMessage,
ObjectAvatarPlayerValueUpdateMessage,
ObjectAvatarPlayingGameUpdateMessage,
ObjectAvatarPostureUpdateMessage,
ObjectAvatarSelectedMessage,
ObjectAvatarSignUpdateMessage,
ObjectAvatarSleepUpdateMessage,
ObjectAvatarTypingUpdateMessage,
ObjectAvatarUpdateMessage,
ObjectAvatarUseObjectUpdateMessage,
} from "../../../messages";
import {MovingObjectLogic} from "../MovingObjectLogic";
export class AvatarLogic extends MovingObjectLogic {
private static MAX_HAND_ID: number = 999999999;
private static MAX_HAND_USE_ID: number = 999;
private static EFFECT_TYPE_SPLASH: number = 28;
private static EFFECT_SPLASH_LENGTH: number = 500;
private static EFFECT_TYPE_SWIM: number = 29;
private static EFFECT_TYPE_SPLASH_DARK: number = 184;
private static EFFECT_TYPE_SWIM_DARK: number = 185;
private _selected: boolean;
private _reportedLocation: Vector3d;
private _effectChangeTimeStamp: number;
private _newEffect: number;
private _blinkingStartTimestamp: number;
private _blinkingEndTimestamp: number;
private _talkingEndTimestamp: number;
private _talkingPauseStartTimestamp: number;
private _talkingPauseEndTimestamp: number;
private _carryObjectStartTimestamp: number;
private _carryObjectEndTimestamp: number;
private _allowUseCarryObject: boolean;
private _animationEndTimestamp: number;
private _signEndTimestamp: number;
private _gestureEndTimestamp: number;
private _numberValueEndTimestamp: number;
constructor() {
super();
this._selected = false;
this._reportedLocation = null;
this._effectChangeTimeStamp = 0;
this._newEffect = 0;
this._blinkingStartTimestamp = GetTickerTime() + this.randomBlinkStartTimestamp();
this._blinkingEndTimestamp = 0;
this._talkingEndTimestamp = 0;
this._talkingPauseStartTimestamp = 0;
this._talkingPauseEndTimestamp = 0;
this._carryObjectStartTimestamp = 0;
this._carryObjectEndTimestamp = 0;
this._allowUseCarryObject = false;
this._animationEndTimestamp = 0;
this._signEndTimestamp = 0;
this._gestureEndTimestamp = 0;
this._numberValueEndTimestamp = 0;
}
public override getEventTypes(): string[] {
const types = [
RoomObjectMouseEvent.CLICK,
RoomObjectMouseEvent.DOUBLE_CLICK,
RoomObjectMoveEvent.POSITION_CHANGED,
RoomObjectMouseEvent.MOUSE_ENTER,
RoomObjectMouseEvent.MOUSE_LEAVE,
RoomObjectFurnitureActionEvent.MOUSE_BUTTON,
RoomObjectFurnitureActionEvent.MOUSE_ARROW,
];
return this.mergeTypes(super.getEventTypes(), types);
}
public override dispose(): void {
if (this._selected && this.object) {
if (this.eventDispatcher) this.eventDispatcher.dispatchEvent(new RoomObjectMoveEvent(RoomObjectMoveEvent.OBJECT_REMOVED, this.object));
}
super.dispose();
this._reportedLocation = null;
}
public override update(time: number): void {
super.update(time);
if (this._selected && this.object) {
if (this.eventDispatcher) {
const location = this.object.getLocation();
if (
!this._reportedLocation ||
this._reportedLocation.x !== location.x ||
this._reportedLocation.y !== location.y ||
this._reportedLocation.z !== location.z
) {
if (!this._reportedLocation) this._reportedLocation = new Vector3d();
this._reportedLocation.assign(location);
this.eventDispatcher.dispatchEvent(new RoomObjectMoveEvent(RoomObjectMoveEvent.POSITION_CHANGED, this.object));
}
}
}
const model = this.object && this.object.model;
if (model) this.updateModel(this.time, model);
}
private updateModel(time: number, model: IRoomObjectModel): void {
if (this._talkingEndTimestamp > 0) {
if (time > this._talkingEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_TALK, 0);
this._talkingEndTimestamp = 0;
this._talkingPauseStartTimestamp = 0;
this._talkingPauseEndTimestamp = 0;
} else {
if (!this._talkingPauseEndTimestamp && !this._talkingPauseStartTimestamp) {
this._talkingPauseStartTimestamp = time + this.randomTalkingPauseStartTimestamp();
this._talkingPauseEndTimestamp = this._talkingPauseStartTimestamp + this.randomTalkingPauseEndTimestamp();
} else {
if (this._talkingPauseStartTimestamp > 0 && time > this._talkingPauseStartTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_TALK, 0);
this._talkingPauseStartTimestamp = 0;
} else {
if (this._talkingPauseEndTimestamp > 0 && time > this._talkingPauseEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_TALK, 1);
this._talkingPauseEndTimestamp = 0;
}
}
}
}
}
if (this._animationEndTimestamp > 0 && time > this._animationEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_EXPRESSION, 0);
this._animationEndTimestamp = 0;
}
if (this._gestureEndTimestamp > 0 && time > this._gestureEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_GESTURE, 0);
this._gestureEndTimestamp = 0;
}
if (this._signEndTimestamp > 0 && time > this._signEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_SIGN, -1);
this._signEndTimestamp = 0;
}
if (this._carryObjectEndTimestamp > 0) {
if (time > this._carryObjectEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_CARRY_OBJECT, 0);
model.setValue(RoomObjectVariable.FIGURE_USE_OBJECT, 0);
this._carryObjectStartTimestamp = 0;
this._carryObjectEndTimestamp = 0;
this._allowUseCarryObject = false;
}
}
if (this._allowUseCarryObject) {
if (time - this._carryObjectStartTimestamp > 5000) {
if ((time - this._carryObjectStartTimestamp) % 10000 < 1000) {
model.setValue(RoomObjectVariable.FIGURE_USE_OBJECT, 1);
} else {
model.setValue(RoomObjectVariable.FIGURE_USE_OBJECT, 0);
}
}
}
if (this._blinkingStartTimestamp > -1 && time > this._blinkingStartTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_BLINK, 1);
this._blinkingStartTimestamp = time + this.randomBlinkStartTimestamp();
this._blinkingEndTimestamp = time + this.randomBlinkEndTimestamp();
}
if (this._blinkingEndTimestamp > 0 && time > this._blinkingEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_BLINK, 0);
this._blinkingEndTimestamp = 0;
}
if (this._effectChangeTimeStamp > 0 && time > this._effectChangeTimeStamp) {
model.setValue(RoomObjectVariable.FIGURE_EFFECT, this._newEffect);
this._effectChangeTimeStamp = 0;
}
if (this._numberValueEndTimestamp > 0 && time > this._numberValueEndTimestamp) {
model.setValue(RoomObjectVariable.FIGURE_NUMBER_VALUE, 0);
this._numberValueEndTimestamp = 0;
}
}
public override processUpdateMessage(message: RoomObjectUpdateMessage): void {
if (!message || !this.object) return;
super.processUpdateMessage(message);
const model = this.object && this.object.model;
if (!model) return;
if (message instanceof ObjectAvatarPostureUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_POSTURE, message.postureType);
model.setValue(RoomObjectVariable.FIGURE_POSTURE_PARAMETER, message.parameter);
return;
}
if (message instanceof ObjectAvatarChatUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_TALK, 1);
this._talkingEndTimestamp = this.time + message.numberOfWords * 1000;
return;
}
if (message instanceof ObjectAvatarTypingUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_IS_TYPING, message.isTyping ? 1 : 0);
return;
}
if (message instanceof ObjectAvatarMutedUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_IS_MUTED, message.isMuted ? 1 : 0);
return;
}
if (message instanceof ObjectAvatarPlayingGameUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_IS_PLAYING_GAME, message.isPlayingGame ? 1 : 0);
return;
}
if (message instanceof ObjectAvatarUpdateMessage) {
model.setValue(RoomObjectVariable.HEAD_DIRECTION, message.headDirection);
model.setValue(RoomObjectVariable.FIGURE_CAN_STAND_UP, message.canStandUp);
model.setValue(RoomObjectVariable.FIGURE_VERTICAL_OFFSET, message.baseY);
return;
}
if (message instanceof ObjectAvatarGestureUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_GESTURE, message.gesture);
this._gestureEndTimestamp = this.time + 3000;
return;
}
if (message instanceof ObjectAvatarExpressionUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_EXPRESSION, message.expressionType);
this._animationEndTimestamp = AvatarAction.getExpressionTimeout(model.getValue<number>(RoomObjectVariable.FIGURE_EXPRESSION));
if (this._animationEndTimestamp > -1) this._animationEndTimestamp += this.time;
return;
}
if (message instanceof ObjectAvatarDanceUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_DANCE, message.danceStyle);
return;
}
if (message instanceof ObjectAvatarSleepUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_SLEEP, message.isSleeping ? 1 : 0);
if (message.isSleeping) this._blinkingStartTimestamp = -1;
else this._blinkingStartTimestamp = this.time + this.randomBlinkStartTimestamp();
return;
}
if (message instanceof ObjectAvatarPlayerValueUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_NUMBER_VALUE, message.value);
this._numberValueEndTimestamp = this.time + 3000;
return;
}
if (message instanceof ObjectAvatarEffectUpdateMessage) {
this.updateAvatarEffect(message.effect, message.delayMilliseconds, model);
return;
}
if (message instanceof ObjectAvatarCarryObjectUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_CARRY_OBJECT, message.itemType);
model.setValue(RoomObjectVariable.FIGURE_USE_OBJECT, 0);
if (message.itemType === 0) {
this._carryObjectStartTimestamp = 0;
this._carryObjectEndTimestamp = 0;
this._allowUseCarryObject = false;
} else {
this._carryObjectStartTimestamp = this.time;
if (message.itemType < AvatarLogic.MAX_HAND_ID) {
this._carryObjectEndTimestamp = 0;
this._allowUseCarryObject = message.itemType <= AvatarLogic.MAX_HAND_USE_ID;
} else {
this._carryObjectEndTimestamp = this._carryObjectStartTimestamp + 1500;
this._allowUseCarryObject = false;
}
}
return;
}
if (message instanceof ObjectAvatarUseObjectUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_USE_OBJECT, message.itemType);
return;
}
if (message instanceof ObjectAvatarSignUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_SIGN, message.signType);
this._signEndTimestamp = this.time + 5000;
return;
}
if (message instanceof ObjectAvatarFlatControlUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE_FLAT_CONTROL, message.level);
return;
}
if (message instanceof ObjectAvatarFigureUpdateMessage) {
model.setValue(RoomObjectVariable.FIGURE, message.figure);
model.setValue(RoomObjectVariable.GENDER, message.gender);
return;
}
if (message instanceof ObjectAvatarSelectedMessage) {
this._selected = message.selected;
this._reportedLocation = null;
return;
}
if (message instanceof ObjectAvatarOwnMessage) {
model.setValue(RoomObjectVariable.OWN_USER, 1);
return;
}
}
private updateAvatarEffect(effect: number, delay: number, model: IRoomObjectModel): void {
if (effect === AvatarLogic.EFFECT_TYPE_SPLASH) {
this._effectChangeTimeStamp = GetTickerTime() + AvatarLogic.EFFECT_SPLASH_LENGTH;
this._newEffect = AvatarLogic.EFFECT_TYPE_SWIM;
} else if (effect === AvatarLogic.EFFECT_TYPE_SPLASH_DARK) {
this._effectChangeTimeStamp = GetTickerTime() + AvatarLogic.EFFECT_SPLASH_LENGTH;
this._newEffect = AvatarLogic.EFFECT_TYPE_SWIM_DARK;
} else if (model.getValue<number>(RoomObjectVariable.FIGURE_EFFECT) === AvatarLogic.EFFECT_TYPE_SWIM) {
this._effectChangeTimeStamp = GetTickerTime() + AvatarLogic.EFFECT_SPLASH_LENGTH;
this._newEffect = effect;
effect = AvatarLogic.EFFECT_TYPE_SPLASH;
} else if (model.getValue<number>(RoomObjectVariable.FIGURE_EFFECT) === AvatarLogic.EFFECT_TYPE_SWIM_DARK) {
this._effectChangeTimeStamp = GetTickerTime() + AvatarLogic.EFFECT_SPLASH_LENGTH;
this._newEffect = effect;
effect = AvatarLogic.EFFECT_TYPE_SPLASH_DARK;
} else if (delay === 0) {
this._effectChangeTimeStamp = 0;
} else {
this._effectChangeTimeStamp = GetTickerTime() + delay;
this._newEffect = effect;
return;
}
model.setValue(RoomObjectVariable.FIGURE_EFFECT, effect);
}
public override mouseEvent(event: RoomSpriteMouseEvent, geometry: IRoomGeometry): void {
let eventType: string = null;
switch (event.type) {
case MouseEventType.MOUSE_CLICK:
eventType = RoomObjectMouseEvent.CLICK;
break;
case MouseEventType.DOUBLE_CLICK:
eventType = RoomObjectMouseEvent.DOUBLE_CLICK;
break;
case MouseEventType.ROLL_OVER:
eventType = RoomObjectMouseEvent.MOUSE_ENTER;
if (this.object.model) this.object.model.setValue(RoomObjectVariable.FIGURE_HIGHLIGHT, 1);
if (this.eventDispatcher)
this.eventDispatcher.dispatchEvent(new RoomObjectFurnitureActionEvent(RoomObjectFurnitureActionEvent.MOUSE_BUTTON, this.object));
break;
case MouseEventType.ROLL_OUT:
eventType = RoomObjectMouseEvent.MOUSE_LEAVE;
if (this.object.model) this.object.model.setValue(RoomObjectVariable.FIGURE_HIGHLIGHT, 0);
if (this.eventDispatcher)
this.eventDispatcher.dispatchEvent(new RoomObjectFurnitureActionEvent(RoomObjectFurnitureActionEvent.MOUSE_ARROW, this.object));
break;
}
if (eventType && this.eventDispatcher)
this.eventDispatcher.dispatchEvent(
new RoomObjectMouseEvent(eventType, this.object, event.eventId, event.altKey, event.ctrlKey, event.shiftKey, event.buttonDown)
);
}
private randomTalkingPauseStartTimestamp(): number {
return 100 + Math.random() * 200;
}
private randomTalkingPauseEndTimestamp(): number {
return 75 + Math.random() * 75;
}
private randomBlinkStartTimestamp(): number {
return 4500 + Math.random() * 1000;
}
private randomBlinkEndTimestamp(): number {
return 50 + Math.random() * 200;
}
}