Jump to content
Mattiewagg

[Student Thread] Paulibobo - Matthiaswagg

Recommended Posts

Lesson on Functions and Events

Resources:

All About Functions (highly recommend you read, as I'm going to have the functions part of this shorter since this is very extensive + examples and written by myself before)

Events Reference

Functions

As you probably know by now, functions make up a lot of your scripts. They make stuff happen, for the most part. Moving things, changing things, getting values, etc. Those are ALL functions. 

A function consists of 5 parts:

Type Function FunctionName(Parameters)
EndFunction

The function type is used for functions that return values, not functions that only DO things and don't return values (if you have one that returns values and does stuff, it should have a function type). As you know, Show is a returning function. It returns an integer - the button chosen. Thus, it is an Int function.  If it weren't a native function (to be explained later), then it's function declaration would have looked like this:

Int Function Show(float afArg1 = 0, float afArg2 = 0, float afArg3 = 0, float afArg4 = 0, float afArg5 = 0, float afArg6 = 0, float afArg7 = 0, float afArg8 = 0, float afArg9 = 0)
     ;what the function does and returns
EndFunction

The function part is just a function declaration, telling the code that THIS is a function. It's just like the "Property" part of property declarations. The FunctionName part is just like the PropertyName. The Parameters are variables that are passed into the function - so you can have an Actor parameter, Int parameter, etc. This parameter can be used within the code of the function, no matter WHERE you call it from, unlike with global functions (discussed later); which can only use the parameters and nothing from within the script they were declared in. So if I have the function HealthierActor, and it compares the healths of two actors, then I'd have to pass in the two actors as parameters:

Function HealthierActor(Actor actorA, Actor actorB); parameters can be named whatever you like
     If actorA.GetActorValue("Health") > actorB.GetActorValue("Health")
          ;whatever code you want here
     ElseIf actorA.GetActorValue("Health") < actorB.GetActorValue("Health")
          ;whatever code you want here
     Else; is equal
          ;whatever code you want here
     EndIf
EndFunction

And then, you must close it off with an EndFunction, just like you would close off an event with EndEvent.

Now let's talk about Return values. You can have your function Return a value, which you can then use. You could assign an integer to the return value of a function that returns an int (or float, or bool, for that matter - see Casting though we'll talk more about it later if you want). Examples of Returning functions are functions like Game.GetPlayer(), which returns the Actor of the player so you can easily use the player in a script. You must have a function type if you want your function to return a value. So, while this will NOT work:

Function ThisIsAFunction()
    Return 10 + 10
    
EndFunction 

But this WILL:

Int Function ThisIsAFunction()
    Return 10 + 10
    
EndFunction 

You can also return the value of a parameter, global, variable declared within a function, or a property within a script (IF it is not a global function).

Read the Resource All About Functions for more examples, and info on Native and Global functions. 

Note that if you have a convenience function which is just there so you don't have to retype code a lot, it doesn't mean the code isn't still happening. If you call a function with 30 lines of code in it 100 times in a script, that's still 3000 lines of code being called (not necessarily a bad thing). It's just you typing out only 30ish lines. So it's not more performance friendly, but it's also not less so. It's the same as if you had typed out all the lines, except the file size is smaller and you don't have to type as much.

Events

Events are a bit simpler than functions. As I've said before, they're called when an event in the game happens. They often, but not always, include parameters. Parameters are variables sent along with the event, which you can manipulate within that event. (If you want to use a parameter throughout a script and not just in the event, then you can assign the value of one variable to the value of a parameter.) Events look like this:

Event EventName(Parameter)
EndEvent

There's not a much that you don't already know about events, to be honest. If you have any questions about them, feel free to ask. There are a few exceptions/things to note, however:

- Don't pile up too much in an OnInit event. It can overload it. It's a rather fragile event, though I know of no others like it. If there's more than a few function/code being called in there, use a RegisterForSingleUpdate(0.1) and then put all that code in the OnUpdate event.

