Author Topic: Arrays  (Read 2242 times)

Legacy_TrekSL

  • Newbie
  • *
  • Posts: 35
  • Karma: +0/-0
Arrays
« on: July 01, 2011, 12:18:36 pm »


               So I've spoken with a helpful guy here called Shadoow to help with a listening script for something I'm designing. Now, I come fresh off of a java course which is similar to C but with differences. If you look at this test code, it works but for just one word. I could, of course, just make lots of string variables, which might be simple for multiple words and that would be ok, except I was thinking about using an array as a way of keeping it tidy - these will be all strings that i'm storing. However, I've only just learned that NWN doesn't allow arrays but someone mentioned pseudo arrays? Can someone enlighten me?

object oDoor = GetObjectByTag("door");//This is the door to open. Need a global variable
void StartListening(object oPlayer, string sScript)//Two functions here, start listening setting a string on the player
{
SetLocalString(oPlayer,"START_LISTENING",sScript);
}
void StopListening(object oPlayer)
{
DeleteLocalString(oPlayer,"START_LISTENING");
}
void main()
{
int nEvent = GetLocalInt(GetModule(),"GetRunningEvent()");
if(nEvent == 15)//check whether the onchat event Module integer exists when the player enters the trigger
{
object oPC = OBJECT_SELF;//set PC up as oPC
string sMessage = GetPCChatMessage();//sMessage will be whatever is written in chat
SetPCChatMessage();//<--Can be commented out- avoids what the player has typed from appearing onscreen
StopListening(oPC);//disable further listening
if(sMessage == "habe")//<-- this is a simple german learning game, hence the word, nested if statement.
{
SetLocked(oDoor, FALSE);//Unlock my door
}
}
else//script fired from trigger
{
object oPC = GetEnteringObject();
if(!GetIsPC(oPC))return;
StartListening(oPC,"secrettest");//start listen the player
FloatingTextStringOnCreature("You may now speak",oPC);
}
}
               
               

               
            

Legacy_CID-78

  • Sr. Member
  • ****
  • Posts: 261
  • Karma: +0/-0
Arrays
« Reply #1 on: July 01, 2011, 12:33:21 pm »


               Pseudo arrays is either a set of Local variables or a Localstring, with fixed size or containing seperating symbols.

ie name|str|int|cha could be treated as a pseudo array with four strings in it.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Arrays
« Reply #2 on: July 01, 2011, 05:48:59 pm »


               If you look at z-dialogue by pspeed, on the Vault, its includes contain pseudoarray functions. Or, for simpler applications like yours, you can just use functions like this:


struct IntList {
    int size;

    int i0,  i1,  i2,  i3,  i4;
    int i5,  i6,  i7,  i8,  i9;
};

struct StringList {
    int size;

    string s0,  s1,  s2,  s3;
    string s4,  s5,  s6,  s7;
    string s8,  s9,  s10, s11;
    string s12, s13, s14, s15;
};

struct SubString {
    string first, rest;
};

/* Return the substring at the given index nIndex of sString, separating
 * sString with sSep. */
string GetStringSubString (string sString, int nIndex, string sSep=" ");

/* Return the number of substrings sString would have if it were separated
 * by sSep. */
int GetStringSubStrings (string sString, string sSep=" ");

/* Return a random string of sString separated by sSep. */
string GetRandomSubString (string sString, string sSep=" ");

/* Return a SubString struct containing the first substring of sString
 * separated by sSep, as well as the remainder of sString. The idiom
 * would be:
 *
 *   struct SubString ss;
 *
 *   ss.rest = sString;
 *
 *   while (ss.rest != "") {
 *       ss = GetFirstSubString(ss.rest);
 *
 *       (do things here)
 *   }
 */
struct SubString GetFirstSubString (string sString, string sSep = " ");

/* Return a StringList struct containing strings extracted from sString
 * separated by sSep. */
struct StringList GetStringList (string sString, string sSep=" ", int nLimit=16);

/* Return an IntList struct containing integers extracted from sString
 * separated by sSep. */
struct IntList GetIntList (string sString, string sSep=" ", int nLimit=10);


string GetStringSubString (string sString, int nIndex, string sSep=" ") {
    int nSep, nStart = 0, nSkip = GetStringLength(sSep);

    while (nIndex-- > 0) {
        nSep = FindSubString(sString, sSep, nStart);

        if (nSep < 0)
            return "";

        nStart = nSep + nSkip;
    }

    if ((nSep = FindSubString(sString, sSep, nStart)) < 0)
        nSep = GetStringLength(sString);

    return GetSubString(sString, nStart, (nSep - nStart));
}

