Technical Reference and Modders Guide
Welcome to the technical reference and modders guide! This guide will help anyone that wants to fiddle around with Ivy's internals, or any modders that want to use Ivy's ESM as base for their mods. This guide explains the different globals, quests and variables you can find to either manipulate Ivy inside your mod, or get info from her current status to integrate with your mod. If you have any specific questions while you are creating a mod with Ivy's ESM as base, or if you're just creating a custom companion yourself and you want some advice, don't hesitate to ask questions in this blog.
The list of global variables are split into globals you can safely update and globals you should use as READ-ONLY/NON-UPDATABLE.
Most of Ivy's important internals are handled through script variables, not readily accessible through the console.
These include her irritation levels, affinity, arousal, etc..etc.. there are globals corresponding with these values, but they are read-only, in the way that they are overwritten by script. Adjusting these types of globals will results in Ivy being in an unstable state (e.g. her dialogue conditions will rely on one state, but her script will have another state, so called 'split brain syndrome'). Below you will find information on WHICH globals you can update SAFELY and which globals you should keep your hands OFF.
Updatable Globals (Might break Ivy but you can experiment after saving)
Non Specific Globals
Enables Ivy's DEBUG mode. Doesn't do a lot of good, but will spew out a lot of internal notifications on the screen that you'll probably not understand.
Debug mode can help you gauge how Ivy's affinity rises, you can see a lot of her internals come by via onscreen notifications.
Some of it will make sense, some of it won't.
WARNING: Debug mode enables a lot of Debug.Trace() messages in your papyrus log. It can grow quite large, make sure to turn it off again at one point!
How often does Ivy scan the environment? A number between 0 and 100. (0/ZERO Means scan ALWAYS (will break Ivy). 100 means NEVER scan. (Default: 30 / Will soon be 75)
If you think that Ivy talks too much about Duct Tape or Raiders in the area, adjust this global to 95!
How Often does Ivy speak to Settlers?? A number between 0 and 100. (0/ZERO Means scan ALWAYS (will break Ivy). 100 means NEVER scan. (Default: 30)
XPMiscQuestIvyJetGumFruit - How much XP do you get from doings Ivy's 'fetch quest' radiant quests? (Default: 25)
_ivy_HyperCombatEnabled When set to 1 this means Ivy's HyperCombat attacks are enabled.
WARNING: WHEN SET TO 1 THROUGH THE CONSOLE IT IMMEDIATELY RULES OUT THE ENTIRE HYPERCOMBAT AFFINITY QUEST and accompanying Affinity jumps!
_ivy_SA_Frequency A random number between 0 and 100, below this global defines if Ivy uses HyperCombat for each combat target she encounters. This is checked only ONCE, upon entering combat. (Default: 50, can be upgraded to 100 through the terminal). NOTE: Even though it can be set to 100 this does not mean that Ivy will always use HyperCombat. There are many factors that come into play, deciding if a HyperCombat attack is possible or not.
_ivy_SA_Min_Distance Minimum distance an enemy must be for HyperCombat to kick in OUT-DOORS. (Default: 750)
_ivy_SA_Min_Distance_indoor The minimum distance Ivy must be to use HyperCombat IN-DOORS. (Default 512)
_ivy_SA_Max_Distance Maximum distance an enemy can be for HyperCombat to kick in. (Default: 14000)
_ivy_SA_Cooldown Amount of seconds it takes to cool down. This is added to a player level multiplication making it so the number goes down the higher the player's level is. (Default: 8 )
_ivy_HyperCombatThreshold The amount of Combat Events Ivy must have encountered, before asking the player to enable her HyperCombat. (read: This counter raises for each enemy she finds as long as HyperCombat is not enabled yet. Once it reaches this threshold and Ivy has an Affinity of 10 for you, she asks you to enable her HyperCombat. (Default: 30)
_ivy_AllowAttack_Electric (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_AllowAttack_Forcepush (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_AllowAttack_Telefrag (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_AllowAttack_Grenade (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_AllowAttack_Frenzy (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_AllowAttack_FreeBird (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_AllowAttack_DeathAbove (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_AllowAttack_Headpop (Configures HyperCombat attack type. Can be set from the controller holotape) Default: 1
_ivy_remote_hack_min_dist Minimum distance for Ivy to decide to hack a terminal remotely. (Default: 450)
_ivy_remote_hack_max_dist Maximum distance for Ivy to decide to hack a terminal remotely. (Default: 1320)
_ivy_scene_short_InterjectionDistance If Ivy is beyond this distance from the player, she will not integrate in certain quest dialogue. (Default 250)
_ivy_warp_teleport_distance - Updatable, but can be configured through the NX-2C Controller Holotape. (Default: 2200).
_ivy_warp_teleport_distance_indoors - (Default: 1700).
_ivy_use_warp_sneak - Set to 0 to disable teleportation while the player is sneaking. - Updatable, but can be configured through the NX-2C Controller Holotape. (Default: 1.)
_ivy_Arousal_Threshold - How much times of flirting it takes for Ivy to reach arousal status. (Default: 7)
These will break/glitch Ivy when adjusted through the console. But they can be READ for curiosity..
Simply put, do NOT adjust any of the globals below, unless you want Ivy to glitch out on you.
_ivy_listens - Set to 1 when Ivy's MAIN A.I. loop is running
_ivy_recruited - Is Ivy recruited at this point?
_ivy_needs_jet - Read only. Quest related. Set by script when the Ivy Needs mutfruit quest.
_ivy_needs_gum - Read only. Quest related. Set by script when the Ivy Needs mutfruit quest.
_ivy_needs_mutfruit - Read only. Quest related. Set by script when the Ivy Needs mutfruit quest.
_ivy_dissapointment - Read Only. How dissapointed Ivy currently is with the player.
_ivy_any_player_answer_good - Read Only. Set right before asking a question to the player that does not affect affinity.
_ivy_IsAroused - Set to 1 after flirting (x) amount of times with Ivy
_ivy_HyperCombatQuestRejected - Set to 1 when the player has refused doing the HyperCombat quest.
_ivy_obscenity_enabled - Configured through Ivy's Service Menu (e.g. Profanity Filter)
_ivy_Affinity_RelationShipsHad - How many relationships has Ivy had with the player?
_ivy_Affinity_AvailableForRelationship - Is Ivy open to a relationship with the player?
_ivy_radiant_chats - Counter that's increased every time you sleep with Ivy in a bed. Once it reaches a threshold (semi random) a 'kill the raider' quest is kicked off when you speak with Ivy.
_ivy_radiant_quest_counter - Counter that's increased every time you sleep with Ivy in a bed. Once it reaches a threshold (semi random) a 'kill the raider' quest is kicked off when you speak with Ivy.
_ivy_Affinity_LoveRelationShipEstablished - Set to 1 when the player has a love relationship with Ivy. DO NOT UPDATE. Will glitch if Affinity does not match!!
_ivy_Affinity - Read only. Does NOT do what you think it does. (See the Advanced Gameplay Guide for more info)
_ivy_Affinity_Override - used internally by Ivy's affinity system.
_ivy_Affinity_HasBeenAngry - Set to 1 when Ivy has ever been angry with you.
_ivy_player_loves_ivy - Set to 1 when a relationship has been established. DO NOT UPDATE.
_ivy_player_loved_ivy - Set to 1 when a relationship has been established and broken off (e.g. Ivy has been your EX). DO NOT UPDATE.
Deep Internal Counters not usable for either reading or writing.
Basically these won't help you at all.
_ivy_DoingSpecialAttack - Used internally during HyperCombat attacks.
_ivy_radio_songs - Used in WIVS radio
_ivy_HyperCombatInstallationStarted - Internal for HC status.
_ivy_HyperCombatInstallationCompleted - Internal for HC status
_ivy_HyperCombatThreshold_ceiling - Internal for HC status
_ivy_SA_LastAttackType - Set on each HC attack, so Ivy doesn't spam certain attacks.
_ivy_SA_AttackSpeechSuccesful - Used internally
_ivy_HyperCombat_IvyBloodCovered - Set to 1 when Ivy is covered in blood due to a HyperCombat attack
_ivy_follow_distance - Internal counter for configuration of follower distance
_ivy_IsHugging - Unused created while trying out an animation but that experiment failed
_ivy_IsSpeaking - Set under certain circumstances to keep Ivy from chatting.
_ivy_decryptionHolotapeKnown - Used in HC Quest
_ivy_decryptionKeyKnown - Used in HC Quest
_ivy_intro_naked - Ivy remembers if you walked in on her when she was naked.
_ivy_intro_scene_done - All introductions done?
_ivy_radiant_stage - Used by Ivy's radiant quests.
_ivy_use_warp - Set internally for Ivy to know she can use warp/teleportation.
_ivy_conflict_success - Unkown. I need to check it out. Most likely unused. Don't touch or update in any case!
_ivy_mutfruitquest_success - Used internally by Ivy's mutfruit quest.
_ivy_item_IsSmall - So Ivy knows that the player picked up a small item and can react accordingly.
_ivy_player_IsInInterior - Set whenever the player is in-doors.
_ivy_last_note_found - ID for the last lore related note that Ivy found.
_ivy_usename - Unused
_ivy_sm_Nun_Stage - Unused
_ivy_temp_dismissed - Unused
_ivy_temp_dismiss_action - Unused
_ivy_sm_Deb_Stage - Unused
_ivy_sm_Priest_Stage - Unused
_ivy_sm_KingPelican_Stage - Unused
_ivy_player_promised_toKillBos - Set to 1 when the player has promised Ivy to kill the Bos Faction
_ivy_BOS_talk_Stage - Internally used by Ivy's Bos quest
_ivy_AI_Blocker_Unlocked - Set to 1 after finishing Ivy's main affinity quest.
_ivy_deepchat_started - Set to 1 during chats with Ivy.
_ivy_full_dismissal - Set to 1 when Ivy has been dismissed
_ivy_affinityQ_InProgress - Set to 1 during the affinity quest.
IVY_ChatterDistance - Unused
_ivy_chats - Unused
_ivy_Allow_Teleportation - Is Ivy allowed to use her teleportation? (Gets set automatically in script. Configure her teleportation through the NX-2C Controller Holotape, in game)
_ivy_pl_knows_prayer - Unused
_ivy_pl_knows_bunny - Unused
_IvyCompQuest "Ivy Companion Dialogue" [QUST:01000805]
Ivy's Main Companion Dialogue Quest. Holds the bulk of her dialogue, framework and quests.
_ivys_porn_radio "W-IVY-S Radio" [QUST:01036194]
Teleportation Related Quests
_ivy_WarperQuest "Ivy's teleportation systems" [QUST:01007F91]
_ivy_warper_crowd_reactions "Crowds React To Ivy's Warping" [QUST:01012203]
_ivy_activate_Quest "Redeem Ivy" [QUST:0101A6A1]
_ivy_HyperCombatEnableQuest "HyperCombat!" [QUST:010041D9]
(The Main Affinity quest is in it's own ESP)
Ivy's Radiant Quests:
_ivy_needs_gum_quest "Ivy needs sweets!" [QUST:01015599]
_ivy_needs_jet_quest "Bring some Jet to Ivy" [QUST:01015597]
_ivy_needs_mutfruit_quest "Give Ivy some Mutfruit" [QUST:01015598]
_ivy_bad_customers "Righteous Revenge at <Alias=Dungeon>" [QUST:01005C56]
_ivy_manager "NX-2C Location Tracker" [QUST:010711E5]
_ivy_MagNiceRack "Nice Rack!" [QUST:02011516]
_ivy_QuestStartChecker "Control Quest to check when to start Ivy's recruitment" [QUST:010088AB]
_Ivy_Introduction_KickStarter "Kickstarts Ivy's Introduction Scene" [QUST:010090EC]
_ivy_special_attacks "Triggered when a special attack is available" [QUST:0100584A]
Ivy's Environment Comment System:
_ivy_AO_Comment "Ivy's AO Comment System" [QUST:01014C19]
_ivy_AO_Comment_Dialogue "Ivy's AO Comment Dialogue" [QUST:01014C1D]
Ivy's Autonomous quests:
_ivy_fights_marcy "Ivy gets upset with Marcy" [QUST:01002290]
_ivy_hacks_a_terminal "Ivy Hacks a Terminal" [QUST:01001172]
_ivy_picks_flowers "Ivy Picks Flowers" [QUST:01015851]
_ivy_random_actions "Ivy's Eats a Corpse" [QUST:01013968]
_ivy_situational_awareness_dialogue "Ivy's Situational Awareness Dialogue (Enemies)" [QUST:010019FD]
_ivy_situational_awareness_scan_items "Ivy's Situational Awareness Dialogue (Items)" [QUST:01001A05]
_ivy_SpeaksWithNPC "Ivy Speaks with random NPC" [QUST:0100604F]
_ivyCompQuestStories "Ivy's Stories (unused)" [QUST:0101006F]
_ivy_affinity_dialogue "Ivy's Affinity Dialogue (Unused)" [QUST:0100A0E5]
_ivy_CA_PickupItem "Ivy Item Pickup Comments (unused)" [QUST:01012001]
_ivy_Interactor "Ivy's World Interactions" [QUST:0100104A]
_ivy_interjections "Ivy Interjections (Unused)" [QUST:01022FFF]
_ivy_killQuest1 "Kill Avery (unused)" [QUST:0101EB30]
Changing Ivy's NPC Actor object / Size / Race and Skin
You can safely alter Ivy's appearance under most normal circumstances. Unfortunately some very sick individuals have forced me to add MINOR CONSTRAINTS as to how Ivy can be modded.
DO NOT MOD IVY TO USE CHILD RACE. Her code has safeguards to prevent this from working. It will bork your game forcing you to load an older save.
Ivy also does not allow her size to be changed below 0.95. When you change her size through the console, she will scold you for it. Other than those two constraints you can do anything you want, give her a pony or shark head if that's your thing. I'll help you mod her and am available at Discord for advice.
These two constraints (child race + NPC size) are NON NEGOTIABLE.
If I find more 'child like' races these will be added to her protection.
Technicalities of HyperCombat
HyperCombat in essence is basically a quest scene playing out. The main part of HyperCombat is Ivy doing a dialogue with added Script Fragments to the BEGIN and END stage of each HyperCombat attack. You Define a new type of HyperCombat attack by creating a new dialogue fragment in the appropriate quest (_ivy_special_attacks "Triggered when a special attack is available" [QUST:0100584A]). Under the 'MISC' Tab.
Step 1: SA Quest is called in OnCombatChanged of Ivy's main alias in her main companion quest.
Step 2: The SA (Special attack) is done inside the SA quest:
All Hypercombat always consists of three parts:
1 - Begin script, Ivy says something the script teleports her to the enemy.
2 - Ivy is done talking, she teleports back (Sometimes in the END FRAGMENT but usually through script) and the scripted KILL is done.
3 - Ivy says something about the attack she just did (e.g. I'm covered in blood and guts again!)
Because the dialogue group is random, a random attack is chosen.
Dialogue conditionals filter the allowed attacks through globals.
An attack looks like this:
Which will in turn call this piece of code, which places a teleportation effect at the enemies neck, and decapitates them:
;teleport the enemies' head right off.
CombatTarget.Dismember("Head1", true, true, true)
utility.wait(0.5) ;let the enemy be without a head for a bit.
The global 'ivy_SA_LastAttackType' is then used to relay to Ivy which kind of special attack she just did, so she can comment appropriately on it.
Ivy uses an autonomous system to check whether to use HyperCombat and checks several things.
It all starts upon the CombatEntered() stage. First a check is done if the target is of an appropriate race (e.g. humanoid) then the following checks are done:
- Is the enemy in the player's view? (No? then skip the attack).
- Is the enemy a named NPC or important boss? (Yes? Skip the attack).
- Is the enemy within the range?
- Is Ivy still powering up from the last attack (cooldown)
- Is Ivy otherwise engaged in something (if so no attack is done through HC).
This check is done ONLY ONCE upon entering combat. Once Ivy has decided she will not use HyperCombat with an enemy she will finish the encounter as normal (with her pistol).
That engagement will then block her from HyperCombat until the enemy is dead and she engages with a new enemy, after which the entire OnCombatEnter routine is run again, for each enemy she encounters and so-on and so-forth..
As there is an NPC Reset Follower AI command inside her regular teleportation routines, you can warp her towards yourself through the NX-2C Local Teleport Module, which will reset her CombatEntered Event, which will kick off the check for HC again. This was initially unplanned. But I like it. It gives players the ability to exert some kind of control over HyperCombat. Experienced scripters might want to change this in their own mod, for instance they might want Ivy to check more or less often for these attacks.
To recap, the workflow for HyperCombat is:
- OnCombatEnter Triggers a dialogue fragment using the NPC.Say() command. It also fills the script alias for the combattarget to be used later on.
- The dialogue fragment triggers speech and a script run mostly on the BEGIN phase of a dialogue line.
- That script then does the actual hypercombat attack and it sets a global to which type of attack was done.
- Then another NPC.Say() command plays a dialogue fragment with conditionals set to the global that was set in the previous script.
- When the CombatExit() event is run, all globals are reset and Ivy's AI status is reset in a basic manner (Follower.Follow()).
Attacks can FUMBLE.
It can happen that Ivy is interrupted in her speech, causing the second phase of a HyperCombat attack to fail. For instance, if she is hit by an enemy weapon during the attack. She can also wait too long before teleporting back, causing her grenade or flashbang to explode in front of her. Again this was unintentional but it's realistic. It could happen as nothing's perfect.
When debug mode is enabled, you will see a notification popup when attacks have fumbled.
Ivy's framework is setup just like any other custom companion. She uses the basic follower scripts and factions. She likes to be first in the currentcompanion faction (otherwise quest integration fails) and she uses all the regular follower quests and aliases.
Her own companion quest has an AI-loop. That's a really fancy name for just a loop that holds (every 4 seconds) and then does something.
Her dialogue is made up of 5 main actions:
- Sitting (erotic & non-erotic groups)
- Enter a new location
- Remark on a quest
All these are handled from the main loop. The loop is stopped and started, every time the played enters a new location. This is done by adding a script to a player alias in Ivy's main companion quest. This way, if people uninstall her and the loop is running, it will automatically stop and unrecruit her/reset her related globals.
Actually part of idling, when sitting down. If the player is standing, Ivy will request the player to come sit with them. Once both the player and Ivy are sitting and they are close enough to each other, Ivy will start rambling to the player. Keep this in mind if you plan on animating her. Animations on furniture are also known as 'sitting' in the engine and that could cause weird things.
Started in the loop, according to globals set, Ivy will either say something random (with a 4 hour in-game time-out), she will chat with a settler NPC or one with the regular voicetypes (e.g. boston_voices) OR she will engage in an area scan. If an area scan reveals items, she will notify the player. This is handled through her Scan Quests.
Actually part of idling, Also started from the main loop. When sneaking, Ivy will sometimes comment on the player.
Enter a New Location
When entering a new location, Ivy will remark on the location.
Remark on a quest
Part of her idle loop. Ivy checks for quest stages and remarks appropriately to the player on quest progress.
IMPORTANT: Because the loop handles all these situations, and because only ONE of these things happens every 4 (real life) seconds, it can take a while before the Enter New Location or Quest Remarks are fired, after these events have occurred. I've chosen not to force these lines upon entering a new location every time as that makes Ivy too predictable, ruining gameplay and surprise.
I am working on making all source code, except for scripts that hold protection against modding her to child race, available on VERY short notice.