const Phaser = require('phaser'); const { TEXT, POSITIONS: { COMBAT } } = require('./constants'); const CRYP_KEY_MAP = ['keydown_ONE', 'keydown_TWO', 'keydown_THREE']; const SKILL_KEY_MAP = ['keydown_Q', 'keydown_W', 'keydown_E', 'keydown_R']; const TARGET_KEY_MAP = ['keydown_SEVEN', 'keydown_EIGHT', 'keydown_NINE', 'keydown_ZERO']; const CRYP_MARGIN = COMBAT.crypMargin(); const TEXT_MARGIN = COMBAT.textMargin(); const SKILL_WIDTH = COMBAT.width() / 10; const SKILL_HEIGHT = COMBAT.height() / 30; const skillPosition = (crypIter, skillIter) => { const skillTextX = COMBAT.width() / 3.8; const skillTextY = (TEXT_MARGIN * skillIter) * 1.5 + CRYP_MARGIN * crypIter + COMBAT.y() + COMBAT.height() * 0.07; return [skillTextX, skillTextY]; }; const skillCheckHitBox = (scenePlugin, pointer) => { const { list } = scenePlugin.get('CombatHitBox').children; for (let i = 0; i < list.length; i += 1) { if (Phaser.Geom.Rectangle.ContainsPoint(list[i].getBounds(), pointer.position)) return list[i]; } // If we didn't find a hitbox deselect them all for (let i = 0; i < list.length; i += 1) list[i].deselect(); return false; }; class CrypSkill extends Phaser.GameObjects.Container { constructor(scene, x, y, skill, cryp) { // Avatar will be a property of cryp super(scene, x, y); const CD_TEXT = skill.cd ? `(${skill.cd}T)` : ''; const SKILL_TEXT = `${skill.skill} ${CD_TEXT}`; this.origX = x; this.origY = y; this.skillBox = scene.add.rectangle(0, 0, SKILL_WIDTH, SKILL_HEIGHT, 0x222222); this.skillText = scene.add.text(0, 0, SKILL_TEXT, TEXT.NORMAL).setOrigin(0.5, 0.5); this.add(this.skillBox); this.add(this.skillText); this.state = 'deselect'; this.cryp = cryp; this.skill = skill; this.scene = scene; this.setSize(SKILL_WIDTH, SKILL_HEIGHT); this.setInteractive(); } clickHandler() { if (this.scene.phase === 'Skill') this.scene.activeSkill = this; this.select(); } select() { this.scene.children.list.forEach((skill) => { if (skill.state === 'select') skill.deselect(); }); this.skillBox.setFillStyle(0x004bfe); this.state = 'select'; } activate() { this.scene.children.list.forEach((skill) => { if (skill.state === 'select') skill.deselect(); }); this.skillBox.setFillStyle(0xff0000); this.state = 'activate'; } deselect() { this.skillBox.setFillStyle(0x222222); this.state = 'deselect'; } } class CombatSkills extends Phaser.Scene { constructor() { super({ key: 'CombatSkills' }); } create(phase) { this.phase = phase; this.registry.events.off('changedata', this.updateData); this.registry.events.on('changedata', this.updateData, this); this.account = this.registry.get('account'); this.input.on('dragstart', (pointer, box) => { box.clickHandler(); }); this.input.on('drag', (pointer, box, dragX, dragY) => { const hitBox = skillCheckHitBox(this.scene, pointer); if (hitBox) hitBox.select(); box.setPosition(dragX, dragY); }); this.input.on('dragend', (pointer, box) => { box.deselect(); const hitBox = skillCheckHitBox(this.scene, pointer); if (hitBox) { hitBox.clickHandler(); } box.setPosition(box.origX, box.origY); }); if (phase === 'animating') return true; // can't set this.game cause of phaser class named the same const game = this.registry.get('game'); this.renderSkills(game, phase); return true; } updateData(parent, key, data) { if (key === 'gamePhase' && data) { const shouldUpdate = data !== this.phase; if (shouldUpdate) { this.scene.get('CombatCryps').selectCryp(null); return this.scene.restart(data); } return false; } return true; } renderSkills(game, phase) { if (phase === 'Skill') return this.renderSkillPhase(game); return false; } renderSkillPhase(game) { const { account } = this; const { keyboard } = this.input; const { events } = this.game; const addSkill = (i, j, skill, cryp) => { const skillTextPos = skillPosition(i, j); const skillObj = new CrypSkill(this, skillTextPos[0], skillTextPos[1], skill, cryp); if (skill.cd) { skillObj.skillBox.setFillStyle(0x9d9ea0); } else { this.input.setDraggable(skillObj); } this.add.existing(skillObj); return skillObj; }; const team = game.teams.find(t => t.id === account.id); const enemyTeam = game.teams.find(t => t.id !== account.id); team.cryps.forEach((cryp) => { // return early if KOd if (cryp.hp.base === 0) return true; // find the cryp position const { iter } = this.scene.get('CombatCryps').cryps.children.entries.find(c => c.cryp.id === cryp.id); // draw the skills const skillButtons = cryp.skills.map((skill, j) => addSkill(iter, j, skill, cryp)); const bindCrypKeys = () => this.mapSkillKeys(skillButtons, game.id, cryp.id, team.id, enemyTeam.id, iter); // reset everything keyboard.on('keydown_ESC', bindCrypKeys, this); events.on('SEND_SKILL', bindCrypKeys, this); bindCrypKeys(); return true; }); return true; } // FIXME // needs to send crypId not team mapSkillKeys(skillButtons, gameId, crypId, alliesId, enemyId, i) { const { keyboard } = this.input; keyboard.removeListener(CRYP_KEY_MAP[i]); keyboard.on(CRYP_KEY_MAP[i], () => { SKILL_KEY_MAP.forEach(k => keyboard.removeListener(k)); this.scene.get('CombatCryps').selectCryp(crypId); skillButtons.forEach((button, j) => { keyboard.on(SKILL_KEY_MAP[j], () => { this.activeSkill = button; button.select(); // clear existing keys CRYP_KEY_MAP.forEach(k => keyboard.removeListener(k)); TARGET_KEY_MAP.forEach(k => keyboard.removeListener(k)); CRYP_KEY_MAP.forEach(k => keyboard.on(k, () => { this.clearCrypActive(crypId); button.activate(); this.activeSkill = null; this.game.events.emit('SEND_SKILL', gameId, crypId, alliesId, button.skill.skill); })); TARGET_KEY_MAP.forEach(k => keyboard.on(k, () => { this.clearCrypActive(crypId); button.activate(); this.activeSkill = null; this.game.events.emit('SEND_SKILL', gameId, crypId, enemyId, button.skill.skill); })); }, this); }); }, this); return true; } clearCrypActive(crypId) { this.scene.scene.children.list.forEach((s) => { if (s.cryp.id === crypId && s.state === 'activate') s.deselect(); }); } clearKeys() { TARGET_KEY_MAP.forEach(tKey => this.input.keyboard.removeListener(tKey)); CRYP_KEY_MAP.forEach(tKey => this.input.keyboard.removeListener(tKey)); SKILL_KEY_MAP.forEach(tKey => this.input.keyboard.removeListener(tKey)); } cleanUp() { this.registry.events.off('changedata', this.updateData); this.scene.remove(); } } module.exports = CombatSkills;