Welcome Guest ( Log In | Register )

6 Pages V « < 3 4 5 6 >  
Reply to this topicStart new topic
> Renee's Modding Thread
Renee
post Apr 1 2022, 01:21 AM
Post #81


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



How to add a bounty to the Player via script. Game: TES V: Skyrim

This is how to modify the CrimeGold variable via a script, adding or removing a bounty from our character's head. In this case, I'll be raising CrimeGold during a quest stage, by adding a simple script. Sure, we can open the console once we're in the game, click on our character, and type Player.SetCrimeGold X or Player.ModCrimeGold X, but here's how to do it during a quest.

And I'm only adding this to the thread because it works. goodjob.gif Not everything listed at CreationKit.com works, or is easy to understand how to add its syntax, especially for a dummy like myself.

1). I am assuming a quest is being written with stages, or will be written with stages. Go to the Quest Stages tab, and find the stage during which we want to modify a character's CrimeGold.

2). Click the Properties button. Click Add Property. When the panel pops, find Factions in the scroll-bar.

I am writing this as though I want a bounty placed upon my character's head, so...

3). In the Name slot, I am typing PlayerCrimeProperty as the property's name. Click OK, which closes the Property panel.

4). After the nifty little blue & yellow symbol shows in the Property Name window, click the Edit Value button, and find whichever hold you'd like the bounty to show. So for instance, my character is doing a quest in which she receives a bounty in Solitude, so I'm going to find CrimeFactionHaafingar in the scroll-bar.

Click OK.

5). In the Papyrus Fragment box, type the property's name, followed by SetCrimeGold, and the amount of gold desired. So in my game, I've got PlayerCrimeProperty.SetCrimeGold(100), which adds a 100 gp bounty in the hold of Haafingar.

This post has been edited by Renee: Apr 3 2022, 04:57 AM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Apr 3 2022, 02:39 AM
Post #82


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



How to add the Player or NPC into a Faction via script. Game: TES V: Skyrim

Again, I am assuming there's a quest being written in stages, and again, I am mostly adding this into this thread because it works. Essentially, I wanted to add my character into a faction, but during gameplay, and not via console.

A good way to see if this script works (especially for our character) is this. Let's say we're trying to add our character into a faction which has items we cannot pick up. We look at some items which belong to, let's say, the Blue Palace, and all we see are Steal this and Steal that.

1). Go to the quest stage which we wish the player or NPC to join. Click Properties button. This time we'll need two properties to make this work.

2). Click Add Property button. In the Type scroll-bar find Actor.

3). Choose a name. If PlayerRef is chosen, this will automatically fill (Auto Fill) as the property's name during step 4 below. But for anyone who wants a customized name, y'all can choose your own name, such as PlayerProperty. Copy-paste that name to a Notepad or Wordpad page (or just remember it). Click OK.

4). If PlayerRef was chosen this will auto-fill. Otherwise, click Edit Value. Find PlayerRef in the Reference scroll-bar.

If we want to affect a particular NPC, choose whichever cell the NPC is in and find the NPC in the Reference scroll-bar. Note that only referenced NPCs will work, so if the NPC hasn't got a Reference ID, go ahead and add one. This Reference ID can become the property's name, which will auto-fill, just like PlayerRef did during step 4.

5). Click OK, closing the Properties for Script panel.

6). And now for the second property. Click Properties > Add Property, and find Faction in the scroll-bar. For my character, this is SolitudeBluePalaceFaction. Give the Faction a Property Name. I am choosing SolitudeBluePalaceFaction, just because this will simply auto-fill. Click OK.

7). If you've chosen a name which doesn't auto-fill, highlight the property just made, and find whichever faction in the scroll-bar. Click OK, closing the Properties panel, and click OK twice more, closing the Quest windows. Reopen the quest.

8). In the Papyrus Fragment box, type CharacterPropertyName.SetFactionRank(FactionPropertyName, 1), with 'CharacterPropertyName' whatever was chosen during step3. Since I am adding my own character into the Blue Palace Faction and used PlayerRef for the property name, I'm typing PlayerRef.SetFactionRank(SolitudeBluePalaceFaction, 1)

Note that final number "1". This is what the Creation Kit calls AIRank, and AIRank is a number which can vary from -127 to 128. In most cases, we're simply going to be using -1, 0, or 1, which removes or adds the PC or NPC to that faction.

9). Go back in the game. If the PlayerRef was just added to a faction, when the quest gets to that particular stage, try going back to wherever those forbidden items were. If the game said we can only Steal these items, now we should be able to pick them up.

For NPCs, the main way to test if a person has been added or removed to the faction is to click on them with the console, and type GetFactionRank "Faction ID", and the ID will be needed in the form of whichever 8 character ID number has been assigned to that faction.

This post has been edited by Renee: Mar 8 2024, 07:00 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Nov 27 2022, 04:20 PM
Post #83


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



How to fix "failed to load snowflake: Meshes\BM_Snow.01.nif" error.

Game: TES III: Morrowind

If Morrowind crashes on startup and the 'snowflake' message shows on your desktop, here's what I did to fix. This assumes Morrowind, Tribunal, and Bloodmoon have already been installed, and may have previously worked.

Some of these words are not mine. I copy/pasted from the Steam website. But I don't use the Steam version of MW, I have the disc version. There are instructions for both versions below.

For steam users
1). MAKE SURE your Steamapps folder is NOT in Program Files folder. Create a custom folder outside of Program Files and install the game there.

2). Once done, install Morrowind and run the launcher, close it. Verify your game integrity game cache


For CD GOTY users
1). Open the CD and RUN the AUTORUN.EXE AS ADMINISTRATOR if you have to. Install the files OUTSIDE PROGRAM FILES one by one: first Morrowind then Tribunal then Bloodmoon. Due to an unexpected failure in Windows Vista or later, some files will not be copied for some reason. You have to copy them manually.

Note: the guy at Steam said we also have to install the Construction Set separately, after installing Morrowind, but I did not need to do this. My CS was automatically installed from the MW disc. But I have the Anthology set, not GOTY. Maybe there's a difference.

2). Right-click on Morrowind (as it appears in the CD drive). Right-click Data Files folder and choose copy (I have Windows 8, I had to click Expand to see these files).

3). Paste the copied Data Files folder into the Morrowind installation folder. Overwrite? Yes. Remove the Morrowind installation disc.

4). Now follow the same steps for the Tribunal and Bloodmoon discs, starting with Tribunal. Right-click Data Files folder and choose copy. Paste these into the main Morrowind installation folder and paste there. Overwrite anything.

5). Follow the same process for the Bloodmoon disc.

Personally, my game was loading up fine by now. But here are some additional steps for those who might still be having probs.


1). Go into the main MW folder and open the Morrowind.ini (it's a Notepad file).

2). Find [Archives] and make sure it looks like this:

[Archives]
Archive 0=Morrowind.bsa
Archive 1=Tribunal.bsa
Archive 2=Bloodmoon.bsa

(note, my Morrowind.ini did not have an [Archives] section, but I found the three pertinent lines of text at the very bottom of the page under [Game Files]

3). If those three lines (nor an Archives or Game File section) exists on the .ini just copy/paste them in.


4). SAVE the ini. Congratulations, You are done, enjoy your game!

This post has been edited by Renee: Dec 7 2022, 03:55 AM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Dec 3 2022, 02:53 AM
Post #84


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



Installing Morrowind from Scratch

Recently I had some problems with Morrowind, and had to install from scratch, all the way back to the discs. At first I tried to circumvent this process, which (long story short) did not work. Here's the story.

I happen to have a backup folder with all the vanilla files intact, so I copy-pasted this, but the same problems persisted. So with no other choice, I decided to go all the way back to the beginning. Started all over, installing from the Anthology discs. But as I did so, I ran into a slew of problems. For some reason the buttons on my Xbox controller were not working properly. Or rather, they weren't registering properly. I'd go to jump, and nothing happened. Ready weapon? Same thing, unless I pressed the button over and over. Finally, the Mod Config menu was missing.

But I was also able to fix all of this, and here's how.

Firstly, do NOT get rid of your old Morrowind folder. Keep this around, at least for a while, even if you think there's nothing useful in there.

--============================================

1a). Rename the old Morrowind folder. For instance, I changed my folder's name from Modded Morrowind to "aModded Morrowind". This is important. If the folder is not renamed, later on when we're trying to reinstall the game it'll keep trying to uninstall from the old folder first. It's doing this so it can reinstall into this folder, which I already know will cause probs. This is what I described toward the end of the paragraph above.

1b). Make a new folder, outside of Program Files (x86). Name it whatever you want. I named this folder Modded Morrowind.

And this is why it's important to keep the old folder, at least for now. Sometimes it's useful to see how folder paths were structured, especially when comparing the old folder to the new one. It's also good to see what's stored in there, for whatever reason. Basically, that old folder becomes a point of reference.


2). Right-click > Install Morrowind from the disc. Follow all the prompts listed by the install wizard as usual. Install the game into your new folder.

Note that my copy of Morrowind is from the Anthology disc set, which included a separate disc for the Construction Set. We won't need to install this disc; the regular Morrowind disc already installs this for us, assuming you've also got the Anthology set. I think this separate CS disc is for those who wish to install only the Construction Set on some other computer.

3a). Remove the Morrowind disc and insert the Tribunal disc. Install, following all prompts. Do the same for the Bloodmoon disc, and don't forget to remove this disc and put the regular Morrowind disc into the tray before trying to start the game!

3b). Cut/paste the Saves folder from the old Morrowind folder to the new one. This is for those gamers who wish to continue a game which is already extant, of course.

>> HOWEVER, if this save included any bad stuff (mods which caused probs in the past, for instance) maybe it's better not to use it. In my case I had a brand-new character, whose game only included Tribunal and Bloodmoon so far. I hadn't added anything else yet, since I was trying to keep her game "pure" for the time being.

That's the vanilla game. At this point, I booted up the save I made from before and tried moving my gal around and stuff, but the same problems listed above were still there. Animations were jerky, especially if I tried to rotate the camera. Several buttons were still not working, unless I tapped them repeatedly.

I was pretty pissed off of course, even the vanilla game is broken??? But being stubborn, I decided to forge ahead with more installs anyway.


Next comes what I like to call the "Big Three" utilities. These are tools which are necessary for a lot of mods, and I installed each one from their original archive files (rather than copy-pasting from the old Morrowind folder).

4). I have Nexus Mod Manager (NMM) for Morrowind, because it's light and easy to use. Some folks use Wrye Mash, which is more comprehensive for those who have larger lists of mods, especially if they're beginning to conflict one another. Some folks won't need a manager at all, usually those with barely any additions. I prefer to have one though. Since I only have maybe 20 plug-ins plus a few random non-.esp additions, all I need is NMM.

NMM can be installed anywhere, it's one of those programs which automatically finds whatever games you've got. I prefer to throw its files straight into my Modded Morrowind folder, for convenience. Made a shortcut to desktop, as well.

5). Next comes Morrowind Code Patch 2.4, and again, I installed this straight into my Morrowind folder, and then made its executable file to a desktop shortcut. MCP fixes a lot of bugs and also includes a LOT of toggles we can click on or off. A lot of mods depend on MCP for its script extender functions. But it's all those dozens of toggles which can be really fun, not just for functionality, but also for roleplaying options.

For instance, for some characters who aren't thieves, I like going onto MCP's Game Mechanics page, toggling Hidden Traps and Hidden Locks on. This adds immersion. Now, my non-thief characters won't automatically know if some door is locked, or if there's a trap on that chest.

> Make sure to press Apply Chosen Patches at the bottom of the MCP page when done toggling stuff.

6). The last of the Big Three is MGE XE, Morrowind Graphics Extender XE. Again, I put this into the Morrowind folder, and sent a shortcut to desktop. This improves graphics in all kinds of ways. We can change resolution for instance, beyond the limited choices the vanilla game gives us. We can use the FPS Limiter to curtail the engine from throwing massive framerates around. I've got this set at 60, which improves overall performance since my Nvida isn't wasting frames.

I also like using its Menu UI Scaling feature. Since my TV is roughly 5 or 6 feet from where I sit while gaming, I jacked this from 1.00 to 1.55. Now I can read the game's menus without my glasses! 👓 Keep in mind that making menus larger can cause other problems. Some stuff can get pushed offscreen for instance, such as the confirmation we need tdo click for Starsigns when rolling a new character.


7). By now I tried starting up my game again and got the "snowflake" error message, which is listed in the tutorial above this one. To fix this I removed the MW disc, inserted Tribunal, and copy/pasted all the files on this disc into my Modded Morrowind folder. Did the same thing with the Bloodmoon disc.

8). Removed Bloodmoon and put Morrowind back in the tray. Went back into the game, and voila... everything was working as it should. smile.gif Why were the animations jerky? I don't know. Why were the buttons I assigned for Jump, Ready Weapon, Ready Magic, Next Weapon, Next Magic, and Use not working instantly? Not a clue. Why did I not have a Mod Config menu? You got me, pretty sure getting MCP added from its original archive fixed this, though.

So that's it: the vanilla game + its two expansions + the three main utility tools. I found it best to also install most mods from scratch, straight from their archives. I did this rather than copy/pasting my old Data Files folder. This way, I knew everything that's going into my game, and was able to take notes on what goes where, and what does what.

This is also a great chance to eliminate any dead weight. There's usually some stuff which got added at some point in the past which is no longer used. Did not work, or has stopped working. During the passionate moments of gaming I tend to forget about these sort of add-ins.


9). Finally, there might be a few things in the old Morrowind folder which can't be taken out of an archive. Here's a few examples: My Screenshots folder, Readmes folder (which I've organized diligently so everything is in its proper place, rather than scattered all over the MW folder), and also Morrowind Additions.esp, my homemade overhaul mod with hundreds of changes. It's a good idea to keep the old folder around, at least for awhile, deleting whatever's not useful anymore while cut-pasting all the stuff that is.

🍷👑

This post has been edited by Renee: Dec 28 2022, 02:29 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
macole
post Dec 3 2022, 07:59 AM
Post #85


Mouth
Group Icon
Joined: 10-January 20



Those Intervention scrolls sure come in handy.

I was interested in you BSA archive issue. Not only do you have to make sure the Archive and the three BSAs are added to the ini but any mod that uses BSA file will have to be manually added to the ini [Archives] list. Oblivion and Skyrim are a bit better in that reguard although they do have their own BSA quirks.


--------------------
Vampire Hunter,
Endure and through enduring grow strong.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Dec 3 2022, 02:26 PM
Post #86


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



Oops, I screwed up. whistling.gif Was cleaning the next draft of Joan's story and you weren't supposed to see that!

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


Each exterior cell is 4096 units by 4096 units or 192 feet by 192 feet or 58.5 meters by 58.5 meters.

There are approximately 86 cells, counting from a bit below Leyawiin all the way up to the invisible border north of Cloud Ruler Temple.

192 x 86 = 16,512 feet. 5,280 feet = 1 mile. 3 miles = 15,840. So, north to south, the game world of Cyrodiil is slightly larger than three miles.

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

The language of papyrus can be broken down into a handful of concepts: Objects, Functions, Events, Variables and Properties. The Script File Structure page provides information and examples of these concepts.

Objects: Nouns. Books, Actors, Quests, Weapons, Potions. These are things in their purest forms.

Functions: Verbs. Actions. SetStage(), Kill(), SetValue()

Events: Adverbs. When? etc. OnDeath, OnInIt, OnItemAdded. Basically "When" does X happen?

Values: Adjectives. How much? How many?

Variables: Adjectives. Whatever value is the answer or result of GetStage, GetActorValue, ModValue, and so on. So not the SetStage itself but the (5) which follows it.

Properties: Nouns, but defined in such a way that the game engine can communicate with. Because scripts are separate from data files, properties are used to define these objects (these nouns) so Papyrus can use them for the game engine.

An example: we won't kill Chamany when the time comes, we will assign a property to him, and use that property instead, even if the Property itself is called "Chamany".



This post has been edited by Renee: Mar 8 2024, 07:12 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Dec 11 2022, 11:41 PM
Post #87


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



Get a Job! Game: TES V: Skyrim

I wanted to make one of my characters in this game get a job working for Corpulus Vinius of the Winking Skeever in Solitude. The idea is going to be that my lady becomes a barmaid. She shows up looking for work, speaks briefly to Corpulus, who gives her a job. Once she's officially hired my barmaid then goes from patron to patron, asking if they'd like anything. Each patron either declines her service or accepts.

This does seem like a pretty useless idea for a mod, I'll admit. But I wanted to use this scenario to learn how variables work in the Creation Kit. Others out there might want to use some of these ideas for something more adventurous: maybe collecting pelts for a skinner, maybe collecting ores for a smith, and so on.

When I was involved more with TES 4: Oblivion, Sarah Phimm became a 'bar wench' as well, toiling for Mog gra-Mogak in Skingrad. She would make food, give it to Mograk several times during her shift, and make a menial amount of money. I was able to make this happen after installing Oblivion Jobs, but I also enhanced this mod with my own quest and dialog, so that Sarah could wait tables, making occasional tips (or not). Some customers were grateful, others were rude, and so on. All of this was easy to do. So easy, I didn't even bother writing a homemade tutorial for myself at the time, explaining how this was accomplished.

For Skyrim things are tougher, of course. I installed a jobs mod for Skyrim a few years back, but it required the USLEEP patch, which broke my game. CTDs between cells and worldspaces. rolleyes.gif Obviously we can't have that. So it's time to make our own content.

Now, there are a myriad of ways this can be made to work. For instance, there could possibly be a barrel full of supplies. Every time somebody asks for, let's say, a beer, she'll go to that barrel and see if there's a beer there. If there is, she returns to the table and delivers the beer, and there'd obviously be dialog for this. If not, there'd be dialog for that.

We can also make it so Corpulus gives a bunch of alcohol right at the beginning of her shift. Every time a sale is made this causes a tally to count. Perhaps we can use GetItemCount for this scenario.

Finally, another way to do this is every time somebody wants a drink, she returns to Corpulus, who gives her one. Then she returns to the alcoholic patron. -- That's the way I'm going to do this: one at a time. Also, I'm going to make this quest so that there's an end possibility of either quitting, or getting fired. laugh.gif

1). Open the Creation Kit and start a quest. Give it an ID (I'm going with aaaBarmaidJob), give it a name, make Priority 40.

I like 40 because what'll happen is the game will put some dialog up top, bumping the "service" dialog I'm about to write down a few notches. This makes many other topics available through that NPC seem more important. And isn't this true of real bars? People get drunk, then they want to tell us their whole life story. wacko.gif Finally, the bartender needs to ask "Can I get you anything?"

Click OK (so other quest tabs open up). Save.

FYI: To figure out how to make something like this operate I found a quest in the Creation Kit called FavorJobsBeggars. I wanted to study how this quest works because of its simplicity. Beggar asks for a coin, we give him/her a coin. For this, we get The Gift of Charity, short-lived magical effect which fortifies Persuasion. Simple enough, or so it would seem. Turns out, I had to come up with some other ways to make my idea work, which has zero similarity to that beggar quest.

OBJECT WINDOW > Character > Quest
2). Reopen the quest. On the Quest Data page, choose Side Quests for the Type scroll-bar.

