Difference between revisions of "Templates explanation"
(Mention script naming convention for local instances) |
|||
(5 intermediate revisions by 2 users not shown) | |||
Line 11: | Line 11: | ||
[[File:Rootsarmy.jpg|frame|Army Men game has 2 roots: ArmyMan and Tank. Thanks art team!|none]] | [[File:Rootsarmy.jpg|frame|Army Men game has 2 roots: ArmyMan and Tank. Thanks art team!|none]] | ||
+ | <br /> | ||
= Local instances/templates = | = Local instances/templates = | ||
<p>You never really place a root in the game. You place a '''reference''' to the root in the game.<br> | <p>You never really place a root in the game. You place a '''reference''' to the root in the game.<br> | ||
Line 22: | Line 23: | ||
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 /> | ||
= Inheritance = | = Inheritance = | ||
<p>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!<br> | <p>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!<br> | ||
Line 48: | Line 52: | ||
|} | |} | ||
+ | <br /> | ||
= Consistency and player expectations = | = Consistency and player expectations = | ||
By using roots, we also ensure consistent behaviour of the items in our world. | By using roots, we also ensure consistent behaviour of the items in our world. | ||
Line 87: | Line 92: | ||
<p>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.</p> | <p>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.</p> | ||
+ | <br /> | ||
= What is wrong = | = What is wrong = | ||
<p>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.</p> | <p>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.</p> | ||
Line 111: | Line 117: | ||
|} | |} | ||
+ | <br /> | ||
= Overrides on local instances = | = Overrides on local instances = | ||
<p>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.</p> | <p>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.</p> | ||
− | [[File:Ingamearmy.jpg|frame|none| | + | [[File:Ingamearmy.jpg|frame|none|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.]] |
+ | |||
<p>But one must always be careful, because overriding properties can be a cause of bugs too.</p> | <p>But one must always be careful, because overriding properties can be a cause of bugs too.</p> | ||
Line 130: | Line 138: | ||
<p>Sometimes, overrides on local instances are perfectly possible and encouraged. But as soon as you are changing systemics, think about what you’re doing.<br> | <p>Sometimes, overrides on local instances are perfectly possible and encouraged. But as soon as you are changing systemics, think about what you’re doing.<br> | ||
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.</p> | 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.</p> | ||
+ | |||
+ | <br /> | ||
= Overrides mean: no more updates from root = | = Overrides mean: no more updates from root = | ||
Line 137: | Line 147: | ||
[[File:Purplearmy.jpg|frame|none|“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.]] | [[File:Purplearmy.jpg|frame|none|“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.]] | ||
+ | <br /> | ||
= Perfectly normal overrides = | = Perfectly normal overrides = | ||
<p>There are cases in which it can be perfectly normal to use the override functionality.<br> | <p>There are cases in which it can be perfectly normal to use the override functionality.<br> | ||
Line 148: | Line 159: | ||
* '''Alignment:''' for specifying for instance more regional alignments to NPCs | * '''Alignment:''' for specifying for instance more regional alignments to NPCs | ||
* '''IsBoss:''' for specifying that this particular local is a boss character | * '''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 | + | * '''IsInspector:''' if you want to turn specific items or characters that are usually not inspectors into an inspector |
+ | ** Inspectors are items that [[Osiris/API/SetCanJoinCombat|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 | ** 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 | ** Other than traps, this may be necessary on some locals in some circumstances | ||
Line 177: | Line 189: | ||
* '''Skills:''' a local can have different skills than its root | * '''Skills:''' a local can have different skills than its root | ||
+ | <br /> | ||
= The parable of the 3 designers = | = The parable of the 3 designers = | ||
<p>3 designers each made a farm.<br> | <p>3 designers each made a farm.<br> | ||
Line 197: | Line 210: | ||
<p>The game is now illegal in Australia.</p> | <p>The game is now illegal in Australia.</p> | ||
+ | <br /> | ||
= Why changing locals is not “a quick hack” = | = Why changing locals is not “a quick hack” = | ||
<p>The argument is often made that to quickly fix something or hack something, or get something ready quick, you “do it to the local”.</p> | <p>The argument is often made that to quickly fix something or hack something, or get something ready quick, you “do it to the local”.</p> | ||
Line 217: | Line 231: | ||
* 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 | * 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 | ||
+ | <br /> | ||
= Real life examples of what people did wrong and why it was wrong = | = Real life examples of what people did wrong and why it was wrong = | ||
=== The jar story === | === The jar story === | ||
Line 247: | Line 262: | ||
|} | |} | ||
+ | <br /> | ||
=== The book story === | === The book story === | ||
<p>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.</p> | <p>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.</p> | ||
Line 271: | Line 287: | ||
|} | |} | ||
+ | <br /> | ||
=== The small statuette story === | === The small statuette story === | ||
<p>Your job is to decorate the museum.<br> | <p>Your job is to decorate the museum.<br> | ||
Line 303: | Line 320: | ||
|} | |} | ||
+ | <br /> | ||
=== The story about you don’t want to break other people’s stuff === | === The story about you don’t want to break other people’s stuff === | ||
<p>You notice that a book cannot be picked up.<br> | <p>You notice that a book cannot be picked up.<br> |
Latest revision as of 10:01, 13 October 2017
Contents
- 1 Root template
- 2 Local instances/templates
- 3 Inheritance
- 4 Consistency and player expectations
- 5 What is wrong
- 6 Overrides on local instances
- 7 Overrides mean: no more updates from root
- 8 Perfectly normal overrides
- 9 The parable of the 3 designers
- 10 Why changing locals is not “a quick hack”
- 11 Real life examples of what people did wrong and why it was wrong
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.
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).
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.)
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. |
Whew. What a relief. I thought we would have to update all local instances everywhere in the entire game. Thank you root system!
Examples:
All hail roots. |
Consistency and player expectations
By using roots, we also ensure consistent behaviour of the items in our world.
Examples:
|
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:
|
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.
But one must always be careful, because overriding properties can be a cause of bugs too.
Examples: |
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.
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.
- 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.
- 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. |
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. |
“I was told to unstub the name of these jars.” Yes. But not these particular jars, you are taking it too literally. |
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 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”. |
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 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. 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. If the root of this statue would get a certain update (for instance, all these statues are now a waypoint shrine), |
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. |