GS2-SkillTree

スキルツリー機能

キャラクターなどの成長要素として一般的に使用されるスキルツリー機能を実現するためのマイクロサービスです。 スキルツリーとは、以下のような木構造を持ち、ノードを解放することでキャラクターのパラメーターを向上させることができる機能を指します。 ノードの解放にはコストが必要で、GS2-SkillTree では各マイクロサービスが提供する《消費アクション》を設定できます。

flowchart TD
  Base --> Node1[STR+5]
  Node1 --> Node2[DEF+5]
  Node2 --> Node3[SPD+5]

  Node3 --> Node4[STR+5]
  Node4 --> Node5[DEF+5]
  Node5 --> Node6[STR+5]
  Node6 --> Node7[DEF+5]

  Node3 --> Node10[SPD+5]
  Node10 --> Node11[DEF+5]
  Node11 --> Node12[SPD+5]
  Node12 --> Node13[DEF+5]

  Node11 --> Node30[SPD+5]
  Node30 --> Node31[STR+5]
  Node31 --> Node32[SPD+5]

  Node7 --> Node20[STR+5]
  Node13 --> Node20
  Node20 --> Node21[STR+5]
  Node21 --> Node22[STR+5]

前提ノード

各ノードにはツリー構造を作るために《前提ノード》を設定できます。 前提ノードには最大10個のノードを設定でき、前提ノードに設定されたノードが解放状態でなければノードは解放することができません。

前提ノードにはそこに至るまでの全てのノードを設定する必要はなく、直前の1つだけ設定すれば木構造を作成できることにご注意ください。

解放したノードを未解放に戻す

各ノード単位、もしくは全てのノードを未解放状態に戻すことができます。

コストの返還

その際、ノードを解放するのに消費したコストを指定した割合に基づいて返還することができます。

このとき注意しなければならないのは、トランザクションの消費アクションには「反転可能」と「反転不可能」の2種類が存在することです。 「反転可能」な消費アクションについては返還が行われますが「反転不可能」な消費アクションについては返還が行われません。

消費アクションが「反転可能」かは、各マイクロサービスのリファレンスの記載を確認してください。

ツリーの途中にあるノードの操作

ノードに依存しているノードが解放済みの場合、ノードを未解放状態に戻すことはできません。

ノードの一括解放

ノードの解放は複数のノードを一括で解放することができます。 その際依存関係について気をつけながらノードを指定する必要はなく、GS2-SkillTree 側で依存関係の順番を考慮しながら解放処理を行い、解放可能判定を行います。

実装例

ノードの解放状態を取得

    var domain = gs2.SkillTree.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
    );
    var item = await domain.ModelAsync();
    const auto Domain = Gs2->SkillTree->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Status(
    );
    const auto Future = Domain.Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

ノードの解放

    var domain = gs2.SkillTree.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
    );
    var result = await domain.ReleaseAsync(
        nodeModelNames: new string[] {
            "node-0001",
        }
    );
    const auto Domain = Gs2->SkillTree->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Status(
    );
    const auto Future = Domain->Release(
        []
        {
            const auto v = MakeShared<TArray<FString>>();
            v->Add("node-0001");
            return v;
        }()
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

ノードの解放状態を元に戻す

    var domain = gs2.SkillTree.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
    );
    var result = await domain.RestrainAsync(
        nodeModelNames: new string[] {
            "node-0001",
        }
    );
    const auto Domain = Gs2->SkillTree->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Status(
    );
    const auto Future = Domain->Restrain(
        []
        {
            const auto v = MakeShared<TArray<FString>>();
            v->Add("node-0001");
            return v;
        }()
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

ノードの解放状態をリセットする

    var domain = gs2.SkillTree.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
    );
    var result = await domain.ResetAsync(
    );
    const auto Domain = Gs2->SkillTree->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Status(
    );
    const auto Future = Domain->Reset(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

詳細なリファレンス