ActiveMagicEffect script failure

Post » Wed Jun 20, 2012 12:29 am

I've been getting reports from people saying my mod occasionally stops working. One of the symptoms is that the potions I use to provide access to menus stop restocking themselves when clicked. Here's the script attached to one of them:

Scriptname IMCNesVitalityMenu extends activemagiceffect  Quest Property IMCNmenus autoPotion Property IMCNmaVitality autoevent OnEffectStart(Actor akTarget, Actor akCaster)   if akTarget == Game.GetPlayer()      Game.GetPlayer().AddItem(IMCNmaVitality, 1, true)      (IMCNmenus as IMCNqsVitalityMenu).ShowMenu()   endIfendEvent

The first thing it's supposed to do is put a copy of the potion that the effect is attached to back in the player's inventory. Can anyone think of a reason this script would be failing?
User avatar
P PoLlo
 
Posts: 3408
Joined: Wed Oct 31, 2007 10:05 am

Post » Wed Jun 20, 2012 3:33 am

I don't know what the problem might be, but it might be useful to add a few debugging lines in there. It would be interesting to know whether it's the event that's failing or something else is the problem.

Oh, and just a hint - if you declare your http://www.creationkit.com/Quest_Script property as type IMCNqsVitalityMenu then only objects with the IMCNqsVitalityMenu script attached will be available for selection, and you won't need to do a manual cast when calling your ShowMenu function.

Cipscis
User avatar
Toby Green
 
Posts: 3365
Joined: Sun May 27, 2007 5:27 pm

Post » Tue Jun 19, 2012 9:09 pm

Alternatively use a spell instead of a potion :)

Then you could at least favourite the spell and wouldn't have to worry about re-adding anything.
User avatar
Monika
 
Posts: 3469
Joined: Wed Jan 10, 2007 7:50 pm

Post » Tue Jun 19, 2012 8:47 pm

I don't know what the problem might be, but it might be useful to add a few debugging lines in there. It would be interesting to know whether it's the event that's failing or something else is the problem.

Oh, and just a hint - if you declare your http://www.creationkit.com/Quest_Script property as type IMCNqsVitalityMenu then only objects with the IMCNqsVitalityMenu script attached will be available for selection, and you won't need to do a manual cast when calling your ShowMenu function.

Cipscis

I personally haven't been able to reproduce the problem, and the mod's working well for many people (up around 10k unique dowloads between Steam and the Nexus, and only a few reports of this happening.) I might be able to get someone to provide me with a glitched save though.

As for casting, this was one of the first Papyrus scripts I wrote so I don't think I'd discovered that trick yet. It definitely simplifies things.

Alternatively use a spell instead of a potion :smile:

Then you could at least favourite the spell and wouldn't have to worry about re-adding anything.

I'm using lesser powers for some stuff, but these particular menus are more helpful if you can access them while you're in your inventory. Plus the token not being added is just a symptom, the real problem is that the message never pops up.
User avatar
Lalla Vu
 
Posts: 3411
Joined: Wed Jul 19, 2006 9:40 am

Post » Wed Jun 20, 2012 11:01 am

Hmm, could it potentially be a problem with IMCNqsVitalityMenu, then? From the reports, does it seem more likely that there's some rare case in which the menu won't show, or does it become permanently broken at some point?

Cipscis
User avatar
Amanda Furtado
 
Posts: 3454
Joined: Fri Dec 15, 2006 4:22 pm

Post » Wed Jun 20, 2012 6:35 am

The menu becomes permanently broken. IMCNqsVitalityMenu.ShowMenu() brings up a pretty hefty multilevel menu that accesses a lot of data in the main thread of my mod, so it would presumably get held up if that thread were to hang.

I did a test though, and replaced the call to IMCNqsVitalityMenu.ShowMenu() with utility.wait(20.0) followed by a call to a test message box, to simulate that ShowMenu() function getting hung up. I wanted to see if having that effect script in the middle of processing would prevent another one from executing. It didn't - I clicked the potion, it was immediately replaced (though the OnEffectStart block was still executing due to the call to wait.) and clicked again and the potion was again immediately replaced. So even if that ShowMenu() function is getting stuck in a permanent loop or something, the potion should still be replaced. The two message boxes popped up one after another 20 seconds after I exited my inventory, as expected.

Scriptname IMCNesVitalityMenu extends activemagiceffect  Quest Property IMCNmenus autoPotion Property IMCNmaVitality autoMessage Property IMCNmsgTestBox autoevent OnEffectStart(Actor akTarget, Actor akCaster)   if akTarget == Game.GetPlayer()      Game.GetPlayer().AddItem(IMCNmaVitality, 1, true)      utility.wait(20.0)      IMCNmsgTestBox.Show()            ;(IMCNmenus as IMCNqsVitalityMenu).ShowMenu()   endIfendEvent
User avatar
mishionary
 
Posts: 3414
Joined: Tue Feb 20, 2007 6:19 am

Post » Wed Jun 20, 2012 4:50 am

