User:DavidJCobb/Methodologies

From the CreationKit Wiki
Jump to navigation Jump to search

Dynamically finding a reference in a specific Location[edit | edit source]

This isn't the cleverest thing in the world, but it's something that may not occur to people who've gotten used to relying on scripting to get things done.

While working on Atronach Crossing, one of my in-development mods, I thought of a method that can apply to several scenarios. I use it to do some scripting tasks involving fake Teleport Doors: the fake doors consist of an Activator that looks like a door, and a marker that defines that door's endpoint, and there are some times where I need to get a reference to a pre-placed endpoint. I could just point a CK-defined property at the marker, but then the marker would become permanently persistent: Skyrim would always keep it in memory, forever, even if I clear the property later on.

Instead, I can use a quest reference alias and some scripting to get a reference to the marker if the following conditions are met:

  • I know the Location that the marker is in
  • There are no other objects in that Location that have the same base form

The process involves creating a unique Activator for the marker, and creating two quests (with one script) to find the marker at run-time. For the purposes of this tutorial, we'll call the quests FindMarker and FindMarkerWorker.


Setting up FindMarker[edit | edit source]

This quest exists solely as a means to pass the search Location to FindMarkerWorker (since I'm not sure it's possible to fill aliases via script before a quest has started). It should Run Once and be Start Game Enabled. Give it a Location Alias with the following settings:

  • Optional
  • Allow Cleared
  • Fill Type: Specific Location: NONE


Setting up FindMarkerWorker[edit | edit source]

This quest is responsible for actually finding our reference. It should not Run Once, and it should not be Start Game Enabled. We'll need to give it two aliases...

Give it a Location Alias with the following settings:

  • Optional
  • Allow Cleared
  • Allow Reserved
  • External Alias Location: \[tell it to mimic the value of the location alias on FindMarker\]

Give it a Reference Alias with the following settings:

  • Optional
  • Allow Reserved
  • Allow Destroyed
  • Fill Type: Find Matching Reference

The Match Conditions should be as follows:

  • Subject GetInCurrentLocAlias \[the location alias on this quest\] == 1.00 AND
  • Subject GetIsID \[the base form of your marker\] == 1.00


Setting up our script[edit | edit source]

Create a script that extends Quest. Give it the following code and attach it to FindMarker:

Bool Property pbBusy = False Auto Hidden
Quest Property pbWorker Auto
{Should point to the AtronachCrossingFindDoorEndpointWorker quest.}

Event OnInit()
   pbWorker = Quest.GetQuest("FindMarkerWorker")
EndEvent

ObjectReference Function FindEndpoint(Location akLocation)
   If pbBusy || !pbWorker
      Return None
   EndIf
   pbBusy = True
   LocationAlias kLocationAlias = GetAlias(0) as LocationAlias ; Location alias on this quest
   If kLocationAlias
      kLocationAlias.ForceLocationTo(akLocation)
      pbWorker.Start()
      ReferenceAlias kEndpointAlias = pbWorker.GetAlias(1) as ReferenceAlias ; Reference alias on the worker quest
      ObjectReference kResult = None
      If kEndpointAlias
         kResult = kEndpointAlias.GetReference()
      EndIf
      pbWorker.Stop()
      pbBusy = False
      Return kResult
   EndIf
   pbBusy = False
   Return None
EndFunction

(Note that the numbers you give to GetAlias(...) are the IDs of the aliases. When editing a quest's aliases, there is a hidden second column, which you can enlarge. This column shows each alias's ID.)

Given a Location to search, this function will:

  • Force that search Location into FindMarker's location alias
  • Start FindMarkerWorker
    • FindMarkerWorker will pull the search Location from FindMarker's location alias into its own location alias
    • FindMarkerWorker will fill its reference alias with the desired ObjectReference (if any) in that Location
  • This function will retrieve the found ObjectReference (if any) from FindMarkerWorker's reference alias, and return it