Jump to content

Fallout New Vegas GECK & Scripting Help 101


Recommended Posts

  • 2 weeks later...

Could someone tell me if there's some pro in running a gamemode script on a npc instead than on a quest? I mean, is the difference the fact that on a npc it is running continuosly while on a quest it is running every (delay time)?

I have a problem understanding the "cycle", the "timing" of how a script is executed. It helps me to understand how handling some scripts to optimize them.

Let's make a simple example, a script with a timer that leasts 10 seconds on a gamemode.

- Attaching it on a character makes it running every single frame until the 10 seconds are expired, then 10 more seconds will start count etc.etc.

- Attaching it on a quest makes it running the first time after (delay time), then it will run every single frame until 10 seconds are expired, then it will wait (delay time) before starting again? Is it correct?

- What happens if the timer is running on the quest and it reaches 5 seconds (that is supposed to be the Delay time)? a second istance of the script will start?

 

To make another practical example: I made a scanner with GetFirstREF / NextREF. I attached to the npc who needed to scan. After that, I decided to move that script from him to a separate quest, and the npc will refer it as quest.var. I though that this could optimize the things because of the (delay time). Is it a correct thought? Is the only downside the fact that the npc will scan only every (delay time) seconds?

Link to comment

There are a few subtle differences between the scripts. You have the basic idea though. The two main reasons to put things in a quest script are less cpu load (so more scripts can run), and to ensure it always runs. A script on an item or spell may unexpectedly stop, say if the item is destroyed, the npc the spell is on is in a different zone, etc.

Link to comment

Thank you both for the answers. Cpu load is my main concern in these few last months, since I started to "feel" it. I'll continue using Quests then, it seems the best choice for that.

@Halstrom what if NO LOW LEVEL PROCESSING isn't flagged on a npc with a script attached? shouldn't take care of that npc even when you are not in his cell? now this could be a nice thing to try :P

 

The last thing I'm wondering if this one:

"- What happens if the timer is running on the quest and it reaches 5 seconds (that is supposed to be the Delay time)? a second istance of the script will start?"

 

I mean, for example in the timer that leasts 10 seconds, after (delay time) it starts to count, but what happens after the next (delay time), since the script is still running? Will a second istance of the same script start, with separated istanced local variables values (so a second timer running)? or there's always only a single istance running until it completely ends?

 

PS yesterday I had obvious mistakes inside End script in AI Packages that were compiled with no error, and then breaking in game... please always doubt to those scripts in AI packages, they are evil, more than End Scripts in dialogues.

Link to comment

What Hal and I said is that by default, the script will not run if it's "on" an NPC (as a spell, or an item they're carrying) if they leave the cell (or if you do). The low level processing flag on an NPC just means their AI package won't run if they're not in the same cell as the player. It doesn't affect scripted items or spell effect scripts, which already will not run if not in the players cell.

 

I don't understand your other question. There's only one instance of the quest script running, ever. Your script taking 5 seconds to run is impossible -- if it doesn't complete within a single frame (1/30th of a second @ 30fps), it is terminated by the engine.

Link to comment

You're right I explained bad, but you got it and already answered that. Taking for example a scanner running on a gamemode script  attached to a npc (so it's supposed running every frame), my concern was "what happens if it can't scan all the objects in a single frame? will it cause slowdowns to the game, stopping all the other things until it finishes, or it will start a second instance of the same script while it is still finishing the previous one?" but as you say the engine will interrupt the script, so I assume it simply won't scan all the objects and will start again a new scan.

Link to comment

You're right I explained bad, but you got it and already answered that. Taking for example a scanner running on a gamemode script  attached to a npc (so it's supposed running every frame), my concern was "what happens if it can't scan all the objects in a single frame? will it cause slowdowns to the game, stopping all the other things until it finishes, or it will start a second instance of the same script while it is still finishing the previous one?" but as you say the engine will interrupt the script, so I assume it simply won't scan all the objects and will start again a new scan.

Yes it will cause slowdowns, and yes it will be interrupted and start over from the top the next frame -- however, variable values are not reset. This is the main reason we use stages in a lot of scripts. We know they can't possibly finish in a single frame, and we need to know where we left off so we can pick back up at the same spot.

 

In a scanner it's a particularly bad idea to do the refwalk and operate on the refs all at once (inside the walk) unless you're doing something very simple. It's better to do the refwalk and just store the results in a list or array, set a new stage, and then begin looping through the list you made. Set a new stage (or back to the refwalk stage) after the loop. This way if the script is interrupted and starts over, it will be able to resume work on the previous list.

 

Not doing this means you'll end up processing the same refs over and over (the top of the list) and never make it to the bottom.

Link to comment

