見出し画像

Elona改造講座 第10回(MMAhにすくつ捕獲玉を実装する)

Elona改造講座、第10回です。
今回はoo系列の「すくつ捕獲玉」をMMAhに移植してみましょう。
まずはすくつ捕獲玉の仕様を、通常のモンスターボール(以下、MB)と比較する形で書き出してみます。
・すくつのボス撃破時に入手できる特殊なMB
・通常のMBと違って★フラグ(貴重品フラグ)が立っている
・すくつのNPCを捕獲できる一方、すくつ以外のNPCは捕獲不能
・入手階層以下の階層で使用可能(100層で入手したすくつ捕獲玉の場合、1~100層のNPCを捕獲可能)
・通常のMBとは違って対象NPCのレベルは参照しない
 
書き出してみると結構違いが多いですね。ですが実はこのすくつ捕獲玉、「すくつ捕獲玉」という固有の名前のアイテムが新規追加されたわけではなく、内部的には単なる「貴重品フラグが立っているだけの緑色のMB」だったりします。バニラや他のヴァリアントに引っ越した場合でも不具合が発生しないよう、このような仕組みになってるみたいですね。


①★フラグ付きMBの表示名をすくつ捕獲玉にする処理

既に述べた通り、すくつ捕獲玉とは「★フラグ付きのMB」です。まずは★フラグが立っているMBの表示名を変更する処理を移植しましょう。この処理を行っているのは関数ioriginalnamecnvとiknownnamecnvです。2箇所あるのは本来の名前と未鑑定状態での名前の分です。
 
まずは関数ioriginalnamecnvから。引数prm_1326が対象となるアイテムです。
「inv(3, prm_1326) == 685」は「このアイテムがMB(ID:685)である場合」を意味します。
その後ろの「ibit(5, prm_1326)」は「このアイテムが★フラグ付きの場合」を意味します。
まとめるとこのif文は「★フラグ付きのMBは名前を『すくつ捕獲玉(英名:void ball)』にする」という処理になります。

#defcfunc ioriginalnamecnv int prm_1326
	if ( en ) {
		if ( inv(3, prm_1326) == 743 ) {
			return cnves(useritemdatan(1, inv(31, prm_1326)), num2@m63)
		}
		if ( ioriginalnameref2(inv(3, prm_1326)) == "" ) {
			return cnves(ioriginalnameref(inv(3, prm_1326)), num2@m63)
		}
		return ioriginalnameref(inv(3, prm_1326))
	}
	if ( inv(3, prm_1326) == 743 ) {
		return useritemdatan(1, inv(31, prm_1326))
	}
	// ★フラグ付きのモンスターボールの場合、名前をすくつ捕獲玉にする
	if ( inv(3, prm_1326) == 685 & ibit(5, prm_1326) ) {
		if ( jp ) {
			return "すくつ捕獲玉"
		}
		else {
			return "void ball"
		}
	}
	return ioriginalnameref(inv(3, prm_1326))

次に関数iknownnamecnvにも同じ処理を追加します。逆コンパイルの都合か、引数名(prm_1327)が先程と異なることに注意しましょう。

#defcfunc iknownnamecnv int prm_1327
	if ( en ) {
		if ( inv(3, prm_1327) == 743 ) {
			return cnves(useritemdatan(4, inv(31, prm_1327)), num2@m63)
		}
		return cnves(iknownnameref(inv(3, prm_1327)), num2@m63)
	}
	if ( inv(3, prm_1327) == 743 ) {
		return useritemdatan(4, inv(31, prm_1327))
	}
	// ★フラグ付きのモンスターボールの場合、名前をすくつ捕獲玉にする
	if ( inv(3, prm_1327) == 685 & ibit(5, prm_1327) ) {
		if ( jp ) {
			return "すくつ捕獲玉"
		}
		else {
			return "void ball"
		}
	}
	return iknownnameref(inv(3, prm_1327))

次の画像のようになれば成功です。

★フラグ付きのMBの表示名をすくつ捕獲玉にする処理です

②ドロップ処理の追加

すくつボスを倒した時にすくつ捕獲玉をドロップする処理を追加します。
「この階の封印が解けたようだ」で検索して、「クエストを達成した」の2行上に以下の処理を追加してください。

// 現在マップがすくつ(ID:42)の場合、すくつ捕獲玉をドロップ
// MB(ID:685)を生成し、★フラグ,色,MBレベル,価値の順に設定
if ( gdata(20) == 42 ) {
	flt
	itemcreate -1, 685, cdata(1, 0), cdata(2, 0), 0
	ibitmod 5, ci, 1
	inv(22, ci) = 2
	inv(26, ci) = gdata(22) - 49
	inv(1, ci) = 2000 + powf(inv(26, ci) + 50, 2) + (inv(26, ci) + 50) * 100
}

