Welcome Guest ( Log In | Register )

> Renee's Modding Thread
Renee
post Feb 25 2018, 01:30 PM
Post #41


Councilor
Group Icon
Joined: 19-March 13
From: Ellicott City, Maryland



Mod-making thread basically, which focuses heavily on quest-making. The first two tutorials (How to make a fetch quest and how to make a kill quest) are very hand-holdy. They are designed for those who are just starting to learn the art of quest-making. Other tutorials get more advanced, as my wacky ideas have pushed their boundaries.

Just click on any of the links in the post below this one. smile.gif


Bethesda Units. (How distance compares in-game to real-life).

Xpadder Walkthrough page. Xpadder is a site which allows gaming controllers to mimic the key & mouse functions. Xpadder, or similar programs such as Joy to Keys, are absolutely crucial to get the most out of older games such as Arena, Daggerfall, Morrowind, and Oblivion, for those who prefer controllers. They can also be used for newer games (Fallout 3/NV or Skyrim) to provide alternate controlling scenarios during times when a game's native D-pad arrangement needs to be shut off.




This post has been edited by Renee: Apr 16 2024, 06:27 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
 
Reply to this topicStart new topic
Replies
Renee
post Feb 10 2023, 03:07 PM
Post #42


Councilor
Group Icon
Joined: 19-March 13
From: Ellicott City, Maryland



Traveling with an NPC, Additional Locations. Game: TES V: Skyrim

This lesson goes with the one started above. The NPC warrior has been taken to Dragonsreach, and now he wants some downtime. Once he's done doing whatever he's done doing in Dragonsreach, he'll want my healer's services again. He's finished whatever business in Dragonsreach, and will want to go somewhere else, which can be either Nightgate Inn or Riverwood the way I'm about to write this, or it can be any other interior cell. But he don't want to go there alone. He wants someone to heal him as he travels, getting in fights and so on.

Eventually it's going to be possible to find multiple travelers who want to go to multiple destinations. Silly idea, but hey. It's necessary I learn how to do this for some future ideas I've got in my main Skyrim fanfiction.

Two quests are going to be needed: one which handles dialog, the other is a timer. If you've already made the timer and finished adding a second location, but wish to add a third location, skip to step 3a.

I'll start with the timer. ⌛ There are two ways to go about this: the timer can be directly attached to the quest which handles dialog, or it can be standalone. I prefer standalone. Reason being: the same timer, just one, can be structured to handle several other quests.

Object window > Character > Quest
1a). Start a new quest.

ID: aaaTimerQuest
Quest Name: not needed.
Priority: 0

Type: None

Flags: Start Game Enabled.

1b). Click OK and reopen the quest. In the Text Display Globals window add...

aaaAccompanyGlobal
aaaTimerGlobal

Other globals might be needed as seen fit. But I've been able to make this work with just those two.

1c). Click the Scripts tab. Right-click > Add Script into the window.

1d). Double left-click on [New Script] and give the script a name. I am calling it aaaTimerScript. The script appears in the window as a blue + icon.

1e). Right-click onto the script's name > Edit Properties (or simply highlight the script name and press the Properties button).

1f). Press Add Property. First property added is like so...
Type: Float
Name: DelayHours


As always, the property's name can be whatever. I like DelayHours because this is the name of the property used by Helgen Reborn, and it's easy for me to remember.

Click OK, closing the Add Script Property panel.

1g). Highlight the property and select Edit Value button. Value is the number of hours which would normally pass before the timer finishes counting. 🕰 Leave this on 0. Reason being, this count gets started later on via dialog, which is when the true number of hours will get set.

1h).Press Add Property again. Second property is...
Type: GlobalVariable
Name: aaaTimerGlobal


Click OK, closing the Add Script Property panel.

1i). Highlight the aaaTimerGlobal property and select Edit Value button. Find the global's name. Or actually... since aaaTimerGlobal has already been created, this will auto-fill as a Value.

Click OK, closing the Script Property panel. The idea: The timer is not going to bump quest stages, instead it'll be moving the GlobalVariable around. The advantage here is exactly the same as found in Oblivion's Construction Set or Fallout's G.E.C.K.: variables can go up OR they can go down, whereas stages can only move upwards. Well, stages can be moved down as well, but the Story Manager is needed to make this happen, which is overly-complicated to use, imo.

1k). Right-click > Edit Source on the script. Right now here is what I'm seeing.

Scriptname aaaTimerScript extends Quest

Float Property DelayHours Auto
GlobalVariable Property aaaTimerGlobal Auto


These next parts, we'll need to type in manually. 📝
Scriptname aaaTimerScript extends Quest

Float Property DelayHours Auto
GlobalVariable Property aaaTimerGlobal Auto

function OnInIt()

EndFunction

Function OnUpdateGameTime()

EndFunction


1j). File > Save (or Ctrl + Save). If the script compiles, continue with the rest. I will color the new parts in red ink to make this process a little easier.

----------------------------------

Scriptname aaaTimerScript extends Quest

Float Property DelayHours Auto
GlobalVariable Property aaaTimerGlobal Auto

function OnInIt()

If Self.IsRunning()
self.RegisterForSingleUpdateGameTime(DelayHours)

EndIf


EndFunction

Function OnUpdateGameTime()

If aaaTimerGlobal.GetValue() == 1
aaaTimerGlobal.SetValue(2)
UnregisterForUpdateGameTime()

EndIf


EndFunction


;----------------------------------------------------

1k). Save that script and close it.

