Array index out of range error

Post » Wed Jun 20, 2012 4:01 am

I've been beating my head against the wall for several days now.
I'm making an automatic perks mod for user's who don't use SKSE or Script Dragon.

I've created a test PC with varying skill levels and no perks in a clean save.
I've taken the same PC and added several perks in several skills in a different clean save.


With the non-perk PC, the script below appears to work perfectly - both adding and removing the perks.
With the perked PC, the script aborts with an array index out of range error (as shown in the papyrus log) when the first active perk is found.
The script should simply bypass that perk and move to the next available perk for the skill level.

I need a fresh set of eyes on this.
This is my working copy, so please excuse all the debugs.
Also it is almost 500 lines, so if anyone has suggestions as to how I might make it more efficient, i'm open to suggestions.

Spoiler
Scriptname ASAPScript extends Quest{Monitors and adds skill perks as earned.}int SkillNameElementint TempPerksElementEvent OnInit()RegisterForUpdate(1)RegisterForTrackedStatsEvent()endEventEvent OnUpdate();Initialization;;;;;;;;;;;;;;;If GetStage() <=10  SetStage (20)  debug.MessageBox("ASAP is initializing.  Do not perform any action that will increase any skill levels until initialization is complete.  Wait for the 'Finished' message.")  ; Sort through skills and initialize temporary arrays to skill arrays.  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  SkillNameElement = 0  While (SkillNameElement < SkillName.Length)   if SkillName[SkillNameElement] == "Alchemy"	TempPerks = AlchemyPerks	TempPerksBreakpoints = AlchemyPerksBreakpoints	TempPerksAdded = AlchemyPerksAdded   elseif SkillName[SkillNameElement] == "ALTERATION"	TempPerks = AlterationPerks	TempPerksBreakpoints = AlterationPerksBreakpoints	TempPerksAdded = AlterationPerksAdded   elseif SkillName[SkillNameElement] == "Marksman"	 TempPerks = ArcheryPerks	 TempPerksBreakpoints = ArcheryPerksBreakpoints	TempPerksAdded = ArcheryPerksAdded   elseif SkillName[SkillNameElement] == "Block"	TempPerks = BlockPerks	TempPerksBreakpoints = BlockPerksBreakpoints	TempPerksAdded = BlockPerksAdded   elseif SkillName[SkillNameElement] == "CONJURATION"	TempPerks = ConjurationPerks	TempPerksBreakpoints = ConjurationPerksBreakpoints	TempPerksAdded = ConjurationPerksAdded   elseif SkillName[SkillNameElement] == "DESTRUCTION"	TempPerks = DestructionPerks	TempPerksBreakpoints = DestructionPerksBreakpoints	TempPerksAdded = DestructionPerksAdded   elseif SkillName[SkillNameElement] == "Enchanting"	TempPerks = EnchantingPerks	TempPerksBreakpoints = EnchantingPerksBreakpoints	TempPerksAdded = EnchantingPerksAdded   elseif SkillName[SkillNameElement] == "HeavyArmor"	TempPerks = HeavyArmorPerks	TempPerksBreakpoints = HeavyArmorPerksBreakpoints	TempPerksAdded = HeavyArmorPerksAdded   elseif SkillName[SkillNameElement] == "ILLUSION"	TempPerks = IllusionPerks	TempPerksBreakpoints = IllusionPerksBreakpoints	TempPerksAdded = IllusionPerksAdded   elseif SkillName[SkillNameElement] == "LightArmor"	TempPerks = LightArmorPerks	TempPerksBreakpoints = LightArmorPerksBreakpoints	TempPerksAdded = LightArmorPerksAdded   elseif SkillName[SkillNameElement] == "Lockpicking"	TempPerks = LockpickingPerks	TempPerksBreakpoints = LockpickingPerksBreakpoints	TempPerksAdded = LockpickingPerksAdded   elseif SkillName[SkillNameElement] == "OneHanded"	TempPerks = OneHandedPerks	TempPerksBreakpoints = OneHandedPerksBreakpoints	TempPerksAdded = OneHandedPerksAdded   elseif SkillName[SkillNameElement] == "Pickpocket"	TempPerks = PickpocketPerks	TempPerksBreakpoints = PickpocketPerksBreakpoints	TempPerksAdded = PickpocketPerksAdded   elseif SkillName[SkillNameElement] == "RESTORATION"	TempPerks = RestorationPerks	TempPerksBreakpoints = RestorationPerksBreakpoints	TempPerksAdded = RestorationPerksAdded   elseif SkillName[SkillNameElement] == "Smithing"	TempPerks = SmithingPerks	TempPerksBreakpoints = SmithingPerksBreakpoints	TempPerksAdded = SmithingPerksAdded   elseif SkillName[SkillNameElement] == "Sneak"	TempPerks = SneakPerks	TempPerksBreakpoints = SneakPerksBreakpoints	TempPerksAdded = SneakPerksAdded   elseif SkillName[SkillNameElement] == "Speechcraft"	TempPerks = SpeechPerks	TempPerksBreakpoints = SpeechPerksBreakpoints	TempPerksAdded = SpeechPerksAdded   else	TempPerks = TwoHandedPerks	TempPerksBreakpoints = TwoHandedPerksBreakpoints	TempPerksAdded = TwoHandedPerksAdded   endif     ; Get skill level, check if perk is already active, add it if not and store if existing for removal.   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   TempPerksElement = 0   int SkillLevel = (Game.GetPlayer().GetBaseAV(SkillName[SkillNameElement])) as int   While (TempPerksElement < TempPerks.Length)	if SkillLevel < 20	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ". Checking base perk only.")	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement = TempPerks.Length	 endif	elseif SkillLevel >= 20 && SkillLevel < 25	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[0]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 25 && SkillLevel < 30	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[1]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 30 && SkillLevel < 40	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[2]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 40 && SkillLevel < 50	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[3]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 50 && SkillLevel < 60	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[4]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 60 && SkillLevel < 70	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[5]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 70 && SkillLevel < 75	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[6]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 75 && SkillLevel < 80	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[7]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 80 && SkillLevel < 90	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[8]	   TempPerksElement = TempPerks.Length	  endif	 endif		elseif SkillLevel >= 90 && SkillLevel < 100	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	  if TempPerksElement == TempPerksBreakpoints[9]	   TempPerksElement = TempPerks.Length	  endif	 endif		else	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0	  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)	  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))	  TempPerksAdded[TempPerksElement].Enable()	  TempPerksElement += 1	 endif		endif   EndWhile  SkillNameElement += 1  endWhile  debug.MessageBox("ASAP initialization is complete.")  RegisterForUpdate(1)endIfif GetStage() == 20  SetStage(30)  debug.notification("Stage 20")endifif GetStage() == 40  UnRegisterForUpdate()  debug.MessageBox("ASAP is removing perks it added.  Do not perform any action that will increase any skill levels until removal is complete.  Wait for the 'Finished' message.")  ; first while loop - sort through skills and initialize temporary arrays to equal skill arrays  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  SkillNameElement = 0  While (SkillNameElement < SkillName.Length)   if SkillName[SkillNameElement] == "Alchemy"	TempPerks = AlchemyPerks	TempPerksAdded = AlchemyPerksAdded   elseif SkillName[SkillNameElement] == "Alteration"	TempPerks = AlterationPerks	TempPerksAdded = AlterationPerksAdded   elseif SkillName[SkillNameElement] == "Marksman"	TempPerks = ArcheryPerks	TempPerksAdded = ArcheryPerksAdded   elseif SkillName[SkillNameElement] == "Block"	TempPerks = BlockPerks	TempPerksAdded = BlockPerksAdded   elseif SkillName[SkillNameElement] == "Conjuration"	TempPerks = ConjurationPerks	TempPerksAdded = ConjurationPerksAdded   elseif SkillName[SkillNameElement] == "Destruction"	TempPerks = DestructionPerks	TempPerksAdded = DestructionPerksAdded   elseif SkillName[SkillNameElement] == "Enchanting"	TempPerks = EnchantingPerks	TempPerksAdded = EnchantingPerksAdded   elseif SkillName[SkillNameElement] == "HeavyArmor"	TempPerks = HeavyArmorPerks	TempPerksAdded = HeavyArmorPerksAdded   elseif SkillName[SkillNameElement] == "Illusion"	TempPerks = IllusionPerks	TempPerksAdded = IllusionPerksAdded   elseif SkillName[SkillNameElement] == "LightArmor"	TempPerks = LightArmorPerks	TempPerksAdded = LightArmorPerksAdded   elseif SkillName[SkillNameElement] == "Lockpicking"	TempPerks = LockpickingPerks	TempPerksAdded = LockpickingPerksAdded   elseif SkillName[SkillNameElement] == "OneHanded"	TempPerks = OneHandedPerks	TempPerksAdded = OneHandedPerksAdded   elseif SkillName[SkillNameElement] == "Pickpocket"	TempPerks = PickpocketPerks	TempPerksAdded = PickpocketPerksAdded   elseif SkillName[SkillNameElement] == "Restoration"	TempPerks = RestorationPerks	TempPerksAdded = RestorationPerksAdded   elseif SkillName[SkillNameElement] == "Smithing"	TempPerks = SmithingPerks	TempPerksAdded = SmithingPerksAdded   elseif SkillName[SkillNameElement] == "Sneak"	TempPerks = SneakPerks	TempPerksAdded = SneakPerksAdded   elseif SkillName[SkillNameElement] == "Speechcraft"	TempPerks = SpeechPerks	TempPerksAdded = SpeechPerksAdded   else	TempPerks = TwoHandedPerks	TempPerksAdded = TwoHandedPerksAdded   endif   ; Check if perk was added and remove it   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   TempPerksElement = 0   While (TempPerksElement < TempPerks.Length)	debug.notification("Checking " + SkillName[SkillNameElement] + " perk " + TempPerksElement + ".")	if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) && (TempPerksAdded[TempPerksElement].IsEnabled())	 debug.notification("This perk is to be removed.")	 Game.GetPlayer().RemovePerk(TempPerks[TempPerksElement])	 TempPerksAdded[TempPerksElement].Disable()	 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement]))	  debug.notification("This perk has not been removed.")	 else	  debug.notification("This perk has been removed.")	 endif	else	 debug.notification("This perk was existing.")	endif	   TempPerksElement += 1   ; second While loop end   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;   EndWhile  SkillNameElement += 1  endWhile  debug.MessageBox("ASAP removal is complete.  Save your game.  Exit Skyrim.  Uninstall ASAP.esp.")endIfendEventEvent OnTrackedStatsEvent(string statFilter, int statValue); if GetStage() == 30;  if (statFilter == "Skill Increases"); Tracking code here;;;;;;;;;;;;;;;;;;;;;  endif; endifEndEventString[] Property SkillName  AutoPerk[] Property AlchemyPerks  AutoPerk[] Property AlterationPerks  AutoPerk[] Property ArcheryPerks  AutoPerk[] Property BlockPerks  AutoPerk[] Property ConjurationPerks  AutoPerk[] Property DestructionPerks  AutoPerk[] Property EnchantingPerks  AutoPerk[] Property HeavyArmorPerks  AutoPerk[] Property IllusionPerks  AutoPerk[] Property LightArmorPerks  AutoPerk[] Property LockpickingPerks  AutoPerk[] Property OneHandedPerks  AutoPerk[] Property PickpocketPerks  AutoPerk[] Property RestorationPerks  AutoPerk[] Property SmithingPerks  AutoPerk[] Property SneakPerks  AutoPerk[] Property SpeechPerks  AutoPerk[] Property TwoHandedPerks  AutoPerk[] Property TempPerks  AutoInt[] Property AlchemyPerksBreakpoints  AutoInt[] Property AlterationPerksBreakpoints  AutoInt[] Property ArcheryPerksBreakpoints  AutoInt[] Property BlockPerksBreakpoints  AutoInt[] Property ConjurationPerksBreakpoints  AutoInt[] Property DestructionPerksBreakpoints  AutoInt[] Property EnchantingPerksBreakpoints  AutoInt[] Property HeavyArmorPerksBreakpoints  AutoInt[] Property IllusionPerksBreakpoints  AutoInt[] Property LightArmorPerksBreakpoints  AutoInt[] Property LockpickingPerksBreakpoints  AutoInt[] Property OneHandedPerksBreakpoints  AutoInt[] Property PickpocketPerksBreakpoints  AutoInt[] Property RestorationPerksBreakpoints  AutoInt[] Property SmithingPerksBreakpoints  AutoInt[] Property SneakPerksBreakpoints  AutoInt[] Property SpeechPerksBreakpoints  AutoInt[] Property TwoHandedPerksBreakpoints  AutoInt[] Property TempPerksBreakpoints  AutoQuest Property ASAP  AutoObjectReference[] Property AlchemyPerksAdded  AutoObjectReference[] Property AlterationPerksAdded  AutoObjectReference[] Property ArcheryPerksAdded  AutoObjectReference[] Property BlockPerksAdded  AutoObjectReference[] Property ConjurationPerksAdded  AutoObjectReference[] Property DestructionPerksAdded  AutoObjectReference[] Property EnchantingPerksAdded  AutoObjectReference[] Property HeavyArmorPerksAdded  AutoObjectReference[] Property IllusionPerksAdded  AutoObjectReference[] Property LightArmorPerksAdded  AutoObjectReference[] Property LockpickingPerksAdded  AutoObjectReference[] Property OneHandedPerksAdded  AutoObjectReference[] Property PickpocketPerksAdded  AutoObjectReference[] Property RestorationPerksAdded  AutoObjectReference[] Property SmithingPerksAdded  AutoObjectReference[] Property SneakPerksAdded  AutoObjectReference[] Property SpeechPerksAdded  AutoObjectReference[] Property TwoHandedPerksAdded  AutoObjectReference[] Property TempPerksAdded  Auto
User avatar
Josee Leach
 
