Jump to content

Shout scripting


ryanshowseason2

Recommended Posts

I should add that the script is attached to a reference alias, set to the player, on a "hidden" quest. I don't know if I create the quest correctly or not. I just started learning this stuff yesterday, so please forgive any noobish mistakes I made - but please let me know of them.

 

- new quest

- set ID and uncheck "Run Once"

- save (*)

- on quest aliases, add new reference alias

- set name

- set Fill Type to Specific Reference

- click Select Forced Reference

- set Cell to (any)

- wait a bit

- ref should set itself to PlayerRef ('Player') by default, select it if not

- save (*)

- add script to the reference alias

 

(*) On my first attempt, I created the quest, alias, added the script and then clicked OK all the way out and CK crashed on me. I read that if you create the quest and save it (and your active file) before adding the script, it won't crash. I tried that and it worked.

 

Wow, does it work as intended then? Do you have a working esp? I'd love to try it out!

Link to comment
Share on other sites

I got it working myself. I don't really know a lot about the ck but I managed even if I didn't know what I was doing. It seemed to work pretty much fine.

 

The engine seems to have a block from equipping an new shout right after using a shout, somewhere around half a second. I haven't seen any problems yet though. This should get published on the nexus though! I'm gonna see if theres anything else to be done with it.

Link to comment
Share on other sites

I've updated the script to add a "real" global cooldown of 1.5 seconds. I want to make it configurable in-game.

 

I still need to figure out how to determine if the spell cast was from a shout or not; otherwise casting a normal spell triggers the gcd.

 

I also want to add groupings such that a group of shouts share a cooldown. For example, grouping shouts into damage, buff, debuff, utility where each group shares a cooldown. And I want that configurable in-game.

 

Not sure what the problem you're describing is. I haven't noticed any problems doing a shout and being able to immediately change shouts using favorites or the magic menu. I haven't tried hotkeys yet. Put a Debug.MessageBox("boo!") after the part of the code that saves shout info. It should immediately pop up when you shout (it does for me).

 

I'd be interested in seeing anything else you do with this.

Link to comment
Share on other sites

exactly thats what I'm talking about. What do you mean by a global cooldown? like no shout would be able to be used for that time?

 

I think I did experience a bug the other day though. I switched to some of my shouts and found that their calculated cooldown was somewhere on the order of entire game hours for shouts like one word of whirlwind sprint. Not sure how the calculations went wrong...

Link to comment
Share on other sites

Yes, the global cooldown is how long no shout could be cast, but super short like a second or two. I thought it would represent the player having to draw in a breath before shouting again.

 

The bug might be from saving the game. I use GetCurrentRealTime because it returns seconds, but it is the number of seconds since the game launched. So, after playing for a while, saving, quitting, launching, loading, the saved timestamps would be large but current times would be small, resulting in negative numbers when calculating the difference. The code is assuming (i.e. not validating) diff will always be positive. It would end up calling SetVoiceRecoveryTime with a large negative value which probably jacks it up.

Link to comment
Share on other sites

ScriptName sgc_PlayerAliasScript Extends ReferenceAlias
{ detects equipping/casting shouts and manually manages the global cooldown }

Actor player
Shout[] shoutArray
Float[] recoveryArray
Float[] timestampArray
int howManyStored = 0
int MAXNUMBER = 128

Event OnInit()
   player = GetActorReference()
   shoutArray = New Shout[128] ;MAXNUMBER
   recoveryArray = New Float[128] ;MAXNUMBER
   timestampArray = New Float[128] ;MAXNUMBER
EndEvent

; ReferenceAlias scripts receive ObjectReference events
; shouting triggers OnSpellCast for the spell on the shout word
; record currently equipped shout and current recovery/time
Event OnSpellCast(Form akSpell)
   Spell sp = akSpell as Spell
   
   ;TODO: determine if spell type is "Voice Power"
   bool isVoicePower = (sp != None)
   If isVoicePower

       Shout currentShout = player.GetEquippedShout()
       Float recovery = player.GetVoiceRecoveryTime() ;seconds
       Float timestamp = Utility.GetCurrentRealTime() ;seconds
       
       int found = shoutArray.Find(currentShout)
       If found == -1
           If howManyStored < MAXNUMBER
               shoutArray[howManyStored] = currentShout
               recoveryArray[howManyStored] = recovery
               timestampArray[howManyStored] = timestamp
               howManyStored += 1
           EndIf
       Else
           recoveryArray[found] = recovery
           timestampArray[found] = timestamp
       EndIf

   EndIf
EndEvent

; ReferenceAlias scripts receive Actor events if pointing to an Actor
; equipping shouts triggers OnObjectEquipped, contrary to what wiki says
; check if equipped shout in array, calc/set remaining recovery
Event OnObjectEquipped(Form akBaseObject, ObjectReference akReference)
   Shout theShout = akBaseObject as Shout

   If theShout
       Float newRecovery = 0.0
       int found = shoutArray.Find(theShout)
       
       If found >= 0
           Float now = Utility.GetCurrentRealTime() ;seconds
           Float diff = now - timestampArray[found]
           
           If diff < recoveryArray[found]
               If diff > 0
                    newRecovery = recoveryArray[found] - diff
               Else
                    timestampArray[found] = now
                    newRecovery = recoveryArray[found]
               Endif
           EndIf
       EndIf

       player.SetVoiceRecoveryTime(newRecovery)
   EndIf
EndEvent

 

Perhaps an improvement or two then, diff should be greater than 0. If it is not then reset the timestamp to now and start the cooldown process for this shout over again? So you can't reload to get a 0 shout cooldown but you also won't have broken cooldowns.

Link to comment
Share on other sites

Yeah, that's fine. There are limited options to choose from, none of them perfect.

 

There some other potential issues related to time...

 

"Real time" is number of seconds since the game launched. Period. Meaning, it's not paused when the game is paused (e.g. in a menu). It does not advance with waiting/sleeping or anything else that affects game time. Saving games and loading games doesn't affect it. And, as we've found, it inherently resets when the game is launched. It's the absolute worst thing to use for this...

 

... except it's in seconds.

 

"Game time" is completely different and is exactly what should be used, except it's not in seconds. It's in days. Granted, it's a float, so technically it can be used. If the precision is high enough, the "diff" (as a very small fraction of a day) could be multiplied by 86400.0 to get seconds to compare to the stored cooldown (or divide the cooldown by 86400.0 to get days, but divides are much slower, especially floating point divides).

 

Time to do some tests...

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...