OPTIONAL: For anyone who wants to make an obvious, immersion-breaking message POP UP after the timer counts down, continue with this lesson. For those who don't, please skip to 2a. Personally, I kinda enjoy messages because they are definite proof the timer has worked. If you agree, make a message as per this post.

ID: aaaTimerMessage

Message Box: I've got this toggled, which pauses the game until we click OK. If this is toggled off a message will flash upon the screen, but I've found it's not as obvious.

Message Text: X hours have passed. I should see if the warrior is ready to go.


1l). Return to the quest, and go to its Scripts tab. Add a Property like so.

Property Name: aaaTimerMessage
Type: Message
Value: the name of the message. In my case it's just aaaTimerMessage.

1m). Edit Source the script. Add this line of code into the second if/endif block... aaaTimerMessage.Show(). That should go right under the line which sets the Timer global-variable.


Time to make the quest which handles dialog. It is possible to use the same quest as before (the one which leads to Dragonsreach) and just add to that. But this also means adding a lot of new Topics as well. For the sake of organization I'm starting a second. Thing is, this second quest doesn't need to have some of the dialogs found in the first quest, because the assumption is that the NPC and our PC know each other a little by now. Because of this a second ForceGreet is not needed, for instance.


Object Window > Character > Quest
2a). Start a new quest.

ID: aaaRandomTravelQuest
Quest Name: A Warrior's Accompanyment
Priority: 50

Type: Side Quests or Miscellaneous

Flags: Start Game Enabled.

Conditions:
PL GetLevel NONE > 5.00 AND
S GetQuestRunning Quest: 'aaaDragonsreachTravelQuest' != 1.00


2b). Click OK. Save. Reopen.

2c). Right-click > Add the following into the Text Display Globals window:

aaaAccompanyGlobal
aaaRefuseAccompany
aaaTimerGlobal
aaaWaitGlobal

Note that the Text Display window is mostly used for Aliases, and therefore is not 100% necessary for this lesson. I like putting these globals here anyway, just for organization's sake.

And actually, RefuseAccompany is optional. I only used it in the initial lesson to get rid of the ForceGreet behavior when the NPC first meets our character. Anyone not planning to use a second ForceGreet won't need aaaRefuseAccompany

2d). Click OK.


Now reopen the previous quest, the one which led the NPC to Dragonsreach. Add aaaTimerGlobal into its Text Quest Globals window.

Now open the final dialog, when the NPC paid us for taking him here.

2e). Remove the Goodbye flag. Right-click > Copy All Conditions.

2f). Click OK 2x, closing the quest window. Reopen it. Right-click > Add Topic into the same branch.

ID: aaaWarriorTravelDragonsreachFinalInfo

Topic Text: Thank you for payment.

Priority: 100

Response Text: I may need your help in a day or two, going somewhere else. Why don't you return tomorrow?

Flags: Has LIP File, Say Once, Force Subtitle, Goodbye.

Properties: Make GlobalValue properties for the TimerGlobal and AccompanyGlobal. Also make two more: a Quest-type property for aaaTimerQuest and a Float for DelayHours. These are created in exactly the same way as they were for the timer itself, except this time, give the Float an actual Value. So if the value is 8, eight hours will pass before the timer concludes.

SCRIPTS

Begin:
;Timer counts down.

End:
aaaTimerGlobal.SetValue(1)
aaaAccompanyGlobal.SetValue(0)
aaaTimerQuest.RegisterForSingleUpdateGameTime(DelayHours)


Conditions:
PL GetInCell Cell: 'WhiterunDragonsreach' == 1.00
S GetGlobalValue Global: 'aaaTravelDragonsreach == 2.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Note: the 'Travel Dragonsreach' has been changed from 1.00 to 2.00, which occurred during step 13e in the previous lesson.


2g). Link the existing topic in the Dragonsreach branch to the new topic. Click OK, closing the qeust window.

2h). OPTIONAL: make some quest stages for this initial quest, or skip to step 3a if you don't want these.

I made stages 0, 10, 50, and 100, for instance. Then I went back to the pertinent dialog, so that Stage 10 occurs after the initial ForceGreet is done, 50 triggers when the player decides to travel to Dragonsreach (this included a Log Entry for the quest journal), and Stage 100 triggers when we get there, get paid, and the NPC says "I may need your help tomorrow..." As stated, stages are only needed for anyone who wants some updates to appear in their in-game journals.

I also made an objective for Stage 50: "Accompany warrior to Dragonsreach" it says. SetObjectiveDisplayed(50) gets triggered. Unfortunately, objective messages can only get triggered via the Quest Stages page as far as I can tell.

2i). Type Stop() into the Papyrus Fragment box. Compile. Click OK.

2j). Click on the final quest stage. Right next to the Complete Quest toggle is the Next Quest scroll-bar. Find the new quest (the one which was started during 2a...) in the scroll. So I've got aaaRandomTravelQuest selected.


Object Window > Miscellaneous > Global
3a). Right-click > New into the main window.

3b). Add a global called aaaTravelRiverwood (or wherever). Repeat for Nightgate Inn, or any other location.

These shall have a Variable Type of Short and 0 for Value.


Object window > Character > Package
4a). Right-click > New into the main window.

ID: aaaTravelRiverwoodPackage
Package Template: Travel
Owner quest: Do not use this. Leave it on NONE.

Package tab, Place to Travel: In cell: 'RiverwoodSleepingGiantInn'

