Difference between revisions of "Arcane University:World Interactions"
(→Scripted Reactions) |
|||
Line 21: | Line 21: | ||
# Hellos: Hello reactions are essentially standard out-of-dialogue hellos, conditioned to only happen under special conditions. These are some of the easiest to set up, and include things NPCs reacting to you walking around with a fire spell equipped, or commenting on you sneaking past them. | # Hellos: Hello reactions are essentially standard out-of-dialogue hellos, conditioned to only happen under special conditions. These are some of the easiest to set up, and include things NPCs reacting to you walking around with a fire spell equipped, or commenting on you sneaking past them. | ||
− | # | + | # Spell Reactions: These are events where an NPC is directly told to say a line using the Papyrus "Say" command when a spell is cast on them. These are relatively easy to set up, and can mostly be completed with default scripts. |
# Engine Events: This covers events with a substype on the [https://www.creationkit.com/index.php?title=Misc_Tab Misc Tab] of quests, such as NPC reactions to the player bumping into them, watching a fight, or noticing the player about to steal something. | # Engine Events: This covers events with a substype on the [https://www.creationkit.com/index.php?title=Misc_Tab Misc Tab] of quests, such as NPC reactions to the player bumping into them, watching a fight, or noticing the player about to steal something. | ||
# Story Manager Events: The story manager allows you to create world interactions for more complex events. This includes NPC reactions to things like the player crafting an item, dropping something, or having a unique "Hello" if the player previously attacked them. | # Story Manager Events: The story manager allows you to create world interactions for more complex events. This includes NPC reactions to things like the player crafting an item, dropping something, or having a unique "Hello" if the player previously attacked them. | ||
Line 44: | Line 44: | ||
===Limiting World Interaction Occurrences=== | ===Limiting World Interaction Occurrences=== | ||
− | Generally, you want to limit how often world interactions play, lest they become stale after a long playthrough. Skyrim uses | + | Generally, you want to limit how often world interactions play, lest they become stale after a long playthrough. Skyrim uses four methods to limit how frequently World Interactions play. |
# Comment Chances: These are global variables set to some value between 0 and 100 and are used to give types of comments a percent chance to occur. There usage is typically a <code>GetRandomPercent</code> quest dialogue condition, compared to the Comment chance global variable. For example, vanilla Skyrim has world interaction where NPCs comment if the player has a flame spell equipped (quest <code>WICommentMagicFlames</code>). There is a corresponding global variable <code>WICommentChanceMagicFlames</code>, and a quest dialogue condition <code>GetRandomPercent() <= WICommentChanceMagicFlames</code>. | # Comment Chances: These are global variables set to some value between 0 and 100 and are used to give types of comments a percent chance to occur. There usage is typically a <code>GetRandomPercent</code> quest dialogue condition, compared to the Comment chance global variable. For example, vanilla Skyrim has world interaction where NPCs comment if the player has a flame spell equipped (quest <code>WICommentMagicFlames</code>). There is a corresponding global variable <code>WICommentChanceMagicFlames</code>, and a quest dialogue condition <code>GetRandomPercent() <= WICommentChanceMagicFlames</code>. | ||
− | # Comment Timers: In vanilla Skyrim, this is | + | # Comment Timers: In vanilla Skyrim, this is usually global variable <code>WICommentNextAllowed</code> used alongside a default script <code>WICommentScript</code> to limit how frequently world interaction comments occur, however there are a few cases of separate times, such as for spell reactions. For <code>WICommentNextAllowed</code>, when a world interaction comment happens, <code>WICommentScript</code> the current game time and sets <code>WICommentNextAllowed</code> to one hour in the future. Then, a quest dialogue condition requires that the current game time be greater than <code>WICommentNextAllowed</code> (specifically, the condition is <code>GetGlobalValue(GameDaysPassed) >= WICommentNextAllowed</code>). This blocks world interaction comments from happening until one hour has passed since the last comment. This script can be used as-is for new world interactions; you could make your own timer global variables and use those instead; or you could use some combination (for instance, you could make a new timer just for Magic Flames comments, then condition those comments to be one hour since the last world interaction comment of any kind and two hours since the last Magic Flames comment). |
− | # Story Manager Timers: This is simply a setting on quest entries in the Story Manager. When quests in the story manager have a value for "Hours until reset", the story manager will not attempt to start that quest again until that much time has passed since the last | + | # Story Manager Timers: This is simply a setting on quest entries in the Story Manager. When quests in the story manager have a value for "Hours until reset", the story manager will not attempt to start that quest again until that much time has passed since the last occurrence. |
+ | # Event Timers: These are timers used to block whole categories of events in the Story Manager. For instance, Skyrim has seven CastMagic world interaction quests in the story manager—the "Hours until reset" setting would block a ''single'' quest for some amount of time, but an event timer would be used to block ''all seven''. Functionally these are similar to comment timers. The code for them exists on <code>WorldInteractionsScript</code>, and are typically used through a custom script that extends <code>WorldInteractionsScript</code>, where the timer functions are called in quest fragments. | ||
− | + | ===WI Quest=== | |
− | |||
− | ===WI | ||
Skyrim has a World Interaction parent quest <code>WI</code>, which holds a script <code>WIFunctionScript</code> for some common WI functions and properties. In truth, you probably won't use this much. The functions primarily concern an unused "Mourner" world interaction and dragon attacks. The two functions you might find useful are <code>AllowComplexInteractions</code>/<code>DisallowComplexInteractions</code>, which enables you to enable/disable certain world interactions for whole locations at once (. Also, <code>ShowPlayerRoom</code> is used for some Skyrim tavern scenes. I've personally never needed any of the functions in this script, so I won't cover it in any more depth in this guide. | Skyrim has a World Interaction parent quest <code>WI</code>, which holds a script <code>WIFunctionScript</code> for some common WI functions and properties. In truth, you probably won't use this much. The functions primarily concern an unused "Mourner" world interaction and dragon attacks. The two functions you might find useful are <code>AllowComplexInteractions</code>/<code>DisallowComplexInteractions</code>, which enables you to enable/disable certain world interactions for whole locations at once (. Also, <code>ShowPlayerRoom</code> is used for some Skyrim tavern scenes. I've personally never needed any of the functions in this script, so I won't cover it in any more depth in this guide. | ||
Line 59: | Line 58: | ||
# Create a new quest. Give the quest a readable ID like "<code><ModPrefix>WIComment<Description></code>". Click "OK" then reopen the quest. | # Create a new quest. Give the quest a readable ID like "<code><ModPrefix>WIComment<Description></code>". Click "OK" then reopen the quest. | ||
+ | #::- Because quests can only have one "Hello" topic, you will generally need one quest per type of interaction. | ||
# Set the quest to Start Game Enabled. At some point before you start testing it, create a new SEQ file for your plugin. | # Set the quest to Start Game Enabled. At some point before you start testing it, create a new SEQ file for your plugin. | ||
# Set the quest data conditions for the world interaction. These are conditions that will apply to ''all'' topicinfos. | # Set the quest data conditions for the world interaction. These are conditions that will apply to ''all'' topicinfos. | ||
Line 82: | Line 82: | ||
# Go to the Misc tab and create a new topic with subtype "Hello". | # Go to the Misc tab and create a new topic with subtype "Hello". | ||
# Create the individual topicinfos for this world interaction. The exact conditions here will depend on what you've written for the lines or what your writing team has given you. For instance, conditioned on voice type, class, race, faction, and so on. | # Create the individual topicinfos for this world interaction. The exact conditions here will depend on what you've written for the lines or what your writing team has given you. For instance, conditioned on voice type, class, race, faction, and so on. | ||
− | # If you're using a timer, then update the timer by setting the quest stage. In | + | # If you're using a timer, then update the timer by setting the quest stage. In a Begin fragment, call: <code>GetOwningQuest().SetStage(<the stage you made earlier>)</code>. |
+ | |||
+ | Your world interaction should now work in-game! | ||
+ | |||
+ | ==Spell Reactions== | ||
+ | "Spell Reactions" are where an NPC is directly told to say a when a spell is cast on them. These work by using a script attached to the magic effect to force the NPC to say a line using Papyrus's [https://www.creationkit.com/index.php?title=Say_-_ObjectReference Say] command. | ||
+ | |||
+ | First, we'll cover setting up the quest and dialogue: | ||
+ | # Create a new quest. Give the quest a readable ID like "<code><ModPrefix>WICastMagic<Description></code>". Click "OK" then reopen the quest. | ||
+ | #:- It is possible to have multiple reaction topics in the same quest, so you could make one quest that holds all your spell reaction topics. | ||
+ | # Set the quest to Start Game Enabled. At some point before you start testing it, create a new SEQ file for your plugin. | ||
+ | # Set the quest data conditions for the world interaction. These are conditions that will apply to ''all'' topicinfos. | ||
+ | #* Check for valid NPCs, such as per [[Arcane University:World Interactions#NPC Preparation]] | ||
+ | #* If desired, a random percent condition. | ||
+ | #: Note 1: We can handle the timer in our MagicEffect script (discussed later), so we don't need that here. | ||
+ | #: Note 2: <code>GetAllowWorldInteractions</code> is optional here, depending on your specific lines. | ||
+ | # Go to the Player Dialogue tab and create a new branch and topic, and '''set the branch type to "Normal"'''. | ||
+ | #* If you want reactions in combat to be different from reactions outside of combat, create a second topic that is just for in-combat lines. Although it is technically possible to put these all in the same topic, the default script we will be using allows for separate combat and noncombat topics, so it will be easier and more organized to use two topics here. | ||
+ | # Create the individual topicinfos for this world interaction. The exact conditions here will depend on what you've written for the lines or what your writing team has given you. For instance, conditioned on voice type, class, race, faction, and so on. | ||
+ | |||
+ | Next, we need to add a script to the magic effects we are interested in. | ||
+ | # Open up the magic effect. | ||
+ | # In the "Scripts" section, add the script <code>SayOnHitByMagicEffectScript</code>, then open up the Script Properties window. | ||
+ | # Auto-fill the <code>GameDaysPassed</code> property. | ||
+ | # You can auto-fill <code>WICastNonHostileTimer</code> or use your own timer global variable. | ||
+ | # Fill <code>TopicToSay</code> and <code>CombatTopicToSay</code> with your newly-created topics. | ||
+ | # Optionally, set <code>AllowForTeammate</code> to 1 to allow your teammates to comment as well when you cast a spell with this magic effect on them. | ||
− | + | NPCs should now comment when you cast your spell on them! | |
− | |||
==Engine Events== | ==Engine Events== |
Revision as of 04:26, 23 November 2020
This guide covers how to set up World Interactions in the Creation Kit. In Skyrim, these "quests" use the "WI" prefix, and include things like NPCs reacting when you cast a spell on them; when you walk around with a weapon drawn; when you when you swing a weapon near an NPC; or when you craft an item.
Contents
Introduction
Prerequisites
Implementing world interactions will require knowledge of dialogue implementation and basic scripting, and more complex reactions will require knowledge of the Story Manager, quest aliases, and scenes. You will also need to know how to generate and SEQ file for the quests you create, and will want Fuz Ro D'oh for testing before you get voiced lines.
- Basic Dialogue Implementation
- Advanced Dialogue Implementation
- Basic Scripting
- Story Manager
- Aliases
- Scenes
- Seq Guide
- Fuz Ro D'oh (LE)
- Fuz Ro D'oh (SE)
Types of World Interactions
World Interactions can be grouped into four categories.
- Hellos: Hello reactions are essentially standard out-of-dialogue hellos, conditioned to only happen under special conditions. These are some of the easiest to set up, and include things NPCs reacting to you walking around with a fire spell equipped, or commenting on you sneaking past them.
- Spell Reactions: These are events where an NPC is directly told to say a line using the Papyrus "Say" command when a spell is cast on them. These are relatively easy to set up, and can mostly be completed with default scripts.
- Engine Events: This covers events with a substype on the Misc Tab of quests, such as NPC reactions to the player bumping into them, watching a fight, or noticing the player about to steal something.
- Story Manager Events: The story manager allows you to create world interactions for more complex events. This includes NPC reactions to things like the player crafting an item, dropping something, or having a unique "Hello" if the player previously attacked them.
Each of these types will be covered separately below.
Initial Setup
NPC Preparation
In Skyrim, World Interactions are (broadly speaking) limited to generic NPCs using a default voice type. When you make your own, you will need to condition them in some way so that they are limited to only the NPCs you want. This is best done with one of three methods (or some combination of them):
- A custom faction, for instance something like "
<Mod Prefix>AllowWorldInteractions
".- - (Remember, factions aren't just in-game factions like the Companions or the Mages Guild, they are used for plenty of behind-the-scenes game mechanic things as well.)
- A formlist of valid NPCs.
- A formlist of valid voice types.
Or, you could use the reverse: a "DisallowWorldInteractions" faction, a formlist of invalid NPCs, and so on.
Pick which method (or methods) you want to use. Depending on your choice, fill out the formlist(s) or add your faction(s) to NPCs. You will use these factions or formlists for quest dialogue conditions, and possibly also as alias fill conditions or story manager event node conditions.
GetAllowWorldInteractions Condition
You may notice that the Creation Kit has a "GetAllowWorldInteractions()
" condition function. This function checks if the NPC's current package has the "World Interactions" flag checked. If it does, then the GetAllowWorldInteractions function will return TRUE
. If not, it will return FALSE
. In this way, you can dynamically change whether an NPC will have world interactions or not. For instance, if an NPC is fighting with you in a dungeon, you probably don't want them to complain that you have your weapon drawn. So, you should remember to include this condition for quest dialogue and when filling an alias.
Limiting World Interaction Occurrences
Generally, you want to limit how often world interactions play, lest they become stale after a long playthrough. Skyrim uses four methods to limit how frequently World Interactions play.
- Comment Chances: These are global variables set to some value between 0 and 100 and are used to give types of comments a percent chance to occur. There usage is typically a
GetRandomPercent
quest dialogue condition, compared to the Comment chance global variable. For example, vanilla Skyrim has world interaction where NPCs comment if the player has a flame spell equipped (questWICommentMagicFlames
). There is a corresponding global variableWICommentChanceMagicFlames
, and a quest dialogue conditionGetRandomPercent() <= WICommentChanceMagicFlames
. - Comment Timers: In vanilla Skyrim, this is usually global variable
WICommentNextAllowed
used alongside a default scriptWICommentScript
to limit how frequently world interaction comments occur, however there are a few cases of separate times, such as for spell reactions. ForWICommentNextAllowed
, when a world interaction comment happens,WICommentScript
the current game time and setsWICommentNextAllowed
to one hour in the future. Then, a quest dialogue condition requires that the current game time be greater thanWICommentNextAllowed
(specifically, the condition isGetGlobalValue(GameDaysPassed) >= WICommentNextAllowed
). This blocks world interaction comments from happening until one hour has passed since the last comment. This script can be used as-is for new world interactions; you could make your own timer global variables and use those instead; or you could use some combination (for instance, you could make a new timer just for Magic Flames comments, then condition those comments to be one hour since the last world interaction comment of any kind and two hours since the last Magic Flames comment). - Story Manager Timers: This is simply a setting on quest entries in the Story Manager. When quests in the story manager have a value for "Hours until reset", the story manager will not attempt to start that quest again until that much time has passed since the last occurrence.
- Event Timers: These are timers used to block whole categories of events in the Story Manager. For instance, Skyrim has seven CastMagic world interaction quests in the story manager—the "Hours until reset" setting would block a single quest for some amount of time, but an event timer would be used to block all seven. Functionally these are similar to comment timers. The code for them exists on
WorldInteractionsScript
, and are typically used through a custom script that extendsWorldInteractionsScript
, where the timer functions are called in quest fragments.
WI Quest
Skyrim has a World Interaction parent quest WI
, which holds a script WIFunctionScript
for some common WI functions and properties. In truth, you probably won't use this much. The functions primarily concern an unused "Mourner" world interaction and dragon attacks. The two functions you might find useful are AllowComplexInteractions
/DisallowComplexInteractions
, which enables you to enable/disable certain world interactions for whole locations at once (. Also, ShowPlayerRoom
is used for some Skyrim tavern scenes. I've personally never needed any of the functions in this script, so I won't cover it in any more depth in this guide.
Hello Reactions
Hello reactions are essentially standard out-of-dialogue hellos, conditioned to only happen under special conditions. These are some of the easiest to set up, and include things NPCs reacting to you walking around with a fire spell equipped, or commenting on you sneaking past them. These are the steps to create "Hello" world interactions:
- Create a new quest. Give the quest a readable ID like "
<ModPrefix>WIComment<Description>
". Click "OK" then reopen the quest.- - Because quests can only have one "Hello" topic, you will generally need one quest per type of interaction.
- Set the quest to Start Game Enabled. At some point before you start testing it, create a new SEQ file for your plugin.
- Set the quest data conditions for the world interaction. These are conditions that will apply to all topicinfos.
- Check for valid NPCs, such as per Arcane University:World Interactions#NPC Preparation
- - This can include other broad conditions, for example you could exclude NPCs in the Mages Guild from commenting on equipped spells.
- GetAllowWorldInteractions returns TRUE
- If desired, a random percent condition
- If desired, a timer condition
- If desired, IsInDialogueWithPlayer returns FALSE. This will make it so the line only happens when the player brushes past the NPC, not when the NPC actually greets them to start a conversation.
- The condition for your specific interaction type. Some examples:
- -
IsSneaking
: React to the player sneaking - -
SpellHasKeyword
: React to an equipped spell - -
HasMagicEffectKeyword
: React to a spell active on the player - -
WornHasKeyword
: React to some thing the player is (or isn't!) wearing - -
IsWeaponOut
: React to the player having a weapon drawn
- -
- Set the quest priority to something above totally generic greetings but below actually important quests. Skyrim uses a priority of 40 for world interactions; your mod or project might need something different.
- If you are using a timer:
- Check the "Allow Repeated Stages" box on the Quest Data Tab.
- Go to the Scripts tab and add
WICommentScript
. If you are using the genericWICommentNextAllowed
, you can auto-fill all properties. Otherwise, autofillGameDaysPassed
and fillWICommentNextAllowed
with your own global variable.- - If you are using multiple timers, you will need a custom script.
- Go to the Quest Stages tab and create a new stage. The stage number is not important. DO NOT enter anything for the log.
- Call
WICommentScript
'sCommented()
function in the stage's quest fragment.
- Go to the Misc tab and create a new topic with subtype "Hello".
- Create the individual topicinfos for this world interaction. The exact conditions here will depend on what you've written for the lines or what your writing team has given you. For instance, conditioned on voice type, class, race, faction, and so on.
- If you're using a timer, then update the timer by setting the quest stage. In a Begin fragment, call:
GetOwningQuest().SetStage(<the stage you made earlier>)
.
Your world interaction should now work in-game!
Spell Reactions
"Spell Reactions" are where an NPC is directly told to say a when a spell is cast on them. These work by using a script attached to the magic effect to force the NPC to say a line using Papyrus's Say command.
First, we'll cover setting up the quest and dialogue:
- Create a new quest. Give the quest a readable ID like "
<ModPrefix>WICastMagic<Description>
". Click "OK" then reopen the quest.- - It is possible to have multiple reaction topics in the same quest, so you could make one quest that holds all your spell reaction topics.
- Set the quest to Start Game Enabled. At some point before you start testing it, create a new SEQ file for your plugin.
- Set the quest data conditions for the world interaction. These are conditions that will apply to all topicinfos.
- Check for valid NPCs, such as per Arcane University:World Interactions#NPC Preparation
- If desired, a random percent condition.
- Note 1: We can handle the timer in our MagicEffect script (discussed later), so we don't need that here.
- Note 2:
GetAllowWorldInteractions
is optional here, depending on your specific lines.
- Go to the Player Dialogue tab and create a new branch and topic, and set the branch type to "Normal".
- If you want reactions in combat to be different from reactions outside of combat, create a second topic that is just for in-combat lines. Although it is technically possible to put these all in the same topic, the default script we will be using allows for separate combat and noncombat topics, so it will be easier and more organized to use two topics here.
- Create the individual topicinfos for this world interaction. The exact conditions here will depend on what you've written for the lines or what your writing team has given you. For instance, conditioned on voice type, class, race, faction, and so on.
Next, we need to add a script to the magic effects we are interested in.
- Open up the magic effect.
- In the "Scripts" section, add the script
SayOnHitByMagicEffectScript
, then open up the Script Properties window. - Auto-fill the
GameDaysPassed
property. - You can auto-fill
WICastNonHostileTimer
or use your own timer global variable. - Fill
TopicToSay
andCombatTopicToSay
with your newly-created topics. - Optionally, set
AllowForTeammate
to 1 to allow your teammates to comment as well when you cast a spell with this magic effect on them.
NPCs should now comment when you cast your spell on them!