Jump to content
Mattiewagg

[Student Thread] Treeaza - Matthiaswagg

Recommended Posts

Write a script that removes all items from a container when it is activated by someone in the player's follower faction (called CurrentFollowerFaction), OR the player themselves, placing it in a different container, and then spawns an item near the person who activated the chest (item of your choosing, could be a book, sword, NPC, whatever).

If you need help, feel free to ask.

Share this post


Link to post
Share on other sites
Scriptname RemoveItemScript extends ObjectReference

ObjectReference Property transferTo auto ; Where to store the items after transfer.
Faction Property currentFollowerFaction auto ; Player's followers.
MiscObject Property objectToPlace auto ; What we should spawn.

Actor Property PlayerREF auto ; The player.

Event OnActivate(ObjectReference akActionRef)
	if akActionRef as Actor ; Make sure they are an actor, so we don't have problems later.
		Actor akActorRef = akActionRef as Actor
		if akActorRef == PlayerREF || akActorRef.IsInFaction(currentFollowerFaction)
			RemoveAllItems(transferTo, true, true) ; Move the items.
			PlayerRef.PlaceAtMe(objectToPlace) ; Spawn the object.
		EndIf
	EndIf
EndEvent

 

 

I'm not sure if this is all correct; My compiler stopped working, and I haven't fixed it yet.  Also, I will be away for ~2 weeks on a camping trip, so I may not respond to posts in that time.

  • reaction_title_1 1

Share this post


Link to post
Share on other sites

I'm going to be away for a week or two as well, so perfect timing.

This is all good, you just done need to cast to actor and make another variable for it. Since only actors can be the player or in a faction, there's no need - ObjectReferences can turn into Actors as Actors EXTEND ObjectRefs. 

Tell me when you return.

Share this post


Link to post
Share on other sites

Done reading now.  Threading Anecdote:  When I had just started programming, I was watching a tutorial series on making a simple little platformer in Java.  Everything was going fine, and I was understanding most of it, so I tried to program the jump function myself.  After I found out that it didn't work, I watched to tutorial on jumping.  At the time, I didn't understand what they were doing, but now I have realized that they were creating a new thread every time the player jumped just to process it.  Logic.

  • reaction_title_1 1

Share this post


Link to post
Share on other sites

Threading is fun stuff! :P Actually, it's possible to make Papyrus use more than one thread at once, but it's quite complicated and not necessary for anything but the most complex functions. See Chesko's Frostfall. But, for example - it is quite code heavy and certain parts of it used to take up to 10 secs. With multithreading, it took 1. You can see the tutorials here, feel free to read them:

http://www.creationkit.com/Creating_Multithreaded_Skyrim_Mods

It's pretty interesting, but not required at all - you'll barely, if ever, use it in the usual scripting endeavours. Depends on what you go on to make, really.

Ill be posting the next lesson soon. Refresh my memory (I seem to be really forgetful the past couple of weeks) - are you interested in quest design too?

Share this post


Link to post
Share on other sites
Advanced Properties pt. 2
The information I have gathered is from the CK Wiki, fellow modders, and other sources. It does WORK but I'm no expert so I apologize if I get anything wrong.
 
IMPORTANT LINKS:
Property and Scriptname Flags - look at full properties
 
We'll be going over the more advanced parts of properties (and a bit about scriptnames).
 
First, we'll be talking about adding more than just "auto†to your scriptnames/properties. There are a few other flags you can have on your properties:
 
Hidden
Conditional
AutoReadOnly
 
These also can be added to your scriptname (after the extends ____ part):
scriptname ____ extends ______ [flag(s)]
For properties, you add flags:
____ Property ____ [flag(s)]
 
Hidden means that the property or script will not be visible within the CK. So, if you make a script called "mahScript†and make it a hidden script (Scriptname mahScript extends ObjectReference Hidden), you can't find that script from the CK. So if I click "Add†to add a new script and search for mahScript, that will not show up. It's hidden from the CK. You can still find the script in the folder relative to the Skyrim directory, and you can still reference hidden properties like you can from Part 1 of Advanced Properties.
 
This is automatically used for something like Papyrus fragments, which is code for dialogue, packages, auto-generated quest scripts, etc. as they all have completely random names and are mostly generated by the CK and not written.
 