Posts: 3371
Joined: Tue Dec 26, 2006 10:50 pm

Post » Wed Jun 20, 2012 7:10 am

Which line does the compiler say the error is on?
User avatar
El Goose
 
Posts: 3368
Joined: Sun Dec 02, 2007 12:02 am

Post » Wed Jun 20, 2012 3:31 am

if Skilllevel < 20
if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0 <------
User avatar
Floor Punch
 
Posts: 3568
Joined: Tue May 29, 2007 7:18 am

Post » Wed Jun 20, 2012 12:42 am

Your script is huge! I don't even know where to look, but right now I think there might be a problem in one of your while loops. This is some of the code inside your nested loop to check if the player is missing some perks:

;...elseif SkillLevel >= 30 && SkillLevel < 40    if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0        debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)        (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))        TempPerksAdded[TempPerksElement].Enable()        TempPerksElement += 1        if TempPerksElement == TempPerksBreakpoints[2]            TempPerksElement = TempPerks.Length        endif    endifelseif ;...

What if the player has a skill level between 30 and 40, but has the perk listed in TempPerks[0]? Then the rest of the code snippet won't fire. The TempPerksElement never gets incremented and stays at 0. You'll be stuck in a endless loop while the script keeps on checking for what to do when skill level is between 30 and 40.
User avatar
TRIsha FEnnesse
 
