Suspended stacks suspends your Scripts. Sometimes indefinite

Post » Wed Jun 20, 2012 10:14 am

Suspended stacks may suspend your Scripts. Sometimes, indefinitely. The only way I've found to get rid of stacks that have suspended my Scripts is to totally uninstall the mod (ESP and Scripts) to do a clean save.

Suspend stacks look this in the log:
Spoiler
[03/30/2012 - 04:24:01PM] Suspended stack count is over our warning threshold, dumping stacks:[03/30/2012 - 04:24:01PM] VM is freezing...[03/30/2012 - 04:24:01PM] VM is frozen[03/30/2012 - 04:24:01PM] Dumping stack 1642340:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (32) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528A8)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1642341:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (33) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528D0)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1678591:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (32) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528A8)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1679901:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (33) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528D0)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1643830:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (34) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (00083318)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1906024:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (47) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (0002A3A5)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1647187:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (33) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528D0)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1637190:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (33) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528D0)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1637191:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (32) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528A8)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1640054:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (33) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528D0)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1640055:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (32) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528A8)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1649602:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (32) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528A8)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 1649698:[03/30/2012 - 04:24:01PM] 	Frame count: 0 (Page count: 0)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for call (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: None[03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (33) on  (00000000)].kuAENPCAliasS.OnMagicEffectApply() - (requested call)[03/30/2012 - 04:24:01PM] 			[param 0]: [ObjectReference < (000528D0)>][03/30/2012 - 04:24:01PM] 			[param 1]: [MagicEffect < (00024315)>][03/30/2012 - 04:24:01PM] Dumping stack 2089195:[03/30/2012 - 04:24:01PM] 	Frame count: 4 (Page count: 4)[03/30/2012 - 04:24:01PM] 	State: Waiting on other stack for return (Freeze state: Freezing)[03/30/2012 - 04:24:01PM] 	Type: Normal[03/30/2012 - 04:24:01PM] 	Return register: [Form < (0010FDD4)>][03/30/2012 - 04:24:01PM] 	Has stack callback: No[03/30/2012 - 04:24:01PM] 	Stack trace:[03/30/2012 - 04:24:01PM] 		[ (0B004346)].FormList.GetAt() - "" Line ?[03/30/2012 - 04:24:01PM] 			IP: 0[03/30/2012 - 04:24:01PM] 			[param1]: 34[03/30/2012 - 04:24:01PM] 		[kuVTQ (0B000D62)].kuVTQS.OnActorHit() - "kuVTQS.psc" Line 237[03/30/2012 - 04:24:01PM] 			IP: 475	Instruction: 14	Line: 237[03/30/2012 - 04:24:01PM] 			[ActorRef]: [masterambushscript < (0004D1D3)>][03/30/2012 - 04:24:01PM] 			[akAggressor]: [ObjectReference < (00000014)>][03/30/2012 - 04:24:01PM] 			[akSource]: [SPELL < (00012FCD)>][03/30/2012 - 04:24:01PM] 			[akProjectile]: [PROJECTILE < (00012FCF)>][03/30/2012 - 04:24:01PM] 			[abPowerAttack]: False[03/30/2012 - 04:24:01PM] 			[abSneakAttack]: False[03/30/2012 - 04:24:01PM] 			[abBashAttack]: False[03/30/2012 - 04:24:01PM] 			[abHitBlocked]: False[03/30/2012 - 04:24:01PM] 			[::temp32]: "OnActorHit [masterambushscript < (0004D1D3)>]"[03/30/2012 - 04:24:01PM] 			[::nonevar]: None[03/30/2012 - 04:24:01PM] 			[::temp33]: [Actor < (00000014)>][03/30/2012 - 04:24:01PM] 			[::temp34]: True[03/30/2012 - 04:24:01PM] 			[::temp35]: 51[03/30/2012 - 04:24:01PM] 			[::temp36]: True[03/30/2012 - 04:24:01PM] 			[::temp37]: True[03/30/2012 - 04:24:01PM] 			[i]: 34[03/30/2012 - 04:24:01PM] 			[exitLoop]: False[03/30/2012 - 04:24:01PM] 			[::temp38]: [Form < (0001EA77)>][03/30/2012 - 04:24:01PM] 			[::temp39]: [MagicEffect < (0001EA77)>][03/30/2012 - 04:24:01PM] 			[mECalm]: [MagicEffect < (0001EA77)>][03/30/2012 - 04:24:01PM] 		[kuAEQ (02000801)].kuaeqs.OnActorHit() - "kuAEQS.psc" Line 369[03/30/2012 - 04:24:01PM] 			IP: 1110	Instruction: 32	Line: 369[03/30/2012 - 04:24:01PM] 			[ActorRef]: [masterambushscript < (0004D1D3)>][03/30/2012 - 04:24:01PM] 			[akAggressor]: [ObjectReference < (00000014)>][03/30/2012 - 04:24:01PM] 			[akSource]: [SPELL < (00012FCD)>][03/30/2012 - 04:24:01PM] 			[akProjectile]: [PROJECTILE < (00012FCF)>][03/30/2012 - 04:24:01PM] 			[abPowerAttack]: False[03/30/2012 - 04:24:01PM] 			[abSneakAttack]: False[03/30/2012 - 04:24:01PM] 			[abBashAttack]: False[03/30/2012 - 04:24:01PM] 			[abHitBlocked]: False[03/30/2012 - 04:24:01PM] 			[::temp116]: "OnActorHit [masterambushscript < (0004D1D3)>] [ObjectReference < (00000014)>] [SPELL < (00012FCD)>] [PROJECTILE < (00012FCF)>] False False False "[03/30/2012 - 04:24:01PM] 			[::temp117]: "OnActorHit [masterambushscript < (0004D1D3)>] [ObjectReference < (00000014)>] [SPELL < (00012FCD)>] [PROJECTILE < (00012FCF)>] False False False False"[03/30/2012 - 04:24:01PM] 			[::nonevar]: None[03/30/2012 - 04:24:01PM] 			[::temp118]: 128[03/30/2012 - 04:24:01PM] 			[::temp119]: True[03/30/2012 - 04:24:01PM] 			[i]: 0[03/30/2012 - 04:24:01PM] 			[::temp120]: [kuVTQS ][03/30/2012 - 04:24:01PM] 			[::temp121]: [kuVTQS ][03/30/2012 - 04:24:01PM] 			[questRef]: [kuVTQS ][03/30/2012 - 04:24:01PM] 		[alias kuNPC04 on quest kuAEAliasesQ (02000802)].kuAENPCAliasS.OnHit() - "kuAENPCAliasS.psc" Line 32...
And it goes on for quite a bit.

I'm not sure what caused it but I tracked it down to two Actor Events attached to Aliases: OnHit () and OnMagicEffectApply (). Especially, if you call a function in your Script that branches off from that Event. Because Scripts only receive a small amount of CPU time slice (Borgut's post: http://www.gamesas.com/topic/1359724-on-the-run-time-of-skyrims-papyrus-scripts), the calling Script will suspend itself until that other Script finishes its operation.

One-off melee hits didn't (and wouldn't) cause this problem. But I believe continual hits from spells (e.g. Flames, etc...) did. And if your Quest is monitoring only one Alias, it should be ok. But for more intensive mods that apply their changes over many (e.g. 30) Aliases, the problem is real. EDIT: Though my mod had 30 Aliases, only a handful (5) of them were populated. So this could also occur on mods that have a very small number of Aliases.

