Jump to content

Reference Aliases not filling


Recommended Posts

In Skyrim SE v1.6.1170.0 I want to attach a script to various types of creatures at run-time so I can change their aggression (make bears cowardly, for example) or disintegrate pests like wolves and skeevers.

I set up a quest for it with a couple of test reference aliases set to Find Matching Reference with In Loaded Area checked. I added Match Conditions to my wolf alias, for example:

GetIsRace Race ‘WolfRace’ == 1.00 AND
IsHostileToActor Reference ‘PlayerRef’ AND

I have a script that catches every type of event and just appends a message to the debug log so I can see all the events that fire for whatever I attach that script to. I attached it to the wolf ref alias, and the only event triggered is OnInit.

That’s fine with me, as I only need access to each creature one time, and I figured new script copies are being created in memory and attached to wolves, for example, when they attach to a cell, as the player moves around in the worldspace or wherever.

When I try this, GetReference() returns none, which I assume means the alias isn’t filled yet.

event OnInit()
    ObjectReference obj_ref = self.GetReference()
    Actor actor_ref = obj_ref as Actor
	    Debug.Trace(“obj_ref: ” +obj_ref +“ actor_ref: ” +actor_ref)
endevent

Obj_ref is always ‘none’ , so actor_ref is none as well. I need to be able to cast the reference alias (‘self’ as the script is attached to Reference Aliases in the quest) to Actor so I can do this:

actor_ref.SetActorValue(“Aggression”, 0)

…or otherwise do things to the actor reference like disintegrate it.

Doing it how I am may not be the best way, but I don’t want to use a magic effect on PlayerRef and constantly poll to see what can be found. I’ve seen that example on creationkit.com, and this way seems more efficient… other than that it’s not working.

I can’t figure out why the Reference Aliases are always ‘none’ even though the game attaches a script to the proper alias (I can see that from logging ‘self’ with Debug.Trace()) and calls OnInit.

I thought no other events were triggering because by the time the reference is filled and the script is attached to a spawned wolf, for example, all the usual stuff like OnCellAttach and OnLoad is already finished. But those events should happen after OnInit, so I don’t know what’s going on.

There’s so little documentation (that I can find) on reference aliases that I just don’t know what I’m doing, as usual. lol I’ve tried looking at Bethesda’s scripts, but haven’t learned anything useful for this situation yet.
 

 

Link to comment
Share on other sites

I am unsure as to when ReferenceAlias scripts are initialized.  It think they are created just the once when the quest is first started.

Try instead to check the alias content from a quest fragment script, in the starting stage, or from the quest's OnInit event.

Quest script OnInit is a bit special.  It fires multiples times:

  • Once when the quest is first added to the game
  • Once when the quest is successfully started
  • Once for each stage change
Script myQuest extends Quest

ReferenceAlias property myAlias Auto

event OnInit()
	if isRunning()
		ObjectReference obj_ref = myAlias.GetReference()
		Actor actor_ref = obj_ref as Actor
		Debug.Trace(“obj_ref: ” +obj_ref +“ actor_ref: ” +actor_ref)
	endif
endevent

 

Link to comment
Share on other sites

5 hours ago, JobVanDam said:

I think it's the self.GetReference(). Try just "ObjectReference obj_ref = GetReference()"
The self is the script itself, not the Reference it's currently attached to.

When 'self' isn't specified, the compiler adds it automatically. There's no difference between self.GetReference() and just GetReference(). What would GetReference() alone be accessing if not 'self'? I always add 'self' just to keep it clear about what I'm accessing.

Link to comment
Share on other sites

4 hours ago, xkkmEl said:

I am unsure as to when ReferenceAlias scripts are initialized.  It think they are created just the once when the quest is first started.

Try instead to check the alias content from a quest fragment script, in the starting stage, or from the quest's OnInit event.

Quest script OnInit is a bit special.  It fires multiples times:

  • Once when the quest is first added to the game
  • Once when the quest is successfully started
  • Once for each stage change
Script myQuest extends Quest

ReferenceAlias property myAlias Auto

event OnInit()
	if isRunning()
		ObjectReference obj_ref = myAlias.GetReference()
		Actor actor_ref = obj_ref as Actor
		Debug.Trace(“obj_ref: ” +obj_ref +“ actor_ref: ” +actor_ref)
	endif
endevent

 

I was thinking of moving the script to the quest itself, but what I'm trying has to be doable. I have to be missing something. There's certainly a way to access reference aliases from scripts attached to reference alias objects. I just can't figure out why no events are triggering other than OnInit.

