How to make OnUpdate event update while player is resting, w

Post » Wed Jun 20, 2012 11:00 am

Here you can see the update event I'm talking about:

Event OnUpdate();Timescale adjuster so that the math is right no matter what scale player has set	float TSAdjust = TimeScale.GetValue()/60;Active and Natural detorioration levels (I don't care how it's spelled!);Natural detorioration is equal to 1 blood point every minute (default) and fraction of that is subtracted every second;Active detorioration is modified by toggleable powers and equals 0 if none are active	float DetActVar = DetAct.GetValue()*TSAdjust	float DetNatVar = DetNat.GetValue()*TSAdjust;Maximum and Current blood levels	float BloodCurVar = BloodCur.GetValue()-DetNatVar-DetActVar	float BloodMaxVar = BloodMax.GetValue();Updating globals	BloodCur.SetValue(BloodCurVar);Imposing bottom and top limits	If (BloodCurVar > BloodMaxVar)		BloodCur.SetValue(BloodMaxVar)	Elseif (BloodCurVar < 0)		BloodCur.SetValue(0)	Endif;Manage hunger state abilities	If (BloodCurVar <= 0 && Game.GetPlayer().HasSpell(HungerState5) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().AddSpell(HungerState5, false)		VampireStatus = 4		VampireProgression(Game.GetPlayer(), 4)		VampireStage4Message.Show()	Elseif (BloodCurVar <= 15*BloodMaxVar/100 && BloodCurVar > 0*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState4) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().AddSpell(HungerState4, false)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 3		VampireProgression(Game.GetPlayer(), 3)		VampireStageProgressionMessage.Show()	Elseif (BloodCurVar <= 30*BloodMaxVar/100 && BloodCurVar > 15*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState3) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().AddSpell(HungerState3, false)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 2		VampireProgression(Game.GetPlayer(), 2)		VampireStageProgressionMessage.Show()	Elseif (BloodCurVar <= 50*BloodMaxVar/100 && BloodCurVar > 30*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState2) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().AddSpell(HungerState2, false)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 2		VampireProgression(Game.GetPlayer(), 2)		VampireStageProgressionMessage.Show()	Elseif (BloodCurVar < 90*BloodMaxVar/100 && BloodCurVar > 50*BloodMaxVar/100 && (Game.GetPlayer().HasSpell(HungerState1) || Game.GetPlayer().HasSpell(HungerState2) || Game.GetPlayer().HasSpell(HungerState3) || Game.GetPlayer().HasSpell(HungerState4) || Game.GetPlayer().HasSpell(HungerState5)))		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 1		VampireProgression(Game.GetPlayer(), 1)	Elseif (BloodCurVar >= 90*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState1) == 0)		Game.GetPlayer().AddSpell(HungerState1, false)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 1		VampireProgression(Game.GetPlayer(), 1)	Endif		RegisterForSingleUpdate(1)  EndEvent

It's a single update chain (I tried normal update and GameTime update events but it made no difference ._.) that subtracts the current values of "DetNat" and "DetAct" from "BloodCur" every second.

Everything is alright during normal gameplay: every second the "BloodCur" global is modified.

But it stops working right while I wait, rest or fast travel: the script just stops during those events. I can sleep for 24 hours and "BloodCur" won't budge an inch during all that time! Only when fast travel or waiting is over it starts deteriorating again completely ignoring the time that passed during waiting!

Please can someone explain what I'm doing wrong?
User avatar
Brιonα Renae
 
Posts: 3430
Joined: Mon Oct 22, 2007 3:10 am

Post » Wed Jun 20, 2012 2:50 pm

All is normal, if you want to modify your "BloodCur" variable across time, you need more script to get the interval of seconds/mins/hours.

A lot of examples are given in this thread : http://www.gamesas.com/topic/1364036-basic-programming-question/

You will maybe need even more lines of code if you need to differentiate the different kinds of "time passing".
User avatar
willow
 
Posts: 3414
Joined: Wed Jul 26, 2006 9:43 pm

Post » Wed Jun 20, 2012 7:45 pm

Thank you! I looked at it and it gave me an idea!

I'd like to have a check in the OnUpdate event that checks how many minutes of game time have passed between current update and the last. This way I could detect if there was a large time jump like sleep or fast travel between subsequent updates!

But I have no idea how to do it ._.
User avatar
Vickytoria Vasquez
 
Posts: 3456
Joined: Thu Aug 31, 2006 7:06 pm

Post » Wed Jun 20, 2012 6:18 pm

I've done this for hunger management in my vampire mod. For starters, I don't recommend using OnUpdate. That's done in realtime. What you probably want is something done in gametime. Here's part of my scripts that hopefully can provide you some ideas

