Category Archives: Uncategorised

When You Want to Have a Conversation: Dialorg

One of the absolute key parts of Ludus is the ability to interact with NPCs and participate in the Roman society from the perspective of a lanista. To achieve this we needed a competent dialogue system. I think anyone who has worked with dialogue trees will know what type of features to expect from that kind of tool, but with our emphasis on modability I think some of our decisions in the actual implementation might be different from some other games.

While we have developed quite ambitous plans for the ways you can interact with the NPCs in Ludus in addition to simple scripted dialogues which rely on what will hopefully be a pretty sophisticated AI – we still maintain that it is important to be able to create more tailor-made content which we can mix with the more spontaneous systems we’re attempting to develop.

Even though simulating almost everything fully is super awesome – if you sprinkle in some more set-in-stone-ish events, we can hopefully put the player in awe of what outcomes arise during the course of the game. It should hopefully also be hard to tell what was scripted and what was simulated, just that we would like to guarantee or at least make it more likely that interesting things happen no matter what.

ice-cream-bear

One way we can do this is to make dialogues that will push the simulation quite hard in a certain direction with the side effects that occur on certain dialogue nodes.

So that’s the justification for still having hardcoded dialogues in the game, but how do you actually go about authoring the dialogues?

Initially when we started we were using a tool called ChatMapper which is a fairly decent choice. But we soon realized that in order to actually export dialogues that the conversation middleware could use, every modder would have to buy a license. Since we care a lot about modders we decided that this was not acceptable so we got rid of both ChatMapper and the middleware. After researching alternatives, we set out to create our own way of authoring dialogues and our own dialogue system.

We wanted a plain text format that could easily be edited by hand and read with eyes (instead of toes!). A common choice for hierarchical data would be XML or JSON, but we’re not huge fans of those. As an Emacs user I soon had the epiphany that the Emacs Org Mode format would be quite nice for modeling a dialogue tree. It has nice properties such as not having to worry about closing tags or parenthesis for the tree nodes. Emacs comes with nice ways to edit and view it, which certainly helps, and we could add extensions to make it even nicer to edit. However if we have the time we might even put an editor for dialogues in the game itself.

2000px-Org-mode-unicorn.svg

Either way if you are not familiar with org-mode, you might want an explanation on how the format is structured! The way you write an org document is that you create a headline which you do by putting a number of asterisks (*) and a space, and then the name of the headline. After that you put a newline and anything you put below that will belong to the headline. Examples of things you’d put in the headlines are things such as paragraphs and source blocks and various attributes and such. The nesting level of the headline is determined by the number of asterisks before the name of the headline. Here’s a very simple example of a document:

* My headline
This is a pragraph that belongs to "My headline"
** My child headline
This paragraph is in a headline which is a child to "My headline"

Here's another pragraph, they are separated by two newlines.
*** My grandchild headline
This paragraph belongs to headline which is a child to "My child headline"!
** My second child headline
This is the second child to "My headline"
* My other headline
This headline is not a child of "My headline" it is a sibling.
** My other child headline
And so on!

It might be hard to read at first but again just pay attention to the asterisks before the headline title and you should be able to visualize the nesting. Emacs makes it much easier to visualize the nesting since you can turn on “org-indent-mode” which is very helpful. You usually indent the text under a headline in emacs but I stopped doing that when I noticed that it broke org-indent-mode which looks much nicer anyway. Even so, even without any indentation to make it more clear I find this format to be less noisy than something like XML or JSON. I think this format could be pleasant for other things than just dialogues, for example I think it could fit quite well as a plain-text representation of a scene-graph.

I mentioned that other than paragraphs you could put things such as source blocks and attributes under a paragraph. Let’s discuss the syntax of these a little bit. For source blocks we use the exact same syntax as Emacs org-mode, which looks like this

#+BEGIN_SRC boo
import UnityEngine
Debug.Log("Gonna set some values now in my boo script")
ludus.dialogue_state.likes_turtles = true
ludus.dialogue_state.hates_bacon = false
Debug.Log("Done setting values! :)")
#+END_SRC

