Vivifica dialogue system

From Chronicles of Torisia
Jump to navigation Jump to search

Vivifica is the only system in Chronicles of Torisia that is so powerful, that I even gave it a name :D While I built it for extreme flexibility and simplicity, it also means it's easy for something to break.


All dialogue lines are stored in an SQLite table DialogueLines.

Dialogue indexes

Dialogue indexes are used to create branching dialogue. Indexes follow a simple structure. The dialogue goes to whatever index the selected reply option tells it to go to.

Tip: It's recommended to use very high differences between indexes (like 1, 1000, 2000) instead of 1, 2, 3 as it makes branching a lot easier to read and change

Examples:

  • Player is on a line with index 3 which didn't open reply options so Vivifica automatically continues by going to a line index stored in reply 1 index.
  • Player is on a line with index 3 which opened reply options. Vivifica continues based on what reply option the player clicks on - clicking on option 4 leads to index stored in reply index 4.

Every line must have a valid index and at least one reply target index.

Vivifica opens reply options automatically. This is done purely based on if the reply 2 text field contains something or not.

  • Reply 2 text field is empty - Vivifica doesn't show reply options and automatically goes to the reply 1 target index as if the player clicked on it.
  • Reply 2 text field contains something - Vivifica reads the text of all replies and builds the reply options based on that.

Special indexes

You can use only numbers from 1 and higher for indexes. 0 are ignored and negative values are reserved for special interactions. All special indexes can be used only as a reply index.

- 1

  • This index is reserved as a guided exit and . If the reply option itself leads to index - 1 right by clicking on it, it colors its text to orange.
  • Requirements:
    • None but reaching it always closes the dialogue
  • Common uses:
    • Closing dialogue
    • With instructions to give/receive quest since it's leading the player towards it by coloring the path yellow.

- 2

  • This index is reserved as a return index. Upon reaching it, the dialogue automatically moves back to whatever line is saved as "returnNode".
  • Requirements:
    • It must have a node to return to, this is created by using "returnNode" instructions
  • Common uses:
    • Any kind of "fluff" dialogue like history of settlements, asking questions about Torisia, etc.

