Jump to content

[LE] Quick Questions, Quick Answers


Recommended Posts

Is there a way to get all world/cell References to an ActorBase (wiki) through script without SKSE?

 

I could manually store them all in a FormList in the CK, but I'd like a way to dynamically detect all references if possible.

 

There's a couple of ways off the top of my head.

 

As long as you don't care about getting them all at once, you could retrigger a search quest whenever the player triggers an OnCellLoad event, and then have the aliases add their references to a formlist.

 

If you're okay with editing the actorbase (should be fine if it's a new one for your mod, conflict-prone if it's a vanilla one) you can add a script to the actorbase in the CK, extending actor, and have them all add themselves to a formlist OnInit.

Link to comment
Share on other sites

If you're okay with editing the actorbase (should be fine if it's a new one for your mod, conflict-prone if it's a vanilla one) you can add a script to the actorbase in the CK, extending actor, and have them all add themselves to a formlist OnInit.

Hmm that might work. Will the containing cell have to be loaded for OnInit to run though? I will need it to list even actors from cells that have never been loaded.

 

This brings up another thing I don't understand about Papyrus. Can I utilize scripts on objects that don't have any instances? Say I attach a script to an Activator, but I never place that Activator anywhere in the world. The only use of it is that it's attached to a property on another script (extending a quest).

 

Will said quest be able to access and change the properties of the Activator's script, call its functions, and expect the Activator to receive events?

Link to comment
Share on other sites

 

If you're okay with editing the actorbase (should be fine if it's a new one for your mod, conflict-prone if it's a vanilla one) you can add a script to the actorbase in the CK, extending actor, and have them all add themselves to a formlist OnInit.

Hmm that might work. Will the containing cell have to be loaded for OnInit to run though? I will need it to list even actors from cells that have never been loaded.

 

 

It will run regardless of if the cell is loaded or not. I use this method to register, for example, all instances of a custom mannequin I've created with a control script on a quest.

Link to comment
Share on other sites

It will run regardless of if the cell is loaded or not. I use this method to register, for example, all instances of a custom mannequin I've created with a control script on a quest.

Were your mannequins set to persistent, or no?

Looking at the wiki notes for OnInit:

 

"For persistent refs: At game start the first time this script is loaded

For non-persistent refs: When the ref is loaded the first time"

 

Which makes it seem like this might not work for non persistent refs? I will have to test it out when I get home.

 

Re: my other question, it says:

 

"For other base objects like Topic Infos, Perks, etc that have scripts that run on the base object: At game start the first time this script is loaded"

 

Which makes it sound like it is possible to use a never-referenced Activator like I was hoping.

 