- You can call an event directly. So, you could just call OnUpdate() like it were a function, rather than RegisterForSingleUpdate, if you wanted. Or, you could call any other event and pass in it's parameters. Etc. I've not experimented with this much but I've heard from others more experienced than I, that it is possible.

That's all I can think of for now. If you have any questions whatsoever, want me to clarify on anything, etc. don't hesitate to ask. :D

Also, I'll probably have you be making your own first script next, but if you'd prefer to have a lesson on say, Casting (how a Boolean turns into an Integer, etc.) or on Advanced Properties (accessing properties from other scripts, properties that can be set but not "got" - value of the property gotten) then we could do that instead. Whichever you prefer. We'd end up doing those lessons later on anyway and then making another or improving your first script to use those concepts. After that we'll do Arrays/Formlists and maybe a few other lessons on advanced concepts with you creating scripts scattered in between.

EDIT: Don't ask me why I used that color. That yellow is... not easy on the eyes. Sorry.

Edited by Matthiaswagg

Share this post


Link to post
Share on other sites

Ok, I think I got it! So first I would prefer to create a Script,  we can have further lessons on Castings and Advanced Propreties later. What do you suggest? I don't want something to basic... What about maybe a door where you have to solve a puzzle with butons chains and levers to get through? Like, if you pull the right ones it opens, Else you get killed/hit by a trap. I am working on a dungeon and that would be a cool addition to it!

If you had somethng else in mind, please tell me about it! 

Edited by Paulibobo

Share this post


Link to post
Share on other sites

Ok, I think I got it! So first I would prefer to create a Script,  we can have further lessons on Castings and Advanced Propreties later. What do you suggest? I don't want something to basic... What about maybe a door where you have to solve a puzzle with butons chains and levers to get through? Like, if you pull the right ones it opens, Else you get killed/hit by a trap. I am working on a dungeon and that would be a cool addition to it!

If you had somethng else in mind, please tell me about it! 

Well, that would require a script on each lever/chain, but it IS entirely possible. I even have a thread bookmarked with a script for it.

If you'd like to try it, go ahead. I will give a few hints, as it's your first script:

You should use a Global to track the value of what has currently been chosen is, which is property type GlobalVariable. (Create one by going to Miscellaneous>Global, right click, make sure it is NOT constant and is short, give it an EditorID you like,) You could also use a property in this case, but that requires Advanced Properties and wouldn't necessarily be prudent in this situation anyway.

A Global has special functions related to it to Set and Get it's values, rather than just = and direct value "getting" access. We'll go over this in Casting later, but the value of a global should be a float (decimal) value, both Getting and Setting. So if you intended to SetValue to 1 use 1.0 instead.

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

This is a more complex script, and will require the use of a few properties. At some point in the script, you will need to have the door be opened. This can be done using Activate

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

I could provide more hints, and I will if you want more. However, you seem to be interested in trying out a more complex script on your own, so I'll back off unless you need more help.

The Creation Kit Wiki is your friend, and I am happy to answer any questions you have. Unless you specifically ask for a hint or just can't figure it out and want to see what the script should be and have me walk you through it, for the most part I'll answer your question in a more "guided" manner so I don't just straight up give you the answer.

Share this post


Link to post
Share on other sites

Ok, I am starting to get an idea of what I am going to do. The plan is that there are 9 levers, and the door opens if you pull three of them. If you pull any of the wrong ones and try to open the doors you get hit with a spell or arrows or something. I am thinking about the script, and there are two options I thouht of:

1-When you activate the door, it checks which levers are active and which arent. If any of the wrong ones are, it activates a trap. Else, the door opens. I guess I would have to create a srcipt for the door but I am not sure how to make it diferentiate between the levers.

2-Every right lever you pull adds 1 to your count. Every wrong one subtracts one. The door only opens if your count is three, which means it'll only open if you only have the right ones.  This creating three scripts. One for the wrong levers, one for the right ones, and a big script fot the door which all those other scripts relate to. 

