Why is this array's value changing?

Post » Sat Aug 23, 2014 12:06 am

I've got a script to convert one gem to another. It's got an odd issue which seems like one I've had before, but I never found the solution. First the script (Note, a line which isn't indented but should be is like that so I can easily remove those. They're just the debug lines. It also means you can easily spot the message boxes I talk about.):

Scriptname SWC_GemConverterScript extends ObjectReference  Event OnActivate(ObjectReference akActivator)	UILib_1 UILib = ((Self as Form) as UILib_1)	String[] GemTypes = New String[13]	GemTypes[0] = "Garnet"	GemTypes[1] = "Flawless Garnet"	GemTypes[2] = "Amethyst"	GemTypes[3] = "Flawless Amethyst"	GemTypes[4] = "Ruby"	GemTypes[5] = "Flawless Ruby"	GemTypes[6] = "Sapphire"	GemTypes[7] = "Flawless Sapphire"	GemTypes[8] = "Emerald"	GemTypes[9] = "Flawless Emerald"	GemTypes[10] = "Diamond"	GemTypes[11] = "Flawless Diamond"	GemTypes[12] = "Cancel"	MiscObject[] Gems = New MiscObject[11]	Gems[0] = GemGarnet	Gems[1] = GemGarnetFlawless	Gems[2] = GemAmethyst	Gems[3] = GemAmethystFlawless	Gems[4] = GemRuby	Gems[5] = GemRubyFlawless	Gems[6] = GemSapphire	Gems[7] = GemSapphireFlawless	Gems[8] = GemEmerald	Gems[9] = GemEmeraldFlawless	Gems[10] = GemDiamond	Gems[11] = GemDiamondFlawlessDebug.MessageBox("Test1: " + Gems[11].GetName())Utility.Wait(0.5)	Actor Player = Game.GetPlayer()Player.AddItem(GemGarnet, 100)	If ( akActivator == Game.GetPlayer() )Debug.MessageBox("Test2: " + Gems[11].GetName())Utility.Wait(0.5)		MiscObject[] GemToConvertList		String[] GemToConvertListNames		Bool[] GemsInInv = New Bool[12]		Int i = 12		Int TotalGemTypesInInv = 0Debug.MessageBox("Test3: " + Gems[11].GetName())Utility.Wait(0.5)		While i			i -= 1			If  Player.GetItemCount(Gems[i]) != 0				GemsInInv[i] = True				TotalGemTypesInInv += GemsInInv[i] as Int			Else				GemsInInv[i] = False			EndIf			;Utility.Wait(0.1)Debug.MessageBox("Test3." + i + ": " + Gems[11].GetName())Utility.Wait(0.5)		EndWhileDebug.MessageBox("Test4: " + Gems[11].GetName())Utility.Wait(0.5)		If ( TotalGemTypesInInv == 1 )			GemToConvertList = New MiscObject[1]			GemToConvertListNames = New String[2]		ElseIf ( TotalGemTypesInInv == 2 )			GemToConvertList = New MiscObject[2]			GemToConvertListNames = New String[3]		ElseIf ( TotalGemTypesInInv == 3 )			GemToConvertList = New MiscObject[3]			GemToConvertListNames = New String[4]		ElseIf ( TotalGemTypesInInv == 4 )			GemToConvertList = New MiscObject[4]			GemToConvertListNames = New String[5]		ElseIf ( TotalGemTypesInInv == 5 )			GemToConvertList = New MiscObject[5]			GemToConvertListNames = New String[6]		ElseIf ( TotalGemTypesInInv == 6 )			GemToConvertList = New MiscObject[6]			GemToConvertListNames = New String[7]		ElseIf ( TotalGemTypesInInv == 7 )			GemToConvertList = New MiscObject[7]			GemToConvertListNames = New String[8]		ElseIf ( TotalGemTypesInInv == 8 )			GemToConvertList = New MiscObject[8]			GemToConvertListNames = New String[9]		ElseIf ( TotalGemTypesInInv == 9 )			GemToConvertList = New MiscObject[9]			GemToConvertListNames = New String[10]		ElseIf ( TotalGemTypesInInv == 10 )			GemToConvertList = New MiscObject[10]			GemToConvertListNames = New String[11]		ElseIf ( TotalGemTypesInInv == 11 )			GemToConvertList = New MiscObject[11]			GemToConvertListNames = New String[12]		ElseIf ( TotalGemTypesInInv == 12 )			GemToConvertList = New MiscObject[12]			GemToConvertListNames = New String[13]		EndIfDebug.MessageBox("Test5: " + Gems[11].GetName())Utility.Wait(0.5)		i = 0		Int j = 0		While ( j < TotalGemTypesInInv )			If GemsInInv[i]				GemToConvertList[j] = Gems[i]				GemToConvertListNames[j] = GemTypes[i]				j += 1			EndIf			i += 1			;Utility.Wait(0.1)		EndWhileDebug.MessageBox("Test6: " + Gems[11].GetName())Utility.Wait(0.5)		GemToConvertListNames[j] = "Cancel"		GemToConvert = UILib.ShowList("Which type of gem would you like to convert?", GemToConvertListNames, 0, 0)		If ( GemToConvert != GemToConvertListNames.Length - 1 )			GemToConvertType = GemToConvertList[GemToConvert]		Else			Return		EndIf;Debug.Notification("GemToConvertType: "+GemToConvertType.GetName())		GemToConvert = UILib.ShowList("Which type of gem would you like to convert to?", GemTypes, 0, 0)		If ( GemToConvert != 12 )			GemToConvertToType = Gems[GemToConvert];Debug.MessageBox("Chosen: " + GemToConvert + " - " + Gems[GemToConvert].GetName())		Else			Return		EndIfDebug.MessageBox("Test7: " + Gems[11].GetName())Utility.Wait(0.5)		GemNumberToConvert = UILib.ShowTextInput("How many " + GemToConvertType.GetName() + "s would you like to convert to " + GemToConvertToType.GetName() + "s?") as Int		If ( Player.GetItemCount(GemToConvertType) < GemNumberToConvert )			GemNumberToConvert = Player.GetItemCount(GemToConvertType)		EndIfDebug.MessageBox("Test8: " + Gems[11].GetName())Utility.Wait(0.5)		Float GemValueToConvert = GemToConvertType.GetGoldValue()		Float GemValueToConvertTo = GemToConvertToType.GetGoldValue();Debug.MessageBox("Converting " + GemNumberToConvert + GemToConvertType.GetName() + "s (" + Math.Floor(GemValueToConvert) + ") to " + GemToConvertToType.GetName() + "s (" + Math.Floor(GemValueToConvertTo) + ")")		GemNumberToConvertTo = Math.Floor((GemNumberToConvert*GemValueToConvert)/GemValueToConvertTo)		GemNumberToConvert = Math.Ceiling((GemNumberToConvertTo*GemValueToConvertTo)/GemValueToConvert);Debug.MessageBox("Converting "+ GemNumberToConvert + " " + GemToConvertType.GetName() + "s to " + GemNumberToConvertTo + " " + GemToConvertToType.GetName() + "s")		Player.RemoveItem(GemToConvertType, GemNumberToConvert)		Player.AddItem(GemToConvertToType, GemNumberToConvertTo)		Remainder = Math.Ceiling(GemNumberToConvert*GemValueToConvert)-Math.Floor(GemNumberToConvertTo*GemValueToConvertTo);Debug.Notification("Remainder: " + Remainder)		Player.AddItem(Gold001, Remainder)	EndIfDebug.MessageBox("Test9: " + Gems[11].GetName())EndEventMiscObject Property GemGarnet AutoMiscObject Property GemAmethyst AutoMiscObject Property GemGarnetFlawless AutoMiscObject Property GemRuby AutoMiscObject Property GemAmethystFlawless AutoMiscObject Property GemSapphire AutoMiscObject Property GemRubyFlawless AutoMiscObject Property GemEmerald AutoMiscObject Property GemSapphireFlawless AutoMiscObject Property GemDiamond AutoMiscObject Property GemEmeraldFlawless AutoMiscObject Property GemDiamondFlawless AutoMiscObject Property Gold001 AutoMiscObject GemToConvertTypeMiscObject GemToConvertToTypeInt GemToConvertInt GemNumberToConvertTempInt GemNumberToConvertInt GemNumberToConvertToInt Remainder

