1,043
edits
m (Armithaig moved page Modding:Conversation to Modding:Conversations: helado is right) |
(demonstrate root element) |
||
(13 intermediate revisions by 2 users not shown) | |||
Line 12: | Line 12: | ||
<syntaxhighlight lang="xml"> | <syntaxhighlight lang="xml"> | ||
<!-- ObjectBlueprints.xml--> | <!-- ObjectBlueprints.xml--> | ||
<object Name="Snapjaw Pal" Inherits="Snapjaw"> | <objects> | ||
<object Name="Snapjaw Pal" Inherits="Snapjaw"> | |||
</object> | <part Name="ConversationScript" ConversationID="FriendlySnapjaw" /> | ||
</object> | |||
</objects> | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="xml"> | |||
<!-- Conversations.xml--> | <!-- Conversations.xml--> | ||
<conversation ID="FriendlySnapjaw"> | <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> | |||
</conversation> | </node> | ||
</conversation> | |||
</conversations> | |||
</syntaxhighlight> | </syntaxhighlight> | ||
(Note that the outer <code>conversations</code> tag is required.) | |||
=== XML Tags === | === XML Tags === | ||
Line 49: | Line 57: | ||
|- | |- | ||
| <code><nowiki><text></nowiki></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. | | 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> | | <code><nowiki><part></nowiki></code> | ||
Line 57: | Line 65: | ||
=== Merging === | === 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 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/> | If an explicit ID isn't defined, one will be created based on other attributes.<br/> | ||
Line 81: | Line 88: | ||
=== Inheritance === | === 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 /> | 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 /> | 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. | Unlike merging, the properties of the current element have precedence over those it is inheriting from. | ||
Line 109: | Line 116: | ||
=== Distribution === | === 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/> | 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/> | 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/> | ||
Line 143: | Line 149: | ||
=== Custom Delegates === | === 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/> | 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. | 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. | ||
Line 166: | Line 171: | ||
== Parts == | == Parts == | ||
For more advanced or specific logic not easily reduced to a generally accessible delegate, a custom part is preferred.<br/> | 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 | 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>. | |||
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"> | <syntaxhighlight lang="xml"> | ||
<conversation ID="JoppaZealot"> | <conversation ID="JoppaZealot"> | ||
Line 206: | Line 211: | ||
=== Events === | === 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. | 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. | ||
Line 228: | Line 232: | ||
==Tables== | ==Tables== | ||
Below are non-exhaustive tables of existing parts, events and | 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 | |||
|- | |||
| 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=== | ===Events=== | ||
Source notes the deepest element that you can expect the event to propagate from. In order, the values are Conversation -> Node -> Choice -> Text.<br/> | Source notes the deepest element that you can expect the event to propagate from. In order, the values are Conversation -> Node -> Choice -> Text.<br/> | ||
Line 310: | Line 447: | ||
===Delegates=== | ===Delegates=== | ||
An Inverse predicate can be invoked with <code>IfNot</code> to negate its value.<br /> | 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> to target the speaker game object.<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 /> | If both are applicable then it can also be invoked with <code>IfNotSpeaker</code>.<br /> | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 377: | Line 514: | ||
| Predicate | | Predicate | ||
| Evaluates an expression of format "ID Operator Value", for example "SlynthSettlementFaction = Joppa", comparing the global game state to the specified value. | | 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 | | Yes | ||
| No | | No | ||
Line 395: | Line 544: | ||
| Predicate | | Predicate | ||
| Continue if the player has the specified reputation level or higher, valid entries are "Loved", "Liked", "Indifferent", "Disliked", and "Hated". | | 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 | | Yes | ||
| No | | No | ||
Line 467: | Line 664: | ||
| Predicate | | Predicate | ||
| Continue if the target has the specified tag or property. | | 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 | ||
| Yes | | Yes | ||
Line 474: | Line 677: | ||
| Continue if the target is at or below the specified value. | | Continue if the target is at or below the specified value. | ||
| Yes | | 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 | | Yes | ||
|- | |- | ||
Line 484: | Line 693: | ||
| FireEvent | | FireEvent | ||
| Action | | 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 | | No | ||
| Yes | | Yes | ||
Line 490: | Line 699: | ||
| FireSystemsEvent | | FireSystemsEvent | ||
| Action | | 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 | ||
| No | | No | ||
Line 496: | Line 705: | ||
| SetStringState | | SetStringState | ||
| Action | | Action | ||
| Takes a comma separated list of " | | 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 | ||
| No | | No | ||
Line 502: | Line 711: | ||
| SetIntState | | SetIntState | ||
| Action | | Action | ||
| Takes a comma separated list of " | | 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 | ||
| No | | No | ||
Line 508: | Line 717: | ||
| AddIntState | | AddIntState | ||
| Action | | Action | ||
| Takes a comma separated list of " | | Takes a comma separated list of "StateID,Value" and adds the specified value to the global game state's value. | ||
| No | | No | ||
| No | | No | ||
Line 514: | Line 723: | ||
| SetBooleanState | | SetBooleanState | ||
| Action | | Action | ||
| Takes a comma separated list of " | | 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 | ||
| No | | No | ||
Line 520: | Line 729: | ||
| ToggleBooleanState | | ToggleBooleanState | ||
| Action | | Action | ||
| Toggles the boolean value of the global game state by specified ID. | | 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 | ||
| No | | No | ||
Line 526: | Line 735: | ||
| SetStringProperty | | SetStringProperty | ||
| Action | | 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 | | No | ||
| Yes | | Yes | ||
Line 532: | Line 741: | ||
| SetIntProperty | | SetIntProperty | ||
| Action | | 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 | | No | ||
| Yes | | 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 | | RevealObservation | ||
Line 541: | Line 768: | ||
| No | | No | ||
| 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 | | StartQuest | ||
Line 567: | Line 806: | ||
|} | |} | ||
=== 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}} | {{Modding Navbox}} | ||
[[Category:Modding]] | [[Category:Modding]] |