Jump to content

Need anyone with experience with arrays to help me out..


Elathia

Recommended Posts

I have two functions. One filles a series of arrays with strings. The other was supposed to compare forms against the contents of these arrays and then fill an alias.

 

However I am able to work out the proper way to do that.

 

 

This is the arrays:

 

 

 

Function SetStringArrays()


sRestoreHealth[0] = "Wheat"
sRestoreHealth[1] = "Monarch Butterfly"
sRestoreHealth[2] = "Swamp Fungal Pod"
sRestoreHealth[3] = "Blisterwort"

sRestoreStamina[0] = "Histcarp"
sRestoreStamina[1] = "Beehive"
sRestoreStamina[2] = "Mudcrab"
sRestoreStamina[3] = "Deer"
sRestoreStamina[4] = "Elk"
sRestoreStamina[5] = "Sabre Cat"
sRestoreStamina[6] = "Snowy Sabre Cat"
sRestoreStamina[7] = "Silverside Perch"
sRestoreStamina[8] = "Torchbug"

sRegenHealth[0] = "Juniper"
sRegenHealth[1] = "Luna Moth"
sRegenHealth[2] = "Nordic Barnacle Cluster"

sRegenStamina[0] = "Bee"
sRegenStamina[1] = "Mora Tapinella"
sRegenStamina[2] = "Scaly Pholiota"

kRefs[0] = kRef01
kRefs[1] = kRef02
kRefs[2] = kRef03
kRefs[3] = kRef04
kRefs[4] = kRef05
kRefs[5] = kRef06
kRefs[6] = kRef07
kRefs[7] = kRef08
kRefs[8] = kRef09
kRefs[9] = kRef10

EndFunction

 

 

 

This is the main code.

 

 

 

Function SortNthRef()

Cell kCell = PlayerRef.GetParentCell()
Int iCellRefs = kCell.GetNumRefs(38)
Int iIndex
Int i


While (iIndex < iCellRefs)
    ObjectReference CellRefs = kCell.GetNthRef(iIndex, 38)
    if CellRefs.GetBaseObject().GetName() == "Wheat"
        kRefs[i].ForceRefTo(CellRefs)
        i += 1
    
    endif
    iIndex += 1
EndWhile

EndFunction

 

 

 

That function works as intended, but in order to do what I really want, I would have to type a ton of code. I'm trying to use those arrays to make this less painless, but all the rewriting this code I've done over the past 2 weeks have led to failure. The closest I got to doing this was this code:

 

 

 

Function SortNthRef()

Cell kCell = PlayerRef.GetParentCell()
Int iCellRefs = kCell.GetNumRefs(38)
Int iIndex
Int i
Int iNameFound

While (iIndex < iCellRefs)
    ObjectReference CellRefs = kCell.GetNthRef(iIndex, 38)
    if CellRefs.GetBaseObject().GetName() == sRestoreHealth[iNameFound]
        kRefs[i].ForceRefTo(CellRefs)
        i += 1
    
    endif
    iIndex += 1
EndWhile

EndFunction

 

 

 

The only problem with that is it starts spamming errors to the log when it goes over 10(the kRefs is 10 aliases). Other past attempts have always resulting it only doing half of what I want. The most frustrating one was when it would add one of that form to the alias, despite there being 7 that match the name. Then there comes the problem with checking the next name against the form. Trying to code that brings up new problems.

 

Any help is appreciated. I've literally tried everything I could think of.

 

Link to comment
Share on other sites

I have two functions. One filles a series of arrays with strings. The other was supposed to compare forms against the contents of these arrays and then fill an alias.

 

...

 

The only problem with that is it starts spamming errors to the log when it goes over 10(the kRefs is 10 aliases). Other past attempts have always resulting it only doing half of what I want. The most frustrating one was when it would add one of that form to the alias, despite there being 7 that match the name. Then there comes the problem with checking the next name against the form. Trying to code that brings up new problems.

 

