Need urgent help: script logic defies logic

Post » Thu Jun 21, 2012 1:47 am

EDIT:
This matter has been solved
I scrapped the whole quest, script, and FormList. Created them entirely new with new EditorIDs. Now it reports the correct size.


Original post here:

So I have this script here:
Scriptname RaestlozArmorChangerPlayerScript extends ReferenceAlias{Script that runs on Player.Changes the instance of armor that player gets}FormList Property VanillaArmorList AutoFormList Property CustomArmorList AutoBool Property ArmorChangingEnabled AutoSpell Property switcherSpell Autoint TempIndex = 0Event OnInit()   AddInventoryEventFilter(VanillaArmorList)   if (Game.getPlayer().hasSpell(switcherSpell) == false)	  Game.getPlayer().addSpell(switcherSpell)   endifendEventEvent OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)   if (Game.getPlayer().hasSpell(switcherSpell) == false)	  Game.getPlayer().addSpell(switcherSpell)   end   GetFormIndex(VanillaArmorList ,CustomArmorList ,akBaseItem,aiItemCount)endEventFunction GetFormIndex(FormList SourceList, FormList TargetList, Form Member, int iItemCount) global{Gets the index of Member in List. Returns -1 if not found}   if (!SourceList.HasForm(Member))	  Return   endif   debug.messagebox("item is present in formlist");   int Index = 0   int MaxIndex = SourceList.getSize()   bool letGo = false   While (letGo == false)	  if(SourceList.GetAt(Index) == Member)		 Game.GetPlayer().removeItem(Member, iItemCount,false)		 Game.getPlayer().addItem(TargetList.GetAt(Index),iItemCount,false)		 debug.messagebox("You got something");		 letGo = true	  elseif (Index == MaxIndex)		 letGo = true;		 trace("finally... it's over");	  else		 debug.trace("test   " + Index);		 Index +=1	  endif   endwhile     Return IndexEndFunction
In case your eyes are a bit sore at the moment, I'm trying to exchange an item that a player takes with something else when they take the item.

The items are listed in a FormList, which literally consists of only 11 items.

You may have noticed that I've put a trace to see how many times the function counts (how many times that "Index" is increased)

The script log prints "test 0" and "test 1072" in the same file.

It defies logic, as counting 12 times is already an overkill. Not to mention if it goes beyond 12 it shouldn't even be able to stop at all. The item in question is at index 5 in 0-10 range. So the 6th count should have done the job.

What I need to know is goddang why? This is not even about my game being slow (it's not, the test environment has 60 fps at all times to make sure no lag hinders the script engine). iPresentInterval is also at value 1, in case it has any impact

The game managed to count well past the limit, ignoring the safe guard I put there in form of MaxIndex and managed to find something that is present at index 5 after counting 1073 times.

Don't tell me that FormList actually do not behave like Arrays and that an 11 item list has more than 11 indexes?

EDIT:
Okay, I traced the size of the FormList and HOLY MOTHER******* it has 1374 slots! To be sure, I created an entirely new FormList to test the size (now with only 9 items) and sure enough, there are 1374 slots there. This is extremely confusing.

On a side note, the script engine managed to count 6 times in one second. Very slow I think, but perhaps it's because there is that if check there?
User avatar
Robert Jr
 
Posts: 3447
Joined: Fri Nov 23, 2007 7:49 pm

Post » Thu Jun 21, 2012 2:13 am

Try:
ScriptName RaestlozArmorChangerPlayerScript extends ReferenceAliasActor Property PlayerREF AutoFormList Property VanillaArmorList AutoFormList Property CustomArmorList AutoBool Property ArmorChangingEnabled AutoSpell Property switcherSpell Autoint TempIndex = 0Event OnInit()	AddInventoryEventFilter(VanillaArmorList)	If !PlayerREF.HasSpell(switcherSpell)		PlayerREF.AddSpell(switcherSpell)	EndIfEndEventEvent OnItemAdded(Form akBaseItem, Int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer);	If !PlayerREF.HasSpell(switcherSpell) ;		PlayerREF.AddSpell(switcherSpell);	EndIf	GetFormIndex(VanillaArmorList, CustomArmorList, akBaseItem, aiItemCount)endEventInt Function GetFormIndex(FormList akSourceList = None, FormList akTargetList = None, Form akBaseItem = None, Int aiItemCount = 0, Int aiIndex = 0) Global	If !akSourceList.HasForm(akForm)		Return -1	Else		aiIndex = akSourceList.GetSize() - 1 ; Item 11 index is 10		While akBaseItem != akSourceList.GetAt(aiIndex)			aiIndex -= 1		EndWhile		PlayerREF.RemoveItem(akBaseItem, aiItemCount, False)		PlayerREF.AddItem(akTargetList.GetAt(aiIndex), aiItemCount, False)		Debug.Notification("You got something")	EndIf 	Return aiIndexEndFunction
You could just transplant the function into the OnItemAdded event.
User avatar
Anthony Diaz
 
Posts: 3474
Joined: Thu Aug 09, 2007 11:24 pm

Post » Thu Jun 21, 2012 7:03 am

A couple of tips:

Make sure exactly what is returned by SourceList.GetSize(). Is it the number you expect?

Don't use "While True" (or "While False") loops. Make the loop depend on the Index. "While Index < MaxIndex". Now, when you increment the Index, you are guaranteed to exit the loop. (If you've verified the value of MaxIndex.)

