Planeshift
|
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* §or); 00443 00447 void GetPosition(csVector3 &pos, iSector* §or); 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* §or, bool useRange = false); 01765 01771 bool MoveToValidPos(bool force = false); 01772 01773 void GetValidPos(csVector3 &pos, float &yrot, iSector* §or, InstanceID &instance); 01774 01778 void GetLastLocation(csVector3 &pos, float &yrot, iSector* §or, 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* §or, 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