- 3

  • Opens NPC actions
  • Requirements:
    • None
  • Common uses:
    • Most commonly used when the NPC cannot interact right away and showing NPC actions must be delayed (E.g. NPC is sleeping

- 100

  • This index is reserved as a placeholder. Reaching it does nothing but it avoids breaking Vivifica.
  • Requirements:
    • It must be used with reply instructions to actually do something, otherwise nothing will happen
  • Common uses:
    • Anything that needs to execute instructions but won't continue in the current dialogue
    • Services - Open UI windows like trade, bank, etc.
    • Loading different dialogue from the current one

NPC actions

Whenever you talk to NPCs, Vivifica collects all possibilities this NPC can talk about.

  • If there's only one possibility, it triggers right away. E.g. - opens trade right when you start talking to the NPC
  • If there's multiple possibilities, it opens a reply menu, allowing you to choose what to talk about.

Overrides

This behavior can however be overriden.

  • NPC is sleeping - In this state, the NPC finds its line to say by looking for ID "default_npcIsSleeping"
  • NPC is talking to someone else - In this state, the NPC finds its line to say by looking for ID "default_npcIsYapping"

Flags

Vivifica allows creating flags for custom conditions without ever touching the code. These flags are also stored in long term memory of NPCs so they persist even through loading a save file. There are 2 types of flags:

  • Static - these flags have a code support as they require handling that cannot be scripted through VitaScriptum alone.
  • Custom - these flags can be created by VitaScriptum without touching the code. However, they're limited to only using and comparing one float value and their time of last update.

VitaScriptum flag commands:

Set and update flag

Both instructions work in almost the same way except for the way the set values.

Syntax: setFlag:flagType:flagID:flagValue:cooldown or updateFlag:flagType:flagID:flagValue:cooldown

  • FlagType: Sets flag type, this works essentially as a group of flags. Since done manually, it should technically support almost any name but it's strongly recommended to set custom flag type as "custom" to avoid future conflicts. Before adding a new type, you should check "Built in flags" under this text to make sure this functionality doesn't exist yet.
  • FlagID: Sets flag ID, this ID is not used by code at all, it's only used to find a specific condition that checks for it.
  • FlagValue: Sets flag value in a decimal format with a big difference between commands -
    • setFlag: Creates a flag and sets its value, if the dialogue hits setFlag for existing flag, it does nothing. E.g. this flag is at value 30, setFlag:custom:fartsReleased:-5 does nothing
    • updateFlag: Creates a flag and sets its value but it will add a value to it on every trigger. Also supports negative values. E.g. this flag is at value 30, setFlag:custom:fartsReleased:-5 changes the flag's value to 25
    • setGlobal and updateGlobal: Work exactly like setFlag and updateFlag but for a global (not NPC specific) memory. E.g. this flag is at value 30, setGlobal:custom:fartsReleased:-5 changes the flag's value to 25
    • forceUpdateFlag and forceUpdateGlobal: These work in the same way as their regular version but they bypass the flag's cooldown
  • Flag cooldown: All flags track the last time they've been updated. You can use flag cooldown to set the time before this flag can be updated again. E.g. setting cooldown as 20 means that if you update a flag, it can be updated again only at least 20 seconds later - Useful to prevent updating flags (like opinion) too often or even multiple times per dialogue. Its timer can also be accessed via memoryTime and used in conditions but you can also set it to 0 to ignore.
  • Outside of entering static values, flags can also parse command values.
    • now - Stores the current playtime in seconds. E.g. setFlag:custom:timeWhenFarted:now


Reading flags:

Read also: conditions

You can use flags stored in the NPC's long term memory for conditions via VitaScriptum. Every flag has 2 values. You can choose what value to compare by changing the start of your condition command.

Format: memory:flagType:flagID:flagValue, E.g. memory:opinion:player:< 50 checks if the creature's opinion on player is below 50.

  • memory - Uses the stored value handle by setFlag or updateFlag
  • memoryTime - Is changed automatically and cannot be changed manually but it can be read. It stores the total play time (since you clicked on "New game") in seconds and it automatically updates to the current total play time anytime its value changes.
  • global - Stores global values that cannot be tied to NPCs themselves.

Flag type and flag ID must match what is in the NPC's memory. If the flag is not there, it will simply not do anything.


Built in flag types:

These flag types behave differently to what are custom made flags capable of.

  • opinion: Stores NPC's opinion on the player. It should be read only. For changes, you should use forceChangeOpinioninstruction instead, E.g. "forceChangeOpinion:30"
  • opinionTimeSinceDecay: Used to store the last time the player visited this NPC to calculate its opinion decay based on it. Should never be changed manually as it's updated by opening dialogue window. To get the time, you should access "last changed" parameter via "memoryTime" command. Its value is always 0.
  • item: This flag is automatically created with ID gaveItem-itemName when the item is spawned by spawnItem instructions.
  • amount: These flags are created automatically with these IDs
    • visits - Tracks the amount of time player visits this NPC
    • petted - Tracks the amount of times this NPC has been petted. Updates with a 60s cooldown
    • goldPlayerGained INACTIVE - Tracks the amount of gold player received from this NPC by trading. Both gold options are adjusted to level gold inflation so selling at level 1 can do as much as selling at level 60
    • goldPlayerSpent INACTIVE - Tracks the amount of gold player spent to this NPC by trading
    • itemPlayerSold INACTIVE - Tracks the amount of items sold to this NPC. This gives every item +1, regardless if it's a potion or a weapon

Triggers

Vivifica can create triggers when used as instructions that listen for a certain action to happen and return back to a dialogue index after.

Syntax: trigger:triggerName:targetIndex:npcID but you can use 3 parameters instruction only (without npcID). Doing so is better in most situations as it automatically uses the ID of the NPC the player is talking to. Using ID manually would

Requirements:

  • There can be only one trigger active at one time.
  • You might want to use "close" instructions on trigger creation if there's something supposed to happen (like a cutscene)

How it works:

  • You create a trigger with trigger:instruction.
  • Vivifica will store the trigger name and wait. (Ideally you close the dialogue as otherwise the game will stay paused)
  • Once any trigger in the game activates that's using the same name as the trigger name in command, it reopens the dialogue window with the same dialogue but on targetIndex specified in instructions.

Usage

  • Useful whenever you need to do something by unpausing the game
All triggers
Trigger When it triggers
trigger:wokeUp:dlgIndexToReopen Reopens dialogue when the talked to NPC wakes up

VitaScriptum instructions

Chronicles of Torisia uses a custom built VitaScriptum scripting language to allow dialogue to trigger actions. There are 2 ways it can do so.

  • On load - These instructions are executed right when the dialogue line starts being written
  • On reply - These instructions are executed when clicking on a reply option. If there's only one reply option (so Vivifica goes to its target index instantly), it executes these instructions the moment the dialogue text disappears.

Syntax:

  • Vivifica can execute unlimited amount of commands but every command must be separated by a semicolon ";".
  • Command parts are split by a colon ":".
  • Instructions are executed from left to right so it's recommended to use any dialogue closing instructions like openTrade as a last instruction.
All VitaScriptum commands
Command Info
showDlgText:dialogueID
  • Info: Reopens dialogue but with text from another dialogue. Can use any ID as long as it's in the database
  • Requirements: It should lead to ID with at least one line without a condition as it will break if it won't pull any lines.
  • Usage: Most commonly used when NPC offers multiple quests - this allows showing a valid text for this quest on trigger.
  • Optional: You can also add a number after the command (showDlgText:dialogueID:index) to target a specific dialogue ID and also a specific index in there
  • You can also use showDlgTextNoQuestCondi in the same format. Doing so will swap all quest based conditions (questState and questObj) to true without checking the condition. This is mostly used to show lore lines so the same line can use a quest condition when showing from NPC actions (no not show) but to still show them in quest dialogue. It automatically replaces all quest based conditions to always return true
  • E.g. showDlgText:mainQuest_0 (shows dialogue for mainQuest_0)
acceptQuest:questID
  • Info: Pulls quest data from database based on entered questID and enters them into "accept quest window", allowing the player to accept a new quest.
  • Requirements: The quest ID must be valid. Conditions leading to this quest are used as a block for accepting quests - if this dialogue is locked behind player's level being under 10, they can't access this dialogue under level 10, thus accept this quest.
  • Usage: Used whenever this NPC should give the player a quest. It should be paired with a reply index - 1 to color all reply options leading to it in yellow.
  • E.g. acceptQuest:mainQuest_0 (Lets player accept quest mainQuest_0).
finishQuest:questID
  • Info: Works the same way as acceptQuest but opens "finish quest window" instead.
  • Requirements: The quest ID must be valid. It also must check if this quest has its objective completed in the condition.
  • Usage: Used whenever when the player is returning a finished quest. It should be paired with a reply index - 1 to color all reply options leading to it in yellow.
  • E.g. finishQuest:mainQuest_0 (Lets player finish quest mainQuest_0).
changeName:name
  • Info: Changes the name currently shown in the dialogue name box
  • Requirements: The name must match existing NPC name in english. It won't break but if done properly, Vivifica will be able to translate the name to other languages.
  • Usage: Most commonly to switch between multiple characters during a quest. Can also be used to potray emotions, this must be done in [] like "Chicken [angry]" to allow translations.
  • E.g. changeName:Chicken [angry] (changes the name in name box to this)
pet
  • Info: Closes dialogue, makes the target walk to your hands and pets it
  • Requirements: None if used manually. It is automatically added to the list of NPC actions but only if the NPC is an animal.
  • Usage: Allows petting the target to make them feel loved and cherished
  • E.g. pet (pets the target)
openTrade
  • Info: Closes dialogue and shows what does the NPC have for sale
  • Requirements: None. The NPC should have at least one item to sell but without that, it can still buy items from the player.
  • Usage: Allows trading with the NPC
  • E.g. openTrade (opens trade window)
openPetBank
  • Info: Closes dialogue and opens the player's pet bank
  • Requirements: None. Pet bank is tied to the UI, NPC is there only to allow opening the window.
  • Usage: Allows the NPC to show you your pet bank
  • E.g. openPetBank (opens pet bank)
openEnchant
  • Info: Closes dialogue and opens the enchanting window
  • Requirements: None. The enchanting window is tied to the UI, NPC is there only to allow opening the window.
  • Usage: Allows the NPC to enchant your items
  • E.g. openEnchant (opens enchanting window)
spawnItem:itemName:amount:location
  • Info: Spawns item based on its name
  • It automatically creates spawnItem:gaveItem-itemName flag that contains total amount of these items spawned as value.
  • Requirements: itemName must be the item's name in english. It cannot spawn enemy souls. Amount parameter can go only up to 99 and works only for stackable items, it does nothing to non-stackable items (equipment).
  • Usage: Used to spawn items based on their name, can also spawn gold using "gold" as the item name. Can be technically used for small trades with takeItem but mostly used for rewards. Location parameter can parse:
    • Direct coordinates - spawnItem:Egg:10:50:70 (spawns at x:50, y: 70)
    • npc - spawnItem:Egg:10:npc (spawns at NPC's location)
    • player - spawnItem:Egg:10:player (spawns at player's location)
  • E.g. spawnItem:Egg:10:player (Spawns 10 eggs at player's location)
changeOpinion:amount
  • Info: Changes the NPC's opinion on the player. Can be added :10 or subtracted :-10
  • Requirements: None. Opinion changes have a 30 seconds cooldown and can range only from -100 to 100 but this is handled internally.
  • Usage: Changes NPC's opinion on player if they do something mean/nice, can be used as a condition for other dialogue.
  • You can also use "forceChangeOpinion" command instead that works in the same way as a regular version but bypasses the opinion cooldown As of now, this is removed. Both changeOpinion and forceChangeOpinion behave exactly the same - ignoring cooldown
  • E.g. changeOpinion:-10 (reduces NPC's opinion on the player by 10)
takeItem:itemName:amount
  • Info: Remove an item from the player's inventory
  • Requirements: Must use "hasItem" condition to check if the player even has this item. Otherwise it will pass the dialogue without removing anything. Works on equipment too (ignores equipped items). Using negative values for amount (-3) will not add the item but break this.
  • Usage: Useful for "mini trades" where the NPC can take a small item (like food) in exchange for something. You can also use "gold" as item name to take the player's gold.
  • E.g. takeItem:Copper ingot:10 (takes 10 copper ingots from the player's inventory)
close
  • Info: Closes the dialogue
  • Requirements: None
  • Usage: Works pretty much like using -1 index but it does not trigger the automatic yellow coloring. Useful if the yellow coloring is used to lead the player to a quest but there is another point where the dialogue must end.
  • E.g. close (closes dialogue)
wakeUp
  • Info: Forces the NPC to wake up
  • Requirements: None but it does nothing if the NPC is not sleeping
  • Usage: Wakes up NPC, used when it's night and the player still wants to talk to the NPC along with negative changeOpinion
  • E.g. wakeUp (wakes NPC up)
hideIf:replyOptionIndex:condition
  • Info: Hides a selected reply option based on the condition. There are no limit for the condition as long as it has a valid syntax.
  • Requirements: You can hide any option you can but you should have at least one always visible. You also shouldn't hide 4 either if this reply option is using the lore index (-2).
  • Usage: Can be used to hide reply options if they're not relevant. Especially useful when a dialogue option must take items away from the player. This can check if player has them and if not, it can just hide the option
  • E.g. hideIf:3:hasItem:gold:<5 (hides reply option number 3 if the player has less than 5 gold)
giveExp:skillType:amount
  • Info: Gives the player a set amount of experience to a selected skill
  • Requirements: None
  • Usage: Useful when the NPC rewards the player for doing something in dialogue (can be used for small trades)
  • E.g. Can be used in 2 ways
    • Directly using the skill gives exp to it (giveExp:offense:50 gives 50 exp to offense)
    • Giving exp to a group (giveExp:professions:50, or combat) gives 50 exp to all skills in the group, spreading it equally
addStatus:statusName:potency:duration
  • Info: Adds a status effect to the player
  • Requirements: This can apply only statuses that enemies can so it cannot be used to apply effects from consumables. However, you can always give that consumable to the player to bypass this.
  • Usage: Maybe someone can get angry and set you on fire, idk xD
    • Dot duration must be in ticks, anything else in seconds
    • Potency determines the damage per tick for dots. It's more complicated for other status effects though, in general if status effect has no other value outside of duration (like stun) potency should be 0. Slow is using it as a percentage of target speed (0.7 = 70% of original speed)
  • E.g. addStatus:Slow:0.7:5 (slows down the player by 30% for 5 seconds)
removeStatus:statusName
  • Info: Removes any status from the player
  • Requirements: None, works on consumables too
  • Usage: Could be useful for RP purposes by clerics removing long term debuffs from the player
  • E.g. removeStatus:Burn (removes 1 stack of burn)
stopTalking
  • Info: Forces two NPCs to stop talking to each other
  • Requirements: None but it's built automatically in NPC actions when NPCs are talking. If used by itself, it does nothing
  • Usage: Works only if used with dialogue ID "default_npcIsYapping"
  • E.g. stopTalking
acceptDelivery
  • Info: Accepts delivery from pigeons
  • Requirements: Works only if the player talks to a pigeon. It should also have something to deliver or it does nothing
  • Usage: Triggering this command makes the bird give all of it items to the player
  • E.g. acceptDelivery
createDelivery:itemName:

itemAmount:dialogueID:gold:exp

  • Info: Queues a pigeon delivery
  • Requirements: None
  • Usage: Due to Vivifica's limitations, this command can deliver only one item. However, you can still achieve the same function by using the spawn command to create the rest of items. dialogueID is the dialogue that the pigeon uses when talking to the player
  • E.g. createDelivery:Bread:1:someOtherDialogue:50:20 (creates a delivery with 1 bread, 50 gold and 20 exp)
addQuestProgress:questType:

objectiveID:amountToAdd:QuestID

  • Info: Adds quest progress
  • Requirements: Player must have the quest accepted, can be checked by condition questState:Accepted:questID
  • Usage: Quest type is used to add progress. The quest system can target only active step so there's no need to check if the current step is correct
  • E.g. addQuestProgress:Obtain:Egg:1:repQuest_0 (adds 1 progress to "obtain egg" objective of repQuest_0)
showHandInOptions:questID
  • Info: Automatically builds options to allow delivery of items in hand in quests
  • Requirements: None
  • Usage: Created automatically, not recommended to call this manually
  • E.g. showHandInOptions:repQuest_0 (builds hand in options for repQuest_0)
addLoreOptions:dialogueID:dialogueIndex
  • Info: Looks at the targeted dialogue ID with its index and adds all of its reply options to the current one
  • Requirements: Must be in instructions on load, adding it in reply instructions can break it
  • Usage: Used to add additional reply options from another dialogue line (like asking for details about some location) while keeping the options centralized and easily usable in any other place again. This command automatically uses showDlgTextNoQuestCondi which also ignores all quest conditions
  • E.g. addLoreOptions:someDialogueID:5
returnNode
  • Info: When these instructions execute, Vivifica saves the current dialogue ID and index
  • Requirements: None but only one line can be saved. Using returnNode again later simply overwrites it
  • Usage: Used to save the current dialogue ID and index. When the player later hits something targeting index -2, Vivifica automatically moves back to the saved dialogue line. Commonly used to return to the main branch from branching dialogue
  • E.g. returnNode
tempValue
  • Info: Used if you need to create and track any value. It's automatically set to 0 when the dialogue closes
  • Requirements: None
  • Usage: Used with additional commands to change the value
    • add - adds a value to the current value
    • deduct - deducts a value from the current value
    • set - sets the value
  • It can later be used to replace {tempValue} in dialogue
  • E.g. tempValue:add:50 (adds 50 to the temp value)
blockClose
  • Info: The player won't be able to close the dialogue window on any line using this command
  • Requirements: Must be in instructions on load, it won't work if it's in reply instructions
speechBubble:trigger:speechBubbleRowID
  • Info: Creates a trigger to automatically show a speech bubble when activated
  • Requirements: Must use a valid row ID and trigger:
    • goToBed - triggers when the NPC enters the bed
  • Usage: It's using the NPC you're currently talk to. Once this NPC activates the correct trigger, they will say the speech bubble at the set rowID (from speech bubbles table)
  • E.g. speechBubble:goToBed:5 (When the NPC enters the bed, they show a speech bubble with the text with row ID 5)
reportCrimes NPC reports its unreported crimes to the reputation faction they belong to. Can be used anywhere, though it doesn't make much sense outside of talking to a guard
stopArrest Wipes the player's crimes in what reputation faction does the NPC belong to. Most commonly used when player convinces guards to stop attacking
hostileArrest Gives NPC (guard) aggro towards the player to start attacking them. Most commonly used when the player resist an arrest
jailPlayer Moves player to jail. Most commonly used when player agrees with this when caught for committing crimes.
punishPlayer Applies all punishments to player based on their crimes. Used for punishing for the crimes that do not require going to jail
addCrime:crimeType Attempts to add crime report to the NPC that the player is currently talking to. The crime still must not be on a cooldown and the NPC has to report it first.
investInGold Invests in merchant's gold capacity. Is done automatically via lines in default_investingGold.
investInProfitShare Invests in profit share with the merchant. Is done automatically via lines in default_investingProfitShare.
openInvestmentOptions Opens investment options for this merchant.

Conditions

Conditions are used to filter dialogue lines. If a condition does not return true, the entire dialogue row is ignored. VitaScriptum also supports complex conditions and unlike with instructions, you shouldn't use semicolon ";" between conditions but operators instead.

VitaScriptum supports:

  • | as an "OR" symbol
  • & as an "AND" symbol

You must use one of these symbols between every 2 conditions. VitaScriptum always prioritizes & symbol first.

Conditions examples:
Condition Result Explanation
true&true true With & symbol, all conditions must be true
true&false false With & symbol, all conditions must be true
true|true true With | symbol, at least one condition must be true
true|false true With | symbol, at least one condition must be true
false|false false With | symbol, at least one condition must be true
false|false&true false false&true return false so neither | symbol sides return true
true|false&true true false&true return false but there is at least one | side returning true
false|true&true true true&true return true so there is at least one | side returning true

Negation

Some conditions allow you to use the ! prefix to invert their value. These are:

  • status
  • inCombat
  • hasItem
  • questState
  • weather

While status:burn returns true only if the player is currently burning, using status:!burn returns true only if the player is NOT burning.

Value comparissons

VitaScriptum supports comparing numerical values. Most commonly for flags but it works with regular commands too, like hasItem. To use it, simply add a symbol before the numeric value. E.g.: hasItem:Apple:<5 returns true if the player has less than 5 apples in their inventory.

Supported symbols are:

  • < Returns true if the in game value is lower
  • > Returns true if the in game value is higher
  • >= Returns true if the in game value is higher or the same
  • <= Returns true if the in game value is lower or the same
  • == Returns true if the in game value is the same

Special prefixes

Value comparissons can also handle prefixes to do simple math actions. To use this prefix, it should be in front of the comparisson symbols (E.g. cd<5).

  • cd - This prefix for cooldown is very useful for comparing any time values (often used with memoryTime flag). Also works to check global flags (global: or globalTime:)
    • memoryTime:item:gaveItem-Egg:<50 - This returns true if the time stored in this flag is under 50 seconds so it triggers only as long as it's been under 50 seconds since starting the current playthrough.
    • memoryTime:item:gaveItem-Egg:cd<50 - This uses time difference as a value to compare so it returns true only if it's been under 50 seconds since the flag got updated (as Vivifica always updates the time when updating flags).


Commands

There are all commands that can be used by the conditional system. You can also use memory: to access NPC's flags.

All conditions readable by Vivifica
Command Info
questState:state:questID
  • Info: Returns true if the quest ID matches the condition
  • Requirements: Required to use for quest related dialogue lines to separate them from other quests. Also used to create conditions to hide dialogues leading to allowing player to accept quests, essentially locking the quest behind the same condition
  • Usage: Returns true if the quest state matches the condition or if it does not match the condition but you use ! before the state (like !accepted)
    • none (quest not even accepted)
    • accepted (quest accepted)
    • objectiveDone (finished, can be turned in)
    • turnedIn (finished and received reward)
    • You can use unlimited amount of quest IDs to check in one condition. E. g. questState:turnedIn :mainQuest_0:mainQuest_1:mainQuest_2 returns true only if all 3 quests have been turned in.
  • This condition works only when the quest is exactly at the set state (accepted doesn't return true if the quest is turned in). For this situation, you have to add + after the state (E.g. accepted+). This works only with 2 states
    • accepted+ (returns true if the quest is accepted, done or turned in
    • objectiveDone+ (returns true if the quest is done or turned in)
  • E.g. questState:objectiveDone:mainQuest_0 (checks if the objective mainQuest_0 has been finished - useful for returning finished quests)
questObj:state:rowID
  • Info: Returns true if the rowID (from quest database) matches the condition
  • Requirements: Required to use for quest related dialogue lines to separate them from other quests. Also used to create conditions to hide dialogues leading to allowing player to accept quests, essentially locking the quest behind the same condition
  • Usage: Returns true if the quest state matches the condition or if it does not match the condition but you use ! before the state (like !accepted)
    • none (quest not even accepted)
    • accepted (quest accepted)
    • objectiveDone (finished, can be turned in)
    • turnedIn (finished and received reward)
    • You can use unlimited amount of quest IDs to check in one condition. E. g. questState:turnedIn :1:2:3 returns true only if all 3 quest objectives have been turned in.
  • This condition works only when the quest is exactly at the set state (accepted doesn't return true if the quest is turned in). For this situation, you have to add + after the state (E.g. accepted+). This works only with 2 states
    • accepted+ (returns true if the objective is accepted, done or turned in
    • objectiveDone+ (returns true if the objective is done or turned in)
  • E.g. questObj:objectiveDone:1(checks if the objective 1 has been finished)
status:statusName
  • Info: Checks if the player has a certain status effect active
  • Requirements: None
  • Usage: status:burn returns true if the player is on fire. It can also be reverted with status:!burn and it support unlimited amount of status effects. status:!bleed:!burn returns true only if the player is not bleeding and not burning
  • E.g. status:burn (returns true if the player is on fire)
inCombat
  • Info: Returns true if the player is in combat with at least 1 enemy. It does NOT check general combat (showing the symbol at hitpoints bar) that can be activated even without enemies, e.g. by activating a rift
  • Requirements: None
  • Usage: Returns true if the player is in combat, can use !inCombat to return true only if the player is not in combat
  • E.g. inCombat (returns true if the player is in combat)
hasItem
  • Info: Compares the amount of some item the player has
  • Requirements: Must use item's name in english. Does not work with enemy souls.
  • Usage: Can also use "gold" as name to check the amount of gold. Must be used before takeItem to validate if it can remove them.
  • E.g. hasItem:Egg:>20 (returns true if the player has over 20 eggs)
level
  • Info: Compares the player's level
  • Requirements: None
  • Usage: Useful for level gating dialogue (especially quests)
  • E.g. level:<20 (returns true if the player's level is under 20)
weather:weatherType
  • Info: Compares the current weather
  • Requirements: None
  • Usage: Useful for lines that have to be conditioned by weather, can be negated (weather:!rain returns true only when it's not raining). Allowed weather variants are: clear, cloudy, rain, windy, snow, thunderstorm
  • E.g. weather:!cloudy (returns true when it's not cloudy)
repSource
  • Info: Checks what reputation is an NPC tied to. Unless there is an override (like fishing guild), this often matches the settlement the NPC is in (like Magdora)
  • Requirements: None
  • Usage: Most commonly used for rummors or in speech bubbles where NPCs talk to each other about some other nearby place as it would make no sense for NPCs to talk about a cave that's on the other end of Torisia. Can be negated.
  • E.g. repSource:!Magdora (returns true when the NPC does not belong to Magdora
hasPetOut Returns true if the player has a pet active
timePeriod:time
  • Info: Checks if the current time period matches the one in the condition
  • Requirements: None
  • Usage: Can be used to gate time specific dialogue (like night only). Can take the following time options (can also be negated):
    • Morning - Lasts from 7:00 to 11:00
    • Midday - Lasts from 11:00 to 15:00 (3 PM)
    • Afternoon - Lasts from 15:00 (3 PM) to 19:00 (7 PM)
    • Evening - Lasts from 19:00 (7 PM) to 23:00 (11 PM)
    • NIght - Lasts from 23:00 (11 PM) to 7:00
  • E.g. timePeriod:!morning (returns true when the current time period is not morning)

Randomization and priority

You can use multiple dialogue lines with the same ID and index. Vivifica automatically finds the highest possible priority with a valid condition and picks any other lines with the same priority, index and a valid condition. Vivifica then randomly picks between these.

E.g. If there are 2 lines with the same priority, index, ID and valid (doesn't have to be the same but it must be true) condition, Vivifica will have 50% to show either line.

Text formatting

You can write certain commands directly into the dialogue or reply text and Vivifica will convert them by using in game values.

Formatting commands
Command Info
{playerName} Converts to player's name
{dayNightPhase} Converts to the current time of the day (morning, midday, afternoon,evening,night)
{enemyInCombat} If in combat, converts into a random enemy's in combat name
{readDlg:npcOrQuestID} Finds text in npcOrQuestID and replaces the current text with it
{talkingToNPC} Converts to the name of NPC this NPC is currently talking to
{specialTargetName} Speech bubbles only. Converts to current special target (most commonly used for NPCs picking up items)
{tempValue} Converts to the current temp value. This value can be changed with instructions

Coloring

Vivifica supports multiple colors to write the reply text with.

  • Green - Automatically used by services, E.g. enchanting window
  • White - Used by unread lines
  • Gray - Used by read lines. Vivifica tracks these automatically. It also ignores all lines starting with ID "default_" or "global_"
  • Orange - Automatically colors options that are currently visible and use either index -1 or -2
  • Yellow - Used to mark quests. Vivifica automatically colors all replies that lead to any reply option with "acceptQuest" or "finishQuest" instructions to make it easier to see what text is actually important. To prevent everything from being yellow, Vivifica colors only a path that leads to higher indexes. E.g. going from index 1000 to 2000 and eventually leading to "acceptQuest" turns it yellow but a detour from 1000 to 900 before going back to 1000 stays white. This must be done only at the start so all the next indexes can keep going up, as long as there's a lower one blocking the path

However, it's also possible to manually force a reply option to be of a set color. This can be done by adding a command to the reply option's instructions

  • colorContinue - Yellow
  • colorService - Green
  • colorExit - Orange
  • colorUnread - White

ID

Vivifica can differentiate between specific IDs and NPC groups. This can be done simply by changing the ID in database.

  • Direct NPC ID - Simply reads the NPC ID
  • Group ID - NPCs can have a group assigned to them. If they do, they will try to get both dialogue types, individual and a group. Group ID can be used to assign the same lines to a group of NPCs (like all chickens).