処理内容を説明します。
まずitemcreate関数でMB(ID:685)を生成します。
「ibitmod 5, ci, 1」は★フラグを立てる処理で、すくつ捕獲玉をすくつ捕獲玉たらしめる最重要項目です。これが無いと単なるMBになってしまいます。
「inv(22, ci) = 2」は色の設定です。すくつ捕獲玉の場合は緑色になります。
「inv(26, ci) = gdata(22) - 49」はMBレベルを入手した階層に応じて設定する処理です。MBレベルは通常のMBの場合は捕獲できるNPCのレベルに関係しますが、すくつ捕獲玉の場合は捕獲できる階層に関係してきます。
「inv(1, ci) 」の行はアイテムの価値を設定しています。
 
次の画像のようになれば成功です。

すくつボス撃破時にドロップされます

③動作確認(すくつ捕獲玉のドロップ)

ここまでの動作確認です。
実際にすくつに潜って5の倍数階のボスを倒してみましょう。
 ・すくつ捕獲玉(外見は緑色のMB)をドロップしたか?
 ・鑑定すると「★すくつ捕獲玉 Lv○○ (空)」と表示されたか?
を確認してください。
 
正常にドロップできたら成功です。この画像の例では70層のボスを撃破した為、生成されるすくつ捕獲玉もLv70になっています。

70層のボスからLv70のすくつ捕獲玉がドロップしました
(左:ドロップ時 右:鑑定後)

④捕獲判定処理の実装

いよいよ捕獲処理の実装に入ります。
ここを読み進める前に、まず以下の3点を把握しておいてください。
 ・gdata(20)はPCが現在いるマップ
 ・gdata(22)はPCが現在いる階層
 ・すくつのマップIDは42
 
「捕獲するためにはもっと弱らせる必要がある」で検索して、捕獲判定処理を行っている箇所を見付けてください。MMAhの場合ウィザードモードでは無条件に捕獲に成功する仕様の為、if ( gdata(828) == 0 ) { … }で括られているので分かりやすいかと思います。
ここを次のように変更してください。変更があるのはコメント文の直後のifの条件だけです(全3箇所)。

if ( gdata(828) == 0 ) {
	// 「現在マップがすくつ(ID:42)の場合」を条件から外す
	if ( gdata(20) == 6 | gdata(20) == 35 | gdata(20) == 40 | gdata(70) == 2401 | gdata(70) == 2402 | gdata(70) == 2403 | (gdata(20) == 27 & gdata(22) > 5) ) {
		txt_select -1, lang("この場所では効果がない。", "This doesn't work in this area."), "", "", "", "", "", "", "", ""
		break
	}
	// 「通常MBかつ現在マップがすくつの場合」または「すくつ捕獲玉かつ現在マップがすくつ以外の場合」は無効
	if ( (ibit(5, ci) == 0 & gdata(20) == 42) | (ibit(5, ci) & gdata(20) != 42) ) {
		txt_select -1, lang("この場所では効果がない。", "This doesn't work in this area."), "", "", "", "", "", "", "", ""
		break
	}
	if ( tc < 57 | cdata(150, tc) != 0 | cdata(25, tc) == 6 | cbit(976, tc) == 1 ) {
		txt_select -1, lang("その生物には無効だ。", "The creature can't be captured."), "", "", "", "", "", "", "", ""
		break
	}
	// 捕獲判定 通常MBの場合は対象キャラのレベルで、すくつ捕獲玉の場合は現在の階層で判定
	if ( ibit(5, ci) == 0 & cdata(38, tc) > inv(26, ci) | (ibit(5, ci) & gdata(22) >= inv(26, ci) + 50) ) {
		txt_select -1, lang("その生物を捕獲するには、より高レベルのモンスターボールが必要だ。", "Power level of the ball is not enough to capture the creature."), "", "", "", "", "", "", "", ""
		break
	}
	if ( cdata(50, tc) > cdata(51, tc) / 10 ) {
		txt_select -1, lang("捕獲するためにはもっと弱らせる必要がある。", "You need to weaken the creature to capture it."), "", "", "", "", "", "", "", ""
		break
	}
}

1つずつ解説していきます。
 
1つ目。ここはMB使用不可のマップの場合に捕獲失敗させる為の処理です。
元々ここの条件には「gdata(20) == 42」(すくつの場合)が含まれていましたが、この判定は2つ目で行うので外しました。
なお、マップID:6は闘技場、27は子犬の洞窟、35はハウスドーム、40はコロシアムです。

if ( gdata(20) == 6 | gdata(20) == 35 | gdata(20) == 40 | gdata(70) == 2401 | gdata(70) == 2402 | gdata(70) == 2403 | (gdata(20) == 27 & gdata(22) > 5) ) {
	txt_select -1, lang("この場所では効果がない。", "This doesn't work in this area."), "", "", "", "", "", "", "", ""
	break
}

