Jump to content
dAb

Four NPC driving me nuts

Recommended Posts

I have a script attached to a MGEF, which is an ability attached to humanoid races, and the following NPC ACHR [it's 4 guards in Solitude exteriors] are giving me a lot of trouble in SE:

0002A308

0002A2C4

0002A309

000FF11F

I need to skip "none" actors to avoid unnecessary checks and logs spam but for some reason checking for NONE does not work at all with those 4 guards, I get lots of  Unable to call blah on blah, the usual.

Can anyone spot any issue with those 4 guards? I've been all over the map and no other NPC throws any error, it's only those 4 bastards. Also, the same script never gave a single problem in years in LE, it's only in SE, the source code is exactly the same. I can spot two diffrences between LE and SE in xEdit: an "Unused" flag in LE and being referenced by the Solitude LCTN in SE. Not that it helps, I can't find anything wrong.

What's driving me crazy is that I'm checking for NONE so that I know when not to run anything on those "none" actors and the logs show that their form is.. none.

 

[05/04/2018 - 11:52:28PM] Error: Unable to call GetWornForm - no native object bound to the script object, or object is of incorrect type
stack:
    [<nullptr form> (0002A309)].Actor.GetWornForm() - "<native>" Line ?
    [None].YASH2_ArmorPenalties.GetEquippedBootsType() - "YASH2_ArmorPenalties.psc" Line 421
    [None].YASH2_ArmorPenalties.OnEffectStart() - "YASH2_ArmorPenalties.psc" Line 229
 

Help?

Share this post


Link to post
Share on other sites

I give up. I ended up adding a condition to exclude them from being affected by the ability. Still, could have been useful knowing WTH is wrong with those guys.

 

 

SkyrimSE_4Bastards.png

Share this post


Link to post
Share on other sites

There probably isn't much way to ever find out since MGEF scripts are one of the 2 types that Papyrus utterly destructs when the effects wear off and you get unpredictable results when trying to do things in the event on the script.

Share this post


Link to post
Share on other sites

According to your log, it is NOT none but a "null pointer". Note the ref 0002A309 that is logged with the null pointer (should be the actor's valid ref) ? "True" none items do not have any ref. This is essentially why this reference passes all checks for 'none': because it actually isn't 'none'. In any other respect though, null pointers will behave like nones: trying to call any functions on them will fail with an error.

There is evidence that null pointers are deliberately used to block script access to a reference (at least temporarily) or to prevent an item from becoming peristent. There are at least two cases documented where references may turn into null pointers and back into valid references at run time:

  • Script properties referencing an exterior cell: that property will turn into a null pointer once the cell detaches, and turn back into a valid ref once it attaches again.
  • Object references stored in a form list: they turn into null pointers if the cell where they are persistent detaches, and turn back into valid refs if that cell re-attaches.

In your case, the magic effect has ended at the time you try to call stuff on the actor: this is obvious because the magic effect script is running on 'none'. I further assume that the actor you try to run stuff on is stored in a property on that script. That would explain why the property turned into a null pointer (it presumably did so as soon as the effect stopped running).

 

Share this post


Link to post
Share on other sites

Actually I'm not running anything directly on those actors. My script runs on those only because it purposely runs on all NPC of their race, no exceptions [it's attached to the MGEF of a SPEL attached to the race of their base NPC]. And no, they are not properties in my script, they are untouched vanilla references.

Share this post


Link to post
Share on other sites
4 hours ago, dAb said:

And no, they are not properties in my script, they are untouched vanilla references.

But you run stuff on them, so you likely save the actor on which a script instance runs at least in a variable once the effect starts running, so you don't have to re-evaluate the actor ref each time the script needs to run stuff on it. Or is your script entirely event based and you get the actor ref always from akCaster/akTarget that are passed in by the respective event ?

See, that could be the problem. Magic effectts are forcibly deleted by the engine as soon as they stop running. If whatever is responsible for an event to fire on your script is happening while a magic effect is still active, your magic effect script will receive that event no matter what - but it may fire after the effect has expired, and if that happens, anything passed in by that event is likely invalid.

If you store the actor in a variable or property once the effect starts running and use that instead of what an event is passing in, you'll always have a valid actor ref to operate on, and things may still be working if the script continues running after the effect has expired.

Share this post


Link to post
Share on other sites

 

3 hours ago, Sclerocephalus said:

If you store the actor in a variable or property once the effect starts running and use that instead of what an event is passing in, you'll always have a valid actor ref to operate on, and things may still be working if the script continues running after the effect has expired.

That's exactly what I'm doing.

Actor actorRef

Event OnEffectStart(actor akTarget, actor akCaster)
	actorRef = akTarget

*snip*

Event WhateverEvent
	if ( actorRef != None)
		do stuff

 

Share this post


Link to post
Share on other sites

There is a way to let a script recognize a null pointer (and to discern it from a 'normal' none ref), but I don't know whether this will be of much help because it will not prevent the error from being thrown:

if actorRef != none
	if actorRef.GetLeveledActorBase() != none
	  :
	  (do your stuff here)
	  :
	  return
	endif
	:
	(everything that needs to be done if actorRef holds a null pointer should be added here)
	:
endif

First check for a 'none', as usual. The second check is a bogus check, as you probably don't need to know the leveled actor base. You know however that the check will fail with an error if actorRef holds a null pointer. If that happens, the script will skip the entire if branch. Thus, do anything you need to do on a valid ref in that if branch and move everthing you might want to do if the ref has turned invalid ibelow that check.

Share this post


Link to post
Share on other sites

Thanks, saved for future reference. However, since the whole point was to avoid log spam [I like my logs clean as a whistle] the CK condition will be more than enough.

Share this post


Link to post
Share on other sites

Found it. I told you there was something wrong with those specific 4 guys, they were broken. Wanna laugh? I AM THE ONE WHO BROKE THEM: 

XnrymGd.png

I have no idea where these edits come from. Only thing that comes to mind, they may be old UP records that I've carried over and didn't remove upon further UP updates. At any rate I have now removed them, no need anymore to add that ability conditions and everything works flawlessly. One way or the other, the UP are always to blame :troll:

edit: no, wait, I got it all wrong. Those edits appear there when I add the conditions to the ability. Aaargh I give up on trying to understand how this thing works. Whatever. Conditions are there, no more log spam, problem solved.

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

Support us on Patreon!

×