Skip to content

Character Attributes

Tailraise has several attributes in the game that each NPC can have set, which can be then used with the Tailraise Parser or with different Game Functions in order to change outcomes, dynamically change text that appears based on the player's current look, or change how a scene plays out based on their anatomy, etc.

Bools, Strings, and Integers

In order to understand this system better, you will need to know these terms and how they are used in Tailraise.

Bools

This is basically just a true or false.

For example, we have a bool named isBald. If this is checked in Unity, it means the player has no hair and is bald.

Behind the scenes, in your save file, you would see this as:

isBald = false

These are primarily used in conditional checks in a scene, where if the statement is true, we display the text. If it's not true, it never shows.

For example, we might have:

<<if_pc_isBald>>You reach up and gently stroke the top of your bald head.<</if_pc_isBald>>

<<!if_pc_isBald>>You reach up and gently run your fingers through your hair.<</if_pc_isBald>>

This means the first statement shows if isBald is true. So, if you are bald, you see the first one.

The second one is hard to see the difference. The ! at the start of it denotes the opposite should apply. So, normally, we are looking for isBald = true. In this case, we are now looking for isBald = false. If this matches, we show the second sentence instead.

For any bool, you can utilize the conditional text system this way.


Strings

This just means "string of text", for example, eyeColor = "blue". "blue" is the string.

Strings are primarily used in the Dynamic Text Replacement System.

An example would be when you want to pull the NPC's eye colour, like above. We do not know what the player might set their eye colour to, so we need to use this system to retrieve this in our writing:

You open your [[pc.eyeColor]] eyes slowly and let out a yawn.

If the player has eyeColor = "blue" this would then become:

You open your blue eyes slowly and let out a yawn.

Any attribute that is a string is able to be used in this way. Some of these are also used in Helper Systems.


Integers

Commonly just called int. These are whole numbers (no decimals!). We use these for things like the game time (in minutes) to determine when a player should be allowed to unlock their cage, pick up their clothes, and more. Some of these are used for sizeLevel type variables to use a list to determine which size adjective to use.

We don't typically use these in most systems, as they are used by the conditional text system, dynamic text replacement system, and helper systems.


Helper Systems

We have several helper systems in the game which use adjectives, size levels, and more to create descriptions or figure out other variables.

The below helper systems might not reflect the current game versions and should just be used as examples. If they have changed, Taw will adjust them accordingly in your writing for any submissions.

If you need something added, please talk to Taw.

skinOrFur

One of those most common ones you'll probably need is determining if the user has skin, fur, scales, feathers, and so on.

To use this in your writing, simply use [[pc.skinOrFur]] You can also replace pc with an NPC's ID, such as [[flint.skinOrFur]].

This is set up using the following code

    private string GetSkinOrFur() => species switch
    {
        "fox" => "fur",
        "wolf" => "fur",
        "rabbit" => "fur",
        "horse" => "fur",
        "cat" => "fur",
        "human" => "skin",
        "dragon" => "scales",
        "avian" => "feathers",
        "kobold" => "scales",
        _ => skinType
    };

If the species is not listed, it defaults to using the player's skinType field, which usually lists fur, skin, scales, etc.

pupName

When you want to have an NPC call the player by a pet/pup name, please use [[pc.pupName]].

Please use this instead of hard coding it in, unless it makes sense in a scene, such as kitten play vs puppy play vs horse play.

    private string GetPupName() => species switch
    {
        "fox" => "pup",
        "wolf" => "pup",
        "dog" => "pup",
        "cat" => "kitty",
        "rabbit" => "bun",
        "horse" => "colt",
        "deer" => "fawn",
        "bat" => "pup",
        _ => "toy"
    };

If the species cannot be found, such as human in this case, it defaults to using "toy" as the pup name.

nose

You can pull the literal string of the player's nose using [[pc.noseType]] but you are also able to use this command, [[pc.nose]] for one based off their species.

    private string GetNose() => species switch
    {
        "fox" => "muzzle",
        "wolf" => "snout",
        "rabbit" => "snout",
        "horse" => "muzzle",
        "cat" => "snout",
        _ => noseType
    };

