Skip to content

Retrieving Achievements

The SDK automatically fetches and caches achievement definitions when connecting to the Scorbit platform. This page covers how to access cached achievements and retrieve specific achievement details.

Checking Cache Status

Before accessing achievements, verify that they have been cached:

// Check if achievements have been fetched and cached
if (sb_has_achievements(gs)) {
    printf("Achievements are available\n");
} else {
    printf("Waiting for achievements to be fetched...\n");
}
// Check if achievements have been fetched and cached
if (gs.hasAchievements()) {
    std::cout << "Achievements are available\n";
} else {
    std::cout << "Waiting for achievements to be fetched...\n";
}
# Check if achievements have been fetched and cached
if gs.has_achievements():
    print("Achievements are available")
else:
    print("Waiting for achievements to be fetched...")

Automatic Fetching

Achievements are automatically fetched when the SDK connects to the Scorbit platform. There is no need to manually trigger a fetch.

Getting All Achievements

Retrieve the complete list of cached achievements:

// Get the count of cached achievements
size_t count = sb_get_cached_achievements_count(gs);
printf("Found %zu achievements\n", count);

// Iterate through all achievements
for (size_t i = 0; i < count; i++) {
    sb_achievement_t achievement;
    if (sb_get_cached_achievement_at(gs, i, &achievement)) {
        printf("Achievement: %s - %s\n", achievement.key, achievement.name);
        printf("  Description: %s\n", achievement.description);
        printf("  Is Trophy: %s\n", achievement.is_trophy ? "yes" : "no");
    }
}
// Get all cached achievements
auto achievements = gs.getAchievements();
std::cout << "Found " << achievements.size() << " achievements\n";

// Iterate through all achievements
for (const auto& achievement : achievements) {
    std::cout << "Achievement: " << achievement.key << " - " << achievement.name << "\n";
    std::cout << "  Description: " << achievement.description << "\n";
    std::cout << "  Is Trophy: " << (achievement.isTrophy ? "yes" : "no") << "\n";
}
# Get all cached achievements
achievements = gs.get_achievements()
print(f"Found {len(achievements)} achievements")

# Iterate through all achievements
for achievement in achievements:
    print(f"Achievement: {achievement.key} - {achievement.name}")
    print(f"  Description: {achievement.description}")
    print(f"  Is Trophy: {'yes' if achievement.is_trophy else 'no'}")

Getting a Specific Achievement

Retrieve a single achievement by its unique key:

// Get a specific achievement by key
sb_achievement_t achievement;
if (sb_get_cached_achievement(gs, "wizard_mode_complete", &achievement)) {
    printf("Found: %s\n", achievement.name);
    printf("Target count: %d\n", achievement.count);
    printf("Image URL: %s\n", achievement.image_url);
} else {
    printf("Achievement not found\n");
}
// Get a specific achievement by key
auto achievement = gs.getAchievement("wizard_mode_complete");
if (achievement) {
    std::cout << "Found: " << achievement->name << "\n";
    std::cout << "Target count: " << achievement->count << "\n";
    std::cout << "Image URL: " << achievement->imageUrl << "\n";
} else {
    std::cout << "Achievement not found\n";
}
# Get a specific achievement by key
achievement = gs.get_achievement("wizard_mode_complete")
if achievement:
    print(f"Found: {achievement.name}")
    print(f"Target count: {achievement.count}")
    print(f"Image URL: {achievement.image_url}")
else:
    print("Achievement not found")

Achievement Properties

Each achievement contains the following properties:

Property Type Description
key string Unique identifier for the achievement
name string Display name
description string Detailed description
count int Target count for limited achievements (1 for unlimited)
image_url string URL to the achievement badge image
obscure_image_url string URL to the obscured/hidden badge image
obscure bool Whether achievement is hidden until unlocked
visible bool Whether achievement appears in lists
is_trophy bool Whether this is a revocable trophy achievement
notify_when_achieved bool Whether to show notification on unlock
input_time enum Limited or Unlimited
achievement_id int Server-side achievement ID
group_id int Achievement group ID (0 if not grouped)
rules array Nested rules defining unlock conditions (see below)
trigger enum Derived from first rule: Game, Mode, Score, SubAchievement
mode_name string Derived from first MODE rule's reference
mode_type enum Derived from first MODE rule type: Start, Complete, Stack
target_score int64 Derived from first SCORE rule's target

Derived Fields

The trigger, mode_name, mode_type, and target_score fields are derived from the first matching rule for backward compatibility. For multi-rule achievements, inspect the rules array directly.

Obscured Achievements

For obscured achievements, display the obscure_image_url and a generic description until the player unlocks it. Once unlocked, show the real image_url, name, and description.

Achievement Rules

Each achievement contains a rules array with one or more rules. Each rule has:

Property Type Description
type string Rule type: MODE, MODE_START, MODE_STACK, SCORE, ACHIEVEMENT, PROGRESS, GAME_CODE
comparison string Comparison operator (e.g., gte, eq)
target int Target value for comparison
reference string Reference value (e.g., mode name for MODE rules)
subachievement_id int Related sub-achievement ID (for ACHIEVEMENT rules)
// Get rules for a specific achievement
size_t rule_count = sb_achievement_get_rules_count(gs, "wizard_mode_complete");
printf("Achievement has %zu rules\n", rule_count);

for (size_t i = 0; i < rule_count; i++) {
    sb_achievement_rule_t rule;
    if (sb_achievement_get_rule_at(gs, "wizard_mode_complete", i, &rule)) {
        printf("  Rule %zu: type=%s, comparison=%s, target=%d, ref=%s\n",
               i, rule.type, rule.comparison, rule.target, rule.reference);
    }
}
// Get rules for a specific achievement
auto achievement = gs.getAchievement("wizard_mode_complete");
if (achievement) {
    std::cout << "Achievement has " << achievement->rules.size() << " rules\n";

    for (const auto& rule : achievement->rules) {
        std::cout << "  Rule: type=" << rule.type
                  << ", comparison=" << rule.comparison
                  << ", target=" << rule.target
                  << ", ref=" << rule.reference << "\n";
    }
}
# Get rules for a specific achievement
achievement = gs.get_achievement("wizard_mode_complete")
if achievement:
    print(f"Achievement has {len(achievement.rules)} rules")

    for rule in achievement.rules:
        print(f"  Rule: type={rule.type}, comparison={rule.comparison}, "
              f"target={rule.target}, ref={rule.reference}")

Filtering Achievements

You can filter achievements based on their properties:

// Get all trophy achievements
auto allAchievements = gs.getAchievements();
std::vector<scorbit::Achievement> trophies;
for (const auto& ach : allAchievements) {
    if (ach.isTrophy) {
        trophies.push_back(ach);
    }
}

// Get achievements that have score rules
std::vector<scorbit::Achievement> scoreAchievements;
for (const auto& ach : allAchievements) {
    for (const auto& rule : ach.rules) {
        if (rule.type == "SCORE") {
            scoreAchievements.push_back(ach);
            break;
        }
    }
}
# Get all trophy achievements
all_achievements = gs.get_achievements()
trophies = [a for a in all_achievements if a.is_trophy]

# Get achievements that have score rules
score_achievements = [
    a for a in all_achievements
    if any(r.type == "SCORE" for r in a.rules)
]

Best Practices

1. Cache Check Before Access

Always verify achievements are cached before attempting to access them:

if (!gs.hasAchievements()) {
    // Show loading indicator or placeholder
    return;
}

2. Handle Missing Achievements

Achievement keys may change between game versions. Always handle the case where an achievement is not found:

auto ach = gs.getAchievement(key);
if (!ach) {
    // Log warning, use default display, or skip
    return;
}

3. Refresh Awareness

Achievement definitions may be updated on the server. The SDK automatically refreshes on reconnection, but be prepared for changes between sessions.