Sean W. Anderson — Game Design Portfolio

Sean W. Anderson

Stellar Fulcrum

This mod was officially featured on Bethesda’s community channels on July 2020.

“The creation of the Mortal Plane, the Mundus, Nirn, is a source of mental anguish to all living things; all souls know deep down they came originally from somewhere else, and that Nirn is a cruel and crucial step to what comes next.”

Spirit of Nirn, God of Mortals, Anonymous

Summary

The Dwemer built great astronomical measuring machines like the orrery of Stros M’kai. Deep under the mineral pools of eastern Skyrim, fueled by the pneumatic power of stream and the heat of lava, a spinning planetary map of the universe is housed under a starry dome. The Dwarves used their understanding of the universe and their distrust of the heavens to calculate the future paths of the gods.

After descending down maintenance shafts and elevators under volcanic mineral pools, the player arrives at the hub of the research facility known as Katumz. It is a mess of gears and pipes with a column housing a spinning shaft suspended over a magma cistern. Around this central column is a spiral ramp that leads to an orrery with all of the planets and celestial bodies of The Elder Scrolls’ universe: Nirn and her two moons, Masser and Secunda; Kynareth; Akatosh and Julianos with Stendarr; Zenithar, Mara, and Dibella; Arkay; and Magnus the sun.

Figures 1-1 through 1-6 show different angles of the orrery in topographic and isometric views with base and starry dome removed for better viewing.

The movement of the planets is controlled by a script that enables and disables the planets based on the day, thereby giving off the impression of movement, and runs as long as the player is in the Stellar Fulcrum cell. The below script is run on seven invisible markers that correspond to the seven days of the week. Figures 2-1 and 2-2 show these markers and the planets that they control.

ScriptName ORMPlanetariumScript extends ObjectReference

Float Property fSeconds Auto
{The amount of seconds that need to go by before checking to see if the positions need to be updated.}
Int Property iDayOfWeek Auto
{The day we want as an integer between 0, Sunday, and 6, Saturday.}
ObjectReference Property DayMarker Auto
{The marker that governs the position of the planets during a particular day.}

Bool bEnableDay = true

Event OnInit()
  RegisterForSingleLOSGain(Game.GetPlayer(), self)
  bEnableDay = !DayMarker.IsDisabled()
  EnableDisablePlanets()
EndEvent

Event OnUpdate()
  EnableDisablePlanets()
  RegisterForSingleUpdate(fSeconds)
EndEvent

Event OnGainLOS(Actor akViewer, ObjectReference akTarget)
  RegisterForSingleLOSLost(Game.GetPlayer(), self)
  RegisterForSingleUpdate(fSeconds)
  EnableDisablePlanets()
EndEvent

Event OnLostLOS(Actor akViewer, ObjectReference akTarget)
  RegisterForSingleLOSLost(Game.GetPlayer(), self)
  UnregisterForUpdate()
  EnableDisablePlanets()
EndEvent

Int Function GetDayOfWeek()
  return ((Utility.GetCurrentGameTime() as Int) % 7) as Int
EndFunction

Bool Function IsDayOfWeek()
  if iDayOfWeek != GetDayOfWeek()
    return false
  endif
  return true
EndFunction

Function EnableDisablePlanets()
  if bEnableDay != IsDayOfWeek()
    bEnableDay = !bEnableDay
      if bEnableDay
        Debug.Trace("Today's the day!")
        DayMarker.Enable()
      else
        Debug.Trace("Today is not the day.")
        DayMarker.DisableNoWait()
      endif
  endif
EndFunction

The first thing the script does is create four events: an OnInit event, which fires when the game is first loaded, when the cell is loaded via leaving, or time passes via the wait command; an OnUpdate event, which fires based upon our fSeconds float; and OnGainLOS and OnLostLOS events, which fire when the player looks at or away from the invisible markers at the center of the machine. These four events can be relied upon to keep the planets in their correct location no matter what the player does.

The final part of the script is the three functions that are needed for the four update events. The first function we make is an integer function called GetDayOfWeek. This function translates the current game day into an integer via modulo operation, which gives us a number between 0 and 6 that corresponds to the iDayOfWeek property we made at the beginning of the script.

The next function, IsDayOfWeek, is a bool function and uses GetDayOfWeek and the integer we give iDayOfWeek to either return true or false. If the integer for the current game day does not equal the integer of iDayOfWeek, the function returns false. Otherwise, it returns true.

The function EnableDisablePlanets checks to see if there is a disconnect between the bEnableDay bool and IsDayOfWeek. If there is, we flip the bool value of bEnableDay. If that value is positive, we enable some planets. If it is negative, we disable them immediately.

Design

  • Use the Dwemer kits to make the Dwemer ruins.

  • Place lights sparingly and use thematically appropriate colors to keep the level dusty and dark.

  • Create custom ambient cell lighting and distance fog.

  • Set the ruin’s music to the Dwemer preset and the acoustic space to the Dwemer preset.

  • Add appropriate clutter to give off the impression untouched ruins.

  • Place animated objects like gears, dust, and flames with corresponding sound effects.

  • Retexture and resize NetImmerse model files to create unique and original pieces.

Story

  • Write all books and supplemental material that flesh out the mod.

  • Edit Dwemer automaton AI packages so that they interact with the environment.

Encounters

  • Create navmesh, designate preferred AI paths, and link teleport markers from the previous cells.

  • Make trigger boxes with ambush scripts that activate the Dwemer automaton ambush markers.

  • Place the ambushes far enough apart so the player can have some breathing room and keep the player guessing for when they might appear next.

  • Stat the Dwemer colossus boss and give them it unique spells and abilities.

  • Adjust the AI behavior of the boss so it attack on sight, will never flee, help other automatons, and give it a wide aggro radius.

Models

  • Edit Skyrim’s NetImmerse files to create custom models with new diffuse and normal maps.

Scripts

  • Reuse on-enter triggers from Skyrim such as changing acoustic space and applying ambient noise, adding first- and third-person camera effects, and playing audio cues.

  • Create new scripts for ambushes, rotating objects, and activators.

Playtests

  • Look for spiderwebbing or seams into the void and remedy them.

  • Fix any Z-fighting by adjusting positions of static objects and sub-kits.

  • Install and test on computers with different hardware to check consistency.

  • Receive and integrate feedback from players knowledgeable in the RPG genre.

Download Links