int GetStringSubStrings (string sString, string sSep=" ") {
    int nCount = 1, nStart = 0;
    int nSep = FindSubString(sString, sSep);
    int nSkip = GetStringLength(sSep);

    if (nSkip < 1)
        return 1;

    while (nSep >= 0) {
        nCount++;
        nSep = FindSubString(sString, sSep, nSep + nSkip);
    }

    return nCount;
}

string GetRandomSubString (string sString, string sSep=" ") {
    int nCount = GetStringSubStrings(sString, sSep);

    return GetStringSubString(sString, Random(nCount), sSep);
}

struct SubString GetFirstSubString (string sString, string sSep = " ") {
    struct SubString ret;
    int nSep = FindSubString(sString, sSep);

    if (nSep < 0) {
        ret.first = sString;
        ret.rest  = "";

        return ret;
    }

    ret.first = GetStringLeft(sString, nSep);
    ret.rest  = GetStringRight(sString, GetStringLength(sString) - (nSep + GetStringLength(sSep)));

    return ret;
}

struct StringList GetStringList (string sString, string sSep=" ", int nLimit=16) {
    int nCount = 0, nSep = 0, nStart = 0;
    int nSkip = GetStringLength(sSep);
    int nLen = GetStringLength(sString);
    struct StringList sl;

    if (nSkip < 1) {
        sl.size = 0;
        return sl;
    }

    while (nSep < nLen && nCount < nLimit) {
        nSep = FindSubString(sString, sSep, nStart);
        if (nSep < 0)
            nSep = nLen;

        switch (nCount & 1) {
            case 0: switch (nCount++) {
                case  0: sl.s0  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  2: sl.s2  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  4: sl.s4  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  6: sl.s6  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  8: sl.s8  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 10: sl.s10 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 12: sl.s12 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 14: sl.s14 = GetSubString(sString, nStart, (nSep - nStart)); break;
            }
            break;

            case 1: switch (nCount++) {
                case  1: sl.s1  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  3: sl.s3  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  5: sl.s5  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  7: sl.s7  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case  9: sl.s9  = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 11: sl.s11 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 13: sl.s13 = GetSubString(sString, nStart, (nSep - nStart)); break;
                case 15: sl.s15 = GetSubString(sString, nStart, (nSep - nStart)); break;
            }
            break;
        }

        nStart = nSep + nSkip;
    }

    sl.size = nCount;

    return sl;
}

struct IntList GetIntList (string sString, string sSep=" ", int nLimit=10) {
    int nCount = 0, nSep = 0, nStart = 0;
    int nLen = GetStringLength(sString);
    int nSkip = GetStringLength(sSep);
    struct IntList il;

    if (nSkip < 1) {
        il.size = 0;
        return il;
    }

    while (nSep < nLen && nCount < nLimit) {
        nSep = FindSubString(sString, sSep, nStart);
        if (nSep < 0)
            nSep = nLen;

        switch (nCount++) {
            case  0: il.i0  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  1: il.i1  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  2: il.i2  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  3: il.i3  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  4: il.i4  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  5: il.i5  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  6: il.i6  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  7: il.i7  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  8: il.i8  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
            case  9: il.i9  = StringToInt(GetSubString(sString, nStart, (nSep - nStart))); break;
        }

        nStart = nSep + nSkip;
    }

    il.size = nCount;

    return il;
}

Funky
               
               

               


                     Modifié par FunkySwerve, 01 juillet 2011 - 04:50 .
                     
                  


            

Legacy_CID-78

  • Sr. Member
  • ****
  • Posts: 261
  • Karma: +0/-0
Arrays
« Reply #3 on: July 02, 2011, 06:04:51 am »


               some of those look quite awful. fixed size arrays is quite pointless you could use a regular struct with propper variable names for that. and when you want to get data you either loop over the string or get the right data directly.  depending on your pseudo array approach, switch/case is pointless, you can just put the lines after each other if you want to push them into a struct.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Arrays
« Reply #4 on: July 02, 2011, 10:16:47 am »


               You don't know what you're talking about.
