summaryrefslogtreecommitdiff
path: root/resources/js/game.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/js/game.js')
-rw-r--r--resources/js/game.js405
1 files changed, 189 insertions, 216 deletions
diff --git a/resources/js/game.js b/resources/js/game.js
index 1ca9387..f68e2fb 100644
--- a/resources/js/game.js
+++ b/resources/js/game.js
@@ -12,6 +12,132 @@ const Game = {
turn: 0,
+ /**
+ * @returns {string}
+ */
+ save () {
+ const saveMonster = (monsterData, monsterState) => {
+ monsterData.level = monsterState.level;
+ monsterData.hp = monsterState.hp;
+
+ if (monsterData.statusEffect && monsterData.statusEffect.slug === 'lifeleech') {
+ monsterData.statusEffect = null;
+ }
+
+ return monsterData;
+ };
+
+ const saveData = JSON.parse(JSON.stringify(state));
+
+ for (const idx in saveData.monsters) {
+ saveData.monsters[idx] = saveMonster(saveData.monsters[idx], state.monsters[idx]);
+ }
+
+ for (const idx in saveData.partyMonsters) {
+ saveData.partyMonsters[idx] = saveMonster(saveData.partyMonsters[idx], state.partyMonsters[idx]);
+ }
+
+ saveData.activeMonsterIdx = state.partyMonsters.indexOf(state.activeMonster);
+
+ saveData.enemy.monster = saveMonster(saveData.enemy.monster, state.enemy.monster);
+
+ return btoa(JSON.stringify(saveData));
+ },
+
+ /**
+ * @param {string} saveData
+ */
+ async load (saveData) {
+ /**
+ * @param {Monster} monsterData
+ */
+ const loadMonster = async (monsterData) => {
+ const monster = await fetchMonster(monsterData.slug);
+
+ monster.level = monsterData.level;
+ monster.hp = monsterData.hp;
+ monster.exp = monsterData.exp;
+ monster.tasteWarm = monsterData.tasteWarm;
+ monster.tasteCold = monsterData.tasteCold;
+ monster.gender = monsterData.gender;
+ monster.heldItem = await loadItem(monsterData.heldItem);
+ monster.statusEffect = await loadStatusEffect(monsterData.statusEffect);
+ monster.statModifiers = monsterData.statModifiers;
+ monster.experienceModifier = monsterData.experienceModifier;
+ monster.moneyModifier = monsterData.moneyModifier;
+ monster.activeTechniques = await Promise.all(monsterData.activeTechniques.map(async (technique) => {
+ return loadTechnique(technique);
+ }));
+
+ return monster;
+ };
+
+ /**
+ * @param {InventoryItem} inventoryItemData
+ */
+ const loadInventoryItem = async (inventoryItemData) => {
+ const inventoryItem = new InventoryItem(await fetchItem(inventoryItemData.item.slug));
+
+ inventoryItem.quantity = inventoryItemData.quantity;
+
+ return inventoryItem;
+ };
+
+ /**
+ * @param {Item} itemData
+ */
+ const loadItem = async (itemData) => {
+ if (!itemData) {
+ return null;
+ }
+
+ const item = await fetchItem(itemData.slug);
+
+ return item;
+ };
+
+ /**
+ * @param {StatusEffect} statusEffectData
+ */
+ const loadStatusEffect = async (statusEffectData) => {
+ if (!statusEffectData) {
+ return null;
+ }
+
+ const statusEffect = await fetchStatusEffect(statusEffectData.slug);
+
+ statusEffect.turnsLeft = statusEffectData.turnsLeft;
+
+ return statusEffect;
+ };
+
+ /**
+ * @param {Technique} techniqueData
+ */
+ const loadTechnique = async (techniqueData) => {
+ const technique = await fetchTechnique(techniqueData.slug);
+
+ return technique;
+ };
+
+ /**
+ * @type {State}
+ */
+ const loadedState = JSON.parse(atob(saveData));
+
+ state.money = loadedState.money;
+ state.monsters = await Promise.all(loadedState.monsters.map(async (monsterData) => await loadMonster(monsterData)));
+ state.inventory = await Promise.all(loadedState.inventory.map(async (itemData) => await loadInventoryItem(itemData)));
+ state.partyMonsters = await Promise.all(loadedState.partyMonsters.map(async (monsterData) => await loadMonster(monsterData)));
+ state.activeMonster = state.partyMonsters[loadedState.activeMonsterIdx];
+ state.activeTechnique = await loadTechnique(loadedState.activeTechnique);
+ state.enemy.monster = await loadMonster(loadedState.enemy.monster);
+
+ UI.drawEnemyMonster();
+ UI.drawActiveMonster();
+ UI.drawActiveTechniques();
+ },
+
async progressTurn () {
Game.turn++;
@@ -62,18 +188,56 @@ const Game = {
* @param {Monster} user
* @param {Monster} target
*/
- async useTechnique (technique, user, target) {
- technique.use();
+ async tryUseTechnique (technique, user, target) {
+ let canUse = true;
- if (!Game.didTechniqueHit) {
- UI.drawDamageMiss(UI.createDamageMiss());
- return;
+ // recharge
+ if (technique.isRecharging()) {
+ const feedbackNode = UI.createActionFeedback('recharge');
+ UI.drawActionFeedback(feedbackNode);
+
+ canUse = false;
}
- for (const techniqueEffect of technique.effects) {
+ // noddingoff
+ if (user.statusEffect && user.statusEffect.slug === StatusEffectType.noddingoff) {
+ const feedbackNode = UI.createActionFeedback('noddingoff');
+ UI.drawActionFeedback(feedbackNode);
+
+ canUse = false;
+ }
+
+ if (canUse) {
+
+ // hit?
+ const accuracy = Math.random();
+ Game.didTechniqueHit = technique.accuracy >= accuracy;
+ if (!Game.didTechniqueHit) {
+ technique.use();
+ UI.drawDamageMiss(UI.createDamageMiss());
+
+ return;
+ }
+
+ await Game.useTechnique(technique, user, target);
+ }
+ },
+
+ /**
+ * @param {Technique} technique
+ * @param {Monster} user
+ * @param {Monster} target
+ */
+ async useTechnique (technique, user, target) {
+ technique.use();
+
+ for (const techniqueEffectCode of technique.effects) {
+ const techniqueEffect = new TechniqueEffect(techniqueEffectCode);
+ techniqueEffect.setUser(user);
+ techniqueEffect.setTarget(target);
// damage
- if (['damage', 'splash', 'area'].includes(techniqueEffect)) {
+ if (['damage', 'splash', 'area'].includes(techniqueEffect.type)) {
Game.phases.action.push(() => {
const damage = simpleDamageCalculation(state.activeTechnique, state.activeMonster, state.enemy.monster);
@@ -82,11 +246,12 @@ const Game = {
UI.applyMultiplierToDamage(damageNode, simpleDamageMultiplier(state.activeTechnique.types, state.enemy.monster.types));
UI.applyTechniqueToDamage(damageNode, state.activeTechnique);
UI.drawDamage(damageNode);
- UI.drawTechniqueAnimation();
+ UI.drawTechniqueAnimation(technique);
});
}
- else if (techniqueEffect === 'money') {
+ // money
+ else if (techniqueEffect.type === 'money') {
Game.phases.action.push(() => {
const money = Math.max(1, Math.floor(Math.random() * target.level));
state.money += money;
@@ -94,34 +259,28 @@ const Game = {
const damageNode = UI.createDamage(`${money} €`);
UI.applyTechniqueToDamage(damageNode, state.activeTechnique);
UI.drawDamage(damageNode);
- UI.drawTechniqueAnimation();
+ UI.drawTechniqueAnimation(technique);
});
}
- else if (techniqueEffect === 'enhance') {
- UI.drawTechniqueAnimation();
+ // healing
+ else if (techniqueEffect.type === 'healing') {
+ techniqueEffect.recipient.hp = techniqueEffect.recipient.stats.hp;
}
- // status effect
- else if (techniqueEffect.includes('status_')) {
- const statusEffect_recipient = techniqueEffect.split(',')[1];
- const statusEffect_application = techniqueEffect.split(' ')[0];
- const statusEffect_type = techniqueEffect.split(',')[0].split(' ')[1].split('_')[0];
- const statusEffect_effect = techniqueEffect.split(',')[0].split(' ')[1].split('_')[1];
+ // enhance
+ else if (techniqueEffect.type === 'enhance') {
+ UI.drawTechniqueAnimation(technique);
+ }
- const statusEffect = await fetchStatusEffect(statusEffect_effect);
+ // status effect
+ else if (techniqueEffect.type === 'status') {
+ const statusEffect = await fetchStatusEffect(techniqueEffect.statusEffect);
if (statusEffect.slug === 'lifeleech') {
statusEffect.issuer = user;
}
- let recipient;
- if (statusEffect_recipient === 'user') {
- recipient = user;
- } else {
- recipient = target;
- }
-
Game.phases.postAction.push(() => {
// add status effect
const potency = Math.random();
@@ -129,22 +288,17 @@ const Game = {
if (success) {
// TODO: check replace
- if (recipient.statusEffect) return;
+ if (techniqueEffect.recipient.statusEffect) return;
- recipient.statusEffect = statusEffect;
+ techniqueEffect.recipient.statusEffect = statusEffect;
}
});
- UI.drawTechniqueAnimation();
+ UI.drawTechniqueAnimation(technique);
}
}
},
- rechargeTechnique () {
- const feedbackNode = UI.createActionFeedback('recharge');
- UI.drawActionFeedback(feedbackNode);
- },
-
/**
* @param {Monster} monster
*/
@@ -288,15 +442,7 @@ const Game = {
async battleClick (event) {
UI.battleClickEvent = event;
- // hit?
- const accuracy = Math.random();
- Game.didTechniqueHit = state.activeTechnique.accuracy >= accuracy;
-
- if (state.activeTechnique.isUsable()) {
- await Game.useTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster);
- } else {
- Game.rechargeTechnique();
- }
+ await Game.tryUseTechnique(state.activeTechnique, state.activeMonster, state.enemy.monster);
Game.progressTurn();
},
@@ -338,182 +484,9 @@ const Game = {
Game.spawnEnemyMonster();
},
-
- /**
- * @returns {string}
- */
- save () {
- const saveMonster = (monsterData, monsterState) => {
- monsterData.level = monsterState.level;
- monsterData.hp = monsterState.hp;
-
- if (monsterData.statusEffect && monsterData.statusEffect.slug === 'lifeleech') {
- monsterData.statusEffect = null;
- }
-
- return monsterData;
- };
-
- const saveData = JSON.parse(JSON.stringify(state));
-
- for (const idx in saveData.monsters) {
- saveData.monsters[idx] = saveMonster(saveData.monsters[idx], state.monsters[idx]);
- }
-
- for (const idx in saveData.partyMonsters) {
- saveData.partyMonsters[idx] = saveMonster(saveData.partyMonsters[idx], state.partyMonsters[idx]);
- }
-
- saveData.activeMonsterIdx = state.partyMonsters.indexOf(state.activeMonster);
-
- saveData.enemy.monster = saveMonster(saveData.enemy.monster, state.enemy.monster);
-
- return btoa(JSON.stringify(saveData));
- },
-
- /**
- * @param {string} saveData
- */
- async load (saveData) {
- /**
- * @param {Monster} monsterData
- */
- const loadMonster = async (monsterData) => {
- const monster = await fetchMonster(monsterData.slug);
-
- monster.level = monsterData.level;
- monster.hp = monsterData.hp;
- monster.exp = monsterData.exp;
- monster.tasteWarm = monsterData.tasteWarm;
- monster.tasteCold = monsterData.tasteCold;
- monster.gender = monsterData.gender;
- monster.heldItem = await loadItem(monsterData.heldItem);
- monster.statusEffect = await loadStatusEffect(monsterData.statusEffect);
- monster.statModifiers = monsterData.statModifiers;
- monster.experienceModifier = monsterData.experienceModifier;
- monster.moneyModifier = monsterData.moneyModifier;
- monster.activeTechniques = await Promise.all(monsterData.activeTechniques.map(async (technique) => {
- return loadTechnique(technique);
- }));
-
- return monster;
- };
-
- /**
- * @param {InventoryItem} inventoryItemData
- */
- const loadInventoryItem = async (inventoryItemData) => {
- const inventoryItem = new InventoryItem(await fetchItem(inventoryItemData.item.slug));
-
- inventoryItem.quantity = inventoryItemData.quantity;
-
- return inventoryItem;
- };
-
- /**
- * @param {Item} itemData
- */
- const loadItem = async (itemData) => {
- if (!itemData) {
- return null;
- }
-
- const item = await fetchItem(itemData.slug);
-
- return item;
- };
-
- /**
- * @param {StatusEffect} statusEffectData
- */
- const loadStatusEffect = async (statusEffectData) => {
- if (!statusEffectData) {
- return null;
- }
-
- const statusEffect = await fetchStatusEffect(statusEffectData.slug);
-
- statusEffect.turnsLeft = statusEffectData.turnsLeft;
-
- return statusEffect;
- };
-
- /**
- * @param {Technique} techniqueData
- */
- const loadTechnique = async (techniqueData) => {
- const technique = await fetchTechnique(techniqueData.slug);
-
- return technique;
- };
-
- /**
- * @type {State}
- */
- const loadedState = JSON.parse(atob(saveData));
-
- state.money = loadedState.money;
- state.monsters = await Promise.all(loadedState.monsters.map(async (monsterData) => await loadMonster(monsterData)));
- state.inventory = await Promise.all(loadedState.inventory.map(async (itemData) => await loadInventoryItem(itemData)));
- state.partyMonsters = await Promise.all(loadedState.partyMonsters.map(async (monsterData) => await loadMonster(monsterData)));
- state.activeMonster = state.partyMonsters[loadedState.activeMonsterIdx];
- state.activeTechnique = await loadTechnique(loadedState.activeTechnique);
- state.enemy.monster = await loadMonster(loadedState.enemy.monster);
-
- UI.drawEnemyMonster();
- UI.drawActiveMonster();
- UI.drawActiveTechniques();
- },
};
// Game click bindings
UI.elements.battleEnemy.addEventListener('click', Game.battleClick);
UI.elements.techniques.addEventListener('click', Game.techniqueClick);
UI.elements.menuCatch.addEventListener('click', Game.catchMonster);
-
-
-(async function () {
- await initializeDB();
-
- const possibleStarterMonsters = ['budaye', 'dollfin', 'grintot', 'ignibus', 'memnomnom'];
-
- // state.enemy.monster = await fetchMonster('grintot');
- state.enemy.monster = await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]);
-
- state.partyMonsters = [
- await fetchMonster('dollfin'),
- await fetchMonster(possibleStarterMonsters[Math.round(Math.random() * (possibleStarterMonsters.length - 1))]),
- await fetchMonster('corvix'),
- await fetchMonster('lunight'),
- await fetchMonster('prophetoise'),
- await fetchMonster('drashimi'),
- await fetchMonster('glombroc'),
- await fetchMonster('uneye'),
- await fetchMonster('nostray'),
- await fetchMonster('dragarbor'),
- await fetchMonster('mk01_omega'),
- ];
-
- state.activeMonster = state.partyMonsters[0];
- state.activeTechnique = state.activeMonster.activeTechniques[0];
-
- state.inventory = [
- new InventoryItem(await fetchItem('tuxeball')),
- new InventoryItem(await fetchItem('ancient_egg')),
- new InventoryItem(await fetchItem('sweet_sand')),
- new InventoryItem(await fetchItem('tectonic_drill')),
- new InventoryItem(await fetchItem('surfboard')),
- new InventoryItem(await fetchItem('sledgehammer')),
- new InventoryItem(await fetchItem('raise_melee')),
- new InventoryItem(await fetchItem('raise_speed')),
- new InventoryItem(await fetchItem('mm_fire')),
- new InventoryItem(await fetchItem('mm_water')),
- new InventoryItem(await fetchItem('cureall')),
- new InventoryItem(await fetchItem('potion')),
- new InventoryItem(await fetchItem('super_potion')),
- ];
-
- UI.drawEnemyMonster();
- UI.drawActiveMonster();
- UI.drawActiveTechniques();
-})();