Planeshift

gem.h

Go to the documentation of this file.
00001 /*
00002  * gem.h - author Keith Fulton <[email protected]>
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  * This is the cel access class for PS.
00019  *
00020  * TODO: This API really needs to be refactored into a set of factories.
00021  */
00022 
00023 #ifndef __GEM_H__
00024 #define __GEM_H__
00025 //=============================================================================
00026 // Crystal Space Includes
00027 //=============================================================================
00028 #include <iengine/mesh.h>
00029 #include <iengine/sector.h>
00030 #include <iutil/vfs.h>
00031 #include <csutil/csobject.h>
00032 #include <csutil/csstring.h>
00033 #include <csutil/hash.h>
00034 #include <csutil/weakreferenced.h>
00035 
00036 //=============================================================================
00037 // Project Space Includes
00038 //=============================================================================
00039 #include "bulkobjects/activespell.h"
00040 #include "bulkobjects/buffable.h"
00041 #include "bulkobjects/pscharacter.h"
00042 
00043 #include "util/gameevent.h"
00044 #include "util/consoleout.h"
00045 
00046 #include "net/npcmessages.h"  // required for psNPCCommandsMessage::PerceptionType
00047 
00048 //=============================================================================
00049 // Local Space Includes
00050 //=============================================================================
00051 #include "msgmanager.h"
00052 #include "deathcallback.h"
00053 
00054 struct iMeshWrapper;
00055 
00056 class ProximityList;
00057 class ServerCharManager;
00058 class EntityManager;
00059 class gemObject;
00060 class PlayerGroup;
00061 class psDatabase;
00062 class psItem;
00063 class csMatrix3;
00064 class NPCManager;
00065 class psGlyphList;
00066 class ProgressionManager;
00067 class psNPCDialog;
00068 class psAllEntityPosMessage;
00069 class psActionLocation;
00070 class psSpellCastEvent;
00071 class MathScript;
00072 class gemItem;
00073 class gemActor;
00074 class gemNPC;
00075 class gemPet;
00076 class gemActionLocation;
00077 class ClientConnectionSet;
00078 class PublishVector;
00079 class psLinearMovement;
00080 class gemMesh;
00081 
00086 #define BUFF_INDICATOR          "+"
00087 #define DEBUFF_INDICATOR        "-"
00088 
00089 #define UNSTICK_TIME 15000
00090 
00091 
00092 //-----------------------------------------------------------------------------
00093 
00097 class psGemServerMeshAttach : public scfImplementationExt1<psGemServerMeshAttach,
00098     csObject,
00099     scfFakeInterface<psGemServerMeshAttach> >
00100 {
00101 public:
00102     SCF_INTERFACE(psGemServerMeshAttach, 0, 0, 1);
00103 
00109     psGemServerMeshAttach(gemObject* object);
00110 
00114     gemObject* GetObject()
00115     {
00116         return object;
00117     }
00118 
00119 private:
00120     gemObject* object;          
00121 };
00122 
00126 class GEMSupervisor : public MessageManager<GEMSupervisor>
00127 {
00128     EntityManager* entityManager;
00129     CacheManager* cacheManager;
00130 public:
00131     iObjectRegistry*        object_reg;                     
00132     psDatabase*             database;                       
00133     NPCManager*             npcmanager;                     
00134 
00143     GEMSupervisor(iObjectRegistry* objreg, psDatabase* db, EntityManager* entitymanager, CacheManager* cachemanager);
00144 
00150     virtual ~GEMSupervisor();
00151 
00157     csHash<gemObject*, EID> &GetAllGEMS()
00158     {
00159         return entities_by_eid;
00160     }
00161 
00164 
00165 
00171     EID        FindItemID(psItem* item);
00172 
00173     gemObject* FindObject(EID cel_id);
00174 
00175     gemObject* FindObject(const csString &name);
00176 
00177     gemActor*  FindPlayerEntity(PID player_id);
00178 
00179     gemNPC*    FindNPCEntity(PID npc_id);
00180 
00181     gemNPC*    FindNPCEntity(EID eid);
00182 
00183     gemItem*   FindItemEntity(uint32 item_id);
00185 
00186     EID  CreateEntity(gemObject* obj);
00187     void AddEntity(gemObject* obj, EID objEid); 
00188     void RemoveEntity(gemObject* which);
00189     void AddActorEntity(gemActor* actor);
00190     void RemoveActorEntity(gemActor* actor);
00191     void AddItemEntity(gemItem* item);
00192     void RemoveItemEntity(gemItem* item, uint32 uid);
00193 
00194     void RemovePlayerFromLootables(PID playerID);
00195 
00196     void UpdateAllDR();
00197     void UpdateAllStats();
00198 
00199     void GetAllEntityPos(csArray<psAllEntityPosMessage> &msgs);
00200     int  CountManagedNPCs(AccountID superclientID);
00201     void FillNPCList(MsgEntry* msg, AccountID superclientID);
00202     void SendAllNPCStats(AccountID superclientID);
00203     void ActivateNPCs(AccountID superclientID);
00204     void StopAllNPCs(AccountID superclientID);
00205 
00214     void GetPlayerObjects(PID playerID, csArray<gemObject*> &list);
00215 
00226     void Teleport(gemObject* object, float x, float y, float z, float rot, const char* sectorname);
00227 
00228     void HandleStatsMessage(MsgEntry* me, Client* client);
00229     void HandleDamageMessage(MsgEntry* me, Client* client);
00230     void HandleStatDRUpdateMessage(MsgEntry* me, Client* client);
00231 
00240     void AttachObject(iObject* object, gemObject* gobject);
00241 
00242 
00251     void UnattachObject(iObject* object, gemObject* gobject);
00252 
00253 
00260     gemObject* FindAttachedObject(iObject* object);
00261 
00262 
00274     csArray<gemObject*> FindNearbyEntities(iSector* sector, const csVector3 &pos, InstanceID instance, float radius, bool doInvisible = false);
00275 
00284     csArray<gemObject*> FindSectorEntities(iSector* sector, bool doInvisible = false);
00285 
00286 protected:
00292     EID GetNextID();
00293 
00294     csHash<gemObject*, EID> entities_by_eid; 
00295     csHash<gemItem*, uint32> items_by_uid;   
00296     csHash<gemActor*,  PID> actors_by_pid;   
00297 
00298     uint32              nextEID;             
00299 
00300 
00301     csRef<iEngine> engine;                   
00302 };
00303 
00304 //-----------------------------------------------------------------------------
00305 
00310 class gemObject : public iDeleteNotificationObject, public CS::Utility::WeakReferenced, public iScriptableVar
00311 {
00312 
00313 public:
00314     virtual ~gemObject();
00315 
00316     EID GetEID()
00317     {
00318         return eid;
00319     }
00320 
00324 
00325     virtual double GetProperty(MathEnvironment* env, const char* ptr);
00326     virtual double CalcFunction(MathEnvironment* env, const char* functionName, const double* params);
00327     virtual const char* ToString()
00328     {
00329         return name.GetData();
00330     }
00332 
00336     virtual void Disconnect();
00337 
00338     virtual bool IsValid(void)
00339     {
00340         return eid.IsValid();
00341     }
00342 
00346     bool IsAlive() const
00347     {
00348         return is_alive;
00349     }
00350 
00359     void SetAlive(bool flag, bool queue = true);
00360 
00361     uint32_t GetClientID();
00362 
00363     virtual const char* GetObjectType()
00364     {
00365         return "Object";
00366     }
00367 
00368     gemItem* GetItemPtr();
00369     gemActor* GetActorPtr();
00370     gemNPC* GetNPCPtr();
00371     gemPet* GetPetPtr();
00372     gemActionLocation* GetALPtr();
00373 
00374     psItem* GetItem();
00375     virtual psCharacter* GetCharacterData()
00376     {
00377         return NULL;
00378     }
00379 
00380     virtual Client* GetClient() const
00381     {
00382         return NULL;
00383     }
00384 
00385     const char* GetName();
00386     void SetName(const char* n);
00387 
00388     void SetInstance(InstanceID newInstance)
00389     {
00390         worldInstance = newInstance;
00391     }
00392     InstanceID  GetInstance()
00393     {
00394         return worldInstance;
00395     }
00396 
00397     void RegisterCallback(iDeleteObjectCallback* receiver)
00398     {
00399         receivers.Push(receiver);
00400     }
00401     void UnregisterCallback(iDeleteObjectCallback* receiver)
00402     {
00403         receivers.Delete(receiver);
00404     }
00405 
00409 
00410 
00414     iMeshWrapper* GetMeshWrapper();
00415 
00419     csString GetMesh()
00420     {
00421         return factname;
00422     }
00423 
00427     void Move(const csVector3 &pos,float rotangle,iSector* room);
00428 
00432     bool IsNear(gemObject* obj,float radius, bool ignoreY = false);
00433 
00437     const csVector3 &GetPosition();
00438 
00442     void GetPosition(csVector3 &pos, float &yrot,iSector* &sector);
00443 
00447     void GetPosition(csVector3 &pos, iSector* &sector);
00448 
00455     float GetAngle();
00456 
00460     iSector* GetSector();
00461 
00465     virtual float GetVelocity();
00466 
00470     const char* GetSectorName()
00471     {
00472         return GetSector() ? GetSector()->QueryObject()->GetName() : "(null)";
00473     }
00474 
00478     csArray<gemObject*>* GetObjectsInRange(float range);
00480 
00483 
00484 
00488     ProximityList* GetProxList()
00489     {
00490         return proxlist;
00491     };
00492 
00496     csArray<PublishDestination> &GetMulticastClients();
00497 
00505     void UpdateProxList(bool force = false);
00506 
00510     void RemoveFromAllProx();
00511 
00515     void SetAlwaysWatching(bool w)
00516     {
00517         alwaysWatching = w;
00518     }
00519 
00523     bool AlwaysWatching()
00524     {
00525         return alwaysWatching;
00526     }
00528 
00529     float RangeTo(gemObject* obj, bool ignoreY = false, bool ignoreInstance = false);
00530 
00531     virtual bool IsUpdateReq(csVector3 const &pos,csVector3 const &oldPos);
00532 
00537     virtual float GetBaseAdvertiseRange()
00538     {
00539         return DEF_PROX_DIST;
00540     };
00541 
00542     virtual void SendBehaviorMessage(const csString &str, gemObject* obj);
00543     virtual csString GetDefaultBehavior(const csString &dfltBehaviors);
00544 
00550     virtual void Dump();
00551 
00552 
00555 
00556 
00561     virtual void Broadcast(int clientnum, bool control);
00562 
00571     virtual bool Send(int clientnum, bool control, bool to_superclients, psPersistAllEntities* allEntities=NULL)
00572     {
00573         return true;
00574     }
00575 
00581     virtual void SendGroupMessage(MsgEntry* me) { };
00583 
00586 
00587     virtual PID GetPID()
00588     {
00589         return 0;
00590     }
00591     virtual int GetGuildID()
00592     {
00593         return 0;
00594     }
00595     virtual psGuildInfo* GetGuild()
00596     {
00597         return 0;
00598     }
00599     virtual bool UpdateDR()
00600     {
00601         return false;
00602     }
00603     virtual void BroadcastTargetStatDR(ClientConnectionSet* clients) { }
00604     virtual void SendTargetStatDR(Client* client) { }
00605     virtual psNPCDialog* GetNPCDialogPtr()
00606     {
00607         return 0;
00608     }
00609     virtual void GetLastSuperclientPos(csVector3 &pos, InstanceID &instance, csTicks &last) const { }
00610     virtual void SetLastSuperclientPos(const csVector3 &pos, InstanceID instance, const csTicks &now) { }
00611     virtual void AddLootablePlayer(PID playerID) { }
00612     virtual void RemoveLootablePlayer(PID playerID) { }
00613     virtual bool IsLootablePlayer(PID playerID)
00614     {
00615         return false;
00616     }
00617     virtual Client* GetRandomLootClient(int range)
00618     {
00619         return NULL;
00620     }
00621     virtual AccountID GetSuperclientID()
00622     {
00623         return 0;
00624     }
00625     virtual void SetSuperclientID(AccountID id) { }
00626 
00627     virtual bool GetVisibility()
00628     {
00629         return true;
00630     }
00631     virtual bool SeesObject(gemObject* object, float range)
00632     {
00633         return false;
00634     }
00635 
00636     virtual gemObject* GetOwner()
00637     {
00638         return NULL;
00639     }
00640 
00649     virtual bool HasKillStealProtection()
00650     {
00651         return false;
00652     }
00654 
00655 protected:
00656     gemObject(GEMSupervisor* gemsupervisor, EntityManager* entitymanager, CacheManager* cachemanager, const char* name, const char* factname, InstanceID myinstance, iSector* room,
00657               const csVector3 &pos, float rotangle, int clientnum);
00658 
00659     bool valid;                                 
00660 
00661     gemMesh* pcmesh;                            
00662     ProximityList* proxlist;                    
00663     csString name;                              
00664     static GEMSupervisor* cel;                  
00665     EntityManager* entityManager;
00666     CacheManager* cacheManager;
00667     InstanceID worldInstance;                   
00668     bool is_alive;                              
00669     csString factname;                          
00670     csString matname;                           
00671     EID eid;                                    
00672     csRef<iMeshFactoryWrapper> nullfact;        
00673     bool alwaysWatching;                           
00674 
00675     csArray<iDeleteObjectCallback*> receivers;  
00676 
00677     float prox_distance_desired;                
00678     float prox_distance_current;                
00679 
00680     bool InitProximityList(float radius,int clientnum);
00681 
00682     void InitMesh(const char* name, const csVector3 &pos, const float rotangle, iSector* room);
00683 };
00684 
00685 //-----------------------------------------------------------------------------
00686 
00690 class gemActiveObject : public gemObject
00691 {
00692 public:
00693     gemActiveObject(GEMSupervisor* gemSupervisor, EntityManager* entitymanager,CacheManager* cachemanager, const char* name,
00694                     const char* factname,
00695                     InstanceID myInstance,
00696                     iSector* room,
00697                     const csVector3 &pos,
00698                     float rotangle,
00699                     int clientnum);
00700 
00701     virtual const char* GetObjectType()
00702     {
00703         return "Active object";
00704     }
00705 
00710     virtual void Broadcast(int clientnum, bool control);
00711 
00720     virtual bool Send(int clientnum, bool control, bool to_superclients, psPersistAllEntities* allEntities=NULL)
00721     {
00722         return true;
00723     }
00724 
00725     virtual void SendBehaviorMessage(const csString &str, gemObject* obj);
00726     virtual csString GetDefaultBehavior(const csString &dfltBehaviors);
00727 
00728     virtual bool IsPickupable()
00729     {
00730         return false;
00731     }
00732     virtual bool IsPickupableWeak()
00733     {
00734         return false;
00735     }
00736     virtual bool IsPickupableStrong()
00737     {
00738         return false;
00739     }
00740     virtual bool IsLockable()
00741     {
00742         return false;
00743     }
00744     virtual bool IsLocked()
00745     {
00746         return false;
00747     }
00748     virtual bool IsConstructible()
00749     {
00750         return false;
00751     }
00752     virtual bool IsSecutityLocked()
00753     {
00754         return false;
00755     }
00756     virtual bool IsContainer()
00757     {
00758         return false;
00759     }
00760 };
00761 
00762 //-----------------------------------------------------------------------------
00763 
00764 class gemItem : public gemActiveObject
00765 {
00766 protected:
00767     psItem* itemdata;
00768     csString itemType;
00769     float xRot;
00770     float yRot;
00771     float zRot;
00772     uint32_t tribeID; 
00773 
00774 public:
00775     gemItem(GEMSupervisor* gemsupervisor,
00776             CacheManager* cachemanager,
00777             EntityManager* entitymanager,
00778             psItem* item,
00779             const char* factname,
00780             InstanceID myInstance,
00781             iSector* room,
00782             const csVector3 &pos,
00783             float xrotangle,
00784             float yrotangle,
00785             float zrotangle,
00786             int clientnum);
00787 
00788     virtual ~gemItem()
00789     {
00790         delete itemdata;
00791     }
00792 
00793     void SetTribeID(uint32_t id)
00794     {
00795         tribeID = id;
00796     }
00797     uint32_t  GetTribeID()
00798     {
00799         return tribeID;
00800     }
00801 
00802     virtual const char* GetObjectType()
00803     {
00804         return itemType.GetData();
00805     }
00806     psItem* GetItemData()
00807     {
00808         return itemdata;
00809     }
00810     void ClearItemData()
00811     {
00812         itemdata = NULL;
00813     }
00814 
00815 
00819 
00820     virtual double GetProperty(MathEnvironment* env, const char* ptr);
00821     virtual double CalcFunction(MathEnvironment* env, const char* functionName, const double* params);
00823 
00824     virtual float GetBaseAdvertiseRange();
00825 
00830     virtual void Broadcast(int clientnum, bool control);
00831 
00840     virtual bool Send(int clientnum, bool control, bool to_superclients, psPersistAllEntities* allEntities=NULL);
00841 
00852     virtual void SetPosition(const csVector3 &pos,float angle, iSector* sector, InstanceID instance);
00853 
00861     virtual void SetRotation(float xrotangle, float yrotangle, float zrotangle);
00862 
00870     virtual void GetRotation(float &xrotangle, float &yrotangle, float &zrotangle);
00871 
00877     virtual bool IsPickupable();
00878 
00887     virtual bool IsPickupableWeak();
00888 
00896     virtual bool IsPickupableStrong();
00897 
00898     virtual bool IsLockable();
00899     virtual bool IsLocked();
00900     virtual bool IsConstructible();
00901     virtual bool IsSecurityLocked();
00902     virtual bool IsContainer();
00903     virtual bool IsUsingCD();
00904 
00905     virtual bool GetCanTransform();
00906     virtual bool GetVisibility();
00907 
00908     virtual void SendBehaviorMessage(const csString &str, gemObject* obj);
00909 
00910 private:
00919     virtual void SendBehaviorMessageTakeAll(const csString &str, gemObject* obj, bool precise);
00920 };
00921 
00922 //-----------------------------------------------------------------------------
00923 
00931 class gemContainer : public gemItem
00932 {
00933 protected:
00934     csArray<psItem*> itemlist;
00935     bool AddToContainer(psItem* item, Client* fromClient,int slot, bool test);
00936 
00937 public:
00938     gemContainer(GEMSupervisor* gemSupervisor, CacheManager* cachemanager,
00939                  EntityManager* entitymanager,
00940                  psItem* item,
00941                  const char* factname,
00942                  InstanceID myInstance,
00943                  iSector* room,
00944                  const csVector3 &pos,
00945                  float xrotangle,
00946                  float yrotangle,
00947                  float zrotangle,
00948                  int clientnum);
00949 
00950     ~gemContainer();
00951 
00957     void CleareWithoutDelete();
00958 
00962     bool CanAdd(unsigned short amountToAdd, psItem* item, int slot, csString &reason);
00963     bool AddToContainer(psItem* item,Client* fromClient, int slot=-1)
00964     {
00965         return AddToContainer(item, fromClient, slot, false);
00966     }
00967     bool RemoveFromContainer(psItem* item,Client* fromClient);
00968 
00977     bool CanTake(Client* client, psItem* item);
00978 
00990     psItem* RemoveFromContainer(psItem* itemStack, int fromSlot, Client* fromClient, int stackCount);
00991 
00992     psItem* FindItemInSlot(int slot, int stackCount = -1);
00993     int SlotCount()
00994     {
00995         return GetItemData()->GetContainerMaxSlots();
00996     }
00997     size_t CountItems()
00998     {
00999         return itemlist.GetSize();
01000     }
01001     psItem* GetIndexItem(size_t i)
01002     {
01003         return itemlist[i];
01004     }
01005 
01006     class psContainerIterator;
01007 
01008     class psContainerIterator
01009     {
01010         size_t current;
01011         gemContainer* container;
01012 
01013     public:
01014 
01015         psContainerIterator(gemContainer* containerItem);
01016         bool HasNext();
01017         psItem* Next();
01018         psItem* RemoveCurrent(Client* fromClient);
01019         void UseContainerItem(gemContainer* containerItem);
01020     };
01021 };
01022 
01023 //-----------------------------------------------------------------------------
01024 
01025 class gemActionLocation : public gemActiveObject
01026 {
01027 private:
01028     psActionLocation* action;
01029     bool visible;
01030 
01031 public:
01032     gemActionLocation(GEMSupervisor* gemSupervisor,EntityManager* entitymanager,CacheManager* cachemanager,
01033                       psActionLocation* action, iSector* isec, int clientnum);
01034 
01035     virtual const char* GetObjectType()
01036     {
01037         return "ActionLocation";
01038     }
01039     virtual psActionLocation* GetAction()
01040     {
01041         return action;
01042     }
01043 
01044     virtual float GetBaseAdvertiseRange();
01045     virtual bool SeesObject(gemObject* object, float range);
01046 
01051     virtual void Broadcast(int clientnum, bool control);
01052 
01061     virtual bool Send(int clientnum, bool control, bool to_superclients, psPersistAllEntities* allEntities=NULL);
01062 
01063     virtual void SendBehaviorMessage(const csString &str, gemObject* obj);
01064 
01065     virtual bool GetVisibility()
01066     {
01067         return visible;
01068     };
01069     virtual void SetVisibility(bool vis)
01070     {
01071         visible = vis;
01072     };
01073 };
01074 
01075 //-----------------------------------------------------------------------------
01076 
01083 class AttackerHistory
01084 {
01085 public:
01086     virtual ~AttackerHistory() {}
01087 
01088     gemActor* Attacker() const
01089     {
01090         return attacker_ref;
01091     }
01092     csTicks TimeOfAttack() const
01093     {
01094         return timeOfAttack;
01095     }
01096     virtual float Damage() const = 0; // Always positive.
01097 protected:
01098     AttackerHistory(gemActor* attacker) : attacker_ref(attacker)
01099     {
01100         timeOfAttack = csGetTicks();
01101     }
01102 
01103     csWeakRef<gemActor> attacker_ref;
01104     csTicks timeOfAttack;
01105 };
01106 
01110 class DamageHistory : public AttackerHistory
01111 {
01112 public:
01113     DamageHistory(gemActor* attacker, float dmg) : AttackerHistory(attacker), damage(dmg)
01114     {
01115         CS_ASSERT(damage > 0);
01116     }
01117     virtual ~DamageHistory() {}
01118     virtual float Damage() const
01119     {
01120         return damage;
01121     }
01122 protected:
01123     float damage;
01124 };
01125 
01129 class DOTHistory : public AttackerHistory
01130 {
01131 public:
01132     DOTHistory(gemActor* attacker, float hpRate, csTicks duration) : AttackerHistory(attacker), hpRate(hpRate), duration(duration)
01133     {
01134         CS_ASSERT(hpRate < 0);
01135     }
01136     virtual ~DOTHistory() {}
01137     virtual float Damage() const
01138     {
01139         csTicks elapsed = csGetTicks() - timeOfAttack;
01140         return -hpRate * csMin(duration, elapsed);
01141     }
01142 protected:
01143     float hpRate;
01144     csTicks duration;
01145 };
01146 
01147 //-----------------------------------------------------------------------------
01148 class FrozenBuffable : public ClampedPositiveBuffable<int>
01149 {
01150 public:
01151     void Initialize(gemActor* actor)
01152     {
01153         this->actor = actor;
01154     }
01155 
01156 protected:
01157     gemActor* actor;
01158     virtual void OnChange();
01159 };
01160 
01161 //-----------------------------------------------------------------------------
01162 
01166 class gemActor :  public gemObject, public iDeathNotificationObject
01167 {
01168 protected:
01169     psCharacter* psChar;
01170     PID pid;                   
01171     csRef<PlayerGroup> group;
01172 
01173     psCharacter* mount;
01174 
01175     csVector3 top, bottom, offset;
01176     csVector3 last_production_pos;
01177 
01178     csWeakRef<Client> clientRef;
01179 
01180     uint8_t attack_cnt; 
01181 
01182     uint8_t DRcounter;  
01183     uint8_t forceDRcounter; 
01184     csTicks lastDR;
01185     csVector3 lastV;
01186 
01188     csVector3 productionStartPos;
01189 
01190     csVector3 lastSentSuperclientPos;
01191     unsigned int lastSentSuperclientInstance;
01192     csTicks      lastSentSuperclientTick;
01193 
01194     csArray<iDeathCallback*> deathReceivers;  
01195 
01196     struct DRstate
01197     {
01198         csVector3 pos;
01199         iSector* sector;
01200         float yrot;
01201         InstanceID instance;
01202     } valid_location;
01203 
01204     DRstate newvalid_location;
01205     DRstate last_location;
01206     DRstate prev_teleport_location;
01207 
01208     // used by /report command.
01209     // for details on current /report implementation
01210     // check PS#2789.
01211 
01213     struct ChatHistoryEntry
01214     {
01216         time_t _time;
01217 
01219         csString _line;
01220 
01222         ChatHistoryEntry(const char* szLine, time_t t = 0);
01223 
01229         void GetLogLine(csString &line) const;
01230     };
01231 
01235     unsigned int activeReports;
01236 
01240     csArray<ChatHistoryEntry> chatHistory;
01241 
01244     csRef<iFile> logging_chat_file;
01245 
01250     bool InitLinMove(const csVector3 &pos,float angle, iSector* sector);
01251     bool InitCharData(Client* c);
01252 
01254     int securityLevel;
01255     int masqueradeLevel;
01256 
01257     bool isFalling;           
01258     csVector3 fallStartPos;   
01259     iSector* fallStartSector; 
01260     csTicks fallStartTime;
01261 
01262     bool invincible;          
01263     bool visible;             
01264     bool viewAllObjects;      
01265 
01266     csWeakRef<gemObject> targetObject; 
01267 
01268     csPDelArray<AttackerHistory> dmgHistory;
01269     csPDelArray<ProgressionScript> onAttackScripts, onDefenseScripts, onNearlyDeadScripts, onMovementScripts;
01270 
01271     csArray<ActiveSpell*> activeSpells;
01272 
01273     virtual void ApplyStaminaCalculations(const csVector3 &velocity, float times);
01274 
01276     void SetGMDefaults();
01277 
01278     uint8_t movementMode; 
01279     bool isAllowedToMove; 
01280     bool atRest;          
01281     FrozenBuffable isFrozen;  
01282 
01283     PSCHARACTER_MODE player_mode;
01284     Stance combat_stance;
01285 
01286     psSpellCastGameEvent* spellCasting; 
01287 
01288     psWorkGameEvent* workEvent;
01289 
01294     iSector* forcedSector;
01295 
01296     bool CanSwitchMode(PSCHARACTER_MODE from, PSCHARACTER_MODE to);
01297 
01301     uint32_t activeMagic_seq;
01302 
01303 public:
01304     psLinearMovement* pcmove;
01305 
01306     gemActor(GEMSupervisor* gemsupervisor,
01307              CacheManager* cachemanager,
01308              EntityManager* entitymanager,
01309              psCharacter* chardata, const char* factname,
01310              InstanceID myInstance,iSector* room,const csVector3 &pos,float rotangle,int clientnum);
01311 
01312     virtual ~gemActor();
01313 
01314     virtual const char* GetObjectType()
01315     {
01316         return "Actor";
01317     }
01318     virtual psCharacter* GetCharacterData()
01319     {
01320         return psChar;
01321     }
01322     virtual Client* GetClient() const;
01323 
01324     virtual PID GetPID()
01325     {
01326         return pid;
01327     }
01328 
01332 
01333     virtual double GetProperty(MathEnvironment* env, const char* ptr);
01334     virtual double CalcFunction(MathEnvironment* env, const char* functionName, const double* params);
01336 
01337     bool SetupCharData();
01338 
01339     void SetTextureParts(const char* parts);
01340     void SetEquipment(const char* equip);
01341 
01342     psCharacter* GetMount() const
01343     {
01344         return mount;
01345     }
01346 
01347     void SetMount(psCharacter* newMount)
01348     {
01349         mount = newMount;
01350     }
01351 
01352     bool IsMounted()
01353     {
01354         return (mount != NULL);
01355     }
01356 
01357 
01358     PSCHARACTER_MODE GetMode()
01359     {
01360         return player_mode;
01361     }
01362     const char* GetModeStr(); 
01363     void SetMode(PSCHARACTER_MODE newmode, uint32_t extraData = 0);
01364     const Stance &GetCombatStance()
01365     {
01366         return combat_stance;
01367     }
01368     virtual void SetCombatStance(const Stance &stance);
01369     bool StartAttack()
01370     {
01371         if(attack_cnt < 2)
01372         {
01373             attack_cnt++;
01374             return true;
01375         }
01376         return false;
01377     }
01378     void EndAttack()
01379     {
01380         CS_ASSERT(attack_cnt);
01381         attack_cnt--;
01382     }
01383     virtual void SetDefaultAttackID(unsigned)
01384     {
01385     }
01386     virtual unsigned GetDefaultAttackID()
01387     {
01388         return 1;
01389     }
01390 
01391     void SetSpellCasting(psSpellCastGameEvent* event)
01392     {
01393         spellCasting = event;
01394     }
01395     bool IsSpellCasting()
01396     {
01397         return spellCasting != NULL;
01398     }
01399     void InterruptSpellCasting()
01400     {
01401         if(spellCasting) spellCasting->Interrupt();
01402     }
01403 
01407     void SetTradeWork(psWorkGameEvent* event)
01408     {
01409         workEvent = event;
01410     }
01411 
01415     psWorkGameEvent* GetTradeWork()
01416     {
01417         return workEvent;
01418     }
01419 
01420     bool IsAllowedToMove()
01421     {
01422         return isAllowedToMove;    
01423     }
01424     void SetAllowedToMove(bool newvalue);
01425 
01427     void SetFrozen(bool flag)
01428     {
01429         isFrozen.SetBase(flag ? 1 : 0);
01430     }
01431     bool IsFrozen()
01432     {
01433         return (isFrozen.Current() > 0);
01434     }
01435     FrozenBuffable &GetBuffableFrozen()
01436     {
01437         return isFrozen;
01438     }
01439 
01443     int GetTargetType(gemObject* target);
01444 
01449     bool IsAllowedToAttack(gemObject* target, csString &msg);
01450 
01451 
01455     void Sit();
01456 
01460     void Stand();
01461 
01465     void SetAllowedToDisconnect(bool allowed);
01466 
01467     void SetSecurityLevel(int level);
01468     void SetMasqueradeLevel(int level);
01469     int GetSecurityLevel()
01470     {
01471         return(securityLevel);
01472     }
01473     int GetMasqueradeLevel()
01474     {
01475         return(masqueradeLevel);
01476     }
01477 
01478     // Last Production Pos is used to require people to move around while /digging
01479     void SetLastProductionPos(csVector3 &pos)
01480     {
01481         last_production_pos = pos;
01482     }
01483     void GetLastProductionPos(csVector3 &pos)
01484     {
01485         pos = last_production_pos;
01486     }
01487 
01493     const csVector3 &GetProductionStartPos(void) const
01494     {
01495         return productionStartPos;
01496     }
01497 
01503     void SetProductionStartPos(const csVector3 &pos)
01504     {
01505         productionStartPos = pos;
01506     }
01507 
01508     // To be used for the /report command.
01509 
01516     bool AddChatReport(gemActor* reporter);
01517 
01524     void RemoveChatReport();
01525 
01529     bool IsLoggingChat() const
01530     {
01531         return activeReports > 0;
01532     }
01533 
01541     bool LogChatMessage(const char* who, const psChatMessage &msg);
01542 
01549     bool LogSystemMessage(const char* szLine);
01550 
01557     bool LogLine(const char* szLine);
01558 
01559 
01560     void UpdateStats();
01561     void ProcessStamina();
01562     void ProcessStamina(const csVector3 &velocity, bool force=false);
01563 
01564     void Teleport(const char* sec, const csVector3 &pos, float yrot, InstanceID instance, int32_t loadDelay = 0, csString background = "", csVector2 point1 = 0, csVector2 point2 = 0, csString widget = "");
01565     void Teleport(iSector* sector, const csVector3 &pos, float yrot, InstanceID instance, int32_t loadDelay = 0, csString background = "", csVector2 point1 = 0, csVector2 point2 = 0, csString widget = "");
01566     void Teleport(iSector* sector, const csVector3 &pos, float yrot, int32_t loadDelay = 0, csString background = "", csVector2 point1 = 0, csVector2 point2 = 0, csString widget = "");
01567 
01568     void SetPosition(const csVector3 &pos,float angle, iSector* sector);
01569     void SetInstance(InstanceID worldInstance);
01570 
01571     void UpdateValidLocation(const csVector3 &pos, float yrot, iSector* sector, InstanceID instance, bool force = false);
01572 
01573     bool SetDRData(psDRMessage &drmsg);
01574     void MulticastDRUpdate();
01575     virtual void ForcePositionUpdate(int32_t loadDelay = 0, csString background = "", csVector2 point1 = 0, csVector2 point2 = 0, csString widget = "");
01576 
01577     using gemObject::RegisterCallback;
01578     using gemObject::UnregisterCallback;
01579     void RegisterCallback(iDeathCallback* receiver)
01580     {
01581         deathReceivers.Push(receiver);
01582     }
01583     void UnregisterCallback(iDeathCallback* receiver)
01584     {
01585         deathReceivers.Delete(receiver);
01586     }
01587     void HandleDeath();
01588 
01589     float GetRelativeFaction(gemActor* speaker);
01590 
01591     csPtr<PlayerGroup> GetGroup();
01592     void SetGroup(PlayerGroup* group);
01593     bool InGroup() const;
01594     bool IsGroupedWith(gemActor* other, bool IncludePets = false) const;
01595     int GetGroupID();
01596     void RemoveFromGroup();
01597 
01598     bool IsMyPet(gemActor* other) const;
01599 
01600     const char* GetFirstName()
01601     {
01602         return psChar->GetCharName();
01603     }
01604 
01605     const char* GetGuildName();
01606     psGuildInfo* GetGuild()
01607     {
01608         return psChar->GetGuild();
01609     }
01610     psGuildLevel* GetGuildLevel()
01611     {
01612         return psChar->GetGuildLevel();
01613     }
01614 
01620     psGuildMember* GetGuildMembership()
01621     {
01622         return psChar->GetGuildMembership();
01623     }
01624 
01625     void DoDamage(gemActor* attacker, float damage);
01626     void AddAttackerHistory(gemActor* attacker, float damage); // direct damage version
01627     void AddAttackerHistory(gemActor* attacker, float hpRate, csTicks duration); // DoT version
01628     void RemoveAttackerHistory(gemActor* attacker);
01629     bool CanBeAttackedBy(gemActor* attacker, gemActor* &lastAttacker) const;
01630 
01640     virtual bool HasBeenAttackedBy(gemActor* attacker);
01641 
01642     void Kill(gemActor* attacker)
01643     {
01644         DoDamage(attacker, psChar->GetHP());
01645     }
01646     void Defeat();
01647     void Resurrect();
01648 
01649     virtual bool UpdateDR();
01650     virtual void GetLastSuperclientPos(csVector3 &pos, InstanceID &instance, csTicks &last) const;
01651     virtual void SetLastSuperclientPos(const csVector3 &pos, InstanceID instance, const csTicks &now);
01652 
01653     virtual void BroadcastTargetStatDR(ClientConnectionSet* clients);
01654     virtual void SendTargetStatDR(Client* client);
01655     virtual void SendGroupStats();
01656 
01657     void SetAction(const char* anim,csTicks &timeDelay);
01658 
01659     virtual void Broadcast(int clientnum, bool control);
01660 
01669     virtual bool Send(int clientnum, bool control, bool to_superclients, psPersistAllEntities* allEntities=NULL);
01670 
01676     virtual void SendGroupMessage(MsgEntry* me);
01677 
01681     gemObject* FindNearbyActorName(const char* name);
01682 
01683     virtual void SendBehaviorMessage(const csString &str, gemObject* obj);
01684     virtual csString GetDefaultBehavior(const csString &dfltBehaviors);
01685 
01692     void FallBegan(const csVector3 &pos, iSector* sector);
01693 
01697     float FallEnded(const csVector3 &pos, iSector* sector);
01698 
01702     bool IsFalling()
01703     {
01704         return isFalling;
01705     }
01706 
01707     csTicks GetFallStartTime()
01708     {
01709         return fallStartTime;
01710     }
01711 
01712     bool AtRest() const
01713     {
01714         return atRest;
01715     }
01716 
01717     virtual bool GetVisibility()
01718     {
01719         return visible;
01720     }
01721     virtual void SetVisibility(bool visible);
01722     virtual bool SeesObject(gemObject* object, float range);
01723 
01724     virtual bool GetInvincibility()
01725     {
01726         return invincible;
01727     }
01728     virtual void SetInvincibility(bool invincible);
01729 
01733     bool GetViewAllObjects()
01734     {
01735         return viewAllObjects;
01736     }
01737     void SetViewAllObjects(bool v);
01738 
01739     void StopMoving(bool worldVel = false);
01740 
01751     bool MoveToSpawnPos(int32_t delay = 0, csString background = "", csVector2 point1 = 0, csVector2 point2 = 0, csString widget = "");
01752 
01764     bool GetSpawnPos(csVector3 &pos, float &yrot, iSector* &sector, bool useRange = false);
01765 
01771     bool MoveToValidPos(bool force = false);
01772 
01773     void GetValidPos(csVector3 &pos, float &yrot, iSector* &sector, InstanceID &instance);
01774 
01778     void GetLastLocation(csVector3 &pos, float &yrot, iSector* &sector, InstanceID &instance);
01779 
01783     void MoveToLastPos();
01784 
01786     void SetPrevTeleportLocation(const csVector3 &pos, float yrot, iSector* sector, InstanceID instance);
01788     void GetPrevTeleportLocation(csVector3 &pos, float &yrot, iSector* &sector, InstanceID &instance);
01789 
01790     AttackerHistory* GetDamageHistory(int pos) const
01791     {
01792         return dmgHistory.Get(pos);
01793     }
01794     size_t GetDamageHistoryCount() const
01795     {
01796         return dmgHistory.GetSize();
01797     }
01798     void ClearDamageHistory()
01799     {
01800         dmgHistory.Empty();
01801     }
01802 
01803     void AttachScript(ProgressionScript* script, int type);
01804     void DetachScript(ProgressionScript* script, int type);
01805     void InvokeAttackScripts(gemActor* defender, psItem* weapon);
01806     void InvokeDefenseScripts(gemActor* attacker, psItem* weapon);
01807     void InvokeNearlyDeadScripts(gemActor* defender, psItem* weapon);
01808     void InvokeMovementScripts();
01809 
01810     void AddActiveSpell(ActiveSpell* asp);
01811     void SendActiveSpells();
01812     bool RemoveActiveSpell(ActiveSpell* asp);
01813     ActiveSpell* FindActiveSpell(const csString &name, SPELL_TYPE type);
01814     int ActiveSpellCount(const csString &name);
01815     csArray<ActiveSpell*> &GetActiveSpells()
01816     {
01817         return activeSpells;
01818     }
01819     void CancelActiveSpellsForDeath();
01820     void CancelActiveSpellsWhichDamage();
01821     int FindAnimIndex(const char* name);
01822 
01823 
01832     void SetDefaults(bool player);
01833 
01834 
01838 
01839 
01840     bool nevertired;        
01841     bool infinitemana;      
01842     bool instantcast;       
01843     bool safefall;          
01844     bool questtester;       
01845     bool givekillexp;       
01846     bool attackable;        
01847 
01848 
01852     bool SetMesh(const char* meshname);
01853 
01854     bool GetFiniteInventory()
01855     {
01856         return GetCharacterData()->Inventory().GetDoRestrictions();
01857     }
01858     void SetFiniteInventory(bool v)
01859     {
01860         GetCharacterData()->Inventory().SetDoRestrictions(v);
01861     }
01862 
01863     // Target information
01864     void SetTargetObject(gemObject* object)
01865     {
01866         targetObject = object;
01867     }
01868     gemObject* GetTargetObject() const
01869     {
01870         return targetObject;
01871     }
01872 
01876     virtual float GetVelocity();
01877 
01883     virtual bool InsideGuardedArea(gemObject* object);
01884 
01888     uint32_t GetActiveMagicSequence()
01889     {
01890         activeMagic_seq++;
01891         return activeMagic_seq;
01892     }
01893 };
01894 
01895 //-----------------------------------------------------------------------------
01896 class NpcDialogMenu;
01897 
01898 class gemNPC : public gemActor
01899 {
01900 protected:
01901     psNPCDialog* npcdialog;
01902     AccountID superClientID;
01903     csWeakRef<gemObject>  target;
01904     csWeakRef<gemObject>  owner;
01905 
01906     csTicks nextVeryShortRangeAvail; 
01907     csTicks nextShortRangeAvail;     
01908     csTicks nextLongRangeAvail;      
01909 
01911     csArray<PID> lootablePlayers;
01912 
01913     struct DialogCounter
01914     {
01915         csString said;
01916         csString trigger;
01917         int      count;
01918         csTicks  when;
01919         static int Compare(DialogCounter* const &first,  DialogCounter* const &second)
01920         {
01921             if(first->count != second->count)
01922                 return first->count - second->count;
01923             return first->when - second->when;
01924 //            if (first.count != second.count)
01925 //                return first.count - second.count;
01926 //            return first.when - second.when;
01927         }
01928     };
01929 
01930     csPDelArray<DialogCounter> badText;
01931 
01932     unsigned default_attackid;          
01933 
01934     int speakers;
01935 
01936     bool busy; 
01937 
01938 public:
01939     gemNPC(GEMSupervisor* gemSupervisor,
01940            CacheManager* cachemanager,
01941            EntityManager* entityManager,
01942            psCharacter* chardata, const char* factname,
01943            InstanceID myInstance,iSector* room,const csVector3 &pos,float rotangle,int clientnum);
01944 
01945     virtual ~gemNPC();
01946 
01947     virtual void SetCombatStance(const Stance &stance);
01948     virtual void SetDefaultAttackID(unsigned id)
01949     {
01950         default_attackid = id;
01951     }
01952     virtual unsigned GetDefaultAttackID()
01953     {
01954         return default_attackid;
01955     }
01956 
01957     virtual const char* GetObjectType()
01958     {
01959         return "NPC";
01960     }
01961     virtual psNPCDialog* GetNPCDialogPtr()
01962     {
01963         return npcdialog;
01964     }
01965 
01966     virtual AccountID GetSuperclientID()
01967     {
01968         return superClientID;
01969     }
01970     virtual void SetSuperclientID(AccountID id)
01971     {
01972         superClientID = id;
01973     }
01974 
01975     void SetupDialog(PID npcID, PID masterNpcID, bool force=false);
01976     void ReactToPlayerApproach(psNPCCommandsMessage::PerceptionType type, gemActor* player);
01977 
01978     virtual void ApplyStaminaCalculations(const csVector3 &velocity, float times) { } // NPCs usually have 0 stamina.
01979     // Before this fix, this caused a major long term bug where NPCs would give up attacking after a few hits and expending all stamina.
01980 
01981     virtual void AddLootablePlayer(PID playerID);
01982     virtual void RemoveLootablePlayer(PID playerID);
01983     bool IsLootablePlayer(PID playerID);
01984     const csArray<PID> &GetLootablePlayers() const
01985     {
01986         return lootablePlayers;
01987     }
01988     virtual Client* GetRandomLootClient(int range);
01989 
02001     void Say(const char* sayText, Client* who, bool sayPublic, csTicks &timeDelay);
02002 
02018     void ActionCommand(bool actionMy, bool actionNarrate, const char* actText, Client* who, bool actionPublic, csTicks &timeDelay);
02019 
02020     void AddBadText(const char* playerSaid,const char* trigger);
02021     void GetBadText(size_t first,size_t last, csStringArray &saidArray, csStringArray &trigArray);
02022 
02031     virtual bool Send(int clientnum, bool control, bool to_superclients, psPersistAllEntities* allEntities=NULL);
02032 
02037     virtual void Broadcast(int clientnum, bool control);
02038 
02039     virtual void SendBehaviorMessage(const csString &str, gemObject* obj);
02040     virtual csString GetDefaultBehavior(const csString &dfltBehaviors);
02041     void ShowPopupMenu(Client* client);
02042 
02043     virtual void SetTarget(gemObject* newTarget)
02044     {
02045         target = newTarget;
02046     }
02047     virtual gemObject* GetTarget()
02048     {
02049         return this->target;
02050     }
02051 
02052     virtual void SetOwner(gemObject* owner);
02053 
02054     virtual gemObject* GetOwner()
02055     {
02056         return this->owner;
02057     }
02058 
02059     virtual void SetPosition(const csVector3 &pos, float angle, iSector* sector);
02060 
02061 
02070     virtual bool HasKillStealProtection()
02071     {
02072         return !GetCharacterData()->IsPet();
02073     }
02074 
02075     virtual void SendGroupStats();
02076     virtual void ForcePositionUpdate();
02077 
02081     void RegisterSpeaker(Client* client);
02082 
02086     void CheckSpeakers();
02087 
02094     void SetBusy(bool busy);
02095 
02102     bool IsBusy() const;
02103 };
02104 
02105 //-----------------------------------------------------------------------------
02106 
02107 class gemPet : public gemNPC
02108 {
02109 public:
02110 
02111     gemPet(GEMSupervisor* gemsupervisor,
02112            CacheManager* cachemanager,
02113            EntityManager* entitymanager,
02114            psCharacter* chardata, const char* factname, InstanceID instance, iSector* room,
02115            const csVector3 &pos,float rotangle,int clientnum,uint32 id) : gemNPC(gemsupervisor, cachemanager, entitymanager, chardata,factname,instance,room,pos,rotangle,clientnum)
02116     {
02117         this->persistanceLevel = "Temporary";
02118     };
02119 
02120     virtual const char* GetObjectType()
02121     {
02122         return "PET";
02123     }
02124 
02125 
02126     void SetPersistanceLevel(const char* level)
02127     {
02128         this->persistanceLevel = level;
02129     };
02130     const char* SetPersistanceLevel(void)
02131     {
02132         return persistanceLevel.GetData();
02133     };
02134     bool IsFamiliar(void)
02135     {
02136         return this->persistanceLevel.CompareNoCase("Permanent");
02137     };
02138 
02139 private:
02140     csString persistanceLevel;
02141 };
02142 
02143 //-----------------------------------------------------------------------------
02144 
02152 class psGEMEvent : public psGameEvent, public iDeleteObjectCallback
02153 {
02154 public:
02155     csWeakRef<gemObject> dependency;
02156 
02157     psGEMEvent(csTicks ticks,int offsetticks,gemObject* depends, const char* newType)
02158         : psGameEvent(ticks,offsetticks,newType)
02159     {
02160         dependency = NULL;
02161 
02162         // Register for disconnect events
02163         if(depends)
02164         {
02165             dependency = depends;
02166             depends->RegisterCallback(this);
02167         }
02168     }
02169 
02170     virtual ~psGEMEvent()
02171     {
02172         // If DeleteObjectCallback() has not been called normal operation
02173         // this object have to unregister to prevent the
02174         // object from calling DeleteObjectCallback() later when destroyed.
02175         if(dependency.IsValid())
02176         {
02177             dependency->UnregisterCallback(this);
02178             dependency = NULL;
02179         }
02180     }
02181 
02182     virtual void DeleteObjectCallback(iDeleteNotificationObject* object)
02183     {
02184         SetValid(false); // Prevent the Trigger from beeing called.
02185 
02186         if(dependency.IsValid())
02187         {
02188             dependency->UnregisterCallback(this);
02189             dependency = NULL;
02190         }
02191     }
02192 };
02193 
02194 //-----------------------------------------------------------------------------
02195 
02196 class psResurrectEvent : public psGameEvent // psGEMEvent
02197 {
02198 protected:
02199     csWeakRef<gemObject> who;
02200 
02201 public:
02202     psResurrectEvent(csTicks ticks,int offsetticks,gemActor* actor)
02203         : psGameEvent(ticks,offsetticks,"psResurrectEvent")
02204     {
02205         who = actor;
02206     }
02207 
02208     void Trigger()
02209     {
02210         if(who.IsValid())
02211         {
02212             gemActor* actor = dynamic_cast<gemActor*>((gemObject*) who);
02213             actor->Resurrect();
02214         }
02215     }
02216 };
02217 
02220 #endif