Flags tab: Must Complete, Preferred Speed: Fast Walk. Everything else off, unless you don't mind the NPC chatting occasionally, or getting involved in "World Interactions".

Conditions tab:
PL GetDistance Reference: 'aaaWarrior01Reference' <= 512 AND
S GetGlobalValue Global: 'aaaTravelRiverwood' == 1.00 AND
S GetGlobalValue Global: 'aaaWaitGlobal' == 0.00


The GetDistance makes sure the NPC won't wander too far ahead. "512" units are about as far as one of the outdoor staircase sets in Whiterun, from bottom to top. Make this number lower if the NPC doesn't want to get too far ahead, and higher if they're more reckless. Run on scroll-bar should be Player and the [TARGET] button set on the NPC's Ref ID.

4b). Repeat 4a for any additional AI packages. In fact it's even easier to do so. Simply rename the ID (aaaTravelNightgateInnPackage), click on the Package tab, change Place to Travel to In cell: 'NightgateInn' (or wherever). Flags are all the same. Change the 'locational' global accordingly.

Close and save as a New Form.


4c). Find the Wait package previously used in the quest to Dragonsreach, or skip to 5a if this is already been done. Here are the Wait's features.

ID: aaaWaitPackage
Package Template: StayAtCurrentLocation

Public Package Data: Not used. Leave this window blank.

Flags tab: Must Complete for sure. Allow Idle Chatter, and any of the "fallout" behaviors on the right of the Flags panel are optional.

Hmm. For Conditions I kinda screwed up earlier, and added a condition which makes traveling to Dragonbridge == 1.00. This is not needed. And I want to make this Wait package generic so I can reuse it for other locations. So change the aaaTravelDragonbrige to aaaAccompanyGlobal.

Conditions tab: S GetGlobalValue Global: 'aaaAccompanyGlobal' == 1.00 AND
..................... S GetGlobalValue Global: 'aaaWaitGlobal == 1.00


5a). Open the new quest started in step 2a. During this quest we return to the NPC, who now wants us to accompany him somewhere else. As hinted, I am going to make two possible destinations, either of them random. So, he'll either want us to take him to Riverwood, or to Nightgate Inn. Random dice-roll here.

But I also don't want him to ask us to take him somewhere right away; in fact it'll be several hours before he's ready to go. During this time, my character can wander around town. Go shopping. Get a room, whatever. That's obviously what the timer is for. ⌛

NOTE: If the quest has already been written and a new "return" dialog set is needed, go ahead and make this now. skip to 5c

5b). First, I went to the Quest Stages tab and added two stages: 0 and 1. I merely added these stages so a journal update would show up in the game once my healer starts this new adventure. "I have accompanied a warrior to Dragonsreach. He has paid me, and wishes for me to accompany him to other destinations. This could be a lucrative opportunity."

... something like that. It's possible to use more stages if anybody wants more journal updates. But I'm only using that one, as a signpost to signify the beginning of my healer's new path in life. Otherwise, this is a quest which never ends.

5c). Go to Dialogue Views or Player Dialogue tab, whatever you're more comfortable with. As per other 'random' quests I've made in the past, there will be several landing spots for dialog. This first one deals with the character when he/she returns to the NPC, during which there are Yes and No choices. The second (if Yes is chosen) is the Locational topic, which leads to several, random destinations. But let's start with the first bit.

ID: aaaRandomTravelQuestPlayerReturnsID
Branch: aaaRandomTravelQuestPlayerReturnsBranch

Topic ID: aaaPlayerReturnsTopic
Subtype: Custom
Topic Text: I have returned.
Prompt: How goes it here in Dragonsreach?
Priority: 100.00

Eventually, several responses from the NPC will share the same "I have returned" Topic Text. Prompt gets used to make the text we click on in-game vary from location to location.

Response Text: Wonderful. I've got another delivery to make. Interested in making more coin?

Flags: Has Lip File, Force Subtitle (if using no voice)

Conditions:
PL GetInCell Cell: 'WhiterunDragonsreach' == 1.00 AND
GetGlobalValue Global: 'aaaAccompanyGlobal' == 0.00 AND
S GetGlobalValue Global: 'aaaTimerGlobal' == 2.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


5d). Copy All those conditions.

5e). Right-click > AddTopic. This next topic shall be the "Locational" one during which the NPC offers a random choice: either Riverwood or Nightgate Inn. And from either of those location-choices there will be either a "yes" or a "no" choice.

ID: aaaLocationalTopic
Priority: 50

Topic Text: So where are you headed next?

Prompt is not used. Several locational responses are going to share the same Topic Text.

5f). As mentioned, there shall be two or more infos contained within this "locational" topic. First one describes Riverwood.

Response: I need to go to Riverwood. I promise to pay 50 coins when we arrive to Riverwood's Tavern, the Sleeping Giant Inn. What say you?

Conditions: Paste the same conditions from step 5c, all four of them, however the GetInCell is going to get changed. Every time a new location gets added: Nightgate Inn, The Bee and Barb, and so on, that GetInCell is used to make sure the NPC will not say this if he's in the particular location. Because we don't want him saying "Please take me to Riverwood" if we're already there.

PL GetInCell Cell: 'RiverwoodSleepingGiantInn' != 1.00 AND
S GetGlobalValue Global: 'aaaAccompanyGlobal' == 0.00 AND
S GetGlobalValue Global: 'aaaTimerGlobal' == 2.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Flags: Has Lip File, Force Subtitle (if using no voice), Random.

The Random flag is important. It makes sure this moment becomes a dice-roll.

5g). Click OK, closing the Topic Info panel. Right-click > Add Topic into the yellow branch section of the window.

Topic: aaaYesRiverwood

Priority: 50

Topic Text: Aye, let's head to Riverwood

Response Text: Splendid. I promise to pay 50 gold when we arrive to the Sleeping Giant Inn.

Flags: Has LIP File, Force Subtitle, Goodbye

Conditions: paste the same four from before, however GetInCell isn't needed anymore.

GetGlobalValue Global: 'aaaAccompanyGlobal' == 0.00 AND
S GetGlobalValue Global: 'aaaTimerGlobal' == 2.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Properties and Scripts:

Begin:
;Player decides to head to Riverwood
aaaNPCName.SetPlayerTeamMate()
aaaAccompanyGlobal.SetValue(1)

End:
aaaTravelNightgateInn.SetValue(1)
aaaNPCName.EvaluatePackage()
aaaTimerGlobal.SetValue(0)


A short tutorial for SetPlayerTeammate is here, for those who have forgotten. EvaluatePackage is described as well. Both of these use Actor for their Property Type.

5h). Click OK.

Also start a new branch which leads to a "no" response (skip to 6a if this has already been done). Several dialog choices can get filtered to this one NO topic, saving time and effort.

ID: aaaNoTopic

Priority: 25

(Priority is lower than the usual 50 so "No" is always below "Yes".)

Topic Text: I cannot follow you at this time.

Response: Ah fiddles. Guess I'm on my own then.

Conditions: Paste the same conditions from step 5c, of them, but get rid of GetInCell. So the Timer should be 2.00, the Accompany should be 0.00, and the GetInFaction is here as well.

Flags: Has Lip File, Force Subtitle (if using no voice), Goodbye.

So, let's review. If the guy is told "No" he will sulk (I gave him a Sad face of 100) but otherwise won't do anything but sandbox a bit. He'll just hang out in Dragonsreach unless we change our minds. When additional dialog for additional locations get added, he'll sulk in those locations as well, due to the DefaultSandbox in his AI Packages stack.

Let's say "No" is chosen, our character goes and does other things, but then changes mind, and returns to the warrior. Dialog should start all over from the beginning in this case. "I have returned," we click on in the game. "Wonderful. Interested in making more coin?" says he.

Good idea to go into the game now, just to make sure that portion of dialog shows up if "No" is chosen, but also repeats. So save all work, leave the Creation kit open, and go in the game. 👍 See you in a few.


6a). Single left-click on the original topic, in which we return to the traveller after X amount of waiting, timer counting down, etc. The mouse icon should turn into a hand. Drag the hand to the Yes topic, and repeat for the No topic.

Note: Actually, for those who use Dialogue Views window, sometimes it's easier to go directly into each Topic Info panel, right-click into the Link To: window, and link topics this way, especially after adding multiple location choices. All those links begin to crisscross after a while, which can get confusing.

6b). Repeat steps 5f through 5g. Starting with the Locational topic, right-click > Edit Topic (so the Topic panel opens), and then right-click > New into the Info window. See? We can put as many location choices here as we want.

Again, make sure to test all of that works. By now, you should be able to return to the NPC in Dragonsreach after the timer counts down (and assuming the PC is in one of the other locations, the same should happen in those locations as well). Yes should lead to a choice of destinations (but NOT the cell the PC is in) and No should lead to a circular dialog loop, during which we can change our minds in the future.



Object window > Actors > Actor
7a). Open the NPC template and go to the AI Packages tab (or if you're using a FormList as described in the next tutorial, open this instead). Right-click > Add any travel packages just written. It shouldn't matter if it sits above the ForceGreet from before, but make sure the DefaultSandbox stays at the very bottom.

7b). Click OK.


Object window > Character > Quest
8a). Reopen the 'additional locations' quest and go into Dialogue Views or Player Dialogue. Time to make some dialog which causes the NPC to wait, continue, or show what he's got in his inventory, all of which are crucial during travel. All of this got written up for the initial quest, but heck, no harm in writing them up again. Each of these is (again) getting their own Branch and Topics, so anyone who already knows this stuff can skip the next few steps. But I'll write it up anyway. 👩‍🦳

Skip to 8d if Wait, Continue, and Share dialog has already been added.

Here's what works for waiting.

ID: aaaWaitID
Branch: aaaWaitBranch
Topic: aaaWaitTopic
Priority: 75

Topic Text: Let us take a few moments of respite.

Response Text: Alright. I'll be right here.

Flags: Has LIP File, Force Subtitle, Goodbye

Conditions:

S GetGlobalValue Global: 'aaaWaitGlobal == 0.00 AND
S GetGlobalValue Global: 'aaaAccompanyGlobal == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Copy All those three. An additional GetInCell "CellName" != 1.00 can be used for each location, this way there won't be an option to make the NPC wait when he/she's already inside the destination. Use AND qualifiers between each location, don't use OR.

PL GetInCell: Cell: 'NightgateInn' != 1.00 AND
PL GetInCell: Cell: 'RiverwoodSleepingGiantInn' != 1.00 AND
S GetGlobalValue Global: 'aaaWaitGlobal == 0.00 AND
S GetGlobalValue Global: 'aaaAccompanyGlobal == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Script Begin Box: ;Party comes to a halt.
Script End Box: aaaWaitGlobal.SetValue(1)


8b). Here's what works if we wish for the NPC to continue moving, after a wait period.

