UNPKG

reldens

Version:
174 lines (161 loc) 5.56 kB
/** * * Reldens - TypePhysicalAttack * * Handles physical attack skills with collision detection, bullets, and PvE/PvP logic. * */ const { PhysicalAttack } = require('@reldens/skills'); const { sc } = require('@reldens/utils'); class TypePhysicalAttack extends PhysicalAttack { /** * @param {Object} props */ constructor(props) { super(props); /** @type {any|false} */ this.room = false; /** @type {any|false} */ this.currentBattle = false; /** @type {number} */ this.hitPriority = sc.get(props, 'hitPriority', 2); /** @type {any|false} */ this.animDir = sc.get(props, 'animDir', false); } /** * @param {Object} props * @returns {Promise<boolean|void>} */ async onHit(props) { // run bullets hit: let bulletsCheck = this.executeBullets(props); // if we have 0 bullets or both bodies are bullets, then we can skip the bullet hit check: if(1 !== bulletsCheck.length){ // @TODO - BETA - Implement bullets bodies without collisions between each other. return false; } let notTheBullet = 'body'+(bulletsCheck.shift().key === 'A' ? 'B' : 'A'); // get and validate the defender which could be a player or an object: let validDefender = this.getValidDefender(props, notTheBullet); if(!validDefender){ return false; } // run battle damage: await super.executeOnHit(validDefender); if(!validDefender?.state){ // Logger.info('Invalid defender, none State.', {key: validDefender?.key}); return false; } let hitKey = this.key+'_hit'; let hitMessage = { act: hitKey, x: validDefender.state.x, y: validDefender.state.y, owner: this.owner.broadcastKey, target: validDefender.broadcastKey }; this.room.broadcast('*', hitMessage); if(sc.hasOwn(this.owner, 'player_id') && sc.hasOwn(validDefender, 'objectBody') && this.currentBattle){ return await this.startPvE(validDefender); } return await this.sendUpdateFromPvP(validDefender); } /** * @param {Object} validDefender * @returns {Promise<boolean|void>} */ async sendUpdateFromPvP(validDefender) { // update the clients if pvp: if(!sc.hasOwn(validDefender, 'player_id')){ return false; } let targetClient = this.room.getClientById(validDefender.broadcastKey); if(!targetClient){ return false; } await this.currentBattle.updateTargetClient( targetClient, validDefender, this.owner.sessionId, this.room, this.owner ); } /** * @param {Object} validDefender * @returns {Promise<any>} */ async startPvE(validDefender) { if(0 < validDefender.stats[this.room.config.get('client/actions/skills/affectedProperty')]){ return await this.restartBattle(validDefender); } return await this.currentBattle.battleEnded(this.owner, this.room); } /** * @param {Object} validDefender * @returns {Promise<void>} */ async restartBattle(validDefender) { if(!this.validateTargetOnHit && sc.hasOwn(validDefender, 'battle')){ if(!validDefender.battle){ return; } // if target validation is disabled then any target could start the battle (pve): validDefender.battle.targetObject = validDefender; await validDefender.battle.startBattleWith(this.owner, this.room); return; } // if target validation is enabled, then we can only start the battle with the target: await this.currentBattle.startBattleWith(this.owner, this.room); } /** * @param {Object} props * @returns {Array} */ executeBullets(props) { let bulletsCheck = []; // @TODO - BETA - Replace all the defaults by constants. // both objects could be bullets, so remove them is needed and broadcast the hit: if(props.bodyA.isBullet){ this.removeBullet(props.bodyA); bulletsCheck.push({key: 'bodyA', obj: props.bodyA}); } if(props.bodyB.isBullet){ this.removeBullet(props.bodyB); bulletsCheck.push({key: 'bodyB', obj: props.bodyB}); } return bulletsCheck; } /** * @param {Object} props * @param {string} defenderBodyKey * @returns {Object} */ getValidDefender(props, defenderBodyKey) { // we already validate if one of the bodies is a bullet so the other will be always a player or an object: let playerId = sc.get(props[defenderBodyKey], 'playerId', null); if(null !== playerId){ return this.room.playerBySessionIdFromState(playerId); } return props[defenderBodyKey].roomObject; } /** * @param {Object} body */ removeBullet(body) { if(body.world){ body.world.removeBodies.push(body); } this.room.state.removeBody(this.key+'_bullet_'+body.id); } } module.exports = TypePhysicalAttack;