Oh I should note, if you have such a script -- one that consistently takes more than a frame to complete, and it's not something that's intended to run for a long time (like the sexout effect, which must run from the act start to finish - thousands of frames), you need to rewrite it. Continually running a script that takes all frame to run and doesn't finish is *the* cause of script related engine lag.

 

When enough scripts start behaving that way, and it doesn't take very many, you get lag in the game and high CPU load.

Link to comment

That's a very nice note, I'll keep it in mind. Problem is how can you really find how much time a script requires to run, that's why few days ago I was asking if there was a list of "slow functions" that was better not to use. I noticed GetRef is quite fast to scan an entire cell looking for a single ref, but this doesn't tell me it takes 1, 2, 5, 10 frames to do it in different cases like when there are a lot of references to scan or running with other active GameMode scripts from other mods.

 

During my plays with another companion mod, I found my game was quite slow since I installed it, I couldn't believe it was only because she had a pretty texture skin. I took a look at the code and it runs a lot of functions in GameMode, all attached to her and not to a quest, I'm trying to understand if it's the real reason of slowdowns. I'm scripting my own companion right now, to try a couple of new features, and I wouldn't like it slowdowns other people just like it happened to me with that other mod.

Link to comment

It's better to do the refwalk and just store the results in a list or array, set a new stage, and then begin looping through the list you made. Set a new stage (or back to the refwalk stage) after the loop. This way if the script is interrupted and starts over, it will be able to resume work on the previous list.

 

Not doing this means you'll end up processing the same refs over and over (the top of the list) and never make it to the bottom.

 

 

Arrays... I suppose it requires NVSE 4... still have big problems understanding arrays, even with Doctasax wonderful tutorial. It's just... too much for me.

Link to comment

There's no list because it's really variable. Any function might be fast one time and slow the next, though generally any that do not update the scenegraph (do not add, remove, or change 3D objects) are usually fast, and any that do are slow.

 

However the best thing to do is just write "tight" code, and do it in small chunks. Sexouts main script works this way and has many stages for just this reason -- it does a small bit of work, sets the stage value to the next stage, and returns.

 

This way, in each frame, it doesn't do a "lot" of work. The next frame, it runs the next stage, thanks to a big if/else block that checks the stage value.

 

(removed timing comment, forgot that function is borked. I need to put one in NX.)

Link to comment

 

It's better to do the refwalk and just store the results in a list or array, set a new stage, and then begin looping through the list you made. Set a new stage (or back to the refwalk stage) after the loop. This way if the script is interrupted and starts over, it will be able to resume work on the previous list.

 

Not doing this means you'll end up processing the same refs over and over (the top of the list) and never make it to the bottom.

 

Arrays... I suppose it requires NVSE 4... still have big problems understanding arrays, even with Doctasax wonderful tutorial. It's just... too much for me.

 

Just use a formlist then. Or bite the bullet and learn. ;)

Link to comment

I wrote staged things, with big if blocks to check them, since start. It was a quite "natural" solution for me and I now reading your comment I can realize it was a good choice, wow one of the rare cases where my sixth sense is right...

 

Some days ago I already bit the bullet and DIDN'T learn :D I really feel these new functions and abstruse syntax are something for programmers and not casual newbies. Prolly I just need to swim inside scripts for a longer time.

 

On a side note, if you still have not read this, I suggest you to do it for curiosity, I find these tests that check how much a function requires to be executed really really interesting: http://forums.bethsoft.com/topic/987561-script-optimisation/

Link to comment

cipcis is a really smart guy, but those tests are really subject to external influence since it's so indirect. It's just about all that is available though. I'm going to add a gettime to NX that just returns a fractional epoch time (unix epoch time + fractional seconds) whenever it's called. This will make normal profiling much easier.

Link to comment

A.J.:  Thanks for asking about all of this.  Stages and the amount of times script runs and respawns really confused me as well.

 

While I haven't read Doc's tutorial on arrays, I might suggest looking up arrays on Wikipedia for an explanation in Italian.  Once you get the idea of how an array works, you can tackle Sexout's syntax and functions that handle the values.

 

I'm trying to write up an explanation below, and forgive me if you already know the basics.  Also, be careful because I'm used to certain formats that Sexout may or may not use.

 

Imagine that you've got a desk (I bet you have a desk anyway : D ).  You know what's in it, but if a friend is visiting you, they won't know where to look for something.  So you say "Can you get me the book (value)?  It's in the desk (array) in the 2nd drawer (array[2])."

 

I'm working on an equipment set mod that allows you to hotkey your armor along with your weapon.  There are a total of 20 equipment slots for characters (which include the pip-boy and weapon, fyi).  They are numbered from 0 to 19 because programming stuff usually starts counting at 0 instead of one.

 

Point being, if I decide to use NVSE with it (another issue entirely), an array would be an easy way to deal with.

 

