server/src/game/Player.h
Schmoozerd ae7348f6b0 [12774] Merged cmangos last changes, special thanks for xfurry, Dramacydal, cala, Schmoozerd,
I'm not taking any credits of this commit.

Implement spell effects 62042, 62278 and 64767
Also limit the targets for 62577 and 62603
----------
Update git_id to reflect recent sql formatting changes
----------
Update to a safer code version and also add GO caster scenarios
----------
Allow aura 62038 to stack at every 3 seconds
----------
Improve handling of TargetMMGen
This will have impact on Chase and Follow Movement.
----------
* Refactor code to check if a new position is required for the MMGen into the new function RequiresNewPosition
* Refactor code to get the current targeted distance into function GetDynamicTargetDistance
* Change ChaseMMGen (angle = 0.0f case) chase to best contact point, not zero angle.

Thanks to Cala and X-Savior for testing. Special thanks to cala for also suggesting improved values for the magic numbers
----------
Improve ObjectPosSelector
Now a spot already occupied by the searcher will be prefered
----------
Get rid of bounding radius in GetNearPoint[2D] and ObjectPosSelector
----------
This changes how ObjectPosSelector is used.
It changes the way how the functions Object::GetNearPoint and Object::GetNearPoint2d behave.
----------
So you need to check all places where these functions are used if they are still used correctly.
----------
Especially check your scripts!
----------
Remove not required duplicate indexes
----------
Implement TARGET_92 as TARGET_SUMMONER
This target is used only as TargetA and the related spells are used only by temporary summoned creatures
----------
Implement some spell effects used by Hodir in Ulduar
Dummy spells 62797, 63499, 63545 and 64543
Periodic dummy auras: 61968, 62038, 62039 and 65272
Limit targets for spells: 62797, 63545, 64543, 62476 and 62477
----------
Implement some spells used at Algalon encounter
Spell aura entries 64345, 62018 and 64412
Positive target exception for spell 64996
Aura stacking exception for spells 62169, 62168, 65250 and 64417
----------
Implement effect for spell 63633
----------
EventAI - Ingame output of script state
----------
With this the command .npc aiinfo will give more output about the current state.
Remark that this output is only given if the LogFilter for EventAIDev mode is disabled
----------
FindGit.cmake already ships with CMake
No reason for us to ship it too. Also, we had an outdated version which
had not been used anyway, because we set the include path in such a way,
that the CMake delivered version is always found first.
----------
FindOpenSSL.cmake already ships with CMake
No reason for us to ship it too. Also, we had an outdated version which
had not been used anyway, because we set the include path in such a way,
that the CMake delivered version is always found first.
----------
EventAI - Add more developing error output
----------
Fix some target-type handling for EventAI
Also increase log-output for bad target-types
----------
Fix crash due to bad compiler (author Xfurry)
----------
Add special condition id for Ulduar
Will be used to check the availability of the siege vehicles for players
----------
Update spells 62374 and 62907
* limit spell targets of spell 62374
* implement spell effect for spell 62907
----------
Remove effect for spell 64503
Will be handled in script library. For details please check 8502cdfa64
----------
Implement spells 64489 and 64673
Both are used by Auriaya (Ulduar)
----------
Implement some spells for Ignis the Furnace Master
Spell entries: 62717, 62381, 62488, 62707, 64475 and 64503
----------
Implement spells 61187 and 61190
----------
CMake: generic way to build a script library
Added new parameter INCLUDE_BINDINGS_DIR which can be set to the name of a
folder inside src/bindings/.

Includes the script library in src/bindings/ with the defined name.
The name must correspond to the name of the folder and the folder must contain
a valid CMakeLists.txt

Note: if you currently use a script library, you will probably get a merge
problem on src/bindings/CMakeLists.txt as you will have modified this file
manually. Please use the new version of this file and rerun CMake once with the
parameter -DINCLUDE_BINDINGS_DIR=ScriptDev2 (if you are not using SD2 but
another script library, replace ScriptDev2 with the name of the folder in
src/bindings/).

If you do not use a script library you should not have any merge problems
and you don't need to do anything.
----------
Add CMake source groups to target 'game'
This is the exact same grouping as it is currently in the VC 2012 files.
These groupings will have to be refactored at some point as they are not
very logical.
----------
Add CMake source groups to target 'framework'
This is the exact same grouping as it is currently in the VC 2012 files.
This is part of cmangos/issues#67
----------
Add CMake source groups to target 'shared'
This is the exact same grouping as it is currently in the VC 2012 files.
----------
Add new parameter 'expansion' to command 'account create'
----------
Update some Sunwell Plateau spells

Limit targets and allow positive effect for spell 46650
Implement effect for spells 46289 and 46637
Remove effect for spell 44845 - will be handled in script library
----------
Implement some custom use for Effect Activate Object spells
This will fix the summoning events for the Wind Stones, Ice Stones, Skettis bosses and quest 11865
----------
Sync mangos.sql with other versions
----------
Redump sql databases to unify formatting
The main reason for this was because classic/cata has updated the sql formatting and manually syncing would be a pain so redumping from master->tbc->classic->cata is easier.

Only the formatting was changed. The values were not changed at all.

mysqldump was used however manual modifications had to be done.

Dump the database:
C:/mysql/bin/mysqldump.exe mangos > sql/mangos.sql

Split insert values into multiple rows:
Replace "),(" with "),\n("
Replace "VALUES (" with "VALUES\n("

Remove the character sets by replacing them with an empty string

Custom formatting of mangos.sql:
Move db_version to the very top
Create all dbscripts_on_* tables based on dbscripts_on_creature_movement
Preserve our custom insert formatting of spell_affect (tbc/classic), spell_bonus_data, spell_chain, spell_elixir, spell_proc_event, spell_proc_item_enchant, spell_template, spell_threat
Remove autoincrement values from insert values of pet_name_generation and remove AUTO_INCREMENT=261 value from its table structure

Custom formatting of characters.sql:
Move character_db_version to the very top

Custom formatting of realmd.sql:
Move realmd_db_version to the very top
----------
Immediately remove corpses when ForcedDespawn is used
Thanks to Neotmiren for pointing, special thanks to cala for testing!
----------
Fix use of config values related to quest-status and level
This fixes use of negative value in config values Quests.LowLevelHideDiff and Quests.HighLevelHideDiff
Also add some documentation around the related code
Thanks to Neotmiren for pointing and to cala for testing.
----------
Loot-System: Fix reference loading check
This fixes a false error output for loot references that are only used with spell loot.
Thanks to X-Savior for properly reporting both error messages and use case
----------
Add missing spell 61437 to playercreate spells for bloodelves
Thanks to NeatElves for porting from TC and pointing to this
----------
Fix load bar step for alendarMgr::LoadCalendarsFromDB
----------
Cody Style Improvements
Also remove an unused variable (thanks to Den for this!)
----------
Implement the spells used in the Chess Event encounter
Combat spell entries: 37775, 37824, 39338, 39342, 39341, 39344, 45260
Melee spells: 37142, 37143, 37147, 37149, 37150, 37220, 37227, 37228, 37337, 37339, 37345, 37348
Chess movement spells: 30012, 32312, 37388, 30284, 37144, 37146, 37148, 37151, 37152, 37153
Aura stacking exception: 32261 and 39400
----------
And more hotfixes with these format strings
----------
Hotfix to recent text loading functions
----------
Use possible changed model names with vmap extraction
----------
Fix some warnings
----------
Store how many texts are loaded for validity checks. Use this with EventAI
----------
EventAI: Use generic DoDisplayText and loading of additional text data
----------
Add generic DoDisplayText function and use additional data of dbscripts table
----------
Add const-correctness to Text related functions
----------
Add database changes to support more data for DB Script texts
----------
Add stacking exception for spells 39993 and 40041
----------
Allow spell effect 86 - Activate Object to use the misc value
----------
Allow player pets to swim
----------
Enable resummoning of warlock pets
----------
Do not remove FLY auras on Evade
Also consider npcs which have SPELL_AURA_FLY as being able to fly
----------
EventAI: Improve code
* Drop rather pointless bool to check if the number of assigned events is empty
* Before the phase was resetted on death if and only if the npc has Events defined
* DoMeleeAttackIfReady could have been called even though combat state could have changed while processing events
----------
EventAI: Implement ACTION_T_SET_THROW_MASK (46)
This Action can be used to set which AIEvents should be thrown automatically, if you need more flexibility, you can always use the manual ACTION_TH_THROW_AI_EVENT version.
* Also clean some error-log output a bit.
----------
Forward original caster GUID to script library
----------
Fixup commit 12511 Thanks to Zakamurite for pointing
Also thanks to him for giving a helping hand in correcting the commit
----------
Implement some spells for Felmyst encounter
Spell entries: 45714, 45717 and 45918. Limit targets of spell 45391
Also add stacking exception for auras 45068 and 45582
----------
Fix invisible spirit healers & such on death near them
This fixes an issue that occurs if you die close to a spirit healer/guide.
----------
Fix take ammo for most ranged spells
Fix spells like Arcane Shot not taking ammo while they should
----------
Check cast spell 51690
----------
Fix SpellDamage modifier of SPELL_AURA_MOD_DAMAGE_DONE_CREATURE
This aura modifies a flat value, not a percent value.
----------
Implement proc effect of spells 67712, 67758
related to items 47316, 47477.
----------
Improve proc of spell 50421
----------
Add and implement server-side spell 23770
----------
EventAI: Improve TargetSelection related ErrorLog output
----------
DBScripts Engine: Change behaviour to search for a different npc when using buddy-search
With this an npc buddy will be interpreted as "another npc with entry"
Also toggle command 31 - TERMINATE_SCRIPT to also look only for other npcs of entry
----------
DBScripts Engine: Allow pets as buddy
Add new flag SCRIPT_FLAG_BUDDY_IS_PET (0x20) that will search not for a normal npc with buddy-search, but also for pets
----------
DBScripts Engine: Support buddy search by guid
* Add new `data_flags` flag SCRIPT_FLAG_BUDDY_BY_GUID (0x10)
If this flag is set, the content of `search_distance` is interpreted as db-guid of the requested buddy
* Also switch most error log output to DB-error log output (though this will include false positives)
----------
2020-02-17 09:20:48 +00:00

2694 lines
118 KiB
C++

