reldens
Version:
Reldens - MMORPG Platform
142 lines (130 loc) • 4.71 kB
JavaScript
/**
*
* Reldens - NpcObject
*
* Non-Player Character object with interactive capabilities (dialogs, options).
*
*/
const { AnimationObject } = require('./animation-object');
const { GameConst } = require('../../../../game/constants');
const { ObjectsConst } = require('../../../constants');
const { Logger, sc } = require('@reldens/utils');
class NpcObject extends AnimationObject
{
/**
* @param {Object} props
*/
constructor(props)
{
super(props);
// this is a hardcoded property for this specific object type:
this.type = ObjectsConst.TYPE_NPC;
this.hasAnimation = true;
this.collisionResponse = true;
this.eventsPrefix = this.uid+'.'+ObjectsConst.EVENT_PREFIX.NPC;
this.listenMessages = true;
// interactive objects will react on click:
this.clientParams.type = ObjectsConst.TYPE_NPC;
this.clientParams.isInteractive = true;
// @NOTE: interaction area is how far the player can be from the object to validate the actions on click, this
// area will be the valid-margin surrounding the object.
this.interactionArea = this.config.get('server/objects/actions/interactionsDistance');
this.closeInteractionOnOutOfReach = this.config.getWithoutLogs(
'server/objects/actions/closeInteractionOnOutOfReach',
true
);
this.sendInvalidOptionMessage = false;
this.invalidOptionMessage = ObjectsConst.SNIPPETS.NPC_INVALID;
this.mapClientParams(props);
this.mapPrivateParams(props);
}
/**
* @param {Object} client
* @param {Object} data
* @param {Object} room
* @param {Object} playerSchema
* @returns {Promise<boolean|undefined>}
*/
async executeMessageActions(client, data, room, playerSchema)
{
// validate for object interaction, object id and interaction area:
if(false === this.isValidId(data)){
return false;
}
let isObjectOptionInteractionMessage = this.isObjectOptionInteractionMessage(data);
if(false === this.isObjectInteractionMessage(data) && false === isObjectOptionInteractionMessage){
return false;
}
if(true === isObjectOptionInteractionMessage && false === this.isValidOptionIndexValue(data.value, client)){
Logger.error('Object "'+this.key+'" invalid option "'+data.value+'" from client "'+client.sessionId+'"');
return false;
}
if(false === this.isValidInteraction(playerSchema.state.x, playerSchema.state.y)){
this.outOfReachClose(client);
return false;
}
let activationData = {act: GameConst.UI, id: this.id};
if(this.title){
activationData.title = this.title;
}
if(this.content){
activationData.content = this.content;
}
if(0 < Object.keys(this.options).length){
// @TODO - BETA - Extend feature to generate different flows, this will help on easily create quests, for
// example we could request confirmation about a choice.
activationData.options = this.options;
}
client.send('*', activationData);
}
/**
* @param {Object} client
*/
outOfReachClose(client)
{
if(!this.closeInteractionOnOutOfReach){
return false;
}
client.send('*', {act: GameConst.CLOSE_UI_ACTION, id: this.id});
}
/**
* @param {Object} data
* @returns {boolean}
*/
isValidId(data)
{
return Number(this.id) === Number(sc.get(data, 'id', false));
}
/**
* @param {Object} data
* @returns {boolean}
*/
isObjectInteractionMessage(data)
{
return (ObjectsConst.OBJECT_INTERACTION).toString() === (sc.get(data, 'act', '')).toString();
}
/**
* @param {Object} data
* @returns {boolean}
*/
isObjectOptionInteractionMessage(data)
{
return (GameConst.BUTTON_OPTION).toString() === (sc.get(data, 'act', '')).toString();
}
/**
* @param {string} optionIdx
* @param {Object} client
* @returns {boolean}
*/
isValidOptionIndexValue(optionIdx, client)
{
if(sc.hasOwn(this.options, optionIdx)){
return true;
}
if(this.sendInvalidOptionMessage){
client.send('*', {act: GameConst.UI, id: this.id, content: this.invalidOptionMessage});
}
return false;
}
}
module.exports.NpcObject = NpcObject;