From 29e2e67b950bae3b848dcd842e8cc49fe8c4e37f Mon Sep 17 00:00:00 2001 From: Joseph Botosh Date: Sat, 5 Sep 2015 16:50:49 +0300 Subject: add script functions for graph-based NPC movement --- npc/functions/npcmovegraph.txt | 207 +++++++++++++++++++++++++++++++++++++++++ npc/scripts.conf | 1 + 2 files changed, 208 insertions(+) create mode 100644 npc/functions/npcmovegraph.txt (limited to 'npc') diff --git a/npc/functions/npcmovegraph.txt b/npc/functions/npcmovegraph.txt new file mode 100644 index 00000000..0a0e29c7 --- /dev/null +++ b/npc/functions/npcmovegraph.txt @@ -0,0 +1,207 @@ +// 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; +} \ No newline at end of file diff --git a/npc/scripts.conf b/npc/scripts.conf index 927cd68a..5c8b9fbc 100644 --- a/npc/scripts.conf +++ b/npc/scripts.conf @@ -18,6 +18,7 @@ npc: npc/functions/goodbye.txt npc: npc/functions/sailordialogue.txt npc: npc/functions/savepoint.txt npc: npc/functions/shops.txt +npc: npc/functions/npcmovegraph.txt // Maps specific scripts import: npc/_import.txt -- cgit v1.2.3-70-g09d2