Rain World

Rain World

Iterator Creator
 This topic has been pinned, so it's probably important
kroun  [developer] 29 Aug @ 5:50am
Custom Iterator Instructions
###############
# Information #
###############

This mod was made for The Melting Tundra, though it has been released as a seperate mod for all to use.
It is intended to aid in the creation of iterators without the need for coding knowledge.

###########
# NOTICE! #
###########

This mod is currently functional, but unfinished. It is a pretty big mod, I'd say, with some (At least for me) quite complicated code. While I would love to finish the mod in its entirety before releasing it, I
am under no illusions on the timescale of this. As such, it will be released in a "beta" so people can use it. Just note that some things may not work correctly. This is mostly in relation to ruined iterators, as well
as some unfortunate limitations. Though if you follow the following guidelines, you shouldn't experience too much issue:
- Ruined iterators have less support for stuff than functional iterators, so if you value stability for your mod, hold on with the ruined iterators for now.
- Saving might not work correctly sometimes. Switching to a new savefile and then back before switching to a new slugcat campaign can sometimes prevent any saving mistake shenanigans. (The current main issue appears to be that rarely the iterator's oraclestate is copied to newly started games if you switched from a slugcat that has visited the iterator in question).
- Custom Events might have some requirements or restrictions. Read the section carefully before making an event, especially after an update to this mod.

If you experience any issues, feel free to contact me through steam or discord.
The same goes for suggestions.

############################
# Setting Up Your Iterator #
############################

Custom Iterators are created by making a folder in your mod's main folder called "customoracles"
Inside this folder, create a txt file (Or use the template)

The custom iterator file is structured by adding lines with a define (A setting) seperated from the values (the value to be assigned to the define) by a colon (:)
Examples:

color:10,90,255

Some defines can also be configured with slugcat-specific values, with the value replaced by slugcat names and an accopmanying value encased in curly brackets ({})

Example:

color:default{10,90,255}hunter{10,80,255}survivor(20,100,255)

Any defines that you want to use slugcat-specific values for are required to have a default value.
Modded slugcats can be included, but requires a hook in CustomIteratorLoader.getSlugCatFromString(CustomIteratorValue index, SlugcatStats.Name slugCat), though how to do that will be explained in "How to hook into this mod.txt"
The normal, full default name for the slugcat must be used. For inv/sofanthiel/???, sofanthiel is used.


Not all defines can use slugcat-specific values.

Some defines have to be defined no matter what. Others can be left undefined if they are not used by your iterator. A few have default values if you do not input a value.

The following Defines exist as of currently:
(nameOfDefine: typeOfValue | function
### Defines (No slugcat-specific support) ###
id: text | id of the iterator. Usually 2 letters. Use a unique identifier to make sure your mod does not conflict with other iterators made with this mod.
room: text
region: text
!Deprecated: Use fromColor and toColor! gown: 6 numbers
palettes: 2 numbers
modules: text separated by commas. Must be text corresponding to existing modules. Currently only for functional iterators. Current list: Go down to the Modules section (For how to add custom modules: "How to hook into this mod.txt")
name: text
default slugcat: text (Same as for slugcat-specific values. Can be skipped if the iterator has no default slugcat)
iconName: text (Must have accompanying icon in the atlases directory (23x21 pixels) unless it is "GuidancePebbles" or "GuidanceMoon"
hasCollection: true/false | Default: true

### Defines (Can use slugcat-specific values) ###
ruined: true/false.
hasPearls: true/false.
readsPearls: true/false
color: 3 numbers
defaultBehavior: text (Must correspond to a behavior. See Section: behaviors)
x: number
y: number
hasThirdEye: true/false
thirdEyeColor: 3 numbers | Color of head symbol
thirdEyeSprite: text (Must correspond to a sprite. Commonly-used symbols: mouseEyeA5, Circle20 | Other suggested symbols: tinyStar)
thirdEyeScale: numbers (For Circle20 it is usually 0.2 while mouseEyeA5 usually uses 0.8) (Suggested Scales | tinyStar: 1.2 |
metalColor: 3 numbers | Affects color of the umbicilical arm /cord
hasHalo: true/false (Requires sunblock to show up)
haloColor: 3 numbers (Can be left undefined)
hasGown: true/false
ruinedGown: true/false
fromColor: 3 numbers
toColor: 3 numbers (Can be left undefined for a robe that is not gradient)
hueShift: Float
saturationShift: Float
lightShift: Float
eyeColor: 3 numbers
ruinedArm: true/false
nameForPlayer: text
hasKillSprite: true/false
initialSwarmers: number (If you do not wish to use neuron flies, write -1, NOT 0.)
acceptsneuronflies: true/false
pearlColor: 3 numbers x 3 (example: 255,255,255:255,10,60:10,55,205) Each set of numbers can have their own slugcat-specific values
deflectSpears: true/false


#################
# Conversations #
#################

To set up conversations for your iterators, make a folder named "text_(id)" inside text/text_eng in your main mod folder.
Each conversation needs its own txt file. The name determines when it will be used.
Current conversations (Conversation id | when the conversation happens | Extra Notes):
AfterGiveMark | Once the slugcat has recieved the mark of communication or after entering the iterator's chamber with one.
FirstConversation | When the slugcat first meets the iterator. Ruined iterators only.
SecondConversation | When the slugcat meets the iterator for the second time. Ruined iterators only.
numbers | For different colored pearls. Each pearl has its own number.
item name | For items. Filename is the name of the item.
38 | For misc pearls. RandomLine enabled by default.
40 | For iterator pearls. RandomLine enabled by default. | Append _id, where id is either ss (Five Pebbles), dm (Looks to the Moon) or xx where xx is the id of a custom iterator to make dialogue for pearls from a specific iterator.
132 | For broadcast pearls. Randomline enabled by default.


A conversation is structured with lines like this:
waittime:text:lingertime
waittime:text2:lingertime
waittime:text3:lingertime

You can use the following inside text for effects:
<LINE> | New line
<PLAYERNAME> / <PlayerName>: Is replaced with "little (nameForPlayer)"
<CAPPLAYERNAME> / <CapPlayerName>: Is replaced with "Little (nameForPlayer)"

You can prepend the following to text (prepend:waittime:text:lingertime) for effects and conditions.
CONDITIONAL:CONDITION
The following conditions exist: MARKEDSLUGCAT and SAWWITHOUTMARK
MARKEDSLUGCAT: true if the iterator gave the mark of communication to the slugcat.
SAWWITHOUTMARK: true if the iterator has seen the player without the mark of communication.
Example: CONDITIONAL:MARKEDSLUGCAT:0:line of dialogue:5
Conditions can be prepended with "!" for inverse effect. For example !MARKEDSLUGCAT will be true if the iterator did not give the mark of communication to the slugcat.
Lines with conditions will only happen if the conditions are fulfilled at the start of the conversation.

You can use the following special events (Currently only for functional iterators)

SPECIALEVENT:EVENTNAME,PARAMETER
The following special events exist: karma, manifoldCloseEyes, manifoldOpenEyes, GetToKillFac, FireEvent, panic
karma: Gives the slugcat the mark of communication in a similar fashion to Five Pebbles.
manifoldCloseEyes: Closes the iterator's eyes.
manifoldOpenEyes: Opens the iterator's eyes.
GetToKillFac,Number: Makes the killfac go to the specified number over a second or two. If it reaches 1, the player will be killed. Once it has reached the desired killfac, it will revert to 0.
FireEvent,FileName: Fires a Custom Event from the specified file.
Panic:Moon's malfunction. Untested, unaltered. Not recommended to use.
Conditions can be prepended to special events.

MANIFOLDWAIT:pauseframes
Makes the iterator wait for a set amount of time.

There's some settings you can use that changes how the conversation works. To use these, start the file with <settings> on the first line and place the settings before the <settings>, seperated by commas.
RandomLine: Enables randomization of text by inserting <NextRandomLine>. Lines of text will be divided such that all lines between a pair of <NextRandomLine> will count as its own seperate conversation. One of these conversations will then be chosen at random.

Conversation files can be appended with -slugcatname to make a different conversation for a specific slugcat.
The names used for this are: Survivor:white | Monk:yellow | Hunter:red | Rivulet:rivulet | Spearmaster:spear | Artificer:artificer | Saint:saint | Gourmand:gourmand | Inv/Sofanthiel/???:cant remember | Watcher:watcher

###################################
# Greetings and other such things #
###################################

Greetings are short (usually) sentences that are not counted as conversations. These are instead defined with the greetings.txt and pearlintro.txt file respectively.
They use a number of numbered lines and random lines to pick an appropriate response to the given action.
The current list of these "small conversations" are as follows (id | value for number | happens when):
greetings | Amount of visits to the iterator by the player | Happens when the player enters the iterator's chamber and also after recieving the mark of communication
pearlintro | Number of pearls read | Happens when the iterator is given a pearl
pebblespearlintro | Numbers not used | Happens when the iterator is given an iterator pearl (Pearls from an iterator's chamber)
releaseNeuronWarning | Number of times the player has annoyed the iterator (Will eventually be changed to number of times a neuron fly has been grabbed) | Happens when the slugcat grabs a neuron fly
noSpeakFinalMessage | Same as Above | Happens when the slugcat grabs a neuron fly after being told not to (Configurable amount in the future) OR has annoyed the iterator five times or more.
playerReleaseNeuron | Same as above | Happens when the slugcat releases the neuron fly if the iterator doesn't refuse to speak to the slugcat. Can append _likes and _dislikes for increased variety depending on how much the iterator likes the slugcat. Will always prioritize _likes and _dislikes over a specifig slugcat (If the slugcat is spearmaster and the iterator likes the player, then: playerReleaseNeuron_likes-spear > playerReleaseNeuron_likes > playerReleaseNeuron-spear > playerReleaseNeuron)
playerReleaseNeuronWarning | Same as above | Happens right after playerReleaseNeuron.
resumeConversation | Depends on append. none = totalinterruptions, _annoyance = annoyances, _leave = leaves | Happens when a conversation is resumed. Can append _annoyance and _leave. Meant to be the "Thank you." part.
conversationResumption | Same as above | Happens after resumeConversation. Meant to be the "As I was saying" part.
swarmerlines | Number of neuron flies given to the iterator | Happens after the iterator has recieved a neuron fly. (This counts as a conversation, but cannot use special events, MANIFOLDWAIT or conditionals.)
swarmerlinesrespondfromnospeakmode | Same as above | Happens after the iterator has recieved a neuron fly while being in nospeak mode. (Same as above).
alreadydiscussedpearl | Numbers not used | Happens when the iterator is given a previously-read pearl (This greeting type does not support multiple chatboxes)
alreadydiscusseditem | Numbers not used | Happens when the iterator is given a previously-read item (This greeting type does not support multiple chatboxes)
interruptPearlReading | Numbers not used | Happens when the iterator is interrupted during a pearl-reading (This greeting type does not support multiple chatboxes)
resumePearlReading | Numbers not used | Happens when the iterator resumes a pearl-reading (This greeting type does not support multiple chatboxes)
hitByWeapon | Numbers not used | Happens when the iterator is hit by a spear (This greeting type does not support multiple chatboxes)

Like conversations, a slugcat's name can be appended to make a special set of lines for that particular slugcat.

#################
# Custom Events #
#################

Custom Events are stored in customoraclesactions/(yourIterator'sID)

They are structured with lines or requirements and actions.
The first line can be either a requirement or an action. Having the first line be a requirement will make the event only (Currently makes it happen once the requirements have been fulfilled, but this is a bug. If you want it to fire once something happen, simply use waituntil as the first action.) happen if the player fulfills all requirements.
The rest of the lines all have to be actions.
Actions can have an action and a requirement. Actions will happen in the order you put them in, and will only happen if the player fulfills that action's requirement. If no requirements are listed for the action, it will always happen.

Custom Events can be called from conversations or by certain in-game actions. Events from in-game actions require a specific name and will disable the default behavior of what would normally happen.
The following in-game actions can trigger a Custom Event (filename | when it happens | required actions):
seeplayer | when the iterator sees the player for the first time this cycle (Exiting the region the iterator resets this cooldown) | Cannot use initial requirements. First action must be setbehavior. The first action cannot use conditions/requirements.
sleepoverbehavior | When the iterator switches to sleepoverbehavior (friendly behavior).
playerGrabbedNeuron | When the player grabs a neuron fly. | Currently not all parts of the original event can be replicated with actions.
hitbyweapon | When the iterator is hit by a spear

Requirements are formatted in this way:

requirement:xxx{parameters}xxx{parameters}xxx{parameters}
Where xxx is the name of the requirement and parameters are the parameters.

The following requirements exist (name | What it does (x = parameter | parameter type):
true | Always True. Exists mostly as a placeholder/default in case of unrecognized triggers | No Parameters. Recommended: null
holdxitems | Is true if the player holds X items | X = number between 0 and 2
noconversation | Is true if no conversations are currently happening | No Parameters. Recommended: null
tickspassed | Is true once X ticks have passed after this requirement has gone into effect. Can only really be used by the waituntil action | X = any number.
hasmark | Is true if the player has the mark of communication. | No Parameters. Recommended: null
isconsious | Is true if the iterator is conscious
statevariable (1 paramer) | returns true if: (X) is true:
neuronwarning: the iterator has told the player to not eat neuron flies
seenwithoutmark: the iterator has seen the slugcat before it recieved the mark of communication
markedplayer: the iterator gave the player the mark of communication
pickeduppearl: if the player has picked up one of the iterator's pearls
the name of a custom save data variable: if the contents of the variable is "true" or "false"
statevariable (3 parameters) | returns true if (X) is (Y) (Z)
(X):
encounters: the number of times the iterator has seen the player
encounterswithmark: the number of times the iterator has seen the player with the mark of communication
timesleft: The number of times the player has left the iterator
timesannoyed: The number of times the player has annoyed the iterator
totalinterruptions: The number of times the iterator's conversations have been interrupted by the player
totalitemsread: The number of items given to and commented on by the iterator
totalpearlsread: The number of pearls the iterator has read
miscpearlsread: The number of misc (white) pearls the iterator has read
neuronsleft: The number of neuron flies the iterator has left
totalneuronsgiven: The number of neuron flies the iterator has been given by the player
killfac: Current killfac (0 - 100) of the iterator. Cannot be used in other custom actions or requirements.
the name of a custom save data variable: Uses the number stored.
(Y):
>,>=,=,<=,<
(Z):
Same as (X) or any number.
Example: encounters =< totalpearlsread
Example: miscpearlsread > 3
Note: spaces MUST be used between the comparator and the two variables.

An Exclamation mark (!) can be added at the start of the parameter string to invert it.

actions are formatted in this way:

action:xxx{parameters}<R>yyy{parameters}
where xxx is the name of the action, yyy is the name of the requirement and parameters are the parameters. The action will only happen if all of its requirements are fulfilled when the action is reached.
If you do not use requirements, do not include the <R>

The following actions exist (name | What it does (x = parameter)| parameter type):
waituntil | Waits until a set of requirements have been fulfilled before continuing to the next action. The requirements that must be fulfilled must be in parameters (X), whereas requirements for the waituntil itself to fire have to be put after the <R>. Add a ? in front of parameters to make it continue upon fulfilling ANY requirement instead of ALL requirements. | X = requirements.
killplayer | Sets the desired killfac to X. Reaching 1 kills the player | X = any float (0 - 1)
setbehavior | Sets the current behavior to X. Same as defaultBehavior. | X = any behavior.
setmovementbehavior | Sets the current movementbehavior to X. Do note that some movement behaviors do not work before the iterator has seen the player. | X = any movement behavior.
startconversation | Starts a conversation. | X = name of file to use for conversation. Append a comma and a movementbehavior to immediately switch to that movementbehavior as well. Default = talk. To avoid changing movementbehavior, write "no" after the comma.
endconversation | Ends the current conversation and sets it to null. Recommended to use after an event is finished and all current conversations are finished if the current behavior is slumberparty. | X = recommended: null.
fireevent | Starts a new event | X = name of file to use for event.
gotolocation | Sets the iterator's movementbehavior to custom and sets the destination to X | X = Two numbers separated by a comma.
shortcutlock | Locks or Unlocks the shortcuts in room the iterator is in | X = lock or unlock
gettoworking | Sets gettoworking to X. gettoworking controls palette, and also gravity when the current subbehavior does not use gravity. | X = number between and including 0 and 1
greeting | Fetches lines of text from a file (X | Works like greetings) with either a specific number or getting one by same method as statevariable (X). | X = filename,number
givemark | Temporarily sets the current behavior to givemark. Recommended to use waituntil with hasmark after. | Does not use parameters. Recommended parameter: null
stopmusic | Stops any SSmusic | X = recommend: null
changehalo | Makes the halo changes its radius. | No Parameters needed. Recommended: null
playsound | Plays a sound from among the following: (exitwork, pebblesvoice1 - pebblesvoice5, moonpain1 - moonpain2) at volume, pan and pitch | X = soundID,volume,pan,pitch (volume, pan and pitch are floats.)
customdata | sets or does math on custom-saved variables or flags. | X = name of variable, operator (=-+), number/statevariable(Cannot use other custom data), use spaces to seperate For flags, use only = and true/false. (Example: customdata{numtimesdonethisevent + 3 (This would increment the variable numtimesdonethisevent by 3
influencelike | Increases or decreased the iterator's like of the player | X = amount
nospeakmode | Sets the iterator to nospeak mode, which makes it not speak. | X = null
StunPlayer | Stuns the player | X = Stuntime,sparks(true/false) (Sparks determine whether or not sparks like those used when the slugcat is killed or given the mark of communication should be spawned.)
endevent | All events must have this at the end. | Does not use parameters. Recommended parameter: null.


Like conversations, a slugcat's name can be appended to make a special event for that particular slugcat.

##############
# Behvariors #
##############

Behaviors determine how the iterator acts and what it does. There's a couple of different types of behavior, and some turn into other behaviors over time or depending on actions.
The following behaviors can be used as defaultBehavior (Though not all are recommended for use):
(ID | General Description | Leads into XXX behavior)

slumberparty | The iterator either meditates or inspects pearls while allowing slugcat to roam freely in the chamber. Only behavior type that allows pearls to be read | Will turn into meetwhite_texting if the slugcat does not have the mark of communication.
throwout | The iterator attempts to throw the slugcat out of the chamber. | Turns into killonsight if the player remains in the chamber for too long.
secondthrowout | The iterator attempts to throw the slugcat out of the chamber. | Turns into killonsight if the player remains in the chamber for too long. Takes less time to turn into killonsight than throwout.
killonsight | The iterator kills the slugcat after a short delay if it is still in the chamber. | Turns back to idle once the the player has left the chamber or has been killed.
idle | The iterator is idle and either meditates or works. Not recommended to switch to or use as default behavior.
politethrowout | The iterator tells the slugcat to leave. | Eventually turns into throwout.
aftergivemark | Locks all shortcuts and gives the aftergivemark speech. Once finished, the shortcuts are unlocked. | Once the speech is finished, the behavior is switched to the default behavior.
meetwhite_shocked | Starts the give mark events. | Once finished, turns into aftergivemark.

###########
# Modules #
###########

Modules are additional behavior, actions and stuff that the iterator can do / does.

pearlreadermodule: Allows the iterator to read pearls if readspearls has been set to true.


############
# Saving #
############

Whenever the player survives a cycle, the oraclestate is saved to the savefile. All data you can fetch from statevariable are part of the savefile, and will thus be saved, including custom variables.

############
# Defaults #
############

### Functional Iterator ###
At default, the iterator will start the aftergivemark speech, then switch to its default behavior upon entry. If the player slugcat lacks the mark of communication, it will first begin a sequence of actions similar to Five Pebbles during Survivor's campagin.

### Ruined Iterator ###
At default, the iterator will greet the player, first with firstConversation, then with secondConversation, then lines from greetings.

###############
# Limitations #
###############

As the mod is not entirely polished, some features remain to be implemented, while others may be barebones and/or not work.
These features are still non or semi-functional at the moment:
- Custom Room location: Currently iterators will consider 350,350 (functional) and 1585,240 (ruined) their default position/location, even if another has been defined.
- Default Values: Only a few defines have a default value if not explicitly defined.
- Optimization: Function > Efficiency > Polish
- Custom Event locations: Currently only very few places to trigger them, like seeplayer and via conversations.
- parity between ruined and functional iterators: Some features currently only work for functional iterators, and may cause the game to crash if used for ruined iterators.
- Lacking Dialogue Costumizability. Not all lines of dialogue are customizable.
- nameForPlayer nonvariety: nameForPlayer currently only supports one name, and no way to change it depending on opinion.
- Overseer Violence: Currently, Iterators can only kill players, not overseers.

The following issues exist and I am aware of them:
- Custom Events initial requirements: Checked each update instead of once and does not prevent the event from happening if unfulfilled.
- The Name for Player is always "little creature" in collection.
- Neuron Flies sometimes behave erratically when given to an iterator.
- Colliding with the iterator will not make it annoyed, nor will it give any held pearls.

The following issues may apply, but have not been tested for:
- Modded Pearls may be unable to be read.

The following issues might exist, but I am unaware of them:
- The iterator might throw out the slugcat towards the wrong shortcut / no shortcut.

These limitations currently apply but are slated to be removed in the future:
- Limit of 1 iterator per room: Making more than one iterator currenlty makes one of them spawn twice instead.

The following features are lacking, but may be added if I get time, skill and motivation:
- Inter-timeline variables: Think moon's cloak.
- Ruined Iterator revival: Ability to revive ruined iterators with hunter's green neuron fly.
- Semi-functional iterators: Think moon after Rivulet has given her the rarefaction cell.
- Hunter Extra Cycles: The ability to grant extra cycles to Hunter.
- Food when giving mark: The ability to make the iterator give food upon granting slugcat the mark of communication, like moon does.
- Score: Score when winning the game for meeting the iterator.
- Vanilla Iterator Pearl Reading: Ability to have Looks to the Moon and Five Pebbles be able to read custom iterator pearls with custom dialogue.
- Overseers: The ability to make overseers guide the player to a room and/or make it stop/start guiding the player.

The following issues may apply, but have not been tested for and are not a priority:
- Saint may be unable to ascend custom iterators.

The following features are lacking and will only be added if someone pays me to do it:
- Iterators in rubicon.

As always, other mods may interfere with this mod and vice-versa.
If you experience problems in relation to other mods, please contact me on discord or make a discussion on the steam workshop page, but please do not write a comment about it on the workshop page.
Last edited by kroun; 5 Sep @ 9:19am
< >
Showing 1-6 of 6 comments
Will the guide also be structured better maybe? Just wondering, because it is kinda hard to figure out what it is trying to say at times. A tutorial would be nice honestly for the full release.
kroun  [developer] 1 Sep @ 2:15am 
Originally posted by King of Fire105:
Will the guide also be structured better maybe? Just wondering, because it is kinda hard to figure out what it is trying to say at times. A tutorial would be nice honestly for the full release.

I do plan to make a better guide.
By tutorial, do you mean a steam tutorial or a video tutorial?
Originally posted by kroun:
Originally posted by King of Fire105:
Will the guide also be structured better maybe? Just wondering, because it is kinda hard to figure out what it is trying to say at times. A tutorial would be nice honestly for the full release.

I do plan to make a better guide.
By tutorial, do you mean a steam tutorial or a video tutorial?

Any would be fine as long as it is a step by step tutorial, because trying to read and understand this is frying my brain.
But it's fine, no worries.
kroun  [developer] 2 Sep @ 3:13pm 
I'm currently taking a break from Iterator Creator, but a video tutorial is planned.
Alright
< >
Showing 1-6 of 6 comments
Per page: 1530 50