{"id":21893304,"url":"https://github.com/jhstoops/ttrpg-tools","last_synced_at":"2025-04-15T15:22:40.528Z","repository":{"id":41422443,"uuid":"500559839","full_name":"JHStoops/ttrpg-tools","owner":"JHStoops","description":"API for generating random dice rolls, NPCs, towns, names, etc. for TTRPG campaigns.","archived":false,"fork":false,"pushed_at":"2024-03-05T16:05:40.000Z","size":909,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-23T01:19:00.607Z","etag":null,"topics":["dice-rolls","dnd","dnd-npc-generator","dnd-tools","javascript","json","random-generation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JHStoops.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-06-06T19:03:52.000Z","updated_at":"2024-08-06T18:58:14.000Z","dependencies_parsed_at":"2024-03-05T17:29:51.484Z","dependency_job_id":"d2ee5e90-68a6-4e18-bdb5-e497c65f91e0","html_url":"https://github.com/JHStoops/ttrpg-tools","commit_stats":{"total_commits":61,"total_committers":3,"mean_commits":"20.333333333333332","dds":0.06557377049180324,"last_synced_commit":"b1d4eeb173817edb42a7177369752926230faf72"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHStoops%2Fttrpg-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHStoops%2Fttrpg-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHStoops%2Fttrpg-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JHStoops%2Fttrpg-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JHStoops","download_url":"https://codeload.github.com/JHStoops/ttrpg-tools/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249095350,"owners_count":21211908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dice-rolls","dnd","dnd-npc-generator","dnd-tools","javascript","json","random-generation"],"created_at":"2024-11-28T13:13:21.312Z","updated_at":"2025-04-15T15:22:40.510Z","avatar_url":"https://github.com/JHStoops.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ttrpg-tools\n\n[![Npm package version](https://badgen.net/npm/v/ttrpg-tools)](https://npmjs.com/package/ttrpg-tools)\n[![Npm package total downloads](https://badgen.net/npm/dt/ttrpg-tools)](https://npmjs.com/package/ttrpg-tools)\n[![GitHub issues](https://img.shields.io/github/issues/jhstoops/ttrpg-tools.svg)](https://GitHub.com/jhstoops/ttrpg-tools/issues/)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/jhstoops/ttrpg-tools/graphs/commit-activity)\n[![Maintainer](https://img.shields.io/badge/maintainer-JHStoops-blue)](https://GitHub.com/jhstoops)\n[![Twitter](https://badgen.net/badge/icon/twitter?icon=twitter\u0026label)](https://twitter.com/jhstoops)\n[![Maintainability](https://api.codeclimate.com/v1/badges/c2c180192985adf4db7c/maintainability)](https://codeclimate.com/github/JHStoops/ttrpg-tools/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/c2c180192985adf4db7c/test_coverage)](https://codeclimate.com/github/JHStoops/ttrpg-tools/test_coverage)\n\nLibrary for generating random dice rolls, NPCs, towns, names, etc. for TTRPG campaigns.\n\n1. [How To Import](#how-to-import)\n2. [API](#api)\n    - [Standard Dice](#standard-dice)\n    - [Custom Dice](#custom-dice)\n    - [Coin Flips](#coin-flips)\n    - [Name Generators](#name-generators)\n    - [NPC Generator](#npc-generator)\n    - [Town Generator](#town-generator)\n3. [Customize Data](#customize-data)\n    - [Classes, Languages, and Occupations](#classes-languages-and-occupations)\n    - [Races](#races)\n    - [NPC Name Parts](#npc-name-parts)\n    - [Town Name Parts](#town-name-parts)\n4. [Supported Races](#supported-races)\n5. [Supported Classes](#supported-classes)\n6. [Contribute](#contribute)\n7. [Contact Information](#contact-information)\n\n## How to Import\n\nES Module Default Export\n\n```js\nimport ttrpgTools from 'ttrpg-tools'\n\nconst {\n  coin, d4, d6, d8, d10, d12, d20, d100, diceRoll, data,\n  generateNpcName, generateTownName, generateNpc, generateTown\n} = ttrpgTools\n```\n\nES Module Named Exports\n\n```js\nimport {\n  coin, d4, d6, d8, d10, d12, d20, d100, diceRoll, data,\n  generateNpcName, generateTownName, generateNpc, generateTown\n}  from 'ttrpg-tools'\n```\n\n## API\n\n### Standard Dice\n\n| Parameter          | Type    | Default | Description |\n| ---------          | ----    | ------- | ----------- |\n| dieCount           | Number  | 1       | How many dice to roll. |\n| verbose            | Boolean | false   | Whether to return an object with individual roll results and total. |\n| modifier            | Number  | 0       | Add modifier to roll. |\n| withAdvantage      | Boolean | false   | Whether to roll with advantage. |\n| withDisadvantage   | Boolean | false   | Whether to roll with disadvantage. |\n\n```js\nimport { d4, d6, d8, d10, d12, d20, d100 } from 'ttrpg-tools'\n\nconst d4Roll = d4() // Defaults to a single die\nconst d6RollThreeDice = d6(3)\nconst d8RollFiveDiceVerbose = d8(5, true)\nconst d10RollWithModifier = d10(1, false, 2)\nconst d12RollWithAdvantage = d12(1, false, 0, true)\nconst d20RollWithDisadvantage = d20(1, false, 0, false, true)\nconst d100RollWithClashingAdvantage = d100(1, false, 0, true, true) // First roll is used\n```\n\n```js\n// d4 roll - single die\n{ \"4\": 3 }\n\n// d6 roll - three dice\n{ \"6\": 15 }\n\n// d8 roll - five dice, verbose\n{ \"8\": {\n    \"rolls\": [3, 7, 4, 8, 6],\n    \"total\": 28\n  }\n}\n\n// d10 roll - single die\n{ \"10\": 8 }\n\n// d12 roll - single die\n{ \"12\": 5 }\n\n// d20 roll - single die\n{ \"20\": 16 }\n\n// d100 roll - single die\n{ \"100\": 42 }\n```\n\n\u003cbr /\u003e\n\n### Custom Dice\n\n| Parameter          | Type    | Default | Description |\n| --------           | ----    | ------- | ----------- |\n| dice               | Object  |         | (Required) How many coins to flip. |\n| asNumeric          | Boolean | false   | Whether to return an object with 1 and 0 instead of \"heads\" and \"tails\", respectively. |\n| modifier            | Number  | 0       | Add modifier to roll. |\n| withAdvantage      | Boolean | false   | Whether to roll with advantage. |\n| withDisadvantage   | Boolean | false   | Whether to roll with disadvantage. |\n\n```js\nimport { diceRoll } from 'ttrpg-tools'\n\nconst rollManyDieTypes = diceroll({\n  \"4\": 2,\n  \"6\": 1,\n  \"8\": 2,\n  \"10\": 3,\n  \"12\": 1,\n  \"42\": 1\n}, true)\n```\n\n```js\n// diceRoll with multiple die types\n{\n  \"4\": {\n    \"rolls\": [2, 1],\n    \"total\": 3\n  },\n  \"6\": {\n    \"rolls\": [5],\n    \"total\": 5\n  },\n  \"8\": {\n    \"rolls\": [5, 7],\n    \"total\": 12\n  },\n  \"10\": {\n    \"rolls\": [10, 2, 6],\n    \"total\": 18\n  },\n  \"12\": {\n    \"rolls\": [9],\n    \"total\": 9\n  },\n  // NOTE: You can also roll custom die types\n  \"42\": {\n    \"rolls\": [42],\n    \"total\": 42 // The Meaning of life, the universe, and everything!\n  }\n}\n```\n\n\u003cbr /\u003e\n\n### Coin Flips\n\n| Parameter          | Type    | Default | Description |\n| --------           | ----    | ------- | ----------- |\n| coinFlips          | Number  | 1       | Specify which die types and their counts to be rolled. |\n| verbose            | Boolean | false   | Whether to return an object with individual roll results and total. |\n| modifier            | Number  | 0       | Add modifier to coin toss. |\n| withAdvantage      | Boolean | false   | Whether to toss coin with advantage. |\n| withDisadvantage   | Boolean | false   | Whether to toss coin with disadvantage. |\n\n```js\nimport { coin } from 'ttrpg-tools'\n\nconst flippedCoin = coin() // Defaults to one coin flip\nconst flippedCoins = coin(3)\nconst flippedCoinsNumericResults = coin(3, true) // Replace \"heads\" and \"tails\" with 1 and 0 respectively.\n```\n\n```js\n// flippedCoin\n{ \"heads\": 1,  \"tails\": 0 }\n\n// flippedCoins\n{ \"heads\": 2,  \"tails\": 1 }\n\n// flippedCoins with numeric results\n{ \"1\": 2,  \"0\": 1 }\n```\n\n\u003cbr /\u003e\n\n### Name Generators\n\n| Parameter      | Type    | Default | Description |\n| ---------      | ----    | ------- | ----------- |\n| *generateNpcName*\n| sex            | String  |         | (Required) The sex of the NPC: 'male' or 'female'. |\n|\n| *generateTownName*\n| withDescriptor     | Boolean | false   | Whether to guarantee a descriptor name part. If false, there's only a 20% chance to add it. |\n| withPostDescriptor | Boolean | false   | Whether to guarantee a postDescriptor name part. If false, there's only a 20% chance to add it. |\n| usePremade         | Boolean | false   | Whether to use a premade town name instead of a generated name. |\n\n```js\nimport { generateNpcName, generateTownName } from 'ttrpg-tools'\n\nconst npcName = generateNpcName('male')\nconst townName = generateTownName()\nconst townNameWithDescriptor = generateTownName(true)\n```\n\n```js\n// Randomly generated NPC name\n\"Jon Heder\"\n\n// Randomly generated town name\n\"Spruceport\"\n\n// Randomly generated town name with guaranteed descriptor name part\n\"Little Redwoods\"\n```\n\n\u003cbr /\u003e\n\n### NPC Generator\n\nThe parameters are passed in as a single object, with the property names defined below.\n\n| Property       | Type           | Default | Description |\n| --------       | ----           | ------- | ----------- |\n| familyName     | String         |         | Specify NPC's family/last name. |\n| givenName      | String         |         | Specify NPC's given/first name. |\n| homeTown       | String         |         | Specify name of NPC's hometown. |\n| languages      | Array[Strings] |         | Specify the languages spoken by the NPC. |\n| npcClass       | String         |         | Specify NPC's class. (Can deviate from `Supported Classes` section below.) |\n| occupation     | String         |         | Specify NPC's occupation. |\n| race           | Array[Strings] |         | Specify the NPC's race. (Must match races from `Supported Races` section below.) |\n| randomizeClass | Boolean        |         | Whether to ensure the NPC has a class. If false, then NPC has 10% of having a class. |\n| sex            | String         |         | Specify NPC's sex. |\n\n```js\nimport { generateNpc } from 'ttrpg-tools'\n\nconst npc = generateNpc()\nconst npcWithSpecifiedName = generateNpc({ givenName: 'Tina', familyName: 'Fey' })\n```\n\n```js\n{\n  // NPC's name\n  \"fullName\": \"Tina Fey\",\n  \"givenName\": \"Tina\",\n  \"familyName\": \"Fey\",\n\n  // NPC's sex\n  \"sex\": \"female\",\n\n  // Randomized town name for NPC's hometown\n  \"homeTown\": \"New York City\",\n\n  // NPC's occupation\n  \"occupation\": \"Actor\",\n\n  // NPC's class. Unless specified or `randomizeClass` flag is passed, NPCs will only have a class 10% of the time.\n  \"class\": \"Bard\",\n\n  // Languages spoken by the NPC\n  \"languages\": [ \"Common\" ],\n\n  // NPC's race\n  \"race\": {\n    \"name\": \"Human\",\n    \"avgAgeOfDeath\": 100,\n    \"avgHeight\": 6,\n    \"avgWeight\": 180,\n    \"size\": \"medium\",\n    \"baseClimbSpeed\": 15,\n    \"baseFlightSpeed\": 0,\n    \"baseSwimSpeed\": 15,\n    \"baseWalkSpeed\": 30,\n    \"languages\": [ \"Common\" ]\n  }\n}\n```\n\n\u003cbr /\u003e\n\n### Town Generator\n\nThe parameters are passed in as a single object, with the property names defined below.\n\n| Property | Type           | Description |\n| -------- | ----           | ----------- |\n| name     | String         | Specify the town name. |\n| races    | Array[Strings] | Specify the prevalent races in the town. Must match races from `Supported Races` section below. |\n| size     | String         | Specify the town population size ranges.  xs: 5-20, sm: 21-50, md: 51-100, lg: 101-250, xl: 251-1000 |\n\n```js\nimport { generateTown } from 'ttrpg-tools'\n\nconst town = generateTown()\nconst townWithSpecifiedName = generateTown({ name: 'Feywild City' })\n```\n\n```js\n{\n  // Town name\n  \"name\": \"Oakport\",\n\n  // Population size\n  \"size\": 124,\n\n  // 1-5 prevalent races in the town.\n  \"races\": [\n    {\n      \"name\": \"Halfling\",\n      \"avgAgeOfDeath\": 250,\n      \"avgHeight\": 3,\n      \"avgWeight\": 40,\n      \"size\": \"small\",\n      \"baseClimbSpeed\": 12,\n      \"baseFlightSpeed\": 0,\n      \"baseSwimSpeed\": 12,\n      \"baseWalkSpeed\": 25,\n      \"languages\": [ \"Common\",  \"Halfling\" ]\n    },\n    ...\n  ],\n\n  // Languages spoken in the town\n  \"languages\": [ \"Common\", \"Halfling\" ],\n\n  // Is one of the prevalent races, speaks all town's languages.\n  \"leader\": randomizedNpcObject\n}\n```\n\n\u003cbr /\u003e\n\n## Customize Data\n\nThis library is intended to continually grow its data to provide the best procedurally generative experience possible, but may not grow as fast as you would like. In an attempt to roll high initiative in that combat, I introduce to you the ability to customize the data!\n\nThe data methods are made available via the `data` named export.\n\n```js\nimport { data } from 'ttrpg-tools'\n```\n\n### Classes, Languages, and Occupations\n\nClasses, Languages, and Occupations data are all arrays of strings. The examples below could be appllied to any of these three data sets.\n\n```js\n// Get the available list of classes (customized or not)\ndata.classes.get()\n\n// Get the list of classes provided originally by ttrpg-tools\n// It can be useful to use this if you want to use most classes, but filter out a few for when you call the customize method.\ndata.classes.getOriginal()\n\n// Customize the available classes (Append to existing classes)\n// Note: This will append your list of new classes to the end of the available list.\n// Note: Duplicates are removed.\ndata.classes.customize(['Couch Potato'])\n\n// Customize the available classes (Replace existing classes)\n// Note: This will replace the existing classes with the list of classes you provide here.\ndata.classes.customize(['Couch Potato'], true)\n\n// Reset to factory settings\ndata.classes.reset()\n```\n\n\u003cbr /\u003e\n\n### Races\n\nRaces data is stored in this format:\n\n```js\n{\n  \"Human\": {\n    \"name\": \"Human\",\n    \"avgAgeOfDeath\": 100,\n    \"avgHeight\": 6.0,\n    \"avgWeight\": 180.0,\n    \"size\": \"medium\",\n    \"baseClimbSpeed\": 15,\n    \"baseFlightSpeed\": 0,\n    \"baseSwimSpeed\": 15,\n    \"baseWalkSpeed\": 30,\n    \"languages\": [\n      \"Common\"\n    ]\n  }\n}\n```\n\nNote: Any missing properties will be filled in with the Human's values.\nNote: You can add custom properties to a race.\nNote: You can override a race by using the same key name with a new race object.\n\n```js\n// Get the available races (customized or not)\ndata.races.get()\n\n// Get the races data originally provided by ttrpg-tools\ndata.races.getOriginal()\n\n// Customize the available races (Append to existing races)\n// Note: The remaining expected properties will be filled in using Human values.\ndata.races.customize({\n  'Couch Potato': {\n    name: 'Couch Potato', // Required\n    avgAgeOfDeath: 30,\n    size: 'large',\n    customPropertyThatIWouldLikeToInclude: 42\n  }\n })\n\n// Customize the available races (Replace existing races)\n// Note: This will replace all races with the races provided.\ndata.races.customize({\n  'Couch Potato': {\n    name: 'Couch Potato', // Required\n    avgAgeOfDeath: 30,\n    size: 'large',\n    customPropertyThatIWouldLikeToInclude: 42\n  }\n }, true)\n\n// Reset to factory settings\ndata.races.reset()\n```\n\n\u003cbr /\u003e\n\n### NPC Name Parts\n\nNPC Name Parts data is stored in this format:\n\n```js\n{\n  givenNames: {\n    female: ['Brienna'],\n    male: ['Bryce'],\n  },\n  familyNames: ['Lastnamington']\n}\n```\n\nNote: You do not have to customize all name parts arrays when you call the `customize` method. For example, you could only pass in `{ givenNames: { male: ['Brad', 'Chad', 'Lad']}}` to just affect the male givenNames.\n\n```js\n// Get the available NPC name parts (customized or not)\ndata.npcNames.get()\n\n// Get the NPC name parts data originally provided by ttrpg-tools\ndata.npcNames.getOriginal()\n\n// Customize the available NPC name parts (Append to existing name parts)\n// Note: This example adds the female and male given names to the available name parts data, and it leaves the familyNames as it is.\ndata.npcNames.customize({\n  givenNames: {\n    female: [ 'Lynn', 'Patricia', 'Gertrude' ],\n    male: [ 'Carl', 'Buster' ]\n  }\n})\n\n// Customize the available NPC name parts (Replace existing NPC name parts)\n// Note: This will replace all femilyNames with the provided list, but the male and female given names will be left alone.\ndata.npcNames.customize({ familyNames: ['Owlbearslayer'] }, true)\n\n// Reset to factory settings\ndata.npcNames.reset()\n```\n\n\u003cbr /\u003e\n\n### Town Name Parts\n\nTown Name Parts data is stored in this format:\n\n```js\n{\n  descriptors: ['Little', 'Higher', 'Grand']\n  prefixes: ['Red', 'Asp']\n  suffixes: ['woods', 'river', ' Town']\n  postDescriptors: ['in the East', 'City', 'Creek'],\n  premades: ['Rivendell', 'Hobbiton', 'Gondor']\n}\n```\n\nNote: You do not have to customize all name parts arrays when you call the `customize` method. For example, you could only pass in `{ descriptors: ['Brad', 'Chad', 'Lad'] }` to just affect the male descriptor name parts.\n\n```js\n// Get the available town name parts (customized or not)\ndata.townNames.get()\n\n// Get the NPC name parts data originally provided by ttrpg-tools\ndata.townNames.getOriginal()\n\n// Customize the available town name parts (Append to existing name parts)\n// Note: This example adds the descriptor, prefix, and postDescriptor name parts to the currently available town name parts data.\ndata.townNames.customize({ descriptors: ['Lower'], prefixes: ['Green', 'Oak'], postDescriptors: ['Landing'] })\n\n// Customize the available town name parts (Replace existing town name parts)\n// Note: This will replace suffix name parts and premades data with the provided lists of suffixes and premades.\ndata.townNames.customize({ suffixes: ['Owlbear', 'Mound'], premades: ['Mordor']}, true)\n\n// Reset to factory settings\ndata.townNames.reset()\n```\n\n\u003cbr /\u003e\n\n## Supported Races\n\nCurrently, the only races supported are form D\u0026D 5e.\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee full list of supported races\u003c/summary\u003e\n\n- Aarakocra\n- Aasimar\n- Air Genasi\n- Bugbear\n- Centaur\n- Changeling\n- Deep Gnome\n- Dragonborn\n- Duergar\n- Dwarf\n- Earth Genasi\n- Eladrin\n- Elf\n- Fairy\n- Firbolg\n- Fire Genasi\n- Githyanki\n- Githzerai\n- Gnome\n- Goblin\n- Goliath\n- Grung\n- Half-Elf\n- Halfling\n- Half-Orc\n- Harengon\n- Hobgoblin\n- Human\n- Kalashtar\n- Kenku\n- Kobold\n- Leonin\n- Lizardfolk\n- Locathah\n- Loxodon\n- Minotaur\n- Orc\n- Owlin\n- Satyr\n- Sea Elf\n- Shadar-kai\n- Shifter\n- Tabaxi\n- Tiefling\n- Tortle\n- Triton\n- Vedalken\n- Verdan\n- Warforged\n- Water Genasi\n- Yuan-ti\n\n\u003c/details\u003e\n\u003cbr/\u003e\n\n## Supported Classes\n\nCurrently, the only classes supported are the basic D\u0026D 5e class. More will be added.\n\n\u003cdetails\u003e\n  \u003csummary\u003eSee full list of classes\u003c/summary\u003e\n\n- Artificer\n- Barbarian\n- Bard\n- Cleric\n- Druid\n- Fighter\n- Monk\n- Paladin\n- Ranger\n- Rogue\n- Sorcerer\n- Warlock\n- Wizard\n\n\u003c/details\u003e\n\u003cbr/\u003e\n\n## Contribute\n\nI welcome any help you are willing to provide! Simply add an \"Issue\" in the [Issues section in Github](https://github.com/JHStoops/ttrpg-tools/issues) or fork the [project](https://github.com/JHStoops/ttrpg-tools) and create a pull request. Feel free to send me an email or tweet if you want to have a conversation.\n\nThank you for you support!\n\n\u003cbr/\u003e\n\n## Contact Information\n\nEmail: Joseph.H.Stoops@Gmail.com\n\nTwitter: [@JHStoops](https://twitter.com/JHStoops)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhstoops%2Fttrpg-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjhstoops%2Fttrpg-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhstoops%2Fttrpg-tools/lists"}