It's a bit long, but it's mostly straight forward. Basically, it starts off with a list of gems, and a list of gems' names. Then, using UILib (a new modder's resource released by mrpwn and created by schlangster, I believe), it asks the user for a gem they have, then for a gem they want, then how many. But it uses a different list for the gem they have because I only want it to show the gems the player actually has in their inventory. That all works perfectly. But when trying to convert 100 garnets to flawless diamonds, I noticed that it thought I was trying to convert TO garnets, as well. That's why there are a bunch of message boxes telling me what Gems[11] is. See, Gems[] is never changed. I query it, but I never set the values after they're set initially. However, the messageboxes tell me a different story. Gems[11] returns:

Test1: Flawless DiamondTest2: Flawless DiamondTest3: Flawless DiamondTest3.11: Flawless DiamondTest3.10: DiamondTest3.9: Flawless EmeraldTest3.8: EmeraldTest3.7: Flawless SapphireTest3.6: SapphireTest3.5: Flawless RubyTest3.4: RubyTest3.3: Flawless AmethystTest3.2: AmethystTest3.1: Flawless GarnetTest3.0: GarnetTest4: GarnetTest5: GarnetTest6: AmethystTest7: GarnetTest8: AmethystTest9: Garnet

This is the result of trying to convert garnets to flawless diamond. Gems[11] takes on a lot of different values. Notably, in the while loop that counts down right after where the Test3 message box is, it takes on the value for Gems[i]. I don't understand what's going on. I can't see a reason Gems[11] should be changing value at all, let alone all the time. Is this a Skyrim issue? I've had similar issues with arrays seemingly randomly changing value even though they shouldn't be. I even had arrays being set equal to another array that it never interacted with.