2つ目。ここは通常MBをすくつで使用した場合や、すくつ捕獲玉をすくつ外で使用した場合に捕獲失敗させる為の処理です。
「ibit(5, ci) == 0 & gdata(20) == 42」は★フラグなし(=通常MB)をすくつで使用した場合です。
「ibit(5, ci) & gdata(20) != 42」はその逆で、★フラグあり(=すくつ捕獲玉)をすくつ以外で使用した場合です。

if ( (ibit(5, ci) == 0 & gdata(20) == 42) | (ibit(5, ci) & gdata(20) != 42) ) {
	txt_select -1, lang("この場所では効果がない。", "This doesn't work in this area."), "", "", "", "", "", "", "", ""
	break
}

3つ目。ここはペットや冒険者、品質6(特別)のキャラを捕獲させない為の処理です。ここには変更はありません。

if ( tc < 57 | cdata(150, tc) != 0 | cdata(25, tc) == 6 | cbit(976, tc) == 1 ) {
	txt_select -1, lang("その生物には無効だ。", "The creature can't be captured."), "", "", "", "", "", "", "", ""
	break
}

4つ目。ここはMBレベルによる成否判定です。
通常MBの場合の判定条件は「cdata(38, tc) > inv(26, ci)」となっています。
cdata(38, tc)は対象NPCのレベル、inv(26, ci)はMBレベルなので「MBレベルより高レベルのNPCは捕獲不可」という意味になります。
 
すくつ捕獲玉の場合の判定条件は「gdata(22) >= inv(26, ci) + 50」となっています。
gdata(22)は現在の階層、inv(26, ci)はMBのレベルなので「MBレベルより高い階層のNPCは捕獲不可」という意味になります。
(+50はすくつ入口のレベルが50階相当だから、のはず……)

if ( ibit(5, ci) == 0 & cdata(38, tc) > inv(26, ci) | (ibit(5, ci) & gdata(22) >= inv(26, ci) + 50) ) {
	txt_select -1, lang("その生物を捕獲するには、より高レベルのモンスターボールが必要だ。", "Power level of the ball is not enough to capture the creature."), "", "", "", "", "", "", "", ""
	break
}

5つ目。ここは対象NPCの現在HPが最大HPの1/10より多い場合に捕獲を失敗させる為の処理です。ここも変更はありません。

if ( cdata(50, tc) > cdata(51, tc) / 10 ) {
	txt_select -1, lang("捕獲するためにはもっと弱らせる必要がある。", "You need to weaken the creature to capture it."), "", "", "", "", "", "", "", ""
	break
}

画像のようになれば成功です。この例では動作確認の都合上、ウィザードモードでも通常モードと同じ判定処理を行うようにしています。

本家ooでは1,2番目は1個のifで処理しています

⑤動作確認(捕獲処理)

実際にすくつのNPCを捕獲してみましょう。画像のすくつ捕獲玉は70層で入手したものの為、70層以下で使用可能です。今回は試しに69層でポーンLv124を捕獲してみました。

ゲットだぜ!
Lv124でした

捕獲失敗例も試しておきましょう。
 
すくつ捕獲玉をすくつ外で使用した場合、「この場所では効果がない」
(画像の例は屋外フィールド)

すくつ外ではLv70以下のNPCも捕獲できません

すくつ内であっても対象がユニーク(品質6)の場合、「その生物には無効だ」
(画像の例はすくつ1層でUSCに対して使用)

すくつ内であってもユニークは捕獲できません

すくつ捕獲玉のレベルよりも深い階層の場合、「より高レベルのモンスターボールが必要だ」
(画像の例はすくつ71層)

Lv70のすくつ捕獲玉は71層以降では使えません

以上が確認できたら成功です。
お疲れ様でした。

⑥移植していない要素

上記の画像では未使用のすくつ捕獲玉は「★すくつ捕獲玉 Lv70 (空)」と表示されていますが、本家ooでは「★すくつ捕獲玉 70階相当 (空)」と表示されるようです。「(空)」で検索するとMBレベルの表示名をしている箇所が見つかるので、暇な方はその辺の処理も移植してみてください。

⑦余談

すくつ捕獲玉は願えません。
★だからとかそういう問題ではなく、そもそも「すくつ捕獲玉」という名前のアイテムが存在しない為です(実態は「★フラグが付いたMB」の為)。試しにウィザードモードで願ってみましたが、すくつ探索許可証が降ってくるだけでした。
これ、デバッグ時に地味に面倒なんですよね……
ウィザードモード限定で願う対象に追加してみるのも良いかもしれません。
前回までで扱った願いの追加と、今回のすくつ捕獲玉生成処理とを組み合わせれば簡単に実装できるはずです。
 
ちなみにすくつ捕獲玉をバニラ・omake・無改造MMAhに持ち込むと「★モンスターボール Lv70 (空)」という名前の緑色のMBとして見えました。
(2024/1/16追記)
この件の検証については次の第11回をご覧ください。


この記事が気に入ったらサポートをしてみませんか?