DQ3 ゲストキャラクター概念の追加1(戦闘中編1)

「特定のイベント中にしか仲間にならないキャラクター」というのを実装したいと思ったわけですが*1、通常のキャラクターと何が違うかというと、「戦闘中自分で操作できない」「アイテム欄を操作できない」「全滅条件が異なる」等が挙げられます。そのうち「戦闘中自分で操作できない」はAIを実装しない限り実現できないので諦めるとして、残りの2つについて実装してみることにします。

まず「全滅条件を変える」ですが、今回は「過去テドンイベント中に1人でも死んだら全滅」「幽霊船イベント中にPC側3人が死ぬorゲストキャラクターが死ぬ」の2つについて実装してみました。オリジナルの実装をよく理解すればその仕組みの中で実装可能です。とっかかりとして「全滅条件を特定の状況で変える」とは、戦闘終了判定の処理に例外処理を加えてやればいいということで、その処理を解析していくところから作業を始めます。

  • SR: $02B32F 戦闘終了時フラグセット?
02B356 JSR $B3C5 SR: $02B3C5 PC側行動可能チェック
  • SR: $02B3C5 PC側行動可能チェック
02B3C5 JSL $C2C739 SR: $02C739 引数:1#$08 行動可能チェック用マスクデータ作成
02B3CA JSL $C2C766 SR: $02C766 引数:1#$00 行動可能フラグセット・死亡キャラクターはフラグをOFFにする
02B3CF PEA #$2011 Push #$2011
02B3D2 PEA #$0040 Push #$0040
02B3D5 PEA #$7E00 Push #$7E00 格闘場の戦闘かチェック
02B3D8 JSL $C9029E SR: $09029E RAM上情報取得
02B3DC BNE #$05 if(z==off) goto $02B3E3
02B3DE JSL $C2C7C6 SR: $02C7C6 引数:1#$28 PC側行動可能フラグセット・麻痺キャラクターはフラグをOFFにする
02B3E3 LDA $00 A=DP($00)
02B3E5 ORA $02 Aor=DP($02)
02B3E7 RTS return
  • SR: $02C739 行動可能チェック用マスクデータ作成
02C739 PHP Push P Flag
02C73A REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C73C PHA Push A
02C73D PHX Push X
02C73E PHY Push Y
02C73F PHB Push DB
02C740 PEA #$7E7E Push #$7E7E
02C743 PLB Pull DB
02C744 PLB Pull DB
02C745 LDA #$FFFF A=#$FFFF 下位から1ビットが戦闘中各キャラクターに相当する
02C748 STA $2434 $2434=A
02C74B LDA #$00FF A=#$00FF 3バイト=24ビット分
02C74E STA $2436 $2436=A
02C751 JSR $C7FB SR: $02C7FB 呼び出し元の後の1バイトを引数として取得し行動可能フラグセット
02C754 LDA $2438 A=$2438
02C757 STA $00 DP($00)=A
02C759 LDA $243A A=$243A
02C75C STA $02 DP($02)=A
02C75E PLB Pull DB
02C75F REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C761 PLY Pull Y
02C762 PLX Pull X
02C763 PLA Pull A
02C764 PLP Pull P Flag
02C765 RTL return
  • SR: $02C8F0 戦闘中各種フラグ作成用アドレスリスト_SR_0004
02C8F0 LDA $203C,Y A=$203C+Y
02C8F3 AND #$00FF A&=#$00FF
02C8F6 CMP #$0004 A==or>=#$0004? キャラクターがPC側か格闘場で賭けたモンスターか
02C8F9 RTS return
  • SR: $02C766 行動可能フラグセット
02C766 PHP Push P Flag
02C767 REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C769 PHA Push A
02C76A PHX Push X
02C76B PHY Push Y
02C76C PHB Push DB
02C76D PEA #$7E7E Push #$7E7E
02C770 PLB Pull DB
02C771 PLB Pull DB
02C772 LDA $00 A=DP($00) 既にセット済みのフラグに対してのみマスクする
02C774 STA $2434 $2434=A
02C777 LDA $02 A=DP($02) 既にセット済みのフラグに対してのみマスクする
02C779 STA $2436 $2436=A
02C77C JSR $C7FB SR: $02C7FB 呼び出し元の後の1バイトを引数として取得し行動可能フラグセット
02C77F LDA $2438 A=$2438
02C782 STA $00 DP($00)=A
02C784 LDA $243A A=$243A
02C787 STA $02 DP($02)=A
02C789 PLB Pull DB
02C78A REP #$30 m=off(A/M:16b) x=off(X/Y:16b)
02C78C PLY Pull Y
02C78D PLX Pull X
02C78E PLA Pull A
02C78F PLP Pull P Flag
02C790 RTL return
  • SR: $02C8C8 戦闘中各種フラグ作成用アドレスリスト_SR_0000
02C8C8 JSL $C2BE8A SR: $02BE8A 引数:1#$1C 生死判定
02C8CD BCS #$02 if(c==on) goto $02C8D1
02C8CF SEC c=on
02C8D0 RTS return
02C8D1 CLC c=off
02C8D2 RTS return

このSRを見ると戦闘終了の判定方法がわかります。DP($00~02)の3バイトを使って各1ビットが戦闘中の各キャラクター(0~23)を表現します。まず、SR: $02C739を使ってPC側に相当するビットを立てます(生死問わず)。次にSR: $02C766をコールしてONになっているビットに対して”のみ”生死判定を行い、死亡時にはビットをOFFにしていきます。SR: $C2C7C6も同様に麻痺しているキャラクターのビットをOFFにしています。この3つのSRをコールした時点でDP($00~02)には死亡していなくて麻痺していないキャラクターのビットだけがONになっている状態になります。従って、DP($00)とDP($02)を足して0でない場合はPC側は全滅していない、と判断出来ます。長くなったので続きは次回。

*1:DQ4のオーリンみたいなキャラクター