For the record, should you want to test this and let me know if it's just my machine, this just needs to go on anything the player can activate. Everything autofills. Upon activating it, you'll be given 100 garnets to work with (this line is being added now, after I've already written this all, so it's definitely not interfering). But you'll need http://www.nexusmods.com/skyrim/mods/57308/?tab=1&navtag=http%3A%2F%2Fwww.nexusmods.com%2Fskyrim%2Fajax%2Fmoddescription%2F%3Fid%3D57308%26preview%3D&pUp=1. Just attach UILib_1 to the same object. The rest is taken care of.

I could potentially set the array in the CK and see if that will work. Or I could create a 100% isolated array and call on it, but I don't understand why that would be necessary.

User avatar
Dylan Markese
 
Posts: 3513
Joined: Sat Dec 01, 2007 11:58 am

Post » Sat Aug 23, 2014 7:09 am

That seems very strange.

I'd suggest defining Gems and GemTypes outside of the Event as static variables in your script, and then assigning them values in a standalone OnInit() event instead. See if that improves things.

User avatar
Krystal Wilson
 
Posts: 3450
Joined: Wed Jan 17, 2007 9:40 am

Post » Sat Aug 23, 2014 11:37 am

Thank you. It ended up being unnecessary, but in the process of doing this I found the problem. Simple, as always. I initialized the array to size 11 and Flawless Diamond would have been number 12. Apparently, setting an array at an index outside its range does in fact work.... until the next time that array is called, at which point it'll assume the value of the index being called. This is... odd... but good to know.

User avatar
Gavin boyce
 
Posts: 3436
Joined: Sat Jul 28, 2007 11:19 pm

Post » Sat Aug 23, 2014 6:25 am

Ha, glad to know it was something simple and not papyrus going nuts :tongue:

(I've had that same bug before too - one tip for the future is to look at your papyrus logs, they will tell you if an array was called with an index out of range)

User avatar
Teghan Harris
 
Posts: 3370
Joined: Mon Mar 05, 2007 1:31 pm


Return to V - Skyrim