hand

The player's handType string is usually plural, so this is best used when you need the singular version of their hand, based on their species.

You can use this in writing by using [[pc.hand]]

    private string GetHand() => species switch
    {
        "fox" => "paw",
        "wolf" => "paw",
        "rabbit" => "hand",
        "horse" => "hand",
        "cat" => "paw",
        "human" => "hand",
        _ => handType
    };

furSummary

This one puts together a very simple description using furColor plus skinType.

You use this in writing by using [[pc.furSummary]].

private string GetFurSummary() => $"{furColor} {skinType}";

Examples that it might return: furColor = "red"
skinType = "fur"

red fur

furColor = "white"
skinType = "scales"

white scales

furColor = "blue and orange striped"
skinType = skin"

blue and orange striped skin

heightDescription

This will return a few difference variables based on how big or small the player's height is.

You can use this by writing [[pc.heightDescription]].

    private string GetHeightDescription() => height switch
    {
        <= 130 => "tiny",
        <= 150 => "short",
        <= 170 => "average",
        <= 190 => "tall",
        > 190 => "towering"
    };

If the player was 155 cm tall, this would return short because it's above 150 but less than 170.

hairDescription

This one will return a few things based on if the player is bald or not.

If they are bald, it will use their species to determine what to put.

If they have hair, it will use their hairLength, hairColor, and GetHairType helper to get their hair.

To use this, you would write [[pc.hairDescription]].

    private string GetHairDescription()
    {
        if (isBald)
        {
            return species switch
            {
                "human" => "smooth scalp",
                "lizard" => "bare, scaled head",
                "dragon" => "scaly head",
                "cat" => "short fur",
                "fox" => "soft fur",
                "wolf" => "thick fur",
                _ => $"{GetSkinOrFur()}-covered head"
            };
        }

        return $"{hairLength}, {hairColor} {GetHairType()}";
    }

and

    private string GetHairType() => species switch
    {
        "lizard" => "scales",
        "dragon" => "scales",
        "cat" => "fur",
        "fox" => "fur",
        "wolf" => "fur",
        _ => "hair"
    };

So if the player is has isBald = true and species = "wolf", this returns thick fur.

If the player is a fox, their hairColor = "white", and their hairLength = "short" this then returns short, white fur.

tailLength

Tails use an int in order to set their length, and we use this to determine the description.

To use this, you would write [[pc.tailLength]].

    private string GetTailLengthDescription() => tailLengthLevel switch
    {
        0 => "lack of",
        1 => "short",
        2 => "medium-length",
        3 => "long",
        4 => "luxurious",
        _ => "unknown"
    };

If the player has tailLengthLevel = 3, then it would return long.

You still need to write "tail", or "appendage" or whatever else after.

dickDescription

We use a combination of two helpers to determine this based on the player's dickType and dickSizeLevel.

To use this, you would write [[pc.dickDescription]].

    private string GetDickSizeDescription()
    {
        string adjective = GetDickSizeAdjective();
        return string.IsNullOrEmpty(adjective) ? dickType : $"{adjective} {dickType}";
    }

    private string GetDickSizeAdjective() => dickSizeLevel switch
    {
        <= 0 => "tiny",
        1 => "small",
        2 => "", // Average sized, no descriptor
        3 => "large",
        4 => "huge",
        5 => "monstrous",
        _ => "unknown"
    };

If the player has dickType = "canine" and dickSizeLevel = 3, then this would return large canine.

If the player has dickType = "feline" and dickSizeLevel = 2", then this returns just feline.

This does NOT add on "cock", "dick", "shaft", etc. afterward so you can fill this in yourself after.

knotDescription

This one just simply uses the knotSizeLevel to determine what to return.

