Team Achievements #

Preview
The features described below are in preview at the moment.

Overview #

Team Achievements let teams work together toward shared goals and unlock rewards through group effort. Teams can tackle everything from simple one-time challenges to complex achievement chains that build on each other, plus seasonal content and recurring goals that reset automatically to keep players engaged long-term.

Features #

  • Flexible goal structures: Create simple one-time achievements or complex multi-part challenges with sub-achievements and dependencies
  • Automated scheduling: Set up recurring achievements with CRON expressions for daily, weekly, or seasonal content
  • Reward control options: Choose between automatic reward distribution or manual admin approval for strategic resource management
  • Progress tracking: Monitor team advancement with cumulative progress that persists across sessions

Permissions #

Viewing Achievements

  • All Members can view achievement progress and status for their teams
  • Players can only see achievements for teams where they are active members

Managing Achievements

  • All Members can contribute progress to team achievements through gameplay actions
  • Admins Only can manually claim completed achievements to receive rewards
  • Individual contributions aggregate automatically into team-wide progress

Key Terms #

Sub-Achievements and Parent Goals

Team achievements can contain nested sub-achievements, each with their own rewards and completion criteria. This creates layered progression where teams work toward multiple smaller goals that contribute to larger objectives.

Individual vs Total Rewards

  • Individual Rewards: Granted when specific achievements or sub-achievements complete
  • Total Rewards: Special bonuses unlocked only when all sub-achievements within a parent achievement are completed

Auto-Claim vs Manual Claim

  • Auto-Claim: Rewards distribute automatically when achievements complete, ideal for routine progression
  • Manual Claim: Requires explicit admin action, giving team leaders control over valuable or strategic resources

Achievement Preconditions #

Achievements can specify prerequisite achievements i.e., preconditions, that must be claimed before progress can continue. This enables multi-layered achievement trees and guided progression systems.

Server
1
2
3
4
5
6
{
  "advanced_combat": {
    "precondition_ids": ["basic_training", "first_victory"],
    "name": "Advanced Combat Training"
  }
}

Use preconditions for:

  • Tutorials that teach features step-by-step
  • Gated content that unlocks advanced challenges after mastering basics
  • Seasonal progression that builds complexity over time
  • Skill-based unlockable trees that require players to prove their mettle

Building with Team Achievements #

Publisher Events

Achievement completions and progress updates generate detailed events for analytics, external integrations, and custom game logic triggers.

For example, say PvP wins are being tracked as a Team Stat. Here’s how you might reward Teams for reaching certain stat thresholds and log a new achievement:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func (p *TeamAchievementPublisher) Send(ctx context.Context, logger runtime.Logger, nk runtime.NakamaModule, userID string, events []*hiro.PublisherEvent) {
    for _, event := range events {
        if event.Name == "team_stat_updated" {
            teamID := event.Metadata["team_id"]
            statName := event.Metadata["stat_name"]
            newValue, _ := strconv.ParseInt(event.Metadata["new_value"], 10, 64)

            if statName == "pvp_wins" && newValue >= 10 {
                // Trigger achievement update server-side
                p.teamsSystem.UpdateAchievements(ctx, logger, nk, userID, teamID, map[string]int64{
                    "pvp_mastery": 1,
                })
            }
        }
    }
}

From the client, you simply update Team Stats as normal:

Client c#
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
await teamsSystem.UpdateStatsAsync(
    null, // private stats
    new List<UpdateStat> {
        new UpdateStat {
            Name = "pvp_wins",
            Value = 1,
            Operator = StatOperator.Increment
        }
    }
);

Learn more in the Publishers guide.

Example: Monthly Team Challenges #

Create engaging recurring content that keeps teams active throughout each month. The following example demonstrates sub-achievements, reset schedules, and progression checkpoints:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public async Task CheckMonthlyProgress(string teamId)
{
    var achievementList = await teamsSystem.GetAchievementsAsync();
    var monthlyChallenge = achievementList.Achievements
        .FirstOrDefault(kvp => kvp.Key == "monthly_challenge");

    if (monthlyChallenge.Value != null && monthlyChallenge.Value.ClaimTimeSec > 0)
    {
        // Check if all sub-achievements are complete for bonus rewards
        var allSubsComplete = monthlyChallenge.Value.SubAchievements
            .All(sub => sub.Value.ClaimTimeSec > 0);

        if (allSubsComplete && monthlyChallenge.Value.TotalClaimTimeSec == 0)
        {
            // Claim total reward for completing everything
            await teamsSystem.ClaimAchievementsAsync(new[] { "monthly_challenge" });

            // Unlock next tier of challenges
            await UnlockEliteChallenges(teamId);
        }
    }
}

