Elona改造講座 第20回(通信教育)

Elona改造講座、第20回です。
今回はoo系列の「通信教育」をMMAhに移植してみましょう。
これは店番ペットが1日の終わりに手持ちのアイテムを売却し、訓練を行うというものです。いちいち店番解除→街に連れ出す→訓練するまで待機→店番再任命などとする必要がなくなって手軽ですね。


①oo系列のアイテム売却&訓練処理

まずはoo系列のソースを"人の来客があり、"で検索してみましょう。店の1日の終わりの処理が見つかるはずです。その末尾にccに店番ペットのIDを代入したうえで*label_2851と*label_2852を呼び出している箇所が見つかるはずです(当然ながらoo系列でもヴァリアントによってラベル番号は異なります)

mode = 0
file = "shop" + 5 + ".s2"
fmode = 4
gosub *label_2082
file = "shoptmp.s2"
fmode = 3
gosub *label_2082
// oo追加 店番の手持ちアイテム売却と通信教育の処理
ccbk = cc
cc = worker
gosub *label_2851
gosub *label_2852
cc = ccbk
// oo追加 ここまで
return
店の1日の終わりの処理です

*label_2851と*label_2852の中身も見てみましょう。前者はNPCの手持ちアイテム売却処理で、後者は訓練の処理みたいですね。NPCの所在地によってメッセージを訓練所か通信教育か変更する処理があるのも分かります。

*label_2851
	inv_getheader cc
	sell = 0, 0
	repeat invrange, invhead
		if ( inv(0, cnt) == 0 ) {
			continue
		}
		a = refitem(inv(3, cnt), 5, cnt)
		if ( a == 77000 ) {
			p = inv(1, cnt) * inv(0, cnt)
			sell += inv(0, cnt)
			sell(1) += p
			inv(0, cnt) = 0
			cdata(30, cc) += p
		}
	loop
	if ( sell != 0 ) {
		txtef 9
		txtvalid = 0
		txt_select lang(cdatan(0, cc) + "は" + sell + "個のアイテムを売りさばき" + sell(1) + "goldを稼いだ。", cdatan(0, cc) + " sells " + sell + " items and earns " + sell(1) + " gold pieces."), "", "", "", "", "", "", "", ""
		skillexp2 156, cc, limit(int(sqrt(sell(1))), 10, 100)
	}
	return

