enderalse/source/scripts/_00e_potionanimationsc.psc

126 lines
5.8 KiB
Plaintext

Scriptname _00E_PotionAnimationSC extends activemagiceffect
; Credit for this script goes to ManaFlow and DavidSid! :)
Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
bool ThisIsSecondRun = SecondRun ; Store whether this is the second run of this script for a single potion use.
SecondRun = !SecondRun ; For some reason, the script runs twice on any potion use--probably a bug with OnItemRemoved. This and the conditional directly below this ensure every other run has no effect.
; Only run this once per item, only if the item is a potion or specified drink--for the latter, only if AnimateBeverages is 1--and only run this if the item was consumed rather than dropped or stored.
if !ThisIsSecondRun && (akBaseItem.HasKeyword(VendorItemPotion) || (AnimatedDrinks.HasForm(akBaseItem) && AnimateBeverages.GetValue())) && !akItemReference && !akDestContainer
DrinksQueued = DrinksQueued + 1 ; Add another drink to the queue.
if DrinksQueued == 1 ; Only run the setup routine once for any given drink queue.
Actor player = Game.GetPlayer()
int EscapeTimer = 0 ; How many times have we iterated any while loop since we started?
int EscapeTimeLimit = 100 ; How many tenths of a second will we wait for the while loops to finish?
bool EscapeClause = false ; This becomes true if EscapeTimer >= EscapeTimeLimit and halts the script ASAP.
float OldZ = player.Z ; Used in determining if the player is falling or jumping.
int atRest = 0 ; Used in determining if the player is in motion.
; Since Wait() only counts game time, this command ensures nothing happens until the player exits menu mode.
Utility.Wait(0.001)
; Disabling fighting controls causes the player to sheathe weapons if possible.
Game.DisablePlayerControls(abMovement = false)
; While the player is ragdolling, wait for him to finish.
while !EscapeClause && player.GetMass()
Utility.Wait(0.1)
if EscapeTimer >= EscapeTimeLimit
EscapeClause = true
endIf
EscapeTimer = EscapeTimer + 1
endWhile
; While the player is mounted, try to have him dismount every tenth-second.
while !EscapeClause && player.IsOnMount() && !player.IsDead()
player.Dismount()
Utility.Wait(0.1)
if EscapeTimer >= EscapeTimeLimit
EscapeClause = true
endIf
EscapeTimer = EscapeTimer + 1
endWhile
; While the player has a weapon drawn, try to have him sheathe it every tenth-second.
while !EscapeClause && player.IsWeaponDrawn() && !player.IsDead()
Game.DisablePlayerControls(abMovement = false)
Utility.Wait(0.1)
if EscapeTimer >= EscapeTimeLimit
EscapeClause = true
endIf
EscapeTimer = EscapeTimer + 1
endWhile
; Wait again for the player to finish ragdolling.
while !EscapeClause && player.GetMass()
Utility.Wait(0.1)
if EscapeTimer >= EscapeTimeLimit
EscapeClause = true
endIf
EscapeTimer = EscapeTimer + 1
endWhile
; Disable movement and view switching so the animation can play without interruption, and wait for the player to settle.
if !EscapeClause && !player.IsDead()
player.SetDontMove() ; This command works better than DisablePlayerControls because it doesn't cause enemies to stop attacking, it doesn't disable the HUD, and it prevents the player from sliding (which would slow down the next while loop). It does result in a slightly odd landing animation in 3rd-person.
Game.DisablePlayerControls(abMovement = false, abCamSwitch = true)
Utility.Wait(0.1)
endIf
; While the player is still falling or jumping, wait until he's at rest.
while !EscapeClause && Math.abs(player.Z - OldZ) > 1 && !player.IsDead()
OldZ = player.Z
Utility.Wait(0.1)
if EscapeTimer >= EscapeTimeLimit
EscapeClause = true
endIf
EscapeTimer = EscapeTimer + 1
endWhile
; Wait one last time for the player to finish ragdolling. (We do this three times so that if the player is thrown by Unrelenting Force at any point in execution, the animation is still almost certain to play.)
while !EscapeClause && player.GetMass()
Utility.Wait(0.1)
if EscapeTimer >= EscapeTimeLimit
EscapeClause = true
endIf
EscapeTimer = EscapeTimer + 1
endWhile
; Assuming the while loops didn't take too long, have the player go through the drinking animation.
if !player.IsDead() && !EscapeClause
Game.ShowFirstPersonGeometry(false) ; Disable first-person geometry so the player doesn't see his sheathed weapon or hands during the animation.
if !player.GetMass() ; GetMass returns 0 unless the player is ragdolling. If we try to play the animation while the player is ragdolling, it goes badly.
Debug.SendAnimationEvent(player, "IdleDrinkPotion") ; Start the animation.
endIf
Utility.Wait(0.05)
while DrinksQueued > 0
DrinksQueued = DrinksQueued - 1
if !player.GetMass()
Debug.SendAnimationEvent(player, "IdleDrinkPotion") ; The initial 1st-person drink only works correctly if this command is run twice consecutively; not sure why.
endIf
Utility.Wait(1.95)
if !player.GetMass()
Debug.SendAnimationEvent(player, "IdleStop") ; Abort the animation after a couple seconds, or 3rd-person will take significantly longer than 1st-person.
endIf
Utility.Wait(0.25)
endWhile
Utility.Wait(0.65)
Game.ShowFirstPersonGeometry(true) ; Reenable first-person geometry.
endIf
; Whatever else happens, reenable the player's controls and movement when the script finishes.
DrinksQueued = 0
player.SetDontMove(false)
Game.EnablePlayerControls()
endIf
endIf
endEvent
GlobalVariable Property AnimateBeverages Auto
FormList Property AnimatedDrinks Auto
Keyword Property VendorItemPotion Auto
int DrinksQueued = 0
bool SecondRun = false