/**
* This code is part of MaNGOS. Contributor & Copyright details are in AUTHORS/THANKS.
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 _PLAYER_H
#define _PLAYER_H
#include "Common.h"
#include "ItemPrototype.h"
#include "Unit.h"
#include "Item.h"
#include "Database/DatabaseEnv.h"
#include "NPCHandler.h"
#include "QuestDef.h"
#include "Group.h"
#include "Bag.h"
#include "WorldSession.h"
#include "Pet.h"
#include "MapReference.h"
#include "Util.h" // for Tokens typedef
#include "AchievementMgr.h"
#include "ReputationMgr.h"
#include "BattleGround/BattleGround.h"
#include "SharedDefines.h"
#include<string>
#include<vector>
struct Mail;
class Channel;
class DynamicObject;
class Creature;
class PlayerMenu;
class Transport;
class UpdateMask;
class SpellCastTargets;
class PlayerSocial;
class DungeonPersistentState;
class Spell;
class Item;
struct AreaTrigger;
typedef std::deque<Mail*> PlayerMails;
#define PLAYER_MAX_SKILLS 128
#define PLAYER_MAX_DAILY_QUESTS 25
#define PLAYER_EXPLORED_ZONES_SIZE 156
// 2^n internal values, they are never sent to the client
enum PlayerUnderwaterState
{
UNDERWATER_NONE = 0x00,
UNDERWATER_INWATER = 0x01, // terrain type is water and player is afflicted by it
UNDERWATER_INLAVA = 0x02, // terrain type is lava and player is afflicted by it
UNDERWATER_INSLIME = 0x04, // terrain type is lava and player is afflicted by it
UNDERWATER_INDARKWATER = 0x08, // terrain type is dark water and player is afflicted by it
UNDERWATER_EXIST_TIMERS = 0x10
};
enum BuyBankSlotResult
{
ERR_BANKSLOT_FAILED_TOO_MANY = 0,
ERR_BANKSLOT_INSUFFICIENT_FUNDS = 1,
ERR_BANKSLOT_NOTBANKER = 2,
ERR_BANKSLOT_OK = 3
};
enum PlayerCurrencyFlag
{
PLAYERCURRENCY_FLAG_NONE = 0x0,
PLAYERCURRENCY_FLAG_UNK1 = 0x1, // unused?
PLAYERCURRENCY_FLAG_UNK2 = 0x2, // unused?
PLAYERCURRENCY_FLAG_SHOW_IN_BACKPACK = 0x4,
PLAYERCURRENCY_FLAG_UNUSED = 0x8,
PLAYERCURRENCY_MASK_USED_BY_CLIENT =
PLAYERCURRENCY_FLAG_SHOW_IN_BACKPACK |
PLAYERCURRENCY_FLAG_UNUSED,
};
enum PlayerCurrencyState
{
PLAYERCURRENCY_UNCHANGED = 0,
PLAYERCURRENCY_CHANGED = 1,
PLAYERCURRENCY_NEW = 2,
PLAYERCURRENCY_REMOVED = 3
};
struct PlayerCurrency
{
PlayerCurrencyState state;
uint32 totalCount;
uint32 weekCount;
uint32 seasonCount;
uint8 flags;
CurrencyTypesEntry const * currencyEntry;
};
enum PlayerSpellState
{
PLAYERSPELL_UNCHANGED = 0,
PLAYERSPELL_CHANGED = 1,
PLAYERSPELL_NEW = 2,
PLAYERSPELL_REMOVED = 3
};
struct PlayerSpell
{
PlayerSpellState state : 8;
bool active : 1; // show in spellbook
bool dependent : 1; // learned as result another spell learn, skill grow, quest reward, etc
bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks
};
struct PlayerTalent
{
TalentEntry const* talentEntry;
uint32 currentRank;
PlayerSpellState state;
};
typedef UNORDERED_MAP<uint32, PlayerCurrency> PlayerCurrenciesMap;
typedef UNORDERED_MAP<uint32, PlayerSpell> PlayerSpellMap;
typedef UNORDERED_MAP<uint32, PlayerTalent> PlayerTalentMap;
struct SpellCooldown
{
time_t end;
uint16 itemid;
};
typedef std::map<uint32, SpellCooldown> SpellCooldowns;
enum TrainerSpellState
{
TRAINER_SPELL_GRAY = 0,
TRAINER_SPELL_GREEN = 1,
TRAINER_SPELL_RED = 2,
TRAINER_SPELL_GREEN_DISABLED = 10 // custom value, not send to client: formally green but learn not allowed
};
enum ActionButtonUpdateState
{
ACTIONBUTTON_UNCHANGED = 0,
ACTIONBUTTON_CHANGED = 1,
ACTIONBUTTON_NEW = 2,
ACTIONBUTTON_DELETED = 3
};
enum ActionButtonType
{
ACTION_BUTTON_SPELL = 0x00,
ACTION_BUTTON_C = 0x01, // click?
ACTION_BUTTON_EQSET = 0x20,
ACTION_BUTTON_EXPANDABLE = 0x30,
ACTION_BUTTON_MACRO = 0x40,
ACTION_BUTTON_CMACRO = ACTION_BUTTON_C | ACTION_BUTTON_MACRO,
ACTION_BUTTON_ITEM = 0x80
};
#define ACTION_BUTTON_ACTION(X) (uint32(X) & 0x00FFFFFF)
#define ACTION_BUTTON_TYPE(X) ((uint32(X) & 0xFF000000) >> 24)
#define MAX_ACTION_BUTTON_ACTION_VALUE (0x00FFFFFF+1)
struct ActionButton
{
ActionButton() : packedData(0), uState(ACTIONBUTTON_NEW) {}
uint32 packedData;
ActionButtonUpdateState uState;
// helpers
ActionButtonType GetType() const { return ActionButtonType(ACTION_BUTTON_TYPE(packedData)); }
uint32 GetAction() const { return ACTION_BUTTON_ACTION(packedData); }
void SetActionAndType(uint32 action, ActionButtonType type)
{
uint32 newData = action | (uint32(type) << 24);
if (newData != packedData || uState == ACTIONBUTTON_DELETED)
{
packedData = newData;
if (uState != ACTIONBUTTON_NEW)
uState = ACTIONBUTTON_CHANGED;
}
}
};
// some action button indexes used in code or clarify structure
enum ActionButtonIndex
{
ACTION_BUTTON_SHAMAN_TOTEMS_BAR = 132,
};
#define MAX_ACTION_BUTTONS 144 // checked in 3.2.0
typedef std::map<uint8, ActionButton> ActionButtonList;
enum GlyphUpdateState
{
GLYPH_UNCHANGED = 0,
GLYPH_CHANGED = 1,
GLYPH_NEW = 2,
GLYPH_DELETED = 3
};
struct Glyph
{
uint32 id;
GlyphUpdateState uState;
Glyph() : id(0), uState(GLYPH_UNCHANGED) { }
uint32 GetId() { return id; }
void SetId(uint32 newId)
{
if (newId == id)
return;
if (id == 0 && uState == GLYPH_UNCHANGED) // not exist yet in db and already saved
{
uState = GLYPH_NEW;
}
else if (newId == 0)
{
if (uState == GLYPH_NEW) // delete before add new -> no change
uState = GLYPH_UNCHANGED;
else // delete existing data
uState = GLYPH_DELETED;
}
else if (uState != GLYPH_NEW) // if not new data, change current data
{
uState = GLYPH_CHANGED;
}
id = newId;
}
};
struct PlayerCreateInfoItem
{
PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) {}
uint32 item_id;
uint32 item_amount;
};
typedef std::list<PlayerCreateInfoItem> PlayerCreateInfoItems;
struct PlayerLevelInfo
{
PlayerLevelInfo() { for (int i = 0; i < MAX_STATS; ++i) stats[i] = 0; }
uint8 stats[MAX_STATS];
};
typedef std::list<uint32> PlayerCreateInfoSpells;
struct PlayerCreateInfoAction
{
PlayerCreateInfoAction() : button(0), type(0), action(0) {}
PlayerCreateInfoAction(uint8 _button, uint32 _action, uint8 _type) : button(_button), type(_type), action(_action) {}
uint8 button;
uint8 type;
uint32 action;
};
typedef std::list<PlayerCreateInfoAction> PlayerCreateInfoActions;
struct PlayerInfo
{
// existence checked by displayId != 0 // existence checked by displayId != 0
PlayerInfo() : displayId_m(0), displayId_f(0), levelInfo(NULL)
{
}
uint32 mapId;
uint32 areaId;
float positionX;
float positionY;
float positionZ;
float orientation;
uint16 phaseMap;
uint16 displayId_m;
uint16 displayId_f;
PlayerCreateInfoItems item;
PlayerCreateInfoSpells spell;
PlayerCreateInfoActions action;
PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1
};
struct PvPInfo
{
PvPInfo() : inHostileArea(false), endTimer(0) {}
bool inHostileArea;
time_t endTimer;
};
struct DuelInfo
{
DuelInfo() : initiator(NULL), opponent(NULL), startTimer(0), startTime(0), outOfBound(0) {}
Player* initiator;
Player* opponent;
time_t startTimer;
time_t startTime;
time_t outOfBound;
};
struct Areas
{
uint32 areaID;
uint32 areaFlag;
float x1;
float x2;
float y1;
float y2;
};
#define MAX_RUNES 6
#define RUNE_COOLDOWN (2*5*IN_MILLISECONDS) // msec
enum RuneType
{
RUNE_BLOOD = 0,
RUNE_UNHOLY = 1,
RUNE_FROST = 2,
RUNE_DEATH = 3,
NUM_RUNE_TYPES = 4
};
struct RuneInfo
{
uint8 BaseRune;
uint8 CurrentRune;
uint16 Cooldown; // msec
};
struct Runes
{
RuneInfo runes[MAX_RUNES];
uint8 runeState; // mask of available runes
void SetRuneState(uint8 index, bool set = true)
{
if (set)
runeState |= (1 << index); // usable
else
runeState &= ~(1 << index); // on cooldown
}
};
struct EnchantDuration
{
EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) {};
EnchantDuration(Item* _item, EnchantmentSlot _slot, uint32 _leftduration) : item(_item), slot(_slot), leftduration(_leftduration) { MANGOS_ASSERT(item); };
Item* item;
EnchantmentSlot slot;
uint32 leftduration;
};
typedef std::list<EnchantDuration> EnchantDurationList;
typedef std::list<Item*> ItemDurationList;
enum LfgRoles
{
LEADER = 0x01,
TANK = 0x02,
HEALER = 0x04,
DAMAGE = 0x08
};
enum RaidGroupError
{
ERR_RAID_GROUP_NONE = 0,
ERR_RAID_GROUP_LOWLEVEL = 1,
ERR_RAID_GROUP_ONLY = 2,
ERR_RAID_GROUP_FULL = 3,
ERR_RAID_GROUP_REQUIREMENTS_UNMATCH = 4
};
enum DrunkenState
{
DRUNKEN_SOBER = 0,
DRUNKEN_TIPSY = 1,
DRUNKEN_DRUNK = 2,
DRUNKEN_SMASHED = 3
};
#define MAX_DRUNKEN 4
enum PlayerFlags
{
PLAYER_FLAGS_NONE = 0x00000000,
PLAYER_FLAGS_GROUP_LEADER = 0x00000001,
PLAYER_FLAGS_AFK = 0x00000002,
PLAYER_FLAGS_DND = 0x00000004,
PLAYER_FLAGS_GM = 0x00000008,
PLAYER_FLAGS_GHOST = 0x00000010,
PLAYER_FLAGS_RESTING = 0x00000020,
PLAYER_FLAGS_UNK7 = 0x00000040, // admin?
PLAYER_FLAGS_UNK8 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state
PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards
PLAYER_FLAGS_IN_PVP = 0x00000200,
PLAYER_FLAGS_HIDE_HELM = 0x00000400,
PLAYER_FLAGS_HIDE_CLOAK = 0x00000800,
PLAYER_FLAGS_PARTIAL_PLAY_TIME = 0x00001000, // played long time
PLAYER_FLAGS_NO_PLAY_TIME = 0x00002000, // played too long time
PLAYER_FLAGS_IS_OUT_OF_BOUNDS = 0x00004000, // Lua_IsOutOfBounds
PLAYER_FLAGS_DEVELOPER = 0x00008000, // <Dev> chat tag, name prefix
PLAYER_FLAGS_ENABLE_LOW_LEVEL_RAID = 0x00010000, // triggers lua event EVENT_ENABLE_LOW_LEVEL_RAID
PLAYER_FLAGS_TAXI_BENCHMARK = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
PLAYER_FLAGS_COMMENTATOR = 0x00080000,
PLAYER_FLAGS_UNK21 = 0x00100000,
PLAYER_FLAGS_UNK22 = 0x00200000,
PLAYER_FLAGS_COMMENTATOR_UBER = 0x00400000, // something like COMMENTATOR_CAN_USE_INSTANCE_COMMAND
PLAYER_FLAGS_UNK24 = 0x00800000, // EVENT_SPELL_UPDATE_USABLE and EVENT_UPDATE_SHAPESHIFT_USABLE, disabled all abilitys on tab except autoattack
PLAYER_FLAGS_UNK25 = 0x01000000, // EVENT_SPELL_UPDATE_USABLE and EVENT_UPDATE_SHAPESHIFT_USABLE, disabled all melee ability on tab include autoattack
PLAYER_FLAGS_XP_USER_DISABLED = 0x02000000,
PLAYER_FLAGS_UNK27 = 0x04000000,
PLAYER_FLAGS_AUTO_DECLINE_GUILDS = 0x08000000, // Automatically declines guild invites
PLAYER_FLAGS_GUILD_LEVELING_ENABLED = 0x10000000, // Lua_GetGuildLevelEnabled() - enables guild leveling related UI
PLAYER_FLAGS_VOID_STORAGE_UNLOCKED = 0x20000000, // unlocks void storage
PLAYER_FLAGS_UNK30 = 0x40000000,
PLAYER_FLAGS_UNK31 = 0x80000000,
};
// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
// can't use enum for uint64 values
#define PLAYER_TITLE_DISABLED UI64LIT(0x0000000000000000)
#define PLAYER_TITLE_NONE UI64LIT(0x0000000000000001)
#define PLAYER_TITLE_PRIVATE UI64LIT(0x0000000000000002) // 1
#define PLAYER_TITLE_CORPORAL UI64LIT(0x0000000000000004) // 2
#define PLAYER_TITLE_SERGEANT_A UI64LIT(0x0000000000000008) // 3
#define PLAYER_TITLE_MASTER_SERGEANT UI64LIT(0x0000000000000010) // 4
#define PLAYER_TITLE_SERGEANT_MAJOR UI64LIT(0x0000000000000020) // 5
#define PLAYER_TITLE_KNIGHT UI64LIT(0x0000000000000040) // 6
#define PLAYER_TITLE_KNIGHT_LIEUTENANT UI64LIT(0x0000000000000080) // 7
#define PLAYER_TITLE_KNIGHT_CAPTAIN UI64LIT(0x0000000000000100) // 8
#define PLAYER_TITLE_KNIGHT_CHAMPION UI64LIT(0x0000000000000200) // 9
#define PLAYER_TITLE_LIEUTENANT_COMMANDER UI64LIT(0x0000000000000400) // 10
#define PLAYER_TITLE_COMMANDER UI64LIT(0x0000000000000800) // 11
#define PLAYER_TITLE_MARSHAL UI64LIT(0x0000000000001000) // 12
#define PLAYER_TITLE_FIELD_MARSHAL UI64LIT(0x0000000000002000) // 13
#define PLAYER_TITLE_GRAND_MARSHAL UI64LIT(0x0000000000004000) // 14
#define PLAYER_TITLE_SCOUT UI64LIT(0x0000000000008000) // 15
#define PLAYER_TITLE_GRUNT UI64LIT(0x0000000000010000) // 16
#define PLAYER_TITLE_SERGEANT_H UI64LIT(0x0000000000020000) // 17
#define PLAYER_TITLE_SENIOR_SERGEANT UI64LIT(0x0000000000040000) // 18
#define PLAYER_TITLE_FIRST_SERGEANT UI64LIT(0x0000000000080000) // 19
#define PLAYER_TITLE_STONE_GUARD UI64LIT(0x0000000000100000) // 20
#define PLAYER_TITLE_BLOOD_GUARD UI64LIT(0x0000000000200000) // 21
#define PLAYER_TITLE_LEGIONNAIRE UI64LIT(0x0000000000400000) // 22
#define PLAYER_TITLE_CENTURION UI64LIT(0x0000000000800000) // 23
#define PLAYER_TITLE_CHAMPION UI64LIT(0x0000000001000000) // 24
#define PLAYER_TITLE_LIEUTENANT_GENERAL UI64LIT(0x0000000002000000) // 25
#define PLAYER_TITLE_GENERAL UI64LIT(0x0000000004000000) // 26
#define PLAYER_TITLE_WARLORD UI64LIT(0x0000000008000000) // 27
#define PLAYER_TITLE_HIGH_WARLORD UI64LIT(0x0000000010000000) // 28
#define PLAYER_TITLE_GLADIATOR UI64LIT(0x0000000020000000) // 29
#define PLAYER_TITLE_DUELIST UI64LIT(0x0000000040000000) // 30
#define PLAYER_TITLE_RIVAL UI64LIT(0x0000000080000000) // 31
#define PLAYER_TITLE_CHALLENGER UI64LIT(0x0000000100000000) // 32
#define PLAYER_TITLE_SCARAB_LORD UI64LIT(0x0000000200000000) // 33
#define PLAYER_TITLE_CONQUEROR UI64LIT(0x0000000400000000) // 34
#define PLAYER_TITLE_JUSTICAR UI64LIT(0x0000000800000000) // 35
#define PLAYER_TITLE_CHAMPION_OF_THE_NAARU UI64LIT(0x0000001000000000) // 36
#define PLAYER_TITLE_MERCILESS_GLADIATOR UI64LIT(0x0000002000000000) // 37
#define PLAYER_TITLE_OF_THE_SHATTERED_SUN UI64LIT(0x0000004000000000) // 38
#define PLAYER_TITLE_HAND_OF_ADAL UI64LIT(0x0000008000000000) // 39
#define PLAYER_TITLE_VENGEFUL_GLADIATOR UI64LIT(0x0000010000000000) // 40
#define KNOWN_TITLES_SIZE 4
#define MAX_TITLE_INDEX (KNOWN_TITLES_SIZE*64) // 3 uint64 fields
// used in (PLAYER_FIELD_BYTES, 0) byte values
enum PlayerFieldByteFlags
{
PLAYER_FIELD_BYTE_TRACK_STEALTHED = 0x02,
PLAYER_FIELD_BYTE_RELEASE_TIMER = 0x08, // Display time till auto release spirit
PLAYER_FIELD_BYTE_NO_RELEASE_WINDOW = 0x10 // Display no "release spirit" window at all
};
// used in byte (PLAYER_FIELD_BYTES2,3) values
enum PlayerFieldByte2Flags
{
PLAYER_FIELD_BYTE2_NONE = 0x00,
PLAYER_FIELD_BYTE2_DETECT_AMORE_0 = 0x02, // SPELL_AURA_DETECT_AMORE, not used as value and maybe not relcted to, but used in code as base for mask apply
PLAYER_FIELD_BYTE2_DETECT_AMORE_1 = 0x04, // SPELL_AURA_DETECT_AMORE value 1
PLAYER_FIELD_BYTE2_DETECT_AMORE_2 = 0x08, // SPELL_AURA_DETECT_AMORE value 2
PLAYER_FIELD_BYTE2_DETECT_AMORE_3 = 0x10, // SPELL_AURA_DETECT_AMORE value 3
PLAYER_FIELD_BYTE2_STEALTH = 0x20,
PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW = 0x40
};
enum MirrorTimerType
{
FATIGUE_TIMER = 0,
BREATH_TIMER = 1,
FIRE_TIMER = 2
};
#define MAX_TIMERS 3
#define DISABLED_MIRROR_TIMER -1
// 2^n values
enum PlayerExtraFlags
{
// gm abilities
PLAYER_EXTRA_GM_ON = 0x0001,
PLAYER_EXTRA_GM_ACCEPT_TICKETS = 0x0002,
PLAYER_EXTRA_ACCEPT_WHISPERS = 0x0004,
PLAYER_EXTRA_TAXICHEAT = 0x0008,
PLAYER_EXTRA_GM_INVISIBLE = 0x0010,
PLAYER_EXTRA_GM_CHAT = 0x0020, // Show GM badge in chat messages
PLAYER_EXTRA_AUCTION_NEUTRAL = 0x0040,
PLAYER_EXTRA_AUCTION_ENEMY = 0x0080, // overwrite PLAYER_EXTRA_AUCTION_NEUTRAL
// other states
PLAYER_EXTRA_PVP_DEATH = 0x0100 // store PvP death status until corpse creating.
};
// 2^n values
enum AtLoginFlags
{
AT_LOGIN_NONE = 0x00,
AT_LOGIN_RENAME = 0x01,
AT_LOGIN_RESET_SPELLS = 0x02,
AT_LOGIN_RESET_TALENTS = 0x04,
AT_LOGIN_CUSTOMIZE = 0x08,
AT_LOGIN_RESET_PET_TALENTS = 0x10,
AT_LOGIN_FIRST = 0x20,
};
typedef std::map<uint32, QuestStatusData> QuestStatusMap;
enum QuestSlotOffsets
{
QUEST_ID_OFFSET = 0,
QUEST_STATE_OFFSET = 1,
QUEST_COUNTS_OFFSET = 2, // 2 and 3
QUEST_TIME_OFFSET = 4
};
#define MAX_QUEST_OFFSET 5
enum QuestSlotStateMask
{
QUEST_STATE_NONE = 0x0000,
QUEST_STATE_COMPLETE = 0x0001,
QUEST_STATE_FAIL = 0x0002
};
enum SkillUpdateState
{
SKILL_UNCHANGED = 0,
SKILL_CHANGED = 1,
SKILL_NEW = 2,
SKILL_DELETED = 3
};
struct SkillStatusData
{
SkillStatusData(uint8 _pos, SkillUpdateState _uState) : pos(_pos), uState(_uState)
{
}
uint8 pos;
SkillUpdateState uState;
};
typedef UNORDERED_MAP<uint32, SkillStatusData> SkillStatusMap;
enum PlayerSlots
{
// first slot for item stored (in any way in player m_items data)
PLAYER_SLOT_START = 0,
// last+1 slot for item stored (in any way in player m_items data)
PLAYER_SLOT_END = 86,
PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START)
};
#define INVENTORY_SLOT_BAG_0 255
enum EquipmentSlots // 19 slots
{
EQUIPMENT_SLOT_START = 0,
EQUIPMENT_SLOT_HEAD = 0,
EQUIPMENT_SLOT_NECK = 1,
EQUIPMENT_SLOT_SHOULDERS = 2,
EQUIPMENT_SLOT_BODY = 3,
EQUIPMENT_SLOT_CHEST = 4,
EQUIPMENT_SLOT_WAIST = 5,
EQUIPMENT_SLOT_LEGS = 6,
EQUIPMENT_SLOT_FEET = 7,
EQUIPMENT_SLOT_WRISTS = 8,
EQUIPMENT_SLOT_HANDS = 9,
EQUIPMENT_SLOT_FINGER1 = 10,
EQUIPMENT_SLOT_FINGER2 = 11,
EQUIPMENT_SLOT_TRINKET1 = 12,
EQUIPMENT_SLOT_TRINKET2 = 13,
EQUIPMENT_SLOT_BACK = 14,
EQUIPMENT_SLOT_MAINHAND = 15,
EQUIPMENT_SLOT_OFFHAND = 16,
EQUIPMENT_SLOT_RANGED = 17,
EQUIPMENT_SLOT_TABARD = 18,
EQUIPMENT_SLOT_END = 19
};
enum InventorySlots // 4 slots
{
INVENTORY_SLOT_BAG_START = 19,
INVENTORY_SLOT_BAG_END = 23
};
enum InventoryPackSlots // 16 slots
{
INVENTORY_SLOT_ITEM_START = 23,
INVENTORY_SLOT_ITEM_END = 39
};
enum BankItemSlots // 28 slots
{
BANK_SLOT_ITEM_START = 39,
BANK_SLOT_ITEM_END = 67
};
enum BankBagSlots // 7 slots
{
BANK_SLOT_BAG_START = 67,
BANK_SLOT_BAG_END = 74
};
enum BuyBackSlots // 12 slots
{
// stored in m_buybackitems
BUYBACK_SLOT_START = 74,
BUYBACK_SLOT_END = 86
};
enum EquipmentSetUpdateState
{
EQUIPMENT_SET_UNCHANGED = 0,
EQUIPMENT_SET_CHANGED = 1,
EQUIPMENT_SET_NEW = 2,
EQUIPMENT_SET_DELETED = 3
};
struct EquipmentSet
{
EquipmentSet() : Guid(0), IgnoreMask(0), state(EQUIPMENT_SET_NEW)
{
for (int i = 0; i < EQUIPMENT_SLOT_END; ++i)
Items[i] = 0;
}
uint64 Guid;
std::string Name;
std::string IconName;
uint32 IgnoreMask;
uint32 Items[EQUIPMENT_SLOT_END];
EquipmentSetUpdateState state;
};
#define MAX_EQUIPMENT_SET_INDEX 10 // client limit
typedef std::map<uint32, EquipmentSet> EquipmentSets;
struct ItemPosCount
{
ItemPosCount(uint16 _pos, uint32 _count) : pos(_pos), count(_count) {}
bool isContainedIn(std::vector<ItemPosCount> const& vec) const;
uint16 pos;
uint32 count;
};
typedef std::vector<ItemPosCount> ItemPosCountVec;
enum TradeSlots
{
TRADE_SLOT_COUNT = 7,
TRADE_SLOT_TRADED_COUNT = 6,
TRADE_SLOT_NONTRADED = 6
};
enum TransferAbortReason
{
TRANSFER_ABORT_NONE = 0x00,
TRANSFER_ABORT_ERROR = 0x01,
TRANSFER_ABORT_MAX_PLAYERS = 0x02, // Transfer Aborted: instance is full
TRANSFER_ABORT_NOT_FOUND = 0x03, // Transfer Aborted: instance not found
TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x04, // You have entered too many instances recently.
TRANSFER_ABORT_ZONE_IN_COMBAT = 0x06, // Unable to zone in while an encounter is in progress.
TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x07, // You must have <TBC,WotLK> expansion installed to access this area.
TRANSFER_ABORT_DIFFICULTY = 0x08, // <Normal,Heroic,Epic> difficulty mode is not available for %s.
TRANSFER_ABORT_UNIQUE_MESSAGE = 0x09, // Until you've escaped TLK's grasp, you cannot leave this place!
TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x0A, // Additional instances cannot be launched, please try again later.
TRANSFER_ABORT_NEED_GROUP = 0x0B, // 3.1
TRANSFER_ABORT_NOT_FOUND2 = 0x0C, // 3.1
TRANSFER_ABORT_NOT_FOUND3 = 0x0D, // 3.1
TRANSFER_ABORT_NOT_FOUND4 = 0x0E, // 3.2
TRANSFER_ABORT_REALM_ONLY = 0x0F, // All players on party must be from the same realm.
TRANSFER_ABORT_MAP_NOT_ALLOWED = 0x10, // Map can't be entered at this time.
// 0x11 not found
TRANSFER_ABORT_LOCKED_TO_DIFFERENT_INSTANCE = 0x12, // 4.0.1
TRANSFER_ABORT_ALREADY_COMPLETED_ENCOUNTER = 0x13, // 4.0.1
};
enum InstanceResetWarningType
{
RAID_INSTANCE_WARNING_HOURS = 1, // WARNING! %s is scheduled to reset in %d hour(s).
RAID_INSTANCE_WARNING_MIN = 2, // WARNING! %s is scheduled to reset in %d minute(s)!
RAID_INSTANCE_WARNING_MIN_SOON = 3, // WARNING! %s is scheduled to reset in %d minute(s). Please exit the zone or you will be returned to your bind location!
RAID_INSTANCE_WELCOME = 4, // Welcome to %s. This raid instance is scheduled to reset in %s.
RAID_INSTANCE_EXPIRED = 5
};
// PLAYER_FIELD_ARENA_TEAM_INFO_1_1 offsets
enum ArenaTeamInfoType
{
ARENA_TEAM_ID = 0,
ARENA_TEAM_TYPE = 1, // new in 3.2 - team type?
ARENA_TEAM_MEMBER = 2, // 0 - captain, 1 - member
ARENA_TEAM_GAMES_WEEK = 3,
ARENA_TEAM_GAMES_SEASON = 4,
ARENA_TEAM_WINS_SEASON = 5,
ARENA_TEAM_PERSONAL_RATING = 6,
ARENA_TEAM_END = 7
};
enum RestType
{
REST_TYPE_NO = 0,
REST_TYPE_IN_TAVERN = 1,
REST_TYPE_IN_CITY = 2
};
enum DuelCompleteType
{
DUEL_INTERRUPTED = 0,
DUEL_WON = 1,
DUEL_FLED = 2
};
enum TeleportToOptions
{
TELE_TO_GM_MODE = 0x01,
TELE_TO_NOT_LEAVE_TRANSPORT = 0x02,
TELE_TO_NOT_LEAVE_COMBAT = 0x04,
TELE_TO_NOT_UNSUMMON_PET = 0x08,
TELE_TO_SPELL = 0x10,
};
/// Type of environmental damages
enum EnviromentalDamage
{
DAMAGE_EXHAUSTED = 0,
DAMAGE_DROWNING = 1,
DAMAGE_FALL = 2,
DAMAGE_LAVA = 3,
DAMAGE_SLIME = 4,
DAMAGE_FIRE = 5,
DAMAGE_FALL_TO_VOID = 6 // custom case for fall without durability loss
};
enum PlayerChatTag
{
CHAT_TAG_NONE = 0x00,
CHAT_TAG_AFK = 0x01,
CHAT_TAG_DND = 0x02,
CHAT_TAG_GM = 0x04,
CHAT_TAG_COM = 0x08, // Commentator
CHAT_TAG_DEV = 0x10, // Developer
};
enum PlayedTimeIndex
{
PLAYED_TIME_TOTAL = 0,
PLAYED_TIME_LEVEL = 1
};
#define MAX_PLAYED_TIME_INDEX 2
// used at player loading query list preparing, and later result selection
enum PlayerLoginQueryIndex
{
PLAYER_LOGIN_QUERY_LOADFROM,
PLAYER_LOGIN_QUERY_LOADGROUP,
PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES,
PLAYER_LOGIN_QUERY_LOADAURAS,
PLAYER_LOGIN_QUERY_LOADSPELLS,
PLAYER_LOGIN_QUERY_LOADQUESTSTATUS,
PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,
PLAYER_LOGIN_QUERY_LOADREPUTATION,
PLAYER_LOGIN_QUERY_LOADINVENTORY,
PLAYER_LOGIN_QUERY_LOADITEMLOOT,
PLAYER_LOGIN_QUERY_LOADACTIONS,
PLAYER_LOGIN_QUERY_LOADSOCIALLIST,
PLAYER_LOGIN_QUERY_LOADHOMEBIND,
PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS,
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES,
PLAYER_LOGIN_QUERY_LOADGUILD,
PLAYER_LOGIN_QUERY_LOADARENAINFO,
PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS,
PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,
PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS,
PLAYER_LOGIN_QUERY_LOADBGDATA,
PLAYER_LOGIN_QUERY_LOADACCOUNTDATA,
PLAYER_LOGIN_QUERY_LOADSKILLS,
PLAYER_LOGIN_QUERY_LOADGLYPHS,
PLAYER_LOGIN_QUERY_LOADMAILS,
PLAYER_LOGIN_QUERY_LOADMAILEDITEMS,
PLAYER_LOGIN_QUERY_LOADTALENTS,
PLAYER_LOGIN_QUERY_LOADWEEKLYQUESTSTATUS,
PLAYER_LOGIN_QUERY_LOADMONTHLYQUESTSTATUS,
PLAYER_LOGIN_QUERY_LOADCURRENCIES,
MAX_PLAYER_LOGIN_QUERY
};
enum PlayerDelayedOperations
{
DELAYED_SAVE_PLAYER = 0x01,
DELAYED_RESURRECT_PLAYER = 0x02,
DELAYED_SPELL_CAST_DESERTER = 0x04,
DELAYED_BG_MOUNT_RESTORE = 0x08, ///< Flag to restore mount state after teleport from BG
DELAYED_BG_TAXI_RESTORE = 0x10, ///< Flag to restore taxi state after teleport from BG
DELAYED_END
};
enum ReputationSource
{
REPUTATION_SOURCE_KILL,
REPUTATION_SOURCE_QUEST,
REPUTATION_SOURCE_SPELL
};
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
#define MAX_MONEY_AMOUNT (UI64LIT(9999999999)) // from wowpedia
struct InstancePlayerBind
{
DungeonPersistentState* state;
bool perm;
/* permanent PlayerInstanceBinds are created in Raid/Heroic instances for players
that aren't already permanently bound when they are inside when a boss is killed
or when they enter an instance that the group leader is permanently bound to. */
InstancePlayerBind() : state(NULL), perm(false) {}
};
enum PlayerRestState
{
REST_STATE_RESTED = 0x01,
REST_STATE_NORMAL = 0x02,
REST_STATE_RAF_LINKED = 0x04 // Exact use unknown
};
class MANGOS_DLL_SPEC PlayerTaxi
{
public:
PlayerTaxi();
~PlayerTaxi() {}
// Nodes
void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level);
void LoadTaxiMask(const char* data);
bool IsTaximaskNodeKnown(uint32 nodeidx) const
{
uint8 field = uint8((nodeidx - 1) / 8);
uint8 submask = 1 << ((nodeidx - 1) % 8);
return (m_taximask[field] & submask) == submask;
}
bool SetTaximaskNode(uint32 nodeidx)
{
uint8 field = uint8((nodeidx - 1) / 8);
uint8 submask = 1 << ((nodeidx - 1) % 8);
if ((m_taximask[field] & submask) != submask)
{
m_taximask[field] |= submask;
return true;
}
else
return false;
}
void AppendTaximaskTo(ByteBuffer& data, bool all);
// Destinations
bool LoadTaxiDestinationsFromString(const std::string& values, Team team);
std::string SaveTaxiDestinationsToString();
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
void AddTaxiDestination(uint32 dest) { m_TaxiDestinations.push_back(dest); }
uint32 GetTaxiSource() const { return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front(); }
uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1]; }
uint32 GetCurrentTaxiPath() const;
uint32 NextTaxiDestination()
{
m_TaxiDestinations.pop_front();
return GetTaxiDestination();
}
bool empty() const { return m_TaxiDestinations.empty(); }
friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
private:
TaxiMask m_taximask;
std::deque<uint32> m_TaxiDestinations;
};
std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
/// Holder for BattleGround data
struct BGData
{
BGData() : bgInstanceID(0), bgTypeID(BATTLEGROUND_TYPE_NONE), bgAfkReportedCount(0), bgAfkReportedTimer(0),
bgTeam(TEAM_NONE), mountSpell(0), m_needSave(false) { ClearTaxiPath(); }
uint32 bgInstanceID; ///< This variable is set to bg->m_InstanceID, saved
/// when player is teleported to BG - (it is battleground's GUID)
BattleGroundTypeId bgTypeID;
std::set<uint32> bgAfkReporter;
uint8 bgAfkReportedCount;
time_t bgAfkReportedTimer;
Team bgTeam; ///< What side the player will be added to, saved
uint32 mountSpell; ///< Mount used before join to bg, saved
uint32 taxiPath[2]; ///< Current taxi active path start/end nodes, saved
WorldLocation joinPos; ///< From where player entered BG, saved
bool m_needSave; ///< true, if saved to DB fields modified after prev. save (marked as "saved" above)
void ClearTaxiPath() { taxiPath[0] = taxiPath[1] = 0; }
bool HasTaxiPath() const { return taxiPath[0] && taxiPath[1]; }
};
class TradeData
{
public: // constructors
TradeData(Player* player, Player* trader) :
m_player(player), m_trader(trader), m_accepted(false), m_acceptProccess(false),
m_money(0), m_spell(0) {}
public: // access functions
Player* GetTrader() const { return m_trader; }
TradeData* GetTraderData() const;
Item* GetItem(TradeSlots slot) const;
bool HasItem(ObjectGuid item_guid) const;
uint32 GetSpell() const { return m_spell; }
Item* GetSpellCastItem() const;
bool HasSpellCastItem() const { return !m_spellCastItem.IsEmpty(); }
uint64 GetMoney() const { return m_money; }
bool IsAccepted() const { return m_accepted; }
bool IsInAcceptProcess() const { return m_acceptProccess; }
public: // access functions
void SetItem(TradeSlots slot, Item* item);
void SetSpell(uint32 spell_id, Item* castItem = NULL);
void SetMoney(uint64 money);
void SetAccepted(bool state, bool crosssend = false);
// must be called only from accept handler helper functions
void SetInAcceptProcess(bool state) { m_acceptProccess = state; }
private: // internal functions
void Update(bool for_trader = true);
private: // fields
Player* m_player; // Player who own of this TradeData
Player* m_trader; // Player who trade with m_player
bool m_accepted; // m_player press accept for trade list
bool m_acceptProccess; // one from player/trader press accept and this processed
uint64 m_money; // m_player place money to trade
uint32 m_spell; // m_player apply spell to non-traded slot item
ObjectGuid m_spellCastItem; // applied spell casted by item use
ObjectGuid m_items[TRADE_SLOT_COUNT]; // traded itmes from m_player side including non-traded slot
};
class MANGOS_DLL_SPEC Player : public Unit
{
friend class WorldSession;
friend void Item::AddToUpdateQueueOf(Player* player);
friend void Item::RemoveFromUpdateQueueOf(Player* player);
public:
explicit Player(WorldSession* session);
~Player();
void CleanupsBeforeDelete() override;
static UpdateMask updateVisualBits;
static void InitVisibleBits();
void AddToWorld() override;
void RemoveFromWorld() override;
void SendTeleportPacket(float oldX, float oldY, float oldZ, float oldO);
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0, AreaTrigger const* at = NULL);
bool TeleportTo(WorldLocation const& loc, uint32 options = 0)
{
return TeleportTo(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation, options);
}
bool TeleportToBGEntryPoint();
void SetSummonPoint(uint32 mapid, float x, float y, float z)
{
m_summon_expire = time(NULL) + MAX_PLAYER_SUMMON_DELAY;
m_summon_mapid = mapid;
m_summon_x = x;
m_summon_y = y;
m_summon_z = z;
}
void SummonIfPossible(bool agree);
bool Create(uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId);
void Update(uint32 update_diff, uint32 time) override;
static bool BuildEnumData(QueryResult* result, ByteBuffer* data, ByteBuffer* buffer);
void SetInWater(bool apply);
bool IsInWater() const override { return m_isInWater; }
bool IsUnderWater() const override;
void SendInitialPacketsBeforeAddToMap();
void SendInitialPacketsAfterAddToMap();
void SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint32 time);
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const;
void ToggleAFK();
void ToggleDND();
bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); }
bool isDND() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND); }
uint8 GetChatTag() const;
std::string autoReplyMsg;
uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, uint32 newskintone);
PlayerSocial* GetSocial() { return m_social; }
PlayerTaxi m_taxi;
void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); }
bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc = NULL, uint32 spellid = 0);
bool ActivateTaxiPathTo(uint32 taxi_path_id, uint32 spellid = 0);
// mount_id can be used in scripting calls
void ContinueTaxiFlight();
bool isAcceptTickets() const { return GetSession()->GetSecurity() >= SEC_GAMEMASTER && (m_ExtraFlags & PLAYER_EXTRA_GM_ACCEPT_TICKETS); }
void SetAcceptTicket(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_ACCEPT_TICKETS; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_ACCEPT_TICKETS; }
bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; }
void SetAcceptWhispers(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; }
bool isGameMaster() const { return m_ExtraFlags & PLAYER_EXTRA_GM_ON; }
void SetGameMaster(bool on);
bool isGMChat() const { return GetSession()->GetSecurity() >= SEC_MODERATOR && (m_ExtraFlags & PLAYER_EXTRA_GM_CHAT); }
void SetGMChat(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_CHAT; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_CHAT; }
bool isTaxiCheater() const { return m_ExtraFlags & PLAYER_EXTRA_TAXICHEAT; }
void SetTaxiCheater(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; }
bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); }
void SetGMVisible(bool on);
void SetPvPDeath(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; }
// 0 = own auction, -1 = enemy auction, 1 = goblin auction
int GetAuctionAccessMode() const { return m_ExtraFlags & PLAYER_EXTRA_AUCTION_ENEMY ? -1 : (m_ExtraFlags & PLAYER_EXTRA_AUCTION_NEUTRAL ? 1 : 0); }
void SetAuctionAccessMode(int state)
{
m_ExtraFlags &= ~(PLAYER_EXTRA_AUCTION_ENEMY | PLAYER_EXTRA_AUCTION_NEUTRAL);
if (state < 0)
m_ExtraFlags |= PLAYER_EXTRA_AUCTION_ENEMY;
else if (state > 0)
m_ExtraFlags |= PLAYER_EXTRA_AUCTION_NEUTRAL;
}
void GiveXP(uint32 xp, Unit* victim);
void GiveLevel(uint32 level);
void InitStatsForLevel(bool reapplyMods = false);
// Played Time Stuff
time_t m_logintime;
time_t m_Last_tick;
uint32 m_Played_time[MAX_PLAYED_TIME_INDEX];
uint32 GetTotalPlayedTime() { return m_Played_time[PLAYED_TIME_TOTAL]; }
uint32 GetLevelPlayedTime() { return m_Played_time[PLAYED_TIME_LEVEL]; }
void ResetTimeSync();
void SendTimeSync();
void SetDeathState(DeathState s) override; // overwrite Unit::SetDeathState
float GetRestBonus() const { return m_rest_bonus; }
void SetRestBonus(float rest_bonus_new);
RestType GetRestType() const { return rest_type; }
void SetRestType(RestType n_r_type, uint32 areaTriggerId = 0);
time_t GetTimeInnEnter() const { return time_inn_enter; }
void UpdateInnerTime(time_t time) { time_inn_enter = time; }
void RemovePet(PetSaveMode mode);
uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn
void Say(const std::string& text, const uint32 language);
void Yell(const std::string& text, const uint32 language);
void TextEmote(const std::string& text);
void Whisper(const std::string& text, const uint32 language, ObjectGuid receiver);
void WhisperAddon(const std::string& text, const std::string& prefix, ObjectGuid receiver);
void BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix = NULL) const;
/*********************************************************/
/*** STORAGE SYSTEM ***/
/*********************************************************/
void SetVirtualItemSlot(uint8 i, Item* item);
void SetSheath(SheathState sheathed) override; // overwrite Unit version
bool GetSlotsForInventoryType(uint8 invType, uint8* slots, uint32 subClass = 0) const;
uint8 FindEquipSlot(ItemPrototype const* proto, uint32 slot, bool swap) const;
uint32 GetItemCount(uint32 item, bool inBankAlso = false, Item* skipItem = NULL) const;
uint32 GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipItem = NULL) const;
Item* GetItemByGuid(ObjectGuid guid) const;
Item* GetItemByEntry(uint32 item) const; // only for special cases
Item* GetItemByLimitedCategory(uint32 limitedCategory) const;
Item* GetItemByPos(uint16 pos) const;
Item* GetItemByPos(uint8 bag, uint8 slot) const;
uint32 GetItemDisplayIdInSlot(uint8 bag, uint8 slot) const;
Item* GetWeaponForAttack(WeaponAttackType attackType) const { return GetWeaponForAttack(attackType, false, false); }
Item* GetWeaponForAttack(WeaponAttackType attackType, bool nonbroken, bool useable) const;
Item* GetShield(bool useable = false) const;
static uint32 GetAttackBySlot(uint8 slot); // MAX_ATTACK if not weapon slot
std::vector<Item*>& GetItemUpdateQueue() { return m_itemUpdateQueue; }
static bool IsInventoryPos(uint16 pos) { return IsInventoryPos(pos >> 8, pos & 255); }
static bool IsInventoryPos(uint8 bag, uint8 slot);
static bool IsEquipmentPos(uint16 pos) { return IsEquipmentPos(pos >> 8, pos & 255); }
static bool IsEquipmentPos(uint8 bag, uint8 slot);
static bool IsBagPos(uint16 pos);
static bool IsBankPos(uint16 pos) { return IsBankPos(pos >> 8, pos & 255); }
static bool IsBankPos(uint8 bag, uint8 slot);
bool IsValidPos(uint16 pos, bool explicit_pos) const { return IsValidPos(pos >> 8, pos & 255, explicit_pos); }
bool IsValidPos(uint8 bag, uint8 slot, bool explicit_pos) const;
uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, 2); }
void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, 2, count); }
bool HasItemCount(uint32 item, uint32 count, bool inBankAlso = false) const;
bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL);
bool CanNoReagentCast(SpellEntry const* spellInfo) const;
bool HasItemOrGemWithIdEquipped(uint32 item, uint32 count, uint8 except_slot = NULL_SLOT) const;
bool HasItemOrGemWithLimitCategoryEquipped(uint32 limitCategory, uint32 count, uint8 except_slot = NULL_SLOT) const;
InventoryResult CanTakeMoreSimilarItems(Item* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(), pItem->GetCount(), pItem); }
InventoryResult CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry, count, NULL); }
InventoryResult CanStoreNewItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 item, uint32 count, uint32* no_space_count = NULL) const
{
return _CanStoreItem(bag, slot, dest, item, count, NULL, false, no_space_count);
}
InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, Item* pItem, bool swap = false) const
{
if (!pItem)
return EQUIP_ERR_ITEM_NOT_FOUND;
uint32 count = pItem->GetCount();
return _CanStoreItem(bag, slot, dest, pItem->GetEntry(), count, pItem, swap, NULL);
}
InventoryResult CanStoreItems(Item** pItem, int count) const;
InventoryResult CanEquipNewItem(uint8 slot, uint16& dest, uint32 item, bool swap) const;
InventoryResult CanEquipItem(uint8 slot, uint16& dest, Item* pItem, bool swap, bool direct_action = true) const;
InventoryResult CanEquipUniqueItem(Item* pItem, uint8 except_slot = NULL_SLOT, uint32 limit_count = 1) const;
InventoryResult CanEquipUniqueItem(ItemPrototype const* itemProto, uint8 except_slot = NULL_SLOT, uint32 limit_count = 1) const;
InventoryResult CanUnequipItems(uint32 item, uint32 count) const;
InventoryResult CanUnequipItem(uint16 src, bool swap) const;
InventoryResult CanBankItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, Item* pItem, bool swap, bool not_loading = true) const;
InventoryResult CanUseItem(Item* pItem, bool direct_action = true) const;
InventoryResult CanUseItem(ItemPrototype const* pItem) const;
InventoryResult CanUseAmmo(uint32 item) const;
Item* StoreNewItem(ItemPosCountVec const& pos, uint32 item, bool update, int32 randomPropertyId = 0);
Item* StoreItem(ItemPosCountVec const& pos, Item* pItem, bool update);
Item* EquipNewItem(uint16 pos, uint32 item, bool update);
Item* EquipItem(uint16 pos, Item* pItem, bool update);
void AutoUnequipOffhandIfNeed();
bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count);
Item* StoreNewItemInInventorySlot(uint32 itemEntry, uint32 amount);
void AutoStoreLoot(WorldObject const* lootTarget, uint32 loot_id, LootStore const& store, bool broadcast = false, uint8 bag = NULL_BAG, uint8 slot = NULL_SLOT);
void AutoStoreLoot(Loot& loot, bool broadcast = false, uint8 bag = NULL_BAG, uint8 slot = NULL_SLOT);
Item* ConvertItem(Item* item, uint32 newItemId);
InventoryResult _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const;
InventoryResult _CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item* pItem = NULL, bool swap = false, uint32* no_space_count = NULL) const;
void ApplyEquipCooldown(Item* pItem);
void SetAmmo(uint32 item);
void RemoveAmmo();
float GetAmmoDPS() const { return m_ammoDPS; }
bool CheckAmmoCompatibility(const ItemPrototype* ammo_proto) const;
void QuickEquipItem(uint16 pos, Item* pItem);
void VisualizeItem(uint8 slot, Item* pItem);
void SetVisibleItemSlot(uint8 slot, Item* pItem);
Item* BankItem(ItemPosCountVec const& dest, Item* pItem, bool update)
{
return StoreItem(dest, pItem, update);
}
Item* BankItem(uint16 pos, Item* pItem, bool update);
void RemoveItem(uint8 bag, uint8 slot, bool update);// see ApplyItemOnStoreSpell notes
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update);
// in trade, auction, guild bank, mail....
void MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool update, bool in_characterInventoryDB = false);
// in trade, guild bank, mail....
void RemoveItemDependentAurasAndCasts(Item* pItem);
void DestroyItem(uint8 bag, uint8 slot, bool update);
void DestroyItemCount(uint32 item, uint32 count, bool update, bool unequip_check = false, bool inBankAlso = false);
void DestroyItemCount(Item* item, uint32& count, bool update);
void DestroyConjuredItems(bool update);
void DestroyZoneLimitedItem(bool update, uint32 new_zone);
void SplitItem(uint16 src, uint16 dst, uint32 count);
void SwapItem(uint16 src, uint16 dst);
void AddItemToBuyBackSlot(Item* pItem);
Item* GetItemFromBuyBackSlot(uint32 slot);
void RemoveItemFromBuyBackSlot(uint32 slot, bool del);
void TakeExtendedCost(uint32 extendedCostId);
void SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2 = NULL, uint32 itemid = 0) const;
void SendBuyError(BuyResult msg, Creature* pCreature, uint32 item, uint32 param);
void SendSellError(SellResult msg, Creature* pCreature, ObjectGuid itemGuid, uint32 param);
void AddWeaponProficiency(uint32 newflag) { m_WeaponProficiency |= newflag; }
void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag; }
uint32 GetWeaponProficiency() const { return m_WeaponProficiency; }
uint32 GetArmorProficiency() const { return m_ArmorProficiency; }
bool IsTwoHandUsed() const
{
Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip();
}
bool HasTwoHandWeaponInOneHand() const
{
Item* offItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
return offItem && ((mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON) || offItem->GetProto()->InventoryType == INVTYPE_2HWEAPON);
}
void SendNewItem(Item* item, uint32 count, bool received, bool created, bool broadcast = false);
bool BuyItemFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorslot, uint32 item, uint32 count, uint8 bag, uint8 slot);
bool BuyCurrencyFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorslot, uint32 currencyId, uint32 count);
float GetReputationPriceDiscount(Creature const* pCreature) const;
Player* GetTrader() const { return m_trade ? m_trade->GetTrader() : NULL; }
TradeData* GetTradeData() const { return m_trade; }
void TradeCancel(bool sendback);
void UpdateEnchantTime(uint32 time);
void UpdateItemDuration(uint32 time, bool realtimeonly = false);
void AddEnchantmentDurations(Item* item);
void RemoveEnchantmentDurations(Item* item);
void RemoveAllEnchantments(EnchantmentSlot slot);
void AddEnchantmentDuration(Item* item, EnchantmentSlot slot, uint32 duration);
void ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool apply_dur = true, bool ignore_condition = false);
void ApplyEnchantment(Item* item, bool apply);
void SendEnchantmentDurations();
void BuildEnchantmentsInfoData(WorldPacket* data);
void AddItemDurations(Item* item);
void RemoveItemDurations(Item* item);
void SendItemDurations();
void LoadCorpse();
void LoadPet();
uint32 m_stableSlots;
uint32 GetEquipGearScore(bool withBags = true, bool withBank = false);
void ResetCachedGearScore() { m_cachedGS = 0; }
typedef std::vector < uint32/*item level*/ > GearScoreVec;
/*********************************************************/
/*** GOSSIP SYSTEM ***/
/*********************************************************/
void PrepareGossipMenu(WorldObject* pSource, uint32 menuId = 0);
void SendPreparedGossip(WorldObject* pSource);
void OnGossipSelect(WorldObject* pSource, uint32 gossipListId, uint32 menuId);
uint32 GetGossipTextId(uint32 menuId, WorldObject* pSource);
uint32 GetGossipTextId(WorldObject* pSource);
uint32 GetDefaultGossipMenuForSource(WorldObject* pSource);
/*********************************************************/
/*** QUEST SYSTEM ***/
/*********************************************************/
// Return player level when QuestLevel is dynamic (-1)
uint32 GetQuestLevelForPlayer(Quest const* pQuest) const { return pQuest && (pQuest->GetQuestLevel() > 0) ? (uint32)pQuest->GetQuestLevel() : getLevel(); }
void PrepareQuestMenu(ObjectGuid guid);
void SendPreparedQuest(ObjectGuid guid);
bool IsActiveQuest(uint32 quest_id) const; // can be taken or taken
// Quest is taken and not yet rewarded
// if completed_or_not = 0 (or any other value except 1 or 2) - returns true, if quest is taken and doesn't depend if quest is completed or not
// if completed_or_not = 1 - returns true, if quest is taken but not completed
// if completed_or_not = 2 - returns true, if quest is taken and already completed
bool IsCurrentQuest(uint32 quest_id, uint8 completed_or_not = 0) const; // taken and not yet rewarded
Quest const* GetNextQuest(ObjectGuid guid, Quest const* pQuest);
bool CanSeeStartQuest(Quest const* pQuest) const;
bool CanTakeQuest(Quest const* pQuest, bool msg) const;
bool CanAddQuest(Quest const* pQuest, bool msg) const;
bool CanCompleteQuest(uint32 quest_id) const;
bool CanCompleteRepeatableQuest(Quest const* pQuest) const;
bool CanRewardQuest(Quest const* pQuest, bool msg) const;
bool CanRewardQuest(Quest const* pQuest, uint32 reward, bool msg) const;
void AddQuest(Quest const* pQuest, Object* questGiver);
void CompleteQuest(uint32 quest_id);
void IncompleteQuest(uint32 quest_id);
void RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, bool announce = true);
void FailQuest(uint32 quest_id);
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
bool SatisfyQuestSpell(Quest const* qInfo, bool msg) const;
bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const;
bool SatisfyQuestLog(bool msg) const;
bool SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const;
bool SatisfyQuestClass(Quest const* qInfo, bool msg) const;
bool SatisfyQuestRace(Quest const* qInfo, bool msg) const;
bool SatisfyQuestReputation(Quest const* qInfo, bool msg) const;
bool SatisfyQuestStatus(Quest const* qInfo, bool msg) const;
bool SatisfyQuestTimed(Quest const* qInfo, bool msg) const;
bool SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) const;
bool SatisfyQuestNextChain(Quest const* qInfo, bool msg) const;
bool SatisfyQuestPrevChain(Quest const* qInfo, bool msg) const;
bool SatisfyQuestDay(Quest const* qInfo, bool msg) const;
bool SatisfyQuestWeek(Quest const* qInfo, bool msg) const;
bool SatisfyQuestMonth(Quest const* qInfo, bool msg) const;
bool CanGiveQuestSourceItemIfNeed(Quest const* pQuest, ItemPosCountVec* dest = NULL) const;
void GiveQuestSourceItemIfNeed(Quest const* pQuest);
bool TakeQuestSourceItem(uint32 quest_id, bool msg);
bool GetQuestRewardStatus(uint32 quest_id) const;
QuestStatus GetQuestStatus(uint32 quest_id) const;
void SetQuestStatus(uint32 quest_id, QuestStatus status);
void SetDailyQuestStatus(uint32 quest_id);
void SetWeeklyQuestStatus(uint32 quest_id);
void SetMonthlyQuestStatus(uint32 quest_id);
void ResetDailyQuestStatus();
void ResetWeeklyQuestStatus();
void ResetMonthlyQuestStatus();
uint16 FindQuestSlot(uint32 quest_id) const;
uint32 GetQuestSlotQuestId(uint16 slot) const { return GetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_ID_OFFSET); }
void SetQuestSlot(uint16 slot, uint32 quest_id, uint32 timer = 0)
{
SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_ID_OFFSET, quest_id);
SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_STATE_OFFSET, 0);
SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET, 0);
SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET + 1, 0);
SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_TIME_OFFSET, timer);
}
void SetQuestSlotCounter(uint16 slot, uint8 counter, uint16 count)
{
uint64 val = GetUInt64Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET);
val &= ~((uint64)0xFFFF << (counter * 16));
val |= ((uint64)count << (counter * 16));
SetUInt64Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_COUNTS_OFFSET, val);
}
void SetQuestSlotState(uint16 slot, uint32 state) { SetFlag(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_STATE_OFFSET, state); }
void RemoveQuestSlotState(uint16 slot, uint32 state) { RemoveFlag(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_STATE_OFFSET, state); }
void SetQuestSlotTimer(uint16 slot, uint32 timer) { SetUInt32Value(PLAYER_QUEST_LOG_1_1 + slot * MAX_QUEST_OFFSET + QUEST_TIME_OFFSET, timer); }
void SwapQuestSlot(uint16 slot1, uint16 slot2)
{
for (int i = 0; i < MAX_QUEST_OFFSET; ++i)
{
uint32 temp1 = GetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET * slot1 + i);
uint32 temp2 = GetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET * slot2 + i);
SetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET * slot1 + i, temp2);
SetUInt32Value(PLAYER_QUEST_LOG_1_1 + MAX_QUEST_OFFSET * slot2 + i, temp1);
}
}
uint32 GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry);
void AreaExploredOrEventHappens(uint32 questId);
void GroupEventHappens(uint32 questId, WorldObject const* pEventObject);
void CurrencyAddedQuestCheck(uint32 entry);
void CurrencyRemovedQuestCheck(uint32 entry);
void ItemAddedQuestCheck(uint32 entry, uint32 count);
void ItemRemovedQuestCheck(uint32 entry, uint32 count);
void SpellAddedQuestCheck(uint32 entry);
void SpellRemovedQuestCheck(uint32 entry);
void KilledMonster(CreatureInfo const* cInfo, ObjectGuid guid);
void KilledMonsterCredit(uint32 entry, ObjectGuid guid = ObjectGuid());
void CastedCreatureOrGO(uint32 entry, ObjectGuid guid, uint32 spell_id, bool original_caster = true);
void TalkedToCreature(uint32 entry, ObjectGuid guid);
void MoneyChanged(uint32 value);
void ReputationChanged(FactionEntry const* factionEntry);
bool HasQuestForItem(uint32 itemid) const;
bool HasQuestForGO(int32 GOId) const;
void UpdateForQuestWorldObjects();
bool CanShareQuest(uint32 quest_id) const;
void SendQuestCompleteEvent(uint32 quest_id);
void SendQuestReward(Quest const* pQuest, uint32 XP, Object* questGiver);
void SendQuestFailed(uint32 quest_id, InventoryResult reason = EQUIP_ERR_OK);
void SendQuestTimerFailed(uint32 quest_id);
void SendCanTakeQuestResponse(uint32 msg) const;
void SendQuestConfirmAccept(Quest const* pQuest, Player* pReceiver);
void SendPushToPartyResponse(Player* pPlayer, uint32 msg);
void SendQuestUpdateAddCreatureOrGo(Quest const* pQuest, ObjectGuid guid, uint32 creatureOrGO_idx, uint32 count);
ObjectGuid GetDividerGuid() const { return m_dividerGuid; }
void SetDividerGuid(ObjectGuid guid) { m_dividerGuid = guid; }
void ClearDividerGuid() { m_dividerGuid.Clear(); }
uint32 GetInGameTime() { return m_ingametime; }
void SetInGameTime(uint32 time) { m_ingametime = time; }
void AddTimedQuest(uint32 quest_id) { m_timedquests.insert(quest_id); }
void RemoveTimedQuest(uint32 quest_id) { m_timedquests.erase(quest_id); }
/*********************************************************/
/*** LOAD SYSTEM ***/
/*********************************************************/
bool LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder);
static uint32 GetZoneIdFromDB(ObjectGuid guid);
static uint32 GetLevelFromDB(ObjectGuid guid);
static bool LoadPositionFromDB(ObjectGuid guid, uint32& mapid, float& x, float& y, float& z, float& o, bool& in_flight);
/*********************************************************/
/*** SAVE SYSTEM ***/
/*********************************************************/
void SaveToDB();
void SaveInventoryAndGoldToDB(); // fast save function for item/money cheating preventing
void SaveGoldToDB();
static void SetUInt32ValueInArray(Tokens& data, uint16 index, uint32 value);
static void SetFloatValueInArray(Tokens& data, uint16 index, float value);
static void Customize(ObjectGuid guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair);
static void SavePositionInDB(ObjectGuid guid, uint32 mapid, float x, float y, float z, float o, uint32 zone);
static void DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRealmChars = true, bool deleteFinally = false);
static void DeleteOldCharacters();
static void DeleteOldCharacters(uint32 keepDays);
bool m_mailsUpdated;
void SendPetTameFailure(PetTameFailureReason reason);
void SetBindPoint(ObjectGuid guid);
void SendTalentWipeConfirm(ObjectGuid guid);
void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker);
void SendPetSkillWipeConfirm();
void CalcRage(uint32 damage, bool attacker);
void RegenerateAll(uint32 diff = REGEN_TIME_FULL);
void Regenerate(Powers power, uint32 diff);
void RegenerateHealth(uint32 diff);
void setRegenTimer(uint32 time) {m_regenTimer = time;}
void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;}
uint64 GetMoney() const { return GetUInt64Value(PLAYER_FIELD_COINAGE); }
void ModifyMoney(int64 d)
{
if (d < 0)
SetMoney(GetMoney() > uint64(-d) ? GetMoney() + d : 0);
else
SetMoney(GetMoney() < uint64(MAX_MONEY_AMOUNT - d) ? GetMoney() + d : MAX_MONEY_AMOUNT);
// "At Gold Limit"
if (GetMoney() >= MAX_MONEY_AMOUNT)
SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
}
void SetMoney(uint64 value)
{
SetUInt64Value(PLAYER_FIELD_COINAGE, value);
MoneyChanged(value);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED);
}
QuestStatusMap& getQuestStatusMap() { return mQuestStatus; };
ObjectGuid const& GetSelectionGuid() const { return m_curSelectionGuid; }
void SetSelectionGuid(ObjectGuid guid) { m_curSelectionGuid = guid; SetTargetGuid(guid); }
uint8 GetComboPoints() const { return m_comboPoints; }
ObjectGuid const& GetComboTargetGuid() const { return m_comboTargetGuid; }
void AddComboPoints(Unit* target, int8 count);
void ClearComboPoints();
void SendComboPoints();
void SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError = 0, uint32 item_guid = 0, uint32 item_count = 0);
void SendNewMail();
void UpdateNextMailTimeAndUnreads();
void AddNewMailDeliverTime(time_t deliver_time);
void RemoveMail(uint32 id);
void AddMail(Mail* mail) { m_mail.push_front(mail);}// for call from WorldSession::SendMailTo
uint32 GetMailSize() { return m_mail.size(); }
Mail* GetMail(uint32 id);
PlayerMails::iterator GetMailBegin() { return m_mail.begin();}
PlayerMails::iterator GetMailEnd() { return m_mail.end();}
/*********************************************************/
/*** MAILED ITEMS SYSTEM ***/
/*********************************************************/
uint8 unReadMails;
time_t m_nextMailDelivereTime;
typedef UNORDERED_MAP<uint32, Item*> ItemMap;
ItemMap mMitems; // template defined in objectmgr.cpp
Item* GetMItem(uint32 id)
{
ItemMap::const_iterator itr = mMitems.find(id);
return itr != mMitems.end() ? itr->second : NULL;
}
void AddMItem(Item* it)
{
MANGOS_ASSERT(it);
// ASSERT deleted, because items can be added before loading
mMitems[it->GetGUIDLow()] = it;
}
bool RemoveMItem(uint32 id)
{
return mMitems.erase(id) ? true : false;
}
void PetSpellInitialize();
void SendPetGUIDs();
void CharmSpellInitialize();
void PossessSpellInitialize();
void RemovePetActionBar();
bool HasSpell(uint32 spell) const override;
bool HasActiveSpell(uint32 spell) const; // show in spellbook
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell, uint32 reqLevel) const;
bool IsSpellFitByClassAndRace(uint32 spell_id, uint32* pReqlevel = NULL) const;
bool IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) const;
bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index, bool castOnSelf) const override;
void SendProficiency(ItemClass itemClass, uint32 itemSubclassMask);
void SendInitialSpells();
bool addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled);
void learnSpell(uint32 spell_id, bool dependent);
void removeSpell(uint32 spell_id, bool disabled = false, bool learn_low_rank = true, bool sendUpdate = true);
void resetSpells();
void learnDefaultSpells();
void learnQuestRewardedSpells();
void learnQuestRewardedSpells(Quest const* quest);
void learnSpellHighRank(uint32 spellid);
uint32 GetFreeTalentPoints() const { return m_freeTalentPoints; }
void SetFreeTalentPoints(uint32 points) { m_freeTalentPoints = points; }
void UpdateFreeTalentPoints(bool resetIfNeed = true);
uint32 GetPrimaryTalentTree(uint8 spec) const { return m_talentsPrimaryTree[spec]; }
void SetPrimaryTalentTree(uint8 spec, uint32 tree) { m_talentsPrimaryTree[spec] = tree; }
bool resetTalents(bool no_cost = false, bool all_specs = false);
uint32 resetTalentsCost() const;
void InitTalentForLevel();
void BuildPlayerTalentsInfoData(WorldPacket* data);
void BuildPetTalentsInfoData(WorldPacket* data);
void SendTalentsInfoData(bool pet);
bool LearnTalent(uint32 talentId, uint32 talentRank);
void LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank);
uint32 CalculateTalentsPoints() const;
// Dual Spec
uint8 GetActiveSpec() { return m_activeSpec; }
void SetActiveSpec(uint8 spec) { m_activeSpec = spec; }
uint8 GetSpecsCount() { return m_specsCount; }
void SetSpecsCount(uint8 count) { m_specsCount = count; }
void ActivateSpec(uint8 specNum);
void UpdateSpecCount(uint8 count);
void InitGlyphsForLevel();
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
uint32 GetGlyphSlot(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
void SetGlyph(uint8 slot, uint32 glyph) { m_glyphs[m_activeSpec][slot].SetId(glyph); }
uint32 GetGlyph(uint8 slot) { return m_glyphs[m_activeSpec][slot].GetId(); }
void ApplyGlyph(uint8 slot, bool apply);
void ApplyGlyphs(bool apply);
uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); }
void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS, profs); }
void InitPrimaryProfessions();
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
PlayerSpellMap& GetSpellMap() { return m_spells; }
SpellCooldowns const& GetSpellCooldownMap() const { return m_spellCooldowns; }
PlayerTalent const* GetKnownTalentById(int32 talentId) const;
SpellEntry const* GetKnownTalentRankById(int32 talentId) const;
void AddSpellMod(Aura* aura, bool apply);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell const* spell = NULL);
static uint32 const infinityCooldownDelay = MONTH; // used for set "infinity cooldowns" for spells and check
static uint32 const infinityCooldownDelayCheck = MONTH / 2;
bool HasSpellCooldown(uint32 spell_id) const
{
SpellCooldowns::const_iterator itr = m_spellCooldowns.find(spell_id);
return itr != m_spellCooldowns.end() && itr->second.end > time(NULL);
}
time_t GetSpellCooldownDelay(uint32 spell_id) const
{
SpellCooldowns::const_iterator itr = m_spellCooldowns.find(spell_id);
time_t t = time(NULL);
return itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0;
}
void AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell = NULL, bool infinityCooldown = false);
void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time);
void SendCooldownEvent(SpellEntry const* spellInfo, uint32 itemId = 0, Spell* spell = NULL);
void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override;
void RemoveSpellCooldown(uint32 spell_id, bool update = false);
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown(uint32 spell_id, Unit* target);
GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
void RemoveArenaSpellCooldowns();
void RemoveAllSpellCooldown();
void _LoadSpellCooldowns(QueryResult* result);
void _SaveSpellCooldowns();
void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; }
uint32 GetLastPotionId() { return m_lastPotionId; }
void UpdatePotionCooldown(Spell* spell = NULL);
void setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana)
{
m_resurrectGuid = guid;
m_resurrectMap = mapId;
m_resurrectX = X;
m_resurrectY = Y;
m_resurrectZ = Z;
m_resurrectHealth = health;
m_resurrectMana = mana;
}
void clearResurrectRequestData() { setResurrectRequestData(ObjectGuid(), 0, 0.0f, 0.0f, 0.0f, 0, 0); }
bool isRessurectRequestedBy(ObjectGuid guid) const { return m_resurrectGuid == guid; }
bool isRessurectRequested() const { return !m_resurrectGuid.IsEmpty(); }
void ResurectUsingRequestData();
uint32 getCinematic() { return m_cinematic; }
void setCinematic(uint32 cine) { m_cinematic = cine; }
static bool IsActionButtonDataValid(uint8 button, uint32 action, uint8 type, Player* player, bool msg = true);
ActionButton* addActionButton(uint8 spec, uint8 button, uint32 action, uint8 type);
void removeActionButton(uint8 spec, uint8 button);
void SendInitialActionButtons() const;
void SendLockActionButtons() const;
ActionButton const* GetActionButton(uint8 button);
PvPInfo pvpInfo;
void UpdatePvP(bool state, bool ovrride = false);
void UpdateZone(uint32 newZone, uint32 newArea);
void UpdateArea(uint32 newArea);
uint32 GetCachedZoneId() const { return m_zoneUpdateId; }
void UpdateZoneDependentAuras();
void UpdateAreaDependentAuras(); // subzones
void UpdateZoneDependentPets();
void UpdateAfkReport(time_t currTime);
void UpdatePvPFlag(time_t currTime);
void UpdateContestedPvP(uint32 currTime);
void SetContestedPvPTimer(uint32 newTime) {m_contestedPvPTimer = newTime;}
void ResetContestedPvP()
{
clearUnitState(UNIT_STAT_ATTACK_PLAYER);
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP);
m_contestedPvPTimer = 0;
}
/** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/
DuelInfo* duel;
bool IsInDuelWith(Player const* player) const { return duel && duel->opponent == player && duel->startTime != 0; }
void UpdateDuelFlag(time_t currTime);
void CheckDuelDistance(time_t currTime);
void DuelComplete(DuelCompleteType type);
void SendDuelCountdown(uint32 counter);
bool IsGroupVisibleFor(Player* p) const;
bool IsInSameGroupWith(Player const* p) const;
bool IsInSameRaidWith(Player const* p) const { return p == this || (GetGroup() != NULL && GetGroup() == p->GetGroup()); }
void UninviteFromGroup();
static void RemoveFromGroup(Group* group, ObjectGuid guid);
void RemoveFromGroup() { RemoveFromGroup(GetGroup(), GetObjectGuid()); }
void SendUpdateToOutOfRangeGroupMembers();
void SetAllowLowLevelRaid(bool allow) { ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_ENABLE_LOW_LEVEL_RAID, allow); }
bool GetAllowLowLevelRaid() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_ENABLE_LOW_LEVEL_RAID); }
void SetInGuild(uint32 GuildId);
void SetGuildLevel(uint32 level) { SetUInt32Value(PLAYER_GUILDLEVEL, level); }
void SetRank(uint32 rankId){ SetUInt32Value(PLAYER_GUILDRANK, rankId); }
void SetGuildInvited(uint32 GuildId, ObjectGuid inviter = ObjectGuid()) { m_GuildIdInvited = GuildId; m_GuildInviterGuid = inviter; }
uint32 GetGuildId() const { return GetGuildGuid().GetCounter(); }
ObjectGuid GetGuildGuid() const { return GetGuidValue(OBJECT_FIELD_DATA); }
std::string GetGuildName() const;
static uint32 GetGuildIdFromDB(ObjectGuid guid);
static ObjectGuid GetGuildGuidFromDB(ObjectGuid guid);
void SendGuildDeclined(std::string name, bool autodecline);
uint32 GetRank() { return GetUInt32Value(PLAYER_GUILDRANK); }
static uint32 GetRankFromDB(ObjectGuid guid);
int GetGuildIdInvited() const { return m_GuildIdInvited; }
ObjectGuid GetGuildInviterGuid() const { return m_GuildInviterGuid; }
static void RemovePetitionsAndSigns(ObjectGuid guid);
void SendPetitionSignResult(ObjectGuid petitionGuid, Player* player, uint32 result);
void SendPetitionTurnInResult(uint32 result);
// Arena Team
void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot, ArenaType type)
{
SetArenaTeamInfoField(slot, ARENA_TEAM_ID, ArenaTeamId);
SetArenaTeamInfoField(slot, ARENA_TEAM_TYPE, type);
}
void SetArenaTeamInfoField(uint8 slot, ArenaTeamInfoType type, uint32 value)
{
SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + type, value);
}
uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_ID); }
uint32 GetArenaPersonalRating(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * ARENA_TEAM_END) + ARENA_TEAM_PERSONAL_RATING); }
static uint32 GetArenaTeamIdFromDB(ObjectGuid guid, ArenaType type);
void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
static void LeaveAllArenaTeams(ObjectGuid guid);
Difficulty GetDifficulty(bool isRaid) const { return isRaid ? m_raidDifficulty : m_dungeonDifficulty; }
Difficulty GetDungeonDifficulty() const { return m_dungeonDifficulty; }
Difficulty GetRaidDifficulty() const { return m_raidDifficulty; }
void SetDungeonDifficulty(Difficulty dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; }
void SetRaidDifficulty(Difficulty raid_difficulty) { m_raidDifficulty = raid_difficulty; }
bool UpdateSkill(uint32 skill_id, uint32 step);
bool UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step);
bool UpdateCraftSkill(uint32 spellid);
bool UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLevel, uint32 Multiplicator = 1);
bool UpdateFishingSkill();
float GetHealthBonusFromStamina();
float GetManaBonusFromIntellect();
bool UpdateStats(Stats stat) override;
bool UpdateAllStats() override;
void UpdateResistances(uint32 school) override;
void UpdateArmor() override;
void UpdateMaxHealth() override;
void UpdateMaxPower(Powers power) override;
void UpdateAttackPowerAndDamage(bool ranged = false) override;
void UpdateShieldBlockDamageValue();
void UpdateDamagePhysical(WeaponAttackType attType) override;
void ApplySpellPowerBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus();
void ApplyRatingMod(CombatRating cr, int32 value, bool apply);
void UpdateRating(CombatRating cr);
void UpdateAllRatings();
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage);
float GetMeleeCritFromAgility();
void GetDodgeFromAgility(float& diminishing, float& nondiminishing);
void GetParryFromStrength(float& diminishing, float& nondiminishing);
float GetSpellCritFromIntellect();
float OCTRegenMPPerSpirit();
float GetRatingMultiplier(CombatRating cr) const;
float GetRatingBonusValue(CombatRating cr) const;
// Returns base spellpower bonus from items without intellect bonus
uint32 GetBaseSpellPowerBonus() const { return m_baseSpellPower; }
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
void UpdateBlockPercentage();
void UpdateCritPercentage(WeaponAttackType attType);
void UpdateAllCritPercentages();
void UpdateParryPercentage();
void UpdateDodgePercentage();
void UpdateMeleeHitChances();
void UpdateRangedHitChances();
void UpdateSpellHitChances();
void UpdateAllSpellCritChances();
void UpdateSpellCritChance(uint32 school);
void UpdateExpertise(WeaponAttackType attType);
void UpdateArmorPenetration();
void ApplyManaRegenBonus(int32 amount, bool apply);
void ApplyHealthRegenBonus(int32 amount, bool apply);
void UpdateManaRegen();
void UpdateMasteryAuras();
void UpdateArmorSpecializations();
bool FitArmorSpecializationRules(SpellEntry const * spellProto) const;
ObjectGuid const& GetLootGuid() const { return m_lootGuid; }
void SetLootGuid(ObjectGuid const& guid) { m_lootGuid = guid; }
void RemovedInsignia(Player* looterPlr);
WorldSession* GetSession() const { return m_session; }
void SetSession(WorldSession* s) { m_session = s; }
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const override;
void SetPhaseAndMap(Player* target) const;
void DestroyForPlayer(Player* target, bool anim = false) const override;
void SendLogXPGain(uint32 GivenXP, Unit* victim, uint32 RestXP);
uint8 LastSwingErrorMsg() const { return m_swingErrorMsg; }
void SwingErrorMsg(uint8 val) { m_swingErrorMsg = val; }
// notifiers
void SendAttackSwingCantAttack();
void SendAttackSwingCancelAttack();
void SendAttackSwingDeadTarget();
void SendAttackSwingNotInRange();
void SendAttackSwingBadFacingAttack();
void SendAutoRepeatCancel(Unit* target);
void SendExplorationExperience(uint32 Area, uint32 Experience);
void SendDungeonDifficulty(bool IsInGroup);
void SendRaidDifficulty(bool IsInGroup);
void ResetInstances(InstanceResetMethod method, bool isRaid);
void SendResetInstanceSuccess(uint32 MapId);
void SendResetInstanceFailed(uint32 reason, uint32 MapId);
void SendResetFailedNotify(uint32 mapid);
bool SetPosition(float x, float y, float z, float orientation, bool teleport = false);
void UpdateUnderwaterState(Map* m, float x, float y, float z);
void SendMessageToSet(WorldPacket* data, bool self) const override;// overwrite Object::SendMessageToSet
void SendMessageToSetInRange(WorldPacket* data, float fist, bool self) const override;
// overwrite Object::SendMessageToSetInRange
void SendMessageToSetInRange(WorldPacket* data, float dist, bool self, bool own_team_only) const;
Corpse* GetCorpse() const;
void SpawnCorpseBones();
Corpse* CreateCorpse();
void KillPlayer();
uint32 GetResurrectionSpellId();
void ResurrectPlayer(float restore_percent, bool applySickness = false);
void BuildPlayerRepop();
void RepopAtGraveyard();
void DurabilityLossAll(double percent, bool inventory);
void DurabilityLoss(Item* item, double percent);
void DurabilityPointsLossAll(int32 points, bool inventory);
void DurabilityPointsLoss(Item* item, int32 points);
void DurabilityPointLossForEquipSlot(EquipmentSlots slot);
uint32 DurabilityRepairAll(bool cost, float discountMod, bool guildBank);
uint32 DurabilityRepair(uint16 pos, bool cost, float discountMod, bool guildBank);
void UpdateMirrorTimers();
void StopMirrorTimers()
{
StopMirrorTimer(FATIGUE_TIMER);
StopMirrorTimer(BREATH_TIMER);
StopMirrorTimer(FIRE_TIMER);
}
void SetRoot(bool enable) override;
void SetWaterWalk(bool enable) override;
void JoinedChannel(Channel* c);
void LeftChannel(Channel* c);
void CleanupChannels();
void UpdateLocalChannels(uint32 newZone);
void LeaveLFGChannel();
void SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step = 0);
uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus
uint16 GetPureMaxSkillValue(uint32 skill) const; // max
uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus
uint16 GetBaseSkillValue(uint32 skill) const; // skill value + perm. bonus
uint16 GetPureSkillValue(uint32 skill) const; // skill value
int16 GetSkillPermBonusValue(uint32 skill) const;
int16 GetSkillTempBonusValue(uint32 skill) const;
bool HasSkill(uint32 skill) const;
uint16 GetSkillStep(uint16 skill) const;
void learnSkillRewardedSpells(uint32 id, uint32 value);
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
bool IsBeingTeleported() const { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; }
bool IsBeingTeleportedNear() const { return mSemaphoreTeleport_Near; }
bool IsBeingTeleportedFar() const { return mSemaphoreTeleport_Far; }
void SetSemaphoreTeleportNear(bool semphsetting) { mSemaphoreTeleport_Near = semphsetting; }
void SetSemaphoreTeleportFar(bool semphsetting) { mSemaphoreTeleport_Far = semphsetting; }
void ProcessDelayedOperations();
void CheckAreaExploreAndOutdoor();
static Team TeamForRace(uint8 race);
Team GetTeam() const { return m_team; }
static uint32 getFactionForRace(uint8 race);
void setFactionForRace(uint8 race);
void InitDisplayIds();
bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const;
void RewardSinglePlayerAtKill(Unit* pVictim);
void RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource);
void RewardPlayerAndGroupAtCast(WorldObject* pRewardSource, uint32 spellid = 0);
bool isHonorOrXPTarget(Unit* pVictim) const;
ReputationMgr& GetReputationMgr() { return m_reputationMgr; }
ReputationMgr const& GetReputationMgr() const { return m_reputationMgr; }
ReputationRank GetReputationRank(uint32 faction_id) const;
void RewardReputation(Unit* pVictim, float rate);
void RewardReputation(Quest const* pQuest);
int32 CalculateReputationGain(ReputationSource source, int32 rep, int32 faction, uint32 creatureOrQuestLevel = 0, bool noAuraBonus = false);
void UpdateSkillsForLevel();
void UpdateSkillsToMaxSkillsForLevel(); // for .levelup
void ModifySkillBonus(uint32 skillid, int32 val, bool talent);
/*********************************************************/
/*** CURRENCY SYSTEM ***/
/*********************************************************/
uint32 GetCurrencyCount(uint32 id) const;
uint32 GetCurrencySeasonCount(uint32 id) const;
uint32 GetCurrencyWeekCount(uint32 id) const;
void SendCurrencies() const;
void ModifyCurrencyCount(uint32 id, int32 count, bool modifyWeek = true, bool modifySeason = true, bool ignoreMultipliers = false);
bool HasCurrencyCount(uint32 id, uint32 count) const { return GetCurrencyCount(id) >= count; }
bool HasCurrencySeasonCount(uint32 id, uint32 count) const { return GetCurrencySeasonCount(id) >= count; }
void SetCurrencyCount(uint32 id, uint32 count);
void SendCurrencyWeekCap(uint32 id) const;
void SendCurrencyWeekCap(CurrencyTypesEntry const * currency) const;
void SetCurrencyFlags(uint32 currencyId, uint8 flags);
void ResetCurrencyWeekCounts();
/*********************************************************/
/*** PVP SYSTEM ***/
/*********************************************************/
void UpdateHonorKills();
bool RewardHonor(Unit *pVictim, uint32 groupsize, float honor = -1);
void SendPvPRewards();
void SendRatedBGStats();
uint32 GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot);
// End of PvP System
void SetDrunkValue(uint8 newDrunkValue, uint32 itemid = 0);
uint16 GetDrunkValue() const { return GetByteValue(PLAYER_BYTES_3, 1); }
static DrunkenState GetDrunkenstateByValue(uint8 value);
uint32 GetDeathTimer() const { return m_deathTimer; }
uint32 GetCorpseReclaimDelay(bool pvp) const;
void UpdateCorpseReclaimDelay();
void SendCorpseReclaimDelay(bool load = false);
uint32 GetShieldBlockDamageValue() const override; // overwrite Unit version (virtual)
bool CanParry() const { return m_canParry; }
void SetCanParry(bool value);
bool CanBlock() const { return m_canBlock; }
void SetCanBlock(bool value);
bool CanDualWield() const { return m_canDualWield; }
void SetCanDualWield(bool value) { m_canDualWield = value; }
bool CanTitanGrip() const { return m_canTitanGrip; }
void SetCanTitanGrip(bool value) { m_canTitanGrip = value; }
bool CanTameExoticPets() const { return isGameMaster() || HasAuraType(SPELL_AURA_ALLOW_TAME_PET_TYPE); }
void SetRegularAttackTime();
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply);
float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const;
float GetTotalBaseModValue(BaseModGroup modGroup) const;
float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; }
void _ApplyAllStatBonuses();
void _RemoveAllStatBonuses();
float GetArmorPenetrationPct() const { return m_armorPenetrationPct; }
int32 GetSpellPenetrationItemMod() const { return m_spellPenetrationItemMod; }
void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply);
void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, Aura* aura, bool apply);
void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, Aura* aura, bool apply);
void _ApplyItemMods(Item* item, uint8 slot, bool apply);
void _RemoveAllItemMods();
void _ApplyAllItemMods();
void _ApplyAllLevelScaleItemMods(bool apply);
void _ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool apply, bool only_level_scale = false);
void _ApplyAmmoBonuses();
bool EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot);
void ToggleMetaGemsActive(uint8 exceptslot, bool apply);
void CorrectMetaGemEnchants(uint8 slot, bool apply);
void InitDataForForm(bool reapplyMods = false);
void ApplyItemEquipSpell(Item* item, bool apply, bool form_change = false);
void ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false);
void UpdateEquipSpellsAtFormChange();
void CastItemCombatSpell(Unit* Target, WeaponAttackType attType);
void CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 cast_count, uint32 glyphIndex);
void ApplyItemOnStoreSpell(Item* item, bool apply);
void DestroyItemWithOnStoreSpell(Item* item, uint32 spellId);
void SendEquipmentSetList();
void SetEquipmentSet(uint32 index, EquipmentSet eqset);
void DeleteEquipmentSet(uint64 setGuid);
void SendInitWorldStates(uint32 zone, uint32 area);
void SendUpdateWorldState(uint32 Field, uint32 Value);
void SendDirectMessage(WorldPacket* data) const;
void FillBGWeekendWorldStates(WorldPacket& data, uint32& count);
void SendAurasForTarget(Unit* target);
PlayerMenu* PlayerTalkClass;
std::vector<ItemSetEffect*> ItemSetEff;
void SendLoot(ObjectGuid guid, LootType loot_type);
void SendLootRelease(ObjectGuid guid);
void SendNotifyLootItemRemoved(uint8 lootSlot, bool currency = false);
void SendNotifyLootMoneyRemoved();
/*********************************************************/
/*** BATTLEGROUND SYSTEM ***/
/*********************************************************/
bool InBattleGround() const { return m_bgData.bgInstanceID != 0; }
bool InArena() const;
uint32 GetBattleGroundId() const { return m_bgData.bgInstanceID; }
BattleGroundTypeId GetBattleGroundTypeId() const { return m_bgData.bgTypeID; }
BattleGround* GetBattleGround() const;
bool InBattleGroundQueue() const
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId != BATTLEGROUND_QUEUE_NONE)
return true;
return false;
}
BattleGroundQueueTypeId GetBattleGroundQueueTypeId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgQueueTypeId; }
BattleGroundQueueTypeId GetBattleGroundQueueTypeIdByClientInstance(uint32 instanceId) const
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId)
return m_bgBattleGroundQueueID[i].bgQueueTypeId;
return BATTLEGROUND_QUEUE_NONE;
}
uint32 GetBattleGroundQueueIndex(BattleGroundQueueTypeId bgQueueTypeId) const
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
return i;
return PLAYER_MAX_BATTLEGROUND_QUEUES;
}
bool IsInvitedForBattleGroundQueueType(BattleGroundQueueTypeId bgQueueTypeId) const
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
return m_bgBattleGroundQueueID[i].invitedToInstance != 0;
return false;
}
bool InBattleGroundQueueForBattleGroundQueueType(BattleGroundQueueTypeId bgQueueTypeId) const
{
return GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES;
}
void SetBattleGroundId(uint32 val, BattleGroundTypeId bgTypeId)
{
m_bgData.bgInstanceID = val;
m_bgData.bgTypeID = bgTypeId;
m_bgData.m_needSave = true;
}
uint32 AddBattleGroundQueueId(BattleGroundQueueTypeId val)
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
{
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == BATTLEGROUND_QUEUE_NONE || m_bgBattleGroundQueueID[i].bgQueueTypeId == val)
{
m_bgBattleGroundQueueID[i].bgQueueTypeId = val;
m_bgBattleGroundQueueID[i].invitedToInstance = 0;
return i;
}
}
return PLAYER_MAX_BATTLEGROUND_QUEUES;
}
bool HasFreeBattleGroundQueueId()
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
return true;
return false;
}
void RemoveBattleGroundQueueId(BattleGroundQueueTypeId val)
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
{
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == val)
{
m_bgBattleGroundQueueID[i].bgQueueTypeId = BATTLEGROUND_QUEUE_NONE;
m_bgBattleGroundQueueID[i].invitedToInstance = 0;
return;
}
}
}
void SetInviteForBattleGroundQueueType(BattleGroundQueueTypeId bgQueueTypeId, uint32 instanceId)
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
m_bgBattleGroundQueueID[i].invitedToInstance = instanceId;
}
bool IsInvitedForBattleGroundInstance(uint32 instanceId) const
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId)
return true;
return false;
}
WorldLocation const& GetBattleGroundEntryPoint() const { return m_bgData.joinPos; }
void SetBattleGroundEntryPoint();
void SetBGTeam(Team team) { m_bgData.bgTeam = team; m_bgData.m_needSave = true; }
Team GetBGTeam() const { return m_bgData.bgTeam ? m_bgData.bgTeam : GetTeam(); }
void LeaveBattleground(bool teleportToEntryPoint = true);
bool CanJoinToBattleground() const;
bool CanReportAfkDueToLimit();
void ReportedAfkBy(Player* reporter);
void ClearAfkReports() { m_bgData.bgAfkReporter.clear(); }
bool GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const;
bool CanUseBattleGroundObject();
bool isTotalImmune();
// returns true if the player is in active state for capture point capturing
bool CanUseCapturePoint();
/*********************************************************/
/*** REST SYSTEM ***/
/*********************************************************/
bool isRested() const { return GetRestTime() >= 10 * IN_MILLISECONDS; }
uint32 GetXPRestBonus(uint32 xp);
uint32 GetRestTime() const { return m_restTime; }
void SetRestTime(uint32 v) { m_restTime = v; }
/*********************************************************/
/*** ENVIROMENTAL SYSTEM ***/
/*********************************************************/
uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage);
/*********************************************************/
/*** FLOOD FILTER SYSTEM ***/
/*********************************************************/
void UpdateSpeakTime();
bool CanSpeak() const;
void ChangeSpeakTime(int utime);
/*********************************************************/
/*** VARIOUS SYSTEMS ***/
/*********************************************************/
bool HasMovementFlag(MovementFlags f) const; // for script access to m_movementInfo.HasMovementFlag
void UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode);
void SetFallInformation(uint32 time, float z)
{
m_lastFallTime = time;
m_lastFallZ = z;
}
void HandleFall(MovementInfo const& movementInfo);
bool isMoving() const { return m_movementInfo.HasMovementFlag(movementFlagsMask); }
bool isMovingOrTurning() const { return m_movementInfo.HasMovementFlag(movementOrTurningFlagsMask); }
bool CanFly() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_CAN_FLY); }
bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_FLYING); }
bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED) || HasAuraType(SPELL_AURA_FLY); }
bool CanStartFlyInArea(uint32 mapid, uint32 zone, uint32 area) const;
void SetClientControl(Unit* target, uint8 allowMove);
void SetMover(Unit* target) { m_mover = target ? target : this; }
Unit* GetMover() const { return m_mover; }
bool IsSelfMover() const { return m_mover == this; }// normal case for player not controlling other unit
ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); }
// Transports
Transport* GetTransport() const { return m_transport; }
void SetTransport(Transport* t) { m_transport = t; }
float GetTransOffsetX() const { return m_movementInfo.GetTransportPos()->x; }
float GetTransOffsetY() const { return m_movementInfo.GetTransportPos()->y; }
float GetTransOffsetZ() const { return m_movementInfo.GetTransportPos()->z; }
float GetTransOffsetO() const { return m_movementInfo.GetTransportPos()->o; }
uint32 GetTransTime() const { return m_movementInfo.GetTransportTime(); }
int8 GetTransSeat() const { return m_movementInfo.GetTransportSeat(); }
uint32 GetSaveTimer() const { return m_nextSave; }
void SetSaveTimer(uint32 timer) { m_nextSave = timer; }
// Recall position
uint32 m_recallMap;
float m_recallX;
float m_recallY;
float m_recallZ;
float m_recallO;
void SaveRecallPosition();
void SetHomebindToLocation(WorldLocation const& loc, uint32 area_id);
void RelocateToHomebind() { SetLocationMapId(m_homebindMapId); Relocate(m_homebindX, m_homebindY, m_homebindZ); }
bool TeleportToHomebind(uint32 options = 0) { return TeleportTo(m_homebindMapId, m_homebindX, m_homebindY, m_homebindZ, GetOrientation(), options); }
Object* GetObjectByTypeMask(ObjectGuid guid, TypeMask typemask);
// currently visible objects at player client
GuidSet m_clientGUIDs;
bool HaveAtClient(WorldObject const* u) { return u == this || m_clientGUIDs.find(u->GetObjectGuid()) != m_clientGUIDs.end(); }
bool IsVisibleInGridForPlayer(Player* pl) const override;
bool IsVisibleGloballyFor(Player* pl) const;
void UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target);
template<class T>
void UpdateVisibilityOf(WorldObject const* viewPoint, T* target, UpdateData& data, std::set<WorldObject*>& visibleNow);
// Stealth detection system
void HandleStealthedUnitsDetection();
Camera& GetCamera() { return m_camera; }
virtual void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite Unit::SetPhaseMask
uint8 m_forced_speed_changes[MAX_MOVE_TYPE];
bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; }
void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; }
void RemoveAtLoginFlag(AtLoginFlags f, bool in_db_also = false);
// Temporarily removed pet cache
uint32 GetTemporaryUnsummonedPetNumber() const { return m_temporaryUnsummonedPetNumber; }
void SetTemporaryUnsummonedPetNumber(uint32 petnumber) { m_temporaryUnsummonedPetNumber = petnumber; }
void UnsummonPetTemporaryIfAny();
void ResummonPetTemporaryUnSummonedIfAny();
bool IsPetNeedBeTemporaryUnsummoned() const { return !IsInWorld() || !isAlive() || IsMounted() /*+in flight*/; }
void SendCinematicStart(uint32 CinematicSequenceId);
void SendMovieStart(uint32 MovieId);
/*********************************************************/
/*** INSTANCE SYSTEM ***/
/*********************************************************/
typedef UNORDERED_MAP < uint32 /*mapId*/, InstancePlayerBind > BoundInstancesMap;
void UpdateHomebindTime(uint32 time);
uint32 m_HomebindTimer;
bool m_InstanceValid;
// permanent binds and solo binds by difficulty
BoundInstancesMap m_boundInstances[MAX_DIFFICULTY];
InstancePlayerBind* GetBoundInstance(uint32 mapid, Difficulty difficulty);
BoundInstancesMap& GetBoundInstances(Difficulty difficulty) { return m_boundInstances[difficulty]; }
void UnbindInstance(uint32 mapid, Difficulty difficulty, bool unload = false);
void UnbindInstance(BoundInstancesMap::iterator& itr, Difficulty difficulty, bool unload = false);
InstancePlayerBind* BindToInstance(DungeonPersistentState* save, bool permanent, bool load = false);
void SendRaidInfo();
void SendSavedInstances();
static void ConvertInstancesToGroup(Player* player, Group* group = NULL, ObjectGuid player_guid = ObjectGuid());
DungeonPersistentState* GetBoundInstanceSaveForSelfOrGroup(uint32 mapid);
AreaLockStatus GetAreaTriggerLockStatus(AreaTrigger const* at, Difficulty difficulty, uint32& miscRequirement);
void SendTransferAbortedByLockStatus(MapEntry const* mapEntry, AreaLockStatus lockStatus, uint32 miscRequirement = 0);
/*********************************************************/
/*** GROUP SYSTEM ***/
/*********************************************************/
Group* GetGroupInvite() { return m_groupInvite; }
void SetGroupInvite(Group* group) { m_groupInvite = group; }
Group* GetGroup() { return m_group.getTarget(); }
const Group* GetGroup() const { return (const Group*)m_group.getTarget(); }
GroupReference& GetGroupRef() { return m_group; }
void SetGroup(Group* group, int8 subgroup = -1);
uint8 GetSubGroup() const { return m_group.getSubGroup(); }
uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; }
void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; }
const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; }
void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); }
Player* GetNextRandomRaidMember(float radius);
PartyResult CanUninviteFromGroup() const;
// BattleGround Group System
void SetBattleGroundRaid(Group* group, int8 subgroup = -1);
void RemoveFromBattleGroundRaid();
Group* GetOriginalGroup() { return m_originalGroup.getTarget(); }
GroupReference& GetOriginalGroupRef() { return m_originalGroup; }
uint8 GetOriginalSubGroup() const { return m_originalGroup.getSubGroup(); }
void SetOriginalGroup(Group* group, int8 subgroup = -1);
GridReference<Player>& GetGridRef() { return m_gridRef; }
MapReference& GetMapRef() { return m_mapRef; }
bool isAllowedToLoot(Creature* creature);
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
// Rune functions, need check getClass() == CLASS_DEATH_KNIGHT before access
uint8 GetRunesState() const { return m_runes->runeState; }
RuneType GetBaseRune(uint8 index) const { return RuneType(m_runes->runes[index].BaseRune); }
RuneType GetCurrentRune(uint8 index) const { return RuneType(m_runes->runes[index].CurrentRune); }
uint16 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const;
void SetBaseRune(uint8 index, RuneType baseRune) { m_runes->runes[index].BaseRune = baseRune; }
void SetCurrentRune(uint8 index, RuneType currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
void SetRuneCooldown(uint8 index, uint16 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); }
void ConvertRune(uint8 index, RuneType newType);
bool ActivateRunes(RuneType type, uint32 count);
void ResyncRunes();
void AddRunePower(uint8 index);
void InitRunes();
AchievementMgr const& GetAchievementMgr() const { return m_achievementMgr; }
AchievementMgr& GetAchievementMgr() { return m_achievementMgr; }
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1 = 0, uint32 miscvalue2 = 0, Unit* unit = NULL, uint32 time = 0);
void StartTimedAchievementCriteria(AchievementCriteriaTypes type, uint32 timedRequirementId, time_t startTime = 0);
bool HasTitle(uint32 bitIndex) const;
bool HasTitle(CharTitlesEntry const* title) const { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title, bool lost = false);
bool canSeeSpellClickOn(Creature const* creature) const;
protected:
uint32 m_contestedPvPTimer;
/*********************************************************/
/*** BATTLEGROUND SYSTEM ***/
/*********************************************************/
/*
this is an array of BG queues (BgTypeIDs) in which is player
*/
struct BgBattleGroundQueueID_Rec
{
BattleGroundQueueTypeId bgQueueTypeId;
uint32 invitedToInstance;
};
BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES];
BGData m_bgData;
/*********************************************************/
/*** QUEST SYSTEM ***/
/*********************************************************/
// We allow only one timed quest active at the same time. Below can then be simple value instead of set.
typedef std::set<uint32> QuestSet;
QuestSet m_timedquests;
QuestSet m_weeklyquests;
QuestSet m_monthlyquests;
ObjectGuid m_dividerGuid;
uint32 m_ingametime;
/*********************************************************/
/*** LOAD SYSTEM ***/
/*********************************************************/
void _LoadActions(QueryResult* result);
void _LoadAuras(QueryResult* result, uint32 timediff);
void _LoadBoundInstances(QueryResult* result);
void _LoadInventory(QueryResult* result, uint32 timediff);
void _LoadItemLoot(QueryResult* result);
void _LoadMails(QueryResult* result);
void _LoadMailedItems(QueryResult* result);
void _LoadQuestStatus(QueryResult* result);
void _LoadDailyQuestStatus(QueryResult* result);
void _LoadWeeklyQuestStatus(QueryResult* result);
void _LoadMonthlyQuestStatus(QueryResult* result);
void _LoadGroup(QueryResult* result);
void _LoadSkills(QueryResult* result);
void _LoadSpells(QueryResult* result);
void _LoadTalents(QueryResult* result);
void _LoadFriendList(QueryResult* result);
bool _LoadHomeBind(QueryResult* result);
void _LoadDeclinedNames(QueryResult* result);
void _LoadArenaTeamInfo(QueryResult* result);
void _LoadEquipmentSets(QueryResult* result);
void _LoadBGData(QueryResult* result);
void _LoadGlyphs(QueryResult* result);
void _LoadIntoDataField(const char* data, uint32 startOffset, uint32 count);
/*********************************************************/
/*** SAVE SYSTEM ***/
/*********************************************************/
void _SaveActions();
void _SaveAuras();
void _SaveInventory();
void _SaveMail();
void _SaveQuestStatus();
void _SaveDailyQuestStatus();
void _SaveWeeklyQuestStatus();
void _SaveMonthlyQuestStatus();
void _SaveSkills();
void _SaveSpells();
void _SaveEquipmentSets();
void _SaveBGData();
void _SaveGlyphs();
void _SaveTalents();
void _SaveStats();
void _SetCreateBits(UpdateMask* updateMask, Player* target) const override;
void _SetUpdateBits(UpdateMask* updateMask, Player* target) const override;
/*********************************************************/
/*** ENVIRONMENTAL SYSTEM ***/
/*********************************************************/
void HandleSobering();
void SendMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, int32 Regen);
void StopMirrorTimer(MirrorTimerType Type);
void HandleDrowning(uint32 time_diff);
int32 getMaxTimer(MirrorTimerType timer);
/*********************************************************/
/*** CURRENCY SYSTEM ***/
/*********************************************************/
PlayerCurrenciesMap m_currencies;
uint32 GetCurrencyWeekCap(CurrencyTypesEntry const * currency) const;
uint32 GetCurrencyTotalCap(CurrencyTypesEntry const * currency) const;
void _LoadCurrencies(QueryResult* result);
void _SaveCurrencies();
void outDebugStatsValues() const;
ObjectGuid m_lootGuid;
Team m_team;
uint32 m_nextSave;
time_t m_speakTime;
uint32 m_speakCount;
Difficulty m_dungeonDifficulty;
Difficulty m_raidDifficulty;
time_t m_lastHonorKillsUpdateTime;
uint32 m_atLoginFlags;
Item* m_items[PLAYER_SLOTS_COUNT];
uint32 m_currentBuybackSlot;
std::vector<Item*> m_itemUpdateQueue;
bool m_itemUpdateQueueBlocked;
uint32 m_ExtraFlags;
ObjectGuid m_curSelectionGuid;
ObjectGuid m_comboTargetGuid;
int8 m_comboPoints;
QuestStatusMap mQuestStatus;
SkillStatusMap mSkillStatus;
uint32 m_GuildIdInvited;
ObjectGuid m_GuildInviterGuid;
uint32 m_ArenaTeamIdInvited;
PlayerMails m_mail;
PlayerSpellMap m_spells;
PlayerTalentMap m_talents[MAX_TALENT_SPEC_COUNT];
uint32 m_talentsPrimaryTree[MAX_TALENT_SPEC_COUNT];
SpellCooldowns m_spellCooldowns;
uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use
GlobalCooldownMgr m_GlobalCooldownMgr;
uint8 m_activeSpec;
uint8 m_specsCount;
ActionButtonList m_actionButtons[MAX_TALENT_SPEC_COUNT];
Glyph m_glyphs[MAX_TALENT_SPEC_COUNT][MAX_GLYPH_SLOT_INDEX];
float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint16 m_baseSpellPower;
uint16 m_baseManaRegen;
uint32 m_baseHealthRegen;
float m_armorPenetrationPct;
int32 m_spellPenetrationItemMod;
AuraList m_spellMods[MAX_SPELLMOD];
EnchantDurationList m_enchantDuration;
ItemDurationList m_itemDuration;
ObjectGuid m_resurrectGuid;
uint32 m_resurrectMap;
float m_resurrectX, m_resurrectY, m_resurrectZ;
uint32 m_resurrectHealth, m_resurrectMana;
WorldSession* m_session;
typedef std::list<Channel*> JoinedChannelsList;
JoinedChannelsList m_channels;
uint32 m_cinematic;
TradeData* m_trade;
bool m_DailyQuestChanged;
bool m_WeeklyQuestChanged;
bool m_MonthlyQuestChanged;
uint32 m_drunkTimer;
uint32 m_weaponChangeTimer;
uint32 m_zoneUpdateId;
uint32 m_zoneUpdateTimer;
uint32 m_areaUpdateId;
uint32 m_positionStatusUpdateTimer;
uint32 m_deathTimer;
time_t m_deathExpireTime;
uint32 m_restTime;
uint32 m_WeaponProficiency;
uint32 m_ArmorProficiency;
bool m_canParry;
bool m_canBlock;
bool m_canDualWield;
bool m_canTitanGrip;
uint8 m_swingErrorMsg;
float m_ammoDPS;
//////////////////// Rest SystemPlayerSpell
time_t time_inn_enter;
uint32 inn_trigger_id;
float m_rest_bonus;
RestType rest_type;
//////////////////// Rest System/////////////////////
// Transports
Transport* m_transport;
uint32 m_freeTalentPoints;
uint32 m_resetTalentsCost;
time_t m_resetTalentsTime;
uint32 m_usedTalentCount;
uint32 m_questRewardTalentCount;
// Social
PlayerSocial *m_social;
// Groups
GroupReference m_group;
GroupReference m_originalGroup;
Group* m_groupInvite;
uint32 m_groupUpdateMask;
uint64 m_auraUpdateMask;
// Player summoning
time_t m_summon_expire;
uint32 m_summon_mapid;
float m_summon_x;
float m_summon_y;
float m_summon_z;
DeclinedName* m_declinedname;
Runes* m_runes;
EquipmentSets m_EquipmentSets;
uint8 m_slot;
/// class dependent melee diminishing constant for dodge/parry/missed chances
static const float m_diminishing_k[MAX_CLASSES];
private:
void _HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEntry const* spellInfo);
// internal common parts for CanStore/StoreItem functions
InventoryResult _CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const* pProto, uint32& count, bool swap, Item* pSrcItem) const;
InventoryResult _CanStoreItem_InBag(uint8 bag, ItemPosCountVec& dest, ItemPrototype const* pProto, uint32& count, bool merge, bool non_specialized, Item* pSrcItem, uint8 skip_bag, uint8 skip_slot) const;
InventoryResult _CanStoreItem_InInventorySlots(uint8 slot_begin, uint8 slot_end, ItemPosCountVec& dest, ItemPrototype const* pProto, uint32& count, bool merge, Item* pSrcItem, uint8 skip_bag, uint8 skip_slot) const;
Item* _StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool update);
void AdjustQuestReqItemCount(Quest const* pQuest, QuestStatusData& questStatusData);
void SetCanDelayTeleport(bool setting) { m_bCanDelayTeleport = setting; }
bool IsHasDelayedTeleport() const
{
// we should not execute delayed teleports for now dead players but has been alive at teleport
// because we don't want player's ghost teleported from graveyard
return m_bHasDelayedTeleport && (isAlive() || !m_bHasBeenAliveAtDelayedTeleport);
}
bool SetDelayedTeleportFlagIfCan()
{
m_bHasDelayedTeleport = m_bCanDelayTeleport;
m_bHasBeenAliveAtDelayedTeleport = isAlive();
return m_bHasDelayedTeleport;
}
void ScheduleDelayedOperation(uint32 operation)
{
if (operation < DELAYED_END)
m_DelayedOperations |= operation;
}
void _fillGearScoreData(Item* item, GearScoreVec* gearScore, uint32& twoHandScore);
Unit* m_mover;
Camera m_camera;
GridReference<Player> m_gridRef;
MapReference m_mapRef;
// Homebind coordinates
uint32 m_homebindMapId;
uint16 m_homebindAreaId;
float m_homebindX;
float m_homebindY;
float m_homebindZ;
uint32 m_lastFallTime;
float m_lastFallZ;
LiquidTypeEntry const* m_lastLiquid;
int32 m_MirrorTimer[MAX_TIMERS];
uint8 m_MirrorTimerFlags;
uint8 m_MirrorTimerFlagsLast;
bool m_isInWater;
// Current teleport data
WorldLocation m_teleport_dest;
uint32 m_teleport_options;
bool mSemaphoreTeleport_Near;
bool mSemaphoreTeleport_Far;
uint32 m_DelayedOperations;
bool m_bCanDelayTeleport;
bool m_bHasDelayedTeleport;
bool m_bHasBeenAliveAtDelayedTeleport;
uint32 m_DetectInvTimer;
// Temporary removed pet cache
uint32 m_temporaryUnsummonedPetNumber;
AchievementMgr m_achievementMgr;
ReputationMgr m_reputationMgr;
uint32 m_timeSyncCounter;
uint32 m_timeSyncTimer;
uint32 m_timeSyncClient;
uint32 m_timeSyncServer;
uint32 m_cachedGS;
};
void AddItemsSetItem(Player* player, Item* item);
void RemoveItemsSetItem(Player* player, ItemPrototype const* proto);
#endif