Any help is appreciated. I've literally tried everything I could think of.

 

 

You code concept looks good to me, over all. If I understand, the first function works as you want it to, but the second one doesn't?

 

If you defined kRefs with a length of 10, both functions should spam log errors when i > 9. To avoid this, you can add a check to exit the function ("return") or just exit the while loop when i = 9.

 

Checking the cell ref against your array should be quick. http://www.creationkit.com/Arrays_(Papyrus)#Searching_Arrays

 

Here's an example with your code:

string sRefName = CellRefs.GetBaseObject().GetName()
if sRestoreHealth.Find(sRefName) != -1
   kRefs[i].ForceRefTo(CellRefs)
   i += 1  
   if i >= 10
      return
   endif
endif

If your goal is to check all the string arrays, you will have to check them separately (sRestoreHealth, sRestoreStamina, etc) as unfortunately papyrus doesn't supposed nested arrays. But you could do this by just adding OR (||) clauses to the IF statement above.

 

Does this answer your question?

 

Edited to add: When in doubt, just add a ton of debug.trace statements to your functions to pinpoint what's going on.

Edited by jayne2132
Link to comment
Share on other sites

I'm assuming you only want a different type in each alias?

I haven't tested it, but I used Find() on each array and used filter to check that the name is not already used.

I'm also assuming that your willing to force ref on an already filled alias?

 

Function SortNthRef()
    Cell kCell = PlayerRef.GetParentCell()
    Int iCellRefs = kCell.GetNumRefs(38)
    Int i = 0
    Int j = 0
    String[] sUsed = New String[10] ;So each Alias has a different item, should be the size of kRefs arary.
    String sName

    While (i < iCellRefs) && (j < kRefs.Length)
        ObjectReference CellRefs = kCell.GetNthRef(iCellRefs, 38)
        sName = CellRefs.GetBaseObject().GetName()
        If (sName != "") && (sUsed.Find(sName) < 0) && ((sRestoreHealth.Find(sName) >= 0) || (sRestoreStamina.Find(sName) >= 0) || (sRegenHealth.Find(sName) >= 0) || (sRegenStamina.Find(sName) >= 0))
            kRefs[j].ForceRefTo(CellRefs)
            sUsed[j] = sName
            j += 1
        EndIf
        i += 1
    EndWhile
EndFunction
Link to comment
Share on other sites

Side note

If you wonder why I prefer to use Find(x) >= 0 instead of Find(x) != -1

 

I don't trust papyrus returns on functions or should I say the documented possible returns on function.

Find() returns -1 if it failed to find anything...

But, if for no apparent reason which should never happen if it returned a negative number other then -1 then you are now passing a negative number to an array as an index.

I know this should never happen as -1 is what the documentation says it returns on failure, but I've been bitten by other functions that say this is the possible return only to be returned an undocumented value.

Once bitten twice shy.

Edited by sLoPpYdOtBiGhOlE
Link to comment
Share on other sites

 

 

Does this answer your question?

Yes, but that's not what I'm doing. The other arrays will be used in another function. I'm just starting with the first one because it's where I encountered this problem. If I can get over this hump, the rest will fall into place.

Yeah first function always works. It's just a work around I use to avoid using property arrays, as I need to change the contents at run time, which properties do allow, but they get baked in the save, so subsequent changes don't occur. You know how that goes. So empty strings are filled on quest start.

 

 

 

I'm assuming you only want a different type in each alias?

Yes but, if the found form has more than one of the same name, I want all of them to be added.

 

Say if there is 7 butterflies. I want all 7 added. That's where the issue begins for me, as I couldn't figure out how to add them to the alias, and THEN go to the next name in the array without breaking the function and spamming the log.

 

I don't want to force fill already filled aliases.

Link to comment
Share on other sites

Cool, remove the filter and check if the reference is filled:

