UNPKG

reldens

Version:
142 lines (130 loc) 4.71 kB
/** * * 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;