The solution I am testing is to throttle the propagation of the Event to only 1 a second. So, even if my Aliases will receive the OnHit () and OnMagicEffectApply () calls several times a second, my other Function will not. I can't think of a situation when missing out on some of those Events would cause detriment to any changes a mod is trying to apply.

To see what I mean by "throttling the propagation of the Event", look at OnHit () and OnMagicEffectApply () Functions below. OnHit () is throttled. OnMagicEffectApply () is not.

Spoiler
Float lastHitTimeEvent OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)	Float timeNow = Utility.GetCurrentRealTime ()	If timeNow - lastHitTime > 1		lastHitTime = timeNow		Actor actorRef = GetActorReference ()		questMain.OnActorHit (actorRef, akAggressor, akSource, akProjectile, abPowerAttack, abSneakAttack, abBashAttack, abHitBlocked)	EndIfEndEventEvent OnMagicEffectApply(ObjectReference akCaster, MagicEffect akEffect) 	Actor actorRef = GetActorReference () 	questMain.OnActorMagicEffectApply(actorRef, akCaster, akEffect)EndEvent

Currently, it looks like throttling works. Testing continues.
User avatar
Annika Marziniak
 
Posts: 3416
Joined: Wed Apr 18, 2007 6:22 am

Post » Wed Jun 20, 2012 8:41 am

