cdcooley Posted December 19, 2016 Share Posted December 19, 2016 If a state doesn't have a particular function defined then a default version of the function is used. It's either the one defined at the default state level (outside of any state declarations) or something inherited from the script that's being extended. Explicitly declaring an empty event in the state will always work. Simply leaving it undeclared may work, but only in certain cases. That's why seeing the entire script matters. Link to comment Share on other sites More sharing options...
lesi123 Posted December 19, 2016 Author Share Posted December 19, 2016 Here's my script that I have been testing: Scriptname BTDCREATUREtoPLAYERDmg extends ReferenceAlias {Script that handles Creature to Player bleed damage} ;--------------------------------------------------------------------------------------------------------------------------------------- ; The HitChance conditions in the function blocks control the hit chances to apply the bleed damage spells to targets. To increase the chances of applying a bleed, use a lower number. To reduce the chances of applying a bleed, use a higher number. ;--------------------------------------------------------------------------------------------------------------------------------------- Actor Property PlayerRef Auto Race Property WolfRace Auto Race Property SlaughterfishRace Auto Race Property SabreCatRace Auto Race Property SabreCatSnowyRace Auto Race Property BearBlackRace Auto Race Property BearBrownRace Auto Race Property BearSnowRace Auto Race Property IceWraithRace Auto Race Property WerewolfBeastRace Auto Race Property SprigganRace Auto Race Property SprigganMatronRace Auto Race Property TrollRace Auto Race Property TrollFrostRace Auto Race Property DwarvenSphereRace Auto Race Property DwarvenCenturionRace Auto Race Property DLC1DeathHoundRace Auto Race Property DLC1SabreCatGlowRace Auto Race Property SprigganEarthMotherRace Auto Race Property DLC1GargoyleRace Auto Race Property DLC1GargoyleVariantBossRace Auto Race Property DLC1GargoyleVariantGreenRace Auto Race Property DLC2SprigganBurntRace Auto Race Property DLC2WerebearBeastRace Auto Race Property DLC1LD_ForgemasterRace Auto Race Property DLC2DwarvenBallistaRace Auto Race Property DLC2dunKarstaagIceWraithRace Auto Race Property DragonRace Auto Spell Property BTDSpellCREATURESmalltoPLAYERBleedDmg Auto Spell Property BTDSpellCREATUREMediumtoPLAYERBleedDmg Auto Spell Property BTDSpellCREATURELargetoPLAYERBleedDmg Auto Spell Property BTDSpellCREATUREXLargetoPLAYERBleedDmg Auto Keyword Property ActorTypeAnimal Auto Keyword Property ActorTypeCreature Auto Keyword Property ActorTypeDwarven Auto Actor Aggressor Race AggressorRace Int HitChance ; Dragons and hagravens had to be excluded since their breaths and spells would apply bleeds to the player. ;------------------------------------------------------------------------------------------------------------------------ ; HIT REGISTERED ON PLAYER ;------------------------------------------------------------------------------------------------------------------------ Auto State Ready Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) GoToState("Busy") ; Don't run this function again until it's finished Aggressor = akAggressor as Actor if (akAggressor != None) && (akSource as Weapon) && (abHitBlocked != true) && (Aggressor.GetRace() != DragonRace) && !(akSource as Spell) if (Aggressor.HasKeyword(ActorTypeAnimal)) PlayerHitByAnimal(Aggressor) elseif (Aggressor.HasKeyword(ActorTypeCreature)) PlayerHitByCreature(Aggressor) elseif (Aggressor.HasKeyword(ActorTypeDwarven)) PlayerHitByDwarven(Aggressor) endif endif GoToState("Ready") ; The function has finished, so it can be called again EndEvent EndState State Busy Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) ; Nothing EndEvent EndState ;------------------------------------------------------------------------------------------------------------------------ ; FUNCTION BLOCKS ;------------------------------------------------------------------------------------------------------------------------ ; ---------- Player hit by an animal ---------- Function PlayerHitByAnimal(Actor Param1) AggressorRace = Aggressor.GetRace() HitChance = Utility.RandomInt() if ((AggressorRace == WolfRace) && (HitChance >= 70)) || ((AggressorRace == SlaughterfishRace) && (HitChance >= 30)) BTDSpellCREATURESmalltoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == SabreCatRace) && (HitChance >= 60)) || ((AggressorRace == SabreCatSnowyRace) && (HitChance >= 50)) || ((AggressorRace == BearBlackRace) && (HitChance >= 50)) || ((AggressorRace == BearBrownRace) && (HitChance >= 60)) || ((AggressorRace == BearSnowRace) && (HitChance >= 50)) || ((AggressorRace == DLC1SabreCatGlowRace) && (HitChance >= 50)) BTDSpellCREATUREMediumtoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == TrollRace) && (HitChance >= 60)) || ((AggressorRace == TrollFrostRace) && (HitChance >= 50)) BTDSpellCREATURELargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) endif EndFunction ; ---------- Player hit by a creature ---------- Function PlayerHitByCreature(Actor Param1) AggressorRace = Aggressor.GetRace() HitChance = Utility.RandomInt() if ((AggressorRace == DLC1DeathHoundRace) && (HitChance >= 70)) BTDSpellCREATURESmalltoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == IceWraithRace) && (HitChance >= 50)) || ((AggressorRace == DLC2dunKarstaagIceWraithRace) && (HitChance >= 50)) BTDSpellCREATUREMediumtoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == WerewolfBeastRace) && (HitChance >= 50)) || ((AggressorRace == SprigganRace) && (HitChance >= 60)) || ((AggressorRace == SprigganMatronRace) && (HitChance >= 50)) || ((AggressorRace == SprigganEarthMotherRace) && (HitChance >= 40)) || ((AggressorRace == DLC1GargoyleRace) && (HitChance >= 50)) || ((AggressorRace == DLC1GargoyleVariantBossRace) && (HitChance >= 40)) || ((AggressorRace == DLC1GargoyleVariantGreenRace) && (HitChance >= 50)) || ((AggressorRace == DLC2SprigganBurntRace) && (HitChance >= 60)) || ((AggressorRace == DLC2WerebearBeastRace) && (HitChance >= 50)) BTDSpellCREATURELargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) endif EndFunction ; ---------- Player hit by a dwarven automaton ---------- Function PlayerHitByDwarven(Actor Param1) AggressorRace = Aggressor.GetRace() HitChance = Utility.RandomInt() if ((AggressorRace == DwarvenSphereRace) && (HitChance >= 50)) BTDSpellCREATURELargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == DwarvenCenturionRace) && (HitChance >= 20)) || ((AggressorRace == DLC1LD_ForgemasterRace) || (AggressorRace == DLC2DwarvenBallistaRace) && (HitChance >= 10)) BTDSpellCREATUREXLargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) endif EndFunction I did two tests just now with a Sun Dragon from DD. Both tests were timed for 1min 30sec as soon as I spawned the dragon. My character was at the entrance to the cave leading from Helgen (save with no mods) and the only other NPC nearby was Rolof. The first test was with the script above as is. The log was 242kb. Image of the Papyrus Log Viewer: http://i.imgur.com/CsM7NdI.png The second test was with the OnHit Event in the Busy state marked out with ;. The log was 598kb. Image of the papyrus Log Viewer: http://i.imgur.com/XEzLEmy.png Link to comment Share on other sites More sharing options...
lofgren Posted December 19, 2016 Share Posted December 19, 2016 (edited) I believe all of the events in the base scripts are empty, so leaving the event undefined should always work. Edited December 19, 2016 by lofgren Link to comment Share on other sites More sharing options...
Masterofnet Posted December 19, 2016 Share Posted December 19, 2016 (edited) Here's my script that I have been testing: Would you please simply take 5 minutes to test the script I wrote? I think if you want that script to function well you need to shut down the event until all of the functions have been completed. I do not think the event being defined in the State has anything to do with this. Now that I can see the script you will have to do the first part like this. Auto State Ready Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) GoToState("Busy") ; Don't run this function again until it's finished Aggressor = akAggressor as Actor if (akAggressor != None) && (akSource as Weapon) && (abHitBlocked != true) && (Aggressor.GetRace() != DragonRace) && !(akSource as Spell) if (Aggressor.HasKeyword(ActorTypeAnimal)) PlayerHitByAnimal(Aggressor) elseif (Aggressor.HasKeyword(ActorTypeCreature)) PlayerHitByCreature(Aggressor) elseif (Aggressor.HasKeyword(ActorTypeDwarven)) PlayerHitByDwarven(Aggressor) Else GoToState("Ready") EndIf Else GoToState("Ready") Endif EndEvent EndState I believe all of the events in the base scripts are empty, so leaving the event undefined should always work. Have you ever seen an event defined in a empty state before? Edited December 19, 2016 by Masterofnet Link to comment Share on other sites More sharing options...
lesi123 Posted December 19, 2016 Author Share Posted December 19, 2016 Would you please simply take 5 minutes to test the script I wrote? I think if you want that script to function well you need to shut down the event until all of the functions have been completed. I do not think the event being defined in the State has anything to do with this. Whoops, I didn't see the other changes in the script. My bad! Just did the same test as the others with all of your changes and had no errors in the log (24kb file). I also spawned in some wolves to double check the hits were registering from races that could give the player bleeds; so far so good! I will continue testing and hope that this was the last scripting hurdle. Thank you very much for all of your help guys! Link to comment Share on other sites More sharing options...
Masterofnet Posted December 20, 2016 Share Posted December 20, 2016 (edited) Just did the same test as the others with all of your changes and had no errors in the log (24kb file). I also spawned in some wolves to double check the hits were registering from races that could give the player bleeds; so far so good! I will continue testing and hope that this was the last scripting hurdle. Thank you very much for all of your help guys! Great! It is always fun to help someone who is willing to do some testing. If you wanted to put an empty function in the Busy State maybe you could find one that would be less likely to get called. BTW I have never seen that done or heard of doing it before this thread. Where did you get the idea to put the OnHit event in the Empty "Busy" State? Edited December 20, 2016 by Masterofnet Link to comment Share on other sites More sharing options...
lofgren Posted December 20, 2016 Share Posted December 20, 2016 Of course I have seen an event defined in the empty state. What a weird question. Link to comment Share on other sites More sharing options...
lesi123 Posted December 20, 2016 Author Share Posted December 20, 2016 Great! It is always fun to help someone who is willing to do some testing. If you wanted to put an empty function in the Busy State maybe you could find one that would be less likely to get called. BTW I have never seen that done or heard of doing it before this thread. Where did you get the idea to put the OnHit event in the Empty "Busy" State? ScriptName LongFunctionScript extends ObjectReference Function LongFunction() GoToState("Busy") ; Don't run this function again until it's finished ; Do something that takes a long time GoToState("Waiting") ; The function has finished, so it can be called again EndFunction State Busy Function LongFunction() ; Do nothing EndFunction EndState On the Cipscis site's example above, I simply replaced LongFunction with OnHit. I thought maybe it was serving an important purpose being there. :| Link to comment Share on other sites More sharing options...
lesi123 Posted December 20, 2016 Author Share Posted December 20, 2016 Well, I spoke too soon. I fought the dragon for longer this time (a little over 5 minutes) and ended up with stack dumps again, log at 3,285kb. The script below is what I'm using. It takes longer to start dumping stacks but it seems to still have trouble keeping up. Scriptname BTDCREATUREtoPLAYERDmg extends ReferenceAlias {Script that handles Creature to Player bleed damage} ;--------------------------------------------------------------------------------------------------------------------------------------- ; The HitChance conditions in the function blocks control the hit chances to apply the bleed damage spells to targets. To increase the chances of applying a bleed, use a lower number. To reduce the chances of applying a bleed, use a higher number. ;--------------------------------------------------------------------------------------------------------------------------------------- Actor Property PlayerRef Auto Race Property WolfRace Auto Race Property SlaughterfishRace Auto Race Property SabreCatRace Auto Race Property SabreCatSnowyRace Auto Race Property BearBlackRace Auto Race Property BearBrownRace Auto Race Property BearSnowRace Auto Race Property IceWraithRace Auto Race Property WerewolfBeastRace Auto Race Property SprigganRace Auto Race Property SprigganMatronRace Auto Race Property TrollRace Auto Race Property TrollFrostRace Auto Race Property DwarvenSphereRace Auto Race Property DwarvenCenturionRace Auto Race Property DLC1DeathHoundRace Auto Race Property DLC1SabreCatGlowRace Auto Race Property SprigganEarthMotherRace Auto Race Property DLC1GargoyleRace Auto Race Property DLC1GargoyleVariantBossRace Auto Race Property DLC1GargoyleVariantGreenRace Auto Race Property DLC2SprigganBurntRace Auto Race Property DLC2WerebearBeastRace Auto Race Property DLC1LD_ForgemasterRace Auto Race Property DLC2DwarvenBallistaRace Auto Race Property DLC2dunKarstaagIceWraithRace Auto Race Property DragonRace Auto Spell Property BTDSpellCREATURESmalltoPLAYERBleedDmg Auto Spell Property BTDSpellCREATUREMediumtoPLAYERBleedDmg Auto Spell Property BTDSpellCREATURELargetoPLAYERBleedDmg Auto Spell Property BTDSpellCREATUREXLargetoPLAYERBleedDmg Auto Keyword Property ActorTypeAnimal Auto Keyword Property ActorTypeCreature Auto Keyword Property ActorTypeDwarven Auto Actor Aggressor Race AggressorRace Int HitChance ; Dragons and hagravens had to be excluded since their breaths and spells would apply bleeds to the player ;------------------------------------------------------------------------------------------------------------------------ ; HIT REGISTERED ON PLAYER ;------------------------------------------------------------------------------------------------------------------------ Auto State Ready Event OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked) GoToState("Busy") ; Don't run this OnHit Event again until it's finished Aggressor = akAggressor as Actor if (akAggressor != None) && (akSource as Weapon) && (abHitBlocked != true) && (Aggressor.GetRace() != DragonRace) && !(akSource as Spell) if (Aggressor.HasKeyword(ActorTypeAnimal)) PlayerHitByAnimal(Aggressor) elseif (Aggressor.HasKeyword(ActorTypeCreature)) PlayerHitByCreature(Aggressor) elseif (Aggressor.HasKeyword(ActorTypeDwarven)) PlayerHitByDwarven(Aggressor) else GoToState("Ready") ; The OnHit Event has finished, so it can be called again endif else GoToState("Ready") ; The OnHit Event has finished, so it can be called again endif EndEvent EndState State Busy ; Nothing EndState ;------------------------------------------------------------------------------------------------------------------------ ; FUNCTION BLOCKS ;------------------------------------------------------------------------------------------------------------------------ ; ---------- Player hit by an animal ---------- Function PlayerHitByAnimal(Actor Param1) AggressorRace = Aggressor.GetRace() HitChance = Utility.RandomInt() if ((AggressorRace == WolfRace) && (HitChance >= 70)) || ((AggressorRace == SlaughterfishRace) && (HitChance >= 30)) BTDSpellCREATURESmalltoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == SabreCatRace) && (HitChance >= 60)) || ((AggressorRace == SabreCatSnowyRace) && (HitChance >= 50)) || ((AggressorRace == BearBlackRace) && (HitChance >= 50)) || ((AggressorRace == BearBrownRace) && (HitChance >= 60)) || ((AggressorRace == BearSnowRace) && (HitChance >= 50)) || ((AggressorRace == DLC1SabreCatGlowRace) && (HitChance >= 50)) BTDSpellCREATUREMediumtoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == TrollRace) && (HitChance >= 60)) || ((AggressorRace == TrollFrostRace) && (HitChance >= 50)) BTDSpellCREATURELargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) endif GoToState("Ready") ; The OnHit Event has finished, so it can be called again EndFunction ; ---------- Player hit by a creature ---------- Function PlayerHitByCreature(Actor Param1) AggressorRace = Aggressor.GetRace() HitChance = Utility.RandomInt() if ((AggressorRace == DLC1DeathHoundRace) && (HitChance >= 70)) BTDSpellCREATURESmalltoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == IceWraithRace) && (HitChance >= 50)) || ((AggressorRace == DLC2dunKarstaagIceWraithRace) && (HitChance >= 50)) BTDSpellCREATUREMediumtoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == WerewolfBeastRace) && (HitChance >= 50)) || ((AggressorRace == SprigganRace) && (HitChance >= 60)) || ((AggressorRace == SprigganMatronRace) && (HitChance >= 50)) || ((AggressorRace == SprigganEarthMotherRace) && (HitChance >= 40)) || ((AggressorRace == DLC1GargoyleRace) && (HitChance >= 50)) || ((AggressorRace == DLC1GargoyleVariantBossRace) && (HitChance >= 40)) || ((AggressorRace == DLC1GargoyleVariantGreenRace) && (HitChance >= 50)) || ((AggressorRace == DLC2SprigganBurntRace) && (HitChance >= 60)) || ((AggressorRace == DLC2WerebearBeastRace) && (HitChance >= 50)) BTDSpellCREATURELargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) endif GoToState("Ready") ; The OnHit Event has finished, so it can be called again EndFunction ; ---------- Player hit by a dwarven automaton ---------- Function PlayerHitByDwarven(Actor Param1) AggressorRace = Aggressor.GetRace() HitChance = Utility.RandomInt() if ((AggressorRace == DwarvenSphereRace) && (HitChance >= 50)) BTDSpellCREATURELargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) elseif ((AggressorRace == DwarvenCenturionRace) && (HitChance >= 20)) || ((AggressorRace == DLC1LD_ForgemasterRace) || (AggressorRace == DLC2DwarvenBallistaRace) && (HitChance >= 10)) BTDSpellCREATUREXLargetoPLAYERBleedDmg.cast(PlayerRef,PlayerRef) endif GoToState("Ready") ; The OnHit Event has finished, so it can be called again EndFunction Link to comment Share on other sites More sharing options...
cdcooley Posted December 20, 2016 Share Posted December 20, 2016 Notice that Cipscis's example is defining the main active version of LongFunction at the default state level not inside Waiting. Those are the cases where you must also then declare an empty version in the Busy state. Link to comment Share on other sites More sharing options...
Recommended Posts