npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

t20-sheet-builder

v1.26.0

Published

Simulates the brazilian RPG: [Tormenta 20](https://jamboeditora.com.br/produto/tormenta20-edicao-jogo-do-ano-digital/).

Downloads

247

Readme

T20 SheetBuilder

Simulates the brazilian RPG: Tormenta 20.

Installation

npm i t20-sheet-builder

Quick start

To create a human warrior:

const sheetBuilder = new SheetBuilder();
const sheet = sheetBuilder
  .setInitialAttributes({strength: 2, dexterity: 0, charisma: 0, constitution: 0, intelligence: 0, wisdom: 2})
  .chooseRace(new Human(
    ['charisma', 'constitution', 'dexterity'], 
    [new VersatileChoiceSkill(SkillName.acrobatics), new VersatileChoicePower(new OneWeaponStyle())] 
  ))
  .chooseRole(new Warrior([SkillName.fight, SkillName.aim, SkillName.athletics]))
  .chooseOrigin(new Acolyte([
    new OriginBenefitGeneralPower(new IronWill()), 
    new OriginBenefitSkill(SkillName.cure)]
  ))
  .trainIntelligenceSkills([])
  .addInitialEquipment({
    simpleWeapon: new Dagger(),
    armor: new LeatherArmor(),
    martialWeapon: new LongSword(),
    money: 24,
  })
  .build();
const character = new Character(sheet);

API

Character

This is the actual character. It receives a CharacterSheet - generated by SheetBuilder, and has the following methods:

export type CharacterInterface = {
	modifiers: CharacterModifiers;
	sheet: CharacterSheetInterface;
	selectFightStyle(fightStyle: FightStyle): void;
	unselectFightStyle(): void;
	serialize(context: Context): SerializedCharacter;
	getAttributes(): Attributes;
	getAttacks(context: Context): Map<EquipmentName, CharacterAttack>;
	toggleEquipItem(name: EquipmentName): void;
	getWieldedItems(): EquipmentName[];
	getFightStyle(): CharacterAppliedFightStyle | undefined;
};

CharacterAttack

Represents a possible attack with an weapon. It has the following methods:

export type CharacterAttack = {
  roll(): AttackResult 
	changeTestAttackAttribute(attribute: Attribute) // used for weapons that allow to change the used attribute
  // you can get the modifiers applied to the attack/damage
  modifiers: CharacterAttackModifiers
  // but also the final calculated values for them
  getTestModifiersMaxTotal(): number
	getTestModifiersTotal(): number
	getDamageModifiersMaxTotal(): number
	getDamageModifiersTotal(): number
  // these values are calculated based on the context
  // max total is the maximum value if all conditions are met
  // total is the value for current character context
}

AttackResult

Is the result of an attack roll. It has the following data:

export type AttackResult = {
	damage: {
		total: number;
		modifiers: Modifiers;
		rollResult: RollResult;
		modifiersTotal: number;
	};
	test: {
		total: number;
		modifiers: Modifiers;
		rollResult: RollResult;
		modifiersTotal: number;
	};
	isCritical: boolean;
	isFumble: boolean;
};

Content

Most content can be retrieved from a method like these:

import {Content} from 't20-sheet-builder';

const races = Content.getRaces();

Content API

  • getDeities(): Deities
  • getHeavyArmors(): HeavyArmors
  • getLightArmors(): LightArmors
  • getExoticWeapons(): ExoticWeapons
  • getFireArmWeapons(): FireArmWeapons
  • getMartialWeapons(): MartialWeapons
  • getSimpleWeapons(): SimpleWeapons
  • getOrigins(): Origins
  • getTormentaPowers(): TormentaPowers
  • getRaces(): Races
  • getRoles(): Roles
  • getArcanistPathWizardFocuses(): ArcanistPathWizardFocuses
  • getSpells(): Spells
  • getArmors(): Armors

Content names

Some names can be retrieved despite the actual class:

const skill = SkillName.acrobatics;
const equipment = EquipmentName.leatherArmor;
const spell = SpellName.bless;
const generalPower = GeneralPowerName.ironWill;
// etc

Sheet Builder

The SheetBuilder class is the main class of the library. It is used to create a character sheet.

It has the following methods:

type SheetBuilderInterface = {
	build(): CharacterSheet;
	reset(): SheetBuilder;
	addInitialEquipment(params: SheetBuilderInitialEquipmentParams): SheetBuilder;
	trainIntelligenceSkills(skills: SkillName[]): SheetBuilder;
	chooseOrigin(origin: OriginInterface): SheetBuilder;
	chooseRole(role: RoleInterface): SheetBuilder;
	chooseRace(race: RaceInterface): SheetBuilder;
};

Internally it uses an "incomplete" sheet class: BuildingSheet. Then after all mandatory choices are made, it builds a CharacterSheet.

Character Sheet

This is the actual builded sheet with all information. But it is not a character yet.

Context

The Context has information about the current situation of the character. It is used to calculate and apply ContextualModifiers to the character.

We have some predefined contexts:

  • OutOfGameContext: disable all contextual modifiers
  • InGameContext: enable all contextual modifiers for validation
  • PreviewContext: enable contextual modifiers that are not "in game" (like "location")

Races

Most races can be instantiated without parameters, but Human, Lefeu and Qareen need some input.

Human

Human receives choices for attributes and versatile choices.

Versatile choices can be either a skill or a power.

const attributes = ['charisma', 'constitution', 'dexterity'];
const versatileChoices = [
  new VersatileChoiceSkill(SkillName.acrobatics), 
  new VersatileChoicePower(new OneWeaponStyle())
]; 
const human = new Human(attributes, versatileChoices);

Lefeu

Lefeu receives choices for attributes and deformities.

const attributes = ['strength', 'constitution', 'dexterity'];
const lefeu = new Lefeu(attributes);
lefeu.addDeformities([SkillName.acrobatics, SkillName.animalHandling]);

Qareen

Qareen receives a QareenType and a spell for Mystic Tattoo.

const qareen = new Qareen('water', SpellName.arcaneArmor);