DQ3 レベルに応じて経験値の配分を変える2

今回から実装に移ります。まず、前提として、オリジナルでも獲得経験値の最大値は3バイトMaxの#$FFFFFFです(平均前)。それ以上獲得しても#$FFFFFFでクリップされます。これを各自のレベルに応じて配分していくわけですが、分子の取り得る最大値は99、分母の取り得る最大値は298(レベル99が1人にレベル1が3人)となります。

誤差を極力抑えるため、分子*経験値をしてから分母で割るようにします(当たり前ですが)。獲得経験値が#$FFFFFFだった場合でも分子をかけた値の最大値は4バイトを超えません。従って分子*経験値の計算はSR: $001107 $00,X(4B)=A(1)*$00,X(3B)が使用できます。次にこれを分母(2バイト)で割るのですが、この除算を行うSRが存在しないので自作します。SR: $001295 $00,x(3B)=$00,X(3B)/A(2B?) 剰余=A,$30というSRが存在するので、基本このSRをパクって割られる数が4バイトに対応したものを作ればいい、ということになります。

というわけで、後は使用するRAM領域を決めて、条件に該当していれば傾斜配分計算を行い、各自への経験値の加算部分をいじれば終わり、ということになります。また、除算した余りを合計し、分母で割った数を余りの経験値として生存人数で割って加算する、ということも考えたのですが、理論的にこの値が各自に加算する際に1を超えないことがわかったのでその処理はスキップします*1。御託が長くなりましたが作業を開始します。まず、傾斜配分した経験値の保存先として、$7E2640-5Fを使用します。戦闘終了時のみ使用となるので、他の使用領域とかぶっていても問題ありません。

$7E2640-31人目の獲得経験値
$7E2644-72人目の獲得経験値
$7E2648-B3人目の獲得経験値
$7E264C-F4人目の獲得経験値
$7E2650-1最大レベル+1-1人目のレベル(2Byte),0の場合は経験値はもらえない
$7E2652-3最大レベル+1-2人目のレベル(2Byte),0の場合は経験値はもらえない
$7E2654-5最大レベル+1-3人目のレベル(2Byte),0の場合は経験値はもらえない
$7E2656-7最大レベル+1-4人目のレベル(2Byte),0の場合は経験値はもらえない
7E2658-9生存者の中の最大レベル+1
7E265A-B傾斜配分の分母
7E265C-D傾斜によって発生した余りの合計値(分母は7E265A)
7E265E0bit経験値傾斜配分が発生した
1bit獲得経験値ウィンドウを表示している
  • SR: $02A6AF 戦闘終了時処理SR_SR_0001(勝利時)
02A6EDJSR $EC75SR: $02EC75戦闘終了後経験値計算用RAM初期化
02A6F0JSR $EE5CSR: $02EE5C一人当たりの経験値計算
02A6F6JSR $EE7CSR: $02EE7C各自獲得経験値ウィンドウオープン

SR: $02EE7C 各自獲得経験値ウィンドウオープンについては次回にまわします。

  • SR: $02A7B3 経験値加算+レベルアップ処理
02A7CAJSR $EC83SR: $02EC83各自の経験値を$00-03にセット(インデックス:Y)
02A7CD-D3NOP

  • SR: $02EC75 戦闘終了後経験値計算用RAM初期化(新SR)
02EC75LDX #$001EX=#$001E
02EC78LDA #$0000A=#$0000
02EC7BSTA $2640,X$7E2640+X=A
02EC7EDEXX–
02EC7FDEXX–
02EC80BPL #$F9if(n==off) goto $02EC7B
02EC82RTSreturn

  • SR: $02EC83 各自の経験値を$00-03にセット(インデックス:Y)(新SR)
02EC83PHXPush X
02EC84TYAA=Y
02EC85ASLA<<1
02EC86ASLA<<1
02EC87TAXX=A
02EC88LDA $2640,XA=$7E2640+X下位2バイト
02EC8BSTA $00$000000=A
02EC8DLDA $2642,XA=$7E2642+X上位2バイト
02EC90STA $02$000002=A
02EC92PLXPull X
02EC93RTSreturn

  • SR: $02EE5C 一人当たりの経験値計算(新SR)
02EE5CPHAPush A
02EE5DPHXPush X
02EE5EPHYPush Y
02EE5FJSR $ECC1SR: $02ECC1生存者の最大レベル+1を返す
02EE62STA $2658$7E2658=A
02EE65JSR $ECC6SR: $02ECC6生存者中の最大レベル+1-レベル値をセット
02EE68JSR $ED50SR: $02ED50経験値の傾斜配分をするか(該当c=on)
02EE6BBCS #$05if(c==on) goto $02EE72
02EE6DJSR $ECF4SR: $02ECF4一人当たりの経験値計算(平等)
02EE70BRA #$03goto $02EE75
02EE72JSR $ED8FSR: $02ED8F一人当たりの経験値計算(傾斜)
02EE75JSR $A746SR: $02A746一人当たりの獲得経験値計算処理
02EE78PLYPull Y
02EE79PLXPull X
02EE7APLAPull A
02EE7BRTSreturn

  • SR: $02ECC1 生存者の最大レベル+1を返す
02ECC1JSR $EC94SR: $02EC94
02ECC4INCA++
02ECC5RTSreturn

  • SR: $02EC94 生存者中の最大レベル取得(新SR)
