Jump to content

Need Help With Script to Sort Items in Container by 3 Form Lists


cavbirdie

Recommended Posts

I am trying to make it so when you put something in the container it will check the list of items to go to mannequins and put them into the mannequins to be equipped by the correct mannequin.

If its not on that list it will check 2 other form lists of items that will activate displays (haven't gotten t that part of the scripting yet), give a message if its on the list, and return to the player if its not on any of the lists.

 

Here is what i have

 

ScriptName _111BW_MstrContScript extends ObjectReference


Actor Property PlayerRef Auto
FormList Property ItemToDisplay Auto
FormList Property ItemToDisplayWpn Auto
FormList Property ItemToMann Auto
ObjectReference Property MannCont Auto


Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
   If ItemToMann.HasForm(akBaseItem)
   Int iIndex1 = ItemToMann.GetSize()
      While iIndex1 > 0
      iIndex1 -= 1
         If ItemToMann.GetAt(iIndex1)>=0 
         RemoveItem(akBaseItem, aiItemCount, false, MannCont)
         Debug.messagebox("Is Mannequin Item")
         EndIf
      EndWhile
   ElseIf ItemToDisplay.HasForm(akBaseItem)
   Int iIndex2 = ItemToDisplay.GetSize()
      While iIndex2 > 0
      iIndex2 -= 1
         If ItemToDisplay.GetAt(iIndex2)<0 
         Debug.messagebox("Is Display Item")
         EndIf
      EndWhile
   ElseIf ItemToDisplayWpn.HasForm(akBaseItem)
   Int iIndex3 = ItemToDisplayWpn.GetSize()
      While iIndex3 > 0
      iIndex3 -= 1
         If ItemToDisplayWpn.GetAt(iIndex3)<0 
         Debug.messagebox("Is Display Weapon")
         Else 
         RemoveItem(akBaseItem, aiItemCount, false, akSourceContainer)
         EndIf
      EndWhile 
   EndIf
EndEvent
_111BW_MstrContScript.psc(14,31): cannot compare a form to a int (cast missing or types unrelated)
_111BW_MstrContScript.psc(23,34): cannot compare a form to a int (cast missing or types unrelated)
_111BW_MstrContScript.psc(31,37): cannot compare a form to a int (cast missing or types unrelated)
No output generated for _111BW_MstrContScript, compilation failed.

Any Help Would Be Apreciated

BTW how do i get my code to hide?

Edited by cavbirdie
Link to comment
Share on other sites

  On 3/2/2015 at 10:21 PM, cavbirdie said:

I am trying to make it so when you put something in the container it will check the list of items to go to mannequins and put them into the mannequins to be equipped by the correct mannequin.

If its not on that list it will check 2 other form lists of items that will activate displays (haven't gotten t that part of the scripting yet), give a message if its on the list, and return to the player if its not on any of the lists.

 

Here is what i have

 

ScriptName _111BW_MstrContScript extends ObjectReference


Actor Property PlayerRef Auto
FormList Property ItemToDisplay Auto
FormList Property ItemToDisplayWpn Auto
FormList Property ItemToMann Auto
ObjectReference Property MannCont Auto


Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
   If ItemToMann.HasForm(akBaseItem)
   Int iIndex1 = ItemToMann.GetSize()
      While iIndex1 > 0
      iIndex1 -= 1
         If ItemToMann.GetAt(iIndex1)>=0 
         RemoveItem(akBaseItem, aiItemCount, false, MannCont)
         Debug.messagebox("Is Mannequin Item")
         EndIf
      EndWhile
   ElseIf ItemToDisplay.HasForm(akBaseItem)
   Int iIndex2 = ItemToDisplay.GetSize()
      While iIndex2 > 0
      iIndex2 -= 1
         If ItemToDisplay.GetAt(iIndex2)<0 
         Debug.messagebox("Is Display Item")
         EndIf
      EndWhile
   ElseIf ItemToDisplayWpn.HasForm(akBaseItem)
   Int iIndex3 = ItemToDisplayWpn.GetSize()
      While iIndex3 > 0
      iIndex3 -= 1
         If ItemToDisplayWpn.GetAt(iIndex3)<0 
         Debug.messagebox("Is Display Weapon")
         Else 
         RemoveItem(akBaseItem, aiItemCount, false, akSourceContainer)
         EndIf
      EndWhile 
   EndIf
EndEvent
_111BW_MstrContScript.psc(14,31): cannot compare a form to a int (cast missing or types unrelated)
_111BW_MstrContScript.psc(23,34): cannot compare a form to a int (cast missing or types unrelated)
_111BW_MstrContScript.psc(31,37): cannot compare a form to a int (cast missing or types unrelated)
No output generated for _111BW_MstrContScript, compilation failed.

Any Help Would Be Apreciated

BTW how do i get my code to hide?

 

 

It's hard to help without knowing the lines that are giving the errors.

 

But I think they must be these:

 

If ItemToMann.GetAt(iIndex1)>=0

If ItemToDisplay.GetAt(iIndex2)<0

If ItemToDisplayWpn.GetAt(iIndex3)<0

 

Formlists are composed of forms (in your case, I'm assuming armor and other items). Formlist.GetAt() returns the form at that index, it doesn't return an integer. I'm also not sure what your goal is with the >=0 and <0.

 

If you're trying to confirm that a form exists at that index, you can use:

If FormlistX.GetAt(iIndex) 

or

 If FormlistX.GetAt(iIndex) != none

They're the same. Though a formlist created in the CK shouldn't have a none entry if you're filling it with base objects (which I assume you're doing).

 

 

If you're trying to compare the form in the formlist to akBaseItem, you can do:

If FormlistX.GetAt(iIndex) == akBaseItem

You can avoid the while loop by writing:

int iIndex = FormlistX.Find(akBaseItem)
If iIndex != -1
   ; do what you need to do
EndIf

But I'm not sure why you need to get the index of the form in the formlist since you've already confirmed that the item is in the form with FormlistX.HasForm(akBaseItem).

Link to comment
Share on other sites

Thank you Thank youThank you

 

Ive been adding and removing code to try to make it work... and your longest solution made my code half as long...

 

now i have to figure out if there is a way to do something like... is on formlist 1 at number 10 remove to Actor listed on formlist 2 at number 10?

 

ive been trying to find how to do that so thats why i was trying to bas it on the iIndex

Edited by cavbirdie
Link to comment
Share on other sites

  On 3/3/2015 at 3:22 AM, cavbirdie said:

Ive been adding and removing code to try to make it work.

 

is there a way to do something like is on formlist 1 at number 10 remove to container listed on formlist 2 at number 10?

 

ive been trying to find how to do that so thats why i was trying to bas it on the iIndex

 

Ah that makes sense then. You can use the Find function for that.

Objectreference ItemContainer

int iIndex = Formlist1.Find(akBaseObject)

If iIndex != -1
   ItemContainer = Formlist2.GetAt(iIndex)
Else
   ; actions if object not in formlist1
EndIf

And a tip -- if you want to optimize for speed, arrays are faster than formlists in papyrus. You can transfer your formlists to arrays when your script starts. The drawback is that there's no Find() function for arrays, so you'd have to iterate the array (like you were doing with the formlist above in the While loop) to find the baseobject. This would still be faster than using formlists.

Link to comment
Share on other sites

Myself I'd sync it all to property arrays.

 

 

Here's a crude example of what I mean.

The first example is so you can see what's what to get the idea of it.

The Second example is the same thing but you'd fill the properties in the CK:

ScriptName _111BW_MstrContScript extends ObjectReference

Actor Property PlayerRef Auto
FormList Property ItemToDisplay Auto
FormList Property ItemToDisplayWpn Auto
FormList Property ItemToMann Auto

ObjectReference Property ItemCont Auto ;Assign this to your Display Item container
ObjectReference Property WpnCont Auto ;Assign this to your Display Weapon container
ObjectReference Property MannCont Auto

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)

    ;I'm only setting these arrays like this so you can see what's in them, you would fill the array properties in CK and remove the array assignment from here.
    Formlist[] FL = New Formlist[3]
    FL[0] = ItemToDisplay
    FL[1] = ItemToDisplayWpn
    FL[2] = ItemToMann

    String[] Msg = New String[3]
    Msg[0] = "Is Display Item"
    Msg[1] = "Is Display Weapon"
    Msg[2] = "Is Mannequin Item"

    ObjectReference[] Cont = New ObjectReference[3]
    Cont[0] = ItemCont
    Cont[1] = WpnCont
    Cont[2] = MannCont

    Int i = 0
    Int j
    Bool bFound = False
    
    While i < FL.Length ;Loop through each formlist
        j = FL[i].Find(akBaseItem) ; Check if the akBaseItem is in the formlist
        If j >= 0
            ;We have found an item in a list, tell what type of item it is.
            Debug.Notification(Msg[i] + " and it's name is: " + akBaseItem.GetName() + " and it's index in the list is: " + j)
            
            ;Put the item in it's matching container
            Self.RemoveItem(akBaseItem, aiItemCount, false, Cont[i])

            ;When we exit the loop we'll know that the item was found and moved to another container.
            bFound = True

            ;Since I assume each list does not contain items from another list, I don't need to look any further, exit the loop.
            i = FL.Length
        EndIf
        i += 1
    EndWhile

    ;If this is false then no items were found in any lists, so we return the item to what ever container put it here.
    If !bFound
        Self.RemoveItem(akBaseItem, aiItemCount, false, akSourceContainer)
    EndIf
EndEvent

2nd example cleaned up:

ScriptName _111BW_MstrContScript extends ObjectReference

Formlist[] Property FL Auto ;In CK assign your formlists.
String[] Property Msg Auto ;In CK assign you Messages, the index of the message should match the index of your formlist.
ObjectReference[] Property Cont Auto ;In CK assign your containers, each container should match the same index as your Forlist and Message

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
    Int i = 0
    Int j
    Bool bFound = False
    While i < FL.Length
        j = FL[i].Find(akBaseItem)
        If j >= 0
            Debug.Notification(Msg[i] + " and it's name is: " + akBaseItem.GetName() + " and it's index in the list is: " + j)
            Self.RemoveItem(akBaseItem, aiItemCount, false, Cont[i])
            bFound = True
            i = FL.Length
        EndIf
        i += 1
    EndWhile
    If !bFound
        Self.RemoveItem(akBaseItem, aiItemCount, false, akSourceContainer)
    EndIf
EndEvent
Link to comment
Share on other sites

  On 3/3/2015 at 3:46 AM, jayne2132 said:

 

  On 3/3/2015 at 3:22 AM, cavbirdie said:

Ive been adding and removing code to try to make it work.

 

is there a way to do something like is on formlist 1 at number 10 remove to container listed on formlist 2 at number 10?

 

ive been trying to find how to do that so thats why i was trying to bas it on the iIndex

 

Ah that makes sense then. You can use the Find function for that.

Objectreference ItemContainer

int iIndex = Formlist1.Find(akBaseObject)

If iIndex != -1
   ItemContainer = Formlist2.GetAt(iIndex)
Else
   ; actions if object not in formlist1
EndIf

And a tip -- if you want to optimize for speed, arrays are faster than formlists in papyrus. You can transfer your formlists to arrays when your script starts. The drawback is that there's no Find() function for arrays, so you'd have to iterate the array (like you were doing with the formlist above in the While loop) to find the baseobject. This would still be faster than using formlists.

 

There is find function for arrays and I use it often.

Arrays vs form lists really they both have pros and cons.

Using them combined can break a lot of limitations that one or the other has.

 

Array's you can not initialize an array with a int variable, which means you can't dynamically assign the size of an array on the fly at runtime.

eg:

int i = 49

ObjectReference[] MyObjects = New ObjectReference

 

This will not work, so if your trying to use the count of something to set the size of an array then nope.

Well if you use SKSE 1.7.2 then you can actually initialize the size of an array using a variable.

 

You can not store an array in an array, which makes formlists handy.

 

You can not set the size of an array greater then 128

eg:

ObjectReference[] MyObjects = New ObjectReference[266]

Will fail, yet you can actually declare an array property and fill it in CK to any size from what I tested.

Once again SKSE 1.7.2 breaks that limitation.

 

No mixed form types in arrays.

 

Formlists don't seem to have a limit on the Size, I often have formlists with more the 15000 entries.

 

I can stick formlists in arrays and loop through forms very easily.

 

A formlist can contain multiple types of forms so I don't need a different formlist just because I want multiple types of items in a list.

Edited by sLoPpYdOtBiGhOlE
Link to comment
Share on other sites

attempting to figure out how to do arrays... the only script i have found so far only works with arrays so it makes sense to use them (esp if the work better anyway)

Link to comment
Share on other sites

It's not a case that they work better, it's a case of what your trying to accomplish.

An array can be just as slow if you have to loop through all elements while calling functions on each element or if you have multiple different types of items.

It really depends on what your trying to do.

 

Your formlists, how many items does each one contain?

 

Does you formlist contain more then one type of item?

eg: Armor and Weapons in 1 list (Shield is Armor, Sword is Weapon, so say you want to put stuff on a 3 piece plaque)

An array can only be declared as 1 type, but you can cast back and forth between types as needed in some instances.

 

Are you filling the formlists at runtime or are you filling the list in ck and they never change?

 

Did you understand what a property array is and how to fill it in CK? (Like what I posted in my example)?

Link to comment
Share on other sites

  On 3/3/2015 at 3:46 AM, jayne2132 said:

 

  On 3/3/2015 at 3:22 AM, cavbirdie said:

Ive been adding and removing code to try to make it work.

 

is there a way to do something like is on formlist 1 at number 10 remove to container listed on formlist 2 at number 10?

 

ive been trying to find how to do that so thats why i was trying to bas it on the iIndex

 

Ah that makes sense then. You can use the Find function for that.

Objectreference ItemContainer

int iIndex = Formlist1.Find(akBaseObject)

If iIndex != -1
   ItemContainer = Formlist2.GetAt(iIndex)
Else
   ; actions if object not in formlist1
EndIf

And a tip -- if you want to optimize for speed, arrays are faster than formlists in papyrus. You can transfer your formlists to arrays when your script starts. The drawback is that there's no Find() function for arrays, so you'd have to iterate the array (like you were doing with the formlist above in the While loop) to find the baseobject. This would still be faster than using formlists.

 

There is a find function for arrays. myArray.Find and myArray.rFind

 

Find starts at 0 index

rFind starts at the last index

 

Many people don't know about it because it was implemented in I think the 1.7 patch, back when arrays were less commonly used.

 

Formlists are slower and can have added forms be persistent. But there is no limit to how many you can have in a list(but it will get progressively slower), unlike arrays and their 128 cap(can be extended, but takes a bit of work).

 

http://www.creationkit.com/Arrays_%28Papyrus%29

 

scroll down for more info on the Find function.

Edited by Terra Nova
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...