/* * pscharacter.h * * Copyright (C) 2001 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #ifndef __PSCHARACTER_H__ #define __PSCHARACTER_H__ #include #include #include "util/poolallocator.h" #include "util/slots.h" #include "pstrait.h" #include "psitemstats.h" #include "psskills.h" #include "psguildinfo.h" #include "psstdint.h" #include "util/psconst.h" #include "util/scriptvar.h" #include "psspell.h" #include "net/charmessages.h" #include "util/skillcache.h" #include "../icachedobject.h" #include "psinventorycachesvr.h" class psServerVitals; class MsgEntry; class psItemStats; class psItem; class psQuest; class psGuildInfo; struct Result; typedef struct { psItemStats * glyphType; int purifyStatus; /* possible values are: 0=not purified 1=purifying 2=purified */ int count; } glyphSlot_t; // used by psCharacter::CreateGlyphList() /** "Normalizes" name of character i.e. makes the first letter uppercase and all the rest downcase */ csString NormalizeCharacterName(const csString & name); //////////////////////////////////////////////////////////////////////////////// enum PSCHARACTER_GENDERRACE { PSCHARACTER_GENRACE_FXACHA = 0, PSCHARACTER_GENRACE_MXACHA = 1, PSCHARACTER_GENRACE_FYLIAN = 2, PSCHARACTER_GENRACE_MYLIAN = 3, PSCHARACTER_GENRACE_FNOLTHRIR = 4, PSCHARACTER_GENRACE_MNOLTHRIR = 5, PSCHARACTER_GENRACE_FDERMORIAN = 6, PSCHARACTER_GENRACE_MDERMORIAN = 7, PSCHARACTER_GENRACE_FSTONEBREAKER = 8, PSCHARACTER_GENRACE_MSTONEBREAKER = 9, PSCHARACTER_GENRACE_FHAMMERWIELDER = 10, PSCHARACTER_GENRACE_MHAMMERWIELDER = 11, PSCHARACTER_GENRACE_FLEMUR = 12, PSCHARACTER_GENRACE_MLEMUR = 13, PSCHARACTER_GENRACE_FDIABOLI = 14, PSCHARACTER_GENRACE_MDIABOLI = 15, PSCHARACTER_GENRACE_FENKIDUKAI = 16, PSCHARACTER_GENRACE_MENKIDUKAI = 17, PSCHARACTER_GENRACE_FKLYROS = 18, PSCHARACTER_GENRACE_MKLYROS = 19, PSCHARACTER_GENRACE_FYNNWN = 20, PSCHARACTER_GENRACE_MYNNWN = 21, PSCHARACTER_GENRACE_NKRAN = 22, // Oddball race - Nuetral/No gender PSCHARACTER_GENRACE_COUNT }; enum PSCHARACTER_TYPE { PSCHARACTER_TYPE_PLAYER = 0, PSCHARACTER_TYPE_NPC = 1, PSCHARACTER_TYPE_PET = 2, PSCHARACTER_TYPE_COUNT = 3, PSCHARACTER_TYPE_UNKNOWN = ~0 } ; #define PSCHARACTER_BULK_COUNT INVENTORY_BULK_COUNT #define PSCHARACTER_BANK_BULK_COUNT 16 /// Base class for several other classes which hold character attributes of different sorts class CharacterAttribute { protected: psCharacter *self; public: CharacterAttribute(psCharacter *character) : self(character) { } }; /** * Advantages/Disadvantages * * A character either has or does not have an advantage/disadvantage. Each advantage/disadvantage is numbered. * A series of bitfields are created to store the actual values. * */ enum PSCHARACTER_ADVANTAGE { PSCHARACTER_ADVANTAGE_6TH_SENSE = 0, PSCHARACTER_ADVANTAGE_HEART_OF_VENGEANCE, PSCHARACTER_DISADVANTAGE_BALDING, PSCHARACTER_DISADVANTAGE_DROPPED_ON_HEAD_AS_CHILD, // More to come PSCHARACTER_ADVANTAGE_COUNT }; #define PSCHARACTER_ADVANTAGE_32BIT_BITFIELDS (PSCHARACTER_ADVANTAGE_COUNT-1)/32+1 // Remember to update the translation table player_mode_to_str when // adding new modes. enum PSCHARACTER_MODE { PSCHARACTER_MODE_UNKNOWN = 0, PSCHARACTER_MODE_PEACE, PSCHARACTER_MODE_COMBAT, PSCHARACTER_MODE_SPELL_CASTING, PSCHARACTER_MODE_WORK, PSCHARACTER_MODE_DEAD, PSCHARACTER_MODE_SIT, PSCHARACTER_MODE_EXHAUSTED, PSCHARACTER_MODE_COUNT }; enum PSCHARACTER_STANCE { PSCHARACTER_STANCE_NONE = 0, PSCHARACTER_STANCE_FULL_DEFENSIVE, PSCHARACTER_STANCE_DEFENSIVE, PSCHARACTER_STANCE_NORMAL, PSCHARACTER_STANCE_AGGRESSIVE, PSCHARACTER_STANCE_BLOODY, PSCHARACTER_STANCE_COUNT }; enum PSCHARACTER_CUSTOM { PSCHARACTER_CUSTOM_EYES = 0, PSCHARACTER_CUSTOM_HAIR, PSCHARACTER_CUSTOM_BEARD, PSCHARACTER_CUSTOM_COLOUR, PSCHARACTER_CUSTOM_SKIN, PSCHARACTER_CUSTOM_COUNT }; typedef struct { unsigned int EquipmentFlags; csTicks NextSwingTime; psItem *item; psItem *default_if_empty; } EQUIPMENTDATA_TYPE; #define PSQUEST_DELETE 'D' #define PSQUEST_ASSIGNED 'A' #define PSQUEST_COMPLETE 'C' /** * This structure tracks assigned quests. */ struct QuestAssignment { /// Character id of player who assigned quest to this player. This is used to make sure you cannot get two quests from the same guy at the same time. int assigner_id; /// Weak pointer to the underlying quest relevant here csWeakRef quest; /// This status determines whether the quest was assigned, completed, or is marked for deletion. char status; /// Dirty flag determines minimal save on exit bool dirty; /// When a quest is completed, often it cannot immediately be repeated. This indicate the time when it can be started again. unsigned long lockout_end; }; /** * This enumeration and structure tracks * the players trade skill efforts */ enum PSCHARACTER_WORKSTATE { PSCHARACTER_WORKSTATE_HALTED = 0, PSCHARACTER_WORKSTATE_STARTED, PSCHARACTER_WORKSTATE_COMPLETE, PSCHARACTER_WORKSTATE_OVERDONE }; /// Set if this slot should continuously attack while in combat #define PSCHARACTER_EQUIPMENTFLAG_AUTOATTACK 0x00000001 /// Set if this slot can attack when the client specifically requests (and only when the client specifically requests) #define PSCHARACTER_EQUIPMENTFLAG_SINGLEATTACK 0x00000002 /// Set if this slot can attack even when empty - requires that a default psItem be set in default_if_empty #define PSCHARACTER_EQUIPMENTFLAG_ATTACKIFEMPTY 0x00000004 struct iDataBuffer; struct iPcCharacterData; // Dirty bits for STATDRDATA //#define PSCHARACTER_STATDRDATA_DIRTY_HITPOINTS 0x00000001 //#define PSCHARACTER_STATDRDATA_DIRTY_HITPOINTS_MAX 0x00000002 //#define PSCHARACTER_STATDRDATA_DIRTY_HITPOINTS_RATE 0x00000004 //#define PSCHARACTER_STATDRDATA_DIRTY_MANA 0x00000008 //#define PSCHARACTER_STATDRDATA_DIRTY_MANA_MAX 0x00000010 //#define PSCHARACTER_STATDRDATA_DIRTY_MANA_RATE 0x00000020 //#define PSCHARACTER_STATDRDATA_DIRTY_STAMINA 0x00000040 //#define PSCHARACTER_STATDRDATA_DIRTY_STAMINA_MAX 0x00000080 //#define PSCHARACTER_STATDRDATA_DIRTY_STAMINA_RATE 0x00000100 struct psRaceInfo; class psSectorInfo; class ExchangeManager; class MathScript; class NpcResponse; class gemActor; struct psGuildLevel; class psLootMessage; class psMerchantInfo; class psQuestListMessage; class psSpell; class psSpellCastGameEvent; class psTradeTransformations; class psTradeProcesses; class psTrainerInfo; struct psTrait; class psWorkGameEvent; //----------------------------------------------------------------------------- /** Contains information about what the character is currently working on. */ /* class WorkInformation { public: WorkInformation(); /// Reset the variables back to 0. void Reset(); public: /// The current item that is being used in the work. psItem* workItem; int patternId; int groupPatternId; float patternKFactor; }; */ //----------------------------------------------------------------------------- struct Buddy { csString name; unsigned int playerID; }; /** * A player's stat. Tracks the base value as well as any buffs accumlated on it. * The final rank should be calculated as rank+rankBuff */ struct CharStat { CharStat() { rank = rankBuff = 0; } unsigned int rank; // base rank without any buffs. int rankBuff; // additional buffs. }; class StatSet : public CharacterAttribute { protected: CharStat stats[PSITEMSTATS_STAT_COUNT]; public: StatSet(psCharacter *self) : CharacterAttribute(self) { Clear(); } void Clear() { for (int i=0; i0 if the item can be partially stacked */ int PutInBulk(psItem * & item, bool test=false, bool stack = true, int slot=ANY_BULK_SLOT); /** Get an item that is in the bulk inventory. * @param z The slot in which we want to retrive the item ( if any ). * @return The item in the given slot. NULL if no item was found. */ psItem* GetBulkItem(int z); /** Get an item that is in the equipment inventory. * @param z The slot in which we want to retrive the item ( if any ). * @return The item in the given slot. NULL if no item was found. */ psItem* GetEquipmentItem(int z); /** Put an item into an equipped container. * @param destEquipSlot The slot which has the container. * @param item The item we want to place into the container. * @return true if the item could be placed fully in the container. */ bool PutInEquipped(int destEquipSlot, psItem * item, bool test = false); /** Put an item into the equipment inventory. * @param destEquipSlot The slot in which we want to place an item. * @param item The item we want to place into the slot. * @return true if the item could be placed fully in the slot. */ bool EquipIn(int destEquipSlot, psItem * item, bool test = false); /** Remove an item from an equipment slot. * @param slot The slot where we want to remove the item from. * @return The item that was removed. */ psItem *RemoveEquipment(int slot); /** Remove an item from the bulk slots. * @param bulkSlot The slot we want to remove the item from. * @param count The number we want to take. -1 Means the entire stack. * @return pointer to the item that was removed. */ psItem *RemoveBulk(int bulkslot, int count = -1 ); /** Find the total stack count in inventory for a particular type of item. * @param item The base stats of the item we want to count. * @return the count of the total items matching the stats description. */ unsigned int TotalStackOfItem(psItemStats* item); /** Finds an item inside the bulk inventory. * @param itemID The UID of the item we are looking for. * @return The item if found, NULL otherwise. */ psItem * FindInBulk(uint32 itemID); /** Checks to see if anything in inventoy counts as the key for a lock. * @param lock The lock we want to try and open. * @return true if a key was found that can open the lock. */ bool HaveKeyForLock(uint32 lock); /** Check to see if a particular slot can be attacked. * @param slot The slot to query. * @return true if the slot can be attacked. */ bool Attackable(int slot); /** Query if a slot is auto attack. * @param slot The slot to query. * @return true if the slot can auto attack. */ bool AutoAttackable(int slot); /** Query a slot to see if it is single attackable. * @param slot The slot to query. * @param true if the slot is single attackable. */ bool SingleAttackable(int slot); /** Acquire a reference to the equipment object inside inventory. * This function does NOT do bounds checking so idx has to be in range. * @param idx The equipment slot we want the equipment structure for. * @return The equipment data structure. */ EQUIPMENTDATA_TYPE & GetEquipmentObject( int idx ); /** Find the equipment slot that a particular item is in. * @param item The item we want to know about. * @return The slot the item is located in. -1 if item not found. */ int FindItemInTopLevelEquipment(psItem *item); /** Find the bulk slot that a particular item is in. * @param item The item we want to know about. * @return The slot the item is located in. -1 if item not found. */ int FindItemInTopLevelBulk(psItem *item); /** Find the bulk slot that a particular item type is in. * @param stats The item stats we want to look for. * @return The slot the item is located in. -1 if no item with those stats found. */ int FindItemInTopLevelBulkWithStats(psItemStats *stats); /** Find the equipment slot that a particular item type is in. * @param stats The item stats we want to look for. * @return The slot the item is located in. -1 if no item with those stats found. */ int FindItemInTopLevelEquipmentWithStats(psItemStats *stats); /** Checks the equipment slot to see if it is a weapon. * An item is considered a weapon if: IsMeleeWeapon() || GetIsRangeWeapon() * @param slot The equipment slot to check weapon status. * @return a pointer to the item if it is a weapon. If no weapon found will use default fists. */ psItem *GetEffectiveWeaponInSlot(int slot); /** Gets the item in the slot. * @param slot The equipment slot to checks. * @return a pointer to the item if one is there. Uses base_cloths otherwise. */ psItem *GetEffectiveArmorInSlot(int slot); /** Iterates over the entire inventory to get a list of all the items from a particular category. * This is useful for npc merchants when you want to get a list of all the items they have. * @param category A pointer to the category that we want to match against. * @return The list of all items in category. */ csArray GetItemsInCategory(psItemCategory * category); /// Run the math scripts to calculate inventory max values. void CalculateStats(); /// Iterates over the equiped items running any scripts on them. void RunEquipScripts(); /// Contain error messge for last function failing. csString lastError; /// Recalculate total weight, bulk, and count of inventory items. (use when dealing with containers) void ReassessInventoryDimensions(); /// Changes this inventories handling of weight/capacity restrictions void SetDoRestrictions(bool v); /// Get the status of the weight/capacity restrictions bool GetDoRestrictions() { return doRestrictions; } /// Get the inventory cache handler psInventoryCacheServer * GetInventoryCacheServer (void) { return &inventoryCacheServer; } private: /** Places loaded items into the correct locations when loading from database. * @param location I=Inventory, E=Equipment, C=Container * @param slot Name where item should go. * @param item The item we are placing. * @return Item was placed correctly. */ bool PlaceLoadedItem(const char *location, const char *slot, psItem * & item); /// Add the weight, bulk, and count of this item to the totals. void AddDimensionsToInventory(psItem *item); /// Subtract the weight, bulk, and count of this item from the totals. void SubtractDimensionsFromInventory(psItem *item); psCharacter* owner; ///< Current owner of the inventory bool doRestrictions; ///< Do weight/capacity restrictions? bool loaded; ///< Has this inventory been fully loaded yet? EQUIPMENTDATA_TYPE equipment[PSCHARACTER_SLOT_COUNT]; ///< Items player is using in various slots psItem* bulk[PSCHARACTER_BULK_COUNT]; ///< Items player has in their 'backpack' float totalWeight; ///< Total Weight of all items being carried float totalSize; ///< Total size of all items being carried size_t totalCount; ///< Total count of all items being carried float maxWeight; ///< Max weight the inventory can hold float maxSize; ///< Max capacity in inventory psInventoryCacheServer inventoryCacheServer; ///< handle inventory cache }; //----------------------------------------------------------------------------- class psCharacter : public iScriptableVar, public iCachedObject { protected: psCharacterInventory inventory; ///< Character's inventory handler. psMoney money; ///< Current cash set on player. psGuildInfo* guildinfo; csArray spellList; csArray assigned_quests; StatSet attributes, modifiers; SkillSet skills; psSkillCache skillCache; bool LoadSpells(unsigned int use_id); bool LoadAdvantages(unsigned int use_id); bool LoadSkills(unsigned int use_id); bool LoadTraits(unsigned int use_id); bool LoadQuestAssignments(); bool LoadRelationshipInfo( unsigned int characterid ); bool LoadBuddies( Result& myBuddy, Result& buddyOf); bool LoadMarriageInfo( Result& result); bool LoadFamiliar( Result& pet, Result& owner); float override_max_hp,override_max_mana; // These values are loaded from base_hp_max,base_mana_max in the db and // should prevent normal HP calculations from taking place static const char *characterTypeName[]; unsigned int characterType; // Array of items waiting to be looted. csArray loot_pending; public: psCharacterInventory& Inventory() { return inventory; } psMoney Money() { return money; } void SetMoney(psMoney m); /** Add a money object to the current wallet. * This is used when money is picked up and will destory the object passed in. * @param moneyObject The money object that was just picked up. */ void SetMoney( psItem *& moneyObject ); void AdjustMoney(psMoney m); void SaveMoney(); void ResetStats(); // WorkInformation* workInfo; unsigned int characterid; unsigned int accountid; csString name; csString lastname; csString fullname; csString oldlastname; csString spouseName; bool isMarried; csArray buddyList; csArray buddyOfList; psRaceInfo *raceinfo; PSCHARACTER_MODE player_mode; static const char * player_mode_to_str[]; PSCHARACTER_STANCE combat_stance; csString faction_standings; csString progressionScript; int impervious_to_attack; float duel_points; /// Bitfield for which help events a character has already encountered. int help_event_flags; /// Checks the bit field for a bit flag from the enum in TutorialManager.h bool NeedsHelpEvent(int which) { return (help_event_flags & which)==0; } /// Sets a bit field complete for a specified flag from the enum in tutorialmanager.h void CompleteHelpEvent(int which) { help_event_flags |= which; } /// Set the active guild for the character. void SetGuild(psGuildInfo *g) { guildinfo = g; } /// Return the active guild, if any for this character. psGuildInfo *GetGuild() { return guildinfo; } /// Return the guild level for this character, if any. psGuildLevel *GetGuildLevel(); StatSet *GetAttributes() { return &attributes; } StatSet *GetModifiers() { return &modifiers; } SkillSet *GetSkills() { return &skills; } /** * Returns a pointer to the skill cache for this character */ psSkillCache *GetSkillCache() { return &skillCache; } // Set the active trade transformation for the character. // void SetTransformation(psTradeTransformations *t) { transformation = t; } // Return the active transformation, if any for this character. // psTradeTransformations *GetTransformation() { return transformation; } // Set the work transformation state for the character. void SetWorkState(PSCHARACTER_WORKSTATE state) { work_state = state; } // Return the work transformation state PSCHARACTER_WORKSTATE GetWorkState() { return work_state; } // Assign trade work event so it can be accessed void SetTradeWork(psWorkGameEvent * event); // // Stop trade events // void InterruptTradeWork(); // Return trade work event so it can be stopped psWorkGameEvent *GetTradeWork() { return workEvent; } // iCachedObject Functions below virtual void ProcessCacheTimeout() {}; /// required for iCachedObject but not used here virtual void *RecoverObject() { return this; } /// Turn iCachedObject ptr into psCharacter virtual void DeleteSelf() { delete this; } /// Delete must come from inside object to handle operator::delete overrides. struct st_bank { psItem *bulk[PSCHARACTER_BANK_BULK_COUNT]; psMoney money; } bank; struct st_location { psSectorInfo *loc_sector; float loc_x,loc_y,loc_z; float loc_yrot; } location; unsigned int advantage_bitfield[PSCHARACTER_ADVANTAGE_32BIT_BITFIELDS]; float situation_wum,effect_wum; float KFactor; psSpellCastGameEvent *spellCasting; // Hold a pointer to the game event // for the spell currently cast. psServerVitals* vitals; psTrait *traits[PSTRAIT_LOCATION_COUNT]; // NPC specific data. Should this go here? int npc_spawnruleid; int npc_masterid; /// Id of Loot category to use if this char has extra loot int loot_category_id; /// Amount of money ready to be looted int loot_money; csString animal_affinity; uint32_t owner_id; uint32_t familiar_id; public: psCharacter(); virtual ~psCharacter(); bool Load(iResultRow& row); /// Load the bare minimum to know what this character is looks like bool QuickLoad(iResultRow& row, bool noInventory); void AddSpell(psSpell * spell); bool Store(const char *location,const char *slot,psItem *what); void SetCharacterID(const unsigned int characterID) { characterid=characterID; } unsigned int GetCharacterID() { return characterid; } unsigned int GetMasterNPCID() { return npc_masterid?npc_masterid:characterid; } void SetAccount(int id) { accountid = id; } int GetAccount() { return accountid; } void SetName(const char* newName) { SetFullName(newName,lastname.GetData()); } void SetLastName(const char* newLastName) { SetFullName(name.GetData(),newLastName); } void SetFullName(const char* newFirstName, const char* newLastName); void SetOldLastName( const char* oldLastName ) { this->oldlastname = oldLastName; }; const char *GetCharName() { return name.GetData(); } const char *GetCharLastName() { return lastname.GetData(); } const char *GetCharFullName() { return fullname.GetData(); } const char *GetOldLastName() { return oldlastname.GetData(); } unsigned int GetCharType() { return characterType; } void SetCharType(unsigned int v) { CS_ASSERT(v < PSCHARACTER_TYPE_COUNT); characterType = v; } const char *GetCharTypeName() { return psCharacter::characterTypeName[ characterType ]; } void SetLastLoginTime( const char* last_login = NULL, bool save = true); csString GetLastLoginTime(); void SetSpouseName(const char* name); /** Gets Spouse Name of a character. * @return SpouseName or "" if not married. */ const char *GetSpouseName() { return spouseName.GetData(); } void SetIsMarried( bool married ) { isMarried = married; } bool GetIsMarried() { return isMarried; } void SetRaceInfo(psRaceInfo *rinfo); psRaceInfo *GetRaceInfo() { return raceinfo; } void RemoveBuddy( unsigned int buddyID ); bool AddBuddy( unsigned int buddyID, csString& name ); void BuddyOf( unsigned int buddyID ); void NotBuddyOf( unsigned int buddyID ); const char *GetFactionStandings() { return faction_standings; } void AppendProgressionScript(csString& script) { progressionScript.Append(script); } void SetLootCategory(int id) { loot_category_id = id; } int GetLootCategory() { return loot_category_id; } bool RemoveLootItem(int id); void AddInventoryToLoot(); void AddLootItem(psItemStats *item); void AddLootMoney(int money) { loot_money += money; } size_t GetLootItems(psLootMessage& msg,int entity,int cnum); int GetLootMoney() { return loot_money; } /// Clears the pending loot items array and money void ClearLoot(); QuestAssignment *IsQuestAssigned(int id); QuestAssignment *AssignQuest(psQuest *quest, int assigner_id); bool CompleteQuest(psQuest *quest); void DiscardQuest(QuestAssignment *q); /** * Sync dirty Quest Assignemnt to DB * * @param force_update Force every QuestAssignment to be dirty * @return True if succesfully updated DB. */ bool UpdateQuestAssignments(bool force_update = false); size_t GetAssignedQuests(psQuestListMessage& quests,int cnum); bool CheckQuestAssigned(psQuest *quest); bool CheckQuestCompleted(psQuest *quest); bool CheckQuestAvailable(psQuest *quest,int assigner_id); /** * Check if all prerequisites are valid for this response * for this character. * * @param resp The Response to check * @return True if all prerequisites are ok for the response */ bool CheckResponsePrerequisite(NpcResponse *resp); int NumberOfQuestsCompleted(csString category); void AddAdvantage( PSCHARACTER_ADVANTAGE advantage); void RemoveAdvantage( PSCHARACTER_ADVANTAGE advantage); bool HasAdvantage ( PSCHARACTER_ADVANTAGE advantage); void CombatDrain(int); float GetSituationWUM() { return situation_wum; } void SetSituationWUM(float wum) { situation_wum=wum; } float GetEffectWUM() { return effect_wum; } void SetEffectWUM(float wum) { effect_wum=wum; } int GetExperiencePoints(); // W void SetExperiencePoints(int W); int AddExperiencePoints(int W); unsigned int GetProgressionPoints(); // X void SetProgressionPoints(unsigned int X,bool save); void UseProgressionPoints(unsigned int X); void SetKFactor(float K) { KFactor = K; } float GetKFactor() { return KFactor; } void SetSpellCasting(psSpellCastGameEvent * event) { spellCasting = event; } bool IsSpellCasting() { return spellCasting != NULL; } void InterruptSpellCasting(); float GetPowerLevel(); /// Get spell casting power level float GetPowerLevel( PSSKILL skill ); // Get the maximum realm the caster can cast with given skill int GetMaxAllowedRealm( PSSKILL skill ); // Checks if this character has enough knowledge to cast spell // of given way and realm bool CheckMagicKnowledge( PSSKILL skill, int realm ); PSCHARACTER_MODE GetMode() { return player_mode; } const char* GetModeStr(); /// Return a string name of the mode void SetMode(PSCHARACTER_MODE newmode); bool MoveToInventory( psItem * & itemdata ); /** Drops an item into the world (one meter from this character's position) * @param Item to be dropped * @param Transient flag (decay?) (default=true) * @param Angle to be dropped at (default=random) */ void DropItem( psItem * & item, bool transient = true, float angle = -1 ); void CreateGlyphList(bool purifiedOnly, csArray & slots); bool HasGlyphs(const glyphList_t & glyphsToCheck); float AdjustHitPoints(float adjust); float AdjustHitPointsMax(float adjust); float AdjustHitPointsRate(float adjust); float GetHitPointsMax(); void SetHitPoints(float v); void SetHitPointsMax(float v); void SetHitPointsRate(float v); float AdjustMana(float adjust); float AdjustManaMax(float adjust); float AdjustManaRate(float adjust); float GetManaMax(); void SetMana(float v); void SetManaMax(float v); void SetManaRate(float v); float AdjustStamina(float adjust,bool pys); float AdjustStaminaMax(float adjust,bool pys); float AdjustStaminaRate(float adjust,bool pys); float GetStaminaMax(bool pys); void SetStaminaRegenerationNone(bool physical = true,bool mental = true); void SetStaminaRegenerationWalk(bool physical = true,bool mental = true); void SetStaminaRegenerationStill(bool physical = true,bool mental = true); void SetStaminaRegenerationWork(int skill); void CalculateMaxStamina(); void SetStamina(float v,bool pys); void SetStaminaMax(float v,bool pys); void SetStaminaRate(float v,bool pys); float GetHP(); float GetMana(); float GetStamina(bool pys); const char* GetHelmGroup() { return helmGroup.GetData(); } private: float AdjustVital( int vitalName, int dirtyFlag, float adjust); float SetVital( int vitalName, int dirtyFlag, float value); csString helmGroup; // Some races share helms so this tells which // group it's in. If empty assume in racial group. public: void RecalculateStats(); bool IsNPC() { return characterType == PSCHARACTER_TYPE_NPC; }; /// Used to determine if this NPC is a pet bool IsPet() { return characterType == PSCHARACTER_TYPE_PET; }; int GetFamiliarID() { return familiar_id; }; void SetFamiliarID(int v); const char *GetAnimalAffinity() { return animal_affinity.GetData(); }; void SetAnimialAffinity( const char* v ) { animal_affinity = v; }; int GetOwnerID() { return owner_id; }; void SetOwnerID(int v) { owner_id = v; }; bool UpdateStatDRData(csTicks now); bool GetStatDRData(MsgEntry * me, int flags); /** Returns true if the character is able to attack with the current slot. * This could be true even if the slot is empty (as in fists). * It could also be false due to effects or other properties. */ bool GetSlotAttackable(int slot); bool GetSlotAutoAttackable(int slot); bool GetSlotSingleAttackable(int slot); void NotifyAttackPerformed(int slot,csTicks timeofattack); csTicks GetSlotNextAttackTime(int slot); void SetCombatStance(PSCHARACTER_STANCE stance); PSCHARACTER_STANCE GetCombatStance() { return combat_stance; } /// Retrieves the calculated Attack Value for the given weapon-slot //float GetAttackValue(psItem *slotitem); //float GetAttackValueForWeaponInSlot(int slot); float GetTargetedBlockValueForWeaponInSlot(int slot); float GetUntargetedBlockValueForWeaponInSlot(int slot); float GetTotalTargetedBlockValue(); float GetTotalUntargetedBlockValue(); float GetCounterBlockValueForWeaponInSlot(int slot); float GetDodgeValue(); float GetAttackValueModifier(); float GetDefenseValueModifier(); void AdjustAttackValueModifier(float mul); void AdjustDefenseValueModifier(float mul); float GetMeleeDefensiveDamageModifier(); void AdjustMeleeDefensiveDamageModifier(float mul); /// Practice skills for armor and weapons void PracticeArmorSkills(unsigned int practice, int attackLocation); void PracticeWeaponSkills(unsigned int practice); void PracticeWeaponSkills(psItem * weapon, unsigned int practice); void SetTraitForLocation(PSTRAIT_LOCATION location,psTrait *trait); psTrait *GetTraitForLocation(PSTRAIT_LOCATION location); void GetLocationInWorld(psSectorInfo *§orinfo,float &loc_x,float &loc_y,float &loc_z,float &loc_yrot); void SetLocationInWorld(psSectorInfo *sectorinfo,float loc_x,float loc_y,float loc_z,float loc_yrot); void SaveLocationInWorld(); /// Construct an XML format string of the player's texture choices. void MakeTextureString( csString& textureString ); /// Construct an XML format string of the player's equipment. void MakeEquipmentString( csString& equipmentString ); /// Returns a level of character based on his 6 base stats. unsigned int GetCharLevel(); bool IsMerchant() { return (merchantInfo != NULL); } psMerchantInfo *GetMerchantInfo() { return merchantInfo; } bool IsTrainer() { return (trainerInfo != NULL); } psTrainerInfo *GetTrainerInfo() { return trainerInfo; } psCharacter *GetTrainer() { return trainer; } void SetTrainer(psCharacter *trainer) { this->trainer = trainer; } /** Figure out if this skill can be trained. * Checks the current knowledge of the skill. If it is already maxed out then * can train no more. * * @param skill The skill we want to train. * @return True if the skill still requires Y credits before it is fully trained. */ bool CanTrain( PSSKILL skill ); /** Trains a skill. * It will only train up to the cost of the next rank. So the yIncrease is * capped by the cost and anything over will be lost. * @param skill The skill we want to train. * @param yIncrease The amount we want to train this skill by. */ void Train( PSSKILL skill, int yIncrease ); /** Directly sets rank of given skill. It completely bypasses the skill logic, it is used for testing only. */ void SetSkillRank( PSSKILL which, int rank); psSpell * GetSpellByName(const csString& spellName); psSpell * GetSpellByIdx(int index); csString GetXMLSpellList(); csArray& GetSpellList() { return spellList; } typedef enum { NOT_TRADING, SELLING, BUYING} TradingStatus; psCharacter* GetMerchant() { return merchant; } TradingStatus GetTradingStatus() { return tradingStatus; } void SetTradingStatus(TradingStatus trading, psCharacter *merchant) { tradingStatus = trading; this->merchant = merchant; } gemActor *GetActor() { return actor; } void SetActor(gemActor *actor); bool SetTradingStopped(bool stopped); bool ReadyToExchange(); /// Number of seconds online this session in seconds. unsigned int GetOnlineTimeThisSession() { return (csGetTicks() - startTimeThisSession)/1000; } /// Number of seconds online ever including this session in seconds. unsigned int GetTotalOnlineTime() { return timeconnected + GetOnlineTimeThisSession(); } /// Total number of seconds online. Updated at logoff. unsigned int timeconnected; csTicks startTimeThisSession; unsigned int GetTimeConnected() { return timeconnected; } const char* GetDescription() { return description; } void SetDescription(const char* newValue) { description = newValue; } /// This is used by the math scripting engine to get various values. double GetProperty(const char *ptr); /// The exp to be handed out when this actor dies int GetKillExperience() { return kill_exp; } void SetKillExperience(int newValue) { kill_exp=newValue; } void SetImperviousToAttack(int newValue) { impervious_to_attack=newValue; } int GetImperviousToAttack() { return impervious_to_attack; } void CalculateEquipmentModifiers(); float GetStatModifier(PSITEMSTATS_STAT attrib); void AddGlyphInSlotList(psGlyph* glyph, csArray & slots); csString& GetLastError() { return lastError; } csString lastError; // State information for merchants csRef merchantInfo; bool tradingStopped; TradingStatus tradingStatus; psCharacter* merchant; // The merchant this charcter trade with gemActor * actor; // csRef trainerInfo; psCharacter* trainer; // psTradeTransformations * transformation; PSCHARACTER_WORKSTATE work_state; psWorkGameEvent * workEvent; //Player description csString description; /// Kill Exp int kill_exp; float attackValueModifier; //attack value is multiplied by this float defenseValueModifier; //defense value is multiplied by this float meleeDefensiveDamageModifier; //melee damage to this character is multiplied by this // The PowerLevel math script MathScript* powerScript, *maxRealmScript; // The stamina calc script MathScript* staminaCalc; protected: // String value copied from the database containing the last login time csString lastlogintime; public: // NPC based functions - should these go here? int NPC_GetSpawnRuleID() { return npc_spawnruleid; } void NPC_SetSpawnRuleID(int v) { npc_spawnruleid=v; } st_location spawn_loc; bool AppendCharacterSelectData(psAuthApprovedMessage& auth); /// The new operator is overriden to call PoolAllocator template functions void *operator new(size_t); /// The delete operator is overriden to call PoolAllocator template functions void operator delete(void *); private: /// Static reference to the pool for all psItem objects static PoolAllocator characterpool; public: bool loaded; }; #endif