Difference between revisions of "Templates explanation"

From Divinity Engine Wiki
Jump to: navigation, search
m (Explain what an inspector is)
(Mention script naming convention for local instances)
 
(One intermediate revision by one other user not shown)
Line 22: Line 22:
 
<p>A local instance can live without data. It '''just refers''' to the root and it will get its data there.<br>
 
<p>A local instance can live without data. It '''just refers''' to the root and it will get its data there.<br>
 
However, if the root is deleted, the link is broken and the local instance will no longer be able to show anything. (This is why you get errors if roots are deleted and they’re used by local instances.)</p>
 
However, if the root is deleted, the link is broken and the local instance will no longer be able to show anything. (This is why you get errors if roots are deleted and they’re used by local instances.)</p>
 +
 +
{{warning|If you place a local instance that will be referenced from any script, or that should be assigned as a parameter to a script, a skill, or any action in the sidebar, make sure its name starts with '''S_'''. This tells the editor the object is/will be referenced, and adds it to auto-completion lists in script editors and to selection menus elsewhere.}}
  
 
<br />
 
<br />

Latest revision as of 10:01, 13 October 2017

Root template

Root templates are the building blocks of our game. A root template can be an item, a character, a trigger, etc.

A root template describes a game object. It contains the data of a thing necessary to put that thing in the game.
(For instance: its visual, the physics, the AI bounds, name, stats, scripts, etc. All these properties describe and make up the game object.)

A root template is set up so that it defines the default visual and default behaviour of the game object. This means that a root template contains important gameplay information.

For our interactive, reactive, systemic game to work correctly, we need roots and they must be carefully set up.

Army Men game has 2 roots: ArmyMan and Tank. Thanks art team!


Local instances/templates

You never really place a root in the game. You place a reference to the root in the game.
Roots really exist on another plane outside of the game.

The game merely contains links to the root. When you drag a root into the game, it creates a local instance (also called local template) of the root at that spot. You could say local instances are children of their parent (the root).

Army Men game has 2 local instances in-game that refer to the root ArmyMan.

A local instance can live without data. It just refers to the root and it will get its data there.
However, if the root is deleted, the link is broken and the local instance will no longer be able to show anything. (This is why you get errors if roots are deleted and they’re used by local instances.)

Warningred.png
If you place a local instance that will be referenced from any script, or that should be assigned as a parameter to a script, a skill, or any action in the sidebar, make sure its name starts with S_. This tells the editor the object is/will be referenced, and adds it to auto-completion lists in script editors and to selection menus elsewhere.


Inheritance

If you are an artist, think of a root template as a magical mold or a magical pattern: when you update the mold, everything you ever made with it updates too!
If you are a programmer, think of a root template as a class.

Every time a root template is updated, all its local instances inherit the updates automatically.

“Green?! NO! All ArmyMan must be red!” The Root ArmyMan was updated with the colour RED. All its instances in the game everywhere inherit the colour automatically.
(NOTE: This is just an example of a property. Colour works differently in our game.)

Whew. What a relief. I thought we would have to update all local instances everywhere in the entire game. Thank you root system!

Colorsarmy.jpg

Examples:

  • If an artist finally gives the root an icon, all the local instances in the game inherit the root. This means that you can close 248 bugs about “vase has no icon” by updating 1 root, and it means that you just gave 3400 vases an icon with 1 click.
  • If a designer finally creates an item combo for the root, you can perform the item combo with all local instances of that root. By updating 1 root, you can close 134 bugs about “cup plus barrel gives no mug of beer”, and it means that you just gave 4200 mugs the ability to become a mug of beer.
  • If a writer finally finds the time to write a kickass description for this special bottle of wine, and she writes it on the root template, she can close the 124 tickets about the 879 bottles in the game not having a description. If we would not have roots and their magical inheritance, we would have to copy paste that description 879 times.

All hail roots.


Consistency and player expectations

By using roots, we also ensure consistent behaviour of the items in our world.

Examples:

  • Every barrel of oil explodes because every barrel of oil in our game gets that piece of information from its root template.
  • You can drink every bottle of wine in the game, because its root refers to wine stats and has the consume action.