ID: aaaContinueTravelID
Branch: aaaContinueTravelTopic
Topic: aaaContinueTravelRiverwood

Topic Text: Let us sojourn.

Priority: 90

Response Text: Fine. Let us commence.

Flags: Has LIP File, Force Subtitle, Goodbye

Conditions: Paste the three conditions from before but change the WaitGlobal from 0.00 to 1.00.

S GetGlobalValue Global: 'aaaWaitGlobal == 1.00 AND
S GetGlobalValue Global: 'aaaAccompanyGlobal == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Script Begin Box: ;Party continues to destination.
Script End Box: aaaWaitGlobal.SetValue(0)


8c)
. And there's inventory management. Very important to upgrade the NPC's gear or hand over a potion and so on, once we're on the dangerous road. 👾

ID: aaaOpenInventoryID
Branch: aaaOpenInventoryBranchTopic
Topic: aaaOpenInventoryTopic

Priority: 20 (or make it higher if you want inventory access to be higher in the topic stack).

Topic Text: Here, let me give you something.

Response Text: Here's what I got.

Flags: Has LIP File, Force Subtitle.

Conditions:

S GetPlayerTeamMate == 1.00 AND
S GetGlobalValue Global: 'aaaAccompanyGlobal' == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Script Begin Box: ;Opens NPC traveller inventory

Script End Box: akSpeaker.OpenInventory()

Follow this tutorial to learn how to get into their stuff. And also, the aaaAccompanyGlobal variable can be used instead of GetStage, for anyone who wants the NPC to share ONLY while traveling. I just wanted the option of sharing at any time.


8d). Here's the dialog for when the NPC makes it to destination. This first example is for Riverwood.

ID: aaaArriveDestinationID
Branch: aaaArriveDestinationBranchTopic
Topic: aaaArriveDestinationTopic

Priority: 100

Topic Text: Looks like we're here.
Prompt: We've made it to Riverwood. Alive.

Response Text
: Yes. And looks like I owe some coin. Why not treat yourself to a night of fun?
You are good at healing magic. Come back in a day, might want to travel with you again.

Flags: Has LIP File, Force Subtitle, Goodbye

Conditions:
PL GetInCell Cell: 'RiverwoodSleepingGiantInn' == 1.00 AND
S GetGlobalValue Global: 'aaaAccompanyGlobal' == 1.00 AND
S GetGlobalValue Global: 'aaaTravelRiverwood' == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00

Script Begin Box:
;Warrior makes it to Riverwood
aaaNPC.SetPlayerTeamMate(FALSE)
aaaTravelRiverwood.SetValue(0)


Script End Box:
aaaAccompanyGlobal.SetValue(0)
aaaTimerGlobal.SetValue(1)
Game.GetPlayer().AddItem(Gold001, 50)
aaaTimerQuest.RegisterForSingleUpdateGameTime(DelayHours)


Note: The TimerGlobal getting set to 1 causes the timer to work at moving dialog forward after X amount of time, however the 'RegisterForSingleUpdateGameTime' is what TRIGGERS the timer's script into action. This is important, and is different from how timers work in earlier games. Each time a new instance of the timer is to run, it has to be "registered" to do so, and also unregistered at some point (assuming the quest is supposed to run eternally, such as a room rental quest).

Two properties are needed which are exactly the same as found in the standalone Timer Script quest written earlier: a Float with X number of hours which I'm calling DelayHours, and the Timer quest also has to be made into a property.

Property Name: DelayHours
Type: Float
Value: 8.00

Property Name: aaaTimerQuest
Type: Quest
Value: aaaTimerQuest

8e). After playtesting this mod a bit, especially out on the road, I also decided to make a global, a package, and dialog to make the NPC follow my character rather than lead. This comes in handy during many situations: 1). if the player decides he/she'd like to stop in an inn along the way or go shopping in some village, and 2). the NPC starts walking in a direction we know is too dangerous, or too much of a long-cut, 3). A simple 'debugging' measure, because sometimes NPCs get stuck!

I won't go into full details with dialog and so forth. Make a package has Follow for the Package Type, with Player as the Reference. Conditions also are important. The NPC should be able to be told to follow while waiting, or while leading. Therefore, the conditions looked like this...

S GetGlobalValue Global: 'aaaFollowGlobal' != 1.00 AND
S GetGlobalValue Global: 'aaaAccompany Global == 1.00 AND
PL GetInCell Cell: 'RiverwoodSleepingGiantInn' != 1.00 AND
PL GetInCell Cell: 'NightgateInn' != 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction == 1.00


Conditions for waiting won't require any new condition, but make a global to 'turn off' the Follow package when we wish to make him lead again, or wait: aaaFollowGlobal.SetValue(0)

Conditions for leading (the NPC leads, not the player) are as follows.

S GetGlobalValue Global: 'aaaFollowGlobal' == 1.00 OR
S GetGlobalValue Global: 'aaaWaitGlobal == 1.00 AND
S GetGlobalValue Global: 'aaaAccompany Global == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction == 1.00


Again, an additional property & script fragment are needed, to make aaaFollowGlobal.SetValue(0) happen.

8f). Go into any "travel" AI packages (such as aaaTravelNightgateInn) and add the condition: S GetGlobalValue Global: 'aaaFollowGlobal' != 1.00. If this is not done the Follow package will begin fighting with the Travel packages, causing the NPC to try going somewhere, but abruptly turning to follow us.


