mirror of
https://github.com/raeleus/Hashtag-DnD.git
synced 2025-07-05 13:10:28 -04:00
Initial commit
This commit is contained in:
commit
0e80d726b4
7 changed files with 2354 additions and 0 deletions
399
Library.js
Normal file
399
Library.js
Normal file
|
@ -0,0 +1,399 @@
|
|||
function getRandomInteger(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1) ) + min;
|
||||
}
|
||||
|
||||
function sanitizeText(text) {
|
||||
if (/^\s*>.*says? ".*/.test(text)) {
|
||||
text = text.replace(/^\s*>\s/, "")
|
||||
text = text.replace(/says? "/, "")
|
||||
text = text.replace(/"\n$/, "")
|
||||
} 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) {
|
||||
return command.substring(match.index).replace(/^"/, "").replace(/"$/, "").replaceAll(/\\"/g, '"')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function searchArgument(command, pattern) {
|
||||
var index = searchArgumentIndex(command, pattern)
|
||||
if (index == -1) 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 matches[0]
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
function getSides(rolltext) {
|
||||
var matches = rolltext.match(/(?<=d)\d+/)
|
||||
if (matches != null) {
|
||||
return matches[0]
|
||||
}
|
||||
|
||||
return 20
|
||||
}
|
||||
|
||||
function formatRoll(text) {
|
||||
var matches = text.match(/(?<=.*)\d*d\d+(?=.*)/)
|
||||
if (matches != null) {
|
||||
return matches[0]
|
||||
}
|
||||
|
||||
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 score = 0;
|
||||
for (i = 0; i < dice; i++) {
|
||||
score += getRandomInteger(1, sides)
|
||||
}
|
||||
|
||||
return score
|
||||
}
|
||||
|
||||
function getCharacter(characterName) {
|
||||
if (characterName == null) characterName = state.characterName
|
||||
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
|
||||
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
|
||||
}
|
||||
state.characters.push(character)
|
||||
return character
|
||||
}
|
||||
|
||||
function deleteCharacter(name) {
|
||||
var index = state.characters.findIndex((element) => element.name == name)
|
||||
state.characters.splice(index, 1)
|
||||
}
|
||||
|
||||
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 => {
|
||||
const oldLevel = getLevel(x.experience)
|
||||
x.experience += experience
|
||||
const newLevel = getLevel(x.experience)
|
||||
if (newLevel > oldLevel) leveledUp += `\n[${x.name} has 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.keys == name)
|
||||
}
|
||||
|
||||
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()
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue