#伺か YAYAでのゴースト開発メモ:ランダムトークを重複させない

ゴーストのランダムトークが重複しないようにするには、一般的には以下のようにする。

RandomTalk : nonoverlap
{
'ほげほげ';
'ごにょごにょ';
}

これで大抵はことが足りるが、より徹底して重複を排除するために、次のようにする。

RandomTalkArray : array    //arrayを指定することで、RandomTalkArray関数の出力(ランダムトーク)が配列として扱われる
{
'ほげほげ';
'ごにょごにょ';
}
RandomTalkMain
{	//------------------------------------------------------------------------------
//	ランダムトーク。汎用リストを利用し、トークが重複しないようにする
//	この関数を、OnAiTalkなどから呼び出す。
//------------------------------------------------------------------------------
_RandomTalk_Length = STRLEN(JOIN(RandomTalkArray,''));
if (!ISVAR('RANDOM_TALK_LENGTH')) { RANDOM_TALK_LENGTH = _RandomTalk_Length; }
if (RANDOM_TALK_LENGTH != _RandomTalk_Length) {
//トークが変更されたらリストを再作成
//総件数ではなく文字列長を見ることで、トーク件数が変わらず、内容だけ変更した場合にも対応。
//文字列長を見るため、トークリストでは変数等の置き換えが発生しないようにすること(""やANYを使わない)。
Talk_Array = RandomTalkArray;
RANDOM_TALK_LENGTH = _RandomTalk_Length;
} elseif (ARRAYSIZE(Talk_Array) == 0) {
//リストが空っぽ(未定義含む)の場合、リスト再作成
Talk_Array = RandomTalkArray;
}
ANY(Talk_Array);	//ランダムトークを格納した配列から要素を1つ取り出して発話
Talk_Array[LSO] = IARRAY;	//取り出した要素を配列から削除して、配列を作成し直すまで重複が発生しないようにする
}

ランダムトークをトーク配列に格納し、ランダムトークイベントが発生するたびに、ANY関数で1つ選んで発話→LSO関数を使い、選ばれた要素をトーク配列から削除、と言う処理をしている。
要素の削除を繰り返すと最終的にトーク配列が空っぽになるが、その時は改めてトーク配列にランダムトークを格納し直す。
要素を配列から削除しているのだから、重複が起こりようがない、と言う理屈である。

TalkArray変数は、そのままセーブファイルに書き込ませても問題ないと思うが、自分の場合、セーブファイルの内容は必要最低限としたいので、ランダムトークをゴースト終了時に専用のファイルに書き出し、ゴースト起動時にそのファイルから読み込むようにしている。

その際の処理がこちら。OnSystemLoadで読み出し、OnSystemUnloadで書き出しを行う。
なお、ファイルへの入出力はUTF-8を指定しているが、必要に応じて別の文字コードに変更することもできる(言うまでもないが、読み書きでは、同じ文字コードを指定すること)。

OnSystemLoad
{	//------------------------------------------------------------------------------
//	ゴーストが読み込まれたときの処理(shiori3.dicからの呼び出し)
//------------------------------------------------------------------------------
//ランダムトーク用配列の初期化
Talk_Array = IARRAY;
//ランダムトークをファイルから読み込み
Filename  = 'randomtalk.sav';	//ファイル書き出しでも使うのでグローバル変数に
FCHARSET(1);	//UTF-8
if (FOPEN(Filename,'r')) {
while 1 {
_talk = FREAD(Filename);
if (_talk == -1) {
break;
}
Talk_Array ,= _talk;
}
FCLOSE(Filename);
}
}
OnSystemUnload
{	//------------------------------------------------------------------------------
//	ゴースト終了時の処理(shiori3.dicからの呼び出し)
//------------------------------------------------------------------------------
//ランダムトークをファイルに書き出し
FCHARSET(1);	//UTF-8
if (ARRAYSIZE(Talk_Array)) {
if (FOPEN(Filename,'w')) {
foreach Talk_Array ; _string {
if (_string != '') {
FWRITE(Filename,_string);
}
}
FCLOSE(Filename);
}
}
//保存不要な変数を削除し、セーブファイルの肥大化を防ぐ
ERASEVAR('Filename');
ERASEVAR('Talk_Array');
}

こうすることで、ゴーストの終了を挟んでも、ランダムトークが重複することがなくなる。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です