9). Proofread everything. Go back through it all and see if everything looks as though it'll work. Or, step 9 can be skipped, or skimmed. Sometimes I get lazy at this point, or too burnt out after all those numbers and script fragments, and stuff gets overlooked, even after I've checked it over.

Mistakes tend to show up as we're out in the gameworld of course, usually something small which gets overlooked. A comparison which is wrong, such as PL GetInCell WhiterunBanneredMare == 1.00 which should have != for a comparison instead of ==. Stuff like that.

Finally, I need to make a death script. ☠ My warrior guy is not Essential, and if he dies, he'll respawn right where he fell. So there needs to be a way to make him respawn in (let's say) Bannered Mare, which is where this all started.


OBJECT window > Actors > Actor
10a). Open up the NPC traveller (not the template). Press the Add button next to the Papyrus Scripts window.

There are two ways to handle this: 1). Set a quest stage when the NPC dies or 2). Set a variable. To set a quest stage, start by typing Death into the Filer slot and scroll down to "defaultOnDeathSetStage". A stage can be set to whatever ... let's say 10. Once the stage is 10 the Story Manager can be used to make the stage return to its initial value (stage 1 in my quest) via a timer, as well as making the NPC teleport to Bannered Mare or wherever.

However I prefer using variables. 🧮 I just love scripting.

10b). Object Window > Global. Make a new global called aaaDeathGlobal. Copy its ID name and paste it somewhere. Variable Type is Short and Value is 0.

10c). Return to the NPC (again, not the template). Right-click > Add Script and double-click [New Script].

Name: aaaDeathScript

10d). Click the Properties > Add Property. GlobalVariable for Type, and paste the ID name just copied, unless you want the Property to have a different name.

10e). Click OK, save. Reopen the NPC and Edit Source the script.

Scriptname aaaDeathScript extends ObjectReference

GlobalVariable aaaDeathGlobal Auto

Event OnDeath (Actor Killer)

EndEvent.


10f). Save that. Now add this code below the OnDeath event line

If aaaDeathGlobal.GetValue() == 0
aaaDeathGlobal.SetValue(1)

EndIf



10g). Save and close that. Close the NPC. A second timer script quest can be started as per this post so that after X amount of time the NPC gets moved to whichever initial location. Since corpses stay around for 10 days (I think) I'm going to use the timer to teleport (or MoveTo) the NPC to a new location after 240 hours. So make a Float property (that's the only one we'll need) for 240 hours.

Make the timer into a standalone quest, or attach it to the second traveling quest (the one which leads from Dragonsreach), don't attach it to the NPC.

10h). In the timer quest's Quest Data page > Text Display Globals window attach aaaAccompanyGlobal, aaaDeathGlobal, aaaTravelRiverwood, aaaTravelNightgateInn (and any other locational globals), and aaaWaitGlobal. Click OK.

10i). Reopen the quest and go its scripts tab. There should be All 5 globals are made into GlobalVariable properties. I'm going to skip a few steps here, just to show the script looks like.

Scriptname aaaDeathTimerScript extends Quest

Float Property DelayHours Auto

GlobalVariable Property aaaAccompanyGlobal Auto
GlobalVariable Property aaaDeathGlobal Auto
GlobalVariable Property aaaTravelNightgateInn Auto
GlobalVariable Property aaaTravelRiverwood Auto
GlobalVariable Property aaaWaitGlobal Auto

Function Oninit()
self.RegisterForSingleUpdateGameTime(DelayHours)

EndFunction

Function OnUpdateGameTime()

If aaaDeathGlobal.GetValue() == 1
aaaAccompanyGlobal.SetValue(0)
aaaDeathGlobal.SetValue(0)
aaaTravelNightgateInn.SetValue(0)
aaaTravelRiverwood.SetValue(0)
aaaWaitGlobal.SetValue(0)

UnregisterForUpdateGameTime()

EndIf

EndFunction


10j). Return to the NPC and open his/her script. There should already be a property for the DeathGlobal. Add a 2nd Property which references the timer quest just made. And add a third which counts time.

Property Name: aaaDeathTimerQuest
Type: Quest:
Value: aaaDeathTimerQuest

Property Name: Hours
Type: Float
Value: 1

10k). Click OK twice, closing the Properties panel, and closing the NPC. Reopen both.

10l). Right-click > Edit Source. Now add this line between the If and EndIf block:

aaaDeathTimerScript.RegisterForSingleUpdateGameTime(Hours)

This ensures the timer is reusable.



11a). Finally, we're going to make the NPC teleport to some other location as per this post.

I put a XMarkerHeading into Bannered Mare, and then added a line like aaaWarrior01()Reference.MoveTo(aaaWarrior01XMarkerHeading) in the Death Timer's If/EndIf block



--------------------------------------

TROUBLESHOOTING:

1). Save often, especially just after the NPC begins heading to his/her next destination. If the NPC disappears while going through a door, reload the previous save, and make sure YOU go through the door FIRST.

2). If the NPC gets stuck somewhere, try telling him/her to Wait, and then Continue. One of my playtests, the guy began watching the preacher in the middle of Whiterun. He became fascinated until I tried the wait/continue trick.

