npcnear.cc

Go to the documentation of this file.
00001 /*
00002  *  npcnear.cc - At random times, run proximity usecode functions on nearby NPC's.
00003  *
00004  *  Copyright (C) 2000-2001  The Exult Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #  include <config.h>
00023 #endif
00024 
00025 #ifndef ALPHA_LINUX_CXX
00026 #  include <cstdlib>
00027 #endif
00028 #include "npcnear.h"
00029 #include "gamewin.h"
00030 #include "actors.h"
00031 #include "ucmachine.h"
00032 #include "schedule.h"
00033 #include "items.h"
00034 #include "game.h"
00035 #include "cheat.h"
00036 
00037 #include "SDL_timer.h"
00038 
00039 #ifndef UNDER_CE
00040 using std::rand;
00041 #endif
00042 
00043 bool Bg_dont_wake(Game_window *gwin, Actor *npc);
00044 
00045 /*
00046  *  Add an npc to the time queue.
00047  */
00048 
00049 void Npc_proximity_handler::add
00050   (
00051   unsigned long curtime,    // Current time (msecs).
00052   Npc_actor *npc,
00053   int additional_secs   // More secs. to wait.
00054   )
00055   {
00056   int msecs;      // Hostile?  Wait 0-2 secs.
00057   if (npc->get_alignment() >= Npc_actor::hostile)
00058     msecs = rand() % 2000;
00059   else        // Wait between 2 & 6 secs.
00060     msecs = (rand() % 4000) + 2000;
00061   unsigned long newtime = curtime + msecs;
00062   newtime += 1000*additional_secs;
00063   gwin->get_tqueue()->add(newtime, this, reinterpret_cast<long>(npc));
00064   }
00065 
00066 /*
00067  *  Remove entry for an npc.
00068  */
00069 
00070 void Npc_proximity_handler::remove
00071   (
00072   Npc_actor *npc
00073   )
00074   {
00075   npc->clear_nearby();
00076   gwin->get_tqueue()->remove(this, reinterpret_cast<long>(npc)); 
00077   }
00078 
00079 /*
00080  *  Is this a Black Gate (Skara Brae) ghost, or Penumbra?
00081  */
00082 
00083 bool Bg_dont_wake
00084   (
00085   Game_window *gwin,
00086   Actor *npc
00087   )
00088   {
00089   int num;
00090   return (Game::get_game_type() == BLACK_GATE &&
00091     (npc->get_info().has_translucency() ||
00092           // Horace or Penumbra?
00093      (num = npc->Actor::get_npc_num()) == 141 || num == 150));
00094   }
00095 
00096 /*
00097  *  Run proximity usecode function for the NPC now.
00098  */
00099 
00100 void Npc_proximity_handler::handle_event
00101   (
00102   unsigned long curtime,
00103   long udata
00104   )
00105   {
00106   Npc_actor *npc = (Npc_actor *) udata;
00107   int extra_delay = 5;    // For next time.
00108           // See if still on visible screen.
00109   Rectangle tiles = gwin->get_win_tile_rect().enlarge(10);
00110   Tile_coord t = npc->get_tile();
00111   if (!tiles.has_point(t.tx, t.ty) || // No longer visible?
00112       npc->is_dead())   // Or no longer living?
00113     {
00114     npc->clear_nearby();
00115     return;
00116     }
00117   Schedule::Schedule_types sched = (Schedule::Schedule_types)
00118             npc->get_schedule_type();
00119           // Sleep schedule?
00120   if (npc->get_schedule() &&
00121       sched == Schedule::sleep &&
00122           // But not under a sleep spell?
00123       !npc->get_flag(Obj_flags::asleep) &&
00124       gwin->is_main_actor_inside() &&
00125       !Bg_dont_wake(gwin, npc) &&
00126       npc->distance(gwin->get_main_actor()) < 6 && rand()%3 != 0)
00127     {
00128           // Trick:  Stand, but stay in
00129           //   sleep_schedule.
00130     npc->get_schedule()->ending(Schedule::stand);
00131     npc->say(first_awakened, last_awakened);
00132           // In 10 seconds, go back to sleep.
00133     npc->start(0, 10000);
00134     extra_delay = 11; // And don't run Usecode while up.
00135     }
00136       
00137   else if (!(curtime < wait_until) && !cheat.in_map_editor() && 
00138           // Do it 50% of the time OR if
00139           //   a rabbit (SI start).
00140      (rand()%2 == 1 || npc->get_shapenum() == 811)  &&
00141           // And not for party members.
00142       !npc->is_in_party() &&
00143           // And not if walking to sched. spot.
00144      sched != Schedule::walk_to_schedule &&
00145           // And not for patrollers/monsters
00146           //  in SI. !!Guessing.
00147      (Game::get_game_type() != SERPENT_ISLE ||
00148       (sched != Schedule::patrol &&
00149        sched != Schedule::wait &&
00150        sched != Schedule::horiz_pace &&
00151        sched != Schedule::vert_pace &&
00152        !npc->is_monster())))
00153         
00154     {
00155     int ucfun = npc->get_usecode();
00156     gwin->get_usecode()->call_usecode(ucfun, npc,
00157           Usecode_machine::npc_proximity);
00158     extra_delay += 3;
00159     curtime = Game::get_ticks();// Time may have passed.
00160     }
00161   add(curtime, npc, extra_delay); // Add back for next time.
00162   }
00163 
00164 /*
00165  *  Set a time to wait for before running any usecodes.  This is to
00166  *  skip all the text events that would happen at the end of a conver-
00167  *  sation.
00168  */
00169 
00170 void Npc_proximity_handler::wait
00171   (
00172   int secs      // # of seconds.
00173   )
00174   {
00175   wait_until = Game::get_ticks() + 1000*secs;
00176   }
00177 
00178 /*
00179  *  Fill a list with all the nearby NPC's.
00180  */
00181 
00182 void Npc_proximity_handler::get_all
00183   (
00184   Actor_queue& alist      // They're appended to this.
00185   )
00186   {
00187   Time_queue_iterator next(gwin->get_tqueue(), this);
00188   Time_sensitive *obj;
00189   long data;      // NPC is the data.
00190   while (next(obj, data))
00191     alist.push((Npc_actor *) data);
00192   }

Generated on Mon Jul 9 14:42:48 2007 for ExultEngine by  doxygen 1.5.1