If you have a keen eye you’ll notice that we explicitly say that the language for the source is “boo”, you’ll be able to use any language here that there exists a driver for, and even add your own language driver if your favorite is missing (assuming everything goes right). But that’s for another post about the scripting system!

yoink

Attributes have a similar syntax and can be put on their own or attached to another element in the headline’s section, such as a source block or paragraph. For example, we support an attribute called WHEN which you attach to a source block to specify when that script should run, a particularly useful stage to run a script is “condition” which can help filter out certain dialogue nodes if the script condition script returns false. An example could look something like this

* You were mean to the NPC
#+ACTOR: npc
#+CONVERSANT: player

I can't believe you said I'm lame. Dang you man.

#+WHEN: condition
#+BEGIN_SRC boo
script_return ludus.dialogue_state.were_mean
#+END_SRC

This example also shows the attributes ACTOR and CONVERSANT which, unlike the WHEN attribute, is not directly attached to an element of the headline – instead it is an element itself. What distinguishes an attribute element from an attribute for an element is the two newlines separating the elements, just like with paragraphs. The main thing that distinguishes an attribute element from a regular element is that you can’t attach attributes to attributes.

acting

That is really almost all of the syntax, the last thing that you might be yearning for is text substitution. Well for that you can use a macro language which again is just any programming language that has a driver for the scripting system. In order to set the property for what macro language to use you use what is called a “property drawer”. Which looks like this:

:PROPERTIES:
:MACRO-LANGUAGE: boo
:END:

Once you’ve done this you can use boo in order to evaluate any code that will in the end return a string for what should be substituted. Like this:

And that's the way {{{ script_return "it is!" }}}!

Finally in org-mode, headlines can have keywords prepended to them, such as TODO. We decided to adopt this for creating link headlines by adding the keyword LINK to designate that the headline is a link. The way you write a link is as follows:

** LINK my link headline
[[The title of the headline I am linking to]]

As you can see this means that it is good practice to name your headline something unique.

That covers basically most of it, there are other useful features as well such as running a script when entering and exiting a dialogue (and even individual dialogue nodes) for setup and cleanup etc. But this article isn’t really intended to fully document every feature of our dialogue format, but rather to introduce you to the basic ideas and principles on how we (and hopefully modders!) will write dialogues for the game. We suspect that the format will evolve over time so documenting everything right now would probably be time down the drain.

If you want to you can take a look here in order to read an example of a dialogue that I’ve been using for testing which showcases everything I mentioned in this post. It kind of lives in its own space for now in that it doesn’t have any real side effects in the real game, but it illustrates how you can arrange a dialogue – quite sloppily though because it was quickly thrown together for testing purposes, the result of running that dialogue (with a work-in-progress UI) can be seen below (click to maximize)! Thanks for reading!

dialoguehurhur

Resolving Missing Script References in Unity

Recently, I have been moving some of our important and core code out of the Unity Assets directory and instead compiling them in to a .NET dll. When I did this I encountered in to the issue of all the scenes and prefabs that were using MonoBehaviours from those scripts had lost their reference.

hillaryshocked

I found this surprising initially because I thought the references to components were simply using the .NET assembly name of the class with all the namespaces etc, perhaps in combination with something else to be able to track renames of classes. However it turns out that all it basically does is to put a GUID in the script .meta file which it in turn puts in the guid property of the m_Script field of the objects in the .unity scene files – along with a fileID property. The fileID property is always the same for scripts in the Assets directory, but it is different for every class in a dll – I suppose it uses this to narrow down the search for the assembly reference or something like that.