private async Task UpdateChallengeProgress(string teamId, string challengeType)
{
    var challengeIds = GetChallengesByType(challengeType);
    await teamsSystem.UpdateAchievementsAsync(challengeIds, 1);
}

Monthly Challenge Structure

  • Parent Achievement: “Monthly Challenge” with total reward for completing everything
  • Sub-Achievements: “Win 10 PvP battles,” “Complete 5 dungeons,” “Collect 1000 gold”
  • Reset Schedule: Automatic monthly reset using CRON expressions
  • Progression Gates: Completion unlocks “Elite Challenges” for advanced teams

This creates urgency (monthly targets) while providing multiple paths to success and escalating difficulty for engaged teams.

What Ifs #

This section describes edge cases and scenarios that may be unintuitive to the developer.

Negative values can be submitted for achievements

While achievement progress is typically cumulative, the system does accept negative progress values for scenarios where progress might need to be reduced. However, there are important safeguards in place:

  • Floor protection: Achievement counts cannot go below 0 - negative submissions that would result in negative progress are floored at zero
  • Ceiling protection: Progress cannot exceed the achievement’s maximum count (MaxCount)

Once progress is made toward an achievement, it persists until the achievement resets according to its schedule or expires, unless explicitly reduced through negative value updates.

A precondition achievement is removed from config

When a precondition achievement is removed from your configuration, any achievements that depend on it become inaccessible. Teams cannot make progress on dependent achievements until you either restore the missing precondition or update the dependency requirements.

Parent and sub-achievements have different reset schedules

If a parent achievement resets but its sub-achievements have different reset schedules, the sub-achievements maintain their individual progress. This can create scenarios where sub-achievements are partially complete when the parent resets, allowing teams to finish the parent achievement more quickly in the next cycle.

A middle achievement in a precondition chain is removed

When a middle achievement in a precondition chain is removed, all achievements that depend on it become unreachable. The system doesn’t automatically reroute dependencies, so you’ll need to manually update precondition requirements or restore the missing achievement.

Teams want to claim the same achievement multiple times

Teams can claim the same achievement multiple times if it has a reset schedule. Each reset creates a new opportunity to complete and claim the achievement, making recurring achievements valuable for ongoing team engagement.

Achievements expire versus reset

When achievements expire, any accumulated progress is lost permanently. When achievements reset according to their schedule, progress returns to zero but the achievement remains available for a new completion cycle. Teams lose progress in both cases, but resets indicate new opportunities while expiration indicates time limits were missed.

Auto-claim fails when an achievement completes

If auto-claim fails due to reward system errors, the achievement remains in a completed but unclaimed state. The system doesn’t automatically retry failed auto-claims, so teams may need to manually claim the achievement or wait for server-side intervention to resolve the issue.

Configuring Teams Achievements #

Achievements Config

PropertyTypeDefinition
achievementsmap[string]AchievementIndividual achievements mapped by achievement ID

Individual Achievement Config

Each achievement is defined by a unique ID (the key) and its configuration properties:

PropertyTypeDefinition
namestringDisplay name for the achievement
descriptionstringDescription of the achievement goals
countintTarget progress value to complete
auto_claimboolWhether rewards auto-distribute on completion
reset_cronexprstringCRON expression for automatic resets
precondition_ids[]stringRequired achievements that must be claimed first
rewardRewardIndividual completion reward
total_rewardRewardBonus reward for completing all sub-achievements
sub_achievementsmap[string]SubAchievementNested achievements within this achievement

Example: Team Achievements JSON #

The JSON schema defines an achievements object which contains individual achievement objects for each achievement you wish to define in the system. You can configure as few or as many achievements as needed for your game.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
  // ... other Team configs
  "achievements": {
    "monthly_challenge": {
      "name": "Monthly Challenge",
      "description": "Complete all monthly objectives",
      "count": 3,
      "auto_claim": false,
      "reset_cronexpr": "0 0 1 * *",
      "reward": {
        "guaranteed": {
          "currencies": { "team_tokens": { "min": 1000 } }
        }
      },
      "total_reward": {
        "guaranteed": {
          "currencies": { "premium_tokens": { "min": 500 } },
          "items": { "exclusive_banner": { "min": 1 } }
        }
      },
      "sub_achievements": {
        "pvp_wins": {
          "name": "PvP Victory",
          "description": "Win 10 PvP battles",
          "count": 10,
          "auto_claim": true,
          "reward": {
            "guaranteed": {
              "currencies": { "battle_points": { "min": 100 } }
            }
          }
        }
      }
    }
  }
}