時間を売買するシステム

最近、MUTOYSさんがフリーで公開されているSOLDOUTを、身内の間で運営しています。5人程度の小規模運営ですが、時間を取引できるように改造してくれといわれたので、良さそうなアイテムを作ってみました(かなり時代の流れに乗り遅れている気がしますが)。

どうでもいいこと

perに触るのは実はほぼ初めてで、perlの文法は正直嫌っています。その上、SOLDOUTのシステムをよく理解していなかったので、かなり苦戦を強いられました。一箇所どうしてもうまくいかない箇所がありましたが、風呂に入っているときに突然アイデアが浮かんできました。

言い訳

十分にテストを重ね、安全性を確かめてはいますが、スクリプトを導入する際は、念のため一度ローカル環境や別街でテストをしてからにしてください。

作成するアイテムの仕様

タイムマシンを使うと、自分の時間を1時間単位でカプセル化することができます。逆に、カプセル状になったものを時間として取り出すことができます。このとき、カプセル化された状態の時間を「タイムカプセル」と呼びます。

時間の取引を行う場合、相互にタイムマシンを所有していることを前提としてタイムカプセルを売買することで見かけ上、時間を取引しているように見えます。御託はそれまでとして、実際に運用してみればすぐ感覚がつかめるはずです。

ソースコード

これらは、soldout/custom/inc-item-data.cgiを改造してください。ファイルが存在しない場合は、soldout/inc/inc-item-data.cgiからコピーしてきて、そのファイルを書き換えてください。SOLDOUTのコアファイルは、custom/にファイルが存在するか先に調べ、存在しない場合はinc/へ読みに行くようです。オリジナルファイルをinc/以下に残しておくことを、お勧めします。

追加すべき分類

後述する、「時間を操作するアイテム」で新しい分類を用いない場合は、記述する必要はありません。ハイライト部を追記してください。

	type13	技術		#type13分類の定義
	type14	水晶		#type14分類の定義
	type15	食材		#type15分類の定義
	type16	飲料		#type16分類の定義
						#↑の様に拡張可
	type17	時間
	
	job	drug		薬屋	#★職業定義(職業コード{スペース}職業名) 職業コードは英小文字10文字以内
	job	tool		道具屋	#以下繰り返し(拡張可)
	job	weapon		武器屋

追加すべきアイテム

メイン部の処理です。前記した通り、専用分類「時間」を用いたい場合は、上記のソースを追加する必要があります。noは適宜、空いている番号を入力してください。番号を変更した場合、複数の該当箇所を書き換えなければならないので、注意してください(該当箇所はハイライトしてあります)。

@@ITEM
	no		241				# *ここを変更した場合
	type	時間
	code	time-capsule
	name	タイムカプセル
	info	時は金なり
	price	10000			# 定価は要バランス調整です(時間の売買には慎重を期してください)
	limit	1000
	pop		0				# NPCに買い取られない設定にしてます
	plus	0				# 市場に出回らないようにしています(調整しないとバランスが壊れます)
	scale	時間
	cost	0

@@ITEM
	no	242
	type	時間
	name	時間操作マシン
	code	time-machine
	info	時間を操作します
	price	0
	limit	1					# このアイテムは使っても消費しない仕組みなので1つで十分です
	pop		0
	plus	1d					# 1dayに一定確率で市場に出回ります
	scale	台
	cost	0
	flag	notrash|noshowcase|nosend	# 破棄・販売・送付ができません
	@@USE
		name	時間をカプセルに詰める
		info	所有時間をカプセルに1時間単位で詰め込みます
		time	0
		scale	時間
		action	詰める
		use	1	time-machine	0%	# 使っても消費されません(0%の確率で消費)
		
		func _local_	# 独自関数です
			my $count = $USE->{arg}->{count};
			my $usetime = 3600 * $count;	# 3600 = 60s * 60m = 1h
			my $retmsg = $count . "時間をカプセルに詰めることに成功しました。";
			if(time() - $DT->{time} < $usetime){
				return "詰める時間が足りません。";
			}
			item::AddItem(241, $count);	# *ここを変更してください
			$DT->{time} += $usetime;
			WriteLog(0, $DT->{id}, $retmsg);
			return $retmsg;
		_local_
	@@USE
		name	時間をカプセルから取り出す
		info	所有時間をカプセルから1時間単位で取り出します
		time	0
		scale	時間
		action	取り出す
		use	1	time-machine	0%
		
		func _local_
			my $count = $USE->{arg}->{count};;
			my $usetime = 3600 * $count;
			my $retmsg = "カプセルから" . $count . "時間を取り出すことに成功しました。";
			if($DT->{item}[241 - 1] < $count){	# *ここを変更してください
				return "タイムカプセルが足りません。";
			}
			item::UseItem(241, $count);			# *ここを変更してください
			$DT->{time} -= $usetime;
			WriteLog(0, $DT->{id}, $retmsg);
			return $retmsg;
		_local_