A lot more problems than this, I don't like the sound of the first line though "Suspended stack count is over our warning threshold, dumping stacks:" you must've had a LOT of scripts suspended in a short period of time. Papyrus can't really handle large amounts of anything, curious why you are handling the event in another script, does the problem persist if you have the contents of your OnActorHit within your OnHit event? (It shouldn't as it wouldn't need to suspend the script) I guess throttling would work, but if those hit events are important your probably losing quite a few. I know its convenient to have an event handler type thing where you can just make most of your changes in a single file, but scripts can pretty much link anywhere so if you add the properties you don't really need to go elsewhere to do the processing. I only did this once because it was within an alias script, and I had 100 of them, so to change the properties I'd have to delete all 100, open the mod in TESVSnip, edit the alias count back to 1 save (So when I create new aliases they don't increment their ID) change the first alias to update the properties, then duplicate it 100 times again, well, not so difficult now but it was before I realized I could edit the alias count subrecord manually.

This only becomes a real problem when you run into the same problem you did, too many suspended scripts. If you don't execute external script functions the stack shouldn't need to be suspended.
User avatar
Erika Ellsworth
 
Posts: 3333
Joined: Sat Jan 06, 2007 5:52 am

Post » Wed Jun 20, 2012 8:21 pm

...curious why you are handling the event in another script, does the problem persist if you have the contents of your OnActorHit within your OnHit event?...
I'm creating an ESM called ActorEvents.esm that will handle all my Aliases for me. Currently, I have two mods (NPCs Yield, Vampirism Tweaks) in development that require polling for nearby NPCs. So, instead of having 60 Aliases across two mods, I have 30 Aliases. And I simply propogate the Actor Events to mods that register themselves to ActoEvents.esm. On top of those two mods, I also need ActorEvents.esm for my NPC Reactions (formerly Clothing matters, in Oblivion).

Also, the only reason I need it for Vampirism Tweaks is that Bethesda decided to kill GetTimeDead (). Even if the Function is still available via Conditions, it returns 0. Grrr @ Bethesda!!! ActorEvents.esm tracks when they die and my separate kuerteeVampirismTweaks.ESP does what it needs.

What's weird is that I wasn't doing anything too extreme in the external (to ActorEvents.esm) mods. I was simply checking for a certain MagicEffect (via FormList.HasForm ()) on the Actor. Reiterating through that FormList is probably what actually caused it.

That's good news re: TESVSnip. I started using it last week to clean "dirty edits". I didn't realise you could do that with Aliases. Thanks!

EDIT for more info: NPCs Yield is a port of my Oblivion mod, NPCs Yield.
Vampirism Tweaks is port of my Oblivion mod, Simple Vampirism.
NPC Reactions is from my Oblivion mod, Clothing Matters.
So, I kinda need this overall NPC Aliases manager to streamline these 3.
User avatar
Brandon Bernardi
 
Posts: 3481
Joined: Tue Sep 25, 2007 9:06 am

Post » Wed Jun 20, 2012 12:26 pm

What I do in my OnHit events to prevent multiple OnHit events from running simultaneously when not needed, is the following:

I declare a variable isRunning = false outside of the events.

The OnHit() event starts with:

If(isRunning)    returnEndIfisRunning=true

So that the first thing that happens is that the script is registered as being running, unless it already is, in which case it immediately returns.

And lastly at the end of the event and right before each return statement, I set isRunning to false again. Not entirely sure yet which way is better/faster, yours or mine :P
User avatar
Jade Barnes-Mackey
 
Posts: 3418
Joined: Thu Jul 13, 2006 7:29 am

Post » Wed Jun 20, 2012 11:32 am

A much simpler and more elegant solution is to use the language, which provides states that can easily solve this.
I did that some time back, you can find the code http://pastebin.com/sisrNQZv.
User avatar
Svenja Hedrich
 
Posts: 3496
Joined: Mon Apr 23, 2007 3:18 pm

Post » Wed Jun 20, 2012 6:11 pm

A much simpler and more elegant solution is to use the language, which provides states that can easily solve this.
I did that some time back, you can find the code http://pastebin.com/sisrNQZv.

oh yes ofc why didn't I think of that.. :P
User avatar
Tamika Jett
 
Posts: 3301
Joined: Wed Jun 06, 2007 3:44 am

Post » Wed Jun 20, 2012 12:15 pm

...I declare a variable isRunning = false outside of the events...
...to use the language, which provides states that can easily solve this...
Of course, States! I suggested this in your posts, Borgut. These two will definitely be faster than mine where I have to get the time and do a subtraction.