Seperate your "If" conditions. Your "If" and "ElseIf" conditions test different things. That can work, but it makes for more difficult trouble-shooting.


Edit: Or see the better version that @JustinOther wrote, while I was writting this. 8-)>
User avatar
Strawberry
 
Posts: 3446
Joined: Thu Jul 05, 2007 11:08 am

Post » Thu Jun 21, 2012 8:15 am

I wonder if one reason it may be slow is that when you do the line

Game.GetPlayer().AddItem(akTargetList.GetAt(aiIndex), aiItemCount, False)

that could be calling the OnItemAdded event again, and so looping through the formlist twice for every item you add--once for the original item and once for the item you're replacing it with.
User avatar
Rude_Bitch_420
 
Posts: 3429
Joined: Wed Aug 08, 2007 2:26 pm

Post » Thu Jun 21, 2012 12:15 am

@Justin:
I'll try it once I'm back from work. Thanks man.

@Calen:
No, it's not the number I expect. See the edit.

There is no point in using MaxIndex as the loop limiter. HasForm has already taken care of that. If the item is not present in the FormList, the function won't check for anything. So the iteration is guaranteed to find something.

Also, yes my if and elseif test different conditions. That's the very reason elseif was created by Fathers of Programming in the first place.

@Dreamking.
No, because I filter the event with a FormList, and the item added is from another list, and each list contains different items. I suspect it's because it has to fetch the object itself and compare it with another object.
User avatar
Jamie Lee
 
Posts: 3415
Joined: Sun Jun 17, 2007 9:15 am

Post » Thu Jun 21, 2012 1:04 pm

Just tried the script from justin, and also did a few changes. The whole event script is now like this:

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)   if(!VanillaArmorList.HasForm(akBaseItem))      return   else      TempIndex = VanillaArmorList.GetSize()      while (VanillaArmorList.getAt(TempIndex) != akBaseItem)         debug.trace("test "+TempIndex)         TempIndex -= 1      endwhile      Game.GetPlayer().removeItem(akBaseItem, aiItemCount,false)      Game.getPlayer().addItem(CustomArmorList.GetAt(TempIndex),aiItemCount,false)      debug.trace("gotcha yeah")      return   endifendEvent

And it still doesn't work. It takes 2 seconds to count from 1374 to 1074, and 20 goddang seconds to count from 0 to 1073
the bottleneck seems to the the fact that the FormList creates 1200 empty entries for the sole purpose of screwing with me
User avatar
Ridhwan Hemsome
 
Posts: 3501
Joined: Sun May 06, 2007 2:13 pm

Post » Thu Jun 21, 2012 6:44 am

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)	If VanillaArmorList.HasForm(akBaseItem)		TempIndex = VanillaArmorList.GetSize() - 1 ; No need to check index 11		While akBaseItem != VanillaArmorList.GetAt(TempIndex) As Form			TempIndex -= 1		EndWhile		Game.GetPlayer().RemoveItem(akBaseItem, aiItemCount, False)		Game.GetPlayer().AddItem(CustomArmorList.GetAt(TempIndex), aiItemCount, False)	EndIfEndEvent
There's no way that won't work unless the FormLists don't line up. If your FLSTs are somehow messing with you, try Revert() and/or gutting their members and refilling?
User avatar
Robert Garcia
 
Posts: 3323
Joined: Thu Oct 11, 2007 5:26 pm

Post » Thu Jun 21, 2012 8:47 am

It's not that it doesn't work. It DOES work as in the item is found, but it's in no way different than my original version. Well, I can say it's "faster", but it still have to count at least 200 times.
User avatar
Vickytoria Vasquez
 
Posts: 3456
Joined: Thu Aug 31, 2006 7:06 pm

Post » Thu Jun 21, 2012 4:30 am

