DQ3 まねまね実装1

まねまねの実装を行います。実質これが戦闘部分に関しての変更としては今のところ最後となります。まだいくつか新しい案が浮かんできたのですが、それはまた後でということにします。さて、戦闘関連の変更をしていて今のところこれが一番厄介でした。例によってDQ6で動作を確認してみます。

  1. 反撃をするのは攻撃が終わってから(2回攻撃の1回目では反撃しない)。
  2. 複数回攻撃を受けても反撃するのは最後の戦闘行動でのみ。
  3. 味方からの行動は反撃?対象にはならない。
  4. まねまねによる反撃はまねされないのでまねまね合戦が延々と続くことはない。
  5. (未確認だが)マホトーン中でも呪文の反撃は可能。MPも消費しない。

実装を簡単にするために、とりあえず敵が使うことは想定しないことにします。事前準備としてまねまねの戦闘行動の定義を#$0115にしておきます。※まねまね実装は一気に実装してしまわないとあっさりフリーズします。実装をパクる場合は一連の記事が完結してからにしてください(全3回を予定)。

  • SR: $02D580 直接攻撃反射ダメージ計算等
02D58C JSR $D970 SR: $02D970
  • SR: $02D980 まねまね中のキャラクタがいるかチェックし反撃するか決定
02D970 LDA $23EE A=$23EE
02D973 CMP #$0115 A==#$0115?
02D976 BNE #$03 if(z==off) goto $02D97B
02D978 JMP $D9FB ($02D9FB) goto $02D9FB
02D97B LDX $23E4 X=$23E4
02D97E STX $2428 $2428=X
02D981 JSL $C2CB2B SR: $02CB2B 引数:1#$2050 引数:2#$0001
02D989 BNE #$70 if(z==off) goto $02D9FB
02D98B JSL $C2CB2B SR: $02CB2B 引数:1#$2049 引数:2#$00FF
02D993 BEQ #$66 if(z==on) goto $02D9FB
02D995 JSL $C2BE8A SR: $02BE8A 引数:1#$1C
02D99A BCS #$5F if(c==on) goto $02D9FB
02D99C LDX $23E8 X=$23E8
02D99F STX $2428 $2428=X
02D9A2 JSL $C2CB2B SR: $02CB2B 引数:1#$2050 引数:2#$0001
02D9AA BEQ #$4F if(z==on) goto $02D9FB
02D9AC JSL $C2BE8A SR: $02BE8A 引数:1#$16
02D9B1 BCS #$48 if(c==on) goto $02D9FB
02D9B3 JSL $C2CB2B SR: $02CB2B 引数:1#$2047 引数:2#$00FF
02D9BB BNE #$3E if(z==off) goto $02D9FB
02D9BD JSL $C2CB2B SR: $02CB2B 引数:1#$2034 引数:2#$01FF
02D9C5 CMP #$0115 A==#$0115?
02D9C8 BNE #$31 if(z==off) goto $02D9FB
02D9CA PHY Push Y
02D9CB LDY #$0000 Y=#$0000
02D9CE TXA A=X
02D9CF SEP #$20 m=on(A/M:8b)
02D9D1 CMP $2620,Y A==$2620+Y?
02D9D4 BEQ #$19 if(z==on) goto $02D9EF
02D9D6 REP #$20 m=off(A/M:16b)
02D9D8 LDA $2620,Y A=$2620+Y
02D9DB AND #$00FF A&=#$00FF
02D9DE CMP #$0018 A>=#$0018?
02D9E1 BCS #$06 if(c==on) goto $02D9E9
02D9E3 INY Y++
02D9E4 CPY #$0018 Y>=#$0018?
02D9E7 BCC #$E5 if(c==off) goto $02D9CE
02D9E9 TXA A=X
02D9EA SEP #$20 m=on(A/M:8b)
02D9EC STA $2620,Y $2620+Y=A
02D9EF REP #$20 m=off(A/M:16b)
02D9F1 TYA A=Y
02D9F2 ASL A<<1
02D9F3 TAY Y=A
02D9F4 LDA $23EE A=$23EE
02D9F7 STA $2630,Y $2630+Y=A
02D9FA PLY Pull Y
02D9FB RTS return

ぐんたいよびの実装同様「まねまねによる反撃を行うキャラのID」および「反撃の際に使用される戦闘行動ID」を1セットとして保存しておく領域を新たに定義する必要があります。それぞれ、$7E2610-1F、$7E2620-2Fに保存することにします。また、これらの領域は初期化時にFFで埋めておくことを前提とします。今回はまず攻撃を受けたときにその行動IDを保存するところまで実装します。実装の内容は以下のとおりです。

  • 戦闘行動がまねまね(#$0115)、逃げる(#$006A)の場合は処理をスキップする。$02D980は行動対象でないキャラクターもループでまわされるため、スキップしないとフリーズしたりする。($02D980-8B)
  • 現在の戦闘行動の行動主体($7E23E4)を調べて主体が味方である、もしくは死亡している(念のため)ば反撃しないのでスキップする。($02D98D-A2)
  • 行動対象($7E23E8)が味方かつその戦闘行動がまねまね(#$0115)であれば反撃用バッファにセットする。セットする際に行動対象のインデックスがすでにバッファ内に存在していれば現在の戦闘行動で上書きする。($02D9AA-EE)

こう書いてしまうと割とさらっと実装できたみたいに見えますが、実際は試行錯誤の上たどりついたもので、途中で何度かやめようかと思うくらいでした。