From b4d97ccf7750f3ad656eafc364aaa9c1dd142eab Mon Sep 17 00:00:00 2001 From: Yaki Khadafi Date: Mon, 13 Aug 2012 12:46:10 +0300 Subject: [PATCH] [0072] Fix world teleport and use normalized orientation in some more places Signed-off-by: Yaki Khadafi --- src/game/Creature.h | 4 +- src/game/DBCStores.cpp | 1 + src/game/MovementHandler.cpp | 9 +- src/game/Object.cpp | 4 +- src/game/Object.h | 5 +- src/game/Opcodes.cpp | 12 +- src/game/Opcodes.h | 12 +- src/game/Player.cpp | 1068 ++++++++++++++++++++-------------- src/game/Player.h | 2 - src/game/WorldSession.cpp | 6 + src/shared/revision_nr.h | 2 +- 11 files changed, 663 insertions(+), 462 deletions(-) diff --git a/src/game/Creature.h b/src/game/Creature.h index ec53023a2..dee330ab0 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -414,11 +414,11 @@ struct CreatureCreatePos public: // exactly coordinates used CreatureCreatePos(Map* map, float x, float y, float z, float o, uint32 phaseMask) - : m_map(map), m_phaseMask(phaseMask), m_closeObject(NULL), m_angle(0.0f), m_dist(0.0f) { m_pos.x = x; m_pos.y = y; m_pos.z = z; m_pos.o = o; } + : m_map(map), m_phaseMask(phaseMask), m_closeObject(NULL), m_angle(0.0f), m_dist(0.0f) { m_pos.x = x; m_pos.y = y; m_pos.z = z; m_pos.o = NormalizeOrientation(o); } // if dist == 0.0f -> exactly object coordinates used, in other case close point to object (CONTACT_DIST can be used as minimal distances) CreatureCreatePos(WorldObject* closeObject, float ori, float dist = 0.0f, float angle = 0.0f) : m_map(closeObject->GetMap()), m_phaseMask(closeObject->GetPhaseMask()), - m_closeObject(closeObject), m_angle(angle), m_dist(dist) { m_pos.o = ori; } + m_closeObject(closeObject), m_angle(angle), m_dist(dist) { m_pos.o = NormalizeOrientation(ori); } public: Map* GetMap() const { return m_map; } uint32 GetPhaseMask() const { return m_phaseMask; } diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index b74b98010..0785941b2 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -21,6 +21,7 @@ #include "Log.h" #include "ProgressBar.h" #include "SharedDefines.h" +#include "SpellAuraDefines.h" #include "ObjectGuid.h" #include "SpellAuraDefines.h" diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 1ec3a2791..f92f31730 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -202,14 +202,15 @@ void WorldSession::HandleMoveWorldportAckOpcode() void WorldSession::HandleMoveTeleportAckOpcode(WorldPacket& recv_data) { - DEBUG_LOG("MSG_MOVE_TELEPORT_ACK"); + DEBUG_LOG("CMSG_MOVE_TELEPORT_ACK"); ObjectGuid guid; - - recv_data >> guid.ReadAsPacked(); - uint32 counter, time; recv_data >> counter >> time; + + recv_data.ReadGuidMask<5, 0, 1, 6, 3, 7, 2, 4>(guid); + recv_data.ReadGuidBytes<4, 2, 7, 6, 5, 1, 3, 0>(guid); + DEBUG_LOG("Guid: %s", guid.GetString().c_str()); DEBUG_LOG("Counter %u, time %u", counter, time / IN_MILLISECONDS); diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 530f04216..a0b4a329c 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1093,7 +1093,7 @@ void WorldObject::Relocate(float x, float y, float z, float orientation) m_position.x = x; m_position.y = y; m_position.z = z; - m_position.o = orientation; + m_position.o = NormalizeOrientation(orientation); if (isType(TYPEMASK_UNIT)) ((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, orientation); @@ -1111,7 +1111,7 @@ void WorldObject::Relocate(float x, float y, float z) void WorldObject::SetOrientation(float orientation) { - m_position.o = orientation; + m_position.o = NormalizeOrientation(orientation); if (isType(TYPEMASK_UNIT)) ((Unit*)this)->m_movementInfo.ChangeOrientation(orientation); diff --git a/src/game/Object.h b/src/game/Object.h index 87728f22d..6a740c6ce 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -25,6 +25,7 @@ #include "UpdateData.h" #include "ObjectGuid.h" #include "Camera.h" +#include "Util.h" #include #include @@ -88,9 +89,9 @@ struct WorldLocation float coord_z; float orientation; explicit WorldLocation(uint32 _mapid = 0, float _x = 0, float _y = 0, float _z = 0, float _o = 0) - : mapid(_mapid), coord_x(_x), coord_y(_y), coord_z(_z), orientation(_o) {} + : mapid(_mapid), coord_x(_x), coord_y(_y), coord_z(_z), orientation(NormalizeOrientation(_o)) {} WorldLocation(WorldLocation const& loc) - : mapid(loc.mapid), coord_x(loc.coord_x), coord_y(loc.coord_y), coord_z(loc.coord_z), orientation(loc.orientation) {} + : mapid(loc.mapid), coord_x(loc.coord_x), coord_y(loc.coord_y), coord_z(loc.coord_z), orientation(NormalizeOrientation(loc.orientation)) {} }; diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 79dcd3eca..89329c911 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -108,8 +108,8 @@ void InitializeOpcodes() OPCODE(SMSG_CHAR_DELETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(CMSG_PLAYER_LOGIN, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandlePlayerLoginOpcode ); OPCODE(SMSG_NEW_WORLD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_TRANSFER_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //OPCODE(SMSG_TRANSFER_ABORTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_TRANSFER_PENDING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_TRANSFER_ABORTED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_CHARACTER_LOGIN_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_LOGIN_SETTIMESPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_GAMETIME_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -260,9 +260,9 @@ void InitializeOpcodes() OPCODE(CMSG_MOVE_SET_RUN_MODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); OPCODE(CMSG_MOVE_SET_WALK_MODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); //OPCODE(MSG_MOVE_TOGGLE_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - OPCODE(MSG_MOVE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + OPCODE(SMSG_MOVE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //OPCODE(MSG_MOVE_TELEPORT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //OPCODE(MSG_MOVE_TELEPORT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveTeleportAckOpcode ); + OPCODE(CMSG_MOVE_TELEPORT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveTeleportAckOpcode ); //OPCODE(MSG_MOVE_TOGGLE_FALL_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); OPCODE(CMSG_MOVE_FALL_LAND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); OPCODE(CMSG_MOVE_START_SWIM, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); @@ -283,7 +283,7 @@ void InitializeOpcodes() //OPCODE(MSG_MOVE_TOGGLE_COLLISION_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); OPCODE(CMSG_MOVE_SET_FACING, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); OPCODE(CMSG_MOVE_SET_PITCH, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - //OPCODE(MSG_MOVE_WORLDPORT_ACK, STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode ); + OPCODE(MSG_MOVE_WORLDPORT_ACK, STATUS_TRANSFER, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveWorldportAckOpcode ); OPCODE(SMSG_MONSTER_MOVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_MOVE_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); OPCODE(SMSG_MOVE_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -824,7 +824,7 @@ void InitializeOpcodes() //OPCODE(SMSG_PET_UNLEARN_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_PARTY_MEMBER_STATS_FULL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(CMSG_PET_SPELL_AUTOCAST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePetSpellAutocastOpcode ); - //OPCODE(SMSG_WEATHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + OPCODE(SMSG_WEATHER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_PLAY_TIME_WARNING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_MINIGAME_SETUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //OPCODE(SMSG_MINIGAME_STATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index dec92c9d9..2e3b2a86a 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -102,8 +102,8 @@ enum Opcodes SMSG_CHAR_DELETE = 0x0304, // 4.3.4 15595 CMSG_PLAYER_LOGIN = 0x05B1, // 4.3.4 15595 SMSG_NEW_WORLD = 0x79B1, // 4.3.4 15595 - SMSG_TRANSFER_PENDING = 0x1040, - SMSG_TRANSFER_ABORTED = 0x1041, + SMSG_TRANSFER_PENDING = 0x18A6, // 4.3.4 15595 + SMSG_TRANSFER_ABORTED = 0x0537, // 4.3.4 15595 SMSG_CHARACTER_LOGIN_FAILED = 0x1042, SMSG_LOGIN_SETTIMESPEED = 0x4D15, // 4.3.4 15595 SMSG_GAMETIME_UPDATE = 0x1044, @@ -254,9 +254,9 @@ enum Opcodes CMSG_MOVE_SET_RUN_MODE = 0x791A, // 4.3.4 15595 CMSG_MOVE_SET_WALK_MODE = 0x7002, // 4.3.4 15595 MSG_MOVE_TOGGLE_LOGGING = 0x10C5, - MSG_MOVE_TELEPORT = 0x55A0, // 4.3.4 15595 + SMSG_MOVE_TELEPORT = 0x55A0, // 4.3.4 15595 MSG_MOVE_TELEPORT_CHEAT = 0x10C7, - MSG_MOVE_TELEPORT_ACK = 0x10C8, + CMSG_MOVE_TELEPORT_ACK = 0x390C, // 4.3.4 15595 MSG_MOVE_TOGGLE_FALL_LOGGING = 0x10C9, CMSG_MOVE_FALL_LAND = 0x380A, // 4.3.4 15595 CMSG_MOVE_START_SWIM = 0x3206, // 4.3.4 15595 @@ -277,7 +277,7 @@ enum Opcodes MSG_MOVE_TOGGLE_COLLISION_CHEAT = 0x10DA, CMSG_MOVE_SET_FACING = 0x7914, // 4.3.4 15595 CMSG_MOVE_SET_PITCH = 0x7312, // 4.3.4 15595 - MSG_MOVE_WORLDPORT_ACK = 0x10DD, + MSG_MOVE_WORLDPORT_ACK = 0x2411, // 4.3.4 15595 SMSG_MONSTER_MOVE = 0x6E17, // 4.3.4 15595 SMSG_MOVE_WATER_WALK = 0x75B1, // 4.3.4 15595 SMSG_MOVE_LAND_WALK = 0x34B7, // 4.3.4 15595 @@ -809,7 +809,7 @@ enum Opcodes SMSG_PET_UNLEARN_CONFIRM = 0x12F2, SMSG_PARTY_MEMBER_STATS_FULL = 0x12F3, CMSG_PET_SPELL_AUTOCAST = 0x12F4, - SMSG_WEATHER = 0x12F5, + SMSG_WEATHER = 0x2904, // 4.3.4 15595 SMSG_PLAY_TIME_WARNING = 0x12F6, SMSG_MINIGAME_SETUP = 0x12F7, SMSG_MINIGAME_STATE = 0x12F8, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8a08f287b..3706b067e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -62,24 +62,13 @@ #include "Mail.h" #include "SpellAuras.h" #include "DBCStores.h" +#include "DB2Stores.h" #include "SQLStorages.h" #include #define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS) -#define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3)) -#define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1) -#define PLAYER_SKILL_BONUS_INDEX(x) (PLAYER_SKILL_INDEX(x)+2) - -#define SKILL_VALUE(x) PAIR32_LOPART(x) -#define SKILL_MAX(x) PAIR32_HIPART(x) -#define MAKE_SKILL_VALUE(v, m) MAKE_PAIR32(v,m) - -#define SKILL_TEMP_BONUS(x) int16(PAIR32_LOPART(x)) -#define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x)) -#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t,p) - enum CharacterFlags { CHARACTER_FLAG_NONE = 0x00000000, @@ -274,6 +263,26 @@ std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi) ss << taxi.m_taximask[i] << " "; return ss; } + +SpellModifier::SpellModifier( SpellModOp _op, SpellModType _type, int32 _value, SpellEntry const* spellEntry, SpellEffectIndex eff, int16 _charges /*= 0*/ ) : op(_op), type(_type), charges(_charges), value(_value), spellId(spellEntry->Id), lastAffected(NULL) +{ + mask = spellEntry->GetEffectSpellClassMask(eff); +} + +SpellModifier::SpellModifier( SpellModOp _op, SpellModType _type, int32 _value, Aura const* aura, int16 _charges /*= 0*/ ) : op(_op), type(_type), charges(_charges), value(_value), spellId(aura->GetId()), lastAffected(NULL) +{ + mask = aura->GetAuraSpellClassMask(); +} + +bool SpellModifier::isAffectedOnSpell( SpellEntry const *spell ) const +{ + SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId); + // False if affect_spell == NULL or spellFamily not equal + if (!affect_spell || affect_spell->GetSpellFamilyName() != spell->GetSpellFamilyName()) + return false; + return spell->IsFitToFamilyMask(mask); +} + //== TradeData ================================================= TradeData* TradeData::GetTraderData() const @@ -425,6 +434,7 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT); m_social = NULL; + m_guildId = 0; // group is initialized in the reference constructor SetGroupInvite(NULL); @@ -541,6 +551,8 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ // Honor System m_lastHonorUpdateTime = time(NULL); + m_honorPoints = 0; + m_arenaPoints = 0; // Player summoning m_summon_expire = 0; @@ -677,18 +689,16 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c SetUInt16Value(PLAYER_BYTES_3, 0, gender); // only GENDER_MALE/GENDER_FEMALE (1 bit) allowed, drunk state = 0 SetByteValue(PLAYER_BYTES_3, 3, 0); // BattlefieldArenaFaction (0 or 1) - SetUInt32Value(PLAYER_GUILDID, 0); - SetUInt32Value(PLAYER_GUILDRANK, 0); - SetUInt32Value(PLAYER_GUILD_TIMESTAMP, 0); + SetInGuild( 0 ); + SetUInt32Value( PLAYER_GUILDRANK, 0 ); + SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 ); for (int i = 0; i < KNOWN_TITLES_SIZE; ++i) SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES + i, 0); // 0=disabled SetUInt32Value(PLAYER_CHOSEN_TITLE, 0); - SetUInt32Value(PLAYER_FIELD_KILLS, 0); - SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); - SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); + SetUInt32Value( PLAYER_FIELD_KILLS, 0 ); + SetUInt32Value( PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0 ); // set starting level uint32 start_level = getClass() != CLASS_DEATH_KNIGHT @@ -836,6 +846,9 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c } // all item positions resolved + if (info->phaseMap != 0) + CharacterDatabase.PExecute("REPLACE INTO `character_phase_data` (`guid`, `map`) VALUES (%u, %u)", guidlow, info->phaseMap); + return true; } @@ -1439,7 +1452,7 @@ void Player::SetDeathState(DeathState s) } } -bool Player::BuildEnumData(QueryResult* result, WorldPacket* p_data) +bool Player::BuildEnumData( QueryResult * result, ByteBuffer * p_data ) { // 0 1 2 3 4 5 6 7 // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.playerBytes, characters.playerBytes2, characters.level, " @@ -1448,139 +1461,146 @@ bool Player::BuildEnumData(QueryResult* result, WorldPacket* p_data) // 15 16 17 18 19 20 // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, character_declinedname.genitive " - Field* fields = result->Fetch(); + Field *fields = result->Fetch(); + + uint32 Guid = fields[0].GetUInt32(); + uint64 GuildGuid = fields[13].GetUInt64(); - uint32 guid = fields[0].GetUInt32(); uint8 pRace = fields[2].GetUInt8(); uint8 pClass = fields[3].GetUInt8(); - - PlayerInfo const* info = sObjectMgr.GetPlayerInfo(pRace, pClass); - if (!info) - { - sLog.outError("Player %u has incorrect race/class pair. Don't build enum.", guid); - return false; - } - - *p_data << ObjectGuid(HIGHGUID_PLAYER, guid); - *p_data << fields[1].GetString(); // name - *p_data << uint8(pRace); // race - *p_data << uint8(pClass); // class - *p_data << uint8(fields[4].GetUInt8()); // gender - + uint8 gender = fields[4].GetUInt8(); uint32 playerBytes = fields[5].GetUInt32(); - *p_data << uint8(playerBytes); // skin - *p_data << uint8(playerBytes >> 8); // face - *p_data << uint8(playerBytes >> 16); // hair style - *p_data << uint8(playerBytes >> 24); // hair color - - uint32 playerBytes2 = fields[6].GetUInt32(); - *p_data << uint8(playerBytes2 & 0xFF); // facial hair - - *p_data << uint8(fields[7].GetUInt8()); // level - *p_data << uint32(fields[8].GetUInt32()); // zone - *p_data << uint32(fields[9].GetUInt32()); // map - - *p_data << fields[10].GetFloat(); // x - *p_data << fields[11].GetFloat(); // y - *p_data << fields[12].GetFloat(); // z - - *p_data << uint32(fields[13].GetUInt32()); // guild id - - uint32 char_flags = 0; + uint8 level = fields[7].GetUInt8(); uint32 playerFlags = fields[14].GetUInt32(); uint32 atLoginFlags = fields[15].GetUInt32(); - if (playerFlags & PLAYER_FLAGS_HIDE_HELM) - char_flags |= CHARACTER_FLAG_HIDE_HELM; - if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK) - char_flags |= CHARACTER_FLAG_HIDE_CLOAK; - if (playerFlags & PLAYER_FLAGS_GHOST) - char_flags |= CHARACTER_FLAG_GHOST; - if (atLoginFlags & AT_LOGIN_RENAME) - char_flags |= CHARACTER_FLAG_RENAME; - if (sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED)) + uint32 zone = fields[8].GetUInt32(); + uint32 petDisplayId = 0; + uint32 petLevel = 0; + uint32 petFamily = 0; + uint32 char_flags = 0; + + uint8 Guid0 = uint8(Guid); + uint8 Guid1 = uint8(Guid >> 8); + uint8 Guid2 = uint8(Guid >> 16); + uint8 Guid3 = uint8(Guid >> 24); + + // show pet at selection character in character list only for non-ghost character + if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT)) { - if (!fields[20].GetCppString().empty()) + uint32 entry = fields[16].GetUInt32(); + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); + if(cInfo) + { + petDisplayId = fields[17].GetUInt32(); + petLevel = fields[18].GetUInt32(); + petFamily = cInfo->family; + } + } + + if(playerFlags & PLAYER_FLAGS_HIDE_HELM) + char_flags |= CHARACTER_FLAG_HIDE_HELM; + if(playerFlags & PLAYER_FLAGS_HIDE_CLOAK) + char_flags |= CHARACTER_FLAG_HIDE_CLOAK; + if(playerFlags & PLAYER_FLAGS_GHOST) + char_flags |= CHARACTER_FLAG_GHOST; + if(atLoginFlags & AT_LOGIN_RENAME) + char_flags |= CHARACTER_FLAG_RENAME; + if(sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED)) + { + if(!fields[20].GetCppString().empty()) char_flags |= CHARACTER_FLAG_DECLINED; } else char_flags |= CHARACTER_FLAG_DECLINED; - *p_data << uint32(char_flags); // character flags - // character customize flags - *p_data << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? CHAR_CUSTOMIZE_FLAG_CUSTOMIZE : CHAR_CUSTOMIZE_FLAG_NONE); - // First login - *p_data << uint8(atLoginFlags & AT_LOGIN_FIRST ? 1 : 0); - // Pets info + PlayerInfo const *info = sObjectMgr.GetPlayerInfo(pRace, pClass); + if(!info) { - uint32 petDisplayId = 0; - uint32 petLevel = 0; - uint32 petFamily = 0; - - // show pet at selection character in character list only for non-ghost character - if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER || pClass == CLASS_DEATH_KNIGHT)) - { - uint32 entry = fields[16].GetUInt32(); - CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(entry); - if (cInfo) - { - petDisplayId = fields[17].GetUInt32(); - petLevel = fields[18].GetUInt32(); - petFamily = cInfo->family; - } - } - - *p_data << uint32(petDisplayId); - *p_data << uint32(petLevel); - *p_data << uint32(petFamily); + sLog.outError("Player %u has incorrect race/class pair. Don't build enum.", Guid); + return false; } + *p_data << uint8(pClass); // Race Tokens data = StrSplit(fields[19].GetCppString(), " "); - for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) + for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; slot++) { uint32 visualbase = slot * 2; uint32 item_id = GetUInt32ValueFromArray(data, visualbase); - const ItemPrototype* proto = ObjectMgr::GetItemPrototype(item_id); - if (!proto) + const ItemPrototype * proto = ObjectMgr::GetItemPrototype(item_id); + if(!proto) { - *p_data << uint32(0); *p_data << uint8(0); *p_data << uint32(0); + *p_data << uint32(0); continue; } - SpellItemEnchantmentEntry const* enchant = NULL; + SpellItemEnchantmentEntry const *enchant = NULL; uint32 enchants = GetUInt32ValueFromArray(data, visualbase + 1); - for (uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) + for(uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) { // values stored in 2 uint16 - uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot * 16); - if (!enchantId) + uint32 enchantId = 0x0000FFFF & (enchants >> enchantSlot*16); + if(!enchantId) continue; if ((enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId))) break; } - *p_data << uint32(proto->DisplayInfoID); *p_data << uint8(proto->InventoryType); + *p_data << uint32(proto->DisplayInfoID); *p_data << uint32(enchant ? enchant->aura_id : 0); } - *p_data << uint32(0); // bag 1 display id - *p_data << uint8(0); // bag 1 inventory type - *p_data << uint32(0); // enchant? - *p_data << uint32(0); // bag 2 display id - *p_data << uint8(0); // bag 2 inventory type - *p_data << uint32(0); // enchant? - *p_data << uint32(0); // bag 3 display id - *p_data << uint8(0); // bag 3 inventory type - *p_data << uint32(0); // enchant? - *p_data << uint32(0); // bag 4 display id - *p_data << uint8(0); // bag 4 inventory type - *p_data << uint32(0); // enchant? + for (int32 i = 0; i < 4; i++) + { + *p_data << uint8(0); + *p_data << uint32(0); + *p_data << uint32(0); + } + + *p_data << uint32(petDisplayId); // Pet DisplayID + *p_data << uint8(0); // char order id + *p_data << uint8(playerBytes >> 16); // Hair style + *p_data << uint32(petDisplayId); // Pet DisplayID + *p_data << uint32(char_flags); // character flags + *p_data << uint8(playerBytes >> 24); // Hair color + *p_data << uint32(fields[9].GetUInt32()); // map + *p_data << fields[12].GetFloat(); // z + *p_data << uint32(petLevel); // pet level + + if (Guid3) + *p_data << uint8(Guid3 ^ 1); + + *p_data << fields[11].GetFloat(); // y + // character customize flags + *p_data << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? CHAR_CUSTOMIZE_FLAG_CUSTOMIZE : CHAR_CUSTOMIZE_FLAG_NONE); + + uint32 playerBytes2 = fields[6].GetUInt32(); + *p_data << uint8(playerBytes2 & 0xFF); // facial hair + *p_data << uint8(gender); // Gender + p_data->append(fields[1].GetCppString().c_str(), fields[1].GetCppString().size()); + *p_data << uint8(playerBytes >> 8); // face + + if (Guid0) + *p_data << uint8(Guid0 ^ 1); + + if (Guid2) + *p_data << uint8(Guid2 ^ 1); + + *p_data << fields[10].GetFloat(); // x + *p_data << uint8(playerBytes); // skin + *p_data << uint8(pRace); // Race + *p_data << uint8(level); // Level + + if (Guid1) + *p_data << uint8(Guid1 ^ 1); + + *p_data << uint32(zone); // Zone id return true; } @@ -1617,8 +1637,42 @@ uint8 Player::GetChatTag() const return tag; } +void Player::SendTeleportPacket(float oldX, float oldY, float oldZ, float oldO) +{ + ObjectGuid guid = GetObjectGuid(); + ObjectGuid transportGuid = m_movementInfo.GetTransportGuid(); + + WorldPacket data(SMSG_MOVE_TELEPORT, 38); + data.WriteGuidMask<6, 0, 3, 2>(guid); + data.WriteBit(0); // unknown + data.WriteBit(!transportGuid.IsEmpty()); + data.WriteGuidMask<1>(guid); + if (transportGuid) + data.WriteGuidMask<1, 3, 2, 5, 0, 7, 6, 4>(transportGuid); + + data.WriteGuidMask<4, 7, 5>(guid); + + if (transportGuid) + data.WriteGuidBytes<5, 6, 1, 7, 0, 2, 4, 3>(transportGuid); + + data << uint32(0); // counter + data.WriteGuidBytes<1, 2, 3, 5>(guid); + data << float(GetPositionX()); + data.WriteGuidBytes<4>(guid); + data << float(GetOrientation()); + data.WriteGuidBytes<7>(guid); + data << float(GetPositionZ()); + data.WriteGuidBytes<0, 6>(guid); + data << float(GetPositionY()); + + Relocate(oldX, oldY, oldZ, oldO); + SendDirectMessage(&data); +} + bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options) { + orientation = NormalizeOrientation(orientation); + if (!MapManager::IsValidMapCoord(mapid, x, y, z, orientation)) { sLog.outError("TeleportTo: invalid map %d or absent instance template.", mapid); @@ -1705,14 +1759,16 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati SetFallInformation(0, z); // code for finish transfer called in WorldSession::HandleMovementOpcodes() - // at client packet MSG_MOVE_TELEPORT_ACK + // at client packet CMSG_MOVE_TELEPORT_ACK SetSemaphoreTeleportNear(true); - // near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing + // near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing if (!GetSession()->PlayerLogout()) { - WorldPacket data; - BuildTeleportAckMsg(data, x, y, z, orientation); - GetSession()->SendPacket(&data); + float oldX, oldY, oldZ; + float oldO = GetOrientation(); + GetPosition(oldX, oldY, oldZ);; + Relocate(x, y, z, orientation); + SendTeleportPacket(oldX, oldY, oldZ, oldO); } } else @@ -1782,12 +1838,17 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { // send transfer packet to display load screen WorldPacket data(SMSG_TRANSFER_PENDING, (4 + 4 + 4)); - data << uint32(mapid); + data.WriteBit(0); // unknown if (m_transport) { - data << uint32(m_transport->GetEntry()); + data.WriteBit(1); // has transport data << uint32(GetMapId()); + data << uint32(m_transport->GetEntry()); } + else + data.WriteBit(0); // has transport + + data << uint32(mapid); GetSession()->SendPacket(&data); } @@ -1821,23 +1882,27 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (!GetSession()->PlayerLogout()) { // transfer finished, inform client to start load - WorldPacket data(SMSG_NEW_WORLD, (20)); - data << uint32(mapid); + WorldPacket data(SMSG_NEW_WORLD, 20); if (m_transport) { data << float(m_movementInfo.GetTransportPos()->x); - data << float(m_movementInfo.GetTransportPos()->y); - data << float(m_movementInfo.GetTransportPos()->z); data << float(m_movementInfo.GetTransportPos()->o); + data << float(m_movementInfo.GetTransportPos()->z); } else { data << float(final_x); - data << float(final_y); - data << float(final_z); data << float(final_o); + data << float(final_z); } + data << uint32(mapid); + + if (m_transport) + data << float(m_movementInfo.GetTransportPos()->y); + else + data << float(final_y); + GetSession()->SendPacket(&data); SendSavedInstances(); } @@ -1995,14 +2060,24 @@ void Player::RegenerateAll(uint32 diff) if (getClass() == CLASS_DEATH_KNIGHT) Regenerate(POWER_RUNE, diff); + if (getClass() == CLASS_HUNTER) + Regenerate(POWER_FOCUS, diff); + m_regenTimer = REGEN_TIME_FULL; } // diff contains the time in milliseconds since last regen. void Player::Regenerate(Powers power, uint32 diff) { - uint32 curValue = GetPower(power); - uint32 maxValue = GetMaxPower(power); + uint32 powerIndex = GetPowerIndex(power); + if (powerIndex == INVALID_POWER_INDEX) + return; + + uint32 maxValue = GetMaxPowerByIndex(powerIndex); + if (!maxValue) + return; + + uint32 curValue = GetPowerByIndex(powerIndex); float addvalue = 0.0f; @@ -2029,6 +2104,9 @@ void Player::Regenerate(Powers power, uint32 diff) float RageDecreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_RAGE_LOSS); addvalue = 20 * RageDecreaseRate; // 2 rage by tick (= 2 seconds => 1 rage/sec) } break; + case POWER_FOCUS: + addvalue = 12; + break; case POWER_ENERGY: // Regenerate energy (rogue) { float EnergyRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_ENERGY); @@ -2059,8 +2137,6 @@ void Player::Regenerate(Powers power, uint32 diff) } } } break; - case POWER_FOCUS: - case POWER_HAPPINESS: case POWER_HEALTH: break; } @@ -2469,17 +2545,15 @@ void Player::GiveLevel(uint32 level) PlayerLevelInfo info; sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), level, &info); - PlayerClassLevelInfo classInfo; - sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, &classInfo); + uint32 basehp = 0, basemana = 0; + sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, basehp, basemana); // send levelup info to client - WorldPacket data(SMSG_LEVELUP_INFO, (4 + 4 + MAX_POWERS * 4 + MAX_STATS * 4)); + WorldPacket data(SMSG_LEVELUP_INFO, (4 + 4 + MAX_STORED_POWERS * 4 + MAX_STATS * 4)); data << uint32(level); - data << uint32(int32(classInfo.basehealth) - int32(GetCreateHealth())); - // for(int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-6) - data << uint32(int32(classInfo.basemana) - int32(GetCreateMana())); - data << uint32(0); - data << uint32(0); + data << uint32(int32(basehp) - int32(GetCreateHealth())); + // for(int i = 0; i < MAX_POWERS; ++i) // Powers loop (0-4) + data << uint32(int32(basemana) - int32(GetCreateMana())); data << uint32(0); data << uint32(0); data << uint32(0); @@ -2505,8 +2579,8 @@ void Player::GiveLevel(uint32 level) for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetCreateStat(Stats(i), info.stats[i]); - SetCreateHealth(classInfo.basehealth); - SetCreateMana(classInfo.basemana); + SetCreateHealth(basehp); + SetCreateMana(basemana); InitTalentForLevel(); InitTaxiNodesForLevel(); @@ -2522,7 +2596,6 @@ void Player::GiveLevel(uint32 level) if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE)) SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); SetPower(POWER_FOCUS, 0); - SetPower(POWER_HAPPINESS, 0); _ApplyAllLevelScaleItemMods(true); @@ -2581,8 +2654,8 @@ void Player::InitStatsForLevel(bool reapplyMods) if (reapplyMods) // reapply stats values only on .reset stats (level) command _RemoveAllStatBonuses(); - PlayerClassLevelInfo classInfo; - sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), &classInfo); + uint32 basehp = 0, basemana = 0; + sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), basehp, basemana); PlayerLevelInfo info; sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), getLevel(), &info); @@ -2605,10 +2678,10 @@ void Player::InitStatsForLevel(bool reapplyMods) for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetStat(Stats(i), info.stats[i]); - SetCreateHealth(classInfo.basehealth); + SetCreateHealth(basehp); // set create powers - SetCreateMana(classInfo.basemana); + SetCreateMana(basemana); SetArmor(int32(m_createStats[STAT_AGILITY] * 2)); @@ -2638,12 +2711,14 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, 0.0f); SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, 0.0f); - SetInt32Value(UNIT_FIELD_ATTACK_POWER, 0); - SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, 0); - SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, 0.0f); - SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0); - SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS, 0); - SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER, 0.0f); + SetInt32Value(UNIT_FIELD_ATTACK_POWER, 0 ); + SetInt32Value(UNIT_FIELD_ATTACK_POWER_MOD_POS, 0 ); + SetInt32Value(UNIT_FIELD_ATTACK_POWER_MOD_NEG, 0 ); + SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER,0.0f); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0 ); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MOD_POS,0 ); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MOD_NEG,0 ); + SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER,0.0f); // Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset SetFloatValue(PLAYER_CRIT_PERCENTAGE, 0.0f); @@ -2688,9 +2763,9 @@ void Player::InitStatsForLevel(bool reapplyMods) // save new stats for (int i = POWER_MANA; i < MAX_POWERS; ++i) - SetMaxPower(Powers(i), GetCreatePowers(Powers(i))); + SetMaxPower(Powers(i), GetCreatePowers(Powers(i))); - SetMaxHealth(classInfo.basehealth); // stamina bonus will applied later + SetMaxHealth(basehp); // stamina bonus will applied later // cleanup mounted state (it will set correctly at aura loading if player saved at mount. SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0); @@ -2726,7 +2801,6 @@ void Player::InitStatsForLevel(bool reapplyMods) if (GetPower(POWER_RAGE) > GetMaxPower(POWER_RAGE)) SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); SetPower(POWER_FOCUS, 0); - SetPower(POWER_HAPPINESS, 0); SetPower(POWER_RUNIC_POWER, 0); // update level to hunter/summon pet @@ -2774,7 +2848,7 @@ void Player::SendInitialSpells() data << uint32(itr->first); data << uint16(itr->second.itemid); // cast item id - data << uint16(sEntry->Category); // spell category + data << uint16(sEntry->GetCategory()); // spell category // send infinity cooldown in special format if (itr->second.end >= infTime) @@ -2786,7 +2860,7 @@ void Player::SendInitialSpells() time_t cooldown = itr->second.end > curTime ? (itr->second.end - curTime) * IN_MILLISECONDS : 0; - if (sEntry->Category) // may be wrong, but anyway better than nothing... + if(sEntry->GetCategory()) // may be wrong, but anyway better than nothing... { data << uint32(0); // cooldown data << uint32(cooldown); // category cooldown @@ -3203,13 +3277,13 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen switch (GetSkillRangeType(pSkill, _spell_idx->second->racemask != 0)) { case SKILL_RANGE_LANGUAGE: - SetSkill(pSkill->id, 300, 300); + SetSkill(pSkill->id, 300, 300, GetSkillStep(pSkill->id)); break; case SKILL_RANGE_LEVEL: - SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel()); + SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel(), GetSkillStep(pSkill->id)); break; case SKILL_RANGE_MONO: - SetSkill(pSkill->id, 1, 1); + SetSkill(pSkill->id, 1, 1, GetSkillStep(pSkill->id)); break; default: break; @@ -3260,10 +3334,12 @@ bool Player::IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) cons // note: form passives activated with shapeshift spells be implemented by HandleShapeshiftBoosts instead of spell_learn_spell // talent dependent passives activated at form apply have proper stance data - bool need_cast = !spellInfo->Stances || (!form && spellInfo->HasAttribute(SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT)); + SpellShapeshiftEntry const* shapeShift = spellInfo->GetSpellShapeshift(); + bool need_cast = (!shapeShift || !shapeShift->Stances || (!form && spellInfo->HasAttribute(SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT))); // Check CasterAuraStates - return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))); + SpellAuraRestrictionsEntry const* auraRestrictions = spellInfo->GetSpellAuraRestrictions(); + return need_cast && (auraRestrictions && (!auraRestrictions->CasterAuraState || HasAuraState(AuraState(auraRestrictions->CasterAuraState)))); } void Player::learnSpell(uint32 spell_id, bool dependent) @@ -3280,7 +3356,7 @@ void Player::learnSpell(uint32 spell_id, bool dependent) { WorldPacket data(SMSG_LEARNED_SPELL, 6); data << uint32(spell_id); - data << uint16(0); // 3.3.3 unk + data << uint32(0); // 3.3.3 unk GetSession()->SendPacket(&data); } @@ -3434,7 +3510,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank, bo (IsProfessionSkill(pSkill->id) || _spell_idx->second->racemask != 0)) continue; - SetSkill(pSkill->id, 0, 0); + SetSkill(pSkill->id, 0, 0, GetSkillStep(pSkill->id)); } } } @@ -3553,9 +3629,9 @@ void Player::RemoveArenaSpellCooldowns() ++next; SpellEntry const* entry = sSpellStore.LookupEntry(itr->first); // check if spellentry is present and if the cooldown is less than 15 mins - if (entry && - entry->RecoveryTime <= 15 * MINUTE * IN_MILLISECONDS && - entry->CategoryRecoveryTime <= 15 * MINUTE * IN_MILLISECONDS) + if( entry && + entry->GetRecoveryTime() <= 15 * MINUTE * IN_MILLISECONDS && + entry->GetCategoryRecoveryTime() <= 15 * MINUTE * IN_MILLISECONDS ) { // remove & notify RemoveSpellCooldown(itr->first, true); @@ -3835,6 +3911,8 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(OBJECT_FIELD_GUID); updateVisualBits.SetBit(OBJECT_FIELD_TYPE); updateVisualBits.SetBit(OBJECT_FIELD_ENTRY); + updateVisualBits.SetBit(OBJECT_FIELD_DATA + 0); + updateVisualBits.SetBit(OBJECT_FIELD_DATA + 1); updateVisualBits.SetBit(OBJECT_FIELD_SCALE_X); updateVisualBits.SetBit(UNIT_FIELD_CHARM + 0); updateVisualBits.SetBit(UNIT_FIELD_CHARM + 1); @@ -3853,16 +3931,12 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(UNIT_FIELD_POWER3); updateVisualBits.SetBit(UNIT_FIELD_POWER4); updateVisualBits.SetBit(UNIT_FIELD_POWER5); - updateVisualBits.SetBit(UNIT_FIELD_POWER6); - updateVisualBits.SetBit(UNIT_FIELD_POWER7); updateVisualBits.SetBit(UNIT_FIELD_MAXHEALTH); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER1); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER2); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER3); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER4); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER5); - updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER6); - updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER7); updateVisualBits.SetBit(UNIT_FIELD_LEVEL); updateVisualBits.SetBit(UNIT_FIELD_FACTIONTEMPLATE); updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 0); @@ -3891,13 +3965,15 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 0); updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 1); updateVisualBits.SetBit(PLAYER_FLAGS); - updateVisualBits.SetBit(PLAYER_GUILDID); + //updateVisualBits.SetBit(PLAYER_GUILDID); updateVisualBits.SetBit(PLAYER_GUILDRANK); + updateVisualBits.SetBit(PLAYER_GUILDLEVEL); updateVisualBits.SetBit(PLAYER_BYTES); updateVisualBits.SetBit(PLAYER_BYTES_2); updateVisualBits.SetBit(PLAYER_BYTES_3); updateVisualBits.SetBit(PLAYER_DUEL_TEAM); updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP); + updateVisualBits.SetBit(UNIT_NPC_FLAGS); // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)... for (uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += MAX_QUEST_OFFSET) @@ -3944,9 +4020,27 @@ void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c } } + SetPhaseAndMap(target); Unit::BuildCreateUpdateBlockForPlayer(data, target); } +void Player::SetPhaseAndMap(Player* target) const +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT map, phase FROM character_phase_data WHERE guid = '%u'", target->GetGUIDLow()); + + if (result) + { + Field *fields = result->Fetch(); + + uint16 mapId = fields[0].GetUInt16(); + uint32 phase = fields[1].GetUInt32(); + + target->GetSession()->SendSetPhaseShift(phase, mapId); + + delete result; + } +} + void Player::DestroyForPlayer(Player* target, bool anim) const { Unit::DestroyForPlayer(target, anim); @@ -4035,9 +4129,10 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->learnedSpell); // secondary prof. or not prof. spell - uint32 skill = spell->EffectMiscValue[1]; + SpellEffectEntry const* spellEffect = spell->GetSpellEffect(EFFECT_INDEX_1); + uint32 skill = spellEffect ? spellEffect->EffectMiscValue : 0; - if (spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill)) + if(spellEffect && (spellEffect->Effect != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill))) return TRAINER_SPELL_GREEN; // check primary prof. limit @@ -4328,16 +4423,23 @@ void Player::SetMovement(PlayerMovementType pType) WorldPacket data; switch (pType) { - case MOVE_ROOT: data.Initialize(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size() + 4); break; - case MOVE_UNROOT: data.Initialize(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size() + 4); break; - case MOVE_WATER_WALK: data.Initialize(SMSG_MOVE_WATER_WALK, GetPackGUID().size() + 4); break; - case MOVE_LAND_WALK: data.Initialize(SMSG_MOVE_LAND_WALK, GetPackGUID().size() + 4); break; + case MOVE_ROOT: + case MOVE_UNROOT: + { + BuildForceMoveRootPacket(&data, pType == MOVE_ROOT, 0); + break; + } + case MOVE_WATER_WALK: + case MOVE_LAND_WALK: + { + BuildMoveWaterWalkPacket(&data, pType == MOVE_WATER_WALK, 0); + break; + } default: sLog.outError("Player::SetMovement: Unsupported move type (%d), data not sent to client.", pType); return; } - data << GetPackGUID(); - data << uint32(0); + GetSession()->SendPacket(&data); } @@ -4531,8 +4633,6 @@ Corpse* Player::CreateCorpse() corpse->SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, GetNativeDisplayId()); - corpse->SetUInt32Value(CORPSE_FIELD_GUILD, GetGuildId()); - uint32 iDisplayID; uint32 iIventoryType; uint32 _cfi; @@ -5115,23 +5215,23 @@ float Player::GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const float Player::OCTRegenHPPerSpirit() { - uint32 level = getLevel(); - uint32 pclass = getClass(); + //uint32 level = getLevel(); + //uint32 pclass = getClass(); - if (level > GT_MAX_LEVEL) level = GT_MAX_LEVEL; + //if (level>GT_MAX_LEVEL) level = GT_MAX_LEVEL; - GtOCTRegenHPEntry const* baseRatio = sGtOCTRegenHPStore.LookupEntry((pclass - 1) * GT_MAX_LEVEL + level - 1); - GtRegenHPPerSptEntry const* moreRatio = sGtRegenHPPerSptStore.LookupEntry((pclass - 1) * GT_MAX_LEVEL + level - 1); - if (baseRatio == NULL || moreRatio == NULL) + //GtOCTRegenHPEntry const *baseRatio = sGtOCTRegenHPStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + //GtRegenHPPerSptEntry const *moreRatio = sGtRegenHPPerSptStore.LookupEntry((pclass-1)*GT_MAX_LEVEL + level-1); + //if (baseRatio==NULL || moreRatio==NULL) return 0.0f; // Formula from PaperDollFrame script - float spirit = GetStat(STAT_SPIRIT); - float baseSpirit = spirit; - if (baseSpirit > 50) baseSpirit = 50; - float moreSpirit = spirit - baseSpirit; - float regen = baseSpirit * baseRatio->ratio + moreSpirit * moreRatio->ratio; - return regen; + //float spirit = GetStat(STAT_SPIRIT); + //float baseSpirit = spirit; + //if (baseSpirit>50) baseSpirit = 50; + //float moreSpirit = spirit - baseSpirit; + //float regen = baseSpirit * baseRatio->ratio + moreSpirit * moreRatio->ratio; + //return regen; } float Player::OCTRegenMPPerSpirit() @@ -5299,14 +5399,18 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (!skill_id) return false; + if (skill_id == SKILL_FIST_WEAPONS) + skill_id = SKILL_UNARMED; + SkillStatusMap::iterator itr = mSkillStatus.find(skill_id); if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint32 data = GetUInt32Value(valueIndex); - uint32 value = SKILL_VALUE(data); - uint32 max = SKILL_MAX(data); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + + uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); if ((!max) || (!value) || (value >= max)) return false; @@ -5317,7 +5421,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (new_value > max) new_value = max; - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, max)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); @@ -5352,7 +5456,7 @@ bool Player::UpdateCraftSkill(uint32 spellid) // Alchemy Discoveries here SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellid); - if (spellEntry && spellEntry->Mechanic == MECHANIC_DISCOVERY) + if (spellEntry && spellEntry->GetMechanic() == MECHANIC_DISCOVERY) { if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this)) learnSpell(discoveredSpell, false); @@ -5432,11 +5536,11 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - uint32 data = GetUInt32Value(valueIndex); - uint16 SkillValue = SKILL_VALUE(data); - uint16 MaxValue = SKILL_MAX(data); + uint16 SkillValue = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 MaxValue = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); if (!MaxValue || !SkillValue || SkillValue >= MaxValue) return false; @@ -5445,16 +5549,16 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) if (Roll <= Chance) { - uint32 new_value = SkillValue + step; + uint16 new_value = SkillValue + step; if (new_value > MaxValue) new_value = MaxValue; - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, MaxValue)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; for (uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl) { - if ((SkillValue < *bsl && new_value >= *bsl)) + if (SkillValue < *bsl && new_value >= *bsl) { learnSkillRewardedSpells(SkillId, new_value); break; @@ -5538,16 +5642,12 @@ void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent) if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return; - uint32 bonusIndex = PLAYER_SKILL_BONUS_INDEX(itr->second.pos); + uint16 field = itr->second.pos / 2 + (talent ? PLAYER_SKILL_TALENT_0 : PLAYER_SKILL_MODIFIER_0); + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - uint32 bonus_val = GetUInt32Value(bonusIndex); - int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val); - int16 perm_bonus = SKILL_PERM_BONUS(bonus_val); + uint16 bonus = GetUInt16Value(field, offset); - if (talent) // permanent bonus stored in high part - SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus, perm_bonus + val)); - else // temporary/item bonus stored in low part - SetUInt32Value(bonusIndex, MAKE_SKILL_BONUS(temp_bonus + val, perm_bonus)); + SetUInt16Value(field, offset, bonus + val); } void Player::UpdateSkillsForLevel() @@ -5571,10 +5671,11 @@ void Player::UpdateSkillsForLevel() if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL) continue; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint32 data = GetUInt32Value(valueIndex); - uint32 max = SKILL_MAX(data); - uint32 val = SKILL_VALUE(data); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + + uint16 val = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); /// update only level dependent max skill values if (max != 1) @@ -5582,14 +5683,16 @@ void Player::UpdateSkillsForLevel() /// maximize skill always if (alwaysMaxSkill) { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill, maxSkill)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, maxSkill); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, pskill); } else if (max != maxconfskill) /// update max skill value if current max skill not maximized { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val, maxSkill)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, val); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; } @@ -5607,14 +5710,14 @@ void Player::UpdateSkillsToMaxSkillsForLevel() uint32 pskill = itr->first; if (IsProfessionOrRidingSkill(pskill)) continue; - uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint32 data = GetUInt32Value(valueIndex); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - uint32 max = SKILL_MAX(data); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); if (max > 1) { - SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(max, max)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, max); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, pskill); @@ -5632,29 +5735,36 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 if (!id) return; + uint16 oldVal; SkillStatusMap::iterator itr = mSkillStatus.find(id); // has skill if (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED) { + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + oldVal = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); if (currVal) { - if (step) // need update step - SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), MAKE_PAIR32(id, step)); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); // update value - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), MAKE_SKILL_VALUE(currVal, maxVal)); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, currVal); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; - learnSkillRewardedSpells(id, currVal); + learnSkillRewardedSpells(id, oldVal); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); } else // remove { // clear skill fields - SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), 0); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), 0); - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos), 0); + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); // mark as deleted or simply remove from map if not saved yet if (itr->second.uState != SKILL_NEW) @@ -5673,7 +5783,10 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 { for (int i = 0; i < PLAYER_MAX_SKILLS; ++i) { - if (!GetUInt32Value(PLAYER_SKILL_INDEX(i))) + uint16 field = i / 2; + uint8 offset = i & 1; // i % 2 + + if (!GetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset)) { SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(id); if (!pSkill) @@ -5682,8 +5795,10 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 return; } - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id, step)); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i), MAKE_SKILL_VALUE(currVal, maxVal)); + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, id); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, currVal); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); @@ -5697,7 +5812,8 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW))); // apply skill bonuses - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i), 0); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); // temporary bonuses AuraList const& mModSkill = GetAurasByType(SPELL_AURA_MOD_SKILL); @@ -5728,6 +5844,18 @@ bool Player::HasSkill(uint32 skill) const return (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED); } +uint16 Player::GetSkillStep(uint16 skill) const +{ + if (!skill) + return 0; + + SkillStatusMap::const_iterator itr = mSkillStatus.find(skill); + if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) + return 0; + + return GetUInt16Value(PLAYER_SKILL_STEP_0 + itr->second.pos / 2, itr->second.pos & 1); +} + uint16 Player::GetSkillValue(uint32 skill) const { if (!skill) @@ -5737,11 +5865,12 @@ uint16 Player::GetSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; - int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - result += SKILL_TEMP_BONUS(bonus); - result += SKILL_PERM_BONUS(bonus); + int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset)); return result < 0 ? 0 : result; } @@ -5754,11 +5883,12 @@ uint16 Player::GetMaxSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; - int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - result += SKILL_TEMP_BONUS(bonus); - result += SKILL_PERM_BONUS(bonus); + int32 result = int32(GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset)); return result < 0 ? 0 : result; } @@ -5771,7 +5901,10 @@ uint16 Player::GetPureMaxSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); } uint16 Player::GetBaseSkillValue(uint32 skill) const @@ -5783,8 +5916,11 @@ uint16 Player::GetBaseSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); - result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + int32 result = int32(GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset)); + result += int32(GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset)); return result < 0 ? 0 : result; } @@ -5797,7 +5933,10 @@ uint16 Player::GetPureSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); } int16 Player::GetSkillPermBonusValue(uint32 skill) const @@ -5809,7 +5948,10 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset); } int16 Player::GetSkillTempBonusValue(uint32 skill) const @@ -5821,7 +5963,10 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + return GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset); } void Player::SendInitialActionButtons() const @@ -5829,7 +5974,6 @@ void Player::SendInitialActionButtons() const DETAIL_LOG("Initializing Action Buttons for '%u' spec '%u'", GetGUIDLow(), m_activeSpec); WorldPacket data(SMSG_ACTION_BUTTONS, 1 + (MAX_ACTION_BUTTONS * 4)); - data << uint8(1); // talent spec amount (in packet) ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec]; for (uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) { @@ -5839,7 +5983,7 @@ void Player::SendInitialActionButtons() const else data << uint32(0); } - + data << uint8(1); // talent spec amount (in packet) GetSession()->SendPacket(&data); DETAIL_LOG("Action Buttons for '%u' spec '%u' Initialized", GetGUIDLow(), m_activeSpec); } @@ -6394,16 +6538,14 @@ void Player::UpdateHonorFields() // update yesterday's contribution if (m_lastHonorUpdateTime >= yesterday) { - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + //SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); // this is the first update today, reset today's contribution - SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); - SetUInt32Value(PLAYER_FIELD_KILLS, MAKE_PAIR32(0, kills_today)); + SetUInt32Value(PLAYER_FIELD_KILLS, MAKE_PAIR32(0,kills_today)); } else { // no honor/kills yesterday or today, reset - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); SetUInt32Value(PLAYER_FIELD_KILLS, 0); } } @@ -6537,7 +6679,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, float honor) // add honor points ModifyHonorPoints(int32(honor)); - ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); + // FIXME 4x ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); return true; } @@ -6546,7 +6688,9 @@ void Player::SetHonorPoints(uint32 value) if (value > sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS)) value = sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS); - SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value); + // FIXME 4x SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value); + // must be recalculated to new honor points items and removed + m_honorPoints = value; } void Player::SetArenaPoints(uint32 value) @@ -6554,7 +6698,9 @@ void Player::SetArenaPoints(uint32 value) if (value > sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS)) value = sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS); - SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value); + // FIXME 4x SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value); + // must be recalculated to new honor points items and removed + m_arenaPoints = value; } void Player::ModifyHonorPoints(int32 value) @@ -7149,7 +7295,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl } // If set ScalingStatValue armor get it or use item armor - uint32 armor = proto->Armor; + uint32 armor = proto->GetArmor(); if (ssv) { if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue)) @@ -7210,8 +7356,8 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl attType = OFF_ATTACK; } - float minDamage = proto->Damage[0].DamageMin; - float maxDamage = proto->Damage[0].DamageMax; + float minDamage = proto->GetMinDamage(); + float maxDamage = proto->GetMaxDamage(); int32 extraDPS = 0; // If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage if (ssv) @@ -7285,7 +7431,7 @@ void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackTy void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, Aura* aura, bool apply) { // generic not weapon specific case processes in aura code - if (aura->GetSpellProto()->EquippedItemClass == -1) + if(aura->GetSpellProto()->GetEquippedItemClass() == -1) return; BaseModGroup mod = BASEMOD_END; @@ -7311,7 +7457,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType att return; // generic not weapon specific case processes in aura code - if (aura->GetSpellProto()->EquippedItemClass == -1) + if(aura->GetSpellProto()->GetEquippedItemClass() == -1) return; UnitMods unitMod = UNIT_MOD_END; @@ -7542,7 +7688,7 @@ void Player::_HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEn break; } } - if (dPoison && dPoison->GetStackAmount() == spellInfo->StackAmount) + if (dPoison && dPoison->GetStackAmount() == spellInfo->GetStackAmount()) { Item* otherWeapon = GetWeaponForAttack(attType == BASE_ATTACK ? OFF_ATTACK : BASE_ATTACK); if (!otherWeapon) @@ -7562,9 +7708,9 @@ void Player::_HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEn if (pSecondEnchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) continue; - SpellEntry const* combatEntry = sSpellStore.LookupEntry(pSecondEnchant->spellid[s]); - if (combatEntry && combatEntry->Dispel == DISPEL_POISON) - CastSpell(Target, combatEntry, true, otherWeapon); + if (SpellEntry const* combatEntry = sSpellStore.LookupEntry(pSecondEnchant->spellid[s])) + if (combatEntry->GetDispel() == DISPEL_POISON) + CastSpell(Target, combatEntry, true, otherWeapon); } } } @@ -7605,7 +7751,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) if (m_extraAttacks && IsSpellHaveEffect(spellInfo, SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return; - float chance = (float)spellInfo->procChance; + float chance = (float)spellInfo->GetProcChance(); if (spellData.SpellPPMRate) { @@ -7658,7 +7804,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) else { // Deadly Poison, unique effect needs to be handled before casting triggered spell - if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & UI64LIT(0x10000)) + if (spellInfo->IsFitToFamily(SPELLFAMILY_ROGUE, UI64LIT(0x0000000000010000))) _HandleDeadlyPoison(Target, attType, spellInfo); CastSpell(Target, spellInfo->Id, true, item); @@ -7873,26 +8019,26 @@ void Player::_ApplyAllLevelScaleItemMods(bool apply) void Player::_ApplyAmmoBonuses() { - // check ammo - uint32 ammo_id = GetUInt32Value(PLAYER_AMMO_ID); - if (!ammo_id) - return; + //// check ammo + //uint32 ammo_id = GetUInt32Value(PLAYER_AMMO_ID); + //if(!ammo_id) + // return; - float currentAmmoDPS; + //float currentAmmoDPS; - ItemPrototype const* ammo_proto = ObjectMgr::GetItemPrototype(ammo_id); - if (!ammo_proto || ammo_proto->Class != ITEM_CLASS_PROJECTILE || !CheckAmmoCompatibility(ammo_proto)) - currentAmmoDPS = 0.0f; - else - currentAmmoDPS = ammo_proto->Damage[0].DamageMin; + //ItemPrototype const *ammo_proto = ObjectMgr::GetItemPrototype( ammo_id ); + //if( !ammo_proto || ammo_proto->Class!=ITEM_CLASS_PROJECTILE || !CheckAmmoCompatibility(ammo_proto)) + // currentAmmoDPS = 0.0f; + //else + // currentAmmoDPS = ammo_proto->Damage[0].DamageMin; - if (currentAmmoDPS == GetAmmoDPS()) - return; + //if(currentAmmoDPS == GetAmmoDPS()) + // return; - m_ammoDPS = currentAmmoDPS; + //m_ammoDPS = currentAmmoDPS; - if (CanModifyStats()) - UpdateDamagePhysical(RANGED_ATTACK); + //if(CanModifyStats()) + // UpdateDamagePhysical(RANGED_ATTACK); } bool Player::CheckAmmoCompatibility(const ItemPrototype* ammo_proto) const @@ -11049,37 +11195,37 @@ InventoryResult Player::CanUseAmmo(uint32 item) const void Player::SetAmmo(uint32 item) { - if (!item) - return; + //if(!item) + // return; - // already set - if (GetUInt32Value(PLAYER_AMMO_ID) == item) - return; + //// already set + //if( GetUInt32Value(PLAYER_AMMO_ID) == item ) + // return; - // check ammo - if (item) - { - InventoryResult msg = CanUseAmmo(item); - if (msg != EQUIP_ERR_OK) - { - SendEquipError(msg, NULL, NULL, item); - return; - } - } + //// check ammo + //if (item) + //{ + // InventoryResult msg = CanUseAmmo( item ); + // if (msg != EQUIP_ERR_OK) + // { + // SendEquipError(msg, NULL, NULL, item); + // return; + // } + //} - SetUInt32Value(PLAYER_AMMO_ID, item); + //SetUInt32Value(PLAYER_AMMO_ID, item); - _ApplyAmmoBonuses(); + //_ApplyAmmoBonuses(); } void Player::RemoveAmmo() { - SetUInt32Value(PLAYER_AMMO_ID, 0); + //SetUInt32Value(PLAYER_AMMO_ID, 0); - m_ammoDPS = 0.0f; + //m_ammoDPS = 0.0f; - if (CanModifyStats()) - UpdateDamagePhysical(RANGED_ATTACK); + //if (CanModifyStats()) + // UpdateDamagePhysical(RANGED_ATTACK); } // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case. @@ -11284,7 +11430,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update) sLog.outError("Weapon switch cooldown spell %u couldn't be found in Spell.dbc", cooldownSpell); else { - m_weaponChangeTimer = spellProto->StartRecoveryTime; + m_weaponChangeTimer = spellProto->GetStartRecoveryTime(); WorldPacket data(SMSG_SPELL_COOLDOWN, 8 + 1 + 4); data << GetObjectGuid(); @@ -15241,6 +15387,16 @@ void Player::SendQuestReward(Quest const* pQuest, uint32 XP, Object* questGiver) data << uint32(pQuest->GetBonusTalents()); // bonus talents data << uint32(0); // arena points GetSession()->SendPacket(&data); + + QuestPhaseMapsVector const* QuestPhaseVector = sObjectMgr.GetQuestPhaseMapVector(questid); + if (QuestPhaseVector) + { + for (QuestPhaseMapsVector::const_iterator itr = QuestPhaseVector->begin(); itr != QuestPhaseVector->end(); ++itr) + { + GetSession()->SendSetPhaseShift(itr->PhaseMask, itr->MapId); + CharacterDatabase.PExecute("REPLACE INTO character_phase_data` (`guid`, `map`, `phase`) VALUES (%u, %u, %u)", GetSession()->GetPlayer()->GetGUIDLow(), itr->MapId, itr->PhaseMask); + } + } } void Player::SendQuestFailed(uint32 quest_id, InventoryResult reason) @@ -15487,9 +15643,9 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) //"resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty," // 39 40 41 42 43 44 45 46 47 48 49 //"arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk," - // 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 - //"health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); - QueryResult* result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); + // 50 51 52 53 54 55 56 57 58 59 60 61 + //"health, power1, power2, power3, power4, power5, specCount, activeSpec, exploredZones, equipmentCache, knownTitles, actionBars FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); if (!result) { @@ -15538,8 +15694,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8()); SetUInt32Value(PLAYER_XP, fields[7].GetUInt32()); - _LoadIntoDataField(fields[60].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); - _LoadIntoDataField(fields[63].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE * 2); + _LoadIntoDataField(fields[58].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); + _LoadIntoDataField(fields[60].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2); InitDisplayIds(); // model, scale and model data @@ -15564,12 +15720,10 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) SetUInt32Value(PLAYER_FLAGS, fields[11].GetUInt32()); SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, fields[48].GetInt32()); - SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64()); - - SetUInt32Value(PLAYER_AMMO_ID, fields[62].GetUInt32()); + //SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64()); // Action bars state - SetByteValue(PLAYER_FIELD_BYTES, 2, fields[64].GetUInt8()); + SetByteValue(PLAYER_FIELD_BYTES, 2, fields[61].GetUInt8()); // cleanup inventory related item value fields (its will be filled correctly in _LoadInventory) for (uint8 slot = EQUIPMENT_SLOT_START; slot < EQUIPMENT_SLOT_END; ++slot) @@ -15632,8 +15786,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) SetHonorPoints(fields[40].GetUInt32()); - SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[41].GetUInt32()); - SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[42].GetUInt32()); + //SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, fields[41].GetUInt32()); + //SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, fields[42].GetUInt32()); SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, fields[43].GetUInt32()); SetUInt16Value(PLAYER_FIELD_KILLS, 0, fields[44].GetUInt16()); SetUInt16Value(PLAYER_FIELD_KILLS, 1, fields[45].GetUInt16()); @@ -15904,8 +16058,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) _LoadMailedItems(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILEDITEMS)); UpdateNextMailTimeAndUnreads(); - m_specsCount = fields[58].GetUInt8(); - m_activeSpec = fields[59].GetUInt8(); + m_specsCount = fields[56].GetUInt8(); + m_activeSpec = fields[57].GetUInt8(); _LoadGlyphs(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGLYPHS)); @@ -16015,10 +16169,12 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) // restore remembered power/health values (but not more max values) uint32 savedhealth = fields[50].GetUInt32(); SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); - for (uint32 i = 0; i < MAX_POWERS; ++i) + + static_assert(MAX_STORED_POWERS == 5, "Query not updated."); + for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) { uint32 savedpower = fields[51 + i].GetUInt32(); - SetPower(Powers(i), savedpower > GetMaxPower(Powers(i)) ? GetMaxPower(Powers(i)) : savedpower); + SetPowerByIndex(i, std::min(savedpower, GetMaxPowerByIndex(i))); } DEBUG_FILTER_LOG(LOG_FILTER_PLAYER_STATS, "The value of player %s after load item and aura is: ", m_name.c_str()); @@ -16200,13 +16356,19 @@ void Player::_LoadAuras(QueryResult* result, uint32 timediff) } // prevent wrong values of remaincharges - if (spellproto->procCharges == 0) + if (uint32 procCharges = spellproto->GetProcCharges()) + { + if (remaincharges <= 0 || remaincharges > procCharges) + remaincharges = procCharges; + } + else remaincharges = 0; - if (!spellproto->StackAmount) + uint32 defstackamount = spellproto->GetStackAmount(); + if (!defstackamount) stackcount = 1; - else if (spellproto->StackAmount < stackcount) - stackcount = spellproto->StackAmount; + else if (defstackamount < stackcount) + stackcount = defstackamount; else if (!stackcount) stackcount = 1; @@ -17329,21 +17491,21 @@ void Player::SaveToDB() stmt.PExecute(GetGUIDLow()); SqlStatement uberInsert = CharacterDatabase.CreateStatement(insChar, "INSERT INTO characters (guid,account,name,race,class,gender,level,xp,money,playerBytes,playerBytes2,playerFlags," - "map, dungeon_difficulty, position_x, position_y, position_z, orientation, " - "taximask, online, cinematic, " - "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " - "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " - "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, " - "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, " - "power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars) " - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, " - "?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); + "map, dungeon_difficulty, position_x, position_y, position_z, orientation, " + "taximask, online, cinematic, " + "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " + "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " + "death_expire_time, taxi_path, arenaPoints, totalHonorPoints, todayHonorPoints, yesterdayHonorPoints, totalKills, " + "todayKills, yesterdayKills, chosenTitle, knownCurrencies, watchedFaction, drunk, health, power1, power2, power3, " + "power4, power5, specCount, activeSpec, exploredZones, equipmentCache, knownTitles, actionBars) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, " + "?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?) "); uberInsert.addUInt32(GetGUIDLow()); uberInsert.addUInt32(GetSession()->GetAccountId()); @@ -17422,9 +17584,9 @@ void Player::SaveToDB() uberInsert.addUInt32(GetHonorPoints()); - uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); + uberInsert.addUInt32(0); // FIXME 4x GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION) - uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); + uberInsert.addUInt32(0); // FIXME 4x GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION) uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS)); @@ -17434,7 +17596,7 @@ void Player::SaveToDB() uberInsert.addUInt32(GetUInt32Value(PLAYER_CHOSEN_TITLE)); - uberInsert.addUInt64(GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES)); + uberInsert.addUInt64(0); // FIXME 4x GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES) // FIXME: at this moment send to DB as unsigned, including unit32(-1) uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX)); @@ -17443,8 +17605,9 @@ void Player::SaveToDB() uberInsert.addUInt32(GetHealth()); - for (uint32 i = 0; i < MAX_POWERS; ++i) - uberInsert.addUInt32(GetPower(Powers(i))); + static_assert(MAX_STORED_POWERS == 5, "Query not updated."); + for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) + uberInsert.addUInt32(GetPowerByIndex(i)); uberInsert.addUInt32(uint32(m_specsCount)); uberInsert.addUInt32(uint32(m_activeSpec)); @@ -17461,9 +17624,7 @@ void Player::SaveToDB() } uberInsert.addString(ss); - uberInsert.addUInt32(GetUInt32Value(PLAYER_AMMO_ID)); - - for (uint32 i = 0; i < KNOWN_TITLES_SIZE * 2; ++i) // string + for(uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i ) //string { ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << " "; } @@ -18005,9 +18166,11 @@ void Player::_SaveSkills() continue; } - uint32 valueData = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)); - uint16 value = SKILL_VALUE(valueData); - uint16 max = SKILL_MAX(valueData); + uint16 field = itr->second.pos / 2; + uint8 offset = itr->second.pos & 1; + + uint16 value = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); switch (itr->second.uState) { @@ -18111,15 +18274,16 @@ void Player::_SaveStats() SqlStatement stmt = CharacterDatabase.CreateStatement(delStats, "DELETE FROM character_stats WHERE guid = ?"); stmt.PExecute(GetGUIDLow()); - stmt = CharacterDatabase.CreateStatement(insertStats, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, " - "strength, agility, stamina, intellect, spirit, armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, " - "blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, spellPower) " - "VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + stmt = CharacterDatabase.CreateStatement(insertStats, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5" + "strength, agility, stamina, intellect, spirit, armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, " + "blockPct, dodgePct, parryPct, critPct, rangedCritPct, spellCritPct, attackPower, rangedAttackPower, spellPower) " + "VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); stmt.addUInt32(GetGUIDLow()); stmt.addUInt32(GetMaxHealth()); - for (int i = 0; i < MAX_POWERS; ++i) - stmt.addUInt32(GetMaxPower(Powers(i))); + static_assert(MAX_STORED_POWERS == 5, "Query not updated."); + for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) + stmt.addUInt32(GetMaxPowerByIndex(i)); for (int i = 0; i < MAX_STATS; ++i) stmt.addFloat(GetStat(Stats(i))); // armor + school resistances @@ -18430,13 +18594,16 @@ void Player::RemovePet(PetSaveMode mode) pet->Unsummon(mode, this); } -void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const +void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix) const { *data << uint8(msgtype); *data << uint32(language); - *data << ObjectGuid(GetObjectGuid()); - *data << uint32(0); // 2.1.0 - *data << ObjectGuid(GetObjectGuid()); + *data << GetObjectGuid(); + *data << uint32(0); // constant unknown time 4.3.4 + if (addonPrefix) + *data << addonPrefix; + else + *data << GetObjectGuid(); *data << uint32(text.length() + 1); *data << text; *data << uint8(GetChatTag()); @@ -18465,22 +18632,15 @@ void Player::TextEmote(const std::string& text) void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiver) { - if (language != LANG_ADDON) // if not addon data - language = LANG_UNIVERSAL; // whispers should always be readable - Player* rPlayer = sObjectMgr.GetPlayer(receiver); WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_WHISPER, text, language); rPlayer->GetSession()->SendPacket(&data); - // not send confirmation for addon messages - if (language != LANG_ADDON) - { - data.Initialize(SMSG_MESSAGECHAT, 200); - rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language); - GetSession()->SendPacket(&data); - } + data.Initialize(SMSG_MESSAGECHAT, 200); + rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language); + GetSession()->SendPacket(&data); if (!isAcceptWhispers()) { @@ -18495,6 +18655,17 @@ void Player::Whisper(const std::string& text, uint32 language, ObjectGuid receiv ChatHandler(this).PSendSysMessage(LANG_PLAYER_DND, rPlayer->GetName(), rPlayer->autoReplyMsg.c_str()); } +void Player::WhisperAddon(const std::string& text, const std::string& prefix, ObjectGuid receiver) +{ + Player* rPlayer = sObjectMgr.GetPlayer(receiver); + + std::string _text(text); + + WorldPacket data(SMSG_MESSAGECHAT, 200); + BuildPlayerChat(&data, CHAT_MSG_WHISPER, _text, LANG_UNIVERSAL, prefix.c_str()); + rPlayer->GetSession()->SendPacket(&data); +} + void Player::PetSpellInitialize() { Pet* pet = GetPet(); @@ -19346,7 +19517,7 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorGuid, uint32 vendorslot, uin if (uint32 extendedCostId = crItem->ExtendedCost) { - ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(extendedCostId); + ItemExtendedCostEntry const* iece = sItemExtendedCostStore.LookupEntry(extendedCostId); if (!iece) { sLog.outError("Item %u have wrong ExtendedCost field value %u", pProto->ItemId, extendedCostId); @@ -19572,9 +19743,9 @@ void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 it // if no cooldown found above then base at DBC data if (rec < 0 && catrec < 0) { - cat = spellInfo->Category; - rec = spellInfo->RecoveryTime; - catrec = spellInfo->CategoryRecoveryTime; + cat = spellInfo->GetCategory(); + rec = spellInfo->GetRecoveryTime(); + catrec = spellInfo->GetCategoryRecoveryTime(); } time_t curTime = time(NULL); @@ -20309,9 +20480,8 @@ void Player::SendInitialPacketsAfterAddToMap() // manual send package (have code in ApplyModifier(true,true); that don't must be re-applied. if (HasAuraType(SPELL_AURA_MOD_ROOT)) { - WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10); - data2 << GetPackGUID(); - data2 << (uint32)2; + WorldPacket data2; + BuildForceMoveRootPacket(&data2, true, 2); SendMessageToSet(&data2, true); } @@ -20338,14 +20508,8 @@ void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg) WorldPacket data(SMSG_TRANSFER_ABORTED, 4 + 2); data << uint32(mapid); data << uint8(reason); // transfer abort reason - switch (reason) - { - case TRANSFER_ABORT_INSUF_EXPAN_LVL: - case TRANSFER_ABORT_DIFFICULTY: - case TRANSFER_ABORT_UNIQUE_MESSAGE: - data << uint8(arg); - break; - } + data << uint8(arg); + GetSession()->SendPacket(&data); } @@ -20449,10 +20613,13 @@ void Player::learnQuestRewardedSpells(Quest const* quest) bool found = false; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { - if (spellInfo->Effect[i] == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellInfo->EffectTriggerSpell[i])) + if(SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(i))) { - found = true; - break; + if(spellEffect->Effect == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellEffect->EffectTriggerSpell)) + { + found = true; + break; + } } } @@ -20461,8 +20628,10 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // prevent learn non first rank unknown profession and second specialization for same profession) - uint32 learned_0 = spellInfo->EffectTriggerSpell[EFFECT_INDEX_0]; - if (sSpellMgr.GetSpellRank(learned_0) > 1 && !HasSpell(learned_0)) + SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(EFFECT_INDEX_0); + uint32 learned_0 = spellEffect ? spellEffect->EffectTriggerSpell : 0; + + if( sSpellMgr.GetSpellRank(learned_0) > 1 && !HasSpell(learned_0) ) { // not have first rank learned (unlearned prof?) uint32 first_spell = sSpellMgr.GetFirstSpellInChain(learned_0); @@ -20474,7 +20643,9 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // specialization - if (learnedInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effect[EFFECT_INDEX_1] == 0) + SpellEffectEntry const* learnedSpellEffect0 = learnedInfo->GetSpellEffect(EFFECT_INDEX_0); + SpellEffectEntry const* learnedSpellEffect1 = learnedInfo->GetSpellEffect(EFFECT_INDEX_1); + if (learnedSpellEffect0 && learnedSpellEffect0->Effect == SPELL_EFFECT_TRADE_SKILL && learnedSpellEffect1 && learnedSpellEffect1->Effect == 0) { // search other specialization for same prof for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) @@ -20487,7 +20658,9 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // compare only specializations - if (itrInfo->Effect[EFFECT_INDEX_0] != SPELL_EFFECT_TRADE_SKILL || itrInfo->Effect[EFFECT_INDEX_1] != 0) + SpellEffectEntry const* itrSpellEffect0 = learnedInfo->GetSpellEffect(EFFECT_INDEX_0); + SpellEffectEntry const* itrSpellEffect1 = learnedInfo->GetSpellEffect(EFFECT_INDEX_1); + if ((itrSpellEffect0 && itrSpellEffect0->Effect != SPELL_EFFECT_TRADE_SKILL) || (itrSpellEffect1 && itrSpellEffect1->Effect != 0)) continue; // compare same chain spells @@ -20770,7 +20943,7 @@ void Player::UpdateForQuestWorldObjects() if (m_clientGUIDs.empty()) return; - UpdateData udata; + UpdateData udata(GetMapId()); WorldPacket packet; for (GuidSet::const_iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr) { @@ -20889,12 +21062,13 @@ void Player::AutoUnequipOffhandIfNeed() bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem) { - if (spellInfo->EquippedItemClass < 0) + int32 itemClass = spellInfo->GetEquippedItemClass(); + if(itemClass < 0) return true; // scan other equipped items for same requirements (mostly 2 daggers/etc) // for optimize check 2 used cases only - switch (spellInfo->EquippedItemClass) + switch(itemClass) { case ITEM_CLASS_WEAPON: { @@ -20925,7 +21099,7 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons break; } default: - sLog.outError("HasItemFitToSpellReqirements: Not handled spell requirement for item class %u", spellInfo->EquippedItemClass); + sLog.outError("HasItemFitToSpellReqirements: Not handled spell requirement for item class %u", itemClass); break; } @@ -21861,6 +22035,7 @@ void Player::_LoadSkills(QueryResult* result) // SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid)); uint32 count = 0; + uint8 professionCount = 0; if (result) { do @@ -21898,9 +22073,28 @@ void Player::_LoadSkills(QueryResult* result) continue; } - SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill, 0)); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), MAKE_SKILL_VALUE(value, max)); - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0); + uint16 field = count / 2; + uint8 offset = count & 1; + + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, skill); + uint16 step = 0; + + if (pSkill->categoryId == SKILL_CATEGORY_SECONDARY) + step = max / 75; + + if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) + { + step = max / 75; + + if (professionCount < 2) + SetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1 + professionCount++, skill); + } + + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, value); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, max); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(count, SKILL_UNCHANGED))); @@ -21920,9 +22114,15 @@ void Player::_LoadSkills(QueryResult* result) for (; count < PLAYER_MAX_SKILLS; ++count) { - SetUInt32Value(PLAYER_SKILL_INDEX(count), 0); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), 0); - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0); + uint16 field = count / 2; + uint8 offset = count & 1; + + SetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); + SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); } // special settings @@ -22149,7 +22349,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) return; // Check if it requires another talent - if (talentInfo->DependsOn > 0) + /*if (talentInfo->DependsOn > 0) { if (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) { @@ -22165,7 +22365,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) if (!hasEnoughRank) return; } - } + }*/ // Find out how many points we have in this field uint32 spentPoints = 0; @@ -22263,7 +22463,7 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa return; // Check if it requires another talent - if (talentInfo->DependsOn > 0) + /*if (talentInfo->DependsOn > 0) { if (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) { @@ -22277,7 +22477,7 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa if (!hasEnoughRank) return; } - } + }*/ // Find out how many points we have in this field uint32 spentPoints = 0; @@ -22332,18 +22532,18 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa void Player::UpdateKnownCurrencies(uint32 itemId, bool apply) { - if (CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId)) - { - if (apply) - SetFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); - else - RemoveFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); - } + //if(CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId)) + //{ + // if(apply) + // SetFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); + // else + // RemoveFlag64(PLAYER_FIELD_KNOWN_CURRENCIES, (UI64LIT(1) << (ctEntry->BitIndex - 1))); + //} } void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode) { - if (m_lastFallTime >= minfo.GetFallTime() || m_lastFallZ <= minfo.GetPos()->z || opcode == MSG_MOVE_FALL_LAND) + if (m_lastFallTime >= minfo.GetFallTime() || m_lastFallZ <= minfo.GetPos()->z || opcode == CMSG_MOVE_FALL_LAND) SetFallInformation(minfo.GetFallTime(), minfo.GetPos()->z); } @@ -22939,17 +23139,6 @@ void Player::SendClearCooldown(uint32 spell_id, Unit* target) SendDirectMessage(&data); } -void Player::BuildTeleportAckMsg(WorldPacket& data, float x, float y, float z, float ang) const -{ - MovementInfo mi = m_movementInfo; - mi.ChangePosition(x, y, z, ang); - - data.Initialize(MSG_MOVE_TELEPORT_ACK, 64); - data << GetPackGUID(); - data << uint32(0); // this value increments every time - data << mi; -} - bool Player::HasMovementFlag(MovementFlags f) const { return m_movementInfo.HasMovementFlag(f); @@ -22983,20 +23172,25 @@ void Player::SendDuelCountdown(uint32 counter) bool Player::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index) const { - switch (spellInfo->Effect[index]) + SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(index); + if(spellEffect) { - case SPELL_EFFECT_ATTACK_ME: - return true; - default: - break; - } - switch (spellInfo->EffectApplyAuraName[index]) - { - case SPELL_AURA_MOD_TAUNT: - return true; - default: - break; + switch(spellEffect->Effect) + { + case SPELL_EFFECT_ATTACK_ME: + return true; + default: + break; + } + switch(spellEffect->EffectApplyAuraName) + { + case SPELL_AURA_MOD_TAUNT: + return true; + default: + break; + } } + return Unit::IsImmuneToSpellEffect(spellInfo, index); } diff --git a/src/game/Player.h b/src/game/Player.h index a2eba49fb..e82db23d8 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2196,8 +2196,6 @@ class MANGOS_DLL_SPEC Player : public Unit } void HandleFall(MovementInfo const& movementInfo); - void BuildTeleportAckMsg(WorldPacket& data, float x, float y, float z, float ang) const; - bool isMoving() const { return m_movementInfo.HasMovementFlag(movementFlagsMask); } bool isMovingOrTurning() const { return m_movementInfo.HasMovementFlag(movementOrTurningFlagsMask); } diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index d22de5023..cba99fbbb 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -139,6 +139,9 @@ void WorldSession::SendPacket(WorldPacket const* packet) return; } + sLog.outError("SESSION: sent packet 0x%.4X (%s) to %s (%u)", packet->GetOpcode(), + LookupOpcodeName(packet->GetOpcode()), GetPlayerName(), GetAccountId()); + const_cast(packet)->FlushBits(); #ifdef MANGOS_DEBUG @@ -219,6 +222,9 @@ bool WorldSession::Update(PacketFilter& updater) packet->GetOpcode()); #endif*/ + sLog.outError("SESSION: received packet 0x%.4X (%s) from %s (%u)", packet->GetOpcode(), + LookupOpcodeName(packet->GetOpcode()), GetPlayerName(), GetAccountId()); + OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()]; try { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b9092185a..af0f25f02 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "12089" + #define REVISION_NR "0072" #endif // __REVISION_NR_H__