「特定のイベント中にしか仲間にならないキャラクター」というのを実装したいと思ったわけですが*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のオーリンみたいなキャラクター
コメント