EDIT: Damn just realized the actor script technique won't actually work for me. The actors will be placed in Leveled Lists, and leveled lists don't accept actors with scripts. :(

Link to comment
Share on other sites

Is there a way to get all world/cell References to an ActorBase (wiki) through script without SKSE?

You can't get them all even with SKSE. At best you'll get the persistent ones and the ones in loaded cells.

 

 

This brings up another thing I don't understand about Papyrus. Can I utilize scripts on objects that don't have any instances? Say I attach a script to an Activator, but I never place that Activator anywhere in the world. The only use of it is that it's attached to a property on another script (extending a quest).

 

Will said quest be able to access and change the properties of the Activator's script, call its functions, and expect the Activator to receive events?

Scripts are only ever attached to instances of things that have an existence in the game. That's almost always a reference or active spell effect but can also be one of the things that have a single global instance like quests, global variables, and (as I found by accident one time) perks. (Dialog topic fragments also have a very fleeting existence but those are a special case.)

 

An Activator defined in the CK is the equivalent of a class definition in traditional object-oriented programming terms. An object instance is the ObjectReference you place somewhere in the game world either through the CK, PlaceAtMe with a script, or the object creation feature of quest aliases. You can't access the script on the generic activator defined with "Activator Property myActivator auto" and instead you need to place an activator into the game world somewhere and then use it to fill "ObjectReference Property myActivatorRef auto" instead.

 

And for most things even the references defined in the CK don't come into existence until the parent cell is loaded. Only persistent references have their scripts initialized at game load. But if you place that activator reference and fill a property with it the CK will tag it as persistent for you.

 

Actors being placed by leveled lists won't exist until their parent cell is loaded but you can give your actors an ability with a script effect and then the script on that effect can take the place of a script on the actor. But the script on that ability will re-run whenever the actor changes locations or the cell gets reloaded so you'll need to account for that.

Link to comment
Share on other sites

 

An Activator defined in the CK is the equivalent of a class definition in traditional object-oriented programming terms. An object instance is the ObjectReference you place somewhere in the game world either through the CK, PlaceAtMe with a script, or the object creation feature of quest aliases. You can't access the script on the generic activator defined with "Activator Property myActivator auto" and instead you need to place an activator into the game world somewhere and then use it to fill "ObjectReference Property myActivatorRef auto" instead.

And for most things even the references defined in the CK don't come into existence until the parent cell is loaded. Only persistent references have their scripts initialized at game load. But if you place that activator reference and fill a property with it the CK will tag it as persistent for you.

 

 

Dang. Thanks for the info. I chose Activator simply because it was a very simple object type that is capable of accepting a script. You see, I have several scripts that need to be attached to some base object in order to set their properties within the CK, but they do not need any of that object's functionality. They are purely for organized data storage in their properties and for running functions on that data (essentially a C++ Class). I could choose a Quest as the base object, but those just have a lot of unnecessary data associated with them that will make this cumbersome, especially since I will be generating and editing very large numbers of these objects in xEdit. Global variables don't have scripts so I can't use those. Perks could maybe work, but it surprises me that they don't need to be referenced by any actors for their scripts to work? Is there any other simple base object you would recommend for my situation? EDIT: looks like Perk will be perfect if it does in fact work without any reference, will update when I've tested.

 

 

 

Actors being placed by leveled lists won't exist until their parent cell is loaded but you can give your actors an ability with a script effect and then the script on that effect can take the place of a script on the actor. But the script on that ability will re-run whenever the actor changes locations or the cell gets reloaded so you'll need to account for that.

 

 

Yes, but actors placed in LeveledActor lists cannot have scripts attached to them -- the engine will not allow it. You need to then use that LeveledActor as a parent for another Actor that does have a script, and replace all references to the LeveledActor with references to the scripted child Actor, but these are vanilla LeveledActors, so I unfortunately can't do that without creating huge conflicts :sad: ... I will just stick with adding all references to a FormList manually / in xEdit. It isn't as flexible but it will work.

Link to comment
Share on other sites

(Problem solved, I had to edit a property for the body token in CK to complete the script, I'll leave the question and info incase it's a frequently asked question)

 

I'm making a simple dead actor pickup script that doesn't store the actor anywhere, and isn't meant to retrieve them later. just removes them and adds a generic inventory token item you can use for crafting at cook pots or other crafting stations. but I'm running into a road block with making the script add the item to the players inventory. my script compiles properly and the spell properly destroys the target, however the token item is not added to the player's inventory. my full script source is below, can someone with more experience maybe tell me the obvious fix I am no doubt missing? this is quite literally the first script I've ever written from scratch in any language, and I could do with any pointers you may have.

 

----------------------

 

Scriptname CC_PickupBody extends activemagiceffect

Actor Property PlayerREF Auto
Keyword Property ActorTypeAnimal Auto
Keyword Property ActorTypeCreature Auto
Keyword Property ActorTypeDwarven Auto
Keyword Property ActorTypeNPC Auto
MiscObject Property CC_HumanCorpseToken Auto

Actor Victim
Actor Lugger

Event OnEffectStart(Actor akTarget, Actor akCaster)

Victim = akTarget
Lugger = akCaster

If akTarget.IsDead() && (akTarget.HasKeyword(ActorTypeNPC) || akTarget.HasKeyword(ActorTypeAnimal) || akTarget.HasKeyword(ActorTypeCreature) || akTarget.HasKeyword(ActorTypeDwarven))
EndIf

Lugger.AddItem(CC_HumanCorpseToken, 1, true)
Victim.RemoveAllItems(akTransferTo = Lugger, abRemoveQuestItems = True)
Victim.SetCriticalStage(Victim.CritStage_DisintegrateEnd)

EndEvent

 

-----------------------

 

I've also tried with PlayerREF.AddItem(CC_HumanCorpseToken, 1, true) to no avail. I keep going over it and over it and I can't spot the problem. could it be related to something in the CK instead?

Edited by YuriOtani
Link to comment
Share on other sites

You can't access the script on the generic activator defined with "Activator Property myActivator auto" and instead you need to place an activator into the game world somewhere and then use it to fill "ObjectReference Property myActivatorRef auto" instead.

 

Actually testing seems to show the contrary. I haven't tried any other base classes, but the following works:

 

Script attached to an Activator with no references:

Scriptname accm_SplicerScript extends Activator

bool property SetToYes Auto


event OnInit()
	Debug.MessageBox("Splicer Init: " + SetToYes);
	RegisterForSingleUpdate(5);
endEvent

event OnUpdate()
	Debug.MessageBox("Splicer Update: " + SetToYes);
endEvent

Script attached to a quest:

Scriptname accm_ControlScript extends Quest  

accm_SplicerScript Property Splicer Auto


event OnInit()
	Debug.MessageBox("Quest Init");
	RegisterForSingleUpdate(1);
endEvent

event OnUpdate()
	Splicer.SetToYes = true;
	Debug.MessageBox("Quest update");
endEvent

When loading a game, you see the following:

 

"Quest Init"

"Splicer Init: False"

"Quest Update"

"Splicer Update: TRUE"

 

So at the very least, events and properties work fine. Hopefully that means everything will work :smile:

Link to comment
Share on other sites

  • Recently Browsing   0 members

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