The script in question has settings that are specific to a certain race. I have an MCM (Mod Configuration Menu via SkyUI/SKSE) that allows the player to configure how to handle wolves, for example, and it's different for trolls, dragons, skeevers, mudcrabs and whatnot with a different setting for each race. Should wolves keep their default behavior, or be cowardly, or be disintegrated and leave an ashpile to loot, or just be disintegrated with no ashpile? Bears and slaughterfish have their own setting.

I don't want to have a huge script on the quest itself that has to test what race the Reference Alias is. The conditions in the Reference Aliases are already testing for the race, so I want the script attached to the Reference Aliases themselves, so that the script doesn't have to spend time testing for this and that race to find out what to do with a given type of creature.

With the Reference Alias itself doing the race testing via conditions, I can just put a property of type GlobalVariable on my script (which the MCM allows players to change) and then point that property to, say, wolf_behavior_global so I have access to the right setting without having to test for the race of the creature inside the script.

I think this project is going to slow the game down as it is. If I have to test every creature that spawns in a huge if/else statement to find out what race it is (when the Reference Alias already tests for that using conditions), it's going to slow things down and could make my mod unusable during things like the civil war when actors are spawning all over the place.

 

Link to comment
Share on other sites

13 hours ago, Sirgallyhave said:

When 'self' isn't specified, the compiler adds it automatically. There's no difference between self.GetReference() and just GetReference(). What would GetReference() alone be accessing if not 'self'? I always add 'self' just to keep it clear about what I'm accessing.

I use a LE program called Skyrim Script Compiler for my scripting. It doesn't add self or anything else for that matter.
I have recently had to edit a bunch of quests with aliases and such and the difference between self and no self is sometimes self would be referencing the script itself not the alias.

Try removing the Subject.GetIsRace condition and adding more aliases.
Also in the OnInit function add a Debug.Notification( "Name: " + GetReference.GetBaseObject().GetName()) so at least the game will try to spit out a name of what it did ultimately capture.
In my experience, if something is not working as expected I messed up something somewhere or the engine is just goofy. So I start removing things or spitting out information on what the alias is pointing to until I can narrow down the problem and work from there.

Link to comment
Share on other sites

12 hours ago, JobVanDam said:

I use a LE program called Skyrim Script Compiler for my scripting. It doesn't add self or anything else for that matter.
I have recently had to edit a bunch of quests with aliases and such and the difference between self and no self is sometimes self would be referencing the script itself not the alias.

Try removing the Subject.GetIsRace condition and adding more aliases.
Also in the OnInit function add a Debug.Notification( "Name: " + GetReference.GetBaseObject().GetName()) so at least the game will try to spit out a name of what it did ultimately capture.
In my experience, if something is not working as expected I messed up something somewhere or the engine is just goofy. So I start removing things or spitting out information on what the alias is pointing to until I can narrow down the problem and work from there.

GetReference() is always returning 'none', so GetReference().GetBaseObject() does nothing but cause an error to be logged. I can already see that the alias itself, not the script, is 'self' with Debug.Trace(self).

[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Wolf_Alias on quest z00s_CC_Main_Quest (1B005900)>] OnInit got obj_ref: None
[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Wolf_Alias on quest z00s_CC_Main_Quest (1B005900)>] <<< WTF >>>, !actor_ref, aborting. What IS obj_ref?
[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Skeever_Alias on quest z00s_CC_Main_Quest (1B005900)>] OnInit got obj_ref: None
[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Skeever_Alias on quest z00s_CC_Main_Quest (1B005900)>] <<< WTF >>>, !actor_ref, aborting. What IS obj_ref?
[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Wolf_Alias on quest z00s_CC_Main_Quest (1B005900)>] OnInit got obj_ref: None
[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Wolf_Alias on quest z00s_CC_Main_Quest (1B005900)>] <<< WTF >>>, !actor_ref, aborting. What IS obj_ref?
[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Skeever_Alias on quest z00s_CC_Main_Quest (1B005900)>] OnInit got obj_ref: None
[03/09/2024 - 10:04:05AM] z00s_CC_handler_script 1.0.0 >> [z00s_CC_handler_script <alias z00s_CC_Skeever_Alias on quest z00s_CC_Main_Quest (1B005900)>] <<< WTF >>>, !actor_ref, aborting. What IS obj_ref?

The aliases themselves are triggering what they're supposed to trigger and 'self' is definitely the Reference Alias. It's what the script (z00s_CC_handler.pex in this case) is attached to, the Reference Aliases, with

Scriptname z00s_CC_handler_script extends ReferenceAlias

A script that extends ReferenceAlias will always have a ReferenceAlias as 'self'. I've never seen a case where the scriptname itself is 'self'. To get the scriptname, it must be cast from 'self' unless 'extends z00s_CC_handler_script' is used.

