mnml/client/src/scenes/combat.skills.js
2019-01-14 12:26:01 +10:00

236 lines
7.8 KiB
JavaScript

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;