You could make smaller, more specific FLSTs to speed it up further. I thought there were only 11 items in the lists?
User avatar
Jeffrey Lawson
 
Posts: 3485
Joined: Tue Oct 16, 2007 5:36 pm

Post » Thu Jun 21, 2012 11:02 am

You could make smaller, more specific FLSTs to speed it up further. I thought there were only 11 items in the lists?
It is. That's why I said it defies logic. I even created an entirely new FormList just to be sure, and it still counts from 1374. Incidentally, there are two old FormLists that has 1374 items in it, but I can't test it now because for some reason the quest broke. See my other thread http://www.gamesas.com/topic/1371733-need-help-script-is-no-longer-attached-to-player-after-being-removed/ for explanation of the incident
User avatar
jasminε
 
Posts: 3511
Joined: Mon Jan 29, 2007 4:12 am

Post » Thu Jun 21, 2012 12:34 pm

Pull the script to wipe the slate clean, reattach and fill the properties? Sounds like the properties are not pointed where they should be?
User avatar
Jerry Jr. Ortiz
 
Posts: 3457
Joined: Fri Nov 23, 2007 12:39 pm

Post » Thu Jun 21, 2012 9:04 am

Pull the script to wipe the slate clean, reattach and fill the properties? Sounds like the properties are not pointed where they should be?
Have you seen my other thread? I did that and now the script is not even attached to the player, and this is not some "dirty save" stuff: I loaded a save that has never been touched and the result is still the same.

But looks like it's more than that. Index 0 and index 1374 is empty (none). It looks like the property prepared 1374 slots because the last property value has 1374 slots
User avatar
Crystal Clarke
 
Posts: 3410
Joined: Mon Dec 11, 2006 5:55 am

Post » Thu Jun 21, 2012 4:29 am

I just tried creating an empty formlist and checking its size, I got the correct return value (0). Could your mod be corrupted somehow? What happens if you create a new formlist in a new mod and check its size?
User avatar
Mrs shelly Sugarplum
 
Posts: 3440
Joined: Thu Jun 15, 2006 2:16 am

Post » Thu Jun 21, 2012 3:51 am

I just tried creating an empty formlist and checking its size, I got the correct return value (0). Could your mod be corrupted somehow? What happens if you create a new formlist in a new mod and check its size?
I shudder at the thought of that. I've spent two weeks duplicating 95% of vanilla armors. I'm not going to lose this esp no matter what. I'm currently creating a new quest to attach to player the script.

Like I said, I created a brand new FormList with only 9 items and it has 1374 slots. The number is too arbitrary and the fact that I have a FormList with 1374 items in it seems to be too much to be a coincidence
User avatar
Jason King
 
Posts: 3382
Joined: Tue Jul 17, 2007 2:05 pm

Post » Wed Jun 20, 2012 10:43 pm

Well, are you sure that you assigned the properties correctly? Maybe instead of pointing to your 9 item formlist, the property is actually pointing at your 1374 item one.

Otherwise, you could make sure you're testing with a clean save by using COC from the main menu.
User avatar
lauren cleaves
 
Posts: 3307
Joined: Tue Aug 15, 2006 8:35 am

Post » Thu Jun 21, 2012 9:00 am

F**K YES! I scrapped the whole quest, script, and FormList. Created them entirely new with new EditorIDs. Now it reports the correct size.

Very-very awesome

But this got me thinking: what was the cause? Anyway, gonna populate this with hundreds of items and see what happens

@Random:
No, it's the correct property. Like I said, index 0 and index 1374 are empty, while in the bigass FormList they have something (obviously)

Also, I'm not sure I'm following you, use COC from main menu? Isn't COC used for moving to a cell? Like, coc testinghall?
User avatar
Sandeep Khatkar
 
Posts: 3364
Joined: Wed Jul 18, 2007 11:02 am

Post » Thu Jun 21, 2012 6:49 am

If you COC from the main menu, you will teleport to the specified cell with the default player character ("Prisoner"), therefore creating a new game without needing to go through the tutorial.
User avatar
Elea Rossi
 
Posts: 3554
Joined: Tue Mar 27, 2007 1:39 am

Post » Thu Jun 21, 2012 10:38 am

Wait... are you talking about the main menu as in "that screen with smokes and invisible guys chanting Dovahkiin Dovahkiin"?
User avatar
Nichola Haynes
 
Posts: 3457
Joined: Tue Aug 01, 2006 4:54 pm

Post » Thu Jun 21, 2012 8:35 am

Yes. Is that what they're chanting? I had no idea.
User avatar
Louise Lowe
 
Posts: 3262
Joined: Fri Jul 28, 2006 9:08 am


Return to V - Skyrim