This post has been edited by Renee: May 19 2024, 06:40 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Posts in this topic
Renee   Renee's Modding Thread   Feb 25 2018, 01:30 PM
Lady Saga   Tip: For Oblivion, Always use [url=https://www.nex...   Feb 25 2018, 01:35 PM
Renee   The Fetch Quest, Game: TES IV: Oblivion. So this...   Feb 25 2018, 01:51 PM
ghastley   The problem with the YouTube tutorials is that the...   Feb 25 2018, 04:25 PM
Renee   Awesome, ghastley. The problem with the YouTube...   Feb 25 2018, 05:18 PM
SubRosa   Excellent fetch tutorial Renee! I will probabl...   Feb 25 2018, 05:41 PM
Renee   Thank you. I tend to write up everything I do step...   Feb 25 2018, 11:40 PM
Renee   [color=green]The Kill Quest, Map Markers, and X ma...   Mar 2 2018, 11:16 PM
Turija   Great thread. I will have to think about what I c...   Mar 7 2018, 11:58 PM
Renee   Sweet Turija! See, I just learned a few new th...   Mar 8 2018, 02:53 AM
Renee   [b]How to repair Hair, Game: TES IV: Oblivion Thi...   Mar 13 2018, 02:27 AM
Renee   [color=#FF6600]How to make an NPC Vendor & Mec...   Mar 18 2018, 06:29 PM
Renee   [color=white]How to fix "Missing flowchartx32...   Mar 25 2018, 05:20 PM
ghastley   FWIW, you CAN paste into the command prompt window...   Mar 26 2018, 03:06 PM
Renee   Okay thanks, ghastley. I'll see if this works ...   Mar 29 2018, 05:18 PM
Renee   How to make a Fetch Quest (with multiple items). G...   Mar 31 2018, 11:36 PM
Renee   Each exterior cell is 4096 units by 4096 units or ...   Apr 3 2018, 02:56 PM
ghastley   At some time in the past I did a tutorial on how t...   Apr 10 2018, 07:33 PM
Renee   That'd be great. :)   Apr 10 2018, 08:15 PM
Renee   [color=#009900]Making a weather-changing item. Gam...   Apr 24 2018, 12:19 AM
Renee   [color=#996633]Faction-changing Armor and Clothing...   May 13 2018, 07:53 PM
Renee   Making an NPC Follower Game: Fallout 3 Note: this...   May 29 2018, 01:25 AM
Renee   Timer Scripts. Game: TES IV: Oblivion or Fallout 3...   Jun 10 2018, 11:53 PM
Renee   [b]Making a house for sale or rent. Game: TES IV: ...   Jun 24 2018, 03:37 AM
Renee   Cripes, it's been since JUNE since I've ad...   Aug 12 2018, 04:13 PM
Renee   [color=#CC9933]Gun Tutorial Game: Fallout 3 This ...   Aug 26 2018, 08:52 PM
SubRosa   Ignores Normal Weapon Resistance is a holdover fro...   Aug 26 2018, 08:59 PM
Renee   Thanks. I changed the info in my previous post. ...   Sep 2 2018, 12:55 PM
Renee   Another tip for making these bounty quests: I like...   Sep 29 2018, 06:50 PM
Renee   This post goes with the one above, and is going to...   Oct 12 2018, 02:41 AM
Renee   [color=green]Lizard Men! -- Game: TES IV: Obli...   Oct 25 2018, 10:59 PM
Lopov   Nice! :goodjob: I'll be using this mod whe...   Oct 25 2018, 11:25 PM
Renee   So it's possible to encounter them in Lake Ru...   Oct 26 2018, 12:04 AM
Renee   Making an NPC Vendor / Repairist. Game: TES IV: Ob...   Oct 28 2018, 02:08 AM
Renee   [b]SEQ Files, Game: TES V: Skyrim Requires the TE...   Oct 29 2018, 12:17 AM
Renee   [color=#996633]Making FOMODs through Fallout Mod M...   Nov 11 2018, 04:32 PM
Renee   ` Making an NPC follower Game: TES V: Skyrim ...   Dec 1 2018, 06:40 PM
Renee   [b]Making an NPC Vendor Game: TES V: Skyrim [b]1...   Dec 5 2018, 02:59 AM
Renee   Making a Book bump a quest stage Game: TESV: Skyri...   Dec 15 2018, 02:39 AM
Renee   [b]Skyrim Quest Tutorial (WORK IN PROGRESS, do no...   Dec 17 2018, 12:02 AM
Renee   Repeatable Bounty Quests II (innkeeper involvemen...   Dec 29 2018, 04:04 PM
mALX   This is an Awesome thread, Renee!!!   Jan 14 2019, 07:56 PM
Renee   Awesome, thanks so much. :) --------------------...   Jan 19 2019, 08:25 PM
Renee   Setting up a gamepad controller Game: Elder Scroll...   May 15 2019, 12:53 AM
mALX   Awesome! You got it working! By the wa...   May 15 2019, 01:55 AM
Renee   Awesome, thanks. I have noticed there's TONS o...   May 15 2019, 01:05 PM
Renee   Game: Fallout 3, How to use Zone Triggers to set q...   Jun 19 2019, 02:28 AM
Renee   How to transfer saves from Xbox to PC, Games: Obli...   Jun 26 2019, 12:10 PM
Renee   Making a generic NPC Enemy, [color=white] Game: TE...   Oct 29 2019, 10:53 PM
Renee   Repeatable Bounty Quests Game: [color=white]TESV: ...   Jan 5 2020, 05:47 AM
Renee   Repeatable Bounty Quests, How to add new locations...   Jan 29 2020, 01:46 AM
mALX   These are awesome tips! Thanks Renee!   Jan 5 2020, 06:26 PM
SubRosa   Wow. That is amazing.   Jan 5 2020, 07:54 PM
Renee   aw, well thanks. I appreciate your encouragement,...   Jan 5 2020, 10:48 PM
Renee   SetActorOwner https://www.creationkit.com/index.p...   Apr 1 2020, 11:43 PM
SubRosa   You can use this at the console. It is a great way...   Apr 2 2020, 12:28 AM
Renee   You can use this at the console. It is a great wa...   Apr 2 2020, 12:33 AM
Renee   USE THIS idea for Fallout3_Jail.esp. We're goi...   May 31 2020, 05:11 PM
Renee   Adding a Jail and enhancing Fallout's Crime Sy...   Jun 4 2020, 08:25 PM
Renee   Making a Patrol package. [color=#993300]Game: Fall...   Jun 20 2020, 04:55 PM
Renee   Horse Rentals. Game: [color=#006600]TES IV: Oblivi...   Jul 26 2020, 06:07 PM
Renee   Getting an Xbox controller to work on PC. Game: [c...   Jun 11 2021, 12:47 AM
Renee   [color=#996633]Trigger Zones, Game: Fallout 3 Fal...   Sep 27 2020, 12:47 AM
Renee   https://www.youtube.com/watch?v=wj6qGCT4isg...nnel...   Sep 28 2020, 02:55 PM
Renee   https://web.archive.org/web/20130429160307/...Obje...   Oct 29 2020, 11:17 PM
Renee   I have found a really good Daggerfall tutorial whi...   Nov 28 2020, 03:00 AM
Renee   More Dynamic NPCs! Game: [color=#663366]TES II...   Jun 24 2021, 02:36 AM
Renee   Getting the Take All button to work, Game: [color=...   Aug 20 2021, 06:40 PM
Renee   Setting fallback cell (instead of Tiber Septim) h...   Sep 1 2021, 01:12 PM
Pseron Wyrd   https://web.archive.org/web/20200218144220/...a-s...   Sep 1 2021, 04:32 PM
Renee   I agree, Wyrd. Now that I know why random stuff sh...   Sep 2 2021, 01:58 AM
Renee   Random Console Commands, Game: TES V: Skyrim This...   Jan 23 2022, 03:36 PM
Renee   How to make a ForceGreet. Game: [color=white]TES V...   Jan 23 2022, 07:24 PM
Lena Wolf   I thought this thread was for Oblivion? ;) Never m...   Jan 25 2022, 03:57 PM
Acadian   I thought this thread was for Oblivion? ;) ... P...   Jan 25 2022, 05:30 PM
Lena Wolf   Well, there are of course a lot of similarities be...   Jan 25 2022, 05:41 PM
Renee   Lena has a point. Maybe this thread can be moved t...   Jan 25 2022, 06:12 PM
Acadian   Okay, the mod projects forum is simply a collectio...   Jan 25 2022, 07:22 PM
Renee   Thanks, paladin!   Jan 25 2022, 08:44 PM
Renee   How to use the PC's face for an NPC. [color=wh...   Mar 13 2022, 10:11 PM
Renee   How to add a bounty to the Player via script. Gam...   Apr 1 2022, 01:21 AM
Renee   How to add the Player or NPC into a Faction via sc...   Apr 3 2022, 02:39 AM
Renee   How to fix "failed to load snowflake: Meshes...   Nov 27 2022, 04:20 PM
Renee   Installing Morrowind from Scratch Recently I had ...   Dec 3 2022, 02:53 AM
macole   Those Intervention scrolls sure come in handy. I ...   Dec 3 2022, 07:59 AM
Renee   Oops, I screwed up. :whistle: Was cleaning the nex...   Dec 3 2022, 02:26 PM
Renee   Get a Job! Game: [color=white]TES V: Skyrim I...   Dec 11 2022, 11:41 PM
Renee   Traveling with an NPC. Game: TES V: Skyrim Here...   Jan 21 2023, 07:32 PM
Renee   Traveling with an NPC, Additional NPCs. Game: [col...   Feb 13 2023, 01:58 AM
Renee   Dialog Speech Checks Game: [color=#FFFFFF]TES V: S...   Mar 3 2023, 03:58 AM
Renee   Map Marker Tutorial, Game: Fallout 3 Firstly, wit...   Mar 19 2023, 05:52 PM
Renee   Repeatable Enemy Raids, Game: Fallout 3 I love ge...   Mar 26 2023, 07:31 PM
Renee   Repeatable Enemy Raids, Additional Locations. Game...   Apr 2 2023, 06:36 PM
Renee   Gray Face bug. Game: [color=#FFFFFF]TES V: Skyrim ...   Apr 23 2023, 01:50 AM
Renee   Script Fragments. Game: [color=white]TES V: Skyrim...   May 19 2023, 06:54 PM
Renee   Fixing the Sideways Glasses Bug, Game: [color=#663...   May 26 2023, 10:29 PM
Renee   Nexus Mod Manager - installing and uninstalling Y...   Jun 8 2023, 08:02 PM
Renee   Breton Magic Resistance Tweak, Game: [color=#66333...   Jun 21 2023, 12:03 PM
Renee   Manipulating Leveled Lists Here is how to change ...   Jun 24 2023, 07:29 PM
2 Pages V  1 2 >


Reply to this topicStart new topic
13 User(s) are reading this topic (13 Guests and 0 Anonymous Users)
0 Members:

 

- Lo-Fi Version Time is now: 6th June 2024 - 10:34 AM