Function SortNthRef()
    Cell kCell = PlayerRef.GetParentCell()
    Int iCellRefs = kCell.GetNumRefs(38)
    Int i = 0
    Int j = 0
    String sName

    While (i < iCellRefs) && (j < kRefs.Length)
        ObjectReference CellRefs = kCell.GetNthRef(iCellRefs, 38)
        sName = CellRefs.GetBaseObject().GetName()
        If (sName != "") && ((sRestoreHealth.Find(sName) >= 0) || (sRestoreStamina.Find(sName) >= 0) || (sRegenHealth.Find(sName) >= 0) || (sRegenStamina.Find(sName) >= 0))
            If kRefs[j].GetReference() == none
                kRefs[j].ForceRefTo(CellRefs)
            EndIF
            j += 1
        EndIf
        i += 1
    EndWhile
EndFunction

Edited the function, this way when the references are filled it quits the loop instead of continuing on checking cell references.

 

Edit Again: the above wont work either as it will skip past a cell ref item if the alias is filled, when it actually needs to find the first available reference alias to fill instead.. doh

Edited by sLoPpYdOtBiGhOlE
Link to comment
Share on other sites

Side note

If you wonder why I prefer to use Find(x) >= 0 instead of Find(x) != -1

 

Never heard of this problem. Can you share ones you have trouble with?

 

I use -1 to make the code more readable. <0 makes me have to think.

 

And if I'm using a lot of functions like these in a script, I add something like:

 

int NotFound = -1

 

at the top of the script, and then use

 

if somereturnvalue != NotFound

 

Everyone has their own preference, but this reduces (stupid) errors for me.

Link to comment
Share on other sites

@ sloppy, well your code works(had to modify it a bit) but the engine seems to be ignoring the array, and instead is adding all the forms found by GetNthRef, rather than ONLY adding the names that match whats in the array.

 

I think this is at least on the right track though.

 

Edit: OK just as everything else, even making changes to your code, it still prefers to fill the entire reference alias array with forms unrelated to whats inside the string array.

 

I'm convinced that the Find function is not doing what one would expect.

Edited by Elathia
Link to comment
Share on other sites

 

Side note

If you wonder why I prefer to use Find(x) >= 0 instead of Find(x) != -1

 

Never heard of this problem. Can you share ones you have trouble with?

 

I use -1 to make the code more readable. <0 makes me have to think.

 

And if I'm using a lot of functions like these in a script, I add something like:

 

int NotFound = -1

 

at the top of the script, and then use

 

if somereturnvalue != NotFound

 

Everyone has their own preference, but this reduces (stupid) errors for me.

 

Probably because I have some bad coding practices.

Example of what I mean

    Int i = Test.Find("B4") ; This should and will never happen, but if i is other then -1, eg: -2 or -3 etc
    If i != -1 ;this means that any number negative or positive other then -1 will pass.
        Debug.Notification(Test[i]) ;Now I'm passing -Number other then -1 then I'm passing a negative index.
    EndIf

 

    Int i = Test.Find("B4") ; This should and will never happen, but if i is other then -1, eg: -2 or -3 etc
    If i >= 0 ;This means any negative number will be ignored.
        Debug.Notification(Test[i]) ;This will only be called ifit's not a negative number
    EndIf

In these examples there is no problem with the return of Find as failure is -1 and nothing else.

 

As I say will never happen, but from looking what a return can possibly be on functions and recieveing a value that is not documented.

I made it a personal habit to not rely on a specific negative number when I'm passing the return value as an array index

Link to comment
Share on other sites

Ok this is a lame limitation of papyrus.

 

In order to get this doing what I want, all arrays need to be the same length. This wouldn't be a problem if not for the fact that I don't care to create 128 reference aliases, when I'm only going to need 10. The whole procedure is totally unecessary. Also papyrus seems to be unable to handle elements that have the same values. You can't isolate them and then void out the values that are not the same and then pull out the remaining values and add them another array or whatever. The array.Find function works as intended, but the operations you perform after that do not coincide with array.Find, if that makes any sense. This isn't without a tiny light though: I learned a great deal about arrays because of all of this.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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