Posts: 3369
Joined: Sun Feb 04, 2007 5:59 am

Post » Wed Jun 20, 2012 3:19 am

THAT'S IT!!!

I forgot the ELSE statement if they havethe perk!

Thank you!!!


Edit: Just compiled and confirmed - sure enough it was the missing "else".
Almost ready now, just need to verify the filtering works as expected.
Thanks again.
User avatar
Amanda savory
 
Posts: 3332
Joined: Mon Nov 27, 2006 10:37 am

Post » Wed Jun 20, 2012 12:03 am

Glad you have it working now. As for thinking of ways to make your script shorter, I can think of a way, but I don't want to risk messing up the script again.
User avatar
Alexis Estrada
 
Posts: 3507
Joined: Tue Aug 29, 2006 6:22 pm

Post » Wed Jun 20, 2012 1:08 am

Your script just BEGS for some functions there. Really :]
Notice that you use the same fragment many times:
		 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0		  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)		  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))		  TempPerksAdded[TempPerksElement].Enable()		  TempPerksElement += 1		  if TempPerksElement == TempPerksBreakpoints[0]		   TempPerksElement = TempPerks.Length		  endif		 endif  

And the only difference there is the number for TempPerksBreakpoints. Such repeating code fragments are the best candidates for functions,
and you can pass those minor changing values as function's arguments.