The player of our game has certain expectations. Things do what they look like they do in real life:

  • you can read a book,
  • you can drink wine,
  • you can eat bread,
  • you can cook meat,
  • you can climb stairs,
  • you can open a cupboard,
  • you can open a door,
  • you can open that hatch,
  • you can open a can of whoop ass,
  • you can wear a helmet,
  • you can put on shoes,
  • you can use that weapon on the wall,
  • that shield is not just decoration,
  • you can wield that broom as a weapon,
  • you can look in that mirror,
  • you can cook something in the oven,
  • you can lie in a bed,
  • you can sit on a chair,
  • you can climb a ladder,
  • ...
  • You can move everything that is not too heavy and not nailed down.
  • You can pick up anything that looks like it can fit in a backpack. (Exceptions: barrels, crates, chests, baskets, a lot of weapons and armour.)
  • You can interact with things that you expect to be interactive and see an animation (turn on a lamp, pull a lever) or hear a funny remark (click on a gravestone) or you can do an item combo with it (an anvil, an oven).

To live up to these expectations, we set up the roots correctly, and as a result, all its instances inherit the settings and everything works as it should. If one item in the game behaves differently, it is experienced as a bug and it’s not the way this game was designed.


What is wrong

If you turn off or change this expected, standard behaviour on a local instance, that is wrong in 99% of the cases: it is no longer consistent with the other items of this type and confuses the player. It’s a bug, it’s an inconsistency.

What is even worse is to set up such behaviour on a local instance. Doing this is wrong in 99% of the cases: it then only works on that local and not on the rest of its brothers and sisters. This is not consistent and you are not using the power of the root system.

“Green?! NO! All ArmyMan must be red!” The WRONG way to do this is to go over every local instance and override their colours. This is wrong because:
  • You forgot a couple in that other level. You introduced bugs.
  • The other guy who is using ArmyMan did not get the memo and is not doing it to his locals. Bugs.
  • All future instances of ArmyMan will still be green because its root is still green.
  • The player will then start seeing green and red army men and will be confused. Bugs.
  • Any updates on the colour of the root will not be inherited because the colour was overridden and some other poor sod will have to find out why fixing the root doesn’t update all instances in the game.
  • All this could have been avoided by updating the root.
Wrongarmy.jpg
Warningred.png
If you find yourself constantly overriding the same things on all the locals of one root, you are probably doing it wrong and you should just fix the root and not try to fix all instances one by one.


Overrides on local instances

A designer or an artist building the world can override properties of game objects. Because sometimes, there are exceptions and then overriding a property is a powerful tool.

This very specific ArmyMan01 must always be green no matter what colour ArmyMan Root has. ArmyMan01 is really special.” In this case, we can override the colour property with green. The rest of the properties are still automatically inherited.


But one must always be careful, because overriding properties can be a cause of bugs too.

Examples:
When is it a good idea to override properties on a local? For instance, you want a certain painting to react differently to a click than usual, because it is part of a quest: you can talk to this particular painting!
Or this hand placed weapon belonged to the duke and has a special name and needs unique stats. Or, this chest is locked with a key. This particular door is possessed and you have to talk to it instead of open it.
This water well is not just a water well, if you do the right things to it, it becomes a wishing well! And so forth.

Sometimes, overrides on local instances are perfectly possible and encouraged. But as soon as you are changing systemics, think about what you’re doing.
And as soon as you find yourself doing the same thing over and over again to the same locals, think about what you’re doing.


Overrides mean: no more updates from root

However, as a designer or artist, you must know that a property of a local that gets an override no longer inherits from its root.
This is only logical, because it is an override. Even if the root is updated, the local instance’s property is still overridden.

“Red is out, we should make our ArmyMan purple in the entire game. For Prince!” We set the root’s colour property with purple. However, all instances that have an override on colour do not inherit this, and that may be fine if that’s what you wanted.


Perfectly normal overrides