I have some questions: Does this make any sense?

Which option would you go with.

Share this post


Link to post
Share on other sites

Ok, I am starting to get an idea of what I am going to do. The plan is that there are 9 levers, and the door opens if you pull three of them. If you pull any of the wrong ones and try to open the doors you get hit with a spell or arrows or something. I am thinking about the script, and there are two options I thouht of:

1-When you activate the door, it checks which levers are active and which arent. If any of the wrong ones are, it activates a trap. Else, the door opens. I guess I would have to create a srcipt for the door but I am not sure how to make it diferentiate between the levers.

2-Every right lever you pull adds 1 to your count. Every wrong one subtracts one. The door only opens if your count is three, which means it'll only open if you only have the right ones.  This creating three scripts. One for the wrong levers, one for the right ones, and a big script fot the door which all those other scripts relate to. 

I have some questions: Does this make any sense?

Which option would you go with.

Ah, okay. So you have to pull 3 in the right order. I was under the impression you had all of them necessary to be pulled.

More like the second, but rather than subtracting one, you set to 0. For the right ones, you could add 1 to it depending on which have been pulled already (I can let you figure out how to do that if needed). If the value is 3 for the right lever (the 3rd), then you just use Activate to open the door. No need for a script on the door.

You can reuse scripts and just change properties BTW. You shouldn't need too many scripts.

Share this post


Link to post
Share on other sites

What would be more efficient, three booleans of 0/1 or one int of 0-3?

Pauli don't read unless you want) hints. :P

The integer. But we're not using an integer. We're using a global, which is a float. This will allow Pauli to access the value from all scripts, and change it. So, if Lever1 is pressed and no other levers have been pressed, set Global to 1. If lever 3 is then pressed and global is not equal to the proper number (you can use an integer property so you only need two scriots and can just reuse the "good" lever script and change properties), then set it back to 0. DEFINITELY/ an integer, basically.

Share this post


Link to post
Share on other sites

I didn't mean tou have to pull them in any particuallar order, only the right three, and if any of the others are pulled, nothing happens. I just want to make sure that of the wrong ones (or not all the right ones) are pulled the door won't open. That's why i came up wit the count idea.

That works then. Your 2nd method should work just fine. There is a way to "mod" (+= is the method for counting up a property or variable, it's a different method for Globals, using a function) a global. I recommend looking for it on the CK Wiki.

And I'll leave the rest to you. So yeah, your second method should work. Just use a global, and figure out the structure of things.

No door script is needed. Look at the Activate link I gave you. If the door is locked, there's also a function to unlock which you can find if needed. And if Activate isn't working you can try SetOpen. You can find all these functions on the CK wiki if you search.

Share this post


Link to post
Share on other sites

What would be more efficient, three booleans of 0/1 or one int of 0-3?

Pauli don't read unless you want) hints. :P

The integer. But we're not using an integer. We're using a global, which is a float. This will allow Pauli to access the value from all scripts, and change it. So, if Lever1 is pressed and no other levers have been pressed, set Global to 1. If lever 3 is then pressed and global is not equal to the proper number (you can use an integer property so you only need two scriots and can just reuse the "good" lever script and change properties), then set it back to 0. DEFINITELY/ an integer, basically.

Why not just use an integer and set the levers up as akAcktionRef? So you can just use a single script instead of 4.

Share this post


Link to post
Share on other sites

What would be more efficient, three booleans of 0/1 or one int of 0-3?

Pauli don't read unless you want) hints. :P

The integer. But we're not using an integer. We're using a global, which is a float. This will allow Pauli to access the value from all scripts, and change it. So, if Lever1 is pressed and no other levers have been pressed, set Global to 1. If lever 3 is then pressed and global is not equal to the proper number (you can use an integer property so you only need two scriots and can just reuse the "good" lever script and change properties), then set it back to 0. DEFINITELY/ an integer, basically.

Why not just use an integer and set the levers up as akAcktionRef? So you can just use a single script instead of 4.

:P

Okay, you'll have to explain better. You can't use an integer, because globals are float values no matter what. You COULD use a property but it would be much harder to set up, and more tedious. And why would you be able to use akActionRef? There's only one akActionRef and I'm not sure when you'd receive it. In which event, I mean.

Sorry Pauli... ;)

