Added hashtags for locations.

This commit is contained in:
raeleus 2024-09-29 23:30:20 -07:00
parent 2507e38739
commit 5a1d9c2f36
4 changed files with 220 additions and 2 deletions

149
Input.js
View file

@ -52,6 +52,12 @@ const showAutoXpSynonyms = ["showautoxp"]
const setDefaultDifficultySynonyms = ["setdefaultdifficulty", "defaultdifficulty", "setdefaultdc", "defaultdc", "setdefaultac", "defaultac", "setdifficulty", "difficulty", "dc"]
const showDefaultDifficultySynonyms = ["showdefaultdifficulty", "showdefaultdc", "showdefaultac"]
const generateNameSynonyms = ["generatename", "name", "randomname", "makename", "createname"]
const createLocationSynonyms = ["createlocation", "makelocation", "generatelocation", "createplace", "makeplace", "generateplace", "createtown", "maketown", "generatetown", "createvillage", "makevillage", "generatevillage", "createcity", "makecity", "generatecity", "updatelocation", "updateplace", "updatetown", "updatevillage", "updatecity"]
const goToLocationSynonyms = ["gotolocation", "golocation", "movetolocation", "traveltolocation", "travellocation", "gotoplace", "goplace", "movetoplace", "traveltoplace", "travelplace", "gototown", "gotown", "movetotown", "traveltotown", "traveltown", "gotovillage", "govillage", "movetovillage", "traveltovillage", "travelvillage", "gotocity", "gocity", "movetocity", "traveltocity", "travelcity", "goto", "go", "moveto", "move", "travelto", "travel"]
const removeLocationSynonyms = ["removelocation", "deletelocation", "eraselocation", "removeplace", "deleteplace", "eraseplace", "removetown", "deletetown", "erasetown", "removevillage", "deletevillage", "erasevillage", "removecity", "deletecity", "erasecity"]
const showLocationsSynonyms = ["showlocations", "showplaces", "showtowns", "showvillages", "showcities", "locations", "places", "towns", "villages", "cities"]
const getLocationSynonyms = ["getlocation", "location", "getcoordinates", "coordinates", "getcoords", "coords", "showlocation"]
const clearLocationsSynonyms = ["clearlocations", "eraselocations", "deletelocations", "resetlocations"]
const helpSynonyms = ["help"]
const modifier = (text) => {
@ -84,7 +90,7 @@ const modifier = (text) => {
return { text }
}
if (!found) found = processCommandSynonyms(command, commandName, helpSynonyms.concat(rollSynonyms, noteSynonyms, eraseNoteSynonyms, showNotesSynonyms, clearNotesSynonyms, showCharactersSynonyms, removeCharacterSynonyms, generateNameSynonyms, setDefaultDifficultySynonyms, showDefaultDifficultySynonyms, renameCharacterSynonyms, cloneCharacterSynonyms, resetSynonyms), function () {return true})
if (!found) found = processCommandSynonyms(command, commandName, helpSynonyms.concat(rollSynonyms, noteSynonyms, eraseNoteSynonyms, showNotesSynonyms, clearNotesSynonyms, showCharactersSynonyms, removeCharacterSynonyms, generateNameSynonyms, setDefaultDifficultySynonyms, showDefaultDifficultySynonyms, renameCharacterSynonyms, cloneCharacterSynonyms, createLocationSynonyms, showLocationsSynonyms, goToLocationSynonyms, removeLocationSynonyms, getLocationSynonyms, clearLocationsSynonyms, resetSynonyms), function () {return true})
if (found == null) {
if (state.characterName == null) {
@ -150,6 +156,12 @@ const modifier = (text) => {
if (text == null) text = processCommandSynonyms(command, commandName, setDefaultDifficultySynonyms, doSetDefaultDifficulty)
if (text == null) text = processCommandSynonyms(command, commandName, showDefaultDifficultySynonyms, doShowDefaultDifficulty)
if (text == null) text = processCommandSynonyms(command, commandName, generateNameSynonyms, doGenerateName)
if (text == null) text = processCommandSynonyms(command, commandName, createLocationSynonyms, doCreateLocation)
if (text == null) text = processCommandSynonyms(command, commandName, goToLocationSynonyms, doGoToLocation)
if (text == null) text = processCommandSynonyms(command, commandName, clearLocationsSynonyms, doClearLocations)
if (text == null) text = processCommandSynonyms(command, commandName, removeLocationSynonyms, doRemoveLocation)
if (text == null) text = processCommandSynonyms(command, commandName, showLocationsSynonyms, doShowLocations)
if (text == null) text = processCommandSynonyms(command, commandName, getLocationSynonyms, doGetLocation)
if (text == null) text = processCommandSynonyms(command, commandName, renameCharacterSynonyms, doRenameCharacter)
if (text == null) text = processCommandSynonyms(command, commandName, cloneCharacterSynonyms, doCloneCharacter)
if (text == null) text = processCommandSynonyms(command, commandName, helpSynonyms, doHelp)
@ -518,6 +530,9 @@ function init() {
}
if (state.characters == null) state.characters = []
if (state.notes == null) state.notes = []
if (state.locations == null) state.locations = []
if (state.x == null) state.x = 0
if (state.y == null) state.y = 0
if (state.autoXp == null) state.autoXp = 0
if (state.defaultDifficulty == null) state.defaultDifficulty = 10
state.show = null
@ -1163,6 +1178,134 @@ function doShowNotes(command) {
return " "
}
function doCreateLocation(command) {
var locationArgIndex = 2
var arg0 = getArgument(command, 0)
var arg1 = getArgument(command, 1)
if (arg0 == null || isNaN(arg0)) {
arg0 = null
arg1 = null
locationArgIndex = 0
}
if (arg0 != null && (arg1 == null || isNaN(arg1))) {
arg1 = null
locationArgIndex = 1
}
var arg2 = getArgumentRemainder(command, locationArgIndex)
if (arg2 == null) {
state.show = "none"
return "\n[Error: Not enough parameters. See #help]\n"
}
var location = createLocation(arg0, arg1, arg2)
state.show = "none"
return `\n[Location ${toTitleCase(arg2)} has been created at (${location.x},${location.y})]\n`
}
function doGoToLocation(command) {
var character = getCharacter()
var characterName = character == null ? "You" : character.name
var possessiveName = getPossessiveName(characterName)
var travelWord = characterName == "You" ? "travel" : "travels"
var locationArgIndex = 2
var arg0 = getArgument(command, 0)
var arg1 = getArgument(command, 1)
if (arg0 == null || isNaN(arg0)) {
arg0 = state.x
arg1 = state.y
locationArgIndex = 0
}
if (arg0 != null && (arg1 == null || isNaN(arg1))) {
arg1 = state.y
locationArgIndex = 1
}
var distance = 0
var location
var locationName = getArgumentRemainder(command, locationArgIndex)
if (locationName == null && locationArgIndex == 0) {
state.show = none
return "\n[Error: Not enough parameters. See #help]\n"
}
if (locationName == null) {
var index = state.locations.findIndex(x => x.x == arg0 && x.y == arg1)
if (index != -1) location = state.locations[index]
} else {
var index = state.locations.findIndex(x => x.name.toLowerCase() == locationName.toLowerCase())
if (index != -1) location = state.locations[index]
else location = createLocation(arg0, arg1, locationName)
}
if (location == null) {
distance = pointDistance(state.x, state.y, arg0, arg1)
state.x = arg0
state.y = arg1
} else {
distance = pointDistance(state.x, state.y, location.x, location.y)
state.x = location.x
state.y = location.y
state.location = location.name
}
distance = distance.toFixed(1)
state.show = "none"
if (location == null) return `\n${characterName} ${travelWord} ${distance > 0 ? distance + " units " : ""} to (${arg0},${arg1})`
if (state.characters.length > 1) return `\n${possessiveName} party travels ${distance > 0 ? distance + " units " : ""}to ${toTitleCase(location.name)} at (${location.x},${location.y})\n`
return `\n${characterName} ${travelWord} ${distance > 0 ? distance + " units " : ""}to ${toTitleCase(location.name)} at (${location.x},${location.y})\n`
}
function doGetLocation(command) {
state.show = "none"
return `\n[You are at ${state.location == null ? "" : "the location " + state.location + " "}(${state.x},${state.y})]`
}
function doClearLocations(command) {
state.locations = []
state.location = null
state.show = "none"
return "\n[The locations have been cleared]\n"
}
function doRemoveLocation(command) {
var arg0 = getArgumentRemainder(command, 0)
if (arg0 == null) {
state.show = "none"
return "\n[Error: Not enough parameters. See #help]\n"
}
var location
if (isNaN(arg0)) arg0 = state.locations.findIndex(x => x.name.toLowerCase() == arg0.toLowerCase())
else arg0--
if (arg0 == -1) {
state.show = "none"
return "\n[Error: Location not found. See #showlocations]\n"
} else if (arg0 >= state.locations.length || arg0 < 0) {
state.show = "none"
return "\n[Error: Location number out of bounds. See #showlocations]\n"
} else {
location = state.locations[arg0]
state.locations.splice(arg0, 1)
}
state.show = "none"
return `\n[The location ${toTitleCase(location.name)} has been removed]\n`
}
function doShowLocations(command) {
state.show = "locations"
return " "
}
function doTake(command) {
var arg0 = getArgument(command, 0)
if (arg0 == null) {
@ -1794,6 +1937,10 @@ function doClearSkills(command) {
function doReset(command) {
state.notes = []
state.characters = []
state.locations = []
state.location = null
state.x = 0
state.y = 0
state.defaultDifficulty = null
state.autoXp = null

View file

@ -17,6 +17,52 @@ function shuffle(array, seed) {
}
}
function pointDistance(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2))
}
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) {
if (x == null || y == null) {
var cx = x == null ? state.x : x
var cy = y == null ? state.y : y
var coords = rotate(cx, cy, getRandomInteger(-10, 10) + cx, cy, Math.random() * 360)
x = coords[0]
y = coords[1]
}
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/, "")
@ -175,7 +221,7 @@ function calculateRoll(rolltext) {
function getCharacter(characterName) {
if (characterName == null) characterName = state.characterName
if (characterName == null) return null
return state.characters.find((element) => element.name.toLowerCase() == characterName.toLowerCase())
return state.characters.find(element => element.name.toLowerCase() == characterName.toLowerCase())
}
function hasCharacter(characterName) {

View file

@ -173,6 +173,20 @@ const modifier = (text) => {
}
text += "******************\n\n"
break
case "locations":
text += `Player location: ${state.location == null ? "" : state.location + " "}(${state.x},${state.y})\n`
text += `*** LOCATIONS ***\n`
if (state.locations.length > 0) {
var index = 0
state.locations.forEach(function(location) {
var distance = pointDistance(state.x, state.y, location.x, location.y).toFixed(1)
text += `${++index}. ${toTitleCase(location.name)} (${location.x},${location.y}) Distance: ${distance}\n`
})
} else {
text += `No locations have been discovered!`
}
text += "******************\n\n"
break
case "none":
text += " "
break
@ -305,6 +319,16 @@ const modifier = (text) => {
text += "\n#spellbook"
text += "\n Shows the list of spells that the character has learned."
text += "\n\n--Locations--"
text += "\n#createlocation (x) (y) location_name"
text += "\n Creates a location at the given coordinates. If the coordinates are not provided, they are randomized within a range of 10 units from the player's current location. Multiple locations may exist at the same coordinates. A story card is created for the location. Quotes are not necessary."
text += "\n#goto (x) (y) or (location_name)"
text += "\n Makes the characters travel to the location specified by the coordinates or location_name. You must provide at least one or the other. If the location does not exist, it is created at your current coordinates. If you only specify coordinates, you will go to the first location at those coordinates. Quotes are not necessary."
text += "\n#getlocation"
text += "\n Returns the coordinates that the player's party is at. It will also list a location if a location was specified when using #goto."
text += "\n#removelocation location_name or location_number"
text += "\n Removes the specified location or location number as listed in #showlocations. Quotes are not necessary."
text += "\n\n--Danger Zone--"
text += "\n#reset"
text += "\n Removes all characters and changes all settings to their defaults. Use with caution!"

View file

@ -15,6 +15,7 @@ Personalized note system that does not take up context space<br>
See the [user guide here](https://github.com/raeleus/Hashtag-DnD/wiki).
v. 0.1.0
* Added `#createlocation`, `#goto`, `#removelocation`, `#clearlocations`, `#getlocation` and `#showlocations` to enable travelling.
* Added `#renameitem` to rename an existing item
* Added `#renamecharacter` to rename an existing character
* Added `#clonecharacter` to copy an existing character