@rbxts/player-statistic-achievements
v1.0.2
Published
A generic, type-safe package for Roblox development made with roblox-ts for giving out rewards to players who achieve specified objectives based on their player statistics.
Downloads
12
Readme
Player Statistic Achievements
Player Statistic Achievements is a package for Roblox game developers. This package is tightly coupled with Player Statistics and Reward Containers.
Define your game's statistics (for Player Statistics) and achievements just using three simple definition files and initialize the PlayerStatisticAchievementsManager
. The manager will handle the rest! If you want to add specific logic when achievements are awarded, there are signals to listen to in order to do so.
Installation
roblox-ts
Simply install to your roblox-ts project as follows:
npm i @rbxts/player-statistic-achievements
Wally
Wally users can install this package by adding the following line to their Wally.toml
under [dependencies]
:
FiniteStateMachine = "bytebit/[email protected]"
Then just run wally install
.
From model file
Model files are uploaded to every release as .rbxmx
files. You can download the file from the Releases page and load it into your project however you see fit.
From model asset
New versions of the asset are uploaded with every release. The asset can be added to your Roblox Inventory and then inserted into your Place via Toolbox by getting it here.
Documentation
Documentation can be found here, is included in the TypeScript files directly, and was generated using TypeDoc.
Example
Let's create a simple example where we will grant players a badge when they hit a high score of at least 1,000 points. We'll first need to write the player statistics definition and player statistic events definition (for Player Statistics), like so:
import { StatisticDefinition, StandardStatisticUpdateFunctions } from "@rbxts/player-statistics";
export const PlayerStatisticsDefinition = {
highScore: identity<StatisticDescription>({
defaultValue: 0,
updateFunction: math.max,
}),
};
export const PlayerStatisticEventsDefinition = {
gameCompleted: identity<ReadonlyArray<typeof PlayerStatisticsDefinition>>([
"highScore",
]),
};
With that, we can define our achievements definition. Each achievement is described by the list of player statistic names that can trigger it to be awarded, a function that computes the progress the player has made on a scale of [0, 1], where 0 is no progress and 1 is complete, and the rewards selector (from Reward Containers) for when the player completes the achievement. In this case, since players can't really make progress but only have a yes/no answer for whether they've achieved the high score, we'll keep the progress function as a binary 0 or 1 response. For things like "Defeat 100 zombies", it would be trivial to write a progress function of math.min(1, numZombiesDefeated / 100)
instead. We also only care about the highScore
statistic, and for now we'll just grant the user a badge for their accomplishment. Here's how we can write that definition:
import { BadgeReward, ConstantRewardsSelector } from "@rbxts/reward-containers";
import { AchievementDescription } from "@rbxts/player-statistic-achievements";
export const PlayerStatisticAchievementsDefinition = {
highScoreOf100: identity<AchievementDescription>({
getProgress: (statisticsSnapshot) => statisticsSnapshot.highScore >= 100 ? 1 : 0,
relevantStatisticNames: ["highScore"],
rewardsSelector: ConstantRewardsSelector.create([
identity<BadgeReward>({
type: "Badge",
badgeId: 67997,
}),
]),
}),
};
Now all of our definitions are done! It is now as easy as just initializing a PlayerStatisticAchievementsManager
in our game's server-side bootstrapping code. Here's an example:
import { DataStoreService } from "@rbxts/services";
import { DataStorePlayerStatisticsPersistenceLayer, PlayerStatisticsProvider } from "@rbxts/player-statistics";
import { PlayerStatisticAchievementsDefinition, PlayerStatisticEventsDefinition, PlayerStatisticsDefinition } from "./data/Definitions";
// PlayerStatisticAchievementsManager needs an instance of IPlayerStatisticsReader,
// so we'll create a PlayerStatisticsProvider from @rbxts/player-statistics for that
const playerStatisticsDataStore = DataStoreService.GetDataStore("PlayerStatistics");
const playerStatisticsPersistenceLayer = DataStorePlayerStatisticsPersistenceLayer.create(playerStatisticsDataStore);
const playerStatisticsProvider = PlayerStatisticsProvider.create(
PlayerStatisticEventsDefinition,
playerStatisticsPersistenceLayer,
PlayerStatisticsDefinition
);
// We'll also need to create our reward granters by their reward type.
// In this example, that's just a granter for badge rewards.
const rewardGrantersByRewardType = new Map([["Badge", BadgeRewardGranter.create()]]);
// And now we actually create the PlayerStatisticAchievementsManager instance
const playerStatisticAchievementsManager = PlayerStatisticAchievementsManager.create(
PlayerStatisticAchievementsDefinition,
rewardGrantersByRewardType,
playerStatisticsProvider,
);
There we go! It is all set up! Now, when we record a player statistics event and the player achieves a high score of 100 or more for the first time, they'll be given their reward! Here's an example of how to do that:
playerStatisticsProvider.recordEvent(player, "gameCompleted", playerScore);
And done! Make your players feel accomplished just like that!!