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.