I would create an array named Set[20], because I know that there are a total of 20 equipment slots.  I would use a loop to get the base ID for each equipped item.  Set[0] (the first space or drawer in the array] gets the base ID for whatever item is in slot 0, and so on until you assign the last one to Set[19].  IIRC, the weapon slot is #5.  If I want to find out what weapon was equipped with this set, I'd do some sort of GetValue Set[5].

 

The most confusing part is that you declare the array size with the number counting up from 1, but when you're working with different array variables, the slots of the array are numbered counting from 0.

 

If you had 3 containers in game, you'd declare your array as My_Containers[3].  If you wanted to get what was in the second container, you'd get the value of My_Containers[1].

 

 

NOTE:  This doesn't get into dynamic arrays, (arrays where you don't know how big the array should be, like if you wanted a list of every NPC that a player has slept with since everyone had their own playstyle and preferences) which are sometimes more difficult to do with some languages, so I don't know if NX supports it.

 

EDIT:  I wrote this from my phone, so there could be plenty of errors.  Hopefully the declaration process and the value getting process are how NX does it.

Link to comment

Thank you Nyaallich for the explanation.

 

I know what an array is, what I don't know is how to use NVSE 4 arrays. In your example, making a catalogue of weapons to equip them with a hotkey, well I suppose it could be simply done with a form of REFs obtained inspecting the inventory. But NVSE 4 arrays have different additional features from what I've read, like the fact I can store different kinds of variables. These features are still something I must understand how to use, in which case I could find it useful. In your example, I would find a use for them if for example I would store also different values, like dps, then IsKeyPressed > atuomatically equip the stronger weapon, or equip the one with bigger range, etc. so for example the 3 would equip the stronger shotgun, 4 the stronger machine gun, 5 the longest range sniper etc.

 

Doctasax's examples are pretty and I can understand them, I simply can't realize on my own where I could use something like that. But as he wrote, probably it's because I still didn't meet a real need to use them in my scripts...

If I add the fact that this new syntax is everything but easy to be read for me, because I don't see it "plain" as for the previous functions, I'm everything but tempted to use it for now... figure the scene: today I write few lines of script, tomorrow I spend one hour trying to understand what I did because it's not easy to read it as the previous scripts... it's a mess when something doesn't work and I must figure where the mistake is.

Link to comment

An array is simply a list, there's no more to it than that. What makes them useful in code is that they can be iterated (a fancy way to say "looped through"), meaning you can use a loop to look at every entry in the list and potentially modify it. The other thing that makes them useful is when you want to store a list of values, but you want to store a lot of them, or you don't know how many you want.

 

Without an array you must create a uniquely named variable for each value you want to store. This isn't a problem when you only have a few values, for example you can easily make 5 ref variables that store 5 different NPCs. If you wanted to get the name of each NPC and print it, you would have to print something like "ref1.getname" through "ref5.getname". Any time you want to perform the same operation on all of the things in your list, you must remember to do it to each of your variables.

 

This gets annoying when you have more than a few, and (in the geck script engine) downright impossible if there are hundreds or more.

 

Anywhere in your code where you have a list like that, you can use an array instead. This is probably the easiest way to learn to start using them -- by converting existing code, even if you don't actually need to.

 

Once you fully understand *how* to use them (once you have experience), knowing *when* they are useful will come naturally.

 

So go look for some simple place in a script where you have two or three variables of the same kind -- integers, refs, whatever. Rewrite that code to use an array instead. Do this a couple times and at some point, it will just "click".

Link to comment

Don't know if anyone has run across this before, but Gribbleschnibit maintains an awesome page where you can look up NVSE commands and other stuff to get their description or values (actor value numbers, equipment slots, etc.).  I've even started to see some of the NX functions making their way in there.

 

Semi-related question.  Obviously, NVSE is required for Sexout stuff.  I don't know why anyone wouldn't have NVSE at this point unless a bad install burned them in the past.  I was trying to avoid using it in one of my mods to make it more user-friendly, but that means the coding is that much more of a pain in the ass.  Are there good reasons NOT to use NVSE)?

 

For example, I'm working on a skill book mod.  Companions can use skill books, and I'd like a message to appear saying in the upper left corner saying "Boone's Barter Skill was increased by 3," etc., for all of the skill books (don't ask why you'd want to raise his barter stat).  If I used NVSE, I could pass "barter" as a string.  Otherwise, I'll have to create 14 different messages - one for each skill.

 

Any thoughts?

Link to comment

Awww the link doesn't work for me :-/

 

Are there good reasons NOT to use NVSE)?

 

From the top of my being noone, I say NO. In my opinion, these few mods really became a standard and they should at least be installed by everyone. If you can avoid requisites / dependencies, do that and it's very appreciable, but not when it comes to something that for me earned the title of "almost vanilla"

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use