Jump to content

MCGUFIN

  • entries
    9
  • comments
    0
  • views
    389

LocTrack


Monoman1

46 views

Mcgufin's player location tracking system has several layers: 
    
Cell: 

Spoiler

Cell change tracker:

 

Just a straight up cell change event. If you're using Mcgufin as a master and need cell change events then might as well use Mcgufins'.
It's implemented natively so no magic effect and no invisible object following you around and it has a practical event payload. 

 

See script: _MGF_Util

 

Usage:

Event OnInit()
    _MGF_Util.RegisterForCellChange(Self)
EndEvent

 

Event On_MGF_CellChange(Cell akCell, Location akLocation, WorldSpace akWorldspace, bool abInterior)
    ; Cell changed.
EndEvent


Area / Hold / World Tracking: 

Spoiler

The is more of a semantic 'geography' system than anything else. 

 

Your current location is expressed by Mcgufin with GlobalVariables: 
_MGF_PcLoc2_AreaIndex: The player's current area. 
_MGF_PcLoc1_HoldIndex: The player's current hold. 

_MGF_PcLoc0_WorldIndex: The player's current 'world'. 

 

And string script properties: 
AreaStateName: The player's current area. This is set as the 'main' area location's EditorID - 'locationstates' in LocationMap.json. 

HoldStateName: The player's current hold. The hold name with any whitespace removed ('TheRift') - 'holdstates' in LocationMap.json. 

WorldStateName: The player's current world - 'worldstates' in LocationMap.json. 

 

Incidentally, these are the same strings you'd pass to LocOpsArea/Hold for an information request about a specific area/hold. 

 

Because LocationMap.json is a json and can be modified Mcgufin will send event "_MGF_LocTrack_JsonReload" when LocTrack's json is reloaded so that outside mods can update any variables they are using. 

RegisterForModEvent("_MGF_LocTrack_JsonReload", "On_MGF_LocTrack_JsonReload")

Event On_MGF_LocTrack_JsonReload(string eventName, string strArg, float numArg, Form sender)
	; Update local variables if needed.
EndEvent

 

Areas:

Spoiler

This system treats groups of locations as single entities. Useful when you don't really care where exactly the PC is, only that they are somewhere in Riverwood or somewhere in Rorikstead or Winterhold etc. Walled cities like Whiterun are a bit of a special case. Inside the walls and outside the walls are defined as separate areas. So the global variable has one value for inside the walls and another for outside. A mod event is sent whenever the player moves between any area. 

 

This system is also capable of 'learning' the structure of the area when location mods are involved. For example if a town mod placed a farmhouse within the Whiterun outskirts region then inside the farmhouse will automatically be mapped to being within the Whiterun outskirts region IF (and only if) the player enters the cell via an activatable door (Not via console, teleport or seamless transition entrance (cave gap) etc). This way you shouldn't get false events when the PC enters interior cells that would normally be undefined. 

 

Areas are usually towns, cities or other localized areas. Eg: Kynesgrove, High Hrothgar, military camps, orc strongholds etc. 
Mcgufin sets a global variable and sends an event when the PC changes area. 

 

Global: _MGF_PcLoc2_AreaIndex: 
                        0 = Wilderness
                        1 = Undefined (Not wilderness but not defined - likely a dungeon entrance etc)
                        x = ?


Locations are mapped via LocationMap.json. 'locationstates' is a 1:1 map with 'locationindex' and 'areanames'.


Global Usage:

MyGlob.SetValueInt(LocTrack.GetIndexForArea("RiverwoodLocation")) ; Because json can potentially be modified

;Dialogue (or anything else) condition:
_MGF_PcLoc2_AreaIndex == MyGlob ; "Welcome to Riverwood"


Event usage:

RegisterForModEvent("_MGF_LocTrack_AreaChange", "On_MGF_LocTrack_AreaChange")

Event On_MGF_LocTrack_AreaChange(string eventName, string strArg, float numArg, Form sender)
	; Do area stuff.
	GoToState(strArg) ; strArg is the location editor name. Eg: WhiterunLocation
EndEvent

State WhiterunLocation
	Event OnBeginState()
		; Set up stuff for Whiterun
	EndEvent
	
	Function GetLocalInnkeeper()
		Return Hulda
	EndFunction
	
	Event OnEndState()
		; Tear down stuff for Whiterun
	EndEvent
EndState

State RiverwoodLocation
	Event OnBeginState()
		; Set up stuff for Riverwood
	EndEvent
	
	Function GetLocalInnkeeper()
		Return Orgnar
	EndFunction
	
	Event OnEndState()
		; Tear down stuff for Riverwood
	EndEvent
EndState

 

Hold: 

Spoiler

Tracks which of the 9 holds the PC is currently in. Works in interiors, town exteriors and out in the wilds too. This system CURRENTLY requires the user run the XCLR region patch TesEdit script and good management of the resulting patch plugin (Smash patch etc). Consult the map to see hold borders. Borders don't tend to extend to ALL areas of the map simply because I didn't want Mcgufin to 'overreach' into possible modded areas. So you can NOT be in any hold while still in the Skyrim world. 

 