02EC94JSL $02B9A6SR: $02B9A6パーティ人数取得
02EC98STA $02$000002=Aパーティ人数を$02にセット
02EC9ALDY #$0000Y=#$0000
02EC9DLDA #$0001A=#$0001初期値としてレベル1をセット
02ECA0PHAPush A
02ECA1CPY $02Y==$000002?
02ECA3BEQ #$18if(z==on) goto $02ECBD
02ECA5JSL $043F87SR: $043F87 引数:1#$01 引数:2#$FD 引数:3#$FF生死判定(死亡c=on?)
02ECACAND #$0010A&=#$0010
02ECAFBNE #$09if(z==off) goto $02ECBA死人は飛ばす
02ECB1JSR $ED35SR: $02ED35指定キャラクターのレベルを返す(ひとりじめベルト装備時は1)
02ECB4CMP $01,SA>=Stack($01)?スタック中のレベル値と比較
02ECB6BCC #$02if(c==off) goto $02ECBA
02ECB8STA $01,SStack($01)=A大きければ入れ替え
02ECBAINYY++
02ECBBBRA #$E4goto $02ECA1
02ECBDNOP
02ECBENOP
02ECBFPLAPull A
02ECC0RTSreturn

  • SR: $02ED35 指定キャラクターのレベルを返す(ひとりじめベルト装備時は1)(新SR)
02ED35STY $2428$7E2428=Y
02ED38LDA #$00F2A=#$00F2ひとりじめベルトのアイテムID
02ED3BSTA $242C$7E242C=A
02ED3EJSL $02B87ASR: $02B87Aアイテム装備チェック
02ED42BVC #$04if(v==off) goto $02ED48
02ED44LDA #$0001A=#$0001レベル1
02ED47RTSreturn
02ED48JSL $042FEBSR: $042FEB 引数:1#$01 引数:2#$FD 引数:3#$FFレベル取得
02ED4FRTSreturn

  • SR: $02ECC6 生存者中の最大レベル+1-レベル値をセット(新SR)
02ECC6JSL $02B9A6SR: $02B9A6パーティ人数取得
02ECCASTA $02$000002=A
02ECCCLDY #$0000Y=#$0000
02ECCFCPY $02Y==$000002?
02ECD1BEQ #$20if(z==on) goto $02ECF3
02ECD3JSL $043F87SR: $043F87 引数:1#$01 引数:2#$FD 引数:3#$FF生死判定(死亡c=on?)
02ECDAAND #$0010A&=#$0010
02ECDDBNE #$11if(z==off) goto $02ECF0死人は飛ばす
02ECDFJSR $ED35SR: $02ED35指定キャラクターのレベルを返す(ひとりじめベルト装備時は1)
02ECE2STA $00$000000=A
02ECE4TYAA=Y
02ECE5ASLA<<1
02ECE6TAXX=A
02ECE7LDA $2658A=$7E2658
02ECEASECc=on
02ECEBSBC $00A-=$000000差分を計算
02ECEDSTA $2650,X$7E2650+X=A
02ECF0INYY++
02ECF1BRA #$DCgoto $02ECCF
02ECF3RTSreturn

  • SR: $02ED50 経験値の傾斜配分をするか(該当c=on)
02ED50LDA #$FFFFA=#$FFFF
02ED53CMP $06FFE2A==$06FFE2?ROM中の傾斜配分フラグを調べる#$FFFF以外は傾斜配分しない
02ED57BEQ #$02if(z==on) goto $02ED5B
02ED59CLCc=off
02ED5ARTSreturn
02ED5BJSR $A7A1SR: $02A7A1生存人数取得
02ED5ECMP #$0001A==#$0001?生存人数が1人なら傾斜配分しない
02ED61BEQ #$F6if(z==on) goto $02ED59
02ED63JSR $EE03SR: $02EE03経験値を傾斜配分するレベル差数取得
02ED66STA $00$000000=A
02ED68LDX #$0000X=#$0000
02ED6BLDA $2650,XA=$7E2650+X
02ED6ECMP $00A>=$000000?
02ED70BCS #$09if(c==on) goto $02ED7B
02ED72INXX++
02ED73INXX++
02ED74CPX #$0008X>=#$0008 ?
02ED77BCC #$F2if(c==off) goto $02ED6B
02ED79CLCc=off
02ED7ARTSreturn
02ED7BSECc=on
02ED7CRTSreturn

  • SR: $2EE03 経験値を傾斜配分するレベル差数取得(新SR)
02EE03LDA $2658A=$7E2658
02EE06STA $00$000000=A
02EE08LDA #$000AA=#$000A
02EE0BLDX #$0000X=#$0000
02EE0EJSL $00121CSR: $00121C$00,X(2B)=$00,X(2B)/A(1B) 剰余=A
02EE12LDA $00A=$000000
02EE14CLCc=off
02EE15ADC #$0002A+=#$0002
02EE18PHAPush A
02EE19LDA #$0006A=#$0006
02EE1CCMP $01,SA>=Stack($01)?
02EE1EBCS #$02if(c==on) goto $02EE22
02EE20BRA #$02goto $02EE24
02EE22STA $01,SStack($01)=A
02EE24PLAPull A
02EE25RTSreturn

思いのほか長くなってしまったのでこのへんで。次回は実際の経験値配分計算(平均・傾斜)を実装します。

*1:例:分母が100で、生存人数が4人の場合、余りの合計値の最大は396、分母の100で割ると整数部分は3となり、これを生存人数の4で割っても各自に加算する経験値は1を超えない。生存人数が2人、3人の場合も同様

コメント

タイトルとURLをコピーしました