There are cases in which it can be perfectly normal to use the override functionality.
The following properties can be overridden in the following cases:

  • DisplayName: if you want to give this particular local a specific name.
    • Pitfall: if you find yourself selecting and renaming an entire group of similar item locals or character locals, you probably want to:
    a) fix the root’s name
    b) create a new root
    • ...because you are probably creating a certain new type that warrants a root
  • Alignment: for specifying for instance more regional alignments to NPCs
  • IsBoss: for specifying that this particular local is a boss character
  • IsInspector: if you want to turn specific items or characters that are usually not inspectors into an inspector
    • Inspectors are items that join combat and participate in the turn order, but that do not keep the combat alive (i.e., if the only "enemies" left are all inspectors, combat will end)
    • A trap item should have this on root level, or you will find yourself turning this on constantly for all trap locals
    • Other than traps, this may be necessary on some locals in some circumstances
  • ActivationGroupId: If you want to group locals to start together (this is never set on root because it is so local-specific)
  • Amount: if you want to put an item in the world and make it a stack
    • e.g. gold or arrows
    • it also works on potato but the visual doesn’t change
  • Description: if you want to give this particular local a specific description.
    • Pitfall: example. You see a healing potion in the game. It has no description. You click on the local instance of the potion and you fill in the description.
      This is wrong. You are only making a description for that one particular healing potion. If you want all healing potions in the game to have that description, you must fix the root.
      If you fill in a description in the root, all healing potions in the game will have the description. Use this field only to override an existing root description for a particular and specific local.
    • Pitfall: example. You see a painting in the game. It has no description. You click on seven local instances of the painting and you fill in the description.
      This is wrong. Someone somewhere else uses the same painting root. This will not have the description you filled in because you didn’t fill it in on the root.
      Someone else fills in a proper description on the root. Your seven instances will not inherit it because you made the error of filling in a description on the local instances.
  • Icon: if you have a really specific icon for this particular local version (e.g. because it is a special NPC or a unique item)
  • Treasure / Inventory: if you want to give this particular instance of the item or character a specific treasure table
    • Pitfall: if you find yourself doing this to the local because the root has no treasure filled in, are you sure the root doesn’t need a default treasure?
  • Trade Treasure : if you want to give this particular copy of the character a specific trade table
  • Items: usually not set on a root, this enables you to put things in an item or in a character’s pockets
  • LevelOverride: can be set to a specific level, zero to take level of stats, or -1 to take level trigger
  • LockLevel: to change lockpicking requirements for this specific container
  • Stats: to change to more specific stats (more common override for characters and weapons and armour, most other items only get an override for special cases like quest objects;
    remember that item combos might not work if you change stats)
  • StoryItem: check this flag if this is a story item
  • TreasureLevel: set to a specific level to force a level, zero to get from area, -1 to get from level trigger
  • UsePartyLevelForTreasureLevel: check this box if you want the party level to determine the level of treasure this particular container generates
  • OnUseActions: for story scripting purposes, this can trigger extra uses, but its default uses should be taken into account carefully;
    the designer should take into account that the default scripts on the root may often change or get fixed and that an override will then not be inherited as soon as this part is changed, so use with caution and don’t forget about player expectation
  • Scale: don’t exaggerate with scaling. This means: don’t turn a ten foot statue into a six inch figurine. And don’t scale a needle up to a sword.
  • Tags: sometimes, a local’s tags can change
  • VisualSet: data can be changed
  • Equipment: a local can wear different weapons than its root
  • IsHardcoreOnly: a local can be added for HC only
  • Skills: a local can have different skills than its root


The parable of the 3 designers

3 designers each made a farm.
When inspecting, the lead designer says to all 3 of them: “I want to see a rooster here among the chickens.”

  • Designer 1 clicks one local chicken, changes the name to “Rooster” and calls it a day.
  • Designer 2 clicks a local chicken, changes the name to “Cock”, sets the treasure to Empty, sets the stats to FTJ_Magister_Soldier cause he thinks it should be stronger than a chicken, and requests an icon and a visual for a cock.
  • Designer 3 opens his Roots panel, right-clicks the root ANIMAL_Chicken and selects “Create new from selected…” and gives it the name “ANIMAL_Rooster”.
    He gives the root a displayname, sets the treasure to Empty, and puts one instance of the root ANIMAL_Rooster near his chickens and requests an icon and a visual for a rooster.

There are now 3 different roosters in the game.

The third designer’s root gets filled in by art, sound designers made it cock-a-doodle, and someone makes a treasure for the rooster and specific stats.
The combat designer changes the behaviour of the root of the rooster: it doesn’t flee but has powerful attacks with its claws and beak.

Everyone’s forgotten about the local overrides. Designer 1’s rooster is still laying eggs if you kill it and is now just a white chicken called “Rooster”.

Designer 2’s rooster never got the icon or the visual, cause the art department thinks they filled his request by completing the root.
Designer 2’s “cock” is also being mistranslated by a lot of loca companies and it’s taken hours to figure out where the dirty word is coming from cause the root has the name “Rooster”.

The game is now illegal in Australia.


Why changing locals is not “a quick hack”