Now this is very little information to work with, so it’s actually harder than it should be to resolve these references. You basically can’t see the name of any script it was using or anything useful besides the GUID. When you look at the scene file you can even see that it has an m_Name and m_EditorClassIdentifier property, but it doesn’t fill them in! This is most likely why, when you look at a missing script in the inspector, it doesn’t even show you the name of it, so you have to rely on your memory to figure out what it was if you are going to fix it by hand – and I don’t know about you, but I certainly can’t do that. TL;DR the format was meticulously designed to break your heart.

ddcry

If you are in total panic right now, and don’t have any way to recover the meta files associated with your old scripts, then anything in this post beyond this paragraph won’t be useful to you. All the advice I can give is that you may be able to look in the scene files at the field names shown for the component and see how the variable names line up with those in your classes. Then you figure out what the new GUID and fileID for those are and edit it in there by hand. That will take quite some time however and I wouldn’t wish it upon my worst enemy. You could probably make some really fancy analysis program for recovery, and someone should maybe do so, but that would take a lot of effort. The best way to not end up in big trouble is to backup your stuff and put your meta files in version control. And also to use the plain text unity scene/prefab format (check the Editor Settings and/or rtfm). Do this, and the gods will smile upon you, or at the very least, I will.

I did look around a bit to see if someone already solved the problem, but pretty much the only “solution” I could find was scripts that would find the missing script references and let you assign them manually, which doesn’t help at all because you can’t get any hint of what the script was named so it’s only slightly better than checking every component manually by clicking on it. But that’s not good enough.

Expectasians-High-Expectations-Asian-Father

I managed to make a solution that does eliminate a large portion of the manual labor. There is still some set up that you do for every missing component, but it’s relatively small. I’ll describe the workflow first, and then tell you how it works internally. Finally I will share the script with you in case you don’t want to write your own.

You start out by figuring out which components possibly could be the ones that are missing. For me this was easy, I knew that the references went missing when I compiled things in to a DLL, so all I really had to do was to search through all of the source files for the DLL for lines containing “MonoBehaviour“. If you don’t know, then one thing you might do is simply to check the scripts from your recently removed meta files. Unity removes these automatically because it hates you so I can’t stress enough how it’s important to have them in version control. Once you’ve done that you can search through the file that the meta file was for in your sources for MonoBehaviours.

Now that you hopefully know which components likely went missing, and have those written down somewhere. You can create a fresh new empty scene, and have it contain nothing but an empty object containing just the MonoBehaviour you are currently fixing.

Save this scene – locate your meta file. Once you have done this, you are set up to run my script to fix one component in your entire project.

What you do is that you pass the script the meta file, as well as the scene you just set up and saved, and also one or more paths that it should search through for scenes and prefabs. It does this recursively so you don’t need to specify every subdirectory of every subdirectory etc.  Passing multiple directories is mainly useful if you have a huge Assets directory and want it to only look through “Assets/Scenes” and “Assets/MyPrefabs” or something like that. I just passed it “Assets” and it was fast enough.

goodenough2txt

What the script will then do is that it will read your meta file, and find the guid that used to be correct. Then it will read your scene file to extract what the new guid is, and also the new fileID. Knowing what the old fileID was is not important, it will simply replace the old one with the new one, it only needs to know what the old guid was to be able to locate it in scenes and prefabs. Once it has the data it asks you if the data seems to make sense to you, and if you answer “y”, then it will start replacing all of the old references for you. Here is a sample invocation of the script, cleaned up a little to remove some of the verbosity:

{ ludus } » racket Pipeline/fix-script-references.rkt ../../../oldludusmetas/CrowdDuplicator.boo.meta Assets/Scenes/FixReferences.unity Assets

I’m going to replace guid 79e4e0dfe8d9bf94b9622e6d68377772 with d79c0ede0316c2b429fad82aa7fc643f and set the file ID to 1803148156, is this ok?(y/n): y
Okay proceeding…
Found old reference(s) in C:\Users\usefulProgrammer\src\boo\ludus\Assets\ExperimentsArchive\drawcalltest\crowd.unity, replacing..
Found old reference(s) in C:\Users\usefulProgrammer\src\boo\ludus\Assets\Scenes\Crowd.unity, replacing..
Found old reference(s) in C:\Users\usefulProgrammer\src\boo\ludus\Assets\Scenes\CrowdPoses.unity, replacing..
<… and so on>

