Elona改造講座 第16回(鍛冶ハンマーの移植:前編)
お久しぶりのElona改造講座です。
大規模な改造として、今回から2~3回かけてoo系列の鍛冶ハンマーの処理をMMAhに移植してみましょう。
最初にいくつか注意点があります。
・本講座で掲載するソースコードのラベル名はMMAhの20230113版(最新版)か20220121版(その1つ前の版)、およびCSの配布ソースに準拠しています。
他のバージョン(CSのexeを逆コンパイルしたものも含む)だとラベル名がズレるのでご注意ください。
・本講座のソースコードには適宜コメントを追加しています。
また、elseとifは1行にまとめた形に書き換えています。
この為、逆コンパイルした直後のソースコードとは若干の違いがあります。
①鍛冶ハンマーとは?
ooで追加されたカスタムアイテムです。
最初は「ボロボロのハンマー」という名前で店売りされているだけのアイテムですが、これを使って武具の作成や修理を行うことでハンマーに経験値が溜まってレベルが上がっていき、やがて「丈夫なハンマー」や「鍛冶師のハンマー」などと名前が変化していき、AF合成や武具の強化などできることが増えていきます。
ここで「カスタムアイテムなのでMMAhに導入することもできるのでは?」と思う方もいるでしょう。実際に導入自体は可能で、導入することで雑貨屋や何でも屋に売り出されもするのですが、いざ使ってみるとこの通り。効果が設定されていない為「それはomake_MMA/TrashThrowでは使用できない」と表示されるだけです。
ソースコードのハンマーの処理(_switch_val == 2000)を見てみても、警告メッセージが出るだけで特に効果は設定されていませんね。
②ooから移植すべき処理を特定
まずはooのソースコードの_switch_val == 2000を見てみましょう。*label_2831にジャンプする処理が見つかりますね。
(*label_2202は全アイテム共通の終了処理ようなので今は忘れておきましょう)
ccが0でない場合(すなわちPC以外が使用した場合)には無視するような安全措置も入っているようです。
// 鍛冶ハンマーを使用
if ( _switch_val == 2000 | _switch_sw ) {
_switch_sw = 0
if ( cc != 0 ) {
txtvalid = 0
txt_select lang("何もおきない… ", "Nothing happens..."), "", "", "", "", "", "", "", ""
goto *label_2202
}
cw = ci
snd 100
gosub *label_2831
if ( stat ) {
extend = 0
cdata(140, cc) = 20012
cdata(141, cc) = 25 + rnd(11)
cdata(142, cc) = cw
}
else {
obvious = 0
}
goto *label_2202
_switch_sw++
}
続いて"鍛冶の技術が足りない。"で検索してみましょう。
(Lv20以下のハンマーでAF合成許可証を使用した時のメッセージです)
*label_2831が見つかりましたね。これがooにおける鍛冶の処理のメインであり、鍛冶ハンマー使用時にはまずこのラベルにジャンプすることになります。溶鉱炉と金床があるかどうかを確認したり、作る武器の種別を選択する処理などが書かれているようです。
*label_2831
invsubroutine = 1
dim craftref, 10
invctrl = 30, 0
step = 0
cancel = 0
cdata(144, cc) = 0
repeat
if ( cdata(144, cc) != 0 ) {
if ( cdata(144, cc) == 3 ) {
gosub *label_2833
if ( stat == 0 ) {
cancel = 1
}
}
break
}
if ( cancel ) {
break
}
gosub *label_2030
if ( stat == 1 ) {
reftypeminor = refitem(inv(3, ci), 9, ci)
if ( step == 0 ) {
// 武器の作成 折れた刃(ID:50)が必要
if ( inv(3, ci) == 50 ) {
anvil = 0
furnance = 0
repeat 5480
// 金床(ID:96)と溶鉱炉(ID:531)がマップ内にあることの確認
if ( anvil & furnance ) {
break
}
if ( inv(0, cnt) <= 0 ) {
continue
}
if ( inv(3, cnt) == 96 ) {
anvil = 1
}
else {
if ( inv(3, cnt) == 531 ) {
furnance = 1
}
}
loop
if ( anvil == 0 | furnance == 0 ) {
txtvalid = 0
txt_select lang("溶鉱炉と金床が必要だ。", "furnace and anvil required."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
txtef 5
txtvalid = 0
txt_select lang("何を作る?", "What do you create? "), "", "", "", "", "", "", "", ""
promptl(0, promptmax) = lang("大剣", "Repair"), "a", "" + 1
promptmax++
promptl(0, promptmax) = lang("長剣", "Repair"), "b", "" + 2
promptmax++
promptl(0, promptmax) = lang("短剣", "Repair"), "c", "" + 3
promptmax++
promptl(0, promptmax) = lang("槍", "Repair"), "d", "" + 7
promptmax++
promptl(0, promptmax) = lang("鉾槍", "Repair"), "e", "" + 8
promptmax++
promptl(0, promptmax) = lang("斧", "Repair"), "f", "" + 9
promptmax++
promptl(0, promptmax) = lang("大斧", "Repair"), "g", "" + 10
promptmax++
promptl(0, promptmax) = lang("鎌", "Repair"), "h", "" + 11
promptmax++
val = promptx, prompty, 220, 1
gosub *label_2103
if ( rtval == (-1) ) {
cancel = 1
break
}
craftref(step * 2) = -1, 10000 + rtval
step++
invctrl(1) = 1
}
else {
// AF合成 AF合成許可証が必要 ハンマーLv21以上必要
if ( equalsitem(ci, "artifacts fusion license") ) {
if ( inv(25, cw) <= 20 ) {
txtvalid = 0
txt_select lang("鍛冶の技術が足りない。", "smith's skill is lacking."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
<以下省略>
鍛冶の処理はこれ以降にも続いており、label_2831~label_2835が鍛冶の処理に関係したサブルーチンとなります。各サブルーチンの内訳は次のようになります。
label_2831
鍛冶の処理のメイン
(鍛冶ハンマー選択時に最初に呼ばれるサブルーチン)
label_2832
鍛冶のオートターン処理
(鍛冶の途中でカキーンとか表示されるやつ)
(結果のアイテム生成処理もここ)
*label_2833
AF合成の処理
*label_2834
AF合成、継承エンチャ一覧のページ送り
*label_2835
AF合成、継承エンチャ一覧表示処理
(決定キーでAF合成開始)
また、これらとは別に鍛冶で使用する専用の関数も存在します。
当然ながらこれらも移植する必要があります。
getencplimit
AF合成のエンチャント強度限界の取得処理
modexpsmith
鍛冶ハンマーの経験値獲得処理
smithcheck
アイテムが鍛冶に使えるか否かのチェック処理
(「鍛えるアイテム」の欄に表示されるアイテムをリストアップする為の処理)
reinforcecheck
会心の出来・自信作の場合の処理
③移植の方針
以上の処理をooからMMAhに移植していきます。従来通りにstart.hspに追加してもかまわないのですが、今回は別ファイルに記述する方式を取ってみましょう。
まずstart.hspと同じフォルダに「cs_smith.hsp」という名前の空のファイルを作成してください。次にstart.hsp内を"どのファイルから神を作成する?"で検索し、出てきたラベル*label_1354の上に以下のように記述してください。
// CS追加 鍛冶ハンマーの処理(別ファイル)のインクルード
#include "cs_smith.hsp"
#includeは指定したソースファイル(ここではcs_smith.hsp)の内容をこの位置に埋め込むことを意味します。
(別にこの位置でincludeする必要はありませんが、移植元のooと揃える為にここでやっています)
以降はこのファイルのみを加筆していきます。
ooからの移植後には、主に以下の変更を加える必要があります。
(1)鍛冶専用の変数・配列の宣言を追加
(無いとコンパイル時に弾かれます)
(2)テキスト表示方式の変更への対応
(txt_selectの第1引数に-1を追加します。また、txtvalid = 0やtxtmoreは削除します)
(3)ジャンプ先ラベルの書き換え
(鍛冶関係の場合はlabel_XXXXをlabel_smith_XXXXに変更します。それ以外のラベルの場合は処理内容から判断して対応するラベルを特定し、そこに飛びます)
この中で一番面倒なのは(3)のジャンプ先ラベルの書き換えです。
ooとMMAhでラベル番号の対応を取らないといけませんので……
ですが今回は私が既に対応を取ってしまっているので、ただ書き換えるだけでOKです。
④*label_2831の移植
まずはooのlabel_2831を移植します。cs_smith.hspにlabel_smith_2831という名前で移植しましょう。
移植後の*label_smith_2831は次のようになります。
ジャンプ先を書き換えたラベルは3種4箇所です。
label_2833はAF合成処理です。後で移植するのでlabel_smith_2833に書き換えておきましょう。
label_2030はインベントリ内のアイテム選択のサブルーチンです。MMAhではlabel_0936にあたります。
label_2103は選択肢を表示するサブルーチンです。MMAhではlabel_0992に相当します。作る武器・防具の種別を選択する為に使用します。
/* 鍛冶の処理 メイン */
*label_smith_2831
// CS追加 鍛冶に使用する変数の宣言(未初期化対策)
dim fusionlist, 2, 15
fusionlistmax = 0
invsubroutine = 1
dim craftref, 10
invctrl = 30, 0
step = 0
cancel = 0
cdata(144, cc) = 0
repeat
if ( cdata(144, cc) != 0 ) {
if ( cdata(144, cc) == 3 ) {
// gosub *label_2833
gosub *label_smith_2833
if ( stat == 0 ) {
cancel = 1
}
}
break
}
if ( cancel ) {
break
}
// インベントリ内のアイテム選択
// CS追加 本来はlabel_2030でcc=0にしてそのまま*label_2031に入る
// CSではcc=0してから*label_0936に移動
// gosub *label_2030
cc = 0
gosub *label_0936
if ( stat == 1 ) {
reftypeminor = refitem(inv(3, ci), 9, ci)
if ( step == 0 ) {
// 武器の作成 折れた刃(ID:50)が必要
if ( inv(3, ci) == 50 ) {
anvil = 0
furnance = 0
repeat 5480
// 金床(ID:96)と溶鉱炉(ID:531)がマップ内にあることの確認
if ( anvil & furnance ) {
break
}
if ( inv(0, cnt) <= 0 ) {
continue
}
if ( inv(3, cnt) == 96 ) {
anvil = 1
}
else : if ( inv(3, cnt) == 531 ) {
furnance = 1
}
loop
if ( anvil == 0 | furnance == 0 ) {
txt_select -1, lang("溶鉱炉と金床が必要だ。", "furnace and anvil required."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
txtef 5
txt_select -1, lang("何を作る?", "What do you create? "), "", "", "", "", "", "", "", ""
promptl(0, promptmax) = lang("大剣", "Repair"), "a", "" + 1
promptmax++
promptl(0, promptmax) = lang("長剣", "Repair"), "b", "" + 2
promptmax++
promptl(0, promptmax) = lang("短剣", "Repair"), "c", "" + 3
promptmax++
promptl(0, promptmax) = lang("槍", "Repair"), "d", "" + 7
promptmax++
promptl(0, promptmax) = lang("鉾槍", "Repair"), "e", "" + 8
promptmax++
promptl(0, promptmax) = lang("斧", "Repair"), "f", "" + 9
promptmax++
promptl(0, promptmax) = lang("大斧", "Repair"), "g", "" + 10
promptmax++
promptl(0, promptmax) = lang("鎌", "Repair"), "h", "" + 11
promptmax++
val = promptx, prompty, 220, 1
// gosub *label_2103
gosub *label_0992
if ( rtval == (-1) ) {
cancel = 1
break
}
craftref(step * 2) = -1, 10000 + rtval
step++
invctrl(1) = 1
}
else {
// AF合成 AF合成許可証が必要 ハンマーLv21以上必要
if ( equalsitem(ci, "artifacts fusion license") ) {
if ( inv(25, cw) <= 20 ) {
txt_select -1, lang("鍛冶の技術が足りない。", "smith's skill is lacking."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
anvil = 0
furnance = 0
repeat 5480
// 金床(ID:96)と溶解炉(ID:111)がマップ内にあることの確認
if ( anvil & furnance ) {
break
}
if ( inv(0, cnt) <= 0 ) {
continue
}
if ( inv(3, cnt) == 96 ) {
anvil = 1
}
else : if ( inv(3, cnt) == 111 ) {
furnance = 1
}
loop
if ( anvil == 0 | furnance == 0 ) {
txt_select -1, lang("溶解炉と金床が必要だ。", "furnace and anvil required."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
txtnew
txt_select -1, lang("まずは土台となるアーティファクトを選ぶ必要がある。", "Choose an base."), "", "", "", "", "", "", "", ""
invctrl(1) = 2
}
else {
// 防具の作成 皮(ID:337)が必要
if ( inv(3, ci) == 337 ) {
anvil = 0
furnance = 0
repeat 5480
// 金床(ID:96)と溶解炉(ID:111)がマップ内にあることの確認
if ( anvil & furnance ) {
break
}
if ( inv(0, cnt) <= 0 ) {
continue
}
if ( inv(3, cnt) == 96 ) {
anvil = 1
}
else : if ( inv(3, cnt) == 111 ) {
furnance = 1
}
loop
if ( anvil == 0 | furnance == 0 ) {
txt_select -1, lang("溶解炉と金床が必要だ。", "furnace and anvil required."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
txtef 5
txt_select -1, lang("何を作る?", "What do you create? "), "", "", "", "", "", "", "", ""
promptl(0, promptmax) = lang("鎧", "Armor"), "a", "" + 16001
promptmax++
promptl(0, promptmax) = lang("兜", "Helmet"), "b", "" + 12001
promptmax++
promptl(0, promptmax) = lang("盾", "Shild"), "c", "" + 14003
promptmax++
promptl(0, promptmax) = lang("重靴", "Heavy boots"), "d", "" + 18001
promptmax++
promptl(0, promptmax) = lang("ガントレット", "Gauntlets"), "e", "" + 22001
promptmax++
val = promptx, prompty, 220, 1
// gosub *label_2103
gosub *label_0992
if ( rtval == (-1) ) {
cancel = 1
break
}
craftref(step * 2) = -1, rtval
step++
cdata(144, cc) = 4
}
else {
notfound = 1
// 装備の修理・強化
if ( inv(20, ci) < 0 ) {
// 装備の修理 無条件に実行可能
notfound = 0
}
else {
anvil = 0
repeat 5480
if ( inv(0, cnt) <= 0 ) {
continue
}
if ( inv(3, cnt) == 96 ) {
anvil = 1
break
}
loop
if ( anvil == 0 ) {
txt_select -1, lang("金床が必要だ。", "anvil required."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
// 装備の強化 ハンマーLv21以上必要 ハンマーLv/7まで強化可能
if ( inv(25, cw) >= 21 & inv(20, ci) < inv(25, cw) / 7 ) {
notfound = 0
}
}
if ( notfound ) {
txt_select -1, lang("鍛冶の必要はない。", "It is not necessary to fix."), "", "", "", "", "", "", "", ""
cancel = 1
break
}
cdata(144, cc) = 2
}
}
}
}
else {
if ( step == 1 ) {
reftype = refitem(inv(3, ci), 5, ci)
if ( inv(4, ci) >= 4 & inv(4, ci) <= 5 & reftype >= 10000 & reftype <= 50000 ) {
txtnew
txt_select -1, lang("エンチャントを継承するアーティファクトを選ぶ必要がある。このアーティファクトは合成後、永久に失われる。", "Choose a artifact. Once you extract a enchant, the subject will be lost forever."), "", "", "", "", "", "", "", ""
snd 100
invctrl(1) = 2
}
}
else {
if ( step == 2 ) {
reftype = refitem(inv(3, ci), 5, ci)
if ( reftypeminor == 77001 | inv(3, ci) == 337 | inv(3, ci) == 716 ) {
cdata(144, cc) = 1
}
else {
if ( inv(4, ci) >= 4 & inv(4, ci) <= 5 & reftype >= 10000 & reftype <= 50000 ) {
if ( ibit(13, ci) ) {
snd 27
txt_select -1, lang("それはあなたの大事なものだ。<調べる>メニューから解除できる。", "It's set as no-drop. You can reset it from the <examine> menu."), "", "", "", "", "", "", "", ""
continue
}
cdata(144, cc) = 3
}
}
}
}
}
craftref(step * 2) = ci, inv(3, ci)
step++
}
else {
cancel = 1
}
loop
if ( cancel ) {
return 0
}
return 1
⑤*label_2832の移植
鍛冶のオートターン処理です。txt_selectとジャンプ先ラベルの変更箇所が多いです。
label_0277は素材に応じて価値を決定する処理で、MMAhではlabel_0241にあたります。
label_1960は銘(異名)の選択処理です。MMAhではlabel_0888にあたります。
label_1441は能力の再計算でしょうか? MMAhではlabel_0515にあたります。
label_1480は所持重量の再計算のようです。MMAhではlabel_0553にあたります。
/* 鍛冶 オートターン処理 MMAhでは*label_1182から呼び出される */
*label_smith_2832
if ( cdata(141, cc) \ 6 == 0 ) {
actionsp cc, 2
if ( stat == 0 ) {
txt_select -1, lang("疲労し過ぎて失敗した!", "You are too exhausted!"), "", "", "", "", "", "", "", ""
rowactend cc
return
}
}
if ( cdata(141, cc) > 0 ) {
if ( rnd(5) == 0 ) {
txtef 4
txt_select -1, lang(" *カキーン* ", "*bang*"), lang(" *カーン* ", "*bang*"), "", "", "", "", "", "", ""
}
if ( cdata(144, cc) == 1 | cdata(144, cc) == 4 ) {
if ( rnd(40 + extend * 10) == 0 ) {
extend++
}
}
return
}
cw = cdata(142, cc)
if ( cdata(144, cc) == 1 | cdata(144, cc) == 4 ) {
quality = 0
repeat step - 1, 1
ci = craftref(cnt * 2)
quality += inv(1, ci)
inv(0, ci)--
loop
randomize inv(25, cw) * 1000000 + inv(26, cw)
exrand_randomize inv(25, cw) * 1000000 + inv(26, cw)
if ( powf(inv(25, cw), 3) + sdata(11, cc) * 5 < rnd(quality) ) {
txtef 3
txt_select -1, lang("作成に失敗した……", "The blending attempt failed..."), "", "", "", "", "", "", "", ""
modexpsmith cw, 1 + rnd(limit(10 / inv(25, cw), 1, 2147483647)) + limitmax(inv(27, cw), quality / 1000)
inv(27, cw)++
skillexp2 11, cc, 10
randomize
exrand_randomize
return
}
flt inv(25, cw)
flttypeminor = craftref(1)
if ( cdata(144, cc) == 4 ) {
ci = craftref(2)
}
else {
ci = craftref(4)
}
reftypeminor = refitem(inv(3, ci), 9, ci)
if ( inv(3, ci) == 716 ) {
fltmaterial = 31 // アダマンタイト製
fixlv = calcfixlv(limit(inv(25, cw) * 2 / 25, 1, 4))
}
else {
if ( reftypeminor == 77001 ) {
if ( inv(3, ci) == 42 ) {
fltmaterial = 13 // ダイヤ製
}
else : if ( inv(3, ci) == 41 ) {
fltmaterial = 23 // エメラルド製
}
else : if ( inv(3, ci) == 40 ) {
fltmaterial = 21 // ミカ製
}
else : if ( inv(3, ci) == 39 ) {
fltmaterial = 15 // ルビナス製
}
refvalue = refitem(inv(3, ci), 20, ci)
fixlv = calcfixlv(limit(quality / (refvalue * powf(11, 2) / limitmin(inv(25, cw) * 2 / 25, 1)), 1, 4))
}
else {
if ( inv(3, ci) == 337 ) {
s = refchara(inv(23, ci), 8, 1)
if ( instr(s, 0, "/dragon/") != (-1) ) {
fltmaterial = 24 // ドラゴン類の場合、竜鱗製
}
else : if ( inv(23, ci) == 134 ) {
fltmaterial = 9 // スティールゴーレムの場合、スティール製
}
else : if ( inv(23, ci) == 135 | inv(23, ci) == 112 ) {
fltmaterial = 32 // ゴールドゴーレムorゴールデンアーマーの場合、ゴールデン製
}
else : if ( inv(23, ci) == 136 ) {
fltmaterial = 7 // ミスリルゴーレムの場合、ミスリル製
}
else : if ( inv(23, ci) == 138 ) {
fltmaterial = 31 // アダマンタイトゴーレムの場合、アダマンタイト製
}
else : if ( inv(23, ci) == 110 ) {
fltmaterial = 12 // リビングアーマーの場合、ブロンズ製
}
else : if ( inv(23, ci) == 111 ) {
fltmaterial = 10 // 鉄塊の場合、鉄製
}
else : if ( inv(23, ci) == 113 ) {
fltmaterial = 29 // デスアーマーの場合、チタン製
}
else : if ( inv(23, ci) == 191 | inv(23, ci) == 193 ) {
fltmaterial = 8 // ウィスプor輝くハリねずみの場合、エーテル製
}
else {
fltmaterial = 4 // 上記以外は鱗製
}
refvalue = refitem(inv(3, ci), 20, ci)
fixlv = calcfixlv(limit(quality / (refvalue * 20 / limitmin(inv(25, cw) * 2 / 25, 1)), 1, 4))
}
}
}
// 神器品質は奇跡品質に
if ( fixlv > 4 ) {
fixlv = 4
}
nostack = 1
mode = 8
itemcreate -1, 0, cdata(1, 0), cdata(2, 0), 0
mode = 0
inv(8, ci) = 3
fixmaterial = fltmaterial
fltmaterial = 0
// 素材に応じて価値を決定
// gosub *label_0277
gosub *label_0241
expsmith = rnd(limit(quality - powf(inv(25, cw), 3), 1, 2147483647)) + limitmax(inv(27, cw), quality / 1000)
if ( extend ) {
if ( inv(4, ci) >= 3 ) {
if ( rnd(40 / limitmax(extend, 40)) <= gettrait(cc, 70) * 3 ) {
txt_select -1, lang("これは会心の出来だ!", "Critical!"), "", "", "", "", "", "", "", ""
//txtmore
repeat 15
p = reinforcecheck(cnt, ci)
if ( p == (-1) ) {
break
}
if ( p ) {
inv(41 + cnt * 2, ci) += p * 3 / 2
}
loop
ibitmod 17, ci, 1
}
else {
if ( rnd(10 / limitmax(extend, 10)) <= gettrait(cc, 70) * 3 ) {
txt_select -1, lang("これは自信作だ!", "Confident of the merits!"), "", "", "", "", "", "", "", ""
//txtmore
repeat 15
p = reinforcecheck(cnt, ci)
if ( p == (-1) ) {
break
}
if ( p ) {
inv(41 + cnt * 2, ci) += p / 2
}
loop
ibitmod 17, ci, 1
}
}
}
}
randomize
exrand_randomize
if ( inv(4, ci) == 4 ) {
txtef 4
txt_select -1, lang("銘は?", "What do you want to name this artifact?"), "", "", "", "", "", "", "", ""
val = 3
// 銘(異名)の選択
// gosub *label_1960
gosub *label_0888
if ( stat ) {
p = stat
inv(23, ci) = list(1, p) + 40000
randomize
}
else {
obvious = 0
randomize
}
}
txtef 2
txt_select -1, lang(itemname(ci, 1) + "の作成に成功した!", "You successfully create " + itemname(ci, 1) + "!"), "", "", "", "", "", "", "", ""
snd 58
modexpsmith cw, expsmith
inv(27, cw)++
skillexp2 11, cc, 50
}
else {
if ( cdata(144, cc) == 2 ) {
ci = craftref(0)
txtef 2
if ( inv(20, ci) < 0 ) {
txt_select -1, lang(itemname(ci) + "の修理を終えた。", "Repair of " + itemname(ci) + " was finished."), "", "", "", "", "", "", "", ""
}
else {
txt_select -1, lang(itemname(ci) + "を打ち直した。", "Upgrade of " + itemname(ci) + " was finished."), "", "", "", "", "", "", "", ""
}
snd 58
inv(20, ci)++
modexpsmith cw, 1 + rnd(limitmin(10 / inv(25, cw), 1))
skillexp2 11, cc, 50
r1 = cc
// gosub *label_1441
gosub *label_0515
}
else {
if ( cdata(144, cc) == 3 ) {
olist = craftref(0), craftref(4)
repeat 2
inv(0, olist(cnt))--
chara_unequip olist(cnt)
cell_refresh inv(5, olist(cnt)), inv(6, olist(cnt))
loop
ci = craftref(2)
repeat fusionlistmax
encadd ci, fusionlist(0, cnt), fusionlist(1, cnt), 0, 1
loop
txtef 2
txt_select -1, lang("合成完了!", "You successfully fusion!"), "", "", "", "", "", "", "", ""
snd 58
modexpsmith cw, 1 + rnd(limitmin(2000 / inv(25, cw), 1)) + limitmax(inv(27, cw), quality / 1000)
inv(27, cw)++
skillexp2 11, cc, 250
// 所持重量計算
// gosub *label_1480
gosub *label_0553
r1 = 0
// gosub *label_1441
gosub *label_0515
}
}
}
return
⑥*label_2833の移植
AF合成の処理です。label_0259はエンチャ名を表示するサブルーチンです。MMAhではlabel_0227に相当します。
これとtxt_selectが1箇所あるだけで、それ以外には特に変更の必要は無さそうですね。
(実はここには1つ大きな落とし穴があるのですが、それについてはまたいずれ……)
/* 鍛冶 AF合成の処理 */
*label_smith_2833
gsel 4
repeat 8
pos cnt \ 4 * 180, cnt / 4 * 300
picload exedir + "\\graphic\\g" + (cnt + 1) + ".bmp", 1
loop
gsel 0
listmax = 0
page = 0
pagesize = 14
cs = 0
cc = 0
cs_bk = -1
inhmax = 0
inh_ci = craftref(4)
getinheritance inh_ci, inhlist, inhmax
if ( stat == 0 ) {
txt_select -1, lang("部屋が一杯で出来ない。", "Your home has no empty spot."), "", "", "", "", "", "", "", ""
return 0
}
base_ci = craftref(2)
repeat inhmax
encno = inhlist(cnt)
val = inv(40 + encno * 2, inh_ci)
if ( inv(25, cw) <= 40 ) {
p(65) = val / 10000
if ( p(65) == 0 ) {
p(65) = val
}
if ( p(65) == 53 | p(65) == 34 ) {
continue
}
if ( encref(0, p(65)) > 2 + (inv(25, cw) > 30) ) {
continue
}
}
val(1) = limitmax(inv(41 + encno * 2, inh_ci), getencplimit(val(0)))
p(59) = 0
encpmax = inv(25, cw) / 10 * getencplimit(val(0))
repeat 15
if ( inv(40 + cnt * 2, base_ci) == 0 ) {
break
}
if ( inv(40 + cnt * 2, base_ci) == val(0) ) {
if ( inv(41 + cnt * 2, base_ci) + val(1) > encpmax ) {
p(59) = 1
break
}
}
loop
if ( p(59) ) {
continue
}
val(2) = 0, refitem(inv(3, inh_ci), 5, inh_ci)
strict = 1
// エンチャント名の表示 MMAhでは*label_0227に相当
// gosub *label_0259
gosub *label_0227
strict = 0
list(0, listmax) = val(0), val(1)
listn(0, listmax) = cnven(s)
listmax++
loop
if ( listmax == 0 ) {
list(0, listmax) = -1
listn(0, listmax) = "継承効果なし"
listmax++
}
windowshadow = 1
このサブルーチンの末尾にはreturnが無い為、末尾まで来るとそのまま次のラベルに進みます。
⑦*label_2834の移植
継承エンチャ一覧のページ送り機能です。これは最初のラベル名以外に変更が必要な部分は無さそうですね。これもreturn無しのサブルーチンです。
/* 鍛冶 AF合成 ページ送り */
*label_smith_2834
redraw 0
cs_bk = -1
pagemax = (listmax - 1) / pagesize
if ( page < 0 ) {
page = pagemax
}
else {
if ( page > pagemax ) {
page = 0
}
}
⑧*label_2835の移植
ここもほぼ変更の必要は無さそうです。ジャンプ先ラベル名は変更していますが、このラベル自身か前章のラベルかしかないので、"_smith"を付けるだけで特に迷う要素はありませんね。
/* 鍛冶 AF合成 継承エンチャ一覧表示 */
*label_smith_2835
redraw 0
s = lang("継承されるエンチャント", "Inheritance enchants."), lang("決定 [開始] ", "Enter [Start] ") + strhint2 + strhint3b
display_window (windoww - 500) / 2 + inf_screenx, winposy(400), 500, 400
x = ww / 5 * 3
y = wh - 80
gmode 4, 180, 300, 50
pos wx + ww / 3 * 2, wy + wh / 2
grotate 4, cmbg / 4 \ 4 * 180, cmbg / 4 / 4 \ 2 * 300, 0, x, y
gmode 2
display_topic lang("継承効果", "Inheritance effects"), wx + 28, wy + 36
keyrange = 0
repeat pagesize
p = pagesize * page + cnt
if ( p >= listmax ) {
break
}
key_list(cnt) = key_select(cnt)
keyrange++
if ( cnt \ 2 == 0 ) {
pos wx + 70, wy + 66 + cnt * 19
gfini ww - 100, 18
gfdec2 12, 14, 16
}
loop
gmode 2
font lang(cfg_font1, cfg_font2), 14 - en * 2, 0
cs_listbk
repeat pagesize
p = pagesize * page + cnt
if ( p >= listmax ) {
break
}
i = list(0, p)
s = "" + listn(0, p)
cs_list s, wx + 58, wy + 66 + cnt * 19 - 1, 19
loop
if ( keyrange != 0 ) {
cs_bk = cs
}
redraw 1
await cfg_wait1
key_check
if ( key == key_enter ) {
if ( i == (-1) ) {
return 0
}
// 継承エンチャを配列fusionlistにセット
repeat listmax
fusionlist(0, cnt) = list(0, cnt)
fusionlist(1, cnt) = list(1, cnt)
loop
fusionlistmax = listmax
return 1
}
cursor_check
if ( key == key_pageup ) {
if ( pagemax != 0 ) {
snd 1
page++
// goto *label_2834
goto *label_smith_2834
}
}
if ( key == key_pagedown ) {
if ( pagemax != 0 ) {
snd 1
page--
// goto *label_2834
goto *label_smith_2834
}
}
if ( key == key_cancel ) {
return 0
}
// goto *label_2835
goto *label_smith_2835
⑨関数getencplimitの移植
ここからは関数の移植です。AF合成時のエンチャ強度限界の取得処理getencplimitを移植しましょう。特に変更する要素はなさそうです。
/* 鍛冶 AF合成用 エンチャント強度限界の取得処理 */
#defcfunc getencplimit int prm_1433
val@m5 = prm_1433 / 10000
if ( val@m5 != 0 ) {
if ( val@m5 == 1 ) {
return 50
}
if ( val@m5 == 2 ) {
return 100
}
if ( val@m5 == 3 ) {
return 200
}
if ( val@m5 == 6 ) {
return 100
}
if ( val@m5 == 7 ) {
return 100
}
if ( val@m5 == 8 ) {
return 50
}
if ( val@m5 == 9 ) {
return 1000
}
}
if ( prm_1433 == 29 ) {
return 100
}
if ( prm_1433 == 40 ) {
return 100
}
return 50
⑨関数modexpsmithの移植
鍛冶ハンマーの経験値獲得処理modexpsmithを移植しましょう。txt_select以外に変更箇所はなさそうです。
……が、せっかくなのでSESTを参考にレベルと経験値を表示する処理も追加してみました。
/* 鍛冶ハンマーの経験値獲得処理 */
#deffunc modexpsmith int prm_1471, int prm_1472
if ( inv(25, prm_1471) >= 2000 ) {
return 0
}
if ( inv(26, prm_1471) < calcexpalive(inv(25, prm_1471)) ) {
inv(26, prm_1471) += prm_1472
}
if ( inv(26, prm_1471) >= calcexpalive(inv(25, prm_1471)) ) {
inv(25, prm_1471)++
inv(26, prm_1471) = 0
inv(27, prm_1471) = 0
txtef 2
snd 61
txt_select -1, lang("あなたは鍛冶の技術の向上を感じた。", "your smithery skill increases."), "", "", "", "", "", "", "", ""
}
// CS追加 SESTを参考にレベルと経験値を表示
txt_select -1, " (Lv:" + inv(25, prm_1471) + " Exp:" + fixtxt("" + double(inv(26, prm_1471) * 100) / double(calcexpalive(inv(25, prm_1471))), 6) + "%) ", "", "", "", "", "", "", "", ""
return 1
⑩関数smithcheckの移植
長いですね……ですがもう一息なので頑張りましょう!アイテムが鍛冶に使えるか否かをチェックする処理smithcheckを移植します。3箇所あるlabel_3055をlabel_smith_3055に書き換えましょう。*label_smith_3055の移植も忘れないでください。
(とは言えこれsmithcheckの中で直接returnすれば済む話な気もしますが)
/* アイテムが鍛冶に使えるか否かのチェック処理 */
#defcfunc smithcheck int prm_1473, int prm_1474
if ( inv(21, prm_1473) == 1 | inv(21, prm_1473) == 5 ) {
return 1
}
found@m18 = 0
repeat step
if ( craftref(cnt * 2) == prm_1473 ) {
found@m18 = 1
break
}
loop
if ( found@m18 ) {
return 1
}
notsmith@m18 = 1
_switch_val@m18 = prm_1474
if ( 0 ) {
_switch_sw@m18++
}
if ( _switch_val@m18 == 0 | _switch_sw@m18 ) {
_switch_sw@m18 = 0
reftype@m18 = refitem(inv(3, prm_1473), 5, prm_1473)
if ( inv(3, prm_1473) == 50 ) {
// 折れた刃(ID:50)
notsmith@m18 = 0
}
else : if ( reftype@m18 >= 10000 & reftype@m18 <= 50000 ) {
// 装備系(10000~50000)
notsmith@m18 = 0
}
else : if ( inv(3, prm_1473) == 337 ) {
// 皮(ID:337)
notsmith@m18 = 0
}
else : if ( equalsitem(prm_1473, "artifacts fusion license") ) {
// AF合成許可証
notsmith@m18 = 0
}
goto *label_smith_3055
_switch_sw@m18++
}
if ( _switch_val@m18 == 1 | _switch_sw@m18 ) {
_switch_sw@m18 = 0
reftypeminor@m18 = refitem(inv(3, prm_1473), 9, prm_1473)
if ( reftypeminor@m18 == 77001 ) {
// 鉱石系(77001)
notsmith@m18 = 0
}
else : if ( inv(3, prm_1473) == 716 ) {
// バニラロック(ID:716)
notsmith@m18 = 0
}
else : if ( inv(3, prm_1473) == 337 ) {
// 皮(ID:337) ドラゴン類に限る
s@m18 = refchara(inv(23, prm_1473), 8, 1)
if ( instr(s@m18, 0, "/dragon/") != (-1) ) {
notsmith@m18 = 0
}
}
goto *label_smith_3055
_switch_sw@m18++
}
if ( _switch_val@m18 == 2 | _switch_sw@m18 ) {
_switch_sw@m18 = 0
reftype@m18 = refitem(inv(3, prm_1473), 5, prm_1473)
if ( reftype@m18 >= 10000 & reftype@m18 <= 50000 ) {
if ( inv(4, prm_1473) == 4 | inv(4, prm_1473) == 5 ) {
if ( ibit(10, prm_1473) == 0 & ibit(18, prm_1473) == 0 ) {
notsmith@m18 = 0
}
}
}
goto *label_smith_3055
}
*label_smith_3055
return notsmith@m18
⑪関数reinforcecheckの移植
最後です。会心の出来や自信作の場合の処理reinforcecheckを移植しましょう。ここは変更は不要です。
/* 鍛冶 会心の出来・自信作の場合の処理 */
#defcfunc reinforcecheck int prm_1485, int prm_1486
if ( inv(40 + prm_1485 * 2, prm_1486) == 0 ) {
return -1
}
encp@m22 = inv(41 + prm_1485 * 2, prm_1486)
repeat 8
mtenc_id@m22 = mtenc(cnt * 2, inv(24, prm_1486))
if ( mtenc_id@m22 == 0 ) {
break
}
if ( inv(40 + prm_1485 * 2, prm_1486) == mtenc_id@m22 ) {
encp@m22 -= mtenc(1 + cnt * 2, inv(24, prm_1486))
break
}
loop
if ( encp@m22 <= 0 ) {
return 0
}
return encp@m22
⑫コンパイル&次回予告
お疲れ様でした。移植が完了したらstart.hspをHSPエディタで開き、コンパイルを実行してください。正常に実行ファイルが生成されたら成功です。
次回は今回移植した関数を実際に呼び出してみましょう。
この記事が気に入ったらサポートをしてみませんか?