a) None of those are fixed length arrays. Some of them are limited in the number of array components. If you think that's pointless, your argument is not with me, but with the professional coders of the world. Think resref (16), VARCHAR (255), and so on.
'B)' The unlimited pseudoarray function there is GetFirstSubString. The fact that we have not just it but others should really have tipped you off that the others have some separate utility. By way of example, here's some code that uses both limited and unlimited arrays - an array of arrays, space-separated item property strings:


    if (nAddCount) {

        sAddedDescription = "=====\\nEnchantment Quantity: " + GetEnchantmentQuantity(nAddCount) + " (+" +
                                 IntToString(nAddCount) + ")\\n" + C_LIGHT_GREEN + "Added:\\n";
        for (ss = GetFirstSubString(sAdded, " "); ss.first != ""; ss = GetFirstSubString(ss.rest, " ")) {

            il = GetIntList(ss.first, ",");
            if (GetIsItemPropertyStacking(il.i0, il.i1)) {

                if (il.i0 == ITEM_PROPERTY_ARCANE_SPELL_FAILURE){

                    //do special asf encoding
                    if (il.i3 < 10) {
                        nX = 10-il.i3;//encode 'asf good 1-10)
                        AddLocalInt(oItem, "RIPStack_84_0", nX);
                    }
                    else {//fake subtype for bad spell fail prop
                        nX = il.i3-9;//encode 'asf bad 1-10)
                        AddLocalInt(oItem, "RIPStack_84_1", nX);
                   }
                }
                else
                    AddLocalInt(oItem, "RIPStack_"+IntToString(il.i0)+"_"+IntToString(il.i1), il.i3);

            } else {


                sAssemble = IntToString(il.i0)+","+IntToString(il.i1)+","
                            +IntToString(il.i2)+","+IntToString(il.i3)+","
                            +IntToString(il.i4)+","+IntToString(il.i5);

                sTempString = GetLocalString(oItem, "TempPropString");
                if (sTempString != "")
                    sTempString += " ";

                sTempString += sAssemble;
                SetLocalString(oItem, "TempPropString", sTempString);
            }

            if (GetIsItemPropertyImmunity(il.i0))
                il.i3 = GetCostValueFromPercentImmune(il.i3);

            sAddedDescription += C_LIGHT_GREEN + "  " + GetItemPropertyInfoDirect(il.i0, il.i1, il.i2, il.i3, il.i4, il.i5) + "\\n";
        }
    }

Funky
               
               

               


                     Modifié par FunkySwerve, 02 juillet 2011 - 09:17 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Arrays
« Reply #5 on: July 02, 2011, 11:34:58 am »


               Anyway OP want to make a chat based conversation with key words aka morrowind or where it was? maybe in Wizardry.

And I cant see any good algorhytm to make it, thats why I sent him there. Does anyone have any idea?
               
               

               
            

Legacy_CID-78

  • Sr. Member
  • ****
  • Posts: 261
  • Karma: +0/-0
Arrays
« Reply #6 on: July 02, 2011, 12:31:00 pm »


               you can simply use space as a delimiter and check each word against a keyword list. and execute accordingly.

funky:

No your adding a unnecissary layer on your system, that isn't the optimal way of doing arrays, especially not if you want to emulate how arrays work in C and C++. It also make the code harder to read.

you want to work as close to the memory as you can. and you want to have clean code. The only reason i can see todo things your way is if you got alot of similar structs but with diffrent names, and you want to save some code space. Normally you want to work directly towards the pseudostring and not against an struct which you can't build loop with.

if you skip the struct layer you got what you need.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Arrays
« Reply #7 on: July 02, 2011, 02:19:11 pm »


               

ShaDoOoW wrote...

Anyway OP want to make a chat based conversation with key words aka morrowind or where it was? maybe in Wizardry.

And I cant see any good algorhytm to make it, thats why I sent him there. Does anyone have any idea?

Just a space-separated string using FindSubString or one of the functions I provided will do the trick. I'd elaborate, but without knowing more specifics, any number of ways could be best. You could allow multiple acceptable passwords with FSS != -1, for example, or randomly changing passes with GetRandomSubString, or any number of other possibilities.

Funky
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Arrays
« Reply #8 on: July 02, 2011, 02:38:47 pm »


               I really agree with Funky, in that we need more info on  what he is designing, to give meaningfull feed back.

If it is just a single NPC that this chat is happening with, The old set listening pattern could do away with the need for arrays. 

