このページには広告が含まれています
ゴースト開発メモ

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

この記事は約5分で読めます。

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

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');
}

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

コメント

タイトルとURLをコピーしました