最近、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_
もうちょいマシなのを作ったのでよければこちらで。