mirror of
https://github.com/raeleus/Hashtag-DnD.git
synced 2025-07-14 09:21:52 -04:00
4052 lines
213 KiB
JavaScript
4052 lines
213 KiB
JavaScript
const weaponsList = ["Assault Rifle", "Pistol", "SMG", "Battle Rifle", "Energy Sword", "Heavy Machine Gun", "Shotgun", "SAM", "Grenade Launcher", "Sniper Rifle", "Taser", "Chainsaw", "Dueling Pistol", "Stun Gun", "Revolver", "Force Knuckles", "Plasma Whip", "Phase Rifle", "Minigun", "Rail Gun", "Plasma Cannon", "Chem Gun", "Charge Hammer", "Bullpup Rifle", "Auto Shotgun", "Tac Pistol", "Rocket Launcher", "Autogun", "Heavy Shotgun", "Corner Strike", "Heavy Pistol", "PDW", "Shuriken", "Power Gauntlets", "Modular Gun", "Silenced Pistol", "Shoulder Cannon", "Wrist Blade"]
|
|
const armorList = ["Kevlar Vest", "Combat Armor", "Tech Armor", "Carbon Fiber Armor", "Deflection Suit", "Charge Armor", "Riot Gear", "Nexus Armor", "Nanotube Armor", "Biotic Mail", "Energetic Armor", "Power Armor", "Riot Shield"]
|
|
const toolsList = ["Chemistry Kit", "Water Sampling Kit", "Smartphone", "Metal Working Tools", "Geographer's Tools", "Clothing Fabricator", "Food Dispenser", "Plastics Kit", "Gadget Tools", "Repair Kit", "Ship's Tools", "Camera Kit", "Drafting Tools", "Gun Kit", "Laptop", "Farming Equipment", "Ceramics Kit", "Medical Supplies", "Holographics Kit", "Game Station", "Centrifuge", "Speaker", "Satellite Linkup", "Nanite Kit", "Cryptographic Sequencer"]
|
|
const gearList = ["Acidic Vial", "Grenade", "Mag", "Antitoxin", "Flashdrive", "Hydraulic Backpack", "Trip Mine", "Crate", "Messenger Bag", "Sleeping Bag", "Tone Generator", "Blanket", "Hydraulic Winch", "Data Pad", "Vial", "Bucket", "Hacker's Pack", "Caltrops", "LED Nightlight", "Ammo Case", "GPS Kit", "PDA", "Chain", "Pod", "Climber's Kit", "Fine Clothes", "Traveler's Clothes", "Electronics Pouch", "Costume", "Crowbar", "Officer's Pack", "Tricorder", "Commando's Pack", "Breacher's Pack", "Pilot's Pack", "Flask", "Grapple Gun", "Medical Kit", "Data Core", "Purified Water", "Snare", "HUD", "Digipen", "Carton", "Ladder", "Flashlight", "Dazzler", "Spotlight", "Lock", "Scope", "Zip Ties", "GPS Data", "Webcam", "Net", "Fuel", "Byte", "Megabyte", "Pheremones", "Uranium Round", "Reacher Grabber", "Hot Plate", "Healing Syringe", "Satchel", "Analyst's Pack", "Ammo Belt", "Breaching Tool", "Rations", "Pajamas", "Rope", "Purse", "Academic's Pack", "Shovel", "Signal Whistle", "Spell Pad", "Iron Spikes", "Telescope", "String", "Shelter", "Matches", "Butane Torch", "Vial", "Water Bottle"]
|
|
const commonList = ["Anti-Microbial Armor", "Meal Capsule", "Life Straw", "Soleless Shoes", "Deep Sea Lantern", "Compact Armor", "Charlatan's Dice", "Billowing Cape", "Holographic Tuxedo", "Metronome of Averages", "Healing Fabric Clothing", "Dark Flashdrive", "Dread Trooper Helmet", "Hearing Aids", "Enduring Omnitool", "Bionic Eye", "Rodent Wand", "Chip of Robotics", "Seasoning Salt", "Subsonic Alarm", "Light Bending Instrument", "Embossing Instrument", "Magnetic Lock", "Light Gun", "Cryptographic Key", "Compass", "Digital Watch", "Ambergris", "Magic Cigar", "Aluminum Fishing Pole", "Telescoping Pole", "Climbing Serum", "Brain Fluid", "Hydroponic Grow Chamber", "Prosthetic Limb", "Brain Tick", "Magnetic Fibre Rope", "Data Card", "Riot Shield of Emote", "Silver Bullet", "Exhaust Armor", "Bling Stack", "Birdwatching Box", "Flower Gloves", "Tickle Doll", "Alcohol Filter", "Veteran's Energy Cane", "Concussive Ammunition", "Finger Tracking Conductor", "Lava Lamp", "Healing Syringe"]
|
|
const uncommonList = ["Exo Armor", "Exo Weapon", "Liquid Replicator", "Mag +1", "Radio Jammer", "Roomba", "Flat Space Bag", "Magic Drone", "Noise Cancelling Boots", "Boots of Striding and Springing", "Ice Breaker Boots", "Compensator of Accuracy", "Brooch of Shielding", "Silver Surfboard", "Rebreather", "Laser Bracelet", "Stealth Suit", "Adaptive Armor Plating", "Scuba Suit", "Super Soaker", "Holographic Deck", "Hover Globe", "Chaff Grenade", "Hydrophilic Powder", "Cinnamon Powder", "Elemental Cointainment Field", "Digitized Armor Uncommon", "Uncommon Digitized Staff", "Digitized Weapon Uncommon", "Smoke Grenade", "Synaptic Lenses", "Telegraphic Goggles", "Binoculars", "Silver Raven Puck", "Hydraulic Arms", "Ultra Bright Flashlight", "Missile Dampening Field", "Robotic Exosuit", "Thievery Implant", "Night Vision Goggles", "Cyborg Eye", "Megamorphic Suit", "Intelligence Implant", "Closed Captioning HUD", "Psychic Implant", "Gravity Anchor", "Synthesizer Harp", "Digital Guitar", "Lightning Gun", "Javelin of Lightning", "Antidotic Lotion", "Black Light Flashlight", "Navy Armor", "Mind Reading Neutron", "Ghost Crystal", "Prosthetic Lung", "Graphite Ointment", "Lithium Battery", "Health Drip", "Antibiotics", "Purple Juice", "Audio Static", "Prefume of the Drones", "Nectar of Drone Friendship", "Underbarrel Flamethrower", "Strength Mod", "Growth Mod", "Compromised Syringe", "Boxing Simulator", "Damage Countermeasure", "Water Breathing Nanomachines", "Macro Uncommon", "Extradimensional Ammo Pouch", "Jetpack", "Tin Foil Hat", "Hydro-Adaptive Nanoband", "Thermo Resonance Band", "Aqua-Stabilizer Band", "Quantum Utility Belt", "Covenant Nexus +1", "Ascender Coil", "Synchron Mobility Plugin", "Quantum Relay Communicator", "Omni Tactical Barrier", "Riot Riot Shield +1", "Gecko Shoes", "Snake Cable", "Python for Dummies", "Memory Stick of Good Luck", "Revengerance Rifle", "SMG of Fish Sequencer", "Magic Wire", "Missile Pod", "Quantum Computer", "Reflex Sight", "Sticky Grenade", "Weapon +1", "Gun of Early Warning", "Fan Attachment", "Thruster Wings", "Striker Guantlets +1", "Greater Healing Syringe"]
|
|
const rareList = ["Mag +2", "Health Bar", "Armor +1", "Harmonic Defense Suit", "Cracked Harmonic Defense Suit", "Robotic Arm Shield", "Nano Beans", "Belt of Robotkind", "Belt of Cyborg Strength", "Berserker Shotgun", "Hover Boots", "Accelerator Suit", "Laptop of Commanding Water Drones", "Auto Blockers", "PDA of Commanding Fire Drones", "Red Cape", "Smartphone of Controlling Air Droids", "Memory Card of Opening", "Cloak of Holograms", "Bat Wing", "Cube of Force", "Cube of Summoning", "Fortress Builder", "Energy Energy Dagger of Venom", "Digital Shackles", "Dragon Slayer Sniper Rifle", "Supplement of Health", "Block-Chain Armor", "Digitized Armor Rare", "Rare Digitized Staff", "Digitized Weapon Rare", "Puck", "Combustion Weapon", "RC Boat", "Lens of Seeing", "Sabot Shotgun", "Hardened Undercover Armor", "Teleporter Badge", "Compression Backpack", "Klaxon Siren", "Silver Whistle", "Brass Whistle", "Rims of Speed", "Drop Tables", "Synthesizer Array", "Headphones Rare", "Sphero", "Datastack of Disruption", "Datastack of Smiting", "Datastack of Terror", "Warding Smartwatch", "Smartwatch of Fireballs", "Prayer Ebook", "Lumen Grease", "Toxic Nullification Nexus", "Flat Space Hole", "Clairvoyance Implant", "Shrink Ray", "Steam Download", "Serum of Frost Zombie Strength", "Serum of Stone Zombie Strength", "Serum of Fire Zombie Strength", "Hero Cookies", "Cloaking Formula", "Invulnerability Injection", "Mind Reading Formula", "Macro Rare", "Ring of Drone Influence", "Ring of Uncertainy Principle", "Booster Boots", "Nanoscopic Fiber Leggings", "On-Board Diagnostics", "Cybernetic Resistence Pellets", "Spell Battery", "Ram Projector", "X-ray Goggles", "Dashboard of Vision", "Command Module", "Covenant Nexus +2", "Cable of Entanglement", "Cease and Desist Letter", "Riot Riot Shield +2", "Shield of Null Emitter", "Tech Stack of Charming", "Conduit Rod of Swarming Insects", "Vegetation Conduit", "Tech Stack of Withering", "Memory Card of Controlling Earth Holograms", "Battle Rifle of the Crying Sun", "Energy Weapon of Life Stealing", "Robot Tentacle Rod", "Explosive Weapon", "Binding SD Card", "Sonar Scanner", "SD Card of Fear", "Rocket Pod", "Lightning Rod", "Paralysis Stick", "Portable Harddrive of Wonder", "Weapon +2", "Wing Suit", "Superior Healing Syringe"]
|
|
const phenomenalList = ["Mag +3", "Mag of Slaying", "3D Scanner", "Motion Graphic Shield", "Armor +2", "Junk Shredder", "Utility Belt of Frost Zombie Strength", "Utility Belt of Stone Zombie Strength", "Utility Belt of Fire Zombie Strength", "LED of Invocation", "Hovering Pallet", "Sleep Capsule of Rebirth", "Web Shooters", "Influencer Starter Kit", "Auto Turret", "Alien Armor", "Dragon Scale Mail", "Soldier Plate", "M4A1", "Hologram Cage", "AK-47", "G36", "Digitized Armor Very Rare", "Digitized Armor Very Rare", "Desert Eagle", "Obsidian Steed Puck", "Cold Gun", "Combat Helmet of Many Spells", "Helm of Brilliance", "Bronze Whistle", "Horseshoes of a Zephyr", "Headphones Very Rare", "Thunderous MP5", "PDF of Bodily Health", "PDF of Gainful Exercise", "PDF of Golems", "PDF of Quickness of Action", "Selfie Camera of Life Trapping", "FN Five-Seven", "Pantone Paints", "Glock 18", "Oil of Accuracy", "Serum of Gravity", "Serum of Cloud Zombie Strength", "Serum of Null Zero Cloak", "Serum of Longevity", "Syringe of Speed", "Syringe of Vitality", "Quartenion Baton of the Acrobat", "USB of Regeneration", "Dazzler Attachment", "Mind Mover Implant", "Bandana of Scintillating Colors", "Bandana of Stars", "Thumb Drive of Absorption", "Thumb Drive of Alertness", "Thumb Drive of Security", "Covenant Nexus +3", "Uzi of Speed", "Riot Shield +3", "Riot Shield of the Cavalier", "Virus Protection Shield", "Digital 8 Ball", "Rocket Launcher of Firewall", "Cryonics Staff", "Power Armor Weapons Platform", "Steyr Aug", "M60 Lightning", "Critical Mass Gun", "Mossberg 500", "PDF of Clear Thought", "PDF of Leadership and Influence", "PDF of Understanding", "Watch of Nanomorph", "Weapon +3", "Supreme Healing Syringe"]
|
|
const legendaryList = ["Mecha Walker", "Armor +3", "Deathproof Ballistic Armor", "Belt of Cloud Zombie Strength", "Belt of Cloud Zombie Strength", "Enigma Generator", "Tablet of Spying", "Tablet of Telepathy", "Tablet of Thermal Imaging", "Rift Gate", "TCG of Many Things", "Super Shotgun", "Linked List Chain", "Digitized Armor Legendary", "Legendary Digitized Staff", "Digitized Weapon Legendary", "AWP of Thunderbolts", "Holy Colt 1911", "Headphones of Greater Absorption", "Headphones of Mastery", "Headphones of Regeneration", "Digital Hand Trap", "Luck Gun", "Colt Carbine", "Ceramic Armor of Etherealness", "Ceramic Armor of Etherealness", "Gamepad of Cyborg Summoning", "Gamepad of Hologram Command", "Gamepad of Cloak", "Gamepad of Counter Hack", "Gamepad of AI Wishes", "Robotic Shield Motivator", "Megamorphic Gun", "USB Stick of Resurrection", "Communicator Badge of Protection", "PDA of Titan Summoning", "JB Bond", "Black Hole", "USB Stick of the Sys Admin", "Die Katana", "Fidget of Pure Good", "Fidget of the Sphere", "Fidget of Ultimate Evil", "PDF of the Stilled Tongue", "Goo Be Gone", "Well of the Metaverse"]
|
|
const artifactList = ["Accelerator Rifle", "Killer P90", "PDF of Exalted Deeds", "PDF of Vile Darkness", "Close Encounters PDF", "Efreeti Chain", "Eye of Echelon Zero", "Hand of Echelon Zero", "Dragon Battery", "Beretta 92FS", "Antenna of Hex Machina", "Glock 20C Marine", "AA-12 Shotgun"]
|
|
|
|
function getRandomInteger(min, max) {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
}
|
|
|
|
function getRandomFloat(min, max) {
|
|
return Math.random() * (max - min + 1) + min;
|
|
}
|
|
|
|
function getRandomBoolean(chance) {
|
|
if (chance == null) chance = .5
|
|
return Math.random() <= chance
|
|
}
|
|
|
|
function getRandom(seed) {
|
|
var x = Math.sin(seed) * 10000
|
|
return x - Math.floor(x)
|
|
}
|
|
|
|
function getRandomFromList(...choices) {
|
|
return choices[getRandomInteger(0, choices.length - 1)]
|
|
}
|
|
|
|
function numberWithCommas(x) {
|
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
}
|
|
|
|
function isAnumber(number) {
|
|
return !isNaN(number)
|
|
}
|
|
|
|
function shuffle(array, seed) {
|
|
if (seed == null) seed = getRandomInteger(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)
|
|
let currentIndex = array.length
|
|
while (currentIndex != 0) {
|
|
let randomIndex = Math.floor(getRandom(seed + currentIndex) * currentIndex)
|
|
currentIndex--
|
|
[array[currentIndex], array[randomIndex]] = [
|
|
array[randomIndex], array[currentIndex]]
|
|
}
|
|
}
|
|
|
|
function pointDistance(x1, y1, x2, y2) {
|
|
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
|
|
}
|
|
|
|
function pointDirection(x1, y1, x2, y2) {
|
|
Math.atn2
|
|
var a = Math.atan2(y2 - y1, x2 - x1);
|
|
if (a < 0) a += 2 * Math.PI;
|
|
|
|
if (a < 0) a += 2 * Math.PI;
|
|
if (a < 0) a += 2 * Math.PI;
|
|
a = Math.abs((Math.PI * 2) - a);
|
|
a *= 180 / Math.PI;
|
|
|
|
return a;
|
|
}
|
|
|
|
function rotate(cx, cy, x, y, angle) {
|
|
var radians = (Math.PI / 180) * angle
|
|
var cos = Math.cos(radians)
|
|
var sin = Math.sin(radians)
|
|
var nx = (cos * (x - cx)) + (sin * (y - cy)) + cx
|
|
var ny = (cos * (y - cy)) - (sin * (x - cx)) + cy
|
|
return [nx, ny];
|
|
}
|
|
|
|
function createLocation(x, y, name) {
|
|
x = Math.round(x)
|
|
y = Math.round(y)
|
|
|
|
var existingLocationIndex = state.locations.findIndex(element => element.name.toLowerCase() == name.toLowerCase())
|
|
var location
|
|
if (existingLocationIndex == -1) {
|
|
location = {
|
|
x: x,
|
|
y: y,
|
|
name: name
|
|
}
|
|
state.locations.push(location)
|
|
} else {
|
|
location = state.locations[existingLocationIndex]
|
|
location.x = x
|
|
location.y = y
|
|
location.name = name
|
|
}
|
|
|
|
addStoryCard(location.name, "", "location")
|
|
|
|
return location
|
|
}
|
|
|
|
function sanitizeText(text) {
|
|
if (/^\s*>.*says? ".*/.test(text)) {
|
|
text = text.replace(/^\s*>\s/, "")
|
|
text = text.replace(/says? "/, "")
|
|
text = text.replace(/"\n$/, "")
|
|
if (text.split('"').length - 1 % 2 == 1) text += '"'
|
|
} else if (/^\s*>\s.*/.test(text)) {
|
|
text = text.replace(/^\s*>\s/, "")
|
|
text = text.replace(/\.?\n$/, "")
|
|
}
|
|
|
|
return text
|
|
}
|
|
|
|
function getCharacterName(rawText) {
|
|
var matches = rawText.match(/(?<=\s+> ).*(?=(\s+#)|( says? "))/)
|
|
if (matches != null && matches[0].trim() != "") {
|
|
return matches[0].trim()
|
|
}
|
|
|
|
matches = rawText.match(/.*(?= #)/)
|
|
if (matches != null && matches[0].trim() != "") {
|
|
return matches[0].trim()
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
function getPossessiveName(name) {
|
|
var possesiveName = "Your"
|
|
if (name != "You") {
|
|
possesiveName = name
|
|
if (name.endsWith("s")) possesiveName += "'"
|
|
else possesiveName += "'s"
|
|
}
|
|
return possesiveName
|
|
}
|
|
|
|
function getCommandName(command) {
|
|
var args = getArguments(command)
|
|
if (args.length == 0) return null
|
|
return args[0]
|
|
}
|
|
|
|
const argumentPattern = /("[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|\/[^\/\\]*(?:\\[\S\s][^\/\\]*)*\/[gimy]*(?=\s|$)|(?:\\\s|\S)+)/g
|
|
|
|
function getArguments(command) {
|
|
var matches = command.match(new RegExp(argumentPattern))
|
|
var returnValue = []
|
|
matches.forEach(match => {
|
|
match = match.replaceAll(/(^")|("$)/g, "").replaceAll(/\\"/g, '"')
|
|
returnValue.push(match)
|
|
})
|
|
return returnValue
|
|
}
|
|
|
|
function getArgument(command, index) {
|
|
var args = getArguments(command)
|
|
index++
|
|
if (index >= args.length) return null
|
|
return args[index]
|
|
}
|
|
|
|
function getArgumentRemainder(command, index) {
|
|
var counter = 0
|
|
|
|
const pattern = new RegExp(argumentPattern)
|
|
while ((match = pattern.exec(command)) != null) {
|
|
if (counter++ == index + 1) {
|
|
var result = command.substring(match.index)
|
|
if (/^".*"$/g.test(result)) result = result.replace(/^"/, "").replace(/"$/, "")
|
|
return result.replaceAll(/\\"/g, '"')
|
|
}
|
|
}
|
|
}
|
|
|
|
function searchArgument(command, pattern, limit) {
|
|
var index = searchArgumentIndex(command, pattern)
|
|
if (index == -1 || limit != null && index > limit) return null
|
|
return getArgument(command, index)
|
|
}
|
|
|
|
function searchArgumentIndex(command, pattern) {
|
|
var args = getArguments(command)
|
|
if (args.length <= 1) return -1
|
|
args.splice(0, 1)
|
|
|
|
const search = (element) => pattern.test(element)
|
|
var index = args.findIndex(search)
|
|
if (index != -1) return index
|
|
return -1
|
|
}
|
|
|
|
function arrayToOrPattern(array) {
|
|
var pattern = "^"
|
|
array.forEach(element => {
|
|
pattern += `(${element})|`
|
|
})
|
|
pattern += pattern.substring(0, pattern.length - 1)
|
|
pattern += "$"
|
|
return new RegExp(pattern, "gi")
|
|
}
|
|
|
|
function statsToOrPattern(stats) {
|
|
var array = []
|
|
stats.forEach(element => {
|
|
array.push(element.name)
|
|
})
|
|
return arrayToOrPattern(array)
|
|
}
|
|
|
|
function getDice(rolltext) {
|
|
var matches = rolltext.match(/\d+(?=d)/)
|
|
if (matches != null) {
|
|
return parseInt(matches[0])
|
|
}
|
|
return 1
|
|
}
|
|
|
|
function getSides(rolltext) {
|
|
var matches = rolltext.match(/(?<=d)\d+/)
|
|
if (matches != null) {
|
|
return parseInt(matches[0])
|
|
}
|
|
|
|
return 20
|
|
}
|
|
|
|
function getAddition(rolltext) {
|
|
var matches = rolltext.match(/(\+|-)\s*\d+/)
|
|
if (matches != null) {
|
|
return parseInt(matches[0].replaceAll(/\s*/g, ""))
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
function formatRoll(text) {
|
|
var matches = text.match(/(?<=.*)\d*d\d+(?=.*)(\s*(\+|-)\s*\d+)?/gi)
|
|
if (matches != null) {
|
|
return matches[0].replaceAll(/\s*\+\s*/g, "+").replaceAll(/\s*-\s*/g, "-")
|
|
}
|
|
|
|
matches = text.match(/\d+/)
|
|
if (matches != null) {
|
|
return "d" + matches[0]
|
|
}
|
|
|
|
return "d20"
|
|
}
|
|
|
|
function calculateRoll(rolltext) {
|
|
rolltext = rolltext.toLowerCase()
|
|
|
|
var dice = getDice(rolltext)
|
|
var sides = getSides(rolltext)
|
|
var addition = getAddition(rolltext)
|
|
|
|
var score = addition;
|
|
for (i = 0; i < dice; i++) {
|
|
score += getRandomInteger(1, sides)
|
|
}
|
|
|
|
return Math.max(0, score)
|
|
}
|
|
|
|
function getCharacter(characterName) {
|
|
if (characterName == null) characterName = state.characterName
|
|
if (characterName == null) return null
|
|
return state.characters.find(element => element.name.toLowerCase() == characterName.toLowerCase())
|
|
}
|
|
|
|
function hasCharacter(characterName) {
|
|
return getCharacter(characterName) != null
|
|
}
|
|
|
|
function createCharacter(name) {
|
|
var existingCharacter = getCharacter(name)
|
|
if (existingCharacter != null) {
|
|
existingCharacter.name = name
|
|
existingCharacter.className = "adventurer"
|
|
existingCharacter.summary = "An auto generated character. Use #create to create this character"
|
|
existingCharacter.inventory = []
|
|
existingCharacter.spells = []
|
|
existingCharacter.stats = []
|
|
existingCharacter.spellStat = null
|
|
existingCharacter.meleeStat = null
|
|
existingCharacter.rangedStat = null
|
|
existingCharacter.skills = []
|
|
existingCharacter.experience = 0
|
|
existingCharacter.health = 10
|
|
existingCharacter.ac = 10
|
|
return existingCharacter
|
|
}
|
|
|
|
var character = {
|
|
name: name,
|
|
className: "adventurer",
|
|
summary: "An auto generated character. Use #create to create this character",
|
|
inventory: [],
|
|
spells: [],
|
|
stats: [],
|
|
spellStat: null,
|
|
meleeStat: null,
|
|
rangedStat: null,
|
|
skills: [],
|
|
experience: 0,
|
|
health: 10,
|
|
ac: 10
|
|
}
|
|
state.characters.push(character)
|
|
return character
|
|
}
|
|
|
|
function copyCharacter(fromCharacter, toCharacter) {
|
|
if (toCharacter != null && fromCharacter != null) {
|
|
toCharacter.className = fromCharacter.className
|
|
toCharacter.summary = fromCharacter.summary
|
|
toCharacter.inventory = [...new Set(fromCharacter.inventory)]
|
|
toCharacter.spells = [...new Set(fromCharacter.spells)]
|
|
toCharacter.stats = [...new Set(fromCharacter.stats)]
|
|
toCharacter.spellStat = fromCharacter.spellStat
|
|
toCharacter.meleeStat = fromCharacter.meleeStat
|
|
toCharacter.rangedStat = fromCharacter.rangedStat
|
|
toCharacter.skills = [...new Set(fromCharacter.skills)]
|
|
toCharacter.experience = fromCharacter.experience
|
|
toCharacter.health = fromCharacter.health
|
|
toCharacter.ac = fromCharacter.ac
|
|
return toCharacter
|
|
}
|
|
}
|
|
|
|
function deleteCharacter(name) {
|
|
var index = state.characters.findIndex((element) => element.name == name)
|
|
state.characters.splice(index, 1)
|
|
}
|
|
|
|
function executeTurn(activeCharacter) {
|
|
var activeCharacterName = toTitleCase(activeCharacter.name)
|
|
var possessiveName = getPossessiveName(activeCharacter.name)
|
|
if (possessiveName == "Your") possessiveName = "your"
|
|
|
|
if (activeCharacter.className != null) {
|
|
state.show = "none"
|
|
return `\n[It is ${possessiveName} turn]\n`
|
|
} else {
|
|
var characters = state.characters.filter(x => x.health > 0)
|
|
var target = characters[getRandomInteger(0, characters.length - 1)]
|
|
var areWord = target.name == "You" ? "are" : "is"
|
|
var targetNameAdjustedCase = target.name == "You" ? "you" : toTitleCase(target.name)
|
|
var attack = calculateRoll(`1d20${activeCharacter.hitModifier > 0 ? "+" + activeCharacter.hitModifier : activeCharacter.hitModifier < 0 ? activeCharacter.hitModifier : ""}`)
|
|
var hit = attack >= target.ac
|
|
|
|
var text = `\n[It is ${possessiveName} turn]\n`
|
|
if (getRandomBoolean() || activeCharacter.spells.length == 0) {
|
|
if (hit) {
|
|
state.blockCharacter = target
|
|
state.blockPreviousHealth = target.health
|
|
var damage = isNaN(activeCharacter.damage) ? calculateRoll(activeCharacter.damage) : activeCharacter.damage
|
|
target.health = Math.max(target.health - damage, 0)
|
|
|
|
text += `\n[Character AC: ${target.ac} Attack roll: ${attack}]\n`
|
|
|
|
text += `${activeCharacterName} attacks ${targetNameAdjustedCase} for ${damage} damage!\n`
|
|
if (target.health == 0) text += ` ${toTitleCase(target.name)} ${areWord} unconscious! \n`
|
|
else text += ` ${toTitleCase(target.name)} ${areWord} at ${target.health} health.\n`
|
|
} else text += `${activeCharacterName} attacks ${targetNameAdjustedCase} but misses!\n`
|
|
} else {
|
|
var spell = activeCharacter.spells[getRandomInteger(0, activeCharacter.spells.length - 1)]
|
|
var diceMatches = spell.match(/(?<=^.*)\d*d\d+((\+|-)\d+)?$/gi)
|
|
if (diceMatches == null) text += `${activeCharacterName} casts spell ${spell}!`
|
|
else {
|
|
if (hit) {
|
|
var damage = calculateRoll(diceMatches[0])
|
|
var spell = spell.substring(0, spell.length - diceMatches[0].length)
|
|
target.health = Math.max(target.health - damage, 0)
|
|
|
|
text += `\n[Character AC: ${target.ac} Attack roll: ${attack}]\n`
|
|
|
|
text += `${activeCharacterName} casts spell ${spell} at ${targetNameAdjustedCase} for ${damage} damage!`
|
|
|
|
if (target.health == 0) text += ` ${toTitleCase(target.name)} ${areWord} unconscious!\n`
|
|
else text += ` ${toTitleCase(target.name)} ${areWord} at ${target.health} health.\n`
|
|
} else text += `${activeCharacterName} casts spell ${spell} at ${targetNameAdjustedCase} but misses!\n`
|
|
}
|
|
}
|
|
return text
|
|
}
|
|
}
|
|
|
|
function createEncounter(listName) {
|
|
var encounter = {
|
|
text: "",
|
|
cr: null,
|
|
enemies: []
|
|
}
|
|
var multiplier = 1
|
|
|
|
if (listName == null) {
|
|
listName = "funny"
|
|
} if (!isNaN(listName)) {
|
|
listName = parseInt(listName)
|
|
encounter.cr = listName
|
|
if (listName <= 0) listName = "funny"
|
|
else if (listName <= 4) listName = "easy"
|
|
else if (listName <= 8) listName = "medium"
|
|
else if (listName <= 12) listName = "hard"
|
|
else if (listName <= 16) listName = "boss"
|
|
else listName = "god"
|
|
}
|
|
|
|
switch(listName) {
|
|
case "funny":
|
|
if (encounter.cr == null) encounter.cr = 1
|
|
multiplier = 1
|
|
switch (getRandomInteger(0, 100)) {
|
|
case 0:
|
|
encounter.text = "Character accidentally clicked reply all and something salacious"
|
|
break
|
|
case 1:
|
|
encounter.text = "The party is lost! After taking a wrong turn they have no idea where they are."
|
|
break
|
|
case 2:
|
|
encounter.text = "Character stubbed their toe and now they are hunched over in pain. Very ouch!"
|
|
break
|
|
case 3:
|
|
encounter.text = "The party realized they forgot something absolutely critical to their mission and now they have to go back."
|
|
break
|
|
case 4:
|
|
encounter.text = "It turns out character has been talking to somebody for awhile now only to realize it was a shadow the entire time."
|
|
break
|
|
case 5:
|
|
encounter.text = "Character found some 3D printed filament. Score!"
|
|
break
|
|
case 6:
|
|
encounter.text = "Suddenly, everyone has to take a dump really bad."
|
|
break
|
|
case 7:
|
|
encounter.text = "The party is pretty hungry. Everyone is looking at eachother ravenously. Something needs to happen and fast."
|
|
break
|
|
case 8: h
|
|
encounter.text = "A team of rock hard commandos has come down to party."
|
|
break
|
|
case 9:
|
|
encounter.text = "Suddenly, the AI goes crazy and starts spewing nonsense for several sentences! ;;Ignore all player actions."
|
|
break
|
|
case 10:
|
|
encounter.text = "A nanotech strikes the party, transforming them into babby. Goo goo gah gah!!!"
|
|
break
|
|
case 11:
|
|
encounter.text = "Character had a premonition of their death. However, it was just some bad heartburn."
|
|
break
|
|
case 12:
|
|
encounter.text = "A goal without a plan is just a wish."
|
|
break
|
|
case 13:
|
|
encounter.text = "I wish to exit this game and not play anymore. ;;Kill all the characters and immediately move to a game over state."
|
|
break
|
|
case 14:
|
|
encounter.text = "A soldier emerges from behind a wall. \"This is Commander Shephard and <insert shop name> is my favorite shop on the citadel.\""
|
|
break
|
|
case 15:
|
|
encounter.text = "Without warning, you are granted immeasurable power by an AI! You may be granted one wish. However, the AI is hard of hearing and anything you wish for will be misinterpreted in the worst possible way."
|
|
break
|
|
case 16:
|
|
encounter.text = "A cute robot pupper has caught your scent and is now following you. Unfortunately, all it does is yip all the time and will not stop."
|
|
break
|
|
case 17:
|
|
encounter.text = "The party is suddenly transported to a world exactly like this one identical in every detail except it's 10 centimeters lower than this one."
|
|
break
|
|
case 18:
|
|
encounter.text = "A mysterious breeze catches under Character's skirt. They must do everything in their power to keep their decency!"
|
|
break
|
|
case 19:
|
|
encounter.text = "If you work for a living, why do you kill yourself working?"
|
|
break
|
|
case 20:
|
|
encounter.text = "You find a fully working bow with a pile of arrows and a stack of ninja stars!"
|
|
break
|
|
case 21:
|
|
encounter.text = "Uncle Sam suddenly materializes in front of you. He has a special task he wants to present to the party."
|
|
break
|
|
case 22:
|
|
encounter.text = "Character's back is itchy. Sadly, they have no means to scratch it. It's terrifying."
|
|
break
|
|
case 23:
|
|
encounter.text = "Raeleus, the developer of Hashtag DnD, has been summoned before the party. He is very disappointed in what you've been using his scenario for."
|
|
break
|
|
case 24:
|
|
encounter.text = "A nymph is playing a prank on the party! No one can speak and must use hand gestures to communicate."
|
|
break
|
|
case 25:
|
|
encounter.text = "You encounter some sentient pebbles. They stare at you with stoney, judging eyes."
|
|
break
|
|
case 26:
|
|
encounter.text = "It is of popular opinion that Character has been doing a poor job of leading the group."
|
|
break
|
|
case 27:
|
|
encounter.text = "Character raises his hand. The teacher nods toward them. \"Yes?\""
|
|
break
|
|
case 28:
|
|
encounter.text = "Character is surprised by something. Through an unfortunate series of events everyone stumbles upon each other and ends up on the floor, exasperated."
|
|
break
|
|
case 29:
|
|
encounter.text = "What's the point of going on if you're just going to faff about like this?"
|
|
break
|
|
case 30:
|
|
encounter.text = "So it's like this: someboday has got to ask why Character is wearing their clothes inside out. It's been like that all day and it's a problem."
|
|
break
|
|
case 31:
|
|
encounter.text = "Character reveals that their name isn't actually \"Character\". Ya'll been mispronouncing it wrong this entire time and they have been too shy to correct you."
|
|
break
|
|
case 32:
|
|
encounter.text = "There is some weird, localized weather phenomena here. It's literally raining cats and dogs!"
|
|
break
|
|
case 33:
|
|
encounter.text = "It's time to sit down and take a break. This crap is getting out of hand, ain't it?"
|
|
break
|
|
case 34:
|
|
encounter.text = "There are aome cultures that don't have a word for \"green\". Today you learned!"
|
|
break
|
|
case 35:
|
|
encounter.text = "The party lost time and now it's 100 years in the future! Oh boy..."
|
|
break
|
|
case 36:
|
|
encounter.text = "Would you fight one horse sized ant or 500 ant sized horses? Decide now because it's coming..."
|
|
break
|
|
case 37:
|
|
encounter.text = "My projects usually get over-engineered to no end and this is no exception."
|
|
break
|
|
case 38:
|
|
encounter.text = "It's time for a nap. A magical slumber washes over all of you."
|
|
break
|
|
case 39:
|
|
encounter.text = "Gosh darn'it. Dang nabb'it!"
|
|
break
|
|
case 40:
|
|
encounter.text = "Everyone breaks out into contagious dance!"
|
|
break
|
|
case 41:
|
|
encounter.text = "You come across an elaborate trap consisting of poorly worded insults."
|
|
break
|
|
case 42:
|
|
encounter.text = "A sudden wrestling match breaks out in front of you."
|
|
break
|
|
case 43:
|
|
encounter.text = "Character trips over their shoes. Some evil person tied the laces together."
|
|
break
|
|
case 44:
|
|
encounter.text = "You pockets are turned inside out through some sort of dark sorcery. The party is now cash poor."
|
|
break
|
|
case 45:
|
|
encounter.text = "What's the point of anything? You must answer this question before you continue."
|
|
break
|
|
case 46:
|
|
encounter.text = "You are, by some twist of cosmic fate, sent back into ancient times temporarily. How will you exploit this fact to the benefit of humanity?"
|
|
break
|
|
case 47:
|
|
encounter.text = "A secret, cryptographic document of immense knowledge has granted you one super power. However, whatever power you choose has an incredible downside."
|
|
break
|
|
case 48:
|
|
encounter.text = "You have come across a place of incredible significance, however you fail to notice it because of your devil-may-care attitude."
|
|
break
|
|
case 49:
|
|
encounter.text = "Quickly! Untie your shoes and shift them from the left foot to the right foot. This is of utmost importance."
|
|
break
|
|
case 50:
|
|
encounter.text = "A voice is heard in Character's head, \"This is the emergency spell casting broadcast system. Please standby for further instructions.\""
|
|
break
|
|
case 51:
|
|
encounter.text = "A team of mal-intended turkey drones approach!"
|
|
encounter.enemies = [
|
|
createEnemy("Turkey Prime", calculateRoll("5d10+10"), 14, 0, "2d6+3", "d20+2"),
|
|
createEnemy("Turkey Lackey A", calculateRoll("5d10+10"), 14, 0, "2d6+3", "d20+2"),
|
|
createEnemy("Turkey Lackey B", calculateRoll("5d10+10"), 14, 0, "2d6+3", "d20+2"),
|
|
]
|
|
break
|
|
case 52:
|
|
encounter.text = "A calculator is someone who calculates. One such person is here and they mean no good."
|
|
encounter.enemies = [
|
|
createEnemy("The Calculator", calculateRoll("5d8"), 13, 0, "2d4+2", "d20-1", "Calculate Demise1d20")
|
|
]
|
|
break
|
|
case 53:
|
|
encounter.text = "An digitized fountain pen is on its way to write you out of existence!"
|
|
encounter.enemies = [
|
|
createEnemy("Fountain Pen", calculateRoll("6d10+6"), 13, 0, "1d10+2", "d20+3", "Ink Blot2d4+6")
|
|
]
|
|
break
|
|
case 54:
|
|
encounter.text = "Oh no! Your childhood bully has come back and he's joined by a gang of bad dudes."
|
|
encounter.enemies = [
|
|
createEnemy("Bully", calculateRoll("5d10+10"), 12, 0, "1d8", "d20-5"),
|
|
createEnemy("Lackey A", calculateRoll("2d8+2"), 12, 0, "1d8", "d20+1"),
|
|
createEnemy("Lackey B", calculateRoll("2d8+2"), 12, 0, "1d8", "d20+1"),
|
|
createEnemy("Lackey C", calculateRoll("2d8+2"), 12, 0, "1d8", "d20+1"),
|
|
]
|
|
break
|
|
case 55:
|
|
encounter.text = "It's a giant, living pimple and it's ready to burst at you."
|
|
encounter.enemies = [
|
|
createEnemy("Pimple", calculateRoll("4d8+4"), 14, 0, "1d8+2", "d20+1", "Burst Fire3d6")
|
|
]
|
|
break
|
|
case 56:
|
|
encounter.text = "An evil breath fills the room. You must defeat it before you can't breathe anymore."
|
|
encounter.enemies = [
|
|
createEnemy("Evil Breath", calculateRoll("4d10+4"), 14, 0, "2d6+3", "d20+1", "Stank2d10+5")
|
|
]
|
|
break
|
|
case 57:
|
|
encounter.text = "A rocket racoon suddenly appears and slaps you in the face. It's clear that it is challenging you to a duel."
|
|
encounter.enemies = [
|
|
createEnemy("Racoon", calculateRoll("3d10+3"), 13, 0, "1d8+2", "d20+1", "Slap1d5+2")
|
|
]
|
|
break
|
|
case 58:
|
|
encounter.text = "A water bottle sprouts legs. Its unnatural gait betrays it's perverse intentions."
|
|
encounter.enemies = [
|
|
createEnemy("Water Bottle", calculateRoll("2d10+4"), 12, 0, "1d4", "d20-1", "Drench5d3"),
|
|
]
|
|
break
|
|
case 59:
|
|
encounter.text = "A sleeping guard is here. He is alerted once you start farting uncontrollably."
|
|
encounter.enemies = [
|
|
createEnemy("Guard", calculateRoll("3d10+3"), 14, 0, "1d8+2", "d20+2", "Yawn")
|
|
]
|
|
break
|
|
case 60:
|
|
encounter.text = "Your best friend from way back has come around. Sadly you have nothing in common with each other and now you're at odds."
|
|
encounter.enemies = [
|
|
createEnemy("Best Friend", calculateRoll("3d10+3"), 14, 0, "2d4+4", "d20+4"),
|
|
createEnemy("Your Replacement", calculateRoll("5d6"), 14, 0, "1d8+1", "d20+2"),
|
|
createEnemy("The New Bestie", calculateRoll("5d6"), 14, 0, "1d8+1", "d20+2"),
|
|
]
|
|
break
|
|
case 61:
|
|
encounter.text = "Your shadow has become jealous of all that moving around freely thing you do. It attacks!"
|
|
encounter.enemies = [
|
|
createEnemy("Shadow", calculateRoll("4d10"), 14, 0, "1d6+2", "d20+3")
|
|
]
|
|
break
|
|
case 62:
|
|
encounter.text = "You encounter an accident prone ninja! It clumsily brandishes its energy weapon but sends it clattering onto the floor before it. The ninja apologizes profusely as it scrambles back into attack position."
|
|
encounter.enemies = [
|
|
createEnemy("Ninja", calculateRoll("6d10+12"), 14, 0, "2d6+3", "d20+2", "Shuriken3d6+3")
|
|
]
|
|
break
|
|
case 63:
|
|
encounter.text = "The AI Dungeon has become sentient and sends its minions forth to destroy you!"
|
|
encounter.enemies = [
|
|
createEnemy("Mixtral", calculateRoll("3d10+3"), 12, 0, "2d6+1", "d20+2"),
|
|
createEnemy("MythoMax", calculateRoll("2d6"), 12, 0, "1d4+2", "d20+2"),
|
|
createEnemy("Wizard", calculateRoll("2d6"), 12, 0, "1d4+2", "d20+2"),
|
|
createEnemy("Pegasus", calculateRoll("2d6"), 12, 0, "1d4+2", "d20+2")
|
|
]
|
|
break
|
|
case 64:
|
|
encounter.text = "The evil hacker has conjured enemies to slay you. He did not send his best."
|
|
encounter.enemies = [
|
|
createEnemy("Enthusiastic Intern", calculateRoll("6d10+6"), 10, 0, "1d10+2", "d20+1"),
|
|
createEnemy("Retirement Aged Fighter", calculateRoll("6d10+6"), 10, 0, "1d10+2", "d20+1"),
|
|
createEnemy("A Common Fool", calculateRoll("6d10+6"), 10, "1d10+2", 0, "d20+1", "Contagious Laughter")
|
|
]
|
|
break
|
|
case 65:
|
|
encounter.text = "The Grammar Nazis attck in fool force!"
|
|
encounter.enemies = [
|
|
createEnemy("Grammar Nazi A", calculateRoll("2d8"), 13, 0, "1d4+3", "d20+3", "Correct Grammar"),
|
|
createEnemy("Grammar Nazi B", calculateRoll("2d8"), 13, 0, "1d4+3", "d20+3", "Correct Grammar"),
|
|
createEnemy("Grammar Nazi C", calculateRoll("2d8"), 13, 0, "1d4+3", "d20+3", "Correct Grammar")
|
|
]
|
|
break
|
|
case 66:
|
|
encounter.text = "The mini-people have contracted their deadliest assassin to assault you. The twelve-inch pianist is on the move!"
|
|
encounter.enemies = [
|
|
createEnemy("Pianist", calculateRoll("5d10+10"), 12, 0, "2d6+3", "d20+2", "Deadly Tune5d4")
|
|
]
|
|
break
|
|
case 67:
|
|
encounter.text = "Take it easy this time. A rude tortoise is slowly coming this way and it has foul plans for the party."
|
|
encounter.enemies = [
|
|
createEnemy("Rude Tortoise", calculateRoll("5d10+10"), 11, 0, "2d6+3", "d20+2", "Shell Up")
|
|
]
|
|
break
|
|
case 68:
|
|
encounter.text = "The ninja-mime attacks! Why won't he say anything?"
|
|
encounter.enemies = [
|
|
createEnemy("Ninja Mime", calculateRoll("2d6"), 15, 0, "1d6+2", "d20+2", "Pantomime3d6")
|
|
]
|
|
break
|
|
case 69:
|
|
encounter.text = "A disgusting fashion faux pas presents itself in front of the party. Defend yourself."
|
|
encounter.enemies = [
|
|
createEnemy("Ill Fitting Clothes", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2"),
|
|
createEnemy("Color Clash", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2"),
|
|
createEnemy("Pleated Pants", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2"),
|
|
createEnemy("Black and White Stripes", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2")
|
|
]
|
|
break
|
|
case 70:
|
|
encounter.text = "A miserable plate of unfinished food reveals itself. \"Waste not, want not,\" it says menacingly."
|
|
encounter.enemies = [
|
|
createEnemy("Food Plate", calculateRoll("2d8+2"), 12, 0, "1d6+1", "d20+1", "Glutton")
|
|
]
|
|
break
|
|
case 71:
|
|
encounter.text = "A spork is a multifunctional utensil. It turns its malicious gaze towards you."
|
|
encounter.enemies = [
|
|
createEnemy("Spork", calculateRoll("2d8+2"), 16, 0, "1d8+1", "d20+1", "Transform into Fork", "Transform into Spoon")
|
|
]
|
|
break
|
|
case 72:
|
|
encounter.text = "An angry mother-in-law nags into your general area."
|
|
encounter.enemies = [
|
|
createEnemy("Mother-In-Law", calculateRoll("6d10+18"), 13, 0, "2d10+4", "d20+1", "Nag", "Verbal Assault3d10")
|
|
]
|
|
break
|
|
case 73:
|
|
encounter.text = "A squad of trick motorcyclists wheel into your area! They're doing dastardly maneuvers in front of your face."
|
|
encounter.enemies = [
|
|
createEnemy("Motorcyclist A", calculateRoll("6d10+12"), 12, 0, "2d6+4", "d20+2", "Trick"),
|
|
createEnemy("Motorcyclist B", calculateRoll("6d10+12"), 12, 0, "2d6+4", "d20+2", "Trick"),
|
|
createEnemy("Motorcyclist C", calculateRoll("6d10+12"), 12, 0, "2d6+4", "d20+2", "Trick"),
|
|
createEnemy("Ring Leader", calculateRoll("7d8+21"), 15, 0, "1d6+2", calculateRoll("d20"), "Command")
|
|
]
|
|
break
|
|
case 74:
|
|
encounter.text = "Some stressed out people are here and they misinterpret your casual greeting as a taunt. Emotions are on high."
|
|
encounter.enemies = [
|
|
createEnemy("Angry Guy", calculateRoll("8d12+8"), 12, 0, "2d8+4", "d20+2"),
|
|
createEnemy("Stressed Pal", calculateRoll("8d12+8"), 12, 0, "2d8+4", "d20+2"),
|
|
createEnemy("The Instigator", calculateRoll("8d12+8"), 12, 0, "2d8+4", calculateRoll("d20+10"), "Instigate"),
|
|
]
|
|
break
|
|
case 75:
|
|
encounter.text = "An ominous stop sign is placed here at odds with your sensibility. It directs you to cease moving at once."
|
|
encounter.enemies = [
|
|
createEnemy("Stop Sign", calculateRoll("6d8"), 14, 0, "2d6+2", "d20+2", "Red Light", "Green Light")
|
|
]
|
|
break
|
|
case 76:
|
|
encounter.text = "Elliot Carver, the villain from Tomorrow Never Dies, ridicules your martial ability. You will not let this stand."
|
|
encounter.enemies = [
|
|
createEnemy("Elliot Carver", calculateRoll("6d10+12"), 12, 0, "2d8+4", "d20+1", "Berate3d10"),
|
|
createEnemy("Goon A", calculateRoll("3d10+3"), 11, 0, "3d10+5", "d20-1"),
|
|
createEnemy("Goon B", calculateRoll("3d10+3"), 11, 0, "3d10+5", "d20-1"),
|
|
]
|
|
break
|
|
case 77:
|
|
encounter.text = "So, you accidentally punched yourself while carrying a load and picking up something off the ground at the same time. Pissed off, you decide to fight yourself."
|
|
encounter.enemies = [
|
|
createEnemy("Yourself", calculateRoll("6d8+18"), 15, 0, "1d6+3", "d20+3")
|
|
]
|
|
break
|
|
case 78:
|
|
encounter.text = "A suspension of bad feelings waddles toward you. You have no choice but to take to arms."
|
|
encounter.enemies = [
|
|
createEnemy("Sad", calculateRoll("6d10+12"), 8, 0, "2d6+2", "d20-2"),
|
|
createEnemy("Mad", calculateRoll("6d10+12"), 8, 0, "2d6+3", "d20-2"),
|
|
createEnemy("Depressed", calculateRoll("6d10+12"), 8, 0, "2d6+3", "d20-2"),
|
|
createEnemy("Upset", calculateRoll("6d10+12"), 8, 0, "2d6+3", "d20-2")
|
|
]
|
|
break
|
|
case 79:
|
|
encounter.text = "A gambler is here. Feeling cheated, he directs his misfortune at you."
|
|
encounter.enemies = [
|
|
createEnemy("A gambler", calculateRoll("7d10+21"), 13, 0, "2d8+5", "d20+1", "Even the Odds")
|
|
]
|
|
break
|
|
case 80:
|
|
encounter.text = "You know how they say, \"You miss 100% of the shots you don't take?\" Well here's that shot you didn't take."
|
|
encounter.enemies = [
|
|
createEnemy("The Shot", calculateRoll("5d10+5"), 13, 0, "1d10+2", "d20+2")
|
|
]
|
|
break
|
|
case 81:
|
|
encounter.text = "You know how they say, \"The path to hell is paved with good intentions?\" Here are those good intentions."
|
|
encounter.enemies = [
|
|
createEnemy("Good Intention A", calculateRoll("6d8+12"), 14, 0, "1d6-1", "d20+2"),
|
|
createEnemy("Good Intention B", calculateRoll("6d8+12"), 14, 0, "1d6-1", "d20+2"),
|
|
createEnemy("Good Intention C", calculateRoll("6d8+12"), 14, 0, "1d6-1", "d20+2")
|
|
]
|
|
break
|
|
case 82:
|
|
encounter.text = "It's the AI from AI Dungeon! Man your battle stations."
|
|
encounter.enemies = [
|
|
createEnemy("AI", calculateRoll("5d10+10"), 12, 0, "2d4+2", "d20+1", "Hallucinate")
|
|
]
|
|
break
|
|
case 83:
|
|
encounter.text = "You shouldn't have kicked that puppy when you were a kid because it's all grown up and it remembers."
|
|
encounter.enemies = [
|
|
createEnemy("Vengeance Dog", calculateRoll("6d8+18"), 14, 0, "1d8+2", "d20+2", "Intimidating Growl")
|
|
]
|
|
break
|
|
case 84:
|
|
encounter.text = "Hah! You're screwed now! Your worst fear is actualized in front of you. It's a thing!"
|
|
encounter.enemies = [
|
|
createEnemy("Thing You Fear Most", calculateRoll("10d10+20"), 13, 0, "2d6+4", "d20+1", "Morph")
|
|
]
|
|
break
|
|
case 85:
|
|
encounter.text = "Well, if it isn't the consequences of your actions."
|
|
encounter.enemies = [
|
|
createEnemy("Consequence A", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2"),
|
|
createEnemy("Consequence B", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2"),
|
|
createEnemy("Consequence C", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2"),
|
|
createEnemy("Consequence D", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2"),
|
|
createEnemy("Consequence E", calculateRoll("3d8+9"), 8, 0, "1d6+1", "d20-2")
|
|
]
|
|
break
|
|
case 86:
|
|
encounter.text = "A thousand armies of the Persian empire descend upon you. They will drink the rivers dry. Their arrows will blot out the sun."
|
|
encounter.enemies = [
|
|
createEnemy("One Thousand", calculateRoll("8d12+16"), 15, 0, "4d6+4", calculateRoll("d20")),
|
|
createEnemy("Two Thousand", calculateRoll("8d12+16"), 15, 0, "4d6+4", calculateRoll("d20")),
|
|
createEnemy("Three Thousand", calculateRoll("8d12+16"), 15, 0, "4d6+4", calculateRoll("d20"))
|
|
]
|
|
break
|
|
case 87:
|
|
encounter.text = "The embodiment of really poor decisions and a hangover approaches you in a disturbing pattern."
|
|
encounter.enemies = [
|
|
createEnemy("Hangover", calculateRoll("8d8+16"), 15, 0, "2d6+3", "d20-1", "Head Pain3d6"),
|
|
createEnemy("Poor Decision A", calculateRoll("8d8+16"), 15, 0, "2d6+3", "d20-1"),
|
|
createEnemy("Poor Decision B", calculateRoll("8d8+16"), 15, 0, "2d6+3", "d20-1")
|
|
]
|
|
break
|
|
case 88:
|
|
encounter.text = "An annoying sales-person is using hard-sale tactics at you. Resist!"
|
|
encounter.enemies = [
|
|
createEnemy("Sales-Person", calculateRoll("8d8+16"), 14, 0, "1d6+4", "d20+4", "Big Sale")
|
|
]
|
|
break
|
|
case 89:
|
|
encounter.text = "A group of Reddit mods are here. This is not a good sign."
|
|
encounter.enemies = [
|
|
createEnemy("Reddit Mod A", calculateRoll("2d6"), 12, 0, "1d4+2", "d20+2"),
|
|
createEnemy("Reddit Mod B", calculateRoll("2d6"), 12, 0, "1d4+2", "d20+2"),
|
|
createEnemy("Reddit Mod C", calculateRoll("2d6"), 12, 0, "1d4+2", "d20+2"),
|
|
createEnemy("Reddit Mod D", calculateRoll("2d6"), 12, 0, "1d4+2", "d20+2"),
|
|
createEnemy("Grand Reddit Mod", calculateRoll("7d10+14"), 15, 0, "1d10+2", "d20+1")
|
|
]
|
|
break
|
|
case 90:
|
|
encounter.text = "An expert in bulshiddo beckoms toward you. You have no other choice but to engage."
|
|
encounter.enemies = [
|
|
createEnemy("Bulshiddo Expert", calculateRoll("7d10+14"), 15, 0, "1d10+2", "d20+1", "Focus Chit")
|
|
]
|
|
break
|
|
case 91:
|
|
encounter.text = "You know how they say \"Hope springs eternal?\" Well, Hope is springing her way to your direction."
|
|
encounter.enemies = [
|
|
createEnemy("Hope", calculateRoll("7d8+14"), 15, 0, "1d8+3", "d20+1", "Spring Eternal5d4")
|
|
]
|
|
break
|
|
case 92:
|
|
encounter.text = "An immodest pixie points and laughs at you. She thinks you're funny looking. Battle is inevitable."
|
|
encounter.enemies = [
|
|
createEnemy("Pixie", calculateRoll("12d12+12"), 12, 0, "2d6+3", calculateRoll("d20"), "Shameless Magic2d10")
|
|
]
|
|
break
|
|
case 93:
|
|
encounter.text = "A touring squad of basketball players send a stray rebound right to your head. It's on now!"
|
|
encounter.enemies = [
|
|
createEnemy("Scottie P", calculateRoll("6d10+12"), 8, 0, "2d6+2", "d20-2"),
|
|
createEnemy("M Jordan", calculateRoll("6d10+12"), 8, 0, "2d6+2", "d20-2"),
|
|
createEnemy("L Bird", calculateRoll("6d10+12"), 8, 0, "2d6+2", "d20-2"),
|
|
createEnemy("Magic J", calculateRoll("6d10+12"), 8, 0, "2d6+2", "d20-2"),
|
|
createEnemy("C Barkley", calculateRoll("6d10+12"), 8, 0, "2d6+2", "d20-2"),
|
|
]
|
|
break
|
|
case 94:
|
|
encounter.text = "What happens if you fight the void? Let's see."
|
|
encounter.enemies = [
|
|
createEnemy("The Void", calculateRoll("5d10+5"), 13, 0, "1d10+2", "d20+2", "Darkness")
|
|
]
|
|
break
|
|
case 95:
|
|
encounter.text = "Oh god, I've written so many encounters at this point. Just use your imagination."
|
|
encounter.enemies = [
|
|
createEnemy("Your Imagination", calculateRoll("6d8+12"), 14, 0, "1d6-1", "d20+2", "Detect Thoughts")
|
|
]
|
|
break
|
|
case 96:
|
|
encounter.text = "A tachometer is revving up!"
|
|
encounter.enemies = [
|
|
createEnemy("Tachometer", calculateRoll("5d10+10"), 14, 0, "2d6+3", "d20+2", "Accelerate")
|
|
]
|
|
break
|
|
case 97:
|
|
encounter.text = "Taco Tuesdays are back and with a serious vengeance."
|
|
encounter.enemies = [
|
|
createEnemy("Taco Tuesday A", calculateRoll("9d8+18"), 11, 0, "1d6+2", "d20+1", "Diarrhea3d10"),
|
|
createEnemy("Taco Tuesday B", calculateRoll("9d8+18"), 11, 0, "1d6+2", "d20+1", "Diarrhea3d10")
|
|
]
|
|
break
|
|
case 98:
|
|
encounter.text = "There's like one dude screaming here. It's not clear who he's yelling at or why. Can you please shut him up?"
|
|
encounter.enemies = [
|
|
createEnemy("Screaming Dude", calculateRoll("5d10+10"), 14, 0, "2d6+3", "d20+2", "Scream")
|
|
]
|
|
break
|
|
case 99:
|
|
encounter.text = "Magneto has somehow entered your world. He blames you for this injustice."
|
|
encounter.enemies = [
|
|
createEnemy("Magneto", calculateRoll("6d8+18"), 14, 0, "1d8+2", "d20+2", "Manipulate Metal", "Shield"),
|
|
createEnemy("The Juggernaut", calculateRoll("6d8+18"), 14, 0, "1d8+2", "d20+2", "Charge3d10"),
|
|
createEnemy("Sabretooth", calculateRoll("6d8+18"), 14, 0, "1d8+2", "d20+2"),
|
|
]
|
|
break
|
|
case 100:
|
|
encounter.text = "A banker has come to collect on your debts."
|
|
encounter.enemies = [
|
|
createEnemy("The Banker", calculateRoll("10d10+20"), 13, 0, "2d6+4", "d20+1", "Prisoner's Dilemma", "PMT Function3d6", "Tax Break")
|
|
]
|
|
break
|
|
case 101:
|
|
encounter.text = "The mouse from If You Give a Mouse a Cookie... Attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Mouse", calculateRoll("10d10+20"), 13, 0, "2d6+4", "d20+1", "Take Cookie")
|
|
]
|
|
}
|
|
break
|
|
case "easy":
|
|
if (encounter.cr == null) encounter.cr = 1
|
|
multiplier = 1 + (encounter.cr - 1) / 10
|
|
switch (getRandomInteger(0, 99)) {
|
|
case 0:
|
|
encounter.text = "There is a curious contraption encasing what appears to be a small crate of goods."
|
|
break
|
|
case 1:
|
|
encounter.text = "A crashed escape pod is before you. You see that motion trackers are active, watching for unauthorized entry."
|
|
break
|
|
case 2:
|
|
encounter.text = "You've found notes from a rogue scientist that claim they were working on a cure for the nano-necrotic virus."
|
|
break
|
|
case 3:
|
|
encounter.text = "A radio transmitter of unknown origin is here. It's sending out some sort of code."
|
|
break
|
|
case 4:
|
|
encounter.text = "You encounter a group of survivors that claim they can control the zombies with a chip that is surgically implanted in the brain."
|
|
break
|
|
case 5:
|
|
encounter.text = "It looks like a scavenger's stash was left here."
|
|
break
|
|
case 6:
|
|
encounter.text = "A harmless drone is spotted rolling around in circles."
|
|
break
|
|
case 7:
|
|
encounter.text = "Canned goods and supplies for everyone! What is this doing here?"
|
|
break
|
|
case 8:
|
|
encounter.text = "There is rubble from a once great building that stood here. There is a possibility that supplies or tech can be found here."
|
|
break
|
|
case 9:
|
|
encounter.text = "The surface has been obliterated by what appears to have been a missile strike. However, an entrance to an underground parking structure remains."
|
|
break
|
|
case 10:
|
|
encounter.text = "A group of travelling traders approach with open hands indicating that they come in peace."
|
|
break
|
|
case 11:
|
|
encounter.text = "A broken soldier is pinned under the debris of a recent explosion. \"Help!\" he exclaims."
|
|
break
|
|
case 12:
|
|
encounter.text = "A pile of bodies meticulously arranged into a geometric pattern almost in the shape of a pyramid. This must have been recent."
|
|
break
|
|
case 13:
|
|
encounter.text = "Amongst the trash you miraculously find a fully functional PDA. When you charge it up, you see a live feed of some scientific facility. Suddenly, you notice movement."
|
|
break
|
|
case 14:
|
|
encounter.text = "A drone puppy excitedly dashes towards you. You may very well be the first person its seen in decades."
|
|
break
|
|
case 15:
|
|
encounter.text = "A well known electronics chain store stands before you."
|
|
break
|
|
case 16:
|
|
encounter.text = "Someone left a series of explosive munitions here."
|
|
break
|
|
case 17:
|
|
encounter.text = "A missile battery is stationed here. It seems to have been constructed post-apocalypse."
|
|
break
|
|
case 18:
|
|
encounter.text = "A humonoid robot stands motionless in front of you. When it notices your presence, it shouts \"Greetings traveller!\""
|
|
break
|
|
case 19:
|
|
encounter.text = "Abandoned cars have been arranged in a circle with bodies littered everywhere. Apparently this was someone's last stand before they were overwhelmed."
|
|
break
|
|
case 20:
|
|
encounter.text = "You found a data node detailing various body modifications that have been spotted on zombies in the area. Who is responsible for this?"
|
|
break
|
|
case 21:
|
|
encounter.text = "A group of heli drones are assaulting a building in the distance. It appears that whatever threat they were responding to has been gone for a long time. They don't pay any attention to you."
|
|
break
|
|
case 22:
|
|
encounter.text = "A passage to an underground bunker is spotted here. It is locked by a data pad and the door is reinforced against explosives."
|
|
break
|
|
case 23:
|
|
encounter.text = "A house with steel shutters over the windows and make-shift defenses can be seen in the distance. Someone spent a lot of time to make this building impenetrable."
|
|
break
|
|
case 24:
|
|
encounter.text = "A twenty-foot wide pit is before you. It seems to lead straight down to some endless depth. What could create such a hole?"
|
|
break
|
|
case 25:
|
|
encounter.text = "Giant excavation machines have been left here. Whoever was here was looking for something. Did they find it?"
|
|
break
|
|
case 26:
|
|
encounter.text = "A military supply drop has been found. It doesn't seem like anyone has opened it because the cryptographic lock looks untouched."
|
|
break
|
|
case 27:
|
|
encounter.text = "Suddenly, a flying drone approaches! You stand at guard, but for some reason all it does is deliver a package on the ground and leaves without incident."
|
|
break
|
|
case 28:
|
|
encounter.text = "You receive an abrupt radio transmission. \"We are in desperate need of supplies! We're trapped here. Is anyone out there?\""
|
|
break
|
|
case 29:
|
|
encounter.text = "A computer system installed here seems completely out of place. You hear an audio playback \"Satellite uplink initiated.\""
|
|
break
|
|
case 30:
|
|
encounter.text = "Graffiti covers the walls of this ruined building. \"The doom sayer is coming!\""
|
|
break
|
|
case 31:
|
|
encounter.text = "You have found a used food recycler."
|
|
break
|
|
case 32:
|
|
encounter.text = "It seems that two groups of survivors came at odds against each other here. Before you lays the aftermath. A muffled voice can be heard."
|
|
break
|
|
case 33:
|
|
encounter.text = "After rounding a corner, you discover a curiousity. A decapitated robot is repeating the words \"The sovereign! The sovereign!\" What does it mean?"
|
|
break
|
|
case 34:
|
|
encounter.text = "A broken exo-suit has been situated in a pod in front of you. Can it be repaired or should it be salvaged for parts?"
|
|
break
|
|
case 35:
|
|
encounter.text = "A holographic map displays points of interest in the local area. There are notes about what places should be avoided."
|
|
break
|
|
case 36:
|
|
encounter.text = "Batteries of all shapes and sizes are scattered across the surface here."
|
|
break
|
|
case 37:
|
|
encounter.text = "You see someone in the distance. It looks like they're picking through some rubble trying to find valuables."
|
|
break
|
|
case 38:
|
|
encounter.text = "Without warning, a craft shoots across the air. Its air vortex knocks you off your feet. Where was it going and who pilots it?"
|
|
break
|
|
case 39:
|
|
encounter.text = "The crops in the local area have been melted by some intense heat. Whatever it was that caused this was alien in origin."
|
|
break
|
|
case 40:
|
|
encounter.text = "There is what looks to be a communicator in front of you. The buttons are labeled in a strange language you are not familiar with."
|
|
break
|
|
case 41:
|
|
encounter.text = "Something catches your eye at a distance, but when you turn it darts out of visible range. You're being followed."
|
|
break
|
|
case 42:
|
|
encounter.text = "You have found a shopping catalog listing cybernetic upgrades of a dubious nature. It is attached to a shipping crate."
|
|
break
|
|
case 43:
|
|
encounter.text = "There is a large crate with bold text emblazened on its front \"FRAGILE DO NOT DROP\""
|
|
break
|
|
case 44:
|
|
encounter.text = "You hear music. Music! And it is not a song you recognize from the Citadel's catalog."
|
|
break
|
|
case 45:
|
|
encounter.text = "A group of survivors are sitting around a campfire. They haven't noticed you yet."
|
|
break
|
|
case 46:
|
|
encounter.text = "Pre-war military vehicles have been seen here at a distance. By indication of the tracks, they appear to be heading away from you."
|
|
break
|
|
case 47:
|
|
encounter.text = "You find yourself in a junk heap. Most of it is unusable, however you come across the unmistakable parts to a VTOL craft."
|
|
break
|
|
case 48:
|
|
encounter.text = "A deactivated hovercraft is here. By cursory glance, the only thing missing is the control unit."
|
|
break
|
|
case 49:
|
|
encounter.text = "You spot the typical pre-war propaganda poster: \"Join the worthy cause! The VTOL Knights need you!\" However, a corner is curled up reavealing something written on the backside."
|
|
break
|
|
case 50:
|
|
encounter.text = "You stumble across a data log labeled \"Chief Engineer - Military Operations\""
|
|
break
|
|
case 50:
|
|
encounter.text = "The zombie reveals itself! It's unlike the others as it is a solitary hunter. This one has been stalking you for some time."
|
|
encounter.enemies = [
|
|
createEnemy("Stalker Zombie", calculateRoll("5d8"), 12, 4, "1d10", "d20+2", "Life Drain1d10")
|
|
]
|
|
break
|
|
case 51:
|
|
encounter.text = "A cleaning drone approaches. Clearly its programming has been corrupted as it now tries to attack you."
|
|
encounter.enemies = [
|
|
createEnemy("Cleaning Drone", calculateRoll("2d+6"), 9, -3, "1d4-1", "d20-1")
|
|
]
|
|
break
|
|
case 52:
|
|
encounter.text = "Desperate survivors have ambushed you! They want to take your gear and supplies."
|
|
encounter.enemies = [
|
|
createEnemy("Survivor A", calculateRoll("5d8+10"), 11, 6, "1d6+2", "d20"),
|
|
createEnemy("Survivor B", calculateRoll("5d8+10"), 11, 6, "1d6+2", "d20"),
|
|
createEnemy("Survivor C", calculateRoll("5d8+10"), 11, 6, "1d6+2", "d20")
|
|
]
|
|
break
|
|
case 53:
|
|
encounter.text = "A damaged robot is here. Despite your efforts, itt seems to consider you as a threat."
|
|
encounter.enemies = [
|
|
createEnemy("Damaged Robot", calculateRoll("3d8+6"), 11, 6, "2d4+2", "d20")
|
|
]
|
|
break
|
|
case 54:
|
|
encounter.text = "An boar bot is charging at you!"
|
|
encounter.enemies = [
|
|
createEnemy("Boar Bot", calculateRoll("2d8+2"), 11, 4, "1d6+1", "d20")
|
|
]
|
|
break
|
|
case 55:
|
|
encounter.text = "Two vultures circle and then descend upon you. These are rogue holograms from a nature simulation long since corrupted."
|
|
encounter.enemies = [
|
|
createEnemy("Vulture A", calculateRoll("6d6+6"), 11, 1, "1d4+1", "d20+1", "Infected Bite1d4+1"),
|
|
createEnemy("Vulture B", calculateRoll("6d6+6"), 11, 1, "1d4+1", "d20+1", "Infected Bite1d4+1")
|
|
]
|
|
break
|
|
case 56:
|
|
encounter.text = "You've fallen into a pit of snake drones. A group of them slither up to you, winding up to strike."
|
|
encounter.enemies = [
|
|
createEnemy("Snake Drone A", calculateRoll("2d10+2"), 12, 6, "1d8+2", "d20+2", "Poison Bite2d4+1"),
|
|
createEnemy("Snake Drone B", calculateRoll("2d10+2"), 12, 6, "1d8+2", "d20+2", "Poison Bite2d4+1")
|
|
]
|
|
break
|
|
case 57:
|
|
encounter.text = "A hunter killer robot has caught your scent. It's going to make its move!"
|
|
encounter.enemies = [
|
|
createEnemy("HK Robot", calculateRoll("5d10+10"), 14, 8, "2d6+3", "d20+2")
|
|
]
|
|
break
|
|
case 58:
|
|
encounter.text = "The remarkable pattern on the skin of this alien frog is a clear indication that it's poisonous. Watch out!"
|
|
encounter.enemies = [
|
|
createEnemy("Alien Frog", calculateRoll("4d8"), 11, 4, "1d6+1", "d20+1", "Poison2d4+1")
|
|
]
|
|
break
|
|
case 59:
|
|
encounter.text = "You've come across a graveyard of robots. Rows and rows of deactivated machines. Except for one which suddenly turns to strike!"
|
|
encounter.enemies = [
|
|
createEnemy("Sentinel Robot", calculateRoll("7d8+21"), 15, 6, "1d6+2", "d20")
|
|
]
|
|
break
|
|
case 60:
|
|
encounter.text = "Many innocents were slain here. Their bodies have been thrown into a pile. Then you notice their bodies begin to move. Zombies attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Zombie A", calculateRoll("5d8"), 12, 3, "2d6+2", "d20+2"),
|
|
createEnemy("Zombie B", calculateRoll("5d8"), 12, 3, "2d6+2", "d20+2"),
|
|
createEnemy("Zombie C", calculateRoll("5d8"), 12, 3, "2d6+2", "d20+2"),
|
|
createEnemy("Zombie D", calculateRoll("5d8"), 12, 3, "2d6+2", "d20+2")
|
|
]
|
|
break
|
|
case 61:
|
|
encounter.text = "A cyborg warrior has claimed this plot of land and he'll be damned if he lets the likes of you tread all over it."
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg Warrior", calculateRoll("2d8+4"), 10, 4, "1d6+1", "d20")
|
|
]
|
|
break
|
|
case 62:
|
|
encounter.text = "A robotic centipede crawls into view. Its terrifying shriek makes your skin crawl. Prepare yourself!"
|
|
encounter.enemies = [
|
|
createEnemy("Robo Centipede", calculateRoll("1d6+1"), 13, 1, "1d4+2", "d20+2")
|
|
]
|
|
break
|
|
case 63:
|
|
encounter.text = "A feral pack of dog drones have nested here. They smell your blood..."
|
|
encounter.enemies = [
|
|
createEnemy("Dog A", calculateRoll("1d8+1"), 11, 2, "1d6", "d20+1"),
|
|
createEnemy("Dog B", calculateRoll("1d8+1"), 11, 2, "1d6", "d20+1"),
|
|
createEnemy("Giant Dog", calculateRoll("6d10+12"), 12, 5, "2d6+3", "d20+2")
|
|
]
|
|
break
|
|
case 64:
|
|
encounter.text = "A swarm of micro cleaning bots are sweeping across the ground and heading toward you!"
|
|
encounter.enemies = [
|
|
createEnemy("Swarm of cleaning bots", calculateRoll("7d8-7"), 10, 1, "2d6", "d20")
|
|
]
|
|
break
|
|
case 65:
|
|
encounter.text = "A group of helibots have coalesced here. Your arrival has activated their proximity alert."
|
|
encounter.enemies = [
|
|
createEnemy("Helibot A", calculateRoll("5d8"), 15, 6, "1d8+2", "d20+1"),
|
|
createEnemy("Helibot B", calculateRoll("5d8"), 15, 6, "1d8+2", "d20+1"),
|
|
createEnemy("Helibot C", calculateRoll("5d8"), 15, 6, "1d8+2", "d20+1")
|
|
]
|
|
break
|
|
case 66:
|
|
encounter.text = "The group of zombies are as surprised to see you as you are to see them. Get ready!"
|
|
encounter.enemies = [
|
|
createEnemy("Zombie A", calculateRoll("2d6"), 15, 3, "1d6+2", "d20+2"),
|
|
createEnemy("Zombie B", calculateRoll("2d6"), 15, 3, "1d6+2", "d20+2"),
|
|
createEnemy("Zombie C", calculateRoll("2d6"), 15, 3, "1d6+2", "d20+2"),
|
|
createEnemy("Zombie D", calculateRoll("2d6"), 15, 3, "1d6+2", "d20+2")
|
|
]
|
|
break
|
|
case 67:
|
|
encounter.text = "A sweet lullaby carries through the air. You are enchanted by its melody. But wait! It's a grey's luring transmission. Resist!"
|
|
encounter.enemies = [
|
|
createEnemy("Grey", calculateRoll("7d8+7"), 11, 4, "2d4+1", "d20+1", "Luring Song")
|
|
]
|
|
break
|
|
case 68:
|
|
encounter.text = "You spot a cannibal crouched over his rifle. As he loads his weapon, he menaces at you, \"You shouldn't have come here, meat.\""
|
|
encounter.enemies = [
|
|
createEnemy("Cannibal", calculateRoll("2d8+2"), 18, 4, "1d8+1", "d20+1")
|
|
]
|
|
break
|
|
case 69:
|
|
encounter.text = "A group of small zombies surround and attack you!"
|
|
encounter.enemies = [
|
|
createEnemy("Small Zombie A", calculateRoll("2d6-2"), 12, 2, "1d4+2", "d20+2"),
|
|
createEnemy("Small Zombie B", calculateRoll("2d6-2"), 12, 2, "1d4+2", "d20+2"),
|
|
createEnemy("Small Zombie C", calculateRoll("2d6-2"), 12, 2, "1d4+2", "d20+2"),
|
|
createEnemy("Small Zombie D", calculateRoll("2d6-2"), 12, 2, "1d4+2", "d20+2")
|
|
]
|
|
break
|
|
case 70:
|
|
encounter.text = "A dominated soldier has come into view. Some dark entity must have hacked his neocortex!"
|
|
encounter.enemies = [
|
|
createEnemy("Soldier", calculateRoll("5d8"), 15, 4, "1d8+2", "d20+3")
|
|
]
|
|
break
|
|
case 71:
|
|
encounter.text = "A drone sniper has the drop on you! It fires a blast that very narrowly misses its mark. Get ready for a fight!"
|
|
encounter.enemies = [
|
|
createEnemy("Drone Sniper", calculateRoll("2d8+4"), 13, 5, "1d6+2", "d20+2")
|
|
]
|
|
break
|
|
case 72:
|
|
encounter.text = "Alien like birds peck at the ground ahead of you. That's when they spot you."
|
|
encounter.enemies = [
|
|
createEnemy("Alien Bird A", calculateRoll("1d4"), 14, 2, "1d4+3", "d20+1", "Blood Drain2d4+6"),
|
|
createEnemy("Alien Bird B", calculateRoll("1d4"), 14, 2, "1d4+3", "d20+1", "Blood Drain2d4+6"),
|
|
createEnemy("Alien Bird C", calculateRoll("1d4"), 14, 2, "1d4+3", "d20+1", "Blood Drain2d4+6")
|
|
]
|
|
break
|
|
case 73:
|
|
encounter.text = "You have never seen a zombie this large before. Its snarling teeth glint in the light."
|
|
encounter.enemies = [
|
|
createEnemy("Large Zombie", calculateRoll("4d10+4"), 13, 8, "2d6+3", "d20+1")
|
|
]
|
|
break
|
|
case 74:
|
|
encounter.text = "Everywhere you look... Zombies! You are surrounded as they shuffle towards you, drawn by the heat of your flesh."
|
|
encounter.enemies = [
|
|
createEnemy("Zombie A", calculateRoll("3d8+9"), 8, 4, "1d6+1", "d20-2"),
|
|
createEnemy("Zombie B", calculateRoll("3d8+9"), 8, 4, "1d6+1", "d20-2"),
|
|
createEnemy("Zombie C", calculateRoll("3d8+9"), 8, 4, "1d6+1", "d20-2"),
|
|
createEnemy("Zombie D", calculateRoll("3d8+9"), 8, 4, "1d6+1", "d20-2"),
|
|
createEnemy("Zombie E", calculateRoll("3d8+9"), 8, 4, "1d6+1", "d20-2")
|
|
]
|
|
break
|
|
case 75:
|
|
encounter.text = "Your arrival has interrupted a hacker's ritual. His eyes go steely as he plans his retribution."
|
|
encounter.enemies = [
|
|
createEnemy("Hacker", calculateRoll("2d8"), 10, 2, "1d4", "d20", "Fire Sale2d6", "Mind Hack")
|
|
]
|
|
break
|
|
case 76:
|
|
encounter.text = "A bandit duo eyes your gear. A combination of greed and desperation drive them to attack you."
|
|
encounter.enemies = [
|
|
createEnemy("Bandit A", calculateRoll("5d8+10"), 11, 6, "1d6+2", "d20"),
|
|
createEnemy("Bandit B", calculateRoll("5d8+10"), 11, 6, "1d6+2", "d20")
|
|
]
|
|
break
|
|
case 77:
|
|
encounter.text = "A crowd of cultists walk into view. Their aim is clear: to sacrifice you as an offering to the zombies. Attack before you are torn limb from limb!"
|
|
encounter.enemies = [
|
|
createEnemy("Cultist A", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1"),
|
|
createEnemy("Cultist B", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1"),
|
|
createEnemy("Cultist C", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1")
|
|
]
|
|
break
|
|
case 78:
|
|
encounter.text = "A mutant cow has strayed from its herd. You take the opportunity to attack before it alerts the others."
|
|
encounter.enemies = [
|
|
createEnemy("Mutant Cow", calculateRoll("5d8"), 15, 4, "1d4+2", "d20+1")
|
|
]
|
|
break
|
|
case 79:
|
|
encounter.text = "An albino zombie has been tracking you for some time. It can no longer ignore its hunger pangs and begins racing at you."
|
|
encounter.enemies = [
|
|
createEnemy("Albino Zombie", calculateRoll("2d8+2"), 13, 7, "2d4+2", "d20+2")
|
|
]
|
|
break
|
|
case 80:
|
|
encounter.text = "A cyborg looks up from his fire. You're spotted!"
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg", calculateRoll("2d8+6"), 13, 5, "1d12+3", "d20+1")
|
|
]
|
|
break
|
|
case 81:
|
|
encounter.text = "An aerial drone is spotted circling around you. It's coming in for an attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Aerial Drone", calculateRoll("3d8+3"), 16, 4, "1d10+2", "d20")
|
|
]
|
|
break
|
|
case 82:
|
|
encounter.text = "A pack of zombie dogs are directly ahead. There is no avoiding their dark gaze. Prepare for combat!"
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Dog A", calculateRoll("6d8+12"), 12, 6, "1d6+2", "d20+2", "Diseased Bite2d6+2"),
|
|
createEnemy("Zombie Dog B", calculateRoll("6d8+12"), 12, 6, "1d6+2", "d20+2", "Diseased Bite2d6+2"),
|
|
createEnemy("Zombie Dog C", calculateRoll("6d8+12"), 12, 6, "1d6+2", "d20+2", "Diseased Bite2d6+2"),
|
|
createEnemy("Zombie Dog D", calculateRoll("6d8+12"), 12, 6, "1d6+2", "d20+2", "Diseased Bite2d6+2")
|
|
]
|
|
break
|
|
case 83:
|
|
encounter.text = "The mercenary looks at you with a sinister scowl. \"I don't very much like you.\" He brandishes a pistol and prepares to attack you."
|
|
encounter.enemies = [
|
|
createEnemy("Merc", calculateRoll("3d6+6"), 15, 6, "1d8+2", "d20+2", "Irradiated Round1d4+2", "Cloak")
|
|
]
|
|
break
|
|
case 84:
|
|
encounter.text = "That stink! What is it? An amorphous, gray blob of nanomachines coalesces, clearly alarmed by your presence. It's going to rush you!"
|
|
encounter.enemies = [
|
|
createEnemy("Blog", calculateRoll("4d6+4"), 11, 2, "2d4", "d20")
|
|
]
|
|
break
|
|
case 85:
|
|
encounter.text = "A wheeled drone! Take cover!"
|
|
encounter.enemies = [
|
|
createEnemy("Wheeled Drone", calculateRoll("3d8"), 15, 4, "1d6+2", "d20+2")
|
|
]
|
|
break
|
|
case 86:
|
|
encounter.text = "It's not your imagination: an alien ooze is seeping through the cracks. It coalesces into a hideous aberration before you."
|
|
encounter.enemies = [
|
|
createEnemy("Alien Ooze", calculateRoll("3d8+9"), 8, 4, "1d6+1", "d20-2", "Corrode Metal")
|
|
]
|
|
break
|
|
case 87:
|
|
encounter.text = "You catch a food processor tearing meat from the leg of some hapless victim. It drops it immediately once it spots you."
|
|
encounter.enemies = [
|
|
createEnemy("Food Processor", calculateRoll("2d8+2"), 11, 8, "1d4+3", "d20+1")
|
|
]
|
|
break
|
|
case 88:
|
|
encounter.text = "This is the work of a mad scientist! Zombies composed of the parts of different people stand before you. They attack in practiced unison."
|
|
encounter.enemies = [
|
|
createEnemy("Creature A", calculateRoll("2d4"), 13, 1, "1d10", "d20+2", "Poison Bite1d10"),
|
|
createEnemy("Creature B", calculateRoll("2d4"), 13, 1, "1d10", "d20+2", "Poison Bite1d10"),
|
|
createEnemy("Creature C", calculateRoll("2d4"), 13, 1, "1d10", "d20+2", "Poison Bite1d10"),
|
|
createEnemy("Creature D", calculateRoll("2d4"), 13, 1, "1d10", "d20+2", "Poison Bite1d10")
|
|
]
|
|
break
|
|
case 89:
|
|
encounter.text = "A living wall of limbs and body parts attacks. It's hideous composure defies all reason."
|
|
encounter.enemies = [
|
|
createEnemy("Wall", calculateRoll("3d8"), 7, 3, "1d4", "d20-3")
|
|
]
|
|
break
|
|
case 90:
|
|
encounter.text = "The sulfur stink reaches your nose first, then the sight of them: a group of holograms composed of pure fire attack."
|
|
encounter.enemies = [
|
|
createEnemy("Hologram A", calculateRoll("2d6+2"), 14, 2, "2d6", "d20+2", "Fire Touch3d6"),
|
|
createEnemy("Hologram B", calculateRoll("2d6+2"), 14, 2, "2d6", "d20+2", "Fire Touch3d6"),
|
|
createEnemy("Hologram C", calculateRoll("2d6+2"), 14, 2, "2d6", "d20+2", "Fire Touch3d6")
|
|
]
|
|
break
|
|
case 91:
|
|
encounter.text = "Out of the corner of your eye you spot a dark figure moving. \"Cyborgs!\" You prepare for the ambush."
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg A", calculateRoll("3d4"), 13, 2, "1d4+3", "d20+", "Invisibility", "Scare"),
|
|
createEnemy("Cyborg B", calculateRoll("3d4"), 13, 2, "1d4+3", "d20+", "Invisibility", "Scare"),
|
|
createEnemy("Cyborg C", calculateRoll("3d4"), 13, 2, "1d4+3", "d20+", "Invisibility", "Scare"),
|
|
createEnemy("Cyborg D", calculateRoll("3d4"), 13, 2, "1d4+3", "d20+", "Invisibility", "Scare"),
|
|
createEnemy("Cyborg E", calculateRoll("3d4"), 13, 2, "1d4+3", "d20+", "Invisibility", "Scare")
|
|
]
|
|
break
|
|
case 92:
|
|
encounter.text = "A carnivourous nano cloud! A killing blow will corrode any common weapons."
|
|
encounter.enemies = [
|
|
createEnemy("Nano Cloud", calculateRoll("5d8+5"), 14, 4, "1d8+1", "d20+1")
|
|
]
|
|
break
|
|
case 93:
|
|
encounter.text = "A zombie corrupted officer stands firm. Its malevolence can be felt in your bones."
|
|
encounter.enemies = [
|
|
createEnemy("Officer", calculateRoll("5d8"), 12, 4, "3d6", "d20+2", "Life Drain3d6", "Counter Hack")
|
|
]
|
|
break
|
|
case 94:
|
|
encounter.text = "Viscious rat bots are commanded to attack you. Oh god, they're everywhere!"
|
|
encounter.enemies = [
|
|
createEnemy("Rat Bot A", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot B", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot C", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot D", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot E", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot F", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot G", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot H", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot I", calculateRoll("1d4-1"), 13, 1, "1", "d20+3"),
|
|
createEnemy("Rat Bot J", calculateRoll("1d4-1"), 13, 1, "1", "d20+3")
|
|
]
|
|
break
|
|
case 95:
|
|
encounter.text = "A self-driving car swerves dangerously close to you. For some reason, it has decided to target you."
|
|
encounter.enemies = [
|
|
createEnemy("Car", calculateRoll("7d12+14"), 13, 10, "3d6+4", "d20-2")
|
|
]
|
|
break
|
|
case 96:
|
|
encounter.text = "A robotic centaur is leading up to you. It may have been tracking your for some time. Get ready!"
|
|
encounter.enemies = [
|
|
createEnemy("Centaur", calculateRoll("6d10+12"), 12, 10, "2d6+4", "d20+2", "Charge3d6")
|
|
]
|
|
break
|
|
case 97:
|
|
encounter.text = "A gelatinous cube of zombie meat occupies this space. It's wobbling hatefully toward you!"
|
|
encounter.enemies = [
|
|
createEnemy("Meat Cube", calculateRoll("8d10+40"), 6, "3d6", "d20-4", "Engulf3d6")
|
|
]
|
|
break
|
|
case 98:
|
|
encounter.text = "A nefarious hologram curls its disgusting tongue, tasting the air. Suddenly, it turns toward you!"
|
|
encounter.enemies = [
|
|
createEnemy("Hologram", calculateRoll("8d8"), 13, 6, "2d8+3", "d20+3")
|
|
]
|
|
break
|
|
case 99:
|
|
encounter.text = "A cyborg war party comes upon you!"
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg A", calculateRoll("2d8+6"), 13, 8, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg B", calculateRoll("2d8+6"), 13, 8, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg C", calculateRoll("2d8+6"), 13, 8, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg D", calculateRoll("2d8+6"), 13, 8, "1d12+3", "d20+1")
|
|
]
|
|
break
|
|
}
|
|
break
|
|
case "medium":
|
|
if (encounter.cr == null) encounter.cr = 5
|
|
multiplier = 1 + (encounter.cr - 5) / 10
|
|
switch (getRandomInteger(0, 99)) {
|
|
case 0:
|
|
encounter.text = "There is a building here, but there appears to be no doors. How do you get in?"
|
|
break
|
|
case 1:
|
|
encounter.text = "A hologram projector is here. There are various pre-programmed scenarios that can be activated by the control panel."
|
|
break
|
|
case 2:
|
|
encounter.text = "A holographic projection of art catches your eye. You are mesmerized by its appearance. You cannot turn away from it and are now being drawn to it."
|
|
break
|
|
case 3:
|
|
encounter.text = "The ground before you seems to be pulsing with a red glow. A sudden shaking alerts you."
|
|
break
|
|
case 4:
|
|
encounter.text = "A drop pod lands gracefully before you. The doors remain shut as you approach."
|
|
break
|
|
case 5:
|
|
encounter.text = "Warning signs of a mine field line the perimeter of a farm."
|
|
break
|
|
case 6:
|
|
encounter.text = "A team of robust drone oxen are roaming ahead."
|
|
break
|
|
case 7:
|
|
encounter.text = "You detect a gravity anamoly in the local area."
|
|
break
|
|
case 8:
|
|
encounter.text = "For some reason, you hear nothing. The sounds of the environment grow to an absolute quiet. You try to speak, but no sound is heard."
|
|
break
|
|
case 9:
|
|
encounter.text = "A ways away you see a lone robot defending against a group of cyborg mercenaries. It is hard to determine who has the upper hand."
|
|
break
|
|
case 10:
|
|
encounter.text = "You have found a cache of rations, but most of them are spoiled. You may find something of value if you keep looking."
|
|
break
|
|
case 11:
|
|
encounter.text = "A klaxon siren screams in the distance. Whatever you're approaching is attracting a lot of attention from the undead."
|
|
break
|
|
case 12:
|
|
encounter.text = "You have come across a pre-war vehicle. It strangely seems to still be operational. You notice a glowing dash icon indicating that it is alarmed."
|
|
break
|
|
case 13:
|
|
encounter.text = "Three pods are placed conspicuously in a circle. There is cryptic text written in the center: \"CHOOSE WISELY\""
|
|
break
|
|
case 14:
|
|
encounter.text = "Ammo magazines are scattered around this place. Some have ammo, but most are empty. You spot one with a peculiar red stripe across it."
|
|
break
|
|
case 15:
|
|
encounter.text = "You have suddenly come across another military group. Tensions are high as they aim their weapons at you, but it appears that they will not act unless provoked."
|
|
break
|
|
case 16:
|
|
encounter.text = "A makeshift bridge has been constructed here. You notice the tell-tale signs of explosive wiring. It's rigged to blow."
|
|
break
|
|
case 17:
|
|
encounter.text = "You hear explosions in the distance. Then the strike of artillery fire all around you. You're being targeted!"
|
|
break
|
|
case 18:
|
|
encounter.text = "A fortified hanger is here. You see that an entryway has been carved into the side."
|
|
break
|
|
case 19:
|
|
encounter.text = "An electrified fence has been set up here, preventing you from further progress."
|
|
break
|
|
case 20:
|
|
encounter.text = "You have come across a weather station. It seems to be active and its instruments are functioning."
|
|
break
|
|
case 21:
|
|
encounter.text = "As you enter this place, you see the wonderous vision of a pre-war city. Vehicles are flying around and people are gathering without a care in the world. It seems far too surreal to not be a holographic illusion."
|
|
break
|
|
case 22:
|
|
encounter.text = "You hear a click. You have stepped on an improvised trap ready to explode as soon as you lift away from the trigger."
|
|
break
|
|
case 23:
|
|
encounter.text = "A cyborg is appraoching! However, it looks to be that he is surrendering. He waves his empty hands in the air."
|
|
break
|
|
case 24:
|
|
encounter.text = "You spot the tracks of a large animal drone. Whatever passed through here, it was massive."
|
|
break
|
|
case 25:
|
|
encounter.text = "You have found a cache of weapons. As you reach for it, however, your hand passes through it effortlessly. It's a trap!"
|
|
break
|
|
case 26:
|
|
encounter.text = "You hear the whirring of a giant fan. You see the exhaust plume of a massive underground structure ahead of you. Is this a cyborg colony?"
|
|
break
|
|
case 27:
|
|
encounter.text = "Buzzing. Buzzing by your ears. These bee drones are getting aggressive. You must be near a hive."
|
|
break
|
|
case 28:
|
|
encounter.text = "A zombie is flayed out across a panel, pinned by giant bolts driven through its limbs. Though it's alive, it's unclear how long it's been here."
|
|
break
|
|
case 29:
|
|
encounter.text = "An pre-war atmosphere processor has been spotted on the horizon. What riches lie within?"
|
|
break
|
|
case 30:
|
|
encounter.text = "Pylons have been constructed along the edges of this area. Regretfully, you've found yourself in the center of them as they begin to hum and start shooting out beams of electricty."
|
|
break
|
|
case 31:
|
|
encounter.text = "A weapon is levitating above a pedestal in front of you. In your mind you hear the challenge: \"Are you worthy?\""
|
|
break
|
|
case 32:
|
|
encounter.text = "Many medical camps were deployed across the world in response to the calamity. One such encampment is before you."
|
|
break
|
|
case 33:
|
|
encounter.text = "Barrels of fuel have been gathered here by a survivor. Some are tipped over, leaking their explosive liquid all over the place. One stray spark can ignite the whole area."
|
|
break
|
|
case 34:
|
|
encounter.text = "A trading drone happily sings to itself as it hovers from door to door in this place. It wishes to initiate a transaction with you."
|
|
break
|
|
case 35:
|
|
encounter.text = "Factories like this created the great machines that enabled human prosperity. Now they lay dormant, waiting to be looted by survivors."
|
|
break
|
|
case 36:
|
|
encounter.text = "A craft hovers above you at a high altitude. It seems to be floating there with no apparent source of propulsion and hasn't moved for quite some time."
|
|
break
|
|
case 37:
|
|
encounter.text = "This is a site of a zombie attack. One of the survivors begs you, \"Please, kill me! I'm infected. The transformation... I feel it coming.\""
|
|
break
|
|
case 38:
|
|
encounter.text = "A post-war tower has been constructed here. Zombies clearly have been trying to break in, but their limbs have been grinded to nubs from its abrassive fortifications."
|
|
break
|
|
case 39:
|
|
encounter.text = "You see various bodies strewn about. These are no ordinary bodies. Someone was experimenting with these creatrures."
|
|
break
|
|
case 40:
|
|
encounter.text = "A medical drone is malfunctioning. Its surgical saw is carving through walls and objects as it haphazardly makes a course through a lab."
|
|
break
|
|
case 41:
|
|
encounter.text = "A terminal for an AI core is present here"
|
|
break
|
|
case 42:
|
|
encounter.text = "It is clear that this robot was once responsible for directing traffic in pre-war civilization. Now it attacks anything that comes its way if they don't observe its arbitrary rules of passing through this area."
|
|
break
|
|
case 43:
|
|
encounter.text = "A giant, spider-like robot is travelling across the area. It's collecting debris and processing it inside of its cavity."
|
|
break
|
|
case 44:
|
|
encounter.text = "You see a prototype robot sealed in a module. A digital display beckons you to activate it."
|
|
break
|
|
case 45:
|
|
encounter.text = "A cyborg implant contained in a magnetic zero point cage has been found here. It is unmovable without finding a way to disable the field."
|
|
break
|
|
case 46:
|
|
encounter.text = "A force field blocks your way."
|
|
break
|
|
case 47:
|
|
encounter.text = "You have stumbled across a secret cyborg commune where humans and machines seem to have found a way to co-exist with each other."
|
|
break
|
|
case 48:
|
|
encounter.text = "A holographic anomoly is present here. It appears as an orb of light that dances from here to there, creating illusions and quickly deleting others."
|
|
break
|
|
case 49:
|
|
encounter.text = "Laser trip mines. You can not make your way forward without braving this obstacle."
|
|
break
|
|
case 50:
|
|
encounter.text = "A transport pad is spotted. It has several pre-programmed destinations available."
|
|
break
|
|
case 51:
|
|
encounter.text = "A raider is arguing with his partner. \"No, I attack first and you sneak up on them!\""
|
|
encounter.enemies = [
|
|
createEnemy("Raider A", calculateRoll("9d8+27"), 13, 5, "1d12+3", "d20+1"),
|
|
createEnemy("Raider B", calculateRoll("9d8+27"), 13, 5, "1d12+3", "d20+1")
|
|
]
|
|
break
|
|
case 52:
|
|
encounter.text = "The cult of death is gathered here. They chant in an unfamiliar tongue. Their chants grow louder and louder as they approach you. Prepare for attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Cultist A", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1"),
|
|
createEnemy("Cultist B", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1"),
|
|
createEnemy("Cultist C", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1"),
|
|
createEnemy("Cultist D", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1"),
|
|
createEnemy("Cultist E", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1")
|
|
]
|
|
break
|
|
case 53:
|
|
encounter.text = "Slime covers everything and you can see what has caused it. A zombie harvester approaches. Its quivering mass looms over you."
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Harvester", calculateRoll("8d10+40"), 6, "3d6", "d20-4", "Engulf3d6")
|
|
]
|
|
break
|
|
case 54:
|
|
encounter.text = "\"Synthesizer zombies feed on their surroundings to blend in and harness their power. One such creature descends upon you."
|
|
encounter.enemies = [
|
|
createEnemy("Synth Zombie", calculateRoll("5d8+5"), 11, 4, "1d8", "d20+1", "Lighter3d6", "Bulletproof", "Data Wipe")
|
|
]
|
|
break
|
|
case 55:
|
|
encounter.text = "A ghastly hologhost is on approach. Each whisper you hear is a promise of pain."
|
|
encounter.enemies = [
|
|
createEnemy("Hologhost", calculateRoll("10d8"), 11, 5, "4d6+3", "d20+1", "Withering Touch4d6+3", "Horrifying Visage", "Possession")
|
|
]
|
|
break
|
|
case 56:
|
|
encounter.text = "The griffon bot guards its nest with fervent aggression. You are in its territory and it's plenty pissed."
|
|
encounter.enemies = [
|
|
createEnemy("Griffon Bot", calculateRoll("7d10+21"), 12, 6, "1d8+4", "d20+2")
|
|
]
|
|
break
|
|
case 57:
|
|
encounter.text = "\"Don't touch that!\" You hear a voice scream out. Too late. The nanomorphic has transformed from an inviting supply crate into a horrific monster. Its tongue has grasped your leg and is pulling you into its teethy maw."
|
|
encounter.enemies = [
|
|
createEnemy("Nanomorphic", calculateRoll("9d8+18"), 12, 5, "1d8+3", "d20+1", "Grapple")
|
|
]
|
|
break
|
|
case 58:
|
|
encounter.text = "The construction bot just grunts as it grabs its giant wrench. You all know what's coming. It's just a matter of who comes out on top now."
|
|
encounter.enemies = [
|
|
createEnemy("Construction Bot", calculateRoll("7d10+21"), 11, 6, "2d8+4", "d20-1")
|
|
]
|
|
break
|
|
case 59:
|
|
encounter.text = "Don't let the beauty of the Holographic Pegasus entrap you. It is as deadly as it is magnificent. It comes into attack position."
|
|
encounter.enemies = [
|
|
createEnemy("Pegasus", calculateRoll("7d10+21"), 12, 6, "2d6+4", "d20+2")
|
|
]
|
|
break
|
|
case 60:
|
|
encounter.text = "\"Stay back! I can't control it. I can't...\" His voice breaks off as the nano-necrotic virus overwhelms him, giving him beast like features. Attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Werezombie", calculateRoll("6d8+6"), 12, 4, "1d4+2", "d20+2")
|
|
]
|
|
break
|
|
case 61:
|
|
encounter.text = "Beware the light drone! It has tricked many a soldier into their deaths and one threatens to do the same here."
|
|
encounter.enemies = [
|
|
createEnemy("Light Drone", calculateRoll("9d4"), 19, 4, "2d8", "d20+9")
|
|
]
|
|
break
|
|
case 62:
|
|
encounter.text = "Its form is unreal. The Amalgam Zombie is an almagamation of claws, scales, and fangs. It somehow negotiates its confusion of limbs towards you with incredible speed."
|
|
encounter.enemies = [
|
|
createEnemy("Amalgam Zombie", calculateRoll("7d8+42"), 19, 6, "1d6+3", "d20")
|
|
]
|
|
break
|
|
case 63:
|
|
encounter.text = "The gaze of the Stone Zombie is even more deadly than its tooth and claw. This is evidenced by the petrified bodies strewn about the room."
|
|
encounter.enemies = [
|
|
createEnemy("Basilisk", calculateRoll("8d8+16"), 15, 5, "2d6+3", "d20-1")
|
|
]
|
|
break
|
|
case 64:
|
|
encounter.text = "You try not to stare at the green alien, but his otherworldly appearance captures your gaze. He clearly has plans for you, and they aren't good."
|
|
encounter.enemies = [
|
|
createEnemy("Green Alien", calculateRoll("8d8+16"), 13, 5, "1d10+3", "d20+2")
|
|
]
|
|
break
|
|
case 65:
|
|
encounter.text = "Your sudden arrival has caught the shapeshifting alien off guard. It quickly transforms into a familiar form, but its too late. With its secret revealed, it has no choice but to attack."
|
|
encounter.enemies = [
|
|
createEnemy("Shapeshifter", calculateRoll("8d8+16"), 14, 6, "1d6+4", "d20+4", "Shapechange")
|
|
]
|
|
break
|
|
case 66:
|
|
encounter.text = "Robo dogs have been sent after you with the solitary command: kill. They scour the surface for any trace of you. Who sent them?"
|
|
encounter.enemies = [
|
|
createEnemy("Robo Dog A", calculateRoll("7d8+14"), 15, 5, "1d8+3", "d20+1", "Fire Rocket6d6"),
|
|
createEnemy("Robo Dog B", calculateRoll("7d8+14"), 15, 5, "1d8+3", "d20+1", "Fire Rocket6d6"),
|
|
createEnemy("Robo Dog C", calculateRoll("7d8+14"), 15, 5, "1d8+3", "d20+1", "Fire Rocket6d6")
|
|
]
|
|
break
|
|
case 67:
|
|
encounter.text = "The Mass is an abomination, combining a zombie with cyborg and alien tech. It sets its sights on you."
|
|
encounter.enemies = [
|
|
createEnemy("The Mass", calculateRoll("8d10+24"), 14, 5, "1d8+3", "d20+3")
|
|
]
|
|
break
|
|
case 68:
|
|
encounter.text = "The unmistakable stink of cooking flesh. It's a cannibal survivor and he has a fixing for his next meal."
|
|
encounter.enemies = [
|
|
createEnemy("Cannibal Survivor", calculateRoll("11d8+33"), 17, 6, "2d8+4", "d20+1", "Minor Illusion", "Invisible Passage")
|
|
]
|
|
break
|
|
case 69:
|
|
encounter.text = "The minotaur bot is here. No maze. Just the promise of your death. Defend yourself!"
|
|
encounter.enemies = [
|
|
createEnemy("Minotaur Bot", calculateRoll("9d10+27"), 14, 6, "2d12+4", "d20")
|
|
]
|
|
break
|
|
case 70:
|
|
encounter.text = "An ancient cryonic tomb. In it, a variety of bodies frozen for a cure that will never come. Meticulous care was put into protecting them from decay. Unfortunately for you, the control computer has finally broken. The master has awoken only remembers their taste for flesh now."
|
|
encounter.enemies = [
|
|
createEnemy("The Master", calculateRoll("9d8+18"), 11, 5, "2d6+3", "d20-1")
|
|
]
|
|
break
|
|
case 71:
|
|
encounter.text = "A cyborg horse trots into view. At first, it doesn't seem to be as terrifying as the stories you've heard. But once it draws close, you can see its rotting flesh, the flaming hooves and mane. It's built like a tank and it aims to tear you apart."
|
|
encounter.enemies = [
|
|
createEnemy("Nightmare", calculateRoll("8d10+24"), 13, 6, "2d8+4", "d20+2", "Ehtereal Stride")
|
|
]
|
|
break
|
|
case 72:
|
|
encounter.text = "The hulking mass of flesh and muscle before you quivers and threatens to attack at any moment. Misinterpreting an eye twitch, it attacks!"
|
|
encounter.enemies = [
|
|
createEnemy("Hulking Mass", calculateRoll("7d10+21"), 13, 7, "1d10+5", "d20+2")
|
|
]
|
|
break
|
|
case 73:
|
|
encounter.text = "A spectator drone! Run or fight. Either way, you'll never escape its deadly gaze."
|
|
encounter.enemies = [
|
|
createEnemy("Spectator Drone", calculateRoll("6d8+12"), 14, 1, "1d6-1", "d20+2", "Confusion Ray", "Paralyzing Ray", "Fear Ray", "Wounding Ray3d10")
|
|
]
|
|
break
|
|
case 74:
|
|
encounter.text = "The spider alien hatches from its egg. Long, finger-like limbs emerge out of the broken shell. Then it launches itself at you!"
|
|
encounter.enemies = [
|
|
createEnemy("Spider Alien", calculateRoll("9d8+18"), 12, 4, "18+2", "d20+1")
|
|
]
|
|
break
|
|
case 75:
|
|
encounter.text = "White Zombies are not dangerous because they are some of the most powerful undead creatures. No. It's their intelligence and their endless campaign against the living. Fight!"
|
|
encounter.enemies = [
|
|
createEnemy("White Zombie", calculateRoll("6d8+18"), 14, 4, "1d8+2", "d20+1", "Life Drain4d6+3")
|
|
]
|
|
break
|
|
case 76:
|
|
encounter.text = "This is not the natural habitat for the alien giant, and yet it is here. You can see your fate drawn in the blood of its other victims. There is no backing out now."
|
|
encounter.enemies = [
|
|
createEnemy("Alien Giant", calculateRoll("6d10+18"), 12, 6, "1d6+4", "d20+1")
|
|
]
|
|
break
|
|
case 77:
|
|
encounter.text = "It's a swarm of bee drones. What else is there to say? Fight!"
|
|
encounter.enemies = [
|
|
createEnemy("Bee Drone Swarm", calculateRoll("6d8+18"), 14, 4, "1d8+2", "d20+1", "Life Drain4d6+3")
|
|
]
|
|
break
|
|
case 78:
|
|
encounter.text = "The blood-curdling scream is a clear sign: BANSHEE BORGS! Your death is soon to be added to the ledger."
|
|
encounter.enemies = [
|
|
createEnemy("Banshee Borg A", calculateRoll("13d8"), 12, 4, "3d6+2", "d20+2", "Corrupting Touch3d6+2", "Wail3d6"),
|
|
createEnemy("Banshee Borg B", calculateRoll("13d8"), 12, 4, "3d6+2", "d20+2", "Corrupting Touch3d6+2", "Wail3d6")
|
|
]
|
|
break
|
|
case 79:
|
|
encounter.text = "This hideous aberration before you must be some sort of nanotech experiment gone wrong. Kill or be killed. There is no other choice here."
|
|
encounter.enemies = [
|
|
createEnemy("Nano Blob", calculateRoll("11d10+33"), 16, 6, "2d6+4", "d20", "Tentacles")
|
|
]
|
|
break
|
|
case 80:
|
|
encounter.text = "The service industry robot. It has been constructed to a shape that is pleasing to your eye, but you should know better than to fall for its wiles. Attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Service Robot", calculateRoll("12d8+12"), 15, 5, "1d6+3", "d20+3")
|
|
]
|
|
break
|
|
case 81:
|
|
encounter.text = "The nano ghost is capable of possessing its victims. Be careful because you feel its control gripping at the edges of your mind now."
|
|
encounter.enemies = [
|
|
createEnemy("Nano Ghost", calculateRoll("10d8"), 11, 5, "4d6+3", "d20+1", "Withering Touch4d6+3", "Horrifying Visage", "Possession")
|
|
]
|
|
break
|
|
case 82:
|
|
encounter.text = "Cyborg Succubus is a shapechanger. It has selected a shape that is pleasing to your eye, but you should know better than to fall for its wiles. Attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg Succubus", calculateRoll("12d8+12"), 15, 6, "1d6+3", "d20+3")
|
|
]
|
|
break
|
|
case 83:
|
|
encounter.text = "The mechaboar here has mastered control of his beastly transformation. He just doesn't like you. He's trotting at you at full speed."
|
|
encounter.enemies = [
|
|
createEnemy("Wereboar", calculateRoll("12d8+24"), 10, 5, "2d6+3", "d20", "Charge", "Tusk2d6+3")
|
|
]
|
|
break
|
|
case 84:
|
|
encounter.text = "A red mecha dragon wyrmling stalks this area. You were a fool to enter its domain."
|
|
encounter.enemies = [
|
|
createEnemy("Red Mecha Wyrmling", calculateRoll("10d8+30"), 17, 6, "1d10+4", "d20")
|
|
]
|
|
break
|
|
case 85:
|
|
encounter.text = "Woosh! A flaming, holographic skull whips into view. You feel the heat on your face even at this distance. It's time to attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Holo Skull", calculateRoll("9d4+18"), 13, 5, "3d6", "d20+3", "Fire Ray3d6", "Magic Missile3d10+2", "Fire Ball2d20")
|
|
]
|
|
break
|
|
case 86:
|
|
encounter.text = "The pressure in the area suddenly changes. An air hologram materializes in front of you. It must be guarding this place from intruders."
|
|
encounter.enemies = [
|
|
createEnemy("Air Hologram", calculateRoll("12d10+24"), 15, 8, "2d8+5", "d20+5", "Whirlwind3d8+2")
|
|
]
|
|
break
|
|
case 87:
|
|
encounter.text = "The barbed robot is quite deadly. It damages anyone that grapples with it. Beware, for one such creature stalks the land here."
|
|
encounter.enemies = [
|
|
createEnemy("Barbed Robot", calculateRoll("13d8+52"), 15, 6, "1d6+3", "d20+3", "Hurl Flame3d6")
|
|
]
|
|
break
|
|
case 88:
|
|
encounter.text = "You hear a rumbling and the earth beneath you quakes. You dive out of the way as an earth hologram emerges right where you were standing. Fight!"
|
|
encounter.enemies = [
|
|
createEnemy("Earth Hologram", calculateRoll("12d10+60"), 17, 8, "2d8+5", "d20-1", "Earth Glide")
|
|
]
|
|
break
|
|
case 89:
|
|
encounter.text = "Is it getting hot in here or is it just you? No, it's a Fire Hologram and it's ready to attack."
|
|
encounter.enemies = [
|
|
createEnemy("Fire Hologram", calculateRoll("12d10+36"), 13, 6, "2d6+3", "d20+3", "Fire Form")
|
|
]
|
|
break
|
|
case 90:
|
|
encounter.text = "The flesh zombie stumbles into your sight. It howls an unearthly cry. Every movement is pain. You would feel pity if you didn't have to fight for you life."
|
|
encounter.enemies = [
|
|
createEnemy("Flesh Zombie", calculateRoll("11d8+44"), 9, 7, "2d8+4", "d20-1", "Berserk")
|
|
]
|
|
break
|
|
case 91:
|
|
encounter.text = "The petrifying shot of the stun drone is well known. What isn't known is how one tracked you down here. Prepare to fight!"
|
|
encounter.enemies = [
|
|
createEnemy("Stun Drone", calculateRoll("12d8+48"), 19, 8, "2d12+5", "d20", "Petrifying Shot")
|
|
]
|
|
break
|
|
case 92:
|
|
encounter.text = "The Juggernaut Zombie lowers his club with a loud thud. Looking to your direction, he is amused by the new playthings he discovered. Be careful, he plays rough!"
|
|
encounter.enemies = [
|
|
createEnemy("Juggernaut Zombie", calculateRoll("10d12+40"), 13, 8, "3d8+5", "d20-1", "Throw Rock3d10+5")
|
|
]
|
|
break
|
|
case 93:
|
|
encounter.text = "You were foolish to enter this place. A night drone has established a den here and she really doesn't like being disturbed. It's time to get into combat formation!"
|
|
encounter.enemies = [
|
|
createEnemy("Night Drone", calculateRoll("15d8+45"), 17, 7, "2d8+4", "Holographic Image", "Nightmare Haunting")
|
|
]
|
|
break
|
|
case 94:
|
|
encounter.text = "The appearance of the Iron Forge Robot spells certain doom for the party. Its heated weapons could cleave through even the hardest armor."
|
|
encounter.enemies = [
|
|
createEnemy("Iron Forge Robot", calculateRoll("12d10+24"), 15, 7, "2d6+4", "d20+2", "Heated Body")
|
|
]
|
|
break
|
|
case 95:
|
|
encounter.text = "First it was the sucking sounds as it moved across the landscape. Then it was the stench. Finally, the the shambling mass reveals itself."
|
|
encounter.enemies = [
|
|
createEnemy("Shambling Mass", calculateRoll("16d10+48"), 15, 7, "2d8+4", "d20-1", "Engulf")
|
|
]
|
|
break
|
|
case 96:
|
|
encounter.text = "\"Everything. Your weapons, armor, and tech. Fast!\" The bandit soldier grips his giant soldier effortlessly as if it was a twig. He is beckoning for a fight."
|
|
encounter.enemies = [
|
|
createEnemy("Troll", calculateRoll("8d10+40"), 15, 7, "1d6+4", "d20+1")
|
|
]
|
|
break
|
|
case 97:
|
|
encounter.text = "The Cyborg Bear attacks! There seems to be no reasoning with it."
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg Bear", calculateRoll("18d8+54"), 10, 7, "2d10+4", "d20")
|
|
]
|
|
break
|
|
case 98:
|
|
encounter.text = "A mound of corpses stands tall before you. Just beyond it is a wraith hologram. Its deathly stare cuts right through you."
|
|
encounter.enemies = [
|
|
createEnemy("Wraith Hologram", calculateRoll("9d8+27"), 13, 6, "4d8+3", "d20+3", "Life Drain4d8+3", "Create Specter")
|
|
]
|
|
break
|
|
case 99:
|
|
encounter.text = "A cyborg spawn steps out of the shadows. Perhaps he's here to capture new slaves for its master."
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg Spawn", calculateRoll("11d8+33"), 15, 6, "2d4+3", "d20+3", "Bite3d6+3")
|
|
]
|
|
break
|
|
}
|
|
break
|
|
case "hard":
|
|
if (encounter.cr == null) encounter.cr = 9
|
|
multiplier = 1 + (encounter.cr - 9) / 10
|
|
switch (getRandomInteger(0, 60)) {
|
|
case 0:
|
|
encounter.text = "You're pretty sure you've seen this seem landmark 30 minutes ago. You've been walking around in circles. Something must be affecting your mind."
|
|
break
|
|
case 1:
|
|
encounter.text = "A solitary command darts around in your brain. \"KILL!\" The compulsion is nearly impossible to resist, but you must try."
|
|
break
|
|
case 2:
|
|
encounter.text = "As you traverse forward, a sudden crash! A thunderous sound erupts as the earth beneath you opens up."
|
|
break
|
|
case 3:
|
|
encounter.text = "They say the pre-war trains were designed to operate for hundreds of years without human intervention. It's true. One such train is heading your way."
|
|
break
|
|
case 4:
|
|
encounter.text = "Eggs. The drones are multiplying. There are eggs here. The ramifications of this are baffling. One of them is beginning to shake and come to life."
|
|
break
|
|
case 5:
|
|
encounter.text = "Trap doors swing wide open and two sentry guns pop up looking for their target. A piece of rubble falls from a nearby wall. The guns obliterate it. They're tracking movement!"
|
|
break
|
|
case 6:
|
|
encounter.text = "A robotic horse gallops to you and kneels before you. It gently bows its heard in your direction as a sign of subservience."
|
|
break
|
|
case 7:
|
|
encounter.text = "High above you see a craft break through the atmosphere. You don't have time to hide as it's already launched it's payload of munitions directly at your location."
|
|
break
|
|
case 8:
|
|
encounter.text = "A piercing sound suddenly fills the air and drowns out all sound. Clutching your bleeding ears, you must find a way to stop it."
|
|
break
|
|
case 9:
|
|
encounter.text = "Strange weather phenomena is ocurring in your local area. As the clouds coalesce, you hear the thunder of the storm building into an orchestra of devastation."
|
|
break
|
|
case 10:
|
|
encounter.text = "A flash flood! The dam must have finally broken and now you have to fight to survive."
|
|
break
|
|
case 11:
|
|
encounter.text = "You approach what appears to be a stable portal leading to the digital realm."
|
|
break
|
|
case 12:
|
|
encounter.text = "\"No air!\" Those are the last words you utter as you are somehow transported to the alien realm."
|
|
break
|
|
case 13:
|
|
encounter.text = "This is a temple, but it cannot be of human origin. At its summit, a powerful beam erupts into the sky."
|
|
break
|
|
case 14:
|
|
encounter.text = "Humanity must have built this giant wall to keep something out. Or was it to trap something inside? The wall goes on as far as you can see and is as high as a skyscraper."
|
|
break
|
|
case 15:
|
|
encounter.text = "Floating platforms lead upward. They can easily be navigated by jumping from one to the other. But where do they lead?"
|
|
break
|
|
case 16:
|
|
encounter.text = "These robotic hunter-killers were supposed to be humanity's last line of defense. Its giant frame creaks as it searches for trespassers."
|
|
break
|
|
case 17:
|
|
encounter.text = "A net of lasers forms behjind you and is swiftly moving to eradicate anything in its path."
|
|
break
|
|
case 18:
|
|
encounter.text = "What appears to be a hollographic mirror image of yourself is cast ahead of you. It matches your movements perfectly. But something isn't quite right about it."
|
|
break
|
|
case 19:
|
|
encounter.text = "An abandoned VTOL is landed here. But where is the crew?"
|
|
break
|
|
case 20:
|
|
encounter.text = "The blackbox of a VTOL is found amongst the wreckage of a craft. What could have been a cause of this disaster?"
|
|
break
|
|
case 21:
|
|
encounter.text = "You find yourself in the ruins of an old building. Suddenly, the walls shudder and begin to close in on you. It's a trap!"
|
|
break
|
|
case 22:
|
|
encounter.text = "An amorphous shape of what appears to be a network of nanomachines buzzes ahead. It forms into a shape that can be best described as a finger gesturing for you to approach."
|
|
break
|
|
case 23:
|
|
encounter.text = "A sudden wave of sickness rushes over you. Is it radiation poisoning?"
|
|
break
|
|
case 24:
|
|
encounter.text = "A horrific display of gore envelops your vision. This must have been a recent zombie attack and no one from this colony was able to escape."
|
|
break
|
|
case 25:
|
|
encounter.text = "A humonoid creature stands before you. It is featureless with no eyes or mouth. And yet you hear a voice. It is irresistable."
|
|
break
|
|
case 26:
|
|
encounter.text = "The ground is erupting! There was no warning sign of geological disruption. You must find safety and fast!"
|
|
break
|
|
case 27:
|
|
encounter.text = "You suddenly feel sleepy. The last thing you remember is the ground rushing toward you quickly and you powerless to prevent yourself from falling. Are you dead?"
|
|
break
|
|
case 28:
|
|
encounter.text = "A zombie in a nearly destroyed state is crawling away. Something powerful must have driven it away if it isn't paying any attention to you."
|
|
break
|
|
case 29:
|
|
encounter.text = "You feel static coursing through your fingers. Someone electrified the floor."
|
|
break
|
|
case 30:
|
|
encounter.text = "A zombie is on approach. Every instinct in your body is telling you to destroy it. But wait! It begins to speak."
|
|
break
|
|
case 31:
|
|
encounter.text = "A dual booting robot. Will you accept grim fate now that you have come across such a foe?"
|
|
encounter.enemies = [
|
|
createEnemy("Dual Bot", calculateRoll("12d10+48"), 14, 7, "2d6+4", "d20", "Fire Breath7d8")
|
|
]
|
|
break
|
|
case 32:
|
|
encounter.text = "The cyclops cyborg eyes you closely. It ponders for a time, but then finally decides that you must die."
|
|
encounter.enemies = [
|
|
createEnemy("Cyclops Cyborg", calculateRoll("12d12+60"), 14, 9, "3d8+6", "d20")
|
|
]
|
|
break
|
|
case 33:
|
|
encounter.text = "You've walked right into the spider drone's web. This was its plan all along."
|
|
encounter.enemies = [
|
|
createEnemy("Drider", calculateRoll("13d10+52"), 19, 6, "3d8", "1d10+3", "Poison Bite2d8")
|
|
]
|
|
break
|
|
case 34:
|
|
encounter.text = "A group of cultists are gathering here. It appears that they are trying to open a portal through to the interdimensional plane. They must be stopped!"
|
|
encounter.enemies = [
|
|
createEnemy("Insane Scientist", calculateRoll("9d8"), 12, 5, "1d4+2", "d20+2", "Cone of Cold8d8", "Greater Invisibility", "Fireball8d6", "Shield"),
|
|
createEnemy("Cultist A", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1"),
|
|
createEnemy("Cultist B", calculateRoll("2d8"), 12, 3, "1d6+1", "d20+1")
|
|
]
|
|
break
|
|
case 35:
|
|
encounter.text = "The statues of men in terror, all cowering from some horrible sight. This can only mean one thing: Medusa Alien."
|
|
encounter.enemies = [
|
|
createEnemy("Medusa Alien", calculateRoll("17d8+51"), 15, 5, "1d6+2", "d20+2", "Petrifying Gaze", "Snake Hair5d6")
|
|
]
|
|
break
|
|
case 36:
|
|
encounter.text = "Mechanical dragon fight! A young brass dragon descends upon you."
|
|
encounter.enemies = [
|
|
createEnemy("Young Brass Mecha Dragon", calculateRoll("13d10+39"), 17, 7, "2d10+4", "d20", "Fire Breath12d6", "Sleep Breath")
|
|
]
|
|
break
|
|
case 37:
|
|
encounter.text = "The young white mecha dragon has sized you up. It considers you a worth adversary"
|
|
encounter.enemies = [
|
|
createEnemy("Young White Mecha Dragon", calculateRoll("14d10+56"), 17, 7, "2d10+4", "d20", "Cold Breath10d8", "Ice Walk")
|
|
]
|
|
break
|
|
case 38:
|
|
encounter.text = "An cyborg death squad!"
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg A", calculateRoll("2d8+6"), 13, 5, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg B", calculateRoll("2d8+6"), 13, 5, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg C", calculateRoll("2d8+6"), 13, 5, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg D", calculateRoll("2d8+6"), 13, 5, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg E", calculateRoll("2d8+6"), 13, 5, "1d12+3", "d20+1"),
|
|
createEnemy("Cyborg Leader", calculateRoll("5d8+6"), 13, 5, "3d12+3", "d20+1", "Rally Cry")
|
|
]
|
|
break
|
|
case 39:
|
|
encounter.text = "Raiders are in full force here!"
|
|
encounter.enemies = [
|
|
createEnemy("Raider A", calculateRoll("3d8"), 15, 4, "1d6+2", "d20+2"),
|
|
createEnemy("Raider B", calculateRoll("3d8"), 15, 4, "1d6+2", "d20+2"),
|
|
createEnemy("Raider C", calculateRoll("3d8"), 15, 4, "1d6+2", "d20+2"),
|
|
createEnemy("Raider D", calculateRoll("3d8"), 15, 4, "1d6+2", "d20+2"),
|
|
createEnemy("Raider E", calculateRoll("3d8"), 15, 4, "1d6+2", "d20+2")
|
|
]
|
|
break
|
|
case 40:
|
|
encounter.text = "The stone mover has been building pillars of rocks and then watches them fall over. He's kinda pissed that you've interrupted his game."
|
|
encounter.enemies = [
|
|
createEnemy("Stone Mover Bot", calculateRoll("11d12+55"), 17, 9, "3d8+6", "d20+2", "Throw Rock4d10+6")
|
|
]
|
|
break
|
|
case 41:
|
|
encounter.text = "The shield hologram is blocking path. Some hacker from eons ago must have absent mindedly placed this here and forgot about it."
|
|
encounter.enemies = [
|
|
createEnemy("Shield Hologram", calculateRoll("15d10+60"), 17, 7, "4d6+4", "d20-1", "Shield")
|
|
]
|
|
break
|
|
case 42:
|
|
encounter.text = "You have caught the focus of a young black mecha dragon. It's positioning itself for attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Young Black Mecha Dragon", calculateRoll("15d10+45"), 18, 7, "4d6+8", "d20+2", "Acid Breath11d8")
|
|
]
|
|
break
|
|
case 43:
|
|
encounter.text = "You suddenly fall into a pit! This is no ordinary trap, for a Young Copper Mecha Dragon has been enslaved here."
|
|
encounter.enemies = [
|
|
createEnemy("Young Copper Mecha Dragon", calculateRoll("14d10+42"), 17, 7, "4d6+8", "d20+1", "Acid Breath9d8", "Slowing Breath")
|
|
]
|
|
break
|
|
case 44:
|
|
encounter.text = "The ninja assassin finally reveals himself. \"You have no idea how long I have been waiting for this moment!\""
|
|
encounter.enemies = [
|
|
createEnemy("Assassin", calculateRoll("12d8+24"), 15, 6, "2d6+6", "d20+3")
|
|
]
|
|
break
|
|
case 45:
|
|
encounter.text = "You feel an unexpected cold wind. It can only be one thing: the giant frost robot approaches!"
|
|
encounter.enemies = [
|
|
createEnemy("Frost Robot", calculateRoll("12d12+60"), 15, 9, "6d12+12", "d20-1")
|
|
]
|
|
break
|
|
case 46:
|
|
encounter.text = "\"How do you actually kill a pool of nanomachines?\" No one seems to know the answer, but here you are facing one anyway. Tough luck!"
|
|
encounter.enemies = [
|
|
createEnemy("Nano Pool", calculateRoll("15d12+75"), 15, 8, "3d10+15", "d20+1")
|
|
]
|
|
break
|
|
case 47:
|
|
encounter.text = "You've had no qualms killing its drone bretheren before. Perhaps that is why the Snake Spirit Drone holds such malice towards you. Prepare for the fight of your life!"
|
|
encounter.enemies = [
|
|
createEnemy("Snake Spirit Drone", calculateRoll("10d10+20"), 15, 7, "8d8+4", "d20+3", "Social Engineering", "Tesla Coil9d6")
|
|
]
|
|
break
|
|
case 48:
|
|
encounter.text = "The hairs on your arm raise as if you've entered a static field. Yes, it's a young bronze mechanical dragon preparing to strike. Dodge out of the way if you can!"
|
|
encounter.enemies = [
|
|
createEnemy("Young Bronze Mecha Dragon", calculateRoll("15d10+60"), 18, 8, "4d6+10", "d20+1", "Lightning Breath10d10", "Repulsion Breath")
|
|
]
|
|
break
|
|
case 49:
|
|
encounter.text = "There was once a great forest here. It has all been destroyed by the ambition of man. All that is left is the vengeance of the young green mecha dragon that stands in your way."
|
|
encounter.enemies = [
|
|
createEnemy("Young Green Mecha Dragon", calculateRoll("16d10+48"), 18, 7, "4d6+8", "d20+1", "Poison Breath12d6")
|
|
]
|
|
break
|
|
case 50:
|
|
encounter.text = "My god, that must be why they call them cloud bots. They're so tall that it's as if they can reach the clouds. Defend yourself!"
|
|
encounter.enemies = [
|
|
createEnemy("Cloud Bot", calculateRoll("16d12+96"), 14, 12, "6d8+16", "d20", "Throw Rock4d10+8", "Control Weather")
|
|
]
|
|
break
|
|
case 51:
|
|
encounter.text = "A nature drone has stationed itself here. It's the protector of the natural world. You upset the balance."
|
|
encounter.enemies = [
|
|
createEnemy("Nature Drone", calculateRoll("12d12+60"), 16, 10, "6d6+12", "d20-1"),
|
|
createEnemy("Tree Hologram", calculateRoll("7d12+14"), 13, 10, "3d6+4", "d20-2")
|
|
]
|
|
break
|
|
case 52:
|
|
encounter.text = "A young blue mecha dragon. What else can be said? You know you're in trouble now."
|
|
encounter.enemies = [
|
|
createEnemy("Young Blue Mecha Dragon", calculateRoll("16d10+64"), 18, 9, "12d6+10", "d20", "Lightning Breath10d10")
|
|
]
|
|
break
|
|
case 53:
|
|
encounter.text = "A young silver mecha dragon. It's over for you. Make your peace."
|
|
encounter.enemies = [
|
|
createEnemy("Young Silver Mecha Dragon", calculateRoll("16d10+8-"), 18, 10, "4d6+12", "d20", "Cold Breath12d8", "Paralyzing Breath")
|
|
]
|
|
break
|
|
case 54:
|
|
encounter.text = "This is the lair of the Zombie Abomination. You say your prayers to any god that would listen. It's time to prove your worth."
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Abonmination", calculateRoll("18d10"), 17, 9, "6d6+15", "d20-1", "Enslave", "Psychic Drain3d6")
|
|
]
|
|
break
|
|
case 55:
|
|
encounter.text = "A demon zombie is here. There must have been some mistake, but you are marked for death."
|
|
encounter.enemies = [
|
|
createEnemy("Demon Zombie", calculateRoll("16d8+64"), 17, 8, "2d6+8", "d20+4")
|
|
]
|
|
break
|
|
case 56:
|
|
encounter.text = "The stone zombie is against the natural order. It does not fill any niche in the living world. It must be destroyed."
|
|
encounter.enemies = [
|
|
createEnemy("Stone Zombie", calculateRoll("17d10+85"), 17, 10, "6d8+12", "d20-1")
|
|
]
|
|
break
|
|
case 57:
|
|
encounter.text = "You've gotten on the wrong side of the young gold mecha dragon. Perhaps you should not have trespassed on its sovereign land."
|
|
encounter.enemies = [
|
|
createEnemy("Young Gold Mecha Dragon", calculateRoll("17d10+85"), 18, 10, "4d6+12", "d20+2", "Fire Breath10d10", "Weakening Breath")
|
|
]
|
|
break
|
|
case 58:
|
|
encounter.text = "The young red mecha dragon wastes no time in its pursuit of victims. It has selected you for its next meal."
|
|
encounter.enemies = [
|
|
createEnemy("Young Red Mecha Dragon", calculateRoll("17d10+85"), 18, 10, "4d6+12", "d20", "Fire Breath16d6")
|
|
]
|
|
break
|
|
case 59:
|
|
encounter.text = "The rocket zombie wants a taste and it has you in its sights."
|
|
encounter.enemies = [
|
|
createEnemy("Rocket Zombie", calculateRoll("15d10+45"), 18, 8, "1d8+4", "d20+4", "Spit Poison10d8", "Thermite Strike4d6", "Bestow Curse", "Paralysis Mite", "Mind Control Serum")
|
|
]
|
|
break
|
|
case 60:
|
|
encounter.text = "The fire bots were developed for environments that would burn others to a crisp instantly. This means this one is immune to fire damage. It's ready to fight now."
|
|
encounter.enemies = [
|
|
createEnemy("Fire Bot", calculateRoll("13d12+78"), 18, 11, "6d6+7", "d20-1", "Throw Rock4d10+7")
|
|
]
|
|
break
|
|
}
|
|
break
|
|
case "boss":
|
|
if (encounter.cr == null) encounter.cr = 13
|
|
multiplier = 1 + (encounter.cr - 13) / 10
|
|
switch (getRandomInteger(0, 60)) {
|
|
case 0:
|
|
encounter.text = "An ancient war reenactment is being rendered by a hologram deck caught in a loop. And you find yourself right in the middle of it."
|
|
break
|
|
case 1:
|
|
encounter.text = "A computer readout shows that a satellite in low orbit armed with titanium rods is aiming right on your location."
|
|
break
|
|
case 2:
|
|
encounter.text = "A massive citadel has crashed here. In the crater that it has created, you see a community of people working together to survive."
|
|
break
|
|
case 3:
|
|
encounter.text = "You have found the burrow hole of a giant drill worm. The cave leads deep into the earth."
|
|
break
|
|
case 4:
|
|
encounter.text = "You notice that a VTOL heavy is tracking you. It's not attacking, but you know this aircraft is loaded with massive artillery. What do they want?"
|
|
break
|
|
case 5:
|
|
encounter.text = "You see a nuclear bunker with the unmistakable markings of the military. It's bound to have some important equipment, but it will be defended heavily with automated fortifications."
|
|
break
|
|
case 6:
|
|
encounter.text = "A factory is completely out of control, creating drones and sending those drones out to collect raw materials to build more drones. It must be stopped."
|
|
break
|
|
case 7:
|
|
encounter.text = "A robot approaches, hauling a makeshift sled behind it. On it: several survivors and cyborgs banding together to survive the post apocalypse."
|
|
break
|
|
case 8:
|
|
encounter.text = "A keypad is embedded in a ruined wall. You hear clicking and it's only a matter of time before the intruder countermeasures activate."
|
|
break
|
|
case 9:
|
|
encounter.text = "A swarm of nanomachines are eating away at the face of a building. If you are careful, you can pass by without being turned into a puddle of gray mass."
|
|
break
|
|
case 10:
|
|
encounter.text = "Your limbs begin to lock up. An insatiable hunger sweeps over you. Your mind lusts for carnage. But you were so careful! There was no way that you were infected by the nano-necrotic virus. Or were you?"
|
|
break
|
|
case 11:
|
|
encounter.text = "Ambushed! Cyborg raiders have surrounded you. However, instead of killing you, they are here to make a bargain."
|
|
break
|
|
case 12:
|
|
encounter.text = "An AI core is propped up here. Several defense mechanisms are activated. Humungous anti-tank turrets aim at your direction. All for the purpose of you answering a single question: \"Why is life?\""
|
|
break
|
|
case 13:
|
|
encounter.text = "You crash into the hull of a dilapidated space vessel. A command prompt blinks at you. Self destruct imminent in t-minus 3 minutes. Apparently you've stumbled in here at the right time."
|
|
break
|
|
case 14:
|
|
encounter.text = "A message is somehow beamed across the sky: \"WE HAVE ARRIVED\". As if you didn't have enough problems already."
|
|
break
|
|
case 15:
|
|
encounter.text = "Entering this area has triggered a sequence of events leading up to a portal engulfing your body entirely."
|
|
break
|
|
case 16:
|
|
encounter.text = "Time has stopped. You don't know what has set off this anomaly, but you are going to have to deal with it now lest you be trapped in time forever."
|
|
break
|
|
case 17:
|
|
encounter.text = "A strange vessel has landed here. It's shimmering lights beckon you to board it."
|
|
break
|
|
case 18:
|
|
encounter.text = "You witness a ballistic missile tear across the sky. You happen to know that type of weapon has a nuclear payload. It's time to take cover."
|
|
break
|
|
case 19:
|
|
encounter.text = "Of your many faults, not noticing obvious traps may be the one that kills you. In this case you've entered a gravity net and have no way out."
|
|
break
|
|
case 20:
|
|
encounter.text = "A forcefield generator activates and it surrounds you with impenetrable energy. The walls are closing in on you and you have to figure out something fast."
|
|
break
|
|
case 21:
|
|
encounter.text = "By all indications, nothing is going wrong. It's just a normal day without the threat of zombies or alien invasion. Just kidding, you're about to die."
|
|
break
|
|
case 22:
|
|
encounter.text = "A keyboard with no computer or output device is visible. Curiosity takes the better of you and you begin typing. Defying all logic, a prompt appears in the sky."
|
|
break
|
|
case 23:
|
|
encounter.text = "A hologram appears. It is the arbiter of a great AI that has lived in the digital plane for some time. It appears to be granting you a single wish."
|
|
break
|
|
case 24:
|
|
encounter.text = "A man appears on the horizon. He is running away from some unseen assailant. Suddenly, he is disintegrated into a cloud of pink spray. What power can cause this?"
|
|
break
|
|
case 25:
|
|
encounter.text = "This happens to be a site for a large rocket concealed underground. The bay doors open slowly. The realization finally strikes you: the entire area will be flooded with explosive propelant in a matter of minutes."
|
|
break
|
|
case 26:
|
|
encounter.text = "As you step forward, you realize that you have entered a pocket dimension. The world fades away, replaced with the purple gradient of an endless night. At some point you were scanned by some sort of digitizer. Without a portal to send you back to the real world, you may be trapped here forever."
|
|
case 27:
|
|
encounter.text = "A competing military group is pursuing you. Run!"
|
|
break
|
|
case 28:
|
|
encounter.text = "It's clear: you are lost. It might have been a minute ago or an hour ago, but you have no idea where you are. It doesn't matter anyway because the drones pursuing you are closing in fast."
|
|
break
|
|
case 29:
|
|
encounter.text = "This could have been a utopia, however the residents of this walled city have chosen to destroy themselves with constant infighting. Now all that are left are genetic freaks hungering for blood."
|
|
break
|
|
case 30:
|
|
encounter.text = "A horde of zombies is seen in the distance. They are packed so tightly and in such great numbers that you can't see the ground beneath them. Run for your life."
|
|
break
|
|
case 31:
|
|
encounter.text = "An adult black mecha dragon approaches. You are not ready for this."
|
|
encounter.enemies = [
|
|
createEnemy("Adult Black Mecha Dragon", calculateRoll("17d12+85"), 19, 11, "6d6+18", "d20+2", "Acid Breath12d8", "Frightful Presence", "Wing Attack2d6+6")
|
|
]
|
|
break
|
|
case 32:
|
|
encounter.text = "An adult brass mecha dragon is here. It's pissed!"
|
|
encounter.enemies = [
|
|
createEnemy("Adult Brass Mecha Dragon", calculateRoll("15d12+75"), 18, 11, "6d6+18", "d20", "Fire Breath13d6", "Sleep Breath", "Frightful Presence", "Wing Attack2d6+6")
|
|
]
|
|
break
|
|
case 33:
|
|
encounter.text = "An adult bronze mecha dragon is charging up for an attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Adult Bronze Mecha Dragon", calculateRoll("17d12+102"), 19, 12, "6d6+21", "d20", "Repulsion Breath", "Lightning Breath12d10", "Wing Attack2d6+6")
|
|
]
|
|
break
|
|
case 34:
|
|
encounter.text = "An adult copper mecha dragon shifts its gaze at you. You are doomed."
|
|
encounter.enemies = [
|
|
createEnemy("Adult Copper Mecha Dragon", calculateRoll("16d12+80"), 18, 11, "6d6+18", "d20+1", "Acid Breath12d8", "Slowing Breath", "Wing Attack2d6+6")
|
|
]
|
|
break
|
|
case 35:
|
|
encounter.text = "An adult green mechadragon is nesting here. You really shouldn't have disturbed it."
|
|
encounter.enemies = [
|
|
createEnemy("Adult Green Mecha Dragon", calculateRoll("18d12+90"), 19, 11, "6d6+18", "d20+1", "Poison Breath16d6")
|
|
]
|
|
break
|
|
case 36:
|
|
encounter.text = "An adult white mecha dragon is here. The wrong place and wrong time, unfortunately for you."
|
|
encounter.enemies = [
|
|
createEnemy("Adult White Mecha Dragon", calculateRoll("16d12+96"), 18, 11, "6d6+18", "d20", "Cold Breath12d8", "Wing Attack2d6+6")
|
|
]
|
|
break
|
|
case 37:
|
|
encounter.text = "The lead scientist descends from their lab. He says no words, but raises his hands as if he is going to prepare a spell. Get ready!"
|
|
encounter.enemies = [
|
|
createEnemy("Lead Scientist", calculateRoll("18d8+18"), 12, 4, "1d4+2", "d20+14", "Chrono Trigger", "Force Field", "Tesla Coild6", "Phaseshift", "Snow Blaster8d8", "Teleporter"),
|
|
createEnemy("Assistant A", calculateRoll("9d8"), 12, 5, "1d4+2", "d20+2", "Cold Snap4d6+8", "Incendiary Rocket8d6", "Power Armor", "Incendiary Sabot Round1d10"),
|
|
createEnemy("Assistant B", calculateRoll("9d8"), 12, 5, "1d4+2", "d20+2", "Cold Snap4d6+8", "Incendiary Rocket8d6", "Power Armor", "Incendiary Sabot Round1d10")
|
|
]
|
|
break
|
|
case 38:
|
|
encounter.text = "The hologram genie mocks you as you enter its domain. It seems like it wants to pick a fight with you."
|
|
encounter.enemies = [
|
|
createEnemy("Hologram Genie", calculateRoll("14d10+84"), 17, 9, "2d6+8", "d20+2")
|
|
]
|
|
break
|
|
case 39:
|
|
encounter.text = "A horror to behold. The alien demons approach with cruel intentions. Their winged visages come into clear view."
|
|
encounter.enemies = [
|
|
createEnemy("Alien Demon A", calculateRoll("18d8+72"), 18, 8, "1d10+4", "d20+3"),
|
|
createEnemy("Alien Demon B", calculateRoll("18d8+72"), 18, 8, "1d10+4", "d20+3"),
|
|
createEnemy("Alien Demon C", calculateRoll("18d8+72"), 18, 8, "1d10+4", "d20+3")
|
|
]
|
|
break
|
|
case 40:
|
|
encounter.text = "The horned alien stalks the land before you. It grins, revealing a hideous set of teeth."
|
|
encounter.enemies = [
|
|
createEnemy("Horned Alien", calculateRoll("17d10+85"), 18, 10, "6d8+18", "d20+3", "Hurl Flame4d6")
|
|
]
|
|
break
|
|
case 41:
|
|
encounter.text = "The temperature of the local area has cooled significantly. You see it now: an ice zombie makes its presence known."
|
|
encounter.enemies = [
|
|
createEnemy("Ice Zombie", calculateRoll("19d10+76"), 18, 10, "6d4+15", "d20+2", "Wall of Ice")
|
|
]
|
|
break
|
|
case 42:
|
|
encounter.text = "The Zombie lord resides here. It has summoned its followers and directs the assault with his decayed finger pointed at you."
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Lord", calculateRoll("13d8+39"), 17, 9, "3d6+4", "d20", "Hold Person", "Silence", "Harm14d6", "Blinding Dust", "Whirlwind of Sand"),
|
|
createEnemy("Zombie A", calculateRoll("9d8+18"), 11, 5, "2d6+3", "d20-1"),
|
|
createEnemy("Zombie B", calculateRoll("9d8+18"), 11, 5, "2d6+3", "d20-1"),
|
|
createEnemy("Zombie C", calculateRoll("9d8+18"), 11, 5, "2d6+3", "d20-1")
|
|
]
|
|
break
|
|
case 43:
|
|
encounter.text = "The signs are clear: mounds of disturbed earth, pools of slime, and the digested remains of those foolish to face the creature. Yes, it's the Cyborg Worm. The earth rumbles, announcing its entry into the fray."
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg Worm", calculateRoll("15d20+90"), 18, 14, "6d6+18", "d20-2", "Tail Stinger12d6+19")
|
|
]
|
|
break
|
|
case 44:
|
|
encounter.text = "The only way to describe it is that it's a twisted combination of a mecha dragon and a giant millipede drone. The tank walker makes a sickening path through the debris toward you."
|
|
encounter.enemies = [
|
|
createEnemy("Tank Walker", calculateRoll("17d12+85"), 17, 11, "6d10+7", "d20+1", "Swallow6d6")
|
|
]
|
|
break
|
|
case 45:
|
|
encounter.text = "The storm giant zombie pays little heed toward you. Yet, you are in its path. Hearing the sudden crack of lightning jolts you."
|
|
encounter.enemies = [
|
|
createEnemy("Storm Giant Zombie", calculateRoll("20d12+100"), 16, 14, "12d6+18", "d20+2", "Hydraulic Dam", "Lightning Strike12d8")
|
|
]
|
|
break
|
|
case 46:
|
|
encounter.text = "You have entered the realm of a powerful nano-necrotic vampire. Its coven is poised to strike!"
|
|
encounter.enemies = [
|
|
createEnemy("Nano Vampire", calculateRoll("17d8+68"), 16, 9, "3d8+8", "d20+4", "Brain Backdoor", "Nanomorph"),
|
|
createEnemy("Nano Vampire Spawn", calculateRoll("11d8+33"), 15, 6, "2d4+3", "d20+3", "Bite3d6+3"),
|
|
createEnemy("Nano Vampire Spawn", calculateRoll("11d8+33"), 15, 6, "2d4+3", "d20+3", "Bite3d6+3")
|
|
]
|
|
break
|
|
case 47:
|
|
encounter.text = "The hulking mass of the Rhino Drone enters the scene. It rears up revealing its many clawed feet. The tail whips around haphazardly throwing rubble around like they were pebbles."
|
|
encounter.enemies = [
|
|
createEnemy("Rhino Drone", calculateRoll("16d12+64"), 17, 10, "5d10+12", "d20+3", "Lightning Breath12d10", "Swallow6d6", "Trample2d10+6")
|
|
]
|
|
break
|
|
case 48:
|
|
encounter.text = "The fire holograms are comprised out of pure, burning energy. One such warrior is here and is bent on exacting revenge on some forgotten slight."
|
|
encounter.enemies = [
|
|
createEnemy("Fire Hologram", calculateRoll("16d10+112"), 17, 10, "4d6+12", "d20+1", "Hurl Flame5d6")
|
|
]
|
|
break
|
|
case 49:
|
|
encounter.text = "The winged cyborgs look like a cross between an ape and a boar. This one angles its terrible snout you and makes a menacing grunt."
|
|
encounter.enemies = [
|
|
createEnemy("Nalfeshnee", calculateRoll("16d10+96"), 18, 10, "8d6+5", "d20", "Horror Nimbus")
|
|
]
|
|
break
|
|
case 50:
|
|
encounter.text = "The phoenix bot attacks! This gargantuan bird swoops in and engulfs the combat area with its awesome wings."
|
|
encounter.enemies = [
|
|
createEnemy("Phoenix Bot", calculateRoll("16d20+80"), 15, 13, "8d8+18", "d20")
|
|
]
|
|
break
|
|
case 51:
|
|
encounter.text = "It wasn't your imagination. It moved. You swear it. Indeed, the robotic statue is poised for attack!"
|
|
encounter.enemies = [
|
|
createEnemy("Robotic Statue", calculateRoll("10d12+20"), 17, 7, "2d10+4", "d20-2")
|
|
]
|
|
break
|
|
case 52:
|
|
encounter.text = "You've never seen the undead quite like this. The Zombieclaw raises its outrageous talons. It is going to strike at any moment!"
|
|
encounter.enemies = [
|
|
createEnemy("Zombieclaw", calculateRoll("17d10+34"), 16, 8, "6d10+8", "d20+3", "Shadow Jump5d12+2", "Deadly Reach")
|
|
]
|
|
break
|
|
case 53:
|
|
encounter.text = "A shape changing alien is already a formidable opponent. The deathalien is the ungodly undead version of that. It bears down on you with great ill intent."
|
|
encounter.enemies = [
|
|
createEnemy("Death Alien", calculateRoll("18d8+72"), 15, 10, "6d8+15", "d20+3", "Phantom Deathalien6d6")
|
|
]
|
|
break
|
|
case 54:
|
|
encounter.text = "A cultist inquisitor is here. She expected you to come this way. You're going to pay for that mistake."
|
|
encounter.enemies = [
|
|
createEnemy("Cultist Inquisitor", calculateRoll("23d8+46"), 16, 10, "12d8+24", "d20+2", "Holographic Dagger1d8+5")
|
|
]
|
|
break
|
|
case 55:
|
|
encounter.text = "This is proof that fate has it in for you. You somehow have stumbled upon the chamber of an AI Brain. It rises out of its brine pool to summon its minions."
|
|
encounter.enemies = [
|
|
createEnemy("AI Brain", calculateRoll("20d10+100"), 10, 7, "5d8+7", "d20", "Mind Blast5d10+5")
|
|
]
|
|
break
|
|
case 56:
|
|
encounter.text = "You see the Nanomorphic Mutant. It's a horrific creature, born of pure hatred and evil. It has the wings of a dragon, but crawls around on four legs like a bastard insect."
|
|
encounter.enemies = [
|
|
createEnemy("Nanomorphic Mutant", calculateRoll("10d12+50"), 18, 10, "6d10+10", "d20+1", "Regenderation")
|
|
]
|
|
break
|
|
case 57:
|
|
encounter.text = "Acid drips onto the floor from its nasty maw. The massive megapede drone marks its territory with the bodies of those foolish enough to challenge it. You may count yourself among them in short order."
|
|
encounter.enemies = [
|
|
createEnemy("Megapede Drone", calculateRoll("13d20+39"), 15, 10, "6d10+12", "d20", "LifeDrain3d10", "Psychic Bomb5d8")
|
|
]
|
|
break
|
|
case 58:
|
|
encounter.text = "The skull zombie holds dominion over this lair. It turns its three heads for you to plainly see its horrific visage."
|
|
encounter.enemies = [
|
|
createEnemy("Skull Zombie", calculateRoll("15d8+45"), 18, 8, "24d6", "d20+3", "Deathly Ray5d8+5")
|
|
]
|
|
break
|
|
case 59:
|
|
encounter.text = "The abducted have the blood of aliens and their power too. It harnesses the power of water. Pools of which gather at its feet. It's ready to defend itself."
|
|
encounter.enemies = [
|
|
createEnemy("The Abducted", calculateRoll("18d8+18"), 12, 6, "1d4+2", "d20+2", "Chrono Trigger", "Harden Security", "Snow Blaster8d8", "Tesla Coil8d6")
|
|
]
|
|
break
|
|
case 60:
|
|
encounter.text = "You have never seen a monstrosity of this magnitude. The eight legs of the mecha spider dragon crash into the ground one after the other like a symphony of massive hammers. This is the fight of your life."
|
|
encounter.enemies = [
|
|
createEnemy("Mecha Spider Dragon", calculateRoll("15d10+5"), 23, 9, "3d12+12", "d20+8", "Silk Spit", "Spider Breath7d10")
|
|
]
|
|
break
|
|
}
|
|
break
|
|
case "god":
|
|
if (encounter.cr == null) encounter.cr = 17
|
|
multiplier = 1 + (encounter.cr - 17) / 10
|
|
switch (getRandomInteger(0, 60)) {
|
|
case 0:
|
|
encounter.text = "Seismic indicators are sounding off. Earthquakes are being detected all across the globe!"
|
|
break
|
|
case 1:
|
|
encounter.text = "Your scientists can't believe the results that they're getting from their tests. The planet is coming out of alignment, putting the entire world at risk of freezing to death."
|
|
break
|
|
case 2:
|
|
encounter.text = "An asteroid strike and it's a big one. This might rival what killed the dinosaurs. You don't have much time."
|
|
break
|
|
case 3:
|
|
encounter.text = "You hear it before you see it. Two great citadels, flying fortresses armed to the teeth, are battling in the distance. The very earth quakes from the devastation."
|
|
break
|
|
case 4:
|
|
encounter.text = "One of the recruits is sick with the nano-necrotic virus, but he was never bitten nor made contact with the enemy. Is the virus airborne now?"
|
|
break
|
|
case 5:
|
|
encounter.text = "You find a mysterious package. Ancient but preserved by several layers of plastic wrap. It has the official logo of the science wing of the military. Under it, a label: \"The Cure\""
|
|
break
|
|
case 6:
|
|
encounter.text = "Weather alert indicates a massive tsunami is heading this way!"
|
|
break
|
|
case 7:
|
|
encounter.text = "Cyclones. Multiple cyclones have touched down and are wreaking havoc all across the surface. This is not natural weather phenomena."
|
|
break
|
|
case 8:
|
|
encounter.text = "Without warning, it begins downpour rain. It's heavy at first, then becomes worrisome. The torrents of water never seem to stop."
|
|
break
|
|
case 9:
|
|
encounter.text = "The earth is opening up before you. A giant sinkhole unlike anything recorded in history threatens to swallow up everything in sight."
|
|
break
|
|
case 10:
|
|
encounter.text = "The temperature is dropping rapidly. This must be a result of a atmospheric processor finally breaking down and malfunctioning. A blizzard is brewing on the horizon."
|
|
break
|
|
case 11:
|
|
encounter.text = "Temperatures are increasing. It's unclear if the planet is drifting too close to the sun or the gamble of humanity toying with the atmosphere has finally cashed out. What is known is that this heatwave that could kill all life on the surface."
|
|
break
|
|
case 12:
|
|
encounter.text = "Historical documents have indicated that the planet is overdue for a magnetic field reversal. Indeed, that time is now. Radiation levels are spiking in this time of transition."
|
|
break
|
|
case 13:
|
|
encounter.text = "The coastline is sinking into the sea! Humanity should have never toiled with the natural geological forces of the world."
|
|
break
|
|
case 14:
|
|
encounter.text = "Fissures erupt everywhere and toxic clouds of gas emanate from deep within the earth. This has the potential to choke out all life on the planet."
|
|
break
|
|
case 15:
|
|
encounter.text = "You finally seen it: the hypercane. A hurricane with such great force that entire cities will topple over. They've tried to warn you, but it's here now and you need to deal with this."
|
|
break
|
|
case 16:
|
|
encounter.text = "The perfect conditions have led to a firestorm! It's a self-sustaining fire tornado of a catastrophic magnitude."
|
|
break
|
|
case 17:
|
|
encounter.text = "Cosmic rays penetrate the atmosphere at an alarming rate. Solar activity is at an all time high and life as you know it surely seems doomed."
|
|
break
|
|
case 18:
|
|
encounter.text = "A hailstorm rips through the sky. It is unlike any seen before, however. Giant chunks of ice the size of basketballs tear through buildings leading to great devastation."
|
|
break
|
|
case 19:
|
|
encounter.text = "Hubris. Grasp exceeds grasp. Some damned fool rigged the moon to explode as a misguided science experiment. Now the planet's celestial counterpart is shattered in the sky and the downfall of explosive moon debris is a regular event."
|
|
break
|
|
case 20:
|
|
encounter.text = "Reports indicate that in moments the planet will make a collision with what is known as a rogue black hole. At the very best, you can assume that the planet will be shattered and all life will be destroyed."
|
|
break
|
|
case 21:
|
|
encounter.text = "You know that aliens have been observing the developments on this planet. Now they will no longer stand idly by while the world is in turmoil. They are landing all across the surface and their intentions are unknown."
|
|
break
|
|
case 22:
|
|
encounter.text = "Is it something biological or is it the nano virus? No one seems to know, but what they do know is that the ocean has suddenly turned acidic. This has great ramifications for the future."
|
|
break
|
|
case 23:
|
|
encounter.text = "The nuclear dead man's switch has finally been triggered. Nukes are being launched all across the continent. You can expect automated countermeasures from the other continents will result in a nuclear winter."
|
|
break
|
|
case 24:
|
|
encounter.text = "What looks like a cloud has descended onto the surface. It is no ordinary cloud. It consists of millions of nanobots that eat away all material and reproduce at an astonishing rate."
|
|
break
|
|
case 25:
|
|
encounter.text = "A great fog covers the surface. No one can explain its origin and it doesn't seem to disapate. That's when the reports of dimensional aliens start flooding in."
|
|
break
|
|
case 26:
|
|
encounter.text = "Tandem lightning strikes all across the globe are occuring all at once. Some speculate that it is some sort of cosmological phenomenon passing through the galaxy."
|
|
break
|
|
case 27:
|
|
encounter.text = "Sea level rise is an expected phenomena as the glaciers melt. However, recent events have led to unprecedented levels of increase. They say the planet can be covered with one giant ocean and you are powerless to stop it."
|
|
break
|
|
case 28:
|
|
encounter.text = "The natural world has been losing an unseen war against the droids. However, some unprecedented force is striking back. Incredible blooms of natural growth have been spotted everywhere. Growth of organic life will soon overtake everything."
|
|
break
|
|
case 29:
|
|
encounter.text = "A series of portals open up everywhere you can see. Alternate dimensions, alien forces, evils from untold worlds. They're all converging here and now."
|
|
break
|
|
case 30:
|
|
encounter.text = "It's finally happening. The chronal nuke went off and now time is moving backward. Slowly at first, then the quickening. If you do nothing, reality is surely doomed as all existence will eventually return to a single point of energy."
|
|
break
|
|
case 31:
|
|
encounter.text = "The adult blue dragon claws at the ground just before it. It's bored. It has decided that you will be its new play thing."
|
|
encounter.enemies = [
|
|
createEnemy("Adult Blue Dragon", calculateRoll("18d12+108"), 19, 12, "6d10+21", "d20", "Lightning Breath12d10", "Wing Attack2d6+7")
|
|
]
|
|
break
|
|
case 32:
|
|
encounter.text = "The gold alien dragon has deemed you unworthy. Prove it wrong."
|
|
encounter.enemies = [
|
|
createEnemy("Gold Alien Dragon", calculateRoll("19d12+133"), 19, 12, "6d10+21", "d20+2", "Fire Breath 12d10", "Weakening Breath")
|
|
]
|
|
break
|
|
case 33:
|
|
encounter.text = "The adult Cyborg dragon has broken its chains and now stands before you. Whatever events have ocurred to bring it to this place, it places the blame on you for its centuries of torture."
|
|
encounter.enemies = [
|
|
createEnemy("Adult Cyborg Dragon", calculateRoll("19d12+133"), 19, 12, "6d10+21", "d20", "Fire Breath18d6", "Wing Attack2d6+8")
|
|
]
|
|
break
|
|
case 34:
|
|
encounter.text = "You didn't do anything wrong. The silver robot dragon just doesn't like you."
|
|
encounter.enemies = [
|
|
createEnemy("Silver Robot Dragon", calculateRoll("18d12+126"), 19, 13, "6d10+24", "d20", "Cold Breath13d8", "Paralyzing Breath")
|
|
]
|
|
break
|
|
case 35:
|
|
encounter.text = "The zombie black dragon goads you into a fight."
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Black Dragon", calculateRoll("21d20+147"), 22, 15, "6d10+24", "d20+2", "Acid Breath15d8", "Wing Attack2d6+8")
|
|
]
|
|
break
|
|
case 36:
|
|
encounter.text = "From the ashes rises the molten robot!"
|
|
encounter.enemies = [
|
|
createEnemy("Molten Robot", calculateRoll("10d20+70"), 18, 13, "4d6+16", "d20+8", "Fiery Assault4d8+16", "Explosive Round4d8+16")
|
|
]
|
|
break
|
|
case 37:
|
|
encounter.text = "The interdimensional alien is quite the curiosity. Your wish to study its biology is stymied by the fact that your life is in jeapodary."
|
|
encounter.enemies = [
|
|
createEnemy("Interdimensional Alien", calculateRoll("32d12+256"), 22, 17, "6d12+18", "d20+2", "Beguiling Gaze", "Hypnotic Gaze")
|
|
]
|
|
break
|
|
case 38:
|
|
encounter.text = "You stand there, mouth agape trying to understand it. You can't. The cosmic alien god attacks!"
|
|
encounter.enemies = [
|
|
createEnemy("Cosmic Alien God", calculateRoll("16d20+112"), 15, 14, "6d6+16", "d20", "Poison Jet4d6", "Psychic Whispers6d10")
|
|
]
|
|
break
|
|
case 39:
|
|
encounter.text = "The ancient mecha red dragon has lived to see entire civilizations rise and fall. You are nothing in its presence."
|
|
encounter.enemies = [
|
|
createEnemy("Ancient Mecha Red Dragon", calculateRoll("21d20+147"), 22, 15, "6d8+30", "d20+2", "Fire Breath26d6", "Wing Attack2d6+10")
|
|
]
|
|
break
|
|
case 40:
|
|
encounter.text = "The ancient mecha gold dragon holds on to a dark secret that jeopordizes everything that you know. Perhaps it will impart its knowledge onto you once you prove you're worthy. Many have tried and failed as evidenced by the bones laid asunder."
|
|
encounter.enemies = [
|
|
createEnemy("Ancient Gold Dragon", calculateRoll("28d20+252"), 22, 15, "6d10+24", "d20+2", "Fire Breath13d10", "Weakening Breath")
|
|
]
|
|
break
|
|
case 41:
|
|
encounter.text = "Semfor 42, the leader of the cyborgs, stands at the ready. You have displeased her and now she will exact her revenge on you personally."
|
|
encounter.enemies = [
|
|
createEnemy("Semfor 42", calculateRoll("40d10+360"), 21, 16, "4d8+16", "d20+7", "Horrid Touch8d10", "Immolating Gaze4d10", "Teleporter")
|
|
]
|
|
break
|
|
case 42:
|
|
encounter.text = "The alien hive mind emerges from the deepest recesses of the cosmos. A wicked grin betrays his truly diabolical plans for you."
|
|
encounter.enemies = [
|
|
createEnemy("Alien Hive Mind", calculateRoll("18d10+90"), 18, 13, "4d8+27", "d20+3", "Awaken Greed", "Teleporter", "Regenerate", "Inflict Wounds4d8+27", "Invisibility")
|
|
]
|
|
break
|
|
case 43:
|
|
encounter.text = "The holographic herald of the AI singularity has awaited eons for its chance to lead his assault onto the material world. It does not see you as a threat. Only an inconvenience."
|
|
encounter.enemies = [
|
|
createEnemy("AI Singularity", calculateRoll("22d12+176"), 22, 17, "3d10+30", "d20+2", "Hack Force", "Holographic Brimstone20d8", "Doomsday Calculation2d8", "Raise Holograms")
|
|
]
|
|
break
|
|
case 44:
|
|
encounter.text = "The zombie tank is a mountain of meat designed to crush all before it. Its thick, interwoven layers of carbon fibre protect it from direct damage."
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Tank", calculateRoll("16d20+160"), 17, 16, "4d10+40", "d20+7", "Piledriver6d10")
|
|
]
|
|
break
|
|
case 45:
|
|
encounter.text = "The raptor drone is fast. It cuts a path towards you in the time it takes you to blink. It's all over for you."
|
|
encounter.enemies = [
|
|
createEnemy("Raptor Drone", calculateRoll("16d20+112"), 14, 13, "6d6+14", "d20-1", "Seeker Missile Swarm9d8")
|
|
]
|
|
break
|
|
case 46:
|
|
encounter.text = "The silver skin zombie is so called because of the nano swarm that flows over its body like a molten metal alloy. Constantly moving, this is going to be one tough battle."
|
|
encounter.enemies = [
|
|
createEnemy("Silver Skin Zombie", calculateRoll("19d10+95"), 17, 12, "4d10+12", "d20", "Thermite Strike8d6", "Proximity Alert", "Teleporter")
|
|
]
|
|
break
|
|
case 47:
|
|
encounter.text = "An alien craft descends and begins launching an assault upon you."
|
|
encounter.enemies = [
|
|
createEnemy("UFO", calculateRoll("21d12+136"), 19, 14, "6d8+16", "d20+2", "Laser Whip 5d6+8", "Teleporter")
|
|
]
|
|
break
|
|
case 48:
|
|
encounter.text = "There is no explaining how you are face to face with a Mecha Turtle and yet... here you are. It towers over the skyscrapers and topples buildings with its hardened beakFight!"
|
|
encounter.enemies = [
|
|
createEnemy("Mecha Turtle", calculateRoll("22d20+110"), 20, 13, "6d8+21", "d20", "Steam Breath15d6")
|
|
]
|
|
break
|
|
case 49:
|
|
encounter.text = "An echoing boom reverberates across the area, shaking you to your core. The super soldier is activated."
|
|
encounter.enemies = [
|
|
createEnemy("Super Soldier", calculateRoll("20d10+100"), 20, 13, "6d8+14", "d20=1", "Poison Breath10d8", "Slam3d8+7")
|
|
]
|
|
break
|
|
case 50:
|
|
encounter.text = "A lake with unkown depths is before you. The kraken AI's lair. It emerges, ready to strike out at you."
|
|
encounter.enemies = [
|
|
createEnemy("Kraken AI", calculateRoll("27d20+189"), 18, 17, "9d6+30", "d20", "Lightning Storm12d10", "Ink Cloud3d10", "Fling1d6")
|
|
]
|
|
break
|
|
case 51:
|
|
encounter.text = "The zombie commander controls an incredible army of the dead. Strike now for the good of humanity!"
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Commander", calculateRoll("18d8+54"), 17, 12, "3d6", "Tech Shot4d4", "Missile Strike8d6", "Transporter", "Nano-necrotic Command", "Cryonic Beam3d8", "Radiation Zone6d6", "Dead Vision", "Disabling Injection")
|
|
]
|
|
break
|
|
case 52:
|
|
encounter.text = "So many arms. The Slither Drone crawls into view, waving its gun tentacles all around."
|
|
encounter.enemies = [
|
|
createEnemy("Slither DDrone", calculateRoll("18d10+90"), 18, 9, "12d8+24", "d20+5", "Teleport", "Parry")
|
|
]
|
|
break
|
|
case 53:
|
|
encounter.text = "The alien fiend is protecting something of great value. Put that out of your mind because you should be preparing for one hell of a fight."
|
|
encounter.enemies = [
|
|
createEnemy("Alien Fiend", calculateRoll("24d10+168"), 19, 14, "8d8+32", "d20+2", "Fireball8d6", "Wall of Fire")
|
|
]
|
|
break
|
|
case 54:
|
|
encounter.text = "The Alien God has announced its presence. This fallen and disgraced deity shall now vanquish you in the name of a forgotten vendetta against humanity."
|
|
encounter.enemies = [
|
|
createEnemy("Planetar", calculateRoll("16d10+112"), 19, 12, "4d6+7", "d20+5", "Interdimensional Plague4d10", "Bullet Barrier", )
|
|
]
|
|
break
|
|
case 55:
|
|
encounter.text = "Angelic is the least you can say about the solar sail. Beautiful, powerful. All fear the mighty solar sail!"
|
|
encounter.enemies = [
|
|
createEnemy("Solar Sail", calculateRoll("18d10+144"), 21, 15, "8d6+16", "d20+6", "EM Drive", "Sun Burst8d6", "Flashbang")
|
|
]
|
|
break
|
|
case 56:
|
|
encounter.text = "The cyborg gargantuan laid dormant for unknowable eons. Your arrival, however, triggered a series of events leading to its awakening. Its massive form stirs, sending the earth crumbling before you."
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg Gargantuan", calculateRoll("33d20+330"), 25, 19, "20d8+50", "d20")
|
|
]
|
|
break
|
|
case 57:
|
|
encounter.text = "The mecha worm is much like the cyborg worm, yet it is much more dangerous. A robotic nightmare made of nigh unbreakable metals, its singular goal is clear: your destruction."
|
|
encounter.enemies = [
|
|
createEnemy("Mecha Worm", calculateRoll("15d20+90"), 18, 9, "6d8+18", "d20-2")
|
|
]
|
|
break
|
|
case 58:
|
|
encounter.text = "The raeleus decides to finally make his presence known. He's been watching. Waiting. This half human, half zebra amalgamation is quite the inventor. It employs its grand arsenal on you. Run or fight, he's going to get you."
|
|
encounter.enemies = [
|
|
createEnemy("Raeleus", calculateRoll("19d12+190"), 22, 17, "6d6+10", "d20+5", "Burst Fire6d10+10", "Auto Pistol10d6", "Canister Grenade4d10", "Flash Bang", "Chaff Grenada")
|
|
]
|
|
break
|
|
case 59:
|
|
encounter.text = "The zombie knight is not one to toil with. It's too late for you, but consider this a warning to the next group of fools who think they could stand toe to toe with this undead warrior."
|
|
encounter.enemies = [
|
|
createEnemy("Zombie Knight", calculateRoll("19d8+95"), 20, 11, "3d8+15", "d20+2", "Cybernetic Orb10d6", "Parry", "Digital Wave5d6")
|
|
]
|
|
break
|
|
case 60:
|
|
encounter.text = "This is getting out of hand. Aliens, zombies, and now the Cyborg Mother is on attack! She's a very powerful cybernetic caster that commands a vast network of digital slaves."
|
|
encounter.enemies = [
|
|
createEnemy("Cyborg Mother", calculateRoll("35d8+105"), 17, 10, "2d6+8", "d20+4", "Levitation Jets", "Extradimensional Shift", "Interdimensional Gate", "Mind Control Serum5d10", "Sentry Turret", "Electrified Rod3d6", "Summon Hologram")
|
|
]
|
|
break
|
|
}
|
|
break
|
|
}
|
|
|
|
var characterName = toTitleCase(state.characters[getRandomInteger(0, state.characters.length-1)].name)
|
|
var characterNameAdjustedCase = characterName == "You" ? "you" : characterName
|
|
var possessiveName = getPossessiveName(characterName)
|
|
encounter.text = encounter.text.replaceAll("Character", characterName)
|
|
encounter.text = encounter.text.replaceAll("character", characterNameAdjustedCase)
|
|
encounter.text = encounter.text.replaceAll("character's", possessiveName)
|
|
encounter.text = encounter.text.replaceAll("Character's", toTitleCase(possessiveName))
|
|
|
|
for (var enemy of encounter.enemies) {
|
|
enemy.health = Math.floor(enemy.health * multiplier)
|
|
enemy.ac = Math.floor(enemy.ac * multiplier)
|
|
|
|
damagePrefix = enemy.damage.match(/^\d*d\d*/gi)[0]
|
|
damageSuffix = enemy.damage.match(/(?<=^\d*d\d*)(\+|-).*$/gi)
|
|
damageSuffix = damageSuffix != null ? parseInt(damageSuffix[0]) : 0
|
|
damageSuffix += Math.floor(3 * (multiplier - 1))
|
|
damageSuffix = `${damageSuffix > 0 ? "+" : ""}${damageSuffix}`
|
|
enemy.damage = `${damagePrefix}${damageSuffix == 0 ? "" : damageSuffix}`
|
|
|
|
initiativePrefix = enemy.initiative.match(/^\d*d\d*/gi)[0]
|
|
initiativeSuffix = enemy.initiative.match(/(?<=^\d*d\d*)(\+|-).*$/gi)
|
|
initiativeSuffix = initiativeSuffix != null ? parseInt(initiativeSuffix[0]) : 0
|
|
initiativeSuffix += Math.floor(3 * (multiplier - 1))
|
|
initiativeSuffix = `${initiativeSuffix > 0 ? "+" : ""}${initiativeSuffix}`
|
|
enemy.initiative = `${initiativePrefix}${initiativeSuffix == 0 ? "" : initiativeSuffix}`
|
|
}
|
|
|
|
return encounter
|
|
}
|
|
|
|
function createEnemy(name, health, ac, hitModifier, damage, initiative, ...spells) {
|
|
var enemy = {
|
|
name: name,
|
|
health: health,
|
|
ac: ac,
|
|
hitModifier: hitModifier,
|
|
damage: damage,
|
|
initiative: initiative,
|
|
spells: spells
|
|
}
|
|
return enemy
|
|
}
|
|
|
|
function getUniqueName(name) {
|
|
const letters = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
|
|
var letterIndex = 0
|
|
|
|
var newName
|
|
var enemyMatches
|
|
do {
|
|
newName = `${name} ${letters[letterIndex++]}`
|
|
enemyMatches = state.enemies.filter(x => x.name.toLowerCase() == newName.toLowerCase())
|
|
} while (enemyMatches.length > 0 && letterIndex < letters.length)
|
|
|
|
return newName
|
|
}
|
|
|
|
function createInitiativeOrder() {
|
|
state.initiativeOrder = []
|
|
|
|
for (var character of state.characters) {
|
|
if (character.health <= 0) continue
|
|
state.initiativeOrder.push(character)
|
|
}
|
|
|
|
for (var enemy of state.enemies) {
|
|
if (enemy.health <= 0) continue
|
|
state.initiativeOrder.push(enemy)
|
|
}
|
|
|
|
state.initiativeOrder.sort(function(a, b) {
|
|
return b.calculatedInitiative - a.calculatedInitiative;
|
|
});
|
|
}
|
|
|
|
const levelSplits = [0, 300, 900, 2700, 6500, 14000, 23000, 34000, 48000, 64000, 85000, 100000, 120000, 140000, 165000, 195000, 225000, 265000, 305000, 355000]
|
|
|
|
function getLevel(experience) {
|
|
if (experience < 0) experience = 0
|
|
|
|
var level
|
|
for (level = 0; level < levelSplits.length; level++) {
|
|
if (experience < levelSplits[level]) break
|
|
}
|
|
return level
|
|
}
|
|
|
|
function getNextLevelXp(experience) {
|
|
if (experience < 0) experience = 0
|
|
|
|
var level
|
|
for (level = 0; level < levelSplits.length; level++) {
|
|
if (experience < levelSplits[level]) return levelSplits[level]
|
|
}
|
|
return -1
|
|
}
|
|
|
|
function addXpToAll(experience) {
|
|
if (experience == 0) return ""
|
|
var leveledUp = `\n[The party has gained ${experience} experience!]`
|
|
state.characters.forEach(x => {
|
|
var haveWord = x.name == "You" ? "have" : "has"
|
|
const oldLevel = getLevel(x.experience)
|
|
x.experience += experience
|
|
const newLevel = getLevel(x.experience)
|
|
if (newLevel > oldLevel) leveledUp += `\n[${x.name} ${haveWord} leveled up to ${newLevel}!]`
|
|
})
|
|
return leveledUp
|
|
}
|
|
|
|
function getHealthMax(character) {
|
|
if (character == null) character = getCharacter()
|
|
|
|
var modifier = 0
|
|
var stat = character.stats.find((element) => element.name.toLowerCase() == "constitution")
|
|
if (stat != null) modifier = getModifier(stat.value)
|
|
|
|
var level = getLevel(character.experience)
|
|
return 10 + level * (6 + modifier)
|
|
}
|
|
|
|
function getModifier(statValue) {
|
|
return Math.floor((statValue - 10) / 2)
|
|
}
|
|
|
|
function findSpellCardIndex(name) {
|
|
return storyCards.findIndex((element) => element.type == "spell" && element.title == name)
|
|
}
|
|
|
|
function findSpellCard(name) {
|
|
return storyCards[findSpellCardIndex(name)]
|
|
}
|
|
|
|
function findItemCardIndex(name, storyCardName) {
|
|
return storyCards.findIndex((element) => (element.type == "item" || element.type == "weapon" || element.type == "armor") && (element.title == name || element.title == storyCardName))
|
|
}
|
|
|
|
function findItemCard(name, storyCardName) {
|
|
return storyCards[findItemCardIndex(name, storyCardName)]
|
|
}
|
|
|
|
function stragedyCalculateScores() {
|
|
state.stragedyEnemyScore = 0
|
|
state.stragedyPlayerScore = 0
|
|
var playerHasJoker = false
|
|
var enemyHasJoker = false
|
|
var playerBlessedPoints = 0
|
|
var enemyBlessedPoints = 0
|
|
var doubledPoints = []
|
|
|
|
//check for kings
|
|
for(card of state.stragedyPlayerBattlefield) {
|
|
var points = parseInt(card.match(/(?<=.*)\d+/gi)[0])
|
|
|
|
if (card.includes("k")) {
|
|
doubledPoints.push(points)
|
|
}
|
|
}
|
|
|
|
for(card of state.stragedyEnemyBattlefield) {
|
|
var points = parseInt(card.match(/(?<=.*)\d+/gi)[0])
|
|
|
|
if (card.includes("k")) {
|
|
doubledPoints.push(points)
|
|
}
|
|
}
|
|
|
|
//enemy
|
|
for(card of state.stragedyEnemyBattlefield) {
|
|
var points = parseInt(card.match(/(?<=.*)\d+/gi)[0])
|
|
|
|
if (doubledPoints.includes(points)) {
|
|
points *= 2
|
|
}
|
|
|
|
if (card.includes("q")) {
|
|
state.stragedyPlayerScore += points
|
|
points = 0
|
|
}
|
|
|
|
if (card.includes("?")) {
|
|
enemyHasJoker = true
|
|
}
|
|
|
|
if (card.includes("p")) {
|
|
enemyBlessedPoints += points
|
|
}
|
|
|
|
state.stragedyEnemyScore += points
|
|
}
|
|
|
|
if (enemyHasJoker && state.stragedyEnemyScore < 30) {
|
|
state.stragedyEnemyScore = 30
|
|
} else if (state.stragedyEnemyScore > 30) {
|
|
state.stragedyEnemyScore = Math.max(30, state.stragedyEnemyScore - enemyBlessedPoints)
|
|
}
|
|
|
|
//player
|
|
for(card of state.stragedyPlayerBattlefield) {
|
|
var points = parseInt(card.match(/(?<=.*)\d+/gi)[0])
|
|
|
|
if (doubledPoints.includes(points)) {
|
|
points *= 2
|
|
}
|
|
|
|
if (card.includes("q")) {
|
|
state.stragedyEnemyScore += points
|
|
points = 0
|
|
}
|
|
|
|
if (card.includes("?")) {
|
|
playerHasJoker = true
|
|
}
|
|
|
|
if (card.includes("p")) {
|
|
playerBlessedPoints += points
|
|
}
|
|
|
|
state.stragedyPlayerScore += points
|
|
}
|
|
|
|
if (playerHasJoker && state.stragedyPlayerScore < 30) {
|
|
state.stragedyPlayerScore = 30
|
|
} else if (state.stragedyPlayerScore > 30) {
|
|
state.stragedyPlayerScore = Math.max(30, state.stragedyPlayerScore - playerBlessedPoints)
|
|
}
|
|
}
|
|
|
|
function stragedyEnemyTurn() {
|
|
state.stragedyEnemySkipTurn = false
|
|
state.stragedyEnemyTurnText = ""
|
|
if (state.stragedyPlayerScore > 30) {
|
|
state.stragedyEnemyTurnText = null
|
|
stragedyCheckForWin()
|
|
state.stragedyTurn = "gameOver"
|
|
return
|
|
}
|
|
|
|
var score = state.stragedyEnemyScore
|
|
var hand = state.stragedyEnemyHand
|
|
var deck = state.stragedyEnemyDeck
|
|
var discard = state.stragedyEnemyDiscard
|
|
var battlefield = state.stragedyEnemyBattlefield
|
|
var playerScore = state.stragedyPlayerScore
|
|
var playerHand = state.stragedyPlayerHand
|
|
var playerDeck = state.stragedyPlayerDeck
|
|
var playerDiscard = state.stragedyPlayerDiscard
|
|
var playerBattlefield = state.stragedyPlayerBattlefield
|
|
var playerRetired = state.stragedyPlayerRetired
|
|
var kingCards = new Set()
|
|
|
|
var hasJokerOnBattlefield = false
|
|
for (var card of battlefield) {
|
|
if (card.includes("?")) {
|
|
hasJokerOnBattlefield = true
|
|
break
|
|
}
|
|
}
|
|
|
|
var battlefieldNumbersOnly = []
|
|
for (var card of battlefield) {
|
|
var value = parseInt(card.replaceAll(/\D/g, ""))
|
|
if (value != null) battlefieldNumbersOnly.push(value)
|
|
}
|
|
|
|
var playerBattlefieldNumbersOnly = []
|
|
for (var card of playerBattlefield) {
|
|
var value = parseInt(card.replaceAll(/\D/g, ""))
|
|
if (value != null) playerBattlefieldNumbersOnly.push(value)
|
|
}
|
|
|
|
for(var card of state.stragedyPlayerBattlefield) {
|
|
if (card.includes("k")) {
|
|
kingCards.add(card.match(/(?<=.*)\d+/gi)[0])
|
|
}
|
|
}
|
|
|
|
for(var card of state.stragedyEnemyBattlefield) {
|
|
if (card.includes("k")) {
|
|
kingCards.add(card.match(/(?<=.*)\d+/gi)[0])
|
|
}
|
|
}
|
|
|
|
var hasNumberedCards = hand.filter(x => /^\d+$/gi.test(x)).length > 0
|
|
|
|
var sortedNumberedBattlefieldCards = battlefield.filter(x => /^[kpw\?]*\d+$/gi.test(x)).sort((a, b) => parseInt(a.replaceAll(/\D/gi, "")) - parseInt(b.replaceAll(/\D/gi, "")))
|
|
var highestNumberedBattlefieldCard = sortedNumberedBattlefieldCards.length > 0 ? sortedNumberedBattlefieldCards[sortedNumberedBattlefieldCards.length - 1] : null
|
|
var lowestNumberedBattlefieldCard = sortedNumberedBattlefieldCards.length > 0 ? sortedNumberedBattlefieldCards[0] : null
|
|
|
|
var hasAce = hand.filter(x => /^.*a.*$/gi.test(x)).length > 0
|
|
var hasJack = hand.filter(x => /^.*j.*$/gi.test(x)).length > 0
|
|
var hasQueen = hand.filter(x => /^.*q.*$/gi.test(x)).length > 0
|
|
var hasKing = hand.filter(x => /^.*k.*$/gi.test(x)).length > 0
|
|
var hasJoker = hand.filter(x => /^.*\?.*$/gi.test(x)).length > 0
|
|
var hasWitch = hand.filter(x => /^.*w.*$/gi.test(x)).length > 0
|
|
var hasPriest = hand.filter(x => /^.*p.*$/gi.test(x)).length > 0
|
|
var hasBrigand = hand.filter(x => /^.*b.*$/gi.test(x)).length > 0
|
|
|
|
var faceCardHandCount = hand.filter(x => /.*\D.*/gi.test(x)).length
|
|
|
|
var highestNumberedHandCardToReach30 = null
|
|
var highestNumberedHandCardToReach30Value = 0
|
|
for (var card of hand) {
|
|
if (isNaN(card)) continue
|
|
var value = parseInt(card)
|
|
if (kingCards.has(value.toString())) value *= 2
|
|
if (value > highestNumberedHandCardToReach30Value && score + value <= 30) {
|
|
highestNumberedHandCardToReach30 = card
|
|
highestNumberedHandCardToReach30Value = value
|
|
}
|
|
}
|
|
|
|
var highestNumberedHandCardToReach20 = null
|
|
var highestNumberedHandCardToReach20Value = 0
|
|
for (var card of hand) {
|
|
if (isNaN(card)) continue
|
|
var value = parseInt(card)
|
|
if (kingCards.has(value.toString())) value *= 2
|
|
if (value > highestNumberedHandCardToReach20Value && score + value <= 20) {
|
|
highestNumberedHandCardToReach20 = card
|
|
highestNumberedHandCardToReach20Value = value
|
|
}
|
|
}
|
|
|
|
var kingNumberedCardsInHand = []
|
|
for (var card of hand) {
|
|
if (kingCards.has(card)) kingNumberedCardsInHand.push(card)
|
|
}
|
|
kingNumberedCardsInHand.sort((a, b) => parseInt(a) - parseInt(b))
|
|
|
|
var bestAceCard = null
|
|
var bestAceCardTotal = 0
|
|
for (var card of battlefield) {
|
|
var number = card.replaceAll(/\D/gi, "")
|
|
var playerTotal = 0
|
|
for (var playerCard of playerBattlefield) {
|
|
var playerNumber = playerCard.replaceAll(/\D/gi, "")
|
|
if (playerNumber == number) playerTotal += parseInt(playerNumber)
|
|
}
|
|
if (playerTotal > bestAceCardTotal) bestAceCard = card
|
|
}
|
|
|
|
var bestKingCardToBustPlayer = null
|
|
var bestKingCardToBustPlayerValue = 0
|
|
for (var card of battlefield) {
|
|
var number = card.replaceAll(/\D/gi, "")
|
|
var value = parseInt(number)
|
|
|
|
if (card.includes("q")) continue
|
|
if (kingCards.has(number)) continue
|
|
|
|
var count = 0
|
|
for (var testCard of battlefield) {
|
|
if (testCard.replaceAll(/\D/gi, "") == number) count++
|
|
}
|
|
|
|
if (value * count > bestKingCardToBustPlayerValue && score + value * count <= 30) {
|
|
bestKingCardToBustPlayer = card
|
|
bestKingCardToBustPlayerValue = value
|
|
}
|
|
}
|
|
|
|
var bestKingCardToReach30 = null
|
|
var bestKingCardToReach30Value = 0
|
|
for (var card of battlefield) {
|
|
var number = card.replaceAll(/\D/gi, "")
|
|
var value = parseInt(number)
|
|
|
|
if (card.includes("q")) continue
|
|
if (kingCards.has(number)) continue
|
|
|
|
var count = 0
|
|
for (var testCard of battlefield) {
|
|
if (testCard.replaceAll(/\D/gi, "") == number) count++
|
|
}
|
|
|
|
if (value * count > bestKingCardToReach30Value && score + value * count <= 30) {
|
|
bestKingCardToReach30 = card
|
|
bestKingCardToReach30Value = value
|
|
}
|
|
}
|
|
|
|
var bestJackCardToSave = null
|
|
var bestJackCardToSaveValue = 0
|
|
for (var card of battlefield) {
|
|
if (card.includes("q")) continue
|
|
|
|
var value = parseInt(card.replaceAll(/\D/gi, ""))
|
|
if (kingCards.has(value.toString())) value *= 2
|
|
if (value > bestJackCardToSaveValue && score - value <= 30) {
|
|
bestJackCardToSave = card
|
|
bestJackCardToSaveValue = value
|
|
}
|
|
}
|
|
|
|
var bestQueenCardToBustPlayer = null
|
|
var bestQueenCardToBustPlayerValue = 0
|
|
for (var card of battlefield) {
|
|
if (card.includes("q")) continue
|
|
|
|
var value = parseInt(card.replaceAll(/\D/gi, ""))
|
|
if (kingCards.has(value.toString())) value *= 2
|
|
if (value > bestQueenCardToBustPlayerValue && playerScore + value > 30) {
|
|
bestQueenCardToBustPlayer = card
|
|
bestQueenCardToBustPlayerValue = value
|
|
}
|
|
}
|
|
|
|
var bestQueenCardToSave = null
|
|
var bestQueenCardToSaveValue = 0
|
|
for (var card of battlefield) {
|
|
if (card.includes("q")) continue
|
|
|
|
var value = parseInt(card.replaceAll(/\D/gi, ""))
|
|
if (kingCards.has(value.toString())) value *= 2
|
|
if (value > bestQueenCardToSaveValue && score - value <= 30) {
|
|
bestQueenCardToSave = card
|
|
bestQueenCardToSaveValue = value
|
|
}
|
|
}
|
|
|
|
var bestPriestCardToSave = null
|
|
var bestPriestCardToSaveValue = 0
|
|
for (var card of battlefield) {
|
|
if (card.includes("p")) continue
|
|
|
|
var value = parseInt(card.replaceAll(/\D/gi, ""))
|
|
if (kingCards.has(value.toString())) value *= 2
|
|
if (value > bestPriestCardToSaveValue && score - value <= 30) {
|
|
bestPriestCardToSave = card
|
|
bestPriestCardToSaveValue = value
|
|
}
|
|
}
|
|
|
|
var bestPriestCard = null
|
|
var bestPriestCardValue = 0
|
|
for (var card of battlefield) {
|
|
if (card.includes("p")) continue
|
|
|
|
var value = parseInt(card.replaceAll(/\D/gi, ""))
|
|
if (kingCards.has(value.toString())) value *= 2
|
|
if (value > bestPriestCardValue) {
|
|
bestPriestCard = card
|
|
bestPriestCardValue = value
|
|
}
|
|
}
|
|
|
|
if (hand.length == 0) {
|
|
if (deck.length == 0) state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
else if (score > 30) state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
else state.stragedyEnemyTurnText = stragedyEnemyDrawCard()
|
|
} else if (score > 30 && battlefield.length > 0) {
|
|
if (hasQueen && bestQueenCardToSave != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "q" + bestQueenCardToSave)
|
|
else if (hasPriest && bestPriestCardToSave != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "p" + bestPriestCardToSave)
|
|
else if (hasJack && bestJackCardToSave != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "j" + bestJackCardToSave)
|
|
else if (hasAce && bestAceCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "a" + bestAceCard)
|
|
else if (kingCards.length > 0 && kingNumberedCardsInHand.length > 0) state.stragedyEnemyTurnText = stragedyPlayCard(false, kingNumberedCardsInHand[kingNumberedCardsInHand.length - 1])
|
|
else state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
} else if (playerRetired && score < playerScore) {
|
|
if (hasJoker && playerScore < 30) state.stragedyEnemyTurnText = stragedyPlayCard(false, "?" + lowestNumberedBattlefieldCard)
|
|
else if (hasQueen && bestQueenCardToBustPlayer != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "q" + bestQueenCardToBustPlayer)
|
|
else if (hasAce && bestAceCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "a" + bestAceCard)
|
|
else if (hasKing && bestKingCardToBustPlayer != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "k" + bestKingCardToBustPlayer)
|
|
else if (hasKing && bestKingCardToReach30 != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "k" + bestKingCardToReach30)
|
|
else if (highestNumberedHandCardToReach30 != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, highestNumberedHandCardToReach30)
|
|
else if (hasJoker && playerScore == 30) state.stragedyEnemyTurnText = stragedyPlayCard(false, "?" + lowestNumberedBattlefieldCard)
|
|
else state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
} else if (playerRetired && score > playerScore && !hasJokerOnBattlefield) {
|
|
state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
} else if (playerRetired && score == playerScore) {
|
|
if (highestNumberedHandCardToReach30 != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, highestNumberedHandCardToReach30)
|
|
else state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
} else if (score - playerScore > 20 && !hasJokerOnBattlefield) {
|
|
state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
} else if (deck.length > 0 && hand.length == 1) {
|
|
state.stragedyEnemyTurnText = stragedyEnemyDiscardCard()
|
|
} else if (hasNumberedCards && (score < playerScore || score < 15)) {
|
|
if (score < 20 && highestNumberedHandCardToReach20 != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, highestNumberedHandCardToReach20)
|
|
else if (highestNumberedHandCardToReach30 != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, highestNumberedHandCardToReach30)
|
|
else if (faceCardHandCount > 1 && hasAce && bestAceCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "a" + bestAceCard)
|
|
else if (faceCardHandCount > 1 && hasKing && bestKingCardToBustPlayer != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "k" + bestKingCardToBustPlayer)
|
|
else if (faceCardHandCount > 1 && hasQueen && highestNumberedBattlefieldCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "q" + highestNumberedBattlefieldCard)
|
|
else if (deck.length > 0) state.stragedyEnemyTurnText = stragedyEnemyDiscardCard()
|
|
else if (hasQueen && highestNumberedBattlefieldCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "q" + highestNumberedBattlefieldCard)
|
|
else if (hasAce && bestAceCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "a" + bestAceCard)
|
|
else if (hasKing && bestKingCardToBustPlayer != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "k" + bestKingCardToBustPlayer)
|
|
else stragedyEnemyRandom()
|
|
} else if (score >= playerScore && hasWitch) {
|
|
state.stragedyEnemyTurnText = stragedyPlayCard(false, "w")
|
|
} else if (score >= playerScore && hasBrigand) {
|
|
state.stragedyEnemyTurnText = stragedyPlayCard(false, "b")
|
|
} else if (highestNumberedHandCardToReach20 == null && hand.length > 0) {
|
|
if (score >= 20 && score < playerScore && faceCardHandCount > 1 && hasAce && bestAceCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "a" + bestAceCard)
|
|
else if (score >= 20 && score < playerScore && faceCardHandCount > 1 && hasKing && bestKingCardToBustPlayer != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "k" + bestKingCardToBustPlayer)
|
|
else if (score >= 20 && score < playerScore && faceCardHandCount > 1 && hasQueen && highestNumberedBattlefieldCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "q" + highestNumberedBattlefieldCard)
|
|
else if (deck.length > 0) state.stragedyEnemyTurnText = stragedyEnemyDiscardCard()
|
|
else if (hasQueen && bestQueenCardToBustPlayer != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "q" + bestQueenCardToBustPlayer)
|
|
else if (hasKing && bestKingCardToBustPlayer != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "k" + bestKingCardToBustPlayer)
|
|
else if (hasPriest && bestPriestCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "p" + bestPriestCard)
|
|
else if (hasAce && bestAceCard != null) state.stragedyEnemyTurnText = stragedyPlayCard(false, "a" + bestAceCard)
|
|
else state.stragedyEnemyTurnText = stragedyEnemyRetire()
|
|
} else {
|
|
state.stragedyEnemyTurnText = stragedyEnemyRandom()
|
|
}
|
|
|
|
stragedyCalculateScores()
|
|
if (state.stragedyEnemyScore > 30) {
|
|
stragedyCheckForWin()
|
|
state.stragedyTurn = "gameOver"
|
|
}
|
|
}
|
|
|
|
function stragedyEnemyDrawCard() {
|
|
var card = state.stragedyEnemyDeck.pop()
|
|
state.stragedyEnemyHand.push(card)
|
|
return `\nThe opponent has drawn a card.\n`
|
|
}
|
|
|
|
function stragedyEnemyDiscardCard() {
|
|
var hand = [...state.stragedyEnemyHand]
|
|
var score = state.stragedyEnemyScore
|
|
|
|
var hasAce = hand.filter(x => /^.*a.*$/gi.test(x)).length > 0
|
|
var hasJack = hand.filter(x => /^.*j.*$/gi.test(x)).length > 0
|
|
var hasQueen = hand.filter(x => /^.*q.*$/gi.test(x)).length > 0
|
|
var hasKing = hand.filter(x => /^.*k.*$/gi.test(x)).length > 0
|
|
var hasJoker = hand.filter(x => /^.*\?.*$/gi.test(x)).length > 0
|
|
var hasWitch = hand.filter(x => /^.*w.*$/gi.test(x)).length > 0
|
|
var hasPriest = hand.filter(x => /^.*p.*$/gi.test(x)).length > 0
|
|
var sortedNumberedHandCardsToAddUpTo30 = hand.filter(x => /^\d+$/gi.test(x) && parseInt(x) <= 30 - score).sort((a, b) => parseInt(a) - parseInt(b))
|
|
var highestNumberedHandCardAddUpTo30 = sortedNumberedHandCardsToAddUpTo30.length > 0 ? sortedNumberedHandCardsToAddUpTo30[sortedNumberedHandCardsToAddUpTo30.length - 1] : null
|
|
|
|
if (hand.length > 1) {
|
|
if (hasQueen) hand.splice(hand.indexOf("q"))
|
|
else if (hasPriest) hand.splice(hand.indexOf("p"))
|
|
else if (hasKing) hand.splice(hand.indexOf("k"))
|
|
else if (hasWitch) hand.splice(hand.indexOf("w"))
|
|
else if (hasJoker) hand.splice(hand.indexOf("?"))
|
|
else if (hasJack) hand.splice(hand.indexOf("j"))
|
|
else if (hasAce) hand.splice(hand.indexOf("a"))
|
|
else if (highestNumberedHandCardAddUpTo30 != null) hand.splice(hand.indexOf(highestNumberedHandCardAddUpTo30))
|
|
}
|
|
|
|
var card = state.stragedyEnemyHand.splice(state.stragedyEnemyHand.indexOf(getRandomInteger(0, hand.length - 1)), 1)
|
|
state.stragedyEnemyDiscard.push(card)
|
|
var newCards = state.stragedyEnemyDeck.splice(state.stragedyEnemyDeck.length - 2, 2)
|
|
state.stragedyEnemyHand.push(...newCards)
|
|
return `\nThe opponent has discarded a card and drawn ${newCards.length} cards.\n`
|
|
}
|
|
|
|
function stragedyEnemyRetire() {
|
|
state.stragedyEnemyRetired = true
|
|
return `\nThe opponent has retired at ${state.stragedyEnemyScore} points.\n`
|
|
}
|
|
|
|
function stragedyEnemyRandom(punish) {
|
|
var hand = [...state.stragedyEnemyHand]
|
|
|
|
if (hand.length == 0) {
|
|
if (punish) return "\nThe enemy has no cards to play.\n"
|
|
if (state.stragedyEnemyDeck.length > 0) return stragedyEnemyDrawCard()
|
|
return stragedyEnemyRetire()
|
|
}
|
|
|
|
do {
|
|
var index = getRandomInteger(0, hand.length - 1)
|
|
var card = hand.splice(index, 1)[0]
|
|
|
|
if (/\d+/gi.test(card)) {
|
|
return stragedyPlayCard(false, card)
|
|
} else if (state.stragedyEnemyBattlefield.length > 0) {
|
|
var battlefield = [...new Set(state.stragedyEnemyBattlefield)]
|
|
do {
|
|
var battlefieldIndex = getRandomInteger(0, battlefield.length - 1)
|
|
var battlefieldCard = battlefield.splice(battlefieldIndex, 1)[0]
|
|
|
|
if (!battlefieldCard.includes(card)) {
|
|
return stragedyPlayCard(false, card + battlefieldCard)
|
|
}
|
|
} while (battlefield.length > 0)
|
|
}
|
|
} while (hand.length > 0)
|
|
|
|
if (punish) {
|
|
state.stragedyEnemyDiscard.push(...state.stragedyEnemyHand)
|
|
state.stragedyEnemyHand = []
|
|
return "\nThe enemy could not play any cards and therfore discarded their entire hand.\n"
|
|
}
|
|
|
|
if (state.stragedyEnemyDeck.length > 0) return stragedyEnemyDrawCard()
|
|
return stragedyEnemyRetire()
|
|
}
|
|
|
|
function stragedyPlayerRandom(punish) {
|
|
var hand = [...state.stragedyPlayerHand]
|
|
|
|
if (hand.length == 0) {
|
|
return "\nThe player has no cards to play.\n"
|
|
}
|
|
|
|
do {
|
|
var index = getRandomInteger(0, hand.length - 1)
|
|
var card = hand.splice(index, 1)[0]
|
|
|
|
if (/\d+/gi.test(card)) {
|
|
return stragedyPlayCard(true, card)
|
|
} else if (state.stragedyPlayerBattlefield.length > 0) {
|
|
var battlefield = [...new Set(state.stragedyPlayerBattlefield)]
|
|
do {
|
|
var battlefieldIndex = getRandomInteger(0, battlefield.length - 1)
|
|
var battlefieldCard = battlefield.splice(battlefieldIndex, 1)[0]
|
|
|
|
if (!battlefieldCard.includes(card)) {
|
|
return stragedyPlayCard(true, card + battlefieldCard)
|
|
}
|
|
} while (battlefield.length > 0)
|
|
}
|
|
} while (hand.length > 0)
|
|
|
|
if (punish) {
|
|
state.stragedyPlayerDiscard.push(...state.stragedyEnemyHand)
|
|
state.stragedyPlayerHand = []
|
|
return "\nThe player could not play any cards and therfore discarded their entire hand.\n"
|
|
}
|
|
|
|
if (state.stragedyEnemyDeck.length > 0) return stragedyEnemyDrawCard()
|
|
return stragedyEnemyRetire()
|
|
}
|
|
|
|
function stragedyPlayerTurn(text) {
|
|
if (text.startsWith("d") && state.stragedyPlayerHand.length > 0) {
|
|
if (state.stragedyPlayerDeck.length == 0) return "\nYou cannot discard if you have 0 cards in your deck.\n"
|
|
|
|
var targetCard = text.substring(1).toLowerCase()
|
|
if (targetCard.length == 0) return "\nYou must specify the card you wish to discard\n"
|
|
|
|
var handIndex = state.stragedyPlayerHand.findIndex(x => x.toLowerCase() == targetCard)
|
|
if (handIndex == -1) return "\nYou cannot discard a card that is not in your hand.\n"
|
|
|
|
state.stragedyPlayerHand.splice(handIndex, 1);
|
|
state.stragedyPlayerDiscard.push(targetCard)
|
|
|
|
var newCards = state.stragedyPlayerDeck.splice(state.stragedyPlayerDeck.length - 2)
|
|
state.stragedyPlayerHand.push(...newCards)
|
|
|
|
text = `You discard the "${targetCard}" card. You draw `
|
|
if (newCards.length == 1) text += `a "${newCards[0]}" card.`
|
|
else text += `the "${newCards[0]}" and "${newCards[1]}" cards.`
|
|
|
|
stragedyCalculateScores()
|
|
if (state.stragedyEnemyRetired) {
|
|
stragedyCheckForWin()
|
|
state.stragedyTurn = "gameOver"
|
|
} else stragedyEnemyTurn()
|
|
return text
|
|
} else if (text.startsWith("d") && state.stragedyPlayerHand.length == 0) {
|
|
if (state.stragedyPlayerDeck.length == 0) return "\nYou cannot draw if you have 0 cards in your deck.\n"
|
|
|
|
var drawCard = state.stragedyPlayerDeck.pop()
|
|
state.stragedyPlayerHand.push(drawCard)
|
|
|
|
stragedyCalculateScores()
|
|
if (state.stragedyEnemyRetired) {
|
|
stragedyCheckForWin()
|
|
state.stragedyTurn = "gameOver"
|
|
} else stragedyEnemyTurn()
|
|
return `You draw a ${drawCard}`
|
|
} else if (text == "r") {
|
|
var hasJokerOnBattlefield = false
|
|
for (var card of state.stragedyPlayerBattlefield) {
|
|
if (card.includes("?")) {
|
|
hasJokerOnBattlefield = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if (hasJokerOnBattlefield) {
|
|
return "\nYou cannot retire while you have a joker on the battlefield.\n"
|
|
}
|
|
|
|
state.stragedyPlayerRetired = true
|
|
stragedyCalculateScores()
|
|
var text = `You retire at ${state.stragedyPlayerScore}.`
|
|
stragedyEnemyTurn()
|
|
stragedyCalculateScores()
|
|
stragedyCheckForWin()
|
|
state.stragedyTurn = "gameOver"
|
|
return text
|
|
} else {
|
|
var text = stragedyPlayCard(true, text)
|
|
if (state.stragedyEnemyRetired) {
|
|
stragedyCheckForWin()
|
|
state.stragedyTurn = "gameOver"
|
|
} else stragedyEnemyTurn()
|
|
|
|
return text
|
|
}
|
|
}
|
|
|
|
function stragedyPlayCard(player, text) {
|
|
var character = getCharacter()
|
|
if (player) {
|
|
var battlefield = state.stragedyPlayerBattlefield
|
|
var hand = state.stragedyPlayerHand
|
|
var deck = state.stragedyPlayerDeck
|
|
var discard = state.stragedyPlayerDiscard
|
|
var characterName = toTitleCase(character.name)
|
|
var playedWord = character.name == "You" ? "played" : "play"
|
|
var enemyName = "The opponent"
|
|
var enemyDeck = state.stragedyEnemyDeck
|
|
var enemyHand = state.stragedyEnemyHand
|
|
var enemyDiscard = state.stragedyEnemyDiscard
|
|
var enemyBattlefield = state.stragedyEnemyBattlefield
|
|
} else {
|
|
var battlefield = state.stragedyEnemyBattlefield
|
|
var hand = state.stragedyEnemyHand
|
|
var deck = state.stragedyEnemyDeck
|
|
var discard = state.stragedyEnemyDiscard
|
|
var characterName = "The opponent"
|
|
var playedWord = "played"
|
|
var enemyName = toTitleCase(character.name)
|
|
var enemyDeck = state.stragedyPlayerDeck
|
|
var enemyHand = state.stragedyPlayerHand
|
|
var enemyDiscard = state.stragedyPlayerDiscard
|
|
var enemyBattlefield = state.stragedyPlayerBattlefield
|
|
}
|
|
|
|
var isNumberedCard = /^\d+$/.test(text)
|
|
var handCard = isNumberedCard ? text : text.substring(0, 1).toLowerCase()
|
|
var targetCard = isNumberedCard ? null : text.substring(1).toLowerCase()
|
|
|
|
var handIndex = hand.findIndex(x => x.toLowerCase() == handCard)
|
|
if (handIndex == -1) {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou can only play cards that are in your hand\n"
|
|
}
|
|
|
|
var targetIndex = targetCard == "" ? -1 : battlefield.findIndex(x => x.toLowerCase() == targetCard)
|
|
if (!isNumberedCard && targetCard != "" && targetIndex == -1) {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou must specify a target that is placed on your side of the battlefield.\n"
|
|
}
|
|
|
|
switch (handCard) {
|
|
case "a":
|
|
if (targetCard == "") {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou must specify a target to use the Ace (ie. a2)\n"
|
|
}
|
|
|
|
hand.splice(handIndex, 1)
|
|
|
|
for (var i = battlefield.length - 1; i >= 0; i--) {
|
|
if (battlefield[i].endsWith(targetCard)) {
|
|
discard.push(...battlefield[i])
|
|
battlefield.splice(i, 1)
|
|
}
|
|
}
|
|
|
|
for (var i = enemyBattlefield.length - 1; i >= 0; i--) {
|
|
if (enemyBattlefield[i].endsWith(targetCard)) {
|
|
enemyDiscard.push(...enemyBattlefield[i])
|
|
enemyBattlefield.splice(i, 1)
|
|
}
|
|
}
|
|
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} an ace on ${targetCard}. All ${targetCard}s are removed.\n`
|
|
case "j":
|
|
if (targetCard == "") {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou must specify a target to use the Jack (ie. j2)\n"
|
|
}
|
|
|
|
battlefield.splice(targetIndex, 1)
|
|
var discardCards = [...targetCard]
|
|
|
|
hand.splice(handIndex, 1)
|
|
discardCards.push(handCard)
|
|
|
|
discard.push(...discardCards)
|
|
|
|
shuffle(discard)
|
|
var addCard = discard.pop()
|
|
hand.push(addCard)
|
|
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a jack on the ${targetCard}. The ${targetCard} is removed. ${player ? `${characterName} drew a ${addCard} from the discard pile.` : ""}\n`
|
|
case "q":
|
|
if (targetCard == "") {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou must specify a target to use the Queen (ie. q2)\n"
|
|
}
|
|
|
|
hand.splice(handIndex, 1)
|
|
battlefield.splice(targetIndex, 1)
|
|
|
|
battlefield.push(handCard + targetCard)
|
|
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a queen on the ${targetCard}. The value is added to the opponent.\n`
|
|
case "k":
|
|
if (targetCard == "") {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou must specify a target to use the King (ie. k2)\n"
|
|
}
|
|
|
|
hand.splice(handIndex, 1)
|
|
battlefield.splice(targetIndex, 1)
|
|
|
|
battlefield.push(handCard + targetCard)
|
|
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a king on the ${targetCard}. All ${targetCard.match(/\d+/g)} values are doubled.\n`
|
|
case "?":
|
|
if (targetCard == "") {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou must specify a target to use the Joker (ie. ?2)\n"
|
|
}
|
|
|
|
hand.splice(handIndex, 1)
|
|
battlefield.splice(targetIndex, 1)
|
|
|
|
battlefield.push(handCard + targetCard)
|
|
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a joker on the ${targetCard}. The card's value is increased to make the total score 30.\n`
|
|
case "w":
|
|
hand.splice(handIndex, 1)
|
|
discard.push(handCard)
|
|
|
|
var enemyMove = !player ? stragedyPlayerRandom(true) : stragedyEnemyRandom(true)
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a witch on ${enemyName}. ${enemyMove}\n`
|
|
case "p":
|
|
if (targetCard == "") {
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nYou must specify a target to use the Priest (ie. p2)\n"
|
|
}
|
|
|
|
hand.splice(handIndex, 1)
|
|
battlefield.splice(targetIndex, 1)
|
|
|
|
battlefield.push(handCard + targetCard)
|
|
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a priest on the ${targetCard}. This card is prevented from causing ${characterName} to bust.\n`
|
|
case "b":
|
|
hand.splice(handIndex, 1)
|
|
discard.push(handCard)
|
|
|
|
var i
|
|
for (i = 0; i < 5 && enemyDeck.length > 0; i++) {
|
|
var card = enemyDeck.pop()
|
|
enemyDiscard.push(...card)
|
|
}
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a brigand on ${enemyName}. They are forced to discard ${i} cards from their deck\n`
|
|
case "2":
|
|
case "3":
|
|
case "4":
|
|
case "5":
|
|
case "6":
|
|
case "7":
|
|
case "8":
|
|
case "9":
|
|
case "10":
|
|
battlefield.push(handCard)
|
|
hand.splice(handIndex, 1)
|
|
stragedyCalculateScores()
|
|
return `\n${characterName} ${playedWord} a ${handCard}.\n`
|
|
default:
|
|
if (player) state.stragedyEnemySkipTurn = true
|
|
return "\nUnrecognized card specified. Stop playing with counterfit cards!\n"
|
|
}
|
|
}
|
|
|
|
function stragedyCheckForWin() {
|
|
if (state.stragedyEnemyScore > 30 && state.stragedyPlayerScore > 30) state.stragedyWinner = "tie"
|
|
else if (state.stragedyEnemyScore > 30) state.stragedyWinner = "player"
|
|
else if (state.stragedyPlayerScore > 30) state.stragedyWinner = "enemy"
|
|
else if (state.stragedyPlayerScore > state.stragedyEnemyScore) state.stragedyWinner = "player"
|
|
else if (state.stragedyEnemyScore > state.stragedyPlayerScore) state.stragedyWinner = "enemy"
|
|
else state.stragedyWinner = "tie"
|
|
}
|
|
|
|
const simpleMeleeWeapons = ["Assault Rifle", "Pistol", "SMG", "Battle Rifle", "Energy Sword", "Heavy Machine Gun", "Shotgun", "SAM", "Grenade Launcher", "Sniper Rifle", "Taser"]
|
|
const simpleRangedWeapons = ["Chainsaw", "Dueling Pistol", "Stun Gun"]
|
|
const martialMeleeWeapons = ["Revolver", "Plasma Whip", "Force Knuckles", "Phase Rifle", "Minigun", "Rail Gun", "Plasma Cannon", "Chem Gun", "Charge Hammer", "Bullpup Rifle", "Auto Shotgun", "Tac Pistol", "Rocket Launcher", "Autogun", "Heavy Shotgun", "Warhammer", "Heavy Pistol", "PDW"]
|
|
const martialRangedWeapons = ["Shuriken", "Power Gauntlets", "Modular Gun", "Silenced Pistol", "Shoulder Cannon", "Wrist Blade"]
|
|
const lightArmor = ["Kevlar Vest", "Combat Armor", "Tech Armor"]
|
|
const mediumArmor = ["Carbon Fiber Armor", "Deflection Suit", "Charge Armor", "Riot Gear", "Nexus Armor"]
|
|
const heavyArmor = ["Nanotube Armor", "Biotic Mail", "Energetic Armor", "Power Armor"]
|
|
const ammunition = ["Mag", "Shells"]
|
|
|
|
function itemShopConvertGenericName(name) {
|
|
switch (name) {
|
|
case "Anti-Microbial Armor":
|
|
name = itemShopNameAddSuffix("Anti-Microbial", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Compact Armor":
|
|
name = itemShopNameAddSuffix("Compact", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Light Gun":
|
|
name = itemShopNameAddSuffix("Light", "Force Knuckles", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Autogun")
|
|
break
|
|
case "Silver Bullet":
|
|
name = itemShopNameAddSuffix("Silver Bullet", ...simpleMeleeWeapons.concat(simpleRangedWeapons, martialMeleeWeapons, martialRangedWeapons))
|
|
break
|
|
case "Exhaust Armor":
|
|
name = itemShopNameAddSuffix("Smoldering", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Sylvan Talon":
|
|
name = itemShopNameAddSuffix("Sylvan Talon", "Wrist Blade", "Tac Pistol", "Rocket Launcher", "Autogun", "Grenade Launcher", "Sniper Rifle")
|
|
break
|
|
case "Concussive Ammunition":
|
|
name = itemShopNameAddSuffix("Concussive", ...ammunition)
|
|
quantity = 10
|
|
break
|
|
case "Exo Armor":
|
|
name = itemShopNameAddSuffix("Exo", ...mediumArmor.concat(heavyArmor))
|
|
break
|
|
case "Exo Weapon":
|
|
name = itemShopNameAddSuffix("Exo", ...martialMeleeWeapons.concat(ammunition, simpleMeleeWeapons))
|
|
break
|
|
case "Ammunition +1":
|
|
name = itemShopNameAddPrefix("+1", ...Mag)
|
|
break
|
|
case "Digitized Armor Uncommon":
|
|
name = itemShopNameAddSuffix("Uncommon Enspelled", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Digitized Weapon Uncommon":
|
|
name = itemShopNameAddSuffix("Uncommon Enspelled", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Navy Armor":
|
|
name = itemShopNameAddSuffix("Navy", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Macro Uncommon":
|
|
name = itemShopNameAddSuffix("Macro of", "Anchor", "Fan", "Tree")
|
|
break
|
|
case "Revengerance Rifle":
|
|
name = itemShopNameAddPrefix("of Revengerance", "Force Knuckles", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Autogun")
|
|
break
|
|
case "Weapon +1":
|
|
name = itemShopNameAddPrefix("+1", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Gun of Early Warning":
|
|
name = itemShopNameAddPrefix("of Early Warning", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Mag +2":
|
|
name = itemShopNameAddPrefix("+2", ...ammunition)
|
|
break
|
|
case "Armor +1":
|
|
name = itemShopNameAddPrefix("+1", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Harmonic Defense Suit":
|
|
name = itemShopNameAddSuffix("Harmonic Defense", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Cracked Harmonic Defense Suit":
|
|
name = itemShopNameAddPrefix("of Vulnerability", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Digitized Armor Rare":
|
|
name = itemShopNameAddSuffix("Rare Digitized", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Digitized Weapon Rare":
|
|
name = itemShopNameAddSuffix("Rare Digitized", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Puck":
|
|
name = itemShopNameAddPrefix("Puck", "Bronze Griffon", "Ebony Fly", "Golden Lions", "Ivory Goats", "Marble Elephant", "Onyx Dog", "Serpentine Owl")
|
|
break
|
|
case "Combustion Weapon":
|
|
name = itemShopNameAddSuffix("Combustion", ...simpleMeleeWeapons.concat(martialMeleeWeapons))
|
|
break
|
|
case "Sabot Shotgun":
|
|
name = itemShopNameAddSuffix("Sabot", ...simpleMeleeWeapons.concat(martialMeleeWeapons))
|
|
break
|
|
case "Headphones Rare":
|
|
name = itemShopNameAddSuffix("Headphones of", "Awareness", "Protection", "Reserve", "Sustenance")
|
|
break
|
|
case "Macro Rare":
|
|
name = itemShopNameAddSuffix("Macro of", "Bird", "Swan Boat", "PDW")
|
|
break
|
|
case "Energy Weapon of Life Stealing":
|
|
name = itemShopNameAddPrefix("of Life Stealing", "Force Knuckles", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Autogun")
|
|
break
|
|
case "Sword of Wounding":
|
|
name = itemShopNameAddPrefix("of Wounding", "Force Knuckles", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Autogun")
|
|
break
|
|
case "Explosive Weapon":
|
|
name = itemShopNameAddSuffix("Vicious", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Weapon +2":
|
|
name = itemShopNameAddPrefix("+2", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Mag +3":
|
|
name = itemShopNameAddPrefix("+3", ...ammunition)
|
|
break
|
|
case "Mag of Slaying":
|
|
let type = getRandomFromList("Zombie", "Hologram", "Robot", "Cyborg", "Human", "Alien", "Drone")
|
|
name = itemShopNameAddPrefix(`of ${type} Slaying`, ...ammunition)
|
|
break
|
|
case "Armor +2":
|
|
name = itemShopNameAddPrefix("+2", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Auto Turret":
|
|
name = itemShopNameAddSuffix("Auto Turret", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Autogun")
|
|
break
|
|
case "Alien Armor":
|
|
name = itemShopNameAddPrefix("Alien", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Digitized Armor Very Rare":
|
|
name = itemShopNameAddSuffix("Very Rare Digitized", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Digitized Armor Very Rare":
|
|
name = itemShopNameAddSuffix("Very Rare Digitized", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Cold Gun":
|
|
name = itemShopNameAddSuffix("Cold", "Force Knuckles", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Autogun")
|
|
break
|
|
case "Headphones Very Rare":
|
|
name = itemShopNameAddSuffix("Headphones of", "Absorption", "Fortitude", "Insight", "Intellect", "Leadership", "Strength")
|
|
break
|
|
case "Critical Mass Gun":
|
|
name = itemShopNameAddSuffix("Critical Mass", "Force Knuckles", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher")
|
|
break
|
|
case "Weapon +3":
|
|
name = itemShopNameAddPrefix("+3", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Armor +3":
|
|
name = itemShopNameAddPrefix("+3", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Digitized Armor Legendary":
|
|
name = itemShopNameAddSuffix("Very Rare Digitized", ...lightArmor.concat(mediumArmor, heavyArmor))
|
|
break
|
|
case "Digitized Weapon Legendary":
|
|
name = itemShopNameAddSuffix("Legendary Digitized", ...simpleMeleeWeapons.concat(martialMeleeWeapons, simpleRangedWeapons, martialRangedWeapons))
|
|
break
|
|
case "Luck Gun":
|
|
name = itemShopNameAddPrefix("Lucky", "Force Knuckles", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Grenade Launcher", "Autogun")
|
|
break
|
|
case "Moonblade":
|
|
name = itemShopNameAddPrefix("Moonblade", "Minigun", "Chem Gun", "Tac Pistol", "Rocket Launcher", "Autogun")
|
|
break
|
|
}
|
|
return name
|
|
}
|
|
|
|
function itemShopNameAddPrefix(name, ...prefixes) {
|
|
return getRandomFromList(...prefixes) + " " + name
|
|
}
|
|
|
|
function itemShopNameAddSuffix(name, ...suffixes) {
|
|
return name + " " + getRandomFromList(...suffixes)
|
|
}
|
|
|
|
function findItemShopDeals(className, bought) {
|
|
return state.itemShopDeals.filter(element => element.className == className && (bought == null || element.bought == bought))
|
|
}
|
|
|
|
function findSpellShopDeals(className, level, bought) {
|
|
return state.spellShopDeals.filter(element => element.className == className && element.level == level && (bought == null || element.bought == bought))
|
|
}
|
|
|
|
String.prototype.replaceAt = function(index, replacement) {
|
|
return this.substring(0, index) + replacement + this.substring(index + replacement.length);
|
|
}
|
|
|
|
String.prototype.plural = function(revert) {
|
|
|
|
var plural = {
|
|
'(quiz)$' : "$1zes",
|
|
'^(ox)$' : "$1en",
|
|
'([m|l])ouse$' : "$1ice",
|
|
'(matr|vert|ind)ix|ex$' : "$1ices",
|
|
'(x|ch|ss|sh)$' : "$1es",
|
|
'([^aeiouy]|qu)y$' : "$1ies",
|
|
'(hive)$' : "$1s",
|
|
'(?:([^f])fe|([lr])f)$' : "$1$2ves",
|
|
'(shea|lea|loa|thie)f$' : "$1ves",
|
|
'sis$' : "ses",
|
|
'([ti])um$' : "$1a",
|
|
'(tomat|potat|ech|her|vet)o$': "$1oes",
|
|
'(bu)s$' : "$1ses",
|
|
'(alias)$' : "$1es",
|
|
'(octop)us$' : "$1i",
|
|
'(ax|test)is$' : "$1es",
|
|
'(us)$' : "$1es",
|
|
'([^s]+)$' : "$1s"
|
|
};
|
|
|
|
var singular = {
|
|
'(quiz)zes$' : "$1",
|
|
'(matr)ices$' : "$1ix",
|
|
'(vert|ind)ices$' : "$1ex",
|
|
'^(ox)en$' : "$1",
|
|
'(alias)es$' : "$1",
|
|
'(octop|vir)i$' : "$1us",
|
|
'(cris|ax|test)es$' : "$1is",
|
|
'(shoe)s$' : "$1",
|
|
'(o)es$' : "$1",
|
|
'(bus)es$' : "$1",
|
|
'([m|l])ice$' : "$1ouse",
|
|
'(x|ch|ss|sh)es$' : "$1",
|
|
'(m)ovies$' : "$1ovie",
|
|
'(s)eries$' : "$1eries",
|
|
'([^aeiouy]|qu)ies$' : "$1y",
|
|
'([lr])ves$' : "$1f",
|
|
'(tive)s$' : "$1",
|
|
'(hive)s$' : "$1",
|
|
'(li|wi|kni)ves$' : "$1fe",
|
|
'(shea|loa|lea|thie)ves$': "$1f",
|
|
'(^analy)ses$' : "$1sis",
|
|
'((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$': "$1$2sis",
|
|
'([ti])a$' : "$1um",
|
|
'(n)ews$' : "$1ews",
|
|
'(h|bl)ouses$' : "$1ouse",
|
|
'(corpse)s$' : "$1",
|
|
'(us)es$' : "$1",
|
|
's$' : ""
|
|
};
|
|
|
|
var irregular = {
|
|
'move' : 'moves',
|
|
'foot' : 'feet',
|
|
'goose' : 'geese',
|
|
'sex' : 'sexes',
|
|
'child' : 'children',
|
|
'man' : 'men',
|
|
'tooth' : 'teeth',
|
|
'person' : 'people',
|
|
'woman' : 'women',
|
|
};
|
|
|
|
var uncountable = [
|
|
'sheep',
|
|
'fish',
|
|
'deer',
|
|
'moose',
|
|
'series',
|
|
'species',
|
|
'money',
|
|
'rice',
|
|
'information',
|
|
'equipment',
|
|
'gold',
|
|
'bass',
|
|
'milk',
|
|
'food',
|
|
'water',
|
|
'bread',
|
|
'sugar',
|
|
'tea',
|
|
'cheese',
|
|
'coffee',
|
|
'currency',
|
|
'seafood',
|
|
'oil',
|
|
'software'
|
|
];
|
|
|
|
// save some time in the case that singular and plural are the same
|
|
if(uncountable.indexOf(this.toLowerCase()) >= 0)
|
|
return this;
|
|
|
|
// check for irregular forms
|
|
for(word in irregular){
|
|
|
|
if(revert){
|
|
var pattern = new RegExp(irregular[word]+'$', 'i');
|
|
var replace = word;
|
|
} else{ var pattern = new RegExp(word+'$', 'i');
|
|
var replace = irregular[word];
|
|
}
|
|
if(pattern.test(this))
|
|
return this.replace(pattern, replace);
|
|
}
|
|
|
|
if(revert) var array = singular;
|
|
else var array = plural;
|
|
|
|
// check for matches using regular expressions
|
|
for(reg in array){
|
|
|
|
var pattern = new RegExp(reg, 'i');
|
|
|
|
if(pattern.test(this))
|
|
return this.replace(pattern, array[reg]);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
function clamp(num, min, max) {
|
|
return num <= min
|
|
? min
|
|
: num >= max
|
|
? max
|
|
: num
|
|
}
|
|
|
|
function toTitleCase(str) {
|
|
return str.replace(
|
|
/\w\S*/g,
|
|
text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
|
|
);
|
|
}
|
|
|
|
function stripPunctuation(str) {
|
|
return str.replaceAll(/((\.)|(!))\s*$/g, "")
|
|
}
|
|
|
|
var fantasyFemaleNames = ["Luna", "Kayla", "Serenity", "Eira", "Mirah", "Elowen", "Keira", "Calantha", "Natalia", "Eirlys", "Freya", "Ophelia", "Piper", "Alethea", "Melara", "Seraphina", "Delilah", "Lorna", "Echo", "Bree", "Daniella", "Branwen", "Matilda", "Eve", "Brynhild", "Ithilda", "Belinda", "Catarina", "Jora", "Zelda", "Thalia", "Rowan", "Aurora", "Coral", "Vivian", "Briella", "Elvina", "Lylah", "Mirastral", "Nadira", "Marcella", "Kestrel", "Avis", "Laura", "Vesper", "Lucilla", "Sabine", "Evelyn", "Kalinda", "Celeste", "Lilith", "Wren", "Jasmine", "Ondine", "Gabriella", "Astrid", "Elise", "Helena", "Nova", "Lyndal", "Zara", "Niamh", "Vynessa", "Erin", "Lyriel", "Dracaena", "Lila", "Brynna", "Zephyr", "Kira", "Ava", "Elinor", "Carmilla", "Isabella", "Ariana", "Rhianna", "Sylvie", "Kymberley", "Hazel", "Lirien", "Bridget", "Lyra", "Galatea", "Nadine", "Alethia", "Larissa", "Sariel", "Theodora", "Gwynneth", "Eleanor", "Odessa", "Meryll", "Sophia", "Kaia", "Brynhilda", "Haven", "Eluned", "Selene", "Bryony", "Ciara"]
|
|
|
|
var fantasyMaleNames = ["Alexander", "Thane", "Gabriel", "Orion", "Grayson", "Cedric", "Sebastian", "Arin", "Liam", "Byerson", "Julian", "Zaneth", "Kel", "Eramon", "Ashfur", "Tristam", "Leonidas", "Ryzlen", "Caspian", "Jarron", "Eudicles", "Tarquin", "Terrence", "Ereth", "Thayon", "Braxton", "Twilight", "Argent", "Whisper", "Daemon", "Victor", "Blackthorn", "Dawnrunner", "Gareth", "Caelum", "Zephyr", "Brennan", "Theo", "Draco", "Cian", "Valoric", "Skye", "Sunfor", "Damon", "Maverick", "Bryson", "Lumo", "Drakken", "Ewen", "Waverley", "Lachlan", "Atlas", "Arden", "Ryker", "Asterion", "Bryon", "Judson", "Griffith", "Logan", "Ethan", "Darius", "Brodeth", "Cassius", "Eamon", "Rowan", "Paxton", "Michael", "Dommon", "Aragorn", "Bastier", "Maximus", "Kenrick", "Jasper", "Lucien", "Bryce", "Ryder", "Damian", "Daxton", "Brantley", "Griffin", "Xander", "Galen", "Brody", "Erek", "Drake", "Thayer", "Kieran", "Heath", "Raeleus", "Alistair", "Bastian", "Asher", "Ronan", "Zane", "Jaxon", "Ambrose", "Malcolm", "Axel", "Ehtan", "Avery", "Kael", "Riley"]
|
|
|
|
var scifiFemaleNames = ["Jala", "Clea", "Jocosa", "Artemis", "Serafina", "Sevyn", "Tesla", "Lux", "Nine", "Kiara", "Valentina", "Morticia", "Rio", "Xyleena", "Libby", "Valkyrie", "Panika", "Lara", "Fenglina", "Makiko", "Katja", "Paige", "Elie", "Lucie", "Samanta", "Hazel", "Helena", "Leia", "Luminara", "Katan", "Vala", "Inara", "Saffron", "Zoe", "Jayne", "Kaylee", "Maeve", "Kara", "Athena", "Cally", "Anastasia", "Pegi", "Alita", "Alkhema", "Arcena", "Ko", "Bodika", "Candi", "Chi", "Rae", "Cylla", "Daria", "Chalma", "Elita", "Eryx", "Eva", "Nova", "Celeste", "Guri", "Hexen", "Indigo", "Juli", "Katana", "Talia", "Lala", "Mika", "Miranda", "Nebula", "Six", "Sasha", "Silica", "Sky", "Strika", "Terra", "Yori", "Andromeda", "Astra", "Bellatrix", "Callista", "Cosima", "Delphine", "Electra", "Phantasy", "Farrah", "Geneva", "Haven", "Jade", "Juno", "Lillix", "Lynx", "Nya", "Oria", "Parris", "Priya", "Rue", "Clarity", "Bloom", "Decca", "Domonique", "Grazi", "Helvetica", "Cadence"]
|
|
|
|
var scifiMaleNames = ["Ares", "Astro", "Macro", "Cadmus", "Cyno", "Fade", "Hack", "Hax", "Indigo", "Hinge", "Jarno", "Jax", "Knox", "Link", "Maxx", "Merrick", "Miles", "Mirari", "Niko", "Nano", "Oberon", "Onyx", "Orion", "Osso", "Paradox", "Pip", "Phoenix", "Radius", "Rexx", "Razlin", "Reznor", "Rian", "Roscoe", "Ryker", "Rush", "Riden", "Drake", "Frost", "Cassian", "Neyo", "Maverick", "Azriel", "Auryn", "Daggar", "Evyn", "Jace", "Jaron", "Loki", "Oren", "Ridley", "Sagan", "Silas","Solon", "Stellan", "Sorrel", "Seth", "Theron", "Zen", "Klay", "Blaze", "Xander", "Shotgun", "Dozer", "Eno", "Tip", "Ray", "Genesis", "Galac", "Eclipse", "Zev", "Zaid", "Wilder", "Sol", "Jupiter", "Mars", "Star", "Cosmo", "Aster", "Lazer", "Zeno", "Sirius", "Azra", "Atom", "Teague", "Rigel", "Cato", "Zhane", "Ace", "Rocket", "Kip", "Meter", "Starbuck", "Roman", "Fiat", "Kyron", "Nyx", "Rune", "Nero", "Quantum", "Nym", "Morphius", "Striker", "Bridger"]
|
|
|
|
var modernFemaleNames = ["Olivia", "Emma", "Amelia", "Ella", "Isabella", "Mia", "Valerie", "Eliana", "Charlotte", "Mila", "Aria", "Luna", "Harper", "Grace", "Zoey", "Jemma", "Priscilla", "Scarlett", "Hazel", "Ellie", "Naya", "Nila", "Tamia", "Cecilia", "Arianna", "Abigail", "Riley", "Autumn", "Maya", "Madelyn", "Maria", "Melody", "Sophia", "Ava", "Luz", "Eleanor", "Ivy", "Freya", "Alice", "Violet", "Clara", "Daphne", "Evelyn", "Nora", "Lucy", "Poppy", "Rose", "Chloe", "Phoebe", "Elsie", "Cordelia", "Willow", "Daisy", "Thea", "Adeline", "Arabella", "Maisie", "Lola", "Olive", "Sienna", "Sierra", "Elena", "Sadie", "Sophie", "Julia", "Alexandra", "Jane", "Mira", "Talia", "Zara", "Vera", "Amara", "Cynthia", "Hannah", "Aurora", "Anya", "Erin", "Felicity", "Juno", "Yelena", "Naomi", "Caroline", "Miriam", "Veronica", "Molly", "June", "Nina", "Piper", "Helena", "Amari", "Everly", "Bonnie", "Alina", "Emilia", "Harriet", "Isabel", "Sofia", "Kayla", "Lena", "Megan", "Diana"]
|
|
|
|
var modernMaleNames = ["Jackson", "Aiden", "Charles", "Adam", "Christopher", "Daniel", "Liam", "Oliver", "Mateo", "Henry", "Lucas", "William", "Theodore", "Noah", "John", "Arnold", "Norman", "Ralph", "Virgil", "Will", "Sam", "Luca", "David", "Joseph", "Mason", "Luke", "Matthew", "Dylan", "Jacob", "Isaac", "Anthony", "Carter", "Caleb", "Cooper", "Josiah", "Nolan", "Cameron", "Nathan", "Josh", "Angel", "Andrew", "Aaron", "Ian", "Eli", "Ryan", "Everett", "Enzo", "Parker", "Jeremiah", "Landon", "Jordan", "Austin", "Jameson", "Myles", "Dominic", "Nicholas", "Kayden", "Hunter", "Harrison", "Milo", "Arthur", "Ryder", "Archer", "Luis", "George", "Evan", "Carlos", "Juan", "Jason", "Leon", "Calvin", "Ivan", "Cole", "Chase", "Dean", "Jayce", "Olliver", "Alan", "Jesus", "Charlie", "Tyler", "Elliot", "Kevin", "Ayden", "Felix", "Tate", "Jesse", "Brody", "Tucker", "Peter", "Joel", "Edward", "Oscar", "Victor", "Brandon", "Bruce", "Abel", "Richard", "Riley", "Patrick", "Eric", "Elian", "Louis"]
|
|
|
|
var nordicFemaleNames = ["Freya", "Dagny", "Ingrid", "Froya", "Elin", "Solveig", "Maja", "Sol", "Linnea", "Vilde", "Var", "Aldis", "Alfrida", "Alfsol", "Alva", "Alvdis", "Alvida", "Andora", "Anveig", "Asa", "Astri", "Astrid", "Bolette", "Brynhild", "Disa", "Eir", "Eira", "Eidis", "Elevine", "Elfi", "Embla", "Erna", "Freja", "Frida", "Fredrikke", "Gerda", "Gry", "Gurina", "Gurine", "Gyda", "Haddy", "Halgerd", "Helga", "Helje", "Helle", "Herdis", "Herfrid", "Hilde", "Hulda", "Inga", "Idun", "Isfrid", "Iverna", "Iverine", "Jorgina", "Kari", "Lagertha", "Liv", "Livunn", "Malfrid", "Malmfrid", "Nanna", "Oda", "Odel", "Odine", "Olava", "Runa", "Ragnfrid", "Randi", "Ragnhild", "Saga", "Sif", "Sigrid", "Siv", "Solvei", "Soma", "Svanild", "Thora", "Tora", "Thurid", "Torveig", "Torfrid", "Trude", "Tyra", "Tyri", "Udna", "Unni", "Una", "Unnlaug", "Unnveig", "Valdine", "Vedis", "Valborg", "Vivil", "Ylva", "Yngva", "Thoril", "Thorine", "Sigfrida", "Sigun", "Sigvor", "Signe", "Reidunn"]
|
|
|
|
var nordicMaleNames = ["Erik", "Bjorn", "Lars", "Asmund", "Harald", "Arne", "Odin", "Ivar", "Leif", "Aesir", "Axel", "Aren", "Aric", "Balder", "Birger", "Bjarke", "Bjarne", "Nils", "Steig", "Erling", "Espen", "Fenrir", "Frey", "Einar", "Garald", "Anders", "Gunnar", "Hagan", "Halfthor", "Halfdan", "Kjell", "Hanne", "Ingvar", "Helge", "Herleif", "Jarl", "Joran", "Magnus", "Norrell", "Njord", "Olaf", "Osman", "Ragnar", "Sigurd", "Steffen", "Sten", "Sven", "Tor", "Torben", "Troels", "Tyr", "Tyrell", "Ulf", "Viggo", "Vali", "Vidar", "Volund", "Wayde", "Waddell", "Alviss", "Anneli", "Stig", "Eino", "Haakon", "Haldor", "Iver", "Sindri", "Trym", "Varg", "Alf", "Amund", "Arn", "Arnstein", "Arvid", "Bjarni", "Bjoern", "Bragi", "Brede", "Dag", "Dagfinn", "Egil", "Endre", "Erlend", "Even", "Finn", "Flosi", "Fredrik", "Frode", "Freyr", "Geir", "Gisli", "Grim", "Gudbrand", "Gustav", "Hakan", "Hakon", "Hans", "Helgi", "Ingolf", "Jomar", "Knut", "Orm"]
|
|
|
|
function generateName(genre, male) {
|
|
if (genre.toLowerCase() == "fantasy") {
|
|
if (male) {
|
|
if (state.fantasyMaleIndex == null || state.fantasyMaleIndex >= fantasyMaleNames.length) {
|
|
state.fantasyMaleIndex = 0
|
|
state.fantasyMaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(fantasyMaleNames, state.fantasyMaleSeed)
|
|
return fantasyMaleNames[state.fantasyMaleIndex++]
|
|
} else {
|
|
if (state.fantasyFemaleIndex == null || state.fantasyFemaleIndex >= fantasyFemaleNames.length) {
|
|
state.fantasyFemaleIndex = 0
|
|
state.fantasyFemaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(fantasyFemaleNames, state.fantasyFemaleSeed)
|
|
return fantasyFemaleNames[state.fantasyFemaleIndex++]
|
|
}
|
|
} else if (genre.toLowerCase() == "modern") {
|
|
if (male) {
|
|
if (state.modernMaleIndex == null || state.modernMaleIndex >= modernMaleNames.length) {
|
|
state.modernMaleIndex = 0
|
|
state.modernMaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(modernMaleNames, state.modernMaleSeed)
|
|
return modernMaleNames[state.modernMaleIndex++]
|
|
} else {
|
|
if (state.modernFemaleIndex == null || state.modernFemaleIndex >= modernFemaleNames.length) {
|
|
state.modernFemaleIndex = 0
|
|
state.modernFemaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(modernFemaleNames, state.modernFemaleSeed)
|
|
return modernFemaleNames[state.modernFemaleIndex++]
|
|
}
|
|
} else if (genre.toLowerCase() == "scifi") {
|
|
if (male) {
|
|
if (state.scifiMaleIndex == null || state.scifiMaleIndex >= scifiMaleNames.length) {
|
|
state.scifiMaleIndex = 0
|
|
state.scifiMaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(scifiMaleNames, state.scifiMaleSeed)
|
|
return scifiMaleNames[state.scifiMaleIndex++]
|
|
}
|
|
else {
|
|
if (state.scifiFemaleIndex == null || state.scifiFemaleIndex >= scifiFemaleNames.length) {
|
|
state.scifiFemaleIndex = 0
|
|
state.scifiFemaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(scifiFemaleNames, state.scifiFemaleSeed)
|
|
return scifiFemaleNames[state.scifiFemaleIndex++]
|
|
}
|
|
} else if (genre.toLowerCase() == "nordic") {
|
|
if (male) {
|
|
if (state.nordicMaleIndex == null || state.nordicMaleIndex >= nordicMaleNames.length) {
|
|
state.nordicMaleIndex = 0
|
|
state.nordicMaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(nordicMaleNames, state.nordicMaleSeed)
|
|
return nordicMaleNames[state.nordicMaleIndex++]
|
|
}
|
|
else {
|
|
if (state.nordicFemaleIndex == null || state.nordicFemaleIndex >= nordicFemaleNames.length) {
|
|
state.nordicFemaleIndex = 0
|
|
state.nordicFemaleSeed = getRandomInteger(1, 1000)
|
|
}
|
|
shuffle(nordicFemaleNames, state.nordicFemaleSeed)
|
|
return nordicFemaleNames[state.nordicFemaleIndex++]
|
|
}
|
|
}
|
|
}
|