; Snatched from the PlayerWerewolfQuest Scriptfloat Function GameTimeDaysToGameTimeSeconds(float gametime) Trace("GameTimeDaysToGameTimeSeconds")    float gameSeconds = gametime * (60 * 60 * 24)    ;return (gameSeconds / TimeScale.Value) return gameSecondsEndFunctionfloat Function GameTimeSecondsToGameTimeDays(float gameTimeSeconds) Trace("GameTimeSecondsToGameTimeDays") return gameTimeSeconds / (60 * 60 * 24)EndFunctionEvent OnUpdateGameTime(); Check to see if the HungerDropDurationSeconds has been passedfloat currentTime = GameDaysPassed.GetValue()float hungerTime = BeluaNextHungerTime.GetValue(); More time has passed...how much???if(currentTime > hungerTime)  ; This checks to see how much time has passed (for instance player has hit T to wait, or FastTravelled  float timepassed = currentTime - hungerTime   ; Now divide the drop duration seconds by GameTimeDaysToGameTimeSeconds to get the multiplier  float hungerMultiplier = GameTimeDaysToGameTimeSeconds(timepassed) / BeluaHungerDropDurationSeconds.GetValue()   ; Just a fixup, since we're only checking if the currentTime is GREATER than the hungertime this should NEVER actually happen  ; But earlier checking up to see if it was >= the division would return a value smaller than 1  if(hungerMultiplier < 1)   hungerMultiplier = 1  endif   ; Multiply the drop amount and adjust the satiated level  float dropAmount = BeluaHungerDropAmount.GetValue() * hungerMultiplier  float tempBeluaSatiatedLevel = (BeluaSatiatedLevel.GetValue() - dropAmount) as int   ; don't let satiated level go into negative  if(tempBeluaSatiatedLevel < 0)   tempBeluaSatiatedLevel = 0  endif   BeluaSatiatedLevel.SetValue(tempBeluaSatiatedLevel)   ; update the next hunger time  UpdateBeluaNextHungerTime()   ;Call the Hunger Manager  VampireHungerManager(Player)endifEndEventFunction UpdateBeluaNextHungerTime() Trace("UpdateBeluaNextHungerTime") float currentTime = GameDaysPassed.GetValue();Currently I don't want to translate realtimeseconds into total gametime passed this way... float newhungerTime = currentTime + GameTimeSecondsToGameTimeDays(BeluaHungerDropDurationSeconds.GetValue()) BeluaNextHungerTime.SetValue(newhungerTime)EndFunction


-MM
User avatar
Monique Cameron
 
Posts: 3430
Joined: Fri Jun 23, 2006 6:30 am

Post » Wed Jun 20, 2012 11:00 am

Take a look at the examples, well my second script can return an interval of just 1 second, so maybe it is what you want.

But i have, just now, a huge issue for time-tracking. There are a few places where Cart Travel or Fast-Travel last more than 24 hours. And the problem is, that the game is just making the travel in one day max ?

Concretely i'm doing a Cart Travel from Markarth, starting on Morndas (Monday) at 23:30, with 260 days passed. And i'm arriving at Riften, between 0.00 and 1:00 A.M., but on Tirdas (Tuesday) instead of Middas (Wednesday) ! And the days passed are now only 261 instead of 262. The travel should have last 24 hours and some minutes, instead it lasted only less than one hour. I don't know what's happening, maybe it's me who's wrong, i will look further.
User avatar
WTW
 
Posts: 3313
Joined: Wed May 30, 2007 7:48 pm

Post » Thu Jun 21, 2012 2:18 am

What are your actual gamedayspassed values before and after the travel and not rounded up like an integer? It certainly sounds like that's VERY FAST travelling, but I wonder if it's possible it's a game day update bug. Skyrim had a bug where the game day was not updated properly at one point. I've actually never watched travel via cart that closely.
User avatar
Ross Zombie
 
Posts: 3328
Joined: Wed Jul 11, 2007 5:40 pm

Post » Wed Jun 20, 2012 7:40 pm

Yesssssssss! I did it!!!

I figured out how to check how much time passes between subsequent updates and then used the game time to real time conversion function from mofomojo's script to calculate how it translates to real time seconds and then multiplied it by my deterioration per second variable to see how much blood to remove from the player's pool! And it works! It works! It works! It WORKS!!! ^^

Thank you guys soooooo much!

Here is how I did it: maybe it will help someone else too!

float Property TimeOld Autofloat Property Thymanw Autofloat Property TimePassed Autofloat Function RealTimeSecondsToGameTimeDays(float realtime)	float scaledSeconds = realtime * TimeScale.Value	return scaledSeconds / (60 * 60 * 24)EndFunctionfloat Function GameTimeDaysToRealTimeSeconds(float gametime)	float gameSeconds = gametime * (60 * 60 * 24)	return (gameSeconds / TimeScale.Value)EndFunctionEvent OnUpdate();Timescale adjuster so that the math is right no matter what scale player has set	float TSAdjust = TimeScale.GetValue()/60;Active and Natural detorioration levels (I don't care how it's spelled!);Natural detorioration is equal to 1 blood point every minute (default);Active detorioration is modified by toggleable powers and equals 0 if none are active	float DetActVar = DetAct.GetValue()*TSAdjust	float DetNatVar = DetNat.GetValue()*TSAdjust;Maximum and Current blood levels	float BloodCurVar = BloodCur.GetValue()	float BloodMaxVar = BloodMax.GetValue();Checking for passage of time (including large time jumps like sleep, fast travel and so on)	Thymanw = GameDaysPassed.GetValue()	TimePassed = Thymanw - TimeOld	float DetMult = GameTimeDaysToRealTimeSeconds(TimePassed)	If TimeOld != 0		BloodCurVar = BloodCur.GetValue() - (DetActVar + DetNatVar)*DetMult	Endif;	Debug.MessageBox("This much game time has passed: " + TimePassed + " Old: " + TimeOld + " New: " + Thymanw);	Debug.MessageBox("This much real time has passed: " + DetMult + " seconds")	TimeOld = GameDaysPassed.GetValue();Updating globals	BloodCur.SetValue(BloodCurVar);Imposing bottom and top limits	If (BloodCurVar > BloodMaxVar)		BloodCur.SetValue(BloodMaxVar)	Elseif (BloodCurVar < 0)		BloodCur.SetValue(0)	Endif;Manage hunger state abilities	If (BloodCurVar <= 0 && Game.GetPlayer().HasSpell(HungerState5) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().AddSpell(HungerState5, false)		VampireStatus = 4		VampireProgression(Game.GetPlayer(), 4)		VampireStage4Message.Show()	Elseif (BloodCurVar <= 15*BloodMaxVar/100 && BloodCurVar > 0*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState4) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().AddSpell(HungerState4, false)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 3		VampireProgression(Game.GetPlayer(), 3)		VampireStageProgressionMessage.Show()	Elseif (BloodCurVar <= 30*BloodMaxVar/100 && BloodCurVar > 15*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState3) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().AddSpell(HungerState3, false)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 2		VampireProgression(Game.GetPlayer(), 2)		VampireStageProgressionMessage.Show()	Elseif (BloodCurVar <= 50*BloodMaxVar/100 && BloodCurVar > 30*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState2) == 0)		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().AddSpell(HungerState2, false)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 2		VampireProgression(Game.GetPlayer(), 2)		VampireStageProgressionMessage.Show()	Elseif (BloodCurVar < 90*BloodMaxVar/100 && BloodCurVar > 50*BloodMaxVar/100 && (Game.GetPlayer().HasSpell(HungerState1) || Game.GetPlayer().HasSpell(HungerState2) || Game.GetPlayer().HasSpell(HungerState3) || Game.GetPlayer().HasSpell(HungerState4) || Game.GetPlayer().HasSpell(HungerState5)))		Game.GetPlayer().RemoveSpell(HungerState1)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 1		VampireProgression(Game.GetPlayer(), 1)	Elseif (BloodCurVar >= 90*BloodMaxVar/100 && Game.GetPlayer().HasSpell(HungerState1) == 0)		Game.GetPlayer().AddSpell(HungerState1, false)		Game.GetPlayer().RemoveSpell(HungerState2)		Game.GetPlayer().RemoveSpell(HungerState3)		Game.GetPlayer().RemoveSpell(HungerState4)		Game.GetPlayer().RemoveSpell(HungerState5)		VampireStatus = 1		VampireProgression(Game.GetPlayer(), 1)	Endif		RegisterForSingleUpdate(1)	EndEvent
User avatar
Lisa
 
Posts: 3473
Joined: Thu Jul 13, 2006 3:57 am

Post » Wed Jun 20, 2012 4:37 pm

I did it!!!
Nice, don't forget though there's an issue with very long travels. Unless you don't mind that user(s) will not lose a whole day of blood hunger, but hey, it's a bit of cheat !

What are your actual gamedayspassed values before and after the travel and not rounded up like an integer? It certainly sounds like that's VERY FAST travelling, but I wonder if it's possible it's a game day update bug. Skyrim had a bug where the game day was not updated properly at one point. I've actually never watched travel via cart that closely.
So i've tried with GameDaysPassed as float, and unfortunately the poor Kibell is always driving his cart faster than light, doing a Markarth-Riften in 43 minutes top chrono.
No clue about what Papynuts and this haunted game are doing, but i still won with the help of a XMarker moved to Player at departure.

As Markarth-Riften in cart = 24 h 43 (average) && PlayerRef.GetDistance(XMarkerRef) = 355986.9 feet (average)
Player travels in exactly 24 h = (355986,9/(86400 + (43*60))*86400 = 345 664,96

Then i added 3 lines in the code :

TimeSpent = GameHour.GetValue() + (24.0 - LastTime)if ( PlayerRef.GetDistance(XMarkerRef) >= 345665.0) && ( TimeSpent < 6.0 )	 TimeSpent += 24.0 ; whole day of variables decreasesendif

And it works, even for fast-travel, but there's now another issue with FT, like Markarth City to Markarth Stables, because of the distance. No problem with Whiterun to WRStables though. I hope that Locations checks will solve it.

I will too make tests with Stamina = 500 (currently 100) to see if the Player Speed is modifying fast-travel time.
User avatar
Marilú
 
Posts: 3449
Joined: Sat Oct 07, 2006 7:17 am


Return to V - Skyrim