Could you post IMCNqsVitalityMenu here? ShowMenu isn't a global function, so it's possible that some external variable or state is causing the problem and making the menu permanently broken.

Cipscis
User avatar
Tania Bunic
 
Posts: 3392
Joined: Sun Jun 18, 2006 9:26 am

Post » Wed Jun 20, 2012 12:18 am

Here it is:

Scriptname IMCNqsVitalityMenu extends QuestMessage Property IMCNmsgInfo0E autoMessage Property IMCNmsgInfo0M autoMessage Property IMCNmsgInfo0P autoMessage Property IMCNmsgInfo0VampireE autoMessage Property IMCNmsgInfo0VampireM autoMessage Property IMCNmsgInfo0VampireP autoMessage Property IMCNmsgInfoActions autoMessage Property IMCNmsgInfoAdvancedE autoMessage Property IMCNmsgInfoAdvancedM autoMessage Property IMCNmsgInfoAdvancedP autoMessage Property IMCNmsgInfoAdvancedVampire autoMessage Property IMCNmsgInfoSubstances autoMessage Property IMCNmsgInfoCharacter autoMessage Property IMCNmsgInfoConfirmReset autoMessage Property IMCNmsgInfoDisabled autoMessage Property IMCNmsgInfoFatigue autoMessage Property IMCNmsgInfoListsRebuilt autoMessage Property IMCNmsgRealistic0 autoMessage Property IMCNmsgRealisticHungry autoMessage Property IMCNmsgRealisticTired autoQuest Property IMCNmain autoIMCNqsSpoilageDefaults Property IMCNspoilage autofunction ShowMenu()IMCNqsMain IMCN = IMCNmain as IMCNqsMainIMCNqsMenuConditions menuConditions = (self as Quest) as IMCNqsMenuConditionsif menuConditions.enabled == 0  if IMCNmsgInfoDisabled.Show() == 0   menuConditions.enabled = 1   IMCN.StartTracking()   IMCN.ResetRates()  endIfendIfif menuConditions.enabled != 0  if ((self as Quest) as IMCNqsMenuConditions).showStats == 1   ShowClassicMenu()  else   ShowRealisticMenu()  endIfendIfendFunctionfunction ShowClassicMenu()IMCNqsMain IMCN = IMCNmain as IMCNqsMainIMCNqsDefaults defaults = IMCNmain as IMCNqsDefaultsIMCNqsMenuConditions menuConditions = (self as Quest) as IMCNqsMenuConditionsMessage msgbool exitMenu = falseint menuLevel = 1while !exitMenu  int response = -1  if menuLevel == 1   if IMCN.isVampire	if menuConditions.units == 0	 msg = IMCNmsgInfo0VampireP	elseIf menuConditions.units == 1	 msg = IMCNmsgInfo0VampireM	else	 msg = IMCNmsgInfo0VampireE	endIf	response = msg.Show(IMCN.GetSatiationPct(IMCN.queue[IMCN.satiationSolid] + IMCN.queue[IMCN.satiationLiquid]), \		 IMCN.GetBloodCU(IMCN.reserves[IMCN.blood]), \		 IMCN.GetBloodCU(IMCN.queue[IMCN.blood]) )   else	if menuConditions.units == 0	 msg = IMCNmsgInfo0P	elseIf menuConditions.units == 1	 msg = IMCNmsgInfo0M	else	 msg = IMCNmsgInfo0E	endIf	response = msg.Show(IMCN.GetSatiationPct(IMCN.queue[IMCN.satiationSolid] + IMCN.queue[IMCN.satiationLiquid]), \		 IMCN.GetCaloriesCU(IMCN.reserves[IMCN.calories]), \		 IMCN.GetCaloriesCU(IMCN.queue[IMCN.calories]), \		 IMCN.GetHydrationCU(IMCN.reserves[IMCN.hydration]), \		 IMCN.GetHydrationCU(IMCN.queue[IMCN.hydration]), \		 IMCN.sleepDebt )   endIf   if response == 0	exitMenu = true   elseIf response == 1	menuLevel = 10   elseIf response == 2	menuLevel = 11   elseIf response == 3	menuLevel = 12   elseIf response == 4	menuLevel = 13   else	menuLevel = 14   endIf  elseIf menuLevel == 10 ; advanced   if IMCN.isVampire	response = IMCNmsgInfoAdvancedVampire.Show(IMCN.morale)   else	if menuConditions.units == 0	 msg = IMCNmsgInfoAdvancedP	elseIf menuConditions.units == 1	 msg = IMCNmsgInfoAdvancedM	else	 msg = IMCNmsgInfoAdvancedE	endIf	response = msg.Show(IMCN.morale, \		 IMCN.GetNutrientsRatePct(IMCN.nutrientsPerHourAvg), \		 IMCN.GetNutrientsPct(IMCN.queue[IMCN.nutrients]), \		 IMCN.GetProteinCU(IMCN.proteinPerHourAvg * 8), \		 IMCN.GetProteinCU(IMCN.queue[IMCN.protein]) )   endIf   menuLevel = 1  elseIf menuLevel == 11 ; substances   IMCNmsgInfoSubstances.Show( IMCN.GetBloodAlcoholPct(IMCN.reserves[IMCN.alcohol]), \		  IMCN.GetBloodAlcoholPct(IMCN.queue[IMCN.alcohol]), \		  IMCN.GetCaffeinePct(IMCN.reserves[IMCN.caffeine]), \		  IMCN.GetCaffeinePct(IMCN.queue[IMCN.caffeine]) )   menuLevel = 1    elseIf menuLevel == 12 ; fatigue   IMCNmsgInfoFatigue.Show(IMCN.mentalFatigue, IMCN.physicalFatigue)   menuLevel = 1  elseIf menuLevel == 13 ; character stats   int feet = ((IMCN.height * defaults.metersToFeet) as int)   float inches = 12.0 * (IMCN.height * defaults.metersToFeet - (feet as float))   if inches > 11.5	inches = 0.0	feet += 1   endIf   IMCNmsgInfoCharacter.Show( feet, inches, IMCN.height, \		  IMCN.bodyWeight * defaults.kilogramsToPounds, \		  IMCN.bodyWeight, \		  IMCN.bodyFat / IMCN.bodyWeight * 100, \		  IMCN.skeletalMuscle / IMCN.bodyWeight * 100 )   menuLevel = 1  elseIf menuLevel == 14   ShowActionsMenu()   menuLevel = 1  endIfendWhileendFunctionfunction ShowRealisticMenu()IMCNqsConditions conditions = IMCNmain as IMCNqsConditionsbool exitMenu = falseint menuLevel = 1while !exitMenu  int response = -1  if menuLevel == 1   response = IMCNmsgRealistic0.Show()   if response == 0	exitMenu = true   elseIf response == 1	conditions.ShowSatiationEffects()   elseIf response == 2	menuLevel = 12   elseIf response == 3	conditions.ShowHydrationEffects()   elseIf response == 4	conditions.ShowBloodEffects()   elseIf response == 5	menuLevel = 15   elseIf response == 6	conditions.ShowAlcoholEffects()   elseIf response == 7	conditions.ShowCaffeineEffects()   else	menuLevel = 18   endIf  elseIf menuLevel == 12   response = IMCNmsgRealisticHungry.Show()   if response == 0	menuLevel = 1   elseIf response == 1	conditions.ShowCaloriesEffects()   elseIf response == 2	conditions.ShowNutrientsEffects()   else	conditions.ShowProteinEffects()   endIf  elseIf menuLevel == 15   response = IMCNmsgRealisticTired.Show()   if response == 0	menuLevel = 1   elseIf response == 1	conditions.ShowSleepEffects()   elseIf response == 2	conditions.ShowMentalFatigueEffects()   else	conditions.ShowPhysicalFatigueEffects()   endIf  elseIf menuLevel == 18   ShowActionsMenu()   menuLevel = 1  endIfendWhileendFunctionfunction ShowActionsMenu()IMCNqsMain IMCN = IMCNmain as IMCNqsMainIMCNqsMenuConditions menuConditions = (self as Quest) as IMCNqsMenuConditionsbool exitMenu = falseint menuLevel = 1while !exitMenu  int response = -1  if menuLevel == 1   response = IMCNmsgInfoActions.Show()   if response == 0	exitMenu = true   elseIf response == 1	menuConditions.enabled = 2	IMCN.StopTracking()   elseIf response == 2	menuConditions.enabled = 1	IMCN.StartTracking()   elseIf response == 3	menuLevel = 13   else	IMCNspoilage.UpdateLists()	IMCNmsgInfoListsRebuilt.Show()   endIf  elseIf menuLevel == 13   response = IMCNmsgInfoConfirmReset.Show()   if response == 0	menuLevel = 1   else	IMCN.ResetAll()	IMCN.StopTracking()	menuConditions.enabled = 2	menuLevel = 1   endIf  endIfendWhileendFunction
User avatar
CArlos BArrera
 
Posts: 3470
Joined: Wed Nov 21, 2007 3:26 am

Post » Wed Jun 20, 2012 9:18 am

Nothing jumps out at me that could cause the problem. You should be able to distribute a modified compiled script with some debugging lines added in to print out conditions to an error log, and get the affected users to give you data back. So long as all names and declarations stay the same they should be able to swap between different versions of the compiled script seamlessly. Hopefully gathering more information could uncover the problem.

Cipscis
User avatar
Marie
 
Posts: 3405
Joined: Thu Jun 29, 2006 12:05 am

Post » Wed Jun 20, 2012 9:01 am

One theory I have is that IMCNqsMain might be getting held up somehow. Some of its data and functions need to be accessed before IMCNqsVitalityMenu will show any message boxes, and IMCNqsMain also has a large function that, if my understanding of threading is correct, would need to finish executing (or at least call an external function) before any of its data would be available. That still doesn't explain why the menu potion wouldn't be replaced though.
User avatar
Cat Haines
 
Posts: 3385
Joined: Fri Oct 27, 2006 9:27 am


Return to V - Skyrim