So you could do something like this:

Function Perks(int Value)		 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0		  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)		  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))		  TempPerksAdded[TempPerksElement].Enable()		  TempPerksElement += 1		  if TempPerksElement == TempPerksBreakpoints[Value]		   TempPerksElement = TempPerks.Length		  endif		 endif  EndFunction

And instead of repeating that fragment many times just put these in your code:

elseif SkillLevel >= 20 && SkillLevel < 25	Perks(0)elseif SkillLevel >= 25 && SkillLevel < 30	Perks(1)elseif SkillLevel >= 30 && SkillLevel < 40	Perks(2)
etc.

This way you will make your script much more manageable, much shorter, far easier to debug, read, and to work with....
And the same with any other fragments of your script - if you need to repeat few lines couple of times, then make a function instead :)
User avatar
stephanie eastwood
 
Posts: 3526
Joined: Thu Jun 08, 2006 1:25 pm

Post » Tue Jun 19, 2012 9:41 pm

Well the If GetStage() == 40 could be an ElseIf, since none of the If statements above it set the stage to 40.

Also, any RegisterForUpdates after the one in Init seem redundant. The only UnRegister is in the stage 40, and once you're unregistered, it won't update again to get to the other register statements since they're alll BEFORE that If statement.

Once you use RegisterForUpdate(1), it will continue updating every second until you un-register it. Did you mean to use RegisterForSingleUpdate instead?

