# Marketplace and Server NPCs (Revamped) — full documentation > Every page below, concatenated, for pasting into an AI assistant's context all at once. Want a link to just one page instead? See /kg-marketplace-docs/llms.txt for an index, or that page's own /index.md. --- # Marketplace and Server NPCs (Revamped) ![Marketplace banner](images/marketplace-logo.png) **Marketplace and Server NPCs (Revamped)** adds server-configurable NPCs and mechanics to Valheim — a player-to-player marketplace, shops, quests, dialogue trees, zones, banking, gambling, transmog, and more. Admins configure everything themselves by editing text files, and changes apply live — no server restart needed, see [Hot reload](setup/hot-reload.md). This documentation is written for **server admins** — nearly every page is about config files only an admin edits. A couple of pages are the exception and matter to any player: [Client config](setup/client-config.md) (each player's own settings — chat, keybinds, UI) and a few entries on [Console commands](setup/console-commands.md) that don't need admin access. Every page leads with practical examples rather than bare reference tables — most open with a working example you can copy and adapt. Install the mod with [Gale](https://hexium.gg/mod-manager) via [Hexium](https://valheim.hexium.gg/mods/KG/Marketplace_And_Server_NPCs_Revamped), or by hand — see [Installation](setup/installation.md) for every option, [File structure](setup/file-structure.md) for what gets created on first run, and [Server config](setup/server-config.md)/[Client config](setup/client-config.md) for the settings worth a look right away (admin access, currency, taxes, and the rest). There is no in-game editor: quests, dialogues, zones, NPCs, and everything else below are built by editing plain text config files that the mod picks up live (see [Hot reload](setup/hot-reload.md) for exactly what that covers) — see [Content creation](concepts/content-creation.md) for how it all fits together, including [config file syntax](concepts/config-syntax.md), [profiles](concepts/profiles.md), [conditions](concepts/conditions.md), [commands](concepts/commands.md), [prefabs and text markup](concepts/prefabs-and-assets.md), [custom assets](assets/custom-assets.md), and [scheduling a config to a time window](concepts/time-windows.md). ## Key features ### Core: NPCs, quests, dialogue & factions - **[NPC system](npc/npc-system.md)** — placeable NPCs: type, appearance, dialogue, map pin, patrol, visibility condition. Placed with the [Marketplace Hammer](npc/marketplace-hammer.md) build tool. Reusable setups: [Saved NPCs](configs/saved-npcs.md). Idle chatter: [Random NPC Speech](configs/random-npc-speech.md). Player-summoned instead of admin-placed: [Spawned NPCs](configs/spawned-npcs.md). - **[Quests](configs/quests.md)** — the full quest system, 10 quest types. Assigning quests to an NPC: [Quest Profiles](configs/quest-profiles.md). Scripting what happens on accept/complete/cancel: [Quest Events](configs/quest-events.md). Walkthroughs: [Your first quest](guides/first-quest.md), [Quest chains](guides/quest-chain.md). - **[Dialogues](configs/dialogues.md)** — branching NPC conversations, with conditions and scripted actions. Attaching extra data to something a dialogue spawns: [Custom Spawn Data](configs/custom-spawn-data.md). Walkthroughs: [A branching dialogue tree](guides/dialogue-tree.md), [Dialogue patterns](guides/dialogue-patterns.md), [Tracking player state](guides/tracking-player-state.md). - **[Factions](configs/factions.md)** — player factions with shared perks, restricted items, and friendly monsters, joined and checked through the same [Dialogues](configs/dialogues.md)/[Quests](configs/quests.md) commands and conditions above. ### Economy: shops, currency & rewards - **[Marketplace](setup/server-config.md)** — the player-to-player auction house. Works immediately with no setup; tax and listing-limit settings live in the server config. - **[Traders](configs/traders.md)** — an NPC shop with a fixed buy/sell list. - **[Bankers](configs/bankers.md)** — deposit and withdraw currency, with periodic interest. - **[Gamblers](configs/gamblers.md)** — spend an item, get a randomized reward. - **[Buffers](configs/buffers.md)** — an Enchanter NPC that sells temporary buffs. Choosing which buffs an NPC offers: [Buffer Profiles](configs/buffer-profiles.md). - **[Transmogrification](configs/transmogrification.md)** — change how an item looks without changing its stats. Walkthrough tying these together: [Shops, currency, and taxes](guides/shop-and-economy.md). ### World: zones, travel & server info - **[Server Info](configs/server-infos.md)** — rules and announcement boards. - **[Teleporters](configs/teleporters.md)** — a fast-travel hub NPC. - **[Territories](configs/territories.md)** — named zones with behavior flags: PvP rules, healing auras, biome overrides, and more. Walkthrough: [Setting up a territory](guides/territory-setup.md). ### Server utilities & extras - **[Player Tags](configs/player-tags.md)** — name-tag prefixes per player, like `[Admin]` or `[Trusted]`. - **[Synced Localizer](configs/synced-localizer.md)** — server-wide text overrides, sent to every player automatically. - **[Console commands](setup/console-commands.md)** — admin and debug commands. - **[Discord Webhooks](configs/discord-webhooks.md)** — posts marketplace sales, gambler wins, and quest completions to a Discord channel. #### UI panels - **[Mail](setup/server-config.md#mail)** — send items and messages between players. Works immediately; mailbox recipe and timing live in the server config. - **[Feedback](setup/server-config.md#feedback)** — a feedback form that posts to a Discord webhook. Works immediately; the webhook link lives in the server config. - **[Chat](setup/client-config.md#kg-chat)** — a replacement chat window. Client-side settings only. - **[Distanced UI](configs/distanced-ui.md)** — open shop/quest/mail menus without a nearby NPC, and spawn a [Spawned NPC](configs/spawned-npcs.md) for yourself. - **[Leaderboard Achievements](configs/leaderboard-achievements.md)** — server-wide leaderboards and achievements. ### How to read a config page Most config pages above follow the same shape: 1. A working example, explained piece by piece. 2. A table of every option/value you can use. 3. Anything that behaves in a way you might not expect. 4. Links to related pages. Every config example is written with generous spacing (`Key: Value | Key2: Value2` rather than `Key:Value|Key2:Value2`) — spaces around punctuation are always safe to use in your own files and make them much easier to read later. ## Tooling - [VS Code extensions](tooling/vscode-extension.md) — editor extensions, starting with syntax highlighting. - [Coming soon](tooling/coming-soon.md) — AI-assisted config generation and a visual config editor, planned but not built yet. ## For mod developers - [Integrating with this mod](api/modder-api.md) — what other mods can read and change. ## Reference - [Localization keys](reference/localization-keys.md) - [Changelog](reference/changelog.md) - [Migrations](reference/migrations.md) — what to do when updating across a version with a breaking change - [Known gaps](reference/known-gaps.md) — current-version quirks and things that look like they should work but do not ## What it looks like | | | |---|---| | ![Marketplace sell panel](images/screenshots/JGXAFxx.png) | ![Marketplace buy panel](images/screenshots/Rm0005s.png) | More screenshots for a specific module live on that module's own page — see **Key features** above. Prefer watching over reading? See [Video guides](guides/video-guides.md) for community walkthroughs. Want to ask an AI about this mod instead of reading? Every page has a "Use with AI" bar at the top — copy that page as Markdown, open it directly in ChatGPT/Perplexity/Grok, or paste it into Claude/Gemini. To hand an AI the whole documentation at once, grab [`/llms-full.txt`](/llms-full.txt) (one file, everything); for just a linked index, see [`/llms.txt`](/llms.txt). ## Support the author If this documentation or the mod itself saved you time, consider supporting KG, the mod's author: - **Discord:** [discord.gg/QgvSmhkbmy](https://discord.gg/QgvSmhkbmy) — questions, comments, community help - **Donate:** PayPal — `war3spells@gmail.com` --- # For other mod developers This mod provides a small integration surface for other mods to hook into — checking whether a player is standing inside a specific zone, reading or changing an NPC's appearance and behavior, and a couple of convenience actions. This page is a plain-language overview of what is possible; if you are building an integration, the mod ships a ready-to-use interface file you can copy into your own project, with the exact calls documented inline. ## What another mod can do - **Check zone membership.** Ask whether the local player, or any object, is currently standing inside a [Territory](../configs/territories.md), and read which behavior flags that zone has active. Useful for a mod that wants to behave differently inside PvP zones, guild land, and so on. - **Read and change an NPC's settings.** Every setting on an NPC — its type, profile, model, name, dialogue, and all appearance fields (see [NPC system](../npc/npc-system.md)) — can be read or changed by another mod, the same data this mod's own build tool edits. - **Trigger a couple of built-in actions.** Refresh a trader's stock, or open the quest journal, from another mod's own code. ## Things worth knowing if you are integrating - A small number of the newer zone flags are not currently visible through this integration, even though they work correctly when set directly in a [Territories](../configs/territories.md) file — see [Known gaps](../reference/known-gaps.md). - The NPC type list exposed to other mods is missing the `Mail` type compared to the full list available in-game (see [NPC system](../npc/npc-system.md#npc-types)) — if you need to detect a Mail NPC specifically from another mod, this is a current limitation. ## Related integrations this mod already has Separately from the above, this mod already talks to a handful of other popular mods on its own — EpicMMO, Cozyheim's leveling system, and RustyClasses all have experience-granting commands and level-check conditions built in (see [Commands](../concepts/commands.md) and [Conditions](../concepts/conditions.md)), and guild-related actions and checks are available the same way if a guild mod is installed. ## Related - [Territories](../configs/territories.md), [NPC system](../npc/npc-system.md). - [Known gaps](../reference/known-gaps.md). --- # Custom assets Five folders on the player's own computer (next to `BepInEx/config/Marketplace/`, see [File structure](../setup/file-structure.md)) let you drop in your own media that configs and NPCs can then reference by file name. | Folder | What goes here | Referenced by | Refresh command | |---|---|---|---| | `Marketplace_Sounds/` | `.mp3` files | File name, in `PlaySound` commands or an NPC's interact sound setting | `mreloadsounds` | | `Marketplace_Models/` | `.obj` files | File name, as a model/prefab override | `mreloadmodels` | | `Marketplace_CachedImages/` | `.png` files | File name, in `` tags | `mreloadimages` | | `Marketplace_VideoClips/` | video files | File name, in the `PlayVideo` command | loads automatically at startup | | `Marketplace_SavedNPCs/` | `.yml` NPC templates | Appears directly in the Hammer build menu | `mreloadnpcs` | | `Marketplace_KGChat_Emojis/` | a spritesheet image | Replaces the default chat emoji set | loads automatically at startup | File names must be unique within a folder — subfolders are fine for organizing, but two files with the same name (in different subfolders) will conflict, and whichever loads last wins. ## Related - [Prefabs and text markup](../concepts/prefabs-and-assets.md) — the ``, sound-volume, and model-override syntax that references these files. - [Console commands](../setup/console-commands.md). --- # Commands Commands are the actions side of scripting — give an item, teleport the player, spawn a creature, play a sound. They run inside [Dialogue](../configs/dialogues.md) options and [Quest Event](../configs/quest-events.md) triggers. ## Quick example A dialogue option that gives the player an item, plays a sound, and moves to the next line of conversation: ```cfg Text: Take this sword | Command: GiveItem, SwordIron, 1, 2 | Command: PlaySound, sword_clink, 0.8 | Transition: farewell ``` A quest event that spawns a mini-boss the moment the quest is accepted, and cleans it up if the quest times out: `Configs/QuestEvents/boss_hunt.cfg`: ```cfg [boss_hunt] OnAcceptQuest: Spawn, GoblinKing, 1, 3 OnQuestTimeout: RemoveQuest, boss_hunt ``` ## Syntax `CommandName, argument1, argument2` — same comma-separated shape as conditions. You can chain several commands on one line with `|`, and they run in order: ```cfg Command: GiveItem, Coins, 100 | Command: PlaySound, coin_jingle | Command: Heal, 50 ``` ## Random outcomes `RandomCommand` gives a command a percent chance (0-100) of firing. **Each `RandomCommand` on the same line rolls independently** — this is not a single pick split between alternatives, so more than one can fire, or none at all: ```cfg Text: Open the chest | RandomCommand: 40, GiveItem, Coins, 10 | RandomCommand: 15, GiveItem, Ruby, 1 ``` This is a 40% chance of the Coins firing and a *separate* 15% chance of the Ruby firing, checked independently — the player could get both, either, or neither. If you want exactly one of several outcomes to happen (never more, never fewer), use `RandomTransition` to jump to a different node for each outcome instead, since transitions genuinely pick one at random from the list. ## Reference: all commands | Command | Arguments | What it does | |---|---|---| | `OpenUI` | [menu type], [profile] | Opens a shop/menu window. Leave both empty to open whatever menu the current NPC itself offers. | | `PlaySound` | sound name, [volume] | Plays a sound you dropped into the sounds folder — see [Custom assets](../assets/custom-assets.md). | | `GiveQuest` | quest ID | Gives the player a quest directly, without them needing to talk to the quest-giving NPC. | | `RemoveQuest` | quest ID, [count as cancelled?] | Removes an active quest from the player. | | `FinishQuest` | quest ID | Force-completes a quest immediately. | | `GiveItem` | item, amount, level | Adds an item to the player's inventory. | | `GiveItemWithData` | item, amount, level, data set name | Same, but stamps extra custom values onto the item — see [Custom Spawn Data](../configs/custom-spawn-data.md). | | `RemoveItem` | item, amount | Removes items from the player's inventory. | | `SetPlayerData` | data set name | Applies a whole [custom data set](../configs/custom-spawn-data.md) directly onto the player. | | `Spawn` | prefab, amount, level | Spawns creatures/items near the player, scattered randomly. | | `SpawnWithData` | prefab, amount, level, data set name | Same, with a custom data set applied to each spawn. | | `SpawnXYZ` | prefab, amount, level, x, y, z, spread | Spawns at an exact world position instead of near the player. | | `SpawnXYZWithData` | prefab, amount, level, x, y, z, spread, data set name | Combination of the above two. | | `Teleport` | x, y, z, [allow while carrying ore?] | Teleports the player to a fixed position. | | `Damage` | amount | Deals flat damage to the player. | | `Heal` | amount | Heals the player. | | `GiveBuff` | buff name, [duration] | Applies a buff. Note: the duration argument here is unreliable for anything longer than about a second — if you need a buff to last a specific amount of time, set its duration on the buff itself instead (see [Buffers](../configs/buffers.md)) and leave this argument out. | | `AddPin` | label, x, y, z | Drops a permanent map pin and centers the map on it. | | `PingMap` | text, x, y, z | Shows a temporary map ping (like a player ping), not a permanent pin. | | `AddEpicMMOExp` | amount | Grants EpicMMO experience (only if that mod is installed). | | `AddCozyheimExp` | amount | Grants Cozyheim leveling experience. | | `AddRustyClassesEXP` | amount | Grants RustyClasses experience. | | `PlayAnimation` | animation name | Plays an animation on the NPC. | | `EnterPassword` | title, password, success command, fail command | Opens a password-entry popup and branches based on the result. | | `GuildAddLevel` | amount | Adds levels to the player's own guild. | | `Battlepass_EXP` | amount | Grants Battlepass experience (only if that separate mod is installed). | | `ConsoleCommand` | command text | Runs any admin console command as if the player had typed it themselves — see the caution note below. | | `AddCustomValue` / `SetCustomValue` | key, amount / value | Adds to, or sets, a [custom value](prefabs-and-assets.md#custom-values). | | `PlayVideo` | video name, [speed %] | Plays a clip you dropped into the video folder. | | `SendWebhook` | webhook address suffix, text | Posts a message to a Discord channel. | | `AddPlayerKey` / `RemovePlayerKey` | key name | Adds/removes a personal one-time flag on the player — this is what `HasPlayerKey` checks. | | `SetPlayerGuild` | guild ID or name | Moves the player into a specific guild. | | `SetPlayerGuildRank` | rank name | Sets the player's rank within their current guild. | | `SetNPCModelLocal` / `SetNPCModelGlobal` | model name | Changes the current NPC's model — `Local` only for the player who triggered it, `Global` for everyone. | | `SetNPCNameLocal` / `SetNPCNameGlobal` | name | Same, for the NPC's displayed name. | | `SetNPCPatrol` | patrol route data | Sets the NPC's patrol path — normally pasted in from a route you recorded, see [Marketplace Hammer](../npc/marketplace-hammer.md). | | `AddFaction` / `RemoveFaction` | faction key | Adds/removes one faction from the player. | | `RemoveAllFactions` | — | Clears every faction from the player. | ## A caution on `ConsoleCommand` `ConsoleCommand` can run **any** admin command, including cheat and world-editing commands — not just mod-specific ones. Anyone who can trigger the dialogue option or quest event that contains it effectively gets that admin access for that one command. Only use it in content you trust, and avoid handing it to untested or community-submitted dialogue/quest files. ## Related - [Conditions](conditions.md) — gating when a command runs. - [Dialogues](../configs/dialogues.md), [Quest Events](../configs/quest-events.md) — where commands are used. - [Custom Spawn Data](../configs/custom-spawn-data.md), [Custom assets](../assets/custom-assets.md). --- # Conditions Conditions are how you gate something behind a requirement — "only let the player click this dialogue option if they have 10 Wood", "only unlock this quest after finishing another one". The same condition language works in three places: [Dialogue](../configs/dialogues.md) options, [Quest](../configs/quests.md) unlock requirements, and [Quest Event](../configs/quest-events.md) triggers. ## Quick example A dialogue option gated behind having 10 Wood and 5 Stone. By default it still shows, greyed out with the reason, until the player has both — see [Dialogues](../configs/dialogues.md#when-a-condition-fails) if you want it hidden instead: ```cfg Text: Sell your materials | Condition: HasItem, Wood, 10 | Condition: HasItem, Stone, 5 | Transition: sell_confirm ``` A quest that only unlocks after finishing an earlier one in the same chain: `Configs/Quests/intro_quest.cfg`: ```cfg [intro_quest] ... QuestFinished, meet_the_elder ``` ## Syntax `ConditionName, argument1, argument2` — the condition's name first, then its arguments, all comma-separated. Spaces around commas are fine (see [Config file syntax](config-syntax.md)). **Negating a condition** — put `!` in front to flip it: ```cfg !HasItem, Wood, 10 ``` means "does NOT have 10 Wood". Most conditions also have a ready-made opposite name (`HasItem` / `NotHasItem`) if you prefer that instead of `!`. ## Combining conditions: AND and OR When a field holds more than one condition, two layers of logic apply: - `|` between conditions means **AND** — every group must pass. - `||` between conditions means **OR** — at least one alternative in that group must pass. ```cfg HasItem, Wood, 10 || HasItem, Stone, 10 | GlobalKey, defeated_bonemass ``` Reads as: **(**has 10 Wood **or** has 10 Stone**) and** has defeated Bonemass. Group your OR-alternatives together between `|`, and stack multiple `|` groups for a chain of AND requirements. More examples: ```cfg # Require two separate things, both must be true SkillMore, WoodCutting, 3 | HasItem, AxeFlint, 1 # Require any ONE of three items (a "pay with whatever you have" gate) HasItem, Wood, 20 || HasItem, Stone, 20 || HasItem, Coins, 50 # Require finishing an earlier quest AND being a guild member QuestFinished, chain_step_1 | HasGuild ``` ## Reference: all conditions | Condition | Arguments | What it checks | |---|---|---| | `HasItem` / `NotHasItem` | item, amount, [level] | Player has (or lacks) at least that many of an item, optionally at a specific quality level. | | `HasBuff` / `NotHasBuff` | buff name | Player currently has (or lacks) a specific active buff. | | `SkillMore` / `SkillLess` | skill, level | Player's skill level compares to a number. | | `GlobalKey` / `NotGlobalKey` | key name | A world-wide flag is set — the same flags used by boss kills (`defeated_bonemass`, etc.) and other mods. | | `HasQuest` / `NotHasQuest` | quest ID | Player currently has that quest accepted. | | `QuestProgressDone` / `QuestProgressNotDone` | quest ID | That quest's objective is complete, whether or not it has been turned in yet. | | `QuestFinished` / `QuestNotFinished` | quest ID | That quest has been completed and turned in — this is what quest chains use. | | `EpicMMOLevelMore` / `EpicMMOLevelLess` | level | Player's EpicMMO level compares (only if that mod is installed). | | `CozyheimLevelMore` / `CozyheimLevelLess` | level | Player's Cozyheim leveling level compares. | | `RustyClassesLevelMore` / `RustyClassesLevelLess` | level | Player's RustyClasses level compares. | | `HasAchievement` / `NotHasAchievement` | achievement ID | Player has earned a specific leaderboard achievement. | | `HasAchievementScore` / `NotHasAchievementScore` | score | Player's total achievement score compares to a number. | | `CustomValueMore` / `CustomValueLess` | key, value, [custom message] | Compares a [custom value](prefabs-and-assets.md#custom-values) you set yourself elsewhere. The optional third argument replaces the default failure message; use `{current}` and `{value}` inside it to show the numbers. | | `ModInstalled` / `NotModInstalled` | mod ID | Whether another mod is installed on the server. | | `IronGateStatMore` / `IronGateStatLess` | stat name, amount | Compares a built-in Valheim player stat. | | `HasGuild` / `NotHasGuild` | — | Player is (or is not) in a guild. | | `HasGuildWithName` / `NotHasGuildWithName` | guild name | Player's guild has a specific name. | | `GuildLevelMore` / `GuildLevelLess` | level | Player's guild level compares. | | `GuildHasAchievement` / `GuildNotHasAchievement` | achievement ID | Player's guild has earned a specific achievement. | | `IsVIP` / `NotIsVIP` | — | No longer functional since 9.9.2 removed the VIP system — `IsVIP` always fails, `NotIsVIP` always passes. See [Known gaps](../reference/known-gaps.md). | | `HasPlayerKey` / `NotHasPlayerKey` | key name | Player has a personal flag previously set with the `AddPlayerKey` command — useful for tracking one-time story beats per player. | | `NPCModelEquals` / `NotNPCModelEquals` | model name | The NPC in this dialogue currently uses a specific model. | | `NPCNameEquals` / `NotNPCNameEquals` | name | The NPC in this dialogue currently has a specific display name. | | `HasFaction` / `NotHasFaction` | faction key | Player belongs to a specific faction. | | `HasAnyFaction` / `NotHasAnyFaction` | — | Player belongs to any faction at all. | | `HealthMore` / `HealthLess`, `MaxHealthMore` / `MaxHealthLess` | value | Player's current/max health compares. | | `StaminaMore` / `StaminaLess`, `MaxStaminaMore` / `MaxStaminaLess` | value | Player's current/max stamina compares. | | `EitrMore` / `EitrLess`, `MaxEitrMore` / `MaxEitrLess` | value | Player's current/max eitr compares. | | `PlayerHasAllCustomDataKeys` | data set name, message | Checks the player against a whole [custom data set](../configs/custom-spawn-data.md) — true only if every value in the set matches the player exactly. | | `PlayerHasOneOfCustomDataKeys` | data set name, message | Checks the same way, but is true if the player differs from the data set on at least one value — despite the name, this is a "does not fully match" check, not a "has one of" check. Test it before relying on it for something important. | ## Related - [Commands](commands.md) — what runs when a condition passes. - [Dialogues](../configs/dialogues.md), [Quests](../configs/quests.md), [Quest Events](../configs/quest-events.md) — where conditions are used. - [Prefabs and text markup](prefabs-and-assets.md) — custom values referenced above. --- # Config file syntax Most config files under `Configs/` (quests, dialogues, territories, traders, bankers, gamblers, buffers, transmog, teleporters, server infos, leaderboard achievements) share the same basic text format. This page covers that shared format once, so the other pages can just show you the specifics. ## The basics A config file is plain text, one entry per line. A quick example (a Server Info page, but the rules apply everywhere): `Configs/ServerInfos/welcome.cfg`: ```cfg # This is a comment, ignored by the game [welcome] Welcome to the server! Please read the rules below. [rules] 1. No griefing. 2. PvP only in designated zones. ``` - Lines starting with `#` are comments — write yourself notes freely. - Blank lines are ignored — use them to visually separate blocks. - A line in `[Brackets]` starts a new **section** — usually a profile name (see [Profiles](profiles.md)). - The file name itself does not matter — call it whatever helps you stay organized. What matters is which folder it is in, and the `[Section]` headers inside it. - You can split one config type across as many files as you like, and put files in subfolders — everything in a folder is read together, including subfolders. ## Section names `[My Profile]`, `[myprofile]`, and `[MyProfile]` are treated as the exact same profile in most formats — spacing and capitalization inside brackets do not matter. The exceptions are [Territories](../configs/territories.md) and [Leaderboard Achievements](../configs/leaderboard-achievements.md), where the header is case-sensitive and keeps spaces exactly as written — see the practical notes on those two pages. Pick a consistent style for your own sake regardless; it makes files easier to read and search. Any script works in a header name, including Cyrillic and Chinese — none of these formats restrict you to specific characters. If you write data lines before any `[Section]` header, they land in a profile literally called `default` in most formats — this is intentional and safe to rely on, and several NPC types come pre-set to use the `default` profile in-game. [Dialogues](../configs/dialogues.md) and the quest database (not [Quest Profiles](../configs/quest-profiles.md) — the file where you write `[QuestID]` quests themselves) are the exception: unlabeled lines before the first header there are silently skipped instead of landing anywhere. ## Separators used across formats Three punctuation marks recur across almost every config type: | Symbol | Meaning | Example | |---|---|---| | `,` | Separates fields within one entry | `Wood, 10, 1` (item, amount, level) | | `\|` | Separates multiple entries on one line | `Wood, 10 \| Stone, 5` (two targets) | | `\|\|` | "OR" inside one condition group (only in requirement/condition fields) | `HasItem, Wood, 10 \|\| HasItem, Stone, 10` | **Write spaces freely around these symbols** — `Wood, 10, 1` and `Wood,10,1` behave identically. Spaces are stripped automatically before the line is read. Use spacing to make your files readable; there is no performance or correctness cost. ## Keeping a literal space (names, sentences) Because spaces are normally stripped, a field that must contain a real space — an NPC's full name, a sentence, a title — needs to be wrapped in `"double quotes"`: ```cfg Talk, "John the Smith", 1 ``` The quotes themselves are removed once the line is read; only the space inside survives. Use this any time a name or phrase has more than one word. ## If a line does not work Most config formats fail quietly per-entry, not per-file — a mistake in one quest, one trade line, or one zone usually only breaks that one entry, not the whole file, and gets logged to the server console with the file name and line number. Quests are stricter: a broken reward or wrong number of lines in a quest block skips that entire quest. Common causes of a "silent" mistake: - A count or amount left at `0` or negative is usually treated as `1` instead of erroring — worth double-checking if a quest target or trade always shows "1" no matter what you type. - Wrong number of comma-separated fields for the line's format (see the specific config page for the expected count). - A typo in a keyword (a condition name, a flag name, a quest type) — these fail silently rather than crashing, so the entry is simply skipped. When something is not appearing in-game, check the server console output first — most parsing problems are logged there in red. ## Related - [Profiles](profiles.md) — how `[Section]` headers group content together. - [Conditions](conditions.md), [Commands](commands.md) — the requirement/action language used inside many of these formats. --- # Content creation There is no in-game editor for quests, dialogues, zones, and so on. You create content by editing plain text files in a `Configs/` folder, one subfolder per feature. The mod watches those folders and picks up changes automatically. NPCs themselves are placed directly in the world, using a build-mode tool (**Marketplace Hammer**) available to players with admin access. When you place an NPC, you give it a **type** (which mechanic it uses) and a **profile** (which config entries it uses) right there in its settings panel. This page and the ones below describe the shared machinery — the syntax, vocabulary, and grouping rules every config format is built from. If you'd rather learn by doing, skip ahead to [NPC system](../npc/npc-system.md), the first page in Core, and place something — the individual feature pages link back here (usually as "Profiles", "Conditions", or "Commands") wherever you actually need one of these concepts, so nothing here is a prerequisite you have to finish first. ## Writing config files A handful of pages cover the syntax and vocabulary shared across many config types — read these once and the rest make a lot more sense: - [Config file syntax](config-syntax.md) — comments, sections, separators, and the general shape every config file follows. - [Profiles](profiles.md) — how content gets grouped and assigned to an NPC. - [Conditions](conditions.md) — the shared requirement language (`HasItem`, `QuestFinished`, and the rest). - [Commands](commands.md) — the shared action language (`GiveItem`, `Teleport`, and the rest). - [Prefabs and text markup](prefabs-and-assets.md) — referencing items, sounds, images, and dynamic text. - [Scheduling a config to a time window](time-windows.md) — limiting a Territory or Trader to specific hours. --- # Prefabs, assets, and inline text markup Shorthand and markup that shows up across many config formats — item names, sound/image references, and dynamic text. ## Item and creature names Any field asking for an item, creature, or object uses the exact same name you would use with the game's own `spawn` command — the vanilla item/creature name (`Wood`, `Wolf`, `SwordIron`) or an item added by another mod. There is no restricted list — if the game or an installed mod knows the name, you can reference it. ## Model with a different animation set `Model@AnimationSource` — makes an NPC use one model's appearance but another's movement/animations. Two useful shortcuts: ```cfg Player@Morgen # use the player model, animated like Morgen SomePrefab@humanoid # shorthand for "use the player's animations" ``` Example, on an NPC's model field: `Haldor@humanoid` gives you Haldor's look, moving like a normal humanoid NPC instead of his usual stiff idle. ## Sound with a custom volume Add `@number` after a sound name to set its volume (`1` = normal): ```cfg PlaySound, tavern_bell, 0.5 ``` is equivalent to a fashion sound field written as `tavern_bell@0.5`. ## Inline image `` inserts a picture wherever it appears — in a quest name or a [Server Info](../configs/server-infos.md) page. `NAME` is the file name (without extension) of an image you dropped into the images folder — see [Custom assets](../assets/custom-assets.md). ```cfg Welcome to the server! Read the rules below. ``` ## Teleporter travel speed Add `` inside a teleport destination's name to make travel take time instead of being instant: ```cfg "Mountain Outpost", 800, 150, -400 ``` Leave it out entirely for an instant teleport (the default). ## Custom values A simple per-player number you can set and read yourself, for tracking anything you like — reputation, a story flag, a counter. There is no fixed list of custom value names; you invent the key name and use it consistently across your quests/dialogues. - Set with `SetCustomValue, key, value` or add to it with `AddCustomValue, key, amount` (see [Commands](commands.md)). - Check with `CustomValueMore` / `CustomValueLess` (see [Conditions](conditions.md)). - Also usable as a quest reward: `SetCustomValue: key, value` or `AddCustomValue: key, amount`. Example — a simple reputation counter: ```cfg # reward line of a quest SetCustomValue: village_rep, 10 # condition elsewhere, gating a discount CustomValueMore, village_rep, 50, You need more reputation with the village. ``` Players can check their own current custom values in-game with the `mcustomvalues` command (see [Console commands](../setup/console-commands.md)). ## Dynamic text (`%keyword%`) A handful of placeholders get replaced automatically wherever greeting/farewell text or webhook messages are shown: | Placeholder | Becomes | |---|---| | `%playername%` | The player's name | | `%day%` | The current in-game day | | `%health%` / `%maxhealth%` | Current/max health | | `%stamina%` / `%maxstamina%` | Current/max stamina | ```cfg GreetText: Welcome back, %playername%! You've survived %day% days so far. ``` ## Custom Spawn Data A more structured way to attach extra values to something — see the dedicated page: [Custom Spawn Data](../configs/custom-spawn-data.md). Used from `GiveItemWithData`, `SpawnWithData`, `SpawnXYZWithData`, and `SetPlayerData` (see [Commands](commands.md)), and from `PlayerHasAllCustomDataKeys` / `PlayerHasOneOfCustomDataKeys` (see [Conditions](conditions.md)). ## Related - [Custom assets](../assets/custom-assets.md) — the sound/image/video folders these references point to. - [Commands](commands.md), [Conditions](conditions.md). --- # Profiles Most content types (Quests, Traders, Bankers, Teleporters, Gamblers, Buffers, Transmogrification, Server Info) are organized into **profiles**: named groups of entries, declared with `[ProfileName]` headers. ## Why this matters day to day An NPC does not carry its own private list of items or quests. Instead, when you place an NPC, you type a **profile name** into its settings, and the NPC shows whatever is registered under that name across every relevant config file. In practice this means: - **You can split one profile across several files.** Put the first ten trades for `[blacksmith]` in one file, and add five more later in a second file — they combine automatically, no special linking needed. - **Many NPCs can share one profile.** Place ten different Trader NPCs around the world, give them all the profile `general_store`, and they all sell the exact same thing. Update the file once, every NPC updates. - **A typo means "nothing shows up."** If the NPC's profile field says `Blacksmith` and your file says `[black_smith]`, the NPC will just show an empty list — there is no error message for a mismatched profile name, just an empty menu. This is the single most common "why is my NPC empty" problem. - **A space in a profile name is a trap, specifically because of the NPC's Profile field.** The config header itself strips spaces (`[Village Elder]` and `[villageelder]` are the same profile) — but the **Profile** field you type into on the NPC only lowercases what you enter, it does not strip spaces. Type `Village Elder` there and it is stored with the space, so it will never match a header that got normalized to `villageelder`. Avoid spaces in profile names entirely and this never comes up — every example in this documentation uses `snake_case` or one unbroken word for exactly this reason. ## Example: one trader profile fed by two files `Configs/Traders/weapons.cfg`: ```cfg [blacksmith] Coins, 50, SwordIron, 1, 2 Coins, 100, AxeIron, 1, 2 ``` `Configs/Traders/armor.cfg`: ```cfg [blacksmith] Coins, 80, HelmetIron, 1 Coins, 120, ChestIron, 1 ``` Any NPC set to Trader type with profile `blacksmith` now offers all four trades, regardless of which file they came from. ## Profile header extras A handful of formats let you attach extra info directly to the `[ProfileName]` header, after `=` or `@`: | Format | Syntax | Meaning | |---|---|---| | Quests | `[quest_id = Autocomplete]` | Special quest behavior tag — see [Quests](../configs/quests.md). | | Territories | `[zone_name@2]` | Priority number — higher wins where zones overlap. | | Traders | `[profile = true]` | Only shows trades for items the player has already discovered. | | Gamblers | `[profile = 3]` | Caps how many rolls can be queued at once. | Spacing around `=` here is safe either way — write `[quest_id = Autocomplete]` or `[quest_id=Autocomplete]`, both parse identically. **The Territories `@` is the one exception**: unlike everywhere else in these config files, a space before `@` is not stripped and becomes part of the zone's actual name — always write it as `[zone_name@2]`, with no space before the `@`. Territory names are also case-sensitive and keep any other internal spaces literally, unlike every other header type on this page. ## Related - [Config file syntax](config-syntax.md). - [NPC system](../npc/npc-system.md) — where you actually type a profile name onto an NPC. --- # Scheduling a config to a time window [Territories](../configs/territories.md) and [Traders](../configs/traders.md) can be limited to a real-world time-of-day window — a "happy hour" zone, a night-only market — by putting their files in a specially-named folder. ## How to set it up Create a subfolder named `HH-MM_HH-MM` (24-hour clock) and put your `.cfg` files directly inside it: ``` Configs/Territories/ ├─ always_on.cfg ← no folder trick used, always active └─ 18-00_23-00/ └─ evening_market.cfg ← only active from 18:00 to 23:00 ``` Anything **not** inside a folder named this way is simply always active — you only need this for content you want to schedule. ## Example: an evening-only bonus zone `Configs/Territories/18-00_23-00/happy_hour.cfg`: ```cfg [happy_hour_zone] Circle 0, 0, 40 255, 255, 150 PeriodicHealALL = 5 None ``` This zone exists in the world only between 18:00 and 23:00 server time. Before and after that window, it is as if the file does not exist at all. ## Example: a night-market trader `Configs/Traders/22-00_04-00/night_market.cfg`: ```cfg [night_market] Coins, 200, RareGem, 1 ``` This trade is only offered between 22:00 and 04:00. ## Things worth knowing - This checks the **server's real clock**, not the in-game day/night cycle. - The schedule is checked roughly every 30 seconds, so a boundary (like exactly 18:00) takes effect within about half a minute, not instantly. - **Windows that cross midnight do not work as written.** `22-00_02-00` will never activate, because the check is a simple "is the current time between the first and second number" — and 22:00 is not less than 2:00. Split an overnight schedule into two folders instead: ``` Configs/Territories/22-00_23-59/night_part1.cfg Configs/Territories/00-00_02-00/night_part2.cfg ``` Put the same content in both, and together they cover 22:00 through 02:00 without a gap. ## Related - [Territories](../configs/territories.md), [Traders](../configs/traders.md). --- # Bankers **Folder:** `Configs/Bankers/` (any file name, `.cfg`) Controls which items a Banker NPC will accept for deposit and withdrawal. Once you have written a profile here, put its name in a `Banker`-type NPC's **Profile** field to make it live — see [Core identity settings](../npc/npc-system.md#core-identity-settings). ![Banker UI in-game — green number is the banked amount, bottom text is inventory](../images/screenshots/KlarEFR.png) ## Example `Configs/Bankers/main_bank.cfg`: ```cfg [main_bank] Coins Ruby Amber ``` One item name per line — this list only decides **which item types** can be banked at all; how much a player has deposited is tracked automatically and does not live in this file. ## Assigning it to an NPC Put the profile name (`main_bank` above) into a `Banker`-type NPC's **Profile** field — see [Core identity settings](../npc/npc-system.md#core-identity-settings): ![Assigning a Banker profile to an NPC](../images/screenshots/dQriWbn.png) ## Accessing a bank without a nearby NPC A Banker profile can also be reached remotely, without a Banker NPC in range at all, by listing it under `BankerProfiles` in [Distanced UI](distanced-ui.md). ## Interest Interest on deposits is not set here — it is a server-wide setting. See [Server config](../setup/server-config.md) for `BankerIncomeTime`, `BankerIncomeMultiplier`, and `BankerInterestItems`. Looking for a separate, higher interest rate for a privileged player tier? That setting was removed in 9.9.2 — see [Migrations](../reference/migrations.md#updating-to-992-the-vip-system-is-gone). ## Related - [Profiles](../concepts/profiles.md) — how a banker profile name groups entries across files. - [Server config](../setup/server-config.md) — interest rate settings. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. - [Shop and economy guide](../guides/shop-and-economy.md). --- # Buffer Profiles **Folder:** `Configs/BufferProfiles/` (any file name, `.cfg`) Chooses which [buffs](buffers.md) an Enchanter NPC actually offers for sale. Once you have written a profile here, put its name in a `Buffer`-type NPC's **Profile** field to make it live — see [Core identity settings](../npc/npc-system.md#core-identity-settings). It can also be reached remotely, without a nearby NPC, by listing it under `BufferProfiles` in [Distanced UI](../configs/distanced-ui.md). ## Example `Configs/BufferProfiles/buff_shop.cfg`: ```cfg [buff_shop] haste_buff, strength_buff, warmth_buff ``` An NPC set to profile `buff_shop` offers exactly these three buffs, defined in [Buffers](buffers.md). ## Important: one line per profile Only the first data line under a `[profile]` header is used — a second line under the same header is ignored. List every buff for one profile on a single line. ## Related - [Profiles](../concepts/profiles.md) — how profile names group content across files in general. - [Buffers](buffers.md) — the buff definitions this profile picks from. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. --- # Buffers (buff catalog) **Folder:** `Configs/Buffers/` (any file name, `.cfg`) Defines the buffs an Enchanter NPC can sell. This page is the buff **definitions** — which buffs a given NPC actually offers is set separately in [Buffer Profiles](buffer-profiles.md). ## Example `Configs/Buffers/haste_buff.cfg`: ```cfg [haste_buff] Wind Runner's Blessing 300 sprite_haste Coins, 50 ModifySpeed = 0.3, ModifyStaminaRegen = 0.2 vfx_haste_start movement_buffs ``` | Line | Content | Meaning | |---|---|---| | header | `[haste_buff]` | The buff's unique ID — this is what a Buffer Profile lists to make it available. | | 1 | `Wind Runner's Blessing` | Display name. | | 2 | `300` | Duration in seconds. | | 3 | `sprite_haste` | Icon. | | 4 | `Coins, 50` | Price — item and amount. | | 5 | `ModifySpeed = 0.3, ModifyStaminaRegen = 0.2` | What the buff actually does — see below. | | 6 | `vfx_haste_start` | A visual effect played when the buff is applied. | | 7 | `movement_buffs` | A group name — see [Buff groups](#buff-groups). | ## What a buff can modify Each modifier needs a `= number` value: | Modifier | Effect | |---|---| | `ModifyAttack` | Attack damage. | | `ModifyHealthRegen` | Health regeneration. | | `ModifyStaminaRegen` | Stamina regeneration. | | `ModifyRaiseSkills` | Skill gain rate. | | `ModifySpeed` | Movement speed. | | `ModifyNoise` | Noise radius (stealth). | | `ModifyMaxCarryWeight` | Carry weight. | | `ModifyStealth` | Stealth. | | `RunStaminaDrain` | Sprint stamina drain. | | `DamageReduction` | Incoming damage reduction. | Combine several on one buff: `ModifyAttack = 0.15, DamageReduction = 0.1` gives more damage and less damage taken at once. ## Buff groups Buffs sharing the same group name (the last line) count as mutually exclusive — buying a new buff in a group replaces whichever one from that group was already active. Use this to stop players from stacking every buff you sell into one overpowered combo; give competing buffs the same group name. ## Related - [Buffer Profiles](buffer-profiles.md) — which buffs an NPC actually offers. --- # Custom Spawn Data **Folder:** `Configs/CustomSpawnData/` (`.yml` files) Custom Spawn Data lets you attach a named set of extra values to something you spawn or give a player — useful for stamping custom data onto an item (for compatibility with other item mods), or for tracking a condition on the player themselves. Referenced by name from: - The `GiveItemWithData`, `SpawnWithData`, `SpawnXYZWithData`, and `SetPlayerData` [commands](../concepts/commands.md). - The `PlayerHasAllCustomDataKeys` / `PlayerHasOneOfCustomDataKeys` [conditions](../concepts/conditions.md). ## Example `Configs/CustomSpawnData/blessed_sword.yml`: ```yaml Ints: crafterID: 12345 Floats: bonusDamage: 25.0 Strings: loreText: "Forged in the ashes of the Bonemass" ``` Used from a dialogue reply: ```cfg Text: Take the blessed sword | Command: GiveItemWithData, SwordIron, 1, 3, blessed_sword ``` ## Format **One file = one named data set.** The file name (without `.yml`) is the name you reference elsewhere — `blessed_sword.yml` is referenced as `blessed_sword`. Inside the file, group your values by type — all five groups are optional, include only what you need: ```yaml Ints: someKey: 5 Floats: someKey: 1.5 Longs: someKey: 100000 Strings: someKey: "hello" Bools: someKey: true ``` The key names (`someKey` above) are entirely up to you — invent whatever makes sense for what you are tagging. ## Practical notes - If one file has a formatting mistake, it can block every other Custom Spawn Data set from updating until it is fixed — double-check indentation and quoting carefully in this format, since small YAML mistakes are easy to make. - There is no built-in meaning to any of these values — they only matter if something reads them back. `PlayerHasAllCustomDataKeys` reads them back against the player, and other item mods may read matching values off an item if you use the same key names they expect. ## Related - [Commands](../concepts/commands.md), [Conditions](../concepts/conditions.md). - [Dialogues](dialogues.md). - [Tracking player state](../guides/tracking-player-state.md) — worked examples using `SetPlayerData` and `PlayerHasAllCustomDataKeys` together, for puzzles and remembered choices. --- # Dialogues **Folder:** `Configs/Dialogues/` (any file name, `.cfg`) Dialogues build branching conversations for an NPC — what it says, what the player can say back, and what happens as a result. Every [condition](../concepts/conditions.md) and [command](../concepts/commands.md) in this mod originates here; [Quests](quests.md) and [Quest Events](quest-events.md) reuse the exact same language. Once you have written a dialogue tree here, put its top-level node's ID in **any** NPC's **Dialogue** field to attach it — see [Core identity settings](../npc/npc-system.md#core-identity-settings). Unlike the [profile](../concepts/profiles.md)-based modules, this field is independent of the NPC's Type, so even a `None`-type NPC can hold a full conversation. A dialogue can also be opened remotely, without a nearby NPC, by listing its top-level node ID under `Dialogues` in [Distanced UI](distanced-ui.md). **If an NPC has a Dialogue set, clicking it always opens the dialogue instead of its normal Type-based menu** (Trader, Banker, and so on). Use the `OpenUI` command from inside the dialogue if you still want to give players a way into that menu — see the [interaction triggers example](#silent-triggers-no-visible-reply) below. ## A simple example `Configs/Dialogues/merchant_greet.cfg`: ```cfg [merchant_greet] Welcome, traveler. What can I do for you? Text: Show me your wares | Command: OpenUI, Trader, merchant_stock Text: I have a quest for you | Condition: NotHasQuest, supply_run | Command: GiveQuest, supply_run Text: Goodbye | Transition: merchant_bye [merchant_bye] Safe travels. ``` - `[merchant_greet]` is the conversation node's ID. Node IDs are matched case-insensitively but are always lowercased internally — writing them in lowercase in your files avoids any confusion. - The first line after the header, `Welcome, traveler...`, is what the NPC says. - Every line after that is one clickable reply for the player, made of `|`-separated pieces. - `Transition: merchant_bye` moves to another node when clicked — that is how you link nodes into a longer conversation. Always give a node at least one reply, even a plain `Text: Goodbye` with no `Transition` — a node with zero replies can only be closed with the Escape key, which is a dead end for players who do not know that. ## Reply line fields Each reply is built from `Key: Value` pieces, separated by `|`. Use as many as you need on one line: | Field | What you put there | |---|---| | `Text` | The text shown for this reply. Use `\n` for a line break. | | `Transition` | The ID of the next conversation node. | | `RandomTransition` | Several node IDs, comma-separated — jumps to one picked at random, each with equal odds. List a node more than once to make it more likely. | | `Command` | One [command](../concepts/commands.md) to run. Add several `Command:` pieces to run more than one. | | `RandomCommand` | `chance, CommandName, args` — a command with an independent percent chance (0-100) of firing, see [Commands](../concepts/commands.md#random-outcomes). | | `Condition` | One [condition](../concepts/conditions.md) the player must meet for this reply to appear enabled. Add several `Condition:` pieces to require all of them. | | `Icon` | An icon to show next to this reply — an image file name (see [Custom assets](../assets/custom-assets.md)) or an existing item/piece prefab's own icon. | | `AlwaysVisible` | `true` (the default) or `false` — see [When a condition fails](#when-a-condition-fails) below. | | `Color` | `r, g, b` — a custom text color. | | `OverrideError` | Custom text to show instead of the default failure reason when a condition fails. | ## When a condition fails `AlwaysVisible` defaults to `true`, and that default surprises people: **a reply whose condition fails is still shown by default** — just greyed out, unclickable, and with the failure reason appended in red. It is not hidden unless you say so explicitly. ```cfg Text: I'm ready | Condition: HasItem, RitualCandle, 3 | OverrideError: You need 3 Ritual Candles first. | Transition: ritual_start ``` With no `AlwaysVisible` field, this reply always shows — a player without the candles sees it greyed out with "You need 3 Ritual Candles first." next to it. To hide the reply completely until the condition is met instead, add `AlwaysVisible: false`: ```cfg Text: I'm ready | Condition: HasItem, RitualCandle, 3 | AlwaysVisible: false | Transition: ritual_start ``` Which behavior you want depends on the reply — showing a locked option with an explanation is often better UX (it tells the player what they are missing) than making them wonder why an option they expect is not there. ## Silent triggers (no visible reply) Some lines should run automatically instead of appearing as a clickable option — for example, playing a sound the moment the player walks up, or immediately redirecting into the NPC's shop UI instead of showing any text. Prefix the line with one of these: | Prefix | Fires | |---|---| | `@interaction` (or `@onopen`) | Every time this specific node is loaded — whether that is the player's first click on the NPC, or a `Transition` from another node into this one. | | `@inrange` | Once, when the player walks within about 10 meters of the NPC. | | `@outrange` | Once, when the player then walks back out past about 12 meters. | Worked examples: [Dialogue patterns](../guides/dialogue-patterns.md#reacting-to-proximity-without-a-visible-reply) — proximity triggers, handing an NPC's normal menu back to it with `@interaction`, and chaining commands before a risky line. ## Random outcomes Each `RandomCommand` on a reply rolls its own independent chance — a line with several `RandomCommand` pieces can give the player none, some, or all of them, not exactly one. If you want exactly one of several outcomes instead — never more, never fewer — send the player to a different node per outcome with `RandomTransition`: ```cfg Text: Open it | RandomTransition: chest_coins, chest_ruby, chest_nothing, chest_nothing, chest_nothing ``` Listing a node more than once (`chest_nothing` three times here) is how you weight a `RandomTransition` — it just becomes more likely to be the one picked, since every entry has an equal chance. Worked example: [Dialogue patterns: independent rolls vs a single random pick](../guides/dialogue-patterns.md#independent-rolls-vs-a-single-random-pick). ## Password gates `EnterPassword` opens a text-entry popup and transitions to one of two nodes depending on whether the player typed the right word. Anything that should happen on success or failure — granting a key, teleporting, showing more text — goes on a reply *inside* the target node, not inside `EnterPassword` itself. Worked example: [Dialogue patterns: a password-gated door](../guides/dialogue-patterns.md#a-password-gated-door). ## Console commands with spaces `ConsoleCommand` runs anything you could type into the admin console yourself, with `{playername}` substituted for the local player's name. Since most console commands contain spaces, wrap the whole thing in quotes. Worked example: [Dialogue patterns: quoting console commands](../guides/dialogue-patterns.md#quoting-console-commands-with-spaces). See the [caution on `ConsoleCommand`](../concepts/commands.md#a-caution-on-consolecommand) before using this in content you did not write yourself. ## Keeping literal spaces Text that needs a real space where the format would otherwise strip it — a name, a sentence used as a command argument — should be wrapped in double quotes: `"Vault Access"`. See [Config file syntax](../concepts/config-syntax.md#keeping-a-literal-space-names-sentences). Any argument containing a comma should be quoted for the same reason. ## Custom spawn data For attaching extra values to spawned items/creatures from a dialogue command, see [Custom Spawn Data](custom-spawn-data.md). ## Related - [Conditions](../concepts/conditions.md), [Commands](../concepts/commands.md) — the full shared vocabulary. - [Dialogue tree guide](../guides/dialogue-tree.md) — a longer worked example. - [Dialogue patterns](../guides/dialogue-patterns.md) — proximity triggers, menu handoffs, weighted rewards, password gates, and quoted console commands. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. --- # Discord Webhooks **File:** `Marketplace/DiscordWebhooks/DiscordSettings.cfg` (a single settings file) Posts server events — marketplace sales, gambler wins, quest completions — to a Discord channel. This is separate from the `SendWebhook` command (see [Commands](../concepts/commands.md)), which you can trigger from any dialogue or quest event; this file only covers a handful of built-in events. ## Example `Marketplace/DiscordWebhooks/DiscordSettings.cfg`: ```ini [Webhook Links] Marketplace Webhook Link = https://discord.com/api/webhooks/XXXX/YYYY Gambler Webhook Link = https://discord.com/api/webhooks/XXXX/ZZZZ [Webhook Messages] Marketplace Webhook Message = **{0}** just listed **x{1} {2}** for **{3} {4}** each! [Webhook Titles] Marketplace Webhook Title = Market Alerts ``` ## Format Three sections, each with one setting per event type (`Marketplace`, `Gambler`, `Quest`, `Lootboxes`): | Section | What it sets | |---|---| | `[Webhook Links]` | The Discord webhook address for each event type. Leave the default placeholder in place to disable posting for that event. | | `[Webhook Messages]` | A message template. `{0}`, `{1}`, etc. get filled in with the relevant details (player name, item, amount, price...). | | `[Webhook Titles]` | The name shown as the poster of the message in Discord. | ### Message placeholders | Type | Placeholders | |---|---| | `Marketplace` | `{0}` seller, `{1}` count, `{2}` item name, `{3}` price, `{4}` currency name | | `Gambler` | `{0}` player, `{1}` count, `{2}` item name | | `Quest` | `{0}` player, `{1}` quest name | | `Lootboxes` | `{0}` player, `{1}` lootbox name, `{2}` result | Note: the Lootboxes settings exist here, but the Lootboxes feature itself is not currently functional in this version of the mod — see [Known gaps](../reference/known-gaps.md). ## Related - `SendWebhook` in [Commands](../concepts/commands.md) — for posting your own custom messages from dialogues/quest events. --- # Distanced UI **File:** `Marketplace/DistancedUI/DistancedUI.cfg` (a single settings file) Lets players open shop/quest/mail menus from anywhere, without needing to stand next to the matching NPC — useful for a "phone book" style menu, or one hub NPC that gives access to everything. ## Example `Marketplace/DistancedUI/DistancedUI.cfg`: ```ini [DistancedUI] Enabled = true CanUseMarketplace = true CanUseMail = true CanTakeMailAttachments = false TraderProfiles = general_store, rare_goods QuestProfiles = village_elder BankerProfiles = main_bank GamblerProfiles = BufferProfiles = TeleporterProfiles = InfoProfiles = default TransmogrificationProfiles = Dialogues = ``` This turns on remote access to the marketplace and mail, plus the `general_store`/`rare_goods` trader profiles, the `village_elder` quest profile, the `main_bank` banker profile, and the `default` info page — everything else stays inaccessible remotely (empty list). ## Settings | Setting | Meaning | |---|---| | `Enabled` | Master on/off switch. | | `CanUseMarketplace` | Allow remote access to the player-to-player marketplace. | | `CanUseMail` | Allow remote access to mail. | | `CanTakeMailAttachments` | Allow claiming mail attachments remotely, separate from just reading mail. | | `TraderProfiles`, `TeleporterProfiles`, `GamblerProfiles`, `BufferProfiles`, `BankerProfiles`, `QuestProfiles`, `InfoProfiles`, `TransmogrificationProfiles`, `Dialogues` | Comma-separated lists of which profiles from each module are remotely accessible. Leave a list empty to keep that module fully local (near-NPC only). | ## Spawning an NPC remotely There's no `SpawnedNPCsProfiles` setting to fill in above — as long as `Enabled` is `true`, every [Spawned NPC](spawned-npcs.md) profile on the server shows up in its own tab here automatically, filtered by that profile's own `Condition` field rather than an admin allowlist. ## Related - [Traders](traders.md), [Teleporters](teleporters.md), [Gamblers](gamblers.md), [Buffer Profiles](buffer-profiles.md), [Bankers](bankers.md), [Quest Profiles](quest-profiles.md), [Server Info](server-infos.md), [Transmogrification](transmogrification.md), [Dialogues](dialogues.md), [Spawned NPCs](spawned-npcs.md). --- # Factions **File:** `Configs/Factions.yml` (a single file, created automatically on first server start) Defines player factions — groups with their own restricted items, friendly monsters, bonus skills, and a shared buff. Players join a faction through dialogue commands, and content can check faction membership through conditions. ## Example `Configs/Factions.yml`: ```yaml forest_clan: Name: Forest Clan Icon: forest_clan_icon FriendlyMonsters: [Boar, Deer] BonusSkills: WoodCutting: 15 Bows: 10 Buff: forest_kinship CanDamageSameFaction: false mountain_clan: Name: Mountain Clan SpecificCraftItems: [FrostArrows] BonusSkills: Pickaxes: 20 ``` Here, `forest_clan` members are friendly with Boars and Deer, get bonus WoodCutting and Bows skill, receive the `forest_kinship` buff, and cannot damage each other. `mountain_clan` members can craft `FrostArrows` (others cannot) and get bonus Pickaxes skill. ## Fields The faction key (`forest_clan`, `mountain_clan` above) is what you reference from `AddFaction`/`RemoveFaction` commands and `HasFaction` conditions. | Field | Meaning | |---|---| | `Name` | Display name — the only required field. | | `Icon` | Faction icon. | | `SpecificUseItems` | Items only this faction's members can use. | | `BlockPickupItems` | Items this faction cannot pick up. | | `SpecificBuildings` | Buildings only this faction can build. | | `SpecificCraftItems` | Items only this faction can craft. | | `FriendlyMonsters` / `FullFriendlyMonsters` | Creatures that will not attack faction members (two tiers of friendliness). | | `BonusSkills` | A list of `Skill: bonus level` for passive skill bonuses. | | `Buff` | A buff (from [Buffers](buffers.md)) applied automatically while a member. | | `CanDamageSameFaction` | Set to `false` to disable friendly fire within the faction (defaults to `true`, friendly fire on). | ## Managing membership Players join and leave factions through dialogue or quest event commands — `AddFaction`, `RemoveFaction`, `RemoveAllFactions` (see [Commands](../concepts/commands.md)). A common pattern is a dialogue reply that recruits the player: ```cfg Text: Join the Forest Clan | Command: AddFaction, forest_clan ``` ## Related - [Buffers](buffers.md) — the `Buff` field references a buff you define there. - [Conditions](../concepts/conditions.md), [Commands](../concepts/commands.md). --- # Gamblers **Folder:** `Configs/Gamblers/` (any file name, `.cfg`) Sets up a gambling NPC's roll table — spend a required item, receive one random item from a prize pool. Once you have written a profile here, put its name in a `Gambler`-type NPC's **Profile** field to make it live — see [Core identity settings](../npc/npc-system.md#core-identity-settings). It can also be reached remotely, without a nearby NPC, by listing it under `GamblerProfiles` in [Distanced UI](distanced-ui.md). ## Example `Configs/Gamblers/tavern_dice.cfg`: ```cfg [tavern_dice] Coins, 20, Coins, 10-40, Wood, 20-50, Ruby, 1 ``` Costs 20 Coins per roll. The prize is a random amount of Coins (10-40), a random amount of Wood (20-50), or 1 Ruby. ## Format The whole line is a flat, comma-separated list of `item, amount` pairs: ```cfg costItem, costAmount, prizeItem1, amount1, prizeItem2, amount2, ... ``` **The first pair is always the cost.** Everything after it is the prize pool. An amount can be a fixed number (`5`) or a range (`10-40`), rolled fresh each time. ## Limiting simultaneous rolls Add a number to the header to cap how many rolls a player can queue at once: `Configs/Gamblers/bronze_gamble.cfg`: ```cfg [bronze_gamble = 3] Coins, 10, Coins, 5-15, Wood, 10-30, ArrowFire, 5, Ruby, 1 ``` ## Important: one line per profile Only the **last** data line under a `[profile]` header is used — writing two separate roll-table lines under the same profile means the first one is silently thrown away. Always put a profile's entire cost-and-prizes on a single line. ## Related - [Profiles](../concepts/profiles.md) — how a gambler profile name groups entries across files. - [Server config](../setup/server-config.md) — `GamblerEnableWinNotifications`. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. - [Shop and economy guide](../guides/shop-and-economy.md). --- # Leaderboard Achievements **Folder:** `Configs/LeaderboardAchievements/` (any file name, `.cfg`) Defines achievements tracked on the server leaderboard — kills, crafting, building, deaths, exploration, PvP kills. Requires `UseLeaderboard = true` in the [server config](../setup/server-config.md); otherwise the leaderboard does not run at all. ![An achievement earned in-game](../images/screenshots/clRp8hT.png) ## Example `Configs/LeaderboardAchievements/achievements.cfg`: ```cfg [wolf_hunter] MonstersKilled Wolf Hunter Kill 50 wolves Wolf, 50 200, 200, 200 100 [explorer] Explored World Explorer Explore 75% of the map 75 100, 200, 255 250 ``` | Line | Meaning | |---|---| | header | The achievement's unique ID. | | 1 | Trigger type — see the table below. | | 2 | Display name. | | 3 | Description. | | 4 | The target — `item, amount` for most types, or just `amount` for `Explored`/`Died`/`PlayersKilled`. | | 5 | Badge color, `r, g, b`. | | 6 | Score — used for sorting achievements and toward `HasAchievementScore`. | Unlike most `[Section]` headers in this mod, an achievement ID is **case-sensitive and keeps internal spaces exactly as written** — `[wolf_hunter]` and `[Wolf_Hunter]` are two different achievements, not the same one. Keep this in mind when referencing an ID from `HasAchievement` in [Conditions](../concepts/conditions.md) — it must match the header exactly, including case. ## Trigger types | Trigger | Needs an item/creature name? | Tracks | |---|---|---| | `MonstersKilled` | yes | Kills of a specific creature. | | `ItemsCrafted` | yes | Crafts of a specific item. | | `StructuresBuilt` | yes | Builds of a specific piece. | | `KilledBy` | yes | Deaths to a specific creature. | | `Harvested` | yes | Harvests of a specific resource. | | `Explored` | no | Total map exploration percentage. | | `Died` | no | Total death count. | | `PlayersKilled` | no | Total PvP kills. | ## Related - [Server config](../setup/server-config.md) — `UseLeaderboard`. --- # Player Tags **File:** `Marketplace/PlayerTags/PlayerTags.cfg` (a single file, created automatically on first server start — note this one lives outside the `Configs/` folder) Prefixes a player's name in the player list with a custom tag, like `[Admin]` or `[Trusted]`. ## Example `Marketplace/PlayerTags/PlayerTags.cfg`: ```cfg 76561198000000001: [Admin] 76561198000000002: [Trusted] ``` ## Format `userID: tag text` — one player per line. The user ID is the player's platform ID (Steam ID, etc.), the same kind of ID used for `OverrideDebug` and `BlockedPlayers` in the [server config](../setup/server-config.md). Keep the tag text free of colons — the line is split on the first `:`, so an extra colon inside the tag will break the line. ## Related - [Server config](../setup/server-config.md) — other places player IDs are configured. --- # Quest Events **Folder:** `Configs/QuestEvents/` (any file name, `.cfg`) Quest Events let you attach [commands](../concepts/commands.md) and [conditions](../concepts/conditions.md) to a quest's lifecycle — accepting it, completing it, cancelling it, timing out, or the player dying while it is active. This is how a quest can do more than just hand out a reward — spawn a boss on accept, remove borrowed gear if the player dies, teleport them somewhere on completion. ![A quest event file, editing directly](../images/screenshots/Qcp98Rx.png) ## Example `Configs/QuestEvents/boss_hunt.cfg`: ```cfg [boss_hunt] OnAcceptQuest: GiveItem, SwordIron, 1, 3 OnAcceptQuest: GiveItem, HealthPotion, 3, 1 OnCompleteQuest: AddPlayerKey, boss_01_defeated OnCompleteQuest: Teleport, 0, 30, 0 OnCompleteQuest: GuildAddLevel, 5 OnDeath: RemoveItem, SwordIron, 1 ``` This lends the player a sword and potions when they accept a "boss hunt" quest, takes the borrowed sword back if they die mid-fight, and on success marks a permanent flag, teleports them home, and gives their guild a level. ## Format ```cfg [quest_id] EventName: entry1 | entry2 | ... ``` The `[quest_id]` header must match a quest defined in [Quests](quests.md) exactly — this is how the event attaches to that specific quest. You can add several `EventName:` lines under the same header; they all apply. ## Available events | Event | Fires when | |---|---| | `OnAcceptQuest` | The player accepts the quest. | | `OnCancelQuest` | The quest is cancelled or removed. | | `OnCompleteQuest` | The quest is turned in / completed. | | `OnQuestTimeout` | The quest's time limit runs out before it is finished (see [Quests](quests.md#cooldown-and-time-limit)). | | `OnDeath` | The player dies while the quest is active. | ## Writing entries Each entry after the event name is either a plain command, or an explicit condition — separate several with `|`: ```cfg OnCompleteQuest: HasAchievement, dragonslayer | GiveItem, Coins, 500 ``` This only gives the bonus 500 Coins if the player already has the `dragonslayer` achievement — conditions gate whatever commands follow them on the same line. You do not need to write `Command:` in front of a plain action — just the action name works: ```cfg OnAcceptQuest: Spawn, GoblinKing, 1, 3 ``` ## Practical patterns Clean up temporary gear on failure: `Configs/QuestEvents/boss_hunt.cfg`: ```cfg [boss_hunt] OnAcceptQuest: GiveItem, SwordIron, 1, 3 OnCancelQuest: RemoveItem, SwordIron, 1 OnQuestTimeout: RemoveItem, SwordIron, 1 ``` Announce a completion in Discord: `Configs/QuestEvents/dragon_slayer.cfg`: ```cfg [dragon_slayer] OnCompleteQuest: SendWebhook, discord.com/api/webhooks/xxxx, %playername% slew the dragon! ``` Teleport to safety on timeout: `Configs/QuestEvents/timed_trial.cfg`: ```cfg [timed_trial] OnQuestTimeout: Teleport, 0, 30, 0 ``` ## Related - [Quests](quests.md), [Commands](../concepts/commands.md), [Conditions](../concepts/conditions.md). --- # Quest Profiles **Folder:** `Configs/QuestProfiles/` (any file name, `.cfg`) This is how you hand your [Quests](quests.md) to an actual NPC. Once you have written a profile here, put its name in a `Quests`-type NPC's **Profile** field — the NPC offers every quest listed under that name here. See [Core identity settings](../npc/npc-system.md#core-identity-settings) for exactly where to enter it. It can also be reached remotely, without a nearby NPC, by listing it under `QuestProfiles` in [Distanced UI](../configs/distanced-ui.md). ## Example `Configs/QuestProfiles/npcs.cfg`: ```cfg [village_elder] kill_10_wolves, timber_run, intro_talk [blacksmith] craft_masterwork_axe ``` An NPC set to profile `village_elder` will offer all three quests listed. An NPC set to `blacksmith` offers just the one. ## Format ```cfg [ProfileName] questID1, questID2, questID3 ``` You can list quest IDs across several lines, or several files, under the same profile name — everything gets combined. For example, `Configs/QuestProfiles/elder-part1.cfg` and `Configs/QuestProfiles/elder-part2.cfg`, shown together here for brevity: ```cfg [village_elder] kill_10_wolves, timber_run [village_elder] intro_talk, escort_merchant ``` This is the same as writing all four quest IDs on one line — useful for organizing a large NPC's quest list into logical groups across separate files. ## Practical notes - The order you list quests in does not control anything about how they are offered — it is just for your own organization. - A quest ID that does not exist anywhere in [Quests](quests.md) is simply ignored — no error, it just never shows up. If a quest is missing in-game, double check the spelling matches exactly. ## Related - [Profiles](../concepts/profiles.md) — how profile names group content across files in general. - [Quests](quests.md) — the quest definitions this profile lists. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. - [First quest guide](../guides/first-quest.md). --- # Quests **Folder:** `Configs/Quests/` (any file name, `.cfg`) This is where you define quests themselves — what to do, what it gives, how long it lasts. A quest here is not tied to any particular NPC yet; you hand it out to NPCs separately, through [Quest Profiles](quest-profiles.md). At a glance, a quest database file (`Configs/Quests/starter.cfg`) with a few simple quests: ```cfg [greet_elder] Talk A Warm Welcome Say hello to the village elder. "Village Elder" Item: Coins, 10 0 [wolf_pelts] Kill Wolf Culling The village needs wolf pelts. Bring me 5. Wolf, 5, 1 Item: Coins, 50 | Skill_EXP: Bows, 20 0 [gather_wood] Collect Timber Run Bring me 20 wood. Wood, 20 Item: Coins, 30 0 ``` ...and a [Quest Profile](quest-profiles.md) (`Configs/QuestProfiles/starter.cfg`) handing all three to one NPC: ```cfg [village_elder] greet_elder, wolf_pelts, gather_wood ``` And what accepting a quest looks like from the NPC's side and the player's own journal: | NPC's quest offer | Player's quest journal | |---|---| | ![Quest shown at the NPC](../images/screenshots/c4FHGqG.png) | ![Quest journal after accepting a quest](../images/screenshots/lleU3rp.png) | ## A complete example, explained line by line `Configs/Quests/wolf_pelts.cfg`: ```cfg [wolf_pelts] Kill Wolf Culling The village needs wolf pelts. Bring me 5. Wolf, 5, 1 Item: Coins, 50 | Skill_EXP: Bows, 20 0 ``` | Line | Content | Meaning | |---|---|---| | header | `[wolf_pelts]` | The quest's unique ID — this is what you reference from a Quest Profile, from another quest's chain condition, or from a Quest Event. | | 1 | `Kill` | The quest type — what kind of objective this is. See [Quest types](#quest-types) below. | | 2 | `Wolf Culling` | The quest's title, shown in the quest journal. | | 3 | `The village needs...` | The description text. | | 4 | `Wolf, 5, 1` | The target: kill Wolves, 5 of them, minimum star level 1 — see [the target line format](#the-target-line-by-type) for exactly how this field works. | | 5 | `Item: Coins, 50 \| Skill_EXP: Bows, 20` | Rewards: 50 Coins and 20 Bow skill experience. | | 6 | `0` | Cooldown in seconds — `0` means the quest is repeatable immediately after completion. | | 7 (not shown above, optional) | unlock requirements | Left empty here — no requirements, so this quest is available right away. See [Conditions](../concepts/conditions.md). | If you leave off the requirements line entirely, that is fine — it defaults to "no requirements." ## Quest types There are 10 quest types. Pick the one that matches the action you want the player to perform: | Type | What the player does | Notes | |---|---|---| | `Kill` | Kill a creature | Most common type — pairs well with `Harvest` for varied daily quests. | | `Collect` | Hand in an item from their inventory | The items are taken away when the quest is turned in — good for "get rid of your surplus" quests, bad for anything rare or hard to get. | | `Harvest` | Gather from a pickable resource (berry bush, ore vein, etc.) | Different from `Collect` — this is about the *action* of harvesting, not just owning the item. | | `Craft` | Craft an item at a specific quality | Good for nudging players toward crafting/upgrading. | | `Talk` | Talk to a specific NPC | Completes automatically as soon as the conversation happens — great for tutorial/intro quests in a chain. | | `Build` | Build a specific structure | Resources used are not refunded if the structure is later destroyed — use sparingly. | | `Move` | Reach a specific location | Good for guiding players to explore somewhere. | | `KillAndCollect` | Kill a creature and also collect a matching drop | A combined objective — see the [example below](#example-killandcollect). | | `Use` | Use a specific item or action | For item-based interactions. | | `Activate` | Interact with a specific object | For activatable world objects. | Most quest types show a marker on their target in the world, and can be toggled off per-player in [Client config](../setup/client-config.md) (`Show Quest Mark`): | `Build` marker | `Harvest`/`Collect` marker | `Talk` marker | |---|---|---| | ![Build quest marker](../images/screenshots/AGJ4bGI.png) | ![Harvest and Collect quest marker](../images/screenshots/Rr3SMac.png) | ![Talk quest marker](../images/screenshots/Ejrhf5u.png) | ### The target line, by type The target line's format depends on the quest type above it. General shape is `item/creature, amount, [level]`, and you can list several targets on one line separated by `|`: ```cfg Wolf, 5, 1 | Boar, 3, 1 ``` (kill 5 wolves and 3 boars, each at least 1-star, all counting toward the same quest) - **`Kill`**: `creature, amount, level` — level is the minimum star rating the creature must have, exactly as written with no hidden offset, `0` (or omit it) for no requirement at all. - **`Collect`** / **`Craft`**: `item, amount, level` — level is item quality. - **`Harvest`** / **`Build`**: `object, amount` — no level field. - **`Talk`**: the full NPC name, in quotes if it has a space — e.g. `"Village Elder"`. - **`Move`**: `X, Z, radius, "Location Name", showOnMap` — `showOnMap` is `true`/`false`. - **`Use`**: `item, amount, extra info` — the third field's exact meaning depends on what you are hooking it up to. - **`Activate`**: `object, extra info, extra info, ...` — any fields after the first are passed along as-is. #### Example: `KillAndCollect` This type needs more detail per target — creature, kill count, level, then a label for the item you want collected, then any extra fields: ```cfg GoblinRaider, 5, 2, ear, none, none, none, none, none ``` Kill 5 at-least-2-star Goblin Raiders and collect 5 "ear" trophies (a quest-only item created just for this quest, not a real item you can get any other way). The level field here works exactly like plain `Kill`'s, above — as of mod version 9.8.9; before that the two disagreed, see [Migrations](../reference/migrations.md). ## Reward types You can combine several reward types on one line with `|`: ```cfg Item: Coins, 200 | Item: Ruby, 1 | Skill_EXP: Swords, 100 ``` | Reward type | Format | Notes | |---|---|---| | `Item` | `item, amount, [level]` | A normal item reward. | | `RandomItem` | `pool name` | Picks from a random-item pool you have set up elsewhere. | | `Skill` / `Skill_EXP` | `skill, amount` | Skill points / raw experience. | | `Pet` | `creature, amount, level` | Gives a tamed pet. | | `EpicMMO_EXP` / `Cozyheim_EXP` / `Battlepass_EXP` / `RustyClasses_EXP` | `amount` | Experience for the matching integration, if that mod is installed. | | `GuildAddLevel` | `amount` | Adds levels to the player's guild. | | `SetCustomValue` / `AddCustomValue` | `key, amount` | Sets/adds to a [custom value](../concepts/prefabs-and-assets.md#custom-values) — good for reputation-style systems. | ## Cooldown and time limit ```cfg 3600, 600 ``` First number is the cooldown in seconds before the quest can be taken again after completion (`0` = always available). Second, optional number is a time limit — how long the player has after accepting before it auto-fails (`0` or omitted = no time limit). ## Unlock requirements The last line uses the [condition language](../concepts/conditions.md) — this is how you build quest chains, level gates, or item-cost quests: ```cfg QuestFinished, meet_the_elder | SkillMore, Swords, 5 ``` Only available once the player has finished `meet_the_elder` **and** has at least skill level 5 in Swords. ## Special quest tags Add one of these to the header, after `=`, for special behavior: ```cfg [final_boss = Autocomplete] ``` | Tag | Effect | |---|---| | `Autocomplete` | Completes automatically the moment the objective is met — no need to talk to an NPC to turn it in. Common for a chain's final boss fight. | | `HiddenAnyCondition` | Stays hidden from the quest list unless at least one requirement currently passes. | | `HiddenOtherQuestCondition` | Stays fully hidden until its chain prerequisite is met — good for not spoiling upcoming quests before they unlock. | Without either tag, a quest whose requirements are not yet met still shows up in the NPC's list — the player just cannot take it yet. Use one of the two tags above only when you specifically want to keep a quest a surprise. ## Cooldown and quest-list visibility A quest that is on cooldown still shows in the NPC's list (with a countdown) as long as the remaining cooldown is under 5000 in-game days. Past that, it disappears from the list entirely once completed — this is the trick behind "one-time" quests: set the cooldown to something like `10000` and the quest vanishes for that player for good after their first completion, instead of reappearing once the cooldown would normally expire. ## A full worked example `Configs/Quests/chain.cfg`: ```cfg [wolf_pelts] Kill Wolf Culling The village needs wolf pelts. Bring me 5. Wolf, 5, 1 Item: Coins, 50 | Skill_EXP: Bows, 20 0 [timber_run = HiddenOtherQuestCondition] Collect Timber Run Bring me wood and craft me a good axe. Wood, 20 | AxeFlint, 1, 2 Item: Coins, 100 | Skill_EXP: WoodCutting, 50 3600, 600 QuestFinished, wolf_pelts ``` Here, `timber_run` stays hidden until `wolf_pelts` is completed, and once accepted the player has 10 minutes (600 seconds) to finish it before it auto-fails; it can then be repeated once per hour (3600 seconds). ## Related - [Quest Profiles](quest-profiles.md) — assigning quests to an NPC. - [Quest Events](quest-events.md) — scripted reactions on accept/complete/cancel/timeout/death. - [Conditions](../concepts/conditions.md). - [First quest guide](../guides/first-quest.md), [Quest chain guide](../guides/quest-chain.md). --- # Random NPC Speech **File:** `Configs/RandomNpcSpeech.yml` (a single file, created automatically on first server start) Defines sets of idle barks an NPC cycles through while a player is nearby — ambient flavor text, separate from its actual dialogue tree. ## Example `Configs/RandomNpcSpeech.yml`: ```yaml guard_idle: RandomTexts: bark1: Text: "Keep your weapons sheathed here." bark2: Text: "Move along, traveler." OnlyIfLookingAtPlayer: true Interval: 25 InvervalRandomOffset: 8 ``` An NPC assigned the `guard_idle` speech set will periodically say one of the two lines above, roughly every 25 seconds (randomly varied by up to 8 seconds either way so multiple NPCs do not all speak in unison). ## Fields | Field | Meaning | |---|---| | `RandomTexts` | A list of lines — each entry needs `Text`, and can optionally include `Animation` (plays an animation with the line) and `OnlyIfLookingAtPlayer` (only says this line if the NPC is facing the player). | | `Interval` | Seconds between barks (default `18`). | | `InvervalRandomOffset` | Random variation applied to the interval, plus or minus (default `4`). | An NPC is assigned a speech set by name through its own settings — see [NPC system](../npc/npc-system.md). ## Related - [NPC system](../npc/npc-system.md) — assigning a speech set to an NPC. --- # Saved NPCs (Hammer templates) **Folder:** `Marketplace_SavedNPCs/` (`.yml` files — a folder next to `Marketplace/`, on the player's own computer) Reusable NPC "stamps" — you build and configure an NPC once, save it, and can then place identical copies anywhere, or share the file with other admins. These files are created by [Marketplace Hammer](../npc/marketplace-hammer.md)'s own save feature; you normally do not hand-write them. Not to be confused with [Spawned NPCs](spawned-npcs.md) — those are player-summoned and temporary, not admin-placed. ## Workflow 1. Build and configure an NPC in-game using [Marketplace Hammer](../npc/marketplace-hammer.md). 2. Save it — this writes a file into this folder and captures a preview picture automatically. 3. Run the `mreloadnpcs` command (see [Console commands](../setup/console-commands.md)) to make the saved template available to place again. 4. Place as many copies as you like, anywhere — including on a different server, if you share the file. ## A useful trick: randomized variety Any appearance field in a saved template — model, item, color, animation — can hold a **space-separated list** of options instead of one value. Every time you place a copy of the template, one option is picked at random, so one saved NPC can produce visually varied instances instead of identical clones. ## Related - [Marketplace Hammer](../npc/marketplace-hammer.md) — the tool that creates and uses these files. - [NPC system](../npc/npc-system.md) — full list of what an NPC's appearance and identity fields do. --- # Server Info **Folder:** `Configs/ServerInfos/` (any file name, `.cfg`) Free-text info/rules/announcement pages shown by an Info NPC. Unlike most other config formats, this one is plain prose — write whatever text you want, and it displays as written (rich text formatting works too). Once you have written a profile here, put its name in an `Info`-type NPC's **Profile** field to make it live — see [Core identity settings](../npc/npc-system.md#core-identity-settings). It can also be reached remotely, without a nearby NPC, by listing it under `InfoProfiles` in [Distanced UI](distanced-ui.md). ![Server Info page in-game](../images/screenshots/cwOiOsO.png) ## Example `Configs/ServerInfos/rules.cfg`: ```cfg [default] Welcome to the server! Please read the rules below. [rules] 1. No griefing. 2. PvP only in designated zones. Thanks for reading! ``` An Info NPC set to profile `rules` shows the two numbered lines, then the banner image, then the closing line. ## Format Just write text under a `[ProfileName]` header — multiple lines stay together as one page. Add a picture anywhere with `` (see [Prefabs and text markup](../concepts/prefabs-and-assets.md#inline-image)) — everything before and after the image becomes its own text block around it. Text written before any `[Section]` header goes to the `default` profile automatically — this is what a fresh Info NPC shows before you assign it a specific profile. ## Related - [Profiles](../concepts/profiles.md) — how an info profile name groups entries across files. - [Prefabs and text markup](../concepts/prefabs-and-assets.md) — the `` tag. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. --- # Spawned NPCs **Folder:** `Configs/SpawnedNPCs/` (`.yml`/`.yaml` files, one profile per file — the filename becomes the profile's ID) Lets a player summon a temporary NPC for themselves, through [Distanced UI](distanced-ui.md) — no admin placement involved. Unlike every other NPC on this site, a Spawned NPC isn't placed with [Marketplace Hammer](../npc/marketplace-hammer.md) and isn't shared world state: each player who spawns one gets their own, client-side, and spawning another replaces it. Think a temporary companion or a "preview" NPC, not a persistent fixture. ## Example `Configs/SpawnedNPCs/village_guide.yml`: ```yaml Name: Wandering Guide Type: None Dialogue: village_guide_greeting SpawnNearPlayer: false Condition: QuestFinished, intro_quest MoveSpeed: 1.5 VisibleToEveryone: false Fashion: RightItem: Torch GreetText: Lost? I can point you toward the village. ``` Any player who has finished `intro_quest` can spawn this from their Distanced UI's Spawned NPCs tab. It walks in from a short distance away, carrying a torch, and only its summoner can see it. ## Fields | Field | Meaning | |---|---| | `Name` | Display name. | | `Type` | One of the [NPC types](../npc/npc-system.md#npc-types) — `Trader`, `Quests`, etc. — if you want this spawned NPC to actually run a shop/quest/etc. `None` for a dialogue-only or purely decorative one. | | `Profile` | The profile this NPC uses from its Type's own folder, same as any other NPC — omit for `Type: None`. | | `Prefab` | Model/creature override, same as [Core identity settings](../npc/npc-system.md#core-identity-settings). | | `Dialogue` | A dialogue ID from [Dialogues](dialogues.md). | | `SpawnNearPlayer` | `true`: appears right next to the player, facing them, and stays put. `false` (default): appears 15-20m away and walks in toward the player once. | | `Condition` | A [condition](../concepts/conditions.md) — only players who currently pass it see this profile listed as spawnable at all. To make it available to everyone, set it to an empty string (`Condition: ""`) — safer than leaving the key out of the file entirely, since every other field here tolerates being missing but this one isn't given a fallback in the source if it's absent. | | `Fashion` | Optional appearance block, same fields as [Appearance settings](../npc/npc-system.md#appearance-settings) (`RightItem`, `GreetText`, and the rest) — everything defaults to none/blank if you skip it. | | `MoveSpeed` | Walk speed for the walk-in approach when `SpawnNearPlayer` is `false`. `0` (default) uses the normal speed. | | `VisibleToEveryone` | `false` (default): only the player who spawned it can see it. `true`: every nearby player sees it. | ## Related - [Distanced UI](distanced-ui.md) — where a player actually triggers a spawn. - [NPC system](../npc/npc-system.md) — the full field reference this format reuses (type, appearance, dialogue). - [Conditions](../concepts/conditions.md) — gating which players can spawn a given profile. - [Hot reload](../setup/hot-reload.md) — editing a file here updates it live. --- # Synced Localizer **Folder:** `Configs/SyncedLocalizer/` (`.yml` files) Lets you override or add translation text server-wide, sent to every connected player, without editing any file on the player's own computer. ## Example `Configs/SyncedLocalizer/English.yml`: ```yaml mpasn_Banker: Vault Keeper marketplace_cannotleaveguild: You cannot abandon your clan right now. ``` Players whose game language is English now see "Vault Keeper" wherever the game would normally show "Banker", and a custom message wherever `marketplace_cannotleaveguild` is used. ## Format **The file name is the language it applies to** — name it to match the language exactly, the same way Valheim itself names its languages (`English.yml`, `Russian.yml`, etc.). Inside, just list `key: replacement text` pairs. Any text key can be overridden this way, including this mod's own labels (see [Localization keys](../reference/localization-keys.md)) and any custom key you reference from your own quests or dialogues. ## Related - [Localization keys](../reference/localization-keys.md) — the mod's built-in labels you can override. --- # Teleporters **Folder:** `Configs/Teleporters/` (any file name, `.cfg`) Lists fast-travel destinations for a Teleporter NPC. Once you have written a profile here, put its name in a `Teleporter`-type NPC's **Profile** field to make it live — see [Core identity settings](../npc/npc-system.md#core-identity-settings). It can also be reached remotely, without a nearby NPC, by listing it under `TeleporterProfiles` in [Distanced UI](distanced-ui.md). ![Teleporter destination pins on the map](../images/screenshots/Hoy6Gg1.png) ## Example `Configs/Teleporters/hub_main.cfg`: ```cfg [hub_main] "Trading Post", 100, 30, 200 "Mountain Outpost", 800, 150, -400, mountain_icon ``` Format: `"Destination Name", x, y, z, [icon]`. The name must be in quotes if it contains a space. The first destination teleports instantly; the second travels at a set speed instead of instantly — see [``](../concepts/prefabs-and-assets.md#teleporter-travel-speed). ## Sharing destinations between profiles Instead of repeating a full list, one profile can simply reuse another's: `Configs/Teleporters/hub_satellite.cfg`: ```cfg [hub_satellite] @from: hub_main ``` Any NPC using `hub_satellite` now offers the exact same destinations as `hub_main`. ## Related - [Profiles](../concepts/profiles.md) — how a teleporter profile name groups destinations across files. - [Prefabs and text markup](../concepts/prefabs-and-assets.md#teleporter-travel-speed) — the `` tag. - [Server config](../setup/server-config.md) — the `CanTeleportWithOre` toggle. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. --- # Territories **Folder:** `Configs/Territories/` (any file name, `.cfg`) Territories are named zones you draw on the map with rules attached — PvP-free areas, no-build zones, healing auras, biome overrides, guild-only land, and more. A zone can be a circle, a square, or a rectangle, and zones can overlap and stack. ## A complete example, explained `Configs/Territories/market_square.cfg`: ```cfg [market_square@2] Circle 0, 0, 50 90, 160, 90, exp: 1.0 NoAttack, PeriodicHeal = 1, NoMonsters None ``` | Line | Content | Meaning | |---|---|---| | header | `[market_square@2]` | Zone name, and a priority of `2` — higher-priority zones win where zones overlap. Leave off `@N` for the default priority of `1`. **Never put a space before the `@`** — unlike everywhere else in these config files, it is not stripped, and ends up baked into the zone's actual name (`market_square ` instead of `market_square`). | | 1 | `Circle` | Shape — `Circle`, `Square`, or `Rectangle`. | | 2 | `0, 0, 50` | Coordinates — for Circle/Square this is `x, y, radius`; for Rectangle it is `x1, y1, x2, y2` (opposite corners). | | 3 | `90, 160, 90, exp: 1.0` | Appearance — a green tint here, with a falloff curve. See [Appearance](#appearance). | | 4 | `NoAttack, PeriodicHeal = 1, NoMonsters` | Behavior flags — no combat, slow healing, no monster spawns. See [Flags](#flags). | | 5 | `None` | Who is allowed in — `None` means no restriction (open to everyone). | Unlike every other `[Section]` header in this mod, a zone name is **case-sensitive and keeps internal spaces exactly as written** — `[Market Square]`, `[market square]`, and `[MarketSquare]` are three different zones, not the same one written three ways. Pick one spelling and stay consistent, since nothing will warn you about a mismatch. ## Appearance The appearance line is a mix of a color and a few optional extras — order does not matter, write whichever pieces you need: ```cfg 255, 0, 0, 0, 255, 0, true, FromCenter, exp: 1.5, heightbounds: 10-40 ``` This is a red-to-green gradient (two color triplets), fading from the zone's center outward, with visible water, an exponential falloff curve, and the zone's effect limited to world heights 10 through 40. | Piece | Meaning | |---|---| | `r, g, b` (one or more triplets) | The zone's color. Two or more triplets create a gradient between them. | | `true` / `false` | Whether water outside the zone edge stays visible. | | A gradient direction name | `FromCenter`, `ToCenter`, `LeftRight`, `RightLeft`, `TopBottom`, `BottomTop`, or one of the four diagonal combinations (`TopLeftBottomRight`, etc.). | | `exp: number` | How sharply the gradient falls off. | | `heightbounds: min-max` | Limits the zone's effect to a height range. | A minimal appearance line is just a color: `100, 200, 100`. ## Flags Flags control what actually happens inside the zone. List them comma-separated; some need a value after `=`: ```cfg NoAttack, PeriodicHeal = 2, ForceBiome = 2, MonstersAddStars = 1 ``` ### Combat and building | Flag | Value? | Effect | |---|---|---| | `PvpOnly` | — | Only PvP damage is allowed. | | `PveOnly` | — | Only PvE damage is allowed. | | `NoAttack` | — | No combat at all. | | `NoMonsters` | — | Monsters will not spawn. | | `MonstersAddStars` | number | Monsters spawn with extra star levels. | | `NoBuild` | — | Building is disabled. | | `NoBuildDamage` | — | Buildings inside cannot take damage. | | `NoStructureSupport` | — | Structural support requirements are ignored. | | `NoPickaxe` | — | Pickaxes cannot be used. | | `PushAway` | — | Pushes players who try to enter out again. | ### Interaction restrictions | Flag | Effect | |---|---| | `NoInteract` | Blocks all interaction. | | `NoInteractItems` | Blocks interacting with dropped items. | | `NoInteractCraftingStation` | Blocks crafting stations. | | `NoInteractItemStands` | Blocks item stands. | | `NoInteractChests` | Blocks chests. | | `NoInteractDoors` | Blocks doors. | | `NoInteractPortals` | Blocks portals. | | `NoPortals` | Portals do not function at all inside the zone. | ### Player and environment effects | Flag | Value? | Effect | |---|---|---| | `PeriodicHeal` | number | Heals players over time. | | `PeriodicHealALL` | number | Same, but heals even at full health (useful with regen-boosting mods). | | `PeriodicDamage` | number | Damages players over time. | | `IncreasedPlayerDamage` | number | Multiplies damage players deal. | | `IncreasedMonsterDamage` | number | Multiplies damage monsters deal. | | `MoveSpeedMultiplier` | number | Changes movement speed. | | `NoDeathPenalty` | — | No skill/item loss on death. | | `InfiniteFuel` | — | Fires/torches never run out of fuel. | | `CustomEnvironment` | weather name(s) | Forces specific weather. | | `ForceBiome` | biome number | Makes the zone act like a different biome. | | `ForceGroundHeight` / `AddGroundHeight` / `LimitZoneHeight` | number | Adjusts terrain height within the zone (only one of these three takes effect if more than one is present). | | `CustomPaint` | `0`-`3` | Paints the ground: `0` = Paved, `1` = Grass, `2` = Cultivated, `3` = Dirt. | ### Extra flags (a second set, same syntax) | Flag | Value? | Effect | |---|---|---| | `NoItemLoss` | — | No item loss on death. | | `SnowMask` | — | Removes snow buildup visuals. | | `NoMist` | — | Removes fog/mist. | | `InfiniteEitr` | — | Eitr never depletes. | | `InfiniteStamina` | — | Stamina never depletes. | | `DropMultiplier` | number | Multiplies loot drops. | | `ForceWind` | number | Sets a fixed wind strength. | | `GodMode` | — | Players are invincible. | | `OnlyForGuild` | guild name | Only members of that guild may enter. | | `OnlyForFaction` | faction key | Only members of that faction may enter. | | `JoinOtherServer` | connection info | Sends players who enter to a different server. | | `RevealOnMap` | — | Reveals this area on the map automatically. | | `CustomJereSpawner` | spawner name | Attaches a named custom spawner (repeat the flag to add more than one). | ## Who is allowed in The last line — a comma list of allowed players or roles, or `None` for open access. ## Scheduling a zone to specific hours Territories can be limited to a real-clock time window using a folder naming trick — see [Scheduling a config to a time window](../concepts/time-windows.md). ## A second, overlapping example `Configs/Territories/market_vip_lounge.cfg`: ```cfg [market_vip_lounge@5] Square 20, 20, 15 255, 215, 0 PeriodicHealALL = 3, MonstersAddStars = 0 OnlyForGuild = MarketGuild ``` Priority `5` beats the `market_square` example above wherever they overlap — inside this smaller square, only `MarketGuild` members may enter, and healing is stronger. ## Related - [Scheduling a config to a time window](../concepts/time-windows.md). - [Territory setup guide](../guides/territory-setup.md) — a full worked example combining several zones. --- # Traders **Folder:** `Configs/Traders/` (any file name, `.cfg`) Fixed-price shop listings for a Trader NPC — spend a set item to get a set item back, no randomness involved. Once you have written a profile here, put its name in a `Trader`-type NPC's **Profile** field to make it live — see [Core identity settings](../npc/npc-system.md#core-identity-settings). It can also be reached remotely, without a nearby NPC, by listing it under `TraderProfiles` in [Distanced UI](distanced-ui.md). ![Trader UI in-game](../images/screenshots/WMFaYl4.png) The `x1` / `x5` / `x10` / `x100` buttons in the top right of the trade window scale a trade's quantities on both sides at once for faster bulk trading — `Coins, 5, Wood, 1` at `x100` becomes 500 Coins for 100 Wood, not a different trade. ## Example `Configs/Traders/general_store.cfg`: ```cfg [general_store] Wood, 10, Coins, 5 Coins, 50, SwordIron, 1, 2 ``` Each line is one trade offer. Format: `cost item, cost amount, result item, result amount, [result level]`. The second line sells a level-2 Iron Sword for 50 Coins. Assigning the profile to an NPC's **Profile** field: ![Assigning a Trader profile to an NPC](../images/screenshots/BjPrHIS.png) ## Trading more than one item per side Wrap both sides with `=` to trade bundles of items instead of one-to-one — up to 5 items per side, and any item on either side can carry its own `, level` field: ```cfg Coins, 100, Ruby, 1 = SwordSilver, 1, 3 ``` Spend 100 Coins **and** 1 Ruby to receive a level-3 Silver Sword. ```cfg GreydwarfEye, 10, Wood, 20 = BowFineWood, 1, 2 ``` ```cfg BlackMetal, 1, AxeBlackMetal, 1, 9, Coins, 25 = AxeBlackMetal, 1, 10, Wood, 123 ``` Spend 1 BlackMetal, a level-9 Iron Axe, and 25 Coins, to receive a level-10 Iron Axe and 123 Wood: ![A multi-item trade with quality on both sides](../images/screenshots/tkb8MM5.png) You can mix plain 4/5-field lines and `=`-bundled lines freely within the same profile: `Configs/Traders/mixed_formats.cfg`: ```cfg [mixed_formats] SwordIron, 1, 9, Ruby, 666 = SwordIron, 1, 10 BlackMetal, 1, AxeBlackMetal, 1, 9, Coins, 25 = AxeBlackMetal, 1, 10, Wood, 123 Coins, 0 = AxeBlackMetal, 1, 9 Coins, 0, BlackMetal, 5 ``` ![Several trade formats offered by the same profile](../images/screenshots/eTT5SbT.png) ## Pets as trade results A creature name on the result side gives a tamed pet instead of an item — spawned already-tamed in front of the player, the same way a quest [Pet reward](quests.md#reward-types) works. The level field becomes the pet's level, shown one star lower on the confirmation screen (a level `5` Wolf displays as 4 stars, since Valheim counts stars from 0 while this field counts from 1): `Configs/Traders/pets_trader.cfg`: ```cfg [pets_trader] Stone, 100, Wolf, 1, 5 Ruby, 25, Boar, 10, 2 ``` ![A pets-only trader profile](../images/screenshots/10OELul.png) Trading Stone for a tamed Wolf, or Ruby for a tamed Boar: ![Trading for a tamed pet in-game](../images/screenshots/W4YHMKr.png) A creature is only recognized on the **result** side — the cost side always expects a plain item. ## Locking trades behind item discovery Add `= true` to a profile header to only show trades for items the player has already discovered/picked up in the world: `Configs/Traders/rare_goods.cfg`: ```cfg [rare_goods = true] Coins, 200, Ruby, 1 = SwordSilver, 1, 3 ``` Leave the header plain (`[profile]`) for trades that are always visible, regardless of what the player has found. ## Scheduling a trader to specific hours Traders can be limited to a real-clock time window using a folder naming trick — see [Scheduling a config to a time window](../concepts/time-windows.md). ``` Configs/Traders/18-00_23-00/evening_specials.cfg ``` ## Related - [Profiles](../concepts/profiles.md) — how a trader profile name groups trades across files. - [Scheduling a config to a time window](../concepts/time-windows.md). - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. - [Shop and economy guide](../guides/shop-and-economy.md). --- # Transmogrification **Folder:** `Configs/Transmogrifications/` (any file name, `.cfg`) Transmogrification lets players change how an item **looks** — including its color — without changing its stats. As admin, you decide which skins a given NPC offers, and what they cost; the rest (picking an item, previewing, applying, removing) happens entirely in a player-facing UI you do not need to configure. Once you have written a profile here, put its name in a `Transmog`-type NPC's **Profile** field to make it live — see [Core identity settings](../npc/npc-system.md#core-identity-settings). It can also be reached remotely, without a nearby NPC, by listing it under `TransmogrificationProfiles` in [Distanced UI](distanced-ui.md). ![Assigning a Transmog profile to an NPC](../images/screenshots/JwHAUpQ.png) ## A complete example, explained `Configs/Transmogrifications/cosmetic_shop.cfg`: ```cfg [cosmetic_shop] SwordCheat, Coins, 100, false CapeLinen, Coins, 50, true ``` | Field | Meaning | |---|---| | item | The item whose **appearance** gets applied to whatever the player is reskinning. | | cost item | Currency item required. | | cost amount | How much of it. | | ignore category | `true`/`false` — see [Categories and "ignore category"](#categories-and-ignore-category) below. | ## What the player sees ![Transmog UI in-game](../images/screenshots/Fq4kjch.png) 1. On the left, the player picks an item from their own inventory to reskin. Only actual equipment shows up here — weapons, shields, armor, capes, tools, utility items — not consumables or materials. 2. On the right, the skins available for that item show up, grouped into the matching category plus any `ignore category` skins (see below). Skins the player cannot currently afford are dimmed. 3. Each skin has an optional **hex color** field — the player can type a color code to recolor the skin before applying it, entirely separate from what you configured. 4. A **preview** button shows the result on the player's own character before committing, so nothing is spent by mistake. ![Picking an item and previewing a skin with a custom color](../images/screenshots/RZoeGwD.png) Clicking the skin's add button spends the cost item and applies the transmog immediately: ![Transmog applied, with a recolor](../images/screenshots/uE9erX1.png) Already-transmogged items are highlighted in the player's inventory list so they can tell at a glance which of their gear has been reskinned. ## Categories and "ignore category" Skins are sorted into categories that mirror the game's own equipment slots: One-Handed Weapon, Two-Handed Weapon, Two-Handed Weapon (Left Hand), Bow, Tool, Shield, Chest, Helmet, Legs, Cape, Utility. By default, a skin only shows up under the category matching its own item type — a skin made from a sword only offers itself to players reskinning a one-handed weapon. Setting **ignore category** to `true` changes two things at once: - The skin appears in a separate **Any** bucket, shown to the player no matter what item type they are reskinning — this is how you let a skin cross categories, like applying a two-handed axe's look onto a one-handed sword. - The normal type check is skipped entirely, which also means the skin prefab itself no longer has to be equipment at all. This is how you can use something like a trophy as a "skin" for a weapon: ![Using a non-equipment item as a skin, with ignore category on](../images/screenshots/T8QmpJm.png) ![The result — the weapon now looks like the trophy](../images/screenshots/Sd4Xsdo.png) Because the type check is off, mismatched combinations (a two-handed skin on a one-handed item, a non-equipment prefab as a skin) are visually possible but not guaranteed to look or animate correctly. Use `ignore category` deliberately, and test unusual combinations before offering them on a live server. ## A worked example with several tiers `Configs/Transmogrifications/testprofile.cfg`: ```cfg [testprofile] SwordIron, Coins, 10, false SwordIronFire, Ruby, 10, false ``` This profile offers two skins to whoever is reskinning a one-handed weapon: a plain Iron Sword look for 10 Coins, or a Fire Sword look for 10 Ruby. Applying a skin, step by step: | Choose the item to reskin | Choose the skin | |---|---| | ![Choosing an item](../images/screenshots/SDJsDOh.png) | ![Choosing a skin](../images/screenshots/DSkdimb.png) | | Confirmed | Result on the item | |---|---| | ![Applied](../images/screenshots/STsZbGs.png) | ![New appearance](../images/screenshots/T4Ss9IB.png) | The item's stats, attack animations, and everything else about it are unchanged — only its model and color are affected. Equipping it shows the new look immediately: ![Equipped with the new appearance](../images/screenshots/apOXM30.png) ## Removing a transmog Players can revert an item to its original appearance at any time from the same UI, at no cost — select the transmogrified item and use the clear/revert option. This removes both the applied skin and any custom color. ## Related - [Profiles](../concepts/profiles.md) — how a transmogrification profile name groups skins across files. - [Server config](../setup/server-config.md) — `EnableTransmogLog`, to log transmog actions to the server log. - [Distanced UI](distanced-ui.md) — remote access without a nearby NPC. - [Migrations](../reference/migrations.md) — an older visual-effects field that used to exist on this page's config format was removed in version 9.0.8. --- # Guide: dialogue patterns A handful of small, self-contained patterns for things that come up once you are past a first tree — proximity triggers, handing off to an NPC's normal menu, weighted rewards, a password gate, and quoting console commands. Format reference: [Dialogues](../configs/dialogues.md). If you have not built a tree yet, start with [A branching dialogue tree](dialogue-tree.md). ## Reacting to proximity without a visible reply `@inrange` and `@outrange` fire once each, without ever showing as a clickable option — useful for ambience that should happen automatically as a player approaches or leaves. See [Silent triggers](../configs/dialogues.md#silent-triggers-no-visible-reply) for the full prefix list. `Configs/Dialogues/guard_dialogue.cfg`: ```cfg [guard_dialogue] Halt! State your business. @inrange | Command: PlaySound, guard_alert, 0.5 @outrange | Command: PlaySound, guard_relax Text: Just passing through | Transition: guard_bye ``` ## Handing off to an NPC's normal menu Setting a Dialogue on an NPC makes clicking it always open the dialogue instead of its normal Type-based menu (Trader, Banker, and so on) — see [Dialogues](../configs/dialogues.md). A common way around this: give the NPC a Dialogue purely so `@interaction` can redirect straight into its real menu with `OpenUI`, keeping that menu reachable: `Configs/Dialogues/shopkeeper_redirect.cfg`: ```cfg [shopkeeper_redirect] @interaction | Command: OpenUI, Trader, shopkeeper_stock ``` ## Chaining commands before a risky line `@interaction` can chain more than one command before anything else happens — for example dealing damage before opening a cursed dialogue, so a player who dies from the hit never sees the text at all: `Configs/Dialogues/cursed_tome.cfg`: ```cfg [cursed_tome] @interaction | Command: Damage, 5 | Command: OpenUI, Dialogue, cursed_tome_text ``` ## Independent rolls vs a single random pick Each `RandomCommand` on a reply rolls its own independent chance — this line can give the player none, some, or all three rewards, not exactly one of them: `Configs/Dialogues/mystery_chest.cfg`: ```cfg [mystery_chest] You found a strange chest. Open it? Text: Open it | RandomCommand: 40, GiveItem, Coins, 10 | RandomCommand: 15, GiveItem, Ruby, 1 | RandomCommand: 5, GiveItem, TrophyWolf, 1 ``` If you want exactly one of several outcomes instead — never more, never fewer — send the player to a different node per outcome with `RandomTransition`: ```cfg Text: Open it | RandomTransition: chest_coins, chest_ruby, chest_nothing, chest_nothing, chest_nothing ``` Listing a node more than once (`chest_nothing` three times here) is how you weight a `RandomTransition` — it becomes more likely to be the one picked, since every entry has an equal chance. See [Reply line fields](../configs/dialogues.md#reply-line-fields). ## A password-gated door `EnterPassword` opens a text-entry popup and transitions to one of two nodes depending on whether the player typed the right word. Anything that should happen on success or failure — granting a key, teleporting, showing more text — goes on a reply *inside* the target node, not inside `EnterPassword` itself: `Configs/Dialogues/vault_door.cfg`: ```cfg [vault_door] A locked door blocks your path. Text: Enter code | Command: EnterPassword, "Vault Access", 1234, vault_open, vault_denied [vault_open] The door swings open. Text: Step through | Command: AddPlayerKey, vault_opened | Command: Teleport, 150, 32, 200 [vault_denied] Incorrect code. ``` ## Quoting console commands with spaces `ConsoleCommand` runs anything you could type into the admin console yourself, with `{playername}` substituted for the local player's name. Since most console commands contain spaces, wrap the whole thing in quotes — see [Keeping literal spaces](../configs/dialogues.md#keeping-literal-spaces): `Configs/Dialogues/admin_tools.cfg`: ```cfg [admin_tools] What would you like me to do? Text: Spawn a troll near me | Transition: admin_tools | Command: ConsoleCommand, "spawn Troll 1 2" Text: Announce my arrival | Transition: admin_tools | Command: ConsoleCommand, "say {playername} has arrived!" ``` See the [caution on `ConsoleCommand`](../concepts/commands.md#a-caution-on-consolecommand) before using this in content you did not write yourself. ## Related - [Dialogues](../configs/dialogues.md) — the full field and syntax reference these patterns build on. - [Dialogue tree guide](dialogue-tree.md) — start here if you have not built a branching tree yet. - [Conditions](../concepts/conditions.md), [Commands](../concepts/commands.md). --- # Guide: a branching dialogue tree A worked example of a small conversation with a gated reply, a silent trigger, and a random outcome. Full field reference: [Dialogues](../configs/dialogues.md). ## What we are building ``` greet ──"Ask about the ritual"──▶ ritual_info │ └─"I'm ready" (needs 3 Ritual Candles) ──▶ ritual_start ──▶ ritual_success │ └─(fails)──▶ ritual_denied ``` ## The dialogue file `Configs/Dialogues/greet.cfg`: ```cfg [greet] The old priestess looks up as you approach. Text: Ask about the ritual | Transition: ritual_info Text: I'm ready | Condition: HasItem, RitualCandle, 3 | OverrideError: You need 3 Ritual Candles first. | Transition: ritual_start Text: Never mind | Transition: greet_bye [ritual_info] The ritual requires three Ritual Candles, gathered from the old shrine. Text: Back | Transition: greet [ritual_start] You light the candles. The air grows still. Command: RemoveItem, RitualCandle, 3 | Command: PlaySound, ritual_chant, 0.8 | Command: GiveBuff, ritual_blessing | Transition: ritual_success [ritual_success] The blessing settles over you. [greet_bye] Safe travels. ``` Worth noting: - The `Condition:` on "I'm ready" does not hide that reply — by default it still shows, greyed out, with the `OverrideError` text appended, until the player has 3 Ritual Candles. Add `AlwaysVisible: false` to the same reply if you would rather it disappear entirely instead. See [Dialogues](../configs/dialogues.md#when-a-condition-fails). - `ritual_start`'s line has commands and a transition but no `Text:` — it runs its commands and moves on right away, without ever showing as a clickable reply. Any reply line with actions but no visible text behaves this way. ## Running something silently on approach To play a sound, or run any command, the moment a player opens the conversation or walks into range — without it appearing as a clickable option — prefix the line with `@interaction`, `@inrange`, or `@outrange`: `Configs/Dialogues/greet.cfg`: ```cfg [greet] The old priestess looks up as you approach. @inrange | Command: PlaySound, ambient_chime, 0.3 Text: Ask about the ritual | Transition: ritual_info ``` See [Dialogues](../configs/dialogues.md#silent-triggers-no-visible-reply). ## Random outcomes Use `RandomTransition` to jump to one node picked at random, or `RandomCommand` to give a command its own independent percent chance of firing: ```cfg Text: Search the shrine | RandomCommand: 70, GiveItem, Coins, 5 | RandomCommand: 15, GiveItem, Ruby, 1 ``` This is a 70% chance of Coins and a *separate* 15% chance of a Ruby — the two rolls do not exclude each other, so a lucky player can get both. See [Commands](../concepts/commands.md#random-outcomes) for how to get an exactly-one-of-several outcome instead. ## Adding an extra branch To extend this example with a second path — say, an intimidation option that skips the candle requirement but costs health: ```cfg Text: "Force the ritual" | Command: Damage, 20 | Transition: ritual_start ``` Add this as another reply under `[greet]`, and now players have two ways to reach the same outcome, one safe and slow, one risky and fast. ## Related - [Conditions](../concepts/conditions.md), [Commands](../concepts/commands.md) — the full vocabulary used above. - [Custom Spawn Data](../configs/custom-spawn-data.md) — for attaching extra data to a `GiveItemWithData`/`SpawnWithData` command. - [Dialogue patterns](dialogue-patterns.md) — more small worked examples: proximity triggers, menu handoffs, weighted rewards, password gates. --- # Guide: your first quest A complete, start-to-finish example: writing a quest, assigning it to an NPC, and placing that NPC in the world. This is the fastest way to see the whole system working together. ## Step 1: Write the quest Create a file, for example `Configs/Quests/starter.cfg`: ```cfg [wolf_pelts] Kill Wolf Culling The village needs wolf pelts. Bring me 5. Wolf, 5, 1 Item: Coins, 50 | Skill_EXP: Bows, 20 0 ``` ![Adding the quest to its database file](../images/screenshots/ejk2NIl.png) What this says: - Quest type `Kill`, targeting `Wolf`, 5 of them, requiring at least star level `1` — see [the target line format](../configs/quests.md#the-target-line-by-type) on Quests. - Reward: 50 Coins and 20 Bow skill experience. - Cooldown `0` — the quest can be repeated right away. - No unlock requirement — leaving the last line empty means it is available immediately. Full field-by-field reference: [Quests](../configs/quests.md). ## Step 2: Give it to an NPC Quests are not attached directly to an NPC — you assign them through a profile. Create `Configs/QuestProfiles/starter.cfg`: ```cfg [village_elder] wolf_pelts ``` ![Adding the quest to a profile](../images/screenshots/rhuUwUh.png) Any NPC set to profile `village_elder` will now offer this quest. Full reference: [Quest Profiles](../configs/quest-profiles.md). ## Step 3: Place the NPC With admin access, open the build menu and select the Marketplace Hammer. Place an NPC, then in its settings: - **Type**: `Quests` - **Profile**: `village_elder` - Optionally set a **Name Override**, a **Dialogue**, and appearance settings. ![Assigning the profile to the NPC](../images/screenshots/ba3gJUh.png) Full reference: [NPC system](../npc/npc-system.md), [Marketplace Hammer](../npc/marketplace-hammer.md). ## Step 4: Test it Both files apply automatically within a moment of saving — no restart needed (see [Hot reload](../setup/hot-reload.md)). Talk to the NPC, accept the quest, kill 5 wolves, and turn it in. ### What this looks like in-game Once accepted, the target creature gets a marker so the player can find it: ![Quest target marker on a wolf](../images/screenshots/nVKKAud.png) ![A closer look at the marker](../images/screenshots/GQKiXZG.png) Progress updates automatically as kills come in — the journal tracks how many of the required kills are done so far: ![Kill progress tracked in the quest journal](../images/screenshots/RIOapFp.png) Turning the quest in at the NPC hands out the reward: ![Turning in a completed quest](../images/screenshots/5qZiacv.png) ![Reward received](../images/screenshots/tlMY7jW.png) ### Trying a different level requirement The level field on a `Kill` target is the minimum star rating the creature must have, exactly as written — no hidden offset to account for. Change the target line from `Wolf, 5, 1` to `Wolf, 5, 2`: ![Editing the target line to add a minimum level](../images/screenshots/hgInMiO.png) ...and the in-game requirement changes to match — only 2-star-and-above wolves count now, shown by the marker over qualifying wolves: | Target updated | Marker on a qualifying wolf | |---|---| | ![Quest target changed in-game](../images/screenshots/ZjP5S3z.png) | ![Marker only shows on 2-star-and-above wolves](../images/screenshots/r47i7qA.png) | ### If the quest does not appear - Check the server console for a parsing error — most mistakes are logged there, in red, with the file and line number. - Confirm the quest ID in `QuestProfiles` matches the quest's own `[header]` exactly — spacing and capitalization do not matter, but typos do. - Confirm the NPC's Profile setting matches the `[village_elder]` header exactly. - If you edited an existing file and nothing changed, make sure you saved it and are editing the copy the running server actually uses. ## Related - [Quest chains](quest-chain.md) — link several quests into a story sequence. - [Dialogue trees](dialogue-tree.md) — give the NPC a full branching conversation instead of just a quest list. --- # Guide: quest chains How to link several quests into a story sequence, where each quest only unlocks once the one before it is finished — no special "chain" feature needed, just the ordinary [condition language](../concepts/conditions.md). ## The pattern Each quest after the first requires `QuestFinished` on the quest before it, in its unlock requirements line. The very first quest in the chain is left with no requirements, so it is available immediately. `Configs/Quests/chain.cfg`: ```cfg [chain_1] Talk Meet the Elder Introduce yourself to the village elder. "Village Elder" Item: Coins, 10 0 [chain_2] Kill Prove Yourself Kill 5 wolves to prove your worth. Wolf, 5 Item: Coins, 50 0 QuestFinished, chain_1 [chain_3 = Autocomplete] Kill The Final Test Defeat the pack leader. AlphaWolf, 1, 3 Item: Coins, 200 | Skill_EXP: Swords, 100 0 QuestFinished, chain_2 ``` Here, `chain_2` only unlocks after `chain_1` is turned in, and `chain_3` only after `chain_2`. Any NPC that has all three quests in its profile will show them one at a time, in order, as the player progresses. ## Hiding upcoming links By default, once `chain_1` is available, `chain_2` and `chain_3` show up too — just greyed out with "locked" text, since the player can see what is coming. If you would rather hide a link entirely until it unlocks, tag its header `HiddenOtherQuestCondition`: ```cfg [chain_2 = HiddenOtherQuestCondition] ``` Now `chain_2` will not appear in the quest list at all until `chain_1` is complete. ## Ending a chain with a boss fight Tag the final quest `Autocomplete` (as in `chain_3` above) so it completes the moment its objective is met, without requiring the player to walk back and talk to anyone — good for a chain that ends in defeating a boss where returning to turn in the quest would feel anticlimactic. ## Reacting to each step Use [Quest Events](../configs/quest-events.md) alongside a chain to script what happens at each transition — spawning the next fight's enemy the moment the previous quest completes, rather than waiting for the next one to be accepted: `Configs/QuestEvents/chain_2.cfg`: ```cfg [chain_2] OnCompleteQuest: Spawn, AlphaWolf, 1, 3 ``` ## Keeping chains organized There is no requirement about file order or which file a quest lives in — `QuestFinished` is what actually links them. That said, keeping one chain's quests together in one file, in narrative order, makes them much easier to read and maintain later. ## Related - [Quests](../configs/quests.md), [Conditions](../concepts/conditions.md), [Quest Events](../configs/quest-events.md). - [First quest](first-quest.md) — the basics, if you have not built a quest yet. --- # Guide: shops, currency, and taxes How the economy pieces fit together — currency, marketplace taxes, a fixed-price trader NPC, and banker interest — with a working example of each. ## Choosing currencies `PossibleCurrencies`, in the [server config](../setup/server-config.md), lists every item usable as marketplace currency (just `Coins` by default). Add more to support several currencies side by side: ```ini PossibleCurrencies = Coins, Ruby ``` If you misspell an item name here, it is silently dropped at startup rather than causing an error — double-check the exact item name if a currency you added does not show up. ## Marketplace taxes Also in `MarketPlace.cfg`: ```ini MarketTaxes = 5 ItemMarketLimit = 20 ``` Every player pays a flat 5% tax per sale, and everyone can list up to 20 items at once. There's no per-player tax tier — if you want some players paying less, gate a discount some other way (a [Trader](../configs/traders.md) with cheaper prices behind a [condition](../concepts/conditions.md), for instance), since the mod itself no longer has a concept of a privileged player class. ## A fixed-price NPC shop `Configs/Traders/general_store.cfg` (full format: [Traders](../configs/traders.md)): ```cfg [general_store] Wood, 10, Coins, 5 Coins, 50, SwordIron, 1, 2 Coins, 100, Ruby, 1 = SwordSilver, 1, 3 ``` Two simple 1-for-1 trades, plus a multi-item trade: spend 100 Coins **and** 1 Ruby to get a level-3 Silver Sword. To offer part of the stock only in the evening, put those trades in a scheduled folder instead — see [Scheduling a config to a time window](../concepts/time-windows.md): ``` Configs/Traders/18-00_23-00/evening_specials.cfg ``` ## Banker interest ```ini BankerIncomeTime = 6 BankerIncomeMultiplier = 0.02 BankerInterestItems = Coins, Ruby ``` Every 6 hours, deposited Coins and Ruby earn 2% interest — the same rate for every player. Set `BankerIncomeTime = 0` to switch off interest payouts entirely, without removing your banker NPCs. Which items can be banked at all — separate from which ones earn interest — is set per profile in [Bankers](../configs/bankers.md): `Configs/Bankers/main_bank.cfg`: ```cfg [main_bank] Coins Ruby Amber ``` ## A gamble-your-earnings NPC `Configs/Gamblers/tavern_dice.cfg` (full format: [Gamblers](../configs/gamblers.md)): ```cfg [tavern_dice] Coins, 20, Coins, 10-40, Wood, 20-50, Ruby, 1 ``` Costs 20 Coins per roll; wins a random amount of Coins or Wood, or a Ruby. ## Putting it together A simple economy loop for a server: players earn Coins from quests, sell surplus items to each other on the marketplace (paying tax), deposit savings with a banker for slow interest, and occasionally gamble spare Coins at the tavern dice NPC for a chance at rarer materials like Ruby. Each piece above is independent — turn on only the ones that fit the server you are running. ## Related - [Server config](../setup/server-config.md), [Traders](../configs/traders.md), [Bankers](../configs/bankers.md), [Gamblers](../configs/gamblers.md), [Scheduling a config to a time window](../concepts/time-windows.md). --- # Guide: setting up a territory A worked example: a PvP-free market zone, a guild-only VIP area layered on top of it, and an evening-only bonus zone. ## Step 1: a base zone `Configs/Territories/market.cfg`: ```cfg [market_square@1] Circle 0, 0, 60 90, 160, 90, exp: 1.0 NoAttack, PeriodicHeal = 1, NoMonsters None ``` A 60-radius circle at the world center, tinted green, with no combat, no monster spawns, and slow passive healing. Priority `1` — the baseline layer everything else stacks on top of. ## Step 2: a smaller zone on top `Configs/Territories/market_vip.cfg`: ```cfg [market_vip_lounge@5] Square 20, 20, 15 255, 215, 0 PeriodicHealALL = 3, MonstersAddStars = 0 OnlyForGuild = MarketGuild ``` Priority `5` beats priority `1` — wherever this smaller square overlaps the market zone above, its rules take over instead: stronger healing, and only `MarketGuild` members may enter. See [Territories](../configs/territories.md#flags) for the full flag list. ## Step 3: an evening-only bonus zone Put a time-scheduled zone in a specially-named folder — see [Scheduling a config to a time window](../concepts/time-windows.md): `Configs/Territories/18-00_23-00/happy_hour.cfg`: ```cfg [happy_hour_bonus@3] Circle 0, 0, 60 255, 255, 150 PeriodicHealALL = 5 None ``` This zone only exists between 18:00 and 23:00 server time — before and after, it is as though this file does not exist. Because its priority (`3`) sits between the base zone (`1`) and the VIP lounge (`5`), during those hours it boosts healing everywhere in the base zone except inside the VIP lounge, where the lounge's own rules still win. ## Checking your work in-game Turn on zone outlines with the `zonevisualizer` console command (needs admin access) to see the boundaries you just drew directly in the world — much easier than guessing from coordinates alone. Adjust how visible the outlines are with `zonevisualizeralpha`. See [Console commands](../setup/console-commands.md). ## Related - [Territories](../configs/territories.md) — the full flag reference. - [Scheduling a config to a time window](../concepts/time-windows.md). --- # Guide: tracking player state with Custom Spawn Data `SetPlayerData` and `PlayerHasAllCustomDataKeys` together give you a small, reusable way to remember something about a specific player and check for it anywhere later — a multi-step puzzle, a remembered story choice, anything that needs to persist without a full [Faction](../configs/factions.md) or a whole new [Quest](../configs/quests.md). Format reference: [Custom Spawn Data](../configs/custom-spawn-data.md). ## Example: a three-trial gate `SetPlayerData` applies **every** field in a named set directly onto the player, and does not clear any fields left over from a *different* set applied earlier — so you can have several small data sets each stamp one flag, then check for all of them together later. This is a clean way to build a "complete several trials in any order" puzzle: `Configs/CustomSpawnData/trial_fire_done.yml`: ```yaml Bools: trial_fire: true ``` `Configs/CustomSpawnData/trial_ice_done.yml`: ```yaml Bools: trial_ice: true ``` `Configs/CustomSpawnData/trial_stone_done.yml`: ```yaml Bools: trial_stone: true ``` Each shrine's dialogue stamps its own flag on success: ```cfg Text: Step onto the fire rune | Command: SetPlayerData, trial_fire_done ``` `Configs/CustomSpawnData/all_trials.yml` lists the same three field names together, all expected `true`: ```yaml Bools: trial_fire: true trial_ice: true trial_stone: true ``` The final door checks the player against that combined set — `PlayerHasAllCustomDataKeys` only passes once all three shrine flags are present and `true`, regardless of the order the player visited them in. Quote the failure message so its spaces survive — every field in a `Condition:` gets stripped of spaces otherwise, same as everywhere else in these config files: ```cfg Text: Push open the door | Condition: PlayerHasAllCustomDataKeys, all_trials, "You have not completed every trial yet." | Transition: inner_sanctum ``` ## Example: a remembered dialogue choice `SetPlayerData` is also a lightweight way to remember a one-time story choice without setting up a full [Faction](../configs/factions.md) for it. Say an NPC lets the player commit to one of two paths early on: `Configs/CustomSpawnData/path_hunter.yml`: ```yaml Strings: chosen_path: hunter ``` `Configs/CustomSpawnData/path_scholar.yml`: ```yaml Strings: chosen_path: scholar ``` `Configs/Dialogues/path_choice.cfg`: ```cfg [path_choice] Two roads lie before you. Which calls to you? Text: The hunter's path | Command: SetPlayerData, path_hunter | Transition: path_confirmed Text: The scholar's path | Command: SetPlayerData, path_scholar | Transition: path_confirmed ``` Any dialogue anywhere else in the world can now branch on that remembered choice. `PlayerHasAllCustomDataKeys` always needs its trailing message argument — even if you leave it blank, the comma must be there — and `AlwaysVisible: false` keeps the non-matching greeting from showing up greyed out next to the real one: ```cfg Text: A fellow hunter, then | Condition: PlayerHasAllCustomDataKeys, path_hunter, | AlwaysVisible: false | Transition: hunter_greeting Text: Ah, a scholar | Condition: PlayerHasAllCustomDataKeys, path_scholar, | AlwaysVisible: false | Transition: scholar_greeting ``` ## Related - [Custom Spawn Data](../configs/custom-spawn-data.md) — the file format used above. - [Conditions](../concepts/conditions.md), [Commands](../concepts/commands.md). - [Dialogue tree guide](dialogue-tree.md) — the basics of branching dialogue, if you have not built one yet. --- # Video guides Community video content about the mod. These are third-party videos, not maintained alongside this documentation — some may show an older version with a different feature set. ## Mod review by Ruijven - [Marketplace and Server NPCs Revamped: Valheim Mod Reviews](https://youtu.be/zolOZ-rcrGQ) — a walkthrough of what the mod can do. ## Tutorial series by Stonedprophet - [Part 1 — Breathe life into your server](https://youtu.be/5fR_9Qygkro) — NPC types and the marketplace UI. - [Part 2 — Gambling, banks, and buffs](https://youtu.be/BthPUGOeaeA) - [Part 3.1 — Territories explained](https://youtu.be/hUU_bPCwFeE) - [Part 3.2 — Quests](https://youtu.be/ZgoeYVpEcI4) - [Part 3.3 — The battlepass](https://youtu.be/xdj2CccUYhk) - [Dialogue system explained](https://youtu.be/0COuBKO3Gpg) --- # Marketplace Hammer ![Marketplace Hammer in the build menu](../images/screenshots/iWZO1dp.png) The build-mode tool for placing and editing NPCs — the main way you create content for the [NPC system](npc-system.md). Available only to players with admin access (see `OverrideDebug` in [Server config](../setup/server-config.md)). ## Basic workflow 1. With admin access, open the build menu and select the Marketplace Hammer. It also lists any [Saved NPC](../configs/saved-npcs.md) templates you have made, as extra placeable pieces. 2. Place a new NPC, or click an existing one, to open its settings panel: the **Main** tab (type, name, profile, model, dialogue, pin icon — see [Core identity settings](npc-system.md#core-identity-settings)) and the **Fashion** tab (appearance — see [Appearance settings](npc-system.md#appearance-settings)). Every field on both tabs is covered in detail on the [NPC system](npc-system.md) page — come back here once you know what you want to set. | Main tab | Fashion tab | |---|---| | ![Main tab](../images/screenshots/jPPhADl.png) | ![Fashion tab](../images/screenshots/gyJCzsG.png) | 3. To record a patrol route, drop waypoints while holding the Hammer, then confirm — the route data is copied for you, ready to paste into a `SetNPCPatrol` command. 4. To reuse this exact NPC elsewhere, use the Hammer's save option — this writes a template file and shows a confirmation message reminding you to run `mreloadnpcs` (see [Saved NPCs](../configs/saved-npcs.md)). ## Handy commands while building | Command | Use | |---|---| | `mreloadnpcs` | Refresh the saved-templates list after adding or editing one — required, since it does not update on its own. | | `mnpcremove` | Quickly clear every mod NPC within 5 meters, useful while iterating on a build. | ## Related - [NPC system](npc-system.md) — the full settings reference for what you are editing. - [Saved NPCs](../configs/saved-npcs.md) — the template format this tool produces. - [Console commands](../setup/console-commands.md). --- # NPC system NPCs are placed in the world using [Marketplace Hammer](marketplace-hammer.md), a build-mode tool. Once placed, you configure an NPC through its own settings panel — no config file needed for the NPC itself (though you can export one for reuse, see [Saved NPCs](../configs/saved-npcs.md)). ## NPC types An NPC's **Type** decides what it does, and which profile folder its **Profile** field looks into: | Type | Profile comes from | See | |---|---|---| | `None` | — | No mechanic — a decorative or dialogue-only NPC. | | `Trader` | Traders | [Traders](../configs/traders.md) | | `Info` | Server Info | [Server Info](../configs/server-infos.md) | | `Teleporter` | Teleporters | [Teleporters](../configs/teleporters.md) | | `Feedback` | — | No config folder — posts player feedback to the Feedback Discord webhook. | | `Banker` | Bankers | [Bankers](../configs/bankers.md) | | `Gambler` | Gamblers | [Gamblers](../configs/gamblers.md) | | `Quests` | Quest Profiles | [Quest Profiles](../configs/quest-profiles.md) | | `Buffer` | Buffer Profiles | [Buffer Profiles](../configs/buffer-profiles.md) | | `Transmog` | Transmogrifications | [Transmogrification](../configs/transmogrification.md) | | `Marketplace` | — | The player-to-player auction NPC — no setup needed, works immediately. | | `Mail` | — | Opens the mail menu. | Every NPC also has an optional **Dialogue** field, separate from its Type — any NPC, including `None`, can have a full conversation attached (see [Dialogues](../configs/dialogues.md)). ## Core identity settings ![Main NPC settings panel](../images/screenshots/FYmh7jk.png) | Setting | What it does | |---|---| | Type | One of the types above. | | Name Override | A custom display name. | | Profile | Which profile this NPC uses, from the folder matching its Type. | | Model/Prefab Override | Swaps the NPC's appearance for a different creature/character model — supports the animation-swap trick and randomized pools, see [Prefabs and text markup](../concepts/prefabs-and-assets.md). | | Dialogue | A dialogue ID from [Dialogues](../configs/dialogues.md). | | Pin Icon | The map pin shown for this NPC, if any. | | Visibility Condition | A [condition](../concepts/conditions.md), same syntax as anywhere else it's used. Leave it empty and the NPC is visible to everyone, as before. Set one and the whole NPC — not just a dialogue option — disappears client-side for any player who doesn't currently pass it, re-checked every couple of seconds. In debug mode ([`OverrideDebug`](../setup/server-config.md)), a hidden NPC shows a placeholder marker instead of vanishing outright, so you can still find it while testing. | ## Appearance settings ![Fashion panel](../images/screenshots/9QHD0cX.png) Set through the NPC's fashion panel: left/right hand items, helmet, chest, legs, cape, hair, hair color, beard, beard color, skin color, model scale, hidden-item toggles, greeting/farewell text and animations, crafting animation, interact sound and animation, text size/height, and periodic idle animation/sound. Most appearance fields accept a **space-separated list** of options — one is picked at random each time the NPC spawns, so a single NPC setup can produce visual variety across several placements. Greeting/farewell text also supports [dynamic placeholders](../concepts/prefabs-and-assets.md#dynamic-text-keyword) like `%playername%`. Periodic animation and periodic sound make the NPC occasionally play an idle animation or sound on their own — separate from [Random NPC Speech](../configs/random-npc-speech.md), which handles idle *text* barks instead. ## Patrol routes Give an NPC a patrol route two ways: - **Record it in-game**: while holding Marketplace Hammer, drop waypoints as you walk the route, then confirm — the route is copied for you to paste into a `SetNPCPatrol` command (see [Commands](../concepts/commands.md)). - **Script it**: use the `SetNPCPatrol` command from a dialogue or quest event to set or change a patrol route on the fly. ## Related - [Marketplace Hammer](marketplace-hammer.md) — the placement tool. - [Saved NPCs](../configs/saved-npcs.md) — exporting an NPC setup as a reusable template. - [Random NPC Speech](../configs/random-npc-speech.md) — idle bark text. --- # Changelog The mod's own version history, 71 versions from 8.4.0 through 9.9.4. This documentation covers **9.9.4**, the top entry below. If your server is running an older version, some fields, flags, or quest types described elsewhere may not exist yet for you — check the entry for your version and everything above it. --- ## [9.9.4] - Fixed Jere's UpgradeWorld's `world_clean` command clearing NPCs ## [9.9.3] - Fixed faction system bugs ## [9.9.2] - **Breaking change:** `IsVIP` and all related VIP functionality removed — see [Migrations](migrations.md#updating-to-992-the-vip-system-is-gone). - Added a visibility condition for NPCs, settable in the main NPC UI — see [NPC system](../npc/npc-system.md#core-identity-settings). - Added a new system, [Spawned NPCs](../configs/spawned-npcs.md), so players can spawn NPCs for themselves through [Distanced UI](../configs/distanced-ui.md) ## [9.9.0] - Bugfixes - Fixed quests/dialogues OR condition not working properly - Small UI/UX changes for trader and banker ## [9.8.9] - Bugfixes - Some dialogue commands logic fixes ## [9.8.8] - Fixed Saved NPCs model not showing up when building presets with hammer - UI / UX improvements - Bugfixes - Quest Events now may contain conditions similar to Dialogues - Added RandomNpcSpeech.yml file and system - Added a new patrol feature to use Navigation Mesh for NPCs - Now while holding Marketplace Hammer you can press + (= keyboard button) to create spot for NPC to patrol. On pressing Enter to confirm the patrol data will be saved to your clipboard - Added tooltips for NPC UI - Added Volume param into PlaySound dialogue command, also now by adding @number to sound in npc fashion UI it will change sound volume - You can now add @Prefab to NPC prefab override to change its animator to another creature. Example: Player@Morgen will use player model with Morgen animator - Added autocomplete for some NPC UI features - Added hotpath cache for ForceBiome ## [9.8.7] - Added an ability to use specific Territory / Trader configs depending on current server time - UI / UX improvements - **BEFORE INSTALLING THIS VERSION TEST IT FIRST ON LOCAL CLIENT CAUSE LOTS OF QUEST SYSTEM CHANGES. IF YOU HAVE QUESTS ALREADY ON SERVER THEY MAY BREAK** ## [9.8.6] - Microoptimizations + some fancy UI/UX improvements - You can now cancel quests in quest journal (J) - Quest Journal can now be closed with same button as opened (J) - Added two new quest types (in beta) - **BEFORE INSTALLING THIS VERSION TEST IT FIRST ON LOCAL CLIENT CAUSE LOTS OF QUEST SYSTEM CHANGES. IF YOU HAVE QUESTS ALREADY ON SERVER THEY MAY BREAK** ## [9.8.5] - Fixed blaxxun's guild mod interactions for quests ## [9.8.3] - Meh ## [9.8.1] - Bugfixes ## [9.8.0] - Faction system bugfix with not being able to shutdown game ## [9.7.9] - Faction chat (/f) added - Faction chat added to KGchat as separated /faction toggle - Added synced option to add X Y offset to faction nameplate - Added new options to faction .yml, such as remove same faction damage between players - Bugfixes ## [9.7.8] - Small bug fix with new faction system ## [9.7.7] - Added new system: Factions (in test mode rn) - Bugfixes ## [9.7.6] - Custom data folder changed - Guide on website for dialogues updated with new features ## [9.7.5] - Fixed a bug with not being able to log out of the game ## [9.7.3-9.7.4] - Bugfixes ## [9.7.2] - Lots of new features that im too lazy to write about... ## [9.7.1] - Fixed Quest / ServerInfo tags not working ## [9.7.0] - New Valheim Update ## [9.6.0] - Main wiki site updated - New Dialogue keyword: OverrideError. Allows you to override error on condition fail - Fixed a bug with trader / quest SkillEXP logout problem ## [9.5.9] - Fixed Transmog preview UI being behind transmog UI itself - Fixed talk quest completion also opening UI with same click ## [9.5.8] - Bugfix ## [9.5.6-9.5.7] - Chat shout fix ## [9.5.5] - New Quest Reward: Random Item - Bugfixes ## [9.5.2-9.5.4] - Bugfixes (again) ## [9.5.1] - Bugfixes ## [9.5.0] - New Quest type: Move - There is now a way to transfer Quest completion from one NPC to another. A.k.a you take Quest from npc A but can only finish it with npc B - New dialogue feature: RandomTransition - New Quest Event: OnDeath ## [9.4.7] - Added %playername% to dialogue text that auto-replaced on Player Name ## [9.4.6] - DB fixes ## [9.4.5] - DB fixes ## [9.4.4] - Fixed Banker withdraw error ## [9.4.3] - Bugfixes (again) ## [9.4.2] - Bugfixes (again) ## [9.4.1] - Bugfixes ## [9.4.0] - Updated for new valheim patch - Spawn MarketplaceHammer to place npcs - **Before installing this version please revert to old one and withdraw all Trade Post items / Banker items / Mail items. Marketplace moved from using .json data files to one single LiteDB file** ## [9.3.3] - Fixed a bug where marketplace would increase Cooking skill food values ## [9.3.2] - Please note that all NPC's moved to separated hammer: MarketplaceHammer ## [9.3.1] - Updated for Ashlands ## [9.2.9] - Its not a real version. Just a keep alive update for current NON-PTB valheim patch. Waiting for Ashlands to release so i can update one more time with patchnotes ## [9.2.3] - Added new quest event: OnQuestTimeout - Now all quest event commands are shareable with dialogue commands - Added and fixed some commands and mechanics ## [9.1.8 - 9.2.2] - Fixes ## [9.1.7] - Added compatibility with AUGA tooltips (quests, traders) - Added NPC Pin Icon inputfield to NPC UI. Pin Icon can be any item/piece or cachedimages folder file ## [9.1.6] - Fixed a bug where KGchat would prevent pings from showing on map ## [9.1.5] - Updated for new Valheim version ## [9.1.4] - Fixed trader ToBank button - Fixed Territories owner list not working ## [9.1.3] - Added MHLevelMore and MHLevelLess condition - Few fixes ## [9.1.2] - Fixed small bug with quests conditions ## [9.1.1] - Added more GuildsAPI methods - Fixed territories priorities bug - Added more localization for lootboxes ## [9.1.0] - Fixed for new Valheim version - Added new system: Lootboxes - Added new chat options - Added trader button to use items directly from banker / to banker - Removed pinned NPC and added that as UI option - Added various blaxxun's Guilds API to quest/dialogue conditions and commands - Added Dialogues to Distanced UI - Removed battlepass - Removed any possible "vip list" (distanced ui, IsVip condition, marketplace taxes) ## [9.0.14] - Fixed Pinned NPC not being displayed on map on dedicated server - Added new dialogue/quest condition: IronGateStatMore/Less - CustomValues now may have icons ## [9.0.13] - Added more info when config not being able to be parsed - New TerritoryFlag: GodMode ## [9.0.12] - Fixed Gambler not working - Added CustomValue to trader exchange ## [9.0.11] - Fixed Territory data not being updated in runtime - Added /mmapcontrol command to enable/disable NPC map control in debug mode ## [9.0.10] - Fixed NPC not being able to place with hammer ## [9.0.9] - Fixed NPC names showup - Fixed NPC patrol bugs - Fixed Teleporter not being synced at first load ## [9.0.8] - Fixed WackyDB compatibility with modules - Removed transmogrification VFX's due to non-readable mesh - Removed all NPC models except default one, will later add skeleton/portal/questboard back as separated mod ## [9.0.7] - Fixed CLLC compatibility with craft quest hook ## [9.0.6] - Fixed configs subfolders not working with runtime save ## [9.0.5] - Fixed compatibility with other PieceManager mods that blocked showing category ## [9.0.4] - Fixed Groups compatibility ## [9.0.3] - Fixed QuestEvents breaking config sync - Added new Dialogue Action: EnterPassword ## [9.0.2] - Fixed scroll wheel camera in all UI's ## [9.0.1] - Small hotfix: Fixed player being naked in menu and added new config for adminlist ## [9.0.0] - Reworked all marketplace folders and how configs applied - Added Transmog Color choice + Item Preview button - Now if you have debug mode it allows you to control NPCs from Map window. Left click = Main UI, Right click = Fashion UI - New territory flags: ForceWind + DropMiltiplier (replaced NoCreaturesDrop), territory optimizations - Added mclearallquests + mclearquest commands for admins to remove quest data for other player - Added mcustomvalues command to show custom values saved in player - Added new dialogue conditions / actions: AddCustomValue, SetCustomValue, CustomValueLess, ModInstalled / More - Trader now has new feature to add result items directly to bank if there is a posibility for it - Reworked leaderboard to allow it to be per steamid+_playername instead of just steamid bind - Reworked NPC Save / Load. Now its done via separated hammer Menu and .cfgs can be shared to other people much easily now. Saved npcs now also contain MAIN data as profile/model/dialogue/name - Fixed playertags to only affect visual name of player but not actual name (groups / other mods compatibility) - Battlepass removed due to CustomValue features - Added some debug tools for F2 menu (mostly for myself but maybe it'll be handy for server admins) - Serverside MapPins folder was removed, use clientside CachedImages now ## [8.7.0] - Leaderboard system added with custom Achievements system - Added players tag system - Traders now can sell Skill EXP - Added new folder: AdditionalConfigs with Quests/Dialogues/Territories folders where you can put additional .cfg files for corresponding NPC type (so you don't flood your main config file and split / manage it better) - Added Color attribute to dialogues - Added new dialogues commands / conditions - Added tag for server info - Now if server info tag named [OnPlayerFirstSpawn] it will show UI when player first joins server - Bugfixes / optimizations - Transmogrification is now a free feature - Added Transmog to DistancedUI - Now you can use ! sign before dialogue condition to simply reverse it - Added gradients for Territory System colors ## [8.6.3] - Posted / updated NPC Dialogues + Territory System guides on site - Added config option to specify banker interest items (All by default) - Added config option to set mailbox item wait time - Fixed gambler code - Now working with wackydb 2.0 (beta) cloned items ## [8.6.0] - New system added: Mailbox - Finished NPC Dialogues system - Bugfixes - Fixed Banker interest not working - Now Marketplace can use SOME of its features locally on client (to enable set config option to true on clientside) - New Quest Restriction - Time: value, allows quest to be time limited - Added NPC font support for chinese symbols and other languages special symbols ## [8.5.0] - New system added: NPC Dialogue (guide soon) - New system added: Item Mocking (guide soon) - Fixed banker multiplier bug - Fixed KGchat text overflow ## [8.4.0] - Player Territories removed. Please do not install this version until you replace Player Territories module on something else (Azumatt wards / e.t.c) (TerritoryDatabase is same and working, just not the players one) - Added KGchat as part of marketplace. Its enabled by default but you can turn it off in Main config on serverside. You can replace KGchat emojis in BepInEx/Config/MarketplaceEmojis. You will find spritesheet_original.png there, change pics on what you need and rename it to spritesheet.png - Added 2 new fields to fashion UI: Periodic Sound + Periodic Sound Time - Added new quest event: NpcText - Optimized mod by rewriting it almost from scratch. The mod's source is now open for anyone to review. - Added an integration for territories so other mods may use it. - NPC's now won't show up in hammer menu if Debug Mode is turned off - Transmogrification system access has changed (now transmogrification is a separated DLL). If you bought Transmog access before this patch please contact me in discord KG#7777 so i can send you mod to enable Transmog --- # Known gaps and traps Things in the **current mod version (9.9.4)** that look like they should work based on folder names, in-game text, or their own naming, but do not — or that behave differently from what their name suggests. Every entry below is checked directly against the mod's own source, not guessed. This page is about present-day behavior, not about updating between versions; for that, see [Migrations](migrations.md). ## `IsVIP` / `NotIsVIP` still parse, but never do anything Since 9.9.2 removed the VIP system (see [Migrations](migrations.md#updating-to-992-the-vip-system-is-gone)), these two [conditions](../concepts/conditions.md) are still valid syntax — they will not error out — but `IsVIP` always evaluates to false and `NotIsVIP` always evaluates to true, regardless of the player. There is no VIP list left to check against. If you're writing new content, use a real condition instead (`HasGuild`/`HasFaction`/a [custom value](../concepts/prefabs-and-assets.md#custom-values) you set yourself) to gate anything that used to be VIP-only. ## Related - [Conditions](../concepts/conditions.md). - [Migrations](migrations.md) — for warnings about updating between versions, which is a different topic from this page. --- # Localization keys The mod's built-in UI text — menu labels, tooltips, messages — comes from a set of keys, all starting with `mpasn_` (a handful of exceptions are noted below). **[translations.English.yml](/reference/translations.English.yml)** — the full, current key list, pulled directly from the mod (mod version **9.8.8**). This is a plain copy of the file embedded in the mod's own `kg.Marketplace.dll`, kept here by hand and updated whenever a mod release changes, adds, or removes translation strings. If you're on a different version and notice this is out of date, please [open an issue](https://github.com/odin-sons/kg-marketplace-docs/issues/new?template=doc-correction.yml) — that's exactly the kind of drift this page can't catch on its own. You can use this file directly as your own [local client translation file](#overriding-a-key) — translate it and drop it in — or read through it to decide what to override with [Synced Localizer](../configs/synced-localizer.md). ## Overriding a key Two different ways to change what a key displays: 1. **[Synced Localizer](../configs/synced-localizer.md)** — a server config. Applies to every connected player automatically, with no file needed on their end. This is the normal way for a server admin to retranslate or reword a piece of UI text. 2. **A local client translation file** — a full translation, entirely local to one player's own computer. Create a file named `MarketplaceAndServerNPCs..yml` (matching Valheim's own language names — `English`, `Russian`, `German`, etc.) and place it anywhere under your `BepInEx` folder — `BepInEx/config/` is the conventional spot. Whichever player has their game language set to `` will load it automatically. This is exactly what the file above is for: rename your translated copy to match your target language and drop it in. Both accept the same `key: replacement text` format. ## How to find which key produced a piece of text you saw in-game There is no in-game inspector that shows you a key name when you point at something — the practical approach is matching text, in three steps: 1. **Search [the file above](/reference/translations.English.yml) for the exact English text you saw.** The text next to each key is exactly what displays in-game (unless you have already overridden it). Searching for a distinctive word or phrase from what you saw is usually enough to find the right key in one try. 2. **If several keys have similar text, use the prefix to narrow it down** — keys are grouped by feature area (see [Key naming](#key-naming) below), so a string you saw on the mail screen will start with `mpasn_CMS_`, one on the leaderboard with `mpasn_Leaderboard_`, and so on. 3. **To confirm you found the right key before rolling a change out to your whole server**, set it to something obviously distinctive with [Synced Localizer](../configs/synced-localizer.md) — e.g. `mpasn_sell: TESTING123` — reload, and check whether `TESTING123` shows up where you expected. Once confirmed, replace the test value with your real text. ## Key naming Keys read as `mpasn_` followed by a short word or phrase describing what the text is for — `mpasn_searchbyname`, `mpasn_itemname`, and so on. Some keys include `$1`, `$2` placeholders that get filled in with real values when shown (`mpasn_added` reads `Added $1 $2`). Keys are grouped by feature area through their prefix — for example `mpasn_CMS_*` is the mail system, `mpasn_transmog_*` is the Transmog menu, `mpasn_Leaderboard*` is the leaderboard, `mpasn_faction_*` is faction messages, `mpasn_tooltip_*` is item/UI tooltips, and `mpasn_lootbox*` is Lootbox UI text (present even though the Lootbox feature itself is not currently working, see [Known gaps](known-gaps.md)). [The file above](/reference/translations.English.yml) groups naturally by these prefixes if you sort or search it. ### NPC type labels Shown as an NPC's type in menus — probably the ones most worth rebranding for your server's theme: | Key | Default text | |---|---| | `mpasn_Banker` | Banker | | `mpasn_Trader` | Trader | | `mpasn_Gambler` | Gambler | | `mpasn_Marketplace` | Marketplace | | `mpasn_Mail` | Mail | | `mpasn_Teleporter` | Teleporter | | `mpasn_Buffer` | Enchanter | | `mpasn_Info` | Info | | `mpasn_Quests` | Quests | | `mpasn_Feedback` | Feedback | | `mpasn_Transmog` | Transmog | Example — reskinning the Enchanter NPC as "Rune Master" server-wide, using [Synced Localizer](../configs/synced-localizer.md): ```yaml mpasn_Buffer: Rune Master ``` A few messages are referenced directly by name rather than through the `mpasn_` prefix — `marketplace_cannotleaveguild`, `kg_banker_putall`, plus any custom message key you invent yourself for use with [Synced Localizer](../configs/synced-localizer.md). ## Related - [Synced Localizer](../configs/synced-localizer.md) — the format for overriding any of these, server-wide. --- # Migrations Most updates to this mod are safe to install directly. This page lists the exceptions — points in the [changelog](changelog.md) where the mod author explicitly warned that updating requires an extra step, or could break existing server data if you are not careful. A couple of entries below are flagged from source-checking a fix instead (noted as such) rather than an author warning, when the fix itself silently changes existing content's behavior. If you are updating across a version not listed here, a plain update is expected to be safe. When in doubt, back up your `Marketplace` folder and save file before updating a live server either way. ## Updating to 9.9.2: the VIP system is gone The changelog calls this out as a **breaking change**, and checking the diff confirms it's thorough — this isn't just one setting: - `VIPplayersList`, `VIPplayersTaxes`, and `BankerVIPIncomeMultiplier` are no longer read from [server config](../setup/server-config.md). Leaving them in your `MarketPlace.cfg` is harmless — they're just ignored — but they no longer do anything: every seller pays `MarketTaxes`, and every banked deposit earns `BankerIncomeMultiplier`, with no VIP-tier exception. - The `IsVIP` / `NotIsVIP` [conditions](../concepts/conditions.md) still parse without error, but `IsVIP` now always evaluates to false and `NotIsVIP` always evaluates to true — see [Known gaps](known-gaps.md) for the current-version detail. Any dialogue option, quest, or zone flag that used to gate on VIP status needs a different condition now (guild membership, a faction, or a [custom value](../concepts/prefabs-and-assets.md#custom-values) you set yourself). - `OrConditionSeparator` is also gone in the same pass, unrelated to VIP specifically — the `||` OR-separator in [conditions](../concepts/conditions.md) is hardcoded now, no longer admin-configurable. This only matters if you had actually changed it away from the default `||`; if you never touched that setting, there's nothing to do. If your server had a VIP tier set up through this mod (taxes, banker interest, or gated content), re-check all three after updating — none of it silently keeps working. ## Updating to 9.8.9: re-check any `KillAndCollect` quest's level field Not an author-flagged warning — found by checking the fix itself. Before 9.8.9, `KillAndCollect`'s level field required one star *less* than the number written (see the now-removed entry on [Known gaps](known-gaps.md) for past versions), so existing quests written to work around that — e.g. writing `3` to mean "2-star minimum" — now require one star *more* than originally intended, since 9.8.9 makes the field mean exactly what's written (matching plain [`Kill`](../configs/quests.md#the-target-line-by-type)). If you have any `KillAndCollect` quests already live, check their level field against what you actually want after updating — a quest that used to accept 1-star-and-above creatures at level `2` now requires 2-star-and-above. ## Updating to 9.8.6 or 9.8.7: test quests locally first Both versions shipped large changes to the quest system. The author's own release notes for both said, verbatim: **"BEFORE INSTALLING THIS VERSION TEST IT FIRST ON LOCAL CLIENT CAUSE LOTS OF QUEST SYSTEM CHANGES. IF YOU HAVE QUESTS ALREADY ON SERVER THEY MAY BREAK."** If your server has active quests and you are updating from before 9.8.6, install the new version on a local/test copy first, confirm your existing [Quests](../configs/quests.md) still work as expected, and only then update the live server. ## Updating from before 9.4.0: withdraw everything first In version 9.4.0, the mod changed how it stores player data — moving from individual save files to a single combined database file. The author's release note: **"Before installing this version please revert to old one and withdraw all Trade Post items / Banker items / Mail items. Marketplace moved from using .json data files to one single database file."** If you are updating a server from a version older than 9.4.0, have every player withdraw their marketplace listings, banked items, and mail attachments **before** you install the update — anything left in those systems at the moment of the switch may not carry over. This mod version documented here (9.9.4) is well past this change; it only matters if you are jumping to a modern version from something very old. ## Since 9.0.8: Transmogrification's visual-effects field is gone Versions 8.2.3 through 9.0.7 supported a fifth field on a [Transmogrification](../configs/transmogrification.md) line — a numbered visual-effect ID (1 through 20, plus 21 for "player's choice", added in 8.2.3) that layered a glowing effect on top of the reskinned item. The author's 9.0.8 release note: **"Removed transmogrification VFX's due to non-readable mesh."** If you're following an old guide or example that includes a fifth field on a Transmogrification line, drop it — it does nothing as of 9.0.8. Only the four documented fields (item, cost item, cost amount, ignore category) apply in this version. Two leftover text labels for it ("No Effect" / "Any Effect") still exist in the mod's translation file, but nothing reads them. ## General advice for any update - Read the entries between your current version and the new one in the [changelog](changelog.md) — the author calls out breaking changes there when they happen. - Back up your `Marketplace` config folder and save data before updating a live server, especially across a large version jump. - Test on a local or backup copy first if your server has valuable, hard-to-recreate content (long quest chains, custom zones, banked items). ## Related - [Changelog](changelog.md) — the full version history these warnings are drawn from. - [Known gaps](known-gaps.md) — current-version quirks, unrelated to updating. --- # Client config `BepInEx/config/MarketplaceAndServerNPCs.cfg` — the standard per-player settings file, set individually by each player (or by whoever is hosting). This is separate from [Server config](server-config.md) and is never shared between players. Unlike most of this documentation, this page isn't admin-only — anyone playing on a server using this mod can edit their own copy of this file to change their own keybinds, chat window, and UI, with no server access needed. ## `[General]` | Setting | Default | What it controls | |---|---|---| | `Use Marketplace Locally` | `false` | Turns on singleplayer/local mode — see [Server, client, or singleplayer](installation.md#server-client-or-singleplayer). | | `Quest Journal Keycode` | `J` | The key that opens/closes the quest journal. | | `Show Quest Mark` | — | Toggles quest target markers on the map/compass — can also be flipped in-game with the `mquestmarker` command. | | `DisableMapNPCControl` | — | Turns off the NPC map-control overlay. | | `Mute Gambler Sounds` | `false` | Mutes gambling roll sound effects. | ## `[Marketplace]` | Setting | Default | What it controls | |---|---|---| | `Market Size` | `Large` | The size of the marketplace window (`Large`, `Medium`, `Small`). | ## `[Territories]` | Setting | What it controls | |---|---| | `Use Map Draw` | Enables map-based zone drawing tools. | | `Always Show Zone Visualizer` | Keeps zone outlines visible at all times, instead of only when toggled on. | ## `[KG Chat]` | Setting | Default | What it controls | |---|---|---| | `Font Size` | `18` | Chat text size. | | `Use Type Sound` | `false` | Plays a typing sound as chat messages appear. | | `Hide Floating Text` | — | Hides floating chat bubbles above characters. | | `Chat Filter` | — | Word filter setting. | | `Transparency` | `Two` | Chat window background transparency. | | `UI_sizeX` / `UI_sizeY` | — | Chat window size. | | `UI_posX` / `UI_posY` | — | Chat window position. | ## `[Database]` | Setting | What it controls | |---|---| | `Database File Path` | Where the server stores its save data — only matters if you are the server host, has no effect for a regular player. | ## Related - [Server config](server-config.md) — the separate, server-wide settings file. - [File structure](file-structure.md), [Server, client, or singleplayer](installation.md#server-client-or-singleplayer). --- # Console commands Type these into the in-game console (usually the F5 key). Most require admin access — a Steam ID listed in `OverrideDebug` (see [Server config](server-config.md)) — but not all: anything marked "no" in the table below works for any player, admin or not. | Command | Arguments | Needs admin access? | What it does | |---|---|---|---| | `mreloadsounds` | — | no | Reloads the sounds folder. | | `mreloadmodels` | — | no | Reloads the models folder. | | `mreloadimages` | — | no | Reloads the images folder. | | `mreloadnpcs` | — | no | Reloads [Saved NPC](../configs/saved-npcs.md) templates into the build menu. | | `mnpcremove` | — | yes | Deletes every mod NPC within 5 meters of you — handy for quickly clearing out a test area. | | `idm` | — | yes | Shows the currently held weapon's extra data — a debugging aid for item mods. | | `mpos` | — | no | Prints your current position, useful for filling in exact coordinates in a config. | | `mfpslimit` | fps | yes | Sets the game's update rate (50-144). | | `zonevisualizer` | — | yes | Toggles zone outlines on/off in the world, so you can see your [Territories](../configs/territories.md) while editing. | | `zonevisualizeralpha` | [amount] | set: yes, view: no | Reads or sets how visible the zone outlines are (25-255). | | `mquestmarker` | — | no | Toggles quest target markers on/off, remembered for next time. | | `mresetcustomvalues` | — | yes | Clears all of your own [custom values](../concepts/prefabs-and-assets.md#custom-values). | | `mcustomvalues` | — | no | Prints your own current custom values — useful for checking a reputation/story-flag system while testing. | | `mclearallquests` | player name | yes | Clears every quest for a named player. | | `mclearquest` | player name, quest ID | yes | Clears one specific quest for a named player. | | `maddterritory` | shape, x, z, radius, r, g, b, price | yes | Adds a territory on the fly for quick testing — not the normal way to build zones, use [Territories](../configs/territories.md) files for anything permanent. | | `mshownpcpath` | — | — | Shows an NPC's patrol path in the world. | | `mshowhumanoids` | — | — | Lists creature models you can use with the humanoid animation trick — see [Prefabs and text markup](../concepts/prefabs-and-assets.md#model-with-a-different-animation-set). | | `mmapcontrol` | — | — | Toggles NPC map-control mode. | | `chatfilter` | word | — | Adds/removes a word from the chat filter. | | `f` | message | no | Sends a message in faction chat. | ## Related - [Hot reload](hot-reload.md) — for the manual-reload commands above. - [Marketplace Hammer](../npc/marketplace-hammer.md) — placing NPCs with admin access. --- # File structure A map of every folder and file the mod creates or uses, and what lives where. For how to install the mod itself, see [Installation](installation.md) on the main page. ## First run Start the server once after installing. On first run, it creates a `Marketplace` folder under `BepInEx/config/` and fills in the subfolders below. ## Server folders Present on a dedicated server, or on a client hosting a game (or a singleplayer game with local mode turned on — see [Server, client, or singleplayer](installation.md#server-client-or-singleplayer)): ![Server-side Marketplace folder](../images/screenshots/KNm9w56.png) ``` BepInEx/config/Marketplace/ ├─ Configs/ ← all content configs, see ../configs/ │ ├─ Quests/ │ ├─ QuestProfiles/ │ ├─ QuestEvents/ │ ├─ Dialogues/ │ ├─ CustomSpawnData/ │ ├─ Territories/ │ ├─ Traders/ │ ├─ Bankers/ │ ├─ Teleporters/ │ ├─ Gamblers/ │ ├─ Buffers/ │ ├─ BufferProfiles/ │ ├─ Transmogrifications/ │ ├─ ServerInfos/ │ ├─ LeaderboardAchievements/ │ ├─ SyncedLocalizer/ │ ├─ Factions.yml │ └─ RandomNpcSpeech.yml ├─ DiscordWebhooks/ │ └─ DiscordSettings.cfg ├─ DistancedUI/ │ └─ DistancedUI.cfg ├─ PlayerTags/ │ └─ PlayerTags.cfg ├─ SavedData/ ← the mod's save data (marketplace listings, banks, mail, leaderboard). Only edit this while the server is offline, and be careful — it is easy to corrupt. └─ MarketPlace.cfg ← the main server settings file, see server-config.md ``` `Configs/` on its own contains one subfolder per content type: ![Configs subfolder listing](../images/screenshots/lrLPgZS.png) ## Player-side folders Live next to `BepInEx/config/Marketplace/`, not inside it — present on every installation, whether or not that computer is also the server: ![Client-only folders](../images/screenshots/NdYsvEV.png) | Folder | Purpose | |---|---| | `Marketplace_Sounds/` | Drop `.mp3` files here to use as sounds — see [Custom assets](../assets/custom-assets.md). | | `Marketplace_Models/` | Drop `.obj` files here for custom NPC models. | | `Marketplace_CachedImages/` | Drop `.png` files here for `` references. | | `Marketplace_VideoClips/` | Drop video files here for the `PlayVideo` command. | | `Marketplace_SavedNPCs/` | Hammer-built NPC templates — see [Saved NPCs](../configs/saved-npcs.md). | | `Marketplace_KGChat_Emojis/` | Custom chat emoji images. | Once you know where a file lives, the natural next question is what happens after you edit it — most of the time, nothing more than saving is needed; see [Hot reload](hot-reload.md) for exactly what applies live and what needs a manual refresh. ## Related - [Installation](installation.md) — how to get the mod installed in the first place. - [Server, client, or singleplayer](installation.md#server-client-or-singleplayer) — which of the folders above exist on which machine. - [Hot reload](hot-reload.md) — what happens after you edit a file in `Configs/`. - [Server config](server-config.md), [Client config](client-config.md). --- # Hot reload Most config changes apply live, without restarting the server — save the file, and within a moment your NPCs, quests, and zones update for everyone on the server. ## What reloads automatically Almost everything under `Configs/`, plus `MarketPlace.cfg`, `DistancedUI.cfg`, `PlayerTags.cfg`, and `DiscordSettings.cfg` — edit any of these while the server is running, save, and the change is picked up on its own. The server re-reads the entire relevant folder each time (not just the one file you touched), so if you have several files contributing to one profile, they will all stay in sync. ## What does NOT reload automatically A few things need a manual nudge — use the matching console command from [Console commands](console-commands.md): | What | How to refresh it | |---|---| | [Saved NPCs](../configs/saved-npcs.md) | `mreloadnpcs` | | Sounds folder | `mreloadsounds` | | Models folder | `mreloadmodels` | | Images folder | `mreloadimages` | Also worth knowing: your own per-player settings (the client config file — see [Client config](client-config.md)) are local to each player and are never synced between players; there is nothing to "reload" there. ## If a change is not showing up - Check the server console — most typos and formatting mistakes are logged there, in red, with the file name and line. - Confirm you edited the file the running server is actually using — double check you are editing the live `BepInEx/config/Marketplace/` folder and not a backup or a copy from an old install. - For the manual-reload items above, remember to run the matching command after editing. ## Related - [Console commands](console-commands.md) — the manual reload commands. - [Config file syntax](../concepts/config-syntax.md) — how to spot a formatting mistake. --- # Installation The mod needs to be installed on **every client and on the dedicated server** (or the hosting client, if you are hosting from within the game). ## Option 1: Hexium (Gale) 1. Open the mod's page: [valheim.hexium.gg/mods/KG/Marketplace_And_Server_NPCs_Revamped](https://valheim.hexium.gg/mods/KG/Marketplace_And_Server_NPCs_Revamped). 2. Click **Install with Gale** — this opens the [Gale mod manager](https://hexium.gg/mod-manager) and adds the mod to your profile automatically. If Gale is not installed yet, the page will prompt you to get it first. 3. Repeat on every client and on the server machine. ## Option 2: Manual install Download the mod file from [Hexium](https://valheim.hexium.gg/mods/KG/Marketplace_And_Server_NPCs_Revamped) and extract it into your `BepInEx/plugins/` folder, the same way as any other BepInEx mod. Requires [BepInEx](https://valheim.hexium.gg/mods/denikson/BepInExPack_Valheim) to already be installed. ## Server, client, or singleplayer The mod figures out its own role automatically: - **Server** — a dedicated server, or a client that is also hosting. Reads and applies everything in `Configs/`. - **Client** — a normal connecting player. Gets everything from the server automatically. - **Both** — singleplayer, with local mode turned on in [Client config](client-config.md). The game builds and reads its own local copy of the server folders, letting you build and test content offline. In singleplayer, most modules work fine: Buffer, Distanced UI, Gambler, Dialogues, Trader, Quests, Territories, Teleporters, Transmog, Server Info, Player Tags, Chat. **Not available in singleplayer**: Banker, the player-to-player Marketplace, and Leaderboard — these save their data to the server and have no local equivalent. ## First run Start the server once after installing. On first run, it creates a `Marketplace` folder under `BepInEx/config/` and fills in the subfolders you will be editing — see [File structure](file-structure.md) for a full map of what gets created and where. ## Updating an existing server Most updates are a plain drop-in with nothing else to do. A few past versions changed something that needed manual action first — see [Migrations](../reference/migrations.md) to check whether the version jump you are making is one of them. ## Related - [File structure](file-structure.md) — a full map of what gets created on first run. - [Client config](client-config.md) — includes the singleplayer local-mode toggle mentioned above. - [Migrations](../reference/migrations.md) — manual steps required by specific past version updates. --- # Server config — MarketPlace.cfg `BepInEx/config/Marketplace/MarketPlace.cfg` — the mod's central settings file, everything under one `[Main]` section. Changes here [reload automatically](hot-reload.md). ## Example `BepInEx/config/Marketplace/MarketPlace.cfg`: ```ini [Main] BankerIncomeTime = 6 BankerIncomeMultiplier = 0.02 ItemMarketLimit = 25 MarketTaxes = 5 MaxAcceptedQuests = 10 UseLeaderboard = true PossibleCurrencies = Coins, Ruby OverrideDebug = 76561198000000001, 76561198000000002 ``` This example: interest pays out every 6 hours at 2%, players can list 25 items with a 5% marketplace tax, quests cap at 10 active, the leaderboard is enabled, both Coins and Ruby work as currency, and two Steam IDs have admin access. ## Settings | Setting | Default | What it controls | |---|---|---| | `EnableTransmogLog` | `false` | Log transmog actions to the server log. | | `EnableTraderLog` | `false` | Log trader transactions. | | `BankerIncomeTime` | `1` | Hours between interest payouts. Set to `0` to turn off interest entirely. | | `BankerIncomeMultiplier` | `0` | Interest rate per payout. | | `BankerInterestItems` | `All` | Which banked items actually earn interest. | | `FeedbackWebhookLink` | placeholder | Discord webhook for the Feedback NPC. | | `ItemMarketLimit` | `15` | Maximum marketplace listing slots per player. | | `BlockedPlayers` | — | Player IDs blocked from the marketplace. | | `MarketTaxes` | `0` | Sell tax percentage (0-100). | | `CanTeleportWithOre` | `true` | Whether players can teleport while carrying ore without needing a special override. | | `MarketSellBlockedPrefabs` | `Coins, SwordCheat` | Items that cannot be listed on the marketplace. | | `GamblerEnableWinNotifications` | `false` | Broadcast a server-wide message whenever someone wins a gamble. | | `AllowMultipleQuestsScore` | `false` | Whether one kill/harvest/craft can count toward more than one matching quest at once. | | `MaxAcceptedQuests` | `7` | Maximum active quests per player. | | `AllowKillQuestsInParty` | `true` | Whether a party member's kills count toward your Kill quests. | | `EnableKGChat` | `true` | Turns the custom chat window on or off. | | `MailPostRecipe` | `SwordCheat, 1` | What it costs to craft a mailbox — `item, amount`. | | `MailPostWaitTime` | `5` | Minutes before sent mail can be picked up. | | `MailPostExcludeItems` | — | Items that cannot be mailed. | | `PieceSaverRecipe` | `SwordCheat, 1` | What it costs to craft a Piece Saver Crystal. | | `UseLeaderboard` | `false` | Turns the leaderboard/achievements system on or off. | | `OverrideDebug` | — | Steam IDs with admin access — build-mode NPC placement, admin console commands. | | `BlockedChatUsers` | — | Steam IDs muted from chat. | | `PossibleCurrencies` | `Coins` | Every item usable as marketplace currency. | | `CanLeaveGuild` | `true` | Whether players can voluntarily leave their guild. | | `FactionNameplateOffset` | `0, 0` | Pixel offset for the faction tag shown above player nameplates. | Looking for a setting that used to be here and isn't anymore? A few were removed in 9.9.2 — see [Migrations](../reference/migrations.md#updating-to-992-the-vip-system-is-gone). ## Related - [Client config](client-config.md) — the separate, per-player settings file. - [Hot reload](hot-reload.md). - [Conditions](../concepts/conditions.md) — the `||` OR-separator these settings don't control. --- # Coming soon Tools planned for this section, not built yet: - **AI skills for the marketplace** — an AI assistant (skill or MCP server) built around this documentation, to help generate and edit this mod's quests, dialogues, traders, and other config files from a plain-language description instead of hand-writing the format. - **A visual config editor** — a browser-based editor for building quests, dialogues, zones, and the rest without hand-writing the `.cfg` format directly. If you'd like to build either of these — or something else that belongs here — see [VS Code extensions](vscode-extension.md) for the kind of thing that fits. ## Related - [VS Code extensions](vscode-extension.md) — tooling that already exists. - [Config file syntax](../concepts/config-syntax.md) — the format any of these would need to read or write. --- # VS Code extensions Extensions that make working with this mod's config files easier inside VS Code. This list will grow over time — if you build one that helps other admins write quests, dialogues, or zones for this mod, it belongs here. ## Syntax highlighting **[KG Marketplace Syntax](https://github.com/odin-sons/kg-marketplace-syntax)** — a Visual Studio Code extension that adds syntax highlighting to `.cfg` config files for this mod. It recognizes and colors: - Comments (`#`) - Section headers (`[ProfileName]`) - Quest types (`Kill`, `Collect`, `Talk`, and the rest — see [Quests](../configs/quests.md)) - Dialogue keywords (`Text:`, `Transition:`, `Command:`, `Condition:`, and the rest — see [Dialogues](../configs/dialogues.md)) - Formatting tags (``, ``, ``, ``, ``) - `%variable%` placeholders (see [Prefabs and text markup](../concepts/prefabs-and-assets.md#dynamic-text-keyword)) - Numbers, coordinates, and [territory flags](../configs/territories.md#flags) **Install:** open the Extensions panel in VS Code (Ctrl+Shift+X), search for "KG Marketplace Syntax", and click Install. Once installed, it activates automatically for any `.cfg` file you open. Full setup notes are in the extension's own README, linked above. Here's everything it highlights in one profile bundle: ```cfg # A profile bundle demonstrating every highlighted construct [welcome_banner] Welcome, traveler! Type help for commands. Current bonus: %server_bonus% [weekly_bounty = HiddenAnyCondition] KillAndCollect Wolfpack Cull Thin the wolf packs threatening the herd. Bring me 5 pelts by week's end. Wolf, 5, 1 Item: Coins, 75 | Skill_EXP: Bows, 30 | RandomItem: loot_pool_common 7 HasItem, Wood, 20 || HasItem, Stone, 20 || QuestFinished, intro_quest GlobalKey, week_started | !HasQuest, weekly_bounty [merchant_greet] Welcome, traveler. What can I do for you today? @onopen | Command: PlaySound, shop_bell, 0.6 Text: Show me your wares | Command: OpenUI, Trader, merchant_stock Text: I'm ready for the ritual | Condition: HasItem, RitualCandle, 3 | AlwaysVisible: false | Transition: ritual_start RandomTransition: farewell_a, farewell_b, farewell_c Text: I have a quest for you | Condition: !HasQuest, weekly_bounty | Command: GiveQuest, weekly_bounty Talk, "Village Elder", 1 [weekly_bounty_events] OnAcceptQuest: GiveItemWithData, TrackingCollar, 1, 3, wolfhunt OnCompleteQuest: HasAchievement, wolfslayer | GiveItem, Coins, 500 OnCompleteQuest: AddEpicMMOExp, 250 | GuildAddLevel, 1 OnQuestTimeout: SetCustomValue, weekly_failed, true [market_square@2] Rectangle 0, 0, 60, 60 120, 180, 120, exp: 1.0, heightbounds: 5-45, TopLeftBottomRight NoAttack, PeriodicHeal = 2, NoMonsters, NoInteractPortals, OnlyForFaction = merchants None ``` ## Related - [Coming soon](coming-soon.md) — tools planned but not built yet, including AI-assisted config generation. - [Config file syntax](../concepts/config-syntax.md) — the format this extension highlights.