If it is a module wide system using On PC chat event. Then the packed string sounds like a good option.  

But more information on the system is needed.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Arrays
« Reply #9 on: July 02, 2011, 03:13:24 pm »


               

CID-78 wrote...
funky:

No your adding a unnecissary layer on your system, that isn't the optimal way of doing arrays, especially not if you want to emulate how arrays work in C and C++. It also make the code harder to read.

You just called them fixed length arrays, and now you want to lecture me on optimization? Lol. First of all, this isn't my code. It was written by a professional - acaos. Secondly, I never said it was the 'optimal' way to do arrays. Without pointers, I'm not really sure that any one way is much better than another, frankly. Those functions were NOT, however, written with only speed in mind, but also convenience. The more you code, the more you realize that the 'best' code is not just the fastest - there are many other concerns to consider, like modularily, readability (and they most certainly do NOT make the code harder to read, they make it easier - you yourself mention saving on code space below), and convenience. And, while we're at it, part of the usefulness of those functions IS PRECISELY that you can treat arrays in more C-like fashion - by pointing directly to a member of the array in your code. See, e.g., the code I posted above.

If you want to run some speed tests against your method, by all means, have at it - the differences were talking about are miniscule, for considerable gains in the other departments.

you want to work as close to the memory as you can. and you want to have clean code.

The concept of working close to the memory is sort of inane when applied to nwscript. It's not like we're doing mallocs or worrying about packing our arrays into nice tidy sections here. Maybe with nwnx plugins. As for clean code, that's part of the motivation for these functions, as I noted above.

The only reason i can see todo things your way is if you got alot of similar structs but with diffrent names,

