Initial commit
This commit is contained in:
581
engines/glk/adrift/scnpcs.cpp
Normal file
581
engines/glk/adrift/scnpcs.cpp
Normal file
@@ -0,0 +1,581 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "glk/adrift/scare.h"
|
||||
#include "glk/adrift/scprotos.h"
|
||||
#include "glk/adrift/scgamest.h"
|
||||
|
||||
namespace Glk {
|
||||
namespace Adrift {
|
||||
|
||||
/* Trace flag, set before running. */
|
||||
static sc_bool npc_trace = FALSE;
|
||||
|
||||
|
||||
/*
|
||||
* npc_in_room()
|
||||
*
|
||||
* Return TRUE if a given NPC is currently in a given room.
|
||||
*/
|
||||
sc_bool npc_in_room(sc_gameref_t game, sc_int npc, sc_int room) {
|
||||
if (npc_trace) {
|
||||
sc_trace("NPC: checking NPC %ld in room %ld (NPC is in %ld)\n",
|
||||
npc, room, gs_npc_location(game, npc));
|
||||
}
|
||||
|
||||
return gs_npc_location(game, npc) - 1 == room;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_count_in_room()
|
||||
*
|
||||
* Return the count of characters in the room, including the player.
|
||||
*/
|
||||
sc_int npc_count_in_room(sc_gameref_t game, sc_int room) {
|
||||
sc_int count, npc;
|
||||
|
||||
/* Start with the player. */
|
||||
count = gs_player_in_room(game, room) ? 1 : 0;
|
||||
|
||||
/* Total up other NPCs inhabiting the room. */
|
||||
for (npc = 0; npc < gs_npc_count(game); npc++) {
|
||||
if (gs_npc_location(game, npc) - 1 == room)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_start_npc_walk()
|
||||
*
|
||||
* Start the given walk for the given NPC.
|
||||
*/
|
||||
void npc_start_npc_walk(sc_gameref_t game, sc_int npc, sc_int walk) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[6];
|
||||
sc_int movetime;
|
||||
|
||||
/* Retrieve movetime 0 for the NPC walk. */
|
||||
vt_key[0].string = "NPCs";
|
||||
vt_key[1].integer = npc;
|
||||
vt_key[2].string = "Walks";
|
||||
vt_key[3].integer = walk;
|
||||
vt_key[4].string = "MoveTimes";
|
||||
vt_key[5].integer = 0;
|
||||
movetime = prop_get_integer(bundle, "I<-sisisi", vt_key) + 1;
|
||||
|
||||
/* Set up walkstep. */
|
||||
gs_set_npc_walkstep(game, npc, walk, movetime);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_turn_update()
|
||||
* npc_setup_initial()
|
||||
*
|
||||
* Set initial values for NPC states, and update on turns.
|
||||
*/
|
||||
void npc_turn_update(sc_gameref_t game) {
|
||||
sc_int index_;
|
||||
|
||||
/* Set current values for NPC seen states. */
|
||||
for (index_ = 0; index_ < gs_npc_count(game); index_++) {
|
||||
if (!gs_npc_seen(game, index_)
|
||||
&& npc_in_room(game, index_, gs_playerroom(game)))
|
||||
gs_set_npc_seen(game, index_, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void npc_setup_initial(sc_gameref_t game) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[5];
|
||||
sc_int index_;
|
||||
|
||||
/* Start any walks that do not depend on a StartTask */
|
||||
vt_key[0].string = "NPCs";
|
||||
for (index_ = 0; index_ < gs_npc_count(game); index_++) {
|
||||
sc_int walk;
|
||||
|
||||
/* Set up invariant parts of the properties key. */
|
||||
vt_key[1].integer = index_;
|
||||
vt_key[2].string = "Walks";
|
||||
|
||||
/* Process each walk, starting at the last and working backwards. */
|
||||
for (walk = gs_npc_walkstep_count(game, index_) - 1; walk >= 0; walk--) {
|
||||
sc_int starttask;
|
||||
|
||||
/* If StartTask is zero, start walk at game start. */
|
||||
vt_key[3].integer = walk;
|
||||
vt_key[4].string = "StartTask";
|
||||
starttask = prop_get_integer(bundle, "I<-sisis", vt_key);
|
||||
if (starttask == 0)
|
||||
npc_start_npc_walk(game, index_, walk);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update seen flags for initial states. */
|
||||
npc_turn_update(game);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_room_in_roomgroup()
|
||||
*
|
||||
* Return TRUE if a given room is in a given group.
|
||||
*/
|
||||
static sc_bool npc_room_in_roomgroup(sc_gameref_t game, sc_int room, sc_int group) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[4];
|
||||
sc_int member;
|
||||
|
||||
/* Check roomgroup membership. */
|
||||
vt_key[0].string = "RoomGroups";
|
||||
vt_key[1].integer = group;
|
||||
vt_key[2].string = "List";
|
||||
vt_key[3].integer = room;
|
||||
member = prop_get_integer(bundle, "I<-sisi", vt_key);
|
||||
return member != 0;
|
||||
}
|
||||
|
||||
|
||||
/* List of direction names, for printing entry/exit messages. */
|
||||
static const sc_char *const DIRNAMES_4[] = {
|
||||
"the north", "the east", "the south", "the west", "above", "below",
|
||||
"inside", "outside",
|
||||
nullptr
|
||||
};
|
||||
static const sc_char *const DIRNAMES_8[] = {
|
||||
"the north", "the east", "the south", "the west", "above", "below",
|
||||
"inside", "outside",
|
||||
"the north-east", "the south-east", "the south-west", "the north-west",
|
||||
nullptr
|
||||
};
|
||||
|
||||
/*
|
||||
* npc_random_adjacent_roomgroup_member()
|
||||
*
|
||||
* Return a random member of group adjacent to given room.
|
||||
*/
|
||||
static sc_int npc_random_adjacent_roomgroup_member(sc_gameref_t game, sc_int room, sc_int group) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[5];
|
||||
sc_bool eightpointcompass;
|
||||
sc_int roomlist[12], count, length, index_;
|
||||
|
||||
/* If given room is "hidden", return nothing. */
|
||||
if (room == -1)
|
||||
return -1;
|
||||
|
||||
/* How many exits to consider? */
|
||||
vt_key[0].string = "Globals";
|
||||
vt_key[1].string = "EightPointCompass";
|
||||
eightpointcompass = prop_get_boolean(bundle, "B<-ss", vt_key);
|
||||
if (eightpointcompass)
|
||||
length = sizeof(DIRNAMES_8) / sizeof(DIRNAMES_8[0]) - 1;
|
||||
else
|
||||
length = sizeof(DIRNAMES_4) / sizeof(DIRNAMES_4[0]) - 1;
|
||||
|
||||
/* Poll adjacent rooms. */
|
||||
vt_key[0].string = "Rooms";
|
||||
vt_key[1].integer = room;
|
||||
vt_key[2].string = "Exits";
|
||||
count = 0;
|
||||
for (index_ = 0; index_ < length; index_++) {
|
||||
sc_int adjacent;
|
||||
|
||||
vt_key[3].integer = index_;
|
||||
vt_key[4].string = "Dest";
|
||||
adjacent = prop_get_child_count(bundle, "I<-sisis", vt_key);
|
||||
|
||||
if (adjacent > 0 && npc_room_in_roomgroup(game, adjacent - 1, group)) {
|
||||
roomlist[count] = adjacent - 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a random adjacent room, or -1 if nothing is adjacent. */
|
||||
return (count > 0) ? roomlist[sc_randomint(0, count - 1)] : -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_announce()
|
||||
*
|
||||
* Helper for npc_tick_npc().
|
||||
*/
|
||||
static void npc_announce(sc_gameref_t game, sc_int npc, sc_int room, sc_bool is_exit, sc_int npc_room) {
|
||||
const sc_filterref_t filter = gs_get_filter(game);
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[5], vt_rvalue;
|
||||
const sc_char *text, *name, *const *dirnames;
|
||||
sc_int dir, dir_match;
|
||||
sc_bool eightpointcompass, showenterexit, found;
|
||||
|
||||
/* If no announcement required, return immediately. */
|
||||
vt_key[0].string = "NPCs";
|
||||
vt_key[1].integer = npc;
|
||||
vt_key[2].string = "ShowEnterExit";
|
||||
showenterexit = prop_get_boolean(bundle, "B<-sis", vt_key);
|
||||
if (!showenterexit)
|
||||
return;
|
||||
|
||||
/* Get exit or entry text, and NPC name. */
|
||||
vt_key[2].string = is_exit ? "ExitText" : "EnterText";
|
||||
text = prop_get_string(bundle, "S<-sis", vt_key);
|
||||
vt_key[2].string = "Name";
|
||||
name = prop_get_string(bundle, "S<-sis", vt_key);
|
||||
|
||||
/* Decide on four or eight point compass names list. */
|
||||
vt_key[0].string = "Globals";
|
||||
vt_key[1].string = "EightPointCompass";
|
||||
eightpointcompass = prop_get_boolean(bundle, "B<-ss", vt_key);
|
||||
dirnames = eightpointcompass ? DIRNAMES_8 : DIRNAMES_4;
|
||||
|
||||
/* Set invariant key for room exit search. */
|
||||
vt_key[0].string = "Rooms";
|
||||
vt_key[1].integer = room;
|
||||
vt_key[2].string = "Exits";
|
||||
|
||||
/* Find the room exit that matches the NPC room. */
|
||||
found = FALSE;
|
||||
dir_match = 0;
|
||||
for (dir = 0; dirnames[dir]; dir++) {
|
||||
vt_key[3].integer = dir;
|
||||
if (prop_get(bundle, "I<-sisi", &vt_rvalue, vt_key)) {
|
||||
sc_int dest;
|
||||
|
||||
/* Get room's direction destination, and compare. */
|
||||
vt_key[4].string = "Dest";
|
||||
dest = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
if (dest == npc_room) {
|
||||
dir_match = dir;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print NPC exit/entry details. */
|
||||
pf_buffer_character(filter, '\n');
|
||||
pf_new_sentence(filter);
|
||||
pf_buffer_string(filter, name);
|
||||
pf_buffer_character(filter, ' ');
|
||||
pf_buffer_string(filter, text);
|
||||
if (found) {
|
||||
pf_buffer_string(filter, is_exit ? " to " : " from ");
|
||||
pf_buffer_string(filter, dirnames[dir_match]);
|
||||
}
|
||||
pf_buffer_string(filter, ".\n");
|
||||
|
||||
/* Handle any associated resource. */
|
||||
vt_key[0].string = "NPCs";
|
||||
vt_key[1].integer = npc;
|
||||
vt_key[2].string = "Res";
|
||||
vt_key[3].integer = is_exit ? 3 : 2;
|
||||
res_handle_resource(game, "sisi", vt_key);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_tick_npc_walk()
|
||||
*
|
||||
* Helper for npc_tick_npc().
|
||||
*/
|
||||
static void npc_tick_npc_walk(sc_gameref_t game, sc_int npc, sc_int walk) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[6];
|
||||
sc_int roomgroups, movetimes, walkstep, start, dest, destnum;
|
||||
sc_int chartask, objecttask;
|
||||
|
||||
if (npc_trace) {
|
||||
sc_trace("NPC: ticking NPC %ld, walk %ld: step %ld\n",
|
||||
npc, walk, gs_npc_walkstep(game, npc, walk));
|
||||
}
|
||||
|
||||
/* Count roomgroups for later use. */
|
||||
vt_key[0].string = "RoomGroups";
|
||||
roomgroups = prop_get_child_count(bundle, "I<-s", vt_key);
|
||||
|
||||
/* Get move times array length. */
|
||||
vt_key[0].string = "NPCs";
|
||||
vt_key[1].integer = npc;
|
||||
vt_key[2].string = "Walks";
|
||||
vt_key[3].integer = walk;
|
||||
vt_key[4].string = "MoveTimes";
|
||||
movetimes = prop_get_child_count(bundle, "I<-sisis", vt_key);
|
||||
|
||||
/* Find a step to match the movetime. */
|
||||
for (walkstep = 0; walkstep < movetimes - 1; walkstep++) {
|
||||
sc_int movetime;
|
||||
|
||||
vt_key[5].integer = walkstep + 1;
|
||||
movetime = prop_get_integer(bundle, "I<-sisisi", vt_key);
|
||||
if (gs_npc_walkstep(game, npc, walk) > movetime)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Sort out a destination. */
|
||||
dest = start = gs_npc_location(game, npc) - 1;
|
||||
|
||||
vt_key[4].string = "Rooms";
|
||||
vt_key[5].integer = walkstep;
|
||||
destnum = prop_get_integer(bundle, "I<-sisisi", vt_key);
|
||||
|
||||
if (destnum == 0) /* Hidden. */
|
||||
dest = -1;
|
||||
else if (destnum == 1) /* Follow player. */
|
||||
dest = gs_playerroom(game);
|
||||
else if (destnum < gs_room_count(game) + 2)
|
||||
dest = destnum - 2; /* To room. */
|
||||
else if (destnum < gs_room_count(game) + 2 + roomgroups) {
|
||||
sc_int initial;
|
||||
|
||||
/* For roomgroup walks, move only if walksteps has just refreshed. */
|
||||
vt_key[4].string = "MoveTimes";
|
||||
vt_key[5].integer = 0;
|
||||
initial = prop_get_integer(bundle, "I<-sisisi", vt_key);
|
||||
if (gs_npc_walkstep(game, npc, walk) == initial) {
|
||||
sc_int group;
|
||||
|
||||
group = destnum - 2 - gs_room_count(game);
|
||||
dest = npc_random_adjacent_roomgroup_member(game, start, group);
|
||||
if (dest == -1)
|
||||
dest = lib_random_roomgroup_member(game, group);
|
||||
}
|
||||
}
|
||||
|
||||
/* See if the NPC actually moved. */
|
||||
if (start != dest) {
|
||||
if (npc_trace)
|
||||
sc_trace("NPC: walking NPC %ld moved to %ld\n", npc, dest);
|
||||
|
||||
/* Move NPC to destination. */
|
||||
gs_set_npc_location(game, npc, dest + 1);
|
||||
|
||||
/* Announce NPC movements, and handle meeting characters and objects. */
|
||||
if (gs_player_in_room(game, start))
|
||||
npc_announce(game, npc, start, TRUE, dest);
|
||||
else if (gs_player_in_room(game, dest))
|
||||
npc_announce(game, npc, dest, FALSE, start);
|
||||
}
|
||||
|
||||
/* Handle meeting characters and objects. */
|
||||
vt_key[4].string = "CharTask";
|
||||
chartask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
if (chartask >= 0) {
|
||||
sc_int meetchar;
|
||||
|
||||
/* Run meetchar task if appropriate. */
|
||||
vt_key[4].string = "MeetChar";
|
||||
meetchar = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
if ((meetchar == -1 && gs_player_in_room(game, dest))
|
||||
|| (meetchar >= 0 && dest == gs_npc_location(game, meetchar) - 1)) {
|
||||
if (task_can_run_task(game, chartask))
|
||||
task_run_task(game, chartask, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
vt_key[4].string = "ObjectTask";
|
||||
objecttask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
if (objecttask >= 0) {
|
||||
sc_int meetobject;
|
||||
|
||||
/* Run meetobject task if appropriate. */
|
||||
vt_key[4].string = "MeetObject";
|
||||
meetobject = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
if (meetobject >= 0 && obj_directly_in_room(game, meetobject, dest)) {
|
||||
if (task_can_run_task(game, objecttask))
|
||||
task_run_task(game, objecttask, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_tick_npc()
|
||||
*
|
||||
* Move an NPC one step along current walk.
|
||||
*/
|
||||
static void npc_tick_npc(sc_gameref_t game, sc_int npc) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
sc_vartype_t vt_key[6];
|
||||
sc_int walk;
|
||||
sc_bool has_moved = FALSE;
|
||||
|
||||
if (npc_trace)
|
||||
sc_trace("NPC: ticking NPC %ld\n", npc);
|
||||
|
||||
/* Set up invariant key parts. */
|
||||
vt_key[0].string = "NPCs";
|
||||
vt_key[1].integer = npc;
|
||||
vt_key[2].string = "Walks";
|
||||
|
||||
/* Find active walk, and if any found, make a step along it. */
|
||||
for (walk = gs_npc_walkstep_count(game, npc) - 1; walk >= 0; walk--) {
|
||||
sc_int starttask, stoppingtask;
|
||||
|
||||
/* Ignore finished walks. */
|
||||
if (gs_npc_walkstep(game, npc, walk) <= 0)
|
||||
continue;
|
||||
|
||||
/* Get start task. */
|
||||
vt_key[3].integer = walk;
|
||||
vt_key[4].string = "StartTask";
|
||||
starttask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
|
||||
/*
|
||||
* Check that the starter is still complete, and if not, stop walk.
|
||||
* Then keep on looking for an active walk.
|
||||
*/
|
||||
if (starttask >= 0 && !gs_task_done(game, starttask)) {
|
||||
if (npc_trace)
|
||||
sc_trace("NPC: stopping NPC %ld walk, start task undone\n", npc);
|
||||
|
||||
gs_set_npc_walkstep(game, npc, walk, -1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get stopping task. */
|
||||
vt_key[4].string = "StoppingTask";
|
||||
stoppingtask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
|
||||
/*
|
||||
* If any stopping task has completed, ignore this walk but don't
|
||||
* actually finish it; more like an event pauser, then.
|
||||
*
|
||||
* TODO Is this right?
|
||||
*/
|
||||
if (stoppingtask >= 0 && gs_task_done(game, stoppingtask)) {
|
||||
if (npc_trace)
|
||||
sc_trace("NPC: ignoring NPC %ld walk, stop task done\n", npc);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Decrement steps. */
|
||||
gs_decrement_npc_walkstep(game, npc, walk);
|
||||
|
||||
/* If we just hit a walk end, loop if called for. */
|
||||
if (gs_npc_walkstep(game, npc, walk) == 0) {
|
||||
sc_bool is_loop;
|
||||
|
||||
/* If walk is a loop, restart it. */
|
||||
vt_key[4].string = "Loop";
|
||||
is_loop = prop_get_boolean(bundle, "B<-sisis", vt_key);
|
||||
if (is_loop) {
|
||||
vt_key[4].string = "MoveTimes";
|
||||
vt_key[5].integer = 0;
|
||||
gs_set_npc_walkstep(game, npc, walk,
|
||||
prop_get_integer(bundle,
|
||||
"I<-sisisi", vt_key));
|
||||
} else
|
||||
gs_set_npc_walkstep(game, npc, walk, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If not yet made a move on this walk, make one, and once made, make
|
||||
* no other
|
||||
*/
|
||||
if (!has_moved) {
|
||||
npc_tick_npc_walk(game, npc, walk);
|
||||
has_moved = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_tick_npcs()
|
||||
*
|
||||
* Move each NPC one step along current walk.
|
||||
*/
|
||||
void npc_tick_npcs(sc_gameref_t game) {
|
||||
const sc_prop_setref_t bundle = gs_get_bundle(game);
|
||||
const sc_gameref_t undo = game->undo;
|
||||
sc_int npc;
|
||||
|
||||
/*
|
||||
* Compare the player location to last turn, to see if the player has moved
|
||||
* this turn. If moved, look for meetings with NPCs.
|
||||
*
|
||||
* TODO Is this the right place to do this. After ticking each NPC, rather
|
||||
* than before, seems more appropriate. But the messages come out in the
|
||||
* right order by putting it here.
|
||||
*
|
||||
* Also, note that we take the shortcut of using the undo gamestate here,
|
||||
* rather than properly recording the prior location of the player, and
|
||||
* perhaps also NPCs, in the live gamestate.
|
||||
*/
|
||||
if (undo && !gs_player_in_room(undo, gs_playerroom(game))) {
|
||||
for (npc = 0; npc < gs_npc_count(game); npc++) {
|
||||
sc_int walk;
|
||||
|
||||
/* Iterate each NPC's walks. */
|
||||
for (walk = gs_npc_walkstep_count(game, npc) - 1; walk >= 0; walk--) {
|
||||
sc_vartype_t vt_key[5];
|
||||
sc_int chartask;
|
||||
|
||||
/* Ignore finished walks. */
|
||||
if (gs_npc_walkstep(game, npc, walk) <= 0)
|
||||
continue;
|
||||
|
||||
/* Retrieve any character meeting task for the NPC. */
|
||||
vt_key[0].string = "NPCs";
|
||||
vt_key[1].integer = npc;
|
||||
vt_key[2].string = "Walks";
|
||||
vt_key[3].integer = walk;
|
||||
vt_key[4].string = "CharTask";
|
||||
chartask = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
if (chartask >= 0) {
|
||||
sc_int meetchar;
|
||||
|
||||
/* Run meetchar task if appropriate. */
|
||||
vt_key[4].string = "MeetChar";
|
||||
meetchar = prop_get_integer(bundle, "I<-sisis", vt_key) - 1;
|
||||
if (meetchar == -1 &&
|
||||
gs_player_in_room(game, gs_npc_location(game, npc) - 1)) {
|
||||
if (task_can_run_task(game, chartask))
|
||||
task_run_task(game, chartask, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate and tick each individual NPC. */
|
||||
for (npc = 0; npc < gs_npc_count(game); npc++)
|
||||
npc_tick_npc(game, npc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* npc_debug_trace()
|
||||
*
|
||||
* Set NPC tracing on/off.
|
||||
*/
|
||||
void npc_debug_trace(sc_bool flag) {
|
||||
npc_trace = flag;
|
||||
}
|
||||
|
||||
} // End of namespace Adrift
|
||||
} // End of namespace Glk
|
||||
Reference in New Issue
Block a user