Jump to content

Papyrus - Getting the distance of an NPC to Control a Variable


Recommended Posts

I have been wrapping my brain around this one and I am hoping I can get some help with this.

 

Pretty much, I am trying to add a script that detects the distance that a player is from an NPC once and if that NPC is close to the player, it will turn a variable to true (once a certain quest stage is triggered). The reason for this is to control some dialogue to prevent possible immersion issues. Here is what I have for code:

ScriptName SDEDLC2TriggerScript Extends Quest

Actor Property PlayerRef Auto
Quest Property DLC2MQ01 Auto
ObjectReference Property Serana Auto
Bool Property SeranaAtDLC21MQ01 = False Auto  Conditional

Event OnInit()
	RegisterForSingleUpdate(1.0)
EndEvent

Event OnUpdate()
	if (DLC2MQ01.GetStage() >= 7)
		if (Game.GetPlayer().GetDistance(Serana) < 1024)
			(GetOwningQuest as SDEDLC2TriggerScript).SeranaAtDLC21MQ01 = True
			UnregisterForUpdate()
		else
			UnregisterForUpdate()
		endif
	endif
EndEvent

I know that this will not work because I can't use a getdistance on an actor. But I am hoping for some ideas to get this to work. Thank you.

Link to comment
Share on other sites

You can use GetDistance on an Actor without problems. If your intention was to have a variable that is only set if Serana was nearby as the quest was completed then it should work just fine except that you're trying to remotely access the script from itself which is likely causing a locking condition. Try this:

ScriptName SDEDLC2TriggerScript Extends Quest

Quest Property DLC2MQ01 Auto
ObjectReference Property Serana Auto
Bool Property SeranaAtDLC21MQ01 = False Auto Conditional

Event OnInit()
    RegisterForSingleUpdate(1.0)
EndEvent

Event OnUpdate()
    if (DLC2MQ01.GetStage() >= 7)
        if (Game.GetPlayer().GetDistance(Serana) < 1024)
            SeranaAtDLC21MQ01 = True
        endif
        UnregisterForUpdate()
    endif
EndEvent
Link to comment
Share on other sites

Yeah, it is pretty much the intention. I want to be able to lock out some dialogue if she wasn't there to partake in them (in particular, she shouldn't be talking about the first attack from the cultists in Dragonborn is she wasn't there during that first encounter).

 

My issue was that I wasn't sure that you could use ObjectReference to point to an actor.

 

Now, since that is possible, I hope I can pick your brain for one last thing. Let's say I want to add a safety net in case someone loads my mod AFTER said encounter, to prevent a trigger from happening, should I modify the code like this:

ScriptName SDEDLC2TriggerScript Extends Quest

Quest Property DLC2MQ01 Auto
ObjectReference Property Serana Auto
Bool Property SeranaAtDLC21MQ01 = False Auto Conditional

Event OnInit()
    RegisterForSingleUpdate(1.0)
EndEvent

Event OnUpdate()
    if (DLC2MQ01.GetStage() == 7)
        if (Game.GetPlayer().GetDistance(Serana) < 1024)
            SeranaAtDLC21MQ01 = True
        endif
        UnregisterForUpdate()
    elseif (DLC2MQ01.GetStage() > 7)
        UnregisterForUpdate()
    endif
EndEvent

That way if someone loads the mod in the middle of the Dragonborn questline, the variable doesn't trigger automatically. Pretty much to prevent an accidental triggering.

Link to comment
Share on other sites

I just realized that we both called RegisterForSingleUpdate but then didn't re-register, so that code won't work. Since it's using RegisterForSingleUpdate there's no need to unregister but you do need to re-register. And I would put the second test in the OnInit block instead of the OnUpdate.

Event OnInit()
    ; Assumes that if the stage is already done when the mod is loaded that Serana wasn't there.
    if DLC2MQ01.IsStageDone(7)
        SeranaAtDLC21MQ01 = false
    else
        RegisterForSingleUpdate(1.0)
    endif
EndEvent
 
Event OnUpdate()
    ; When it finally happens, record if Serana was nearby
    if DLC2MQ01.IsStageDone(7)
        SeranaAtDLC21MQ01 = Game.GetPlayer().GetDistance(Serana) < 1024
    else ; not yet, keep waiting
        RegisterForSingleUpdate(1.0)
   endif
EndEvent
Link to comment
Share on other sites

I did RegisterforSingleUpdate mostly because I am aware RegisterforUpdate can cause problems (i.e. bloat) so my last question is will calling a single update like that in the new code cause any problems?

Link to comment
Share on other sites

Assuming that DLC2MQ01 is the Dragonborn DLC, you shouldn't encounter a problem since there is an exit strategy if someone uninstalled the mod (Might bark an error about SeranaAtDLC21MQ01 doesn't exist in the game console or something, but won't affect gameplay and the Update check will cease).

Link to comment
Share on other sites

You need to re-register the single update to keep things working, but as Arron Dominion said, the only problem would be a single error reported to the Papyrus log if the mod using the script is ever removed from an existing game. It's far better than any alternative.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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