summaryrefslogblamecommitdiff
path: root/npc/functions/npcmovegraph.txt
blob: 0a0e29c7b5f120ef7a743bb72a2efbfa87cb18b9 (plain) (tree)














































































































































































































                                                                                                                                        
// 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
    {
        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;
    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;
}