*label_2852
	if ( sorg(156, cc) == 0 ) {
		correctionvalue = 0
	}
	else {
		correctionvalue = 50 + sdata(156, cc)
		if ( correctionvalue > 300 ) {
			correctionvalue = 300
		}
	}
	if ( cdata(30, cc) >= cdata(38, cc) * 500 * 100 / (100 + correctionvalue) ) {
		snd 61
		txtef 9
		txtvalid = 0
		s = cdatan(0, cc) + "は"
		if ( mdata(6) == 3 & cdata(80, cc) == 0 | adata(0, cdata(80, cc)) == 3 ) {
			s += "訓練所に通い"
		}
		else {
			s += "通信教育で"
		}
		txt_select lang(s + "潜在能力を伸ばした!", cdatan(0, cc) + " visits a trainer and develops " + his(cc) + " potential!"), "", "", "", "", "", "", "", ""
		olistmax = 0
		inv_getheader cc
		repeat invrange, invhead
			if ( inv(0, cnt) == 0 ) {
				continue
			}
			if ( inv(3, cnt) == 563 ) {
				olist(olistmax) = inv(25, cnt)
				olistmax++
			}
		loop
売却&訓練処理です

②MMAhのアイテム売却&訓練処理

MMAhのこれに対応する処理を見てみましょう。*label_1148がその処理ですがここで1つ問題が……
ooだと無かった「1/100の確率で実施する」という条件がMMAh側には含まれています。
(実際のところはooに「1/100の確率で実施する」という条件が無いわけではありません。単にサブルーチンの呼び出し元の側で行っているというだけのことです)
 
この為、単にこのサブルーチンを店の処理から呼び出したところで、100日に約1日のペースでしか通信教育が行われません。これなら連れ出した方がてっとり早そうですね。

if ( rnd(100) == 0 ) {
	inv_getheader cc
	sell = 0, 0
	repeat invrange, invhead
		if ( inv(0, cnt) == 0 ) {
			continue
		}
		a = refitem(inv(3, cnt), 5, cnt)
		if ( a == 62000 | a == 77000 | inv(3, cnt) == 54 ) {
			if ( inv(3, cnt) != 504 & inv(3, cnt) != 503 ) {
				p = inv(1, cnt) * inv(0, cnt)
				sell += inv(0, cnt)
				sell(1) += p
				inv(0, cnt) = 0
				modgold cc, p, 1
			}
		}
	loop
	if ( sell != 0 ) {
		txtef 9
		txt_select -1, lang(name(cc) + "は" + sell + "個のアイテムを売りさばき" + sell(1) + "goldを稼いだ。", name(cc) + " sells " + sell + " items and earns " + sell(1) + " gold pieces."), "", "", "", "", "", "", "", ""
		skillexp 156, cc, limit(int(sqrt(sell(1))), 10, 100) * expadjust(cc)
	}
}
if ( rnd(100) == 0 ) {
	if ( sorg(156, cc) == 0 ) {
		correctionvalue = 0
	}
	else {
		correctionvalue = 50 + sdata(156, cc)
		if ( correctionvalue > 300 ) {
			correctionvalue = 300
		}
	}
	if ( cdata(30, cc) >= cdata(38, cc) * 50000 / (100 + correctionvalue) ) {
		snd 61
		txtef 9
		txt_select -1, lang(cdatan(0, cc) + "は訓練所に通い潜在能力を伸ばした!", cdatan(0, cc) + " visits a trainer and develops " + his(cc) + " potential!"), "", "", "", "", "", "", "", ""
		training cc, 4, 200, cdata(38, cc) * 12500 / (100 + correctionvalue)
		if ( trainingvalue > 0 ) {
			put_mongold cc, -trainingvalue
		}
		if ( p == 0 ) {
			txtef 9
			txt_select -1, lang(cdatan(0, cc) + "にはこれ以上伸ばせる潜在能力はないようだ", cdatan(0, cc) + " can't develop " + his(cc) + " potential anymore."), "", "", "", "", "", "", "", ""
		}
		r1 = cc
		gosub *label_0515
	}
	else {
		if ( rnd(5) == 0 ) {
			txtef 9
			ctalk cc, 418, cc, cc
		}
	}
}
MMAhの売却&訓練処理です
1/100で実施するという条件があることに注目

③MMAhに通信教育処理を追加

ではどうすれば良いか? 答えは明確ですね。通常の売却&訓練処理を模擬して、通信教育専用の関数を作ってしまいましょう。
新規ファイル「cs_online_training.hsp」を作成して、ここに次の関数online_trainingを作成してください。
※gosub *label_0515はお使いのヴァリアントに合わせてジャンプ先を変更してください。

#deffunc online_training
	// ccに現在の店番workerを代入
	cs_ccbk = cc
	cc = worker

	// アイテムの売却
	inv_getheader cc
	sell = 0, 0
	repeat invrange, invhead
		if ( inv(0, cnt) == 0 ) {
			continue
		}
		a = refitem(inv(3, cnt), 5, cnt)
		if ( a == 62000 | a == 77000 | inv(3, cnt) == 54 ) {
			if ( inv(3, cnt) != 504 & inv(3, cnt) != 503 ) {
				p = inv(1, cnt) * inv(0, cnt)
				sell += inv(0, cnt)
				sell(1) += p
				inv(0, cnt) = 0
				modgold cc, p, 1
			}
		}
	loop
	if ( sell != 0 ) {
		txtef 9
		txt_select -1, lang(cdatan(0, cc) + "は" + sell + "個のアイテムを売りさばき" + sell(1) + "goldを稼いだ。", cdatan(0, cc) + " sells " + sell + " items and earns " + sell(1) + " gold pieces."), "", "", "", "", "", "", "", ""
		skillexp 156, cc, limit(int(sqrt(sell(1))), 10, 100) * expadjust(cc)
	}
	
	// 訓練
	if ( sorg(156, cc) == 0 ) {
		correctionvalue = 0
	}
	else {
		correctionvalue = 50 + sdata(156, cc)
		if ( correctionvalue > 300 ) {
			correctionvalue = 300
		}
	}
	if ( cdata(30, cc) >= cdata(38, cc) * 50000 / (100 + correctionvalue) ) {
		snd 61
		txtef 9
		txt_select -1, lang(cdatan(0, cc) + "は通信教育で潜在能力を伸ばした!", cdatan(0, cc) + " takes lessons online and develops " + his(cc) + " potential!"), "", "", "", "", "", "", "", ""
		training cc, 4, 200, cdata(38, cc) * 12500 / (100 + correctionvalue)
		if ( trainingvalue > 0 ) {
			put_mongold cc, -trainingvalue
		}
		if ( p == 0 ) {
			txtef 9
			txt_select -1, lang(cdatan(0, cc) + "にはこれ以上伸ばせる潜在能力はないようだ", cdatan(0, cc) + " can't develop " + his(cc) + " potential anymore."), "", "", "", "", "", "", "", ""
		}
		r1 = cc
		gosub *label_0515
	}
	else {
		if ( rnd(5) == 0 ) {
			txtef 9
			ctalk cc, 418, cc, cc
		}
	}
	
	// 元のccを復元
	cc = cs_ccbk
	
	return

単にMMAhのアイテム売却&訓練処理の「1/100の確率で実施する」部分の中身をほぼそのまま書き写しただけです。通信教育専用なのでメッセージも"は通信教育で潜在能力を伸ばした!"に固定しています。また、oo系列では「ccに店番のIDを代入し、終わったらccを元に戻す」という処理は呼び出し元の側で行っていましたが、ここでは関数内の最初と最後で実施しています。

④通信教育処理の呼び出し

前章で追加した通信教育処理をstart.hsp側から呼び出します。ソース内を"また、宿泊客は一人もいなかった。"で検索してヒットしたところの約50行下です。

funcaddshoplog "[" + mdatan(0) + "]", "@BO"
var_string1 = ""
if ( sold > (110 - gdata(125) / 100) / 10 ) {
	modrank 5, 30, 2
}
mode = 0
file = "shop" + 5 + ".s2"
fmode = 4
gosub *label_0973
file = "shoptmp.s2"
fmode = 3
gosub *label_0973
file = exedir + "save\\" + playerid + "\\shopdatatmp.bin"
result = funcloadshopdata(file)
// CS追加(v1.2) 店番の手持ちアイテム売却と通信教育の処理
online_training
// CS追加 ここまで
店の処理から関数online_trainingを呼び出します

もちろん新規追加ファイル「cs_online_training.hsp」のインクルードも忘れてはいけません。店の処理と関数funcaddshoplogの間に追加しておきましょう。

// CS追加(v1.2) 通信教育用の処理のインクルード
#include "cs_online_training.hsp"
通信教育処理を記述したファイルをインクルードしておきます

⑤動作確認

通信教育の動作確認です。店番に売却可能なアイテム(鉱石類やNPCの残骸)を預けておきましょう。ここではダイヤ原石(価値4200)を10個預けてみました。

店番に売却用アイテム(鉱石類やNPCの残骸)を預けておきます

この状態で日付が変わるのを待ってみましょう。店番がアイテムの売却と訓練を行ってくれたら成功です。ダイヤ原石を10個売却し、計42000goldの訓練費用を獲得しました。そのまま訓練も行ってくれているようですね。

通信教育に成功しました!

⑥余談

NPCが売却可能なアイテムは主に鉱石と残骸ですが、それ以外に一部のカスタムアイテムも売却するようです。例えば色々追加パック付属の「グリフォンの羽根」などは1個50000goldで売却してくれました。
(内部的には鉱石の一種として扱われている?)
ただしこれは貴重品フラグ(★)の付いたアイテムの為、PCは売却できません。NPCに渡して訓練費用を稼がせる為の専用アイテムみたいですね。

グリフォンの羽根はNPC専用の売却アイテムです

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