// Evol functions.
// Authors:
// Travolta
// Description:
// Moving npc utility functions (graph-based)
// Variables:
// none
function script initmovegraph {
deletearray getvariableofnpc(.movegraphcmd$, strnpcinfo(3));
deletearray getvariableofnpc(.movegraphlabels$, strnpcinfo(3));
deletearray getvariableofnpc(.movegraphweight, strnpcinfo(3));
deletearray getvariableofnpc(.moveposy, strnpcinfo(3));
deletearray getvariableofnpc(.moveposx, strnpcinfo(3));
.@cnt = 0;
for (.@f = 0; .@f < getargcount(); .@f = .@f + 3)
{
set getvariableofnpc(.movegraphlabels$[.@cnt], strnpcinfo(3)), getarg(.@f);
set getvariableofnpc(.moveposx[.@cnt], strnpcinfo(3)), getarg(.@f + 1);
set getvariableofnpc(.moveposy[.@cnt], strnpcinfo(3)), getarg(.@f + 2);
.@cnt ++;
}
return;
}
function script findmovegraphlabel {
if (!getargcount())
return -1;
.@arg$ = getarg(0);
for (.@i = 0; .@i < getarraysize(getvariableofnpc(.movegraphlabels$, strnpcinfo(3))); .@i++)
{
if (getvariableofnpc(.movegraphlabels$[.@i], strnpcinfo(3)) == .@arg$)
return .@i;
}
return -1;
}
/* setmovegraphcmd(fromPositionLabel,toPositionLabel,moveChanceWeight,postCommand, ...);
* This function manipulates NPC moving graph. Before calling it, make sure
* `initmovegraph' was called. The function accepts multiplier of 4 parameters:
* fromPositionLabel, toPositionLabel -- starting and ending position of NPC move
* moveChanceWeight -- positive integer, represents the cnance of moving in given direction
* postCommand -- either "moveon" (start moving to next location straight after arriving from
* fromPositionLabel to toPositionLabel) or a semicolon-separated set of commands
* ("wait 3", "emote 5" etc, see `execmovecmd') that will be executed after arrival.
* The commands don't have to end with ";moveon", it's executed in the end by default.
*/
function script setmovegraphcmd {
.@size = getarraysize(getvariableofnpc(.moveposx, strnpcinfo(3)));
for (.@f = 0; .@f < getargcount(); .@f = .@f + 4)
{
.@from = findmovegraphlabel(getarg(.@f));
.@to = findmovegraphlabel(getarg(.@f + 1));
.@weight = getarg(.@f + 2);
.@cmd$ = getarg(.@f + 3);
.@index = .@from * .@size + .@to; // emulation of 2d array
set getvariableofnpc(.movegraphcmd$[.@index], strnpcinfo(3)), .@cmd$;
set getvariableofnpc(.movegraphweight[.@index], strnpcinfo(3)), .@weight;
}
return;
}
function script execmovecmd {
explode(.@cmd$, getarg(0), " ");
if (.@cmd$[0] == "moveon")
{
return 0;
}
else if (.@cmd$[0] == "dir")
{
setnpcdir atoi(.@cmd$[1]);
}
else if (.@cmd$[0] == "wait")
{
set getvariableofnpc(.waitticks, strnpcinfo(3)), atoi(.@cmd$[1]);
}
else if (.@cmd$[0] == "emote")
{
unitemote getnpcid(0), atoi(.@cmd$[1]);
}
else if (.@cmd$[0] == "class")
{
setnpcdisplay strnpcinfo(3), atoi(.@cmd$[1]);
}
else if (.@cmd$[0] == "warp")
{
.@pos = findmovegraphlabel(.@cmd$[1]);
if (.@pos > 0)
{
movenpc strnpcinfo(3), getvariableofnpc(.moveposx[.@pos], strnpcinfo(3)), getvariableofnpc(.moveposy[.@pos], strnpcinfo(3));
set getvariableofnpc(.movepos, strnpcinfo(3)), .@pos;
}
else
{
debugmes "execmovecmd: unknown WARP destination label: " + .@cmd$[1];
}
}
else if (.@cmd$[0] == "call")
{
switch (getarraysize(.@cmd$))
{
case 1:
debugmes "execmovecmd: CALL command needs some parameters";
return -1;
case 2:
callfunc .@cmd$[1];
break;
case 3:
callfunc .@cmd$[1], .@cmd$[2];
break;
case 4:
default:
callfunc .@cmd$[1], .@cmd$[2], .@cmd$[3];
break;
}
}
else if (.@cmd$[0] == "speed")
{
npcspeed atoi(.@cmd$[1]);
}
else if (.@cmd$[0] == "say")
{
deletearray .@cmd$[0], 1;
npctalk implode(.@cmd$, " ");
}
else
{
debugmes "Unknown move graph cmd: " + .@cmd$[0];
}
return 1;
}
function script getnextmovecmd {
.@cmds$ = getvariableofnpc(.nextcmd$, strnpcinfo(3));
.@firstCmd$ = .@cmds$;
.@restCmd$ = "moveon";
.@index = strpos(.@cmds$, ";");
if (.@index >= 0)
{
.@firstCmd$ = substr(.@cmds$, 0, .@index - 1);
.@restCmd$ = substr(.@cmds$, .@index + 1, getstrlen(.@cmds$) - 1);
}
// debugmes "firstCmd = " + .@firstCmd$ + " restCmd = " + .@restCmd$;
set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@restCmd$;
return strip(.@firstCmd$);
}
function script movetonextpoint {
.@wait = getvariableofnpc(.waitticks, strnpcinfo(3));
if (.@wait > 0)
{
.@wait --;
set getvariableofnpc(.waitticks, strnpcinfo(3)), .@wait;
return;
}
.@nextcmd$ = getnextmovecmd;
if (.@nextcmd$ != "moveon")
{
execmovecmd(.@nextcmd$);
return;
}
// choose a random path from all possible paths
.@size = getarraysize(getvariableofnpc(.moveposx, strnpcinfo(3)));
.@cur = 0;
.@pos = getvariableofnpc(.movepos, strnpcinfo(3));
.@weight_sum = 0;
for (.@i = 0; .@i < .@size; .@i++)
{
.@cmd$ = getvariableofnpc(.movegraphcmd$[.@pos * .@size + .@i], strnpcinfo(3));
if (.@cmd$ != "")
{
setarray .@nextpos[.@cur], .@i;
setarray .@weights[.@cur], getvariableofnpc(.movegraphweight[.@pos * .@size + .@i], strnpcinfo(3));
.@weight_sum += .@weights[.@cur];
.@cur++;
}
}
// pick a random number based on weight_sum
.@rnd = rand(.@weight_sum);
.@k = -1; .@weight_sum = 0;
while (.@rnd >= .@weight_sum)
{
.@k++;
.@weight_sum += .@weights[.@k];
}
.@next_idx = .@nextpos[.@k];
.@next_x = getvariableofnpc(.moveposx[.@next_idx], strnpcinfo(3));
.@next_y = getvariableofnpc(.moveposy[.@next_idx], strnpcinfo(3));
.@nextcmd$ = getvariableofnpc(.movegraphcmd$[.@pos * .@size + .@next_idx], strnpcinfo(3));
set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@nextcmd$;
set getvariableofnpc(.movepos, strnpcinfo(3)), .@next_idx;
// debugmes strnpcinfo(1) + " moving to " + getvariableofnpc(.movegraphlabels$[.@next_idx], strnpcinfo(3));
npcwalkto .@next_x, .@next_y;
return;
}
function script firstmove {
.@nextcmd$ = "moveon";
if (getargcount() > 0)
.@nextcmd$ = getarg(0);
set getvariableofnpc(.movepos, strnpcinfo(3)), 0;
set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@nextcmd$;
set getvariableofnpc(.waitticks, strnpcinfo(3)), -1;
movetonextpoint;
return;
}