I mean, you're in the Update when you reach the other RegisterForUpdates, so you're clearly already registered...
User avatar
Yama Pi
 
Posts: 3384
Joined: Wed Apr 18, 2007 3:51 am

Post » Tue Jun 19, 2012 10:32 pm

Your script just BEGS for some functions there. Really :]
Notice that you use the same fragment many times:
		 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0		  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)		  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))		  TempPerksAdded[TempPerksElement].Enable()		  TempPerksElement += 1		  if TempPerksElement == TempPerksBreakpoints[0]		   TempPerksElement = TempPerks.Length		  endif		 endif  

And the only difference there is the number for TempPerksBreakpoints. Such repeating code fragments are the best candidates for functions,
and you can pass those minor changing values as function's arguments.


So you could do something like this:

Function Perks(int Value)		 if (Game.GetPlayer().HasPerk(TempPerks[TempPerksElement])) == 0		  debug.notification(SkillName[SkillNameElement] + " is " + SkillLevel + ", Checking perks available. Index No.: " + TempPerksElement)		  (Game.GetPlayer().AddPerk(TempPerks[TempPerksElement]))		  TempPerksAdded[TempPerksElement].Enable()		  TempPerksElement += 1		  if TempPerksElement == TempPerksBreakpoints[Value]		   TempPerksElement = TempPerks.Length		  endif		 endif  EndFunction

And instead of repeating that fragment many times just put these in your code:

elseif SkillLevel >= 20 && SkillLevel < 25	Perks(0)elseif SkillLevel >= 25 && SkillLevel < 30	Perks(1)elseif SkillLevel >= 30 && SkillLevel < 40	Perks(2)
etc.

This way you will make your script much more manageable, much shorter, far easier to debug, read, and to work with....
And the same with any other fragments of your script - if you need to repeat few lines couple of times, then make a function instead :smile:
I thought about using functions. Somewhere I got the impression that function values were not accessable outside of the function.
So pointing my Temp Arrays in the first while block would not pass to a function. But now that I have a working script I can save, I can afford to experiment with functions.
User avatar
sally coker
 
Posts: 3349
Joined: Wed Jul 26, 2006 7:51 pm

Post » Tue Jun 19, 2012 4:59 pm

Well the If GetStage() == 40 could be an ElseIf, since none of the If statements above it set the stage to 40.

Also, any RegisterForUpdates after the one in Init seem redundant. The only UnRegister is in the stage 40, and once you're unregistered, it won't update again to get to the other register statements since they're alll BEFORE that If statement.

Once you use RegisterForUpdate(1), it will continue updating every second until you un-register it. Did you mean to use RegisterForSingleUpdate instead?

