Jump to content

Is there a way to create "functions" like in Papyrus scripting


Guest Messenjah

Recommended Posts

Guest Messenjah

Honestly when I started working in Skyrim, I was a bit overwhelmed by it's scripting system. However, after a year of scripting and then returning to Fallout NV scripting, I really feel like I have become rather spoiled by it lol. So, my current goal right now is to try and give finishing my old mod a shot. However, I want to re-build it from the ground up with a much simpler design. My first and formost goal is to try and find an organized infrastructure that I can use in both Skyrim and Fallout for future projects and that I can perhaps use in a tutorial to help others.

The design flow I'm looking for involves running all npcs off from one central quest script that controls everything they do in a very simple way. I usually contain all general dialogue and all quest starting dialogue within this quest since this quest is start game enabled. This way, I only have one single quest that is start game enabled.

One of the things I really like about Papyrus vs Fallout's system, is the unique "function" system. Now, what we call functions in Skyrim and what we call functions in Fallout are two very different things, from my understanding. In Skyrim, we can create a unique function, name it anything we want, and call on that at any time in order to execute certain lines within a quest script or other script.

So, for example, I would do something along the lines of this:



function GiveReward()
Quest.SetStage(100)
Game.GetPlayer().AddItem(Gold,200)
;Execute any additional code here.
EndFunction


This way, when I handle my dialogue end script fragments to control different variables, I only have to call on one single line "GiveReward()" in order for all the code related to that particular function to automatically execute.

This is also nice because it makes the code clean, and it allows me to control everything from one single location in an organized fashion so I don't have to go looking all over the place to find out what is wrong with my scripts.

So, this has me wondering if there is a way to do this with the scripting language used by the GECK? Have I missed something or is this functionality just not there?


Is there an alternative way to do this?

Link to comment
Share on other sites

There's no 'function' system for Geck scripting.
But some things you can do are:
1. A quest so you can just set stages (start game enabled and Allow repeated stages). As long as there are no objectives to display then it will just run silently. When you set a stage - the result script is your function code. Setting a quest stage has the added benefit that it is like a call from the script that called it. The calling script suspends itself to run the stage script, then returns - all in the same frame. Quest stages can call other stages and all execute in the same frame then it returns to the calling script.
2. Make a quest with a script that will run a section of code depending on a quest variable. The sections are your 'functions. Set the quest delay to .016. To call a function:
1. ResetQuest MyFunctionQuest
2. Set MyFunctionQuest.FunctionNumber to X
3. StartQuest MyFunctionQuest
When the section of code is done, it resets MyFunctionQuest.FunctionNumber to 0 and calls a stopquest on MyFunctionQuest.
3. Place an activator in a dummy cell and use 'Activate' on it to run the activation block for a section of code instead of a quest script like in #2. The activation block will run even if the cell isn't loaded.

Link to comment
Share on other sites

Guest Messenjah

I have a few questions.

 

On the first method, I could see how this might work, however, I don't really like having 'functions' called on as a number sequence. It just makes it feel a bit odd. However, I'm not really using quest stages for anything, so it may be the most optimal solution. My primary concern is that, will stages be able to go back to previous stages? I thought they could only progress to higher stages? From my experience, I usually had to use a controller quest outside of a quest in order to get it to repeat stages? IE: After you reach stage 100, you set a stage on the controller stage that executes code that will start the other quest stages over to get a quest to repeat itself. I need to be able to use functions over and over again, so associating them to stages would be a bad thing wouldn't it? As I couldn't for example, set the stage 10 function and then call on stage 5?

 

#2 method isn't bad, it is just a little sloppy to do it this way. I wasn't sure that just changing a variable would cause the script to run again?

 

#3 I thought of this. It's not a bad idea but I don't really like the idea of having my functions called on by physical objects within the game itself.

Link to comment
Share on other sites

For method one, that's why you have to set "Allow repeated stages" in the quest. This lets it repeat any stage whenever you want. It is a bit odd compared to a normal scripting language with functions, but once you get used to it it's not really that bad at all. I've made use of it A LOT in my mods to add functions for things that don't need to be in always processing object scripts.

 

Just remember that no matter what method you use, you'll also need to pass in your data values. So I usually have a whole block of variables in the quest script that is solely for passing data into my stages. When you want to call a 'function' you would do:

set funcQuest.iPassVar1 to 12
set funcQuest.iPassVar2 to 57
setStage funcQuest 23

Obviously your variable types, names, and values will be whatever needs to go in. In you stage script you would then need to pull those variables back out and set them to something locally, as some functions will not take the Quest.Variable method as a parameter. So then you get this in the stage script:

set iVar1 to funcQuest.iPassVar1
set iVar2 to funcQuest.iPassVar2

 

If you want examples of what can be done and how to do various things with stages as functions, check out my Vending Machines of the Wastes mod. I made extensive use of stage functions.

Link to comment
Share on other sites

#1

The "Allow repeated stages" check box will let you set any stage regardless of the previous stage. You could setstage 10 then 57 then 10 again, etc. Something to watch out for is 'GetStage'. This function only returns the highest stage number that has ever been set, regardless of the current stage. If you need to track the last stage that was called, you need to set a variable somewhere else to do it. And don't define any variables in the stage result scripts - they will overwrite the player script if you do.


#2

Setting a quest variable does not start the quest. You can use quest variables even if you never intend to start the quest. Setting a stage will start a quest, but I don't do that for this method.

