const Phaser = require('phaser'); const genAvatar = require('./avatar'); const StatBar = require('./elements/combat.statbar'); const { DELAYS, TEXT, POSITIONS: { COMBAT } } = require('./constants'); const CRYP_MARGIN = COMBAT.crypMargin(); const TEXT_MARGIN = COMBAT.textMargin(); const crypAvatarText = (team, iter) => { const nameX = COMBAT.width() * team; const nameY = COMBAT.y() + CRYP_MARGIN * iter + COMBAT.height() * 0.07; const statusX = COMBAT.width() * team; const statusY = COMBAT.y() + TEXT_MARGIN * 6 + CRYP_MARGIN * iter + COMBAT.height() * 0.07; return { statusX, statusY, nameX, nameY }; }; const crypEffects = (team, iter) => { const crypEffectsX = team ? COMBAT.width() - COMBAT.width() / 6.5 : COMBAT.width() / 6.5; const crypEffectsY = TEXT_MARGIN * 2 + CRYP_MARGIN * iter; return { crypEffectsX, crypEffectsY }; }; const crypPosition = (team, iter) => { const crypAvatarX = team ? COMBAT.width() - COMBAT.width() / 6 : COMBAT.width() / 6; const crypAvatarY = TEXT_MARGIN * 5 + CRYP_MARGIN * iter; return { crypAvatarX, crypAvatarY }; }; class Effects extends Phaser.GameObjects.Group { constructor(scene, team, iter) { super(scene); this.scene = scene; const { crypEffectsX, crypEffectsY } = crypEffects(team, iter); this.x = crypEffectsX; this.y = crypEffectsY; this.effectCount = 0; } addEffect(effect) { const y = this.y + this.effectCount * TEXT_MARGIN; const text = `${effect.effect} for ${effect.duration} turn`; const e = this.scene.add.text(this.x, y, text, TEXT.NORMAL); e.effect = effect.effect; this.add(e); this.effectCount += 1; } removeEffect(effect) { this.children.entries.forEach((e) => { if (e.effect === effect) e.destroy(); }); } update(effects) { this.effectCount = 0; this.children.entries.forEach(e => e.destroy()); effects.forEach((effect) => { this.addEffect(effect); }); return true; } } class CrypImage extends Phaser.GameObjects.Image { constructor(scene, team, iter, cryp) { // Get coords const { crypAvatarX, crypAvatarY } = crypPosition(team, iter); const { statusX, statusY, nameX, nameY } = crypAvatarText(team, iter); // Cryp display // const avatar = team ? 'magmar' : 'alk'; super(scene, crypAvatarX, crypAvatarY, 'aztec', genAvatar(cryp.name)); this.setScale(0.5); if (!team) this.flipX = true; // Save position and cryp details this.scene = scene; this.iter = iter; this.team = team; this.cryp = cryp; this.state = 'deselect'; // Add cryp name scene.add.text(nameX, nameY, cryp.name, TEXT.NORMAL).setOrigin(team, 0); // Add cryp stat bars this.health = scene.add.existing(new StatBar(scene, this, 'HP')); this.red_shield = scene.add.existing(new StatBar(scene, this, 'Red Shield')); this.blue_shield = scene.add.existing(new StatBar(scene, this, 'Blue Shield')); // this.evasion = scene.add.existing(new StatBar(scene, this, 'Evasion')); this.effects = scene.add.existing(new Effects(scene, team, iter)); this.statusText = scene.add.text(statusX, statusY, '', TEXT.NORMAL); } select() { this.setTint('0x00bb00'); this.state = 'select'; } setKo() { this.state = 'ko'; this.setTint('0x9d9ea0'); } deselect() { if (this.state !== 'ko') { this.clearTint(); this.state = 'deselect'; } } clearStatus() { this.statusText.text = ''; } reduceDefense(amount, type) { if (type === 'PhysDmg') { this.red_shield.takeDamage(amount); } else if (type === 'BlueDmg') { this.blue_shield.takeDamage(amount); } } takeDamage(props) { const { amount, mitigation, category } = props; if (mitigation) this.reduceDefense(mitigation, category); this.setTint(0xff0000); this.health.takeDamage(amount); this.scene.time.delayedCall(DELAYS.DAMAGE_TICK, () => { if (this.state !== 'ko') this.clearTint(); }); } takeHealing(amount) { this.setTint(0x00bb00); this.health.takeDamage(amount * -1); this.scene.time.delayedCall(DELAYS.DAMAGE_TICK, () => { if (this.state !== 'ko') this.clearTint(); }); } } class CombatCryps extends Phaser.Scene { constructor() { super({ key: 'CombatCryps' }); } create(game) { this.cryps = this.add.group(); this.phase = game.phase; this.account = this.registry.get('account'); this.drawCryps(game); this.registry.events.on('changedata', this.updateData, this); this.registry.set('crypStatusUpdate', false); this.teams = game.teams.length; } updateData(parent, key, data) { if (key === 'game' && data) { if (data.teams.length !== this.teams) this.scene.restart(data); const isAnimating = this.phase === 'animating'; this.game = data; if (isAnimating) return false; } if (key === 'gamePhase' && data) { const shouldUpdate = data !== this.phase; this.phase = data; if (shouldUpdate) { this.cryps.children.entries.forEach(c => c.clearStatus()); this.drawCryps(this.game); } } if (key === 'crypStatusUpdate' && data) { this.updateCrypStatus(data); } return true; } drawCryps(game) { const renderCryp = (cryp, iter, team) => { // Add Image Avatar Class const crypObj = new CrypImage(this, team, iter, cryp); this.add.existing(crypObj); this.cryps.add(crypObj); return crypObj; }; const renderTeam = (cryp, iter, team) => { const crypObj = this.cryps.children.entries .find(c => c.cryp.id === cryp.id) || renderCryp(cryp, iter, team); crypObj.health.val = cryp.hp.value; crypObj.red_shield.val = cryp.red_shield.value; crypObj.blue_shield.val = cryp.red_shield.value; crypObj.health.drawStatBar(); crypObj.red_shield.drawStatBar(); crypObj.blue_shield.drawStatBar(); crypObj.effects.update(cryp.effects); }; const allyTeam = game.teams.find(t => t.id === this.account.id); // in future there will be more than one const [enemyTeam] = game.teams.filter(t => t.id !== this.account.id); allyTeam.cryps.forEach((cryp, i) => renderTeam(cryp, i, 0)); if (!enemyTeam) return false; enemyTeam.cryps.forEach((cryp, i) => renderTeam(cryp, i, 1)); return true; } selectCryp(crypId) { this.cryps.children.entries.forEach(c => c.deselect()); if (crypId) this.cryps.children.entries.find(c => c.cryp.id === crypId).select(); } updateCrypStatus(status) { const sourceCryp = this.cryps.children.entries .find(c => c.cryp.id === status.id); const targetCryp = this.cryps.children.entries .find(c => c.cryp.id === status.target); if (this.phase === 'Skill') { sourceCryp.statusText.text = `${status.skill} on ${targetCryp.cryp.name}`; } } cleanUp() { this.registry.events.off('changedata', this.updateData); this.scene.remove(); } } module.exports = CombatCryps;