Jump to content

Help with Papyrus Scripting


AzerDraco

Recommended Posts

I need some assistance in understanding the Papyrus Scripting syntax. I am a novice programmer in Java, so the basic idea of Object Oriented Programming is pretty clear. I just need a bit of assistance beyond what the CK Wiki has.

 

I am trying to set up bounding boxes as trigger areas to affect the area as the player (and NPCs once I learn to Navmesh a little better) move through. I am wanting to make portcullis gates open as the actor approaches and close again once they walk through and leave the trigger box.

 

Once I get that situation resolved so that the map is running smoothly, then I'd like to tie the same trigger activation into the lighting areas in the level (increase the light emanating as the actor approaches, then reduce it as they leave the area.

 

I understand that this is a LOT of scripting, and I'd really like to actually understand Papyrus as a language BEFORE I start blundering around writing scripts. There is nothing worse than a needlessly bloated script that slows the game to a crawl.

 

Basically, I am looking for a kind of "Papyrus 101" crash course. I have read through a lot of the CK Wiki regarding Papyrus, and I have yet to find a page that explains exactly how to refer to the objects as they are "categorized" when actually creating the physical map.

 

Any assistance is greatly appreciated, but please keep it constructive. Replies to this post in the vein of "L2Mod dumbass" will be laughed at and subsequently ignored as the immature comments that they are. I am looking for simple and helpful explanations about a highly technical and structured scripting language (even if it is structured english).

Link to comment
Share on other sites

to refer to an object on the map, you need to set up a "property" for that object. A property is like a variable, but you can define what a property holds outside of the script, and you need to do that.

 

So if you want to point to an object in your world, such as a rock, you need to create a property of the type "ObjectReference":

ObjectReference Property MyRockREF Auto

Then you can treat "MyRockREF" as if it were your literal rock reference, and use it in your script. You just have to remember to setup the property (outside of the script) to refer to your reference of the rock in the world, in the properties window.

Link to comment
Share on other sites

This should do it somewhat. There is no scripted way to increase light emission through scripts that I know of. The only workaround would be to stack multiple weaker lights on top of each other and then enable them one by one as the player gets closer. There wouldn't be a smooth transition though.


ObjectReference[] Property Lights auto

Event OnTriggerEnter(ObjectReference Ref)
     If(Ref != game.getPlayer())
          return
     endif

     int i = 0
     while i<Lights.length
          Lights.enable()
     endWhile

     self.getLinkedRef().SetOpen(true);  Not sure on this one though. Also make sure to set your portcullis as a linked ref to the trigger

EndEvent

Event OnTriggerLeave(ObjectReference Ref)
     If(Ref != game.getPlayer())
          return
     endif

     int i = 0
     while i<Lights.length
          Lights.disable()
     endWhile

     self.getLinkedRef().SetOpen(false);  Not sure on this one though. Also make sure to set your portcullis as a linked ref to the trigger
EndEvent
Edited by Sjogga
Link to comment
Share on other sites

to refer to an object on the map, you need to set up a "property" for that object. A property is like a variable, but you can define what a property holds outside of the script, and you need to do that.

 

So if you want to point to an object in your world, such as a rock, you need to create a property of the type "ObjectReference":

ObjectReference Property MyRockREF Auto

Then you can treat "MyRockREF" as if it were your literal rock reference, and use it in your script. You just have to remember to setup the property (outside of the script) to refer to your reference of the rock in the world, in the properties window.

 

Thanks, rjhelms. I read that myself, but where I get hazy is how I set the property to indicate a specific object.

Basically, how do I get "MyRockRef" to point to "MyRock001"?

 

Am I over-analyzing the code, here? Does the script "know" which object to use because I have linked the objects together through "Activate Parents"?

 

In my specific case, my reference would be TrapLinker (0200a30a), which links 9 individual instances of 'PortGatePoleDwemer' allowing a single activation to be sent to all of them simultaneously. I figured that this would make the scripting a little less bulky, as I am sending a single Activation event instead of multiple ones. I have four gates, each off their own trigger boxes and TrapLinker combos.

 

I know that I have them linked correctly, as I can switch the Trigger box to "Player Activation", and am then able to send the activation manually. It's the automation of that Activation that has got me scratching my head.

 

 

This should do it somewhat. There is no scripted way to increase light emission through scripts that I know of. The only workaround would be to stack multiple weaker lights on top of each other and then enable them one by one as the player gets closer. There wouldn't be a smooth transition though.


ObjectReference[] Property Lights auto

Event OnTriggerEnter(ObjectReference Ref)
     If(Ref != game.getPlayer())
          return
     endif

     int i = 0
     while i<Lights.length
          Lights.enable()
     endWhile

     self.getLinkedRef().SetOpen(true);  Not sure on this one though. Also make sure to set your portcullis as a linked ref to the trigger

EndEvent

Event OnTriggerLeave(ObjectReference Ref)
     If(Ref != game.getPlayer())
          return
     endif

     int i = 0
     while i<Lights.length
          Lights.disable()
     endWhile

     self.getLinkedRef().SetOpen(false);  Not sure on this one though. Also make sure to set your portcullis as a linked ref to the trigger