I mean, you're in the Update when you reach the other RegisterForUpdates, so you're clearly already registered...
The problem I ran into was the initialization kept appearing on every update. Even though clearly the script was running. At first I had a runonce varible in an if block. Then I read about the unregister. That stop the mbx from showing up more than once. But I need the script to continue running so registerforupdate needs to reinstated - hence the getstage. I intend to put a new registerfor update there - I just hadn't done so yet.
User avatar
N Only WhiTe girl
 
Posts: 3353
Joined: Mon Oct 30, 2006 2:30 pm

Post » Tue Jun 19, 2012 7:41 pm

The problem I ran into was the initialization kept appearing on every update. Even though clearly the script was running. At first I had a runonce varible in an if block. Then I read about the unregister. That stop the mbx from showing up more than once. But I need the script to continue running so registerforupdate needs to reinstated - hence the getstage. I intend to put a new registerfor update there - I just hadn't done so yet.

I'd just set a boolean "BoxAlreadyDisplayed = False" and make an if statement:

if !BoxAlreadyDisplayed  BoxAlreadyDisplayed = True  Debug.MessageBox("Message that only appears once here")endif
User avatar
Abel Vazquez
 
Posts: 3334
Joined: Tue Aug 14, 2007 12:25 am

Post » Tue Jun 19, 2012 6:35 pm

Well, just as an fyi, I leterally copied the function above and pasted it into the script changed my perk checks.
Now the script just goes into a never ending loop. this papyrus log doesn't show any errors, but the script profiling log shows this repeating endlessly (not literally of course but a full 100 kb by the time I shut skyrim down). Ideas? I see that a functions should work perfextly in this script, but I'm having a bit of trouble.

Script_ASAPScript log opened (PC)
18022:QUEUE_PUSH:1198:2:ASAP (02000D62):ASAPScript.??.GetCurrentStageID
18034:QUEUE_PUSH:1198:2:ASAP (02000D62):ASAPScript.??.SetCurrentStageID
18051:QUEUE_PUSH:1198:1:ASAP (02000D62):ASAPScript.??.UnregisterForUpdate
18123:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18151:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18151:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18183:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18183:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18216:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18216:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18251:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18251:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks

until the end

32109:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
Log closed
User avatar
Brandon Bernardi
 
Posts: 3481
Joined: Tue Sep 25, 2007 9:06 am

Post » Wed Jun 20, 2012 5:33 am

Well, just as an fyi, I leterally copied the function above and pasted it into the script changed my perk checks.
Now the script just goes into a never ending loop. this papyrus log doesn't show any errors, but the script profiling log shows this repeating endlessly (not literally of course but a full 100 kb by the time I shut skyrim down). Ideas? I see that a functions should work perfextly in this script, but I'm having a bit of trouble.

Script_ASAPScript log opened (PC)
18022:QUEUE_PUSH:1198:2:ASAP (02000D62):ASAPScript.??.GetCurrentStageID
18034:QUEUE_PUSH:1198:2:ASAP (02000D62):ASAPScript.??.SetCurrentStageID
18051:QUEUE_PUSH:1198:1:ASAP (02000D62):ASAPScript.??.UnregisterForUpdate
18123:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18151:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18151:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18183:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18183:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18216:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18216:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
18251:POP:1198:1:ASAP (02000D62):ASAPScript..Perks
18251:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks

until the end

32109:PUSH:1198:1:ASAP (02000D62):ASAPScript..Perks
Log closed

Guessing that it's because it's trying to update every second...when the previous update hasn't finished.

Try adding this code:

Bool AlreadyUpdating = FalseEvent Onupdate()   If !AlreadyUpdating	 AlreadyUpdating = True; The rest of your event code here	 AlreadyUpdating = False   endifEndEvent

This will cause any update that interrupts an update in progress to skip everything else and exit.
User avatar
Jason King
 
Posts: 3382
Joined: Tue Jul 17, 2007 2:05 pm

Post » Tue Jun 19, 2012 8:53 pm

You really should just use RegisterForSingleUpdate() instead of setting up a continous Update that constantly overlaps itself...
User avatar
Cassie Boyle
 
Posts: 3468
Joined: Sun Nov 05, 2006 9:33 am


Return to V - Skyrim