UNPKG

reldens

Version:
434 lines (404 loc) 13.7 kB
/** * * Reldens - LifebarUi * * Manages health/life bar UI for players and objects in the game. * */ const { UsersConst } = require('../constants'); const { ActionsConst } = require('../../actions/constants'); const { GameConst } = require('../../game/constants'); const { ObjectsConst } = require('../../objects/constants'); const { ObjectsHandler } = require('./objects-handler'); const { sc } = require('@reldens/utils'); /** * @typedef {import('@reldens/utils').EventsManager} EventsManager */ class LifebarUi { /** * @param {Object} props */ constructor(props) { /** @type {EventsManager} */ this.events = props.events; } /** * @param {Object} gameManager * @returns {boolean|Object} */ createLifeBarUi(gameManager) { // @TODO - BETA - General refactor, extract methods into different services. this.barConfig = gameManager.config.get('client/ui/lifeBar'); if(!this.barConfig.enabled){ return false; } this.gameManager = gameManager; this.fixedPositionX = false; this.fixedPositionY = false; this.barProperty = this.gameManager.config.get('client/actions/skills/affectedProperty'); this.playerSize = this.gameManager.config.get('client/players/size'); this.lifeBars = {}; this.lifeDataByKey = {}; this.listenEvents(); return this; } listenEvents() { this.events.on('reldens.playerStatsUpdateAfter', (message, roomEvents) => { this.updatePlayerLifeBar(message, roomEvents); }); this.events.on('reldens.joinedRoom', (room) => { this.listenMessages(room); }); this.events.on('reldens.runPlayerAnimation', (playerEngine, playerId) => { this.drawPlayerLifeBar(playerId); }); this.events.on('reldens.updateGameSizeBefore', (gameEngine, newWidth, newHeight) => { this.drawOnGameResize(newWidth, newHeight); }); this.events.on('reldens.playersOnRemove', (player, key) => { this.removePlayerLifeBar(key); }); this.events.on('reldens.playerEngineAddPlayer', () => { this.processLifeBarQueue(); }); this.events.on('reldens.createAnimationAfter', () => { ObjectsHandler.drawObjectsLifeBar(this); }); this.events.on('reldens.objectBodyChanged', (event) => { ObjectsHandler.generateObjectLifeBar(event.key, this); }); this.events.on('reldens.gameEngineShowTarget', (gameEngine, target, previousTarget) => { this.showTargetLifeBar(target, previousTarget); }); this.events.on('reldens.gameEngineClearTarget', (gameEngine, previousTarget) => { this.clearPreviousBar(previousTarget); }); } /** * @param {number} newWidth * @param {number} newHeight * @returns {boolean} */ drawOnGameResize(newWidth, newHeight) { if(!this.barConfig.fixedPosition){ return false; } this.setPlayerLifeBarFixedPosition(newWidth, newHeight); this.drawPlayerLifeBar(this.gameManager.getCurrentPlayer().playerId); } /** * @param {Object} previousTarget * @returns {void} */ clearPreviousBar(previousTarget) { if( previousTarget && sc.hasOwn(this.lifeBars, previousTarget.id) && this.gameManager.getCurrentPlayer().playerId !== previousTarget.id ){ this.lifeBars[previousTarget.id].destroy(); } } /** * @param {Object} target * @param {Object} previousTarget * @returns {boolean} */ showTargetLifeBar(target, previousTarget) { if(!this.barConfig.showOnClick){ return false; } this.clearPreviousBar(previousTarget); if(target.type === ObjectsConst.TYPE_OBJECT){ ObjectsHandler.generateObjectLifeBar(target.id, this); } if(target.type === GameConst.TYPE_PLAYER){ this.drawPlayerLifeBar(target.id); } } /** * @returns {string} */ barPropertyValue() { return this.barProperty+'Value'; } /** * @returns {string} */ barPropertyTotal() { return this.barProperty+'Total'; } /** * @param {number} [newWidth] * @param {number} [newHeight] * @returns {void} */ setPlayerLifeBarFixedPosition(newWidth, newHeight) { if(!newWidth || !newHeight){ let position = this.gameManager.gameEngine.getCurrentScreenSize(this.gameManager); newWidth = position.newWidth; newHeight = position.newHeight; } let {uiX, uiY} = this.gameManager.gameEngine.uiScene.getUiConfig('lifeBar', newWidth, newHeight); this.fixedPositionX = uiX; this.fixedPositionY = uiY; } /** * @param {Object} message * @param {Object} roomEvents * @returns {void} */ updatePlayerLifeBar(message, roomEvents) { let currentPlayer = roomEvents.gameManager.getCurrentPlayer(); this.updatePlayerBarData( currentPlayer.playerId, message.statsBase[this.barProperty], message.stats[this.barProperty] ); this.drawPlayerLifeBar(currentPlayer.playerId); } /** * @param {Object} room * @returns {void} */ listenMessages(room) { room.onMessage('*', (message) => { this.listenBattleEnd(message); this.listenLifeBarUpdates(message); }); } /** * @param {Object} message * @returns {boolean} */ listenBattleEnd(message) { if(message.act !== ActionsConst.BATTLE_ENDED){ return false; } if(!sc.hasOwn(this.lifeBars, message.t)){ return false; } this.lifeBars[message.t].destroy(); } /** * @param {Object} message * @returns {boolean} */ listenLifeBarUpdates(message) { if(message.act !== UsersConst.ACTION_LIFEBAR_UPDATE){ return false; } ObjectsHandler.processObjectLifeBarMessage(message, true, this); this.processPlayerLifeBarMessage(message, true); } /** * @param {string} playerId * @returns {boolean} */ canShowPlayerLifeBar(playerId) { let currentPlayer = this.gameManager.getCurrentPlayer(); if(!sc.isFunction(currentPlayer?.isDeath)){ // expected, when changing scenes the next scene could not be active yet return false; } let isCurrentPlayer = playerId === currentPlayer?.playerId; if(isCurrentPlayer && currentPlayer && (currentPlayer.isDeath() || currentPlayer.isDisabled())){ this.lifeBars[playerId]?.setVisible(false); return false; } if(isCurrentPlayer){ return this.barConfig.showCurrentPlayer; } if(this.barConfig.showAllPlayers){ // @TODO - BETA - Include validation for other players inState. return true; } return this.barConfig.showOnClick && playerId === this.getCurrentTargetId(); } /** * @param {Object} message * @returns {void} */ queueLifeBarMessage(message) { if(!sc.hasOwn(this.gameManager, 'lifeBarQueue')){ this.gameManager.lifeBarQueue = []; } this.gameManager.lifeBarQueue.push(message); } /** * @param {Object} message * @param {boolean} [queue] * @returns {boolean} */ processPlayerLifeBarMessage(message, queue = false) { if(ActionsConst.DATA_TYPE_VALUE_PLAYER !== message[ActionsConst.DATA_OWNER_TYPE]){ return false; } let currentPlayer = this.gameManager.getCurrentPlayer(); let messageOwnerKey = message[ActionsConst.DATA_OWNER_KEY]; if(!currentPlayer || !currentPlayer.players || !currentPlayer.players[messageOwnerKey]){ if(queue){ this.queueLifeBarMessage(message); } return false; } this.updatePlayerBarData(messageOwnerKey, message.totalValue, message.newValue); if(this.canShowPlayerLifeBar(messageOwnerKey)){ this.drawPlayerLifeBar(messageOwnerKey); } return true; } /** * @param {string} playerId * @param {number} total * @param {number} newValue * @returns {void} */ updatePlayerBarData(playerId, total, newValue) { let currentPlayer = this.gameManager.getCurrentPlayer(); currentPlayer.players[playerId][this.barPropertyTotal()] = total; currentPlayer.players[playerId][this.barPropertyValue()] = newValue; } /** * @returns {boolean} */ processLifeBarQueue() { if(0 === this.gameManager.lifeBarQueue.length){ return false; } let forDelete = []; for(let message of this.gameManager.lifeBarQueue){ if(ObjectsHandler.processObjectLifeBarMessage(message, false, this)){ forDelete.push(message); } if(this.processPlayerLifeBarMessage(message, false)){ forDelete.push(message); } } if(0 < forDelete.length){ this.gameManager.lifeBarQueue = this.gameManager.lifeBarQueue.filter(item => !forDelete.includes(item)); } } /** * @param {string} playerId * @returns {boolean|Object} */ drawPlayerLifeBar(playerId) { this.destroyByKey(playerId); if(!this.canShowPlayerLifeBar(playerId)){ this.lifeBars[playerId]?.setVisible(false); return false; } let barData = this.prepareBarData(playerId); let barHeight = this.barConfig.height; let barTop = this.barConfig.top; let fullBarWidth = this.barConfig.width; let uiX = barData.player.x-(fullBarWidth/2); let uiY = barData.player.y-barHeight-barTop+(barData.ownerTop/2); if(playerId === this.gameManager.getCurrentPlayer().playerId && this.barConfig.fixedPosition){ // if the position is fixed then the bar has to go on the ui scene: this.lifeBars[playerId] = this.gameManager.getActiveScenePreloader().add.graphics(); if(this.fixedPositionX === false || this.fixedPositionY === false){ this.setPlayerLifeBarFixedPosition(); } uiX = this.fixedPositionX; uiY = this.fixedPositionY; } else { // otherwise, the bar will be added in the current scene: this.lifeBars[playerId] = this.gameManager.getActiveScene().add.graphics(); } this.drawBar(this.lifeBars[playerId], barData.fullValue, barData.filledValue, uiX, uiY); return this; } /** * @param {string} barKey * @returns {void} */ destroyByKey(barKey) { if(sc.hasOwn(this.lifeBars, barKey)){ this.lifeBars[barKey].destroy(); } } /** * @param {string} playerId * @returns {Object} */ prepareBarData(playerId) { let player = this.gameManager.getCurrentPlayer().players[playerId]; let fullValue = player[this.barPropertyTotal()]; let filledValue = player[this.barPropertyValue()]; let ownerTop = sc.get(player, 'topOff', 0)-this.playerSize.height; return {player, fullValue, filledValue, ownerTop}; } /** * @param {string} playerId * @returns {boolean} */ removePlayerLifeBar(playerId) { if(!sc.hasOwn(this.lifeBars, playerId)){ return false; } this.lifeBars[playerId].destroy(); delete this.lifeBars[playerId]; } /** * @param {Object} lifeBarGraphic * @param {number} fullValue * @param {number} filledValue * @param {number} uiX * @param {number} uiY * @returns {void} */ drawBar(lifeBarGraphic, fullValue, filledValue, uiX, uiY) { let barHeight = this.barConfig.height; let fullBarWidth = this.barConfig.width; let filledBarWidth = (filledValue*fullBarWidth)/fullValue; lifeBarGraphic.clear(); lifeBarGraphic.fillStyle(parseInt(this.barConfig.fillStyle), 1); lifeBarGraphic.fillRect(uiX, uiY, filledBarWidth, barHeight); lifeBarGraphic.lineStyle(1, parseInt(this.barConfig.lineStyle)); lifeBarGraphic.strokeRect(uiX, uiY, fullBarWidth, barHeight); lifeBarGraphic.alpha = 0.6; lifeBarGraphic.setDepth(300000); } /** * @returns {string|boolean} */ getCurrentTargetId() { return sc.get(this.gameManager.getCurrentPlayer()?.currentTarget, 'id', false); } /** * @param {string} objectKey * @returns {Object|boolean} */ getObjectByKey(objectKey) { return sc.get(this.gameManager.getActiveScene()?.objectsAnimations, objectKey, false); } } module.exports.LifebarUi = LifebarUi;