However, with States and Bool variables, I can only control the propogation's frequency via its iteration rather than over time.
E.g., I can stop the Event every other time (or every 2 times, every 3 times, etc. with a bit more checks).
But I'm not really sure how many OnHit () and OnMagicEffectApply () Events will trigger over that one second. If it's like Oblivion's OnEffectUpdate () (e.g. a spell's update tick), it could get triggered many times (10, 25, 50, ? I don't really know) over one second. Testing continues...
User avatar
Guy Pearce
 
Posts: 3499
Joined: Sun May 20, 2007 3:08 pm

Post » Wed Jun 20, 2012 10:51 pm

Many times... When I was writing that script I posted earlier, it initially spawned debug messages minutes after I hit a dummy with some concentration destruction spell, like flames.
States dramatically reduced that, now the script handles events as fast as it can, everything that it cannot handle, is simply discarded.

Edit: You can combine states with a timer, just switch states in an OnUpdate event, almost trivial.
User avatar
YO MAma
 
Posts: 3321
Joined: Thu Dec 21, 2006 8:24 am

Post » Wed Jun 20, 2012 2:23 pm

Good point! And with states, the code looks better. However, registering the Script for a timed Event will probably detract from it. Here's my Aliases Script. There's nothing in it. So, for 90% of the time, it doesn't do anything. And only when an actor is hit with a Spell that continuous (Flame, Frost, Shock?), etc... will it get busy in the OnHit () and OnMagicEffectapply () (currently, disabled) Events. And at this time, I can't imagine more than 5 (and thats a lot) of Actors will be affected by those spells.

What do you think?
Spoiler
Scriptname kuAENPCAliasS extends ReferenceAlias  kuAEQS Property questMain AutoEvent OnInit ()	Actor actorRef = GetActorReference ()	questMain.OnActorInit (actorRef)EndEventEvent OnActivate(ObjectReference akActionRef)	Actor actorRef = GetActorReference ()	questMain.OnActorActivate (actorRef, akActionRef)EndEventEvent OnCombatStateChanged(Actor akTarget, int aeCombatState)	Actor actorRef = GetActorReference ()	questMain.OnActorCombatStateChanged (actorRef, akTarget, aeCombatState)EndEventEvent OnDeath(Actor akKiller)	Actor actorRef = GetActorReference ()	questMain.OnActorDeath (actorRef, akKiller)EndEventEvent OnEnterBleedOut ()	Actor actorRef = GetActorReference ()	questMain.OnActorEnterBleedOut (actorRef)EndEventFloat lastHitTimeEvent OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)	Float timeNow = Utility.GetCurrentRealTime ()	If timeNow - lastHitTime > 1		lastHitTime = timeNow		Actor actorRef = GetActorReference ()		questMain.OnActorHit (actorRef, akAggressor, akSource, akProjectile, abPowerAttack, abSneakAttack, abBashAttack, abHitBlocked)	EndIfEndEvent; Event OnMagicEffectApply(ObjectReference akCaster, MagicEffect akEffect); 	Actor actorRef = GetActorReference (); 	questMain.OnActorMagicEffectApply(actorRef, akCaster, akEffect); EndEventEvent OnSpellCast(Form akSpell)	Actor actorRef = GetActorReference ()	questMain.OnActorSpellCast (actorRef, akSpell)EndEventEvent OnOpen(ObjectReference akActionRef)	Actor actorRef = GetActorReference ()	questMain.OnActorOpen (actorRef, akActionRef)EndEvent



Your code, Xetrill, controls the OnHit () every other time (e.g. process 1, drop 2, process 3, etc...), right? That's how I read it.

EDIT: Sorry, I get it now. Your code actually process only the Event WHEN it's not busy. So it could drop not only 1 but several - even 10, if that code is still busy. Good method!

EDIT 2: This also applies to Borgut's Bool method. Until that variable is set to False, the OnHit () is triggered, but none of the code is run.
User avatar
jessica breen
 
Posts: 3524
Joined: Thu Aug 03, 2006 1:04 am

Post » Wed Jun 20, 2012 3:15 pm

Correct, and yes a boolean can be used as a guard as well. Although, it might be a race-condition, states are backed into the language and handle this case.
Which I think is stated somewhere in the wiki.
User avatar
Kelsey Anna Farley
 
Posts: 3433
Joined: Fri Jun 30, 2006 10:33 pm

