GS2-Grade

Grade/rarity feature

A common specification for character and equipment development is to provide for upgrading in addition to level-up as a short-term growth goal. Upgrading raises the level cap and makes it possible to develop more powerful characters and equipment.

There are several possible methods of upgrading, some of which can be done by consuming growth materials, and others by synthesizing characters and equipment of the same type. GS2-Grade does not care about the method, but aims to make the operation of the GS2-Experience level cap simpler to implement by setting a level cap for each grade.

Grades

For each grade, you can define the value to be set for the GS2-Experience rank cap.

Initial values for a grade

You can set the initial grade value depending on whether the property ID matches a regular expression. For example, by starting with grade 3 if the name of the ItemModel in GS2-Inventory starts with SSR, or grade 2 if it starts with SR It is possible to change the initial rank cap depending on the type of ItemModel.

Grade raising material determination

In the case of “synthesizing the same kind of character or equipment” as a method of upgrading, a function is provided to support processing to determine if the resource being used as material is “the same kind of character or equipment.” This is achieved by using a regular expression to extract parameters from the property ID of the grade, constructing a regular expression, and determining whether the property ID of the resource to be used as material matches.

For example, to determine if an ItemSet in GS2-Inventory is by the same type of ItemModel, the regular expression is set as follows.

propertyIdRegex: grn:gs2:{region}:{ownerId}:inventory:namespace-0001:user:(.*):inventory:character:item:(.*):.*
gradeUpPropertyIdRegex: grn:gs2:{region}:{ownerId}:inventory:namespace-0001:user:$1:inventory:character:item:$2:.*

Now use propertyIdRegex to retrieve the “user ID” and the “ItemModel name”. If the user ID is “user-0001”, the name of the ItemModel is “item-0001”, and the name of the ItemSet is “item-set-0001”, then the GRN (property ID) of the ItemSet is

grn:gs2:{region}:{ownerId}:inventory:namespace-0001:user:user-0001:inventory:character:item:item-0001:item-set-0001

and the replaced value of gradeUpPropertyIdRegex is:

gradeUpPropertyIdRegex: grn:gs2:{region}:{ownerId}:inventory:namespace-0001:user:user-0001:inventory:character:item:item-0001:.*

This allows for expressions that allow the same kind of item to be specified as a material.

Reward addition table

The grade model can have acquireActionRates configured to adjust reward amounts of acquire actions according to the grade. In addition to rates in double mode, bigRates is also available for handling numbers exceeding int64, supporting cases involving large rewards such as BigItem in GS2-Inventory.

Script Triggers

Setting changeGradeScript in the namespace allows custom scripts to be executed synchronously or asynchronously via Amazon EventBridge before and after grade changes.

Main event triggers and script setting names are:

  • changeGradeScript (completion notification: changeGradeDone): before and after grade changes

Transaction Actions

GS2-Grade provides the following transaction actions:

  • Verify Actions: Verify grade, verify grade-up material
  • Consume Actions: Subtract grade
  • Acquire Actions: Add grade, reflect rank cap, apply reward multipliers according to grade

By using “Verify grade-up material” as a verify action, you can perform validations within a transaction, such as ensuring that the material intended for synthesis (another item or character) is actually possessed. This helps prevent unauthorized upgrades using invalid materials.

Master Data Operations

Registering master data allows you to configure data and behavior that can be used by the microservice.

Available master data types:

  • GradeModel: rank caps and reward amounts per grade

Master data can be registered through the management console, imported from GitHub, or registered from CI using GS2-Deploy.

Example implementation

Grade addition

Grade addition cannot be handled by the SDK for game engines.

Use GS2-Exchange to add grades as a reward for consuming enhancement materials or for enhancing GS2-Enhance.

Get a list of grades

    var items = await gs2.Grade.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).StatusesAsync(
        gradeName: "grade-0001"
    ).ToListAsync();
    const auto It = Gs2->Grade->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Statuses(
        "grade-0001" // gradeName
    );
    TArray<Gs2::UE5::Grade::Model::FEzStatusPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

Get the grade

    var item = await gs2.Grade.Namespace(
        namespaceName: "namespace-0001"
    ).GradeModel(
        gradeName: "grade-0001"
    ).ModelAsync();
    const auto Future = Gs2->Grade->Namespace(
        "namespace-0001" // namespaceName
    )->GradeModel(
        "grade-0001" // gradeName
    )->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

Synchronize rank caps in GS2-Experience

When a grade changes, GS2-Experience will automatically reflect the change in the rank cap. However, when the grade model is updated and the value of the rank cap at a specific grade is updated, the updated rank cap can be applied by explicitly calling the following synchronization API.

    var result = await gs2.Grade.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        gradeName: "grade-0001",
        propertyId: "property-0001"
    ).ApplyRankCapAsync(
    );
    var item = await result.ModelAsync();
    const auto Future = Gs2->Grade->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "grade-0001", // gradeName
        "property-0001" // propertyId
    )->ApplyRankCap(
    );
    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 Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

Detailed Reference