独自関数の解説

func _local_	# 独自関数です
	my $count = $USE->{arg}->{count};
	my $usetime = 3600 * $count;	# 3600 = 60s * 60m = 1h
	my $retmsg = $count . "時間をカプセルに詰めることに成功しました。";
	if(time() - $DT->{time} < $usetime){
		return "詰める時間が足りません。";
	}
	item::AddItem(241, $count);	# *ここを変更してください
	$DT->{time} += $usetime;
	WriteLog(0, $DT->{id}, $retmsg);
	return $retmsg;
	local_

36行目で、$USE->{arg}->{count};ではなく、$USE->{use}[0]->{count};を使ってはいけません。これで私は、少し詰まりました。$USE->{arg}->{count};は使用回数(未補正)とマニュアルにも書いてあるかと思います。$USE->{use}[0]->{count};は、使用しようとした結果、実際に持っている個数などの条件が考慮された上で、実際に使用される個数を取得します。今回の仕様上、タイムマシンは常に個数1なため、前者を使用すると常に1が取得されてしまいます。

39行目で、time() – $DT->{time}は、そのプレイヤーが行動可能な時間を取得できます。詳しい説明は少し面倒なので省きますが、これで取得できるものと覚えてしまったほうが良いでしょう。

43行目で、$DT->{time} += $usetimeは、プレイヤーの行動可能時間の増減を行うことができます。「なぜ+しているのに時間を減らすことになるのか?」という疑問は、上述した通り「できるもの」と考えてください。逆に、マイナスすると時間が増やせそうですね? その予想は当たっており、63行で似たような処理を行っています。

44行目でのWriteLog(0, $DT->{id}, $retmsg);は、自分のみに見えるログへ行動を出力しています。

まとめ

まだまだ改良の余地はありそうです。コアプログラムを書き換えるのは面倒そうなのでやらないですが、アイテムに独自関数を組み込むことで、かなりトリッキーな処理が行えると思います。独自アイテムを、開発していきたいかなと思っています。

もしよろしければ……

各アイテムのアイコンを描いてみたので、もしよろしければ使ってやって下さい。soldout/image/以下にファイルのみアップロードしてください。

タイムマシン・タイムカプセルの画像

追記(2010/08/07)

@@ITEM
	no	241
	type	システム
	code	time-capsule
	name	タイムカプセル
	info	時は金なり
	price	17500
	cost	0
	limit	250/100
	pop		0
	base	80/1000
	scale	時間
	plus	12h
@@ITEM
	no	242
	type	システム
	code	time-machine
	name	タイムマシン
	info	時間を操作します
	price	0
	cost	0
	limit	1
	pop	0
	scale	台
	plus	1h
	flag	noshowcase|nosend|notrash
	@@USE
		name	時間をカプセルに詰める
		time	1h
		scale	時間
		action	詰める
		info	所有時間をカプセルに1時間単位で詰め込みます
		okmsg	時間をカプセルに詰めることに成功しました
			get	1	タイムカプセル
	@@USE
		name	時間をカプセルから取り出す
		info	所有時間をカプセルから1時間単位で取り出します
		time	0
		scale	時間
		action	取り出す
		use	1	time-machine	0%

		func _local_
			my $count = $USE->{arg}->{count};;
			my $usetime = 3600 * $count;
			my $retmsg = "カプセルから" . $count . "時間を取り出すことに成功しました。";
			if($DT->{item}[@@ITEMNO"タイムカプセル" - 1] < $count){
				return "タイムカプセルが足りません。";
			}
			item::UseItem(@@ITEMNO"タイムカプセル", $count);
			$DT->{time} -= $usetime;
			return $retmsg;
		_local_

もうちょいマシなのを作ったのでよければこちらで。

コメントを残す

メールアドレスが公開されることはありません。