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 .