mirror of
https://github.com/RussellChamp/tpw-roller.git
synced 2026-10-27 16:12:40 +00:00
make more changes to rollers
This commit is contained in:
1 parent
08aa49d727
commit
7392647a3d
10 files changed
+462
-130
No files matched your search
Vendored
+2
-1
@@ -4,5 +4,6 @@
|
||||
140
|
||||
],
|
||||
"editor.minimap.maxColumn": 140,
|
||||
"svelte.plugin.svelte.format.config.printWidth": 140
|
||||
"svelte.plugin.svelte.format.config.printWidth": 140,
|
||||
"editor.tabSize": 2
|
||||
}
|
||||
@@ -1,105 +1,3 @@
|
||||
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
|
||||
Interactive roller for The Perilous Wilds overworld adventure supplement for Dungeon World
|
||||
|
||||
---
|
||||
|
||||
# svelte app
|
||||
|
||||
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
|
||||
|
||||
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
|
||||
|
||||
```bash
|
||||
npx degit sveltejs/template svelte-app
|
||||
cd svelte-app
|
||||
```
|
||||
|
||||
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
|
||||
|
||||
|
||||
## Get started
|
||||
|
||||
Install the dependencies...
|
||||
|
||||
```bash
|
||||
cd svelte-app
|
||||
npm install
|
||||
```
|
||||
|
||||
...then start [Rollup](https://rollupjs.org):
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
|
||||
|
||||
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
|
||||
|
||||
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
|
||||
|
||||
## Building and running in production mode
|
||||
|
||||
To create an optimised version of the app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
|
||||
|
||||
|
||||
## Single-page app mode
|
||||
|
||||
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
|
||||
|
||||
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
|
||||
|
||||
```js
|
||||
"start": "sirv public --single"
|
||||
```
|
||||
|
||||
## Using TypeScript
|
||||
|
||||
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
|
||||
|
||||
```bash
|
||||
node scripts/setupTypeScript.js
|
||||
```
|
||||
|
||||
Or remove the script via:
|
||||
|
||||
```bash
|
||||
rm scripts/setupTypeScript.js
|
||||
```
|
||||
|
||||
## Deploying to the web
|
||||
|
||||
### With [Vercel](https://vercel.com)
|
||||
|
||||
Install `vercel` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g vercel
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
cd public
|
||||
vercel deploy --name my-project
|
||||
```
|
||||
|
||||
### With [surge](https://surge.sh/)
|
||||
|
||||
Install `surge` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g surge
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
surge public my-project.surge.sh
|
||||
```
|
||||
With content from The Perilous Wilds by Jason Lutes Distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported license
|
||||
@@ -2,6 +2,8 @@
|
||||
import KingdomRoller from "./rollers/KingdomRoller.svelte";
|
||||
import RegionRoller from "./rollers/RegionRoller.svelte";
|
||||
import PlaceRoller from "./rollers/PlaceRoller.svelte";
|
||||
import FollowerRoller from "./rollers/FollowerRoller.svelte";
|
||||
import Footer from "./componenets/Footer.svelte";
|
||||
</script>
|
||||
|
||||
<main>
|
||||
@@ -11,6 +13,10 @@
|
||||
<RegionRoller />
|
||||
<hr />
|
||||
<PlaceRoller />
|
||||
<hr />
|
||||
<FollowerRoller />
|
||||
<hr />
|
||||
<Footer />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<footer>
|
||||
<div>With content from The Perilous Wilds by Jason Lutes</div>
|
||||
<div>Distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported license</div>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,125 @@
|
||||
<script lang="ts">
|
||||
import { Button, Card, CardHeader, CardTitle, CardBody, CardSubtitle, CardText, CardFooter, Container, Col, Row } from "sveltestrap";
|
||||
import * as _ from "lodash";
|
||||
import { format as formatDate } from "date-fns";
|
||||
import { rollFollower, Follower } from "./followers";
|
||||
|
||||
export let rollResults: { value: Follower; timestamp: string }[] = [];
|
||||
|
||||
function roll(event: Event) {
|
||||
let follower = rollFollower();
|
||||
|
||||
rollResults = [{ value: follower, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h2>Random Follower</h2>
|
||||
<span class="btn">
|
||||
<Button color="primary" on:click={roll}>Roll Follower</Button>
|
||||
</span>
|
||||
|
||||
{#each rollResults as result}
|
||||
<Card class="mb-3">
|
||||
<CardHeader>
|
||||
<CardTitle>{result.value.name} ({result.value.gender})</CardTitle>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardSubtitle>
|
||||
From <em>{result.value.homeSteading.homesteadName}</em> in <em>{result.value.homeSteading.kingdomName}</em>
|
||||
</CardSubtitle>
|
||||
<CardText>
|
||||
<Container>
|
||||
<Row>
|
||||
<strong>Quality:</strong>
|
||||
<p>
|
||||
They are <em>{result.value.quality.description}</em> (Quality: {result.value.quality.value}). They
|
||||
<em>{result.value.background.description}</em>.
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Tags:</strong>
|
||||
<ul>
|
||||
{#each result.value.tags as tag}
|
||||
<li>{tag.name}: {tag.description}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Moves:</strong>
|
||||
<ul>
|
||||
{#each result.value.moves as move}
|
||||
<li>{move.description}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Loyalty:</strong>
|
||||
<p>
|
||||
They have a loyalty score of {result.value.loyalty.value}{#if !!result.value.loyalty.description}
|
||||
and <em>{result.value.loyalty.description}</em>{/if}.
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Instinct:</strong>
|
||||
<p>
|
||||
When left to their own devices, they will <em>{result.value.instinct.description}</em>.
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Cost:</strong>
|
||||
<p>
|
||||
They are motivated by <em>{result.value.cost.name}</em>. They will want <em>{result.value.cost.description}</em>
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Hit Points:</strong>
|
||||
<p>
|
||||
They are <em>{result.value.hitPoints.description}</em> and have {result.value.hitPoints.value} HP.
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Armor & Shield:</strong>
|
||||
<p>
|
||||
They are equipped with <em>{result.value.armor.description}</em> ({result.value.armor.value} armor).
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Damage:</strong>
|
||||
<p>
|
||||
In a fight, they <em>{result.value.damage.description}</em> dealing <em>d{result.value.damage.value}</em> damage.
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
<strong>Load & Gear:</strong>
|
||||
<ul>
|
||||
{#each result.value.loadAndGear.gear as gear}
|
||||
<li>{gear}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</Row>
|
||||
</Container>
|
||||
</CardText>
|
||||
</CardBody>
|
||||
<CardFooter>{result.timestamp}</CardFooter>
|
||||
</Card>
|
||||
{/each}
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
text-align: left;
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
p {
|
||||
margin-left: 1em;
|
||||
}
|
||||
ul {
|
||||
margin-left: 2em;
|
||||
}
|
||||
.btn {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,45 +1,46 @@
|
||||
<script lang="ts">
|
||||
import { kingdoms } from "./data";
|
||||
import * as _ from "lodash";
|
||||
import { format as formatDate } from "date-fns";
|
||||
import { Button, Icon } from "sveltestrap";
|
||||
|
||||
export let rollResults: { value: string; timestamp: string }[] = [];
|
||||
import { kingdoms } from "./data";
|
||||
|
||||
export let rollResults: { value: string; icon: string; timestamp: string }[] = [];
|
||||
let kingdom = "arpad";
|
||||
let category = "male";
|
||||
let categories: string[];
|
||||
let values: string[];
|
||||
|
||||
function addResult(result: string) {
|
||||
rollResults = [{ value: result, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
|
||||
function addResult(value: string, category: string) {
|
||||
let icon = { male: "person-fill", female: "person", steading: "house-door-fill", mount: "bicycle" }[category] || "";
|
||||
rollResults = [{ value, icon, timestamp: formatDate(new Date(), "P kk:mm:ss") }, ...rollResults];
|
||||
}
|
||||
|
||||
function rollName(event: Event) {
|
||||
addResult(_.sample(values));
|
||||
function rollName(category: string) {
|
||||
let values = kingdoms[kingdom][category];
|
||||
|
||||
addResult(_.sample(values), category);
|
||||
}
|
||||
|
||||
$: categories = kingdoms[kingdom].categories;
|
||||
$: values = kingdoms[kingdom][category];
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h1>
|
||||
<h2>
|
||||
<select bind:value={kingdom}>
|
||||
{#each Object.keys(kingdoms) as k}
|
||||
<option value={k}>{kingdoms[k].description}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</h1>
|
||||
<h2>{kingdoms[kingdom].subtitle}</h2>
|
||||
<hr />
|
||||
</h2>
|
||||
<h3>{kingdoms[kingdom].subtitle}</h3>
|
||||
|
||||
{#each categories as category}
|
||||
<span class="btn">
|
||||
<Button color="primary" on:click={() => rollName(category)}>Roll {_.capitalize(category)}</Button>
|
||||
</span>
|
||||
{/each}
|
||||
|
||||
<select bind:value={category}>
|
||||
{#each categories as c}
|
||||
<option value={c}>{_.capitalize(c)}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<button type="button" class="btn btn-primary" on:click={rollName}>Roll {_.capitalize(category)}</button>
|
||||
{#each rollResults as result}
|
||||
<h3>{result.timestamp}: {result.value}</h3>
|
||||
<h4>{result.timestamp}: <Icon name={result.icon} /> {result.value}</h4>
|
||||
{/each}
|
||||
</main>
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h1>Random Places</h1>
|
||||
<h2>Random Places</h2>
|
||||
<button type="button" class="btn btn-primary" on:click={roll}>Roll Region</button>
|
||||
|
||||
{#each rollResults as result}
|
||||
<h3>{result.timestamp}: {result.value}</h3>
|
||||
<h4>{result.timestamp}: {result.value}</h4>
|
||||
{/each}
|
||||
</main>
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h1>Random Regions</h1>
|
||||
<h2>Random Regions</h2>
|
||||
<button type="button" class="btn btn-primary" on:click={roll}>Roll Region</button>
|
||||
|
||||
{#each rollResults as result}
|
||||
<h3>{result.timestamp}: {result.value}</h3>
|
||||
<h4>{result.timestamp}: {result.value}</h4>
|
||||
{/each}
|
||||
</main>
|
||||
|
||||
|
||||
+9
-1
@@ -1,4 +1,12 @@
|
||||
export const kingdoms = {
|
||||
export class Kingdom {
|
||||
constructor(public description: string = "", public subtitle: string = "") { };
|
||||
categories: string[];
|
||||
male: string[];
|
||||
female: string[];
|
||||
steading: string[];
|
||||
mount: string[];
|
||||
}
|
||||
export const kingdoms: { [kingdom: string]: Kingdom } = {
|
||||
arpad: {
|
||||
description: 'The Kingdom of Arpad',
|
||||
subtitle: 'Based loosely on Hungarian',
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
import { random, sample, sampleSize, times } from 'lodash';
|
||||
|
||||
import { Kingdom, kingdoms } from './data';
|
||||
|
||||
export class Follower {
|
||||
constructor(public name: string = "") { };
|
||||
gender: "male" | "female";
|
||||
quality: Quality;
|
||||
background: Background;
|
||||
tags: Tag[];
|
||||
moves: Move[];
|
||||
loyalty: Loyalty;
|
||||
instinct: Instinct;
|
||||
cost: Cost;
|
||||
hitPoints: HitPoints;
|
||||
armor: Armor;
|
||||
damage: Damage;
|
||||
loadAndGear: LoadAndGear;
|
||||
homeSteading: Homesteading;
|
||||
}
|
||||
|
||||
class Quality {
|
||||
constructor(public description: string = "", public value: number = 0, public bonusTags: number = 0) { };
|
||||
}
|
||||
|
||||
class Background {
|
||||
constructor(public description: string = "", public bonusTags: number = 0, public tags: Tag[] = [], public bonusQuality: number = 0) { };
|
||||
}
|
||||
|
||||
class Tag {
|
||||
constructor(public name: string = "", public description: string = "") { };
|
||||
}
|
||||
|
||||
class Move {
|
||||
constructor(public description: string = "") { };
|
||||
}
|
||||
|
||||
class Loyalty {
|
||||
constructor(public description: string = "", public value: number = 1) { };
|
||||
}
|
||||
|
||||
class Instinct {
|
||||
constructor(public description: string = "") { };
|
||||
}
|
||||
|
||||
class Cost {
|
||||
constructor(public name: string = "", public description: string = "") { };
|
||||
}
|
||||
|
||||
class HitPoints {
|
||||
constructor(public description: string = "", public value: number = 0) { };
|
||||
}
|
||||
|
||||
class Armor {
|
||||
constructor(public description: string = "", public value: number = 0) { };
|
||||
}
|
||||
|
||||
class Damage {
|
||||
constructor(public description: string = "", public value: number = 0) { };
|
||||
}
|
||||
|
||||
class LoadAndGear {
|
||||
constructor(public limit: number = 2, public gear: string[] = []) { };
|
||||
}
|
||||
|
||||
class Homesteading {
|
||||
constructor(public kingdomName: string = "", public homesteadName: string = "") { };
|
||||
}
|
||||
|
||||
export function rollFollower(): Follower {
|
||||
let follower = new Follower();
|
||||
let kingdom = sample(Object.keys(kingdoms));
|
||||
|
||||
follower.gender = sample(["male", "female"]);
|
||||
follower.name = sample(kingdoms[kingdom][follower.gender]);
|
||||
follower.quality = rollQuality();
|
||||
follower.background = rollBackground();
|
||||
follower.quality.value += follower.background.bonusQuality; // this is probably not the best way to do this
|
||||
follower.tags = rollTags(follower.background.tags, follower.quality.bonusTags + follower.background.bonusTags);
|
||||
follower.moves = rollMoves();
|
||||
follower.loyalty = rollLoyalty();
|
||||
follower.instinct = rollInstinct();
|
||||
follower.cost = rollCost();
|
||||
follower.hitPoints = rollHitPoints();
|
||||
follower.armor = rollArmor();
|
||||
follower.damage = rollDamage();
|
||||
follower.loadAndGear = rollLoadAndGear();
|
||||
follower.homeSteading = rollHomesteading(kingdoms[kingdom]);
|
||||
|
||||
return follower;
|
||||
}
|
||||
|
||||
function rollQuality(): Quality {
|
||||
let roll = random(1, 12);
|
||||
|
||||
if (roll <= 3) {
|
||||
return new Quality("a liability", -1, 0);
|
||||
} else if (roll <= 9) {
|
||||
return new Quality("reasonably competent", 0, 1);
|
||||
} else if (roll <= 11) {
|
||||
return new Quality("fully capable", 1, 2);
|
||||
} else if (roll <= 12) {
|
||||
return new Quality("an exception individual", 2, 4);
|
||||
}
|
||||
|
||||
return new Quality();
|
||||
}
|
||||
|
||||
function rollBackground(doingBonus: boolean = false): Background {
|
||||
let roll = random(1, doingBonus ? 11 : 12);
|
||||
if (roll <= 2) {
|
||||
return new Background("have lived a life of servitude and oppression", 0, [new Tag("Meek")]);
|
||||
} else if (roll <= 3) {
|
||||
return new Background("are past their prime", 0, [new Tag("+1 Wise")], -1); // this is probably incorrect. revisit later
|
||||
} else if (roll <= 5) {
|
||||
return new Background("have lived a life of danger", 2);
|
||||
} else if (roll <= 9) {
|
||||
return new Background("are otherwise unremarkable");
|
||||
} else if (roll <= 10) {
|
||||
return new Background("have lived a life of privilige", 1);
|
||||
} else if (roll <= 11) {
|
||||
return new Background("are a specialist", -2);
|
||||
} else if (roll <= 12) {
|
||||
let bg1 = rollBackground(true);
|
||||
let bg2 = rollBackground(true);
|
||||
|
||||
// this could result in the same bg being selected twice but that's ok for now
|
||||
return new Background(`${bg1.description} and ${bg1.description}`, bg1.bonusTags + bg2.bonusTags, [...bg1.tags, ...bg2.tags], bg1.bonusQuality + bg2.bonusQuality);
|
||||
}
|
||||
}
|
||||
|
||||
const followerTags: Tag[] = [
|
||||
{ name: "___-wise", description: "They know all about and can roll +Quality to Spout Lore about it on your behalf. Examples: Woods-wise, Sea-wise, Herb-wise" },
|
||||
{ name: "Archer", description: "They use ranged attacks (not necessarily bows) effectively and can roll +Quality to Volley on your behalf" },
|
||||
{ name: "Athletic", description: "They are good at running, jumping, climbing and the like" },
|
||||
{ name: "Beautiful", description: "They make an impression, drawing admiration and attention" },
|
||||
{ name: "Cautious", description: "They are careful and methodical; they avoid acting rashly" },
|
||||
{ name: "Connected (___)", description: "They have friends or contacts in ___, a steading or group" },
|
||||
{ name: "Cunning", description: "They are clever and observant. They can roll +Quality to Discern Realities on your behalf" },
|
||||
{ name: "Devious", description: "They are deceitful, treacherous, tricky. Just the sort you want working for you" },
|
||||
{ name: "Group", description: "They are a team, gang, or mob, with all the strengths and disadvantages that come with greater numbers" },
|
||||
{ name: "Guide (___)", description: "They knows a particular steading or region and can roll +Quality to Spout Lore, Scout Ahead, or Navigate for the party therein" },
|
||||
{ name: "Hardy", description: "They are tough, hard-working, and willing to put up with discomfort. They get +2 Load" },
|
||||
{ name: "Healer", description: "They have the knowledge and ability to provide aid to the injured and the sick. When they tend wounds with bandages or herbs & poultice, add their Quality to damage healed" },
|
||||
{ name: "Meek", description: "They accept their lowly lot, and will do degrading or unreasonable things without needing to Follow Orders" },
|
||||
{ name: "Magical", description: "They are magical by nature or training, and sensitive to the workings of magic. Use at least one of their moves to elaborate on their powers" },
|
||||
{ name: "Organized", description: "They make and follow plans well, and work well in a group. Once they agree to a plan, you do not need to Order Followers as long as the plan doesn't go south" },
|
||||
{ name: "Self-sufficient", description: "They can live off the land and roll +Quality to Forage" },
|
||||
{ name: "Stealthy", description: "They can avoid detection and often get the drop on foes" },
|
||||
{ name: "Warrior", description: "They take +1 to their damage die roll, and you don't need to Order Follower to get them to fight (as long as the opposition is not terrifying or overwhelming)" },
|
||||
];
|
||||
|
||||
|
||||
function rollTags(backgroundTags: Tag[], tagsCount: number): Tag[] {
|
||||
if (tagsCount == 0) {
|
||||
return backgroundTags;
|
||||
} else {
|
||||
// return one "_-wise", any tags added from the background, and then additional tags
|
||||
return [followerTags[0], ...backgroundTags, ...sampleSize(followerTags, tagsCount - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
function rollMoves(): Move[] {
|
||||
// This is really up to the player and GM to determine
|
||||
return [
|
||||
new Move("1-3 moves determined by the player and GM"),
|
||||
new Move("1-3 moves determined by the player and GM"),
|
||||
new Move("1-3 moves determined by the player and GM")
|
||||
];
|
||||
}
|
||||
|
||||
function rollLoyalty(): Loyalty {
|
||||
// Up to GM
|
||||
return new Loyalty();
|
||||
}
|
||||
|
||||
function rollInstinct(): Instinct {
|
||||
let roll = random(1, 12);
|
||||
if (roll <= 1) {
|
||||
return new Instinct("loot, pillage, and burn");
|
||||
} else if (roll <= 2) {
|
||||
return new Instinct("hold a grudge and seek payback");
|
||||
} else if (roll <= 3) {
|
||||
return new Instinct("question leadership or authority");
|
||||
} else if (roll <= 5) {
|
||||
return new Instinct("lord over others");
|
||||
} else if (roll <= 7) {
|
||||
return new Instinct("act impulsively");
|
||||
} else if (roll <= 9) {
|
||||
return new Instinct("give in to temptation");
|
||||
} else if (roll <= 11) {
|
||||
return new Instinct("slack off");
|
||||
} else if (roll <= 12) {
|
||||
return new Instinct("avoid danger or punishment");
|
||||
}
|
||||
|
||||
return new Instinct();
|
||||
}
|
||||
|
||||
function rollCost(): Cost {
|
||||
let roll = random(1, 12);
|
||||
if (roll <= 1) {
|
||||
return new Cost("debauchery", "food, drink, gambling, sex, and mischief. The higher their Loyalty, the more extreme the cost.");
|
||||
} else if (roll <= 2) {
|
||||
return new Cost("vengeance", "payback against those that have wronged them or their loved ones. The higher their Quality, the more direct and tangible the payback they require.");
|
||||
} else if (roll <= 5) {
|
||||
return new Cost("lucre", "coin appropriate to their steading's Prosperity; highly skilled followers might demand more coin.");
|
||||
} else if (roll <= 7) {
|
||||
return new Cost("renown", "public recognition for their deeds and skills. The higher their Quality, the larger the audience required.");
|
||||
} else if (roll <= 9) {
|
||||
return new Cost("glory", "to defeat a worthy foe in battle. The higher their Quality, the more worthy the foe must be. Possibly limited to certain enemy types (demons, barbarians, etc.).");
|
||||
} else if (roll <= 10) {
|
||||
return new Cost("affection", "kind words and deeds, quality time and attention. The more extreme their Loyalty, the more affection they require.");
|
||||
} else if (roll <= 11) {
|
||||
return new Cost("knowledge", "secrets, mysteries, and wonders only found by exploring the wider world.");
|
||||
} else if (roll <= 12) {
|
||||
return new Cost("good", "suffering alleviated, innocents defended, wrongs righted. The higher their Quality, the greater the good required.");
|
||||
}
|
||||
|
||||
return new Cost();
|
||||
}
|
||||
|
||||
function rollHitPoints(): HitPoints {
|
||||
let roll = random(1, 12);
|
||||
if (roll <= 3) {
|
||||
return new HitPoints(sample(["weak", "frail", "soft"]), 3);
|
||||
} else if (roll <= 9) {
|
||||
return new HitPoints("able-bodied", 6);
|
||||
} else if (roll <= 12) {
|
||||
return new HitPoints(sample(["tough", "strong", "hard"]), 9);
|
||||
}
|
||||
|
||||
return new HitPoints();
|
||||
}
|
||||
|
||||
const armors: Armor[] = [
|
||||
{ description: "no armor", value: 0 },
|
||||
{ description: "hide armor", value: 1 },
|
||||
{ description: "leather armor", value: 1 },
|
||||
{ description: "scale mail", value: 2 },
|
||||
{ description: "chain mail", value: 2 },
|
||||
{ description: "plate mail", value: 3 },
|
||||
];
|
||||
|
||||
function rollArmor(): Armor {
|
||||
let armor = sample(armors);
|
||||
if (random(1, 2) == 2) {
|
||||
armor.description += " and a shield";
|
||||
armor.value += 1;
|
||||
}
|
||||
|
||||
return armor;
|
||||
}
|
||||
|
||||
|
||||
function rollDamage(): Damage {
|
||||
let roll = random(1, 12);
|
||||
if (roll <= 4) {
|
||||
return new Damage("are not very dangerous", 4);
|
||||
} else if (roll <= 10) {
|
||||
return new Damage("can defend themselves", 6);
|
||||
} else if (roll <= 12) {
|
||||
return new Damage("are a veteran fighter", 8);
|
||||
}
|
||||
|
||||
return new Damage();
|
||||
}
|
||||
|
||||
function rollLoadAndGear(limit: number = 2): LoadAndGear {
|
||||
// Equip them with whatever is appropriate for the circumstances and prosperity of their home steading
|
||||
let load = new LoadAndGear(limit, ["Tools of their trade"]);
|
||||
times(limit, () => load.gear.push("Appropriate equipment for the circumstance and homesteading"));
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
function rollHomesteading(kingdom: Kingdom): Homesteading {
|
||||
// I dunno what this should be but the load&gear section mentioned homesteading
|
||||
|
||||
return new Homesteading(kingdom.description, sample(kingdom.steading));
|
||||
}
|
||||
Reference in new issue
Block a user