Post » Wed Jun 20, 2012 7:27 am

I figured out what causes these.
This happens when a Script is stopped while it has an internal operation running (e.g. While/EndWhile),
This generally happens when you have an aliases Quest and another Quest that Stop/Starts it to force it to continually look for game objects. I.e. This method described by Borgut: http://www.gamesas.com/topic/1349649-dynamically-attaching-scripts-to-actors-near-the-player

Lesson: Use variables or States to set your Aliases Quest as busy and check those before your main Quest issues a Stop () on it.

Edit: To clarify...
In my case above , the Script with the While/EndWhile is running on an Alias attached to that aliases Quest.
The aliases Quest itself has no Script.
What I had to do is if the Alias is busy, I set a variable in the main Quest as busy.
And I make sure that variable is not True before the aliases Quest is Stopped ().
User avatar
matt white
 
Posts: 3444
Joined: Fri Jul 27, 2007 2:43 pm

Post » Wed Jun 20, 2012 2:38 pm

What happened was you suspended too many script stacks because your OnHit is in one script which can occur quite rapidly, but your main processing function in another script. Meaning it had to suspend the OnHit function stack to run the one in the other script and those happened to pile up because your main processing function I take it was too slow to return back to the OnHit before too many were suspended.

OnHit
... Suspend OnHit
... Execute MyOnHit
........ Does stuff
........ return to OnHit
... Resume OnHit

If your processing happened within the OnHit and mostly referenced native functions it likely wouldn't need to suspend for very long and could just plow through the processing of them all as it received them.

I've never personally had this happened, but I've also never hooked a fast firing event like OnHit... The Papyrus settings may also effect the suspension threshold, not sure what your values are but mine are:

iMinMemoryPageSize=100000
iMaxMemoryPageSize=5000000
iMaxAllocatedMemoryBytes=1800000000
User avatar
Charles Weber
 
Posts: 3447
Joined: Wed Aug 08, 2007 5:14 pm

Post » Wed Jun 20, 2012 12:07 pm

I've never personally had this happened, but I've also never hooked a fast firing event like OnHit... The Papyrus settings may also effect the suspension threshold, not sure what your values are but mine are:

iMinMemoryPageSize=100000
iMaxMemoryPageSize=5000000
iMaxAllocatedMemoryBytes=1800000000
Those values are really wasteful! Relevant wiki page: http://www.creationkit.com/INI_Settings_(Papyrus)#iMinMemoryPageSize

My guess with people having problems with Papyrus's performance is a misunderstanding of how script-execution is different from the previous script-engine. Especially latent functions seem to fall under the radar. Understandably, because non of the provided editor language files on the wiki account for them.
On my setup of choice - Sublime Text - I highlight them in italics, letting me know when the VM will certainly suspend execution, that is useful.
User avatar
Devils Cheek
 
Posts: 3561
Joined: Sun Aug 13, 2006 10:24 pm

Post » Wed Jun 20, 2012 2:06 pm

Haha, they sure are! I just want my games to run without running into memory issues. I have more than enough memory to spare, might as well use it (12GB total, 8GB usually free, 5-6GB when running my virtual machine)
User avatar
luke trodden
 
Posts: 3445
Joined: Sun Jun 24, 2007 12:48 am

Post » Wed Jun 20, 2012 7:30 am

There's also less obvious ways of generating suspended stacks. Take this for example:
Scriptname ARTH_OCS_WhiterunLODLightsScript extends ObjectReference  {Dummy object to turn city lights off when the player enters the actual city.}objectReference property LODlights auto{Point this as the reference in Tamriel of the LOD lights object}Event OnTriggerEnter( ObjectReference ActorRef )    if( ActorRef == Game.GetPlayer() )        LODlights.disable()    endifEndEventEvent OnTriggerLeave( ObjectReference ActorRef )    if( ActorRef == Game.GetPlayer() )        LODlights.enable()    endifEndEvent

Looks innocent enough, right? Just make sure the trigger box you generated to attach this to isn't set as type L_TRIGGER. Everything that has collision will set that off. Walls, buildings, cheese wheels, chickens, you name it. It generated so many trigger events that it suspended the script stack many times over while you were anywhere near Whiterun.

The fix was easy and the script didn't need editing. Setting the trigger box to use L_ACTORZONE instead fixed it right up.
User avatar
Lily Something
 
Posts: 3327
Joined: Thu Jun 15, 2006 12:21 pm


Return to V - Skyrim