|
const _ = require('lodash'); |
|
|
|
const genList = function(list, max){ |
|
return _.sampleSize(list, _.random(0, max)).join(', ') || 'None'; |
|
}; |
|
|
|
const getMonsterName = function(){ |
|
return _.sample([ |
|
'All-devouring Baseball Imp', |
|
'All-devouring Gumdrop Wraith', |
|
'Chocolate Hydra', |
|
'Devouring Peacock', |
|
'Economy-sized Colossus of the Lemonade Stand', |
|
'Ghost Pigeon', |
|
'Gibbering Duck', |
|
'Sparklemuffin Peacock Spider', |
|
'Gum Elemental', |
|
'Illiterate Construct of the Candy Store', |
|
'Ineffable Chihuahua', |
|
'Irritating Death Hamster', |
|
'Irritating Gold Mouse', |
|
'Juggernaut Snail', |
|
'Juggernaut of the Sock Drawer', |
|
'Koala of the Cosmos', |
|
'Mad Koala of the West', |
|
'Milk Djinni of the Lemonade Stand', |
|
'Mind Ferret', |
|
'Mystic Salt Spider', |
|
'Necrotic Halitosis Angel', |
|
'Pinstriped Famine Sheep', |
|
'Ritalin Leech', |
|
'Shocker Kangaroo', |
|
'Stellar Tennis Juggernaut', |
|
'Wailing Quail of the Sun', |
|
'Angel Pigeon', |
|
'Anime Sphinx', |
|
'Bored Avalanche Sheep of the Wasteland', |
|
'Devouring Nougat Sphinx of the Sock Drawer', |
|
'Djinni of the Footlocker', |
|
'Ectoplasmic Jazz Devil', |
|
'Flatuent Angel', |
|
'Gelatinous Duck of the Dream-Lands', |
|
'Gelatinous Mouse', |
|
'Golem of the Footlocker', |
|
'Lich Wombat', |
|
'Mechanical Sloth of the Past', |
|
'Milkshake Succubus', |
|
'Puffy Bone Peacock of the East', |
|
'Rainbow Manatee', |
|
'Rune Parrot', |
|
'Sand Cow', |
|
'Sinister Vanilla Dragon', |
|
'Snail of the North', |
|
'Spider of the Sewer', |
|
'Stellar Sawdust Leech', |
|
'Storm Anteater of Hell', |
|
'Stupid Spirit of the Brewery', |
|
'Time Kangaroo', |
|
'Tomb Poodle', |
|
]); |
|
}; |
|
|
|
const getType = function(){ |
|
return `${_.sample(['Tiny', 'Small', 'Medium', 'Large', 'Gargantuan', 'Stupidly vast'])} ${_.sample(['beast', 'fiend', 'annoyance', 'guy', 'cutie'])}`; |
|
}; |
|
|
|
const getAlignment = function(){ |
|
return _.sample([ |
|
'annoying evil', |
|
'chaotic gossipy', |
|
'chaotic sloppy', |
|
'depressed neutral', |
|
'lawful bogus', |
|
'lawful coy', |
|
'manic-depressive evil', |
|
'narrow-minded neutral', |
|
'neutral annoying', |
|
'neutral ignorant', |
|
'oedpipal neutral', |
|
'silly neutral', |
|
'unoriginal neutral', |
|
'weird neutral', |
|
'wordy evil', |
|
'unaligned' |
|
]); |
|
}; |
|
|
|
const getStats = function(){ |
|
return `>|${_.times(6, function(){ |
|
const num = _.random(1, 20); |
|
const mod = Math.ceil(num/2 - 5); |
|
return `${num} (${mod >= 0 ? `+${mod}` : mod})`; |
|
}).join('|')}|`; |
|
}; |
|
|
|
const genAbilities = function(){ |
|
return _.sample([ |
|
'> ***Pack Tactics.*** These guys work together. Like super well, you don\'t even know.', |
|
'> ***Fowl Appearance.*** While the creature remains motionless, it is indistinguishable from a normal chicken.', |
|
'> ***Onion Stench.*** Any creatures within 5 feet of this thing develops an irrational craving for onion rings.', |
|
'> ***Enormous Nose.*** This creature gains advantage on any check involving putting things in its nose.', |
|
'> ***Sassiness.*** When questioned, this creature will talk back instead of answering.', |
|
'> ***Big Jerk.*** Thinks he is just *waaaay* better than you.', |
|
]); |
|
}; |
|
|
|
const genAction = function(){ |
|
const name = _.sample([ |
|
'Abdominal Drop', |
|
'Airplane Hammer', |
|
'Atomic Death Throw', |
|
'Bulldog Rake', |
|
'Corkscrew Strike', |
|
'Crossed Splash', |
|
'Crossface Suplex', |
|
'DDT Powerbomb', |
|
'Dual Cobra Wristlock', |
|
'Dual Throw', |
|
'Elbow Hold', |
|
'Gory Body Sweep', |
|
'Heel Jawbreaker', |
|
'Jumping Driver', |
|
'Open Chin Choke', |
|
'Scorpion Flurry', |
|
'Somersault Stump Fists', |
|
'Suffering Wringer', |
|
'Super Hip Submission', |
|
'Super Spin', |
|
'Team Elbow', |
|
'Team Foot', |
|
'Tilt-a-whirl Chin Sleeper', |
|
'Tilt-a-whirl Eye Takedown', |
|
'Turnbuckle Roll' |
|
]); |
|
|
|
return `> ***${name}.*** *Melee Weapon Attack:* +4 to hit, reach 5ft., one target. *Hit* 5 (1d6 + 2) `; |
|
}; |
|
|
|
|
|
module.exports = { |
|
|
|
full : function(){ |
|
return `${[ |
|
'___', |
|
'___', |
|
`> ## ${getMonsterName()}`, |
|
`>*${getType()}, ${getAlignment()}*`, |
|
'> ___', |
|
`> - **Armor Class** ${_.random(10, 20)}`, |
|
`> - **Hit Points** ${_.random(1, 150)}(1d4 + 5)`, |
|
`> - **Speed** ${_.random(0, 50)}ft.`, |
|
'>___', |
|
'>|STR|DEX|CON|INT|WIS|CHA|', |
|
'>|:---:|:---:|:---:|:---:|:---:|:---:|', |
|
getStats(), |
|
'>___', |
|
`> - **Condition Immunities** ${genList(['groggy', 'swagged', 'weak-kneed', 'buzzed', 'groovy', 'melancholy', 'drunk'], 3)}`, |
|
`> - **Senses** passive Perception ${_.random(3, 20)}`, |
|
`> - **Languages** ${genList(['Common', 'Pottymouth', 'Gibberish', 'Latin', 'Jive'], 2)}`, |
|
`> - **Challenge** ${_.random(0, 15)} (${_.random(10, 10000)} XP)`, |
|
'> ___', |
|
_.times(_.random(3, 6), function(){ |
|
return genAbilities(); |
|
}).join('\n>\n'), |
|
'> ### Actions', |
|
_.times(_.random(4, 6), function(){ |
|
return genAction(); |
|
}).join('\n>\n'), |
|
].join('\n')}\n\n\n`; |
|
}, |
|
|
|
half : function(){ |
|
return `${[ |
|
'___', |
|
`> ## ${getMonsterName()}`, |
|
`>*${getType()}, ${getAlignment()}*`, |
|
'> ___', |
|
`> - **Armor Class** ${_.random(10, 20)}`, |
|
`> - **Hit Points** ${_.random(1, 150)}(1d4 + 5)`, |
|
`> - **Speed** ${_.random(0, 50)}ft.`, |
|
'>___', |
|
'>|STR|DEX|CON|INT|WIS|CHA|', |
|
'>|:---:|:---:|:---:|:---:|:---:|:---:|', |
|
getStats(), |
|
'>___', |
|
`> - **Condition Immunities** ${genList(['groggy', 'swagged', 'weak-kneed', 'buzzed', 'groovy', 'melancholy', 'drunk'], 3)}`, |
|
`> - **Senses** passive Perception ${_.random(3, 20)}`, |
|
`> - **Languages** ${genList(['Common', 'Pottymouth', 'Gibberish', 'Latin', 'Jive'], 2)}`, |
|
`> - **Challenge** ${_.random(0, 15)} (${_.random(10, 10000)} XP)`, |
|
'> ___', |
|
_.times(_.random(2, 3), function(){ |
|
return genAbilities(); |
|
}).join('\n>\n'), |
|
'> ### Actions', |
|
_.times(_.random(1, 2), function(){ |
|
return genAction(); |
|
}).join('\n>\n'), |
|
].join('\n')}\n\n\n`; |
|
} |
|
}; |
|
|