Basic Programming Question

Post » Wed Jun 20, 2012 3:37 pm

This is so stupid, I know how to do this, but I'm drawing a complete blank. Basically what I need is a script that starts a quest if the player sleeps 8 or more hours. But for the life of me I can't think of how you make a 24 hour clock report the right amount of time that passed if the "wake up" hour is after midnight and the "sleep" hour before (for example, 3 AM - 23 PM = -20 hours instead of 4). I know this is like, CS 101 crap, but I totally forgot how you do this. Anyway, this is what the rest of it would look like I imagine.

Scriptname GoodNightsRest extends Game autoGlobalVariable Property SleepHour autoQuest Property WhateverQuest autoevent OnSleepStart()   int SleepyTime = Game.GetHour() as int   SleepHour.SetValue(SleepyTime)endEventevent OnSleepStop()   int EggsandBakey = Game.GetHour() as int   ;this part is obviously wrong   int sleepduration = EggsandBakey - SleepHour.GetValue() as int;this should be right though   if sleepduration >=8	  WhateverQuest.Start()   endIfendEvent
User avatar
Ana
 
Posts: 3445
Joined: Sat Jul 01, 2006 4:29 am

Post » Wed Jun 20, 2012 2:16 pm

Well for one thing, what if he slept 24 hours...EAB and SLT would be the same, resulting in zero. Is there an event that fires on the hours while sleeping? I know the hours count down while you sleep...if you can catch THOSE, you could count the number of cycles in a counter variable.
User avatar
Raymond J. Ramirez
 
Posts: 3390
Joined: Sun Oct 14, 2007 8:28 am

Post » Wed Jun 20, 2012 3:03 pm

Also, did you RegisterForSleep()? I don't see it here...
User avatar
Charlotte X
 
Posts: 3318
Joined: Thu Dec 07, 2006 2:53 am

Post » Thu Jun 21, 2012 1:23 am

The 24 hour thing isn't really a big concern of mine. First of all, who does that? Secondly, it would be pretty easy to put in:

if sleep duration >=8 || EggsandBakey == SleepHour.GetValue() as int   ;rest of codeendIf

I don't know what RegisterforSleep is though. Wiki time!
User avatar
Genevieve
 
Posts: 3424
Joined: Sun Aug 13, 2006 4:22 pm

Post » Wed Jun 20, 2012 8:49 pm

http://www.creationkit.com/GetCurrentGameTime_-_Utility
User avatar
Danii Brown
 
Posts: 3337
Joined: Tue Aug 22, 2006 7:13 am

Post » Wed Jun 20, 2012 7:00 pm

if you get the time OnSleepStart and OnSleepStop, you can just use math to compare against your condition
User avatar
Olga Xx
 
Posts: 3437
Joined: Tue Jul 11, 2006 8:31 pm

Post » Wed Jun 20, 2012 8:23 pm

Getting the current in game hour isn't as simple as Game.GetHour() unless you've written your own function called GetHour() that I'm not aware of. I was writing a script to toggle a light at 8PM and 6AM game time, the portion of script with the math looks like this:

Event OnInit()	RegisterForUpdateGameTime(2) ;; Checks the game time every 2 in-game hoursEndEventEvent OnUpdateGameTime() ;; <-- The event sent on the update that occurs every two hoursfloat GameTime = utility.GetCurrentGameTime()int GameTimeInt = (GameTime as int)float TOD = ((GameTime - GameTimeInt)*24)EndEvent

TOD represents the hour of the day, where 0 is midnight, 4 is 4AM, 8 is 8AM, 12 is NOON, 16 is 4PM, and 20 is 8PM. With some tweaking you can get the minutes too, but I'll leave that math up to you.


Anyway, looks like you're trying to do something like:



Scriptname SleepFor8Hours Extends ObjectReferenceQuest Property MyQuest AutoEvent OnSleepStart()RegisterForUpdateGameTime(8)EndEventEvent OnUpdate()	Int SleepState = Game.GetPlayer().GetSleepState()	If(SleepState == 3)	MyQuest.Start()	EndIf	EndEventEvent OnSleepStop()UnregisterForUpdateGameTimeEndEvent

That will do what you're looking to do if I understand correctly, without the need for calculating game time at all.
User avatar
suzan
 
Posts: 3329
Joined: Mon Jul 17, 2006 5:32 pm

Post » Wed Jun 20, 2012 6:26 pm

...There's a global variable called GameHour. It'll keep track of what the game hour is for you without you needing to do anything.