The 'resetquest' will stop a quest if it's running and clear all it's variables to zero. Then you can set it's variables and start it, to run the 'function'. You can do this over and over as needed. I use this method a lot for menus and for when I need to stage a sequence of events with actors, using staged timers, where things are not going to be occurring in the same frame. I wouldn't use this method for a function that had to be called really frequently. I would use method 1 for that.
Link to comment
Share on other sites

Guest Messenjah

I'm not understanding what you mean by passing the data?

set funcQuest.iPassVar1 to 12
set funcQuest.iPassVar2 to 57
setStage funcQuest 23

So, is this on the quest script itself or is it on the whatever script is calling the function? For example, I call them most often from dialogue end scripts. If it is on the quest script, setting stages and values will just cause the quest script to default to these values whenever the script is run? If it is within a dialogue end script, wouldn't setting each value here defeat the entire purpose behind creating a function? I use functions in Skyrim as a SHORTCUT to execute complex bits of code by typing a single line whenever I need to run a specific batch of code together.

 

The only thing I want to have to type when I call on all of this code to run is:

setstage funcQuest to 10

This is the only line I want to write if I want to execute a batch of code or what Fallout defines "functions" as. This is what we should be calling on AS what Skyrim would define as a "function" in order to set all of our variables up.

 

 

lol, I think my brain is scrambled. :P

Link to comment
Share on other sites

A normal function call would be something like

 

functionName(int Var1, int Var2)

We can't do that. So you have to pass the variables from whatever you are calling them from into an intermediate step, and THEN you can use them from the stage script.

 

Rickerhk says not to set variables in stages, but I have done this in a TON of mods and never encountered an issue with anything. Project Nevada also does it, and thousands of people use it with no issue. I have heard/read that you shouldn't declare vars in stage scripts, but I have not encountered anything bad from doing it (and some things cannot be done any other way).

 

What you quoted is correct. You would need to set some quest vars from your dialogue, then set the stage, which grabs those variables from the intermediate quest storage, and uses them in its script, and then does something or returns a value back to a quest storage variable to be used by the rest of the dialogue script (if that was never finished)

 

One thing to keep in mind, and this helps me to think about, is that Fallout has a single script thread. All scripts ALWAYS process every single frame. As soon as you call SetStage, everything where you are suspends and goes to the stage, does what the stage is supposed to do, then comes back. Which is why we can use them as functions, because you can pass a value in, do something with it, then get it back.

Link to comment
Share on other sites

Guest Messenjah

Ugh, it really seams to me, from what I"m reading... that there really isn't any advantage at all to doing this.... maybe I'm not understanding what you mean?

 

What I'm getting at is this:

 

 

Normally when I write a dialogue end script.... it would go something like this:

set int01 to int01 + 1
set int02 to int02 + 1
PlayerRef.AddItem Caps 100

And so on....

 

In Skyrim.... I call a function as a shortcut to do all this in one quick swipe so that I don't have to write all of that code if I want to change these same variables and give the same reward from say another npc or for another quest.

 

What you are suggesting, involves me writing out this code inside the quest script.... then the quest stage..... then the dialogue end script... and setting these variables 3 different times? How would this make it easier? If I'm defining these things 2 or 3 times, it doesn't save any time that I can think of?

 

 

Maybe I'm not using Functions in Skyrim for what they are intended for? I'm using them as shortcuts so that I don't have to write several lines of code, every time I want to use it. WIth your method, I appear to be doing this anyway. :( At least to my understanding.

functionName(int Var1, int Var2)

This certainly isn't how I use functions in Skyrim. I just leave the brackets empty.

 

This is how I do it within the quest script:

MyFunction()

Int01 = 1
Int02 = 2
Int03 = 1
int04 = 15

EndFunction

Then I call it within the dialogue end script like so:

MyFunction()

I use this to AVOID ever useing any variables/integers/functions or other code within a dialogue end script. That way the only place I can screw up, is within the quest script itself, and that is where I must look to resolve any issues I may find.

 

What I'm trying to accomplish, is I want to be able to only type one line in the dialogue to run the function. If I'm setting the variables in each dialogue end script anway... I'm defeating the purpose of what I'm attempting to accomplish.

 

If I do it the way your suggesting... I have to look at each variable within the stage result script, the quest script, and each dialogue end script that I have written in order to check for bugs. This can double and even triple the possible bugs.

 

The only real advantage I see to creating a function as you suggest, is to create that subtle pause in order for that code to execute. :\

 

 

If I'm missing the point, please feel free to make a short tutorial on this in it's simplest form. Could you quickly type up an simple and short example by showing me how you would set up the quest script, stage result script, and end dialogue script that you use to call the function please?

 

The way I'm doing it right now:

 

QuestScript:

int GainAffection
int FavorPoints

My Result Script For Stage 5

set functQuest.GainAffection to functQuest.GainAffection + 1
set functQuest.FavorPoints to functQuest.FavorPoints + 1

My Dialogue End Script used to call the function:

SetStage functQuest 5

I'm headed for bed. Sorry to be such a pain but I'm not really sure we are on the same page?

Link to comment
Share on other sites

I was referring to traditional programming languages that use functions that take passed in values. Of course a function doesn't have to have values passed in, and can just perform a specific action.

 

If all you're wanting to do is do the same reward over and over again, with the same values, then you just need a simple stage to do that. Call the stage and you're done. That assumes though that the increment values are of course the same for all uses of that 'function'.

 

What you have there is fine. I was going into the more extreme uses of making functions.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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