EndEvent

Sjogga, thanks for the information.

 

I'm not looking so much for brightness/dimness based on distance (though it would be AWESOME if it could be done without serious script overkill).

 

What I am planning is to utilize the different lighting furnishings (such as "DweWallSconce01" and "DweWallSconce01On"), with the intent of hiding the unlit lamp and enabling both the lit lamp and the lighting effect when entering the area. When leaving, the exact opposite happens, leaving (hopefully) an unlit lamp. Thus it would appear that the lamps "ignite" in response to the presence of an inhabitant...

 

Thanks for this bit of code, though. I'll definitely save this and see what I can use it for later.

Link to comment
Share on other sites

You just need to set the value of the property, outside of the script, in the properties window, to your specific reference (TrapLinker). It's that simple. Then you just run the "activate" function in your script. Here is a basic example:

ObjectReference Property TrapLinkProp Auto

Event OnTriggerEnter(ObjectReference akActorREF)

If (akActorREF == Game.GetPlayer())
TrapLinkProp.Activate(Game.GetPlayer())
Endif

EndEvent

Do you know what I mean by the "property window"? In other words, do you know how to set the value of the property outside of the script?

Link to comment
Share on other sites

You just need to set the value of the property, outside of the script, in the properties window, to your specific reference (TrapLinker). It's that simple. Then you just run the "activate" function in your script. Here is a basic example:

ObjectReference Property TrapLinkProp Auto

Event OnTriggerEnter(ObjectReference akActorREF)

If (akActorREF == Game.GetPlayer())
TrapLinkProp.Activate(Game.GetPlayer())
Endif

EndEvent

Do you know what I mean by the "property window"? In other words, do you know how to set the value of the property outside of the script?

If I am reading http://www.creationkit.com/Reference correctly, you are referring to the window that shows all properties of the object, including 3D data and other reference data. (Right click and select "Edit", or just double click the object)

 

If that's the case, then I would assume that the "Reference Editor ID" field would be where I set up the "nickname" for an individual item.

As an example, the TrapLink controlling the North Gate on my map could be named "NorthGateTrapLink".

I then utilize that as my reference name in the header line:

 

ObjectReference Property NorthGateTrapLink Auto

 

If I'm wrong, please correct me.

Link to comment
Share on other sites

No, I mean: in the new activator/trigger window itself, on the right hand side of the window where you select your scripts, there is a button that says "properties".

 

For example, I found this image of google images, showing a "book" form: http://www.rarityguide.com/articles/content_images/1/skyrim/skyrimcreationkitbookinterf.jpg

 

You see in the scripts section of the form there are 3 buttons: add, remove and properties? Well, if you were going to add a script to a book, you would click the properties button after adding or creating your script, and then you would be faced with the properties window, where you can assign values to the properties declared in your script.

 

If you create a new trigger-box, there will be a "scripts" section, with the same 3 boxes.

 

Does that make sense?

Link to comment
Share on other sites

Okay. So I have a trigger "defaultActivateSelfTRIG" used in the WarehouseAmbushes prefab for a draugr ambush.

 

I double click on it and get the "Reference" window. I click on the "Edit Base" button and it opens the "Activator" window.

At the far right hand side is an area labeled "Scripts" with those three buttons you stated.

I select the Script and click "Properties" and that will allow me to reference the individual items.

 

Awesome. One major obstacle overcome. I know exactly where to go to "educate" my script as to the objects it is supposed to be acting upon.

 

Now for the second half of the problem: The actual syntax of the code.

Is Papyrus as modular as Java in terms of reusing code?

 

For example, utilizing the pseudocode:

 

IF ActorEnteringTrigger is Actor(Player)

THEN (Create a loop here to act as a timer. A Loop is utilized to allow for premature termination if conditions are not met.)

count < delay AND ActorWithinTrigger IS true

(End the loop once the delay time has been reached)

SendActivateEvent TrapLinkGateNorth

ELSE END EVENT

 

Without going into too much detail on the specifics, how do I make this a "self-contained script" that I can reuse this script for each of my gates?

Do I simply omit the SET so that it becomes read-only to any other script that MIGHT have a reference to it?

 

Thanks for all the help on this, rjhelms84 .... Once this thing is finished and working for Vanilla Skyrim, I'm planning on publishing it and there WILL be an honorable mention for your assistance.

Link to comment
Share on other sites

Yeah, you can reuse the script by just selecting it from the list when you press the "add script" button on subsequent activators.

 

But of course you will need to condition your final result with an if statement, so the script knows which reference to activate based on which trigger has been entered. You'll have to browse through the functions to see what you could use. But if there's nothing obvious and straightforward to use, you could run a bit of an equation using the getdistance function, and calculate the player's distance from each trigger ref, and check which is the smallest value distance.

 

though if that's a pain, just copy and paste new versions of the script and alter them. Or maybe there is a simple function that will return the trigger ref that is running the script, I'm not sure as I'm away from the PC.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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