cm-check
v1.0.1
Published
Role Playing Game (RPG) Toolkit which facilitates easy-to-use and customizable checks. Ability checks, combat checks, and anything else you can imagine.
Downloads
5
Readme
CM-Check
Check is a suite of lightweight, customizable tools for game developers. The project was developed to serve the simple purpose of making it easy to execute Ability Checks, much like you might find in most modern Role Playing Games (RPGs), but offer the extensibility and customization developers should expect.
Running a basic check
In essence, the concept is this: Dice are rolled against a target number and compared with the result, and the success of each 'check' is then determined.
Benny the Barbarian is going to need to knock down that wooden door before she can escape the evil wizard's cave. She needs to pass a Strength check with a target of 14. If she succeeds, the door will be knocked off of its hinges and she will be free!
Creating and Executing a Basic Check
According to the classic d20 rules, characters making a check need to roll 1d20 ( one 20-sided die ) and the result needs to be higher than, or equal to 14. Lets express this in code.
// Invoke the CheckExecutor class, the brain center of the system.
var CheckExecutor = require( 'cm-check' );
// Create a new check;
var strengthTest = CheckExecutor.generateCheck();
strengthTest.setTarget( 14 ); // Check Target # = 14
strengthTest.addDie( 1, 20 ); // Check Die Rolled = 1 die with 20 sides
// Execute the Check
CheckExecutor.execute( strengthTest ); // Roll dice, do other processes...
// Get Result and print to console
if ( strengthTest.isPass() ) { console.log( 'Pass!' ); }
else { console.log( 'Fail :(' ); }
Default Checks
The following checks can be generated out of the box:
- SimpleCheck - 'simple' : A simple check with no configuration
- D20AttributeCheck - 'd20-attribute' : A check which handles standard D20 SRD attribute checks. Automatically applies the appropriate roll modifier for the given attribute score. Automatically registers 1d20 to the roll.
To create a new check:
var CheckExecutor = require( 'cm-check' );
var simpleCheck = CheckExecutor.generateCheck( 'simple' ); // Simple Check (also works with no string provided)
var d20AttributeCheck = CheckExecutor.generateCheck( 'd20-attribute' ); // D20 Attribute Check
Modifiers
Right of the box, you can generate Modifiers for the check. You can add or subtract values from Check Results, Check Targets, as well as add or remove die from the check itself.
By adding modifiers to a check, you can account for factors that affect the outcome of the check. Consider the following scenario:
After rolling a 12 on their Strength Check when attempting to knock down the door, failing to hit the target of 14, Benny the Barbarian still needs to get the door open somehow. She drinks a potion of extra strength, which will add 3 points to her next Strength Check ( Strength Check +3 ).
Applying a Modifier
To make a second check, we can simply add a modifier to the same check and run it again.
var CheckExecutor = require( 'cm-check' );
var strengthTest = CheckExecutor.generateCheck();
var strengthModifier = CheckExecutor.generateModifier( 'result' );
strengthTest.setTarget( 14 );
strengthTest.addDie( 1, 20 );
// Configure strength modifier
strengthModifier.setName( 'Potion of Strength' );
strengthModifier.setValue( 3 ); //
// Apply modifier
strengthTest.addModifier( strengthModifier);
// Execute the check
CheckExecutor.execute( strengthTest );
// Get result
if ( strengthTest.isPass() ) { console.log( 'PASS' ); }
else { console.log( 'FAIL' ); }
If you prefer daisy-chaining and consolidating your code a bit, The same scenerio can be expressed as
var CheckExecutor= require( 'cm-check' );
var strengthCheck =
CheckExecutor.generateCheck()
.setTarget( 14 )
.addDie( 1, 20 )
.addModifier(
CheckExecutor.generateModifier( 'result' )
.setName( 'Potion of Strength' )
.setValue( 3 )); // You can supply number | string (numeric) | number[] or string (numeric)[] for value
Check.execute( strengthCheck );
if ( strengthTest.isPass() ) { console.log( 'PASS' ); }
else { console.log( 'FAIL' ); }
Default Modifiers
The following default modifiers are available:
- ResultModifier - 'result' : Affects the result generated by the Check roll
- TargetModifier - 'target' : Affects the target of the Check
- DieModifier - 'die' : Affects the die used to execute the roll, or the die after the Check is rolled.
To create a modifier:
var CheckExecutor = require( 'cm-check' );
var ResultModifier = CheckExecutor.generateModifier( 'result' ); // Result Modifier
var TargetModifier = CheckExecutor.generateModifier( 'target' ); // Target Modifier
var DieModifier = CheckExecutor.generateModifier( 'die' ); // Die modifier
Note also that you can get all modifiers applied to a check with the .getModifiers()
method on the check.
Advanced Usage
We've been over how to execute a simple check, but Check is easily extensible to handle more customized scenarios as well. Let's review these features below.
Hooks and Phases
When executing a check, 4 event hooks are fired, giving any other participating javascript a chance to interject and affect the check before it has finished execution.
The hooks are as follows:
- '{checkTypeName}_modifier' : This gives you an opportunity to affect things right before the modifiers are applied. There is a _modifier hook before and after the roll, you can use phases to define which hook you mean to target (default phase is 'after' )
- '{checkTypeName}_roll' : This hook triggers its listeners to fire after the modifiers have been applied, but just before the die on the check are rolled.
- '{checkTypeName)_finish' : This hook fires and invokes subscribers after the final wave of modifiers has been applied after the roll. It is the last step in the check evaluation before accounting for changes in the die.
Why use custom hooks?
Custom hooks allow you to make global changes to some or all checks at the global check execution level. For instance, lets consider the following scenario:
Suddenly, the entire mansion is filled with horrific shrieks of maniacal laughter! The sound is so distracting that all members of the party - and monsters! - will take a -4 penalty to all combat checks until the laughter subsides.
To express this idea in code, we will register a new event reaction method, or Hook, that will be fired before any other modifiers are applied to any check of a given type that will be executed.
var CheckExecutor = require( 'cm-check' );
var checkType = 'd20-attribute'; // We're targeting d20 attribute checks specifically, so we'll want to include the typename. You can also get the typename by making a new check instance and using the .getType() method.
// Now let's register a new callback function for the _finish hook
CheckExecutor.on( checkType + '_finish', function( check, phase ) {
check.addModifier( CheckExecutor.generateModifier( 'Maniacal Laughter Penalty', -4 ) );
});
That's it! When we run any type of D20 check through the CheckExecutor, this modifier will now be automatically applied.
#####Check Hook Callback Signature
Note in the function above that the callback function for each of these interrupts has two parameters. The 0th parameter is the check object itself, which you may modify as you see fit. The 1st parameter is the phase string, which tells you which phase is currently being executed (a string).
The function need not return any values, they will get lost in the pipeline and not used.
Phases
As each hook is fired and it calls all of the registered callback functions, it passes along the phase to each callback. Also, each modifier registers itself as belonging to a certain phase 'before' or 'after' at the time of this writing.
Customization and Extension in Typescript
This library is built in typescript and transpiled into node.js - If you would like to use typescript to extend any part of this library, you'll find you should be able to do so.
With typescript, you will be able to register new types of Checks and Modifiers with whatever properties and behaviors you wish. The system is designed to make extension very simple using classic OOP architecture to enforce core rules and allow you freedom as much as possible.
You can get access to all of the classes provided on the CheckExecutor.Class object.
API Docs
API Documentation is available at http://creativemutagens.com/projects/cm-check/api/