Planeshift
|
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* §or, 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