Functions
There are several helper functions written to be used to direct the game where we need it to go, add progression, etc.
Here is a list of the most common ones used.
More options will be added in time, but these should be very beneficial to help you give progression or influence the game outside of just written content.
talk_to_npc
Typically this is used when you want to offer a choice to a player to talk to an NPC who isn't attached to the tile in the usual way.
This means that the NPC needs to be in the map file's global NPC list in order for them to be accessible on that map on any tile that uses this command, or it won't know who to load.
In writing, you would add this to a scene:
~ talk_to_npc("NPCNAME")
Usage:
+ [Head to your room]
~ talk_to_npc("private_room")
-> DONE
We write it this way to satisfy Ink's requirement to include an endpoint or it won't compile. The talk_to_npc
command triggers first and loads the file if it finds it.
leave_npc
This one is used heavily in the game for every NPC to have a way to return to the tile mode instead of NPC mode.
You typically create an option for the player to leave an NPC at different points so they cannot be stuck talking indefinitely to an NPC.
Usage:
+ [Decide to leave]
~ leave_npc()
-> END
add_eflag
This is our bread and butter for progression typically. By using this, we add to the PlayerState
a new flag, and we can check that flag to show or hide choices.
If you need to progress a quest step, or NPC so new options appear (like after seeing Taw's cage, more options show up, we track this using taw_seen_cage
), you would use this function.
Usage:
~ add_eflag("taw_seen_cage)
has_eflag
Typically, when checking progression to show a choice or lock the player from choices.
Usage:
+ { has_eflag("taw_private_cage_check") } [Head Back to Taw's place]
-> taw_after_hours_intro
In this example, if the player does not have taw_private_cage_check
, they do not see this option at all.
{ has_eflag("intro_complete"):
{ has_eflag("taw_seen_cage"):
-> casual_talk_after_cage
- else:
-> casual_talk
}
- else:
-> first_time_intro
}
In this example, this is written into the start
branch when you talk to the NPC.
If you do not have intro_complete
, you get sent to first_time_intro
.
If you have intro_complete
but not taw_seen_cage
you get sent to casual_talk
.
If you have intro_complete
and taw_seen_cage
, you get sent to casual_talk_after_cage
.
go_to_tile
This is used when you need to teleport the player somewhere. Keep in mind, they need to teleport to a valid tile if you use this. It will also take them out of dialogue with whoever they are talking to immediately.
The format to use for this is go_to_tile("mapID", x, y)
Usage:
+ [Travel to the tavern]
~ go_to_tile("1", 4, 2)
-> END
This would teleport you to Flint's tavern, since Twigleaf is mapID 1 (this might change to be more readable), and this is it's x and y coordinates.
If you need to know a specific coordinate, please ask Taw.
mark_npc_met
This is used so the game knows if someone has been met or not. You don't need to use this on the first scene with the player. You can do it when they have been formally introduced. This makes it so when you get a button choice, instead of it reading [Talk to the large wolf]
it instead says [Talk to Flint]
.
Usage:
~ mark_npc_met("flint")
check_attribute
This usually is used in navigation choices to make it so if you do not meet the condition(s), it will grey the option out, typically with a tooltip to explain to the player what's needed to access the scene. This is great if you want to showcase a bunch of content and tease it, but the player needs to make some changes to access it.
This only works on bools
, so things like hasBald
would work since it's true or false, but if you use it to check eyeColor
, it wouldn't work since it's a colour that gets returned.
You can use not
modifiers for different attributes and also check multiple at once.
The usage is typically check_attribute("ID", "attribute")
where ID can be "pc" (player), "flint", etc. Attribute can be any bool.
Usage:
+ [Let him suck you off ~ check_attribute("pc", "hasCock") and not check_attribute("pc", "cockIsLocked") ~ Requires an unlocked cock.]
~ advance_time(55)
-> taw_after_hours_cock
In this example, if the player does NOT have a cock or their cock is locked in chastity at the moment, the option would be greyed out with the tooltip Requires an unlocked cock
.
check_attribute_equals
Similar to the check_attribute
, but this version can be used to check a value and compare it to see if it matches or not, so this can be used for more than just bools.
The usage is typically check_attribute_equals("ID", "attribute", "expectedValue")
This hasn't been tested extensively yet, but should work for comparing strings, like check_attribute_equals("pc", "eyeColor", "blue")
to see if they have blue eyes, and if so, do something.
Relationship Functions
These functions primarily are used for things around the relationship system. Keep in mind this system is still early and these functions might change or be extended further.
All NPCs can have an infinite number of relationship stats with different names. You can set it from anything such as "friendliness", "dominance", "submissiveness", or whatever you want.
set_npc_value
This function sets a relationship stat to exactly the value specified.
This function does NOT add or subtract. Use this when making a new value for the first time, or if you need to hard reset to a specific number.
The structure is set_npc_value("npcID", "key", value)
.
Usage:
~ set_npc_value("flint", "romance", 5)
This would set the "romance" stat with Flint to 5, even if it was previously 90, or didn't exist.
add_npc_value
How to add or subtract from one of the relationship stats with an NPC.
Keep in mind, stats cannot go below zero, so if you try to subtract 50 from a stat that is at 40, it'll just go to 0.
The structure is add_npc_value("npcID", "key", delta)
.
Delta is what you want to add or subtract.
Usage:
~ add_npc_value("flint", "romance", 5)
This would check the "romance" stat for Flint with the player and add 5 to it, so if it was 0, it would now be 5.
~ add_npc_value("flint", "romance", -15)
This would check the "romance" stat for Flint with the player and subtract 15 from it, so if it was 60, it would now be 55.
add_npc_value_clamped
When you need to change a value, but keep it from going above a certain maximum, you'd want to use this.
This is good for repeatable scenes but you don't want basic options to be able to infinitely increase a relationship, so they might only get the player to 30 and they'd need to do heavier actions (kiss them instead of shake their hand) to get further progress. Otherwise, someone could just pet Taw 100 times to max out a stat, where this makes it so petting Taw constantly only get it to a max of 10, etc.
The structure is add_npc_value_clamped("npcID", "key", delta, maxValue)
.
Usage:
~ add_npc_value_clamped("taw", "affection", 5, 10)
Every time this scene is repeated with this, it tries to add +5 to "affection", but it will never raise it above 10.
get_npc_value
This is how you can check to see if specific relationship stats are above or below certain numbers, and use them to determine which choices can be seen.
The structure is get_npc_value("npcID", "key")
Usage:
+ { get_npc_value("taw", "friendliness") >= 0 } [This option is always visible]
-> always_visible
+ { get_npc_value("taw", "friendliness") >= 3 } [This option is for Taw's friends]
-> only_friends_see_this
In this example, if the "friendliness" stat with Taw is equal to or above 3, you see the choice [This option is for Taw's friends]
. Otherwise, it won't appear.
Time Functions
Here are functions related to checking the current time or managing time and advancing it to push plots or make things take a long time, etc.
Tailraise automatically moves time 5 minutes for every action taken, such as moving tiles, talking to an NPC, leaving an NPC, or choosing any options.
get_time_segment
If you need to get a certain time of day to use in the story, such as making it so different flavour texts appear on a tile based on time of day, you can use this.
The command is just ~ get_time_segment()
and takes no parameters.
This only can return:
- Morning (6AM to 11:59AM)
- Afternoon (12PM to 5:59PM)
- Evening (6PM to 9:59PM)
- Night (10PM to 5:59AM)
Usage:
~ temp time = get_time_segment()
{ time == "morning":
You can hear the birds singing and people starting their day.
}
{ time == "afternoon":
You can smell coffee and various scents of people's lunches.
}
{ time == "evening":
The day is quieter now and less people are around.
}
{ time == "night":
It's completely empty and devoid of life at the moment.
}
We use ~ temp time
to set a temporary variable in Ink to pull this when the scene is accessed in case the time changes and should use a different line.
advance_time
When you need to advance time when an option is chosen, this function is ideal to specify how much time to move in minutes.
Time always moves 5 minutes, so if you want to advance time an hour, you would use 55 minutes instead.
The way to use this is advance_time(int)
where int
is the time in minutes.
Usage:
+ [Take an hour long nap]
~ advance_time(55)
-> hour_nap_scene
advance_to_morning
Advances time to the morning (6AM) immediately when called.
Usage is ~ advance_to_morning()
.
advance_to_afternoon
Advances time to the afternoon (12PM) immediately when called.
Usage is ~ advance_to_afternoon()
.
advance_to_evening
Advances time to the evening (6PM) immediately when called.
Usage is ~ advance_to_evening()
.
advance_to_night
Advances time to the night (10PM) immediately when called.
Usage is ~ advance_to_night()
.
npc_available
Checks if the NPC is available at this hour. Use this for NPCs on the current tile to add in some flavour text or dialogue if they see the player walking by, etc.
Each NPC can have a schedule set for specific hours they can show up on that tile. So you can make them show up between:
10AM to 2PM
5PM to 8PM
and so on. Multiple times can be set per NPC so they have varying schedules.
This function is a bool
so it returns true or false.
Usage:
~ temp flintAvailable = npc_available("flint")
{ flintAvailable == true:
Flint gives you a cocky grin as you walk into the Tavern.
}
Typically, this is used on the tile itself. Don't use this in an NPC file, as it wouldn't make sense in almost all cases.
set_flag_time
Primarily used when we set a flag that has a specific time before it becomes true
.
This is set using ~ set_flag_time("flagName", hours)
.
This function automatically converts to hours for the variable, instead of using minutes. Hours will be calculated behind the scenes to check game time, which is in minutes.
Usage:
~ set_flag_time("clothesReady", 24)
Your clothes will be ready for pickup in 24 hours from now.
check_flag_time
To check if a flag time has passed the time it was set to, we use this command.
We use this as ~ check_flag_time("flagName")
.
Usage:
+ { check_flag_time("clothesReady")} [Pick up your clothes]
-> clothes_are_ready
If the flag time hasn't passed (24 hours in this case), then the option won't show yet.
{ check_flag_time("clothesReady):
<color=\#F6CD4B>"Your clothes are ready. Let me know when you're ready to try them on."</color>
- else:
<color=\#F6CD4B>"I'm still working on your clothes. Anything you need?"</color>
}
This will show the first line if the clothes are ready and it's been 24 hours.
If not, it will show the second line instead.
check_flag_time_clear
This option is the same as check_flag_time
, but if it returns true (the time has passed), it removes the flag from the PlayerState.
This one is not used to change dialogue or choices, but simply when you want to clear the flag after it's true.
Ideal use is to lock a scene behind the flag being true, and then at the end of the scene, use:
~ check_flag_time_clear("flagName")
.
get_flag_time_duration_hours
If you need to get the flag for use in dialogue, such as saying "you'll be free to go in 30 hours", you can use this.
This only checks how long the duration is, not the time remaining. See get_flag_time_remaining_hours
for this instead.
We use this as ~ check_flag_time_duration_hours("flagName")
.
Usage:
~ temp timer = get_flag_time_duration_hours("clothesReady")
You remember you were told it would take {timer} hours to be done, so you should check in later.
We use {timer} here, which is Ink's temporary variable, to pull the time.
get_flag_time_remaining_hours
If you need to use the remaining time, such as in dialogue to let the player know "Hey, there's 5 hours left until your clothes are ready", etc. You'd use this.
We use this as ~ check_flag_time_remaining_hours("flagName")
.
This can return negative hours and doesn't stop at zero. This might be reworked later to output something specific at 0 instead. In the meantime, do a check for if it's 0 or negative and set specific dialogue that should appear.
Usage:
~ temp timer = get_flag_time_remaining_hours("clothesReady")
You just remembered, you can't pick up your clothes for another {timer} hours.
We use {timer} here, which is Ink's temporary variable, to pull the time.
get_flag_time_state
This returns the state of the flag and is more clean than returning the remaining hours.
This returns either:
0
- No active timer
1
- Active timer
2
- Expired timer
So you can then use this to set up dialogue based on these states.
We use this as ~ get_flag_time_state("flagName")
.
Usage:
~ temp timer = get_flag_time_state("clothesReady")`
{ timer:
- 0:
<color=\#F6CD4B>"Did you need something?"</color>
- 1:
<color=\#F6CD4B>"Your clothes aren't quite ready yet, sorry."</color>
- 2:
<color=\#F6CD4B>"Your clothes are ready. Let me know when you're ready to try them on."</color>
}
This is how you'd use all three states using this function cleanly.
Encounter Functions
Anything related to the encounter system will be listed here and what it's purpose is. This will include stats related to encounters (strength, dexterity, intelligence, and charisma).
encounter_win
When leaving an encounter we've won, we use this option on the choices instead of leave_npc()
in order to make it so the player's movement goes through when they've won the encounter. Otherwise, their movement won't go through and they'll be stuck unable to progress.
We use this as ~ encounter_win()
Usage:
+ [Take your victory]
~ encounter_win()
-> END
encounter_lose
When leaving an encounter we've lost, we use this option on the choices instead of leave_npc()
. This will cleanly exit the encounter and the player's movement won't go through.
We use this as ~ encounter_lose()
Usage:
+ [Accept defeat]
~ encounter_lose()
-> END
save_imprint
This is only used when we finalize the character customization and leave. This function saves a backup of the player's intended appearance, anatomy, and so on. This way, if they step on a trap, lose an encounter, or something else happens that randomly transforms them, they can then restore their imprint later.
We use this as ~ save_imprint()
.
restore_imprint
This is in conjunction with save_imprint
and we use this at Attuner NPCs who have the ability to restore the player back to their intended form. This will restore their intended appearance back entirely from the backup that was made from the character creator.
We use this as ~ restore_imprint()
.
is_in_chastity
As the game develops and gets more complicated, we need a better way to check for all combinations if chastity exists in any manner.
We can still check individually using check_attribute
and use either cockIsLocked
or isWearingBelt
, however.
When you want to simplify a check, this is the ideal option to use.
Usage:
+ [Ask to be put back in chastity ~ not is_in_chastity() ~ Must not be in chastity to ask to be put back in! ~ Chastity]
-> thimble_new_lockup
This means the option is greyed out if the player currently is in a chastity cage or belt and won't work. The tooltip and content warnings are also added in this example.