I don't want to use OnInit. I should be able to use OnLoad, and if I could, I'd be certain that the reference had been resolved (or at least that the wolf or whatever had been fully loaded) by the time my script is executed. 'Self' is definitely the reference alias and the correct ones are being created and the correct script is being attached to them. But GetReference() is always returning 'none' from OnInit, and there's no real documentation about that. I assume it means the alias hasn't yet loaded but then what is the script being attached to, and why does Debug.Trace(self) log the correct aliases?

If they didn't exist, my script couldn't execute because it's only attached to the reference aliases themselves and they're all set to only match references that match the conditions (GetIsRace) "In Loaded Area". None of the wolves or skeevers in my testing exist when the quest starts. I'm creating them and when they're created, everything is working fine. The game is noticing my reference aliases and the conditions on them. It's attaching the correct script (z00s_CC_handler_script) to the wolves and skeevers as I spawn them with the console, but GetReference() is always 'none' from OnInit... and no other events are being triggered so I'm stuck with OnInit.

 

Link to comment
Share on other sites

ReferenceAlias scripts don't get an event when the aliased reference changes.  They do see events fired by the aliased reference.

Inside the ReferenceAlias script, if getReference() returns None, it's because the alias is not filled at this time.  I believe you are seeing None because you are calling getReference too early, before the quest is started and the aliases are filled.

You should use the console command "sqv myQuest" to see your quest state and check whether aliases are filled properly.

You may then want to listen to some event, like "OnHit" or "OnItemAdded" or "OnActivate" from your alias script (depending on what event you think you can trigger in testing).

I only suggested using the quest as a way of knowing when to check the alias content for debugging purposes.

 

Link to comment
Share on other sites

Rereading your original message...

Have you set the "optional" flag on your aliases? 

The quest will not start if any non-optional alias fails to find a target.  None of the aliases will be filled if any one of them fails.

The console command "sqv myQuest" will tell you the current state of your quest and show you the currently assigned aliases.

 

Link to comment
Share on other sites

6 hours ago, xkkmEl said:

ReferenceAlias scripts don't get an event when the aliased reference changes.  They do see events fired by the aliased reference.

Inside the ReferenceAlias script, if getReference() returns None, it's because the alias is not filled at this time.  I believe you are seeing None because you are calling getReference too early, before the quest is started and the aliases are filled.

You should use the console command "sqv myQuest" to see your quest state and check whether aliases are filled properly.

You may then want to listen to some event, like "OnHit" or "OnItemAdded" or "OnActivate" from your alias script (depending on what event you think you can trigger in testing).

I only suggested using the quest as a way of knowing when to check the alias content for debugging purposes.

 

Thanks for the response. That's what I needed to know, what's going on with events. I guess I can't use this method if reference aliases don't trigger any event when the reference changes.

I still don't understand how the game is handling this. The aliases are optional. I do realize that the quest wouldn't even start if they weren't optional, as the aliases only exist (or only should exist) when wolves or skeevers spawn "In Loaded Area" as that's how the aliases are set up. So, there should be nothing to attach my script to until a wolf and/or skeever has spawned, so I don't know how or why OnInit is ever being called to begin with from a script that's only attached to reference aliases that don't exist until a wolf or skeever spawns. 

With no wolves or skeevers in the same cell, sqv tells me that my wolf alias and skeever alias already exist and are set to NONE. I don't know why that is as no wolves or skeevers exist anywhere at that point. My script has also already been loaded into memory and OnInit has been called twice per wolf alias, twice per skeever alias and I have no idea why.

When I spawn three wolves from the console, nothing changes. No new aliases are created and sqv shows that my one wolf alias is still set to NONE even though three wolves are right in front of me attacking my player character, so thanks also for mentioning sqv as I didn't think to check that.

What I used to do was just attach my script to Lvl*Predator in the Object Window of the CK under the Actor category. It works fine when I do that as I can have the script watch for OnLoad events and whenever a pest (predator) spawns, my script is attached to it and deals with it.

I just want to do that in a way that's compatible with other mods. I can't edit base objects directly, attaching a script to them, and release the mod like that, which is why I'm trying to use aliases. But I can't figure out how to do it. I'm just trying to attach a script to Lvl*Predator (there are a few of them, LeveledCharacter lists) without doing it directly by editing the base objects.

Edit: I should just say I'm trying to attach a script to EncWolf in the Actor category but at run-time because wolves spawn randomly depending on the player's level. If I attach my script to EncWolf in the CK's Object Window, I can use the OnLoad event to deal with any newly-spawned wolves. I'm trying to do that via an alias.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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