diff --git a/acks/templates/base.html b/acks/templates/base.html index 1617218..ee26bd3 100644 --- a/acks/templates/base.html +++ b/acks/templates/base.html @@ -7,6 +7,7 @@ {% set judge_bar = [ ('/npc/party', 'npcparty', 'Generate Party', false), ('/npc/single', 'npcsingle', 'Generate NPC', false), + ('/wandering_monster', 'wandering', 'Wandering Monster', false), ('/lairs', 'lairs', 'Lairs', false), ('http://autarch.co/treasure', 'treasure', 'Treasure', true), ('/quest/list', 'questlist', 'Quests', false), @@ -34,11 +35,11 @@ - + - - + + - - - -

Adventurer Conqueror King System

- -

Rules for Roleplaying in a World of Swords, Sorcery, and Strongholds

- -

Table of Contents

- -

Chapter 1 Introduction

- -

Chapter 2 Characters

- -

Chapter 3 Equipment

- -

Chapter 4 Proficiencies

- -

Chapter 5 Spells

- -

Chapter 6 Adventures

- -

Chapter 7 Campaigns

- -

Chapter 8 Monsters

- -

Chapter 9 Treasure

- -

Chapter 10 Secrets

- -

OGL

- -

Detailed Table of Contents

- -

Chapter 1 Introduction

- - - -

Chapter 2 Characters

- - - -

Chapter 3 Equipment

- - - -

Chapter 4 Proficiencies

- - - -

Chapter 5 Spells

- - - -

Chapter 6 Adventures

- - - -

Chapter 7 Campaigns

- - - -

Chapter 8 Monsters

- - - -

Chapter 9 Treasure

- - - -

Chapter 10 Secrets

- - - -

Open Game License

- -
- - - - - + +{% endblock %} diff --git a/acks/templates/wandering_monster.html b/acks/templates/wandering_monster.html new file mode 100644 index 0000000..ff9da67 --- /dev/null +++ b/acks/templates/wandering_monster.html @@ -0,0 +1,381 @@ +{% extends "base.html" %} +{% set active_page = "wandering_monster" %} + +{% block title %}Wandering Monsters{% endblock %} +{% block content %} +
+

Adventurer Conqueror KingWandering Monsters

+
+ +
+
+ Where is the party? + + +
+ +
+
+
+ +
+
+

Dungeon Monster

+

Configure

+ +
+ Frequency: When in a dungeon, the Judge should make an encounter throw every 2 turns. A throw of 6+ on a 1d6 indicates a wandering monster is encountered. +
+
+
+ + +
+ +
+ +
+
+
+
 
+
+
+
+

+ +
+
Quantity:
+
Reaction:
+
Dungeon Level:
+ +
Distance:
+
Surprise:
+
Roll/Adjust:
+
Monster Table:
+
+
+
+
+
+ +
+
+ +
+
+

Wilderness Monster

+

Configure

+ +
+ Frequency: When the characters in the wilderness, the Judge should make an encounter throw once per day if they are stationary or in settled terrain. Otherwise, the Judge should make an encounter throw each time the adventurers enter a new 6-mile hex. +
+
+
+ + +
+ +
+ +
+
+
+
+   +
+
+
+
+

+ +
+
Surprise:
+
Reaction:
+
Monster Table:
+
Terrain Type:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TerrainEncounter Distance (yards)
Badlands2d6x10
Desert4d6x10
Fields, Fallow4d6x10
Fields, Ripe5d10
Fields, Wild3d6x5
Forest, Heavy or Jungle5d4
Forest, Light5d8
Marsh8d10
Mountains4d6x10
Plains5d20x10
+
+
+
+
+
+
+ +
+ +
+

Roll Modifiers

+
+
+
Encounter:
+
Adjustment to chance of encountering a wandering monster at all.
+
+
+
Surprise:
+
Adjustments to surprise for vigilance, lighting, noises, and any other bonuses/penalties.
+
+
+
Reaction:
+
Charisma modifier of "lead" character, other situational bonuses/penalties.
+
+
+
+
+{% endblock %} + +{% block head %} + +{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/acks/views.py b/acks/views.py index 5452c01..f235558 100644 --- a/acks/views.py +++ b/acks/views.py @@ -1,8 +1,10 @@ from pathlib import Path -from flask import Blueprint, render_template, url_for, redirect +from flask import Blueprint, render_template, url_for, redirect, request from flask_basicauth import BasicAuth +from . import wandering_monster + class PlayerAuth(BasicAuth): @@ -79,3 +81,17 @@ def token_gallery(): categories = [(k, v) for k, v in tokens.items()] categories = sorted(categories, key=lambda category: len(category[1]), reverse=True) return render_template('player_tokens.html', categories=categories, data=tokens) + +@default_views.route('/wandering_monster') +def view_wandering_monster(): + return render_template('wandering_monster.html') + +@default_views.route('/wandering_monster/generate', methods=['POST']) +def generate_wandering_monster(): + data = request.get_json() + if data['type'] == "dungeon": + monster = wandering_monster.generate_dungeon_monster(data['check_mod'], data['dungeon_level'], data['reaction_mod'], data['surprise_mod']) + if data['type'] == "wilderness": + monster = wandering_monster.generate_wilderness_monster(data['check_mod'], data['terrain_type'], data['reaction_mod'], data['surprise_mod']) + return monster + diff --git a/acks/wandering_monster.py b/acks/wandering_monster.py new file mode 100644 index 0000000..b20b955 --- /dev/null +++ b/acks/wandering_monster.py @@ -0,0 +1,267 @@ +import math +import random + +import dice + + + +DUNGEON_WANDERING_MONSTER_LEVEL = { + # 1 2 3 4 5 6 7 8 9 0 1 2 + 1: [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3], + 2: [1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4], + 3: [1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5], + 4: [2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 6], + 5: [3, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6], + 6: [4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6], +} + +DUNGEON_RANDOM_MONSTERS_BY_LEVEL = { + 1: [ + ("Goblin", "2d4"), ("Kobold", "4d4"), ("Morlock", "1d12"), + ("Orc", "2d4"), ("Beetle, Fire", "1d8"), ("Centipede, Giant", "2d4"), + ("Ferret, Giant", "1d8"), ("Rat, Giant", "3d6"), ("Men, Brigand", "2d4"), + ("Skeleton", "3d4"), ("Stirge", "1d10"), ("NPC Party (Lvl 1)", "1d4+2") + ], + 2: [ + ("Gnoll", "1d6"), ("Hobgoblin", "1d6"), ("Lizardman", "2d4"), + ("Troglodyte", "1d8"), ("Bat, Giant", "1d10"), + ("Fly, Giant Carnivorous", "1d8"), ("Locust, Cavern", "1d10"), + ("Snake, Pit Viper", "1d8"), ("Ghoul", "1d6"), ("Men, Berserker", "1d6"), + ("Zombie", "2d4"), ("NPC Party (Lvl 2)", "1d4+2") + ], + 3: [ + ("Bugbear", "2d4"), ("Lycanthrope, Werewolf", "1d6"), ("Ogre", "1d6"), + ("Throghrin", "1d6"), ("Ant, Giant", "2d4"), ("Lizard, Drago", "1d3"), + ("Scorpion, Giant", "1d6"), ("Wolf, Dire", "1d4"), + ("Carcass Scavenger", "1d3"), ("Gargoyle", "1d6"), ("Wight", "1d6"), + ("NPC Party (Lvl 4)", "1d4+2") + ], + 4: [ + ("Lycanthrope, Werebear", "1d4"), ("Lycanthrope, Weretiger", "1d4"), + ("Minotaur", "1d6"), ("Boar, Giant", "1d4"), ("Owl Bear", "1d4"), + ("Phase Tiger", "1d4"), ("Rhagodessa, Giant", "1d4"), + ("Snake, Giant Python", "1d4"), ("Cockatrice", "1d4"), ("Medusa", "1d3"), + ("Wraith", "1d4"), ("NPC Party (Lvl 5)", "1d4+2") + ], + 5: [ + ("Ettin", "1d2"), ("Giant, Hill", "1d4"), ("Giant, Stone", "1d2"), + ("Troll", "1d8"), ("Ankheg", "1d6"), ("Caecilian", "1d3"), + ("Basilisk", "1d6"), ("Hell Hound, Greater", "2d4"), + ("Salamander, Flame", "1d4+1"), ("Spectre", "1d4"), ("Wyvern", "1d2"), + ("NPC Party (Lvl 8)", "1d4+3") + ], + 6: [ + ("Cyclops", "1`"), ("Giant, Cloud", "1d2"), ("Purple Worm", "1d2"), + ("Demon Boar", "1d4"), ("Dragon (20 HD)", "1"), ("Hydra (12 HD)", "1"), + ("Gorgon", "1d2"), ("Lamia", "1"), ("Remorhaz (15 HD)", "1"), + ("Skittering Maw", "1"), ("Vampire (9 HD)", "1d4"), + ("NPC Party (Lvl 14)", "1d4+3") + ] +} + +WILDERNESS_TYPE_BY_ID = { + 1: ["Clear", "Grass", "Scrub"], + 2: ["Woods"], + 3: ["River"], + 4: ["Swamp"], + 5: ["Mountains", "Hills"], + 6: ["Barren", "Desert"], + 7: ["Inhabited"], + 8: ["City"], + 9: ["Ocean"], + 10: ["Jungle"], +} + +WILDERNESS_FREQUENCY_BY_TERRAIN = { + 1: 6, # Clear, Grass, Scrub + 2: 5, # Woods + 3: 5, # River + 4: 4, # Swamp + 5: 4, # Mountains, Hills + 6: 4, # Barren, Desert + 7: 6, # Inhabited + 8: 6, # City + 9: 5, # Ocean + 10: 4, # Jungle +} + +WILDERNESS_ENCOUNTER_BY_TERRAIN = { + 1: ["Men", "Flyer", "Humanoid", "Animal", "Animal", "Unusual", "Dragon", "Insect"], + 2: ["Men", "Flyer", "Humanoid", "Insect", "Unusual", "Animal", "Animal", "Dragon"], + 3: ["Men", "Flyer", "Humanoid", "Insect", "Swimmer", "Swimmer", "Animal", "Dragon"], + 4: ["Men", "Flyer", "Humanoid", "Swimmer", "Undead", "Undead", "Insect", "Dragon"], + 5: ["Men", "Flyer", "Humanoid", "Unusual", "Animal", "Humanoid", "Dragon", "Flyer"], + 6: ["Men", "Flyer", "Humanoid", "Humanoid", "Animanl", "Dragon", "Undead", "Unusual"], + 7: ["Men", "Flyer", "Humanoid", "Men", "Men", "Insect", "Animal", "Dragon"], + 8: ["Men", "Undead", "Humanoid", "Men", "Men", "Men", "Men", "Men", "Men", "Men"], + 9: ["Men", "Flyer", "Insect", "Insect", "Humanoid", "Animal", "Animal", "Dragon"], + 10: ["Men", "Flyer", "Insect", "Insect", "Humanoid", "Animal", "Animal", "Dragon"], +} + +WILDERNESS_ENCOUNTER_SUBTABLES = { + "Men": { + "Clear, Grass, Scrub": ["Brigand", "Noble", "Mage", "Fighter", "Thief", "Cleric", "Nomad", "Thief", "NPC Party", "Merchant", "Berserker", "Venturer"], + "Woods": ["Brigand", "Thief", "NPC Party", "Merchant", "Berserker", "Brigand", "Cleric", "Mage", "Fighter", "Thief", "Brigand", "NPC Party"], + "River": ["Brigand", "Thief", "NPC Party", "Merchant", "Buccaneer", "Buccaneer", "Cleric", "Mage", "Fighter", "Merchant", "Buccaneer", "NPC Party"], + "Swamp": ["Brigand", "Thief", "NPC Party", "NPC Party", "Merchant", "Cleric", "Venturer", "Berserker", "Fighter", "Mage", "NPC Party", "Thief"], + "Barrens, Mountains, Hills": ["Brigand", "Thief", "NPC Party", "Venturer", "Berserker", "NPC Party", "Cleric", "Mage", "Fighter", "Brigand", "NPC Party", "Barbarian"], + "Desert": ["Nomad", "Nomad", "NPC Party", "Merchant", "Nomad", "Nomad", "Cleric", "Mage", "Fighter", "Noble", "Nomad", "Nomad"], + "Inhabited": ["Thief", "Venturer", "NPC Party", "NPC Party", "Merchant", "Fighter", "Merchant", "Fighter", "Mage", "Cleric", "Cleric", "Noble"], + "City": ["Thief", "Venterer", "NPC Party", "NPC Party", "Merchant", "Fighter", "Merchant", "Fighter", "Mage", "Cleric", "Cleric", "Noble"], + "Ocean": ["Buccaneer", "Pirate", "Merchant", "NPC Party", "Pirate", "Merchant", "Merchant", "Merchant", "Buccaneer", "Pirate", "Merchant", "Pirate"], + "Jungle": ["Brigand", "Venturer", "Thief", "NPC Party", "Cleric", "Fighter", "Medium", "Berserker", "Brigand", "Barbarian", "NPC Party", "Brigand"], + }, + "Humanoid": { + "Clear, Grass, Scrub": ["Bugbear", "Elf", "Gnoll", "Goblin", "Halfling", "Hobgoblin", "Kobold", "Ogre", "Orc", "Pixie", "Throghrin", "Troll"], + "Woods": ["Bugbear", "Cyclops", "Dryad", "Elf", "Giant, Hill", "Gnoll", "Goblin", "Hobgoblin", "Ogre", "Orc", "Pixie", "Troll"], + "River": ["Bugbear", "Elf", "Gnoll", "Hobgoblin", "Lizard Man", "Lizard Man", "Naiad", "Naiad", "Ogre", "Orc", "Sprite", "Troll"], + "Swamp": ["Gnoll", "Goblin", "Hobgoblin", "Lizard Man", "Lizard Man", "Lizard Man", "Naiad", "Ogre", "Orc", "Troglodyte", "Troll", "Troll"], + "Hills, Mountain": ["Dwarf", "Giant, Cloud", "Giant, Frost", "Giant, Hill", "Giant, Stone", "Giant, Storm", "Goblin", "Kobold", "Ogre", "Orc", "Troglodyte", "Troll"], + "Barrens": ["Bugbear", "Giant, Hill", "Goblin", "Gnoll", "Hobgoblin", "Hobgoblin", "Ogre", "Orc", "Orc", "Throghrin", "Troll"], + "Desert": ["Bugbear", "Gnoll", "Giant, Fire", "Hobgoblin", "Hobgoblin", "Minotaur", "Ogre", "Ogre", "Orc", "Orc", "Troll", "Troll"], + "City": ["Doppelganger", "Dwarf", "Elf", "Gnome", "Halfling", "Pixie", "Sprite", "Werebear", "Wereboar", "Wererat", "Weretiger", "Werewolf"], + "Inhabited": ["Doppelganger", "Dwarf", "Elf", "Gnome", "Goblin", "Halfling", "Kobold", "Ogre", "Orc", "Pixie", "Sprite", "Wererat"], + "Jungle": ["Bugbear", "Cyclops", "Elf", "Giant, Fire", "Giant, Hill", "Gnoll", "Goblin", "Lizard Man", "Ogre", "Orc", "Troglodyte", "Troll"], + }, + "Animal": { + "Clear, Grass, Scrub": ["Herd Animal (Antelope)", "Boar*", "Cat, Lion", "Cat, Panther", "Elephant", "Hawk*", "Horse, Light", "Lizard, Tuatara", "Mule (Donkey)", "Snake, Pit Viper", "Snake, Giant Rattler", "Weasel, Giant"], + "Woods": ["Herd Animal (Antelope)", "Bat*", "Bear, Grizzly", "Boar*", "Cat, Panther", "Hawk*", "Owl*", "Snake, Pit Viper", "Spider, Black Widow", "Unicorn", "Wolf", "Wolf, Dire"], + "River": ["Herd Animal (Antelope)", "Bear, Black", "Boar*", "Cat, Panther", "Crab, Giant", "Crocodile*", "Leech, Giant", "Piranha, Giant", "Rat*", "Shrew, Giant", "Swan", "Toad, Giant"], + "Hills": ["Herd Animal (Antelope)", "Bear, Grizzly", "Boar*", "Cat, Mountain Lion", "Eagle*", "Hawk*", "Horse, Light", "Herd Animal (Sheep)", "Snake, Pit Viper", "Owl*", "Wolf", "Wolf, Dire"], + "Mountains": ["Herd Animal (Antelope)", "Bear, Cave", "Cat, Mountain Lion", "Eagle*", "Herd Animal (Goat)", "Hawk*", "Mule (Donkey)", "Baboon, Rock", "Snake, Pit Viper", "Snake, Giant Rattler", "Wolf", "Wolf, Dire"], + "Barrens": ["Herd Animal (Antelope)", "Bear, Cave", "Cat, Mountain Lion", "Eagle*", "Goat, Wild", "Hawk*", "Rock Babooon", "Snake, Pit Viper", "Snake, Giant Rattler", "Spider, Crab", "Wolf, Dire", "Vulture"], + "Desert": ["Herd Animal (Antelope)", "Herd Animal (Antelope)", "Camel", "Camel", "Cat, Lion", "Hawk*", "Lizard, Gecko", "Lizard, Tuatara", "Snake, Giant Rattler", "Wolf (Wild Dog)", "Wolf, Dire", "Vulture"], + "Inhabited": ["Herd Animal (Antelope)", "Boar*", "Cat, Panther", "Lizard, Draco", "Lizard, Gecko", "Lizard, Horned", "Monkey", "Shrew, Giant", "Snake, Pit Viper", "Snake, Python", "Snake, Spitting Cobra", "Spider, Crab"], + "Jungle": ["Goat", "Boar*", "Dog", "Ferret, Giant", "Hawk*", "Horse, Light", "Mule (Donkey)", "Rat*", "Snake, Pit Viper", "Herd Animal (Sheep)", "Weasel, Giant", "Wolf"], + "Other": ["Bear, Cave", "Cat, Sabre-Tooth Tiger", "Crocodile, Giant", "Mastodon", "Pteranodon", "Rhino, Woolly", "Snake, Python", "Stegosaurus", "Titanothere", "Triceratops", "Tyrannosaurus Rex", "Wolf, Dire"], + "*": "Roll 1d6: 1-4 Normal or Swarm, 5-6 Giant" + }, + "Flyer": { + "Barrens": ["Cockatrice", "Gargoyle", "Griffon", "Harpy", "Hawk, Giant", "Hippogriff", "Lammasu", "Manticore", "Pegasus", "Roc, Small", "Stirge", "Wyvern"], + "Desert": ["Chimera", "Cockatrice", "Gargoyle", "Griffon", "Hawk, Giant", "Lammasu", "Manticore", "Pterodactyl", "Roc, Small", "Sphinx", "Wyvern", "Vulture"], + "Mountains": ["Swarm, Bat", "Chimera", "Cockatrice", "Gargoyle", "Griffon", "Harpy", "Hawk, Giant", "Hippogriff", "Manticore", "Pegasus", "Roc*", "Wyvern"], + "Woods": ["Bat, Giant", "Swarm, Bat", "Cockatrice", "Griffon", "Hawk, Giant", "Hippogriff", "Pegasus", "Owl, Giant", "Pixie", "Roc, Small", "Sprite", "Stirge"], + "Other": ["Cockatrice", "Fly, Giant Carnivorous", "Gargoyle", "Griffon", "Hawk, Giant", "Hippogriff", "Bee, Killer Giant", "Pegasus", "Pixie", "Roc, Small", "Sprite", "Stirge"], + "*": "Roll 1d6: 1-3 Small, 4-5 Large, 6 Giant" + }, + "Swimmer": { + "River, Lake": ["Crab, Giant", "Crocodile", "Crocodile", "Crocodile, Large", "Fish, Catfish", "Fish, Piranha", "Fish, Sturgeon", "Leech, Giant", "Lizard Man", "Merman", "Naiad", "Skittering Maw"], + "Ocean": ["Dragon Turtle", "Hydra, Sea", "Merman", "Octopus, Giant", "Sea Dragon", "Sea Serpent", "Shark*", "Shark*", "Skittering Maw", "Snake, Sea", "Squid, Giant", "Whale"], + "Swamp": ["Crab, Giant", "Crocodile", "Crocodile, Large", "Crocodile, Giant", "Fish, Catfish", "Insect Swarm", "Insect Swawrm", "Leech, Giant", "Leech, Giant", "Lizard Man", "Lizard Man", "Skittering Maw"], + "*": "Roll 1d6: 1-2 Bull Shark, 3-4 Mako Shark, 5-6 Great White Shark" + }, + "Dragon": { + "Other": ["Basilisk", "Caecilian", "Chimera", "Dragon*", "Dragon*", "Sphinx", "Hydra/Sea Hydra", "Lamia", "Purple Worm", "Snake, Python", "Salamander", "Wyvern"], + "*": "Always Black in Swamp, Blue in Mountains, Brown in Desert, Green in Woods, Red in Barrens, Sea in Oceans/Rivers/Lake. Otherwise roll 1d10: 1 Black, 2 Blue, 3 Brown, 4 Green, 5 Metallic, 6 Red, 7 Sea, 8 White, 9 Wyrm, 10 Judge’s Choice.", + }, + "Insect": { + "Other": ["Beetle, Fire", "Beetle, Giant Bombardier", "Beetle, Tiger", "Carcass Scavenger", "Centipede, Giant", "Ant, Giant", "Fly, Giant Carnivorous", "Killer Bee", "Rhagodessa", "Scorpion, Giant", "Spider, Black Widow", "Spider, Crab"], + }, + "Undead": { + "Other": ["Ghoul", "Ghoul", "Mummy", "Mummy", "Skeleton", "Skeleton", "Spectre", "Wight", "Wraith", "Vampire", "Zombie", "Zombie"], + }, + "Unusual": { + "Other": ["Basilisk", "Blink Dog", "Centaur", "Gorgon", "Hellhound", "Lycanthrope", "Medusa", "Phase Tiger", "Rust Monster", "Skittering Maw", "Treant", "Ape, White"], + } +} + + +def surprise_roll(mod): + roll = int(dice.roll("1d6 + {}".format(mod))) + status = "Surprised" if roll < 3 else "Ready" + return (status, roll) + +def reaction_roll(mod, difference): + roll = int(dice.roll("2d6 + {}".format(mod))) + roll += difference + + if roll <= 2: + status = "Hostile, attacks" + elif roll >= 3 and roll <= 5: + status = "Unfriendly, may attack" + elif roll >= 6 and roll <= 8: + status = "Neutral, uncertain" + elif roll >= 9 and roll <= 11: + status = "Indifferent, uninterested" + elif roll >= 12: + status = "Friendly, helpful" + + return (status, roll) + +def check_encounter(mod=0, throw=6): + roll = int(dice.roll("1d6 + {}".format(mod))) + return ((roll >= throw), roll) + +def generate_dungeon_monster(check_mod, dungeon_level, reaction_mod, surprise_mod): + check = check_encounter(check_mod) + if not check[0]: + return {"check": False, "check_roll": check[1]} + + if not dungeon_level in DUNGEON_WANDERING_MONSTER_LEVEL: + return None + + monster_table = random.choice(DUNGEON_WANDERING_MONSTER_LEVEL[dungeon_level]) + encounter = random.choice(DUNGEON_RANDOM_MONSTERS_BY_LEVEL[monster_table]) + + difference = monster_table - dungeon_level + + quantity = int(dice.roll(encounter[1])) + adjusted = quantity + for _ in range(abs(difference)): + adjusted = adjusted + (adjusted * 0.5) if difference > 0 else adjusted - (adjusted * 0.5) + adjusted = math.floor(adjusted) if adjusted > 1 else 1 + + distance = int(dice.roll("2d6")) * 10 + surprise = surprise_roll(surprise_mod) + reaction = reaction_roll(reaction_mod, difference) + + return { + "dungeon_level": dungeon_level, + "monster_table": monster_table, + "entity": encounter[0], + "quantity": adjusted, + "initial": quantity, + "roll": encounter[1], + "adjustment": difference, + "distance": distance, + "surprise": surprise, + "reaction": reaction, + "check": True, + "check_roll": check[1] + } + +def generate_wilderness_monster(check_mod, terrain_type, reaction_mod, surprise_mod): + check_throw = WILDERNESS_FREQUENCY_BY_TERRAIN[terrain_type] + check = check_encounter(check_mod, check_throw) + if not check[0]: + return {"check": False, "check_roll": check[1]} + + encounter_type_roll = int(dice.roll("1d8")) + encounter_type = WILDERNESS_ENCOUNTER_BY_TERRAIN[terrain_type][encounter_type_roll - 1] + + subtable = WILDERNESS_ENCOUNTER_SUBTABLES[encounter_type] + terrain_type_labels = WILDERNESS_TYPE_BY_ID[terrain_type] + + endtable = None + for k in subtable.keys(): + for l in terrain_type_labels: + if l in k: + endtable = subtable[k] + if endtable == None and "Other" in subtable: + endtable = subtable["Other"] + + entity_roll = int(dice.roll("1d12")) + entity = endtable[entity_roll - 1] + + surprise = surprise_roll(surprise_mod) + reaction = reaction_roll(reaction_mod, 0) + + return { + "terrain_type": ', '.join(terrain_type_labels), + "monster_table": encounter_type, + "entity": entity, + "surprise": surprise, + "reaction": reaction, + "check": True, + "check_roll": check[1] + } diff --git a/roll20/macros/initiative.macro b/roll20/macros/initiative.macro new file mode 100644 index 0000000..c38569a --- /dev/null +++ b/roll20/macros/initiative.macro @@ -0,0 +1 @@ +&{template:acks} {{name=Initiative}} {{roll=[[1d6+@{selected|initiative_mod} &{tracker}]]}} diff --git a/roll20/macros/roll-stats.macro b/roll20/macros/roll-stats.macro new file mode 100644 index 0000000..d012e9e --- /dev/null +++ b/roll20/macros/roll-stats.macro @@ -0,0 +1 @@ +&{template:acks} {{name=Character Stat Roll}} {{Strength = [[3d6]]}} {{Dexterity = [[3d6]]}} {{Intelligence = [[3d6]]}} {{Constitution = [[3d6]]}} {{Wisdom = [[3d6]]}} {{Charisma = [[3d6]]}} diff --git a/roll20/macros/scavenge.macro b/roll20/macros/scavenge.macro new file mode 100644 index 0000000..c30e193 --- /dev/null +++ b/roll20/macros/scavenge.macro @@ -0,0 +1,11 @@ +?{Equipment Type| +Bladed Weapon, +&{template:acks}{{name=Scavenge Gear}}{{subheader=Bladed Weapon}}{{desc=[[1t[Scavenge-Blade]]]}} +| +Blunt Weapon, +&{template:acks}{{name=Scavenge Gear}}{{subheader=Blunt Weapon}}{{desc=[[1t[Scavenge-Blunt]]]}} +| +Armor and Equipment, +&{template:acks}{{name=Scavenge Gear}}{{subheader=Armour and Equipment}}{{desc=[[1t[Scavenge-Other]]]}} +} +