No, not just structs. These are pseudoarray functions. IntList, by way of example, is used all over the place in our mod, for schlepping up numerical data in string into ready-to-use format. It can handle an enormous variety of things, from dynamically applied var-based weapon onhits (yes, it's quite fast enough for that, and then some), to our quest-system data, to parsing chat commands with multiple numeric inputs. I'm getting the impression that you really don't understand how we're using these, so here's another example (var-based weapon onhits able to apply any effect/s with just about any conditions - they're used for nearly all our npcs' onhits and for a fair number of pc-based abilities, all running from a single script, the intelligent weapon onhit):


/*
 * OnHitDamages format:
 *   TYPE,DICE,SIDES,BONUS[,RACEMASK]
 *
 * OnHitEffects format:
 *   DYNEFFECT[|CHECK[|CHECK...]]
 *
 * DYNEFFECT format:
 *   LINKEFFECT[;LINKEFFECT...][:SECONDS[+RANDOM]][:E|S]][/VFX][#SPELLID]
 *
 * LINKEFFECT format:
 *   EFFECTID[,PARAM...]
 *
 * CHECK format:
 *   CHECKTYPE:PARAM[:PARAM...][/NAME]
 *
 * CHECKTYPES
 *   1 - percent chance (param is percentage chance)
 *   2 - saving throw (params are type, dc, random dc, subtype, feedback)
 *   3 - ability check (params are ability, dc, random dc, feedback, auto)
 *   4 - skill check (params are skill, dc, random dc, feedback, auto)
 *   5 - favored enemy check (param is a favored enemy mask)
 *   6 - spell resistance check (param is spell penetration)
 *
 *   & - last check was successful (and)
 *   ^ - last check failed (exclusive or)
 *
 * OnHitBreach (integer)
 *   if > 0 will breach that many spells
 *   if < 0 will act as a dispel of level = abs(OnHitBreach)
 *
 */

*snip*

    /* apply special on-hit effects */
    if (sEffects != "") {
        int nPos, nDurType, nSubType, bPetrify, bSelf, bLast = FALSE;
        float fDur;
        string sDur;
        effect eLink;
        struct IntList il;
        struct SubString css;

        ss.rest = sEffects;

        /* parse each effect in turn */
        while (ss.rest != "") {
            ss  = GetFirstSubString(ss.rest);
            css = GetFirstSubString(ss.first, "|");

            /* if the effect has any pre-effect checks (e.g. random chance, saving throw),
             * make them before applying the effect */
            if (css.rest != "") {
                ss.first = css.first;

                if (css.rest == "&") {
                    if (!bLast)
                        continue;
                } else if (css.rest == "^") {
                    if (!(bLast = !bLast))
                        continue;
                } else {
                    bLast = !(CheckDynamic(css.rest, oTarget, OBJECT_SELF) > 0);

                    /* CheckDynamic returns TRUE if they pass; we invert it above so
                     * bLast is 'did the last effect go through' */
                    if (!bLast)
                        continue;
                }
            }


            if ((nPos = FindSubString(ss.first, "#")) >= 0) {
                nSpellId = StringToInt(GetStringRight(ss.first, GetStringLength(ss.first) - (nPos + 1)));
                ss.first = GetStringLeft(ss.first, nPos);

                if (GetHasSpellEffect(nSpellId, oTarget))
                    continue;
            } else
                nSpellId = -1;


            /* check if the effect has an associated visual */
            if ((nPos = FindSubString(ss.first, "/")) >= 0) {
                nVis     = StringToInt(GetStringRight(ss.first, GetStringLength(ss.first) - (nPos + 1)));
                ss.first = GetStringLeft(ss.first, nPos);
            } else
                nVis = 0;


            nSubType = 0;
            bPetrify = FALSE;
            bSelf    = FALSE;

            /* check if the effect has a duration parameter specified; if so, apply it;
             * otherwise, determine the duration of the effect automatically */
            if ((nPos = FindSubString(ss.first, ":")) >= 0) {
                sDur     = GetStringRight(ss.first, GetStringLength(ss.first) - (nPos + 1));
                ss.first = GetStringLeft(ss.first, nPos);

                /* check if a subtype was specified */
                if ((nPos = FindSubString(sDur, ":")) >= 0) {
                    string sSub = GetStringRight(sDur, 1);

                    if (sSub == "E")
                        nSubType = SUBTYPE_EXTRAORDINARY;
                    else if (sSub == "S")
                        nSubType = SUBTYPE_SUPERNATURAL;

                    sDur = GetStringLeft(sDur, nPos);
                }

                if ((nPos = FindSubString(sDur, "+")) >= 0) {
                    int nRandDur = StringToInt(GetStringRight(sDur, GetStringLength(sDur) - (nPos + 1)));

                    fDur = StringToFloat(GetStringLeft(sDur, nPos)) + Random(nRandDur);
                } else
                    fDur = StringToFloat(sDur);

                if (fDur < 0.0) {
                    fDur = 0.0;
                    nDurType = DURATION_TYPE_PERMANENT;
                } else if (fDur == 0.0)
                    nDurType = DURATION_TYPE_INSTANT;
                else
                    nDurType = DURATION_TYPE_TEMPORARY;


                int bFirst = TRUE;
                struct SubString sss;
                sss.rest = ss.first;

                while (sss.rest != "") {
                    sss = GetFirstSubString(sss.rest, ";");
                    il = GetIntList(sss.first, ",");

                    if (bFirst) {
                        bFirst = FALSE;
                        eLink  = EffectDynamic(il.i0, il.i1, il.i2, il.i3, il.i4, il.i5, il.i6);
                    } else
                        eLink = EffectLinkEffects(eLink, EffectDynamic(il.i0, il.i1, il.i2, il.i3, il.i4, il.i5, il.i6));
                }
            } else {
                il = GetIntList(ss.first, ",");

                if (il.i0 < 100) {
                    fDur     = 6.0;
                    nDurType = DURATION_TYPE_TEMPORARY;
                } else {
                    fDur     = 0.0;
                    nDurType = DURATION_TYPE_INSTANT;
                }

                if (il.i0 == EFFECT_TYPE_HEAL)
                    bSelf = TRUE;
                else if (il.i0 == EFFECT_TYPE_PETRIFY)
                    bPetrify = TRUE;

                eLink = EffectDynamic(il.i0, il.i1, il.i2, il.i3, il.i4, il.i5, il.i6);
            }

            if (bSelf) {
                if (GetCurrentHitPoints(oCaster) < GetMaxHitPoints(oCaster)) {
                    if (nVis > 0)
                        ApplyVisualToObject(nVis, oCaster);

                    ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oCaster);
                }
            } else {
                if (nVis > 0)
                    ApplyVisualToObject(nVis, oTarget);
                else if (nVis < 0)
                    eLink = EffectLinkEffects(eLink, EffectVisualEffect(-nVis));

                if (nSubType == SUBTYPE_EXTRAORDINARY)
                    eLink = ExtraordinaryEffect(eLink);
                else if (nSubType == SUBTYPE_SUPERNATURAL)
                    eLink = SupernaturalEffect(eLink);

                if (nSpellId >= 0)
                    SetEffectSpellId(eLink, nSpellId);

                if (bPetrify)
                    ApplyPetrifyEffect(nDurType, eLink, oTarget, fDur);
                else
                    ApplyEffectToObject(nDurType, eLink, oTarget, fDur);
            }
        }
    }


