Planeshift

npc.h

Go to the documentation of this file.
00001 /*
00002 * npc.h
00003 *
00004 * Copyright (C) 2003 Atomic Blue ([email protected], http://www.atomicblue.org)
00005 *
00006 *
00007 * This program is free software; you can redistribute it and/or
00008 * modify it under the terms of the GNU General Public License
00009 * as published by the Free Software Foundation (version 2 of the License)
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 * GNU General Public License for more details.
00014 * You should have received a copy of the GNU General Public License
00015 * along with this program; if not, write to the Free Software
00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 *
00018 */
00019 
00020 /* This file holds definitions for ALL global variables in the planeshift
00021 * server, normally you should move global variables into the psServer class
00022 */
00023 #ifndef __NPC_H__
00024 #define __NPC_H__
00025 //=============================================================================
00026 // Crystal Space Includes
00027 //=============================================================================
00028 #include <csutil/hash.h>
00029 
00030 struct iMovable;
00031 
00032 #include "util/psutil.h"
00033 #include "util/gameevent.h"
00034 #include "util/remotedebug.h"
00035 
00036 //=============================================================================
00037 // Local Includes
00038 //=============================================================================
00039 #include "tribe.h"
00040 #include "gem.h"
00041 #include "stat.h"
00042 
00043 class  Behavior;
00044 class  EventManager;
00045 class  HateList;
00046 class  LocationType;
00047 class  NPCType;
00048 class  NetworkManager;
00049 class  Tribe;
00050 class  Waypoint;
00051 class  gemNPCActor;
00052 class  gemNPCObject;
00053 class  iResultRow;
00054 class  psLinearMovement;
00055 class  psNPCClient;
00056 class  psNPCTick;
00057 struct iCollideSystem;
00058 struct HateListEntry;
00059 
00064 #define NPC_BRAIN_TICK 200
00065 
00066 // Define a variadic macro for debugging prints for NPCs.
00067 // In this way only the check IsDebugging is executed for each NPC unless debugging
00068 // is turned on. Using the Printf functions will cause all args to be
00069 // resolved and that will result in a lot off spilled CPU.
00070 #define NPCDebug(npc,debug,...) \
00071     { if (npc->IsDebugging()) { npc->Printf(debug, __VA_ARGS__); }}
00072 
00077 class HateList
00078 {
00079 protected:
00080     csHash<HateListEntry*, EID> hatelist;
00081 
00082 public:
00083     HateList(psNPCClient* npcclient, iEngine* engine, psWorld* world)
00084     {
00085         this->npcclient = npcclient;
00086         this->engine = engine;
00087         this->world = world;
00088     }
00089     ~HateList();
00090 
00091     void AddHate(EID entity_id, float delta);
00092 
00109     gemNPCActor* GetMostHated(NPC* npc, csVector3 &pos, iSector* sector, float range, LocationType* region,
00110                               bool includeOutsideRegion, bool includeInvisible, bool includeInvincible, float* hate);
00111     bool Remove(EID entity_id);
00112     void DumpHateList(csString &output, const csVector3 &myPos, iSector* mySector);
00113     void DumpHateList(NPC* npc, const csVector3 &myPos, iSector* mySector);
00114     void Clear();
00115     float GetHate(EID ent);
00116 
00117 private:
00118     psNPCClient* npcclient;
00119     iEngine* engine;
00120     psWorld* world;
00121 };
00122 
00126 class NPC : private ScopedTimerCB, public iScriptableVar, public RemoteDebug
00127 {
00128 public:
00132     typedef struct
00133     {
00134         csVector3               pos;        
00135         iSector*                sector;     
00136         float                   angle;      
00137         Waypoint*               wp;         
00138         float                   radius;     
00139         csWeakRef<gemNPCObject> target;     
00140     } Locate;
00141     typedef csHash<Locate*,csString> LocateHash;
00142 
00143     enum
00144     {
00145         LOCATION_NONE = 0,
00146         LOCATION_POS = 1,
00147         LOCATION_SECTOR = 2,
00148         LOCATION_ANGLE = 4,
00149         LOCATION_WP = 8,
00150         LOCATION_RADIUS = 16,
00151         LOCATION_TARGET = 32,
00152         LOCATION_ALL = -1
00153     };
00154 
00155 protected:
00156 
00157     typedef csHash<csString,csString> BufferHash;
00158 
00159     NPCType*           oldbrain;        
00160     NPCType*           brain;
00161     csString           origtype;        
00162     csString           type;
00163     PID                pid;
00164     csString           name;
00165     csTicks            last_update;
00166     gemNPCActor*       npcActor;
00167     iMovable*          movable;
00168 
00169     uint8_t            DRcounter;
00170     csVector3          lastDrPosition;
00171     iSector*           lastDrSector;
00172     csTicks            lastDrTime;
00173     bool               lastDrMoving;
00174     float              lastDrYRot;
00175     csVector3          lastDrVel;
00176     float              lastDrAngVel;
00177 
00178     Locate*            activeLocate;   
00179     LocateHash         storedLocates;  
00180 
00181     float              ang_vel,vel;
00182     float              walkVelocity;
00183     float              runVelocity;
00184     float              scale;                
00185     csString           region_name;          
00186     LocationType*      region;               
00187     bool               insideRegion;         
00188     Perception*        last_perception;
00189     bool               alive;
00190     EID                owner_id;
00191     EID                target_id;
00192 
00193     csArray<csString>  autoMemorizeTypes;    
00194 
00195     Tribe*             tribe;
00196     csString           tribeMemberType;      
00197     bool               insideTribeHome;      
00198 
00199     csVector3          spawnPosition;        
00200     iSector*           spawnSector;          
00201 
00202     psNPCRaceListMessage::NPCRaceInfo_t*        raceInfo;
00203 
00204     // Stats
00205     Stat               hp;
00206     Stat               mana;
00207     Stat               pysStamina;
00208     Stat               menStamina;
00209 
00210     csArray< csWeakRef<gemNPCActor> > controlledActors; 
00211 
00212     // Initial position checks
00213     csVector3          checkedPos;
00214     iSector*           checkedSector;
00215     bool               checked;
00216     bool               checkedResult;
00217     bool               disabled;
00218 
00219     int                fallCounter; // Incremented if the NPC fall off the map
00220 
00221     void Advance(csTicks when);
00222 
00226     void TickPostProcess(csTicks when);
00227 
00228     HateList           hatelist;
00229 
00230 public:
00231 
00232     NPC(psNPCClient* npcclient, NetworkManager* networkmanager, psWorld* world, iEngine* engine, iCollideSystem* cdsys);
00233     virtual ~NPC();
00234 
00235 
00236     void Tick();
00237 
00238     PID                   GetPID()
00239     {
00240         return pid;
00241     }
00245     EID                   GetEID();
00246     iMovable*             GetMovable()
00247     {
00248         return movable;
00249     }
00250     psLinearMovement*     GetLinMove();
00251 
00252     uint8_t               GetDRCounter(csTicks when, const csVector3 &pos, float yRot, iSector* sector,
00253                                        const csVector3 &vel, float angVel)
00254     {
00255         lastDrTime = when;
00256         lastDrPosition = pos;
00257         lastDrSector = sector;
00258         lastDrYRot = yRot;
00259         lastDrVel = vel;
00260         lastDrAngVel = angVel;
00261         return ++DRcounter;
00262     }
00263     void                  SetDRCounter(uint8_t counter)
00264     {
00265         DRcounter = counter;
00266     }
00267 
00273     bool Load(iResultRow &row,csHash<NPCType*, const char*> &npctypes, EventManager* eventmanager, PID usePID);
00274 
00278     void Load(const char* name, PID pid, NPCType* type, const char* region_name, int debugging, bool disabled, EventManager* eventmanager);
00279 
00282     bool InsertCopy(PID use_char_id, PID ownerPID);
00283 
00286     bool Delete();
00287 
00288     void SetActor(gemNPCActor* actor);
00289     gemNPCActor* GetActor()
00290     {
00291         return npcActor;
00292     }
00293     const char* GetName()
00294     {
00295         return name.GetDataSafe();
00296     }
00297     void SetAlive(bool a);
00298     bool IsAlive() const
00299     {
00300         return alive;
00301     }
00302     void Disable(bool disable = true);
00303     bool IsDisabled()
00304     {
00305         return disabled;
00306     }
00307 
00308     Behavior* GetCurrentBehavior();
00309     NPCType*  GetBrain();
00310     const char* GetOrigBrainType()
00311     {
00312         return origtype;
00313     }
00314 
00319     void SetBrain(NPCType* type);
00320 
00324     void ScopedTimerCallback(const ScopedTimer* timer);
00325 
00332     csString Info(const csString &infoRequestSubCmd);
00333 
00340     void Dump();
00341 
00345     void DumpState(csString &output);
00346 
00350     void DumpBehaviorList(csString &output);
00351 
00355     void DumpReactionList(csString &output);
00356 
00360     void DumpHateList(csString &output);
00361 
00365     void DumpHateList(NPC* npc);
00366 
00370     void DumpDebugLog(csString &output);
00371 
00375     void DumpMemory(csString &output);
00376 
00380     void DumpControlled(csString &output);
00381 
00387     void ClearState();
00388 
00404     void TriggerEvent(Perception* pcpt, float maxRange=-1.0,
00405                       csVector3* basePos=NULL, iSector* baseSector=NULL,
00406                       bool sameSector=false);
00407 
00415     void TriggerEvent(const char* pcpt);
00416 
00417     void SetLastPerception(Perception* pcpt);
00418     Perception* GetLastPerception()
00419     {
00420         return last_perception;
00421     }
00422 
00435     gemNPCActor* GetMostHated(float range, bool includeOutsideRegion, bool includeInvisible,
00436                               bool includeInvincible, float* hate=NULL);
00437 
00453     gemNPCActor* GetMostHated(csVector3 &pos, iSector* sector, float range, LocationType* region, bool includeOutsideRegion,
00454                               bool includeInvisible, bool includeInvincible, float* hate);
00455 
00456 
00463     float GetEntityHate(gemNPCActor* entity);
00464 
00471     void AddToHateList(gemNPCActor* attacker,float delta);
00472 
00476     void RemoveFromHateList(EID who);
00477 
00481     void SetLocate(const csString &destination, const NPC::Locate &locate);
00482 
00486     void GetActiveLocate(csVector3 &pos, iSector* &sector, float &rot);
00487 
00493     void GetActiveLocate(Waypoint* &wp);
00494 
00500     float GetActiveLocateRadius() const;
00501 
00507     bool CopyLocate(csString source, csString destination, unsigned int flags);
00508 
00514     void ReplaceLocations(csString &result);
00515 
00519     float GetAngularVelocity();
00520 
00524     float GetVelocity();
00525 
00529     float GetWalkVelocity();
00530 
00534     float GetRunVelocity();
00535 
00536     csString &GetRegionName()
00537     {
00538         return region_name;
00539     }
00540     LocationType* GetRegion();
00541 
00546     bool IsInsideRegion()
00547     {
00548         return insideRegion;
00549     }
00550 
00556     void SetInsideRegion(bool inside)
00557     {
00558         insideRegion = inside;
00559     }
00560 
00561 
00571     gemNPCActor* GetNearestActor(float range, csVector3 &destPosition, iSector* &destSector, float &destRange);
00572 
00582     gemNPCActor* GetNearestNPC(float range, csVector3 &destPosition, iSector* &destSector, float &destRange);
00583 
00593     gemNPCActor* GetNearestPlayer(float range, csVector3 &destPosition, iSector* &destSector, float &destRange);
00594 
00595     gemNPCActor* GetNearestVisibleFriend(float range);
00596 
00597     gemNPCActor* GetNearestDeadActor(float range);
00598 
00602     void AddAutoMemorize(csString types);
00603 
00607     void RemoveAutoMemorize(csString types);
00608 
00612     bool HasAutoMemorizeTypes() const
00613     {
00614         return !autoMemorizeTypes.IsEmpty();
00615     }
00616 
00620     bool ContainAutoMemorizeType(const csString &type);
00621 
00622 private:
00626     virtual void LocalDebugReport(const csString &debugString);
00627 
00631     virtual void RemoteDebugReport(uint32_t clientNum, const csString &debugString);
00632 
00633 public:
00634     gemNPCObject* GetTarget();
00635     void SetTarget(gemNPCObject* t);
00636 
00637     gemNPCObject* GetOwner();
00638     const char* GetOwnerName();
00639 
00648     void SetOwner(EID owner_EID);
00649 
00653     void SetTribe(Tribe* new_tribe);
00654 
00660     Tribe* GetTribe();
00661 
00665     void SetTribeMemberType(const char* tribeMemberType);
00666 
00669     const csString &GetTribeMemberType() const;
00670 
00675     bool IsInsideTribeHome()
00676     {
00677         return insideTribeHome;
00678     }
00679 
00685     void SetInsideTribeHome(bool inside)
00686     {
00687         insideTribeHome = inside;
00688     }
00689 
00693     psNPCRaceListMessage::NPCRaceInfo_t* GetRaceInfo();
00694 
00695 
00699     float GetHP();
00700 
00704     float GetMaxHP() const;
00705 
00709     float GetHPRate() const;
00710 
00714     float GetMana();
00715 
00719     float GetMaxMana() const;
00720 
00724     float GetManaRate() const;
00725 
00729     float GetPysStamina();
00730 
00734     float GetMaxPysStamina() const;
00735 
00739     float GetPysStaminaRate() const;
00740 
00744     float GetMenStamina();
00745 
00749     float GetMaxMenStamina() const;
00750 
00754     float GetMenStaminaRate() const;
00755 
00759     void TakeControl(gemNPCActor* actor);
00760 
00764     void ReleaseControl(gemNPCActor* actor);
00765 
00769     void UpdateControlled();
00770 
00774     void CheckPosition();
00775 
00782     void StoreSpawnPosition();
00783 
00787     const csVector3 &GetSpawnPosition() const;
00788 
00792     iSector* GetSpawnSector() const;
00793 
00794 
00800     void IncrementFallCounter()
00801     {
00802         ++fallCounter;
00803     }
00804 
00810     int GetFallCounter()
00811     {
00812         return fallCounter;
00813     }
00814 
00823     csString GetBuffer(const csString &bufferName);
00824 
00831     void SetBuffer(const csString &bufferName, const csString &value);
00832 
00838     void ReplaceBuffers(csString &result);
00839 
00843     Tribe::Memory* GetBufferMemory()
00844     {
00845         return bufferMemory;
00846     }
00847 
00853     void SetBufferMemory(Tribe::Memory* memory);
00854 
00860     void SetBuildingSpot(Tribe::Asset* buildingSpot);
00861 
00865     Tribe::Asset* GetBuildingSpot();
00866 
00867 private:
00871 
00872     virtual double GetProperty(MathEnvironment* env, const char* ptr);
00873     virtual double CalcFunction(MathEnvironment* env, const char* functionName, const double* params);
00874     virtual const char* ToString();
00876 
00877 private:
00878     psNPCTick*        tick;
00879     psNPCClient*      npcclient;
00880     NetworkManager*   networkmanager;
00881     psWorld*          world;
00882     iCollideSystem*   cdsys;
00883 
00884     BufferHash        npcBuffer;        
00885     Tribe::Memory*    bufferMemory;     
00886     Tribe::Asset*     buildingSpot;     
00887 
00888     friend class psNPCTick;
00889 
00890 };
00891 
00894 class psNPCTick : public psGameEvent
00895 {
00896 protected:
00897     NPC* npc;
00898 
00899 public:
00900     psNPCTick(int offsetticks, NPC* npc): psGameEvent(0,offsetticks,"psNPCTick"), npc(npc) {};
00901 
00902     virtual void Trigger()
00903     {
00904         if(npc)
00905         {
00906             npc->tick = NULL;
00907             npc->Tick();
00908         }
00909     }
00910 
00911     void Remove()
00912     {
00913         npc = NULL;
00914     }
00915 
00916 
00917     virtual csString ToString() const
00918     {
00919         return "psNPCTick";
00920     }
00921 };
00922 
00923 struct HateListEntry
00924 {
00925     EID   entity_id;
00926     float hate_amount;
00927 };
00928 
00931 #endif
00932