I thought there was a problem with OnUpdateGameTime() not firing if you're sleeping/waiting/fast traveling... BRB, going to test it.
User avatar
Hearts
 
Posts: 3306
Joined: Sat Oct 20, 2007 1:26 am

Post » Wed Jun 20, 2012 7:24 pm

It does fire, but the OnUpdate() event doesn't happen until the END of the sleep/wait/travel period instead of interrupting.

As for GameHour, wow, that would have been useful. Either way, the second script I posted will do what he needs without checking game time, so long as the Registration and OnUpdate events fire properly.

Is there a list of Global Vars somewhere or do I just have to go through the CK and find them myself?
User avatar
Robert Jackson
 
Posts: 3385
Joined: Tue Nov 20, 2007 12:39 am

Post » Wed Jun 20, 2012 1:40 pm

Yeah, I just tested and found out they do fire after you regain control. Doesn't make a very good timer then... But I also tried the GetSleepState() and since the update fires after you wake up, the script you posted wouldn't work. Didn't try with 'GetSleepState() == 4' though.

Anyway, I would use :

Scriptname SomeScript extends SomeThingfloat SleepStartTimeEvent SomeEvent(some parameters)    RegisterForSleep()EndEventEvent OnSleepStart()    SleepStartTime = Utility.GetCurrentGameTime()EndEventEvent OnSleepStop()    if (Utility.GetCurrentGameTime() - SleepStartTime >= 8.0)        ;do something    endifEndEvent

No, I don't know of a list of global variables. I just thought there would be one since Oblivion had it, and when I checked it was there.
User avatar
Emily Jeffs
 
Posts: 3335
Joined: Thu Nov 02, 2006 10:27 pm

Post » Wed Jun 20, 2012 11:34 am

int HoursSleptint TimeCheckEVENT OnUpdate()if ( TimeCheck == 0 )	 HoursSlept = QueryStat("Hours Slept")	 TimeCheck = 1endifif ( QueryStat("Hours Slept") > HoursSlept ) && ( TimeCheck == 1 )	 Debug.Notification("Player slept "+(QueryStat("Hours Slept") - HoursSlept)+" hours.")	 if ( (QueryStat("Hours Slept") - HoursSlept) >= 8 )			; do your stuff	 endif	 HoursSlept = QueryStat("Hours Slept")endifEndEVENT

Or

GlobalVariable Property GameDaysPassed  AutoGlobalVariable Property GameHour  Autoint Dayint TimeCheckfloat TimeFloatfloat TimeSpentEVENT OnUpdate()if ( TimeCheck == 0 )	 Day = GameDaysPassed.GetValueInt()	 TimeFloat = GameHour.GetValue()	 TimeCheck = 1endifif ( TimeCheck == 1 )if ( Day == GameDaysPassed.GetValueInt() )	 if ( TimeFloat != GameHour.GetValue() )		  TimeSpent = GameHour.GetValue() - TimeFloat	 endifelse	 TimeSpent = GameHour.GetValue() + (24.0 - TimeFloat)	 Day = GameDaysPassed.GetValueInt()endifendif; if TimeSpent >= 8 hours && Player has slept, do your stuffEndEVENT
User avatar
His Bella
 
Posts: 3428
Joined: Wed Apr 25, 2007 5:57 am

Post » Wed Jun 20, 2012 11:51 am

Thanks Aw3s0m3, that should work nicely. I should have thought of that to be honest.
User avatar
CArlos BArrera
 
Posts: 3470
Joined: Wed Nov 21, 2007 3:26 am

Post » Wed Jun 20, 2012 5:50 pm

I can't get Global Variable at all. The value always be 0.
And when I open the log it show this message "error: Cannot call GetValue() on a None object, aborting function call".

Below is simple function to trying to read "GameHour" global variable.
Scriptname testCustomChar01Lute extends ObjectReference{TestLute}GlobalVariable Property GameHour  Autofloat TimeFloatEVENT OnInit()Debug.Trace("This object is loaded, playing animations should work now") TimeFloat = GameHour.GetValue()Debug.messageBox("adsad"+TimeFloat)endEvent

When I using command, I can read and set the global variable but I can't with the script.
The global variable I get from script always be null.
User avatar
Cameron Wood
 
Posts: 3384
Joined: Wed Oct 31, 2007 3:01 pm

Post » Wed Jun 20, 2012 10:35 pm

http://www.creationkit.com/Bethesda_Tutorial_Papyrus_Introduction_to_Properties
User avatar
Pants
 
Posts: 3440
Joined: Tue Jun 27, 2006 4:34 am

Post » Wed Jun 20, 2012 9:19 am