Normally you want to work directly towards the pseudostring and not against an struct which you can't build loop with.

Again, I'm not sure you understand how GetFirstSubString works. It uses a struct with two strings to loop through a given string evaluating substrings. Check the comments above it.


Funky
               
               

               


                     Modifié par FunkySwerve, 02 juillet 2011 - 02:16 .
                     
                  


            

Legacy_CID-78

  • Sr. Member
  • ****
  • Posts: 261
  • Karma: +0/-0
Arrays
« Reply #10 on: July 02, 2011, 04:06:23 pm »


               let just say we have diffrent opinions on what's the best approach. I allways go for speed. And I do know what i am talking about, perhaps i don't get the whole message across to you. I am a computer engineer and I know how  a computer and compilers works. The above seem to have been written by a high level programmer. Which have been things more like a class and waste resources instead of writting a clean interface. I don't say that he don't know what he do/did,

I just say that you can do it better if you skip structs, because you rarely need structs in nwscript.
they are certainly not good for lists. which is the most common use for arrays. and list are often used in loops where you only need to see one entry or two at a time. not the whole array at the same time

and when i talk about as close to memory i obviously mean as close that you can get in nwscript ie. the string itself. the more you nest and build layer the slower will each operation become.
               
               

               
            

Legacy_Khuzadrepa

  • Sr. Member
  • ****
  • Posts: 347
  • Karma: +0/-0
Arrays
« Reply #11 on: July 02, 2011, 04:20:43 pm »


               Can you give an example of how you would do it, CID-78? I'm trying to follow your logic, but it would be easier with something to compare against the code Funky provided.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Arrays
« Reply #12 on: July 02, 2011, 06:16:25 pm »


               

Khuzadrepa wrote...

Can you give an example of how you would do it, CID-78? I'm trying to follow your logic, but it would be easier with something to compare against the code Funky provided.


I'll second that. I'm especially curious to see how you write a function with GetFirstSubString's functionality without using a struct.

Funky
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Arrays
« Reply #13 on: July 02, 2011, 07:03:01 pm »


               

Khuzadrepa wrote...

Can you give an example of how you would do it, CID-78? I'm trying to follow your logic, but it would be easier with something to compare against the code Funky provided.


I will try and answer this.  I hop CID does not ming me butting in. 

Most of the work for paeceing a string has alrady been done for you in the x3_inc_string include.

here is a simple example for adding a get first/next functionality to it.   allong with a simple script to show/test the use.  Of cource it would be better to just make the top two functions along with the one declaired global string as an include file.

#include "x3_inc_string"

string sParse; // This string if for use by GetFirst/Next only
                          // It is a place holder for the itorator.
                          // it is global to both functions.

// sArray is a string with space delimited tokens as array elements.
string GetFirstToken(string sArray)
{
   string sToken = StringParse(sArray);
   sParse = StringRemoveParsed(sArray,sToken);
   return sToken;
}


// the token string used by this function is the one  set in the GetFirstToken function. 
//therefore it has no arguments.
string GetNextToken()
{
   return GetFirstToken(sParse);
}
 
 

void main()
{
  string Array = "Red Blue Green";
   float fDelay=1.0;
 
string sSpeak =   GetFirstToken(Array );
  while (sSpeak != "")
  {
     DelayCommand(fDelay,SpeakString(sSpeak));
     fDelay += 1.0;
     sSpeak = GetNextToken();
  }
}



Edited to correct spacing.
               
               

               


                     Modifié par Lightfoot8, 02 juillet 2011 - 06:17 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Arrays
« Reply #14 on: July 02, 2011, 07:43:02 pm »


               

Lightfoot8 wrote...

I will try and answer this.  I hop CID does not ming me butting in. 

Most of the work for paeceing a string has alrady been done for you in the x3_inc_string include.

Those functions are essentially the same as the ones I posted...though not as cleanly written (look at the include above, though I think I might've left out our StringReplace function). I'm curious to see what CID is advocating.

Funky
               
               

               


                     Modifié par FunkySwerve, 02 juillet 2011 - 06:44 .