3). Start Game Enabled should be toggled on by default. But toggle Run Once off.


4a). Click on the Quest Stages Tab. Five stages are needed: I'm going with 0, 10, 50, 99, and 100.

Stage 0: Toggle Start Up Stage on. Right-click > New into the top Log Entry box so it says EMPTY.

Stage 10: Right-click > New into the Log Entry box and do nothing else. During this stage we're going to speak to the innkeeper, the shopkeeper, whomever. Dialog will be added, during which we'll ask if there are any jobs. And of course there are.

Stage 50: We're hired on the spot! cake.gif Right-click > new into Log Entry. In the lower Log Entry box type "I have found a job", or whatever.

Stage 99: Right-click > New, etc. Toggle Shut Down Stage and Fail Quest on. During this stage we can possibly get fired. In real life, we can get terminated for all sorts of reasons: insubordination, not showing up, showing up late, and so on. For the purposes of this tutorial, I'm keeping it simple. The only way we can get fired is if we don't sell any drinks at all. Of course, the possibility of losing our job is near-impossible for obvious reasons. I.e., IT'S A BAR!!!

> Type "I have not made enough money, so I have been let go from my job", or whatever.
> In the Papyrus Fragment box, type Stop()

Stage 100: In this case, we "beat" the quest by quitting. laugh.gif Wouldn't that be nice. Right-click > New into the Log Entry box and type "I have quit my job........"

> Toggle Shut Down Stage and Complete Quest ON.
> In the Papyrus Fragment box, type Stop()


4b). Click OK and save.

Reopen the quest, and click on Dialogue Views or Player Dialog. I'm more comfortable with Dialogue Views so that's what I'm using for the rest of this lesson.

5a). Right-click > New into the vertical left window of the Dialog Views page and type an ID. I'm typing aaaJobQuestHiringBranch. Click OK.

5b). Highlight the ID just created and right-click > Create Branch into the large window on the right. Give this Branch a unique ID and click OK.

5c). Right-click > Edit Topic into the gray box within the yellow box. The Topic panel pops up. Give this topic an ID and type some Topic Text. I've got aaaJobQuestYoureHired for an ID. For Topic Text I've got "I'd like a job. Are you hiring right now?"

5d). Click OK twice, closing the Topic panel. Probably a good idea to also click OK on the Quest window as well, so we can save.

5e). Reopen the quest. The same page should open, so right-click > Edit Topic into the gray box, and right-click > New into the large Info window.

5f). Type the proprietor's Response Text. "Sure, we could use somebody here. Have you ever worked as an X before?" ... X being woodchopper, bar wench, hunter / gatherer, whatever.

5g). Here are the conditions I put into the Conditions tab.


GetStage Quest: aaaBarmaidJob < 10.00 AND
GetIsID Actor: 'CorpulusVinius' == 1.00


Right-click on either of these and choose Copy All Conditions.

5h). In the End: Papyrus Fragment box type GetOwningQuest().SetStage(10)

5i). Left-click on the Response text written a moment ago and click Record. Record your own voice, have someone else do it, or simply record silence. Once that's done, click Stop. Click Save. Toggle From WAV on, and click Generate Lip File.

5j). Click OK, closing the Response Text panel. Make sure Has LIP File and Force Subtitle are both toggled on (those who recorded actual voice might not need Force toggled on) and click OK.

That's the opening text. Now the PC's going to ask for a job.

6a). Return to steps 5c through 5f, except right-click > Add Topic into the yellow box, so some follow-up dialog can be made. For Topic Text I've got "I've never held a job before, is that okay?" since this answer follows the question asked during 5f.

The bartender's Response Text is "Sure I could use a second barmaid...Shift hours range from 11 in the morning until 6 at night, but you don't have to be here for all seven of those hours..."

Basically, the idea I've got is that my character will need to sell at least 1 bottle of ale to keep her job, and also get paid. She works anywhere between 11:00 and 18:00, but can only get paid after 18:00, because that's when the shift ends, and Corpulus has a dialog change. This is absolutely silly, of course. In real-life we'd need to show up near 11 AM, or else. But this is a game. So I'm trying not to be so strict. 🕥

6b). Right-click > Paste Conditions into the Conditions window, but change GetStage to 10. Altogether now I've got....

GetStage Quest: aaaBarmaidJob == 10.00 AND
GetIsID Actor: 'CorpulusVinius' == 1.00


6c). Type GetOwningQuest().SetStage (50) into the End: Papyrus Fragment box, or simply copy it from the Topic Info panel created before. If you copy/paste, make sure to change the 10 to 50. Stage 50 is where the quest shall live as long as we're working at this job.

Click OK, closing the Topic Info panel.

6d). Left-click on the first topic's middle area, so that a hand icon shows onscren. Drag the hand over to the second topic. (Those who use Player Dialog will need to use the Link To window to link the first topic to the second.)

Click OK. There we go. Our character's got a job, thanks to that nifty speech process. Next, we're going to create our own variable. In the CS or GECK, many quest and script variables coincided with whichever quest or script the variable was associated with. For the Creation Kit (as usual) this is often done differently. We can literally declare a variable (actually, they're called global variables) which has nothing directly to do with any particular quest, or a script within that quest. Is this also how it's sometimes done in the old editors? Probably so, but I've never utilized variables in such a way in those older programs.

7a).. OBJECT window > Miscellaneous > Global
All the game's global variables are listed in the larger Object window. Right-click > New and give the new variable an ID. I am typing aaaDrinksBought into the ID slot. COPY this name and put it on a Notepad page, so it can be pasted later.

7b). Variable type can be Short if we want the game to count whole numbers (such as 1.00 and 4.00) or Float if we want a decimal point to float back and forth (0.75, 1.50, etc.). In most cases Long is not used. And I'm keeping my variable on Short.

7c). Leave the Value at 0 and do NOT toggle Constant on. Apparently, Constant means the game won't be able to count or change the value for whatever items we're dealing with. Whichever value the variable starts at is where it will constantly stay, see?

7d). Click OK and save.


8a). OBJECT Window > Character > Quest
Select the Quest Data tab. Now, right-click into the Text Display Globals window (which is the lower right) and choose New. Find the global just created. Click OK.

Apparently we don't have to do this 100%. Bethesda never seems to use this window. But it's an option, which makes things organized a bit nicer.

8b). Click OK (closing the Quest window) and save.


9a). Reopen the quest, and select the Misc tab. Let's give the boss a greeting. Right-click > New into the middle window and select Hello. Highlight this and right-click into the right window and follow the typical process for making dialog. "Ah, look who's here." Follow all the processes for recording (even if it's just silence), and so on.

9b). Conditions are...

S GetGlobalValue Global: 'GameHour' > 11.00 AND
S GetGlobalValue Gloval: 'GameHour' < 15.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


Note that it is possible to make a tardiness factor at this point. For those who really want to be strict just change the second GameHour from 15.00 to 12.00. Make a second Hello which says "You're late! This better not happen again." A variable can then be used to make it so the boss only gives one chance. Once that variable climbs from 0 to 1 to 2 (as we're late twice), we're 86'd! ⌚

A final hello can be added, which states "Sorry, but gonna have to let you go..." which setstages to Stage 99. verysad.gif


9c). Locate the Hours Until Repeat slot, which is to the right of the other flags. Normally this is set at 0.00. Change this to 12.00. This is done so the bar owner won't keep greeting us with the same greeting. Basically, the shift lasts from 11:00 until 18:00, which is 7 hours. But we want to give a bit of extra time just so he doesn't keep delivering the same Hello on the same day.

Note: There is no Say Once a Day flag like there was in Fallout 3's/NV's GECK, so what just happened in 9c can simulate this.

9d). Now switch to Dialogue Views or Player Dialog. I am right-clicking > New into the Dialog Views window again, then following the steps above for making a new branch, and adding a topic to this branch. 5a through 5j. This phase of the quest is about us showing up for work, and speaking to whoever runs the place. In my game I've got...

ID: aaaJobStartWork

Branch: aaaJobStartWorkBranchTopic

Topic Text: "I'm here! What's going on at the Skeever today?"

Response Text: "Ah, glad you have arrived. Let's see if we can make some sales today."

Conditions:
S GetGlobalVariable Global: 'aaaDrinksBought' == 0.00 AND
S GetGlobalValue Global: 'GameHour' > 11.00 AND
S GetGlobalValue Gloval: 'GameHour' < 18.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