Conditional on a script means that properties defined as Conditional within that Conditional script can have their values checked with a condition function (a condition function will be used a lot later - they are not script commands, but how you condition things in the CK like magic effects, spells, dialogue, and more. The particular one for a script is GetVMScriptVariable, but it won't work on ReferenceAlias scripts. For quest scripts, you have to use GetVMQuestVariable). If you define a script as conditional but none of it's properties as conditional, then they won't be able to be checked via those condition functions. If you define a property as conditional but not the script, then none of the conditional properties in the script can be checked. It has to be like so:
Scriptname conditionalScript extends WhateverYouWant Conditional
 
WhateverType Property conditionalProperty Auto Conditional
You can have more than one conditional property in a script, or just one. Only ones with the conditional flag will be checkable. When creating a property with "New Property†in the script properties box, you have checkboxes for properties to become hidden/conditional as well as for the script itself when making the script. You can use those or just tack it on/remove it in the script as you like.
 
Auto read only is much like a normal property (Auto), except it CANNOT be set. The value of an AutoReadOnly property can only be "gotâ€, not "set†or changed in any way shape or form:
Int Property autoReadOnlyProp AutoReadOnly
 
;event
     int x = autoReadOnlyProp; this works, you're "getting†the value and making x equal to it
     if (autoReadOnlyProp == 86); this works, you're checking if the value of the property is 86
          ;code
     endif
     autoReadOnlyProp = 99999; this will NOT work because you're not allowed to set your variable
;endevent
This will rarely be used - I myself have never used this, and it is unlikely you will ever need to in the average or even semi-complex script. However, if you happen upon an instance where you need a "constant†and unchangeable value for a property, this is what you would use. The initial value of the property is allowed. You cannot change it anywhere, however. And you can't change flags on the fly either so your property will always be the same.
 
==========
 
Now, this brings us to something more complex. Conditional and Hidden were both supplementary flags, which can be added to a property (or both added to a property). AutoReadOnly replaces Auto. So what exactly is "Auto†doing?
 
Auto is the simplest way to declare a property. It means that you can get the value of a property, AND set the value of the property. You can do this whenever you want, however you want. It's usually how you'll want a property used.
 
However, you can manually define your property as well. This means that you can completely control what happens when your property is set and got. So, you could say that propertyA CANNOT be set but it CAN be gotten (this is AutoReadOnly so you could just use that flag instead). Or, it could be set but not got. OR, and this is where it gets really powerful, you can completely define what happens when a property is "set†or "gotâ€. What value is actually got? IS a value even sent, depending on a variable? Perhaps setting a property actually sets the value to 2x what you said to set it to.
 
This isn't used incredibly often, and I haven't found just cause to use it yet. However, when you get into more complex scripting environments, it may be of tremendous use to you. It's another way Properties one-up variables - variables can't be manipulated in this fashion, or have flags. They're simpler, which is a downfall and a benefit.
 
Each Property actually has two little functions built into it. When you declare a property as Auto, this is what it's really saying:
int myValue = 0
int Property ValueProperty
  Function Set(int newValue)
      myValue = newValue
  EndFunction
  int Function Get()
    return myValue
  EndFunction
EndProperty
Two things to note: the first is that omitting one function or the other means that it can't be written to (if removing set - can't be set) or read, like AutoReadOnly vars, (if removing get - can't be got). Secondly, removing a Set function means you can't see the property in the editor and thus can't give it an initial value.
 
Something else is that you NEED to declare a variable that is the same type as your property, such as myValue, and reference that in your property. If you don't, there will be a compiler error. This variable should equal the initial value of your property. If you set the initial value in the editor to be different than the initial value of your internal variable, the initial value of your property will be the one set in the editor, UNTIL you Set your property.
 
So, we could make a Property that cannot be set and, when got, actually gives the value of itself + 5, like so:
int testValue = 0
int Property testProperty
  int Function Get()
    return myValue += 5
  EndFunction
EndProperty
 
Any property or local variable declared outside of events or functions can be called within your property functions. Functions can be called within your property functions. Unless you've only got a ReadOnly function (Get only), make sure you've got a variable like testValue/myValue referenced before. The name can be whatever.
 
However, you cannot declare anymore parameters for Get() or Set(). They absolutely MUST look like this in your property:
  Function Set(int newValue)
     ;stuff
  EndFunction
  int Function Get()
    ;stuff
  EndFunction
 
You'll get compiler errors if you do. 
 
These full properties CAN be called from other scripts, just like any other. (See Advanced Properties Part I for reference.) They can be any type of property.
 
I want you to write me one script with 4 different properties. Name them as you like. These should be Full Properties (the ones right after here). The 1st Full Property should be one that CANNOT be read, but only Set. The 2nd should return the negative version of the newValue when read, and when Set should add 3 to the value stated. The 3rd should only be readable, not writable. The 4th should be a Bool, readable and writable, with a normal write but when read it should return the opposite bool of what is currently is.
 
Then, paste the script here. We're nearing the end of scripting!

Share this post


Link to post
Share on other sites
Scriptname AdvPropScript extends ObjectReference

Int onlySetableVal
Int Property onlySetable
	Function Set(Int newValue)
		onlySetableVal = newValue
	endFunction
endProperty

Int TSPYVal
Int Property theSecondPropertyYay
	Function Set(Int newValue)
		TSPYval = newValue + 3
	endFunction
	
	Int Function Get()
		return -(TSPYval)
	endFunction
endProperty

Float onlyReadableVal
Float Property onlyReadable
	Float Function Get()
		return onlyReadableVal
	endFunction
endProperty

Bool strangeVal
Bool Property strange
	Function Set(Bool newValue)
		strangeVal = newValue
	endFunction
	
	Bool Function Get()
		return !strangeVal
	endFunction
endProperty

 

There's one of the stranger bits of code I've ever written.

  • reaction_title_1 1

Share this post


Link to post
Share on other sites

Apologies for any typos that there may be, wrote on phone just now.

Update Functions and Events

As you have seen before (I think, can provide sample code of in use if not), you can call a function (RegisterForSingleUpdate), filling the parameter with the time in seconds that you want an update to be called. In that # of seconds, an event WILL be called which you can use like any other - OnUpdate.

There are a LOT of updates you can register for.

http://www.creationkit.com/RegisterForSingleUpdate_-_Form With the event called being OnUpdate (no parameters for any of these events). This will call ONE OnUpdate event within the script in the interval (FLOAT) of RL seconds you set as the function parameter.

http://www.creationkit.com/RegisterForSingleUpdateGameTime_-_Form With the event being OnUpdateGameTime. This will call ONE OnUpdateGameTime event within the script in the interval (FLOAT) of in-game hours you set as the function parameter. I.e 24.0 is one ingame day.

http://www.creationkit.com/RegisterForUpdate_-_Form With the event OnUpdate. This will keep calling OnUpdate events every interval (FLOAT) of RL seconds you set as the function parameter, until you http://www.creationkit.com/UnregisterForUpdate_-_FormThis function and the following can cause issues (Esp. This one). Read WHY.

http://www.creationkit.com/RegisterForUpdateGameTime_-_Form With the event OnUpdateGameTime. This will keep calling OnUpdateGameTime every interval (FLOAT) of in-game hours you set as the function parameter, until you http://www.creationkit.com/UnregisterForUpdateGameTime_-_Form.

As you can see, some of these functions share the same event. So if you called a single update twice in a script for different reasons, the same event would be called twice (at the appropriate times). You'd be able to differentiate between what was supposed to be happening with some simple variable use though.

You can also call an update inter-script. In Advanced Properties I, I showed the two methods of accessing another script. I mentioned how you can call a function in another script. This doesn't just include custom functions - though not all functions can be called in a script because they're meant to be called on a specific reference, you can do:

(Self as OtherScriptName).RegisterForSingleUpdate(30.0)
OtherScriptName Property OtherScr Auto
OtherScr.RegisterForUpdateGameTime(21.5)

If you register for an update, other code will run event after it's been registered. It doesn't block other parts of the script at all, unlike latent functions.

Latent Functions

There are several latent functions in the game, and I won't go over all of them.

But a latent function performs an action (like any other function) but then PAUSES the entire script its in until done. This means that until a latent function is finished, NO OTHER CODE in the script will run.

The main latent function is http://www.creationkit.com/Wait_-_Utility

You can find a full list here.

Now, sometimes you'll want to use something like Wait because you want to pause the entire script and do nothing until say, 3 seconds have passed after a certain action. Or, because Wait doesn't count time spent in game-pausing menus, you could wait for a fraction of a second so your code won't run until the PC is out of a menu.

It's okay to use as long as you are aware of what it does, and sure that you want it to be doing that.

Share this post


Link to post
Share on other sites

Oh, I know that feeling.  You know that thing on Android phones where you can slide from letter to letter to form words?  I used to try to say "yay", and my phone would correct it to "yeasty".

That must have been awkward.

"You get 100$!"

"YEASTY!"

Is there anything else you feel I haven't covered before we do a few practice scripts and such?

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

×