Jump to content

Few question about papyrus


0x400000

Recommended Posts

Hello! I'm pretty new to Fallout modding or papyrus modding in general.

But I'm familiar with C# and C++.

I would glad if someone could help me with these questions:

As I understood, Form is a basic form of any object. ObjectReference is a ???. Actor is a player's entity/AI entity.

Are statements above correct? If not, please correct me.

 

I'm struggling to understand how and when game actually loads scripts. For example we have this code:

Scriptname MyTriggerBoxScript extends ObjectReference
 
Quest Property MyQuest Auto
Int Property StageToSet Auto
 
Event OnTriggerEnter(ObjectReference akActionRef)
    If akActionRef == Game.GetPlayer()
        MyQuest.SetStage(StageToSet)
    EndIf
 
EndEvent

(It's from tutorial page)

 

My questions are:

 

If we extend ObjectReference that means that game will automaticly load it up? If yes, then when it will be loaded and activated?

When OnTriggerEnter will be called? When player enters ANY trigger in-game or one specific?

 

And my last question: is it possible to look up ALL entities which loaded (even disabled) in the world and iterate them?

 

-Edited:

 

P.S. Is it possible to hook a function in papyrus?

Edited by 0x400000
Link to comment
Share on other sites

These are sensible questions and there is no straightforward 101 description (that I have found). Some quick intro thoughts:

 

Everything starts as a form at design time. Forms can be configured as Actors, Weapons, Ammo, Activators, Furniture, FormLists etc etc, many of which can have scripts directly attached to them.

 

They are instantiated in the run-time world to become object references which inherit scripts from the parent form, or can have them directly attached:

 

1. Manually dragging forms into the render window. These are loaded when the game loads your mod so scripts can fire, but 3d is only loaded when the cell your stuff is placed in loads.

 

2. Spawning forms in a Quest alias fill type (quest aliases can also have scripts attached). These are filled when the quest starts, or;

 

3. Spawning forms in a Quest attached script with PlaceAtMe & MoveTo & etc.

 

To produce manageable stuff try and hang as much as you can off of a Quest (even though you may not be creating an actual quest) rather than create stacks of isolated objects with individual scripts and fragments.

Edited by SKK50
Link to comment
Share on other sites

I'm going to try not to repeat everything SKK50 just said, it's very accurate.

 

As I understood, Form is a basic form of any object. ObjectReference is a ???. Actor is a player's entity/AI entity.

Are statements above correct? If not, please correct me.

The base of a papyrus object is ScriptObject. Though Form would be the base of any game object. In most cases the method .GetBaseObject() which is typically used on an ObjectReference will give you the base as a raw. It must then be cast as the type you expect to be dealing with. See https://www.creationkit.com/index.php?title=GetBaseObject_-_ObjectReference

 

An ObjectReference is as its name sounds, a specific instance of an object. So if you had a container chest that was placed in the world, the base would be a container. The ObjectReference is then the specific instance of that container. I suppose you could think of it in C++ terms as the base class vs the instantiated object of that class.

 

Actor is a more special type of an ObjectReference as it deals with character type entities whether it be player or AI. It would be any type of character be it a creature or humanoid. The game makes no distinction in that respect. That's what the particulars of the Actor properties related to Race, Sex, etc are for.

I'm struggling to understand how and when game actually loads scripts. For example we have this code:

Scriptname MyTriggerBoxScript extends ObjectReference
 
Quest Property MyQuest Auto
Int Property StageToSet Auto
 
Event OnTriggerEnter(ObjectReference akActionRef)
    If akActionRef == Game.GetPlayer()
        MyQuest.SetStage(StageToSet)
    EndIf
 
EndEvent
(It's from tutorial page)

 

My questions are:

 

If we extend ObjectReference that means that game will automaticly load it up? If yes, then when it will be loaded and activated?

When OnTriggerEnter will be called? When player enters ANY trigger in-game or one specific?

 

This gets a bit technical but it seems that's what you're looking for. Scripts themselves must be placed on something to get instantiated. Nothing gets auto loaded just by making a script. You can attach it to most base object types (except statics, trees, grass, maybe a few others). Then when the base is instantiated as an ObjectReference the script is instanced to that object. As SKK50 just mentioned base objects dragged into the render window will create an ObjectReference. The engine will create that reference an instantiate the script as soon as the game loads. However not all of the creation functions and events will fire immediately until the first time the 3D is loaded. As SKK50 also suggested you can attach to a quest. In those cases the instance of the script is created as soon as the quest from the plugin is made. Even if the quest is not started. The same goes for scripts attached to aliases. The events for such scripts will not fire until the appropriate time.

 

In the script you exampled, if the script is properly attached to an activator base, and then that is created in the game world as an activator trigger box, then the event you asked about OnTriggerEnter will be called any time an ObjectReference enters the trigger box covered area. The if statement, as it should be obvious, is there to ensure that the script only takes further action if the ObjectReference that entered the trigger area is the player. This is generally desired behavior, and in most cases you would need/want some sort of check to ensure only the thing you want to activate the triggers is actually activating it.

 

Regarding the last part of your question there the event only applies to that script on that instance of the object. Not all trigger boxes. Each object gets its own instances of scripts and they must be attached either per base or per ObjectReference.

 

Something I haven't mentioned yet is that you don't actually have to place scripts on the base object. You can place them on ObjectReferences in the render window directly. In practice this generally isn't desired behavior as you'd usually want the script on all instances of an object. There are exceptions of course, such as if you used the 10mm gun base and placed it in the world. But then renamed that instance of the gun and wanted a special script to fire when you picked it up. Then you would put the script on the ObjectReference instead of the base object. Then the script will only ever be instantiated on that one instance of the gun.

And my last question: is it possible to look up ALL entities which loaded (even disabled) in the world and iterate them?

I can't think of any sane reason you would want to try and do that. That being said, basically no. There are 2 functions that might get you close to what you might be trying to do:

FindAllReferencesOfType - https://www.creationkit.com/fallout4/index.php?title=FindAllReferencesOfType_-_ObjectReference

FindAllReferencesWithKeyword - https://www.creationkit.com/fallout4/index.php?title=FindAllReferencesWithKeyword_-_ObjectReference

-Edited:

 

P.S. Is it possible to hook a function in papyrus?

Probably not in the way you're thinking. There is a function RegisterForRemoteEvent that allows you to ask the engine to notify your script of a specific event that will fire on a different object. See https://www.creationkit.com/fallout4/index.php?title=RegisterForRemoteEvent_-_ScriptObject

 

I can't think of any quick examples of why you might want to use that but there are many. That's the only real way to "hook" anything remote that isn't your script or the object it is attached to itself.

 

Some other relevant links I think you might find useful related to programming in papyrus

 

Persistence https://www.creationkit.com/fallout4/index.php?title=Persistence_(Papyrus)

Save File Notes for Papyrus https://www.creationkit.com/fallout4/index.php?title=Save_File_Notes_(Papyrus)

Link to comment
Share on other sites

Wow let this serve as a reference for everyone else. Should pin this as Papyrus 101 or something.

 

Just wanted to touch on what BnF said about registering for remote events, a good use for this is to listen to certain quests for stage changes. I don't know what idea your working on, but I wanted to mention it because that is my favorite use of that event. You could work a mod to be aware of story quests or whatever quests, and change settings or outcomes based on this. It's really quite a powerful tool.

Link to comment
Share on other sites

In addition to the very informative post by BigAndFlabby, as a C++ dev you might want to know that the different ScriptObjects indeed inherit functions and properties from the parents they extend. So, Actor has all properties and functions that every ObjectReference has in addition to those that are specific to Actor.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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