// Preset / routine system
// Author:
// gumi
// Description:
// allows to execute multiple commands in a single step
// to ease testing and debugging
//
// usage: @pre [options] <instruction>[, <instruction>...]
// usage: DoRoutine "[options] <instruction>[, <instruction>...]";
//
// example: @pre -s a22 v14
// resets all stats, gives 22 agi, gives 14 vit
//
// ^ actual documentation may come one day, when I feel like it
// *hides*
function script DoRoutine {
function parsev {
// parsev(base, patterns{, min{, max}}) => value
.@value = getarg(0, 0);
.@raw$ = getarg(1, "");
.@patterns = explode(.@patterns$, .@raw$, "|");
for (.@pattern = 0; .@pattern < .@patterns; ++.@pattern)
{
.@pattern$ = .@patterns$[.@pattern];
.@len = getstrlen(.@pattern$);
if (charat(.@pattern$, 0) == "=" && .@len >= 2)
{
.@value = atoi(delchar(.@pattern$, 0));
break;
}
else if (charat(.@pattern$, 0) == "+" && .@len >= 2)
{
if (charat(.@pattern$, 1) == "+" && getargcount() >= 4)
.@value = getarg(3);
else
.@value += atoi(delchar(.@pattern$, 0));
}
else if (charat(.@pattern$, 0) == "-" && .@len >= 2)
{
if (charat(.@pattern$, 1) == "-" && getargcount() >= 3)
.@value = getarg(2);
else
.@value -= atoi(delchar(.@pattern$, 0));
}
else if (charat(.@pattern$, 0) == ">" && .@len >= 2)
{
if (charat(.@pattern$, 1) == "=" && .@len >= 3)
.@value = max(atoi(substr(.@pattern$, 2, .@len - 1)), .@value);
else
.@value = max(atoi(delchar(.@pattern$, 0)) + 1, .@value);
}
else if (charat(.@pattern$, 0) == "<" && .@len >= 2)
{
if (charat(.@pattern$, 1) == "=" && .@len >= 3)
.@value = min(atoi(substr(.@pattern$, 2, .@len - 1)), .@value);
else
.@value = min(atoi(delchar(.@pattern$, 0)) - 1, .@value);
}
else if (.@len >= 1)
{
.@value = atoi(.@pattern$);
break;
}
}
if (getargcount() >= 3)
.@value = max(getarg(2), .@value);
if (getargcount() >= 4)
.@value = min(getarg(3), .@value);
return .@value;
}
.@routine$ = strip(getarg(0,""));
.@m = explode(.@routine$[0], .@routine$, " "); // prep the base array
if (charat(.@routine$[0], 0) == "-")
{
if (compare(.@routine$[0], "t"))
{
clearitem;
}
if (compare(.@routine$[0], "e"))
{
nude;
}
if (compare(.@routine$[0], "k"))
{
resetskill;
}
if (compare(.@routine$[0], "s"))
{
resetstatus;
}
if (compare(.@routine$[0], "x"))
{
resetlvl 2;
}
if (compare(.@routine$[0], "q"))
{
//doevent "::OnGlobalQuestReset"; // executes in all quest npcs // FIXME: maybe have a `resetquest` buildin?
// FIXME: ^ need a buildin that can run *right now* instead of on script end
}
if (compare(.@routine$[0], "n"))
{
closeclientdialog;
}
.@i = 1;
}
for (; .@i < .@m; ++.@i)
{
.@type = ord(charat(strip(.@routine$[.@i]), 0));
if (.@type > 0)
{
.@raw$ = delchar(.@routine$[.@i], 0);
.@args = explode(.@args$, .@raw$, ",");
.@a = atoi(.@args$[0]);
.@b = atoi(.@args$[1]);
.@c = atoi(.@args$[2]);
.@d = atoi(.@args$[3]);
.@e = atoi(.@args$[4]);
switch (.@type)
{
case 97: /* a => Agi */
.@base = readparam(bAgi);
statusup2 bAgi, parsev(.@base, .@args$[0], 1, 99) - .@base;
break;
/* (b) */
case 99: /* c => job */
jobchange max(0, min(6, .@a));
break;
case 100: /* d => Dex */
.@base = readparam(bDex);
statusup2 bDex, parsev(.@base, .@args$[0], 1, 99) - .@base;
break;
case 101: /* e => equip */
equip max(1, min(32767, .@a));
break;
/* (f) */
/* (g) => gender (reserved) */
/* (h) */
case 105: /* i => Int */
.@base = readparam(bInt);
statusup2 bInt, parsev(.@base, .@args$[0], 1, 99) - .@base;
break;
/* (j) */
case 107: /* k => skill */
.@k = max(1, min(32767, .@a));
skill .@k, parsev(getskilllv(.@k), .@args$[1], 0, 10), 0;
break;
case 108: /* l => luk */
.@base = readparam(bLuk);
statusup2 bLuk, parsev(.@base, .@args$[0], 1, 99) - .@base;
break;
/* (m) => mercenary (reserved) */
/* (n) => talk to npc (reserved) */
/* (o) */
case 112: /* p => pet */
makepet max(1002, min(32767, .@a));
break;
case 113: /* q => quest */
.@q = max(0, min(32767, .@a));
setq .@q, parsev(getq(.@q), .@args$[1]),
parsev(getq2(.@q), .@args$[2]),
parsev(getq3(.@q), .@args$[3]),
parsev(getqtime(.@q), .@args$[4]);
break;
/* (r) */
case 115: /* s => Str */
.@base = readparam(bStr);
statusup2 bStr, parsev(.@base, .@args$[0], 1, 99) - .@base;
break;
case 116: /* t => item */
.@t = max(1, min(32767, .@a));
.@c = countitem(.@t);
.@v = parsev(.@c, .@args$[1], 0, 32767);
if (.@c > .@v)
delitem .@t, .@c - .@v;
else if (.@c < .@v)
getitem .@t, .@v - .@c;
break;
/* (u) */
case 118: /* v => vit */
.@base = readparam(bVit);
statusup2 bVit, parsev(.@base, .@args$[0], 1, 99) - .@base;
break;
case 119: /* w => warp */
warp .@args$[0], .@b, .@c;
break;
case 120: /* x => base level */
BaseLevel = parsev(BaseLevel, .@args$[0], 1, 99);
BaseExp = parsev(BaseExp, .@args$[1], 0);
break;
case 121: /* y => job level */
JobLevel = parsev(JobLevel, .@args$[0], 1, 255);
JobExp = parsev(JobExp, .@args$[1], 0);
break;
case 122: /* z => zeny */
Zeny = parsev(Zeny, .@args$[0], 0, 0x7FFFFFFE);
BankVault = parsev(BankVault, .@args$[1], 0, MAX_BANK_ZENY);
break;
}
}
}
return;
}
- script @pre 32767,{
end;
OnCall:
if (!debug && !is_admin())
{
end;
}
if (.@atcmd_parameters$[0] != "")
{
.@atcmd_parameters$[0] = implode(.@atcmd_parameters$[0], " ");
}
DoRoutine strip(.@atcmd_parameters$[0]);
end;
OnInit:
bindatcmd "pre", "@pre::OnCall", 0, 99, 0;
}