The argument is often made that to quickly fix something or hack something, or get something ready quick, you “do it to the local”.

This is wrong in a lot of cases.

First and foremost, creating a new root for your specific item is only 2 clicks away.

Second of all, if you are trying to fix a local while you should have fixed the root,
you went through more trouble loading the level and finding the local, than fixing the root, which would have been the correct solution.

Third, by “hacking the local”, you are

  • Creating unexpected behaviour
  • Creating inconsistent behaviour
  • Possibly removing expected behaviour
  • Possibly no longer inheriting future updates and fixes to the root
  • Not updating the other locals that may need the same treatment you are giving this local (you should be doing it in the root)
  • Possibly creating a standalone version of something that is now untraceable (needs an icon but it’s hiding away between thousands of other tiny local items)
  • Causing bugs that are hard to find and fix because “the root works”
  • Causing skeletons that drop out of the closet at the end of the project and wasting time that could have been spent on polish instead of fixing “quick” hacks


Real life examples of what people did wrong and why it was wrong

The jar story

You get a ticket about the name of a jar being wrong. There is nothing special about the jar. It is not a quest item or puzzle item.

Correct Wrong
You look for the root template of the jar and you fix the name of the root. You go to the location of the jar in the ticket.
You fix the name of the local.
Why correct? Why wrong?

You just fixed not just this one jar, but all 473 jars in one go.
Future jars will also have the correct name

You fixed only 1 instance of the jar. There are 472 other jars.

You could fix all 472 other jars if you have a lot of time. But you don’t.

Even if you did fix all 472 jars, 23 of them are checked out by someone else and 34 are being added at this moment and 78 will be added between now and next year. How will you fix those?

When the name of the root gets fixed or updated, your jar name remains in the game and you have made a unique jar.
It will not stack with other jars. It will stand out and the player will think it is special.

“I was told to unstub the name of these jars.” Yes. But not these particular jars, you are taking it too literally.
You were told to unstub all jars of this type in the entire game. So you do it in the root.


The book story

You have a library full of books. You think there are too many books there, and too many of them don’t have actual content.

Correct Wrong

You leave the books be and use a generic BookID
(e.g. “You cannot read this.” or “Pages are ripped from this book so it doesn’t make a lot of sense anymore.”)

Also correct: you remove some books (careful not to touch story items) and use BookRows instead.

You delete their onUse action.

And you don’t want to waste the player’s time, so you turn off the flags “CanMove” and “CanPickup”.
You think they’re only decoration.

Why correct? Why wrong?
You are keeping the game consistent.

Killing player expectation: you should never make a moveable item non-moveable.

Killing player expectation: you should never make an interactable item non-interactable.


The small statuette story

Your job is to decorate the museum.
You think you’re short on decoration items so you decide to start using those big statues that are all over the game.

Correct Wrong

You select the root of a statue, right click it, you choose “Create new from selected…” and you make a new root.
You give it the same name but append _Tiny

You set the Scaling of the new root to 5%.

Yet grab your new root and put it on a shelf.

You tell a lead you made a new root and that it needs checking (stats, flags, visual, AI bounds…).

You grab a statue and put it on a shelf, you resize it to 5% and check it in thinking “I’m done, I am so smart.”

Why correct? Why wrong?

All people responsible will now update your root.
Doing so will result in all current and future instances of the little statue to be correct.

They will all get stats, moveable and pickupable flags, AI bounds, and a visual made for that small size.

The statue can not be moved or picked up. There is no specific root for this statue, so nobody will ever know.
You could start overriding this local, but then you are creating a very specific statue.
If someone else is doing the same thing in another spot in the game, you are both creating inconsistency.
By doing it to a local, you are hiding the problem.

If the root of this statue would get a certain update (for instance, all these statues are now a waypoint shrine),
your statue will inherit behaviour it was not intended to inherit.


The story about you don’t want to break other people’s stuff

You notice that a book cannot be picked up.
You are afraid to change the root because you think that other people may have used this book and you don’t want to break their stuff.

Correct Wrong

You fix the root because you must be able to pick up all books in this game.

You tell everyone about what root you fixed and tell them to check if their stuff still works.

If they complain, they are using the book incorrectly and should not hack their local back again to not be moveable.

You don’t do anything and make your own locals pickupable.

Why correct? Why wrong?

Player expectation, rules of the game.

Not following player expectation, not according to the rules of the game.