Arcanima dialogue system is way to make NPCs talk. It is generally very simple to use, if you're familiar to Lua programming and can check examples. Specific format for dialogue is also planned, since writing tables in code by hand is not that fun.

Currently dialogue is handled by editing templates and Lua scripts. Editor is planned, but no implementation has been done yet.

Adding to NPC

Templates

Dialogue can be added to NPC in template as part of modular AI or separately. Either way, dialogue data file name must be specified in initializer with name <code>DialogueData</code>. Here is a quick example of the modular AI way (simplified from stonemason Gwen):

<syntaxhighlight lang="lua">

{

Modules = {

"ai_modules.dialogue"

},

Stats = {

Str = 50,

Agi = 45,

Int = 90,

},

EquipTable = {

RightHand = { "tool_mining_pick" },

Chest = {{"padded_chest_earth", "0x8888AA00"}},

Legs = { "padded_legs_sewn" },

BodyPartHair = {{"hair_female_shaggy","0xFFFF9984"}},

BodyPartHead = {"head_female01"},

Backpack= {

"backpack",

},

},

DialogueData = "aberfan_stonemason"

}

</syntaxhighlight>

The data file is searched from script directory <code>data_dialogue</code>. In this example, file is <code>data_dialogue/aberfan_stonemason.lua</code>

ObjVars

You can also add dialogue by setting object variable <code>DialogueData</code> to point at data file and then reloading NPC. If you do this and then save it using editor, template will be working one.

Dialogue Concepts

Writing dialogue is easy... If you understand the concepts. Lua knowledge is not really needed, since writing tables in Lua is like writing them in most programming languages. It is quite possible write (or copy-paste) code skeleton for dialogue, but it is not possible to actually use that without understanding the concepts. Soo, let's take look at components of dialogue...

Starting Point

Starting point is basically list of possible starting nodes. It is iterated through (using <code>ipairs</code>), and for each node name, certain conditions are checked. Those conditions are defined by NPC creator; there are no standard ones. If conditions match to player talking to NPC, node associated with them is shown to player. If they do not match, then next node in the list is evaluated in similar way.

If no node in list can be shown to player, nothing is shown. It is not an error, since sometimes NPC should just ignore players without specific features. Imagine some NPC being hostily towards you, but allow you to right click and interact? Yeah, that would be stupid.

Nodes

The skeleton of dialogue consists of nodes. Each node has text which will be shown when player enters it. Nodes may (or may not) also have responses, which are clickable buttons shown to player. Player may click these buttons and get redirected to other nodes - that is how dialogue flows. Certain responses from player can also stop dialogue - for example if player says "Goodbye!" to NPC, it will probably not respond.

Special Nodes

Nodes may redirect to other nodes without showing anything. These redirect nodes are basically starting points which are entered through other redirect nodes or clicked responses.

Then there are function nodes, which are called special handles. They are just functions, which can do whatever you can do normally using Lua. Want to drop meteorite to player's head if they insult some NPC? If you know how you'd write it using lua for Shards Online, then you can call that code from special handles and have spectacular meteor shower killing everyone if players do not like your cool NPC.

Mechanics

Now, we need to dive into dialogue table format... It is quite simple:

<syntaxhighlight lang="lua">

Dialogue = {

Situations = { INSERT STARTING POINTS HERE, as Lua list table }, Nodes = { INSERT NODES HERE, as Lua table (key-value) }

}

</syntaxhighlight>

Wait, you need more instructions? Very well...

Situations

This is very easy. Each situation is Lua table, which contains name of node and condition table as follows:

<syntaxhighlight lang="lua">

{

Conditions = INSERT CONDITION TABLE HERE, Node = "NameOfNode"

},

</syntaxhighlight>

<code>Node</code> is just code name of node (see below for what that means). Conditions are standard condition system table (i.e. use docs for condition system if you need help).

Nodes

As said, nodes are skeleton of dialogue. They contain everything that is shown to player; all NPC speech and responses what player can take. Nodes are stored under keys in <code>Nodes</code> table. Key of node is code name of it, which will be used in responses and situations.

Node is defined as follows:

<syntaxhighlight lang="lua">

CodeNameOfThis = {

Text = What the NPC is saying goes here., Responses = { -- Under this goes list of responses! {"CodeName", "What player would say to NPC goes here.", CONDITIONS} }

},

</syntaxhighlight>

So, code name of node is key for node's data. Logical, isn't it? Anyway, <code>Text</code> here should be self-explanatory. It is what NPC will say to player in interaction window. You can use color codes here, but just plain text is fine usually.

Responses are equally simple. You just put a list of Lua tables under <code>Responses</code>. These tables will contain code names of nodes where user will go if they clicked buttons; they will also contain text to show at those buttons. Buttons texts are basically what player is saying to the NPC.

You can restrict responses of player by setting conditions to them; replace <code>CONDITIONS</code> with your requirements for option to show.

Special Handles

You can define nodes, which are actually functions and show nothing to player:

<syntaxhighlight lang="lua">

function SpecialHandles.NodeName(user)

INSERT LUA CODE HERE

end

</syntaxhighlight>

User is gameobj of player; use it for whatever you want. The script is running on NPC AI module; you can use <code>this</code> to refer to the NPC.

Note that <code>SpecialHandles</code> table is separate to <code>Dialogue</code> table; you should place special handles below declaration of dialogue. You should not set <code>SpecialHandles</code> table to other table, only alter contents of it.

Redirect Nodes

Sometimes you just need to pick next node of few possibilities according to properties of user. How to do so? It is very simple; you will need to create one node which shows nothing to player and redirects to other nodes based on conditions. This is similar to starting point situations table:

<syntaxhighlight lang="lua">

RedirectNode = {

Redirect = { INSERT LIST HERE }

}

The list uses exactly same format as with situations. You can literally copy-paste situation list to redirect node!

</syntaxhighlight>

Macros

You can use macros in NPC's text and player responses. Basically macros are static text keys, which are replaced with some dynamic data. Macroes are sourrounded by brackets: <code>{macroname}</code>.

Currently only usable macro is <code>{player}</code> to refer who is NPC talking to.

Generated Nodes

Sometimes you just can't write static text for node... Well, no problem; you can use function which returns text as <code>Text</code> in nodes:

<syntaxhighlight lang="lua">

SomeDynamicNode = {

Text = function (user, node) LUA CODE HERE end Responses = { { function (user, node) LUA CODE HERE end, function (user, node) LUA CODE HERE end, CONDITIONS HERE } }

}

</syntaxhighlight>

You see three similar functions here, all they will return text which would normally be static... First is for NPC speech. Second and third are part of one and only response player can take in this situation. Of them, first determines which node will this response lead to (returns name of that node). Second returns text which user should see in the response button.

You should return text from these functions in most cases. If no <code>nil</code> is returned, following will happen:

Scripting API

You can call dialogue API from same module using function calls or from other modules/game object using messages.

<code>function StartDialogue(user)</code>

Starts dialogue for given user at the beginning in same way as they would just have interacted with the NPC.

<code>function GetEntryNode(user)</code>

Gets entry node name for given user. <code>StartDialogue</code> calls this.

Note: Not available as message

<code>function ShowNode(name, user)</code>

Shows node with given name to given user. If no node with name exists, nothing happens; it is ok to use this feature intentionally to stop dialogue.

Note: Message name is <code>ShowDialogNode</code>

<code>function MarkNPCMeet(user)</code>

Marks that this NPC has met given user.