To use this, you would write [[pc.knotDescription]].

    private string GetKnotSizeDescription() => knotSizeLevel switch
    {
        <= 0 => "tiny",
        1 => "modest",
        2 => "thick",
        3 => "fat",
        4 => "massive",
        _ => "unknown"
    };

If the player has a knotSizeLevel = 3, this would return fat.

This does NOT add on "knot", "bulb", etc. afterward so you can fill this in yourself after.

slitType

This one checks for what type of slit characters with genital slits have, since it might use specific language.

To use this, simply write [[pc.slitType]].

    private string GetSlitTypeDesc() => slitType switch
    {
        "vent" => "vent",
        "cloaca" => "cloaca",
        _ => slitType
    };

sheathDescription / sheathSize

This system got replaced to be used with sheathSize instead, both are interchangeable and give a size description of the sheath based on it's size.

This describes a sheath but you need to add the word 'sheath' or whatever else you want to use.

To use this, simply write [[pc.sheathDescription]] or `[[pc.sheathSize]].

    private string GetSheathSize() => sheathSizeLevel switch
    {
        <= 0 => "barely-noticeable",
        1 => "tiny",
        2 => "small",
        3 => "medium-sized",
        4 => "thick",
        5 => "large",
        6 => "massive",
        _ => "medium-sized"
    };

So if the player has sheathSizeLevel = 4, this would return thick.

ballsDescription

This describes the balls based on their size, but leaves the word 'balls' or whatever else you choose out, so you can set this yourself.

To use this, simply write [[ballsDescription]].

    private string GetBallsSizeDescription() => ballsSizeLevel switch
    {
        <= 0 => "tiny",
        1 => "small",
        2 => "sizeable",
        3 => "plump",
        4 => "heavy",
        _ => "sizeable"
    };

So if the player has ballsSizeLevel = 3 it would return plump.

scentDescription / scentIntensity

Every character can have a scent to them and this can be used in writing to describe the intensity of it.

To use this, simply write [[pc.scentDescription]].

    private string GetScentIntensity() => scentLevel switch
    {
        0 => "clean",
        1 => "subtle",
        2 => "faint",
        3 => "noticeable",
        4 => "sharp",
        5 => "strong",
        6 => "powerful",
        7 => "overwhelming",
        _ => "clean"
    };

So if the player has scentIntensity = 5 it instead returns strong.

You can pair this with pulling their scent itself, such as [[pc.scentIntensity]] [[pc.scent]]


List of Attributes

Here is the full list of attributes and what type they are so you can know if you can use it as either conditional text system (bools), dynamic text replacement system (strings), and helper systems (combination of multiple).

This system is constantly evolving and changing as the game is developed. Many of these fields may be repurposed, removed, or modified to better fit the game needs. Some of these may no longer be relevant as other game systems were developed to take their place.

A lot of these were added in as placeholders to be used for future systems and content. Please ask Taw for clarification if you're unsure how to use some of these, in case it's not fully implemented and needs work.

    [Header("Identity")]
    [Tooltip("The character's name, use [[pc.name^]] to capitalize it. Default is Wanderer on new game.")]
    public string name = "Unnamed"; 
    [Tooltip("Player's species, use [[pc.species]] to pull.")]
    public string species = "human";
    [Tooltip("Optional subspecies to pull.")]
    public string subspecies = "";
    [Tooltip("Player gender, mostly unusued in favor of pronouns")]
    public string gender = "male"; // Character's gender, mostly unused to pull but we set this anyways in characters.
    public PronounSet pronouns = new(); // Use [[pc.they]], [[pc.them]], [[pc.their]] or [[pc.theirs]] to pull these.
    public int age = 24; // Age if needed, we specify this for all characters.
    public string sexuality = "pansexual"; // Character's sexuality in case we want to lock a choice using check_attribute_equals("npcID", "sexuality", "straight") or something

    [Header("Stats (Encounters)")] // For the encounter system, we set these relatively high for NPCs, such as 10
    public int strength = 3;
    public int dexterity = 3;
    public int intelligence = 3;
    public int charisma = 3;

    [Header("Physical")]
    [Tooltip("Height in centimeters")]
    public int height = 165;
    [Tooltip("Overall build scale.\n1-5 = Slim\n6-10 = Thin\n11-15 = Average\n16-20 = Stocky\n21-25 = Chubby\n26-30 = Plump\n31-35 = Fat")]
    [Range(1, 35)]public int buildLevel = 15;
    [Tooltip("Shoulder width.\n1-2 = Narrow\n3-4 = Thin\n5-6 = Modest\n7-8 = Wide\n9-10 = Broad")]
    [Range(1, 10)]public int shoulderSizeLevel = 5;
    [Tooltip("Hip width.\n1-2 = Narrow\n3-4 = Petite\n5-6 = Full\n7-8 = Wide")]
    [Range(1, 8)]public int hipSizeLevel = 6;
    [Tooltip("Butt size.\n1-2 = Flat\n3-4 = Soft\n5-6 = Small\n7-8 = Plump\n9-10 = Massive")]
    [Range(1, 10)] public int buttSizeLevel = 5;
    [Tooltip("Belly size.\n1-2 = Flat\n3-4 = Slim\n5-6 = Soft\n7-8 = Chubby\n9-10 = Large\n11-12 = Round\n13-14 = Bulging")]
    [Range(1, 14)]public int bellySizeLevel = 1;
    [Tooltip("Muscle tone.\n1-2 = Soft\n3-4 = Slightly Toned\n5-6 = Fit\n7-8 = Defined\n9-10 = Muscular")]
    [Range(1, 10)]public int muscleToneLevel = 5;

    [Header("Skin/fur")]
    public string skinType = "skin"; // skin, fur, feathers, scales, mostly used with [[pc.skinOrFur]]
    public string furColor = "white"; // still used for skin and scales, put a colour always

    [Header("Eyes")]
    public string eyeColor = "blue"; // If hasHeterochromia = true, this should match leftEyeColor
    public string leftEyeColor = "blue";
    public string rightEyeColor = "blue";
    public bool hasHeterochromia = false;

    [Header("Hair")]
    public bool isBald = false; // If they are bald or not
    public string hairColor = "black";
    [Tooltip("Hair length.\n1 = Bald\n2 = Buzzed\n3 = Cropped\n4 = Short\n5 = Shoulder-Length\n6 = Lengthy\n7 = Long\n8 = Lustrous")]
    [Range(1, 8)]public int hairLengthLevel = 4; // short
    public string hairStyle = "messy";

    [Header("Tail")]
    public bool hasTail = false;
    public string tailType = "none";
    [Tooltip("Tail length.\n0 = Non-existent\n1 = Short\n2 = Medium-Length\n3 = Long\n4 = Luxurious")]
    [Range(0, 4)]public int tailLengthLevel = 0;

    [Header("Misc")]
    public string earType = "round";
    public string hornType = "none";
    public string wingType = "none";
    public string noseType = "nose";
    public string handType = "hands";
    public string feetType = "feet";

    [Header("Scent")]
    public string scent = "clean";
    public string armpitScent = "neutral";
    public string crotchScent = "neutral";
    public string ballScent = "neutral";
    [Tooltip("Scent Intensity\n0 = Clean\n1 = Subtle\n2 = Faint\n3 = Noticeable\n4 = Sharp\n5 = Strong\n6 = Powerful\n7 = Overwhelming")]
    [Range(0, 7)]public int scentLevel = 1;

    [Header("Cock")]
    public bool hasCock = true;
    public string dickType = "human";
    public string dickColor = "pink";
    [Tooltip("Dick size.\n0 = Tiny\n1 = Small\n2 = (null)\n3 = Large\n4 = Huge\n5 = Monstrous")]
    [Range(0, 5)]public int dickSizeLevel = 2;
    public bool hasKnot = false;
    [Tooltip("Knot size.\n0 = Tiny\n1 = Small\n2 = Medium-sized\n3 = Fat\n4 = Massive")]
    [Range(0, 4)]public int knotSizeLevel = 2;
    public bool hasBarbs = false;
    public bool hasSpines = false;
    public bool hasRidges = false;

    [Header("Balls related")]
    public bool hasBalls = true;
    [Tooltip("Balls size.\n0 = Tiny\n1 = Small\n2 =Sizeable\n3 = Plump\n4 = Heavy")]
    [Range(0, 4)]public int ballsSizeLevel = 2;

    [Header("Slit Related")]
    public bool hasSlit = false;
    public string slitType = "vent"; // vent, cloaca
    public string slitAppearance = "neat"; // neat, taut, plump, pouty, hidden
    public string slitColor = "flesh"; // For colour support

    [Header("Sheath related")]
    public bool hasSheath = false;
    public string sheathType = "none";
    [Tooltip("Sheath size.\n0 = Barely-noticeable\n1 = Small\n2 = Soft\n3 = Plump\n4 = Thick\n5 = Large\n6 = Massive")]
    [Range(0, 6)]public int sheathSizeLevel = 3;

    [Header("Butt related")]
    public string anusType = "tight";
    public bool isPlugged = false;
    public string plugType = "buttplug";

    // Advanced Anal State
    public int analTightnessLevel = 3; // 0 = loose, 5 = vice-tight
    public string analLubeState = "dry"; // "dry", "slick", "dripping"
    public List<string> analContents = new(); // e.g., ["cum"], ["piss", "lube"]
    public float analStretchDecayTimer = 0f; // time since last stretch event
    public bool analGapedRecently = false; // auto-clears over time
    public int analLoosenessLevel = 0; // long-term stretch memory (0 = pristine, 5 = widely trained)

    [Header("Vagina related")]
    public bool hasVagina = false;
    public string vaginaType = "none";
    public string pussyStyle = "soft";

    public int wetnessLevel = 1;
    public int tightnessLevel = 0;

    [Header("Breasts related")]
    public bool hasBreasts = false;
    [Tooltip("Breast size.\n1-2 = Flat\n3-4 = Small\n5-6 = Modest\n7-8 = Large\n9-10 = Huge")]
    public int breastSizeLevel = 1;
    [Tooltip("Areola size.\n1 = Tiny\n2 = Small\n3 = Average\n4 = Wide\n5 = Broad")]
    public int areolaSizeLevel = 3;
    public string nipples = "standard";
    [Tooltip("Nipple size.\n1 = Tiny\n2 = Small\n3 = Average\n4 = Large\n5 = Prominent")]
    public int nippleSizeLevel = 3;


    [Header("Cum related")]
    public string cumAmount = "normal";
    public string cumFlavor = "neutral";
    public bool isCumInflated = false;
    public float cumInflationLevel = 0f; // 0 = flat, 1 = slight bump, 5+ = distended
    public float cumInflationDecayTimer = 0f; // tracks how long since last fill

    [Header("Exposure / exhibitionism")]
    public bool cockExposed = false;
    public bool vaginaExposed = false;
    public bool breastsExposed = false;

    [Header("Player States")]
    public bool isInHeat = false;
    public bool virginity = false;
    public bool pregnant = false;
    public bool lactating = false;
    public bool hasCumOnFur = false;
    public bool hasCumInMouth = false;
    public bool hasCumInAnus = false;
    public bool hasCumInVagina = false;

    [Header("NSFW Stats")]
    public int arousal = 0;
    public int libido = 5;
    public int orgasmCount = 0;
    public int orgasmDenialCount = 0;

    [Header("Chastity related")]
    public bool cockIsLocked = false;
    public string cageType = "standard";
    public string cageSize = "snug";
    public string keyholder = "";
    public int unlockAttempts = 0;
    public int daysLocked = 0;
    public bool isWearingBelt = false;
    public string beltType = "leather";

    [Header("Social")]
    public string temperament = "friendly";
    public int dominanceLevel = 5;