Just concerned about some recursive calls I'm trying to make.
Thanks!
This is incorrect, if I remember right. Delaycommands have a separate stack, or so I seem to recall. I'd have to ask my co-admin to be absolutely sure (he's the one who does all the sexy NWNeXalt hacks, and has spent prodigious amounts of time digging around in the engine), but I will say that he's advised me, and it's our policy, to avoid using 2 delaycommands where one will do, not out of fear of them failing, but in an attempt to keep overhead down.kalbaern wrote...
Any "buffing" spells with a duration are delayed commands.
void DoAoEHeartbeat (struct SpellInfo si, object oAoE, effect eEff, effect eDur, effect eVis) {
int bDestroy = FALSE, bAllPCs = FALSE;
if (!GetIsObjectValid(oAoE))
return;
/* Storm of Vengeance doesn't destroy properly sometimes */
if (GetPersistentAoEEffect(si) == AOE_PER_STORM) {
if (si.id == SPELL_STORM_OF_VENGEANCE && GetLocalInt(GetArea(oAoE), "Area_Underwater"))
bAllPCs = TRUE;
if (GetLocalInt(GetModule(), "uptime") > GetLocalInt(oAoE, "AoEExpires"))
bDestroy = TRUE;
}
if (bDestroy ||
!GetIsObjectValid(si.caster) ||
GetIsDead(si.caster) ||
GetArea(si.caster) != si.area) {
SetPlotFlag(oAoE, FALSE);
DestroyObject(oAoE);
return;
}
DelayCommand(6.0, DoAoEHeartbeat(si, oAoE, eEff, eDur, eVis));
AddLocalInt(oAoE, "AoERounds", 1);
si.target = oAoE;
int nMask = GetPersistentAoETargetMask(si);
int nType = GetPersistentAoETargetType(si);
for (si.target = GetFirstInPersistentObject(oAoE, nMask);
GetIsObjectValid(si.target);
si.target = GetNextInPersistentObject(oAoE, nMask)) {
if (GetIsSpellTarget(si, si.target, nType) || (bAllPCs && GetIsPC(si.target))) {
SignalEvent(si.target, EventSpellCastAt(si.caster, si.id));
AssignCommand(si.caster, DelayCommand(GetRandomDelay(0.5, 4.5), ApplyAoEEffect(si, oAoE, si.target, eEff, eDur, eVis)));
}
}
}
Modifié par Dark Defiance, 17 octobre 2010 - 02:16 .
Modifié par the.gray.fox, 18 octobre 2010 - 05:02 .
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;
};
/* Replace the first (or all) occurrence of sFind in sStr with sRepl. */
string ReplaceString(string sStr, string sFind, string sRepl, int bAll=FALSE, int nLen=-1);
/* Return the specified digit nDigit of nInt. nDigit is the number of
* powers of 10 to use (hence, 0 = 1s, 1 = 10s, 2 = 100s, etc). */
int GetIntegerDigit(int nInt, int nDigit);
/* Set the specified digit nDigit of nInt. */
int SetIntegerDigit(int nInt, int nDigit, int nValue);
/* Return an IntList struct containing all the digits of nInt. */
struct IntList GetDigitList(int nInt);
/* Get a random floating-point number in the range [-1.0, 1.0]. If fRange
* is specified, a random number in the range [0.0, fRange] will be returned. */
float RandomFloat(float fRange=0.0);
/* 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);
/* Return vPos in string form X, Y, Z. */
string GetPositionStringFromVector(vector vPos);
/* Return the position of lLoc in string form [X, Y, Z | F] */
string GetPositionStringFromLocation(location lLoc);
/* Return the position of oObject in string form [X, Y, Z | F] */
string GetPositionString(object oObject);
string ReplaceString(string sStr, string sFind, string sRepl, int bAll=FALSE, int nLen=-1) {
int nPos = FindSubString(sStr, sFind);
if (nPos
return sStr;
if (nLen
nLen = GetStringLength(sFind);
do {
sStr = GetStringLeft(sStr, nPos) + sRepl +
GetStringRight(sStr, GetStringLength(sStr) - (nPos + nLen));
if (!bAll)
break;
nPos = FindSubString(sStr, sFind);
} while (nPos >= 0);
return sStr;
}
int GetIntegerDigit(int nInt, int nDigit) {
switch (nDigit) {
case 0: nDigit = 1; break;
case 1: nDigit = 10; break;
case 2: nDigit = 100; break;
case 3: nDigit = 1000; break;
case 4: nDigit = 10000; break;
case 5: nDigit = 100000; break;
case 6: nDigit = 1000000; break;
case 7: nDigit = 10000000; break;
case 8: nDigit = 100000000; break;
case 9: nDigit = 1000000000; break;
default:
return 0;
}
return ((nInt / nDigit) % 10);
}
int SetIntegerDigit(int nInt, int nDigit, int nValue) {
if (nValue
nValue = 0;
else if (nValue > 9)
nValue = 9;
switch (nDigit) {
case 0: nDigit = 1; break;
case 1: nDigit = 10; break;
case 2: nDigit = 100; break;
case 3: nDigit = 1000; break;
case 4: nDigit = 10000; break;
case 5: nDigit = 100000; break;
case 6: nDigit = 1000000; break;
case 7: nDigit = 10000000; break;
case 8: nDigit = 100000000; break;
case 9: nDigit = 1000000000; break;
default:
return 0;
}
nInt -= ((nInt / nDigit) % 10) * nDigit;
nInt += nValue * nDigit;
return nInt;
}
struct IntList GetDigitList(int nInt) {
struct IntList ret;
ret.i0 = (nInt % 10);
ret.i1 = (nInt /= 10) % 10;
ret.i2 = (nInt /= 10) % 10;
ret.i3 = (nInt /= 10) % 10;
ret.i4 = (nInt /= 10) % 10;
ret.i5 = (nInt /= 10) % 10;
ret.i6 = (nInt /= 10) % 10;
ret.i7 = (nInt /= 10) % 10;
ret.i8 = (nInt /= 10) % 10;
ret.i9 = (nInt /= 10) % 10;
return ret;
}
float RandomFloat(float fRange=0.0) {
if (fRange > 0.0)
return (Random(FloatToInt(fRange * 1000)) / 1000.0);
return ((Random(10000001) - 5000000) / 5000000.0);
}
float RandomNormal(float fStdDev=1.0, float fMean=0.0) {
float u1, u2, v1, v2, s;
do {
u1 = RandomFloat();
u2 = RandomFloat();
v1 = (2.0 * u1) - 1.0;
v2 = (2.0 * u2) - 1.0;
s = (v1 * v1) + (v2 * v2);
} while (s > 1.0);
return (sqrt((-2.0 * log(s)) / s) * v1 * fStdDev) + fMean;
}
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
return "";
nStart = nSep + nSkip;
}
if ((nSep = FindSubString(sString, sSep, nStart))
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
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
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
sl.size = 0;
return sl;
}
while (nSep
nSep = FindSubString(sString, sSep, nStart);
if (nSep
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
il.size = 0;
return il;
}
while (nSep
nSep = FindSubString(sString, sSep, nStart);
if (nSep
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;
}
string GetPositionStringFromVector(vector vPos) {
return FloatToString(vPos.x, 1, 2) + ", " +
FloatToString(vPos.y, 1, 2) + ", " +
FloatToString(vPos.z, 1, 2);
}
string GetPositionStringFromLocation(location lLoc) {
vector vPos = GetPositionFromLocation(lLoc);
return "[" + GetPositionStringFromVector(GetPositionFromLocation(lLoc)) +
" | " + FloatToString(GetFacingFromLocation(lLoc), 1, 0) + "]";
}
string GetPositionString(object oObject) {
return GetPositionStringFromLocation(GetLocation(oObject));
}
location GetLocationFromString(object oArea, string sLoc) {
float fFacing;
vector vVec;
vVec = Vector(StringToFloat(GetStringSubString(sLoc, 0, ",")),
StringToFloat(GetStringSubString(sLoc, 1, ",")),
StringToFloat(GetStringSubString(sLoc, 2, ",")));
fFacing = StringToFloat(GetStringSubString(sLoc, 3, ","));
return Location(oArea, vVec, fFacing);
}
Nice. Speed is ALWAYS an issue. Given the size of strings that NWNX throws left and right, however (it uses large string groups as well, with a ~ delimiter), I wouldn't bother with the hex conversion in this case.If speed is not a concern (frankly... is it? We got uber CPUs today), we may even operate a conversion from integer to Hex, thus dropping from 10 to 8 digits per integer, culling 20 more bytes.
Modifié par FunkySwerve, 19 octobre 2010 - 08:13 .
This is an awesome tip, thanks!the.gray.fox wrote...
In that same stack also end up any and all parameters you pass to the delayed command.
The more the params, the greater and quicker the stack explosion.
Which leads to quicker and badder memory fragmentation, which is bad for performance.
As a general rule of thumb, for delayed commands it is best to limit the param count to max 2.