Global: _MGF_PcLoc1_HoldIndex: 
                                0 = Wilderness (Not in any hold)
                                1 = Eastmarch
                                ; Holds are unlikely to change but I still wouldn't recommend hardcoded values. LocationMap.json can be modified. 
                                ; LocTrack.GetIndexForHold("Eastmarch")

 

Event sent: 

SendModEvent("_MGF_LocTrack_HoldChange", strArg = HoldStateName, numArg = HoldIndex)

Usage:

RegisterForModEvent("_MGF_LocTrack_HoldChange", "On_MGF_LocTrack_HoldChange")

Event On_MGF_LocTrack_HoldChange(string eventName, string strArg, float numArg, Form sender)
	; Do hold stuff.
	GoToState(strArg) ; strArg is the hold name with any white space removed. Eg: "The Pale" -> "ThePale". So it can be used in state names
EndEvent

State Whiterun
	Event OnBeginState()
		; Player entered Whiterun hold
	EndEvent

	Function GetJarlHere()
		Return Balgruuf
	EndFunction
	
	Event OnEndState()
		; Player left Whiterun hold
	EndEvent
EndState

State TheRift
	Event OnBeginState()
		; Player entered The Rift hold
	EndEvent
	
	Function GetJarlHere()
		Return Laila
	EndFunction
	
	Event OnEndState()
		; Player left The Rift hold
	EndEvent
EndState

 

 

 

World: 

Spoiler

Probably the least useful. Mcgufin only tracks a few 'worlds'. Skyrim, Sovngarde, The Soul Cairn, Solstheim and they are treated as human logical worlds rather than game logic worlds. Ie: Most of these worlds are made up of multiple worldspaces. The overall idea is that if Mcgufin says the player is somewhere in Skyrim then they should be geographically somewhere in Skyrim regardless of whether they're indoors, outdoors, in a city or in some niche pocket worldspace. 

 

Event sent: 

SendModEvent("_MGF_LocTrack_WorldChange", strArg = WorldStateName, numArg = Value)

Usage: 

RegisterForModEvent("_MGF_LocTrack_WorldChange", "On_MGF_LocTrack_WorldChange")

Event On_MGF_LocTrack_WorldChange(string eventName, string strArg, float numArg, Form sender)
	; Do world change stuff
	GoToState(strArg) ; strArg is the world name with any white space removed. Eg: "The Soul Cairn" -> "TheSoulCairn". So it can be used in state names
EndEvent

State TheSoulCairn
	Event OnBeginState()
		; Player entered The Soul Cairn
	EndEvent

	Event OnEndState()
		; Player left The Soul Cairn
	EndEvent
EndState

 


Area Proximity:

Spoiler

Events only. Fires when you get 'close to an area'. This is usually when a center marker's OnCellAttach() event fires. So how close to an area it fires is determined by where the marker is and how wide the area spans (and the number of cells configured to load in the users ini settings). IE: If it's a really small place like a shack or cabin it may fire from relatively far away. If it's a biggish town it may not fire until a lot closer. Note that because of the size and span of walled cities and the outskirts of walled cities, this event does not fire for them. A center marker would be too far away to be effective usually. Use the area tracker above for walled cities. 

 

Why use this? Sometimes you need to do things as the player approaches a location but before the player actually arrives there. SLS's enforcer randomizer uses this to randomize the enforcer Npcs as the player approaches but before they'd usually be within visible range of the enforcers. I've decided against gating the events in any way so that you can decide how it's gated.

 

But as an example, in the case of SLS's enforcer randomizer, I want to run it while the player is far enough away that they can't see the enforcers but not so close that they would see them being enabled/disabled. So I added a basic distance check to the marker on SLS's side. Around >= 8000.0 seems to work well. If the PC is at a distance of > 8000.0 when the event fires
it likely means that they walked into the area and that they 1) didn't fast travel into the area and 2) didn't just exit a building in the area. 


There is one event for approaching a location and another for departing a location. At default ugridsToLoad departing usually occurs around the 12000 - 15000 distance mark. Distance to the marker when entering an internal cell will be astronomically high even if the marker is just outside the door.

 

Event sent (approaching area): 

ObjRef.SendModEvent("_MGF_LocTrack_ApproachingArea", strArg = LocStateName, numArg = ObjRef.GetDistance(PlayerRef))

Usage:

RegisterForModEvent("_MGF_LocTrack_ApproachingArea", "On_MGF_LocTrack_ApproachingArea")

Event On_MGF_LocTrack_ApproachingArea(string eventName, string strArg, float numArg, Form sender)
	; strArg = AreaStateName - See LocationMap.json 'locationstates'
	; numArg = The distance to the marker
	; sender = The marker object reference
EndEvent


Event sent (departing area):
 

ObjRef.SendModEvent("_MGF_LocTrack_DepartedArea", strArg = LocStateName, numArg = ObjRef.GetDistance(PlayerRef))

Usage:

RegisterForModEvent("_MGF_LocTrack_DepartedArea", "On_MGF_LocTrack_DepartedArea")

Event On_MGF_LocTrack_DepartedArea(string eventName, string strArg, float numArg, Form sender)
	; strArg = AreaStateName - See LocationMap.json 'locationstates'
	; numArg = The distance to the marker
	; sender = The marker object reference
EndEvent

 

 

Edited by Monoman1

0 Comments


Recommended Comments

There are no comments to display.

×
×
  • Create New...