The way I've got this set up, the hire will need to speak to his/her boss first, before selling any drinks. This is not 100% necessary, it's simply the way I prefer things. `=

9e). Change the Hours Until Repeat slot from 0.00 to 12.00.

For those who are not making a job in which we're constantly interacting with the boss; let's say the boss is spoken to once, and then we're off to go hunting animals or whatever for the next day or however long, Hours Until Reset might not be needed at all.

9f). Select either of the Papyrus Fragment boxes: Begin or End. Type a semicolon and follow it with any text at all. Doesn't matter what it is, but perhaps it's best to put a description of what we want to happen at this moment.

So for instance I am typing ; Here is where the first variable gets set into the End: Papyrus Fragment box. This actually doesn't do anything in the game at all, but it's important to get a simple script into the Script Name window. We cannot add properties here unless there's a script already present.

9g). Click OK, and click OK again. Reopen the quest.

9h). Highlight the script so it turns blue. Click the Properties button. And select Add Property.

9i). Find Global Variable in the Type scroll-bar. For Name, we can just put the ID name of the variable created earlier. So I am putting aaaDrinksBought into the Name slot. This can simply be copy/pasted from that Notepad page started earlier.

>> Thing is, if we're constantly typing the variable name into this slot and in other areas of the quest's windows, and let's say we get it wrong. This can cause error messages if we consistently get it wrong!

9j). Click OK. Left-click on the property so it turns blue. If you gave the property the same name as the variable, it should automatically appear in the Pick Object scroll-bar. If not, find the variable.

Click OK, and OK again, closing the Quest panel. Note that it's important to keep OK-ing and re-opening the Quest panel, because this saves any actions just performed. If this is not done; if the modder just skips to the next step that is, have fun dealing with a litany of errors. mad.gif

9k). Reopen the quest window. Now type ; aaaDrinksBought.SetValue(1) into the End: Papyrus Fragment box. Compile that bit of code WITH the semi-colon in front. Now remove the semicolon and compile again. Voila. No error messages? Go ahead and close the Quest window and save.

On the other hand, if there ARE error messages do NOT press OK. Instead, click on the red X in the top right corner of the Topic Info panel and try again. The worst thing we can do in Skyrim's Creation Kit is introduce faulty script fragments into the game.

The next bit of dialog in my game is going to come from any customers who dwell within Winking Skeever.


10a). In the Dialogue Views or Player Dialog tabs once again. Here's what I've got in my game.

ID: aaaBarWenchServiceID

Branch: aaaBarWenchPatronServiceBranch

Topic Text: "Can I get you anything?"

Response Text: "Yeah, gimme an ale."

Conditions:
S GetIsID Actor: 'CorpulusVinius' != 1.00 AND
S GetIsID Actor: 'Lisette' != 1.00 AND
S GetGlobalVariable Global: 'aaaDrinksBought' == 1.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetInCell Cell: 'SolitudeWinkingSkeever' == 1.00


> As we can see, anyone can get asked this question "Can I get you anything?" except the bar's owner, or Lisette. Lisette is the lady who plays music. Um, she's the bard.

>> Do not use the Prompt slot for this topic. We're going to want just ONE topic to click on, but two or more infos as a result.

10b) Has LIP File and Force Subtitle should both be toggled after recording is done. Toggle Random as well. This is done so the patron can refuse service, which we'll write up in a moment. Goodbye can be toggled, though this is optional.

10c). Change the Hours Until Reset slot to some small amount, such as 0.25. This allows a little time, so the same "Can I get you anything?" topic theoretically doesn't immediately show up (from the same NPC) after we've retrieved money, gotten a drink from Corpulus. Keep in mind I've got my timescale set to 30. Those with slower timescales, or even Skyrim's default of 20, might want less time than a quarter-hour.

0.25 (a quarter hour in-game) translates to roughly 15 seconds in our time with timescale of 30. I think..

10d). Type a semicolon and follow it with some text into either Papyrus Fragment box and compile. I just typed ; Patron gives barmaid money. Click OK twice. Reopen the same quest windows.

Now we need to make two properties: one for money, and one for the global variable. Let's start with the variable.

10e). Highlight the TIF script so it turns blue. Click the Properties button. And select Add Property.

10f). Find Global Variable in the Type scroll-bar. For Name, we can just put the ID name of the variable created earlier. So I am pasting aaaDrinksBought into the Name slot.

10g). Click OK. Left-click on the property so it turns blue. If you gave the property the same name as the variable, it should automatically appear in the Pick Object scroll-bar. If not, find the variable.

Click OK, and OK again, closing the Quest panel.

10g). Reopen the quest window. Now type ; aaaDrinksBought.SetValue(2) into the End: Papyrus Fragment box. Compile that bit of code WITH the semi-colon in front. Now remove the semicolon and compile again.

10h). Highlight the script and press the Properties button. Click Add Property.

10i). Find MiscObject in the scroll-bar and type Gold001 into the Name slot. Click OK. Click Edit Value. Again, Gold001 should automatically be in the Pick Object scroll-bar. Click OK.

Click OK twice more (closing the Topic Info and Quest panels) and reopen.

10j). Type Game.GetPlayer().AddItem(Gold001, 5) into the Begin: Papyrus Fragment box. Click OK twice more.

OPTIONAL: A sixth condition can be added to the stack above in 10a, which'll check to make sure the NPC has enough money in his/her pocket. Add GetItemCount MiscItem: 'Gold001' >= 5.00, and make sure the Run On scroll-bar has Target selected. Another script/property can be used to remove gold from the NPC.

This gets complicated though. It's beyond my capabilities as a modder, but let's also consider that eventually the NPC will run out of money! And once this happens, will that money ever respawn in their inventory? There's a bard mod which was used by Lopov a couple years back which did consider how much money was in the pockets of various NPCs, and somehow it also removed this money as they requested songs. Guess what? Eventually those NPCs would run out of money! blink.gif

Up to you, folks.


11a). Now let's add some dialog which'll allow the patron to refuse service. Go back to the same branch which was just made for serving drinks. Right-click into its center (which should either be white or grey) and select New Info.


Topic Text: "Can I get you anything?" -- essentially this is the same text which is used for "Yes, gimme an ale."

Response Text: "No, I'm good."

Conditions:
S GetIsID Actor: 'CorpulusVinius' != 1.00 AND
S GetIsID Actor: 'Lisette' != 1.00 AND
S GetGlobalVariable Global: 'aaaDrinksBought' == 1.00 AND
S GetStage Quest: aaaJob == 50.00 AND
S GetInCell Cell: 'SolitudeWinkingSkeever' == 1.00 AND


11b). After recording is done Toggle Has LIP File, Force Subtitle, and Random. Goodbye should also be selected. Make sure a small number is in the Hours Until Reset slot. This time I've got 0.50. Click OK.

Notice that Random is selected for either service choice: Yes or No. As my character moves from patron to patron, some will want a drink, others will not.

Now to make the innkeeper hand over some drinks.

12a). Yet another branch is needed. I think we're up to four of these so far. I've got something like this...

ID: aaaBartenderFetchDrinks

Branch: aaaBartenderFetchDrinksBranch

Topic Text: "Someone over there wants a drink."

Response Text: "Here ya go!"

Conditions:
PL GetItemCount: MiscObject: 'Gold001' >=5.00 AND
S GetGlobalVariable Global: 'aaaDrinksBought' == 2.00 AND
S GetGlobalValue Global: 'GameHour' > 11.00 AND
S GetGlobalValue Gloval: 'GameHour' < 18.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


12b). After writing up the Response Text I toggled Use Emoticon Animation off, selecting IdleGive in the Idle Animations/Speaker scroll-bar. This is obviously to make it seems like the bartender's giving a bottle to my toon.

12c). After recording, toggle Has LIP File, Force Subtitle, and Goodbye on.

12d).. Follow steps 10d through 10j to make a simple semicolon script, and a property for the money. Here is how to utilize them...

; Player gives money to boss
Game.GetPlayer().RemoveItem(Gold001, 5)


This time I put the gold removal script into the Papyrus: Begin Fragment box, as my character's supposed to be handing the money just paid over to the barkeep right away.

Click OK twice.

12e). Reopen. Make a second property following the steps above, except this time choose Potion in the Type scroll-bar. I've chosen aaaAleProperty as the property name, as for some reason just typing Ale caused problems. Once that was done I clicked Edit Value and manually found Ale in the scroll-bar.

12f). Click OK twice and reopen. In the Papyrus: End Fragment box type Game.GetPlayer().AddItem(aaaPropertyName, 1), with "aaaPropertyName" whatever you really named that property. Click OK 2x. Save.

12g). A third property can be made which bumps aaaDrinksBought.Setvalue(3), though this is optional. Without this addition, if we speak to the boss he or she will still have the "Someone over there wants a drink" and "Here you go" Topic Text and Response, meaning the player can just keep hitting the boss up for endless drinks!

But otherwise, there we go. Now my lady's got a drink she can serve.


13a). Start another branch, and this time ...

ID: aaaBarmaidServeDrinks

Branch: aaaBarmaidServeDrinksBranch

Topic Text: "Here you are."

Response Text: "Why thank you!"

Conditions:
PL GetItemCount Potion: 'Ale' >= 1.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetInCell Cell: 'SolitudeWinkingSkeever' == 1.00 AND
S GetIsID Actor: 'CorpulusVinius' != 1.00 AND
S GetIsID Actor 'Lisette' != 1.00


Flags: Has LIP File, Force Subtitle, Goodbye.

Script: ; Barmaid serves drink.

13b). In the Begin: Papyrus Fragment box create the same property as before using the steps above, but change the value: aaaDrinksBought.SetValue(1). This is done so the quest returns back to where it was before, and we can ask someone else if they'd like a drink. 🍷

13c). The same property for the drink can also be used: Game.GetPlayer().RemoveItem(aaaPropertyName, 1). I put this into the End: Papyrus Fragment box.

Click OK 2x. Next step is to make it so that the boss can pay us when the shift ends. We will also have the option to quit during this phase of the quest, or get fired (although as stated, my lady would really have to suck to get fired).

14a). Start yet another new branch.

ID: aaaBarmaidEndOfShiftID

Branch: aaaEndOFShiftBranch

Topic Text: "Looks as though my day is done."

Response Text: "Wonderful! Excellent service, today."

Conditions:
S GetGlobalVariable Global: 'aaaDrinksBought' == 1.00 AND
S GetGlobalValue Global: 'GameHour' > 18.00 AND
S GetGlobalValue Global: 'GameHour' < 23.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


Flags: Has LIP File, Force Subtitle, Goodbye.

Script: ; End of shift begins now

14b). Make a property for Gold001 and also the same variable (which I called aaaDrinksBought earlier).

Game.GetPlayer().AddItem(Gold001, 40)
aaaDrinksBought.SetValue(0)


Now that the global variable is set to 0 if we try to speak to the boss he won't have anything to say regarding the day's job. There'll only be the usual topics he normally offers (Have you heard any rumors?, etc.) before we barged in with our own content. And this is how it'll stay until 11:00 the next day, unless some after-hours dialog gets added.

But the quest is not over yet. We still need to have some dialog regarding getting fired, or quitting. tongue.gif An optional step is going into the Misc tab and making another Hello. "Ah, whatta day," says the boss.


S GetGlobalValue Global: 'GameHour' > 18.00 AND
S GetGlobalValue Global: 'GameHour' < 22.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


I gave 4 hours of leeway there just in case of emergency. tongue.gif


15a). Object Window > Miscellaneous > Global
Make a new global. I'm calling this one aaaFiredGlobal. Leave it on Short, and leave Value at 0. Copy this name and paste it onto the Notepad page.

15b). Reopen the quest, and click on its Quest Data tab. In the Text Display Globals window find the new global just added.

15c). Go to Dialogue Views or Player Dialog. Find the Topic/Info panel which deals with making the first sale. "Yeah, gimme an ale" says the NPC in my game.

15d). Follow the process above for making a Global property (left-click the TIF script so it turns blue, click Properties, Add Property, GlobalVariable in the scroll-bar, paste or type the name of the global in the Name slot, click OK (if the name already shows in the Pick Object scroll-bar, that is), OK, OK...

15e). Put aaaFiredGlobal.SetValue(1) into the Begin: Papyrus Fragment box. Compile. OK. OK.

15f). Reopen the quest and find the "end of shift" topic/info. Add a fifth condition which is GetGlobalValue Global: 'aaaFiredGlobal' == 1.00. And yes, I know it appears that Fired == 1, yet we're not being fired.

Altogether now we've got...

S GetGlobalVariable Global: 'aaaFiredGlobal == 1.00 AND
S GetGlobalVariable Global: 'aaaDrinksBought' == 1.00 AND
S GetGlobalValue Global: 'GameHour' > 18.00 AND
S GetGlobalValue Global: 'GameHour' < 23.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


15g). Finally, go to the "beginning of shift" dialog started in step 9a. Follow the process above for making a Global property (left-click the TIF script so it turns blue, click Properties, Add Property, GlobalVariable in the scroll-bar, paste or type the aaaFiredGlobal into the Pick Object scroll-bar. Click OK, click ok...

15i). Reopen the Quest window. Put aaaFiredGlobal.SetValue(0) into the Begin: Papyrus Fragment box. Compile. OK. OK.

That's the happy shift ending. Now for the sad one.


16a). Reopen the same quest/branch which was used for "end of shift", right-click into its center, and select New Info. Follow all the usual steps for making new dialog...

Topic Text: "Looks as though my day is done." (THIS won't need to be changed).

Response Text: "I'm afraid it is. Looks like you've bottomed out with sales today.
I'm afraid I'm gonna have to let you go..."

Conditions:
S GetGlobalVariable Global: aaaFiredGlobal == 0.00 AND
S GetGlobalValue Global: 'GameHour' > 18.00 AND
S GetGlobalValue Global: 'GameHour' < 23.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


Flags: Has LIP File, Force Subtitle, Goodbye.

Script: GetOwningQuest().SetStage(99) can go into the Begin or End Papyrus Frag boxes.


17a). Finally, let's take this job and shove it! There are three ways this can be done. Quit dialog can be made to (1) be an option at any time (2) be an option only after the shift is done or (3) be an option while we're working.

Start a new branch, and this should be the very last one.

ID: aaaBarmaidJobQuit

Branch: aaaBarmaidJobQuitBranch

Topic Text: "I'm taking this job and shoving it!"

Response Text: "But...but why? What am I going to do without you?" (I believe there is a Emotion Animation which makes the NPC cry or at least bow down in sadness.)

Flags: Has LIP File, Force Subtitle, Goodbye.

Script: GetOwningQuest().SetStage(100)

17b). Conditions vary. If we want the option to be able to quit at any time, thereby ending the quest entirely, all that are needed is something like...

S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


If we want to quit during work hours...


S GetGlobalValue Global: 'GameHour' > 11.00 AND
S GetGlobalValue Global: 'GameHour' < 18.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


And if we're doing this strictly after hours (effectively getting paid before we quit)...


S GetGlobalValue Global: 'GameHour' > 18.00 AND
S GetGlobalValue Global: 'GameHour' < 23.00 AND
S GetStage Quest: aaaBarmaidJob == 50.00 AND
S GetIsID Actor: 'CorpulusVinius' == 1.00


Thing is, for those who choose the anytime-quit scenario, the boss is always going to have that Topic Text we can click on at all times, which can be rather awkward. I think I prefer the after-hours scenario.


18). Don't forget to update your mod's SEQ file after all dialog is written up, or while it's being written, for those who are in the habit of testing along the way. This is especially true when going into the game, trying to speak to the boss or whomever, and none of our dialog is showing up. Here's how to do it (Click Here), in case a quick reminder is needed.

This post has been edited by Renee: Mar 8 2024, 07:15 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Jan 21 2023, 07:32 PM
Post #88


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



Traveling with an NPC. Game: TES V: Skyrim

Here's my next wacky idea. Usually when we've got a companion, he or she is following us. But for this post the opposite is true. My character's going to be following an NPC.

I've got a high elf Healer who's going to be taking her healing skills on the road, by helping travelers she randomly encounters, but also I've got a more specific idea: helping somebody get to another destination. The specific traveler wants my elf to go with him, healing him up as encounters occur, and wounds are suffered.

The idea here is that a random NPC is going to dwell within Whiterun's Bannered Mare. This NPC wants to go to some other location, and wants my healer to accompany him, keeping him full of health. I want this to seem like a somewhat random endeavor, so that the person who tries to hire my healer will be a bit different every time he respawns. viking.gif

This first travel journey is going to be a test. The NPC will ask my character to walk to Dragonsreach. Once he gets there he'll be satisfied, and dialog will change. He'll give my character some money. In the future, there will be much greater distances being requested: Riverwood, Falkreath, Windhelm, and so on. But let's start off with something basic and easy.


Object window > Character > Class
1a). So, class-wise, which sort of NPC's going to need a healer the most? Warriors, that's who. Warriors, fighters, basically those who've put all their skills into wielding weapons and shields while wearing armor, but have eschewed magical disciplines.

So first thing is to find a Class which already has some of the features I'm wanting. I scrolled the Class window down until I got to CombatWarrior1H. Right-click > Edit this class.

1b) ID is being changed to aaaWarriorClass. I'm clicking OK, choosing "Yes" when it asks if I'd like to make a New Form. Reopen the new class.

Thing is, even though the selections on the Class panel feature 1-handed warriors I'm going to modify this so a 1-handed OR a 2-handed guy can show up.

1c). I'm leaving Full Name as Warrior. The main thing I'm changing are the Skill Weight for Two-Handed, which is being changed from 1 to 3. I also added 2 into the Light Armor slot. Hmm. Nothing else really needs to be changed.

1b). Click OK.


Object window > Character > Faction
2a). Right-click > New. ID = aaaTravellerFaction, Name: Traveller Faction.

2b). Click the General tab. Hidden from PC is toggled on. Right-Click > New into Interfaction Relations and find PlayerFaction in the scroll-bar. Ally can be selected. I'm not choosing Friends and Allies because I don't want the guy to become too helpful to other travelers on the road, who are being attacked.

2c). In the Crime tab we can select any of these toggles (or not), depending if we want somebody who doesn't care what we do at all, to somebody who's a stickler for any sort of criminal activity. emot-ninja1.gif All the toggles are self-explanatory.

2d). Click OK, unless more features are desired (training, merchant ability, etc.)


Object window > Actors > Actor
3a). Click on the Actors > Actor section. Right-click > New. I'm going to make a template, which will make it easier to make NPCs from this template in the future. There's going to be more than one NPC who wants my character's services, and templates make it easier to set up multiple people in the gameworld.

ID: aaaWarriorTemplate

Name: Warrior Template.


3b.) Toggle Respawn on, do NOT toggle Unique.

3c.) Race can be anything human, elf, or beast, but the main thing is we're going to want to choose a Voice Type which works. Any of these below are supposed to work...

MaleEvenTonedAccented
FemaleSultry
MaleDrunk
FemaleDarkElf
MaleDarkEfl
MaleNord
FemaleCommander
MaleBrute
MaleArgonian
MaleKhajiit
FemaleOrc
FemaleCondescending
MaleEvenToned
FemaleEvenToned
MaleYoungEager
FemaleYoungEager

3d). Here is how I've got the rest of the tabs set up... and these can be played with, depending if a wimp is desired, or an Uberboss. Note that I am only messing with the choices which matter. Everything else not mentioned is optional. Keep in mind that what's being made is NOT the actual warrior NPC who wants assistance, it is a template for other warrior NPCs.

Stats tab
Auto Calc Stats can be chosen along with the Level slot if a static NPC is desired. I prefer PC Level Mult, with 2.00 in the Level Mult slot. This way, the traveling NPC is always tougher than my healer.

I also used the Class scroll-bar to find the aaaWarriorClass made a few steps ago.

Factions tab
Right-click > New and find the faction just created. aaaTravellerFaction is what I've got.

AI Data tab
Aggression: Aggressive
Confidence: Brave
Assistance: Helps Allies

AI Packages tab
DefaultSanboxCurrentLocation1024 is a good one to choose, since it'll cause the NPC to do random stuff wherever he winds up, but he won't try to return to Bannered Mare. In other words, don't choose an Editor version of Sandbox.

This Sandbox package will become the "base" AI that the NPC will possess during time off. More packages will get added later which will have the ability to override this sandbox package.

Inventory tab


Um, Actually, I'm going to stop before continuing with the Inventory tab. Stuff will get added here in a moment, but it's not as simple as finding stuff in the main Inventory window. Because the idea is that the NPC who shows up in the game is going to wear totally random stuff, and carry a random weapon.

3d). So click OK, closing the Actor panel.


Object window > Items > LeveledItem
4a). Right-click > New so that the LeveledItem panel pops up. Here's what I got:

ID: aaaWarriorArmorList

Chance None: 0
Calculate from all levels <= PC's level: OFF
Calculate for each item in Count: OFF

4b). Now click on Items > Armor in the left side of the Object window, and drag whatever is desired into the LeveledItem's main window. I dragged ArmorIronCuirass, ArmorLeatherCuirass, and ArmorBandedIronCuirass A mishmash of armor types, basically.

Just for fun, I also dragged ClothesFarm into the window, which is a separate leveled list. 🧺 This way, the NPC can be met while wearing armor, but there's also a chance for ordinary clothes, as well.

We can also right-click > New into the window to find armor that way.

4c). Steps 4a through 4c can be followed to also add Helmet and Boots into separate LeveledItem lists. For Boots I set Chance None at 0 (so the NPC will always have a chance of wearing several boot types) but I made the aaaWarriorHelmetList with a 50% of Chance None. Just for variety.

4d). Click OK.

4e). Follow the same process for weapons: 4a through 4d. Here's what I came up with.

ID: aaaWarriorWeaponList

Chance None: 10

Calculate for each item in Count: OFF

I dragged a bunch of iron into the main window: IronGreatsword, IronMace, and so on. Only one of these will be chosen, since the Calculate toggle is off. There's a chance the NPC won't have a weapon at all when he's met. Note that I've got 1-handed and 2-handed weapons, to mix things up as much as possible.


Object window > Items > Outfit
5a). Right-click > New into the right window. ID = aaaWarriorOutfit in my Creation Kit.

The Outfit section determines what the NPC shall wind up wearing out in the world. We cannot just add clothing or armor items into their main Inventory; they'll wind up not wearing anything if it's done this way.

5b). Drag or right-click > New the Leveled List items into the Outfit window. So I've got aaaWarriorArmorList, aaaWarriorBootsList, and aaaWarriorHelmetList.

5c). Click OK.

5d). Reopen the NPC template (Actor) panel. The Inventory tab should be open, or opened. Use the Default Outfit scroll-bar to find the Outfit just made. So, aaaWarriorOutfit is what's in my CK.

5e). Right-click > New into the Inventory window, and find the weapons list made earlier. Click OK, closing the Actor panel. The NPC can also have gauntlets added directly here, including a LeveledList version of gauntlet choices.

There. The NPCs which get pulled from this template will got random gear, Stats and Level will vary, and he's part of a faction which is completely separate from anything vanilla. We cannot make random faces, but later on it's possible to make several NPCs, who will later become part of a randomized list drawing from the 'Warrior List' made in step 3a, so that a different (and only one) NPC shows up at a time, and with random gear.

5f) Still in the Actor section, right-click into the Object window and select New. I am making aaaWarrior01 for the ID, and Name is simply staying as Warrior. I don't have a problem with generic names, but I know a lot of gamers do. laugh.gif

5g). Change the ActorBase scroll-bar (middle-lower-left side of the Actor panel) from NONE to whatever the name of the template is. So in my game, it'll be aaaWarriorTemplate.

5h). Now toggle the following on: Use Traits, Use Stats, Use Factions, Use AI Data, Use AI Packages, Use Def Pack List, Use Attack Data, Use Inventory, and Use Base Data. Click OK. A script might also get added to the template to make the NPC return or teleport back to his original location, we'll see.


Cell and Render Windows
6a). Find whichever cell is desired and drag the NPC into the Render window. Keep in mind that he might appear without clothes, which is fine. Once we're in the game he'll be wearing something due to the Outfit added to his inventory.

6b). Double left-click NPC in the Render window, and click the Persist Location tab and find whichever cell or worldspace the NPC will dwell in. I've got WhiterunLocation. Click OK.

6c). Give the NPC a Reference ID. I've got aaaWarrior01Ref. Copy/paste that name to the text page.

Save. Now start the game, get your character into whichever cell or worldspace was used to drop the NPC into. Make sure the NPC's wearing clothes or armor, and has a weapon (if a weapon was added into inventory).


Object window > Miscellaneous > Global
7a). Make these Globals:

aaaAccompanyGlobal
aaaRefuseAccompany
aaaTimerGlobal
aaaTravelDragonsreach
aaaWaitHereGlobal

All of these will have Short variables, with Values of 0.

7b). Copy the ID of all five names and paste them onto a Notepad page for later.


Object window > Character > Package
8a). Make a ForceGreet package as per this post. This is an optional step, but it also makes sense that if my character is supposed to be getting known throughout parts of Skyrim as a healer, the warrior is going to interrupt her when he sees her walk into Bannered Mare.

I am calling its aaaWarrior01ForcegreetPackage. I'm just going to leave everything default for now on the Package tab, other than moving the Package Template scroll-bar to ForceGreet.

8b). Flags tab: toggle Must Complete, Hellos to Player, and Preferred Speed on. I've got that final selection placed on Walk.

8c). Conditions tab.

GetGlobalValue Global: aaaAccompanyGlobal == 0.00 AND
GetGlobalValue Global: aaaRefuseAccompany == 0.00
.

Click OK or type into the package's ID slot and press Return or ENTER on the keyboard.

8d). Open up the NPC Template, find the AI Packages tab and right-click > Add the package just made. Make sure this package gets placed over the Sandbox one added earlier. Click OK.

Save.

Now's a good time to start the game, just to see if everything works. The NPC won't have any dialog yet since no quest has been written (other than saying generic lines such as "Need something?" "Yes?"), but the guy should walk up to our character and keep following him or her around Bannered Mare. Keep in mind that if the NPC is sitting when encountered he probably won't forcegreet. A second "forcegreet from sitting" package is needed for that. rolleyes.gif

Here's something neat: by now I've loaded saves into the game three times, starting in the main Whiterun market area, and then walking into Bannered Mare. Each time, the NPC is wearing different gear: sometimes clothes, sometimes armor, and wielding a different weapon.


Object window > Character > Quest
9a). Make a new quest.

ID: aaaDragonsreachTravelQuest
Name: A Journey to Dragonsreach

Type: Side Quests
Priority: 50

Start Game Enabled: toggled on. I toggled Run Once off.

Quest Dialog Conditions: PL GetLevel NONE > 5.00 (Player is selected as the Reference.)

Basically, the quest won't start unless my character's got more than 5 levels of experience. Only makes sense.

9b). Click OK, save, and reopen the quest. Still on the Quest Data page, right-click > New all the globals made during step 7a into the Text Display Globals window on the right. Here they are again.

aaaAccompanyGlobal
aaaRefuseAccompany
aaaTimerGlobal
aaaTravelDragonsreach
aaaWaitHereGlobal

9c). Misc tab. Right-click > New Topic into the middle window and find Hello.

"Oi, you're that healer. Might I have a word with you?" says the Warrior guy.

Conditions:
GetInFaction aaaTravellerFaction == 1.00 AND
GetGlobalValue Global: 'aaaAccompanyGlobal' == 0.00
GetGlobalValue Global: 'aaaRefuseAccompany' == 0.00


Copy All those. Record dialog (or silence) and click OK.

WARNING: Make sure the Say Once flag is not toggled for this, for most of the dialogs in this quest. These topics are going to need to return every so often. If the PC refuses to go with the NPC for instance, but then later changes mind.


9d). Switch to Dialogue Views or Player Dialog tab.

ID: aaaTravellerRequestsCompanyID
Branch: aaaTravellerRequestsCompanyTopic

Topic ID: aaaTravellerForcegreet
Subtype: ForceGreet
Topic Text: Aye, what is it?
Priority: 100

Response: "Can you accompany me to Dragonsreach? I'll pay 5 gold once we get there."

9e). Paste the same conditions from the Hello made earlier but REMOVE aaaRefuseAccompany. Here are the remaining conditions.

GetInFaction aaaTravellerFaction == 1.00 AND
GetGlobalValue Global: 'aaaAccompanyGlobal' == 0.00


Copy All those two.

9f). Change the Hours until reset: slot from 0.00 to 24.00.

The aaaRefuseAccompany was removed because: if the player refuses to go with the warrior this triggers aaaRefuseAccompany on, which kills the warrior's ability to ForceGreet in the future. However, if (after 24+ hours) we change our mind, and want to go with the guy, we can do so, because aaaRefuseAccompany is not a condition for this dialog.

Toggle Force Subtitle on, and record. Click OK. Again, make sure Say Once is NOT toggled on.

9f). Now right-click > Add two more Topics into the same yellow branch. aaaDragonsreachYes and aaaDragonsreachNo. Let's start with the Yes version.

Topic Text: Yes, I shall accompany you...
Response: Let us go.

Conditions: Paste the two conditions from before.

GetInFaction aaaTravellerFaction == 1.00 AND
GetGlobalValue Global: 'aaaAccompanyGlobal' == 0.00


Flags: Has LIP File, Force Subtitle, Goodbye

Scripts: make a semicolon script into either box: Begin or End. ; Player goes with NPC or whatever. Compile and press OK.

9g). Follow step 9f to flesh out some "No" dialog, including a semicolon "No" script. Toggle Goodbye on.

Topic Text: No, I am too busy now.
Response: Drats. Too bad. Coulda made some coin! I'll be here if you change your mind.

Conditions: Paste the two conditions from before.

GetInFaction aaaTravellerFaction == 1.00 AND
GetGlobalValue Global: 'aaaAccompanyGlobal' == 0.00


Flags: Has LIP File, Force Subtitle, Goodbye

Scripts: make a semicolon script into either box: Begin or End. ; Player refuses accompany..

Once that is done, left-click onto the initial topic (the forcegreet) and link from there to the Yes, and from there to the No. Click OK, closing the Quest window. Again, go into the game, just to make sure everything's working so far. Um, make an SEQ file if you haven't for this .esp yet.


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

To make the NPC go to his/her destination I have experimented with Escort and EscortPlayerWhenNear because I wanted the NPC to lead my character, but not get too far ahead. These work initially, and are great if only one cell or worldspace is being traversed. But once the NPC goes through a load door he always disappears. mad.gif

So choose a Travel package in Package Template scroll-bar.

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

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

Flags tab: Must Complete, Preferred Speed: Fast Walk. Everything else off.

Conditions tab: S GetGlobalValue Global: 'aaaTravelDragonsreach' == 1.00
........................ S GetGlobalValue Global: 'aaaWaitGlobal' == 0.00
........................ PL GetDistance <= 1024


NOTE: Even though all the "Fallout" flags are off (Hellos to Player, Random Conversations, etc.) there are still a few things which can make the NPC halt his progress. If the bard starts singing a song, this is one of those things. Do not fret. When the song is over the NPC should continue walking.

Even though Escort is not an option, the GetDistance condition is being used to make this work in a similar way to Escort.


10b). Now to make a package which tells the NPC to wait. But since Escort is not an option, I'm going to need to make sure the NPC is able to stop when my 'toon needs to take a break!

ID: aaaWaitPackage
Package Template: StayAtCurrentLocation

Package tab: not used. StayAtCurrentLocation defaults to a standard Wait package, basically.

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

Conditions tab: S GetGlobalValue Global: 'aaaTravelDragonsreach' == 1.00
........................ S GetGlobalValue Global: 'aaaWaitGlobal == 1.00



Object window > Character > Quest
11a). Go back to the Notepad or text file which has the globals pasted from before. Copy aaaTravelDragonsreach.

11b). Reopen the quest, and go to the Dialog which says "Yes".

11c). Click on the TIF script and press Properties. Press Add Property.

Type: GlobalVariable
Name: Paste the name just copied. Find the global's name in the Edit Value scroll-bar. Click OK.

11d). Now copy aaaAccompanyGlobal from the same page. Make a second property in the same manner as found in step 11c.

Click OK twice more, closing the Quest window, and reopen it. Type

; aaaTravelDragonsreach.SetValue(1)
; aaaAccompanyGlobal.SetValue(1)

into the End Script box. Compile. Remove the semicolons, compile again. Click OK and OK again, closing the Quest window.

11e). Make a third property.

Type: Actor
Property Name: aaaWarrior01 (the base ID gets used for the Property name, not the Ref ID)

Edit Value: Find the NPC's Reference ID in the Render window or using the Cell + Reference scroll-bars.

Script fragment: aaaWarrior01.SetPlayerTeammate()

SetPlayerTeammate causes the NPC to mirror whatever our character's doing. IF our character sneaks, the NPC will do so as well. If he/she draws a weapon, so will the NPC. Really the main reason SPT is needed is so we can get into their inventory as we're travelling.

Click OK.

11f). Reopen the Quest window and find the "No" dialog

Follow steps 11a through 11c, except copy aaaRefuseAccompany from the Notepad or text page.

Script fragment: aaaRefuseAccompany.SetValue(1)


Object window > Actors > Actor
12a). Open the NPC template and go to the AI Packages tab. Right-click > Add the travel package just written. It shouldn't matter if it sits above the ForceGreet from before, but make sure the DefaultSandbox stays at the very bottom.

12b). Also add the Wait package as well. Doesn't matter if it's above or below the Travel package. Overall the NPC now has four AIs:

aaaForceGreetPackage
aaaTravelDragonsreachPackage
aaaWaitPackage
DefaultSandboxCurrentLocation1024


Object window > Character > Quest
13a). Reopen the 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. Each of these is getting their own Branch and Topics.

13b). Here's what works for waiting.

ID: aaaDragonsreachTravelQuestWaitID
Branch: aaaDragonsreachTravelQuestWaitIDBranchTopic
Topic: aaaDragonsreachTravelQuestWaitIDTopic

Topic Text: Let's take a rest for just a moment.

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

Hours until reset: 0.00
Flags: Has LIP File, Force Subtitle, Goodbye

Conditions:

S GetGlobalValue Global: 'aaaWaitHereGlobal == 0.00 AND
S GetGlobalValue Global: 'aaaTravelDragonsreach == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


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


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

ID: aaaDragonsreachTravelQuestContinueID
Branch: aaaDragonsreachTravelQuestIDBranchTopic
Topic: aaaDragonsreachTravelQuestContinueIDTopic

Topic Text: Let's go.

Response Text: Fine. Let us commence.

Hours until reset: 0.00
Flags: Has LIP File, Force Subtitle, Goodbye

Conditions:

S GetGlobalValue Global: 'aaaWaitHereGlobal == 1.00 AND
S GetGlobalValue Global: 'aaaTravelDragonsreach == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


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


13d). Here's what works if we wish to open the NPC's inventory.

ID: aaaDragonsreachTravelQuestOpenInventoryID
Branch: aaaDragonsreachTravelQuestOpenInventoryBranchTopic
Topic: aaaDragonsreachTravelQuestOpenInventoryTopic

opic TexTt: Can we exchange items?

Response Text: Here's what I got.

Flags: Has LIP File, Force Subtitle.

Conditions:

S GetGlobalValue Global: 'aaaTravelDragonsreach == 1.00 AND
S GetInFaction Faction: 'aaaTravellerFaction' == 1.00


Script Begin Box: ;Opens NPC traveller inventory

Script End Box: NPCPropertyName.OpenInventory()



13e).
Here's the dialog for when the NPC makes it to destination.

ID: aaaWarriorArriveDragonsreachID
Branch: aaaWarriorArriveDragonsReachBranch

Topic Text: Looks like we're here.

Response Text
: Yes. And looks like I owe some coin.

Flags: Has LIP File, Force Subtitle, Goodbye

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


Script Begin Box: ;Warrior makes it to Dragonsreach

Script End Box: aaaTravelDragonsreach.SetValue(2)
........................ aaaTimerGlobal.SetValue(1)
........................Game.GetPlayer().AddItem(Gold001, 5)
........................NPC.SetPlayerTeamMate(FALSE)



There we go. In the post below this one, I'm going to describe how to add some other locations to the quest, but also make it so that the Warrior (or any others in the Traveller Faction) can direct us to several, random locations.


TROUBLESHOOTING: As anyone who's had a follower knows, sometimes they like to disappear. Especially after they've gone through a door which leads from a cell into a worldspace. Here's a couple ways to avoid this.

1). Firstly, save often! Especially before the door or gate.

2). Whenever approaching a door or a gate which leads from an interior cell to an outdoor worldspace, our character should activate this door first. And sometimes, when going from an outdoor space to an interior cell the opposite is true. Let them enter the door first. I have found these actions cut down the disappearing act 100% so far.

3). The console command moveto <actor ID> can also be tried.

This post has been edited by Renee: Jan 19 2024, 03:39 AM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Feb 10 2023, 03:07 PM
Post #89


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:[/i] We've made it to Riverwood. Alive.
[u]
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.


9a). Return to the initial branch & topic which started this entire quest in step 3c. This is aaaPlayerReturnsBranchTopic for me.

9b). Right-click > Edit Topic the top (yellow) portion of the topic, so the Topic panel shows up. There should already be a Dragonsreach info here.

9c). Right-click > New into the window. The info/response being written is going to share this same topic. So "I have returned" should be the Topic Text from before.

Response: Good. Think I'm done here in Riverwood. Wish to head somewhere else?
Prompt: Are you done here in Riverwood?

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

Conditions
:
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

Make sure the "GetInCell" references the Player.

9d). Use the Link To: window to link to the Locational topic. And also the "No" topic.

Now... the Locational topic currently has one or two random choices: Riverwood and maybe Nightgate Inn, I'm forgetting if I added Nightgate already. As before it'd be silly to have the guy say "Take me to Riverwood" if this was just done, so.....

9e). Add a PL GetInCell Cell: 'RiverwoodSleepingGiantInn' != 1.00

Hmm, I think I added that before. Anyway,

9f). Repeat the step above for Nightgate Inn, or any other locations.

Click OK 2x and save.

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: Yesterday, 10:06 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Feb 13 2023, 01:58 AM
Post #90


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



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

This lesson goes with the two posts above. I have found that traveling with a second NPC (both of them warrior-types) is also possible. However, it is best if one of these people is regarded as the 'primary', any additional people are more secondary. Best to organize it this way, as we'll see.

I'm not sure if there's a limit to building a party this way. The more people we add, the more management they'll need: keeping them from straying too far ahead or behind, occasional disappearing acts, and so on.

Disappearing acts? Sounds aggravating! Why bother, Renee?

Hey, I find this method of gaming to be really fun, most of the time. Something different from the norm. I enjoy the idea that my character has a boss who she travels along with, not the other way around. tongue.gif NPCs also have different directions of travel, oftentimes they lead me into parts of the gameworld I never seen before.

Object Window > Actors > Actor
1a). Make a second NPC. This time I made a woman warrior, so now my elf has a man and a woman to travel with.

ID: aaaWarrior02
Name: Myrmidon

Toggle ON: Respawn.

1b). Click OK and reopen. Find aaaWarriorTemplate in the ActorBase scroll-bar. Here's what I got toggled on:

Use Stats
Use Factions
Use AI Data
Use Def Pack List
Use Attack Data
Use Inventory

"Use Traits", "Use AI Data", and "Use Base Data" were all toggled on for the first NPC, but for reasons I'll explain they don't need to be on for the second one.

1c).
Traits tab: For instance, I've got Traits untoggled because the template only includes a Male Imperial. Otherwise, the most important choice is Voice Type. Again here's the list supported by the vanilla game.

MaleEvenTonedAccented
FemaleSultry
MaleDrunk
FemaleDarkElf
MaleDarkElf
MaleNord
FemaleCommander
MaleBrute
MaleArgonian
MaleKhajiit
FemaleOrc
FemaleCondescending
MaleEvenToned
FemaleEvenToned
MaleYoungEager
FemaleYoungEager

1d). First open tab not covered by the template is the AI Packages tab. It's because I made a ForceGreet for the second warrior so she too can approach my healer and say "Looks like you've got an adventuring party, may I join?" - I also made a second AI which the first one doesn't have. We'll get to that in a few. Otherwise, she's got all the same AI as the first NPC.

And since she's also got the same Outfit, she'll also show up wearing random armor when first encountered.

1e). Click OK and save. Reopen.

1f). Press the Add button and add the Death script used for the first NPC. Press OK again.

However, since there are two NPCs traveling together I'm gonna need to change a few things. If the original guy got pwned, a timer would begin which would eventually 'clean up' the body from wherever he fell, and he'd respawn back in Bannered Mare. All the globals got cleared to zero. However this won't work if there's two people. If one of them dies and the script remains the same, we can't be traveling along with the second NPC and then all the sudden *poof*, he or she gets teleported into Whiterun! biggrin.gif

1g). Find a cell to drop the second traveler into, give him or her a Reference ID. Click the Persist Location tab and use the scroll-bar to find the cell he/she's in.

Go into the Object Window > WorldObjects > Static and drop an XMarkerHeading into the same cell. Reference that. I'm calling it aaaWarrior02XMarkerHeading.


Object Window > Character > Quest
2a). Open the Death Timer quest and click on the Scripts tab.

2b). New properties will be needed for the second NPC (Type: Actor), the reference to that actor (Type: ObjectReference), and the second XMarkerHeading (ObjectReference) which sends the NPC into some other cell. So... my first NPC gets teleported back to Bannered Mare while the second would get sent back to where we picked her up: Nightgate Inn. 🦉

2c). Click OK and reopen the death timer quest. Right-click > Edit Source. Note that I'm keeping the entire script intact, but making some changes, going mad with semicolons so those additional globals don't read.

Scriptname aaaDeathTimerScript extends Quest

Actor Property aaaWarrior01 Auto
Actor Property aaaWarrior02 Auto

Float Property DelayHours Auto

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

ObjectReference Property aaaWarrior01Ref Auto
ObjectReference Property aaaWarrior02Ref Auto
ObjectReference Property aaaWarrior01XMarkerHeading Auto
ObjectReference Property aaaWarrior02XMarkerHeading Auto

Function Oninit()
self.RegisterForSingleUpdateGameTime(DelayHours)

EndFunction

Function OnSingleUpdateGameTime()

If aaaDeathGlobal.GetValue() == 1
If aaaWarrior01.IsDead() == 1 && aaaWarrior02.IsDead() != 1
;aaaAccompanyGlobal.SetValue(0)
aaaDeathGlobal.SetValue(0) ; Leave this without a semicolon
;aaaTravelNightgateInn.SetValue(0)
;aaaTravelRiverwood.SetValue(0)
;aaaWaitGlobal.SetValue(0)

aaaWarrior01Ref.MoveTo(aaaWarrior01XMarkerHeading)

UnregisterForUpdateGameTime()

EndIf
EndIf

If aaaDeathGlobal.GetValue() == 1
If aaaWarrior02.IsDead() == 1 && aaaWarrior01.IsDead() != 1
;aaaAccompanyGlobal.SetValue(0)
aaaDeathGlobal.SetValue(0)
;aaaTravelNightgateInn.SetValue(0)
;aaaTravelRiverwood.SetValue(0)
;aaaWaitGlobal.SetValue(0)

aaaWarrior02Ref.MoveTo(aaaWarrior02XMarkerHeading)

UnregisterForUpdateGameTime()

EndIf
EndIf

EndFunction


See that? Most of those globals will no longer trigger if the timer counts down, IF one of the travellers dies; only the DeathGlobal remains. Now... If BOTH of them get killed the script is going to need to reflect this as well. Add a third block (as seen below) below the two blocks from above.


aaaDeathGlobal.GetValue() == 1
If aaaWarrior01.IsDead() == 1 && aaaWarrior02.IsDead() == 1
aaaAccompanyGlobal.SetValue(0)
aaaDeathGlobal.SetValue(0)
aaaTravelNightgateInn.SetValue(0)
aaaTravelRiverwood.SetValue(0)
aaaWaitGlobal.SetValue(0)

aaaWarrior01Ref.MoveTo(aaaWarrior01XMarkerHeading)
aaaWarrior02Ref.MoveTo(aaaWarrior02XMarkerHeading)

UnregisterForUpdateGameTime()

EndIf
EndIf

EndFunction


In this scenario both NPCs get killed during the same battle, or during a battle which occurs before the 240-hour (10 day) timer counts down, both of them will be teleported to wherever. In this case, all the globals are getting zeed-out to zero, so the entire quest can start anew. At this writing this portion of the script is untested, since I've PC Level Mult'd both travelers multiple levels above my healer's Level. viking.gif

2d). OPTIONAL: Make a message as per this post's instructions which indicates when the timer's done counting. I only made a message for the final block, during which both NPCs were pwned, to indicate when both have respawned.


Object Window > Character > Quest
3a). Open the quest which handles dialog for traveling, written up during the "Additional Locations" lesson up above. For me this is aaaRandomTravelQuest.

The aim now is to go through all the dialog which is going to need to reference the second NPC.

First, there's the branch and topics which deal with locational stuff. We speak to the NPC (either one, since both of them are in the TravellerFaction) and during this phase he or she explains where they'd like to go next.

> To start, there's the initial topic which occurs after the timer script counts down. We return to the NPC after x amount of hours, who welcomes us back, and says he/she is "ready to go somewhere else". Nothing additional is needed here.

>> Next topic is the Locational one. Riverwood, Nightgate Inn, or wherever else. In my game, I've added Windhelm's Candlehearth Hall and Ivarstead's Vilemyr Inn by now. Anyway, nothing additional is needed here. It's the NEXT topic (the one where they choose where to go next) where some changes occur. There should already be a slew of script fragments and properties associated with these Infos. 💽

3b). Make a property for the second warrior, with the Type being Actor. So for me this is aaaWarrior02. Click OK (closing the Topic Info panel) and reopen. This'll need to get done for any topic where an NPC states which location they'd like to go next.

3c). Here are the relevant scripts which get added.

Begin
aaaWarrior02.SetPlayerTeamMate()

End
aaaWarrior02.EvaluatePackage()


...That's how I've got them set up, anyway. All the TeamMate stuff is in the Begin box, all the globals and package evaluations in the End box.

3d). Repeat 3b and 3c for any "Yes" locational topics.

>>> The Wait topic, Follow topic, Open Inventory, and Continue topics can get skipped for now. Globals handle everything, and since both NPCs have the same Faction, and the same directional AI, they'll already do all these things when we tell 'em to. We'll add to these topic/infos later.

3e). Open the "Arrive" topic. This occurs once the NPCs reach their destination. Make a property for the second warrior with the Type being Actor. So for me (again) this is aaaWarrior02. Click OK (closing the Topic Info panel) and reopen.


3f). Here is the relevant script which gets added.

Begin
aaaWarrior02.SetPlayerTeamMate(FALSE)



Wow, am I done typing? Looks to be so. smile.gif Whoops no I'm not.

So the original Ai added to the original NPC includes several travel packages such as aaaTravelNightgatePackage and aaaTravelRiverwoodPackage. Both of these are set so that the Player needs to be within 512 units (about 24 feet, or 7 meters) to the original NPC for him to keep moving. If we're too far away from him, he'll stop moving until we get closer. I set it up this way because my character is a healer. She's always close enough to him so she can conveniently heal the guy at a moment's notice, and I loathe the idea of losing him if he gets too far away.

The decision needs to get made, though. Should I also reference the second person with a GetDistance? This is possible. However, problem is if BOTH NPCs are being referenced, this means my healer will need to be near both of them at all times. If one of them strays too far ahead or behind, the entire party comes to a halt.

One solution is to add a second GetDistance with an OR qualifier to each of the travel AIs.

PL GetDistance Reference: 'aaaWarrior01Ref' <= 512.00 OR
PL GetDistance Reference: 'aaaWarrior02Ref' <= 512.00 AND


The advantage here is if the primary NPC gets pwned, the secondary NPC can be traveled near as well. Again though, there's a problem. While traveling with this party I began to notice one of the NPCs still has the possibility of straying too far ahead or behind.

Let's step that dilemma aside for a moment, while another gets fixed. The next task is AI. By now, the NPC Template and the second NPC will both have quite a stack of AI in their AI Packages window, and this is okay if all you're doing is adding two locations. But as I write this (3/2/2024) I'm up to 8. I've also added some individual AI for the extra follower I'm adding now, and a third follower as well, who's got his own Forcegreet. That stack of AI keeps growing and growing. Here is a way to tidy it up.


Object Window > Miscellaneous > FormList
4a). Right-click > New and start a new formlist. I'm calling it aaaWarriorPackageList. This list is going to include ALL the AI Packages. Don't click OK yet.

4b). Drag any AI packages written so far from the Object window into the FormList window; I believe this includes the following: aaaTravelDragonreachPackage, aaaNightgateInnPackage, aaaTravelRiverwoodPackage, aaaWaitPackage, and aaaFollowPackage. Also drag the DefaultSandboxCurrentLocation1024, and the Forcegreet added to the second traveller (if one was added to her or him).

4c). Arrange these AI just as they'd be arranged in the AI Packages window, making sure the DefaultSandbox goes at the very bottom.

4d). If a Forcegreet was added to the second NPC, go back to that package and add a GetIsID condition to that package, with the NPC's name (not the template) as the ID.

4e). Return to the NPC template > AI Packages window. Now remove all AI from this window. Use the Default Package List scroll-bar to add AI instead. Click OK.

4f). Return to the secondary NPC. And NOW we can toggle Use AI Packages on for him or her as well. This will automatically erase any AI in their window.


And now, to solve the dilemma described above in step 3f. If the secondary follower keeps straying back and forth, here's how to fix that.

Object Window > Character > Package
5a). Right-click > New

ID: aaaAlternateFollowerPackage

5b). Click on the Package tab. Change Package Template to Follow

Target to Follow: SingleRef 'PlayerRef' Y
Min Radius: Float 256.000
Max Radius: Float 2048.000

Flags tab
Preferred Speed: Jog (or Run.. whatever). All other flags optional.

Conditions tab
S GetIsID Actor: aaaWarrior02 == 1.00 AND
R GetDead, Run on: aaaWarrior01Ref != 1.00 AND
S GetGlobalValue Global: 'aaaAccompanyGlobal' == 1.00 AND
S GetGlobalValue Global: 'aaaWaitGlobal' != 1.00 AND
R (aaaWarrior01Ref) GetDistance aaaWarrior02Ref => 2048


The advantage of having Preferred Speed on Jog or Run is secondary followers will move a bit faster, making shuffling sounds with their feet, as they follow us. This way, we avoid having to constantly look back to make sure they're still behind.

5c). Click OK (if you can see it) or highlight the cursor into the ID slot and press RETURN or ENTER on the keyboard.

Make sure to add this AI into the FormList added to the NPC Template. The GetIsID will make sure the original traveller will NOT use this AI.

And there we go. If the secondary NPC falls too far behind the primary NPC, this causes her to start following the Player instead. Catch is, The first warrior/traveller must be alive for this to happen.

That package alone works most of the time, but I also back it up with properties and a script, as follows.

5d). With the secondary NPC's Actor panel still open, start a new script. Make properties for the new package (aaaAlternateFollowerPackage), the Actor him or herself (aaaWarrior2Ref), and at least one of the GlobalVariables (aaaAccompanyGlobal).


Scriptname aaaAlternateFollowerScript extends ObjectReference

Actor Property aaaWarrior02Ref Auto
GlobalVariable Property aaaAccompanyGlobal Auto
Package Property aaaAlternateFollowerPackage Auto

Event OnPackageStart(Package akaaaAlternateFollowerPackage)
If aaaAccompanyGlobal.GetValue() == 1
aaaWarrior02Ref.EvaluatePackage()
Debug.Trace("New package starts running")


EndIf
EndEvent


I also added a message in the If/EndIf block so that I know when the package kicks in, but messages are optional.

6). Final step (this time I mean it). Reopen the quest. Go into the "Open Inventory" topic and make an Actor property for the second NPC.

aaaWarrior02.OpenInventory() goes into either box if stuff is to be shared between both NPCs. akSpeaker.OpenInventory() can also be used if only that NPC is to be traded with. The advantage of this second script is properties aren't needed.

Okay NOW we're done.

🍷🍷

This post has been edited by Renee: Mar 2 2024, 11:03 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Mar 3 2023, 03:58 AM
Post #91


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



Dialog Speech Checks Game: TES V: Skyrim

This tutorial comes from this Creation Kit page, main difference is I'm going to make this step by step, and add a couple things as well.

There are several ways Speech works in Skyrim. First, we'll discuss Persuasion. An example is from the WERJ02 quest (Thieves Guild Holdup), which has a thief walking up to us as we travel roads, and demanding money. There is a chance to Persuade the thief to leave us alone, as well as chances for Intimidation, walking away, or simply getting into a brawl. I will also include Bribery. We can't bribe the thief, but there are times when bribes can be offered. An example is when we approach the gates of Whiterun for the very first time, and a guard tells us we cannot go into town. viking.gif

PERSUASION


Object window > Character > Quests
1a). Use the Dialogue Views or Player Dialogue systems to start some dialog. ID can be whatever's unique, it's the Topic Text that's going to be important, since there needs to be something which makes it obvious which topic to click on for persuasion. Here is an example.

Do I look like I am rich? (Persuade)

1b). Two infos are needed under this topic, okay? First info, the NPC is persuaded by our character's loquacious Speechcraft abilities. Second info, they ... aren't.
Speech works: You win. I'll leave you be.. for now.

Speech doesn't work: Prepare for your room... erm... doom!!!

Make sure the Prompt slot is not used; both infos should share the same Topic Text.

1c). Goodbye is toggled on for both infos. Basically, the NPC will leave our toon alone if he or she is persuaded, or try to fight if not, with no further dialog.

1d). Use whatever conditions are appropriate, but make sure GetActorValue Speechcraft is used for the successful Info. Here is the entire condition.

PL GetActorValue Speechcraft >= X

The Player is used as a reference in the Run On scroll-bar. And where the X is there are two options. A physical number can be used to define how difficult the condition should be, but what's even easier to use are globals.

1e) Toggle Use Global on and find the Speech section in the Value scroll-bar. So if we want a really easy persuasion attempt, go for PL GetActorValue Speechcraft >= SpeechVeryEasy

1f). Type a semicolon script ;Persuasion succeeds into the Begin: Papyrus Script box. Compile that. Click OK 2x and reopen.

Again, this condition is not needed for the "fail" dialog.

2a). Add a property to the script.

Name: pFavorDialogueScript
Type: FavorDialogueScript (don't try looking for it in the scroll-bar, just type it in).

2b). Click Edit Value. There's only one value to pick which is DialogueFavorGeneric. Click OK 3x and reopen the Quest and Topic Info panels.

2c). Type pFavorDialogueScript.Persuade(akSpeaker) into the Begin: Papyrus box. Compile that.


Now let's move on to the negative response... make sure the NPC is in the Render Window, and has been given a Reference ID. Keep in mind that this will only work for a specific NPC. Beth's random road thieves use a much more complicated system of dialogs and aliases, since they needed to write their quest dialog for a radiant-type thief who is not specific.

3a). Response Text: "You can't fool me!"

Flags: Goodbye

Papyrus script: ;Persuasion attempt fails

3b). Two properties are needed for this script: one for the Player, and one for the NPC who attacks us. I start with the NPC.

Property Name: aaaNPCName (this can be the NPC's actual base ID name.)

Type: Actor

Edit Value: Find the NPC in the Cell and Reference scroll-bars, or simply double left-click on the NPC in the Render window.

3c).
Property Name: Player (or PlayerRef).

Type: Actor

Edit Value: Choose (any) for the Cell scroll-bar and PlayerRef for the reference.

3d). The Papyrus fragment is aaaNPCName.StartCombat(Game.GetPlayer())

Note that StartCombat can also be used if our character wishes to just skip the speech stuff, and choose to fight. "I'd rather die!" is Beth's topic text for this when dealing with road thieves.


INTIMIDATION


4a). Everything is the same so far as setting up dialog: two infos are used (one positive, one negative). But make sure to put (Intimidate) at the end of the Topic Text slot.

4b). For conditions, GetIntimidateSuccess == 1.00 is used for the positive response, and this can simply be kept on Subject for the Reference.

In Bethesda's words, "[when] successful according to the algorithm used by the game engine to calculate this, which takes into account variables such as the player's level and the speaker's [NPC's] confidence value, as well as the player's speechcraft skill and some other factors", that's when this condition becomes chosen.

4c). For the Papyrus script, make a script and property as per steps 1f through 2c up above, but the script used is pFavorDialogueScript.Intimidate(akSpeaker), which goes into the Begin box.

4d). Continue through steps 3a through 3d for the failed Intimidation attempt. ph34r.gif


BRIBERY


5a). In this situation we attempt to pay those whom we're trying to influence. (<BribeCost> gold) goes at the end of the Topic Text. "Here, take my gold!" (<BribeCost> gold). "X" is a specific amount of coin, which automatically gets filled in by the game engine.

5b). This time, GetBribeSuccess == 1.00 is the needed condition.

5c). Follow steps 1f through 2c, with pFavorDialogueScript.Bribe(akSpeaker) going into the Begin script box.

For 5a, a specific amount of gold is not needed, as the favor dialogue script will calculate a levelled amount and handle its removal from the player's inventory. If a specific bribe amount is desired, its best to do this other ways without favor dialogue. GetItemCount works.

This post has been edited by Renee: Apr 6 2023, 07:34 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Mar 19 2023, 05:52 PM
Post #92


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



Map Marker Tutorial, Game: Fallout 3

Firstly, with some vanilla locations added by Bethesda themselves, these can sometimes be hard to find in the Render window. An example: Nuka Cola Plant. I needed to add the reference ID for its map marker into a script, yet where is the map marker?

Beth likes to sometimes put map markers UNDERNEATH the location, the building, the settlement we're trying to use. I found Nuka Cola's map marker by tapping on the entire Nuka Cola building, and then rotating the entire image until I was viewing under this building. Voila. There's the map marker, and now I can retrieve its Ref ID: NukaColaMapMarker.

The rest of this lesson shall focus on adding making map markers into the game.


1). Find the worldspace location in the Cell or Render windows.

2). In the Object window > World Objects > Static, find MapMarker, and drag it into the Render window.

Note that the marker itself is green, but it has a large yellow circle surrounding it. Walking into this circle is what causes the marker to appear on the map if we discover a new location.

3). Double left-click on the marker and give it a Reference ID. This is optional, and only needed if the marker's going to be used in scripts, like to make it appear in the map and stuff if somebody says "Let me mark that location on your map." 🌎

4). Click on the Marker Data tab. Toggle Marker Data on, and notice there's now a bunch of other toggles to press.

5). Give the marker a name, type this into the Name slot. This name is what will appear when somebody views the map's marker in-game. Very good.

6). Click on whatever sort of area the marker's going to portray, whether it's a factory or a settlement, or a cave, etc. This changes the marker's actual icon, making it easy to distinguish as what type of location is viewed on the map.

7). There are three other toggles underneath the icon panel:

Visible: The marker starts off visible right from the start of the game, even before the area's discovered or referenced in a script.

Can Travel To: If this toggle is ON it means we can immediately fast-travel there, as long as the icon appears on the map and we're in the world somewhere (not in an interior cell). Visible also needs to be toggled on for this to be an immediate option from the start of the game.

"Show All" Hidden: If this is toggled, the map marker will NOT appear if the ShowAllMapMarkers function is called for.


Normally, none of those three are toggled. So unless the location is supposed to be known to the player right away for some reason (and can also FT there) click OK.

8). Let's say the marker is going to be referenced during dialog, the classic "Let me mark that location on your map". The script necessary is ShowMap MapMarkerReferenceName

... to make it so the place can be fast-traveled to immediately, make that ShowMap MapMarkerReferenceName, 1

9). Final step. When we fast-travel to the location the map marker is not what's actually used to travel to. For this to happen, an XMarkerHeading needs to be placed somewhere. Usually right in front of the place's front door. So drag 'n' drop an XMarkerHeading into the world. Sometimes it helps to give it a Reference ID too.

10). Double left-click on the MapMarker and when the Reference panel pops up, select the Linked Ref tab. Find the XMHeading in the Reference scroll-bar. A green line should connect both markers once OK is clicked.

This post has been edited by Renee: Mar 21 2023, 04:02 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Mar 26 2023, 07:31 PM
Post #93


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



Repeatable Enemy Raids, Game: Fallout 3

I love generic, repeatable quests. We speak to a quest agent who gives us a quest to pwn some enemy boss, we pwn the boss, then return to the agent to get paid. I've made these sort of quests for Oblivion and Skyrim, here's how to do it for Fallout 3.

The process has a lot of similarities to the way it all works in Oblivion, since both games use the Gamebyro engine and similar scripting. But there are enough differences for Fallout that this game deserves its own methods.

First of all, highly recommended to download Encounter Zone Respawn Control, which makes interior locations (Super Duper Mart, for instance) respawn with enemies, but also loot. This mod requires Fallout Script Extender, for those who don't have it yet.

Once both of those are in place, the way it works: whenever an interior location is entered, go into the character's ITEMS > Aid menus and select Zone Control. There are options to do Nothing, Enable Respawn, and Disable Respawn. If respawn is enabled, the enemies inside will (guess) return the place after 3 days. Most containers will also be restocked with loot. Note that this mod works mostly with vanilla locations. Mod-added locations sometimes can have respawn enabled, sometimes not.

I have also come across one vanilla location (Bethesda Offices East) which did not accept the Enable Respawn command. However, Beth's offices are also supposed to be one of the rare interior locations in the gameworld which respawn by default. EDIT: And now I know why the office could not be Enabled. It's because it's not on Bethesda's "non-respawn" list. To further learn more about this list, click the spoiler tag.



So...the way my idea works is: I use Metro tickets to remind me of which location is currently on the roster; i.e., which location we're supposed to be headed to, to take care of its boss. Metro tickets, Messages, and Quest Objectives are how these reminders work. No quest stages. Repeatable quest stages can probably also be used, but I don't know how to do it that way.

Let's say the first location is a place we're all familiar with: Springvale School. I'm going to put the enemy boss into SpringvaleSchool02 (Springvale School Lower Level).

OBJECT window > Items > Misc Item
1a). Find and then edit MetroTicket.

ID: aaaSpringvaleSchoolTicket
Name: Kill Boss of Springvale School

See? The ticket states exactly what the latest mission is.

1b). Toggle Quest Item on. Don't worry, the way this works, the ticket won't be in the PC's inventory forever.

It is possible to skip this step, of course. Especially for those who want to do the "pack rat" thing; acquire a stack of tickets to be kept in their home. Personally, I can't do it this way. I'd get confused after forgetting to drop my ticket(s). Wait, is my guy on a mission? unsure.gif Which one?

1c). Copy the ID name and paste it onto a Text file or Wordpad file.

1d). Click OK, saving as a New Form.


Object window > Actors > NPC
2a). Make a new NPC, who's going to be the quest agent. If it's your first time doing so, Bethesda's own GECK page is a good place to start: LINK.

The guy or gal can be pretty minimal; like my other Quest Agents in other games, he/she only needs to handle and deliver a minimal number of lines. In my game, I made the agent a Regulator, who is part of the Regulator Faction (along with a couple Megaton factions). He lives in his own flat in Megaton, has his own little life and so on. But minimally, it's possible just to add somebody who lives in Moriarty's, if simplicity is desired.

2b). The only things I insisted upon was to make my agent's Alignment as Good (he is a Regulator, which means good guy). I gave him one of the DefaultSandboxEditorLocation packages too, just so he wanders around and stuff. Everything's an option.

2c). Put the agent into whichever location is desired.


Cell View window
3). Find the location where the enemy boss will get added. Again, for me this is SpringvaleSchool02, which is the school's basement. I like putting bosses into areas which can possibly be the very last place we search. Don't put a boss near the entry door, for instance. More fun to have to get through the boss's minions and sanctuary first!


Object window > Actor Data > Quest
4a). Start a new quest. This tutorial's assuming those who read this know a lot about the Quest window already.

Quest Name: Generic Wasteland Quests
ID: aaaGenericWastelandQuests

Priority: 30

4b).Start Game Enabled and Script Processing Delay can both be toggled.

4c). Start a script like so...

Scriptname aaaGenericWastelandQuestScript

short DoOnce



4d). Make sure the Script Type scroll-bar is set to Quest, not Object.

Save and close the script, click OK (closing the Quest window) and reopen it. Find the script in the scroll-bar, click OK again.


Object window > Actors > NPC
5a). Make a new NPC.

ID: aaaSpringvaleSchoolBoss

Name: Springvale Headmaster (I like silly names)

Respawn: ON


5b). Click OK, closing the NPC panel. Save and reopen the NPC.

This next part is an optional step for those who want to skip a lot of the little stuff: adding gear, factions, and so on. These can be done with a quick set of toggles by using a pre-made template. Since Springvale is populated by bandits, it's easy to use a raider template to set the NPC up, with random gear and so on. Those who want to hand-craft their enemy a bit more can skip to step 6a.

5c). Use the ActorBase scroll-bar to select whichever template is most appropriate.

I started to use Raider2GunAAFTEMPLATE but this bothered me, because choosing its Use Traits flag always defaulted to African American Female. And I'm wanting a guy to rule this former school. So, time to make my own template. Again, those who just want to use one of Bethesda's default templates (or make a completely hand-made boss) can skip to 6a.

5d). Still in the NPC section, type Template into the Filter slot. I am editing Raider2GunAAFTEMPLATE, making only the changes stated below.

ID: aaaRaider2GunCAMTEMPLATE

Flags: No low level processing and Respawn both toggled ON.

TRAITS tab
Race: CaucasianRaider
Female: OFF
Voice Type: MaleAdult02*

STATS tab
PC Level Mult: ON
Level Mult: 4.00

FACTIONS tab
I removed the GeneralIdleFaction and MS13CanMez factions. Not needed. Two raider factions remained in this tab's window, and I also left this template's Smoker Faction.


Note that making the NPC's level go 4 levels above the player in the Stats area makes the boss into a bullet sponge. Hey, I like 'em tough. 🤬 Those who don't prefer this can substitute whatever, maybe put the boss into power armor to toughen him/her up and use Auto Calc Stats instead of PC Level Mult, and so on.

* I used MaleAdult02 as the voice type instead of MaleRaiderGroup because I wanted the guy to be distinct from all the usual raiders, with their toughguy Jersey accents.

Click OK.


6a). Reopen the NPC boss started in step 4a, or continued from the last step. Those who wanted to use the template just made can find it in the ActorBase scroll-bar, selecting whichever toggles fit best. Those who don't can continue to hand-craft, skipping to 6b.

I am choosing: Use Traits, Use Stats, Use AI Data, Use AI Packages, Use Factions, and Use Inventory. Therefore, I've always got a random white guy running the school, who's always 4 levels above the PC, is part of all the Raider factions (and smokes), is always mean, sandboxes, and has random raider-type inventory.

Note I did not use Add Script. It's best to give the NPC boss his/her own script. Stuff like this works best when it's kept local (rather than drawn from a template).

--Also, do not choose Use Base Data, as this can also mess up the script stuff. I also like giving each boss a unique name (like Nuka Cola Plant Bottler) while sometimes using templates. By default, the template I made earlier has "Raider" for a name.

6b). Drop the boss into the Render window. If Use Inventory was one of the flags toggled on, the boss will be in underclothes, which is fine. They get suited up once we're in the game.

6c). Give the boss a Reference ID. Copy this ID and paste it somewhere. I just typed aaaSpringvaleSchoolBossRef.

6d).Make sure to toggle Persistent Reference on. Click OK.

6e). Reopen the NPC's Reference and NPC panels from the Render window. Start a script like so...

Scriptname aaaSpringvaleSchoolBossScript

Short Dead


6f). Save that script, close the editor, click OK 2x (closing the NPC panels) and reopen them. Find the script in the Script scroll-bar, click OK, and reopen.

Here is the rest of the script, and note that it's exactly the same as what'd be found in an Oblivion script.


Scriptname aaaSpringvaleSchoolBossScript

Short Dead

Begin OnDeath

If (aaaSpringvaleSchoolBoss.dead == 1)
Set aaaSpringvaleSchoolBossRef.dead to 2
Set aaaGenericWastelandQuests.DoOnce to 2

EndIf

End



7a). Reopen the quest, and select the Quest Objectives tab. Right-click > New into the top(Objective Index) window. Two objectives are needed for now.

Index: 1
Display Text: Pwn the boss of Springvale Elementary.

Index: 2
Display Text: Return to Quest Agent for Reward.


7b). Go to the Topics tab. Right-click > Add Topic into the left-most window, and find GREETING.

"Hello &PCName;, and how are you today?" the agent greets. "Do you have any interest in tackling a location for the Regulators today?"

Note that typing &PCName; into the Response Text window causes our character's name to get placed automatically. In my game it'll say "Hello Cho Zen Wan, and how are you today?"

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetQuestVariable aaaGenericWastelandQuests, DoOnce == 0.00


Copy All both those.

7c). In the Add Topics window, right-click > Add Topic, and then right-click > New into the window which pops up. Select the ID name of the topic. I'm calling it aaaWastelandMissions. Click OK.

Do this again, and add a "No" topic. aaaNo in my game.

7d). Find both these topics in the left-most window. Let's start with the missions topic.

7e). Topic Text: aaaWastelandMissions

Response Text: Well there are several problem areas, always are. Some locations close by, others farther away. Got a list here, hold on.

Prompt: Sure, whatcha got?

Conditions: paste the same conditions from step 7b.

Result Script (End): Set aaaGenericWastelandQuests.DoOnce to 1

Choices: Right-click > Add Topic. I'm adding aaaSpringvaleSchoolBossTopic, and also the aaaNo topic.

7f). Find the new topic just added into Choices (aaaSpringvaleSchoolBossTopic in my GECK) in the left-most window. Change the Topic Text to something in plain wording (Springvale Elementary School) and click OK.

Save. Reopen the quest window. Let's flesh out the No dialog. This is going to be an all-purpose topic + dialog which gets used whenever a "no" answer is needed. It's important to continually offer decisions like this, so that the player isn't railroaded into quests they don't want, and have maximum choice all along.

7g). Topic Text: aaaNo

Response: Damn, you're letting us down, soldier.
...............Prompt: No, I cannot help at this time.

Priority: Change this from 50.00 to, let's say, 20.00. This makes the "No" topic always show up underneath whatever locational topics get added later on, as long as those topics have higher numbers than 20.

As more locations get added later on, Priority can be attempted to make them show in-game in alphabetical order, even if they aren't alphabetical in the Choices window. However, this doesn't always work correctly. I've had some success making jumps of 10, so that Bethesda Ruins (Priority 100) is at the top of my in-game list, Evergreen Mills (Priority 90) is underneath, Nuka Cola Plant (80) comes next, and so on. This doesn't always work 100% though, and might need to be played with.

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetQuestVariable aaaGenericWastelandQuests, DoOnce < 2.00


Toggle Goodbye ON. salute.gif

Result Script [End]: Set aaaGenericWastelandQuests.DoOnce to 0

7h). Compile and click OK.

7i). Reopen the quest window and find the new location topic.
Topic Text: Springvale Elementary School

Response Text: "Springvale School. Once a bastion of PreK to 5th grade learning, now a den full of menacing raiders! - You'd think those *bungholes* would leave such a formerly innocent place alone, but no, they've continued to infest the school."

For this next part, it helps to have the NPC boss in the Render window, so he/she can be easily selected.

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetScriptVariable aaaSpringvaleSchoolBoss, Dead == 0.00 AND
GetDead aaaSpringvaleSchoolBossRef != 1.00


The Reference for the GetDead should have the Run on slot changed from Subject to Reference, and then we can simply select the NPC in the window.

Choices: aaaSpringvaleSchoolBossYes and aaaNo.

7j). Right-click > Add Topic into the vertical window and add aaaSpringvaleSchoolBossYes (or whatever it's named in your GECK).

Topic Text: Leave this just as it is (aaaSpringvaleSchoolBossYes) since Prompt is being used for the clickable topic.

Response Text: Awesome soldier. I think you already know where Springvale is; chances are you've been there before, right? - I'll add a map marker just in case. Here's a ticket to remind you. - Their leader is called the Headmaster. Kill him, and 300 caps are yours. - Make sure to search the entire place, the school's got two levels.

Prompt: Springvale's boss has taught his last lesson.

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetScriptVariable aaaSpringvaleSchoolBossRef Reference: Dead == 0.00


(Note that the GetDead variable is not needed, it's already established the boss is alive.)

Result Script [Begin]:
Set aaaSpringvaleSchoolBossRef.dead to 1
Player.AddItem aaaSpringvaleSchoolTicket 1
SetObjectiveDisplayed aaaGenericWastelandQuests 1 1


Result Script [End]:
ShowMap SpringvaleElementaryMapMarker

7k: Compile that and click OK.

Now, make sure the NPC boss is still in the Render window.


Object window > World Objects > Static
8).: Drag an XMarkerHeading into the Render window and give it a Reference ID. I've got aaaSpringvaleSchoolXMarkerHeading. Copy its name and paste this onto the Notepad. This marker is going to be where the NPC gets teleported to, later on via script. So make sure it's in a spot which is clear of rubble / static items.

Note: Step 8 is especially necessary for Fallout 3, since enemies will often respawn wherever they were killed. If the fight with the boss gets continued outside, or in some other cell, THIS is where he/she will respawn, even if a Sandbox package is supposed to make him/her return to an editor location.

Object window > Miscellaneous > Message
9a). Right-click > New.
ID: aaaSpringvaleSchoolDeathMessage (copy/paste this to the Notepad).

Display Time: I've got 18, which means the message stays onscreen for 18 seconds. This can be changed to whatever is desired.

I like for the msg. to stay onscreen for awhile. Thing is, during the heat of combat, sometimes a quick message which flashes on for the default of 2 seconds can easily get missed.

Title: Springvale Elementary Death Message
Message Text: The Headmaster of Springvale has been pwned.

Note: Message Box is chosen by default, and I always toggle this off because when a box pops up in the game, this means all the action stops, until the player clicks OK.

Messages are not 100% necessary and some mind even find them unimmersive. But I like this sort of thing because it shows that the quest is working.

9b). Click OK. Save.


10a). Reopen the NPC's script, either from the pencil icon on the main toolbar, or from the enemy itself.

10b). Add this line somewhere between the If and EndIf statements:

SetObjectiveDisplayed aaaGenericWastelandQuests 1 0
ShowMessage aaaSpringvaleSchoolDeathMessage
SetObjectiveDisplayed aaaGenericWastelandQuests 2 1


Note: "SetObjectiveDisplayed" for the original mission is set to zero. This means this objective will no longer be displayed at the start of the game, or whenever this quest is toggled on. DO NOT use SetObjectiveCompleted. Doing so makes the objective work only once. If the quest is picked up later on (after the boss has been rid) those objectives will no longer show up in-game.

Note 2: Make sure the second SetObjectiveDisplayed (the one which tells the player to return for reward) goes UNDER the ShowMessage. This way, once the NPC boss has been rid, the message shows first, and the reward objective follows this.


10c). Save and close the script, and OK the NPC's panel(s) if needed.


11a). Now return to the quest. Open the first locational topic, which in my game is aaaSpringvaleSchoolBossTopic. Copy All its conditions stack.

11b). Right-click > New into the Info window.

Response Text: Well, good news is the baddies have not returned to Springvale. Yet. Would you like to take a look at the rest of our list?

Conditions: Paste these...

GetIsID aaaQuestAgent == 1.00 AND
GetDead aaaSpringvaleSchoolBossRef == 1.00


Basically, the ScriptVariable is not needed, and change the != comparison to ==.

11c). In the Choices window only aaaNo can go in there now. For future additions to the quest agent's list, other locational topics can get added here.

11d). Click OK and reopen the quest's Topics tab. Find GREETING.

Response Text: You are back. How's the latest mission coming along?

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetQuestVariable aaaGenericWastelandQuests, DoOnce == 1.00


Copy All those.

Add Topics: Add aaaWastelandMissions

11e). Find the Missions topic, there should already be a topic here with its own Topic Text and its own prompt. Right-click > New into the Info window.

Response Text: Seems you've got yourself a mission already. - Take a look at the latest ticket in your inventory, it should clue you in.

Prompt: What else you got?

Conditions: Paste the same conditions from the GREETING in 11d.

Toggle Say Once a Day and Goodbye on. Click OK.


12a).: Go back to the GREETING, and make a new one. This is what the agent's going to say when the boss has been put down, and now we're ready to be paid. 💰

Response Text: Ah wonderful, look who's back.

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetQuestVariable aaaGenericWastelandQuests, DoOnce == 2.00



Add Topics: Add aaaRewardTopic.

12b). Add the Reward topic into the leftmost window.

Topic Text: Reward
Response Text: Glad to hear Springvale's Headmaster is in detention. Here are your caps.
Prompt: The Headmaster of Springvale School is no longer in office.

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetScriptVariable aaaSpringvaleSchoolBossRef, Dead == 2.00


Toggle Goodbye on.

Result Script [Begin]:
Set aaaGenericWastelandQuests to 0
Player.RemoveItem aaaSpringvaleSchoolTicket 1
SetObjectiveDisplayed aaaGenericWastelandQuests 2 0


Result Script [End]:
Set aaaSpringvaleSchoolBossRef.Dead to 3
Player.AddItem F 500
RewardXP 10


12c). Click OK, closing the quest window, and save. And now to finish up the main script. For anybody who's made one of these repeatable quests for Oblivion, you'll be familiar with the timer script to come.


13a). Here's what the main script looks like so far...

Scriptname aaaGenericWastelandQuestScript

short DoOnce


Now add the following, so that overall it'll look like this

----------------------------------------------------
Scriptname aaaGenericWastelandQuestScript

short DoOnce

Short Timer1
Short StartDay1

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

13b). Save and close the script. Close and reopen the quest. Here's the entire script.

------------------------------------------------
Scriptname aaaGenericWastelandQuestScript

short DoOnce

short Timer1
short StartDay1

Begin GameMode

;----------------------------------
;This section pertains to the boss of Springvale Elementary

If (Timer1 == 0)
If (aaaSpringvaleSchoolBossBossRef.Dead == 3)
Set StartDay1 to GameDaysPassed
Set Timer1 to 1

EndIf
EndIf

If (Timer1 == 1)
If ((GameDaysPassed - StartDay1) >= 3)
Set Timer1 to 0
Set aaaSpringvaleSchoolBossRef.Dead to 0

aaaSpringvaleSchoolBossRef.MoveTo aaaSpringvaleSchoolXMarkerHeading

EndIf
EndIf

End

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

Pretty sure that covers everything. smile.gif

This post has been edited by Renee: Jul 24 2023, 10:34 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Apr 2 2023, 06:36 PM
Post #94


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



Repeatable Enemy Raids, Additional Locations. Game: Fallout 3

This time I'm going to put a boss into one of the Metro tunnels. Let's go for FriendshipMetro02. This is the tunnel which comes after the one Moira sends us into, when she's trying to get us to test her stupid mole rat repellant stick. The place is populated by ghouls, so I'm going to drop a Glowing One into one of the tunnel's restrooms.

OBJECT window > Items > Misc Item
1a). Edit the previous Metro ticket. Here is how I'm going to edit it for my game. Since the boss I'm adding is going to be a Glowing One type of ghoul, he's going to be known as "the Glower".

ID: aaaFriendshipMetroTicket
Name: Kill Glower of Friendship Tunnel 2

1b). Copy the ID name and paste it onto a Text file or Wordpad file.

1c). Click OK, saving as a New Form.


Cell View window
2). Find the location where the enemy boss will get added. Again, in my game this is FriendshipMetro02, somewhat towards the end of one of its branches, where the restrooms are.

Since I'm editing a creature this time (rather than an NPC) and I've never outlined how to set one of these up, here's the quick way. There are specific templates for ghouls, but a template is not needed. For those of you who wish to just make an NPC, and use the previous template to set him or her up quickly, have a look at steps 5b through 6a in the above tutorial.

Anyway, to make a quick ghoul, check this out.

Object window > Actors > Creature
3a). Find CFeralGhoulGlowingOne and right-click > Edit it.

ID: aaaFriendshipMetroGlowingOne

Name: Glower of Friendship Metro

No low level processing: OFF
Respawn: ON
Allow PC Dialog: ON

STATS tab
PC Level Mult: On
Level Mult: .25

AI PACKAGES tab: Remove the DefaultPatrolCasual package.


Level Mult(iplier) is set to 0.25, which means the glowing bastard levels up 1/4 as much as the Player-Character does. I tried using 1.00 but this was ridiculously tough. By default Glowing Ones are Level 11 I think.

3b). Click OK, closing the Creature panel, saving as a New Form.

3c). Drop the boss into the Render window.

3d). Give the boss a Reference ID. Copy this ID and paste it somewhere. I just typed aaaFriendshipMetroGlowingOneRef.

3e).Make sure to toggle Persistent Reference on.

This time, I'm also going to try something new, which is to toggle Initially Disabled on. Reason is, there are times when one of my guys or gals might just want to pass through this tunnel as they head on to one of the locations outside of Friendship Metro Exterior. And it would get a bit unrealistic (and also annoying) if the Glowing One is always there, even if the Friendship mission has not been chosen.

3f). Click Edit Base. Start a script like so...

Scriptname aaaFrienshipMetroGlowingOneScript

Short Dead


3g). Save that script, close the editor, click OK 2x (closing the Creature and Reference panels) and reopen them. Find the script in the Script scroll-bar, click OK, and reopen.

-------------------------------------------------------
Scriptname aaaFrienshipMetroGlowingOneScript

Short Dead

Begin OnDeath

If (aaaFriendshipMetroGlowingOneRef.dead == 1)
Set aaaFriendshipMetroGlowingOneRef.dead to 2
Set aaaGenericWastelandQuests.DoOnce to 2

EndIf

End


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

Save and close.

Object window > Actor Data > Quest
4a). Open the quest started up above, and select the Quest Objectives tab. Right-click > New into the top (Objective Index) window. There should already be two other objectives so far. Only one additional objective is needed.

Index: 3
Display Text: Pwn the boss of Friendship Metro Station #2.


4b). Go to the Topics tab. The same initial GREETING and initial topic are already set up. Click on the initial topic (aaaWastelandMissions).

4c). Right-click > Add Topic into the Choices window, and right-click > New into the Select Topic window. aaaFriendshipMetroTopic is going in my game. Click OK.

4d). Right-click > New the new topic in the left-most window.

4e). Topic Text: Change the Topic Text to something in plain wording (Friendship Metro Tunnel #2) and click OK.

4f). Save. Reopen the Quest panel.

4g). Right-click > New into the Info window.

Response Text: Long ago before the bombs dropped, Metro tunnels were used as daily transport for the masses.
Now they're inhabited by ghouls! And in this particular tunnel, a Glowing One has been reported!
I can't emphasize how important it is to rid Glowing Ones from the Wasteland. Top priority, soldier.


Priority:

For this next part, it helps to have the NPC boss in the Render window, so he/she can be easily selected.

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetScriptVariable aaaFriendshipMetroGlowingOneRef, Dead == 0.00 AND
GetDisabled, Reference: aaaFriendshipMetroGlowingOneRef == 1.00


The Reference for GetDisabled should have the Run on slot changed from Subject to Reference, and then we can simply select the NPC in the window.

4h):Right-click > Copy All those conditions.

4i: Choices: aaaFriendshipMetroYes and aaaNo.

4j). Right-click > Add Topic into the vertical window and add whatever "yes" topic was just created. In my game: aaaFriendshipMetroYes is the one.

Topic Text: Leave this just as it is (aaaFriendshipMetroYes) since Prompt is being used for the clickable topic.

Response Text: Grreat. We'll be looking forward to hearing this glowing menace has been defeated.
Job pays 500 caps, standard contract. Here's some Rad-X, you'll probably need it.
I'll mark the nearest location on your map.

Prompt: It'll soon be "lights out" for that Glower of a ghoul.

Conditions: Paste the same conditions just copied, but remove the GetDisabled...

GetIsID aaaQuestAgent == 1.00 AND
GetScriptVariable aaaFriendshipMetroGlowingOneRef, Dead == 0.00 AND


Result Script [Begin]:
aaaFriendshipMetroGlowingOneRef.Enable
Set aaaFriendshipMetroGlowingOneRef.dead to 1
SetObjectiveDisplayed aaaGenericWastelandQuests 3 1


Result Script [End]:
Player.AddItem aaaFriendshipMetroTicket 1
Player.AddItem RadX 3
ShowMap X


Note: In my game, I'm using FriendshipHeightsMapMarkerREF for the Map Marker. Optional, for those who've already been there, or haven't been to this location, yet want to go HARDCORE!!!

4k: Compile that and click OK.

Now, make sure the NPC boss is still in the Render window.


Object window > World Objects > Static
5).: Drag an XMarkerHeading into the Render window and give it a Reference ID. I've got aaaFriendshipMetroXMarkerHeading. Copy its name and paste this onto the Notepad. This marker is going to be where the NPC gets teleported to, later on via script. So make sure it's in a spot which is clear of rubble / static items.

Object window > Miscellaneous > Message
6a). Right-click > Edit the previous message made for the previous boss.
ID: aaaFriendshipMetroBossDeathMessage (copy/paste this to the Notepad).

Title: Friendship Metro Death Message
Message Text: The Glowing One of Friendship Tunnel has been pwned!

6b). Click OK, saving as a New Form. Save from the main toolbar.


7a). Reopen the NPC's script, either from the pencil icon on the main toolbar, or from the enemy itself.

7b). Add this line somewhere between the If and EndIf statements:

SetObjectiveDisplayed aaaGenericWastelandQuests 3 0
ShowMessage aaaFriendshipMetroBossDeathMessage
SetObjectiveDisplayed aaaGenericWastelandQuests 2 1


Overall, what we've got for the boss's script goes like this...

-------------------------------------------------------
Scriptname aaaFrienshipMetroGlowingOneScript

Short Dead

Begin OnDeath

If (aaaFriendshipMetroGlowingOneRef.dead == 1)
Set aaaFriendshipMetroGlowingOneRef.dead to 2
Set aaaGenericWastelandQuests.DoOnce to 2

SetObjectiveDisplayed aaaGenericWastelandQuests 3 0
ShowMessage aaaFriendshipMetroBossDeathMessage
SetObjectiveDisplayed aaaGenericWastelandQuests 2 1

EndIf

End


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

7c). Save and close the script, and OK the NPC's panel(s) if needed.


8a). Now return to the quest. Open the new locational topic, which in my game is aaaFriendshipMetroTopic. Copy All its conditions stack. There should be three conditions to copy.

8b). Right-click > New into the Info window.

Response Text: There might be some ghouls in that tunnel, but haven't got word of any Glowing Ones roaming about.
Would you like to see the other problem locations?

Conditions: Paste these...

GetIsID aaaQuestAgent == 1.00 AND
GetScriptVarible aaaFriendshipMetroGlowingOneRef.dead == 3.00


The ScriptVariable is needed this time instead of GetDead, since there's a juggling act between whether the boss is Enabled or not, and whether he/she is dead or not. GetDisabled can get tricky to use, since the main script is going to disable the enemy in a few...

However, if the enemy did not start as Initially Disabled and GetDead was previously used, GetDead can be substituted now. Make sure to make the Comparison == 1.00 instead of != 1.00 though.


8c). Find any previous locational topics (so for me, this is aaaSpringvaleSchoolTopic). Find the "Good news, the enemy has not returned" response (this should be the second topic in the Info window).

8d). Add the new location into the Choices window and right-click > Copy All the stack. So, for those who are strictly following these tutorials, there should now be two locational topics in the Choices window.

aaaFriendshipMetroTopic
aaaNo


8e). Return to the new locational topic (Friendship Metro in my GECK) and click on the second response. "There might be some ghouls in that tunnel, but good news is the Glowing One has not returned...."

Paste the Choices stack copied from step 8d into the Choices window, but remove aaaFriendshipMetroTopic. How convenient. Now add aaaSpringvaleSchoolTopic.

-- That was a bit clumsy. But as more and more locations get added, pasting the locations into Choices makes the job somewhat easier than was found in the TES4 Construction Set. We still need to make sure the right locations get added into the right Choices windows, and the wrong ones get excluded. Basically, whichever location we're working with, in which the boss has NOT respawned, should have all the other locations (plus aaaNo) in its Choices window.

Hope that made sense.


9a).: Select the Reward topic, and right-click > New into the Info window.

Response Text: You were able to get rid of the Glowing One in the Metro, here are your caps.
Prompt: The Glower of the Friendship tunnel #2 is no longer alight.

Conditions:
GetIsID aaaQuestAgent == 1.00 AND
GetScriptVariable aaaFriendshipMetroGlowingOneRef, Dead == 2.00


Toggle Goodbye on.

Result Script [Begin]:
Set aaaGenericWastelandQuests to 0
Player.RemoveItem aaaFriendshipMetroTicket 1
SetObjectiveDisplayed aaaGenericWastelandQuests 2 0


Result Script [End]:
Set aaaFriendshipMetroGlowingOneRef.dead to 3
aaaFriendshipMetroGlowingOneRef.Disable
Player.AddItem F 500
RewardXP 10


--------

9b). Click OK, closing the quest window, and save. And now to finish up the main script. For anybody who's made one of these repeatable quests for Oblivion, you'll be familiar with the timer script to come.


10a). Here's what the main script looks like so far...

====================================

Scriptname aaaGenericWastelandQuestScript

short DoOnce

short Timer1
short StartDay1

Begin GameMode

;----------------------------------
;This section pertains to the boss of Springvale Elementary

If (Timer1 == 0)
If (aaaSpringvaleSchoolBossBossRef.Dead == 3)
Set StartDay1 to GameDaysPassed
Set Timer1 to 1

EndIf
EndIf

If (Timer1 == 1)
If ((GameDaysPassed - StartDay1) >= 3)
Set Timer1 to 0
Set aaaSpringvaleSchoolBossRef.Dead to 0

aaaSpringvaleSchoolBossRef.MoveTo aaaSpringvaleSchoolXMarkerHeading

EndIf
EndIf

End


========================================

10b). At the top of the script, right under "short DoOnce" and above "Begin GameMode", add

short Timer2
short StartDay2


10c). Save and close the script. Click OK, closing the Quest panel. Reopen it.

10d). Copy everything between the first If and final EndIf statements. So, I'm copying this...

If (Timer1 == 0)
If (aaaSpringvaleSchoolBossBossRef.Dead == 3)
Set StartDay1 to GameDaysPassed
Set Timer1 to 1

EndIf
EndIf

If (Timer1 == 1)
If ((GameDaysPassed - StartDay1) >= 3)
Set Timer1 to 0
Set aaaSpringvaleSchoolBossRef.Dead to 0

aaaSpringvaleSchoolBossRef.MoveTo aaaSpringvaleSchoolXMarkerHeading

EndIf
EndIf


10e). Paste all of that text below the final EndIf, but above End

Now, make the following changes, so it'll look something like this...

If (Timer2 == 0)
If (aaaFriendshipMetroGlowingOneRef.dead == 3)
Set StartDay2 to GameDaysPassed
Set Timer2 to 1

EndIf
EndIf

If (Timer2 == 1)
If ((GameDaysPassed - StartDay2) >= 3)
Set Timer1 to 0
Set aaaFriendshipMetroGlowingOneRef.dead to 0

aaaFriendshipMetroGlowingOneRef.MoveTo aaaFriendshipMetroXMarkerHeading

EndIf
EndIf


Overall, the main script should now look something like....


========================================

Scriptname aaaGenericWastelandQuestScript

short DoOnce

short Timer1
short StartDay1

short Timer2
short StartDay2

Begin GameMode

;----------------------------------
;This section pertains to the boss of Springvale Elementary

If (Timer1 == 0)
If (aaaSpringvaleSchoolBossBossRef.Dead == 3)
Set StartDay1 to GameDaysPassed
Set Timer1 to 1

EndIf
EndIf

If (Timer1 == 1)
If ((GameDaysPassed - StartDay1) >= 3)
Set Timer1 to 0
Set aaaSpringvaleSchoolBossRef.Dead to 0

aaaSpringvaleSchoolBossRef.MoveTo aaaSpringvaleSchoolXMarkerHeading

EndIf
EndIf


;----------------------------------------
;This section pertains to the Glower of Friendship Metro Tunnel #2

If (Timer2 == 0)
If (aaaFriendshipMetroGlowingOneRef.dead == 3)
Set StartDay2 to GameDaysPassed
Set Timer2 to 1

EndIf
EndIf

If (Timer2 == 1)
If ((GameDaysPassed - StartDay2) >= 3)
Set Timer2 to 0
Set aaaFriendshipMetroGlowingOneRef.dead to 0

aaaFriendshipMetroGlowingOneRef.MoveTo aaaFriendshipMetroXMarkerHeading

EndIf
EndIf

End


This post has been edited by Renee: Apr 5 2023, 03:02 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Apr 23 2023, 01:50 AM
Post #95


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



Gray Face bug. Game: TES V: Skyrim

These are SubRosa's words, edited by me. Sometimes when making an NPC in the CK he or she will have a "two-tone" coloring: the face will be considerably darker or lighter than the rest of the body. Sometimes we can just cover this up with full-body armor or clothing. But to fix it properly.

1.) Create a new NPC, or edit one which has been afflicted by the bug.

2.) Edit the face if the person is new, or edit the already-made person, if needed.

Note: If there are additional textures installed in actors/character, NPC customization will result into a two toned NPC, move all the extra textures into a back up folder. (This doesn't apply to me, as far as I know.)

3.) Click "Okay" on the character window closing it. In the Object window, highlight (left-click) your new NPC in the actors list and press CTRL + F4. This causes the kit to export FacegenData.

4.) Save plugin.

5.) You can confirm success by checking Data/Meshes/Actors/Characters/FaceGenData/FaceGeom/<mod name> folder. There should be a folder specfically per the mod the actor is from (Laprima's World.esp for instance).

Also check Textures/Actors/Characters/FaceGenData/FaceTint/<mod name> folder. If it is simply a change to a vanilla NPC, it will be in the .../FaceGeom/Skyrim.esm subfolder. The file will be a .nif with the same name as the base id in the construction set.



This post has been edited by Renee: Dec 22 2023, 08:19 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post May 19 2023, 06:54 PM
Post #96


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



Script Fragments. Game: TES V: Skyrim

I am writing this page to instruct how script fragments work, and to give direct instructions how to set them up.

Script fragments are small bits of code which are localized (they only affect the specific quest or object they've been placed into, unless called to act more globally). They make very specific changes in the game, usually when a bit of dialog is spoken, or a quest stage gets set, and so on.

There will be a bunch of script fragments on this page when it is done. I will include links to Bethesda's official Creation Kit site for each of these, as well. Click on the Spoiler tags for my "plain English" directions as well.

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

Let's start with AddItem.



If adding an object to the player, type Game.GetPlayer().AddItem(ObjectName, X) instead of "aaaNPCRef.AddItem..."

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

ENABLE -------- (click spoiler tag below for my explanations).



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

EVALUATE PACKAGE



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

Making a Door set a Stage -- (Not a script fragment)



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


Game.ShowLimitedRaceMenu()

"LimitedRaceMenu" used as a script frag opens up the limited version of SRM, which means the character's Name, Race, Sex (and skills) stay intact while we can modify only their looks. It is apparently what the face sculptor added by Dawnguard in the Ragged Flagon uses.

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

MoveTo



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

OPENInventory



Quest Messages




SetEssential



SetPlayerTeamMate




StartCombat



This post has been edited by Renee: Mar 26 2024, 10:31 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post May 26 2023, 10:29 PM
Post #97


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



Fixing the Sideways Glasses Bug, Game: Fallout 3 & Fallout New Vegas

When putting on mod-added glasses, goggles, and sometimes hats, these items will sometimes hang off the side of the PC's face instead of sitting properly. Here is an example. Look at Cho Zen Wan's glasses (he's the one on the right) which are hanging askew.

Basically, vanilla items (such as Biker Goggles) are fine, but when editing these items in the G.E.C.K. they won't sit properly on our character's nose. Instead, they'll hang sideways.

Here's the video tutorial which teaches the fix. It's made by Seddon, who makes perhaps the very best video tutorials!

And Here is the New Vegas fix. Note that trying to fix this in NV is different from FO3. Essentially, you'll need FNVEdit to fix the problem. *LINK*

Here is my own written fix for Fallout 3, though.

1). Open Fallout 3 GECK, and boot up whichever mod adds the appropriate item(s).

2). SAVE the plug-in from the main toolbar before continuing. Once the mod's been saved, click on Character from (again) the main toolbar. Select "Update FaceGen model availability". This is the second selection from the bottom of the list.

3). Save again. Problem should be fixed.

This post has been edited by Renee: Jun 19 2023, 02:06 AM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Jun 8 2023, 08:02 PM
Post #98


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



Nexus Mod Manager - installing and uninstalling

Yeah I know... why is she posting how to use NMM? wacko.gif Isn't that program self-explanatory? Hey, I get lost sometimes... So this lesson shows how to install entire mods from the manager itself (rather than copy/pasting into the Data Files folder, which was what I've been doing up til now). This can be helpful especially when installing or uninstalling lots of files.

Note that NMM is an outdated program which includes several features which don't work correctly. It occasionally gets buggy. Nowadays THE Nexus uses Vortex, which I believe they had to outsource. Personally though, I prefer the original Nexus Mod Manager.


1). Open up Nexus Mod Manager, click on the Mods tab.

2). There should be an orange-colored icon which is called Unassigned. Expand this icon.

3). Click the large + button on the manager's left side. This is the Add Mod from File button. This should open up our Downloads folder. From here, simply navigate to the archive we wish to add.

4). Single left-click on the archive.

5). Click Open. The archive has been transferred into the Mods folder. Right-click on it and select Install and Activate. There we go. This should install the mod's entire folder path (not just the .esp). Larger mods (overhauls and such) might require a few minutes to install.

If the archive contains several .esp files yet we only need one of these, Open the archive itself and delete any files which are not wanted. There is no way to delete them straight from NMM, not that I've found, anyway.

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

Here is how to make different Character profiles. When swapping from one guy or gal to the next, we can make it so all the particular mods in their game automatically switch as well. First step is to create a profile. If a profile has already been made and you just want to learn how to swap from one profile to the next, skip to Step 3.

1). Open the Mods tab. At the very top of the toolbar there should be a button for Launch "X", with X being whichever game, and next to this is the Profile button. Click on the little arrow to the RIGHT of the Profile button. This arrow points downwards.

This is tricky to do. Instead of making the actual Profile name the button, we gotta click on the tiny down-arrow to the right of the button. rolleyes.gif

2). Select New Profile. Name and address this profile somewhere.

Now let's say I've got two characters: one is an archer, the other a paladin-type. I want an Archery specific mod to show up in my archer's game, but not in my paladin's. I am now switching to my archer's list from my paladin's list.

3). Assuming the mod has already been installed from its compressed archive (see the instructions above for how to do this) left-click on the mod we wish to use for this particular 'toon. laugh.gif Now press the Big Green Check Icon on the left toolbar. The mod should install automatically.

Conversely, if we wish for a mod to Uninstall at the same moment, left-click on it and select the Big Red Cancel Icon. Voila.

4). Switch to the Plugins tab. Now click on the little arrow next to the Profile button, and select Save Current Profile.

5). Assuming a second Character Profile has been added, follow steps 3 and 4 again, to Install and/or Uninstall from that character's world as well.

Double-check that each pertinent .esp or .esm has activated. NMM is a buggy program. It Installs and Uninstalls faithfully, but sometimes it won't activate.

This post has been edited by Renee: Oct 22 2023, 04:08 PM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Jun 21 2023, 12:03 PM
Post #99


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



Breton Magic Resistance Tweak, Game: TES III: Morrowind

I recently discovered something about the way Magic Resistance works in this game and have come to this conclusion: MR is nearly useless! bluewizardsmile.gif Well, it's useless against elemental magics: Cold, Fire, and Shock spells do NOT get resisted by base Magic Resistance spells, abilities, potions or scrolls in this game. No wonder the Breton characters I've rolled in TES3 over the years keep getting drastically damaged by elemental magic, even though they've got 50% MR. rolleyes.gif

Poison and Paralyze also do not get affected by Magic Resistance. This sucks. Granted, MR does protect against plenty other magic types: Absorbs, Damages, Drains, Weakness spells, and a variety of Illusion spells. But not being able to resist against the elemental stuff is huge. As we're getting late into the game, dealing with atronachs and Daedra and some undead, lack of MR against their magics really makes things complicated. devilsmile.gif

So yeah, it's cheating, but I'm changing at least the elemental magic part. And it's not because MR resists all elemental magic in Oblivion and Skyrim, it's because the alternative to not making the changes below includes carrying a ton of potions and/or scrolls. Or cramming the Magic menu with three extra new resistance spells. My magical characters already have enough potions in their inventories, and spells in their books, which makes it cumbersome to select one of these spells in real-time (I prefer selecting spells in real-time rather than pausing constantly to switch magic).

So here goes. I am not changing the way Magic Resistance spells work; we can already do so with Spellmakers in the game. But I am changing the Breton's Magic Resistance ability. This is relatively easy.

1). In the Object window, select the Spellmaking tab.

2). Find Resist_Magicka_50. I am manipulating the Ability by the way, I'm not talking about any MR spells (though spells can also be tweaked). Resist_Magicka_50 is what Bretons have as a base Ability.

> We can also make tweaks to any Magicka Resistance spells as well, but the problem is this'll drive up Magicka costs in-game, and also lower the chance for a successful cast. Anyway,

3). As we can see, Resist_Magicka_50 already has Resist Magicka as an Effect, and there are seven additional scroll-bars below. To add additional effects, simply select any of the scroll-bars, and find the magical effect desired.

4). Change Magnitude as well. I've selected 50 for Resist Fire, Resist Frost, and Resist Shock.

Save. Voilà.

To double-check click on Character on the main tool bar. Select Race. Make sure the ability just modified corelates to what's shown in the Specials window. Yeup, resist magicka_50 is being shown.



This post has been edited by Renee: Jun 24 2023, 12:50 AM


--------------------
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Renee
post Jun 24 2023, 07:29 PM
Post #100


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



Manipulating Leveled Lists

Here is how to change the leveled lists which reside in any Elder Scrolls or Fallout game made by Bethesda. This helps a lot to manage when certain enemies show up, whether stronger enemies replace weaker ones, and so on.

Do you want Minotaurs to show up in the game even though your character's a total Level 1 weakling? Make it happen. And for those who already have a mod which introduces leveled lists (such as MMM), these lists can be changed as well.

One of my only pet peeves with Oblivion when I was new to that game was the way it would replace weaker enemies with stronger ones, all due to our character attaining a certain level. rolleyes.gif I don't have a problem with stronger enemies eventually showing up, but what I didn't like was the way a lot of the weaker ones disappeared from the game entirely.

An example: Wolves are in the world of TES4 right away. But once we gain Level 6, ALL of the Wolves vanish, and now we have only Timber Wolves, which are stronger. To me, this seems unrealistic. Even a fantasy world such as Tamriel's should feature weaker and stronger opponents, with weaker enemies outnumbering the stronger ones. 🐺 Alpha monsters basically are at the very top of the food chain; that's Darwinism, baby!

Anyway, here's how to manipulate these lists. It's so easy, too. smile.gif I am going to manipulate the way skeletons show up in Morrowind for this example. Because lately I notice that we're not seeing any plain Skeletons in my Level 14 character's game if she's in the majority of Shrines; her world is only populated by Skeleton Champions.


OBJECT window
1). Find the area of the window where Leveled Lists are posted. So in Morrowind, this is in the Leveled Creatures tab.

2). Now, find the proper list. So... I am trying to change the list for Skeletons, and there are three lists in the Leveled Creatures page: in_tomb_skele_lev+0, in_tomb_skele_lev+2, and in_tomb_skele_lev-2. 🦴

Selecting in_tomb_skele_lev+0, I can see right away in the list's Creature Name window it looks like this.

1 Skeleton
1 Skeleton Archer
7 Skeleton Warrior
10 Skeleton Champion


The number on the left is our character's level. So from levels 1 through 6, Skeletons and Skeleton Archers are prevalent. From 7 to 9 we've got Skeleton Warriors, and from Level 10 there are Skeleton Champions. No wonder I'm not seeing any weaker variants in my gal's gameworld.

Here's how I'm changing it.

3). Note that every game does this part differently. Let's say I want ordinary Skeletons to show up at any time, along with the stronger variants. For Morrowind, click on the Creature tab. Find Skeleton, and drag this choice over to the Leveled Creature window. Here's what it looks like now.

1 Skeleton
1 Skeleton Archer
7 Skeleton Warrior
10 Skeleton Champion
10 Skeleton


Perfect. Now when my characters go delving into an area where this list is featured, Skeletons Champions are arranged at Level 10, but so are ordinary Skeletons.

4). And to change the Level modifier, left-click on whichever choice is desired, and press F2. I just dragged a second Skeleton into the window, clicked F2, and changed the number from 10 to 7. Now the list looks like this:

1 Skeleton
1 Skeleton Archer
7 Skeleton Warrior
7 Skeleton
10 Skeleton Champion
10 Skeleton


Overall, I came up with this when I was completely done with the in_tomb_skele_lev=0 list.

1 Skeleton
1 Skeleton Archer
7 Skeleton Archer
7 Skeleton Warrior
7 Skeleton
10 Skeleton Champion
10 Skeleton
10 Skeleton
10 Skeleton Archer


I've basically nerfed the lists for skeletons, because to me I'm after overall realism, not overall challenge. Some folks might want to make lists stronger, of course. Sure, this is possible as well.

I'll include guides for some latter games, as well. Each game does things a little differently.

This post has been edited by Renee: Jun 25 2023, 05:05 AM


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

6 Pages V « < 3 4 5 6 >
Reply to this topicStart new topic
5 User(s) are reading this topic (5 Guests and 0 Anonymous Users)
0 Members:

 

- Lo-Fi Version Time is now: 28th March 2024 - 10:25 AM