GS2-Mission

Mission and achievement feature

It is a mechanism for rewarding players based on their accumulated actions in the game. This feature is used to implement features commonly referred to as Achievements, Trophies, and Missions.

Mission Counter

An entity to count the number of times based on a player’s actions. A counter is provided to count the number of times a player has completed a quest, enhanced a character, or drawn a gacha, etc. in the game.

Scope can be set for the counter. The following values can be set for the scope.

Scope TypeScope Content
Not resettingTotal since the start of game play
Reset at X time every dayNumber of executed in same day
Reset at X time every week on X day of the weekNumber of times executed in this week
Reset at X time on X day of every monthNumber of times executed in this month
Reset every specified number of daysReset every specified number of days from the anchor time
Count up only when matching verify actionIncrement counter based on verifyAction execution result

Counter values are managed by each scope and the values of each scope can be used for mission accomplishment conditions.

Scope Control with Verify Actions

Using scopeType=verifyAction allows you to define arbitrary conditions with conditionName and condition, controlling whether to increment the counter based on verification results from other microservices. This enables creating scopes that only increment during specific event periods or when specific characters are in the formation.

Challenge Period

CounterModel can have challengePeriodEventId configured to limit counter operation periods using a GS2-Schedule event GRN. Counters cannot be updated outside the specified period, making this useful for time-limited events.

Mission Task

This is the master data that defines the goal to be presented to the player.

It defines the “mission counter,” the “scope,” the “target value,” and the “reward” for achieving the goal. For example, the following settings can be configured

Mission CounterScope TypeTarget ValueReward
Number of times you completed the questReset at X time every day10Item A
Number of times you complete a questReset every specified number of days from the anchor time50Item B
Number of times you have enhanced your characterReset at X time every day5Item C

Achievement Determination with Verify Actions

By specifying verifyActions for verifyCompleteType, task achievement can be determined by whether verification actions from other microservices are satisfied. When using this feature, achievement determination via the Complete object provided by GS2-Mission is not available, so achievement status must be calculated on the client side to control the reward UI.

Challenge Period

MissionTaskModel’s challengePeriodEventId can limit the achievable period using a GS2-Schedule event. Completed tasks can still be collected after the period ends, but if the mission task has a reset interval configured, they become uncollectable when the reset timing is reached.

Mission Group

An entity that unites multiple mission tasks. A mission group can have a reset cycle for the reward receipt flag.

Mission CounterScope TypeTarget ValueReward
Number of times you completed the questReset at X time every day10Item A
Number of times you have enhanced your characterReset at X time every day5Item C

By associating these mission tasks with a single mission group and setting “Reset at X time every day” for the reset cycle of the reward receipt flag for the mission group as well When a mission task is accomplished every day, the user will be able to receive the reward every day.

Reset by Arbitrary Number of Days

By specifying days for resetType, you can reset the reward receipt flag every specified number of days from the anchor time specified with anchorTimestamp. For example, this enables operations such as resetting every 3 days from the event start.

Script Triggers

By setting missionCompleteScript, counterIncrementScript, and receiveRewardsScript in the namespace, you can call custom scripts before or after mission completion, counter increments, or reward collection. Scripts can be executed synchronously or asynchronously; asynchronous execution supports integration with GS2-Script and external systems via Amazon EventBridge.

The main configurable event triggers and script names are as follows:

  • missionCompleteScript (Completion Notification: missionCompleteDone): Before and after mission completion
  • counterIncrementScript (Completion Notification: counterIncrementDone): Before and after counter increments
  • receiveRewardsScript (Completion Notification: receiveRewardsDone): Before and after reward receipt

Push Notifications

The main configurable push notifications and their names are as follows.

  • completeNotification: Notification upon mission task completion

Supports mobile push forwarding to offline devices, enabling prompting for reward collection.

Master Data Management

Registering master data allows configuration of data and behaviors available to microservices.

Master data types include the following.

  • CounterModel: Counting target and reset cycle
  • MissionGroupModel: Reward reset settings per group
  • MissionTaskModel: Achievement conditions and rewards

Master data can be registered via the Management Console. Alternatively, you can set up workflows to reflect data from GitHub or register via CI using GS2-Deploy.

GS2-Buff Integration

Integrating with GS2-Buff allows buffs to adjust the completeAcquireActions of MissionTaskModels, enabling flexible reward amount adjustments based on events and other factors.

Example of implementation

Raise Mission Counter

Raising the mission counter cannot be handled by the SDK for the game engine.

Please implement it in a way such as raising the counter as a reward for clearing GS2-Quest or as a lottery reward for GS2-Lottery.

Obtain information on mission task accomplishment status and reward receipt

    var item = await gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    ).ModelAsync();
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Complete(
        "mission-group-0001" // missionGroupName
    );
    const auto item = Domain.Model();

Receive rewards for mission accomplishment

    var result = await gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Complete(
        missionGroupName: "mission-group-0001"
    ).ReceiveRewardsAsync(
        missionTaskName: "mission-task-0001"
    );
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Complete(
        "mission-group-0001" // missionGroupName
    );
    const auto Future = Domain->ReceiveRewards(
        "mission-task-0001"
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError()) return false;

Get the value of the mission counter

    var item = await gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Counter(
        counterName: "quest_complete"
    ).ModelAsync();
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        AccessToken
    )->Counter(
        "quest_complete" // counterName
    );
    const auto item = Domain.Model();

Get the mission’s target value

    var items = await gs2.Mission.Namespace(
        namespaceName: "namespace-0001"
    ).MissionGroupModel(
        missionGroupName: "mission-group-0001"
    ).MissionTaskModelsAsync(
    ).ToListAsync();
    const auto Domain = Gs2->Mission->Namespace(
        "namespace-0001" // namespaceName
    )->MissionGroupModel(
        "mission-group-0001" // missionGroupName
    );
    const auto It = Domain->MissionTaskModels(
    );
    TArray<Gs2::UE5::Mission::Model::FEzMissionTaskModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

Detailed Reference