This is difficult to describe but I will try my best.
I have a very large script that performs a lot of things as part of my "main loop" in my mod. In the past, I was running into some scripting issues due to using RegisterForUpdate(), and having scripts pile up on top of one another. I have since switched to RegisterForSingleUpdate() chains. Everything works great, until script execution time exceeds 1 second, at which time you see this foolishness: http://i.imgur.com/bO3gj.jpg
The output you see here is my script's RegisterForSingleUpdate(5) taking over one second to run. It then rapid-fires 4 executions of the script, each taking about a second to complete. The time value at the end of the debug output is the time delta between script executions.
After seeing this, I decided to short-circuit my long, main loop with just a "return 1", to have it return almost instantly. The script runs like a swiss watch and the reported time delta between executions was about 5.01 seconds.
Next, I changed the RegisterForSingleUpdate(5) to RegisterForSingleUpdate(8), to see if that made a difference. I got this back.
http://i.imgur.com/NIIxL.jpg
The true / false you see at the end of the debug output is a variable that flips itself at the very end of the function's execution and ensures me that the script is indeed running to completion each of these times.
I have gone back several times and blocked off entire sections of code in my main function to see if there was one particular call or line that was causing this issue; the issue in every case comes up randomly, when the script reaches the magic 1-second execution time threshold, freaks out, and calls OnUpdate in rapid succession several times.
You can take a look at the script itself below if you like, but warning; it's gigantic (1550 lines). It needs a lot of cleaning up and entire blocks of code are commented out. If you do a ctrl+F search, look for "ZZZOK" and "ZZZBAD", there are the points where I "return 1" the function and everything stays stable (and under 1 second execution time). When you see ZZZBAD, I start seeing a problem and note my observations.
I don't mind breaking the script up into smaller pieces and using properties to pass values between them, that's fine. What I want to know is why isn't RegisterForSingleUpdate() doing it's job, and preventing another execution of the script until the entire script has run to completion? It shouldn't matter how long it takes to run the script; it should only register for the next update when the current one is finished!
Spoiler
Scriptname _DE_EPMonitor_1_6 extends Quest {Main loop.}import debugimport utilityActor property pPlayer autoGlobalVariable property GameHour auto{ Make this point to the GameHour global }GlobalVariable Property TimeScale Auto{Set this to point to the current TimeScale.}GlobalVariable Property _DE_ExposurePoints Auto{Exposure Points value}Quest property _DE_Main_1_6 autoQuest property _DE_TrackingQuest autoPlayerVampireQuestScript property VampireQuestRef autoimagespacemodifier property _DE_Cold3 autoimagespacemodifier property _DE_Cold4 autoimagespacemodifier property _DE_Cold5 auto;Rain cycle counters.bool property bRainLatch = false autoint property iRainCycleCounter = 0 autobool property pFTExceptionDetected = false auto{(Deprecated v1.6)Whether or not the player is near a Fast Travel Exception}FormList property _DE_HeatSources auto{Form list that stores the list of objects designated as heat sources.}FormList property _DE_FastTravelExceptions auto{Form list that stores the list of objects designated as fast travel exceptions (i.e. Carriages).}FormList property _DE_HeatSources_Big auto{Form list that stores the list of objects designated as "big" heat sources.}FormList property _DE_SleepObjects auto{Form list that stores the list of objects designated as exterior beds.}MiscObject property Firewood01 autoSpell property _DE_Hypo_Spell_0_2 auto{Warm.}Spell property _DE_Hypo_Spell_1 auto{Comfortable.}Spell property _DE_Hypo_Spell_2 auto{Cold.}Spell property _DE_Hypo_Spell_3 auto{Very Cold.}Spell property _DE_Hypo_Spell_4 auto{Freezing.}Spell property _DE_Hypo_Spell_5 auto{Freezing to Death.}Spell property _DE_NoWait_Spell autoSpell property _DE_SwimDetect_Dry auto{Spell that detects if the player is no longer swimming.}Spell property _DE_SwimDetect_Wet auto{Spell that detects if the player is currently swimming.}Spell property _DE_WetState_Spell auto{Spell that applies the "wet" shader effect.}spell property _DE_TorchState_Spell auto{Spell that applies Torch active effect.}Spell property _DE_FoodSpell1 autoSpell property _DE_Weathersense_Spell AutoSpell property _DE_SurvivalSkills_Spell autoSpell property _DE_WEARExamineArmor_Spell automagiceffect property FoodRestoreStaminaDuration automagiceffect property FoodRestoreHealthDuration automessage property _DE_HypoState_0a automessage property _DE_HypoState_0 automessage property _DE_HypoState_1 automessage property _DE_HypoState_2 automessage property _DE_HypoState_3 automessage property _DE_HypoState_4 automessage property _DE_HypoState_5 automessage property _DE_WetStateMsg_Wet automessage property _DE_WetStateMsg_Dry automessage property _DE_WetStateMsg_DryFire automessage property _DE_WarmUp automessage property _DE_ShutdownComplete automessage property _DE_FirstBootMsg automessage property _DE_FirstBoot_Confirm automessage property _DE_Travel_FireKit automessage property _DE_Travel_Firewood automessage property _DE_TravelOn autobool property pFTMessageLock auto{Logic lock that prevents "You are prepared to travel" spam in interiors.}GlobalVariable property _DE_FireNearState autoGlobalVariable property _DE_FireNearTime autoGlobalVariable property _DE_Count_FireKit auto;GlobalVariable property _DE_FastTravel_Allow auto ;Deprecated v1.6GlobalVariable property _DE_LastPosX autoGlobalVariable property _DE_LastPosY autoGlobalVariable property _DE_SwimState autoGlobalVariable property _DE_WetState autoGlobalVariable property _DE_WetTime autoGlobalVariable property _DE_EPDebug auto{1 = debug output on. 0 = off.}GlobalVariable property _DE_CurrentTemp autoGlobalVariable property _DE_LastVel autoGlobalVariable property _DE_LastFireState autoGlobalVariable property _DE_BadWeather autoGlobalVariable property _DE_BadWeatherType autoGlobalVariable property _DE_LastLocType autoGlobalVariable property _DE_Setting_ExposureRate2 autoGlobalVariable property _DE_Setting_FastTravel autoGlobalVariable property _DE_Setting_Shutdown autobool property pSetting_FastTravelDisable = false autobool property pSetting_NoWait = false autobool property pSetting_CombatDisable = true autoGlobalVariable property _DE_FirstBoot autoGlobalVariable property HirelingRecognizeJenassaCOPY0000 auto{Unused Skyrim ESM Global for exporting Exposure Point value to external scripts}Keyword property _DE_FoodBuffKeyword20 autoKeyword property _DE_FoodBuffKeyword30 autoKeyword property _DE_FoodBuffKeyword40 autoKeyword property _DE_FoodBuffKeyword50 autoKeyword property ClothingHands autoKeyword property ClothingHead autoKeyword property ClothingFeet autoKeyword property ClothingBody autoKeyword property ArmorGauntlets autoKeyword property ArmorHelmet autoKeyword property ArmorBoots autoKeyword property ArmorCuirass auto;Quest fragment replacement propertiesReferenceAlias property Alias_DE_Player autobook property _DE_SurvivorsGuide autoActivator property _DE_CampFireKit_PlacedUnlit_ACT autoweapon property Axe01 autoweapon property dunHaltedStreamPoachersAxe auto_DE_ClothingMonitor_1_6 property ClothingMonitorRef auto{Property to link to the Clothing Monitor script. Checks worn equipment.}bool property ShutdownState = false autostring[] property sWeatherFormID auto{Array that stores all of the FormIDs for all known vanilla weather types.}int[] property iWeatherTemp auto{Array that stores the corresponding temperature values for all known vanilla weather types.}int property thisLocType auto{The current Location Type.}int property LastLocType auto{The location type from the last update cycle.}WorldSpace property thisWorldSpace auto{The current worldspace.}WorldSpace property lastWorldSpace auto{The worldspace from the last update cycle.};Timer properties (usually for debug purposes);int property pRandomNum = 0 autofloat property pfThreadLastUpdateTime = 0.0 autofloat property pfLastUpdateTime autofloat property lastGameHour autofloat property fPointLoss auto{Stores the amount of EP lost during this update cycle.}bool property pFirstUpdate = true auto{Stores whether or not this was the first update cycle (for ignoring the first distance check).}int property pLastFastTravelState auto{The last known fast-travel state for the player.}bool property TorchState auto{Does the player have a torch equipped?}bool property PlayerCombatState = false auto{Is the player in combat?}int pRandomNumbool property pFlipper = false autoevent OnInit() pPlayer = Game.GetPlayer() ;notification("[debug]I just initialized v1.5.1 beta 2.") RegisterForSingleUpdate(8) ;_DE_Main.SetStage(0) ;Add detection spells to player (silently) pPlayer.AddSpell(_DE_SwimDetect_Dry, false) pPlayer.AddSpell(_DE_SwimDetect_Wet, false) _DE_Setting_Shutdown.SetValue(0) ;Make sure the user won't get a shutdown message at start! gotoState("polling")endeventstate pollingEvent OnUpdate() ;Store the Player reference pPlayer = Game.GetPlayer() Alias_DE_Player.ForceRefIfEmpty(pPlayer) if _DE_TrackingQuest.GetStage() == 0 ;Kicks things off for the player _DE_TrackingQuest.SetStage(10) endif ;What is the state of the primary quest? if ShutdownState == false ;if _DE_Main_1_6.IsRunning() MainLoop() ;endif endif if pRandomNum == 0 pRandomNum = utility.RandomInt() endif float fThreadTimeDelta = GetCurrentGameTime() - pfThreadLastUpdateTime ;(difference in game-time days) float fThreadTimeDeltaSec = (fThreadTimeDelta * 86400)/TimeScale.GetValueInt() ;(difference in real seconds) notification("ThreadID:" + pRandomNum + ", last update occurred " + fThreadTimeDeltaSec + "sec ago " + pFlipper) pfThreadLastUpdateTime = GetCurrentGameTime() RegisterForSingleUpdate(8) endEventendstatebool function MainLoop() ;notification("Main loop was called") ;=========================Thread timing debug======================== ;if pRandomNum == 0 ; pRandomNum = utility.RandomInt() ;endif ;float fThreadTimeDelta = GetCurrentGameTime() - pfThreadLastUpdateTime ;(difference in game-time days) ;notification("ThreadID " + pRandomNum + " " + GetCurrentGameTime() + " - " + pfThreadLastUpdateTime) ;float fThreadTimeDeltaSec = (fThreadTimeDelta * 86400)/TimeScale.GetValueInt() ;(difference in real seconds) ;float fWaitTime = (5.0 - fThreadTimeDeltaSec) ;if fThreadTimeDeltaSec < 5.0 ;notification("Thread " + pRandomNum + " waiting an additional " + fWaitTime + "...") ;utility.wait(5.0 - fThreadTimeDeltaSec) ;endif ;pfThreadLastUpdateTime = GetCurrentGameTime() ;=========================Thread timing debug======================== ;Make sure the player only has one of these books if pPlayer.GetItemCount(_DE_SurvivorsGuide) > 1 pPlayer.RemoveItem(_DE_SurvivorsGuide, 1, true) elseif pPlayer.GetItemCount(_DE_SurvivorsGuide) == 1 if _DE_TrackingQuest.GetStage() < 20 _DE_TrackingQuest.SetStage(20) endif endif ;Fill the Player quest alias if unfilled Alias_DE_Player.ForceRefIfEmpty(pPlayer) ;Add the Weathersense lesser power if the player doesn't already have it if !(pPlayer.HasSpell(_DE_Weathersense_Spell)) pPlayer.AddSpell(_DE_Weathersense_Spell) endif ;Add the Survival Skills lesser power if the player doesn't already have it if !(pPlayer.HasSpell(_DE_SurvivalSkills_Spell)) pPlayer.AddSpell(_DE_SurvivalSkills_Spell) endif ;Add the Inspect Equipment lesser power if the player doesn't already have it if !(pPlayer.HasSpell(_DE_WEARExamineArmor_Spell)) pPlayer.AddSpell(_DE_WEARExamineArmor_Spell) endif ;Initialize the Weather Array if uninitialized if sWeatherFormID == None || iWeatherTemp == None InitializeWeatherArray() ;Set up weather array endif ;Check for Wait Prevention if pSetting_NoWait == true ;If the player is inside, or near a bedroll, disable the spell if pPlayer.IsInInterior() || Game.FindClosestReferenceOfAnyTypeInList(_DE_SleepObjects, pPlayer.GetPositionX(), pPlayer.GetPositionY(), pPlayer.GetPositionZ(), 600.0) != None if pPlayer.HasSpell(_DE_NoWait_Spell) pPlayer.RemoveSpell(_DE_NoWait_Spell) endif else if !pPlayer.HasSpell(_DE_NoWait_Spell) pPlayer.AddSpell(_DE_NoWait_Spell, false) endif endif else if pPlayer.HasSpell(_DE_NoWait_Spell) pPlayer.RemoveSpell(_DE_NoWait_Spell) endif endif ;ZZZOK FastTravelCheck() ;Update the player's Fast Travel status ;====================Weather Discovery======================= ;What is the current weather? Weather MyWeather = Weather.GetCurrentWeather() ;Get the current temperature based on the weather int iCurrWeatherTemp = GetWeatherTemp(MyWeather) int maxTemp = GetExceptionBlockTemp() ;Store the temperature in a global so that other scripts can use it int iCurrTemp = 10 if maxTemp == 100 && iCurrWeatherTemp == 100 iCurrTemp = 10 else if maxTemp < iCurrWeatherTemp iCurrTemp = maxTemp else iCurrTemp = iCurrWeatherTemp endif endif _DE_CurrentTemp.SetValue(iCurrTemp) ;ZZZOK pLastFastTravelState = DistanceCheck() ;ZZZOK ;======================Player State========================== int iNearFire = GetFireState() ;ZZZOK int WetFactor = GetWetState(iNearFire) ;ZZZOK (Saw issue only once at start, script execution time regularly ~ 0.86sec) float FoodFactor = GetFoodState() float ClothingFactor = GetClothingState() float TorchFactor = GetTorchState() ;ZZZOK (saw issue several times at start, then never again) ;float CloakFactor = ClothingMonitorRef.fAux float CloakFactor = 0.1 float Auxfactor = 1 - (FoodFactor + TorchFactor + CloakFactor) ;ZZZWARN (saw issue more times than before) SetPlayerCombatState() ;ZZZBAD (See issue constantly) float FrostFactor = (pPlayer.GetAV("FrostResist")/100) ;notification("Frost Resist " + pPlayer.GetAV("FrostResist")/100) ;ZZZBAD (See issue constantly) int FireFactor = 6 float fTotalChange = 0 ;Apply fire values if necessary if iNearFire == 1 fTotalChange = FireFactor + currEPChange else fTotalChange = currEPChange endif ;=================Calculate Exposure Point Loss========================= float currEPChange = GetEPChange(iCurrTemp, WetFactor, ClothingFactor, FrostFactor, AuxFactor) ;=================Apply Exposure Point Loss============================= ApplyEP(currEPChange, fTotalChange, FireFactor, WetFactor, iNearFire) ;Take action based on EP value if _DE_ExposurePoints.GetValue() > 102 ;102 - Prevents acquiring this bonus due to "point bounce" if pPlayer.HasSpell(_DE_Hypo_Spell_0_2) if VampireQuestRef.VampireStatus >= 1 pPlayer.RemoveSpell(_DE_Hypo_Spell_0_2) endif else ;Remove all other effects pPlayer.RemoveSpell(_DE_Hypo_Spell_1) pPlayer.RemoveSpell(_DE_Hypo_Spell_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_3) pPlayer.RemoveSpell(_DE_Hypo_Spell_4) pPlayer.RemoveSpell(_DE_Hypo_Spell_5) ;Apply "Warm" condition if !(VampireQuestRef.VampireStatus >= 1) ;Vampires don't get the warmth bonus if (pPlayer.AddSpell(_DE_Hypo_Spell_0_2, false)) _DE_HypoState_0.Show() endif endif pPlayer.SetActorValue("SpeedMult", 100) ImageSpaceModifier.RemoveCrossFade(4.0) endif endif if _DE_ExposurePoints.GetValue() < 100 && _DE_ExposurePoints.GetValue() >= 81 if pPlayer.HasSpell(_DE_Hypo_Spell_1) if VampireQuestRef.VampireStatus >= 1 pPlayer.RemoveSpell(_DE_Hypo_Spell_1) endif else ;Remove all other effects pPlayer.RemoveSpell(_DE_Hypo_Spell_0_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_3) pPlayer.RemoveSpell(_DE_Hypo_Spell_4) pPlayer.RemoveSpell(_DE_Hypo_Spell_5) ;Apply "Comfortable" condition if !(VampireQuestRef.VampireStatus >= 1) if (pPlayer.AddSpell(_DE_Hypo_Spell_1, false)) _DE_HypoState_1.Show() endif endif pPlayer.SetActorValue("SpeedMult", 100) ImageSpaceModifier.RemoveCrossFade(4.0) endif endif if _DE_ExposurePoints.GetValue() < 81 && _DE_ExposurePoints.GetValue() >= 61 if pPlayer.HasSpell(_DE_Hypo_Spell_2) if VampireQuestRef.VampireStatus >= 1 pPlayer.RemoveSpell(_DE_Hypo_Spell_2) endif else ;Remove all other effects pPlayer.RemoveSpell(_DE_Hypo_Spell_0_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_1) pPlayer.RemoveSpell(_DE_Hypo_Spell_3) pPlayer.RemoveSpell(_DE_Hypo_Spell_4) pPlayer.RemoveSpell(_DE_Hypo_Spell_5) ;Apply "Cold" condition if !(VampireQuestRef.VampireStatus >= 1) if (pPlayer.AddSpell(_DE_Hypo_Spell_2, false)) _DE_HypoState_2.Show() endif endif pPlayer.SetActorValue("SpeedMult", 100) ImageSpaceModifier.RemoveCrossFade(4.0) endif endif if _DE_ExposurePoints.GetValue() < 61 && _DE_ExposurePoints.GetValue() >= 41 if pPlayer.HasSpell(_DE_Hypo_Spell_3) if VampireQuestRef.VampireStatus >= 1 pPlayer.RemoveSpell(_DE_Hypo_Spell_3) endif else ;Remove all other effects pPlayer.RemoveSpell(_DE_Hypo_Spell_0_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_1) pPlayer.RemoveSpell(_DE_Hypo_Spell_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_4) pPlayer.RemoveSpell(_DE_Hypo_Spell_5) ;Apply "Very Cold" condition if !(VampireQuestRef.VampireStatus >= 1) if (pPlayer.AddSpell(_DE_Hypo_Spell_3, false)) _DE_HypoState_3.Show() endif endif pPlayer.SetActorValue("SpeedMult", 100) _DE_Cold3.ApplyCrossFade(4.0) endif endif if _DE_ExposurePoints.GetValue() < 41 && _DE_ExposurePoints.GetValue() >= 21 if pPlayer.HasSpell(_DE_Hypo_Spell_4) if VampireQuestRef.VampireStatus >= 1 pPlayer.RemoveSpell(_DE_Hypo_Spell_4) endif else ;Remove all other effects pPlayer.RemoveSpell(_DE_Hypo_Spell_0_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_1) pPlayer.RemoveSpell(_DE_Hypo_Spell_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_3) pPlayer.RemoveSpell(_DE_Hypo_Spell_5) ;Apply "Freezing" condition if !(VampireQuestRef.VampireStatus >= 1) if (pPlayer.AddSpell(_DE_Hypo_Spell_4, false)) _DE_HypoState_4.Show() endif endif pPlayer.SetActorValue("SpeedMult", 80) _DE_Cold4.ApplyCrossFade(4.0) endif endif if _DE_ExposurePoints.GetValue() < 21 && _DE_ExposurePoints.GetValue() >= 1 if pPlayer.HasSpell(_DE_Hypo_Spell_5) if VampireQuestRef.VampireStatus >= 1 pPlayer.RemoveSpell(_DE_Hypo_Spell_5) endif else ;Remove all other effects pPlayer.RemoveSpell(_DE_Hypo_Spell_0_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_1) pPlayer.RemoveSpell(_DE_Hypo_Spell_2) pPlayer.RemoveSpell(_DE_Hypo_Spell_3) pPlayer.RemoveSpell(_DE_Hypo_Spell_4) ;Apply "Freezing to Death" condition if !(VampireQuestRef.VampireStatus >= 1) if (pPlayer.AddSpell(_DE_Hypo_Spell_5, false)) _DE_HypoState_5.Show() endif endif ;Apply imagespace modifier, and remove all others pPlayer.SetActorValue("SpeedMult", 60) _DE_Cold5.ApplyCrossFade(4.0) endif endif if _DE_ExposurePoints.GetValue() < 0 ;Oh no... if !(VampireQuestRef.VampireStatus >= 1) pPlayer.Kill() endif _DE_ExposurePoints.SetValue(0.0) endif if pFlipper == false pFlipper = true else pFlipper = false endif endFunctionfunction DebugEPReport(int myEP, bool myVel, bool myFire, bool myCap, int myInterior) ;notification("Debug Report was called") ;Builds a debug message for monitoring EP change if _DE_EPDebug.GetValueInt() == 1 ;continue else return endif string sVel = "" string sFire = "" string sCap = "" string sInterior = "" string sWet = "" if myVel == true sVel = "Warming" else sVel = "Cooling" endif if myFire == true sFire = "Fire Detected" else sFire = "No Fire" endif if myCap == true sCap = "/EP at Max" else sCap = "" endif if myInterior == 1 sInterior = "/Inside" elseif myInterior == 0 sInterior = "/Outside" else sInterior = "" endif if _DE_WetState.GetValueInt() == 1 sWet = "Wet" else sWet = "Dry" endif notification("EP: " + myEP + "/" + sWet + "/" + sVel + "/" + sFire + sInterior + sCap + " " + ((GameHour.GetValue() - lastGameHour) * 180) + "sec") ;debug.trace("Joe was here") lastGameHour = GameHour.GetValue() endFunctionfunction ApplyEP(float currEPChange, float fTotalChange, int FireFactor, int WetFactor, int iNearFire) ;This change caused script timing issues ;int dbInterior = 2 ;int dbChange = 2 ;bool dbFire = false ;bool dbCap = false ;if PlayerCombatState == false ; if iNearFire == 1 ; dbFire = true ; if ( _DE_ExposurePoints.GetValue() >= 120.0 ) ; if ( _DE_ExposurePoints.GetValue() > 120.0 ) ; ;Catch the bounce to show the player that they are completely warm ; _DE_HypoState_0a.Show() ; dbInterior = 2 ; dbChange = 2 ; dbCap = false ; endif ; dbInterior = 2 ; dbChange = 2 ; dbCap = true ; _DE_ExposurePoints.SetValue(120.0) ; HirelingRecognizeJenassaCOPY0000.SetValue(120) ;For external use ; else ; dbInterior = 2 ; dbChange = 2 ; dbCap = false ; _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() + FireFactor) ; HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) ; ;Tell the player that they're warming up (once) ; endif ; else ; dbFire = false ; if pPlayer.IsInInterior() ; ;do nothing ; dbInterior = 1 ; dbChange = 2 ; dbCap = false ; _DE_LastFireState.SetValue(0) ; else ; dbInterior = 0 ; if currEPChange < 0 ; if ( _DE_ExposurePoints.GetValue() >= 100.0 ) ; dbChange = 2 ; dbCap = true ; ;Not near a fire, temp going up, EP above 100; do nothing ; _DE_LastFireState.SetValue(0) ; else ;Not near a fire, temp going up, EP less than 100; set value ; dbChange = 1 ; dbCap = false ; _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() - currEPChange) ; HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) ; _DE_LastFireState.SetValue(0) ; endif ; else ; dbChange = 0 ; dbCap = false ; _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() - currEPChange) ; HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) ; _DE_LastFireState.SetValue(0) ; endif ; endif ; endif ; DebugEPReport(_DE_ExposurePoints.GetValueInt(), dbChange, dbFire, dbCap, dbInterior) ;endif ;====================================Pre - v1.6 =============================================== ;====================================Pre - v1.6 =============================================== if PlayerCombatState == false ;The player is not in combat! if iNearFire == 1 ;Near a fire if fTotalChange > 0 ;Up (warm) velocity if ( _DE_ExposurePoints.GetValue() >= 120.0 ) if ( _DE_ExposurePoints.GetValue() > 120.0 ) ;Catch the bounce to show the player that they are completely warm _DE_HypoState_0a.Show() endif _DE_ExposurePoints.SetValue(120.0) HirelingRecognizeJenassaCOPY0000.SetValue(120) ;For external use DebugEPReport(_DE_ExposurePoints.GetValueInt(), true, true, true, 2) else _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() + FireFactor) HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) DebugEPReport(_DE_ExposurePoints.GetValueInt(), true, true, false, 2) ;Tell the player that they're warming up (once) endif else ;Near a fire, cold area if pPlayer.IsInInterior() ;Is in interior _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() + FireFactor) HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) DebugEPReport(_DE_ExposurePoints.GetValueInt(), false, true, false, 1) else _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() + FireFactor) HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) DebugEPReport(_DE_ExposurePoints.GetValueInt(), false, true, false, 0) endif endif else ;Not near a fire if currEPChange < 0 ;Up (warm) velocity if ( _DE_ExposurePoints.GetValue() >= 100.0 ) ;Not near a fire, temp going up, EP above 100; do nothing DebugEPReport(_DE_ExposurePoints.GetValueInt(), true, false, true, 2) _DE_LastFireState.SetValue(0) else ;Not near a fire, temp going up, EP less than 100; set value _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() - currEPChange) HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) DebugEPReport(_DE_ExposurePoints.GetValueInt(), true, false, false, 2) _DE_LastFireState.SetValue(0) endif else ;Not near a fire, cold area if pPlayer.IsInInterior() ;Is in interior ;do nothing DebugEPReport(_DE_ExposurePoints.GetValueInt(), false, false, false, 1) _DE_LastFireState.SetValue(0) else _DE_ExposurePoints.SetValue(_DE_ExposurePoints.GetValue() - currEPChange) HirelingRecognizeJenassaCOPY0000.SetValue(_DE_ExposurePoints.GetValueInt()) DebugEPReport(_DE_ExposurePoints.GetValueInt(), false, false, false, 0) _DE_LastFireState.SetValue(0) endif endif endif endif ;====================================Pre - v1.6 =============================================== ;====================================Pre - v1.6 =============================================== endFunctionfloat function GetTorchState() if pPlayer.GetEquippedItemType(0) == 11 || pPlayer.GetEquippedItemType(1) == 11 ;If the player has a torch in either hand if (!pPlayer.HasSpell(_DE_TorchState_Spell)) ;If no spell, add it pPlayer.AddSpell(_DE_TorchState_Spell, false) endif return 0.1 ;10% bonus to Exposure Resistance else if pPlayer.HasSpell(_DE_TorchState_Spell) ;If spell, dispel it pPlayer.RemoveSpell(_DE_TorchState_Spell) endif return 0.0 endifendFunctionfunction SetPlayerCombatState() if pSetting_CombatDisable == true if pPlayer.GetCombatState() == 0 PlayerCombatState = false else PlayerCombatState = true endif else PlayerCombatState = false endifendFunctionfloat function GetFoodState() ;Go get this from another script running on the player alias return 0.0endFunction int function GetFireState() ;Find out if the player is standing near a heat source int iNearFire = 0 ;===============LtMattMoo's Camping Compatibility================= if Game.FindClosestReferenceOfAnyTypeInList(_DE_HeatSources, pPlayer.GetPositionX(), pPlayer.GetPositionY(), pPlayer.GetPositionZ(), 285.0) != None iNearFire = 1 elseif Game.FindClosestReferenceOfAnyTypeInList(_DE_HeatSources_Big, pPlayer.GetPositionX(), pPlayer.GetPositionY(), pPlayer.GetPositionZ(), 600.0) != None iNearFire = 1 else iNearFire = 0 endif if iNearFire == 1 _DE_FireNearTime.SetValue(GameHour.GetValue()) _DE_FireNearState.SetValue(1) ReportNearFire() return iNearFire else _DE_LastFireState.SetValue(0) _DE_FireNearState.SetValue(0) return iNearFire endif ;===============LtMattMoo's Camping Compatibility================= endFunction int function GetWetState(int iNearFire) ;Check if Wet int WetFactor = 0 if _DE_WetState.GetValueInt() == 1 if _DE_SwimState.GetValueInt() == 1 ;Player is still in the water WetFactor = 8 return WetFactor else ;if iNearFire == 1 ;Dry off immediately near fires ; _DE_WetState.SetValue(0) ; WetFactor = 0 ; pPlayer.RemoveSpell(_DE_WetState_Spell) ; _DE_WetStateMsg_DryFire.Show() ; return WetFactor ;else if GameHour.GetValue() - _DE_WetTime.GetValue() > 1 ;Dry off after an hour _DE_WetState.SetValue(0) WetFactor = 0 pPlayer.RemoveSpell(_DE_WetState_Spell) _DE_WetStateMsg_Dry.Show() return WetFactor else WetFactor = 8 ;Old value 2 return WetFactor endif endif else if pPlayer.HasSpell(_DE_WetState_Spell) ;Wet state sanity check pPlayer.RemoveSpell(_DE_WetState_Spell) endif endif endFunctionfloat function GetClothingState() ;float ClothingFactor = ClothingMonitorRef.fBody + ClothingMonitorRef.fHead + ClothingMonitorRef.fHands + ClothingMonitorRef.fFeet ;notification("ClothingFactor = " + ClothingFactor) float ClothingFactor = 3.0 return ClothingFactorendFunctionfunction ReportNearFire() ;Mostly controls the frequency which the player will see the "You begin to warm up" message. ;Makes this message less spammy in towns. if _DE_LastFireState.GetValueInt() == 0 if _DE_ExposurePoints.GetValueInt() < 100 ;Show the message if the player has less than 100EP _DE_WarmUp.Show() _DE_LastFireState.SetValue(1) else _DE_LastFireState.SetValue(1) ;Set this value, silently endif endifendFunctionfunction FastTravelCheck() ;Can the player fast-travel? if pSetting_FastTravelDisable == true ;(Immersion) Fast Travel Disabled Game.EnableFastTravel(false) elseif _DE_Setting_FastTravel.GetValueInt() == 1 ;Fast Travel Cost = On if pPlayer.GetItemCount(Axe01) > 0 || pPlayer.GetItemCount(dunHaltedStreamPoachersAxe) > 0 if pFTMessageLock == false _DE_TravelOn.Show() ;"You are now prepared to travel." Game.EnableFastTravel() pFTMessageLock = true endif else if pFTMessageLock == true Game.EnableFastTravel(false) pFTMessageLock = false endif endif else ;Fast Travel Cost = Off Game.EnableFastTravel() endifendFunctionint function DistanceCheck() ;Find the distance the player has traveled since the last update interval ;by calculating the hypotenuse between the two x and y positions float myPosX = pPlayer.GetPositionX() ;Get location float myPosY = pPlayer.GetPositionY() float myPosXdelta = math.abs(_DE_LastPosX.GetValue() - myPosX) ;Get distance float myPosYdelta = math.abs(_DE_LastPosY.GetValue() - myPosY) float myPosXdeltasq = math.pow(myPosXdelta, 2) ;a^2 float myPosYdeltasq = math.pow(myPosYdelta, 2) ;b^2 float myDistance = math.sqrt(myPosXdeltasq + myPosYdeltasq) ;c = sqrt(a^2 + b^2) ;If the distance has been greater than 30000 game units since the last update interval, ;the player has fast traveled far enough to consume a fire kit ;Check if greater than zero first; some forced fast travel from quests may ;cause this to fire, and we don't want the Fire Kit count dropping below zero if myDistance > 30000 ;Player moved more than 30000 game units since last update ;notification("Just moved...") if pFTExceptionDetected == false ;Player was not near a carriage ;notification("No exception...") if pPlayer.IsInInterior() thisLocType = 1 else thisLocType = 0 endif thisWorldSpace = pPlayer.GetWorldSpace() ;What worldspace are we in now? if lastLocType == thisLocType ;Both locations were exteriors (most likely) ;notification("Same LocType...") if thisWorldSpace == lastWorldSpace ;Both locations have the same worldspace ;The Player traveled; set the player's EP to 100 post-travel _DE_ExposurePoints.SetValue(100.0) else ;notification("Worldspace change!") endif endif endif endif ;Store the last known location type if pPlayer.IsInInterior() lastLocType = 1 else lastLocType = 0 endif ;Store the last Fast Travel exception status if Game.FindClosestReferenceOfAnyTypeInList(_DE_FastTravelExceptions, pPlayer.GetPositionX(), pPlayer.GetPositionY(), pPlayer.GetPositionZ(), 600.0) != None ;Don't eat a fire kit or firewood when the player is near certain things (carriages) pFTExceptionDetected = true ;notification("FT Exception Detected!") else pFTExceptionDetected = false ;notification("No FT Exceptions.") endif _DE_LastPosX.SetValue(pPlayer.GetPositionX()) _DE_LastPosY.SetValue(pPlayer.GetPositionY()) lastWorldSpace = pPlayer.GetWorldSpace() if myDistance > 30000 return 1 else return 0 endif ;notification("X:" + pPlayer.GetPositionX() + " Y:" + pPlayer.GetPositionY() + " Z:" + pPlayer.GetPositionZ()) endFunction float function GetEPChange(int iCurrWeatherTemp, int WetFactor, float ClothingFactor, float FrostFactor, float AuxFactor) ;Variables float fExtremeTemp = -50.0 float fExtremeMult = 3.0 float fStasisTemp = 10.0 float fStasisMult = 0.0 int iNightFactor = 0 ; notification("Temp = " + MyWeatherTemp) ;Is it daytime, or nighttime? if GameHour.GetValue() > 19 iNightFactor = 5 elseif GameHour.GetValue() < 7 iNightFactor = 5 else iNightFactor = 0 endif ;Calculate EP Loss ;Calculate the Temperature Multiplier based on a linear plot using the ;Extreme vs. Stasis values as given above. float fSlope = fExtremeMult/(fExtremeTemp-fStasisTemp) ;Rise (multiplier on Y-axis) over Run (distance from hemeostasis temperature) float fX = (iCurrWeatherTemp-iNightFactor) ;Plug in X (current weather temperature) float fB = (-fSlope + fStasisMult)*fStasisTemp ;Calculate Y-intercept ;notification("Y = " + fSlope + " * " + fX + " + " + fB) float fTempMultiplier = (fSlope * fX) + fB ;Slope-intercept form solving for Y ;notification("m" + fSlope + " x" + fX + " b" + fB) ;notification(iCurrWeatherTemp - iNightFactor) ;=====================Master EP Loss Function======================= ;First, determine the time in real seconds between the last update and this one float fTimeDelta = GetCurrentGameTime() - pfLastUpdateTime ;(difference in game-time days) float fTimeDeltaSec = (fTimeDelta * 86400)/TimeScale.GetValueInt() ;(difference in real seconds) ;float fTimeDivisor = ( (12 * fTimeDeltaSec) / 5 ) ;Ratio to ensure accuracy; if 5 is to 12, fTimeDelta is to pfTimeDivisor (x) ;if fTimeDivisor <= 1.0 ;Clamp to sane value ; fTimeDivisor = 1 ;endif ;if fTimeDeltaSec < 5.0 ; return 0 ;endif ;Did the player just wait outside in the cold? Let's find out if fTimeDeltaSec >= 360.0 ;Player just waited for 2 hours, or two hours has passed if pFirstUpdate == false ;Notification("5...") if pLastFastTravelState == 0 ;Player did not just recently fast-travel ;Notification("4...") if Game.FindClosestReferenceOfAnyTypeInList(_DE_SleepObjects, pPlayer.GetPositionX(), pPlayer.GetPositionY(), pPlayer.GetPositionZ(), 600.0) == None ;Player is not near an outdoor sleep object ;Notification("3...") if _DE_LastFireState.GetValueInt() == 0 ;Player is not near a heat source ;Notification("2...") if pPlayer.IsInInterior() == False ;Notification("Exterior wait detected!") ;The player waited while outdoors - hammer their EP for an amount corresponding to the temp if (iCurrWeatherTemp-iNightFactor) <= 5 && (iCurrWeatherTemp-iNightFactor) > 0 ;Chilly if _DE_ExposurePoints.GetValue() >= 70.0 _DE_ExposurePoints.SetValue(70.0) endif elseif (iCurrWeatherTemp-iNightFactor) <= 0 && (iCurrWeatherTemp-iNightFactor) > -5 ;Very Cold if _DE_ExposurePoints.GetValue() >= 60.0 _DE_ExposurePoints.SetValue(60.0) endif elseif (iCurrWeatherTemp-iNightFactor) <= -5 && (iCurrWeatherTemp-iNightFactor) > -15 ;Freezing if _DE_ExposurePoints.GetValue() >= 50.0 _DE_ExposurePoints.SetValue(50.0) endif elseif (iCurrWeatherTemp-iNightFactor) <= -15 ;Freezing if _DE_ExposurePoints.GetValue() >= 40.0 _DE_ExposurePoints.SetValue(40.0) endif endif endif else _DE_ExposurePoints.SetValue(120.0) ;Restore the player's EP when waiting by a fire. endif endif endif else ;notification("Ignoring First Update") pFirstUpdate = false endif elseif fTimeDeltaSec >= 180.0 ;Player just waited for 1 hours, or one hour has passed if pFirstUpdate == 1 ;Notification("5...") if pLastFastTravelState == 0 ;Player did not just recently fast-travel ;Notification("4...") if Game.FindClosestReferenceOfAnyTypeInList(_DE_SleepObjects, pPlayer.GetPositionX(), pPlayer.GetPositionY(), pPlayer.GetPositionZ(), 600.0) == None ;Player is not near an outdoor sleep object ;Notification("3...") if _DE_LastFireState.GetValueInt() == 0 ;Player is not near a heat source ;Notification("2...") if pPlayer.IsInInterior() == False ;Notification("Exterior wait detected!") ;The player waited while outdoors - hammer their EP for an amount corresponding to the temp if (iCurrWeatherTemp-iNightFactor) <= 5 && (iCurrWeatherTemp-iNightFactor) > 0 ;Chilly if _DE_ExposurePoints.GetValue() >= 80.0 _DE_ExposurePoints.SetValue(80.0) endif elseif (iCurrWeatherTemp-iNightFactor) <= 0 && (iCurrWeatherTemp-iNightFactor) > -5 ;Chilly if _DE_ExposurePoints.GetValue() >= 70.0 _DE_ExposurePoints.SetValue(70.0) endif elseif (iCurrWeatherTemp-iNightFactor) <= -5 && (iCurrWeatherTemp-iNightFactor) > -15 ;Very Cold if _DE_ExposurePoints.GetValue() >= 60.0 _DE_ExposurePoints.SetValue(60.0) endif elseif (iCurrWeatherTemp-iNightFactor) <= -15 ;Freezing if _DE_ExposurePoints.GetValue() >= 50.0 _DE_ExposurePoints.SetValue(50.0) endif endif endif else _DE_ExposurePoints.SetValue(120.0) ;Restore the player's EP when waiting by a fire. endif endif endif else ;notification("Ignoring First Update") pFirstUpdate = false endif elseif fTimeDeltaSec <= 10.0 ;Clamp point loss to 10-seconds between intervals fPointLoss = ((((((fTempMultiplier * 20) + WetFactor)/(ClothingFactor + FrostFactor)) * AuxFactor) * _DE_Setting_ExposureRate2.GetValue()) * fTimeDeltaSec) / 60 ;notification("Temp" + fTempMultiplier + " Wet" + WetFactor + " Cl" + ClothingFactor + " Fr" + FrostFactor + " Aux" + AuxFactor + " ER" + _DE_Setting_ExposureRate2.GetValue()) ;notification(fPointLoss + "points " + fTimeDeltaSec + " dTime") endif ;Now, calculate EP loss per minute, divided by the correct time factor given by the ratio: divide by 12 every 5 seconds pfLastUpdateTime = GetCurrentGameTime() ;=====================Master EP Loss Function======================= ;notification(pRandomNum + " " + fPointLoss + "points " + fTimeDeltaSec + " dTime") return fPointLoss ;return 0 ;notification("Temp = " + iCurrWeatherTemp + " TempMulti = " + fTempMultiplier)endfunctionfunction InitializeWeatherArray() sWeatherFormID = new string[83] ;Pine Forest sWeatherFormID[0] = "[Weather < (0000081A)>]" ;SkyrimClear sWeatherFormID[1] = "[Weather < (0010E1F2)>]" ;SkyrimClear_A sWeatherFormID[2] = "[Weather < (00012F89)>]" ;SkyrimCloudy sWeatherFormID[3] = "[Weather < (0010E1F1)>]" ;SkyrimCloudy_A sWeatherFormID[4] = "[Weather < (000C821E)>]" ;SkyrimFog sWeatherFormID[5] = "[Weather < (000C821F)>]" ;SkyrimOvercastRain ;BadWeather sWeatherFormID[6] = "[Weather < (000C8220)>]" ;SkyrimStormRain ;BadWeather ;Volcanic Tundra sWeatherFormID[7] = "[Weather < (0010A7A5)>]" ;SkyrimClearVT sWeatherFormID[8] = "[Weather < (0010E1E4)>]" ;SkyrimClearVT_A sWeatherFormID[9] = "[Weather < (0010A7A8)>]" ;SkyrimCloudyVT sWeatherFormID[10] = "[Weather < (0010E1E3)>]" ;SkyrimCloudyVT_A sWeatherFormID[11] = "[Weather < (0010A7A7)>]" ;SkyrimFogVT sWeatherFormID[12] = "[Weather < (0010A7A6)>]" ;SkyrimOvercastRainVT ;BadWeather ;Fall Forest sWeatherFormID[13] = "[Weather < (0010A23B)>]" ;SkyrimClearFF sWeatherFormID[14] = "[Weather < (0010E1EC)>]" ;SkyrimClearFF_A sWeatherFormID[15] = "[Weather < (0010A23F)>]" ;SkyrimCloudyFF sWeatherFormID[16] = "[Weather < (0010E1EB)>]" ;SkyrimCloudyFF_A sWeatherFormID[17] = "[Weather < (0010A23E)>]" ;SkyrimFogFF sWeatherFormID[18] = "[Weather < (0010A23D)>]" ;SkyrimOvercastRainFF ;BadWeather sWeatherFormID[19] = "[Weather < (0010A23C)>]" ;SkyrimStormRainFF ;BadWeather ;Reach sWeatherFormID[20] = "[Weather < (0010A237)>]" ;SkyrimClearRE sWeatherFormID[21] = "[Weather < (0010E1EA)>]" ;SkyrimClearRE_A sWeatherFormID[22] = "[Weather < (0010A23A)>]" ;SkyrimCloudyRE sWeatherFormID[23] = "[Weather < (0010E1E9)>]" ;SkyrimCloudyRE_A sWeatherFormID[24] = "[Weather < (0010A239)>]" ;SkyrimFogRE sWeatherFormID[25] = "[Weather < (0010A238)>]" ;SkyrimOvercastRainRE ;BadWeather ;Tundra sWeatherFormID[26] = "[Weather < (0010A240)>]" ;SkyrimClearTU sWeatherFormID[27] = "[Weather < (0010E1EE)>]" ;SkyrimClearTU_A sWeatherFormID[28] = "[Weather < (0010A243)>]" ;SkyrimCloudyTU sWeatherFormID[29] = "[Weather < (0010E1ED)>]" ;SkyrimCloudyTU_A sWeatherFormID[30] = "[Weather < (0010A242)>]" ;SkyrimOvercastRainTU ;BadWeather sWeatherFormID[31] = "[Weather < (0010a241)>]" ;SkyrimStormRainTU ;BadWeather ;Tundra Marsh sWeatherFormID[32] = "[Weather < (0010A230)>]" ;SkyrimClearMA sWeatherFormID[33] = "[Weather < (0010E1E6)>]" ;SkyrimClearMA_A sWeatherFormID[34] = "[Weather < (0010A233)>]" ;SkyrimCloudyMA sWeatherFormID[35] = "[Weather < (0010E1E5)>]" ;SkyrimCloudyMA_A sWeatherFormID[36] = "[Weather < (0010A232)>]" ;SkyrimFogMA sWeatherFormID[37] = "[Weather < (0010A231)>]" ;SkyrimOvercastRainMA ;BadWeather ;Coast sWeatherFormID[38] = "[Weather < (0010a234)>]" ;SkyrimClearCO sWeatherFormID[39] = "[Weather < (0010E1E8)>]" ;SkyrimClearCO_A sWeatherFormID[40] = "[Weather < (0010A236)>]" ;SkyrimCloudyCO sWeatherFormID[41] = "[Weather < (0010E1E7)>]" ;SkyrimCloudyCO_A sWeatherFormID[42] = "[Weather < (0010A235)>]" ;SkyrimFogCO ;Snowy sWeatherFormID[43] = "[Weather < (0010A244)>]" ;SkyrimClearSN sWeatherFormID[44] = "[Weather < (0010E1F0)>]" ;SkyrimClearSN_A sWeatherFormID[45] = "[Weather < (0010A244)>]" ;SkyrimCloudySN sWeatherFormID[46] = "[Weather < (0010E1EF)>]" ;SkyrimCloudySN_A sWeatherFormID[47] = "[Weather < (0004D7FB)>]" ;SkyrimOvercastSnow ;BadWeather ;Blizzard sWeatherFormID[48] = "[Weather < (000C8221)>]" ;SkyrimStormSnow ;BadWeather ;Misc sWeatherFormID[49] = "[Weather < (00048C14)>]" ;BlackreachWeather sWeatherFormID[50] = "[Weather < (0010FEF8)>]" ;SovngardeDark sWeatherFormID[51] = "[Weather < (0010D9EC)>]" ;SovngardeClear sWeatherFormID[52] = "[Weather < (000923FD)>]" ;SovngardeFog sWeatherFormID[53] = "[Weather < (0010199F)>]" ;SkyrimMQ206weather ;Misc sWeatherFormID[54] = "[Weather < (0000015e)>]" ;DefaultWeather sWeatherFormID[55] = "[Weather < (00105f40)>]" ;SkyrimDA02Weather sWeatherFormID[56] = "[Weather < (00106635)>]" ;KarthspireRedoubtFog sWeatherFormID[57] = "[Weather < (00105941)>]" ;BloatedMansGrottoFog sWeatherFormID[58] = "[Weather < (00104ab4)>]" ;SkuldafnCloudy sWeatherFormID[59] = "[Weather < (00105945)>]" ;SolitudeBluePalaceFog sWeatherFormID[60] = "[Weather < (00105944)>]" ;SolitudeBluePalaceFogNMARE sWeatherFormID[61] = "[Weather < (00105943)>]" ;SolitudeBluePalaceFogFEAR sWeatherFormID[62] = "[Weather < (00105942)>]" ;SolitudeBluePalaceFogARENA sWeatherFormID[63] = "[Weather < (000d9329)>]" ;HelgenAttackWeather sWeatherFormID[64] = "[Weather < (000d299e)>]" ;SkyrimOvercastWar sWeatherFormID[65] = "[Weather < (00101910)>]" ;FXWthrInvertLightMarkarth sWeatherFormID[66] = "[Weather < (000ecc96)>]" ;FXWthrInvertWindowsWindhelm2 sWeatherFormID[67] = "[Weather < (0010da13)>]" ;FXWthrInvertWfindowsWinterhold sWeatherFormID[68] = "[Weather < (0005ed7a)>]" ;FXWthrInvertLightsSolitude sWeatherFormID[69] = "[Weather < (0008282a)>]" ;FXWthrInvertLightsWhiterun sWeatherFormID[70] = "[Weather < (0008277a)>]" ;FXWthrInvertWindowsWhiterun sWeatherFormID[71] = "[Weather < (000aee84)>]" ;FXWthrInvertWindowsWindhelm sWeatherFormID[72] = "[Weather < (000777cf)>]" ;FXWthrInvertDayNighWarm sWeatherFormID[73] = "[Weather < (000d4886)>]" ;FXMagicStormRain ;BadWeather sWeatherFormID[74] = "[Weather < (00075491)>]" ;FXWthrSunlightWhite sWeatherFormID[75] = "[Weather < (0007548f)>]" ;FXWthrSunlight sWeatherFormID[76] = "[Weather < (00075de5)>]" ;FXWthrCaveBluePaleLight sWeatherFormID[77] = "[Weather < (0006ed5b)>]" ;FXWthrCaveBlueSkylight sWeatherFormID[78] = "[Weather < (0006ed5a)>]" ;FXWthrInvertDayNight sWeatherFormID[79] = "[Weather < (0010c32f)>]" ;FXSkyrimStormBlowingGrass sWeatherFormID[80] = "[Weather < (0002e7ab)>]" ;TESTCloudyRain sWeatherFormID[81] = "[Weather < (000a6858)>]" ;WorldMapWeather sWeatherFormID[82] = "[Weather < (0010e3d4)>]" ;EditorCloudPreview ;===========================================================; ; Daytime Temperature Values (in degrees C) ; ; ; ; Nighttime values are always -5 the daytime value ; ; ; ; Note: Only daytime values are returned from this ; ; function! ; ;===========================================================; iWeatherTemp = new int[83] ;Pine Forest iWeatherTemp[0] = 20 ;SkyrimClear iWeatherTemp[1] = 20 ;SkyrimClear_A iWeatherTemp[2] = 18 ;SkyrimCloudy iWeatherTemp[3] = 18 ;SkyrimCloudy_A iWeatherTemp[4] = 17 ;SkyrimFog iWeatherTemp[5] = 15 ;SkyrimOvercastRain iWeatherTemp[6] = 13 ;SkyrimStormRain ;Volcanic Tundra iWeatherTemp[7] = 18 ;SkyrimClearVT iWeatherTemp[8] = 18 ;SkyrimClearVT_A iWeatherTemp[9] = 16 ;SkyrimCloudyVT iWeatherTemp[10] = 16 ;SkyrimCloudyVT_A iWeatherTemp[11] = 15 ;SkyrimFogVT iWeatherTemp[12] = 13 ;SkyrimOvercastRainVT ;Fall Forest iWeatherTemp[13] = 12 ;SkyrimClearFF iWeatherTemp[14] = 12 ;SkyrimClearFF_A iWeatherTemp[15] = 10 ;SkyrimCloudyFF iWeatherTemp[16] = 10 ;SkyrimCloudyFF_A iWeatherTemp[17] = 9 ;SkyrimFogFF iWeatherTemp[18] = 7 ;SkyrimOvercastRainFF iWeatherTemp[19] = 5 ;SkyrimStormRainFF ;Reach iWeatherTemp[20] = 10 ;SkyrimClearRE iWeatherTemp[21] = 10 ;SkyrimClearRE_A iWeatherTemp[22] = 8 ;SkyrimCloudyRE iWeatherTemp[23] = 8 ;SkyrimCloudyRE_A iWeatherTemp[24] = 7 ;SkyrimFogRE iWeatherTemp[25] = 5 ;SkyrimOvercastRainRE ;Tundra iWeatherTemp[26] = 10 ;SkyrimClearTU ;old value:5 iWeatherTemp[27] = 10 ;SkyrimClearTU_A ;old value:5 iWeatherTemp[28] = 8 ;SkyrimCloudyTU ;old value:3 iWeatherTemp[29] = 8 ;SkyrimCloudyTU_A ;old value:3 iWeatherTemp[30] = 7 ;SkyrimOvercastRainTU ;old value:1 iWeatherTemp[31] = 5 ;SkyrimStormRainTU ;old value:-1 ;Tundra Marsh iWeatherTemp[32] = 1 ;SkyrimClearMA iWeatherTemp[33] = 1 ;SkyrimClearMA_A iWeatherTemp[34] = 0 ;SkyrimCloudyMA iWeatherTemp[35] = 0 ;SkyrimCloudyMA_A iWeatherTemp[36] = -1 ;SkyrimFogMA iWeatherTemp[37] = -3 ;SkyrimOvercastRainMA ;Coast iWeatherTemp[38] = -5 ;SkyrimClearCO iWeatherTemp[39] = -5 ;SkyrimClearCO_A iWeatherTemp[40] = -7 ;SkyrimCloudyCO iWeatherTemp[41] = -7 ;SkyrimCloudyCO_A iWeatherTemp[42] = -8 ;SkyrimFogCO ;Snowy iWeatherTemp[43] = -10 ;SkyrimClearSN iWeatherTemp[44] = -10 ;SkyrimClearSN_A iWeatherTemp[45] = -12 ;SkyrimCloudySN iWeatherTemp[46] = -12 ;SkyrimCloudySN_A iWeatherTemp[47] = -15 ;SkyrimOvercastSnow ;Blizzard iWeatherTemp[48] = -50 ;SkyrimStormSnow ;Misc iWeatherTemp[49] = 10 ;BlackreachWeather iWeatherTemp[50] = 20 ;SovngardeDark iWeatherTemp[51] = 20 ;SovngardeClear iWeatherTemp[52] = 20 ;SovngardeFog iWeatherTemp[53] = 40 ;SkyrimMQ206weather ;Misc iWeatherTemp[54] = 10 ;DefaultWeather iWeatherTemp[55] = 10 ;SkyrimDA02Weather iWeatherTemp[56] = 10 ;KarthspireRedoubtFog iWeatherTemp[57] = 10 ;BloatedMansGrottoFog iWeatherTemp[58] = 10 ;SkuldafnCloudy iWeatherTemp[59] = 10 ;SolitudeBluePalaceFog iWeatherTemp[60] = 10 ;SolitudeBluePalaceFogNMARE iWeatherTemp[61] = 10 ;SolitudeBluePalaceFogFEAR iWeatherTemp[62] = 10 ;SolitudeBluePalaceFogARENA iWeatherTemp[63] = 10 ;HelgenAttackWeather iWeatherTemp[64] = 10 ;SkyrimOvercastWar iWeatherTemp[65] = 10 ;FXWthrInvertLightMarkarth iWeatherTemp[66] = -8 ;FXWthrInvertWindowsWindhelm2 iWeatherTemp[67] = -10 ;FXWthrInvertWfindowsWinterhold iWeatherTemp[68] = 10 ;FXWthrInvertLightsSolitude iWeatherTemp[69] = 5 ;FXWthrInvertLightsWhiterun iWeatherTemp[70] = 5 ;FXWthrInvertWindowsWhiterun iWeatherTemp[71] = -8 ;FXWthrInvertWindowsWindhelm iWeatherTemp[72] = 10 ;FXWthrInvertDayNighWarm iWeatherTemp[73] = 10 ;FXMagicStormRain iWeatherTemp[74] = 10 ;FXWthrSunlightWhite iWeatherTemp[75] = 10 ;FXWthrSunlight iWeatherTemp[76] = 10 ;FXWthrCaveBluePaleLight iWeatherTemp[77] = 10 ;FXWthrCaveBlueSkylight iWeatherTemp[78] = 10 ;FXWthrInvertDayNight iWeatherTemp[79] = 5 ;FXSkyrimStormBlowingGrass iWeatherTemp[80] = 10 ;TESTCloudyRain iWeatherTemp[81] = 10 ;WorldMapWeather iWeatherTemp[82] = 10 ;EditorCloudPreview ;notification("Array initialized.")endFunctionint function GetExceptionBlockTemp() ;Location exception check float myX = pPlayer.GetPositionX() float myY = pPlayer.GetPositionY() float myZ = pPlayer.GetPositionZ() int maxTemp = 100 ;notification("Found weather!") ;Ensure that the player is in the Tamriel WorldSpace so we can check for location blocks if pPlayer.GetWorldSpace() == "[WorldSpace ]" ;High Hrothgar if (myX <= 74340 && myX >= 32000) && (myY <= -21000 && myY >= -66600) ;I am near High Hrothgar, set maximum temperature values based on altitude ; ~~~~ _ ~~~~ if myZ >= 34000 ;Elevation 4 ~~/~~\~~~~~~ maxTemp = -25 ; ~~~ / ~~\~~~ elseif myZ >= 27500 ;Elevation 3 / ?? \ maxTemp = -15 ; / . ~~ ?? \ elseif myZ >= 21300 ;Elevation 2 . . ~~~~ ??\ <----High Hrothgar maxTemp = -10 ; / . . ~~ ?? \ elseif myZ >= 15750 ;Elevation 1 / . . ?? \ maxTemp = -5 ; /######## ??########\ endif ; o ))))FUS RO DAH)))) ; [ ]|/={===> <----Dovahkiin ; / \ ; ;The Rift Block elseif (myX <= 210000 && myX >= 53800) && (myY <= -66600 && myY >= -150000) ;notification("I'm in The Rift Block") if myZ >= 16600 maxTemp = -10 endif ;Falkreath Hold Block elseif (myX <= 53800 && myX >= -42500) && (myY <= -66600 && myY >= -150000) ;notification("I'm in Falkreath Hold Block") if myZ >= 7300 maxTemp = -10 endif ;Bleak Falls Barrow Block elseif (myX <= 19400 && myX >= -42500) && (myY <= -15000 && myY >= -60900) ;notification("I'm in Black Falls Barrow Block") if myZ >= 1500 maxTemp = -10 endif ;Brittleshin Pass Block elseif (myX <= 15300 && myX >= -42500) && (myY <= -60900 && myY >= -80000) ;notification("I'm in Brittleshin Pass Block") if myZ >= 800 maxTemp = -10 endif ;Haafingar Block elseif (myX <= -52000 && myX >= -150000) && (myY <= 150000 && myY >= 78000) ;notification("I'm in Haafingar Block") if myZ >= -7000 maxTemp = -10 endif ;Tundra Marsh Block elseif (myX <= -30240 && myX >= -62200) && (myY <= 150000 && myY >= 57000) ;notification("I'm in Tundra Marsh Block") maxTemp = 1 ;The Pale Block 1 elseif (myX <= 46500 && myX >= -30240) && (myY <= 160000 && myY >= 30500) ;notification("I'm in Pale Block 1") if myZ >= -3100 maxTemp = -15 else maxTemp = -10 endif ;The Pale Block 2 elseif (myX <= 210000 && myX >= 46500) && (myY <= 160000 && myY >= 10140) ;notification("I'm in Pale Block 2") if myZ >= -3100 maxTemp = -15 else maxTemp = -10 endif else ;notification("I'm not in an Exception Block.") endif else ;notification("I'm not in Tamriel") endif return maxTemp endFunction int Function GetWeatherTemp(Weather wWeather) ;Now that the values are set up, let's perform the lookup int i = 0 while (i < sWeatherFormID.Length) if sWeatherFormID[i] == wWeather if i == 5 || i == 6 || i == 12 || i == 18 || i == 19 || i == 25 || i == 30 || i == 31 || i == 37 || i == 73 _DE_BadWeather.SetValue(1) _DE_BadWeatherType.SetValue(1) ;1 = rain, 2 = snow, 3 = blizzard if _DE_LastFireState.GetValueInt() == 0 ;I'm not near a fire if pPlayer.IsInInterior() == false ;I'm outside if bRainLatch == false iRainCycleCounter += 1 ;notification("Rain cycle " + iRainCycleCounter) if iRainCycleCounter >= 7 ;Wait about 10 update cycles before getting the player wet (a little over a minute) bRainLatch = true endif elseif bRainLatch == true ;notification("Making the player wet") _DE_WetState.SetValue(1) _DE_WetTime.SetValue(GameHour.GetValue()) if pPlayer.HasSpell(_DE_WetState_Spell) ;ignore else pPlayer.AddSpell(_DE_WetState_Spell, false) _DE_WetStateMsg_Wet.Show() endif endif endif else ;Player is near a fire, so reset values ;Reset rain timing values bRainLatch = false iRainCycleCounter = 0 endif elseif i == 47 _DE_BadWeather.SetValue(1) _DE_BadWeatherType.SetValue(2) ;1 = rain, 2 = snow, 3 = blizzard ;Reset rain timing values bRainLatch = false iRainCycleCounter = 0 elseif i == 48 _DE_BadWeather.SetValue(1) _DE_BadWeatherType.SetValue(3) ;1 = rain, 2 = snow, 3 = blizzard ;Reset rain timing values bRainLatch = false iRainCycleCounter = 0 else _DE_BadWeather.SetValue(0) ;Reset rain timing values bRainLatch = false iRainCycleCounter = 0 endif ;Return the lower of the two figures return iWeatherTemp[i] else i += 1 endif endwhile return 100 ;Lookup failed endFunctionfunction DepreciatedFunctions();;;;;;;;;;;Deprecated v1.6;;;;;;;;;;;;;;;;;;; ;Welcome to Frostfall! ;if _DE_FirstBoot.GetValueInt() == 2 ; int ibutton = _DE_FirstBootMsg.Show() ; if ibutton == 0 ; _DE_Setting_FastTravel.SetValue(1) ; _DE_FirstBoot.SetValue(1) ; _DE_FirstBoot_Confirm.Show() ; else ; _DE_Setting_FastTravel.SetValue(0) ; _DE_FirstBoot.SetValue(1) ; _DE_FirstBoot_Confirm.Show() ; endif ;endif ;;;;;;;;;;Deprecated v1.6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Deprecated v1.6;;;;;;;;;;;;;;;;;;; ;;Make super-duper sure that the player has these items ;if pPlayer.GetItemCount(Alias_DE_Backpack.GetRef()) == 0 ; ;notification("I don't have the backpack!") ; Alias_DE_Backpack.ForceRefIfEmpty(_DE_BackpackREF) ; pPlayer.AddItem(Alias_DE_Backpack.GetRef()) ;else ; ;notification("I have the backpack!") ;endif ;if pPlayer.GetItemCount(Alias_DE_Ring.GetRef()) == 0 ; ;notification("I don't have the ring!") ; Alias_DE_Ring.ForceRefIfEmpty(_DE_WeatherRingREF) ; pPlayer.AddItem(Alias_DE_Ring.GetRef()) ;else ; ;notification("I have the ring!") ;endif ;Ensure that the player only has one of these items ;if pPlayer.GetItemCount(_DE_Backpack) > 1 ; pPlayer.RemoveItem(_DE_Backpack, 1) ;endif ;if pPlayer.GetItemCount(_DE_WeatherRing) > 1 ; pPlayer.RemoveItem(_DE_WeatherRing, 1) ;endif ;;;;;;;;;;;;Deprecated v1.6;;;;;;;;;;;;;;;;;;;=====================v1.6 Deprecated Function - Mainly drove Fire Kit Cost functionality==================================endFunction 
