Hello everyone and welcome to another blog post! This time, we want to go a bit more in-depth into our Traits, what kinds there are, how they work, and how they’re implemented in the game.
Today we’re joined by Lauren, Senior Game Designer at Paradox Tectonic. Lauren has been working on Traits, Items, and Behavior Scripts, so she’s our resident expert on how they all work together in Life by You. Without further ado, let’s jump into some Q&A with Lauren with some of the basics!
What are the types of Traits?
We have so many types! Here’s a handy high-level guide:
Personality: These are generally what most people think of when they hear “traits” - permanent aspects of the character that influence their behavior.
Conditions: These are temporary character states such as “Sore” (from working out), “Sunburnt” (from sunbathing too long), and “Stung By Bees” (from getting stung by bees). They last for a limited time or until removed by an interaction.
Emotions: Emotional states are determined by either changes to the character’s emotion stats, or the interaction performed. Technically, Emotions function as a subset of Conditions.
Needs States: These traits reflect the character’s current needs status, signaling when they’re in a critical state.
Relationship: These traits function more like state markers, tracking the relationship status between two characters (e.g. “in love”, “dating”, “despises”). Any trait that begins with r_ is a Relationship trait.
Object States: These function like Conditions, but for objects instead of humans. For example, when the Food_Hot trait gets assigned to a plate of food, it turns on a steam particle effect.
Timers: When you need a script or conditional check to run at a set time interval, a timed trait is currently your best option. These are often hidden from the UI and treated more like an extension of a script instead of a traditional trait.
What do Traits impact?
The world is your oyster when it comes to what traits can affect. Here’s another handy little guide outlining how we’ve chosen to use each type of trait.
For Personality traits, the concept of “personality” is so broad we’ve subdivided it into further categories, where each category focuses on a specific type of effect.
Lifestyles: These determine what actions the character’s AI is likely to perform. They use the Trait Appeal settings in an interaction’s properties, so you can set how likely a certain interaction is for that lifestyle. For example, exercise interactions have high Trait Appeal for the Active trait, meaning they’re prioritized over non-exercise interactions when an Active character’s AI chooses its next action. Technically any trait can be referenced in Trait Appeal, we simply chose to focus Lifestyle traits in that area.
Talents: These determine what skills the character is good at, which we wanted to separate out from the likelihood of doing that same activity. This is how we allow for things like lazy athletes, mediocre mischief-makers, and business gurus who are bad with money. Each skill has a corresponding Talent trait, which grants bonus XP and increases success rates for that skill. Some talents you’ll be able to learn include:
Attitudes: These determine how the character responds to emotional changes. For example, Cheerful boosts increases to Happiness, Hot-Headed boosts increases to Angry, and Dramatic boosts increases to everything.
Quirks: These unlock unique interactions, make slight changes to behavior, and/or modify conditional checks. For example, a Messy character will ignore reaction triggers to messes they encounter.
Likes/Dislikes: These determine what the character enjoys doing. Interactions tagged with their likes result in an increase to Happiness, whereas disliked interactions will make them Sad or Very Sad.
Backgrounds: These are currently a work in progress - originally these were planned as narrative flavor text, we are currently exploring possibilities around adding gameplay effects. Stay tuned for more!
We haven’t self-imposed limits on what all trait types can affect, but in general you can expect the following:
Emotions: Changes the character’s portrait expression and idle animation.
Needs States: Changes the character’s portrait expression, idle animation, and determines whether the character passes out or not.
Relationship: Used primarily for conditional checks for conversations and human-to-human interactions.
Object States: Visual changes to the object.
Timers: These don’t directly impact gameplay, but are used to trigger scripts that will.
What are Suppressed Traits, Supporting/Reciprocal Traits, and Opposing Traits?
I know those names sound scary and complicated, but fortunately their function is quite simple!
Suppression is helpful for managing potential conflicts between traits. For example, if you decide that a character shouldn’t gain the Happy emotion trait while the Miserable emotion trait is active, then simply set Miserable to suppress Happy.
For example, we use opposing traits to prevent your character’s sister from also being their grandmother. Or your Lazy character from also being Active.
Activating and deactivating trait selections based on these categories is handled automatically within the Character Creator, but there are also HasOpposingTrait and HasSupportingTrait conditional commands if you need to check against them in scripts.
More personally, which are some of your favorite Traits in the game?
As the resident harbinger of chaos, Quirks are my favorite since they’re often the product of my, “Wouldn’t it be fun/dumb if…” moments. For example, the Shameless trait ignores the rules of public decency - to you, all plants are toilets - without ever becoming embarrassed. The Eccentric trait lets you talk to certain inanimate objects. However, my favorite favorite is currently the Fickle trait, which introduces a random chance of waking up the next morning with different likes and dislikes.
And now for some more specific, modding questions that you all have had, including a few from specific users in our YouTube comments (thank you all so much for asking)!
How does tagging work in creating Traits?
Tags are assigned in the Organization tab of the Traits Editor, and determine what the trait can be assigned to and/or whether it is visible in the UI. Here are some of our commonly used tags:
AvatarCreation: Allows the trait to be viewed and selected in the Character Creator
Lifestage Tags (e.g. _Adult, _Elder, etc.): Determines which lifestage a character must be in order to be assigned the trait
HumanTraits: Allows the trait to appear as an option when assigning traits to a human
Hidden: Hides the trait in the UI
You can also create your own tags to use however you wish!
Another way tags are critical to traits has to do with Interaction Script Wrappers, but that’s covered in a different answer.
How do you build out a script for a Trait, and what kind of scripts can you give Traits?
Each trait comes with a set of built-in scripts located in the Function tab of the Traits Editor:
OnAdd: Runs immediately after the trait is assigned
OnRenew: Runs when a timed trait is assigned to a character that already has that trait active (this also resets the trait’s timer)
OnRemove: Runs immediately after the trait is removed
How you use these scripts is entirely dependent on what you need your trait to do, but here is my typical script set-up using the Caffeinated trait as an example. For context, the Caffeinated trait fully satisfies the Rest need for a period of time before resulting in a caffeine crash based on how much caffeine you drank.
The OnAdd script is where I put any HUD (Heads Up Display) notifications, immediate effects, and variable setup. For Caffeinated, this includes:
Fully satisfying the Rest need
Creating a coffeeCount variable on the character
Showing a HUD notification that you got the trait
OnRenew scripts are where I usually handle any variable changes or repeating effects. Keep in mind that OnRenew scripts only work on timed traits that don’t have the Non-Renewable box checked.
The Caffeinated trait renews every time you drink caffeine while it’s active. Using methods outside the scope of this question, Caffeinated prevents your Rest need from increasing until it’s removed, so all its OnRenew script needs to do is increment the coffeeCount variable on the character.
OnRemove is where I trigger any final effects, cleanup variables, and revert things to their original state. Once Caffeinated is removed, its OnRemove script does the following:
Fires off a “Here comes the caffeine crash!” thought bubble
Calculates how much the Rest need will increase based on the coffeeCount variable
Increases the Rest need by that amount
Deletes all trait-related variables from the character
And that’s basically it! All that said, these scripts are entirely optional and can be left empty when not necessary.
What is an Interaction Script Wrapper?
When it comes to visual scripting, nothing makes me start flipping tables faster than nightmare webs of chained conditionals. They are overwhelming to look at, complicate the debugging process, and generally give that “there’s gotta be a better way” feeling that makes my inner programmer cry.
So when faced with the prospect of manually adding HasTrait conditionals to every interaction affected by traits, I whined about it until one of our amazing(ly patient) engineers came up with the Interaction Script Wrapper.
Wrappers are like a burger bun around an Interaction meat patty, allowing you to run additional commands before and after the interaction. They live under the Function tab in the Traits Editor, where you can define any number of Wrapper scripts to trigger off interaction tags. For example, the likes_exercise trait has a wrapper that activates whenever the character performs an interaction tagged as exercise.
What this means is that if you have a trait that applies the same effect to a large set of interactions, instead of copying and pasting the same handful of commands into all those scripts you simply need to throw a tag on those interactions and the Wrapper handles everything automatically. It also removes the need for chained conditionals if multiple traits could affect the interaction.
The general structure of a wrapper is:
Commands To Run Before The Interaction -> RunEmbeddedInteraction (aka The Interaction) -> Commands To Run After The Interaction
Here’s an in-game example showing the Wrapper script for the Athletic trait, which grants bonus Fitness XP after interactions with the skill_fitness tag.
The main thing to note here is that the RewardSkillPractice command only fires if the interaction successfully completes (i.e. the script ends on a green node), otherwise that XP would be granted even if you canceled the interaction midway. If successful completion doesn’t matter for your Wrapper, simply have the red node also connect to the next command.
Here are two final notes about Wrappers to keep in mind while scripting:
Only 1 Wrapper can be applied to an interaction at a time. If the character has multiple traits with Wrappers that trigger off the same interaction tag, the system will choose one at random.
Interactions can access variables declared in a Wrapper before the RunEmbeddedInteraction command, but Wrappers can’t access variables declared in interactions.
A question from @andrewfleming4027:
Can you also personalize your character's traits to interact with other characters' traits? For instance, I noticed you can link objects to traits (e.g., associating a fireplace with the 'cozy' trait), but can you create a custom trait for your character, like 'rugged,' that involves them responding negatively to characters possessing the 'fragile' trait?
For conversations, absolutely! We have a lot of tools in place to allow dialogue scenarios based on the relationship between the two characters - which is marked by Relationship traits - so there’s no reason you can’t create custom scenarios based on other types of traits.
On interactions it’s a little different. Technically, you can simply add a HasTraitTarget conditional with a unique outcome to the interaction script, however we don’t currently have an easy way to trigger effects based on another character’s traits on a large scale yet like we do with Interaction Script Wrappers. As we continue developing our tools, we hope to add more user-friendly ways to support this type of trait usage.
A question from @user-lv6cl4dy1l:
Can we also assign traits to buildings that will attract a certain personality or lifestyles of characters, to frequent those lots more often than others?
Currently we can’t assign traits to buildings or lots, but that’s a fun idea! Right now the best way to draw certain personality types to a specific location is to increase the Trait Appeal for the desired traits on interactions around that area.
A question from @judialbert1349:
Does the color-coding on the traits in character creator indicate which tags they fall under? How many "slots" is each individual character allowed to have, and are there limits or recommendations on the number of each kind of tag?
The color-coding indicates the subcategory of Personality the trait falls under, which is keyed off of the trait’s tags so you’ve got that part correct! We decided to limit characters to 2 slots per subcategory, except for Likes/Dislikes which allows 5 each. This is to avoid what we’ve been calling “Trait Soup”, where too many conflicting Interaction Script Wrappers causes the character to behave and react as though it were doing so completely at random.
A question from @katefosk8906:
Can we have conditional emotions? So some hungover people might be sad, others angry, some just withdrawn depending on their personality?
Most certainly! To use your hungover example, when someone receives the Hungover condition its OnAdd script could increase or decrease certain emotion stats based on the character’s personality traits with HasTrait conditionals.
Thank you all so much for all of your questions and continued support leading up to our Early Access! As always, please continue to ask us questions on our social channels, and we will continue to answer them both in blog posts like this and on our channels.