-
Notifications
You must be signed in to change notification settings - Fork 265
Game Mechanic State pattern
Most of the game mechanics in AD follow consistent logic and structure. Based on this assumption, we created a framework for working with them in the form of GameMechanicState class which simplified and made cleaner game state access all over the code. This generalization also works in favor of Effects system that is explained here: https://github.com/IvarK/HahaSlabWontGetHere/wiki/Effects-system-explained
But, the game mechanic declaration doesn't consist only of state class - additionally we need to bind gameDB configs, add declaration function, add some additional functions/accessors that are tightly coupled with the game mechanic. Currently, there's no standard for such declarations and the following pattern is expected to give the guidelines for a consistent game mechanic code.
- (Optional) GameDB declaration. For game mechanics that have configurable elements. Reference: https://github.com/IvarK/HahaSlabWontGetHere/wiki/How-to-GameDatabase-(draft)
- State class that extends
GameMechanicState. This is a staple element between player object (PO) and game logic that allows separation of PO structure from logic code. - Accessor object created with the
createAccessorfunction. It hasindexproperty which contains all the GameDB entries wrapped into State class instances. Apart from that it is itself a callable function which accepts an index as an argument. Example:Achievement(101). This is the very method which should be used when accessing state objects in game logic code. - (Very Optional) Additional method or getter declaration for Accessor object. Very situational, most likely you want to place this functionality in the collection object (explained below). Example:
NormalChallenge.current - Collection object. Contains all sorts of functions for non-state-specific operations. Usually contains the
allproperty that contains all state instances. SincecreateAccessorcreates a sparse array, GameDB-basedallshould be created withcompactarray extension, for instance:all: Achievement.index.compact()
GameDB file
// 1. GameDB declaration
GameDatabase.challenges.normal = [
{
id: 1,
legacyId: 1,
isQuickResettable: false,
description: "Reach Infinity for the first time.",
reward: "First Dimension Autobuyer"
},
...
};File with game logic
// 2. Class that extends `GameMechanicState`
class NormalChallengeState extends GameMechanicState {
constructor(config) {
super(config);
...
}
...
}
// 3. Accessor object
/**
* @param {number} id
* @return {NormalChallengeState}
*/
const NormalChallenge = NormalChallengeState.createAccessor(GameDatabase.challenges.normal);
// 4. Additional method or getter declaration for Accessor object
Object.defineProperty(NormalChallenge, "current", {
get: () => (player.challenge.normal.current > 0
? NormalChallenge(player.challenge.normal.current)
: undefined),
});
// 5. Collection object
const NormalChallenges = {
/** @type {NormalChallengeState[]} */
all: NormalChallenge.index.compact(),
completeAll() {
for (const challenge of NormalChallenges.all) challenge.complete();
},
...
};