diff --git a/_datafiles/guides/building/scripting/FUNCTIONS_ACTORS.md b/_datafiles/guides/building/scripting/FUNCTIONS_ACTORS.md index a07ba2b1..d69188c8 100644 --- a/_datafiles/guides/building/scripting/FUNCTIONS_ACTORS.md +++ b/_datafiles/guides/building/scripting/FUNCTIONS_ACTORS.md @@ -16,6 +16,7 @@ ActorObjects are the basic object that represents Users and NPCs - [ActorObject.GetLevel() int](#actorobjectgetlevel-int) - [ActorObject.GetStat(statName string) int](#actorobjectgetstatstatname-string-int) - [ActorObject.SetTempData(key string, value any)](#actorobjectsettempdatakey-string-value-any) + - [ActorObject.SetResetRoomId(roomId int)](#actorobjectsetresetroomidroomid-int) - [ActorObject.GetTempData(key string) any](#actorobjectgettempdatakey-string-any) - [ActorObject.SetMiscCharacterData(key string, value any)](#actorobjectsetmisccharacterdatakey-string-value-any) - [ActorObject.GetMiscCharacterData(key string) any](#actorobjectgetmisccharacterdatakey-string-any) @@ -25,16 +26,19 @@ ActorObjects are the basic object that represents Users and NPCs - [ActorObject.GetRoomId() int](#actorobjectgetroomid-int) - [ActorObject.HasQuest(questId string) bool](#actorobjecthasquestquestid-string-bool) - [ActorObject.GiveQuest(questId string)](#actorobjectgivequestquestid-string) - - [ActorObject.GetPartyMembers() \[\]Actor](#actorobjectgetpartymembers-actor) + - [ActorObject.GetParty(\[excludeSelf bool\])](#actorobjectgetpartyexcludeself-bool) + - [ActorObject.GetPartyPresent(\[excludeSelf bool\])](#actorobjectgetpartypresentexcludeself-bool) + - [ActorObject.GetPartyMissing()](#actorobjectgetpartymissing) - [ActorObject.AddGold(amt int \[, bankAmt int\])](#actorobjectaddgoldamt-int--bankamt-int) - [ActorObject.AddHealth(amt int) int](#actorobjectaddhealthamt-int-int) + - [ActorObject.AddMana(amt int) int](#actorobjectaddmanaamt-int-int) - [ActorObject.Sleep(seconds int)](#actorobjectsleepseconds-int) - [ActorObject.Command(cmd string \[, waitTurns int\])](#actorobjectcommandcmd-string--waitturns-int) - [ActorObject.CommandFlagged(cmd string, flag int \[, waitTurns int\])](#actorobjectcommandflaggedcmd-string-flag-int--waitturns-int) - [ActorObject.IsTameable() bool](#actorobjectistameable-bool) - [ActorObject.TrainSkill(skillName string, skillLevel int)](#actorobjecttrainskillskillname-string-skilllevel-int) - [ActorObject.GetSkillLevel(skillName string)](#actorobjectgetskilllevelskillname-string) - - [ActorObject.MoveRoom(destRoomId int \[, leaveCharmedMobsBehind bool\] )](#actorobjectmoveroomdestroomid-int--leavecharmedmobsbehind-bool-) + - [ActorObject.MoveRoom(destRoomId int )](#actorobjectmoveroomdestroomid-int-) - [ActorObject.UpdateItem(itemId ItemObject)](#actorobjectupdateitemitemid-itemobject) - [ActorObject.GiveItem(itemId ItemObject)](#actorobjectgiveitemitemid-itemobject) - [ActorObject.TakeItem(itemId ItemObject)](#actorobjecttakeitemitemid-itemobject) @@ -118,7 +122,7 @@ Retrieves a ActorObject for a given mobInstanceId. | createIfMissing | If true and mob isn't found, the mob will be created and returned. | ## [ActorObject.UserId() int](/internal/scripting/actor_func.go) -Returns the userId of the ActorObject.˚ +Returns the userId of the ActorObject. _Note: Only useful for User ActorObjects - Returns zero otherwise._ @@ -173,6 +177,16 @@ _Note: This is useful for saving/retrieving data that an ActorObject can carry a | key | A unique identifier for the data. | | value | What you will be saving. If null, frees from memory. | +## [ActorObject.SetResetRoomId(roomId int)](/internal/scripting/actor_func.go) +Sets the "Reset Room Id" a player will be sent to if they log out. + +_Note: This is only useful if the player is being sent to an ephemeral chunk._ + +| Argument | Explanation | +| --- | --- | +| roomId | The RoomId the player should be sent to. | + + ## [ActorObject.GetTempData(key string) any](/internal/scripting/actor_func.go) Gets temporary data for the ActorObject. @@ -235,14 +249,28 @@ Get whether a ActorObject has a quest/progress. | questId | The quest identifier string to check, such as `3-start`. | ## [ActorObject.GiveQuest(questId string)](/internal/scripting/actor_func.go) -Grants a quest or progress on a quest to a ActorObject. If they are in a party, grants to the party members as well. +Grants a quest or progress on a quest to a ActorObject. | Argument | Explanation | | --- | --- | | questId | The quest identifier string to give, such as `3-start`. | -## [ActorObject.GetPartyMembers() []Actor](/internal/scripting/actor_func.go) -Returns a list of actors in the party, both players and mobs. +## [ActorObject.GetParty([excludeSelf bool])](/internal/scripting/actor_func.go) +Returns a Party object that operates on the entire party and charmed mobs. + +| Argument | Explanation | +| --- | --- | +| excludeSelf | If true, excludes the actor from the operating list. | + +## [ActorObject.GetPartyPresent([excludeSelf bool])](/internal/scripting/actor_func.go) +Returns a Party object that operates on the party members and charmed mobs in the same room. + +| Argument | Explanation | +| --- | --- | +| excludeSelf | If true, excludes the actor from the operating list. | + +## [ActorObject.GetPartyMissing()](/internal/scripting/actor_func.go) +Returns a Party object that operates on the party members and charmed mobs missing from the room. ## [ActorObject.AddGold(amt int [, bankAmt int])](/internal/scripting/actor_func.go) Update how much gold an ActorObject has @@ -259,6 +287,13 @@ Update how much health an ActorObject has, and returns the actual amount their h | --- | --- | | amt | A positive or negative amount of health to alter the actors health by. | +## [ActorObject.AddMana(amt int) int](/internal/scripting/actor_func.go) +Update how much mana an ActorObject has, and returns the actual amount their mana changed. + +| Argument | Explanation | +| --- | --- | +| amt | A positive or negative amount of mana to alter the actors mana by. | + ## [ActorObject.Sleep(seconds int)](/internal/scripting/actor_func.go) Force a mob to wait this many seconds before executing any additional behaviors @@ -309,13 +344,14 @@ Returns the current skil level for the skillName, or zero if none. | skillName | The name of the skill to train, such as `map` or `backstab`. | -## [ActorObject.MoveRoom(destRoomId int [, leaveCharmedMobsBehind bool] )](/internal/scripting/actor_func.go) +## [ActorObject.MoveRoom(destRoomId int )](/internal/scripting/actor_func.go) Quietly moves an ActorObject to a new room | Argument | Explanation | | --- | --- | | destRoomId | The room id to move them to. | -| leaveCharmedMobsBehind | If true, does not also move charmed mobs with the user. | + + ## [ActorObject.UpdateItem(itemId ItemObject)](/internal/scripting/actor_func.go) Accepts an ItemObject to update in the players backpack. If the item does not already exist in the players backpack, it is ignored. diff --git a/_datafiles/guides/building/scripting/FUNCTIONS_ITEMS.md b/_datafiles/guides/building/scripting/FUNCTIONS_ITEMS.md index e5eda869..c02f0800 100644 --- a/_datafiles/guides/building/scripting/FUNCTIONS_ITEMS.md +++ b/_datafiles/guides/building/scripting/FUNCTIONS_ITEMS.md @@ -16,6 +16,7 @@ ActorObjects are the basic object that represents Users and NPCs - [ItemObject.SetTempData(key string, value any)](#itemobjectsettempdatakey-string-value-any) - [ItemObject.GetTempData(key string) any](#itemobjectgettempdatakey-string-any) - [ItemObject.Rename(newName string \[, displayNameOrStyle string\])](#itemobjectrenamenewname-string--displaynameorstyle-string) + - [ItemObject.ShorthandId() string](#itemobjectshorthandid-string) - [ItemObject.Redescribe(newDescription string)](#itemobjectredescribenewdescription-string) ## [CreateItem(itemId int) ItemObject ](/internal/scripting/item_func.go) @@ -74,10 +75,10 @@ Sets temporary data of any sort on the item. This data is not saved/loaded when | Argument | Explanation | | --- | --- | | key | The name to store the data under. Also used to retrieve the data later. | -| vaue | The data to store. | +| value | The data to store. | ## [ItemObject.GetTempData(key string) any](/internal/scripting/item_func.go) -Sets temporary data of any sort on the item. This data is not saved/loaded when despawning. +Gets temporary data of any sort on the item. This data is not saved/loaded when despawning. | Argument | Explanation | | --- | --- | @@ -92,6 +93,9 @@ Renames the item, also optionally provide a fancy name or colorpattern | newName | The plaintext name. | | displayNameOrStyle | A fancy name in ansi tags, color short tags, or a pattern like :flame | +## [ItemObject.ShorthandId() string](/internal/scripting/item_func.go) +Returns the shorthand identifier for the item. + ## [ItemObject.Redescribe(newDescription string)](/internal/scripting/item_func.go) Change the description for an item diff --git a/_datafiles/guides/building/scripting/FUNCTIONS_PARTY.md b/_datafiles/guides/building/scripting/FUNCTIONS_PARTY.md new file mode 100644 index 00000000..696f285a --- /dev/null +++ b/_datafiles/guides/building/scripting/FUNCTIONS_PARTY.md @@ -0,0 +1,198 @@ +# PartyObject + +PartyObjects represent collections of actors (users and NPCs) that are grouped together. They provide convenient methods to perform operations on multiple actors at once. + +- [PartyObject](#partyobject) + - [PartyObject.GetMembers() \[\]ActorObject](#partyobjectgetmembers-actorobject) + - [PartyObject.SendText(msg string)](#partyobjectsendtextmsg-string) + - [PartyObject.SetResetRoomId(roomId int)](#partyobjectsetresetroomidroomid-int) + - [PartyObject.GiveQuest(questId string)](#partyobjectgivequestquestid-string) + - [PartyObject.AddGold(amt int \[, bankAmt int\])](#partyobjectaddgoldamt-int--bankamt-int) + - [PartyObject.AddHealth(amt int)](#partyobjectaddhealthamt-int) + - [PartyObject.AddMana(amt int)](#partyobjectaddmanaamt-int) + - [PartyObject.Command(cmd string \[, waitSeconds float\])](#partyobjectcommandcmd-string--waitseconds-float) + - [PartyObject.TrainSkill(skillName string, skillLevel int)](#partyobjecttrainskillskillname-string-skilllevel-int) + - [PartyObject.MoveRoom(destRoomId int)](#partyobjectmoveroomdestroomid-int) + - [PartyObject.AddEventLog(category string, message string)](#partyobjectaddeventlogcategory-string-message-string) + - [PartyObject.GiveBuff(buffId int, source string)](#partyobjectgivebuffbuffid-int-source-string) + - [PartyObject.CancelBuffWithFlag(buffFlag string)](#partyobjectcancelbuffwithflagbuffflag-string) + - [PartyObject.RemoveBuff(buffId int)](#partyobjectremovebuffbuffid-int) + - [PartyObject.ChangeAlignment(alignmentChange int)](#partyobjectchangealignmentalignmentchange-int) + - [PartyObject.LearnSpell(spellId string)](#partyobjectlearnspellspellid-string) + - [PartyObject.SetHealth(amt int)](#partyobjectsethealthamt-int) + - [PartyObject.SetAdjective(adj string, addIt bool)](#partyobjectsetadjectiveadj-string-addit-bool) + - [PartyObject.GiveTrainingPoints(ct int)](#partyobjectgivetrainingpointsct-int) + - [PartyObject.GiveStatPoints(ct int)](#partyobjectgivestatpointsct-int) + - [PartyObject.GiveExtraLife()](#partyobjectgiveextralife) + - [PartyObject.GrantXP(xpAmt int, reason string)](#partyobjectgrantxpxpamt-int-reason-string) + - [PartyObject.TimerSet(name string, period string)](#partyobjecttimersetname-string-period-string) + + + + +## [PartyObject.GetMembers() []ActorObject](/internal/scripting/party_func.go) +Returns an array of all ActorObjects in the party based on the party configuration. + +_Note: This includes both party members and their charmed creatures, filtered by presence/absence based on how the party object was created._ + +## [PartyObject.SendText(msg string)](/internal/scripting/party_func.go) +Sends a message to all members of the party. + +| Argument | Explanation | +| --- | --- | +| msg | the message to send to all party members | + +## [PartyObject.SetResetRoomId(roomId int)](/internal/scripting/party_func.go) +Sets the "Reset Room Id" for all user party members (where they will be sent if they log out). + +_Note: Only affects user party members, not NPCs. This is only useful if players are being sent to ephemeral chunks._ + +| Argument | Explanation | +| --- | --- | +| roomId | The RoomId all party members should be sent to | + +## [PartyObject.GiveQuest(questId string)](/internal/scripting/party_func.go) +Grants a quest or progress on a quest to all party members. + +| Argument | Explanation | +| --- | --- | +| questId | The quest identifier string to give, such as `3-start` | + +## [PartyObject.AddGold(amt int [, bankAmt int])](/internal/scripting/party_func.go) +Updates how much gold all party members have. + +| Argument | Explanation | +| --- | --- | +| amt | A positive or negative amount of gold to alter each party member's gold by | +| bankAmt (optional) | A positive or negative amount of gold to alter each party member's bank gold by | + +## [PartyObject.AddHealth(amt int)](/internal/scripting/party_func.go) +Updates how much health all party members have. + +| Argument | Explanation | +| --- | --- | +| amt | A positive or negative amount of health to alter each party member's health by | + +## [PartyObject.AddMana(amt int)](/internal/scripting/party_func.go) +Updates how much mana all party members have. + +| Argument | Explanation | +| --- | --- | +| amt | A positive or negative amount of mana to alter each party member's mana by | + +## [PartyObject.Command(cmd string [, waitSeconds float])](/internal/scripting/party_func.go) +Forces all party members to execute a command as if they entered it. + +_Note: Don't underestimate the power of this function! Complex and interesting behaviors or interactions can emerge from using it._ + +| Argument | Explanation | +| --- | --- | +| cmd | The command to execute such as `look west` or `say goodbye` | +| waitSeconds (optional) | The number of seconds to wait before executing the command | + +## [PartyObject.TrainSkill(skillName string, skillLevel int)](/internal/scripting/party_func.go) +Sets a skill level for all party members, if it's greater than what they already have. + +| Argument | Explanation | +| --- | --- | +| skillName | The name of the skill to train, such as `map` or `backstab` | +| skillLevel | The skill level to train to | + +## [PartyObject.MoveRoom(destRoomId int)](/internal/scripting/party_func.go) +Quietly moves all party members to a new room. + +| Argument | Explanation | +| --- | --- | +| destRoomId | The room id to move them all to | + +## [PartyObject.AddEventLog(category string, message string)](/internal/scripting/party_func.go) +Adds a line to all party members' Event Log (`history`). + +| Argument | Explanation | +| --- | --- | +| category | A short single word category | +| message | A single line describing the event | + +## [PartyObject.GiveBuff(buffId int, source string)](/internal/scripting/party_func.go) +Grants all party members a Buff. + +| Argument | Explanation | +| --- | --- | +| buffId | The ID of the buff to give them | +| source | The source of the buff, "item", "spell", "trap", "curse", etc. or empty | + +## [PartyObject.CancelBuffWithFlag(buffFlag string)](/internal/scripting/party_func.go) +Cancels any buffs that have the flag provided for all party members. + +| Argument | Explanation | +| --- | --- | +| buffFlag | The buff flag to check [see buffspec.go](../buffs/buffspec.go) | + +## [PartyObject.RemoveBuff(buffId int)](/internal/scripting/party_func.go) +Remove a buff from all party members without triggering onEnd. + +| Argument | Explanation | +| --- | --- | +| buffId | The ID of the buff to remove | + +## [PartyObject.ChangeAlignment(alignmentChange int)](/internal/scripting/party_func.go) +Updates the alignment of all party members by a relative amount. Caps result at -100 to 100. + +| Argument | Explanation | +| --- | --- | +| alignmentChange | The alignment adjustment, from -200 to 200 | + +## [PartyObject.LearnSpell(spellId string)](/internal/scripting/party_func.go) +Adds the spell to all party members' spellbooks. + +| Argument | Explanation | +| --- | --- | +| spellId | The ID of the spell | + +## [PartyObject.SetHealth(amt int)](/internal/scripting/party_func.go) +Sets all party members' health to a specific amount. If this exceeds their maximum health, sets to their maximum health. + +| Argument | Explanation | +| --- | --- | +| amt | number of hitpoints to set them to | + +## [PartyObject.SetAdjective(adj string, addIt bool)](/internal/scripting/party_func.go) +Adds or removes a specific text adjective to all party members' names. + +| Argument | Explanation | +| --- | --- | +| adj | Adjective such as "sleeping", "crying" or "busy" | +| addIt | `true` to add it. `false` to remove it | + +## [PartyObject.GiveTrainingPoints(ct int)](/internal/scripting/party_func.go) +Increases training points for all party members. + +| Argument | Explanation | +| --- | --- | +| ct | How many training points to give | + +## [PartyObject.GiveStatPoints(ct int)](/internal/scripting/party_func.go) +Increases stat points for all party members. + +| Argument | Explanation | +| --- | --- | +| ct | How many stat points to give | + +## [PartyObject.GiveExtraLife()](/internal/scripting/party_func.go) +Increases extra lives by 1 for all party members. + +## [PartyObject.GrantXP(xpAmt int, reason string)](/internal/scripting/party_func.go) +Gives experience points to all party members. + +| Argument | Explanation | +| --- | --- | +| xpAmt | How much experience to grant | +| reason | Short reasons such as "combat", "trash cleanup" | + +## [PartyObject.TimerSet(name string, period string)](/internal/scripting/party_func.go) +Starts a new Round timer for all party members. + +| Argument | Explanation | +| --- | --- | +| name | A string identifier. Reusing names will overwrite previously assigned names | +| period | How long until the timer expires. `1 real hour`, `1 hour`, etc | \ No newline at end of file diff --git a/_datafiles/guides/building/scripting/FUNCTIONS_ROOMS.md b/_datafiles/guides/building/scripting/FUNCTIONS_ROOMS.md index a871255c..78d619c3 100644 --- a/_datafiles/guides/building/scripting/FUNCTIONS_ROOMS.md +++ b/_datafiles/guides/building/scripting/FUNCTIONS_ROOMS.md @@ -1,11 +1,13 @@ # Room Specific Functions - [Room Specific Functions](#room-specific-functions) + - [CreateEmptyRoomInstances(quantity int) \[\]int](#createemptyroominstancesquantity-int-int) - [CreateInstancesFromRoomIds(RoomIds \[int, int...\]) Object ](#createinstancesfromroomidsroomids-int-int-object-) - [CreateInstancesFromZone(zoneName string) Object ](#createinstancesfromzonezonename-string-object-) - [GetRoom(roomId int) RoomObject ](#getroomroomid-int-roomobject-) - [RoomObject.RoomId() int](#roomobjectroomid-int) - [RoomObject.SendText(msg string\[, excludeUserIds int\])](#roomobjectsendtextmsg-string-excludeuserids-int) + - [RoomObject.SendTextToExits(msg string, isQuiet bool\[, excludeUserIds int\])](#roomobjectsendtexttoexitsmsg-string-isquiet-bool-excludeuserids-int) - [RoomObject.SetTempData(key string, value any)](#roomobjectsettempdatakey-string-value-any) - [RoomObject.GetTempData(key string) any](#roomobjectgettempdatakey-string-any) - [RoomObject.SetPermData(key string, value any)](#roomobjectsetpermdatakey-string-value-any) @@ -13,7 +15,7 @@ - [RoomObject.GetItems() \[\]ItemObject](#roomobjectgetitems-itemobject) - [RoomObject.DestroyItem(itm ScriptItem) ](#roomobjectdestroyitemitm-scriptitem-) - [RoomObject.SpawnItem(itemId int, inStash bool) \[\]ItemObject](#roomobjectspawnitemitemid-int-instash-bool-itemobject) - - [RoomObject.GetMob(mobId int) Actor](#roomobjectgetmobmobid-int-actor) + - [RoomObject.GetMob(mobId int \[, createIfMissing bool\]) Actor](#roomobjectgetmobmobid-int--createifmissing-bool-actor) - [RoomObject.GetMobs(\[mobId int\]) \[\]Actor](#roomobjectgetmobsmobid-int-actor) - [RoomObject.GetPlayers() \[\]Actor](#roomobjectgetplayers-actor) - [RoomObject.GetAllActors() \[\]Actor](#roomobjectgetallactors-actor) @@ -23,17 +25,24 @@ - [RoomObject.HasQuest(questId string \[,partyUserId int\]) \[\]int](#roomobjecthasquestquestid-string-partyuserid-int-int) - [RoomObject.MissingQuest(questId string \[,partyUserId int\]) \[\]int](#roomobjectmissingquestquestid-string-partyuserid-int-int) - [RoomObject.SpawnMob(mobId int) Actor](#roomobjectspawnmobmobid-int-actor) - - [RoomObject.AddTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int, expiresTimeString string](#roomobjectaddtemporaryexitexitnamesimple-string-exitnamefancy-string-exitroomid-int-expirestimestring-string) - - [RoomObject.RemoveTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int](#roomobjectremovetemporaryexitexitnamesimple-string-exitnamefancy-string-exitroomid-int) + - [RoomObject.AddTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int, expiresTimeString string) bool](#roomobjectaddtemporaryexitexitnamesimple-string-exitnamefancy-string-exitroomid-int-expirestimestring-string-bool) + - [RoomObject.RemoveTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int) bool](#roomobjectremovetemporaryexitexitnamesimple-string-exitnamefancy-string-exitroomid-int-bool) - [RoomObject.HasMutator(mutName string) bool](#roomobjecthasmutatormutname-string-bool) - [RoomObject.AddMutator(mutName string)](#roomobjectaddmutatormutname-string) - [RoomObject.RemoveMutator(mutName string)](#roomobjectremovemutatormutname-string) - [RoomObject.IsEphemeral() bool](#roomobjectisephemeral-bool) - [RoomObject.RoomIdSource() int](#roomobjectroomidsource-int) - - [RoomObject.RepeatSpawnItem(itemId int, roundInterval int \[, containerName\]](#roomobjectrepeatspawnitemitemid-int-roundinterval-int--containername) + - [RoomObject.RepeatSpawnItem(itemId int, roundInterval int \[, containerName\]) bool](#roomobjectrepeatspawnitemitemid-int-roundinterval-int--containername-bool) - [RoomObject.SetLocked(exitName string, lockIt bool)](#roomobjectsetlockedexitname-string-lockit-bool) - [RoomObject.IsLocked(exitName string) bool](#roomobjectislockedexitname-string-bool) +## [CreateEmptyRoomInstances(quantity int) []int](/internal/scripting/room_func.go) +Creates a specified number of empty ephemeral room instances. + +| Argument | Explanation | +| --- | --- | +| quantity | Number of empty rooms to create | + ## [CreateInstancesFromRoomIds(RoomIds [int, int...]) Object ](/internal/scripting/room_func.go) Returns an Object with key/value pairs of `ProvidedRoomId`=>`NewRoomId` Creates ephemeral instances of the RoomId's provided. @@ -66,6 +75,15 @@ Sends a message to everyone in the room. | msg | the message to send | | excludeUserIds | One or more comma separated userIds to exclude from receiving the message. | +## [RoomObject.SendTextToExits(msg string, isQuiet bool[, excludeUserIds int])](/internal/scripting/room_func.go) +Sends a message to all rooms with an exit leading to this room. + +| Argument | Explanation | +| --- | --- | +| msg | the message to send | +| isQuiet | If true, only those with superior "hearing" will see it. | +| excludeUserIds | One or more comma separated userIds to exclude from receiving the message. | + ## [RoomObject.SetTempData(key string, value any)](/internal/scripting/room_func.go) Sets temporary data for the room (Lasts until the room is unloaded from memory). @@ -112,7 +130,7 @@ _Note: See [/scripting/docs/FUNCTIONS_ITEMS.md](FUNCTIONS_ITEMS.md) for details ## [RoomObject.DestroyItem(itm ScriptItem) ](/internal/scripting/room_func.go) Destroy an item from the ground. -## [RoomObject.SpawnItem(itemId int, inStash bool) []ItemObject](/internal/scripting/room_func.go) +## [RoomObject.SpawnItem(itemId int, inStash bool)](/internal/scripting/room_func.go) Spawns an item in the room. | Argument | Explanation | @@ -121,12 +139,13 @@ Spawns an item in the room. | inStash | If true, spawns stashed instead of visible. | -## [RoomObject.GetMob(mobId int) Actor](/internal/scripting/room_func.go) +## [RoomObject.GetMob(mobId int [, createIfMissing bool]) Actor](/internal/scripting/room_func.go) Returns the first mob that matches the provided MobId type (Note: NOT MOB INSTANCE ID!) | Argument | Explanation | | --- | --- | | mobId | MobId to match. | +| createIfMissing (optional) | If true, will spawn the mob if not found. | ## [RoomObject.GetMobs([mobId int]) []Actor](/internal/scripting/room_func.go) Returns an array of mob `Actor`s in the room. @@ -186,7 +205,7 @@ _Note: This could be useful for situations where you want to allow a whole party | partyUserId (optional) | Only check the specified user and their party | ## [RoomObject.MissingQuest(questId string [,partyUserId int]) []int](/internal/scripting/room_func.go) -Returns an array of userId's in the romo who DON'T have the questId. If partyyUserId is supplied, only checks the user and their party specified. +Returns an array of userId's in the room who DON'T have the questId. If partyUserId is supplied, only checks the user and their party specified. _Note: This could be useful for situations where you want to disallow a whole party access to an area even if only one of them is missing the quest._ @@ -202,7 +221,7 @@ Creates a new instance of MobId,and returns the `Actor` of the mob. | --- | --- | | mobId | The ID if the mob type to spawn. NOT THE INSTANCE ID. | -## [RoomObject.AddTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int, expiresTimeString string](/internal/scripting/room_func.go) +## [RoomObject.AddTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int, expiresTimeString string) bool](/internal/scripting/room_func.go) Adds a temporary exit to the room for the specified amount of time. | Argument | Explanation | @@ -212,7 +231,7 @@ Adds a temporary exit to the room for the specified amount of time. | exitRoomId | The roomId the exit should lead to. | | expiresTimeString | Time string (1 day, 1 real day, 4 hours, etc) before it vanishes. | -## [RoomObject.RemoveTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int](/internal/scripting/room_func.go) +## [RoomObject.RemoveTemporaryExit(exitNameSimple string, exitNameFancy string, exitRoomId int) bool](/internal/scripting/room_func.go) Removes a temporary exit _Note: all 3 parameters much match an existing temporary exit for it to be removed._ @@ -243,7 +262,7 @@ _Note: If the mutator already exists this is ignored._ ## [RoomObject.RemoveMutator(mutName string)](/internal/scripting/room_func.go) Removes a mutator from a room. -_Note: This only expires it. It may be a mutator that respawns, in which case this doens't really completely remove it._ +_Note: This only expires it. It may be a mutator that respawns, in which case this doesn't really completely remove it._ | Argument | Explanation | | --- | --- | @@ -252,20 +271,14 @@ _Note: This only expires it. It may be a mutator that respawns, in which case th ## [RoomObject.IsEphemeral() bool](/internal/scripting/room_func.go) Returns true if the room is an Ephemeral Copy of a room. -_Note: This only expires it. It may be a mutator that respawns, in which case this doens't really completely remove it._ - -| Argument | Explanation | -| --- | --- | -| mutName | the MutatorId of the mutator. | - ## [RoomObject.RoomIdSource() int](/internal/scripting/room_func.go) Returns the source RoomId if this room is an ephemeral copy, otherwise just the normal RoomId -## [RoomObject.RepeatSpawnItem(itemId int, roundInterval int [, containerName]](/internal/scripting/room_func.go) -Removes a temporary exit +## [RoomObject.RepeatSpawnItem(itemId int, roundInterval int [, containerName]) bool](/internal/scripting/room_func.go) +Sets up automatic item respawning in the room. -_Note: all 3 parameters much match an existing temporary exit for it to be removed._ +_Note: The item will respawn after the specified interval when removed from the room._ | Argument | Explanation | | --- | --- | diff --git a/_datafiles/guides/building/scripting/README.md b/_datafiles/guides/building/scripting/README.md index 81b3ff54..c3dcd2b0 100644 --- a/_datafiles/guides/building/scripting/README.md +++ b/_datafiles/guides/building/scripting/README.md @@ -21,6 +21,8 @@ See [Spell Scripting](SCRIPTING_SPELLS.md) [ActorObject Functions](FUNCTIONS_ACTORS.md) - Functions that query or alter user/mob data. +[ActorObject Functions](FUNCTIONS_PARTY.md) - Functions that operate on the whole party. + [RoomObject Functions](FUNCTIONS_ROOMS.md) - Functions that query or alter room data. [ItemObject Functions](FUNCTIONS_ITEMS.md) - Functions that query or alter item data. diff --git a/_datafiles/sample-scripts/mobs/item-gold-quest.js b/_datafiles/sample-scripts/mobs/item-gold-quest.js index cc0b5ab2..171ddfdb 100644 --- a/_datafiles/sample-scripts/mobs/item-gold-quest.js +++ b/_datafiles/sample-scripts/mobs/item-gold-quest.js @@ -46,7 +46,7 @@ function onAsk(mob, room, eventDetails) { // // Search the text they inputted for the "ask" command for one of the questStartSubjects // - match = UtilFindMatchIn(eventDetails.askText, questStartSubjects); + var match = UtilFindMatchIn(eventDetails.askText, questStartSubjects); if ( match.found ) { @@ -55,7 +55,7 @@ function onAsk(mob, room, eventDetails) { // // Give them the start quest id // - user.GiveQuest(QUEST_START_ID); + user.GetParty().GiveQuest(QUEST_START_ID); } @@ -66,7 +66,7 @@ function onAsk(mob, room, eventDetails) { // By this point in the script we know they've at least started the quest // Lets see if they are asking any follow up questions for more info. // - match = UtilFindMatchIn(eventDetails.askText, questInfoSubjects); + var match = UtilFindMatchIn(eventDetails.askText, questInfoSubjects); if ( match.found ) { mob.Command("emote thinks hard for a moment."); mob.Command("say You can get sharp sticks from a shop, and gold from selling objects, or possibly killing bad guys and looting them."); @@ -129,7 +129,7 @@ function onGive(mob, room, eventDetails) { // // Give them the next step of the quest // - user.GiveQuest(QUEST_NEXT_STEP_ID); + user.GetParty().GiveQuest(QUEST_NEXT_STEP_ID); return true; } @@ -170,7 +170,7 @@ function onGive(mob, room, eventDetails) { // // If they gave too much gold, lets give them back the change. // - excessGold = eventDetails.gold - REQUIRED_GOLD_AMOUNT; + var excessGold = eventDetails.gold - REQUIRED_GOLD_AMOUNT; if ( excessGold > 0 ) { mob.Command("say Here's your change."); mob.Command("give "+String(excessGold)+" gold " + user.ShorthandId()); // Give it to the player using shorthand @@ -179,7 +179,7 @@ function onGive(mob, room, eventDetails) { // // They have now completed the entire quest, all steps are complete. // - user.GiveQuest(QUEST_END_ID); + user.GetParty().GiveQuest(QUEST_END_ID); return true; } diff --git a/_datafiles/world/default/ansi-aliases.yaml b/_datafiles/world/default/ansi-aliases.yaml index e58b518e..eee715a0 100644 --- a/_datafiles/world/default/ansi-aliases.yaml +++ b/_datafiles/world/default/ansi-aliases.yaml @@ -154,6 +154,7 @@ colors: user-corpse: 143 tip-text: 219 character-joined: 120 + md-p: 8 md-h1-prefix: black-bold md-h1: magenta md-h2: yellow-bold diff --git a/_datafiles/world/default/buffs/40-tripping.js b/_datafiles/world/default/buffs/40-tripping.js new file mode 100644 index 00000000..2c467327 --- /dev/null +++ b/_datafiles/world/default/buffs/40-tripping.js @@ -0,0 +1,18 @@ + +// Invoked when the buff is first applied to the player. +function onStart(actor, triggersLeft) { + SendUserMessage(actor.UserId(), 'You notice that the world looks more vibrant and alive.'); + SendRoomMessage(actor.GetRoomId(), actor.GetCharacterName(true)+' seems to be distracted.', actor.UserId()); +} + +// Invoked every time the buff is triggered (see roundinterval) +function onTrigger(actor, triggersLeft) { + SendUserMessage(actor.UserId(), 'The colors and sounds of the world captivate you.'); + SendRoomMessage(actor.GetRoomId(), actor.GetCharacterName(true)+' stares into the distance.', actor.UserId()); +} + +// Invoked when the buff has run its course. +function onEnd(actor, triggersLeft) { + SendUserMessage(actor.UserId(), 'The world starts to look a little more normal.'); + SendRoomMessage(actor.GetRoomId(), actor.GetCharacterName(true)+' seems sober again.', actor.UserId()); +} diff --git a/_datafiles/world/default/buffs/40-tripping.yaml b/_datafiles/world/default/buffs/40-tripping.yaml new file mode 100644 index 00000000..77425d3b --- /dev/null +++ b/_datafiles/world/default/buffs/40-tripping.yaml @@ -0,0 +1,8 @@ +buffid: 40 +name: Tripping +description: You feel connected to everything. +secret: false +triggerrate: 15 rounds +triggercount: 3 +flags: + - tripping diff --git a/_datafiles/world/default/color-patterns.yaml b/_datafiles/world/default/color-patterns.yaml index 6061b4e5..2f369850 100644 --- a/_datafiles/world/default/color-patterns.yaml +++ b/_datafiles/world/default/color-patterns.yaml @@ -24,6 +24,7 @@ rainbow: [196, 214, 226, 118, 51, 21, 93] red: [52, 88, 124, 160, 196, 197, 204, 210, 217] rust: [94, 130, 172, 214] swamp: [58, 64, 64, 70, 70, 70, 36, 36, 79] +tripping: [129, 135, 141, 147, 153, 159, 165, 171, 177, 183, 189, 195] turquoise: [23, 29, 36, 42, 49, 86, 122, 158, 194] vommit: [34, 112, 202, 214, 223] zombie: [77, 77, 113, 72, 65, 78] diff --git a/_datafiles/world/default/items/consumables-30000/30016-spotted_mushroom.yaml b/_datafiles/world/default/items/consumables-30000/30016-spotted_mushroom.yaml new file mode 100644 index 00000000..f4629aee --- /dev/null +++ b/_datafiles/world/default/items/consumables-30000/30016-spotted_mushroom.yaml @@ -0,0 +1,10 @@ +itemid: 30016 +name: spotted mushroom +namesimple: mushroom +description: A small red capped mushroom with white spots. Small magenta spores occasionally fall from it. +type: food +subtype: edible +uses: 1 +value: 20 +buffids: +- 40 diff --git a/_datafiles/world/default/items/other-0/4-winterfire_crystal.yaml b/_datafiles/world/default/items/other-0/4-winterfire_crystal.yaml index 478168ef..fb5b3676 100644 --- a/_datafiles/world/default/items/other-0/4-winterfire_crystal.yaml +++ b/_datafiles/world/default/items/other-0/4-winterfire_crystal.yaml @@ -1,7 +1,7 @@ itemid: 4 name: winterfire crystal namesimple: gemstone -description: These crystal is extraordinarily rare and capable of generating a localized, gentle warmth when activated. +description: This crystal is extraordinarily rare and capable of generating a localized, gentle warmth when activated. type: object questtoken: 5-return subtype: mundane diff --git a/_datafiles/world/default/mobs/frostfang/scripts/2-guard-hungry.js b/_datafiles/world/default/mobs/frostfang/scripts/2-guard-hungry.js index eab32f0e..aed40db2 100644 --- a/_datafiles/world/default/mobs/frostfang/scripts/2-guard-hungry.js +++ b/_datafiles/world/default/mobs/frostfang/scripts/2-guard-hungry.js @@ -23,7 +23,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say I forgot my lunch today, and I'm so hungry."); mob.Command("say Do you think you could find a cheese sandwich for me?"); - user.GiveQuest("4-start"); + user.GetParty().GiveQuest("4-start"); } else if ( user.HasQuest("4-end") ) { mob.Command("sayto @" + String(user.UserId()) + " Thanks, but you've done enough. Too much, really."); @@ -70,7 +70,7 @@ function onGive(mob, room, eventDetails) { if ( user.HasQuest("4-start") ) { - user.GiveQuest("4-end"); + user.GetParty().GiveQuest("4-end"); mob.Command("say Thanks! I can get on with my day now."); mob.Command("eat !"+String(eventDetails.item.ItemId) ); @@ -137,10 +137,10 @@ function onIdle(mob, room) { if ( sizeAfter != sizeBefore ) { if ( sizeAfter == 0 ) { + mob.SetTempData('playersTold', null); + } else { mob.SetTempData('playersTold', playersTold); } - } else { - mob.SetTempData('playersTold', null); } action = round % 3; diff --git a/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-locketsadness.js b/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-locketsadness.js index fc92bcf5..bf613af0 100644 --- a/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-locketsadness.js +++ b/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-locketsadness.js @@ -30,7 +30,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("emote sighs deeply."); mob.Command("say I lost my locket. I think it was when I was gardening."); - user.GiveQuest("1-start"); + user.GetParty().GiveQuest("1-start"); return true; } @@ -78,7 +78,7 @@ function onGive(mob, room, eventDetails) { mob.Command("give !20033 @" + String(eventDetails.sourceId)); // Give it to the player using shorthand } - user.GiveQuest("1-end"); + user.GetParty().GiveQuest("1-end"); return true; diff --git a/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-rattrap.js b/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-rattrap.js index 54e12cbe..d6727f47 100644 --- a/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-rattrap.js +++ b/_datafiles/world/default/mobs/frostfang/scripts/26-frostfang_citizen-rattrap.js @@ -19,7 +19,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say Thanks for picking it up!"); - user.GiveQuest("7-gettrap"); + user.GetParty().GiveQuest("7-tradetrap"); return true; } diff --git a/_datafiles/world/default/mobs/frostfang/scripts/39-elara.js b/_datafiles/world/default/mobs/frostfang/scripts/39-elara.js index c7537891..591a08c7 100644 --- a/_datafiles/world/default/mobs/frostfang/scripts/39-elara.js +++ b/_datafiles/world/default/mobs/frostfang/scripts/39-elara.js @@ -19,7 +19,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say I took a book called The History of Frostfang out with me weeks ago and can't remember where I left it."); mob.Command("say If you can find it for me, I'll teach you a useful spell."); - user.GiveQuest("6-start"); + user.GetParty().GiveQuest("6-start"); return true; } @@ -61,18 +61,14 @@ function onGive(mob, room, eventDetails) { if ( user.HasQuest("6-start") ) { - user.GiveQuest("6-end"); + user.GetParty().GiveQuest("6-end"); mob.Command("say Thank you! It is such an interesting history. For example, Frostfang used to be called DragonsFang!"); mob.Command("say I'll teach you the Illuminate spell. It's useful in dark places."); mob.Command("emote Shows you some useful gestures."); mob.Command("say Check your spellbook."); - partyMembers = user.GetPartyMembers(); - for( i = 0; i < partyMembers.length; i++ ) { - a = partyMembers[i]; - a.LearnSpell("illum"); - } + user.GetParty().LearnSpell("illum"); return true; } diff --git a/_datafiles/world/default/mobs/frostfang/scripts/4-clergyman-sanctuary.js b/_datafiles/world/default/mobs/frostfang/scripts/4-clergyman-sanctuary.js index e7eb94a8..297b00d9 100644 --- a/_datafiles/world/default/mobs/frostfang/scripts/4-clergyman-sanctuary.js +++ b/_datafiles/world/default/mobs/frostfang/scripts/4-clergyman-sanctuary.js @@ -15,7 +15,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say I often see some priests snooping around in the alley behind the Sanctuary."); mob.Command("say I used to think they were just taking care of the rat problem, but now I'm not so sure."); - user.GiveQuest("2-catacombs"); + user.GetParty().GiveQuest("2-catacombs"); return true; } diff --git a/_datafiles/world/default/mobs/frostfang/scripts/40-rodric.js b/_datafiles/world/default/mobs/frostfang/scripts/40-rodric.js index 83e1508e..d760b677 100644 --- a/_datafiles/world/default/mobs/frostfang/scripts/40-rodric.js +++ b/_datafiles/world/default/mobs/frostfang/scripts/40-rodric.js @@ -19,7 +19,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say I'm running out of traps and don't seem to be making a dent in the rat numbers."); mob.Command("say If you can kill 25 of them, come back and see me. I'll pay you for your trouble."); - user.GiveQuest("7-start"); + user.GetParty().GiveQuest("7-start"); return true; } return false; @@ -33,7 +33,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say Thank you for killing those rats! I can finally get a little rest."); mob.Command("say While you're feeling helpful, if you could recover a rat trap from a frostfang citizen I was working for, I would be very grateful."); - user.GiveQuest("7-gettrap"); + user.GetParty().GiveQuest("7-gettrap"); return true; } @@ -104,7 +104,7 @@ function onGive(mob, room, eventDetails) { mob.Command("say Thank you so much! I can finally get back to catching some rats, and maybe earn a little coin."); mob.Command("say The thieves guild used to employ me to eliminate rats around their hideout, but for some reason they don't seem to need my help anymore, and didn't pay me for my last job I did for them."); - user.GiveQuest("7-end"); + user.GetParty().GiveQuest("7-end"); } diff --git a/_datafiles/world/default/mobs/frostfang/scripts/8-king.js b/_datafiles/world/default/mobs/frostfang/scripts/8-king.js index 9868edd1..62734e46 100644 --- a/_datafiles/world/default/mobs/frostfang/scripts/8-king.js +++ b/_datafiles/world/default/mobs/frostfang/scripts/8-king.js @@ -20,7 +20,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say My spies haven't been able to discover anything suspicious about their behavior, which is the first clue something is up."); mob.Command("say Maybe you could snoop around there a bit and see if you can discover anything. They are just to the south of Town Square."); - user.GiveQuest("2-start"); + user.GetParty().GiveQuest("2-start"); return true; } @@ -51,7 +51,7 @@ function onGive(mob, room, eventDetails) { mob.AddGold(1250); mob.Command("give 1250 gold @" + String(eventDetails.sourceId)); - user.GiveQuest("2-end"); + user.GetParty().GiveQuest("2-end"); return true; } else { @@ -74,7 +74,7 @@ function onShow(mob, room, eventDetails) { mob.Command("say Thank you for taking care of that problem. The kingdom is indebted to you."); - user.GiveQuest("2-end"); + user.GetParty().GiveQuest("2-end"); return true; diff --git a/_datafiles/world/default/mobs/whispering_wastes/scripts/27-hermit-winterfire.js b/_datafiles/world/default/mobs/whispering_wastes/scripts/27-hermit-winterfire.js index a8dcb8c2..64517a74 100644 --- a/_datafiles/world/default/mobs/whispering_wastes/scripts/27-hermit-winterfire.js +++ b/_datafiles/world/default/mobs/whispering_wastes/scripts/27-hermit-winterfire.js @@ -14,7 +14,7 @@ function onAsk(mob, room, eventDetails) { mob.Command("say I've been waiting for a shipment of winterfire crystals. They should have been here months ago."); mob.Command("say I'll never abandon my post! Can you find out what happened to my crystals?"); - user.GiveQuest("5-start"); + user.GetParty().GiveQuest("5-start"); return true; } @@ -23,7 +23,7 @@ function onAsk(mob, room, eventDetails) { if ( match.found ) { mob.Command("say The shipment was supposed to come from the far east city of Mystarion. I'm not sure what happened to it."); - user.GiveQuest("5-lookeast"); + user.GetParty().GiveQuest("5-lookeast"); return true; } @@ -47,9 +47,9 @@ function onGive(mob, room, eventDetails) { } if (eventDetails.item) { - if (eventDetails.item.ItemId != 4) { + if (eventDetails.item.ItemId == 4) { mob.Command("say Finally! My winterfire crystal! Thank you so much!"); - user.GiveQuest("5-end"); + user.GetParty().GiveQuest("5-end"); return true; } } diff --git a/_datafiles/world/default/rooms/dark_forest/565.js b/_datafiles/world/default/rooms/dark_forest/565.js index f7e58363..aa762c20 100644 --- a/_datafiles/world/default/rooms/dark_forest/565.js +++ b/_datafiles/world/default/rooms/dark_forest/565.js @@ -75,13 +75,12 @@ function onCommand(cmd, rest, user, room) { if ( climbDown ) { - partyMembers = user.GetPartyMembers(); - + partyMembers = user.GetPartyPresent().GetMembers(); for( i = 0; i < partyMembers.length; i++ ) { a = partyMembers[i]; - if ( a.UserId() == user.UserId() ) { + if ( a.UserId() == user.UserId() ) { continue; } diff --git a/_datafiles/world/default/rooms/dark_forest/568.js b/_datafiles/world/default/rooms/dark_forest/568.js index 54a915ae..41c18c38 100644 --- a/_datafiles/world/default/rooms/dark_forest/568.js +++ b/_datafiles/world/default/rooms/dark_forest/568.js @@ -74,9 +74,8 @@ function onCommand(cmd, rest, user, room) { if ( climbDown ) { - - partyMembers = user.GetPartyMembers(); - + + partyMembers = user.GetPartyPresent().GetMembers(); for( i = 0; i < partyMembers.length; i++ ) { a = partyMembers[i]; diff --git a/_datafiles/world/default/rooms/frostfang/26.js b/_datafiles/world/default/rooms/frostfang/26.js index 19f591df..9c309ec1 100644 --- a/_datafiles/world/default/rooms/frostfang/26.js +++ b/_datafiles/world/default/rooms/frostfang/26.js @@ -17,7 +17,7 @@ function onCommand(cmd, rest, user, room) { SendUserMessage(user.UserId(), "You press the eyes of the raven, and follow a secret entrance to the west!"); SendRoomMessage(room.RoomId(), user.GetCharacterName(true)+" presses in the eyes of the raven, and falls through into a room to the west!", user.UserId()); - user.GiveQuest("2-investigate"); + user.GetParty().GiveQuest("2-investigate"); user.MoveRoom(31); return true; diff --git a/_datafiles/world/default/rooms/frostfang/276.js b/_datafiles/world/default/rooms/frostfang/276.js index 41f37e75..3e2055b5 100644 --- a/_datafiles/world/default/rooms/frostfang/276.js +++ b/_datafiles/world/default/rooms/frostfang/276.js @@ -57,7 +57,7 @@ function onCommand(cmd, rest, user, room) { SendRoomMessage(room.RoomId(), user.GetCharacterName(true)+" takes a golden locket from the pile of leaves.", user.UserId()); user.GiveItem(20025); - user.GiveQuest("1-return"); + user.GetParty().GiveQuest("1-return"); locketAvailableRound = roundNow + UtilGetMinutesToRounds(15); diff --git a/_datafiles/world/default/rooms/frostfang/35.js b/_datafiles/world/default/rooms/frostfang/35.js index 10ca4bb4..21ae873d 100644 --- a/_datafiles/world/default/rooms/frostfang/35.js +++ b/_datafiles/world/default/rooms/frostfang/35.js @@ -2,6 +2,12 @@ const magic_phrase = "zyphrial lumara vorthos"; +// EventFlags constants +const EventFlags = { + CmdSkipScripts: 1, + CmdBlockInputUntilComplete: 2 +}; + function onCommand_west(rest, user, room) { if ( !user.HasQuest("3-end") ) { @@ -49,7 +55,7 @@ function onCommand_say(rest, user, room) { return true; } - user.GiveQuest("3-end"); + user.GetParty().GiveQuest("3-end"); user.GiveBuff(3, "enchantment"); diff --git a/_datafiles/world/default/rooms/frostfang_slums/1004.js b/_datafiles/world/default/rooms/frostfang_slums/1004.js new file mode 100644 index 00000000..ddf3f66e --- /dev/null +++ b/_datafiles/world/default/rooms/frostfang_slums/1004.js @@ -0,0 +1,7 @@ + +function onEnter(user, room) { + + + + return true; +} diff --git a/_datafiles/world/default/rooms/frostfang_slums/1004.yaml b/_datafiles/world/default/rooms/frostfang_slums/1004.yaml new file mode 100755 index 00000000..9a667bea --- /dev/null +++ b/_datafiles/world/default/rooms/frostfang_slums/1004.yaml @@ -0,0 +1,15 @@ +roomid: 1004 +zone: Frostfang Slums +title: Poorly Lit Street +description: 'Tucked away in the heart of Frostfang''s sprawling slums, a dimly lit + alleyway meanders from the bustling Beggars Lane. This concealed corner, a world + apart from the temple''s tranquility, boasts ramshackle shanties crafted from discarded + wood, rusted metal sheets, and tattered fabric. Makeshift tents of mismatched fabrics + and fraying ropes dot the gaps between these structures. The uneven ground is littered + with remnants of daily life: discarded meal bones, worn-out shoes, and glimmers + from shattered glass. An ornate door stands out here, clearly well cared for.' +biome: city +exits: + out: + roomid: 488 + mapdirection: northeast diff --git a/_datafiles/world/default/rooms/frostfang_slums/488.yaml b/_datafiles/world/default/rooms/frostfang_slums/488.yaml index 043e2da2..31be1068 100755 --- a/_datafiles/world/default/rooms/frostfang_slums/488.yaml +++ b/_datafiles/world/default/rooms/frostfang_slums/488.yaml @@ -7,10 +7,17 @@ description: 'Tucked away in the heart of Frostfang''s sprawling slums, a dimly wood, rusted metal sheets, and tattered fabric. Makeshift tents of mismatched fabrics and fraying ropes dot the gaps between these structures. The uneven ground is littered with remnants of daily life: discarded meal bones, worn-out shoes, and glimmers - from shattered glass. Muffled whispers and subtle movements hint at the precarious - lives within, hidden deep in the slums, yet a stone''s throw from a place of refuge.' + from shattered glass. An ornate door stands out here, clearly well cared for.' biome: city exits: + door: + roomid: 1004 + mapdirection: southwest + exitmessage: You get the feeling you shouldn't be here. + lock: + difficulty: 4 + relockinterval: 15 minutes + trapbuffids: [13] east: roomid: 489 north: diff --git a/_datafiles/world/default/spells/sparks.js b/_datafiles/world/default/spells/sparks.js index 188510a0..d31f44b3 100644 --- a/_datafiles/world/default/spells/sparks.js +++ b/_datafiles/world/default/spells/sparks.js @@ -42,12 +42,12 @@ function onMagic(sourceActor, targetActors) { SendRoomMessage(roomId, sourceName+' stops chanting and lets loose a shower of sparks, hitting '+targetName+'.', sourceUserId, targetUserId); // Tell the target about the dmg - SendUserMessage(targetUserId, sourceName+' stops chanting fires a shower of sparks at you, hitting for '+dmgAmtStr+' damage.'); + SendUserMessage(targetUserId, sourceName+' stops chanting and fires a shower of sparks at you, hitting for '+dmgAmtStr+' damage.'); } else { // Tell the cast they did it to themselves - SendUserMessage(sourceUserId, 'You stop chanting and fires a shower of sparks at yourself, doing '+dmgAmtStr+' damage.'); + SendUserMessage(sourceUserId, 'You stop chanting and fire a shower of sparks at yourself, doing '+dmgAmtStr+' damage.'); // Tell the room about the dmg, except the source and target SendRoomMessage(roomId, sourceName+' stops chanting and fires a shower of sparks at themselves, hurting themselves.', sourceUserId, targetUserId); diff --git a/_datafiles/world/default/spells/tameskill.js b/_datafiles/world/default/spells/tameskill.js index 3218ece6..18d89bcb 100644 --- a/_datafiles/world/default/spells/tameskill.js +++ b/_datafiles/world/default/spells/tameskill.js @@ -91,7 +91,7 @@ function onWait(sourceActor, targetActor) { break; default: SendUserMessage(sourceActor.UserId(), 'You whistle several times, changing your pitch ever so slightly.'); - SendRoomMessage(sourceActor.GetRoomId(), ``+sourceActor.GetCharacterName(true)+' whistles several times, changing your pitch ever so slightly.', sourceActor.UserId()); + SendRoomMessage(sourceActor.GetRoomId(), ``+sourceActor.GetCharacterName(true)+' whistles several times, changing their pitch ever so slightly.', sourceActor.UserId()); } } diff --git a/_datafiles/world/default/templates/help/alias.md b/_datafiles/world/default/templates/help/alias.md new file mode 100644 index 00000000..860e7a56 --- /dev/null +++ b/_datafiles/world/default/templates/help/alias.md @@ -0,0 +1,11 @@ +# Help for ~alias~ + +The ~alias~ command lists and sets aliases. + +## Usage: + + ~alias~ - List all aliases, including system defaults + + ~alias [name]=[value]~ - Create a custom alias. Left of the '=' is the command, right of the '=' is the replacement. + + ~alias [name]=~ - Clear an alias (value of [name]) \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/alias.template b/_datafiles/world/default/templates/help/alias.template deleted file mode 100644 index ea42c8ec..00000000 --- a/_datafiles/world/default/templates/help/alias.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for alias - -The alias command lists and sets aliases - -Usage: - - alias - List all aliases, including system defaults - - alias [name]=[value] - Create a custom alias. Left of the '=' is the command, right of the '=' is the replacement. - - alias [name]= - Clear an alias (value of [name]) diff --git a/_datafiles/world/default/templates/help/appraise.md b/_datafiles/world/default/templates/help/appraise.md new file mode 100644 index 00000000..e7483072 --- /dev/null +++ b/_datafiles/world/default/templates/help/appraise.md @@ -0,0 +1,8 @@ +# Help for ~appraise~ + +The ~appraise~ command will pay a merchant a fee to get basic information on an item. + +## Usage: + + ~appraise sword~ + This would be equivalent to using the ~inspect~ skill. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/appraise.template b/_datafiles/world/default/templates/help/appraise.template deleted file mode 100644 index c73e1d87..00000000 --- a/_datafiles/world/default/templates/help/appraise.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for appraise - -The appraise command will pay a merchant a fee to get basic information on an item. - -Usage: - - appraise sword - This would be equivalent to using the inspect skill. - diff --git a/_datafiles/world/default/templates/help/ask.md b/_datafiles/world/default/templates/help/ask.md new file mode 100644 index 00000000..64577c39 --- /dev/null +++ b/_datafiles/world/default/templates/help/ask.md @@ -0,0 +1,9 @@ +# Help for ~ask~ + +The ~ask~ command asks mobs/NPC's questions. This is useful for getting information about quests, or when you have a hired mercenary, to give them commands. + +## Usage: + + ~ask quest~ + ~ask Why are you sad?~ + ~ask buddy to drop sword~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/ask.template b/_datafiles/world/default/templates/help/ask.template deleted file mode 100644 index b673f841..00000000 --- a/_datafiles/world/default/templates/help/ask.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for ask - -The ask command asks mobs/NPC's questions. This is useful -for getting information about quests, or when you have a hired mercenary, to give them commands. - -Usage: - - ask quest - ask Why are you sad? - ask buddy to drop sword - diff --git a/_datafiles/world/default/templates/help/attack.template b/_datafiles/world/default/templates/help/attack.template deleted file mode 100644 index a96a7e8b..00000000 --- a/_datafiles/world/default/templates/help/attack.template +++ /dev/null @@ -1,15 +0,0 @@ -.: Help for attack - -The attack command engages in combat with a player or NPC. Once started combat continues -until someone flees or someone dies. - -Usage: - - attack goblin - This would start combat with the goblin - -When in combat your chance to hit is: attackersSpeed / (atackerSpeed+defenderSpeed) * 70 + 30 -You always have a minimum 5% chance to miss and a minimum 5% chance to hit - -Crits Chance is calculated as follows: (Strength+Speed) / (attackerLevel-defenderLevel) + 5 - diff --git a/_datafiles/world/default/templates/help/bank.md b/_datafiles/world/default/templates/help/bank.md new file mode 100644 index 00000000..8d7dd2e1 --- /dev/null +++ b/_datafiles/world/default/templates/help/bank.md @@ -0,0 +1,11 @@ +# Help for ~bank~ + +The ~bank~ command lets you deposit and withdraw from a bank. + +## Usage: + + ~bank~ - See your gold on hand and in the bank + + ~deposit [amount/all]~ - Deposit an amount of gold (or all) into the bank + + ~withdraw [amount/all]~ - Withdraw an amount of gold (or all) from the bank \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/bank.template b/_datafiles/world/default/templates/help/bank.template deleted file mode 100644 index 17d6125c..00000000 --- a/_datafiles/world/default/templates/help/bank.template +++ /dev/null @@ -1,12 +0,0 @@ -.: Help for bank - -The bank command lets you deposit and withdraw from a bank. - -Usage: - - bank - See your gold on hand and in the bank - - deposit [amount/all] - Deposit an amount of gold (or all) into the bank - - withdraw [amount/all] - Withdraw an amount of gold (or all) from the bank - diff --git a/_datafiles/world/default/templates/help/biome.md b/_datafiles/world/default/templates/help/biome.md new file mode 100644 index 00000000..7d41d231 --- /dev/null +++ b/_datafiles/world/default/templates/help/biome.md @@ -0,0 +1,9 @@ +# Help for ~biome~ + +The ~biome~ tells you a little bit about the biome you are located in. + +Different biomes have risks or benefits associated with them. + +## Usage: + + ~biome~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/biome.template b/_datafiles/world/default/templates/help/biome.template deleted file mode 100644 index 83995b51..00000000 --- a/_datafiles/world/default/templates/help/biome.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for biome - -The biome tells you a little bit about the biome you are located in. - -Different biomes have risks or benefits associated with them. - -Usage: - - biome diff --git a/_datafiles/world/default/templates/help/break.md b/_datafiles/world/default/templates/help/break.md new file mode 100644 index 00000000..137dde74 --- /dev/null +++ b/_datafiles/world/default/templates/help/break.md @@ -0,0 +1,9 @@ +# Help for ~break~ + +The ~break~ command disengages your part of combat. +**Note:** Enemies may still attack you! + +## Usage: + + ~break~ + This would allow you to move around again. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/break.template b/_datafiles/world/default/templates/help/break.template deleted file mode 100644 index 8f98128f..00000000 --- a/_datafiles/world/default/templates/help/break.template +++ /dev/null @@ -1,10 +0,0 @@ -.: Help for break - -The break command disengages your part of combat. -Note: Enemies may still attack you! - -Usage: - - break - This would allow you to move around again. - diff --git a/_datafiles/world/default/templates/help/broadcast.md b/_datafiles/world/default/templates/help/broadcast.md new file mode 100644 index 00000000..320ada02 --- /dev/null +++ b/_datafiles/world/default/templates/help/broadcast.md @@ -0,0 +1,15 @@ +# Help for ~broadcast~ + +The ~broadcast~ command sends a message to everyone connected. + +You can also use ~`~ and ~'~ as a shortcut. + +## Usage: + + ~broadcast hi everyone~ + ~` hi everyone~ + ~' hi everyone~ + + Output to everyone: + + (broadcast) Charles: hi everyone \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/broadcast.template b/_datafiles/world/default/templates/help/broadcast.template deleted file mode 100644 index ad4e0301..00000000 --- a/_datafiles/world/default/templates/help/broadcast.template +++ /dev/null @@ -1,16 +0,0 @@ -.: Help for broadcast - -The broadcast command sends a message to everyone connected. - -You can also use ` and ' as a shortcut. - -Usage: - - broadcast hi everyone - ` hi everyone - ' hi everyone - - Output to everyone: - - (broadcast) Charles: hi everyone - diff --git a/_datafiles/world/default/templates/help/buy.md b/_datafiles/world/default/templates/help/buy.md new file mode 100644 index 00000000..42268367 --- /dev/null +++ b/_datafiles/world/default/templates/help/buy.md @@ -0,0 +1,10 @@ +# Help for ~buy~ + +The ~buy~ command buys an item for sale at a merchant. + +## Usage: + + ~buy sword~ + This would a sword, if you have the gold and the merchant carries the object. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/buy.template b/_datafiles/world/default/templates/help/buy.template deleted file mode 100644 index 632ac263..00000000 --- a/_datafiles/world/default/templates/help/buy.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for buy - -The buy command buys an item for sale at a merchant. - -Usage: - - buy sword - This would a sword, if you have the gold and the merchant carries the object. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/cast.md b/_datafiles/world/default/templates/help/cast.md new file mode 100644 index 00000000..6f87b833 --- /dev/null +++ b/_datafiles/world/default/templates/help/cast.md @@ -0,0 +1,12 @@ +# Help for ~cast~ + +The ~cast~ command attempts to cast a learned spell. + +## Usage: + + ~cast illum~ + This would attempt to cast the "Illuminate" spell, if it's in your spell book. + + Spells can also be cast by using their shorthand/ID directly, such as: ~illum~ + +**See also:** ~help spells~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/cast.template b/_datafiles/world/default/templates/help/cast.template deleted file mode 100644 index 4b0cb96b..00000000 --- a/_datafiles/world/default/templates/help/cast.template +++ /dev/null @@ -1,13 +0,0 @@ -.: Help for cast - -The cast command attempts to cast a learned spell. - -Usage: - - cast illum - This would attempt to cast the "Illuminate" spell, if it's in your spell book. - - Spells can also be cast by using their shorthand/ID directly, such as: illum - -See also: help spells - diff --git a/_datafiles/world/default/templates/help/character.md b/_datafiles/world/default/templates/help/character.md new file mode 100644 index 00000000..04630e31 --- /dev/null +++ b/_datafiles/world/default/templates/help/character.md @@ -0,0 +1,9 @@ +# Help for ~character~ + +The ~character~ command can only be used in special rooms that indicate it is supported. + +When used, you can re-create your current character, create an alt character (if enabled), or switch between alt characters. + +## Usage: + + ~character~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/character.template b/_datafiles/world/default/templates/help/character.template deleted file mode 100644 index 7146151a..00000000 --- a/_datafiles/world/default/templates/help/character.template +++ /dev/null @@ -1,7 +0,0 @@ -.: Help for character - -The character command can only be used in special rooms that indicate it is -supported. - -When used, you can re-create your current character, create an alt character (if enabled), or switch -between alt characters. diff --git a/_datafiles/world/default/templates/help/consider.md b/_datafiles/world/default/templates/help/consider.md new file mode 100644 index 00000000..f55e4538 --- /dev/null +++ b/_datafiles/world/default/templates/help/consider.md @@ -0,0 +1,8 @@ +# Help for ~consider~ + +The ~consider~ command tries to determine if an enemy is a good match. + +## Usage: + + ~consider goblin~ + You will receive a range of results, from YOU WILL DIE! to Very Favorable. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/consider.template b/_datafiles/world/default/templates/help/consider.template deleted file mode 100644 index 313132aa..00000000 --- a/_datafiles/world/default/templates/help/consider.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for consider - -The consider command tries to determine if an enemy is a good match. - -Usage: - - consider goblin - You will receive a range of results, from YOU WILL DIE! to Very Favorable. - diff --git a/_datafiles/world/default/templates/help/cooldowns.md b/_datafiles/world/default/templates/help/cooldowns.md new file mode 100644 index 00000000..553233ea --- /dev/null +++ b/_datafiles/world/default/templates/help/cooldowns.md @@ -0,0 +1,7 @@ +# Help for ~cooldowns~ + +The ~cooldowns~ command is currently a debugging tool available to all players. + +## Usage: + + ~cooldowns~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/cooldowns.template b/_datafiles/world/default/templates/help/cooldowns.template deleted file mode 100644 index f67454d3..00000000 --- a/_datafiles/world/default/templates/help/cooldowns.template +++ /dev/null @@ -1,3 +0,0 @@ - -This is currently a debugging tool available to all players. - diff --git a/_datafiles/world/default/templates/help/drink.md b/_datafiles/world/default/templates/help/drink.md new file mode 100644 index 00000000..84bde132 --- /dev/null +++ b/_datafiles/world/default/templates/help/drink.md @@ -0,0 +1,10 @@ +# Help for ~drink~ + +The ~drink~ command drinks an item you carry (if it is drinkable). + +## Usage: + + ~drink potion~ + This would drink your potion. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/drink.template b/_datafiles/world/default/templates/help/drink.template deleted file mode 100644 index 9755d85b..00000000 --- a/_datafiles/world/default/templates/help/drink.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for drink - -The drink command drinks an item you carry (if it is drinkable). - -Usage: - - drink potion - This would drink your potion. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/drop.md b/_datafiles/world/default/templates/help/drop.md new file mode 100644 index 00000000..9206f6db --- /dev/null +++ b/_datafiles/world/default/templates/help/drop.md @@ -0,0 +1,10 @@ +# Help for ~drop~ + +The ~drop~ command drops an item you carry onto the ground. + +## Usage: + + ~drop stick~ + This would drop a stick if you had it in your backpack. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/drop.template b/_datafiles/world/default/templates/help/drop.template deleted file mode 100644 index 45281350..00000000 --- a/_datafiles/world/default/templates/help/drop.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for drop - -The drop command drops an item you carry onto the ground. - -Usage: - - drop stick - This would drop a stick if you had it in your backpack. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/dual-wield.md b/_datafiles/world/default/templates/help/dual-wield.md new file mode 100644 index 00000000..e3a238e2 --- /dev/null +++ b/_datafiles/world/default/templates/help/dual-wield.md @@ -0,0 +1,13 @@ +# Help for ~dual-wield~ (skill) + +The ~dual-wield~ skill lets you dual wield weapons that usually wouldn't allow it. + +At levels 1-3, you incur a **35%** chance-to-hit penalty. +At level 4, you incur a **25%** chance-to-hit penalty. + +## Usage: + +(Lvl 1) You can dual wield weapons that you normally couldn't. Attacks use a random weapon. +(Lvl 2) Occasionally you will attack with both weapons in one round. +(Lvl 3) You will always attack with both weapons when Dual wielding. +(Lvl 4) Dual wielding incurs fewer penalties \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/dual-wield.template b/_datafiles/world/default/templates/help/dual-wield.template deleted file mode 100644 index 2b667ef2..00000000 --- a/_datafiles/world/default/templates/help/dual-wield.template +++ /dev/null @@ -1,15 +0,0 @@ -.: Help for dual-wield (skill) - -The dual-wield skill lets you dual wield weapons that usually wouldn't allow it. - -At levels 1-3, you incur a 35% chance-to-hit penalty. -At level 4, you incur a 25% chance-to-hit penalty. - -Usage: - -(Lvl 1) You can dual wield weapons that you normally couldn't. Attacks use a - random weapon. -(Lvl 2) Occasionally you will attack with both weapons in one round. -(Lvl 3) You will always attack with both weapons when Dual wielding. -(Lvl 4) Dual wielding incurs fewer penalties - diff --git a/_datafiles/world/default/templates/help/eat.md b/_datafiles/world/default/templates/help/eat.md new file mode 100644 index 00000000..1a1bec34 --- /dev/null +++ b/_datafiles/world/default/templates/help/eat.md @@ -0,0 +1,10 @@ +# Help for ~eat~ + +The ~eat~ command eats an item you carry (if it is edible). + +## Usage: + + ~eat sandwich~ + This would eat your sandwich. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/eat.template b/_datafiles/world/default/templates/help/eat.template deleted file mode 100644 index 261495ed..00000000 --- a/_datafiles/world/default/templates/help/eat.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for eat - -The eat command eats an item you carry (if it is edible). - -Usage: - - eat sandwich - This would drink your sandwich. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/emote.md b/_datafiles/world/default/templates/help/emote.md new file mode 100644 index 00000000..b395dacf --- /dev/null +++ b/_datafiles/world/default/templates/help/emote.md @@ -0,0 +1,16 @@ +# Help for ~emote~ + +The ~emote~ command is a simple role playing command that lets you customize an action or reaction to the room. + +Example: + + [HP:10/10 MP:10/10]: emote scratches his head. + **Chuckles** *scratches his head.* + +What others see: + + [HP:6/6 MP:8/8]: **Chuckles** *scratches his head.* + +Here are some shortcut emotes that can be invoked with a single word: + +{{ $counter := 0 -}}{{ range $command, $output := . }} ~{{ padRight 8 $command }}~ {{ if eq (mod $counter 6) 5 }}{{ printf "\n" }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/emote.template b/_datafiles/world/default/templates/help/emote.template deleted file mode 100644 index e77f9a9e..00000000 --- a/_datafiles/world/default/templates/help/emote.template +++ /dev/null @@ -1,18 +0,0 @@ -.: Help for emote - -The emote command is a simple role playing command that lets you customize an -action or reaction to the room. - -Example: - - [HP:10/10 MP:10/10]: emote scratches his head. - Chuckles scratches his head. - -What others see: - - [HP:6/6 MP:8/8]: Chuckles scratches his head. - -Here are some shortcut emotes that can be invoked with a single word: - -{{ $counter := 0 -}}{{ range $command, $output := . }} {{ padRight 8 $command }} {{ if eq (mod $counter 6) 5 }}{{ printf "\n" }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} - diff --git a/_datafiles/world/default/templates/help/enchant.md b/_datafiles/world/default/templates/help/enchant.md new file mode 100644 index 00000000..bbd26fbd --- /dev/null +++ b/_datafiles/world/default/templates/help/enchant.md @@ -0,0 +1,26 @@ +# Help for ~enchant~ (skill) + +The ~enchant~ skill embues objects with enhanced properties. + +As you level up the ~enchant~ skill, it can apply a great enchantment. +Your odds of success (and degree of succes) are influence by the Mysticism stat. + +**Beware**, no item can be enchanted more than once! + +## Usage: + +(Lvl 1) ~enchant [item]~ Enchant a weapon with a damage bonus. +(Lvl 2) ~enchant [item]~ Enchant equipment with a defensive bonus. +(Lvl 3) ~enchant [item]~ Add a stat bonus to a weapon or equipment in addition to the above. +(Lvl 4) ~unenchant/uncurse [item]~ Remove the enchantment or curse from any object. + +Check the odds of it exploding before you enchant it with: ~enchant chance [item]~ + +Enchant bonuses are calculated as follows: + - Damage Bonus - **SquareRoot( Mysticism )** + - Defense Bonus - **SqareRoot( Mysticism )** + - Random Status Bonus - **SqareRoot( Mysticism )** + - You get 2 random stat bonus at SkillLevel 3, and another at SkillLevel 4 + + Enchanted items have a **25%** chance of becoming cursed. + Items that are enchanted have a **50 - (SkillLevel*10) + (NumberOfEnchantments*20) - (Mysticism/4)%** Chance to be destroyed \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/enchant.template b/_datafiles/world/default/templates/help/enchant.template deleted file mode 100644 index cc50f3f1..00000000 --- a/_datafiles/world/default/templates/help/enchant.template +++ /dev/null @@ -1,26 +0,0 @@ -.: Help for enchant (skill) - -The enchant skill embues objects with enhanced properties. - -As you level up the enchant skill, it can apply a great enchantment. -Your odds of success (and degree of succes) are influence by the Mysticism stat. - -Beware, no item can be enchanted more than once! - -Usage: - -(Lvl 1) enchant [item] Enchant a weapon with a damage bonus. -(Lvl 2) enchant [item] Enchant equipment with a defensive bonus. -(Lvl 3) enchant [item] Add a stat bonus to a weapon or equipment in addition to the above. -(Lvl 4) unenchant/uncurse [item] Remove the enchantment or curse from any object. - -Check the odds of it exploding before you enchant it with: enchant chance [item] - -Enchant bonuses are calculated as follows: - - Damage Bonus - SquareRoot( Mysticism ) - - Defense Bonus - SqareRoot( Mysticism ) - - Random Status Bonus - SqareRoot( Mysticism ) - - You get 2 random stat bonus at SkillLevel 3, and another at SkillLevel 4 - - Enchanted items have a 25% chance of becoming cursed. - Items that are enchanted have a 50 - (SkillLevel*10) + (NumberOfEnchantments*20) - (Mysticism/4)% Chance to be destroyed diff --git a/_datafiles/world/default/templates/help/equip.md b/_datafiles/world/default/templates/help/equip.md new file mode 100644 index 00000000..3dedd520 --- /dev/null +++ b/_datafiles/world/default/templates/help/equip.md @@ -0,0 +1,14 @@ +# Help for ~equip~ + +The ~equip~ command wields or wears an item from your backpack. + +## Usage: + + ~equip stick~ + This would wield a stick from your backpack. + ~equip cloak~ + This would wear a cloak from your backpack. + +Aliases: ~wield~, ~wear~ + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/equip.template b/_datafiles/world/default/templates/help/equip.template deleted file mode 100644 index 617c5adb..00000000 --- a/_datafiles/world/default/templates/help/equip.template +++ /dev/null @@ -1,15 +0,0 @@ -.: Help for equip - -The equip command wields or wears an item from your backpack. - -Usage: - - equip stick - This would wield a stick from your backpack. - equip cloak - This would wear a cloak from your backpack. - -Aliases: wield, wear - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/exits.md b/_datafiles/world/default/templates/help/exits.md new file mode 100644 index 00000000..f2e3120d --- /dev/null +++ b/_datafiles/world/default/templates/help/exits.md @@ -0,0 +1,7 @@ +# Help for ~exits~ + +The ~exits~ command tells what known exits are in the room. + +## Usage: + + ~exits~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/exits.template b/_datafiles/world/default/templates/help/exits.template deleted file mode 100644 index 3aef5926..00000000 --- a/_datafiles/world/default/templates/help/exits.template +++ /dev/null @@ -1,4 +0,0 @@ -.: Help for exits - -The exits command tells what known exits are in the room. - diff --git a/_datafiles/world/default/templates/help/experience.md b/_datafiles/world/default/templates/help/experience.md new file mode 100644 index 00000000..9e8ec66a --- /dev/null +++ b/_datafiles/world/default/templates/help/experience.md @@ -0,0 +1,13 @@ +# Help for ~experience~ + +The ~experience~ command gives you your current level, current experience points, what you need to reach for your next level, and how many unspent training points you have. + +## Usage: + + ~experience~ - See a summary of your level information + +## Extra Usage: + + ~experience chart [max_level]~ - See the level chart for your race + ~experience chart [race]~ - See the level chart for any other race race + ~experience chart [race] [max_level]~ - See the level chart for any other race race \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/experience.template b/_datafiles/world/default/templates/help/experience.template deleted file mode 100644 index 18932d33..00000000 --- a/_datafiles/world/default/templates/help/experience.template +++ /dev/null @@ -1,16 +0,0 @@ -.: Help for experience - -The experience command gives you your current level, current experience points, -what you need to reach for your next level, and how many unspent training -points you have. - -Usage: - - experience - See a summary of your level information - -Extra Usage: - - experience chart [max_level] - See the level chart for your race - experience chart [race] - See the level chart for any other race race - experience chart [race] [max_level] - See the level chart for any other race race - diff --git a/_datafiles/world/default/templates/help/flee.md b/_datafiles/world/default/templates/help/flee.md new file mode 100644 index 00000000..0e301742 --- /dev/null +++ b/_datafiles/world/default/templates/help/flee.md @@ -0,0 +1,11 @@ +# Help for ~flee~ + +The ~flee~ command attempts to run away from combat into another area. + +If successful, foes will not chase you. You must escape every foe attacking you, however. + +The chance of success is **30 + (fleeSpeed / (fleeSpeed+attackerSpeed) * 70)** + +## Usage: + + ~flee~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/flee.template b/_datafiles/world/default/templates/help/flee.template deleted file mode 100644 index 36a66ce7..00000000 --- a/_datafiles/world/default/templates/help/flee.template +++ /dev/null @@ -1,7 +0,0 @@ -.: Help for flee - -The flee command attempts to run away from combat into another area. - -If successful, foes will not chase you. You must escape every foe attacking you, however. - -The chance of success is 30 + (fleeSpeed / (fleeSpeed+attackerSpeed) * 70) diff --git a/_datafiles/world/default/templates/help/get.md b/_datafiles/world/default/templates/help/get.md new file mode 100644 index 00000000..41f49b4a --- /dev/null +++ b/_datafiles/world/default/templates/help/get.md @@ -0,0 +1,12 @@ +# Help for ~get~ + +The ~get~ command picks up an item on the ground and puts it in your backpack. + +## Usage: + + ~get stick~ + This would get a stick from the ground and put it in your backpack. + ~get stick from stash~ + This would get a stick stashed in the area and put it in your backpack. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/get.template b/_datafiles/world/default/templates/help/get.template deleted file mode 100644 index c13b493b..00000000 --- a/_datafiles/world/default/templates/help/get.template +++ /dev/null @@ -1,13 +0,0 @@ -.: Help for get - -The get command picks up an item on the ground and puts it in your backpack. - -Usage: - - get stick - This would get a stick from the ground and put it in your backpack. - get stick from stash - This would get a stick stashed in the area and put it in your backpack. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/give.md b/_datafiles/world/default/templates/help/give.md new file mode 100644 index 00000000..ca508df8 --- /dev/null +++ b/_datafiles/world/default/templates/help/give.md @@ -0,0 +1,11 @@ +# Help for ~give~ + +The ~give~ command gives an object to another player or mob. + +## Usage: + + ~give sword sam~ + This gives your sword to sam. + + ~give 30 gold sam~ + This gives 30 gold to sam. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/give.template b/_datafiles/world/default/templates/help/give.template deleted file mode 100644 index 7b8e8844..00000000 --- a/_datafiles/world/default/templates/help/give.template +++ /dev/null @@ -1,12 +0,0 @@ -.: Help for give - -The look command gives an object to another player or mob. - -Usage: - - give sword sam - This gives your sword to sam. - - give 30 gold sam - This gives 30 gold to sam. - diff --git a/_datafiles/world/default/templates/help/go.md b/_datafiles/world/default/templates/help/go.md new file mode 100644 index 00000000..fd145436 --- /dev/null +++ b/_datafiles/world/default/templates/help/go.md @@ -0,0 +1,10 @@ +# Help for ~go~ + +The ~go~ command is used to travel from area to area. + +Typing ~go~ is unnecessary though, you can just type the exit name. + +## Usage: + + ~go north~ + This is identical to typing ~north~ by itself to exit the room. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/go.template b/_datafiles/world/default/templates/help/go.template deleted file mode 100644 index 7c4aaeef..00000000 --- a/_datafiles/world/default/templates/help/go.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for go - -The go command is used to travel from are to area. - -Typing go is unnecessary though, you can just type the exit name. - -Usage: - - go north - This is identical to typing north by itself to exit the room. - diff --git a/_datafiles/world/default/templates/help/help.md b/_datafiles/world/default/templates/help/help.md new file mode 100644 index 00000000..03f8a739 --- /dev/null +++ b/_datafiles/world/default/templates/help/help.md @@ -0,0 +1,35 @@ +# Help for ~help~ + +The ~help~ command looks up guidance on a command. + +## Usage: + + ~help say~ + Find help on the command ~say~. + +Here are some *skills* and *commands* to look up to get started: +{{/* padRight 80 "" "-" */}} +{{ if gt (len .Commands) 0 -}} +Commands: +{{ range $category, $commandList := .Commands -}} +**{{ uc $category }}** +{{ $counter := 0 }} {{ range $i, $cmdInfo := $commandList }}~{{ if $cmdInfo.Missing }}***{{ else }} {{ end }}{{ padRight 17 $cmdInfo.Command " " }}~{{ if eq (mod $counter 4) 3 }}{{ if ne $i (sub (len $commandList) 1) }}{{ printf "\n " }}{{ end }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} +{{ end }} +{{ end }} + +{{- if gt (len .Skills) 0 -}} +Skills: +{{- range $category, $commandList := .Skills -}} +**{{ uc $category }}** +{{ $counter := 0 }} {{ range $i, $cmdInfo := $commandList }}~{{ if $cmdInfo.Missing }}***{{ else }} {{ end }}{{ padRight 17 $cmdInfo.Command " " }}~{{ if eq (mod $counter 4) 3 }}{{ if ne $i (sub (len $commandList) 1) }}{{ printf "\n " }}{{ end }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} +{{ end }} +{{ end }} + +{{- if gt (len .Admin) 0 -}} +Admin: +{{- range $category, $commandList := .Admin -}} +**{{ uc $category }}** +{{ $counter := 0 }} {{ range $i, $cmdInfo := $commandList }}~{{ if $cmdInfo.Missing }}***{{ else }} {{ end }}{{ padRight 17 $cmdInfo.Command " " }}~{{ if eq (mod $counter 4) 3 }}{{ if ne $i (sub (len $commandList) 1) }}{{ printf "\n " }}{{ end }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} +{{ end }}{{ end }} + +**See also:** ~help gomud~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/help.template b/_datafiles/world/default/templates/help/help.template deleted file mode 100644 index d99f6000..00000000 --- a/_datafiles/world/default/templates/help/help.template +++ /dev/null @@ -1,35 +0,0 @@ -.: Help for help - -The help command looks up guidance on a command. - -Usage: - - help say - Find help on the command say. - -Here are some skills and commands to look up to get started: -{{/* padRight 80 "" "-" */}} -{{ if gt (len .Commands) 0 -}} -Commands: -{{ range $category, $commandList := .Commands -}} - {{ uc $category }} -{{ $counter := 0 }} {{ range $i, $cmdInfo := $commandList }}{{ if $cmdInfo.Missing }}*{{ else }} {{ end }}{{ padRight 17 $cmdInfo.Command " " }} {{ if eq (mod $counter 4) 3 }}{{ if ne $i (sub (len $commandList) 1) }}{{ printf "\n " }}{{ end }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} -{{ end }} -{{ end }} - -{{- if gt (len .Skills) 0 -}} -Skills: -{{- range $category, $commandList := .Skills -}} - {{ uc $category }} -{{ $counter := 0 }} {{ range $i, $cmdInfo := $commandList }}{{ if $cmdInfo.Missing }}*{{ else }} {{ end }}{{ padRight 17 $cmdInfo.Command " " }} {{ if eq (mod $counter 4) 3 }}{{ if ne $i (sub (len $commandList) 1) }}{{ printf "\n " }}{{ end }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} -{{ end }} -{{ end }} - -{{- if gt (len .Admin) 0 -}} -Admin: -{{- range $category, $commandList := .Admin -}} - {{ uc $category }} -{{ $counter := 0 }} {{ range $i, $cmdInfo := $commandList }}{{ if $cmdInfo.Missing }}*{{ else }} {{ end }}{{ padRight 17 $cmdInfo.Command " " }} {{ if eq (mod $counter 4) 3 }}{{ if ne $i (sub (len $commandList) 1) }}{{ printf "\n " }}{{ end }}{{ end }}{{ $counter = (add $counter 1) }}{{ end }} -{{ end }}{{ end }} - -See also: help gomud diff --git a/_datafiles/world/default/templates/help/hire.md b/_datafiles/world/default/templates/help/hire.md new file mode 100644 index 00000000..05a11b01 --- /dev/null +++ b/_datafiles/world/default/templates/help/hire.md @@ -0,0 +1,8 @@ +# Help for ~hire~ + +The ~hire~ command hires mercenaries offered by merchants. + +## Usage: + + ~hire guard~ + This hires the guard, if you have the gold and the merchant offers a guard. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/hire.template b/_datafiles/world/default/templates/help/hire.template deleted file mode 100644 index fab712d9..00000000 --- a/_datafiles/world/default/templates/help/hire.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for hire - -The hire command hires mercenaries offered by merchants. - -Usage: - - hire guard - This hires the guard, if you have the gold and the merchant offers a guard. - diff --git a/_datafiles/world/default/templates/help/history.md b/_datafiles/world/default/templates/help/history.md new file mode 100644 index 00000000..be6e57b8 --- /dev/null +++ b/_datafiles/world/default/templates/help/history.md @@ -0,0 +1,11 @@ +# Help for ~history~ + +The ~history~ shows a list of logged events for your character. + +## Usage: + + ~history~ + Show all history for all categories. + + ~history [category name]~ + Show all history for the category name supplied, such as "experience". \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/history.template b/_datafiles/world/default/templates/help/history.template deleted file mode 100644 index 28b5204f..00000000 --- a/_datafiles/world/default/templates/help/history.template +++ /dev/null @@ -1,12 +0,0 @@ -.: Help for history - -The history shows a list of logged events for your character. - -Usage: - - history - Show all history for all categories. - - history [category name] - Show all history for the category name supplied, such as "experience". - diff --git a/_datafiles/world/default/templates/help/inbox.md b/_datafiles/world/default/templates/help/inbox.md new file mode 100644 index 00000000..baa5212a --- /dev/null +++ b/_datafiles/world/default/templates/help/inbox.md @@ -0,0 +1,9 @@ +# Help for ~inbox~ + +The ~inbox~ command checks your inbox for messages. + +## Usage: + + ~inbox~ - See all new messages + ~inbox old~ - See all old messages + ~inbox clear~ - Delete all messages from your inbox \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/inbox.template b/_datafiles/world/default/templates/help/inbox.template deleted file mode 100644 index 48153763..00000000 --- a/_datafiles/world/default/templates/help/inbox.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for inbox - -The inbox command checks your inbox for messages. - -Usage: - - inbox - See all new messages - inbox old - See all old messages - inbox clear - Delete all messages from your inbox diff --git a/_datafiles/world/default/templates/help/inspect.md b/_datafiles/world/default/templates/help/inspect.md new file mode 100644 index 00000000..b06acfa3 --- /dev/null +++ b/_datafiles/world/default/templates/help/inspect.md @@ -0,0 +1,12 @@ +# Help for ~inspect~ (skill) + +The ~inspect~ skills looks at items and reveals hidden details. + +As you level up the ~inspect~ skill, new things can become revealed. + +## Usage: + +(Lvl 1) ~inspect [item_name]~ Reveals the type and value of items. +(Lvl 2) ~inspect [item_name]~ Reveals weapon damage or uses an item has left. +(Lvl 3) ~inspect [item_name]~ Reveals any stat modifiers an item has. +(Lvl 4) ~inspect [item_name]~ Reveals special magical properties like elemental effects. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/inspect.template b/_datafiles/world/default/templates/help/inspect.template deleted file mode 100644 index 06e866bb..00000000 --- a/_datafiles/world/default/templates/help/inspect.template +++ /dev/null @@ -1,14 +0,0 @@ -.: Help for inspect (skill) - -The inspect skills looks at items and reveals hidden details. - -As you level up the inspect skill, new things can become revealed. - -Usage: - -(Lvl 1) inspect [item_name] Reveals the type and value of items. -(Lvl 2) inspect [item_name] Reveals weapon damage or uses an item has left. -(Lvl 3) inspect [item_name] Reveals any stat modifiers an item has. -(Lvl 4) inspect [item_name] Reveals special magical properties like elemental - effects. - diff --git a/_datafiles/world/default/templates/help/inventory.md b/_datafiles/world/default/templates/help/inventory.md new file mode 100644 index 00000000..e8ced8af --- /dev/null +++ b/_datafiles/world/default/templates/help/inventory.md @@ -0,0 +1,12 @@ +# Help for ~inventory~ + +The ~inventory~ command gives you a summary of your characters equipment. + +You can search for a specific object by entering its full (or partial) name: +~inventory wood~ would list items with "wood" in the name. +~inventory wearable~ would list all wearable items in your inventory. + +## Usage: + + ~inventory~ + ~inventory [search term]~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/inventory.template b/_datafiles/world/default/templates/help/inventory.template deleted file mode 100644 index 27284072..00000000 --- a/_datafiles/world/default/templates/help/inventory.template +++ /dev/null @@ -1,8 +0,0 @@ -.: Help for inventory - -The inventory command gives you a summary of your characters equipment. - -You can search for a specific object by entering its full (or partial) name: -inventory wood would list items with "wood" in the name. -inventory wearable would list all wearable items in your inventory. - diff --git a/_datafiles/world/default/templates/help/jobs.md b/_datafiles/world/default/templates/help/jobs.md new file mode 100644 index 00000000..87a07088 --- /dev/null +++ b/_datafiles/world/default/templates/help/jobs.md @@ -0,0 +1,24 @@ +# Help for ~jobs~ + +The ~jobs~ command lists suggested jobs and your progress towards them. +What job you are is determined by what skills you have and what level you are at the skills. + +Some skills overlap jobs such as Brawling. What Job you are classified by what what skills you have and how many of the assigned skills of a job you have. If you type "jobs" its will show you a % of each job you have. If you have 50% in Warrior and Paladin, you will be designated as a dual class warrior and paladin. If you have 50% in Merchant but only 20% in Treasure Hunter, you will be designated as a Merchant. + +## Usage: + + ~jobs~ + +**Note:** Jobs are labels/groupings that describe areas you've trained a lot in. + +To find out about some specific jobs, try the following help commands: + ~help arcane-scholar~ + ~help assassin~ + ~help explorer~ + ~help merchant~ + ~help monster-hunter~ + ~help paladin~ + ~help ranger~ + ~help sorcerer~ + ~help treasure-hunter~ + ~help warrior~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/jobs.template b/_datafiles/world/default/templates/help/jobs.template deleted file mode 100644 index c5ed066f..00000000 --- a/_datafiles/world/default/templates/help/jobs.template +++ /dev/null @@ -1,30 +0,0 @@ -.: Help for jobs - -The jobs command lists suggested jobs and your progress towards them. -What job you are is determined by what skills you have and what level you are at the skills. - -Some skills overlap jobs such as Brawling. What Job you are classified by what what skills you -have and how many of the assigned skills of a job you have. If you type "jobs" its will show you -a % of each job you have. If you have 50% in Warrior and Paladin, you will be designated as a -dual class warrior and paladin. If you have 50% in Merchant but only 20% in Treasure Hunter, you -will be designated as a Merchant. - -Usage: - - jobs - -Note: Jobs are labels/groupings that describe areas you've trained a lot in. - -To find out about some specific jobs, try the following help commands: - - help arcane-scholar - help assassin - help explorer - help merchant - help monster-hunter - help paladin - help ranger - help sorcerer - help treasure-hunter - help warrior - \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/keyring.md b/_datafiles/world/default/templates/help/keyring.md new file mode 100644 index 00000000..98357eeb --- /dev/null +++ b/_datafiles/world/default/templates/help/keyring.md @@ -0,0 +1,26 @@ +# Help for ~keyring~ + +The ~keyring~ command tracks your current keys and picked locks. + +Whenever you use a key, it is taken from your items and added to your keyring forever. You cannot lose a key once this happens. + +Similarly, if you pick a lock, you will always remember the sequence to pick the lock. The lock will be instantaneously picked when you attempt to cross through an exit or open a container. + +## Usage: + + ~keyring~ - This will list all keys and lockpick sequences you have. + It will tell you the Type, Location, exit or container name, and + as the lockpick sequence if applicable. + +## Example: + + **[HP:66/66 MP:35/35]:** ~keyring~ + **Your Keyring:** + **╒══════════╕══════════════════════════════╕═══════╕══════════╕** + **│ Type │ Location │ Where │ Sequence │** + **└──────────┘──────────────────────────────┘───────┘──────────┘** + **│ Key │ #110 Inside of the Catacombs │ west │ - │** + **│ Lockpick │ #784 Inside a Residence │ chest │ D U U │** + **└──────────┘──────────────────────────────┘───────┘──────────┘** + +**See also:** ~help picklock~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/keyring.template b/_datafiles/world/default/templates/help/keyring.template deleted file mode 100644 index b41d15c9..00000000 --- a/_datafiles/world/default/templates/help/keyring.template +++ /dev/null @@ -1,29 +0,0 @@ -.: Help for keyring - -The keyring command tracks your current keys and picked locks. - -Whenever you use a key, it is taken from your items and added to your keyring -forever. You cannot lose a key once this happens. - -Similarly, if you pick a lock, you will always remember the sequence to pick -the lock. The lock will be instantaneously picked when you attempt to cross -through an exit or open a container. - -Usage: - - keyring - This will list all keys and lockpick sequences you have. - It will tell you the Type, Location, exit or container name, and - as the lockpick sequence if applicable. - -Example: - - [HP:66/66 MP:35/35]: keyring - .: Your Keyring: - ╒══════════╕══════════════════════════════╕═══════╕══════════╕ - │ TypeLocationWhereSequence │ - └──────────┘──────────────────────────────┘───────┘──────────┘ - │ Key#110 Inside of the Catacombswest- │ - │ Lockpick#784 Inside a ResidencechestD U U │ - └──────────┘──────────────────────────────┘───────┘──────────┘ - -See also: help picklock diff --git a/_datafiles/world/default/templates/help/killstats.md b/_datafiles/world/default/templates/help/killstats.md new file mode 100644 index 00000000..4e5b4229 --- /dev/null +++ b/_datafiles/world/default/templates/help/killstats.md @@ -0,0 +1,13 @@ +# Help for ~killstats~ + +The ~killstats~ tells you your stats for all the different mobs you've killed, and your kill/death ratio. + +The ~killstats race~ tells you the same information, broken down by mob race. + +The ~killstats zone~ tells you the same information, broken down by zone/area. + +## Usage: + + ~killstats~ + ~killstats race~ + ~killstats zone~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/killstats.template b/_datafiles/world/default/templates/help/killstats.template deleted file mode 100644 index 20f20335..00000000 --- a/_datafiles/world/default/templates/help/killstats.template +++ /dev/null @@ -1,8 +0,0 @@ -.: Help for killstats - -The killstats tells you your stats for all the different mobs you've killed, and your kill/death ratio. - -The killstats race tells you the same information, broken down by mob race. - -The killstats zone tells you the same information, broken down by zone/area. - diff --git a/_datafiles/world/default/templates/help/list.md b/_datafiles/world/default/templates/help/list.md new file mode 100644 index 00000000..52182df4 --- /dev/null +++ b/_datafiles/world/default/templates/help/list.md @@ -0,0 +1,10 @@ +# Help for ~list~ + +The ~list~ command lists items for sale at any merchants you are visiting. Some merchants may even offer help for hire! + +## Usage: + + ~list~ + This would list whatever the merchant is carrying. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/list.template b/_datafiles/world/default/templates/help/list.template deleted file mode 100644 index a1d4c644..00000000 --- a/_datafiles/world/default/templates/help/list.template +++ /dev/null @@ -1,12 +0,0 @@ -.: Help for list - -The list command lists items for sale at any merchants you are visiting. Some merchants -may even offer help for hire! - -Usage: - - list - This would list whatever the merchant is carrying. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/lock.md b/_datafiles/world/default/templates/help/lock.md new file mode 100644 index 00000000..66ce6e6b --- /dev/null +++ b/_datafiles/world/default/templates/help/lock.md @@ -0,0 +1,10 @@ +# Help for ~lock~ + +The ~lock~ command attempts to re-lock any exit or container. +You'll need an appropriate *key* in your backpack or on your keyring. + +## Usage: + + ~lock [exit name/container name]~ - This locks it if it is unlocked. + +**See also:** ~help unlock~, ~help keyring~, ~help picklock~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/lock.template b/_datafiles/world/default/templates/help/lock.template deleted file mode 100644 index 7f7e497f..00000000 --- a/_datafiles/world/default/templates/help/lock.template +++ /dev/null @@ -1,10 +0,0 @@ -.: Help for lock - -The lock command attempts to re-lock any exit or container. -You'll need an appropriate key in your backpack or on your keyring. - -Usage: - - lock [exit name/container name] - This locks it if it is unlocked. - -See also: help unlock, help keyring, help picklock diff --git a/_datafiles/world/default/templates/help/look.md b/_datafiles/world/default/templates/help/look.md new file mode 100644 index 00000000..71029e0b --- /dev/null +++ b/_datafiles/world/default/templates/help/look.md @@ -0,0 +1,20 @@ +# Help for ~look~ + +The ~look~ command looks at things in the room around you. + +## Usage: + + ~look~ + This looks at the room you are in and tells you about it. + + ~look north~ + This tries to peer into the room to the north exit. + + ~look dave~ + This looks at the user **dave** and tells you what you can see about him. + + ~look sword#2~ + This looks at the second *sword* in your backpack and gives you a description. + + Sometimes there is text in a room description that warrants a closer look. + You can often look at these for more information about them. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/look.template b/_datafiles/world/default/templates/help/look.template deleted file mode 100644 index ca146b7b..00000000 --- a/_datafiles/world/default/templates/help/look.template +++ /dev/null @@ -1,23 +0,0 @@ -.: Help for look - -The look command looks at things in the room around -you. - -Usage: - - look - This looks at the room you are in and tells you about it. - - look north - This tries to peer into the room to the north exit. - - look dave - This looks at the user dave and tells you what you - can see about him. - - look sword#2 - This looks at the second sword in your backpack and gives you a description. - - Sometimes there is text in a room description that warrants a closer look. - You can often look at these for more information about them. - diff --git a/_datafiles/world/default/templates/help/macros.md b/_datafiles/world/default/templates/help/macros.md new file mode 100644 index 00000000..03abcba8 --- /dev/null +++ b/_datafiles/world/default/templates/help/macros.md @@ -0,0 +1,27 @@ +# Help for ~macros~ + +~macros~ are special aliases that can issue one or more commands. + +## Usage: + + ~set =# [command]~ - e.g. ~set =1 "say hi everyone"~ + Sets a macro # (0-10) to a command of your choice. You can then use this macro + as a shortcut to quickly issue to a command as follows: ~=1~ + If your terminal program supports it, prettying a corresponding F-Key + + ~set =#~ - e.g. ~set =1~ + Clears a macro # (0-10) + + ~=#~ - e.g. ~set =1~ + Executes macro # (0-10) + + ~=?~ + Lists all currently set macros. + +## Special Usage: + + You can split a macro into more than one command by separating extra commands + with a semicolon - **;** + e.g. ~set =1 wave;say hi;emote sits down~ + + **See also:** ~help set~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/macros.template b/_datafiles/world/default/templates/help/macros.template deleted file mode 100644 index cfef42d4..00000000 --- a/_datafiles/world/default/templates/help/macros.template +++ /dev/null @@ -1,27 +0,0 @@ -.: Help for macros - -macros are special aliases that can issue one or more commands. - -Usage: - - set =# [command] - e.g. set =1 "say hi everyone" - Sets a macro # (0-10) to a command of your choice. You can then use this macro - as a shortcut to quickly issue to a command as follows: =1 - If your terminal program supports it, prettying a corresponding F-Key - - set =# - e.g. set =1 - Clears a macro # (0-10) - - =# - e.g. set =1 - Executes macro # (0-10) - - =? - Lists all currently set macros. - -Special Usage: - - You can split a macro into more than one command by separating extra commands - with a semicolon - ; - e.g. set =1 wave;say hi;emote sits down - - See also: help set diff --git a/_datafiles/world/default/templates/help/map.md b/_datafiles/world/default/templates/help/map.md new file mode 100644 index 00000000..12bdb174 --- /dev/null +++ b/_datafiles/world/default/templates/help/map.md @@ -0,0 +1,16 @@ +# Help for ~map~ (skill) + +The ~map~ command displays a map of the area, centered on your character. + +Not everything is guaranteed to be shown on the map. For example, hidden areas may not be shown. + +With each level of training, your mapping skill will become more effective, covering more area. + +## Usage: + +(Lvl 1) ~map~ Map a 5x5 area around you. +(Lvl 2) ~map~ Map a 9x7 area around you. +(Lvl 3) ~map~ Map a 13x9 area around you. +(Lvl 4) ~map [wide]~ Map a 17x9 area around you, or if "wide" is specified, twice the distance zoomed out. + +Your maps continue to expand with your perception: **Perception/5** \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/map.template b/_datafiles/world/default/templates/help/map.template deleted file mode 100644 index 79a55706..00000000 --- a/_datafiles/world/default/templates/help/map.template +++ /dev/null @@ -1,20 +0,0 @@ -.: Help for map (skill) - -The map command displays a map of the area, centered on your character. - -Not everything is guaranteed to be shown on the map. For example, hidden areas -may not be shown. - -With each level of training, your mapping skill will become more effective, -covering more area. - -Usage: - -(Lvl 1) map Map a 5x5 area around you. -(Lvl 2) map Map a 9x7 area around you. -(Lvl 3) map Map a 13x9 area around you. -(Lvl 4) map [wide] Map a 17x9 area around you, or if "wide" is specified, - twice the distance zoomed out. - -Your maps continue to expand with your perception: Perception/5 - diff --git a/_datafiles/world/default/templates/help/offer.md b/_datafiles/world/default/templates/help/offer.md new file mode 100644 index 00000000..e85aaabe --- /dev/null +++ b/_datafiles/world/default/templates/help/offer.md @@ -0,0 +1,10 @@ +# Help for ~offer~ + +The ~offer~ asks a merchant what they are willing to pay for an item. + +## Usage: + + ~offer sword~ + The merchant will tell you what he will pay for it, if anything. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/offer.template b/_datafiles/world/default/templates/help/offer.template deleted file mode 100644 index dbe48dde..00000000 --- a/_datafiles/world/default/templates/help/offer.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for offer - -The offer asks a merchant what they are willing to pay for an item. - -Usage: - - offer sword - The merchant will tell you what he will pay for it, if anything. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/online.md b/_datafiles/world/default/templates/help/online.md new file mode 100644 index 00000000..d1f95b36 --- /dev/null +++ b/_datafiles/world/default/templates/help/online.md @@ -0,0 +1,17 @@ +# Help for ~online~ + +The ~online~ command shows who is currently online. +It also tells you how long they are online, their role, and some other information about their character in game. + +## Example: + + **[HP:66/66 MP:35/35]:** ~online~ + **4 users online** + **╒══════════╕═══════╕═══════════╕════════════════════╕════════╕═══════╕** + **│ Name │ Level │ Alignment │ Profession │ Online │ Role │** + **└──────────┘───────┘───────────┘────────────────────┘────────┘───────┘** + **│ Chuckles │ 9 │ neutral │ apprentice paladin │ 43m │ admin │** + **│ Rockshot │ 3 │ corrupt │ novice assassin │ 3m │ user │** + **│ Wutend │ 13 │ lawful │ expert warrior │ 1h8m │ user │** + **│ Skitzith │ 23 │ virtuous │ journeyman paladin │ 2h21m │ user │** + **└──────────┘───────┘───────────┘────────────────────┘────────┘───────┘** \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/online.template b/_datafiles/world/default/templates/help/online.template deleted file mode 100644 index 985867b6..00000000 --- a/_datafiles/world/default/templates/help/online.template +++ /dev/null @@ -1,19 +0,0 @@ -.: Help for online - -The online command shows who is currently online. -It also tells you how long they are online, their role, and some other -information about their character in game. - -Example: - - [HP:66/66 MP:35/35]: online - .: 4 users online - ╒══════════╕═══════╕═══════════╕════════════════════╕════════╕═══════╕ - │ NameLevelAlignmentProfessionOnlineRole │ - └──────────┘───────┘───────────┘────────────────────┘────────┘───────┘ - │ Chuckles9neutralapprentice paladin43madmin │ - │ Rockshot3corruptnovice assassin3muser │ - │ Wutend13lawfulexpert warrior1h8muser │ - │ Skitzith23virtuousjourneyman paladin2h21muser │ - └──────────┘───────┘───────────┘────────────────────┘────────┘───────┘ - diff --git a/_datafiles/world/default/templates/help/party.md b/_datafiles/world/default/templates/help/party.md new file mode 100644 index 00000000..34e3049c --- /dev/null +++ b/_datafiles/world/default/templates/help/party.md @@ -0,0 +1,17 @@ +# Help for ~party~ + +The ~party~ manages player parties/groups. + +## Usage: + + ~party~ - Lists your current party and its members + ~party [create/new/start]~ - Creates a new party that you lead + ~party invite [name]~ - Invites a player to your party + ~party [accept/join]~ - Accepts an invitation to a party + ~party decline~ - Declines an invitation to a party + ~party [leave/quit]~ - Leaves a party you are a member of + ~party [disband/stop]~ - Destroys a party you lead + ~party kick [name]~ - Kicks a player out of a party you lead + ~party promote [name]~ - Promotes a player to leader of the party + ~party [say/chat] [message]~ - Sends a message only your party can receive + ~party autoattack [on/off]~ - Automatically join your party leader in combat \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/party.template b/_datafiles/world/default/templates/help/party.template deleted file mode 100644 index 49782647..00000000 --- a/_datafiles/world/default/templates/help/party.template +++ /dev/null @@ -1,18 +0,0 @@ -.: Help for party - -The party manages player parties/groups. - -Usage: - - party - Lists your current party and its members - party [create/new/start] - Creates a new party that you lead - party invite [name] - Invites a player to your party - party [accept/join] - Accepts an invitation to a party - party decline - Declines an invitation to a party - party [leave/quit] - Leaves a party you are a member of - party [disband/stop] - Destroys a party you lead - party kick [name] - Kicks a player out of a party you lead - party promote [name] - Promotes a player to leader of the party - party [say/chat] [message] - Sends a message only your party can receive - party autoattack [on/off] - Automatically join your party leader in combat - diff --git a/_datafiles/world/default/templates/help/password.md b/_datafiles/world/default/templates/help/password.md new file mode 100644 index 00000000..f9bb14da --- /dev/null +++ b/_datafiles/world/default/templates/help/password.md @@ -0,0 +1,8 @@ +# Help for ~password~ + +The ~password~ command allows you to change your password. + +## Usage: + + ~password~ + Type ~password~ and answer the prompts to make the change. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/password.template b/_datafiles/world/default/templates/help/password.template deleted file mode 100644 index a198915c..00000000 --- a/_datafiles/world/default/templates/help/password.template +++ /dev/null @@ -1,5 +0,0 @@ -.: Help for password - -The password command allows you to change your password. - -Type password and answer the prompts to make the change. diff --git a/_datafiles/world/default/templates/help/peep.md b/_datafiles/world/default/templates/help/peep.md new file mode 100644 index 00000000..2a1d3b4b --- /dev/null +++ b/_datafiles/world/default/templates/help/peep.md @@ -0,0 +1,12 @@ +# Help for ~peep~ (skill) + +The ~peep~ skill gives special information about NPC's and players. + +As you level up the ~peep~ skill, new information becomes available and may become passively useful. + +## Usage: + +(Lvl 1) You always can tell how healthy an NPC is. +(Lvl 2) ~peep [player/mob]~ Reveals detailed stats of the player or mob. +(Lvl 3) ~peep [player/mob]~ Also reveals equipment and items. +(Lvl 4) ~peep [player/mob]~ Also reveals the chance of dropping equipment. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/peep.template b/_datafiles/world/default/templates/help/peep.template deleted file mode 100644 index 66d56360..00000000 --- a/_datafiles/world/default/templates/help/peep.template +++ /dev/null @@ -1,14 +0,0 @@ -.: Help for peep (skill) - -The peep skill gives special information about NPC's and players. - -As you level up the peep skill, new information becomes available and may -become passively useful. - -Usage: - -(Lvl 1) You always can tell how healthy an NPC is. -(Lvl 2) peep [player/mob] Reveals detailed stats of the player or mob. -(Lvl 3) peep [player/mob] Also reveals equipment and items. -(Lvl 4) peep [player/mob] Also reveals the chance of dropping equipment. - diff --git a/_datafiles/world/default/templates/help/pets.md b/_datafiles/world/default/templates/help/pets.md new file mode 100644 index 00000000..51314fbe --- /dev/null +++ b/_datafiles/world/default/templates/help/pets.md @@ -0,0 +1,11 @@ +# Help for ~pets~ + +~pets~ are familiars that follow you and assist you. + +They may provide you with stat bonuses, special powers, help you in combat, or carry objects for you. + +When you first get a ~pet~, you can give it a name: + + ~pet name {newname}~ - This will name your pet. + +**Beware**, you can only name a pet once. Try looking at your pet to get some quick information about their wellbeing. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/pets.template b/_datafiles/world/default/templates/help/pets.template deleted file mode 100644 index 265b4dc5..00000000 --- a/_datafiles/world/default/templates/help/pets.template +++ /dev/null @@ -1,13 +0,0 @@ -.: Help for pets - -pets are familiars that follow you and assist you. - -They may provide you with stat bonuses, special powers, help you in combat, or -carry objects for you. - -When you first get a pet, you can give it a name: - - pet name {newname} - This will name your pet. - -Beware, you can only name a pet once. Try looking at your pet to get some quick -information about their wellbeing. diff --git a/_datafiles/world/default/templates/help/picklock.md b/_datafiles/world/default/templates/help/picklock.md new file mode 100644 index 00000000..6e7cb139 --- /dev/null +++ b/_datafiles/world/default/templates/help/picklock.md @@ -0,0 +1,30 @@ +# Help for ~picklock~ + +The ~picklock~ command attempts to pick the lock of any exit or container. +You'll need a set of *lockpicks*. + +## Usage: + + ~picklock [exit name/container name]~ - This picks the lock. You can also use it to inspect the lock and select `quit` without attempting to pick it. + +## Examples: + + **[HP:66/66 MP:35/35]:** ~north~ + There's a lock preventing you from going that way. You'll need a *Key* or to ~pick~ the lock with *lockpicks*. + + + **[HP:66/66 MP:35/35]:** ~pick north~ + + .: The Lock Sequence Looks like: + + ╔═══════╦═══════╦═══════╦═══════╦═══════╗ + ║ ║ ║ ║ ║ ║ + ? ? ? ? ? + ║ ║ ║ ║ ║ ║ + ╚═══════╩═══════╩═══════╩═══════╩═══════╝ + + .: Move your lockpick? [UP/DOWN/quit] + +**Note:** Each **?** symbol represents an UP or DOWN you must guess in the sequence. + +**See also:** ~help picklock-example~, ~help keyring~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/picklock.template b/_datafiles/world/default/templates/help/picklock.template deleted file mode 100644 index 5d365889..00000000 --- a/_datafiles/world/default/templates/help/picklock.template +++ /dev/null @@ -1,30 +0,0 @@ -.: Help for picklock - -The picklock command attempts to pick the lock of any exit or container. -You'll need a set of lockpicks. - -Usage: - - picklock [exit name/container name] - This picks the lock. You can also use - it to inspect the lock and select `quit` without attempting to pick it. - -Examples: - - [HP:66/66 MP:35/35]: north - There's a lock preventing you from going that way. You'll need a Key or to - pick the lock with lockpicks. - - - [HP:66/66 MP:35/35]: pick north - - .: The Lock Sequence Looks like: - ╔═══════╦═══════╦═══════╦═══════╦═══════╗ - ║ ║ ║ ║ ║ ║ - ║ ????? ║ - ║ ║ ║ ║ ║ ║ - ╚═══════╩═══════╩═══════╩═══════╩═══════╝ - .: Move your lockpick? [UP/DOWN/quit] - -Note: Each ? symbol represents an UP or DOWN you must guess in the sequence. - -See also: help picklock-example, help keyring diff --git a/_datafiles/world/default/templates/help/portal.md b/_datafiles/world/default/templates/help/portal.md new file mode 100644 index 00000000..8722164b --- /dev/null +++ b/_datafiles/world/default/templates/help/portal.md @@ -0,0 +1,14 @@ +# Help for ~portal~ (skill) + +The ~portal~ skills transports you to a new location. + +As you level up the ~portal~ skill, it can do more things. + +## Usage: + +(Lvl 1) ~portal~ Transports you back to the Town Square of Frostfang. +(Lvl 2) ~portal~ Transports you to the root area of your zone. +(Lvl 3) ~portal set/clear~ Sets to your current area (or removes) the new location you transport to. +(Lvl 4) ~portal open~ Creates a physical portal in the room for anyone to travel through. + +The lifespan in seconds of your portals is calculated as follows: **Mysticism * 10 + 30** \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/portal.template b/_datafiles/world/default/templates/help/portal.template deleted file mode 100644 index 3d7c2961..00000000 --- a/_datafiles/world/default/templates/help/portal.template +++ /dev/null @@ -1,17 +0,0 @@ -.: Help for portal (skill) - -The portal skills transports you to a new location. - -As you level up the portal skill, it can do more things. - -Usage: - -(Lvl 1) portal Transports you back to the Town Square of Frostfang. -(Lvl 2) portal Transports you to the root area of your zone. -(Lvl 3) portal set/clear Sets to your current area (or removes) the new - location you transport to. -(Lvl 4) portal open Creates a physical portal in the room for anyone to - travel through. - -The lifespan in seconds of your portals is calculated as follows: Mysticism * 10 + 30 - diff --git a/_datafiles/world/default/templates/help/put.md b/_datafiles/world/default/templates/help/put.md new file mode 100644 index 00000000..0d19976d --- /dev/null +++ b/_datafiles/world/default/templates/help/put.md @@ -0,0 +1,10 @@ +# Help for ~put~ + +The ~put~ command puts objects into containers. + +## Usage: + + ~put stick in chest~ + This would put a stick you hold into the chest in the room. + ~put 10 gold into chest~ + This would put 10 gold into the chest. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/put.template b/_datafiles/world/default/templates/help/put.template deleted file mode 100644 index e934b0b5..00000000 --- a/_datafiles/world/default/templates/help/put.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for put - -The put command puts objects into containers. - -Usage: - - put stick in chest - This would put a stick you hold into the chest in the room. - put 10 gold into chest - This would put 10 gold into the chest. - diff --git a/_datafiles/world/default/templates/help/pvp.md b/_datafiles/world/default/templates/help/pvp.md new file mode 100644 index 00000000..8b88ec49 --- /dev/null +++ b/_datafiles/world/default/templates/help/pvp.md @@ -0,0 +1,11 @@ +# Help for ~pvp~ + +PVP is short for Player-versus-player. It's when two or more players can or do enter combat with eachother. + +You can see whether PVP is enabled on this server by typing: ~pvp~ + +The possible settings are: + + **disabled** - PVP is **disabled** on this server. You cannot fight other players. + **enabled** - PVP is **enabled** on this server. You can fight other players anywhere. + **limited** - PVP is **limited** on this server. You can fight other players in places labeled with: **☠ PK Area ☠**. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/pvp.template b/_datafiles/world/default/templates/help/pvp.template deleted file mode 100644 index a0faa5f1..00000000 --- a/_datafiles/world/default/templates/help/pvp.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for ☠ PVP ☠ - -PVP is short for Player-versus-player. It's when two or more players can or do enter combat with eachother. - -You can see whether PVP is enabled on this server by typing: pvp - -The possible settings are: - - disabled - PVP is disabled on this server. You cannot fight other players. - enabled - PVP is enabled on this server. You can fight other players anywhere. - limited - PVP is limited on this server. You can fight other players in places labeled with: ☠ PK Area ☠ . diff --git a/_datafiles/world/default/templates/help/quests.md b/_datafiles/world/default/templates/help/quests.md new file mode 100644 index 00000000..e0b719a6 --- /dev/null +++ b/_datafiles/world/default/templates/help/quests.md @@ -0,0 +1,7 @@ +# Help for ~quests~ + +The ~quests~ command shows all current and completed quests. + +## Usage: + + ~quests~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/quests.template b/_datafiles/world/default/templates/help/quests.template deleted file mode 100644 index 441ffcd0..00000000 --- a/_datafiles/world/default/templates/help/quests.template +++ /dev/null @@ -1,7 +0,0 @@ -.: Help for quests - -The quests command shows all current and completed quests. - -Usage: - - quests diff --git a/_datafiles/world/default/templates/help/quit.md b/_datafiles/world/default/templates/help/quit.md new file mode 100644 index 00000000..2610710b --- /dev/null +++ b/_datafiles/world/default/templates/help/quit.md @@ -0,0 +1,9 @@ +# Help for ~quit~ + +The ~quit~ command initiates a meditation which must be undisturbed for several rounds, after which you will be logged out of the game. + +If you drop a connection without doing this, you will become a zombie in game for a while, where you will remain vulnerable even while disconnected. + +## Usage: + + ~quit~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/quit.template b/_datafiles/world/default/templates/help/quit.template deleted file mode 100644 index 348f9170..00000000 --- a/_datafiles/world/default/templates/help/quit.template +++ /dev/null @@ -1,7 +0,0 @@ -.: Help for quit - -The quit command initiates a meditation which must be undisturbed for several -rounds, after which you will be logged out of the game. - -If you drop a connection without doing this, you will become a zombie in game for a while, where you -will remain vulnerable even while disconnected. diff --git a/_datafiles/world/default/templates/help/read.md b/_datafiles/world/default/templates/help/read.md new file mode 100644 index 00000000..9e11d6ff --- /dev/null +++ b/_datafiles/world/default/templates/help/read.md @@ -0,0 +1,8 @@ +# Help for ~read~ + +The ~read~ command reads notes and maps you carry. + +## Usage: + + ~read map~ + This reads the item in your inventory and shows you was it written on it. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/read.template b/_datafiles/world/default/templates/help/read.template deleted file mode 100644 index ba6faeea..00000000 --- a/_datafiles/world/default/templates/help/read.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for read - -The read command reads notes and maps you carry. - -Usage: - - read map - This reads the item in your inventory and shows you was it written on it. - diff --git a/_datafiles/world/default/templates/help/remove.md b/_datafiles/world/default/templates/help/remove.md new file mode 100644 index 00000000..d5c2e616 --- /dev/null +++ b/_datafiles/world/default/templates/help/remove.md @@ -0,0 +1,14 @@ +# Help for ~remove~ + +The ~remove~ command removes an equipped item and returns it to your backpack. + +## Usage: + + ~remove stick~ + This would remove a stick from your hand and put it in your backpack. + ~remove cloak~ + This would remove a cloak from your body and put it in your backpack. + +Aliases: ~unwear~, ~unwield~, ~unequip~ + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/remove.template b/_datafiles/world/default/templates/help/remove.template deleted file mode 100644 index e5fe7228..00000000 --- a/_datafiles/world/default/templates/help/remove.template +++ /dev/null @@ -1,15 +0,0 @@ -.: Help for remove - -The remove command wields or wears an item from your backpack. - -Usage: - - remove stick - This would wield a stick from hand. - remove cloak - This would wear a cloak from body. - -Aliases: unwear, unwield, unequip - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/say.md b/_datafiles/world/default/templates/help/say.md new file mode 100644 index 00000000..4438fba0 --- /dev/null +++ b/_datafiles/world/default/templates/help/say.md @@ -0,0 +1,9 @@ +# Help for ~say~ + +The ~say~ command says something aloud for anyone in the room to hear. + +Example: + + [HP:10/10 MP:10/10]: say hello everyone! + you say, "hello everyone!" + [HP:10/10 MP:10/10]: \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/say.template b/_datafiles/world/default/templates/help/say.template deleted file mode 100644 index 04f179c2..00000000 --- a/_datafiles/world/default/templates/help/say.template +++ /dev/null @@ -1,10 +0,0 @@ -.: Help for say - -The say command says something aloud for anyone in the room to hear. - -Example: - - [HP:10/10 MP:10/10]: say hello everyone! - you say, "hello everyone!" - [HP:10/10 MP:10/10]: - diff --git a/_datafiles/world/default/templates/help/scribe.md b/_datafiles/world/default/templates/help/scribe.md new file mode 100644 index 00000000..9e2fe704 --- /dev/null +++ b/_datafiles/world/default/templates/help/scribe.md @@ -0,0 +1,16 @@ +# Help for ~scribe~ (skill) + +The ~scribe~ skill gives the player the ability to write down things in the world. +These will eventually decay into dust and scraps, but can be quite useful for a time. + +You can train the ~scribe~ skill at a *bard* training school. +With each level of training, the variety of things you can scribe increases. + +Beware! Sometimes scribe may need to be used in combination with another skill! + +## Usage: + +(Lvl 1) ~scribe note [txt]~ Write a message to a scrap of paper that can be saved or shared. +(Lvl 2) ~scribe sign [txt]~ Create/Replace a makeshift sign with a short message and place it in the area. Decays in a weeks time. +(Lvl 3) ~scribe rune [txt]~ Create/Replace a short hidden message into the area that only you can see. Decays in a months time. +(Lvl 4) \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/scribe.template b/_datafiles/world/default/templates/help/scribe.template deleted file mode 100644 index 6cd81c5d..00000000 --- a/_datafiles/world/default/templates/help/scribe.template +++ /dev/null @@ -1,21 +0,0 @@ -.: Help for scribe (skill) - -The scribe skill gives the player the ability to write down things in the -world. -These will eventually decay into dust and scraps, but can be quite useful for -a time. - -You can train the scribe skill at a bard training school. -With each level of training, the variety of things you can scribe increases. - -Beware! Sometimes scribe may need to be used in combination with another skill! - -Usage: - -(Lvl 1) scribe note [txt] Write a message to a scrap of paper that can be saved - or shared. -(Lvl 2) scribe sign [txt] Create/Replace a makeshift sign with a short message - and place it in the area. Decays in a weeks time. -(Lvl 3) scribe rune [txt] Create/Replace a short hidden message into the area - that only you can see. Decays in a months time. -(Lvl 4) diff --git a/_datafiles/world/default/templates/help/search.md b/_datafiles/world/default/templates/help/search.md new file mode 100644 index 00000000..78d9ba94 --- /dev/null +++ b/_datafiles/world/default/templates/help/search.md @@ -0,0 +1,16 @@ +# Help for ~search~ (skill) + +The ~search~ skill searches the area for hidden objects. + +You can only search once every so often, and it relies on your Smarts for success. + +As you level up the ~search~ skill, new things can become revealed. + +## Usage: + +(Lvl 1) ~search~ Search for secret exits or hidden players/mobs. +(Lvl 2) ~search~ Finds objects that may be hidden in the area. +(Lvl 3) ~search~ Finds special/unknown "things of interest" in the area. +(Lvl 4) ~search~ Doubles your chance of success when searching. + +Your chances of success when searching are calculated as follows: **Smarts/4 + Perception/2 + 5** \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/search.template b/_datafiles/world/default/templates/help/search.template deleted file mode 100644 index 6128502f..00000000 --- a/_datafiles/world/default/templates/help/search.template +++ /dev/null @@ -1,17 +0,0 @@ -.: Help for search (skill) - -The search skill searches the area for hidden objects. - -You can only search once every so often, and it relies on your Smarts for success. - -As you level up the search skill, new things can become revealed. - -Usage: - -(Lvl 1) search Search for secret exits or hidden players/mobs. -(Lvl 2) search Finds objects that may be hidden in the area. -(Lvl 3) search Finds special/unknown "things of interest" in the area. -(Lvl 4) search Doubles your chance of success when searching. - -Your chances of success when searching are calculated as follows: Smarts/4 + Perception/2 + 5 - diff --git a/_datafiles/world/default/templates/help/sell.md b/_datafiles/world/default/templates/help/sell.md new file mode 100644 index 00000000..e7d490b8 --- /dev/null +++ b/_datafiles/world/default/templates/help/sell.md @@ -0,0 +1,10 @@ +# Help for ~sell~ + +The ~sell~ sells an item to merchants you are visiting. + +## Usage: + + ~sell sword~ + This would sell a sword, the merchant wants it and has the gold. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/sell.template b/_datafiles/world/default/templates/help/sell.template deleted file mode 100644 index bcca501c..00000000 --- a/_datafiles/world/default/templates/help/sell.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for sell - -The sell sells an item to merchants you are visiting. - -Usage: - - sell sword - This would sell a sword, the merchant wants it and has the gold. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/set-wimpy.md b/_datafiles/world/default/templates/help/set-wimpy.md new file mode 100644 index 00000000..0d5728da --- /dev/null +++ b/_datafiles/world/default/templates/help/set-wimpy.md @@ -0,0 +1,8 @@ +# Help for ~set wimpy~ + +The ~set wimpy~ command allows you specify at what percentage health you will automatically attempt to flee. + +## Usage: + + ~set wimpy 0~ - Disable wimpy + ~set wimpy 10~ - At 10% or lower health you will flee combat. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/set-wimpy.template b/_datafiles/world/default/templates/help/set-wimpy.template deleted file mode 100644 index 4e3b44ac..00000000 --- a/_datafiles/world/default/templates/help/set-wimpy.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for set wimpy - -The set wimpy command allows you specify at what percentage health you will -automatically attempt to flee. - -Usage: - - set wimpy 0 - Disable wimpy - set wimpy 10 - At 10% or lower health you will flee combat. diff --git a/_datafiles/world/default/templates/help/set.md b/_datafiles/world/default/templates/help/set.md new file mode 100644 index 00000000..521abf58 --- /dev/null +++ b/_datafiles/world/default/templates/help/set.md @@ -0,0 +1,33 @@ +# Help for ~set~ command + +The ~set~ command configures your account. + +There are a handful of settings you can adjust with this command, including: + +## Usage: + + ~set =# [command]~ - e.g. ~set =1 "say hi everyone"~ + Sets a macro # (0-10) to a command of your choice. You can then use this macro + as a shortcut to quickly issue to a command as follows: ~=1~ + If your terminal program supports it, prettying a corresponding F-Key + Type ~help macros~ for more information about macros. + + ~set description [description]~ - e.g. ~set description "A fearsome warrior"~ + This sets the description players see when they look at your character. You + can also look at yourself to see your current description. + + ~set auction~ + This toggles the auction system on or off. If off, you will not receive notifications about system-wide auctions. + + ~set shortadjectives~ + This toggles short adjective displayes on or off. See ~help adjectives~ + + ~set prompt [prompt text]~ + This sets a custom prompt (See ~help prompt~) + If you ommit the [prompt text], your current prompt will be displayed. + + ~set tinymap~ + This toggles the automatic tinymap on or off. It shows when looking at rooms. + + ~set wimpy~ + Set your wimpy percentage (See ~help wimpy~) \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/set.template b/_datafiles/world/default/templates/help/set.template deleted file mode 100644 index a6aa39e5..00000000 --- a/_datafiles/world/default/templates/help/set.template +++ /dev/null @@ -1,33 +0,0 @@ -.: Help for set command - -The set command configures your account. - -There are a handful of settings you can adjust with this command, including: - -Usage: - - set =# [command] - e.g. set =1 "say hi everyone" - Sets a macro # (0-10) to a command of your choice. You can then use this macro - as a shortcut to quickly issue to a command as follows: =1 - If your terminal program supports it, prettying a corresponding F-Key - Type help macros for more information about macros. - - set description [description] - e.g. set description "A fearsome warrior" - This sets the description players see when they look at your character. You - can also look at yourself to see your current description. - - set auction - This toggles the auction system on or off. If off, you will not receive notifications about system-wide auctions. - - set shortadjectives - This toggles short adjective displayes on or off. See help adjectives - - set prompt [prompt text] - This sets a custom prompt (See help prompt) - If you ommit the [prompt text], your current prompt will be displayed. - - set tinymap - This toggles the automatic tinymap on or off. It shows when looking at rooms. - - set wimpy - Set your wimpy percentage (See help wimpy) diff --git a/_datafiles/world/default/templates/help/share.md b/_datafiles/world/default/templates/help/share.md new file mode 100644 index 00000000..e0e1077b --- /dev/null +++ b/_datafiles/world/default/templates/help/share.md @@ -0,0 +1,8 @@ +# Help for ~share~ + +The ~share~ command shares wealth with your party. + +## Usage: + + ~share [amt] gold~ + This will split the [amt] of gold you specify amongst everyone in the party. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/share.template b/_datafiles/world/default/templates/help/share.template deleted file mode 100644 index 7ea03973..00000000 --- a/_datafiles/world/default/templates/help/share.template +++ /dev/null @@ -1,8 +0,0 @@ -.: Help for share - -The share command shares wealth with your party - -Usage: - - share [amt] gold - This will split the [amt] of gold you specify amongst everyone in the party. diff --git a/_datafiles/world/default/templates/help/shoot.md b/_datafiles/world/default/templates/help/shoot.md new file mode 100644 index 00000000..cb9a99d2 --- /dev/null +++ b/_datafiles/world/default/templates/help/shoot.md @@ -0,0 +1,10 @@ +# Help for ~shoot~ + +The ~shoot~ command fires a weapon into an adjacent room. + +## Usage: + + ~shoot [target] [exit]~ + This shoots at the target specified in the direction specified. + + **Note:** This engages combat but will break combat if the space between you and the target is not closed quickly. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/shoot.template b/_datafiles/world/default/templates/help/shoot.template deleted file mode 100644 index e9e7f857..00000000 --- a/_datafiles/world/default/templates/help/shoot.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for shoot - -The shoot command fires a weapon into an adjacent room. - -Usage: - - shoot [target] [exit] - This shoots at the target specified in the direction specified. - - Note: This engages combat but will break combat if the space between you and the target - is not closed quickly. diff --git a/_datafiles/world/default/templates/help/shout.md b/_datafiles/world/default/templates/help/shout.md new file mode 100644 index 00000000..2a615080 --- /dev/null +++ b/_datafiles/world/default/templates/help/shout.md @@ -0,0 +1,12 @@ +# Help for ~shout~ + +The ~shout~ command shouts something to everyone in the room, and can be heard by anyone in adjacent rooms. + +## Usage: + + ~shout [message]~ + +Example: + + [HP:10/10 MP:10/10]: shout here I am! + you shout, "HERE I AM!" \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/shout.template b/_datafiles/world/default/templates/help/shout.template deleted file mode 100644 index e256de05..00000000 --- a/_datafiles/world/default/templates/help/shout.template +++ /dev/null @@ -1,10 +0,0 @@ -.: Help for shout - -The shout command shouts something to everyone in the room, and can be heard by -anyone in adjacent rooms. - -Example: - - [HP:10/10 MP:10/10]: shout here I am! - you shout, "HERE I AM!" - diff --git a/_datafiles/world/default/templates/help/show.md b/_datafiles/world/default/templates/help/show.md new file mode 100644 index 00000000..dca21b2e --- /dev/null +++ b/_datafiles/world/default/templates/help/show.md @@ -0,0 +1,8 @@ +# Help for ~show~ + +The ~look~ command shows an object to another player or mob. + +## Usage: + + ~show sword sam~ + This shows your sword to sam. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/show.template b/_datafiles/world/default/templates/help/show.template deleted file mode 100644 index 19ee8171..00000000 --- a/_datafiles/world/default/templates/help/show.template +++ /dev/null @@ -1,8 +0,0 @@ -.: Help for show - -The look command shows an object to another player or mob. - -Usage: - - show sword sam - This shows your sword to sam. diff --git a/_datafiles/world/default/templates/help/skills.md b/_datafiles/world/default/templates/help/skills.md new file mode 100644 index 00000000..7368b79e --- /dev/null +++ b/_datafiles/world/default/templates/help/skills.md @@ -0,0 +1,7 @@ +# Help for ~skills~ + +The ~skills~ command lists your current known skills. + +## Usage: + + ~skills~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/skills.template b/_datafiles/world/default/templates/help/skills.template deleted file mode 100644 index 4d31e88a..00000000 --- a/_datafiles/world/default/templates/help/skills.template +++ /dev/null @@ -1,8 +0,0 @@ -.: Help for skills - -The skills command lists your current known skills. - -Usage: - - skills - diff --git a/_datafiles/world/default/templates/help/skulduggery.md b/_datafiles/world/default/templates/help/skulduggery.md new file mode 100644 index 00000000..de2cace7 --- /dev/null +++ b/_datafiles/world/default/templates/help/skulduggery.md @@ -0,0 +1,19 @@ +# Help for ~skulduggery~ (skill) + +The ~skulduggery~ skill is actuall several skills you learn. + +Each skill is improved by your stats and level as well. + +## Usage: + +(Lvl 1) ~sneak [direction/exit]~ Remain hidden for a period of time, even when moving between areas. +(Lvl 2) ~bump [enemy]~ Bump into a player or NPC, causing a fraction of their coins to drop to the ground. +(Lvl 3) ~backstab [enemy]~ Guarenteed critical on successful attack. +(Lvl 4) ~pickpocket [enemy]~ Gain ability to steal from players and NPC's while hidden. + +Odds of success on a bump attempt: **attackStrength / 2 / LevelDifference** +On success up to 25% of their gold will drop to the floor. + +Odds of success on a pickpocket attempt: **((attackSpeed+attackSmarts+attackPerception)/3 - defendPerception) / LevelDifference** +You gain a +15% chance of success if you are sneaking at the time of a pickpocket attempt. +On success you steal at least 25% of their money and 1 item. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/skulduggery.template b/_datafiles/world/default/templates/help/skulduggery.template deleted file mode 100644 index facc4590..00000000 --- a/_datafiles/world/default/templates/help/skulduggery.template +++ /dev/null @@ -1,21 +0,0 @@ -.: Help for skulduggery (skill) - -The skulduggery skill is actuall several skills you learn. - -Each skill is improved by your stats and level as well. - -Usage: - -(Lvl 1) sneak [direction/exit] Remain hidden for a period of time, even when moving between areas. -(Lvl 2) bump [enemy] Bump into a player or NPC, causing a fraction of their coins to drop to the ground. -(Lvl 3) backstab [enemy] Guarenteed critical on successful attack. -(Lvl 4) pickpocket [enemy] Gain ability to steal from players and NPC's while hidden. - -Odds of success on a bump attempt: attackStrength / 2 / LevelDifference -On success up to 25% of their gold will drop to the floor. - -Odds of success on a pickpocket attempt: ((attackSpeed+attackSmarts+attackPerception)/3 - defendPerception) / LevelDifference -You gain a +15% chance of success if you are sneaking at the time of a pickpocket attempt. -On success you steal at least 25% of their money and 1 item. - - diff --git a/_datafiles/world/default/templates/help/spells.md b/_datafiles/world/default/templates/help/spells.md new file mode 100644 index 00000000..3b5997d9 --- /dev/null +++ b/_datafiles/world/default/templates/help/spells.md @@ -0,0 +1,11 @@ +# Help for ~spells~ + +The ~spells~ command lists spells you have learned, along with some useful information about them. + +## Usage: + + ~spells~ + + To get help on a particular spell, try: ~help spell [spellId]~ + +**See also:** ~help cast~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/spells.template b/_datafiles/world/default/templates/help/spells.template deleted file mode 100644 index 36e9a0b3..00000000 --- a/_datafiles/world/default/templates/help/spells.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for spells - -The spells command lists spells you have learned, along with some useful information about them. - -Usage: - - spells - - To get help on a particular spell, try: help spell [spellId] - -See also: help cast diff --git a/_datafiles/world/default/templates/help/stash.md b/_datafiles/world/default/templates/help/stash.md new file mode 100644 index 00000000..ebe6be21 --- /dev/null +++ b/_datafiles/world/default/templates/help/stash.md @@ -0,0 +1,12 @@ +# Help for ~stash~ + +The ~stash~ command hides an item in the room. Nobody will know it's there but you. + +Stashes can be searched for if someone has the ~search~ skill. To recover an item from a stash, type ~get [item_name] from stash~. + +## Usage: + + ~stash stick~ + This would hide a stick in the room if you had it in your backpack. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/stash.template b/_datafiles/world/default/templates/help/stash.template deleted file mode 100644 index 129dfdae..00000000 --- a/_datafiles/world/default/templates/help/stash.template +++ /dev/null @@ -1,15 +0,0 @@ -.: Help for stash - -The stash command hides an item in the room. Nobody will know it's there but -you. - -Stashes can be searched for if someone has the search skill. To recover -an item from a stash, type get [item_name] from stash. - -Usage: - - stash stick - This would hide a stick in the room if you had it in your backpack. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/stat-train.md b/_datafiles/world/default/templates/help/stat-train.md new file mode 100644 index 00000000..a7405b5a --- /dev/null +++ b/_datafiles/world/default/templates/help/stat-train.md @@ -0,0 +1,9 @@ +# Help for ~stat-train~ + +The ~stat-train~ command spends Stat Points you gave from leveling to improve your character. + +It will start an interactive prompt to choose what to improve in. + +## Usage: + + ~stat-train~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/stat-train.template b/_datafiles/world/default/templates/help/stat-train.template deleted file mode 100644 index 1612ca35..00000000 --- a/_datafiles/world/default/templates/help/stat-train.template +++ /dev/null @@ -1,5 +0,0 @@ -.: Help for stat-train - -The stat-train command spends Stat Points you gave from leveling to improve your character. - -It will start an interactive prompt to choose what to improve in. diff --git a/_datafiles/world/default/templates/help/status.md b/_datafiles/world/default/templates/help/status.md new file mode 100644 index 00000000..4b9b57e3 --- /dev/null +++ b/_datafiles/world/default/templates/help/status.md @@ -0,0 +1,27 @@ +# Help for ~status~ + +The ~status~ command gives you a summary of your characters information. + +When you level up, you gain *Stat Points* which you can spend to upgrade your stats base value. + +## Usage: + + ~status~ - Show your character status + + ~status train~ - Spend stat points on upgrades to base stats. + +## Related Help: + + ~race~ + ~level~ + ~experience~ + ~health~ + ~mana~ + ~armor~ + + ~strength~ + ~vitality~ + ~speed~ + ~mysticism~ + ~smarts~ + ~perception~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/status.template b/_datafiles/world/default/templates/help/status.template deleted file mode 100644 index 3e2aa51a..00000000 --- a/_datafiles/world/default/templates/help/status.template +++ /dev/null @@ -1,29 +0,0 @@ -.: Help for status - -The status command gives you a summary of your characters information. - -When you level up, you gain Stat Points which you can spend to upgrade your -stats base value. - -Usage: - - status - Show your character status - - status train - Spend stat points on upgrades to base stats. - -Related Help: - - race - level - experience - health - mana - armor - - strength - vitality - speed - mysticism - smarts - perception - diff --git a/_datafiles/world/default/templates/help/storage.md b/_datafiles/world/default/templates/help/storage.md new file mode 100644 index 00000000..a98a9914 --- /dev/null +++ b/_datafiles/world/default/templates/help/storage.md @@ -0,0 +1,12 @@ +# Help for ~storage~ + +The ~storage~ command lets you store and unstore items. +These items can be retrieved at various locations in the world. + +## Usage: + + ~storage~ - See what you have in storage + + ~unstore [item]~ - Remove an item from storage + + ~store [item]~ - Add an item in storage \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/storage.template b/_datafiles/world/default/templates/help/storage.template deleted file mode 100644 index 5ae1398c..00000000 --- a/_datafiles/world/default/templates/help/storage.template +++ /dev/null @@ -1,13 +0,0 @@ -.: Help for storage - -The storage command lets you store and unstore items. -These items can be retrieved at various locations in the world. - -Usage: - - storage - See what you have in storage - - unstore [item] - Remove an item from storage - - store [item] - Add an item in storage - diff --git a/_datafiles/world/default/templates/help/tame.md b/_datafiles/world/default/templates/help/tame.md new file mode 100644 index 00000000..d65be403 --- /dev/null +++ b/_datafiles/world/default/templates/help/tame.md @@ -0,0 +1,27 @@ +# Help for ~tame~ (skill) + +The ~tame~ skill lets you tame certain types of creatures for up to an hour. + +Each skill level you train adds to the number of creatures you can have tamed at once. + +You have a random chance to learn to tame a new creature whenever you defeat it in combat. This random chance can also increase over time if you continue to defeat the same creature type over and over. + +## Usage: + +(Lvl ?) ~tame~ List specific creatures you have learned to tame. + +(Lvl 1) ~tame [mobname]~ 2 tamed creatures. +(Lvl 2) ~tame [mobname]~ 3 tamed creatures. +(Lvl 3) ~tame [mobname]~ 4 tamed creatures. +(Lvl 4) ~tame [mobname]~ 5 tamed creatures. + +Your skill level affects how long a creature stays tamed for. + +Only some creatures can be successfully tamed, and some may require special equipment. It is up to you to discover what creatures or equipment. + +Your chances of tame success are calculated from the following factors: + 1. Your level difference (the more of a level advantage you have the easier) + 2. The size of your target (the bigger the more difficult) + 3. The number of successes you have for this mob type - increases each 10 + 4. The targets health % - the lower their HP the easier it is. + 5. Whether the target is aggro'ed towards you. A 50% penalty if so. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/tame.template b/_datafiles/world/default/templates/help/tame.template deleted file mode 100644 index 0747c6f6..00000000 --- a/_datafiles/world/default/templates/help/tame.template +++ /dev/null @@ -1,32 +0,0 @@ -.: Help for tame (skill) - -The tame skill lets you tame certain types of creatures for up to an hour. - -Each skill level you train adds to the number of creatures you can have tamed -at once. - -You have a random chance to learn to tame a new creature whenever you defeat -it in combat. This random chance can also increase over time if you continue to -defeat the same creature type over and over. - -Usage: - -(Lvl ?) tame List specific creatures you have learned to tame. - -(Lvl 1) tame [mobname] 2 tamed creatures. -(Lvl 2) tame [mobname] 3 tamed creatures. -(Lvl 3) tame [mobname] 4 tamed creatures. -(Lvl 4) tame [mobname] 5 tamed creatures. - -Your skill level affects how long a creature stays tamed for. - -Only some creatures can be successfully tamed, and some may require special -equipment. It is up to you to discover what creatures or equipment. - -Your chances of tame success are calculated from the following factors: - 1. Your level difference (the more of a level advantage you have the easier) - 2. The size of your target (the bigger the more difficult) - 3. The number of successes you have for this mob type - increases each 10 - 4. The targets health % - the lower their HP the easier it is. - 5. Whether the target is aggro'ed towards you. A 50% penalty if so. - diff --git a/_datafiles/world/default/templates/help/track.md b/_datafiles/world/default/templates/help/track.md new file mode 100644 index 00000000..959801d9 --- /dev/null +++ b/_datafiles/world/default/templates/help/track.md @@ -0,0 +1,17 @@ +# Help for ~track~ (skill) + +The ~track~ command searches the area for rooms a player or npc has recently visited. + +Once the trail goes cold (Which could be immediately!) your map will end. + +If they are close enough, an X will mark their location on your map. + +You can train the ~track~ skill at a *ranger* training school. +With each level of training, your tracking skill will reach farther out to find your target. + +## Usage: + +(Lvl 1) ~track~ See the most recent mob/player to pass through this room, excluding any present mobs/players. +(Lvl 2) ~track~ See all recent mobs/players to pass through this room, excluding any present mobs/players. +(Lvl 3) ~track~ Shows exit information for all tracked players or mobs. +(Lvl 4) Enhances the ~map~ skill to show nearby mobs and players, including the mini map. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/track.template b/_datafiles/world/default/templates/help/track.template deleted file mode 100644 index 26a38773..00000000 --- a/_datafiles/world/default/templates/help/track.template +++ /dev/null @@ -1,19 +0,0 @@ -.: Help for track (skill) - -The track command searches the area for rooms a player or npc has recently -visited. - -Once the trail goes cold (Which could be immediately!) your map will end. - -If they are close enough, an X will mark their location on your map. - -You can train the track skill at a ranger training school. -With each level of training, your tracking skill will reach farther out to find your target. - -Usage: - -(Lvl 1) track See the most recent mob/player to pass through this room, excluding any present mobs/players. -(Lvl 2) track See all recent mobs/players to pass through this room, excluding any present mobs/players. -(Lvl 3) track Shows exit information for all tracked players or mobs. -(Lvl 4) Enhances the map skill to show nearby mobs and players, including the mini map. - diff --git a/_datafiles/world/default/templates/help/train.md b/_datafiles/world/default/templates/help/train.md new file mode 100644 index 00000000..8dfa25ca --- /dev/null +++ b/_datafiles/world/default/templates/help/train.md @@ -0,0 +1,11 @@ +# Help for ~train~ + +The ~train~ command spends Training Points (TP) at guilds and other training spots. + +You can earn Traning Points by earning experience points through combat and quests, and gaining levels. + +Each level you train for a skill costs more Training Points than before. + +## Usage: + + ~train~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/train.template b/_datafiles/world/default/templates/help/train.template deleted file mode 100644 index 8ace1a67..00000000 --- a/_datafiles/world/default/templates/help/train.template +++ /dev/null @@ -1,10 +0,0 @@ -.: Help for train - -The train command spends Training Points (TP) at guilds and other -training spots. - -You can earn Traning Points by earning experience points through combat -and quests, and gaining levels - -Each level you train for a skill costs more Training Points than before. - diff --git a/_datafiles/world/default/templates/help/unlock.md b/_datafiles/world/default/templates/help/unlock.md new file mode 100644 index 00000000..566fc49c --- /dev/null +++ b/_datafiles/world/default/templates/help/unlock.md @@ -0,0 +1,10 @@ +# Help for ~unlock~ + +The ~unlock~ command attempts to unlock any exit or container. +You'll need an appropriate *key* in your backpack or on your keyring. + +## Usage: + + ~unlock [exit name/container name]~ - This unlocks it if it is locked. + +**See also:** ~help lock~, ~help keyring~, ~help picklock~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/unlock.template b/_datafiles/world/default/templates/help/unlock.template deleted file mode 100644 index 2d88f4c1..00000000 --- a/_datafiles/world/default/templates/help/unlock.template +++ /dev/null @@ -1,10 +0,0 @@ -.: Help for unlock - -The unlock command attempts to unlock any exit or container. -You'll need an appropriate key in your backpack or on your keyring. - -Usage: - - unlock [exit name/container name] - This unlocks it if it is locked. - -See also: help lock, help keyring, help picklock diff --git a/_datafiles/world/default/templates/help/use.md b/_datafiles/world/default/templates/help/use.md new file mode 100644 index 00000000..c794ce76 --- /dev/null +++ b/_datafiles/world/default/templates/help/use.md @@ -0,0 +1,10 @@ +# Help for ~use~ + +The ~use~ command uses items (if they are usable). For example, a sleeping bag. + +## Usage: + + ~use sleeping bag~ + This would sleep in your sleepping bag. + +Find out more about referring to items by name by typing ~help item-names~. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/use.template b/_datafiles/world/default/templates/help/use.template deleted file mode 100644 index 822a4a89..00000000 --- a/_datafiles/world/default/templates/help/use.template +++ /dev/null @@ -1,11 +0,0 @@ -.: Help for use - -The use command uses items (if they are usable). For example, a sleeping bag. - -Usage: - - use sleeping bag - This would sleep in your sleepping bag. - -Find out more about referring to items by name by typing help item-names. - diff --git a/_datafiles/world/default/templates/help/whisper.md b/_datafiles/world/default/templates/help/whisper.md new file mode 100644 index 00000000..e7f53499 --- /dev/null +++ b/_datafiles/world/default/templates/help/whisper.md @@ -0,0 +1,8 @@ +# Help for ~whisper~ + +The ~whisper~ sends a message to another player. + +## Usage: + + ~whisper chuckles Hey what's up?~ + This will send a whisper to that players character anywhere in the realm. \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/whisper.template b/_datafiles/world/default/templates/help/whisper.template deleted file mode 100644 index 5743a6d4..00000000 --- a/_datafiles/world/default/templates/help/whisper.template +++ /dev/null @@ -1,9 +0,0 @@ -.: Help for whisper - -The whisper sends a message to another player. - -Usage: - - whisper chuckles Hey what's up? - This will send a whisper to that players character anywhere in the realm. - diff --git a/_datafiles/world/default/templates/help/who.md b/_datafiles/world/default/templates/help/who.md new file mode 100644 index 00000000..a52ee2f0 --- /dev/null +++ b/_datafiles/world/default/templates/help/who.md @@ -0,0 +1,7 @@ +# Help for ~who~ + +The ~who~ command tells you who is in the room with you (That you are aware of). + +## Usage: + + ~who~ \ No newline at end of file diff --git a/_datafiles/world/default/templates/help/who.template b/_datafiles/world/default/templates/help/who.template deleted file mode 100644 index 177f42bf..00000000 --- a/_datafiles/world/default/templates/help/who.template +++ /dev/null @@ -1,4 +0,0 @@ -.: Help for who - -The who command tells you who is in the room with you (That you are aware of) - diff --git a/_datafiles/world/default/users/1.yaml b/_datafiles/world/default/users/1.yaml index c8474524..e29ba163 100755 --- a/_datafiles/world/default/users/1.yaml +++ b/_datafiles/world/default/users/1.yaml @@ -17,10 +17,9 @@ character: other adventurers, granting them strength, wisdom, or fortune beyond their wildest dreams. Conversely, he can also mete out justice to those who would seek to disrupt the balance of the world, swiftly and decisively. - adjectives: - - zombie - roomid: 2 - zone: Frostfang + roomid: 487 + roomidonreset: 0 + zone: Frostfang Slums raceid: 2 stats: strength: @@ -65,18 +64,16 @@ character: list: - buffid: 28 permabuff: true - roundcounter: 3 + roundcounter: 22 triggersleft: 1000000000 - buffid: 29 permabuff: true - roundcounter: 11 + roundcounter: 15 triggersleft: 1000000000 - buffid: 39 permabuff: true + roundcounter: 4 triggersleft: 1000000000 - - buffid: 32 - roundcounter: 79 - triggersleft: 1 equipment: weapon: itemid: 10004 diff --git a/internal/buffs/buffspec.go b/internal/buffs/buffspec.go index 90615822..277d9511 100644 --- a/internal/buffs/buffspec.go +++ b/internal/buffs/buffspec.go @@ -47,8 +47,9 @@ const ( RemoveCurse Flag = `remove-curse` // Harmful flags - Poison Flag = `poison` - Drunk Flag = `drunk` + Poison Flag = `poison` + Drunk Flag = `drunk` + Tripping Flag = `tripping` // Useful flags Hidden Flag = `hidden` diff --git a/internal/characters/character.go b/internal/characters/character.go index 081439df..21613a23 100644 --- a/internal/characters/character.go +++ b/internal/characters/character.go @@ -50,6 +50,7 @@ type Character struct { Description string // A description of the character. Adjectives []string `yaml:"adjectives,omitempty"` // Decorative text for the name of the character (e.g. "sleeping", "dead", "wounded") RoomId int // The room id the character is in. + RoomIdOnReset int // The room they are sent to if their RoomId isn't found. Zone string // The zone the character is in. The folder the room can be located in too. RaceId int // Character race Stats stats.Statistics // Character stats diff --git a/internal/colorpatterns/colorpatterns.go b/internal/colorpatterns/colorpatterns.go index 7e963552..39bb7e87 100644 --- a/internal/colorpatterns/colorpatterns.go +++ b/internal/colorpatterns/colorpatterns.go @@ -10,8 +10,11 @@ import ( "strings" "time" + "unicode" + "github.com/GoMudEngine/GoMud/internal/configs" "github.com/GoMudEngine/GoMud/internal/mudlog" + "github.com/GoMudEngine/GoMud/internal/util" "github.com/GoMudEngine/ansitags" "github.com/mattn/go-runewidth" "github.com/pkg/errors" @@ -63,6 +66,94 @@ func ApplyColorPattern(input string, pattern string, method ...ColorizeStyle) st return ApplyColors(input, patternValues, method...) } +func ApplyCharacterWarping(input string) string { + + randomSymbols := []rune{'°', '•', '·', '˚', '˙', '✧', '✦', '✺', '~', '≈', '⋆'} + newString := strings.Builder{} + + inTagPlaceholder := false + + // + // Tokenize existing ansi tags to avoid colorizing them + // + // Regular expression to match ... tags + re := regexp.MustCompile(`]*>.*?`) + // Counter to keep track of the unique numbers + counter := 0 + preExistingTags := map[string]string{} + // Function to replace each match with a unique number + input = re.ReplaceAllStringFunc(input, func(match string) string { + counter++ + tag := `:` + strconv.Itoa(counter) + preExistingTags[tag] = match + return tag + }) + // + // End tokenization + // + + // Color change on a per character basis (not spaces), reverses at the end + for _, runeChar := range input { + + // Handle placeholder tags that look like :123 + if inTagPlaceholder { + if runeChar != 32 { + newString.WriteString(string(runeChar)) + continue + } + inTagPlaceholder = false + } else { + if runeChar == ':' { + inTagPlaceholder = true + newString.WriteString(string(runeChar)) + continue + } + } + + if runeChar == 32 { // space + + if util.Rand(5) == 0 { + runeChar = randomSymbols[util.Rand(len(randomSymbols))] + } + + } else { + if util.Rand(3) == 0 { + runeChar = unicode.ToUpper(runeChar) + } + if util.Rand(5) == 0 { + switch runeChar { + case 'a': + runeChar = 'ɑ' + case 'A': + runeChar = 'Λ' + case 'b': + runeChar = 'Ƅ' + case 'E': + runeChar = 'Ξ' + case 'O': + runeChar = 'Θ' + case 'S': + runeChar = '§' + case 't': + runeChar = 'τ' + case 'u': + runeChar = 'υ' + } + + } + } + newString.WriteRune(runeChar) + } + + finalString := newString.String() + + for tmp, replacement := range preExistingTags { + finalString = strings.Replace(finalString, tmp, replacement, -1) + } + + return finalString +} + func ApplyColors(input string, patternValues []int, method ...ColorizeStyle) string { patternValueLength := len(patternValues) diff --git a/internal/conversations/context.md b/internal/conversations/context.md index 31b82ca4..b62434ec 100644 --- a/internal/conversations/context.md +++ b/internal/conversations/context.md @@ -128,26 +128,28 @@ YAML-loadable conversation definition: ### Conversation YAML Structure ```yaml # Example conversation file: conversations/frostfang/123.yaml -- Supported: +- + Supported: # A map of lowercase names of "Initiator" (#1) to array of "Participant" (#2) names allowed to use this conversation. "guard": ["player", "visitor"] "*": ["*"] # Universal conversation Conversation: - - ["#1", "say Hello there, traveler!"] - - ["#2", "say Greetings, guard."] - - ["#1", "say Welcome to our town."] - - ["#2", "emote nods politely"] + - ["#1 say Hello there, traveler!"] + - ["#2 say Greetings, guard."] + - ["#1 say Welcome to our town."] + - ["#2 emote nods politely"] -- Supported: +- + Supported: "guard": ["merchant"] Conversation: - - ["#1", "say Any goods to declare?"] - - ["#2", "say Just the usual wares."] + - ["#1 say Any goods to declare?"] + - ["#2 say Just the usual wares."] ``` ### Command Format - **Participant Prefix**: `#1` (initiator) or `#2` (participant) -- **Command Structure**: `["#1", "command arguments"]` -- **Action Types**: Any valid mob command (say, emote, look, etc.) +- **Command Structure**: `["#1 command arguments"]` - participant identifier and command are in a single string +- **Action Types**: Any valid mob command (say, sayto, emote, look, etc.) ## Usage Patterns @@ -212,77 +214,3 @@ if conversations.HasConverseFile(mobId, zoneName) { - **Cultural Context**: Zone-appropriate dialogue and interactions - **Immersion**: Rich, contextual NPC interactions enhance world building - **Scalable Content**: Easy addition of new conversations per zone - -## Performance Considerations - -### Caching Strategy -- **File Existence**: Cache file existence checks to reduce filesystem access -- **Conversation Loading**: Load conversations only when needed -- **Memory Cleanup**: Automatic cleanup of inactive conversations -- **Usage Tracking**: Efficient tracking of conversation usage patterns - -### Memory Management -- **Lightweight Storage**: Minimal memory footprint per active conversation -- **Automatic Cleanup**: Periodic removal of stale conversations -- **Efficient Indexing**: Fast lookup of active conversations by ID -- **Resource Limits**: Implicit limits through automatic cleanup - -### File System Optimization -- **Organized Structure**: Hierarchical file organization for efficient access -- **Lazy Loading**: Conversations loaded only when participants match -- **Error Handling**: Graceful handling of missing or malformed files -- **Path Sanitization**: Consistent file path generation - -## Future Enhancements - -### Advanced Features -- **Branching Conversations**: Multiple conversation paths based on conditions -- **Dynamic Content**: Conversations that change based on game state -- **Emotional States**: NPC mood affecting conversation selection -- **Relationship Tracking**: Conversation history affecting future interactions - -### Enhanced Selection -- **Weighted Selection**: Probability-based conversation selection -- **Conditional Conversations**: Conversations requiring specific conditions -- **Time-Based Conversations**: Conversations available at certain times -- **Reputation-Based**: Conversations based on player reputation - -### Content Management -- **Conversation Editor**: Visual tool for creating conversations -- **Validation Tools**: Tools for validating conversation syntax -- **Import/Export**: Tools for sharing conversations between servers -- **Version Control**: Track changes to conversation content - -### Performance Improvements -- **Preloading**: Preload frequently used conversations -- **Compression**: Compressed storage for large conversation sets -- **Database Integration**: Optional database storage for conversations -- **Streaming**: Stream large conversations for memory efficiency - -## Security and Validation - -### Input Validation -- **Name Sanitization**: Ensure participant names are properly sanitized -- **Command Validation**: Validate conversation commands for safety -- **Path Security**: Prevent path traversal attacks through zone names -- **Resource Limits**: Prevent resource exhaustion through conversation abuse - -### Content Safety -- **Command Filtering**: Filter dangerous or inappropriate commands -- **Content Validation**: Validate conversation content for appropriateness -- **Error Handling**: Safe handling of malformed conversation files -- **Access Control**: Ensure only authorized conversations are accessible - -## Administrative Features - -### Monitoring and Analytics -- **Usage Statistics**: Track conversation usage patterns -- **Performance Metrics**: Monitor conversation system performance -- **Error Tracking**: Log and track conversation-related errors -- **Content Analysis**: Analyze conversation effectiveness and popularity - -### Content Management -- **Dynamic Loading**: Hot-reload conversations without server restart -- **Content Validation**: Validate conversation files before deployment -- **Backup and Recovery**: Backup and restore conversation content -- **Version Management**: Track conversation content versions \ No newline at end of file diff --git a/internal/hooks/PlayerSpawn_HandleJoin.go b/internal/hooks/PlayerSpawn_HandleJoin.go index 1072b778..127b6756 100644 --- a/internal/hooks/PlayerSpawn_HandleJoin.go +++ b/internal/hooks/PlayerSpawn_HandleJoin.go @@ -34,15 +34,34 @@ func HandleJoin(e events.Event) events.ListenerReturn { users.RemoveZombieUser(evt.UserId) room := rooms.LoadRoom(user.Character.RoomId) - if room == nil { + sendResetMessage := false + + // If an onreset room is set, send to it, then clear it. + // This way, if they were in an ephemeral chunk and it has been cleared, we + // handle sending them to whatever "reset" room was defined (if any) + if room == nil && user.Character.RoomIdOnReset != 0 { + mudlog.Warn("HandleJoin", "msg", fmt.Sprintf("room %d not found, trying RoomIdOnReset %d", user.Character.RoomId, user.Character.RoomIdOnReset)) + room = rooms.LoadRoom(user.Character.RoomIdOnReset) + + if room != nil { + sendResetMessage = true + user.Character.RoomId = user.Character.RoomIdOnReset + } + + user.Character.RoomIdOnReset = 0 + } + // If still no room was found, send to the zero room (default world start room) + if room == nil { mudlog.Error("EnterWorld", "error", fmt.Sprintf(`room %d not found`, user.Character.RoomId)) if err := rooms.MoveToRoom(user.UserId, 0); err != nil { mudlog.Error("EnterWorld", "msg", "could not move to room 0", "error", err) } + // Load whatever default room they have been assigned room = rooms.LoadRoom(user.Character.RoomId) + sendResetMessage = true } // TODO HERE @@ -62,6 +81,11 @@ func HandleJoin(e events.Event) events.ListenerReturn { } if room != nil { + + if sendResetMessage { + user.SendText("A portal opens before you and you feel an intense pulling... you can't escape it... You are transported elsewhere!") + } + if doLook, err := scripting.TryRoomScriptEvent(`onEnter`, user.UserId, user.Character.RoomId); err != nil || doLook { user.CommandFlagged(`look`, events.CmdSecretly) // Do a secret look. } diff --git a/internal/inputhandlers/cleanser.go b/internal/inputhandlers/cleanser.go index 5e57c817..8b89261f 100644 --- a/internal/inputhandlers/cleanser.go +++ b/internal/inputhandlers/cleanser.go @@ -29,7 +29,7 @@ func CleanserInputHandler(clientInput *connections.ClientInput, sharedState map[ // send backspace, space, backspace if len(clientInput.Buffer) > 0 { connections.SendTo([]byte{term.ASCII_BACKSPACE, term.ASCII_SPACE, term.ASCII_BACKSPACE}, clientInput.ConnectionId) - + // Handle UTF-8 properly by removing the last complete character (rune) bufferStr := string(clientInput.Buffer) if len(bufferStr) > 0 { diff --git a/internal/inputhandlers/cleanser_test.go b/internal/inputhandlers/cleanser_test.go index d1269bee..70e6d695 100644 --- a/internal/inputhandlers/cleanser_test.go +++ b/internal/inputhandlers/cleanser_test.go @@ -119,4 +119,4 @@ func TestCleanserInputHandler_NoBackspace(t *testing.T) { if clientInput.BSPressed { t.Error("Expected BSPressed to be false") } -} \ No newline at end of file +} diff --git a/internal/mapper/mapper.go b/internal/mapper/mapper.go index 044d5d50..a6c15492 100644 --- a/internal/mapper/mapper.go +++ b/internal/mapper/mapper.go @@ -998,15 +998,15 @@ func PreCacheMaps() { func validateRoomBiomes() { missingBiomeCount := 0 invalidBiomeCount := 0 - + for _, roomId := range rooms.GetAllRoomIds() { room := rooms.LoadRoom(roomId) if room == nil { continue } - + originalBiome := room.Biome - + // Check if room has no biome if originalBiome == "" { zoneBiome := rooms.GetZoneBiome(room.Zone) @@ -1022,7 +1022,7 @@ func validateRoomBiomes() { } } } - + if missingBiomeCount > 0 || invalidBiomeCount > 0 { mudlog.Info("Biome validation complete", "missing", missingBiomeCount, "invalid", invalidBiomeCount) } diff --git a/internal/mobcommands/unlock.go b/internal/mobcommands/unlock.go new file mode 100644 index 00000000..713c2a7c --- /dev/null +++ b/internal/mobcommands/unlock.go @@ -0,0 +1,61 @@ +package mobcommands + +import ( + "fmt" + "strings" + + "github.com/GoMudEngine/GoMud/internal/mobs" + "github.com/GoMudEngine/GoMud/internal/rooms" + "github.com/GoMudEngine/GoMud/internal/util" +) + +func Unlock(rest string, mob *mobs.Mob, room *rooms.Room) (bool, error) { + + args := util.SplitButRespectQuotes(strings.ToLower(rest)) + + if len(args) < 1 { + return true, nil + } + + containerName := room.FindContainerByName(args[0]) + exitName, _ := room.FindExitByName(args[0]) + + if containerName != `` { + + container := room.Containers[containerName] + + if !container.Lock.IsLocked() { + return true, nil + } + + container.Lock.SetUnlocked() + room.Containers[containerName] = container + + room.PlaySound(`change`, `other`) + + room.SendText(fmt.Sprintf(`%s unlocks the %s.`, mob.Character.Name, containerName)) + + return true, nil + + } else if exitName != `` { + + exitInfo, _ := room.GetExitInfo(exitName) + + if !exitInfo.Lock.IsLocked() { + return true, nil + } + + exitInfo.Lock.SetUnlocked() + room.SetExitLock(exitName, false) + + room.PlaySound(`change`, `other`) + + room.SendText(fmt.Sprintf(`%s unlocks the %s lock`, mob.Character.Name, exitName)) + + return true, nil + + } + + return true, nil + +} diff --git a/internal/procedural/gridmaze.go b/internal/procedural/gridmaze.go new file mode 100644 index 00000000..a72a583a --- /dev/null +++ b/internal/procedural/gridmaze.go @@ -0,0 +1,539 @@ +package procedural + +import ( + "hash/fnv" + "math/rand" + "time" +) + +// GridRoom implements the MazeRoom interface +type GridRoom struct { + x, y, z int + connections []*GridRoom + step int + distanceFromStart int + isStart bool + isEnd bool +} + +func (r *GridRoom) GetPosition() (int, int, int) { + return r.x, r.y, r.z +} + +func (r *GridRoom) GetConnections() []MazeRoom { + connections := make([]MazeRoom, len(r.connections)) + for i, conn := range r.connections { + connections[i] = conn + } + return connections +} + +func (r *GridRoom) IsConnectedTo(room MazeRoom) bool { + if room == nil { + return false + } + rx, ry, rz := room.GetPosition() + for _, conn := range r.connections { + if conn.x == rx && conn.y == ry && conn.z == rz { + return true + } + } + return false +} + +func (r *GridRoom) GetStep() int { + return r.step +} + +func (r *GridRoom) IsStart() bool { + return r.isStart +} + +func (r *GridRoom) IsEnd() bool { + return r.isEnd +} + +func (r *GridRoom) IsDeadEnd() bool { + return len(r.connections) == 1 +} + +func (r *GridRoom) GetDistanceFromStart() int { + return r.distanceFromStart +} + +func (r *GridRoom) addConnection(other *GridRoom) { + if r.IsConnectedTo(other) { + return + } + r.connections = append(r.connections, other) + other.connections = append(other.connections, r) +} + +// GridMaze implements the Maze interface +type GridMaze struct { + rooms Maze2D + startX, startY int + endX, endY int + criticalPath []*GridRoom + rand *rand.Rand +} + +// NewGridMaze creates a new grid maze generator +func NewGridMaze() *GridMaze { + return &GridMaze{ + rand: rand.New(rand.NewSource(time.Now().UnixNano())), + } +} + +func (m *GridMaze) Generate2D(xMax, yMax int, seed ...string) [][]*GridRoom { + // Set up random generator with seed if provided + if len(seed) > 0 && seed[0] != "" { + h := fnv.New64a() + h.Write([]byte(seed[0])) + m.rand = rand.New(rand.NewSource(int64(h.Sum64()))) + } + m.rooms = make(Maze2D, yMax) + for y := range m.rooms { + m.rooms[y] = make([]*GridRoom, xMax) + } + + // Create all rooms initially + m.createAllRooms(xMax, yMax) + + // Generate maze using recursive backtracking + m.generateMazeRecursiveBacktracking(xMax, yMax) + + // Set start and end points + m.setStartAndEnd(xMax, yMax) + + // Calculate distances from start + m.calculateDistancesFromStart() + + // Find critical path and set steps + m.findCriticalPath() + + // Add additional connections to create more branching and dead ends + m.addAdditionalConnections(xMax, yMax) + + // Remove some rooms randomly, but protect critical path and preserve dead ends + m.removeRoomsProtectingPath(xMax, yMax) + + // Remove any orphaned rooms (not reachable from start) + m.removeOrphanedRooms(xMax, yMax) + + // Recalculate after room removal and connection addition + m.calculateDistancesFromStart() + m.findCriticalPath() + + // Convert to interface slice + result := make([][]*GridRoom, yMax) + for y := range result { + result[y] = make([]*GridRoom, xMax) + for x := range result[y] { + if m.rooms[y][x] != nil { + result[y][x] = m.rooms[y][x] + } + } + } + + return result +} + +func (m *GridMaze) createAllRooms(xMax, yMax int) { + // Create all rooms initially - maze algorithm will determine connectivity + for x := 0; x < xMax; x++ { + for y := 0; y < yMax; y++ { + m.rooms[y][x] = &GridRoom{ + x: x, y: y, + connections: make([]*GridRoom, 0), + } + } + } +} + +func (m *GridMaze) setStartAndEnd(xMax, yMax int) { + // Collect all available rooms + availableRooms := make([][2]int, 0) + for x := 0; x < xMax; x++ { + for y := 0; y < yMax; y++ { + if m.rooms[y][x] != nil { + availableRooms = append(availableRooms, [2]int{x, y}) + } + } + } + + if len(availableRooms) == 0 { + return + } + + // Randomly select start position + startIdx := m.rand.Intn(len(availableRooms)) + m.startX, m.startY = availableRooms[startIdx][0], availableRooms[startIdx][1] + m.rooms[m.startY][m.startX].isStart = true + + if len(availableRooms) == 1 { + return + } + + // For end position, use a weighted random selection that favors distant rooms + // but still allows for some variety + weightedCandidates := make([]weightedCandidate, 0) + for _, pos := range availableRooms { + x, y := pos[0], pos[1] + if x == m.startX && y == m.startY { + continue // Skip start position + } + + // Calculate Manhattan distance from start + dist := abs(x-m.startX) + abs(y-m.startY) + // Weight increases with distance, but add base weight for variety + weight := dist + 1 // Base weight of 1 ensures all rooms have some chance + weightedCandidates = append(weightedCandidates, weightedCandidate{x: x, y: y, weight: weight}) + } + + if len(weightedCandidates) > 0 { + selected := m.selectWeightedRandom(weightedCandidates) + m.endX, m.endY = selected.x, selected.y + m.rooms[m.endY][m.endX].isEnd = true + } +} + +// weightedCandidate represents a position with an associated weight for selection +type weightedCandidate struct { + x, y int + weight int +} + +// selectWeightedRandom selects a candidate based on weighted probability +func (m *GridMaze) selectWeightedRandom(candidates []weightedCandidate) weightedCandidate { + // Calculate total weight + totalWeight := 0 + for _, candidate := range candidates { + totalWeight += candidate.weight + } + + // Select random value within total weight + randomValue := m.rand.Intn(totalWeight) + + // Find the candidate that corresponds to this random value + currentWeight := 0 + for _, candidate := range candidates { + currentWeight += candidate.weight + if randomValue < currentWeight { + return candidate + } + } + + // Fallback (should never reach here) + return candidates[len(candidates)-1] +} + +func (m *GridMaze) generateMazeRecursiveBacktracking(xMax, yMax int) { + // Recursive backtracking algorithm for maze generation + visited := make([][]bool, yMax) + for y := range visited { + visited[y] = make([]bool, xMax) + } + + // Start from a random position + startX := m.rand.Intn(xMax) + startY := m.rand.Intn(yMax) + + m.backtrack(startX, startY, visited, xMax, yMax) +} + +func (m *GridMaze) backtrack(x, y int, visited [][]bool, xMax, yMax int) { + visited[y][x] = true + + // Get all valid neighbors in random order + directions := [][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}} + m.shuffleDirections(directions) + + for _, dir := range directions { + nx, ny := x+dir[0], y+dir[1] + + // Check if neighbor is valid and unvisited + if nx >= 0 && nx < xMax && ny >= 0 && ny < yMax && !visited[ny][nx] { + // Connect current room to neighbor + m.rooms[y][x].addConnection(m.rooms[ny][nx]) + + // Recursively visit neighbor + m.backtrack(nx, ny, visited, xMax, yMax) + } + } +} + +func (m *GridMaze) shuffleDirections(directions [][2]int) { + for i := len(directions) - 1; i > 0; i-- { + j := m.rand.Intn(i + 1) + directions[i], directions[j] = directions[j], directions[i] + } +} + +func (m *GridMaze) removeRoom(x, y int) { + if m.rooms[y][x] == nil { + return + } + + // Remove all connections to this room + for _, conn := range m.rooms[y][x].connections { + for i, backConn := range conn.connections { + if backConn == m.rooms[y][x] { + conn.connections = append(conn.connections[:i], conn.connections[i+1:]...) + break + } + } + } + + // Remove the room + m.rooms[y][x] = nil +} + +func (m *GridMaze) removeRoomsProtectingPath(xMax, yMax int) { + // Create a set of critical path rooms to protect + criticalPathSet := make(map[*GridRoom]bool) + for _, room := range m.criticalPath { + criticalPathSet[room] = true + } + + // Remove some rooms + for x := 0; x < xMax; x++ { + for y := 0; y < yMax; y++ { + room := m.rooms[y][x] + if room == nil { + continue + } + + if criticalPathSet[room] { + continue + } + + if m.rand.Float32() < 0.5 { + // Only remove rooms that are not adjacent to critical path + if m.canRemoveWithoutDisconnectingPath(x, y) { + m.removeRoom(x, y) + } + } + + } + } +} + +func (m *GridMaze) canRemoveWithoutDisconnectingPath(x, y int) bool { + room := m.rooms[y][x] + if room == nil { + return false + } + + // Don't remove rooms that are directly on the critical path + if room.GetStep() > 0 { + return false + } + + // Don't remove rooms that would isolate other rooms + // Check if removing this room would create orphaned areas + if len(room.connections) > 1 { + // Temporarily remove connections and check connectivity + originalConnections := make([]*GridRoom, len(room.connections)) + copy(originalConnections, room.connections) + + // If this room bridges different areas, keep it + for i, conn1 := range room.connections { + for j, conn2 := range room.connections { + if i != j && !m.areConnectedWithoutRoom(conn1, conn2, room) { + return false + } + } + } + } + + return true +} + +func (m *GridMaze) removeOrphanedRooms(xMax, yMax int) { + if m.rooms[m.startY][m.startX] == nil { + return + } + + // Use BFS to find all rooms reachable from the start room + reachable := make(map[*GridRoom]bool) + queue := []*GridRoom{m.rooms[m.startY][m.startX]} + reachable[m.rooms[m.startY][m.startX]] = true + + for len(queue) > 0 { + current := queue[0] + queue = queue[1:] + + for _, conn := range current.connections { + if !reachable[conn] { + reachable[conn] = true + queue = append(queue, conn) + } + } + } + + // Remove any rooms that are not reachable from the start + for x := 0; x < xMax; x++ { + for y := 0; y < yMax; y++ { + room := m.rooms[y][x] + if room != nil && !reachable[room] { + m.removeRoom(x, y) + } + } + } +} + +func (m *GridMaze) calculateDistancesFromStart() { + if m.rooms[m.startY][m.startX] == nil { + return + } + + // Use BFS to calculate distances from start + queue := []*GridRoom{m.rooms[m.startY][m.startX]} + visited := make(map[*GridRoom]bool) + + m.rooms[m.startY][m.startX].distanceFromStart = 0 + visited[m.rooms[m.startY][m.startX]] = true + + for len(queue) > 0 { + current := queue[0] + queue = queue[1:] + + for _, conn := range current.connections { + if !visited[conn] { + visited[conn] = true + conn.distanceFromStart = current.distanceFromStart + 1 + queue = append(queue, conn) + } + } + } +} + +func (m *GridMaze) findCriticalPath() { + if m.rooms[m.startY][m.startX] == nil || m.rooms[m.endY][m.endX] == nil { + return + } + + // Use BFS to find shortest path + queue := []*GridRoom{m.rooms[m.startY][m.startX]} + visited := make(map[*GridRoom]bool) + parent := make(map[*GridRoom]*GridRoom) + + visited[m.rooms[m.startY][m.startX]] = true + + for len(queue) > 0 { + current := queue[0] + queue = queue[1:] + + if current == m.rooms[m.endY][m.endX] { + // Reconstruct path + path := make([]*GridRoom, 0) + for room := current; room != nil; room = parent[room] { + path = append([]*GridRoom{room}, path...) + } + + // Set steps + for i, room := range path { + room.step = i + 1 + } + + m.criticalPath = path + return + } + + for _, conn := range current.connections { + if !visited[conn] { + visited[conn] = true + parent[conn] = current + queue = append(queue, conn) + } + } + } +} + +func (m *GridMaze) GetStart() (int, int) { + return m.startX, m.startY +} + +func (m *GridMaze) GetEnd() (int, int) { + return m.endX, m.endY +} + +func (m *GridMaze) GetCriticalPath() []MazeRoom { + path := make([]MazeRoom, len(m.criticalPath)) + for i, room := range m.criticalPath { + path[i] = room + } + return path +} + +// areConnectedWithoutRoom checks if two rooms are connected without going through a specific room +func (m *GridMaze) areConnectedWithoutRoom(room1, room2, excludeRoom *GridRoom) bool { + if room1 == room2 { + return true + } + + visited := make(map[*GridRoom]bool) + queue := []*GridRoom{room1} + visited[room1] = true + visited[excludeRoom] = true // Exclude the room we're testing + + for len(queue) > 0 { + current := queue[0] + queue = queue[1:] + + if current == room2 { + return true + } + + for _, conn := range current.connections { + if !visited[conn] { + visited[conn] = true + queue = append(queue, conn) + } + } + } + + return false +} + +// addAdditionalConnections creates more branching paths to increase dead ends +func (m *GridMaze) addAdditionalConnections(xMax, yMax int) { + // Add some additional connections to create more complex paths + // This increases the number of potential dead ends + connectionAttempts := (xMax * yMax) / 10 // Attempt connections for 10% of grid size + + for i := 0; i < connectionAttempts; i++ { + x := m.rand.Intn(xMax) + y := m.rand.Intn(yMax) + + if m.rooms[y][x] == nil { + continue + } + + // Try to connect to a nearby room that's not already connected + directions := [][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}} + m.shuffleDirections(directions) + + for _, dir := range directions { + nx, ny := x+dir[0], y+dir[1] + + if nx >= 0 && nx < xMax && ny >= 0 && ny < yMax && + m.rooms[ny][nx] != nil && !m.rooms[y][x].IsConnectedTo(m.rooms[ny][nx]) { + + // Only add connection if it doesn't create too dense connectivity + if len(m.rooms[y][x].connections) < 3 && len(m.rooms[ny][nx].connections) < 3 { + m.rooms[y][x].addConnection(m.rooms[ny][nx]) + break + } + } + } + } +} + +func abs(x int) int { + if x < 0 { + return -x + } + return x +} diff --git a/internal/procedural/gridmaze_test.go b/internal/procedural/gridmaze_test.go new file mode 100644 index 00000000..35bb7976 --- /dev/null +++ b/internal/procedural/gridmaze_test.go @@ -0,0 +1,326 @@ +package procedural + +import ( + "fmt" + "strings" + "testing" +) + +func TestGridMaze_Generate(t *testing.T) { + tests := []struct { + name string + xMax int + yMax int + seeds []string // Test with specific seeds for consistent results + }{ + { + name: "Very Small maze 5x5", + xMax: 5, + yMax: 5, + seeds: []string{"abcdef"}, + }, + { + name: "Small maze 8x8", + xMax: 8, + yMax: 8, + seeds: []string{"one"}, + }, + { + name: "Medium maze 12x12", + xMax: 12, + yMax: 12, + seeds: []string{"four"}, + }, + { + name: "Large maze 25x5", + xMax: 25, + yMax: 5, + seeds: []string{"five"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + for i, seed := range tt.seeds { + t.Run(fmt.Sprintf("seed_%s", seed), func(t *testing.T) { + // Create maze with deterministic seed + maze := NewGridMaze() + + // Generate the maze + rooms := maze.Generate2D(tt.xMax, tt.yMax, seed) + + // Verify basic properties + if len(rooms) != tt.yMax { + t.Errorf("Expected %d rows, got %d", tt.yMax, len(rooms)) + } + + for y := range rooms { + if len(rooms[y]) != tt.xMax { + t.Errorf("Expected %d columns in row %d, got %d", tt.xMax, y, len(rooms[y])) + } + } + + // Verify start and end points exist + startX, startY := maze.GetStart() + endX, endY := maze.GetEnd() + + if rooms[startY][startX] == nil { + t.Error("Start room is nil") + } + if rooms[endY][endX] == nil { + t.Error("End room is nil") + } + + if !rooms[startY][startX].IsStart() { + t.Error("Start room doesn't report as start") + } + if !rooms[endY][endX].IsEnd() { + t.Error("End room doesn't report as end") + } + + // Verify critical path exists + criticalPath := maze.GetCriticalPath() + if len(criticalPath) == 0 { + t.Error("Critical path is empty") + } + + // Verify critical path starts at start and ends at end + if len(criticalPath) > 0 { + firstRoom := criticalPath[0] + lastRoom := criticalPath[len(criticalPath)-1] + + fx, fy, _ := firstRoom.GetPosition() + lx, ly, _ := lastRoom.GetPosition() + + if fx != startX || fy != startY { + t.Errorf("Critical path doesn't start at start room: expected (%d,%d), got (%d,%d)", startX, startY, fx, fy) + } + if lx != endX || ly != endY { + t.Errorf("Critical path doesn't end at end room: expected (%d,%d), got (%d,%d)", endX, endY, lx, ly) + } + } + + // Render the maze beautifully + rendered := renderMaze(rooms, maze, tt.xMax, tt.yMax) + + // Print the maze (this will show in test output with -v flag) + t.Logf("\n=== Maze %dx%d (seed: %s) ===\n%s\n", tt.xMax, tt.yMax, seed, rendered) + + // Verify maze has some complexity (not all rooms should exist due to removal) + roomCount := 0 + for x := 0; x < tt.xMax; x++ { + for y := 0; y < tt.yMax; y++ { + if rooms[y][x] != nil { + roomCount++ + } + } + } + + expectedMinRooms := (tt.xMax * tt.yMax) / 2 // At least half should remain + if roomCount < expectedMinRooms { + t.Logf("Warning: Maze seems sparse with only %d/%d rooms", roomCount, tt.xMax*tt.yMax) + } + + // Test connectivity of critical path + for i := 0; i < len(criticalPath)-1; i++ { + current := criticalPath[i] + next := criticalPath[i+1] + + if !current.IsConnectedTo(next) { + t.Errorf("Critical path broken: room at step %d not connected to step %d", i+1, i+2) + } + } + + // Only run first seed for large mazes to avoid too much output + if tt.xMax >= 16 && i > 0 { + return + } + }) + } + }) + } +} + +func TestGridMaze_Properties(t *testing.T) { + maze := NewGridMaze() + maze.rand.Seed(12345) // Deterministic for testing + + rooms := maze.Generate2D(10, 8) + + // Test room properties + roomsFound := 0 + deadEnds := 0 + criticalPathRooms := 0 + + var z = 0 + for x := 0; x < 10; x++ { + for y := 0; y < 8; y++ { + room := rooms[y][x] + if room == nil { + continue + } + + roomsFound++ + + // Test position consistency + rx, ry, rz := room.GetPosition() + if rx != x || ry != y || rz != z { + t.Errorf("Room position mismatch: expected (%d,%d,%d), got (%d,%d,%d)", x, y, z, rx, ry, rz) + } + + // Test connections are bidirectional + connections := room.GetConnections() + for _, conn := range connections { + if !conn.IsConnectedTo(room) { + t.Error("Connection is not bidirectional") + } + } + + // Count dead ends + if room.IsDeadEnd() { + deadEnds++ + } + + // Count critical path rooms + if room.GetStep() > 0 { + criticalPathRooms++ + } + + // Test distance from start is reasonable + dist := room.GetDistanceFromStart() + if dist < 0 { + t.Errorf("Negative distance from start: %d", dist) + } + } + } + + t.Logf("Maze statistics: %d rooms, %d dead ends, %d critical path rooms", roomsFound, deadEnds, criticalPathRooms) + + // Verify we have some rooms + if roomsFound == 0 { + t.Error("No rooms found in maze") + } + + // Verify critical path length matches what we found + criticalPath := maze.GetCriticalPath() + if len(criticalPath) != criticalPathRooms { + t.Errorf("Critical path length mismatch: expected %d, got %d", criticalPathRooms, len(criticalPath)) + } +} + +// renderMaze creates a beautiful ASCII representation of the maze +func renderMaze(rooms [][]*GridRoom, maze *GridMaze, xMax, yMax int) string { + var result strings.Builder + + // Create a larger grid to show walls and passages + displayWidth := xMax*4 + 2 + displayHeight := yMax*2 + 2 + display := make([][]rune, displayHeight) + for i := range display { + display[i] = make([]rune, displayWidth) + for j := range display[i] { + display[i][j] = ' ' + } + } + + // Fill in walls initially + for y := 0; y < displayHeight; y++ { + for x := 0; x < displayWidth; x++ { + display[y][x] = '█' + } + } + + // Get critical path for highlighting + criticalPath := maze.GetCriticalPath() + criticalPathSet := make(map[MazeRoom]bool) + for _, room := range criticalPath { + criticalPathSet[room] = true + } + + roundCount := 0 + // Process each room + for x := 0; x < xMax; x++ { + for y := 0; y < yMax; y++ { + room := rooms[y][x] + if room == nil { + continue + } + + roundCount++ + + // Calculate display position + displayX := x*4 + 2 + displayY := y*2 + 1 + + // Choose room symbol + var roomSymbol rune + if room.IsStart() { + roomSymbol = 'S' + } else if room.IsEnd() { + roomSymbol = 'E' + } else if criticalPathSet[room] { + roomSymbol = '.' // Highlight critical path + } else if room.IsDeadEnd() { + roomSymbol = '☠' + } else { + roomSymbol = ' ' + } + + // Place room symbol + display[displayY][displayX] = roomSymbol + display[displayY][displayX+1] = roomSymbol + + // Draw connections + connections := room.GetConnections() + for _, conn := range connections { + connX, connY, _ := conn.GetPosition() + + // Only draw if connection is to adjacent room to avoid duplicates + if connX == x && connY == y+1 { // Vert-Down + display[displayY+1][displayX] = ' ' + display[displayY+1][displayX+1] = ' ' + } else if connX == x+1 && connY == y { // Right + display[displayY][displayX+2] = ' ' + display[displayY][displayX+3] = ' ' + } + } + } + } + + // Convert display to string with nice borders + result.WriteString("┌") + for x := 0; x < displayWidth; x++ { + result.WriteString("─") + } + result.WriteString("┐\n") + + for y := 0; y < displayHeight; y++ { + result.WriteString("│") + for x := 0; x < displayWidth; x++ { + char := display[y][x] + if char == '█' { + result.WriteString("█") + } else { + result.WriteRune(char) + } + } + result.WriteString("│\n") + } + + result.WriteString("└") + for x := 0; x < displayWidth; x++ { + result.WriteString("─") + } + result.WriteString("┘\n") + + // Add legend + result.WriteString("\nLegend: SS=Start, EE=End, ..=Critical Path, ☠☠=Dead End, ██=Wall\n") + + // Add statistics + startX, startY := maze.GetStart() + endX, endY := maze.GetEnd() + result.WriteString(fmt.Sprintf("Start: (%d,%d), End: (%d,%d), Room Count: %d, Critical Path Length: %d\n", + startX, startY, endX, endY, roundCount, len(criticalPath))) + + return result.String() +} diff --git a/internal/procedural/procedural.go b/internal/procedural/procedural.go new file mode 100644 index 00000000..28a80eb7 --- /dev/null +++ b/internal/procedural/procedural.go @@ -0,0 +1,51 @@ +package procedural + +// [y][x] +type Maze2D [][]*GridRoom + +// [z][y][x] +type Maze3D [][][]*GridRoom + +// MazeRoom represents a single room/space in the maze +type MazeRoom interface { + // GetPosition returns the x, y, z coordinates of this room + GetPosition() (int, int, int) + + // GetConnections returns all rooms this room connects to + GetConnections() []MazeRoom + + // IsConnectedTo checks if this room is connected to another room + IsConnectedTo(room MazeRoom) bool + + // GetStep returns the step number on the critical path (0 if not on critical path) + GetStep() int + + // IsStart returns true if this is the start room + IsStart() bool + + // IsEnd returns true if this is the end room + IsEnd() bool + + // IsDeadEnd returns true if this room is a dead end (only one connection) + IsDeadEnd() bool + + // GetDistanceFromStart returns the number of steps from the start room + GetDistanceFromStart() int +} + +// Maze represents a 2D maze generator +type Maze interface { + // Generate creates a new maze with the specified dimensions + // Optional seed string can be provided for deterministic generation + // Returns a 2D slice where [x][y] contains a MazeRoom or nil + Generate2D(xMax, yMax int, seed ...string) Maze2D + + // GetStart returns the starting room position + GetStart() (int, int) + + // GetEnd returns the ending room position + GetEnd() (int, int) + + // GetCriticalPath returns the rooms on the critical path from start to end + GetCriticalPath() []MazeRoom +} diff --git a/internal/procedural/rooms.go b/internal/procedural/rooms.go new file mode 100644 index 00000000..218edf43 --- /dev/null +++ b/internal/procedural/rooms.go @@ -0,0 +1,150 @@ +package procedural + +import ( + "github.com/GoMudEngine/GoMud/internal/exit" + "github.com/GoMudEngine/GoMud/internal/rooms" +) + +func CreateEphemeralMaze2D(mazeRooms [][]*GridRoom) (allRoomIds []int, startRoomId int, endRoomId int) { + + startRoomId = 0 + endRoomId = 0 + + mazeH := len(mazeRooms) + mazeW := len(mazeRooms[0]) + + roomCt := 0 + mazeRoomToTmpRoomId := map[MazeRoom]int{} + + for x := 0; x < mazeW; x++ { + for y := 0; y < mazeH; y++ { + + mazeRoomNow := mazeRooms[y][x] + + if mazeRoomNow == nil { + continue + } + + roomCt++ + } + } + + allRoomIds, _ = rooms.CreateEmptyEphemeralRooms(roomCt) + + nextTmpRoomId := 0 + + for y := 0; y < mazeH; y++ { + for x := 0; x < mazeW; x++ { + + if mazeRooms[y][x] == nil { + continue + } + + tmpId1, ok := mazeRoomToTmpRoomId[mazeRooms[y][x]] + if !ok { + tmpId1 = allRoomIds[nextTmpRoomId] + mazeRoomToTmpRoomId[mazeRooms[y][x]] = tmpId1 + nextTmpRoomId++ + } + + r1 := rooms.LoadRoom(tmpId1) + + if mazeRooms[y][x].IsStart() { + startRoomId = tmpId1 + } else if mazeRooms[y][x].IsEnd() { + endRoomId = tmpId1 + } + + if y > 0 && mazeRooms[y-1][x] != nil { + if mazeRooms[y][x].IsConnectedTo(mazeRooms[y-1][x]) { + // Connect the rooms + tmpId2, ok := mazeRoomToTmpRoomId[mazeRooms[y-1][x]] + if !ok { + tmpId2 = allRoomIds[nextTmpRoomId] + mazeRoomToTmpRoomId[mazeRooms[y-1][x]] = tmpId2 + nextTmpRoomId++ + } + r2 := rooms.LoadRoom(tmpId2) + + r1.Exits["north"] = exit.RoomExit{ + RoomId: r2.RoomId, + MapDirection: "north", + } + r2.Exits["south"] = exit.RoomExit{ + RoomId: r1.RoomId, + MapDirection: "south", + } + } + } + + if x > 0 && mazeRooms[y][x-1] != nil { + if mazeRooms[y][x].IsConnectedTo(mazeRooms[y][x-1]) { + // Connect the rooms + tmpId2, ok := mazeRoomToTmpRoomId[mazeRooms[y][x-1]] + if !ok { + tmpId2 = allRoomIds[nextTmpRoomId] + mazeRoomToTmpRoomId[mazeRooms[y][x-1]] = tmpId2 + nextTmpRoomId++ + } + r2 := rooms.LoadRoom(tmpId2) + + r1.Exits["west"] = exit.RoomExit{ + RoomId: r2.RoomId, + MapDirection: "west", + } + r2.Exits["east"] = exit.RoomExit{ + RoomId: r1.RoomId, + MapDirection: "east", + } + } + } + + if y < mazeH-1 && mazeRooms[y+1][x] != nil { + + if mazeRooms[y][x].IsConnectedTo(mazeRooms[y+1][x]) { + // Connect the rooms + tmpId2, ok := mazeRoomToTmpRoomId[mazeRooms[y+1][x]] + if !ok { + tmpId2 = allRoomIds[nextTmpRoomId] + mazeRoomToTmpRoomId[mazeRooms[y+1][x]] = tmpId2 + nextTmpRoomId++ + } + r2 := rooms.LoadRoom(tmpId2) + + r1.Exits["south"] = exit.RoomExit{ + RoomId: r2.RoomId, + MapDirection: "south", + } + r2.Exits["north"] = exit.RoomExit{ + RoomId: r1.RoomId, + MapDirection: "north", + } + } + } + if x < mazeW-1 && mazeRooms[y][x+1] != nil { + if mazeRooms[y][x].IsConnectedTo(mazeRooms[y][x+1]) { + // Connect the rooms + tmpId2, ok := mazeRoomToTmpRoomId[mazeRooms[y][x+1]] + if !ok { + tmpId2 = allRoomIds[nextTmpRoomId] + mazeRoomToTmpRoomId[mazeRooms[y][x+1]] = tmpId2 + nextTmpRoomId++ + } + r2 := rooms.LoadRoom(tmpId2) + + r1.Exits["east"] = exit.RoomExit{ + RoomId: r2.RoomId, + MapDirection: "east", + } + r2.Exits["west"] = exit.RoomExit{ + RoomId: r1.RoomId, + MapDirection: "west", + } + } + } + + } + } + + return allRoomIds, startRoomId, endRoomId +} diff --git a/internal/rooms/ephemeral.go b/internal/rooms/ephemeral.go index f12121f5..57beaf3e 100644 --- a/internal/rooms/ephemeral.go +++ b/internal/rooms/ephemeral.go @@ -12,7 +12,7 @@ import ( const ( ephemeralChunksLimit = 100 // The maximum number of ephemeral chunks that can be created - ephemeralChunkSize = 250 // The maximum quantity of ephemeral room's that can be copied/created in a given chunk. + ephemeralChunkSize = 1000 // The maximum quantity of ephemeral room's that can be copied/created in a given chunk. roomIdMin32Bit = 1000000 // 1,000,000 - Safe for 32-bit systems (was 1,000,000,000 which overflows when multiplied by 1000) ) @@ -22,7 +22,9 @@ var ( originalRoomIdLookups = map[int]int{} // a map of ephemeralId's to their original RoomId's, for special purposes // errors errNoRoomIdsProvided = errors.New(`no RoomId's were provided`) + errInvalidRoomQuantity = errors.New(`one or more empty rooms must be requested.`) errRoomNotFound = errors.New(`the requested RoomId wasn't found`) + errZoneNotFound = errors.New(`the requested zone wasn't found`) errEphemeralChunkLimit = fmt.Errorf(`the ephemeral chunk limit of %d has been reached.`, ephemeralChunksLimit) errEphemeralRoomLimit = fmt.Errorf(`the ephemeral room request limit of %d is exceeded.`, ephemeralChunkSize) errNonUniqueRoomId = errors.New(`a RoomId has been provided more than once. they must all be unique`) @@ -38,6 +40,16 @@ func GetChunkCount() int { return result } +// Looks at chunk array and returns the first unused/empty index, or error if none found. +func getNextAvailableChunk() (int, error) { + for i := 0; i < ephemeralChunksLimit; i++ { + if len(ephemeralRoomChunks[i]) == 0 { + return i, nil + } + } + return -1, errEphemeralChunkLimit +} + // Looks for any ephemeralRoomId's that exits for the given roomId. // Returns a slice containing all found ephemeralIds func FindEphemeralRoomIds(roomId int) []int { @@ -52,19 +64,64 @@ func FindEphemeralRoomIds(roomId int) []int { return allEphemeralRoomIds } -// accepts RoomId's as arguments, and creates ephemeral copies of them, returning the new ID's of the copies. -func CreateEphemeralRoomIds(roomIds ...int) (map[int]int, error) { +// Accepts a quantity and returns roomId's for a chunk of empty rooms +// This is a special use function for dynamically building ephemeral rooms in code +func CreateEmptyEphemeralRooms(qty int) ([]int, error) { + + if qty > ephemeralChunkSize { + return []int{}, errEphemeralRoomLimit + } - ephemeralRooms := map[int]int{} + if qty < 1 { + return []int{}, errInvalidRoomQuantity + } + + ephemeralRoomIds := make([]int, 0, qty) + + // First find a chunk ID + chunkId, err := getNextAvailableChunk() + if err != nil { + return []int{}, err + } + + for i := 0; i < qty; i++ { + room := NewEmptyRoom() + room.RoomId = ephemeralRoomIdMinimum + (chunkId * ephemeralChunkSize) + i + + // Save the original room ID in case we need it at some point + originalRoomIdLookups[room.RoomId] = 0 + + addRoomToMemory(room) + ephemeralRoomIds = append(ephemeralRoomIds, room.RoomId) + } + + trackedRoomIds := make([]int, len(ephemeralRoomIds)) + copy(trackedRoomIds, ephemeralRoomIds) + + ephemeralRoomChunks[chunkId] = trackedRoomIds + + mudlog.Info("CreateEmptyEphemeral...()", + "created", len(trackedRoomIds), + "chunkId", chunkId, + "Ephemeral RoomIds", fmt.Sprintf("%d - %d", ephemeralRoomIds[0], ephemeralRoomIds[len(ephemeralRoomIds)-1]), + "Chunks Remaining", ephemeralChunksLimit-GetChunkCount()) + + return ephemeralRoomIds, nil +} + +// accepts RoomId's as arguments, and creates ephemeral copies of them, returning the new ID's of the copies. +func CreateEphemeralRoomIds(roomIds ...int) (map[int]int, error) { if len(roomIds) == 0 { - return ephemeralRooms, errNoRoomIdsProvided + return map[int]int{}, errNoRoomIdsProvided } if len(roomIds) > ephemeralChunkSize { - return ephemeralRooms, errEphemeralRoomLimit + return map[int]int{}, errEphemeralRoomLimit } + ephemeralRooms := make(map[int]int, len(roomIds)) + // Make sure that all values in the roomIds slice are unique. roomIdReplacements := map[int]int{} // original=>ephemeral replacements for _, roomId := range roomIds { @@ -74,17 +131,14 @@ func CreateEphemeralRoomIds(roomIds ...int) (map[int]int, error) { roomIdReplacements[roomId] = 0 } - // First reserve the chunk - chunkId := -1 - for i := 0; i < ephemeralChunksLimit; i++ { - if len(ephemeralRoomChunks[i]) == 0 { - chunkId = i - break - } + // First find a chunk ID + chunkId, err := getNextAvailableChunk() + if err != nil { + return map[int]int{}, err } ephemeralRoomIds := []int{} - for idx, roomId := range roomIds { + for i, roomId := range roomIds { // Load only data from the template if roomId == 0 { @@ -96,7 +150,7 @@ func CreateEphemeralRoomIds(roomIds ...int) (map[int]int, error) { continue } - room.RoomId = ephemeralRoomIdMinimum + (chunkId * ephemeralChunkSize) + idx + room.RoomId = ephemeralRoomIdMinimum + (chunkId * ephemeralChunkSize) + i // Save the original room ID in case we need it at some point originalRoomIdLookups[room.RoomId] = roomId @@ -132,7 +186,7 @@ func CreateEphemeralRoomIds(roomIds ...int) (map[int]int, error) { "created", len(ephemeralRoomIds), "chunkId", chunkId, "Ephemeral RoomIds", fmt.Sprintf("%d - %d", ephemeralRoomIds[0], ephemeralRoomIds[len(ephemeralRoomIds)-1]), - "Chunks Remaining", GetChunkCount()) + "Chunks Remaining", ephemeralChunksLimit-GetChunkCount()) return ephemeralRooms, nil } @@ -140,6 +194,10 @@ func CreateEphemeralRoomIds(roomIds ...int) (map[int]int, error) { // accepts RoomId's as arguments, and creates ephemeral copies of them, returning the new ID's of the copies. func CreateEphemeralZone(zoneName string) (map[int]int, error) { + if _, exists := roomManager.zones[zoneName]; !exists { + return nil, errZoneNotFound + } + roomIds := make([]int, len(roomManager.zones[zoneName].RoomIds)) idx := 0 diff --git a/internal/rooms/roomdetails.go b/internal/rooms/roomdetails.go index 01fbcb71..abf706fe 100644 --- a/internal/rooms/roomdetails.go +++ b/internal/rooms/roomdetails.go @@ -447,6 +447,14 @@ func GetDetails(r *Room, user *users.UserRecord, tinymap ...[]string) RoomTempla } } + if user.Character.HasBuffFlag(buffs.Tripping) { + details.Title = colorpatterns.ApplyCharacterWarping(details.Title) + details.Description = colorpatterns.ApplyCharacterWarping(details.Description) + + details.Title = colorpatterns.ApplyColorPattern(details.Title, "tripping") + details.Description = colorpatterns.ApplyColorPattern(details.Description, "tripping") + } + return details } diff --git a/internal/rooms/roommanager.go b/internal/rooms/roommanager.go index eb2afd65..d76a1f2c 100644 --- a/internal/rooms/roommanager.go +++ b/internal/rooms/roommanager.go @@ -264,6 +264,8 @@ func MoveToRoom(userId int, toRoomId int, isSpawn ...bool) error { // Put them in their own instance of it. deathRecoveryRoomId := int(cfg.DeathRecoveryRoom) if toRoomId == deathRecoveryRoomId { + // Set their reset room id to death recovery. + user.Character.RoomIdOnReset = deathRecoveryRoomId if newRooms, err := CreateEphemeralRoomIds(deathRecoveryRoomId); err == nil { toRoomId = newRooms[deathRecoveryRoomId] } @@ -325,6 +327,32 @@ func MoveToRoom(userId int, toRoomId int, isSpawn ...bool) error { } } } + + // + // If they are moving into an ephemeral room + // + if IsEphemeralRoomId(newRoom.RoomId) { + + if user.Character.RoomIdOnReset == 0 { + // + // If their previous room was non ephemeral, set it to their reset room by default + // This can be overridden manually by scripts/coding if/when needed. + // + if !IsEphemeralRoomId(user.Character.RoomId) { + user.Character.RoomIdOnReset = user.Character.RoomId + } + } + + } else { + // + // If their RoomIdOnReset is non zero and they are moving to a non ephemeral room + // Clear their RoomIdOnReset. + // + if user.Character.RoomIdOnReset != 0 { + user.Character.RoomIdOnReset = 0 + } + } + // // Done adding mutator buffs // diff --git a/internal/rooms/rooms.go b/internal/rooms/rooms.go index 49906960..b167e361 100644 --- a/internal/rooms/rooms.go +++ b/internal/rooms/rooms.go @@ -122,6 +122,19 @@ func NewRoom(zone string) *Room { return r } +func NewEmptyRoom() *Room { + r := &Room{ + Title: "An empty room.", + Description: "This is an empty room that was never given a description.", + MapSymbol: ``, + Exits: make(map[string]exit.RoomExit), + players: []int{}, + visitors: make(map[VisitorType]map[int]uint64), + tempDataStore: make(map[string]any), + } + return r +} + func (r *Room) IsEphemeral() bool { return r.RoomId >= ephemeralRoomIdMinimum } @@ -2198,7 +2211,6 @@ func (r *Room) Validate() error { } } - // Make sure all items are validated (and have uids) for i := range r.Items { r.Items[i].Validate() diff --git a/internal/scripting/actor_func.go b/internal/scripting/actor_func.go index f1260099..93b478c5 100644 --- a/internal/scripting/actor_func.go +++ b/internal/scripting/actor_func.go @@ -9,7 +9,6 @@ import ( "github.com/GoMudEngine/GoMud/internal/configs" "github.com/GoMudEngine/GoMud/internal/events" "github.com/GoMudEngine/GoMud/internal/mobs" - "github.com/GoMudEngine/GoMud/internal/parties" "github.com/GoMudEngine/GoMud/internal/pets" "github.com/GoMudEngine/GoMud/internal/races" "github.com/GoMudEngine/GoMud/internal/rooms" @@ -104,6 +103,13 @@ func (a ScriptActor) GetStat(statName string) int { return 0 } +func (a ScriptActor) SetResetRoomId(roomId int) { + if a.userRecord == nil { + return + } + a.userRecord.Character.RoomIdOnReset = roomId +} + func (a ScriptActor) SetTempData(key string, value any) { if a.userRecord != nil { @@ -203,72 +209,41 @@ func (a ScriptActor) HasQuest(questId string) bool { func (a ScriptActor) GiveQuest(questId string) { - if a.userRecord != nil { - // If in a party, give to all party members. - if party := parties.Get(a.userId); party != nil { - for _, userId := range party.GetMembers() { - - events.AddToQueue(events.Quest{ - UserId: userId, - QuestToken: questId, - }) - - } - return - } else { - - events.AddToQueue(events.Quest{ - UserId: a.userId, - QuestToken: questId, - }) - - } - } - //a.characterRecord.GiveQuestToken(questId) + events.AddToQueue(events.Quest{ + UserId: a.UserId(), + QuestToken: questId, + }) } -func (a ScriptActor) GetPartyMembers() []ScriptActor { - - partyMembers := []ScriptActor{} - partyUserId := 0 - - if a.userRecord == nil { - if a.mobRecord.Character.Charmed == nil { - return partyMembers - } - - partyUserId = a.mobRecord.Character.Charmed.UserId - } else { - partyUserId = a.userId +// Gets a party object that indexes ALL members of the party +func (a ScriptActor) GetParty(excludeSelf ...bool) ScriptParty { + return ScriptParty{ + actor: &a, + includePresent: true, + includeMissing: true, + includeSelf: len(excludeSelf) == 0 || !excludeSelf[0], } +} - if partyUserId < 1 { - return partyMembers - } - - // If in a party, give to all party members. - if party := parties.Get(partyUserId); party != nil { - for _, userId := range party.GetMembers() { - - if a := GetActor(userId, 0); a != nil { - partyMembers = append(partyMembers, *a) - } - - } +// Gets a party object that indexes only party members in the same room +func (a ScriptActor) GetPartyPresent(excludeSelf ...bool) ScriptParty { + return ScriptParty{ + actor: &a, + includePresent: true, + includeMissing: false, + includeSelf: len(excludeSelf) == 0 || !excludeSelf[0], } +} - mobPartyMembers := []ScriptActor{} - - for _, char := range partyMembers { - for _, mobInstId := range char.characterRecord.GetCharmIds() { - if a := GetActor(0, mobInstId); a != nil { - mobPartyMembers = append(mobPartyMembers, *a) - } - } +// Gets a party object that indexes only members NOT in the same room. +func (a ScriptActor) GetPartyMissing() ScriptParty { + return ScriptParty{ + actor: &a, + includePresent: false, + includeMissing: true, + includeSelf: false, } - - return append(partyMembers, mobPartyMembers...) } func (a ScriptActor) AddGold(amt int, bankAmt ...int) { @@ -364,7 +339,7 @@ func (a ScriptActor) GetSkillLevel(skillName string) int { return a.characterRecord.GetSkillLevel(skills.SkillTag(skillName)) } -func (a ScriptActor) MoveRoom(destRoomId int, leaveCharmedMobs ...bool) { +func (a ScriptActor) MoveRoom(destRoomId int) { if a.userRecord != nil { @@ -374,11 +349,9 @@ func (a ScriptActor) MoveRoom(destRoomId int, leaveCharmedMobs ...bool) { rooms.MoveToRoom(a.userId, destRoomId) - if len(leaveCharmedMobs) < 1 || !leaveCharmedMobs[0] { - for _, mobInstId := range a.characterRecord.GetCharmIds() { - rmNow.RemoveMob(mobInstId) - rmNext.AddMob(mobInstId) - } + for _, mobInstId := range a.characterRecord.GetCharmIds() { + rmNow.RemoveMob(mobInstId) + rmNext.AddMob(mobInstId) } if doLook, err := TryRoomScriptEvent(`onEnter`, a.userRecord.UserId, destRoomId); err != nil || doLook { diff --git a/internal/scripting/party_func.go b/internal/scripting/party_func.go new file mode 100644 index 00000000..b66dc795 --- /dev/null +++ b/internal/scripting/party_func.go @@ -0,0 +1,240 @@ +package scripting + +import ( + "github.com/GoMudEngine/GoMud/internal/parties" +) + +type ScriptParty struct { + actor *ScriptActor + includeSelf bool + includePresent bool + includeMissing bool +} + +// GetMembers() is the core feature of this, everything works off of it. +func (p ScriptParty) GetMembers() []ScriptActor { + + partyMembers := []ScriptActor{} + addedUsers := map[int]struct{}{} // Track so we never accidentally add someone twice + addedMobs := map[int]struct{}{} // Track so we never accidentally add someone twice + + // Usually we would include self, but just in case... + if p.includeSelf { + + partyMembers = append(partyMembers, *p.actor) + + if p.actor.characterRecord != nil { + addedUsers[p.actor.userId] = struct{}{} + } else if p.actor.mobRecord != nil { + addedMobs[p.actor.mobInstanceId] = struct{}{} + } + } + + partyUserId := p.actor.UserId() + sourceRoomId := p.actor.GetRoomId() + + if p.actor.userRecord == nil { + if p.actor.mobRecord.Character.Charmed == nil { + return partyMembers + } + + partyUserId = p.actor.mobRecord.Character.Charmed.UserId + } + + if partyUserId < 1 { + return partyMembers + } + + // If in a party, give to all party members. + if party := parties.Get(partyUserId); party != nil { + for _, userId := range party.GetMembers() { + + if _, ok := addedUsers[userId]; ok { + continue + } + + if a := GetActor(userId, 0); a != nil { + + if a.GetRoomId() == sourceRoomId { + if !p.includePresent { + continue + } + } else { + if !p.includeMissing { + continue + } + } + + partyMembers = append(partyMembers, *a) + addedUsers[userId] = struct{}{} + + } + + } + } + + mobPartyMembers := []ScriptActor{} + + // Add all charmed mobs for all party members, too. + for _, char := range partyMembers { + for _, mobInstId := range char.characterRecord.GetCharmIds() { + + if _, ok := addedMobs[mobInstId]; ok { + continue + } + + if a := GetActor(0, mobInstId); a != nil { + + if a.GetRoomId() == sourceRoomId { + if !p.includePresent { + continue + } + } else { + if !p.includeMissing { + continue + } + } + + mobPartyMembers = append(mobPartyMembers, *a) + addedMobs[mobInstId] = struct{}{} + + } + } + } + + return append(partyMembers, mobPartyMembers...) +} + +// +// Simple helper to loop through all members and apply a function +// + +func (p ScriptParty) each(fn func(ScriptActor)) { + allParty := p.GetMembers() + for _, a := range allParty { + fn(a) + } +} + +// +// What follows are many functions graduated from the actor level to the party level +// + +func (p ScriptParty) SendText(msg string) { + p.each(func(a ScriptActor) { + a.SendText(msg) + }) +} + +func (p ScriptParty) SetResetRoomId(roomId int) { + p.each(func(a ScriptActor) { + if a.userRecord == nil { + return + } + a.userRecord.Character.RoomIdOnReset = roomId + }) +} + +func (p ScriptParty) GiveQuest(questId string) { + p.each(func(a ScriptActor) { + a.GiveQuest(questId) + }) +} + +func (p ScriptParty) AddGold(amt int, bankAmt ...int) { + p.each(func(a ScriptActor) { + a.AddGold(amt, bankAmt...) + }) +} +func (p ScriptParty) AddHealth(amt int) { + p.each(func(a ScriptActor) { + a.AddHealth(amt) + }) +} +func (p ScriptParty) AddMana(amt int) { + p.each(func(a ScriptActor) { + a.AddMana(amt) + }) +} +func (p ScriptParty) Command(cmd string, waitSeconds ...float64) { + p.each(func(a ScriptActor) { + a.Command(cmd, waitSeconds...) + }) +} +func (p ScriptParty) TrainSkill(skillName string, skillLevel int) { + p.each(func(a ScriptActor) { + a.TrainSkill(skillName, skillLevel) + }) +} +func (p ScriptParty) MoveRoom(destRoomId int) { + p.each(func(a ScriptActor) { + a.MoveRoom(destRoomId) + }) +} +func (p ScriptParty) AddEventLog(category string, message string) { + p.each(func(a ScriptActor) { + a.AddEventLog(category, message) + }) +} + +func (p ScriptParty) GiveBuff(buffId int, source string) { + p.each(func(a ScriptActor) { + a.GiveBuff(buffId, source) + }) +} +func (p ScriptParty) CancelBuffWithFlag(buffFlag string) { + p.each(func(a ScriptActor) { + a.CancelBuffWithFlag(buffFlag) + }) +} +func (p ScriptParty) RemoveBuff(buffId int) { + p.each(func(a ScriptActor) { + a.RemoveBuff(buffId) + }) +} +func (p ScriptParty) ChangeAlignment(alignmentChange int) { + p.each(func(a ScriptActor) { + a.ChangeAlignment(alignmentChange) + }) +} +func (p ScriptParty) LearnSpell(spellId string) { + p.each(func(a ScriptActor) { + a.LearnSpell(spellId) + }) +} +func (p ScriptParty) SetHealth(amt int) { + p.each(func(a ScriptActor) { + a.SetHealth(amt) + }) +} +func (p ScriptParty) SetAdjective(adj string, addIt bool) { + p.each(func(a ScriptActor) { + a.SetAdjective(adj, addIt) + }) +} +func (p ScriptParty) GiveTrainingPoints(ct int) { + p.each(func(a ScriptActor) { + a.GiveTrainingPoints(ct) + }) +} +func (p ScriptParty) GiveStatPoints(ct int) { + p.each(func(a ScriptActor) { + a.GiveStatPoints(ct) + }) +} +func (p ScriptParty) GiveExtraLife() { + p.each(func(a ScriptActor) { + a.GiveExtraLife() + }) +} + +func (p ScriptParty) GrantXP(xpAmt int, reason string) { + p.each(func(a ScriptActor) { + a.GrantXP(xpAmt, reason) + }) +} +func (p ScriptParty) TimerSet(name string, period string) { + p.each(func(a ScriptActor) { + a.TimerSet(name, period) + }) +} diff --git a/internal/scripting/room_func.go b/internal/scripting/room_func.go index 86321c88..183bd472 100644 --- a/internal/scripting/room_func.go +++ b/internal/scripting/room_func.go @@ -25,6 +25,7 @@ import ( func setRoomFunctions(vm *goja.Runtime) { vm.Set(`GetRoom`, GetRoom) vm.Set(`GetMap`, GetMap) + vm.Set(`CreateEmptyRoomInstances`, CreateEmptyRoomInstances) vm.Set(`CreateInstancesFromRoomIds`, CreateInstancesFromRoomIds) vm.Set(`CreateInstancesFromZone`, CreateInstancesFromZone) } @@ -386,7 +387,12 @@ func (r ScriptRoom) IsEphemeral() bool { // # These functions get exported to the scripting engine // // //////////////////////////////////////////////////////// -func CreateInstancesFromRoomIds(roomList []int) map[int]int { +func CreateEmptyRoomInstances(quantity int) []int { + ret, _ := rooms.CreateEmptyEphemeralRooms(quantity) + return ret +} + +func CreateInstancesFromRoomIds(roomList ...int) map[int]int { ret, _ := rooms.CreateEphemeralRoomIds(roomList...) return ret } diff --git a/internal/usercommands/start.go b/internal/usercommands/start.go index f99c43da..067c68aa 100644 --- a/internal/usercommands/start.go +++ b/internal/usercommands/start.go @@ -21,7 +21,31 @@ import ( ) func Start(rest string, user *users.UserRecord, room *rooms.Room, flags events.EventFlag) (bool, error) { + /* + mazeW := 15 + mazeH := 8 + maze := procedural.NewGridMaze() + // Generate the maze + mazeRooms := maze.Generate2D(mazeW, mazeH) + + allRoomIds, startRoomId, endRoomId := procedural.CreateEphemeralMaze2D(mazeRooms) + + mudlog.Error("TEST", "startTmpRoomId", startRoomId, "endRoomId", endRoomId, "allRoomIds", allRoomIds) + + rooms.MoveToRoom(user.UserId, startRoomId) + + // "Beyond the ornate door, the building’s interior dissolves into a forgotten maze of narrow chambers and crooked corridors, as if the structure has been slowly folding in on itself for decades. The air is damp and stale, heavy with the earthy scent of rot and wet stone. Cracked walls sag beneath peeling plaster, exposing warped beams blackened by age and moisture. Mushrooms thrive in the gloom—pale caps cluster along the floorboards, spill from crumbling mortar, and creep up the walls in soft, phosphorescent patches that provide the only light, casting sickly shadows that twist and crawl as you move. Debris crunches underfoot: fallen ceiling tiles, splintered furniture, and heaps of unidentifiable refuse softened by mold. Water drips somewhere unseen, echoing through the labyrinth, making it impossible to tell how large the place truly is." + + // "The room feels like just another fragment of a structure long past saving, its original purpose impossible to guess. The ceiling hangs low and uneven, with sections bowed inward as though the building itself is slowly collapsing. Damp stone and rotting wood dominate every surface, feeding thick growths of mushrooms that sprout in tangled clusters along the walls and floor. Some are brittle and gray, others swollen and faintly luminous, staining the air with a sour, fungal musk. Old debris lies half-buried in mold—splintered crates, scraps of cloth, and rusted metal shapes softened by decay. Every sound seems muted here, swallowed by the damp, until the occasional drip of water or distant creak of settling timbers reminds you that the maze is still shifting, still alive in its own slow, ruinous way." + return true, nil + */ + // + // + // + // + // + // if user.Character.RoomId != -1 { return false, errors.New(`only allowed in the void`) } @@ -250,6 +274,9 @@ func Start(rest string, user *users.UserRecord, room *rooms.Room, flags events.E return true, nil } + // Send them back to the void if they leave the game in the middle of the tutorial + user.Character.RoomIdOnReset = -1 + ephemeralStartRoomId := createdRoomIds[startRoom] user.SendText(fmt.Sprintf(`Suddenly, a vortex appears before you, drawing you in before you have any chance to react!%s`, term.CRLFStr)) diff --git a/main.go b/main.go index 02f2eb18..59b77663 100644 --- a/main.go +++ b/main.go @@ -243,7 +243,7 @@ func main() { // // Capture OS signals to gracefully shutdown the server - signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGTSTP) // for testing purposes, enable event debugging //events.SetDebug(true)