GS2-Idle
ゲームをプレイしていない期間に応じて報酬を付与する仕組みを実現します。
カテゴリー
放置報酬は複数用意することができます。 プレイヤーはカテゴリー毎に1つの待機時間を持つことができます。
放置時間
カテゴリーには放置時間 何分毎に報酬を得られるかと、放置時間の最大値の初期値を設定できます。 放置時間の最大値はプレイヤーごとに引き上げることが可能です。
放置報酬
放置報酬には放置時間が一定時間経過すると得られるアイテムの一覧を定義します。 付与する報酬は、「経験値+アイテム」のように複数(最大10個)設定することができます。
さらに、待機時間内で報酬の内容にバリエーションをもてるように、複数の報酬リストを設定することができます。
例えば、10分待機する毎に「経験値+10」と「強化素材Lv.1 x 1」を入手できる。 ただし、60分毎のタイミングでは上記の報酬の代わりに「経験値+20」と「強化素材Lv.2 x 1」を入手できる。 上記のような例を考えてみましょう。
この場合、放置報酬には以下のようなテーブルを設定します。
- | 報酬1 | 報酬2 |
---|---|---|
1 | 経験値+10 | 強化素材Lv.1 x 1 |
2 | 経験値+10 | 強化素材Lv.1 x 1 |
3 | 経験値+10 | 強化素材Lv.1 x 1 |
4 | 経験値+10 | 強化素材Lv.1 x 1 |
5 | 経験値+10 | 強化素材Lv.1 x 1 |
6 | 経験値+20 | 強化素材Lv.2 x 1 |
これで経過時間に応じて報酬アイテムの内容を変更することができます。 報酬の内容はループするため、2時間経過後には「1,2,3,4,5,6,1,2,3,4,5,6」のアイテムが手に入ることになります。
放置報酬のランダム抽選
報酬の内容にもっとランダム性を持たせたいことがあります。 そのような場合には、報酬に GS2-Lottery の抽選処理を設定してください。
従来の GS2-Lottery では抽選を行うまで結果が不定ですが、GS2-Idle を使用するケースでは待機開始時点で乱数シードを生成し 報酬の計算時にその乱数シードを利用して抽選を行うことで、待機途中でもランダムに抽選されたアイテムの内容をプレイヤーに提示でき、内容は不変になります。 (GS2-Lottery の景品テーブルを変更すると、この前提は崩れます)
待機時間のスケジュール管理
イベントと連動した放置報酬を実装できるように、カテゴリー毎に GS2-Schedule のイベントと関連づけることができます。
イベントの開催期間を 2023-01-01 00:00 ~ 2023-02-01 00:00 とした場合に、2023-01-31 23:00 から待機を始めたとします。 この場合、2023-02-01 00:00 になった段階で放置時間のカウントはストップします。
そのため、2023-02-01 01:00 に報酬を受け取る場合も、2023-02-01 09:00 に報酬を受け取る場合も内容は一定となります。
イベントに繰り返し設定がある場合、繰り返し回数が変化する時に放置時間はリセットされます。 例えば、毎週月曜日 00:00 ~ 火曜日 00:00 の繰り返しイベントの場合、翌週月曜日 00:00 になった瞬間に前週の報酬を受け取っていなかったとしても待機時間はリセットされます。
待機時間のスケジュールとは別に、報酬の受取可能期間を設定できます。
実装例
待機の開始
初めて待機時間の情報を取得した際に待機が開始されます。
var item = await gs2.Idle.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
category: "category-0001"
).ModelAsync();
const auto Future = Gs2->Idle->Namespace(
"namespace-0001" // namespaceName
)->Me(
AccessToken
)->Status(
"category-0001" // categoryName
)->ModelAsync();
Future->StartSynchronousTask();
if (Future->GetTask().IsError()) return false;
待機中の一覧を取得
var items = await gs2.Idle.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).StatusesAsync(
).ToListAsync();
const auto It = Gs2->Idle->Namespace(
"namespace-0001" // namespaceName
)->Me(
AccessToken
)->Statuses(
);
TArray<Gs2::UE5::Idle::Model::FEzStatusPtr> Result;
for (auto Item : *It)
{
if (Item.IsError())
{
return false;
}
Result.Add(Item.Current());
}
報酬の内容を確認
var items = await gs2.Idle.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
category: "category-0001"
).PredictionAsync();
const auto Domain = Gs2->Idle->Namespace(
"namespace-0001" // namespaceName
)->Me(
AccessToken
)->Status(
"category-0001" // categoryName
);
const auto Future = Domain->Prediction(
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}
// obtain changed values / result values
const auto Future2 = Future->GetTask().Result()->Model();
Future2->StartSynchronousTask();
if (Future2->GetTask().IsError()) return false;
const auto Result = Future2->GetTask().Result();
報酬の受け取り
報酬を受け取ると、待機時間がリセットされます。 また、待機時間に報酬獲得タイミングまでのあまりが存在する場合も0にリセットされます。
await gs2.Idle.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).Status(
category: "category-0001"
).ReceiveAsync();
const auto Future = Gs2->Idle->Namespace(
"namespace-0001" // namespaceName
)->Me(
AccessToken
)->Status(
"category-0001" // categoryName
)->ReceiveAsync();
Future->StartSynchronousTask();
if (Future->GetTask().IsError()) return false;