123hamster Posted October 7, 2021 Share Posted October 7, 2021 (edited) So I have a simple script that cast a spell whenever I get hit, which is attached to a permanent magic effect with conditions. Problem is, when I get hit by flame or frost it triggers like 100 times a second and crash my PC, before my conditions kick in to make it stop. How do I limit the event to trigger only once per second? Scriptname MagicCastOnHit extends ActiveMagicEffect {This script cast a spell on hit.};======================================================================================;; PROPERTIES /;=============/SPELL PROPERTY armorSpell AUTO;======================================================================================;; VARIABLES /;=============/Actor TargetActor;======================================================================================;; EVENTS /;=============/Event OnEffectStart(Actor Target, Actor Caster) TargetActor = TargetEndEventEvent OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) armorSpell.cast(TargetActor, TargetActor)EndEvent Edited October 7, 2021 by 123hamster Link to comment Share on other sites More sharing options...
rkkn Posted October 7, 2021 Share Posted October 7, 2021 (edited) One way to do it is to have the script go into a cooldown state as soon as the OnHit event is called, and then have the OnHit event do nothing while in cooldown state example: Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) GoToState("Cooldown") armorSpell.cast(TargetActor, TargetActor) RegisterForSingleUpdate(1) EndEvent State Cooldown Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) EndEvent EndState Event OnUpdate() GoToState("") EndEvent Edited October 7, 2021 by rkkn Link to comment Share on other sites More sharing options...
123hamster Posted October 7, 2021 Author Share Posted October 7, 2021 (edited) Thanks, it works great. Edit: Though I don't immediately crash, my video card still wind up freezing up after a while. I probably should avoid using this script. Edited October 7, 2021 by 123hamster Link to comment Share on other sites More sharing options...
123hamster Posted November 19, 2021 Author Share Posted November 19, 2021 Thanks again for the code, this wind up being very useful as a replacement for the original MagicPlayEffectShaderOnHitScript. I didn't realize the original script was this problematic. Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) GoToState("Cooldown") MagicEffectShader.play(TargetActor,ShaderDuration) RegisterForSingleUpdate(1) EndEvent State Cooldown Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) EndEvent EndState Event OnUpdate() GoToState("") EndEvent Link to comment Share on other sites More sharing options...
ReDragon2013 Posted November 20, 2021 Share Posted November 20, 2021 (edited) vanilla script as follow: Scriptname MagicPlayEffectShaderOnHitScript extends ActiveMagicEffect {This script plays an effect shader on hit.} ;======================================================================================; ; PROPERTIES / ;=============/ EffectShader property MagicEffectShader auto {The Effect Shader we want.} float property ShaderDuration = 0.00 auto {Duration of Effect Shader.} ;======================================================================================; ; VARIABLES / ;=============/ Actor TargetActor ;======================================================================================; ; EVENTS / ;=============/ Event OnEffectStart(Actor Target, Actor Caster) TargetActor = Target EndEvent Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) MagicEffectShader.play(TargetActor,ShaderDuration) endevent MagicPlayEffectShaderOnHitScript Scriptname MagicPlayEffectShaderOnHitScript extends ActiveMagicEffect {v1.5 ReDragon 2021} ; script plays an effect shader on hit ; https://forums.nexusmods.com/index.php?/topic/10580203-how-do-i-limit-a-script-event-to-trigger-once-a-second/ EffectShader PROPERTY MagicEffectShader auto ; The Effect Shader we want. Float PROPERTY ShaderDuration auto ; [default=0.0], duration of EffectShader ObjectReference Target ; as replacement for vanilla variable "TargetActor" ; -- EVENTs -- EVENT OnEffectStart(Actor akTarget, Actor akCaster) Target = akTarget as ObjectReference gotoState("Waiting") ; ### STATE ### ENDEVENT EVENT OnEffectFinish(Actor akTarget, Actor akCaster) gotoState("") ; ### STATE ### Target = None ENDEVENT ;=============================== State Waiting ;============ EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4) gotoState("CoolDown") ; ### STATE ### IF ( Target ) MagicEffectShader.Play(Target, ShaderDuration) RegisterForSingleUpdate(1.0) ENDIF ENDEVENT ;======= endState ;=============================== State CoolDown ; like rkkn version ;============= EVENT OnUpdate() IF ( Target ) gotoState("Waiting") ; ### STATE ### ENDIF ENDEVENT ;======= endState Edited November 20, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
123hamster Posted November 20, 2021 Author Share Posted November 20, 2021 Thanks for your interest. So just a n00b question, would Float PROPERTY ShaderDuration auto Work without modify every magical effect that uses this script? Do we have to go into each mage armor (and whatever else that uses it), and set property to 0.0? Link to comment Share on other sites More sharing options...
IsharaMeradin Posted November 20, 2021 Share Posted November 20, 2021 Thanks for your interest. So just a n00b question, would Float PROPERTY ShaderDuration auto Work without modify every magical effect that uses this script? Do we have to go into each mage armor (and whatever else that uses it), and set property to 0.0? Modify the original script and keep the property line as-is rather than changing it to the way ReDragon had it. You will then be able to have the default value of 0.0 for any records that do not have an overriding value assigned in the Creation Kit's property interface. float property ShaderDuration = 0.00 auto Link to comment Share on other sites More sharing options...
ReDragon2013 Posted November 20, 2021 Share Posted November 20, 2021 (edited) 123hamster asked: 1. "Work without modify every magical effect that uses this script?"YES 2. "Do we have to go into each mage armor (and whatever else that uses it), and set property to 0.0?"not really, see answer of IsharaMeradin Just in addition to IsharaMeradins posting to make the things hopefully more clearly.PapyrusSampleScript Scriptname PapyrusSampleScript extends Quest ; ObjectReference, ReferenceAlias, ActiveMAgicEffect etc. ; https://forums.nexusmods.com/index.php?/topic/10580203-how-do-i-limit-a-script-event-to-trigger-once-a-second/ ; Properties and script variables starts with a default value, if this value is not overriding ; - by script itself as new default ; - by using the Creation Kits property interface to change the default script value. ; ---------------- ; property samples ; ---------------- Float PROPERTY fTimer auto ; [default=0.0], the property starts with None which is the same as 0.0 ; exception: if another value has been set by CK, the CreationKit value is taken !!! ;Float PROPERTY fTimer = 0.0 auto Int PROPERTY iCounter auto ; [default=0] ;Int PROPERTY iCounter = 0 auto Bool PROPERTY bRun auto ; [default=False] ;Bool PROPERTY bRun = False auto ; ------------------------------------ Float PROPERTY fTimer1 = 1.0 auto ; [default=1.0], during papyrus script initialization the value of property "fTimer1" will be set to 1.0 ; exception: if another value has been set by CK, the CreationKit value is taken !!! Int PROPERTY iCounter1 = 1 auto Bool PROPERTY bRun1 = TRUE auto ; ---------------- ; variable samples ; ---------------- Float fTimer2 ; [default=0.0] ;Float fTimer2 = 0.0 Int iCounter2 ; [default=0] ;Int iCounter2 = 0 Bool bRun2 ; [default=False] ;Bool bRun2 = False ;----------------------- Float fTimer3 = 2.0 ; [default=2.0], during papyrus script initialization the value of variable "fTimer3" will be set to 2.0 Int iCounter3 = 2 Bool bRun3 = TRUE ; [default=TRUE], during .. value of variable "bRun3" will be set to TRUE Script initialization runs before event OnInit() is ready to start any code inside! And if event OnInit() has been finished any other event or function inside the script can be triggered or called. Thats the reason why anyone should avoid this: DO NOT DO THAT! EVENT OnInit() ; any code here Utility.Wait(1.0) ; or any other waittime here ; any code here ENDEVENT What is the different between (A) Float PROPERTY fTimer auto ; [default=0.0], the property starts with this value Int PROPERTY iCounter auto ; [default=0] Bool PROPERTY bRun auto ; [default=False]and these with property pre-selection by script (B) Float PROPERTY fTimer = 0.0 auto ; [default=0.0] Int PROPERTY iCounter = 0 auto ; [default=0] Bool PROPERTY bRun = False auto ; [default=False] (A) .variableTable .variable ::fTimer_var float .userFlags 0 .initialValue None ; None is here the same as 0.0 - FLOAT .endVariable .variable ::iCounter_var int .userFlags 0 .initialValue None ; None is here the same as 0 - INT .endVariable .variable ::bRun_var bool .userFlags 0 .initialValue None ; None is here the same as False - BOOL .endVariable .endVariableTable (B) .variableTable .variable ::fTimer_var float .userFlags 0 .initialValue 0.0 .endVariable .variable ::iCounter_var int .userFlags 0 .initialValue 0 .endVariable .variable ::bRun_var bool .userFlags 0 .initialValue False .endVariable .endVariableTable Edited November 20, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
123hamster Posted November 21, 2021 Author Share Posted November 21, 2021 (edited) alright cool, so I can just copy and compile as is with no esp changes? Thanks. Never would have thought that int/float/bool would make a difference when the code will run either way (but slower). Hopefully Mage Armor stop crashing my game when hit by multiple flame spells. Edited November 21, 2021 by 123hamster Link to comment Share on other sites More sharing options...
123hamster Posted November 21, 2021 Author Share Posted November 21, 2021 It works! 60 FPS. Would you mind uploading this fix on Nexus or should I do it? I can't be the only one who needed this fix. Link to comment Share on other sites More sharing options...
Recommended Posts