1,046
edits
(→Building the message: tweaks) |
(demonstrate root element) |
||
(37 intermediate revisions by 10 users not shown) | |||
Line 1: | Line 1: | ||
{{Modding Info}} | |||
Conversations are trees of XML loaded from <code>Conversations.xml</code> and usually executed from a <code>ConversationScript</code> part on a game object. | |||
The most common elements are the Node and the Choice: a node is a piece of text spoken by the creature you're interacting with, coupled with a list of choices for the player to respond with. | |||
This usually takes you to another node where the cycle repeats. | |||
For extensive conversation design in mods that use a lot of conversations, some modders have recommended using a tool such as [https://twinery.org/ Twine] to map out your conversation logic. | |||
== Conversation | == Adding a Conversation == | ||
In order to be conversable, an object should have a <code>ConversationScript</code> part and define a <code>ConversationID</code> which references a conversation template of the same <code>ID</code> in Conversations.xml. | |||
A barebones definition might look like this for a lovely snapjaw. | |||
<syntaxhighlight lang="xml"> | <syntaxhighlight lang="xml"> | ||
<object Name=" | <!-- ObjectBlueprints.xml--> | ||
<part Name="ConversationScript" ConversationID=" | <objects> | ||
<object Name="Snapjaw Pal" Inherits="Snapjaw"> | |||
<part Name="ConversationScript" ConversationID="FriendlySnapjaw" /> | |||
</object> | </object> | ||
</objects> | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=== | <syntaxhighlight lang="xml"> | ||
<!-- Conversations.xml--> | |||
<conversations> | |||
<conversation ID="FriendlySnapjaw"> | |||
<start ID="Welcome"> | |||
<text>ehekehe. gn. welcom.</text> | |||
<choice Target="LibDink">Thank you.</choice> | |||
</start> | |||
<node ID="LibDink"> | |||
<text>hrffff... lib? dink?</text> | |||
<text>nyeh. heh! friemd?</text> | |||
<choice Target="End">Live and drink.</choice> | |||
</node> | |||
</conversation> | |||
</conversations> | |||
</syntaxhighlight> | |||
(Note that the outer <code>conversations</code> tag is required.) | |||
=== XML Tags === | |||
These are the basic tags supported by conversations, not including any custom elements used by parts. | |||
{| class="wikitable" | |||
! XML Tag | |||
! Description | |||
|- | |||
| <code><nowiki><conversation></nowiki></code> | |||
| Single conversation template typically containing <code><nowiki><node></nowiki></code> and <code><nowiki><start></nowiki></code> elements, linked to a <code>ConversationScript</code> via its <code>ID</code>. | |||
|- | |||
| <code><nowiki><node></nowiki></code> | |||
| Collection of <code><nowiki><text></nowiki></code> from the Speaker's point of view, along with a range of <code><nowiki><choice></nowiki></code> for the Player to respond with. | |||
|- | |||
| <code><nowiki><start></nowiki></code> | |||
| Special variant of <code><nowiki><node></nowiki></code> that can be selected when starting a conversation. <br />For backwards compatibility, a <code><nowiki><node></nowiki></code> with an ID of "Start" will behave similarly. | |||
|- | |||
| <code><nowiki><choice></nowiki></code> | |||
| Collection of <code><nowiki><text></nowiki></code> from the Player's point of view, commonly defines a <code>Target</code> <code><nowiki><node></nowiki></code> to navigate to if selected. <br />The <code>Target</code> attribute has two special values: <code>Start</code> and <code>End</code>, which will return to the beginning of the conversation or end it, respectively. <br />For backwards compatibility, the <code>GotoID</code> attribute will behave similarly to <code>Target</code>. | |||
|- | |||
| <code><nowiki><text></nowiki></code> | |||
| Contains a block of text to display for an element, multiple of these can be defined and randomly selected from if valid. <br/>Additional text nodes can be recursively defined within other text nodes, allowing groups of text to use the same conditions. <br />For backwards compatibility, delimiting the text with <code>~</code> characters will behave similarly to multiple text nodes. | |||
|- | |||
| <code><nowiki><part></nowiki></code> | |||
| Reference to a C# class that inherits from <code>IConversationPart</code>. <br />Any attributes defined here will be inserted into the fields & properties of the part, if possible. <br />Anything defined as a child element of the part can be loaded with custom C# behavior. | |||
|- | |||
|} | |||
=== Merging === | |||
If multiple elements with the same <code>ID</code> are defined within the same scope, a merge will occur by default where the properties of the later element overwrite the former.<br /> | |||
If an explicit ID isn't defined, one will be created based on other attributes.<br/> | |||
You can alter the conflict behavior of an element by setting a <code>Load</code> attribute with valid values of: "Merge", "Replace", "Add", or "Remove". | |||
<syntaxhighlight lang="xml"> | |||
<conversation ID="FriendlySnapjaw"> | |||
<node ID="SnappyNoise"> | |||
<text>gnnnnnnn.</text> <!-- ID is "Text" --> | |||
<text>beh. mmmf.</text> <!-- ID is "Text2" --> | |||
<text>mmnnn!</text> <!-- ID is "Text3" --> | |||
<choice Target="LibDink">Thank you.</choice> <!-- ID is "LibDinkChoice" --> | |||
</node> | |||
</conversation> | |||
<conversation ID="FriendlySnapjaw"> <!-- Will merge with above conversation --> | |||
<node ID="SnappyNoise"> <!-- Will merge with "SnappyNoise" node --> | |||
<text>gra! gra! gra!</text> <!-- ID is "Text" and will merge --> | |||
<text Cardinal="3">gra! gra! gra!</text> <!-- ID is "Text3" and will merge --> | |||
<choice Target="End">Live and drink.</choice> <!-- ID is "EndChoice" and will not merge --> | |||
</node> | |||
</conversation> | |||
</syntaxhighlight> | |||
=== Inheritance === | |||
In cases where you'd like your elements to appear in multiple places, you can inherit their properties with the <code>Inherits</code> attribute.<br /> | |||
By default, every conversation inherits from <code>BaseConversation</code>, which holds the definitions of common elements to all conversations like trade and the water ritual.<br /> | |||
The attribute can also take a comma separated list, meaning you can inherit and merge the properties of multiple parent elements together.<br /> | |||
Unlike merging, the properties of the current element have precedence over those it is inheriting from. | |||
<syntaxhighlight lang="xml"> | |||
<conversation ID="FriendlySnapjaw"> | |||
<start ID="SnappyNoise"> | |||
<text>gnnnnnnn.</text> | |||
<choice Target="LibDink">Thank you.</choice> | |||
</start> | |||
</conversation> | |||
=== | <conversation ID="ExcitedSnapjaw" Inherits="FriendlySnapjaw"> <!-- Inherits SnappyNoise --> | ||
<node ID="SnappyBye"> | |||
<text>gra! gra! gra!</text> | |||
<choice Target="End">Live and drink.</choice> | |||
</node> | |||
</conversation> | |||
== | <conversation ID="AngryArconaut"> | ||
<start ID="Grumpy"> | |||
<text>I hate things.</text> | |||
<choice Inherits="ExcitedSnapjaw.SnappyBye.EndChoice" /> <!-- Inherits "Live and drink." --> | |||
</start> | |||
</conversation> | |||
</syntaxhighlight> | |||
=== | === Distribution === | ||
An alternative to explicitly inheriting elements where you'd like them repeated is distribution, where you specify directly on the element where it should propagate.<br/> | |||
The <code>Distribute</code> attribute normally takes a list of element types, but if <code>Qualifier="ID"</code> is specified, a list of IDs can be provided.<br/> | |||
Choices that are defined as children under a conversation will propagate to all start nodes by default. | |||
<syntaxhighlight lang="xml"> | |||
<conversation ID="FriendlySnapjaw"> | |||
<start ID="SnappyHello"> | |||
<text>heeeelo!</text> | |||
</start> | |||
<start ID="SnappyNoise"> | |||
<text>gnnnnnnn.</text> | |||
</start> | |||
<choice Target="End">Live and drink.</choice> <!-- Added to both start nodes --> | |||
<choice GiveItem="Dagger" Distribute="SnappyNoise" Qualifier="ID">It is time to grill cheese.</choice> | |||
</conversation> | |||
</syntaxhighlight> | |||
=== | == Delegates == | ||
Unique to conversations are their delegate attributes such as <code>IfHaveQuest="What's Eating the Watervine?"</code> or <code>GiveItem="Joppa Recoiler"</code>.<br/> | |||
These are distinguished between two types: Predicates which control whether an element is accessible, and Actions which perform some task when the element is selected.<br/> | |||
After the Deep Jungle update these are now for the most part agnostic as to what their parent element is. | |||
<syntaxhighlight lang="xml"> | |||
<conversation ID="FriendlySnapjaw"> | |||
<start ID="FurFriend" IfHavePart="ThickFur"> <!-- Hidden if player doesn't have thick fur --> | |||
<text>ooohh. pretty...</text> | |||
<text IfReputationAtLeast="Loved">deheh. like you. hohohoho.</text> <!-- Hidden if not Loved by speaker's faction --> | |||
<choice Target="End" IfReputationAtLeast="Loved" GiveItem="Dagger">I like you too.</choice> <!-- Gives the player a dagger if selected--> | |||
<choice Target="End">Thank you.</choice> | |||
</start> | |||
</conversation> | |||
</syntaxhighlight> | |||
=== | === Custom Delegates === | ||
It's possible to add your own delegates for you to use in XML by adding a <code>[ConversationDelegate]</code> attribute to a static method in C#.<br/> | |||
Depending on the return type it will either be registered as a predicate (bool) or action (void), and variants of the delegate will automatically be created. | |||
For example the below delegate will automatically create the inversion <code>IfNotHaveItem</code>, and because we set the <code>Speaker</code> attribute parameter, another two (<code>IfSpeakerHaveItem</code>, <code>IfSpeakerNotHaveItem</code>) where <code>Context.Target</code> holds the Speaker instead of the Player. | |||
<syntaxhighlight lang="C#"> | |||
[HasConversationDelegate] // This is required on the surrounding class to reduce the search complexity. | |||
public static class DelegateContainer | |||
{ | |||
// A predicate that receives a DelegateContext object with our values assigned, this to protect mods from signature breaks. | |||
[ConversationDelegate(Speaker = true)] | |||
public static bool IfHaveItem(DelegateContext Context) | |||
{ | |||
// Context.Value holds the quoted value from the XML attribute. | |||
// Context.Target holds the game object. | |||
// Context.Element holds the parent element. | |||
return Context.Target.HasObjectInInventory(Context.Value); | |||
} | |||
} | |||
</syntaxhighlight> | |||
=== | == Parts == | ||
For more advanced or specific logic not easily reduced to a generally accessible delegate, a custom part is preferred.<br/> | |||
Similar to their equivalent for objects in <code>ObjectBlueprints.xml</code>, parts define custom behaviour for elements within and can be attached to most any element just like delegates. | |||
==== | If you use a period within the part's name, it's assumed you are specifying your own namespace and won't be required to place your part within <code>XRL.World.Conversations.Parts</code>. You can optionally declare a <code>Namespace</code> on the root <code><nowiki><conversations></nowiki></code> element, and concatenated sub-namespaces on each <code><nowiki><conversation></nowiki></code>. It will try to find your part within those first before falling back to the default namespace. | ||
<syntaxhighlight lang="xml"> | |||
<conversation ID="JoppaZealot"> | |||
<part Name="SpiceContext" /> | |||
<start ID="OrphanOfTheSalt"> | |||
<text> | |||
Blah! Orphan of the salt! Blooh! | |||
<part Name="TextInsert" Spoken="false" NewLines="2" Text="[Press Tab or T to open trade]" /> | |||
</text> | |||
<choice Target="End"> | |||
<text>You intrigue me. I will go to the Six Day Stilt for no particular reason.</text> | |||
<part Name="QuestHandler" QuestID="O Glorious Shekhinah!" Action="Start" /> | |||
</choice> | |||
</start> | |||
</conversation> | |||
</syntaxhighlight> | |||
A very basic C# implementation of a part that adds a laugh to any text it's added to might look like this. | |||
<syntaxhighlight lang="C#"> | |||
public class SnapjawLaugh : IConversationPart | |||
{ | |||
public override bool WantEvent(int ID, int Propagation) | |||
{ | |||
return base.WantEvent(ID, Propagation) | |||
|| ID == PrepareTextEvent.ID | |||
; | |||
} | |||
public override bool HandleEvent(PrepareTextEvent E) | |||
{ | |||
E.Text.Append("\n\nehehehehe!"); | |||
return base.HandleEvent(E); | |||
} | |||
} | |||
</syntaxhighlight> | |||
=== | === Events === | ||
Conversations have their own set of events to handle, but should be immediately familiar to anyone that has tampered with the [[Modding:Events#Minimal_Events|Minimal Events]] of game objects. | |||
Unlike min events which cascade down, conversation events will propagate up the element tree from where it was fired (See [https://en.wikipedia.org/wiki/Event_bubbling event bubbling]). This means an event fired on a choice will first be handled by parts on the choice itself, then its parent node, last the node's conversation. | |||
Finally the propagation is separated by perspective, Speaker and Listener (the listener being you, the player). In most cases when you attach a part that modifies the text of a node, you do not want to also modify the text of its underlying choices since those are spoken by a different entity. By default parts will register for the perspective they are placed in, but can be overriden with the <code>Register</code> attribute. | |||
<syntaxhighlight lang="xml"> | |||
<conversation ID="EventfulSnapjaw"> | |||
<part Name="SpiceContext" Register="All" /> <!-- Registers for Speaker events by default, but overrides with both --> | |||
<start ID="TasterOfTheSalt"> | |||
<part Name="SnapjawLaugh" /> <!-- Registers for Speaker events --> | |||
<text>mmmg. salt.</text> | |||
<text>tasty.</text> | |||
<choice Target="End"> | |||
<text>Salt responsibly, friend.</text> | |||
<part Name="ReceiveItem" Blueprints="EmptyWaterskin" /> <!-- Registers for Listener events --> | |||
</choice> | |||
</start> | |||
</conversation> | |||
</syntaxhighlight> | |||
==== | ==Tables== | ||
Below are non-exhaustive tables of existing parts, events, delegates, and additional XML attributes. | |||
=== | ===Parts=== | ||
Described with their function, parameters and an example where applicable. | |||
{| class="wikitable" | |||
|- | |||
! Name | |||
! Description | |||
== | |- | ||
This | | AddSlynthCandidate | ||
| Adds the current location as a possible sanctuary for the slynth during the quest [[Landing Pads]]. | |||
==== | ---- | ||
'''Sanctuary''': Optional explicit sanctuary name to use instead of zone name.<br/> | |||
'''Plural''': Whether the explicit sanctuary name is plural. | |||
---- | |||
==== | <code><nowiki><part Name="AddSlynthCandidate" Location="pariah caravans" Plural="true" /></nowiki></code> | ||
|- | |||
| ChangeTarget | |||
| Takes any number of predicates as parameters and changes the navigation target (GetTargetElementEvent) if all predicates match. | |||
== | ---- | ||
'''Target''': The alternate navigation target if predicates match.<br/> | |||
'''Any''': Require one predicate to match rather than all. | |||
---- | |||
=== | <code><nowiki><part Name="ChangeTarget" Target="ShowSonnet" IfHaveBlueprint="Sonnet" /></nowiki></code> | ||
|- | |||
| GiveArtifact | |||
| Make the player give an artifact from their inventory to continue navigation. | |||
|- | |||
| GiveReshephSecret | |||
| Share a secret from Resheph's life to gain some XP. | |||
|- | |||
| IPredicatePart | |||
| An extensible abstract part that takes predicates as parameters and can check all or any for a match. ChangeTarget derives from this, for example. | |||
|- | |||
| LibrarianGiveBook | |||
| Donate a book to the librarian to gain some XP. | |||
|- | |||
| PaxInfectLimb | |||
| Choose a limb to infect with Klanq. | |||
---- | |||
'''IfQuestActive''': Only display this element if the quest is active and the player has no infected limb. | |||
---- | |||
<code><nowiki><part Name="PaxInfectLimb" IfQuestActive="true" /></nowiki></code> | |||
|- | |||
| QuestHandler | |||
| Manipulates quest and step state. If a child text is provided it will replace the normal ending tag for that action, e.g. <code>[Accept Quest]</code>. | |||
---- | |||
'''QuestID''': The quest's ID, usually the same as its display name.<br/> | |||
'''StepID''': The ID of a step within the quest, if applicable.<br/> | |||
'''XP''': The XP awarded for completing the step, if applicable. This will override the value in Quests.xml if provided.<br/> | |||
'''Action''': Takes a string value of an action to perform on the quest and/or step; | |||
: '''Start''': Find an unstarted quest with QuestID and start it. | |||
: '''Step''': Complete a step within the quest, finishes the parent quest if all steps are completed. | |||
: '''Finish''': Finish a started quest, regardless of what steps are currently completed. | |||
: '''Complete''': Finish a started quest and mark all steps as complete if they weren't already. | |||
---- | |||
<code><nowiki><part Name="QuestHandler" Action="Step" QuestID="Fetch Argyve a Knickknack" StepID="Return to Argyve" XP="75" /></nowiki></code> | |||
|- | |||
| ReceiveItem | |||
| The player receives one or several potentially identified items. | |||
---- | |||
'''Blueprints''': A comma separated list of blueprints for the player to receive.<br/> | |||
'''Identify''': A comma separated list of blueprints to identify, of those given. "*" or "All" can be specified to identify all of them.<br/> | |||
'''Mods''': A dice roll of how many mods to apply to the received items.<br/> | |||
'''Pick''': Makes the player choose one item of those allotted, instead of receiving all of them.<br/> | |||
'''FromSpeaker''': Takes an existing item of the same blueprint from the speaker if available, instead of creating new ones. | |||
---- | |||
<code><nowiki><part Name="ReceiveItem" Pick="true" Mods="1" Blueprints="Long Sword4,Cudgel4,Dagger4,Battle Axe4" Identify="All" /></nowiki></code> | |||
|- | |||
| RequireReputation | |||
| Require the player's reputation with a specific faction to be at or above a certain level to continue. If the parent element is a choice, its text will be greyed out. | |||
---- | |||
'''Faction''': The ID of a faction within the current game.<br/> | |||
'''Level''': The name of a reputation level, valid values are: Loved, Liked, Indifferent, Disliked, and Hated. | |||
---- | |||
<code><nowiki><part Name="RequireReputation" Faction="Snapjaws" Level="Loved" /></nowiki></code> | |||
|- | |||
| SpiceContext | |||
| Replaces template variables in the spoken text with excerpts from history spice, e.g. replacing <code>=spice.commonPhrases.sacred.!random=</code> with <code>sanctified</code>. | |||
|- | |||
| Tag | |||
| Adds an ending tag to the parent element's text. Most parts with functionality will handle their own tags via <code>GetChoiceTagEvent</code>, this is mostly for informational purposes.<br/> | |||
The game makes a distinction between spoken and unspoken text for the purposes of filtering (e.g. the cawing of corvids), hence why unspoken tags should not be written together with the spoken text. | |||
---- | |||
<code><nowiki><part Name="Tag">{{g|[begin trade]}}</part></nowiki></code> | |||
|- | |||
| TakeItem | |||
| Items are taken from the player's inventory or body. | |||
---- | |||
'''Blueprints''': A comma separated list of blueprints to take.<br/> | |||
'''IDs''': A comma separated list of game object IDs to take.<br/> | |||
'''Amount''': A dice roll of how many items to take. "*" or "All" can be specified to take all of them.<br/> | |||
'''Unsellable''': Mark the taken items as unsellable.<br/> | |||
'''ClearQuest''': Clear quest properties from the taken items.<br/> | |||
'''Destroy''': Destroy the items instead of placing them inside the speakers inventory. | |||
---- | |||
<code><nowiki><part Name="TakeItem" Blueprints="Wire Strand" Amount="200" Destroy="true" /></nowiki></code> | |||
|- | |||
| TextFilter | |||
| Mutates the spoken text with a filter, e.g. the cawing of corvids or croaking of frogs. | |||
---- | |||
'''FilterID''': The ID of a filter, valid values are: Angry, Corvid, WaterBird, Fish, Frog, Leet, Lallated, Weird, and Cryptic Machine.<br/> | |||
'''Extras''': A comma separated list of additional noises to include in the filter, used in the Lallated and Weird filters currently.<br/> | |||
'''ProtectFormatting''': Outputs color protected text, currently used for Leet ampersands which are doubled to preserve them. | |||
---- | |||
<code><nowiki><part Name="TextFilter" FilterID="Lallated" Extras="*growl*,*whine*" /></nowiki></code> | |||
|- | |||
| TextInsert | |||
| Appends or prepends a text that can be either spoken or unspoken to the element. | |||
---- | |||
'''Prepend''': Add the text to the beginning instead of the end.<br/> | |||
'''Spoken''': Whether the inserted text is treated as spoken or unspoken for the purposes of filtering.<br/> | |||
'''NewLines''': A number of new lines to add as padding between the inserted text and the existing text. | |||
---- | |||
<code><nowiki><part Name="TextInsert" Spoken="false" NewLines="2">[Press Tab or T to open trade]</part></nowiki></code> | |||
|- | |||
| Trade | |||
| Opens the trade screen when navigating to the parent element. | |||
|- | |||
| VillageContext | |||
| Replaces template variables in the spoken text with excerpts from the village's history, e.g. replacing <code>=village.sacred=</code> with <code>the act of procreation</code>.<br/> | |||
Uses the faction of the speaker to find the village's historical context. | |||
---- | |||
'''GameState''': Try to get the village's historical context from the faction provided in specified game state. | |||
---- | |||
<code><nowiki><part Name="VillageContext" GameState="SlynthSettlementFaction" /></nowiki></code> | |||
|- | |- | ||
| WaterRitualRandomMutation | |||
| Purchase a random mutation of specified category for reputation in the water ritual. | |||
---- | |||
'''Category''': A mutation category, valid values for the base game are: Physical, Mental. | |||
---- | |||
<code><nowiki><part Name="WaterRitualRandomMutation" Category="Physical">You gain =mutation.name=.</part></nowiki></code> | |||
|} | |} | ||
===Events=== | |||
Conversation | Source notes the deepest element that you can expect the event to propagate from. In order, the values are Conversation -> Node -> Choice -> Text.<br/> | ||
Order notation is very approximate, as the same event will be fired multiple times on different elements during a navigation. | |||
{| class="wikitable" | |||
|- | |||
! Name | |||
! Source | |||
! Description | |||
! Order | |||
|- | |||
| IsElementVisibleEvent | |||
| Text | |||
| Fired when determining whether an element is possibly available for rendering and selection, after any predicates defined on the element. | |||
| Before: GetTextElementEvent, After: EnteredElementEvent | |||
|- | |||
| GetTextElementEvent | |||
| Text | |||
| Fired when choosing a text element for preparation and can control the chosen text. | |||
| Before: PrepareTextEvent, After: IsElementVisibleEvent | |||
|- | |||
| PrepareTextEvent | |||
| Text | |||
| Fired when preparing spoken text for display after a node has been entered.<br/> | |||
This precedes the standard variable replacements like =subject.name= and allows setting a new Subject and Object. | |||
| Before: DisplayTextEvent, After: GetTextElementEvent | |||
|- | |||
| DisplayTextEvent | |||
| Choice | |||
| Fired before displaying the prepared text to screen.<br/> | |||
This is where you will typically add unspoken text like tooltips or other metagame information. | |||
| Before: ColorTextEvent, After: PrepareTextEvent | |||
|- | |||
| ColorTextEvent | |||
| Choice | |||
| Fired when coloring the display text of an element. | |||
| With: DisplayTextEvent | |||
|- | |||
| GetChoiceTagEvent | |||
| Choice | |||
| Fired when selecting an ending tag to apply to the display text such as [begin trade]. | |||
| With: DisplayTextEvent | |||
|- | |||
| EnteredElementEvent | |||
| Choice | |||
| Fired after an element has successfully been entered. | |||
| Before: PrepareTextEvent, After: EnterElementEvent | |||
|- | |||
| EnterElementEvent | |||
| Choice | |||
| Fired as an element is being entered and can prevent navigation. | |||
| Before: EnteredElementEvent, After: LeaveElementEvent | |||
|- | |||
| GetTargetElementEvent | |||
| Choice | |||
| Fired after leaving the current node and can control the navigation target. | |||
| Before: EnterElementEvent, After: LeaveElementEvent | |||
|- | |||
| LeaveElementEvent | |||
| Node | |||
| Fired as an element is being left and can prevent navigation. | |||
| Before: GetTargetElementEvent, After: GetDisplayTextEvent | |||
|- | |||
| LeftElementEvent | |||
| Node | |||
| Fired after an element has successfully been exited. | |||
| Before: EnteredElementEvent, After: GetTargetElementEvent | |||
|- | |||
| HideElementEvent | |||
| Choice | |||
| Fired when evaluating elements to display that are hidden by special outside conditions.<br/> | |||
One such condition is the last choice selected that will be hidden if navigation was successful but did not leave the current node. | |||
| Before: PrepareTextEvent, After: IsElementVisibleEvent | |||
|- | |- | ||
| PredicateEvent | |||
| Text | |||
| Fired by the <code>IfCommand</code> predicate and controls visibility similarly to IsElementVisibleEvent. | |||
| Before: IsElementVisibleEvent, After: EnteredElementEvent | |||
| | |||
| | |||
|} | |} | ||
=== | ===Delegates=== | ||
{| class=" | An Inverse predicate can be invoked with <code>IfNot</code> to negate its value.<br /> | ||
A Speaker delegate can be invoked with <code>IfSpeaker</code>/<code>SetSpeaker</code> to target the speaker game object.<br /> | |||
If both are applicable then it can also be invoked with <code>IfNotSpeaker</code>.<br /> | |||
{| class="wikitable" | |||
|- | |- | ||
! | ! Name | ||
! | ! Type | ||
! | ! Description | ||
! Inverse | |||
| | ! Speaker | ||
| | |- | ||
| | | IfHaveQuest | ||
| | | Predicate | ||
| | | Continue if the player has an active or finished quest by specified ID. | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfHaveActiveQuest | ||
| | | Predicate | ||
| | | Continue if the player has an active quest by specified ID. | ||
|- | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfFinishedQuest | ||
|- | | Predicate | ||
| Continue if the player has a finished quest by specified ID. | |||
|- | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfFinishedQuestStep | ||
| | | Predicate | ||
| | | Takes a '~' separated value of "Quest ID~Step ID" and checks if the step is completed. | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfHaveObservation | ||
| | | Predicate | ||
| | | Continue if the player knows of any gossip or lore with the specified ID. | ||
| | | Yes | ||
| No | |||
|- | |- | ||
| | | IfHaveObservationWithTag | ||
| | | Predicate | ||
| | | Continue if the player knows of any gossip or lore with the specified tag. | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfHaveSultanNoteWithTag | ||
|- | | Predicate | ||
| | | Continue if the player knows any history of a sultan with the specified tag. | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfHaveVillageNote | ||
| | | Predicate | ||
| | | Continue if the player knows any history of a village with the specified ID. | ||
| Yes | |||
| | | No | ||
| | |- | ||
| | | IfHaveState | ||
|- | | Predicate | ||
| | | Continue if any global game state has been set by specified ID. | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfTestState | ||
| | | Predicate | ||
| | | Evaluates an expression of format "ID Operator Value", for example "SlynthSettlementFaction = Joppa", comparing the global game state to the specified value. | ||
| Yes | |||
| | | No | ||
| | |- | ||
| | | IfHaveConversationState | ||
| Predicate | |||
| | | Continue if any local conversation state has been set by specified ID. | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfHaveText | ||
| | | Predicate | ||
| | | Continue if the specified value is present within the currently displayed node text. | ||
|- | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfLastChoice | ||
| | | Predicate | ||
| Continue if the last selected choice in this conversation has the specified ID. | |||
|- | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfCommand | ||
| Predicate | |||
|- | | Fires an event on the element with the specified value as its command, continue if the result is set true by a consuming part. | ||
| | | Yes | ||
| | | No | ||
|- | |||
| IfReputationAtLeast | |||
| | | Predicate | ||
| | | Continue if the player has the specified reputation level or higher, valid entries are "Loved", "Liked", "Indifferent", "Disliked", and "Hated". | ||
| | | Yes | ||
| | | No | ||
|- | |||
|- | | IfTime | ||
| | | Predicate | ||
| | | Takes a time tick from the [[Calendar]], with valid ranges like "325-1000" (Harvest Dawn to Jeweled Dusk) or "1100-500" (Waxing Beetle Moon to Waxing Salt Sun). | ||
| | | Yes | ||
| No | |||
|- | |- | ||
| | | IfLedBy | ||
| | | Predicate | ||
| | | Continue if the speaker is led by the specified value, valid entries are "*" (anyone), "Player" or a blueprint ID. | ||
| Yes | |||
| | | No | ||
| | |- | ||
| | | IfZoneID | ||
| | | Predicate | ||
| Continue if the current zone's ID starts with the specified value, e.g. "JoppaWorld.22.14.1.0.13" for Grit Gate, "JoppaWorld.5.2" for the entire Stilt. | |||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfZoneName | ||
| Predicate | |||
|- | | Continue if the current zone's name contains the specified value, e.g. "Grit Gate". | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| IfZoneLevel | |||
|- | | Predicate | ||
| | | Continue if the current zone's Z level is within the specified range, e.g. "10-15" to include the surface and 5 zones down. | ||
| | | Yes | ||
| | | No | ||
|- | |||
| | | IfZoneTier | ||
| | | Predicate | ||
| | | Continue if the current zone's [[Zone_tier#Regional_Zone_Tier|regional zone tier]] is within the specified range. | ||
| | | Yes | ||
| No | |||
|- | |- | ||
| | | IfZoneWorld | ||
| | | Predicate | ||
| | | Continue if the current zone is within the specified world, e.g. "JoppaWorld". | ||
| Yes | |||
|- | | No | ||
| | |- | ||
| | | IfUnderstood | ||
| | | Predicate | ||
| | | Continue if the player has seen and understands the specified blueprint. | ||
| | | Yes | ||
| | | No | ||
| | |- | ||
| | | IfIn100 | ||
| | | Predicate | ||
| | | Continue if the randomly rolled value is below or equal to the specified value. | ||
| | | No | ||
| No | |||
|- | |||
| IfGenotype | |||
| | | Predicate | ||
| Continue if the target is of the specified genotype. | |||
|- | | Yes | ||
| | | Yes | ||
| | |- | ||
| | | IfSubtype | ||
|- | | Predicate | ||
| | | Continue if the target is of the specified subtype. | ||
| | | Yes | ||
| | | Yes | ||
|- | |- | ||
| | | IfTrueKin | ||
| | | Predicate | ||
| | | Continue if the target counts as a true kin and can implant cybernetics. | ||
|- | | Yes | ||
| | | Yes | ||
| | |- | ||
| | | IfMutant | ||
| Predicate | |||
| Continue if the target counts as a mutant and can gain mutations. | |||
| | | Yes | ||
| | | Yes | ||
| | |- | ||
| | | IfHaveItem | ||
| | | Predicate | ||
| | | Continue if the target has an item of the specified blueprint in their inventory or equipped on their body. | ||
|- | | Yes | ||
| | | Yes | ||
| | |- | ||
| | | IfWearingBlueprint | ||
| | | Predicate | ||
| | | Continue if the target has an item of the specified blueprint equipped on their body. | ||
| Yes | |||
| Yes | |||
|- | |||
| IfHaveBlueprint | |||
| Predicate | |||
| Continue if the target has an item of the specified blueprint in their inventory. | |||
| Yes | |||
| Yes | |||
|- | |||
| IfHavePart | |||
| Predicate | |||
| Continue if the target has a part by the specified class name. Mutations are a variant of a part that this is applicable to. | |||
| Yes | |||
| Yes | |||
|- | |||
| IfHaveTag | |||
| Predicate | |||
| Continue if the target's blueprint has the specified tag. | |||
| Yes | |||
| Yes | |||
|- | |||
| IfHaveProperty | |||
| Predicate | |||
| Continue if the target game object has the specified property. | |||
| Yes | |||
| Yes | |||
|- | |||
| IfHaveTagOrProperty | |||
| Predicate | |||
| Continue if the target has the specified tag or property. | |||
| Yes | |||
| Yes | |||
|- | |||
| IfHaveLiquid | |||
| Predicate | |||
| Continue if the target has the specified liquid with an optional amount of drams, e.g. "water" for at least 1 dram of water, or "sludge:64" for 64 drams of sludge. | |||
| Yes | |||
| Yes | |||
|- | |||
| IfLevelLessOrEqual | |||
| Predicate | |||
| Continue if the target is at or below the specified value. | |||
| Yes | |||
| Yes | |||
|- | |||
| AwardXP | |||
| Action | |||
| Gives the specified amount of XP to the target, preceding the amount with an exclamation mark will suppress the XP popup, e.g. "!5000". | |||
| No | |||
| Yes | |||
|- | |||
| FinishQuest | |||
| Action | |||
| Marks a quest by the specified ID as finished. This will not complete all the quest's steps. | |||
| No | |||
| No | |||
|- | |||
| FireEvent | |||
| Action | |||
| Constructs an event from a comma and colon separated list of "EventID,Parameter1:Value1,Parameter2:Value2,Para..." then fires it on the target game object. | |||
| No | |||
| Yes | |||
|- | |||
| FireSystemsEvent | |||
| Action | |||
| Constructs an event from a comma and colon separated list of "EventID,Parameter1:Value1,Parameter2:Value2,Para..." then fires it on all game systems. | |||
| No | |||
| No | |||
|- | |||
| SetStringState | |||
| Action | |||
| Takes a comma separated list of "StateID,Value" and sets the global game state to the specified string value. If no value is specified the state is removed. | |||
| No | |||
| No | |||
|- | |||
| SetIntState | |||
| Action | |||
| Takes a comma separated list of "StateID,Value" and sets the global game state to the specified int value. If no value is specified the state is removed. | |||
| No | |||
| No | |||
|- | |||
| AddIntState | |||
| Action | |||
| Takes a comma separated list of "StateID,Value" and adds the specified value to the global game state's value. | |||
| No | |||
| No | |||
|- | |||
| SetBooleanState | |||
| Action | |||
| Takes a comma separated list of "StateID,Value" and sets the global game state to the specified boolean value. If no value is specified the state is removed. | |||
| No | |||
| No | |||
|- | |||
| ToggleBooleanState | |||
| Action | |||
| Toggles the boolean value of the global game state by specified ID. If no value existed prior, it will be set to true. | |||
| No | |||
| No | |||
|- | |||
| SetStringProperty | |||
| Action | |||
| Takes a comma separated list of "PropertyID,Value" and sets a string property on the target game object to the specified value. If no value is specified the property is removed. | |||
| No | |||
| Yes | |||
|- | |||
| SetIntProperty | |||
| Action | |||
| Takes a comma separated list of "PropertyID,Value" and sets an int property on the target game object to the specified value. If no value is specified the property is removed. | |||
| No | |||
| Yes | |||
|- | |||
| SetStringConversationState | |||
| Action | |||
| Takes a comma separated list of "StateID,Value" and sets the temporary conversation state to the specified string value. If no value is specified the state is removed. | |||
| No | |||
| No | |||
|- | |||
| SetIntConversationState | |||
| Action | |||
| Takes a comma separated list of "StateID,Value" and sets the temporary conversation state to the specified int value. If no value is specified the state is removed. | |||
| No | |||
| No | |||
|- | |||
| SetBooleanConversationState | |||
| Action | |||
| Takes a comma separated list of "StateID,Value" and sets the temporary conversation state to the specified boolean value. If no value is specified the state is removed. | |||
| No | |||
| No | |||
|- | |||
| RevealObservation | |||
| Action | |||
| Reveals a piece of gossip or lore by the specified ID. | |||
| No | |||
| No | |||
|- | |||
| GiveLiquid | |||
| Action | |||
| Fills valid liquid containers of the target with specified liquid, e.g. "water" for 1 dram of water, or "sludge:64" for 64 drams of sludge. | |||
| No | |||
| Yes | |||
|- | |||
| UseLiquid | |||
| Action | |||
| Empties valid liquid containers of the target with specified liquid, e.g. "water" for 1 dram of water, or "sludge:64" for 64 drams of sludge. | |||
| No | |||
| Yes | |||
|- | |||
| StartQuest | |||
| Part Generator | |||
| Adds a QuestHandler part to the parent element with the Start action and specified QuestID. | |||
| No | |||
| No | |||
|- | |||
| CompleteQuestStep | |||
| Part Generator | |||
| Adds a QuestHandler part to the parent element with the Step action and specified "QuestID~StepID". | |||
| No | |||
| No | |||
|- | |||
| GiveItem | |||
| Part Generator | |||
| Adds a ReceiveItem part to the parent element with the specified comma separated blueprints. | |||
| No | |||
| No | |||
|- | |||
| TakeItem | |||
| Part Generator | |||
| Adds a TakeItem part to the parent element with the specified comma separated blueprints. | |||
| No | |||
| No | |||
|} | |||
=== Choice ordering === | |||
The following attributes can be added to the <code><choice></code> XML tag to manipulate the order in which conversational choices are presented. By default, choices are ordered by how they appear in <code>Conversations.xml</code>. | |||
{| class="wikitable" | |||
|- | |||
! Name | |||
! Description | |||
|- | |||
| Priority | |||
| An integer priority that that specifies where a choice should appear; choices with a higher priority appear closer to the top. By default all choices are given a priority of zero unless explicitly specified, although some parts influence the priority of a choice. | |||
|- | |||
| Before | |||
| Place a choice before another choice with the specified ID, e.g., <code>Before="WaterRitualChoice"</code>. | |||
|- | |||
| After | |||
| Place a choice after another choice with the specified ID, e.g. <code>After="WaterRitualChoice"</code>. | |||
|} | |} | ||
{{Modding Navbox}} | |||
[[Category:Modding]] | |||