summaryrefslogtreecommitdiff
path: root/script.js
diff options
context:
space:
mode:
Diffstat (limited to 'script.js')
-rw-r--r--script.js1152
1 files changed, 0 insertions, 1152 deletions
diff --git a/script.js b/script.js
deleted file mode 100644
index 2fab2fc..0000000
--- a/script.js
+++ /dev/null
@@ -1,1152 +0,0 @@
-const DB = {
- allMonsters: [],
- allAnimations: {},
- monsters: {},
- shapes: {},
- elements: {},
- techniques: {},
- statusEffects: {},
-};
-
-const ElementType = {
- aether: 'aether',
- wood: 'wood',
- fire: 'fire',
- earth: 'earth',
- metal: 'metal',
- water: 'water',
-
- /* lightning: 'lightning',
- frost: 'frost',
- venom: 'venom',
- //vermin: 'vermin',
- cosmic: 'cosmic',
- battle: 'battle',
- psionic: 'psionic',
- darkness: 'darkness',
- heaven: 'heaven',
-
- combineTypes(typeA, typeB) {
- if (typeA === ElementType.earth & typeB === ElementType.fire) {
- return ElementType.lightning;
- }
- if (typeA === ElementType.earth & typeB === ElementType.water) {
- return ElementType.frost;
- }
- if (typeA === ElementType.earth & typeB === ElementType.wood) {
- return ElementType.venom;
- }
- // if (typeA === ElementType.earth & typeB === ElementType.metal) {
- // return ElementType.vermin;
- // }
- if (typeA === ElementType.fire && typeB === ElementType.water) {
- return ElementType.cosmic;
- }
- } */
-};
-const ElementTypeColor = {
- [ElementType.aether]: 'rgba(255, 255, 255, 1)',
- [ElementType.wood]: '#3ca6a6',
- [ElementType.fire]: '#ca3c3c',
- [ElementType.earth]: '#eac93c',
- [ElementType.metal]: '#e4e4e4',
- [ElementType.water]: '#3c3c3c',
-};
-const TasteWarm = {
- tasteless: 'tasteless',
- peppy: 'peppy',
- salty: 'salty',
- hearty: 'hearty',
- zesty: 'zesty',
- refined: 'refined',
-};
-const TasteCold = {
- tasteless: 'tasteless',
- mild: 'mild',
- sweet: 'sweet',
- soft: 'soft',
- flakey: 'flakey',
- dry: 'dry',
-};
-const TechniqueRange = {
- melee: 'melee',
- touch: 'touch',
- ranged: 'ranged',
- reach: 'reach',
- reliable: 'reliable',
-};
-const StatusType = {
- melee: 'melee',
- armour: 'armour',
- ranged: 'ranged',
- dodge: 'dodge',
- speed: 'speed',
-};
-const StatusEffectType = {
- blinded: 'blinded',
- burn: 'burn',
- chargedup: 'chargedup',
- charging: 'charging',
- confused: 'confused',
- diehard: 'diehard',
- dozing: 'dozing',
- elementalshield: 'elementalshield',
- eliminated: 'eliminated',
- enraged: 'enraged',
- exhausted: 'exhausted',
- faint: 'faint',
- feedback: 'feedback',
- festering: 'festering',
- flinching: 'flinching',
- focused: 'focused',
- grabbed: 'grabbed',
- hardshell: 'hardshell',
- harpooned: 'harpooned',
- lifeleech: 'lifeleech',
- lockdown: 'lockdown',
- noddingoff: 'noddingoff',
- poison: 'poison',
- prickly: 'prickly',
- recover: 'recover',
- slow: 'slow',
- sniping: 'sniping',
- softened: 'softened',
- stuck: 'stuck',
- tired: 'tired',
- wasting: 'wasting',
- wild: 'wild',
-};
-
-class State {
- money = 0;
- monsters = [];
-
- inventory = [];
-
- partyMonsters = [];
-
- activeMonster = null;
- activeTechnique = null;
-
- turn = 0;
- currentArea = null;
-
- enemy = {
- monster: null,
- };
-};
-
-class Monster {
- #level = 1;
- #hp = 0;
-
- exp = 1;
-
- tasteWarm = TasteWarm.tasteless;
- tasteCold = TasteCold.tasteless;
-
- gender = '';
-
- heldItem = null;
- statusEffect = '';
-
- statusModifier = {
- hp: 0,
- melee: 0,
- armour: 0,
- ranged: 0,
- dodge: 0,
- speed: 0,
- };
-
- experienceModifier = 1;
- moneyModifier = 1;
-
- activeTechniques = [];
-
- constructor (slug) {
- this.slug = slug;
-
- const tasteWarm = Object.keys(TasteWarm).slice(1);
- this.tasteWarm = tasteWarm[Math.floor(Math.random() * tasteWarm.length)];
- const tasteCold = Object.keys(TasteCold).slice(1);
- this.tasteCold = tasteCold[Math.floor(Math.random() * tasteCold.length)];
-
- this.hp = this.status.hp;
-
- const possibleGenders = DB.monsters[this.slug].possible_genders;
- this.gender = possibleGenders[Math.floor(Math.random() * possibleGenders.length)]
- }
-
- get shape () {
- for (const shapeData of DB.shapes) {
- if (shapeData.slug === DB.monsters[this.slug].shape) {
- return shapeData;
- }
- }
- }
-
- get types () {
- return DB.monsters[this.slug].types;
- }
-
- get moveset () {
- return DB.monsters[this.slug].moveset;
- }
-
- get evolutions () {
- return DB.monsters[this.slug].evolutions;
- }
-
- get level () {
- return this.#level;
- }
-
- set level (level) {
- const statusPreLevelUp = this.status;
- const hpPreLevelUp = this.hp;
-
- this.#level = level;
-
- const statusPostLevelUp = this.status;
-
- this.hp = statusPostLevelUp.hp - (statusPreLevelUp.hp - hpPreLevelUp);
-
- if (this.exp < this.getExperienceRequired(-1)) {
- this.exp = this.getExperienceRequired(-1);
- }
- }
-
- get hp () {
- return this.#hp;
- }
-
- set hp (hp) {
- this.#hp = Math.max(0, Math.min(hp, this.status.hp));
- }
-
- get name () {
- return slugToName(this.slug);
- }
-
- getLearnableTechniques () {
- return this.moveset.filter((move) => this.level >= move.learned_at);
- }
-
- canLevelUp () {
- return this.exp >= this.getExperienceRequired();
- }
-
- levelUp () {
- while (this.canLevelUp()) {
- this.level++;
- }
- }
-
- getExperienceRequired (levelOffset = 0) {
- return Math.max(
- Math.pow(this.level + levelOffset, 3),
- 1
- );
- }
-
- getPossibleEvolutions () {
- // return this.evolutions.filter((evolution) => this.level >= evolution.at_level && (!evolution.item || this.heldItem === evolution.item));
- return this.evolutions.filter((evolution) => evolution.path === 'standard' && this.level >= evolution.at_level);
- }
-
- canEvolve () {
- return this.getPossibleEvolutions().length > 0;
- }
-
- evolve () {
- const evolution = this.getPossibleEvolutions()[0];
-
- const statusPreEvolve = this.status;
- const hpPreEvolve = this.hp;
-
- this.slug = evolution.monster_slug;
-
- const statusPostEvolve = this.status;
-
- this.hp = statusPostEvolve.hp - (statusPreEvolve.hp - hpPreEvolve);
- }
-
- getTasteStatusModifier (statusName, baseStatus) {
- let positive = 0;
- let negative = 0;
-
- let isPositive = false;
- let isNegative = false;
- if (statusName === 'melee') {
- isPositive = this.tasteWarm === TasteWarm.salty;
- isNegative = this.tasteCold === TasteCold.sweet;
- }
- else if (statusName === 'armour') {
- isPositive = this.tasteWarm === TasteWarm.hearty;
- isNegative = this.tasteCold === TasteCold.soft;
- }
- else if (statusName === 'ranged') {
- isPositive = this.tasteWarm === TasteWarm.zesty;
- isNegative = this.tasteCold === TasteCold.flakey;
- }
- else if (statusName === 'dodge') {
- isPositive = this.tasteWarm === TasteWarm.refined;
- isNegative = this.tasteCold === TasteCold.dry;
- }
- else if (statusName === 'speed') {
- isPositive = this.tasteWarm === TasteWarm.peppy;
- isNegative = this.tasteCold === TasteCold.mild;
- }
-
- if (isPositive) {
- positive = baseStatus * 10 / 100;
- }
- if (isNegative) {
- negative = baseStatus * 10 / 100;
- }
-
- return Math.floor(positive) - Math.floor(negative);
- }
-
- get status () {
- const multiplier = this.level + 7;
- let hp = (this.shape.hp * multiplier) + this.statusModifier.hp;
- let melee = (this.shape.melee * multiplier) + this.statusModifier.melee;
- let armour = (this.shape.armour * multiplier) + this.statusModifier.armour;
- let ranged = (this.shape.ranged * multiplier) + this.statusModifier.ranged;
- let dodge = (this.shape.dodge * multiplier) + this.statusModifier.dodge;
- let speed = (this.shape.speed * multiplier) + this.statusModifier.speed;
-
- // Tastes
- melee += this.getTasteStatusModifier('melee', melee);
- armour += this.getTasteStatusModifier('armour', melee);
- ranged += this.getTasteStatusModifier('ranged', melee);
- dodge += this.getTasteStatusModifier('dodge', melee);
- speed += this.getTasteStatusModifier('speed', melee);
-
- return {
- hp,
- melee,
- armour,
- ranged,
- dodge,
- speed,
- };
- }
-
- setStatusModifier (statusType, newAbsoluteValue) {
- this.statusModifier[statusType] = newAbsoluteValue - this.status[statusType];
- }
- resetStatusModifier () {
- for (const m in this.statusModifier) {
- this.statusModifier[m] = 0;
- }
- }
-};
-
-class Technique {
- #accuracy = 0;
- #potency = 0;
- #power = 0;
-
- combatEffects = [];
-
- constructor (slug) {
- this.slug = slug;
-
- this.resetToBase();
- }
-
- get name () {
- return slugToName(this.slug);
- }
-
- get types () {
- return DB.techniques[this.slug].types;
- }
-
- get range () {
- return DB.techniques[this.slug].range;
- }
-
- get animation () {
- return DB.techniques[this.slug].animation;
- }
-
- get sfx () {
- return DB.techniques[this.slug].sfx;
- }
-
- get effects () {
- return DB.techniques[this.slug].effects;
- }
-
- get accuracy () {
- return this.#accuracy;
- }
- set accuracy (accuracy) {
- this.#accuracy = accuracy;
- }
-
- get potency () {
- return this.#potency;
- }
- set potency (potency) {
- this.#potency = potency;
- }
-
- get power () {
- return this.#power;
- }
- set power (power) {
- this.#power = power;
- }
-
- get base () {
- const accuracy = DB.techniques[this.slug].accuracy;
- const potency = DB.techniques[this.slug].potency;
- const power = DB.techniques[this.slug].power;
-
- return {
- accuracy,
- potency,
- power,
- };
- }
-
- resetToBase () {
- this.accuracy = this.base.accuracy;
- this.potency = this.base.potency;
- this.power = this.base.power;
- }
-}
-
-class Item {}
-
-class TechniqueEffect {
- constructor (str) {
- this.recipient = str.split(',')[1];
- this.application = str.split(' ')[0];
- this.type = str.split(',')[0].split(' ')[1].split('_')[0];
- this.effect = str.split(',')[0].split(' ')[1].split('_')[1];
- }
-}
-
-class StatusEffect {
- turnsLeft = 0;
-
- constructor (slug) {
- this.slug = slug;
-
- if (['recover', 'lifeleech'].includes(this.slug)) {
- this.turnsLeft = 1;
- }
- else if (['charging'].includes(this.slug)) {
- this.turnsLeft = 2;
- }
- else if (this.category === 'positive') {
- this.turnsLeft = Math.ceil(Math.random() * 6) + 4;
- }
- else if (this.category === 'negative') {
- this.turnsLeft = Math.ceil(Math.random() * 3) + 2;
- }
- else {
- this.turnsLeft = Math.ceil(Math.random() * 3) + 2;
- }
- }
-
- get effects () {
- return DB.statusEffects[this.slug].effects;
- }
-
- get category () {
- return DB.statusEffects[this.slug].category;
- }
-
- get name () {
- return slugToName(this.slug);
- }
-
- get status () {
- const status = {};
-
- const statusChangeKeys = Object.keys(DB.statusEffects[this.slug]).filter((key) => key.startsWith('stat'));
- for (const key of statusChangeKeys) {
- status[key.replace('stat', '')] = DB.statusEffects[this.slug][key];
- }
-
- return status;
- }
-}
-
-function simpleDamageMultiplier (techniqueTypes, targetTypes) {
- let multiplier = 1;
-
- for (const techniqueType of techniqueTypes) {
- if (techniqueType === ElementType.aether) {
- continue;
- }
-
- for (const targetType of targetTypes) {
- if (targetType === ElementType.aether) {
- continue;
- }
-
- multiplier *= DB.elements[techniqueType].types.find((type) => type.against === targetType).multiplier;
- }
- }
-
- return Math.max(0.25, Math.min(multiplier, 4));
-}
-function simpleDamageCalculation (technique, user, target) {
- if (technique.power === 0) {
- return 0;
- }
-
- let userBaseStrength = user.level + 7;
- let userStrength = 1;
- let targetResist = 1;
-
- if (technique.range === TechniqueRange.melee) {
- userStrength = userBaseStrength * user.status.melee;
- targetResist = target.status.armour;
- }
- else if (technique.range === TechniqueRange.touch) {
- userStrength = userBaseStrength * user.status.melee;
- targetResist = target.status.dodge;
- }
- else if (technique.range === TechniqueRange.ranged) {
- userStrength = userBaseStrength * user.status.ranged;
- targetResist = target.status.dodge;
- }
- else if (technique.range === TechniqueRange.reach) {
- userStrength = userBaseStrength * user.status.ranged;
- targetResist = target.status.armour;
- }
- else if (technique.range === TechniqueRange.reliable) {
- userStrength = userBaseStrength;
- targetResist = 1;
- }
-
- const multiplier = simpleDamageMultiplier(technique.types, target.types);
- const moveStrength = technique.power * multiplier;
- const damage = Math.floor((userStrength * moveStrength) / targetResist);
-
- return Math.max(damage, 1);
-}
-
-function calculateAwardedExperience (playerMonster, enemyMonster) {
- return Math.max(
- Math.floor(
- enemyMonster.getExperienceRequired(-1) / enemyMonster.level * enemyMonster.experienceModifier / playerMonster.level
- ),
- 1
- );
-}
-
-async function fetchMonster (slug) {
- if (! DB.monsters[slug]) {
- DB.monsters[slug] = await fetch(`/modules/tuxemon/mods/tuxemon/db/monster/${slug}.json`).then((response) => response.json());
- }
-
- return new Monster(slug);
-}
-async function fetchTechnique (slug) {
- if (! DB.techniques[slug]) {
- DB.techniques[slug] = await fetch(`/modules/tuxemon/mods/tuxemon/db/technique/${slug}.json`).then((response) => response.json());
- }
-
- return new Technique(slug);
-}
-async function fetchStatusEffect (slug) {
- if (! DB.statusEffects[slug]) {
- DB.statusEffects[slug] = await fetch(`/modules/tuxemon/mods/tuxemon/db/technique/status_${slug}.json`).then((response) => response.json());
- }
-
- return new StatusEffect(slug);
-}
-
-function standardizeColor (color) {
- var ctx = document.createElement('canvas').getContext('2d');
- ctx.fillStyle = color;
-
- return ctx.fillStyle;
-}
-function mixColors(...colors) {
- let r = 0;
- let g = 0;
- let b = 0;
-
- for (const color of colors) {
- const [cr, cg, cb] = color.match(/\w\w/g).map((c) => parseInt(c, 16));
-
- r += cr;
- g += cg;
- b += cb;
- }
-
- r = r / colors.length;
- g = g / colors.length;
- b = b / colors.length;
-
- return `rgb(${r}, ${g}, ${b})`;
-}
-
-function slugToName (slug) {
- return slug.split('_').map((item) => item.charAt(0).toUpperCase() + item.slice(1)).join(' ');
-}
-
-(async function () {
- DB.allMonsters = await fetch('/db/all-monsters.json').then((response) => response.json());
- DB.allAnimations = await fetch('/db/animations.json').then((response) => response.json());
- DB.shapes = await fetch('/modules/tuxemon/mods/tuxemon/db/shape/shapes.json').then((response) => response.json());
- for (const element of Object.keys(ElementType)) {
- DB.elements[element] = await fetch(`/modules/tuxemon/mods/tuxemon/db/element/${element}.json`).then((response) => response.json());
- }
-
- const state = new State();
- state.enemy.monster = await fetchMonster('grintot');
-
- state.partyMonsters = [
- await fetchMonster('corvix'),
- await fetchMonster('lunight'),
- await fetchMonster('prophetoise'),
- await fetchMonster('drashimi'),
- await fetchMonster('glombroc'),
- await fetchMonster('uneye'),
- await fetchMonster('nostray'),
- await fetchMonster('dragarbor'),
- ];
- state.activeMonster = state.partyMonsters[0];
- state.activeTechnique = await fetchTechnique(state.activeMonster.moveset[0].technique);
-
- const templatePartyMonster = document.querySelector('#tpl___party__monster').innerHTML;
- const templateBattleMonster = document.querySelector('#tpl___battle__monster').innerHTML;
- const templatePopup = document.querySelector('#tpl___popup').innerHTML;
- const templateMovesetList = document.querySelector('#tpl___moveset__list').innerHTML;
- const templateMovesetItem = document.querySelector('#tpl___moveset__item').innerHTML;
- const templateTechnique = document.querySelector('#tpl___technique').innerHTML;
-
- const party = document.querySelector('#party');
- const money = document.querySelector('#money');
-
- const battle = document.querySelector('#battle');
- const battleEnemy = document.querySelector('#battle__enemy');
- const battlePlayer = document.querySelector('#battle__player');
-
- const UI = {
- activeMonster: null,
-
- enemyImg: null,
- damageHighlightClickDuration: 0.1,
- damageHighlightClickTimeout: null,
- imgClickDuration: 0.1,
- damageClickTimeout: null,
-
- damageAnimationIsRunning: false,
- damageAnimationNumber: 0,
-
- getTemplate (template) {
- var tpl = document.createElement('div');
- tpl.innerHTML = template.trim();
-
- return tpl.firstChild;
- },
-
- setExp (monster, parentNode) {
- const expBar = parentNode.querySelector('.exp-bar');
- const expText = parentNode.querySelector('.exp-text');
-
- const expToNextLevel = monster.getExperienceRequired() - monster.getExperienceRequired(-1);
- const currentExp = monster.exp - monster.getExperienceRequired(-1);
- expBar.style.width = (currentExp / expToNextLevel) * 100 + '%';
- expText.textContent = monster.exp + ' / ' + monster.getExperienceRequired();
- },
-
- setHp (monster, parentNode) {
- const hpBar = parentNode.querySelector('.hp-bar');
- const hpText = parentNode.querySelector('.hp-text');
-
- const percentHp = (monster.hp / monster.status.hp) * 100;
- if (percentHp > 60) {
- hpBar.style.backgroundColor = 'green';
- } else if (percentHp > 15) {
- hpBar.style.backgroundColor = 'rgb(240, 240, 100)';
- } else {
- hpBar.style.backgroundColor = 'red';
- }
-
- hpBar.style.width = percentHp + '%';
- hpText.textContent = monster.hp + ' / ' + monster.status.hp;
- },
-
- async createDamage (event, damage) {
- const damageNode = document.createElement('div');
- damageNode.classList.add('damage');
- damageNode.textContent = damage;
-
- const damageMultiplier = simpleDamageMultiplier(state.activeTechnique.types, state.enemy.monster.types);
- damageNode.style.fontSize = damageMultiplier*2 + 'rem';
-
- damageNode.style.top = event.pageY - battleEnemy.offsetTop + (Math.random() * 40 - 20);
- damageNode.style.left = event.pageX - battleEnemy.offsetLeft + (Math.random() * 40 - 20);
-
- damageNode.style.color = mixColors(...state.activeTechnique.types.map((type) => standardizeColor(ElementTypeColor[type])));
-
- const damageNodeDuration = 2;
- damageNode.style.animationDuration = damageNodeDuration + 's';
-
- battleEnemy.appendChild(damageNode);
- setTimeout(() => damageNode.remove(), (damageNodeDuration * 1000) - 500);
-
- this.enemyImg.classList.add('damaged');
- clearTimeout(this.damageHighlightClickTimeout);
- this.damageHighlightClickTimeout = setTimeout(() => this.enemyImg.classList.remove('damaged'), this.damageHighlightClickDuration * 1000);
-
- var enemyAnimation = battleEnemy.querySelector('.battle__monster-sprite__animation');
- if (!this.damageAnimationIsRunning && state.activeTechnique.animation && DB.allAnimations[state.activeTechnique.animation]) {
- this.damageAnimationIsRunning = true;
-
- const damageAnimationLoop = () => {
- enemyAnimation.src = `/modules/tuxemon/mods/tuxemon/animations/technique/${state.activeTechnique.animation}_${("00" + this.damageAnimationNumber).slice(-2)}.png`;
- enemyAnimation.style.top = event.clientY - (enemyAnimation.clientHeight / 2);
- enemyAnimation.style.left = event.clientX - (enemyAnimation.clientWidth / 2);
- // console.log(enemyAnimation.src);
-
- this.damageAnimationNumber++;
-
- if (this.damageAnimationNumber >= DB.allAnimations[state.activeTechnique.animation].length) {
- this.damageAnimationIsRunning = false;
- this.damageAnimationNumber = 0;
- enemyAnimation.src = '';
- return;
- }
-
- setTimeout(() => requestAnimationFrame(damageAnimationLoop), 50);
- };
-
- requestAnimationFrame(damageAnimationLoop);
-
- // sfx
- /* let sfx = state.activeTechnique.sfx.substr(4);
- const audio = new Audio(`/modules/tuxemon/mods/tuxemon/sounds/technique/${sfx}.ogg`);
- audio.play(); */
- }
- },
-
- setBattleMonster (monster, where) {
- let battleMonster = document.createElement('div');
- battleMonster.innerHTML = templateBattleMonster.trim();
- battleMonster = battleMonster.firstChild;
-
- battleMonster.querySelector('.battle__monster-info__name').textContent = monster.name;
- battleMonster.querySelector('.battle__monster-info__gender').textContent = monster.gender === 'male' ? '♂' : monster.gender === 'female' ? '♀' : '⚲';
- battleMonster.querySelector('.battle__monster-info__level').textContent = monster.level;
- battleMonster.querySelector('.battle__monster-info__status').innerHTML = UI.createStatusEffectIcon(monster.statusEffect);
- battleMonster.querySelector('.battle__monster-img').src = `/modules/tuxemon/mods/tuxemon/gfx/sprites/battle/${monster.slug}-front.png`;
-
- UI.setHp(monster, battleMonster.querySelector('.hp'));
-
- if (where === 'player') {
- UI.setExp(monster, battleMonster.querySelector('.exp'));
- battleMonster.querySelector('.battle__monster-technique').addEventListener('click', UI.openMovesetSelection);
-
- battleMonster.classList.add('battle__monster--player');
- battlePlayer.querySelector('.battle__monster') && battlePlayer.removeChild(battlePlayer.querySelector('.battle__monster'));
- battlePlayer.appendChild(battleMonster);
-
- UI.setActiveTechnique();
-
- UI.setActiveTechniques();
- } else {
- battleMonster.classList.add('battle__monster--enemy');
-
- this.enemyImg = battleMonster.querySelector('.battle__monster-img');
- this.enemyImg.style.transitionDuration = this.damageHighlightClickDuration + 's';
-
- const previousBattleMonster = battleEnemy.querySelector('.battle__monster');
- if (previousBattleMonster) {
- this.enemyImg.classList = previousBattleMonster.querySelector('.battle__monster-img').classList;
-
- battleEnemy.removeChild(previousBattleMonster);
- }
-
- battleEnemy.appendChild(battleMonster);
- }
- },
-
- setEnemyMonster () {
- UI.setBattleMonster(state.enemy.monster, 'enemy');
- },
-
- setActiveMonster () {
- UI.setBattleMonster(state.activeMonster, 'player');
- },
-
- setActiveTechnique () {
- battlePlayer.querySelector('.battle__monster-technique').innerHTML =
- slugToName(state.activeTechnique.slug) + ' &nbsp; '
- + state.activeTechnique.types.map((type) => UI.createElementTypeIcon(type)).join('');
- },
-
- setActiveTechniques () {
- const techniquesNode = document.querySelector('#techniques');
- techniquesNode.replaceChildren();
-
- for (const technique of state.activeMonster.activeTechniques) {
- const techniqueNode = UI.getTemplate(templateTechnique);
- techniqueNode.querySelector('.techniques__technique__name').innerHTML = technique.name;
- techniquesNode.appendChild(techniqueNode);
- }
- },
-
- async chooseActiveTechnique () {
- let activeMoveIndex = 0;
- while ((await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique)).power === 0) {
- activeMoveIndex++;
- }
- state.activeTechnique = await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique);
-
- UI.setActiveTechnique();
- },
-
- async openMovesetSelection () {
- const popup = UI.createPopup();
-
- const movesetList = UI.getTemplate(templateMovesetList);
- for (const move of state.activeMonster.moveset) {
- const technique = await fetchTechnique(move.technique);
- const movesetItem = UI.getTemplate(templateMovesetItem);
-
- movesetItem.querySelector('.moveset__item__name').textContent = slugToName(technique.slug);
- movesetItem.querySelector('.moveset__item__type').innerHTML = technique.types.map((type) => UI.createElementTypeIcon(type)).join('');
- movesetItem.querySelector('.moveset__item__power').innerHTML = technique.power;
- movesetItem.querySelector('.moveset__item__level').innerHTML = move.level_learned;
-
- if (state.activeMonster.activeTechniques.find((item) => item.slug === technique.slug)) {
- movesetItem.setAttribute('selected', true);
- }
-
- movesetItem.addEventListener('click', () => {
- if (movesetItem.getAttribute('disabled')) {
- return false;
- }
-
- state.activeTechnique = technique;
- UI.setActiveTechnique();
-
- if (movesetItem.getAttribute('selected')) {
- movesetItem.removeAttribute('selected');
- state.activeMonster.activeTechniques.splice(state.activeMonster.activeTechniques.findIndex((item) => item.slug === technique.slug), 1);
- } else {
- movesetItem.setAttribute('selected', true);
- state.activeMonster.activeTechniques.push(technique);
- }
- UI.setActiveTechniques();
- });
-
- if (state.activeMonster.level < move.level_learned) {
- movesetItem.setAttribute('disabled', true);
- }
-
- movesetList.appendChild(movesetItem);
- }
-
- popup.querySelector('.popup').appendChild(movesetList);
- document.body.appendChild(popup);
- },
-
- async createNewEnemyMonster () {
- state.enemy.monster = await fetchMonster(DB.allMonsters[Math.floor(Math.random() * DB.allMonsters.length)]);
- state.enemy.monster.level = Math.ceil(Math.random() * state.activeMonster.level);
- // state.enemy.monster.experienceModifier = state.enemy.monster.level;
- state.enemy.monster.moneyModifier = state.enemy.monster.level;
- UI.setEnemyMonster();
- },
-
- createElementTypeIcon (type) {
- var img = document.createElement('img');
- img.src = `/modules/tuxemon/mods/tuxemon/gfx/ui/icons/element/${type}_type.png`;
- img.title = slugToName(type);
-
- return img.outerHTML;
- },
-
- createStatusEffectIcon (statusEffect) {
- if (!statusEffect) return '';
-
- var img = document.createElement('img');
- img.src = `/modules/tuxemon/mods/tuxemon/gfx/ui/icons/status/icon_${statusEffect.slug}.png`;
- img.title = statusEffect.name;
-
- return img.outerHTML;
- },
-
- createPopup () {
- const popup = UI.getTemplate(templatePopup);
- popup.addEventListener('click', ({ target }) => target === popup && popup.remove());
-
- return popup;
- },
-
- openPartyMenu () {
- const popup = UI.createPopup();
-
- const party = document.createElement('div');
- party.id = 'party';
- for (const monster of state.partyMonsters) {
- const partyMonster = UI.getTemplate(templatePartyMonster);
-
- partyMonster.dataset.slug = monster.slug;
- partyMonster.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/sprites/battle/${monster.slug}-front.png`;
-
- partyMonster.addEventListener('click', async (event) => {
- let target = event.target;
- while (target.parentNode.id !== 'party') {
- target = target.parentNode;
- }
-
- state.activeMonster = state.partyMonsters[Array.prototype.indexOf.call(document.querySelector('#party').children, target)];
- await UI.chooseActiveTechnique();
- UI.setActiveMonster();
-
- popup.remove();
- });
-
- party.appendChild(partyMonster);
- }
-
- popup.querySelector('.popup').appendChild(party);
- document.body.appendChild(popup);
- },
-
- openInventoryMenu () {
- const popup = UI.createPopup();
-
- const inventory = document.createElement('div');
- inventory.id = 'inventory';
- for (const item of state.inventory) {
- }
-
- popup.querySelector('.popup').appendChild(inventory);
- document.body.appendChild(popup);
- },
- };
-
- const Game = {
- async useTechnique(technique, user, target) {
- let statusEffects = [];
- let combatEffects = [];
-
- for (const effect of technique.effects) {
- if (effect.includes('status_')) {
- statusEffects.push(new TechniqueEffect(effect));
- }
- else if (!['damage', 'splash', 'area'].includes(effect)) {
- combatEffects.push(effect);
- }
- }
-
- for (const effect of statusEffects) {
- let recipient;
-
- if (effect.recipient === 'user') {
- recipient = user;
- } else {
- recipient = target;
- }
-
- if (effect.type === 'status') {
- if (effect.application === 'give') {
- if (recipient.statusEffect) {
- continue;
- }
-
- const potency = Math.random();
- const success = technique.potency >= potency;
- if (success) {
- recipient.statusEffect = await fetchStatusEffect(effect.effect);
- }
- }
- else if (effect.application === 'remove') {
- if (recipient.statusEffect.slug === effect.effect) {
- recipient.statusEffect = '';
- }
- }
- }
- }
-
- technique.combatEffects = combatEffects;
- },
-
- async applyStatusEffect (affectedMonster, opposingMonster) {
- if (!affectedMonster.statusEffect) {
- return;
- }
-
- if (! (affectedMonster.statusEffect instanceof StatusEffect)) {
- return;
- }
-
- if (affectedMonster.statusEffect.slug === 'poison' || affectedMonster.statusEffect.slug === 'burn') {
- const statusEffectDamage = Math.floor(affectedMonster.status.hp / 8);
- affectedMonster.hp -= statusEffectDamage;
-
- UI.createDamage(clickEvent, statusEffectDamage);
- }
-
- else if (affectedMonster.statusEffect.slug === 'recover') {
- const statusEffectHeal = Math.floor(affectedMonster.status.hp / 16);
- affectedMonster.hp += statusEffectHeal;
- }
-
- else if (affectedMonster.statusEffect.slug === 'lifeleech') {
- const statusEffectLeech = Math.floor(affectedMonster.status.hp / 16);
- affectedMonster.hp -= statusEffectLeech;
- opposingMonster.hp += statusEffectLeech;
-
- UI.createDamage(clickEvent, statusEffectLeech);
- }
-
- else if (affectedMonster.statusEffect.slug === 'charging') {
- turnEndPhaseEvents.push(async () => {
- if (affectedMonster.statusEffect.turnsLeft === 0) {
- affectedMonster.statusEffect = await fetchStatusEffect('chargedup');
- }
- });
- }
-
- else if (affectedMonster.statusEffect.effects.includes('statchange')) {
- affectedMonster.resetStatusModifier();
-
- for (const statusType in affectedMonster.statusEffect.status) {
- const statusChange = affectedMonster.statusEffect.status[statusType];
-
- const modifiedValue = Math.floor(eval(`${affectedMonster.status[statusType]} ${statusChange.operation} ${statusChange.value}`));
- affectedMonster.setStatusModifier(statusType, modifiedValue);
- }
- }
-
- affectedMonster.statusEffect.turnsLeft--;
- turnEndPhaseEvents.push(() => {
- if (affectedMonster.statusEffect.turnsLeft === 0) {
- affectedMonster.statusEffect = null;
- affectedMonster.resetStatusModifier();
- }
- });
- },
-
- applyTechniqueEffect (technique, user, target) {
- for (const effect of technique.combatEffects) {
- if (effect === 'money') {
- if (!techniqueHit) {
- state.money += Math.floor(Math.random() * target.level);
- }
- }
- }
-
- // modify technique stats
- if (user.statusEffect) {
- if (user.statusEffect.slug === 'grabbed') {
- if ([TechniqueRange.ranged, TechniqueRange.reach].includes(technique.range)) {
- technique.potency = technique.base.potency * 0.5;
- technique.power = technique.base.power * 0.5;
- }
- }
-
- else if (user.statusEffect.slug === 'stuck') {
- if ([TechniqueRange.melee, TechniqueRange.touch].includes(technique.range)) {
- technique.potency = technique.base.potency * 0.5;
- technique.power = technique.base.power * 0.5;
- }
- }
-
- // remove effect
- if (user.statusEffect.turnsLeft === 0) {
- turnEndPhaseEvents.push(() => {
- technique.resetToBase();
- });
- }
- }
- },
-
- damage () {
- const damage = simpleDamageCalculation(state.activeTechnique, state.activeMonster, state.enemy.monster);
- UI.createDamage(clickEvent, damage);
-
- state.enemy.monster.hp -= damage;
- },
- };
-
- UI.setActiveMonster();
- UI.setEnemyMonster();
-
- let techniqueHit;
- let clickEvent;
- let turnEndPhaseEvents = [];
- document.querySelector('#battle__enemy').addEventListener('click', async (event) => {
- clickEvent = event;
-
- const accuracy = Math.random();
- techniqueHit = state.activeTechnique.accuracy >= accuracy;
-
- if (techniqueHit) {
- await Game.useTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster);
- }
-
- await Game.applyStatusEffect(state.activeMonster, state.enemy.monster);
- await Game.applyStatusEffect(state.enemy.monster, state.activeMonster);
-
- Game.applyTechniqueEffect(state.activeTechnique, state.activeMonster, state.enemy.monster);
-
- if (techniqueHit) {
- Game.damage();
-
- if (state.enemy.monster.hp <= 0) {
- const faintedMonster = state.enemy.monster;
-
- await UI.createNewEnemyMonster();
-
- state.money += faintedMonster.level * faintedMonster.moneyModifier;
-
- state.activeMonster.exp += calculateAwardedExperience(state.activeMonster, faintedMonster);
- state.activeMonster.levelUp();
- if (state.activeMonster.canEvolve()) {
- await fetchMonster(state.activeMonster.evolutions[0].monster_slug);
- state.activeMonster.evolve();
- }
- }
- } else {
- UI.createDamage(event, 'MISS!');
- }
-
- UI.setActiveMonster();
- UI.setEnemyMonster();
-
- UI.setHp(state.enemy.monster, battleEnemy);
-
- money.textContent = state.money;
-
- for (const turnEndPhaseEvent of turnEndPhaseEvents) {
- const returnValue = turnEndPhaseEvent();
- if (returnValue instanceof Promise) {
- await returnValue;
- }
- }
- turnEndPhaseEvents = [];
- });
-
- document.querySelector('#menu__party').addEventListener('click', UI.openPartyMenu);
-
- document.querySelector('#menu__catch').addEventListener('click', async () => {
- const caughtMonster = new Monster(state.enemy.monster.slug);
- caughtMonster.level = state.enemy.monster.level;
-
- state.partyMonsters.push(caughtMonster);
-
- UI.createNewEnemyMonster();
- });
-
- document.querySelector('#menu__inventory').addEventListener('click', UI.openInventoryMenu);
-})();