Share this post


Link to post
Share on other sites

What would be more efficient, three booleans of 0/1 or one int of 0-3?

Pauli don't read unless you want) hints. :P

The integer. But we're not using an integer. We're using a global, which is a float. This will allow Pauli to access the value from all scripts, and change it. So, if Lever1 is pressed and no other levers have been pressed, set Global to 1. If lever 3 is then pressed and global is not equal to the proper number (you can use an integer property so you only need two scriots and can just reuse the "good" lever script and change properties), then set it back to 0. DEFINITELY/ an integer, basically.

Why not just use an integer and set the levers up as akAcktionRef? So you can just use a single script instead of 4.

:P

Okay, you'll have to explain better. You can't use an integer, because globals are float values no matter what. You COULD use a property but it would be much harder to set up, and more tedious. And why would you be able to use akActionRef? There's only one akActionRef and I'm not sure when you'd receive it. In which event, I mean.

Sorry Pauli... ;)

event onActivate (akActionRef)

Share this post


Link to post
Share on other sites

What would be more efficient, three booleans of 0/1 or one int of 0-3?

Pauli don't read unless you want) hints. :P

The integer. But we're not using an integer. We're using a global, which is a float. This will allow Pauli to access the value from all scripts, and change it. So, if Lever1 is pressed and no other levers have been pressed, set Global to 1. If lever 3 is then pressed and global is not equal to the proper number (you can use an integer property so you only need two scriots and can just reuse the "good" lever script and change properties), then set it back to 0. DEFINITELY/ an integer, basically.

Why not just use an integer and set the levers up as akAcktionRef? So you can just use a single script instead of 4.

:P

Okay, you'll have to explain better. You can't use an integer, because globals are float values no matter what. You COULD use a property but it would be much harder to set up, and more tedious. And why would you be able to use akActionRef? There's only one akActionRef and I'm not sure when you'd receive it. In which event, I mean.

Sorry Pauli... ;)

event onActivate (akActionRef)

The akActionRef is the player. That wouldn't help, I'm afraid. We'll be using OnActivate to check the value of whether or not the levers have been activated, but you need a global to check which have been activated thus far. 

Share this post


Link to post
Share on other sites

One question. So I make it so that the right levers increase the count and the wrong ones decrease it, but how do I make it so that when it's at 3 it opens the door and when not you ge hit by a spell? I was thinking about placing a script on the door so that when it was activated it would check if the count was 3; If it was it'd oen, if not you would get hit by a spell. Whithout a script on the door I don't think I can do that.

Share this post


Link to post
Share on other sites

Ok, here is the Script I have made so far for the first right lever. What do you think? PMRightLever is the name of the script, the Global is OpenSesame. Tell me if I did anything wrong, but now I think what i have to do is make the second lever check if the Value of OpenSesame is 1 and if it is set it to 2, and the same for the thrid only it sets it from 2 to 3. Then I was thinking about putting a script on te gate so that if  OpenSesame is 3 it opens, else you get hit by a spell. The wrong ones i'll just make the same script but with OpenSesame.SetValue(0.0) instead. Does this make any sense?

 
Scriptname PMRightLever extends ObjectReference
GlobalVariable Property OpenSesame auto
float OpenSesame
Event OnActivate (ObjectReference akActionRef)
OpenSesame.SetValue(1.0) 
EndEvent
 
 
PS: I wanted to put the script in a spoiler but I don't know how, could you please explain that to me?

Share this post


Link to post
Share on other sites

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

×