Done!

Once it’s finished you remove the component from the empty object in the scene and add the next component, save and change the meta file to the current relevant one. If you accidentally start mixing meta files etc then you will pretty much be screwed, so be careful with this. Also don’t forget to back up everything before you do this! Cool? Cool.

racketlogo

And that’s really all there is to it, I wrote the script using Racket, which was very pleasant. The script is available here under a CC0 license.

This process could probably be improved somewhat, for example you could script the editor to add all of the components for you and try to figure out which meta file it should look at etc, but that is definitely more difficult to implement and probably rather error prone. If Unity actually used the m_Name field or m_EditorClassIdentifier that they simply left empty – then it would have been less of an undertaking to automate this further. For me, going further than this would stop saving time for us in this situation, which is why I started writing the script in the first place. If we end up having a bigger catastrophy which requires really intense recovery then I’ll let you know what I do about it. But since we are using version control I suspect we won’t need anything more sophisticated than this.

I hope this post helped you out, or at the very least made you put your .meta files in version control because otherwise you could lose everything. See you next time.

fiiiiiiiiine

Game play

Ludus is a business simulation game crossed with a role-playing game, where you play as the head of a gladiator school. In your pursuit of becoming a successful Lanista, you must procure good slaves, train them as gladiators of the arena and put on amazing shows to the roar of the crowds.

In order to be commissioned for new games, you must also pick your friends and enemies carefully as you navigate your way through the deceitful social environment where every pleb, magistrate and senator is looking out for themselves. Socialize with the best people in society, and cut deals with the worst.

The gameplay consists of two phases; the Managerial & Role-playing phase and the Games Resolution phase

During the Managerial & Role-playing phase, you have many options available to you, but only a limited amount of Action Points [AP]. You can upgrade your Ludus and the Arena, hire new staff and set out the training schedule of your gladiators. You may also choose to buy slaves at the market, buy new armour and weapons from the blacksmith, advertise your up-coming games to build hype, visit the bath-house for a chance of bumping into the upper echelons of society (and gain new patronage), visit the tavern to learn about rumours and place unsavoury bets, or carry out missions to gain the patronage of ambitious magistrates. Various events will take place in this phase where you have multiple options to choose from and that affect your social position, the gladiators, your Ludus, or even your personal character. The role-playing aspects of the game immerses you in the role of the gladiator manager, and provides you with a lot of options to fit your player style and helps you carve out your character’s vices and virtues.

In The Games Resolution phase of the game, you take the role of the tactical coach, while the matches that you have set up for the current Games play out in the arena. You shout instructions to your gladiators to change their stance or alter their attacking intensity. The gladiators attempt to follow your orders as best they can, though it is not always easy to get a new order across to a gladiator mid-fight when his leg has just taken a knock from a sledge hammer and his helmet is obscuring his vision and hearing. Your objective is to give the audience a great show whilst not killing off or heavily injuring too many of your gladiators. The gladiators play as either Heroes or Villains, and their aptitude for this is determined by their statistics as well as how you have kitted them out. It is not enough to just fight, the gladiators must excite their audience by doing so in an impressive manner. The excitement of the audience must at least match the hype that you have built up for the games for the audience not to go home unimpressed, and the Editor/Sponsor of the games being displeased with your show.

Ludus is a game

Screenshot2LUDUS is a business simulation game crossed with a role-playing game, where you play as the head of a gladiator school. In your pursuit of becoming a successful Lanista, you must procure good slaves, train them as gladiators of the arena and put on amazing shows to the roar of the crowds.

In order to be commissioned for new games, you must also pick your friends and enemies carefully as you navigate your way through the deceitful social environment where every pleb, magistrate and senator is looking out for themselves. Socialize with the best people in society, and cut deals with the worst.