« get me outta code hell

Basic concept of unique actions - csb-game - Pixelly spin-off of the Command Synergy Battle system used in Final Fantasy XIII
summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorrie <towerofnix@gmail.com>2018-08-12 16:02:07 -0300
committerFlorrie <towerofnix@gmail.com>2018-08-12 16:02:07 -0300
commit87b37dc9d6dfc9fe48d8226657d11e36e2a66b99 (patch)
treea0dbc539b0f5e86aa49a6c62e673b5a6e3126f48
parent367facda08882fc0ac68fcf9a7cb2ea235040a7f (diff)
Basic concept of unique actions
-rw-r--r--index.js74
1 files changed, 48 insertions, 26 deletions
diff --git a/index.js b/index.js
index 6e0af27..8bf7ee5 100644
--- a/index.js
+++ b/index.js
@@ -2,6 +2,24 @@
 
 const canvas = document.getElementById('canvas')
 
+const last = arr => arr[arr.length - 1]
+
+const actionDatabase = {
+  fire: [
+    {id: 'fire',   chain: 'fire', label: 'Fire',   size: 1, target: 'enemy', color: '#F77'},
+    {id: 'fira',   chain: 'fire', label: 'Fira',   size: 2, target: 'enemy', color: '#F77'},
+    {id: 'firaga', chain: 'fire', label: 'Firaga', size: 3, target: 'enemy', color: '#F77'}
+  ],
+  cure: [
+    {id: 'cure', chain: 'cure', label: 'Cure', size: 1, target: 'ally', color: '#AFA'}
+  ],
+  blizz: [
+    {id: 'blizz',    chain: 'blizz', label: 'Blizz',    size: 1, target: 'enemy', color: '#AAF'},
+    {id: 'blizzara', chain: 'blizz', label: 'Blizzara', size: 2, target: 'enemy', color: '#AAF'},
+    {id: 'blizzaga', chain: 'blizz', label: 'Blizzaga', size: 3, target: 'enemy', color: '#AAF'}
+  ]
+}
+
 class Sprite {
   constructor() {
     this.x = 0
@@ -145,14 +163,14 @@ class ATBBar {
   aiUpdate(dt) {
     // Determine a target
     if (!this.battleCharacter.targetCharacter) {
-      this.battleCharacter.determineNewOffenseTarget()
+      this.battleCharacter.determineNewTarget('enemy')
     }
 
     // ATB gauge not full? Try to queue actions
     if (!this.battleCharacter.isExecutingChain && this.battleCharacter.targetCharacter && this.getRemainingSpace() >= 0) {
       // TODO: More moves
       while (this.getRemainingSpace()) {
-        this.queuedActions.push({label: 'Fire', size: 1})
+        this.queuedActions.push(actionDatabase.fire[0])
       }
     }
 
@@ -332,17 +350,12 @@ class BaseBattleMenu {
 
 class ActionMenu extends BaseBattleMenu {
   constructor(battle) {
-    super({options: [
-      ['Fire', 'Fira', 'Firaga'],
-      ['Blizz', 'Blizza', 'Blizzaga'],
-      ['Aero', 'Aerora', 'Aeroga'],
-      ['Zap', 'Zappa', 'Zappaga'],
-      ['Bio', 'Biora'],
-      ['Stun', 'Stunra', 'Stunga']
-    ].map(arr => ({levelTexts: arr}))})
+    super({options: Object.values(actionDatabase)
+      .map(chain => ({chain, levelTexts: chain.map(action => action.label)}))
+    })
 
     this.battle = battle
-    this.uiLevel = 6 // 1-3 -- which of "fire", "fira", "firaga" is selected.
+    this.uiLevel = 3 // 1-3 -- which of "fire", "fira", "firaga" is selected.
   }
 
   drawOption(option, ctx) {
@@ -364,7 +377,7 @@ class ActionMenu extends BaseBattleMenu {
   }
 
   getEffectiveLevel(option) {
-    return Math.min(option.levelTexts.length, this.uiLevel)
+    return Math.min(this.getMaxLevel(option), this.uiLevel)
   }
 
   getMaxLevel(option) {
@@ -396,10 +409,7 @@ class ActionMenu extends BaseBattleMenu {
     const remainingSpace = atbBar.getRemainingSpace()
 
     if (effectiveLevel <= remainingSpace) {
-      atbBar.queuedActions.push({
-        label: option.levelTexts[effectiveLevel - 1],
-        size: effectiveLevel
-      })
+      atbBar.queuedActions.push(option.chain[effectiveLevel - 1])
 
       if (effectiveLevel === remainingSpace) {
         this.battle.showTargetMenu()
@@ -416,8 +426,8 @@ class TargetMenu extends BaseBattleMenu {
     this.battle = battle
   }
 
-  buildOptions() {
-    this.options = this.battle.playerCharacter.getValidOffenseTargets()
+  buildOptions(action) {
+    this.options = this.battle.playerCharacter.getValidTargets(action)
       .map(char => ({label: char.name, battleCharacter: char}))
   }
 }
@@ -501,8 +511,8 @@ class BattleCharacter extends Sprite {
     }
   }
 
-  determineNewOffenseTarget() {
-    const targets = this.getValidOffenseTargets()
+  determineNewTarget(targetType) {
+    const targets = this.getValidTargets(targetType)
     if (targets.length) {
       this.targetCharacter = targets[0]
     } else {
@@ -510,9 +520,11 @@ class BattleCharacter extends Sprite {
     }
   }
 
-  getValidOffenseTargets() {
+  getValidTargets(targetType) {
     return battle.getAllBattleCharacters()
-      .filter(char => char.team !== this.team)
+      .filter(char =>
+        targetType === 'enemy' && char.team !== this.team ||
+        targetType === 'ally' && char.team === this.team)
       .filter(char => !char.dead)
   }
 
@@ -525,13 +537,19 @@ class BattleCharacter extends Sprite {
     }
   }
 
+  recoverHP(amount) {
+    if (!this.dead) {
+      this.hp = Math.min(this.maxHP, this.hp + amount)
+    }
+  }
+
   died() {
     this.hp = 0
     this.dead = true
 
     for (const battleCharacter of this.battle.getAllBattleCharacters()) {
       if (battleCharacter.targetCharacter === this) {
-        battleCharacter.determineNewOffenseTarget()
+        battleCharacter.determineNewTarget('enemy') // TODO: battleCharacter.targetType
       }
     }
   }
@@ -693,7 +711,7 @@ class Battle {
   showTargetMenu() {
     this.changeMenuAnim = {old: this.currentMenu, direction: 1, time: 1}
     this.currentMenu = this.targetMenu
-    this.targetMenu.buildOptions()
+    this.targetMenu.buildOptions(last(this.playerCharacter.atbBar.queuedActions).target) // TODO: Target type stored on the player
   }
 
   hideCurrentMenu() {
@@ -763,7 +781,11 @@ class MagicProjectile {
     this.y += dt * 5 * (this.target.y - this.y)
 
     if (Math.abs(this.target.x - this.x) <= 5 && Math.abs(this.target.y - this.y) <= 5) {
-      this.target.takeDamage(this.action.size * 20)
+      if (['fire', 'blizz'].includes(this.action.chain)) {
+        this.target.takeDamage(this.action.size * 20)
+      } else if (this.action.id === 'cure') {
+        this.target.recoverHP(200)
+      }
       this.discarded = true
     }
   }
@@ -771,7 +793,7 @@ class MagicProjectile {
   draw() {
     const ctx = this.canvas.getContext('2d')
     ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
-    ctx.fillStyle = 'red'
+    ctx.fillStyle = this.action.color
     ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)
   }
 }