Are you assigning the property to the global in the "Properties" button area of the script in your object?
User avatar
C.L.U.T.C.H
 
Posts: 3385
Joined: Tue Aug 14, 2007 6:23 pm

Post » Wed Jun 20, 2012 11:14 am

float GameTimefloat CurrentTime;CurrentTime == current hour of the dayGameTime = utility.GetCurrentGameTime()CurrentTime = Math.Floor(GameTime*24) - Math.Floor(GameTime)*24

Easier than messing with the global variable in my opinion. You could just put it into a function and have it return CurrentTime.
User avatar
Charlotte Lloyd-Jones
 
Posts: 3345
Joined: Fri Jun 30, 2006 4:53 pm

Post » Wed Jun 20, 2012 1:21 pm

Are you assigning the property to the global in the "Properties" button area of the script in your object?

lol, thanks I forgot to doing that.

But another problem, in a script I need to use global variable, isn't allow "properties".
So, I have to manually get the global variable value but I don't know how.
I had try to do something like this.
GlobalVariable globalVarFloat floatValglobalVar = Game.GetForm(0x02009989) as GlobalVariable ;02009989 is my global variable's form IDfloatVal = globalVar.GetValue()Debug.messageBox("adsad"+floatVal)endEVENT
Its show as null again in a log file. Maybe Global variable can't get from using "GetForm" function? Or I casting it wrong?
PS. The global variable that I really need isn't GameHour but it the one that I create for my mod.
User avatar
[ becca ]
 
Posts: 3514
Joined: Wed Jun 21, 2006 12:59 pm

Post » Wed Jun 20, 2012 12:33 pm

Form IDs change depending on the load order of the mod. What script are you using that doesn't allow properties?
User avatar
Charlie Sarson
 
Posts: 3445
Joined: Thu May 17, 2007 12:38 pm

Post » Wed Jun 20, 2012 11:10 am

It a Papyrus Fragment in an "On Begin Idle Event", inside AI Packages of Actors object.

But I manage to get "Lute music" by using "Form IDs" that way. But It seem doesn't work with Global Variable.
This is the code that I working on, It random play Lute music when NPC enter IdleLuteStart event.
int randomNumint musicIDint intSoundRefIDGlobalVariable globalSoundRefIDSound luteMusicglobalSoundRefID = Game.getForm(0x02009989) as GlobalVariableintSoundRefID = globalSoundRefID.getValueInt()randomNum = Utility.randomInt(1,4)Debug.MessageBox(intSoundRefID)if(randomNum == 1)musicID = 0x0010e444elseif(randomNum == 1)musicID = 0x0010e445elseif(randomNum == 1)musicID = 0x0010e446elsemusicID = 0x0010e447endifluteMusic = Game.GetForm(musicID) as SoundintSoundRefID = luteMusic.play(Game.GetPlayer())globalSoundRefID.setValueInt(intSoundRefID)
I need Global Variable to store a sound reference ID, to use it to stop music when animation is end or cancel.
(It can be cancel by talking to the NPC, but music will continue playing and if the NPC go back to playing
lute agian, it will play 2 music at the same time = =)
User avatar
Isaiah Burdeau
 
Posts: 3431
Joined: Mon Nov 26, 2007 9:58 am

Post » Wed Jun 20, 2012 4:40 pm

That's because the lute music is from skyrim.esm, which is always first in the load order. That means all of its items start with 00 as form IDs. If you want to be able to use your "0200..." form IDs, you would need to make sure your mod is always 3rd in the load order.

But anyway, it is possible to add properties to fragments. Now that you've compiled and saved the fragment, there should now be a script attached to your package. Edit the script, and add in the properties there.
User avatar
Amelia Pritchard
 
Posts: 3445
Joined: Mon Jul 24, 2006 2:40 am

Post » Wed Jun 20, 2012 10:06 am

That's because the lute music is from skyrim.esm, which is always first in the load order. That means all of its items start with 00 as form IDs. If you want to be able to use your "0200..." form IDs, you would need to make sure your mod is always 3rd in the load order.

But anyway, it is possible to add properties to fragments. Now that you've compiled and saved the fragment, there should now be a script attached to your package. Edit the script, and add in the properties there.
Oh yes! I see it now lol, how can I miss that.
Thank a lot :biggrin:

But if I need to get other objects from mod file via Papyrus, how can I get it if I can't use form IDs?
Edit: Answer to my self ... "properties" ... lol, silly me.
User avatar
Ian White
 
Posts: 3476
Joined: Thu Jul 19, 2007 8:08 pm


Return to V - Skyrim