diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 5bb530167..a04cb7f9e 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -764,7 +764,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder) pCurrChar->CastSpell(pCurrChar, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - pCurrChar->SetMovement(MOVE_WATER_WALK); + pCurrChar->SetWaterWalk(true); } pCurrChar->ContinueTaxiFlight(); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 8c008b120..78dd3fd12 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -2554,7 +2554,32 @@ void Creature::SetLevitate(bool enable) m_movementInfo.AddMovementFlag(MOVEFLAG_LEVITATING); else m_movementInfo.RemoveMovementFlag(MOVEFLAG_LEVITATING); + WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9); data << GetPackGUID(); SendMessageToSet(&data, true); } + +void Creature::SetRoot(bool enable) +{ + if (enable) + m_movementInfo.AddMovementFlag(MOVEFLAG_ROOT); + else + m_movementInfo.RemoveMovementFlag(MOVEFLAG_ROOT); + + WorldPacket data(enable ? SMSG_SPLINE_MOVE_ROOT : SMSG_SPLINE_MOVE_UNROOT, 9); + data << GetPackGUID(); + SendMessageToSet(&data, true); +} + +void Creature::SetWaterWalk(bool enable) +{ + if (enable) + m_movementInfo.AddMovementFlag(MOVEFLAG_WATERWALKING); + else + m_movementInfo.RemoveMovementFlag(MOVEFLAG_WATERWALKING); + + WorldPacket data(enable ? SMSG_SPLINE_MOVE_WATER_WALK : SMSG_SPLINE_MOVE_LAND_WALK, 9); + data << GetPackGUID(); + SendMessageToSet(&data, true); +} diff --git a/src/game/Creature.h b/src/game/Creature.h index 954f52b10..a3cd20aa1 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -535,6 +535,8 @@ class MANGOS_DLL_SPEC Creature : public Unit void SetWalk(bool enable); void SetLevitate(bool enable); + void SetRoot(bool enable) override; + void SetWaterWalk(bool enable) override; uint32 GetShieldBlockValue() const override // dunno mob block value { diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 5b553a703..e4ded3806 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -4998,9 +4998,9 @@ bool ChatHandler::HandleWaterwalkCommand(char* args) return false; if (value) - player->SetMovement(MOVE_WATER_WALK); // ON + player->SetWaterWalk(true); // ON else - player->SetMovement(MOVE_LAND_WALK); // OFF + player->SetWaterWalk(false); // OFF PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str()); if (needReportToTarget(player)) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a17a2231e..2daab2270 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -63,13 +63,24 @@ #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, @@ -264,26 +275,6 @@ 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 @@ -435,7 +426,6 @@ 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); @@ -552,8 +542,6 @@ 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; @@ -571,8 +559,6 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ m_lastFallZ = 0; m_cachedGS = 0; - - m_slot = 255; } Player::~Player() @@ -696,16 +682,18 @@ 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) - SetInGuild( 0 ); - SetUInt32Value( PLAYER_GUILDRANK, 0 ); - SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 ); + SetUInt32Value(PLAYER_GUILDID, 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_KILLS, 0); + SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0); + SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0); // set starting level uint32 start_level = getClass() != CLASS_DEATH_KNIGHT @@ -853,9 +841,6 @@ 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; } @@ -1459,17 +1444,18 @@ void Player::SetDeathState(DeathState s) } } -bool Player::BuildEnumData(QueryResult* result, ByteBuffer* data, ByteBuffer* buffer) +bool Player::BuildEnumData(QueryResult* result, WorldPacket* 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, " // 8 9 10 11 12 13 14 // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, guild_member.guildid, characters.playerFlags, " - // 15 16 17 18 19 20 21 - // "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, characters.slot, character_declinedname.genitive " + // 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(); - ObjectGuid guid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); + + uint32 guid = fields[0].GetUInt32(); uint8 pRace = fields[2].GetUInt8(); uint8 pClass = fields[3].GetUInt8(); @@ -1480,143 +1466,126 @@ bool Player::BuildEnumData(QueryResult* result, ByteBuffer* data, ByteBuffer* bu return false; } - // FIXME - //ObjectGuid guildGuid = ObjectGuid(HIGHGUID_GUILD, fields[13].GetUInt32()); - ObjectGuid guildGuid = ObjectGuid(uint64(fields[13].GetUInt32())); - std::string name = fields[1].GetCppString(); - uint8 gender = fields[4].GetUInt8(); + *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 + uint32 playerBytes = fields[5].GetUInt32(); - uint8 level = fields[7].GetUInt8(); + *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; uint32 playerFlags = fields[14].GetUInt32(); uint32 atLoginFlags = fields[15].GetUInt32(); - uint32 zone = fields[8].GetUInt32(); - uint32 petDisplayId = 0; - uint32 petLevel = 0; - uint32 petFamily = 0; - uint32 char_flags = 0; - - data->WriteGuidMask<3>(guid); - data->WriteGuidMask<1, 7, 2>(guildGuid); - data->WriteBits(name.length(), 7); - data->WriteGuidMask<4, 7>(guid); - data->WriteGuidMask<3>(guildGuid); - data->WriteGuidMask<5>(guid); - data->WriteGuidMask<6>(guildGuid); - data->WriteGuidMask<1>(guid); - data->WriteGuidMask<5, 4>(guildGuid); - data->WriteBit(atLoginFlags & AT_LOGIN_FIRST); - data->WriteGuidMask<0, 2, 6>(guid); - data->WriteGuidMask<0>(guildGuid); - - // 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; - } - } - - if(playerFlags & PLAYER_FLAGS_HIDE_HELM) + if (playerFlags & PLAYER_FLAGS_HIDE_HELM) char_flags |= CHARACTER_FLAG_HIDE_HELM; - if(playerFlags & PLAYER_FLAGS_HIDE_CLOAK) + if (playerFlags & PLAYER_FLAGS_HIDE_CLOAK) char_flags |= CHARACTER_FLAG_HIDE_CLOAK; - if(playerFlags & PLAYER_FLAGS_GHOST) + if (playerFlags & PLAYER_FLAGS_GHOST) char_flags |= CHARACTER_FLAG_GHOST; - if(atLoginFlags & AT_LOGIN_RENAME) + if (atLoginFlags & AT_LOGIN_RENAME) char_flags |= CHARACTER_FLAG_RENAME; - if(sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED)) + if (sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED)) { - if(!fields[21].GetCppString().empty()) + if (!fields[20].GetCppString().empty()) char_flags |= CHARACTER_FLAG_DECLINED; } else char_flags |= CHARACTER_FLAG_DECLINED; - *buffer << uint8(pClass); // class + *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); - Tokens tdata = StrSplit(fields[19].GetCppString(), " "); + // Pets 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); + } + + + Tokens data = StrSplit(fields[19].GetCppString(), " "); for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) { uint32 visualbase = slot * 2; - uint32 item_id = GetUInt32ValueFromArray(tdata, visualbase); - const ItemPrototype * proto = ObjectMgr::GetItemPrototype(item_id); - if(!proto) + uint32 item_id = GetUInt32ValueFromArray(data, visualbase); + const ItemPrototype* proto = ObjectMgr::GetItemPrototype(item_id); + if (!proto) { - *buffer << uint8(0); - *buffer << uint32(0); - *buffer << uint32(0); + *p_data << uint32(0); + *p_data << uint8(0); + *p_data << uint32(0); continue; } - SpellItemEnchantmentEntry const *enchant = NULL; + SpellItemEnchantmentEntry const* enchant = NULL; - uint32 enchants = GetUInt32ValueFromArray(tdata, visualbase + 1); - for(uint8 enchantSlot = PERM_ENCHANTMENT_SLOT; enchantSlot <= TEMP_ENCHANTMENT_SLOT; ++enchantSlot) + uint32 enchants = GetUInt32ValueFromArray(data, visualbase + 1); + 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; } - *buffer << uint8(proto->InventoryType); - *buffer << uint32(proto->DisplayInfoID); - *buffer << uint32(enchant ? enchant->aura_id : 0); + *p_data << uint32(proto->DisplayInfoID); + *p_data << uint8(proto->InventoryType); + *p_data << uint32(enchant ? enchant->aura_id : 0); } - for (int32 i = 0; i < 4; i++) - { - *buffer << uint8(0); - *buffer << uint32(0); - *buffer << uint32(0); - } - - *buffer << uint32(petFamily); // Pet DisplayID - buffer->WriteGuidBytes<2>(guildGuid); - *buffer << uint8(fields[20].GetUInt8()); // char order id - *buffer << uint8((playerBytes >> 16) & 0xFF); // Hair style - buffer->WriteGuidBytes<3>(guildGuid); - *buffer << uint32(petDisplayId); // Pet DisplayID - *buffer << uint32(char_flags); // character flags - *buffer << uint8((playerBytes >> 24) & 0xFF); // Hair color - buffer->WriteGuidBytes<4>(guid); - *buffer << uint32(fields[9].GetUInt32()); // map - buffer->WriteGuidBytes<5>(guildGuid); - *buffer << fields[12].GetFloat(); // z - buffer->WriteGuidBytes<6>(guildGuid); - *buffer << uint32(petLevel); // pet level - buffer->WriteGuidBytes<3>(guid); - *buffer << fields[11].GetFloat(); // y - // character customize flags - *buffer << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? CHAR_CUSTOMIZE_FLAG_CUSTOMIZE : CHAR_CUSTOMIZE_FLAG_NONE); - - uint32 playerBytes2 = fields[6].GetUInt32(); - *buffer << uint8(playerBytes2 & 0xFF); // facial hair - buffer->WriteGuidBytes<7>(guid); - *buffer << uint8(gender); // Gender - buffer->append(name.c_str(), name.length()); - *buffer << uint8((playerBytes >> 8) & 0xFF); // face - - buffer->WriteGuidBytes<0, 2>(guid); - buffer->WriteGuidBytes<1, 7>(guildGuid); - - *buffer << fields[10].GetFloat(); // x - *buffer << uint8(playerBytes & 0xFF); // skin - *buffer << uint8(pRace); // Race - *buffer << uint8(level); // Level - buffer->WriteGuidBytes<6>(guid); - buffer->WriteGuidBytes<4, 0>(guildGuid); - buffer->WriteGuidBytes<5, 1>(guid); - - *buffer << uint32(zone); // Zone id + *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? return true; } @@ -1653,42 +1622,8 @@ 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); @@ -1775,16 +1710,14 @@ 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 CMSG_MOVE_TELEPORT_ACK + // at client packet MSG_MOVE_TELEPORT_ACK SetSemaphoreTeleportNear(true); - // near teleport, triggering send CMSG_MOVE_TELEPORT_ACK from client at landing + // near teleport, triggering send MSG_MOVE_TELEPORT_ACK from client at landing if (!GetSession()->PlayerLogout()) { - float oldX, oldY, oldZ; - float oldO = GetOrientation(); - GetPosition(oldX, oldY, oldZ);; - Relocate(x, y, z, orientation); - SendTeleportPacket(oldX, oldY, oldZ, oldO); + WorldPacket data; + BuildTeleportAckMsg(data, x, y, z, orientation); + GetSession()->SendPacket(&data); } } else @@ -1854,17 +1787,12 @@ 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.WriteBit(0); // unknown + data << uint32(mapid); if (m_transport) { - data.WriteBit(1); // has transport - data << uint32(GetMapId()); data << uint32(m_transport->GetEntry()); + data << uint32(GetMapId()); } - else - data.WriteBit(0); // has transport - - data << uint32(mapid); GetSession()->SendPacket(&data); } @@ -1898,26 +1826,22 @@ 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); + WorldPacket data(SMSG_NEW_WORLD, (20)); + data << uint32(mapid); if (m_transport) { data << float(m_movementInfo.GetTransportPos()->x); - data << float(m_movementInfo.GetTransportPos()->o); + data << float(m_movementInfo.GetTransportPos()->y); data << float(m_movementInfo.GetTransportPos()->z); + data << float(m_movementInfo.GetTransportPos()->o); } else { data << float(final_x); - 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); + data << float(final_z); + data << float(final_o); + } GetSession()->SendPacket(&data); SendSavedInstances(); @@ -2076,24 +2000,14 @@ 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 powerIndex = GetPowerIndex(power); - if (powerIndex == INVALID_POWER_INDEX) - return; - - uint32 maxValue = GetMaxPowerByIndex(powerIndex); - if (!maxValue) - return; - - uint32 curValue = GetPowerByIndex(powerIndex); + uint32 curValue = GetPower(power); + uint32 maxValue = GetMaxPower(power); float addvalue = 0.0f; @@ -2120,9 +2034,6 @@ 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); @@ -2153,6 +2064,8 @@ void Player::Regenerate(Powers power, uint32 diff) } } } break; + case POWER_FOCUS: + case POWER_HAPPINESS: case POWER_HEALTH: break; } @@ -2561,15 +2474,17 @@ void Player::GiveLevel(uint32 level) PlayerLevelInfo info; sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), level, &info); - uint32 basehp = 0, basemana = 0; - sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, basehp, basemana); + PlayerClassLevelInfo classInfo; + sObjectMgr.GetPlayerClassLevelInfo(getClass(), level, &classInfo); // send levelup info to client - WorldPacket data(SMSG_LEVELUP_INFO, (4 + 4 + MAX_STORED_POWERS * 4 + MAX_STATS * 4)); + WorldPacket data(SMSG_LEVELUP_INFO, (4 + 4 + MAX_POWERS * 4 + MAX_STATS * 4)); data << uint32(level); - 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(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(0); data << uint32(0); data << uint32(0); @@ -2595,8 +2510,8 @@ void Player::GiveLevel(uint32 level) for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetCreateStat(Stats(i), info.stats[i]); - SetCreateHealth(basehp); - SetCreateMana(basemana); + SetCreateHealth(classInfo.basehealth); + SetCreateMana(classInfo.basemana); InitTalentForLevel(); InitTaxiNodesForLevel(); @@ -2612,6 +2527,7 @@ 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); @@ -2670,8 +2586,8 @@ void Player::InitStatsForLevel(bool reapplyMods) if (reapplyMods) // reapply stats values only on .reset stats (level) command _RemoveAllStatBonuses(); - uint32 basehp = 0, basemana = 0; - sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), basehp, basemana); + PlayerClassLevelInfo classInfo; + sObjectMgr.GetPlayerClassLevelInfo(getClass(), getLevel(), &classInfo); PlayerLevelInfo info; sObjectMgr.GetPlayerLevelInfo(getRace(), getClass(), getLevel(), &info); @@ -2694,10 +2610,10 @@ void Player::InitStatsForLevel(bool reapplyMods) for (int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetStat(Stats(i), info.stats[i]); - SetCreateHealth(basehp); + SetCreateHealth(classInfo.basehealth); // set create powers - SetCreateMana(basemana); + SetCreateMana(classInfo.basemana); SetArmor(int32(m_createStats[STAT_AGILITY] * 2)); @@ -2727,14 +2643,12 @@ 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_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); + 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); // Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset SetFloatValue(PLAYER_CRIT_PERCENTAGE, 0.0f); @@ -2779,9 +2693,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(basehp); // stamina bonus will applied later + SetMaxHealth(classInfo.basehealth); // 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); @@ -2817,6 +2731,7 @@ 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 @@ -2864,7 +2779,7 @@ void Player::SendInitialSpells() data << uint32(itr->first); data << uint16(itr->second.itemid); // cast item id - data << uint16(sEntry->GetCategory()); // spell category + data << uint16(sEntry->Category); // spell category // send infinity cooldown in special format if (itr->second.end >= infTime) @@ -2876,7 +2791,7 @@ void Player::SendInitialSpells() time_t cooldown = itr->second.end > curTime ? (itr->second.end - curTime) * IN_MILLISECONDS : 0; - if(sEntry->GetCategory()) // may be wrong, but anyway better than nothing... + if (sEntry->Category) // may be wrong, but anyway better than nothing... { data << uint32(0); // cooldown data << uint32(cooldown); // category cooldown @@ -3293,13 +3208,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, GetSkillStep(pSkill->id)); + SetSkill(pSkill->id, 300, 300); break; case SKILL_RANGE_LEVEL: - SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel(), GetSkillStep(pSkill->id)); + SetSkill(pSkill->id, 1, GetMaxSkillValueForLevel()); break; case SKILL_RANGE_MONO: - SetSkill(pSkill->id, 1, 1, GetSkillStep(pSkill->id)); + SetSkill(pSkill->id, 1, 1); break; default: break; @@ -3350,12 +3265,10 @@ 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 - SpellShapeshiftEntry const* shapeShift = spellInfo->GetSpellShapeshift(); - bool need_cast = (!shapeShift || !shapeShift->Stances || (!form && spellInfo->HasAttribute(SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT))); + bool need_cast = !spellInfo->Stances || (!form && spellInfo->HasAttribute(SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT)); // Check CasterAuraStates - SpellAuraRestrictionsEntry const* auraRestrictions = spellInfo->GetSpellAuraRestrictions(); - return need_cast && (auraRestrictions && (!auraRestrictions->CasterAuraState || HasAuraState(AuraState(auraRestrictions->CasterAuraState)))); + return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))); } void Player::learnSpell(uint32 spell_id, bool dependent) @@ -3372,7 +3285,7 @@ void Player::learnSpell(uint32 spell_id, bool dependent) { WorldPacket data(SMSG_LEARNED_SPELL, 6); data << uint32(spell_id); - data << uint32(0); // 3.3.3 unk + data << uint16(0); // 3.3.3 unk GetSession()->SendPacket(&data); } @@ -3526,7 +3439,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, GetSkillStep(pSkill->id)); + SetSkill(pSkill->id, 0, 0); } } } @@ -3645,9 +3558,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->GetRecoveryTime() <= 15 * MINUTE * IN_MILLISECONDS && - entry->GetCategoryRecoveryTime() <= 15 * MINUTE * IN_MILLISECONDS ) + if (entry && + entry->RecoveryTime <= 15 * MINUTE * IN_MILLISECONDS && + entry->CategoryRecoveryTime <= 15 * MINUTE * IN_MILLISECONDS) { // remove & notify RemoveSpellCooldown(itr->first, true); @@ -3659,21 +3572,8 @@ void Player::RemoveAllSpellCooldown() { if (!m_spellCooldowns.empty()) { - ObjectGuid guid = GetObjectGuid(); - - WorldPacket data(SMSG_CLEAR_COOLDOWNS, 1 + 8 + m_spellCooldowns.size() * 4); - data.WriteGuidMask<1, 3, 6>(guid); - data.WriteBits(m_spellCooldowns.size(), 24); // cooldown count - data.WriteGuidMask<7, 5, 2, 4, 0>(guid); - - data.WriteGuidBytes<7, 2, 4, 5, 1, 3>(guid); - for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr) - data << uint32(itr->first); - - data.WriteGuidBytes<0, 6>(guid); - - SendDirectMessage(&data); + SendClearCooldown(itr->first, this); m_spellCooldowns.clear(); } @@ -3940,8 +3840,6 @@ 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); @@ -3960,12 +3858,16 @@ 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); @@ -3994,15 +3896,13 @@ 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) @@ -4049,27 +3949,9 @@ 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); @@ -4158,10 +4040,9 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->learnedSpell); // secondary prof. or not prof. spell - SpellEffectEntry const* spellEffect = spell->GetSpellEffect(EFFECT_INDEX_1); - uint32 skill = spellEffect ? spellEffect->EffectMiscValue : 0; + uint32 skill = spell->EffectMiscValue[1]; - if(spellEffect && (spellEffect->Effect != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill))) + if (spell->Effect[1] != SPELL_EFFECT_SKILL || !IsPrimaryProfessionSkill(skill)) return TRAINER_SPELL_GREEN; // check primary prof. limit @@ -4447,28 +4328,19 @@ void Player::DeleteOldCharacters(uint32 keepDays) } } -void Player::SetMovement(PlayerMovementType pType) +void Player::SetRoot(bool enable) { - WorldPacket data; - switch (pType) - { - 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; - } + WorldPacket data(enable ? SMSG_FORCE_MOVE_ROOT : SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size() + 4)); + data << GetPackGUID(); + data << uint32(0); + GetSession()->SendPacket(&data); +} +void Player::SetWaterWalk(bool enable) +{ + WorldPacket data(enable ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, GetPackGUID().size() + 4)); + data << GetPackGUID(); + data << uint32(0); GetSession()->SendPacket(&data); } @@ -4509,9 +4381,9 @@ void Player::BuildPlayerRepop() // convert player body to ghost SetHealth(1); - SetMovement(MOVE_WATER_WALK); + SetWaterWalk(true); if (!GetSession()->isLogingOut()) - SetMovement(MOVE_UNROOT); + SetRoot(false); // BG - remove insignia related RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); @@ -4547,8 +4419,8 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) RemoveAurasDueToSpell(20584); // speed bonuses RemoveAurasDueToSpell(8326); // SPELL_AURA_GHOST - SetMovement(MOVE_LAND_WALK); - SetMovement(MOVE_UNROOT); + SetWaterWalk(false); + SetRoot(false); m_deathTimer = 0; @@ -4601,7 +4473,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) void Player::KillPlayer() { - SetMovement(MOVE_ROOT); + SetRoot(true); StopMirrorTimers(); // disable timers(bars) @@ -4662,6 +4534,8 @@ Corpse* Player::CreateCorpse() corpse->SetUInt32Value(CORPSE_FIELD_DISPLAY_ID, GetNativeDisplayId()); + corpse->SetUInt32Value(CORPSE_FIELD_GUILD, GetGuildId()); + uint32 iDisplayID; uint32 iIventoryType; uint32 _cfi; @@ -5244,23 +5118,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() @@ -5368,12 +5242,24 @@ void Player::UpdateRating(CombatRating cr) if (affectStats) UpdateAllSpellCritChances(); break; - case CR_RESILIENCE_DAMAGE_TAKEN: + case CR_HIT_TAKEN_MELEE: // Implemented in Unit::MeleeMissChanceCalc + case CR_HIT_TAKEN_RANGED: + break; + case CR_HIT_TAKEN_SPELL: // Implemented in Unit::MagicSpellHitResult + break; + case CR_CRIT_TAKEN_MELEE: // Implemented in Unit::RollMeleeOutcomeAgainst (only for chance to crit) + case CR_CRIT_TAKEN_RANGED: + break; + case CR_CRIT_TAKEN_SPELL: // Implemented in Unit::SpellCriticalBonus (only for chance to crit) break; case CR_HASTE_MELEE: // Implemented in Player::ApplyRatingMod case CR_HASTE_RANGED: case CR_HASTE_SPELL: break; + case CR_WEAPON_SKILL_MAINHAND: // Implemented in Unit::RollMeleeOutcomeAgainst + case CR_WEAPON_SKILL_OFFHAND: + case CR_WEAPON_SKILL_RANGED: + break; case CR_EXPERTISE: if (affectStats) { @@ -5385,16 +5271,6 @@ void Player::UpdateRating(CombatRating cr) if (affectStats) UpdateArmorPenetration(); break; - // deprecated - case CR_HIT_TAKEN_MELEE: - case CR_HIT_TAKEN_RANGED: - case CR_HIT_TAKEN_SPELL: - case CR_CRIT_TAKEN_SPELL: - case CR_CRIT_TAKEN_MELEE: - case CR_WEAPON_SKILL_MAINHAND: - case CR_WEAPON_SKILL_OFFHAND: - case CR_WEAPON_SKILL_RANGED: - break; } } @@ -5426,18 +5302,14 @@ 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; - 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); + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint32 data = GetUInt32Value(valueIndex); + uint32 value = SKILL_VALUE(data); + uint32 max = SKILL_MAX(data); if ((!max) || (!value) || (value >= max)) return false; @@ -5448,7 +5320,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) if (new_value > max) new_value = max; - SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value); + SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, max)); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id); @@ -5483,7 +5355,7 @@ bool Player::UpdateCraftSkill(uint32 spellid) // Alchemy Discoveries here SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellid); - if (spellEntry && spellEntry->GetMechanic() == MECHANIC_DISCOVERY) + if (spellEntry && spellEntry->Mechanic == MECHANIC_DISCOVERY) { if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this)) learnSpell(discoveredSpell, false); @@ -5563,11 +5435,11 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return false; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); - uint16 SkillValue = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); - uint16 MaxValue = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); + uint32 data = GetUInt32Value(valueIndex); + uint16 SkillValue = SKILL_VALUE(data); + uint16 MaxValue = SKILL_MAX(data); if (!MaxValue || !SkillValue || SkillValue >= MaxValue) return false; @@ -5576,16 +5448,16 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) if (Roll <= Chance) { - uint16 new_value = SkillValue + step; + uint32 new_value = SkillValue + step; if (new_value > MaxValue) new_value = MaxValue; - SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, new_value); + SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(new_value, MaxValue)); 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; @@ -5669,12 +5541,16 @@ void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent) if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return; - 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 bonusIndex = PLAYER_SKILL_BONUS_INDEX(itr->second.pos); - uint16 bonus = GetUInt16Value(field, offset); + uint32 bonus_val = GetUInt32Value(bonusIndex); + int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val); + int16 perm_bonus = SKILL_PERM_BONUS(bonus_val); - SetUInt16Value(field, offset, bonus + val); + 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)); } void Player::UpdateSkillsForLevel() @@ -5698,11 +5574,10 @@ void Player::UpdateSkillsForLevel() if (GetSkillRangeType(pSkill, false) != SKILL_RANGE_LEVEL) continue; - 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); + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint32 data = GetUInt32Value(valueIndex); + uint32 max = SKILL_MAX(data); + uint32 val = SKILL_VALUE(data); /// update only level dependent max skill values if (max != 1) @@ -5710,16 +5585,14 @@ void Player::UpdateSkillsForLevel() /// maximize skill always if (alwaysMaxSkill) { - SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, maxSkill); - SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill); + SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill, 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 { - SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, val); - SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxSkill); + SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val, maxSkill)); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; } @@ -5737,14 +5610,14 @@ void Player::UpdateSkillsToMaxSkillsForLevel() uint32 pskill = itr->first; if (IsProfessionOrRidingSkill(pskill)) continue; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 + uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos); + uint32 data = GetUInt32Value(valueIndex); - uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); + uint32 max = SKILL_MAX(data); if (max > 1) { - SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, max); + SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(max, max)); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, pskill); @@ -5762,36 +5635,29 @@ 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) { - SetUInt16Value(PLAYER_SKILL_STEP_0 + field, offset, step); + if (step) // need update step + SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos), MAKE_PAIR32(id, step)); // update value - SetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset, currVal); - SetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset, maxVal); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos), MAKE_SKILL_VALUE(currVal, maxVal)); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; - learnSkillRewardedSpells(id, oldVal); + learnSkillRewardedSpells(id, currVal); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); } else // remove { // clear skill fields - 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); + 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); // mark as deleted or simply remove from map if not saved yet if (itr->second.uState != SKILL_NEW) @@ -5810,10 +5676,7 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 { for (int i = 0; i < PLAYER_MAX_SKILLS; ++i) { - uint16 field = i / 2; - uint8 offset = i & 1; // i % 2 - - if (!GetUInt16Value(PLAYER_SKILL_LINEID_0 + field, offset)) + if (!GetUInt32Value(PLAYER_SKILL_INDEX(i))) { SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(id); if (!pSkill) @@ -5822,10 +5685,8 @@ void Player::SetSkill(uint16 id, uint16 currVal, uint16 maxVal, uint16 step /*=0 return; } - 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); + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id, step)); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i), MAKE_SKILL_VALUE(currVal, maxVal)); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id); @@ -5839,8 +5700,7 @@ 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 - SetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset, 0); - SetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset, 0); + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i), 0); // temporary bonuses AuraList const& mModSkill = GetAurasByType(SPELL_AURA_MOD_SKILL); @@ -5871,18 +5731,6 @@ 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) @@ -5892,12 +5740,11 @@ uint16 Player::GetSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; + uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); - 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)); + int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); + result += SKILL_TEMP_BONUS(bonus); + result += SKILL_PERM_BONUS(bonus); return result < 0 ? 0 : result; } @@ -5910,12 +5757,11 @@ uint16 Player::GetMaxSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; + uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)); - 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)); + int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)))); + result += SKILL_TEMP_BONUS(bonus); + result += SKILL_PERM_BONUS(bonus); return result < 0 ? 0 : result; } @@ -5928,10 +5774,7 @@ uint16 Player::GetPureMaxSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; - - return GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); + return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); } uint16 Player::GetBaseSkillValue(uint32 skill) const @@ -5943,11 +5786,8 @@ uint16 Player::GetBaseSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - 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)); + 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))); return result < 0 ? 0 : result; } @@ -5960,10 +5800,7 @@ uint16 Player::GetPureSkillValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; - - return GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))); } int16 Player::GetSkillPermBonusValue(uint32 skill) const @@ -5975,10 +5812,7 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; - - return GetUInt16Value(PLAYER_SKILL_TALENT_0 + field, offset); + return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); } int16 Player::GetSkillTempBonusValue(uint32 skill) const @@ -5990,10 +5824,7 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED) return 0; - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; - - return GetUInt16Value(PLAYER_SKILL_MODIFIER_0 + field, offset); + return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos))); } void Player::SendInitialActionButtons() const @@ -6001,6 +5832,7 @@ 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) { @@ -6010,7 +5842,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); } @@ -6565,14 +6397,16 @@ 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_KILLS, MAKE_PAIR32(0,kills_today)); + SetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, 0); + 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); } } @@ -6706,7 +6540,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, float honor) // add honor points ModifyHonorPoints(int32(honor)); - // FIXME 4x ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); + ApplyModUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION, uint32(honor), true); return true; } @@ -6715,9 +6549,7 @@ void Player::SetHonorPoints(uint32 value) if (value > sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS)) value = sWorld.getConfig(CONFIG_UINT32_MAX_HONOR_POINTS); - // FIXME 4x SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value); - // must be recalculated to new honor points items and removed - m_honorPoints = value; + SetUInt32Value(PLAYER_FIELD_HONOR_CURRENCY, value); } void Player::SetArenaPoints(uint32 value) @@ -6725,9 +6557,7 @@ void Player::SetArenaPoints(uint32 value) if (value > sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS)) value = sWorld.getConfig(CONFIG_UINT32_MAX_ARENA_POINTS); - // FIXME 4x SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value); - // must be recalculated to new honor points items and removed - m_arenaPoints = value; + SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, value); } void Player::ModifyHonorPoints(int32 value) @@ -7142,7 +6972,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl if (ssd && ssd_level > ssd->MaxLevel) ssd_level = ssd->MaxLevel; - ScalingStatValuesEntry const* ssv = proto->StatScalingFactor ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL; + ScalingStatValuesEntry const* ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL; if (only_level_scale && !ssv) return; @@ -7156,10 +6986,12 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl if (ssd->StatMod[i] < 0) continue; statType = ssd->StatMod[i]; - val = (ssv->getssdMultiplier(proto->StatScalingFactor) * ssd->Modifier[i]) / 10000; + val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000; } else { + if (i >= proto->StatsCount) + continue; statType = proto->ItemStat[i].ItemStatType; val = proto->ItemStat[i].ItemStatValue; } @@ -7169,9 +7001,12 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl switch (statType) { - /*case ITEM_MOD_MANA: + case ITEM_MOD_MANA: HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); - break;*/ + break; + case ITEM_MOD_HEALTH: // modify HP + HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply); + break; case ITEM_MOD_AGILITY: // modify agility HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply); ApplyStatBuffMod(STAT_AGILITY, float(val), apply); @@ -7192,15 +7027,63 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply); ApplyStatBuffMod(STAT_STAMINA, float(val), apply); break; + case ITEM_MOD_DEFENSE_SKILL_RATING: + ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply); + break; case ITEM_MOD_DODGE_RATING: ApplyRatingMod(CR_DODGE, int32(val), apply); break; case ITEM_MOD_PARRY_RATING: ApplyRatingMod(CR_PARRY, int32(val), apply); break; + case ITEM_MOD_BLOCK_RATING: + ApplyRatingMod(CR_BLOCK, int32(val), apply); + break; + case ITEM_MOD_HIT_MELEE_RATING: + ApplyRatingMod(CR_HIT_MELEE, int32(val), apply); + break; + case ITEM_MOD_HIT_RANGED_RATING: + ApplyRatingMod(CR_HIT_RANGED, int32(val), apply); + break; + case ITEM_MOD_HIT_SPELL_RATING: + ApplyRatingMod(CR_HIT_SPELL, int32(val), apply); + break; + case ITEM_MOD_CRIT_MELEE_RATING: + ApplyRatingMod(CR_CRIT_MELEE, int32(val), apply); + break; case ITEM_MOD_CRIT_RANGED_RATING: ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply); break; + case ITEM_MOD_CRIT_SPELL_RATING: + ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply); + break; + case ITEM_MOD_HIT_TAKEN_MELEE_RATING: + ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply); + break; + case ITEM_MOD_HIT_TAKEN_RANGED_RATING: + ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply); + break; + case ITEM_MOD_HIT_TAKEN_SPELL_RATING: + ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_HASTE_MELEE_RATING: + ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply); + break; + case ITEM_MOD_HASTE_RANGED_RATING: + ApplyRatingMod(CR_HASTE_RANGED, int32(val), apply); + break; + case ITEM_MOD_HASTE_SPELL_RATING: + ApplyRatingMod(CR_HASTE_SPELL, int32(val), apply); + break; case ITEM_MOD_HIT_RATING: ApplyRatingMod(CR_HIT_MELEE, int32(val), apply); ApplyRatingMod(CR_HIT_RANGED, int32(val), apply); @@ -7211,8 +7094,20 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl ApplyRatingMod(CR_CRIT_RANGED, int32(val), apply); ApplyRatingMod(CR_CRIT_SPELL, int32(val), apply); break; + case ITEM_MOD_HIT_TAKEN_RATING: + ApplyRatingMod(CR_HIT_TAKEN_MELEE, int32(val), apply); + ApplyRatingMod(CR_HIT_TAKEN_RANGED, int32(val), apply); + ApplyRatingMod(CR_HIT_TAKEN_SPELL, int32(val), apply); + break; + case ITEM_MOD_CRIT_TAKEN_RATING: + ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); + break; case ITEM_MOD_RESILIENCE_RATING: - ApplyRatingMod(CR_RESILIENCE_DAMAGE_TAKEN, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_MELEE, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, int32(val), apply); + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, int32(val), apply); break; case ITEM_MOD_HASTE_RATING: ApplyRatingMod(CR_HASTE_MELEE, int32(val), apply); @@ -7229,6 +7124,12 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl case ITEM_MOD_RANGED_ATTACK_POWER: HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); break; + case ITEM_MOD_MANA_REGENERATION: + ApplyManaRegenBonus(int32(val), apply); + break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply); + break; case ITEM_MOD_SPELL_POWER: ApplySpellPowerBonus(int32(val), apply); break; @@ -7236,35 +7137,13 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -int32(val), apply); m_spellPenetrationItemMod += apply ? val : -val; break; - case ITEM_MOD_MASTERY_RATING: - ApplyRatingMod(CR_MASTERY, int32(val), apply); + case ITEM_MOD_BLOCK_VALUE: + HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(val), apply); break; - // deprecated item mods - case ITEM_MOD_HEALTH: - case ITEM_MOD_DEFENSE_SKILL_RATING: - case ITEM_MOD_BLOCK_RATING: - case ITEM_MOD_HIT_MELEE_RATING: - case ITEM_MOD_HIT_RANGED_RATING: - case ITEM_MOD_HIT_SPELL_RATING: - case ITEM_MOD_CRIT_MELEE_RATING: - case ITEM_MOD_CRIT_SPELL_RATING: - case ITEM_MOD_HIT_TAKEN_MELEE_RATING: - case ITEM_MOD_HIT_TAKEN_RANGED_RATING: - case ITEM_MOD_HIT_TAKEN_SPELL_RATING: - case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: - case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: - case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: - case ITEM_MOD_HASTE_MELEE_RATING: - case ITEM_MOD_HASTE_RANGED_RATING: - case ITEM_MOD_HASTE_SPELL_RATING: - case ITEM_MOD_HIT_TAKEN_RATING: - case ITEM_MOD_CRIT_TAKEN_RATING: + // deprecated item mods case ITEM_MOD_FERAL_ATTACK_POWER: case ITEM_MOD_SPELL_HEALING_DONE: case ITEM_MOD_SPELL_DAMAGE_DONE: - case ITEM_MOD_MANA_REGENERATION: - case ITEM_MOD_ARMOR_PENETRATION_RATING: - case ITEM_MOD_BLOCK_VALUE: break; } } @@ -7272,15 +7151,15 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl // Apply Spell Power from ScalingStatValue if set if (ssv) { - if (int32 spellbonus = ssv->getSpellBonus(proto->StatScalingFactor)) + if (int32 spellbonus = ssv->getSpellBonus(proto->ScalingStatValue)) ApplySpellPowerBonus(spellbonus, apply); } // If set ScalingStatValue armor get it or use item armor - uint32 armor = proto->GetArmor(); + uint32 armor = proto->Armor; if (ssv) { - if (uint32 ssvarmor = ssv->getArmorMod(proto->StatScalingFactor)) + if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue)) armor = ssvarmor; } // Add armor bonus from ArmorDamageModifier if > 0 @@ -7303,6 +7182,27 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl } } + if (proto->Block) + HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply); + + if (proto->HolyRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply); + + if (proto->FireRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply); + + if (proto->NatureRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply); + + if (proto->FrostRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply); + + if (proto->ShadowRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply); + + if (proto->ArcaneRes) + HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply); + WeaponAttackType attType = BASE_ATTACK; float damage = 0.0f; @@ -7317,13 +7217,13 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl attType = OFF_ATTACK; } - float minDamage = proto->GetMinDamage(); - float maxDamage = proto->GetMaxDamage(); + float minDamage = proto->Damage[0].DamageMin; + float maxDamage = proto->Damage[0].DamageMax; int32 extraDPS = 0; // If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage if (ssv) { - if ((extraDPS = ssv->getDPSMod(proto->StatScalingFactor))) + if ((extraDPS = ssv->getDPSMod(proto->ScalingStatValue))) { float average = extraDPS * proto->Delay / 1000.0f; minDamage = 0.7f * average; @@ -7346,7 +7246,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl // Apply feral bonus from ScalingStatValue if set if (ssv) { - if (int32 feral_bonus = ssv->getFeralBonus(proto->StatScalingFactor)) + if (int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue)) ApplyFeralAPBonus(feral_bonus, apply); } // Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue) @@ -7392,7 +7292,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()->GetEquippedItemClass() == -1) + if (aura->GetSpellProto()->EquippedItemClass == -1) return; BaseModGroup mod = BASEMOD_END; @@ -7418,7 +7318,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType att return; // generic not weapon specific case processes in aura code - if(aura->GetSpellProto()->GetEquippedItemClass() == -1) + if (aura->GetSpellProto()->EquippedItemClass == -1) return; UnitMods unitMod = UNIT_MOD_END; @@ -7649,7 +7549,7 @@ void Player::_HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEn break; } } - if (dPoison && dPoison->GetStackAmount() == spellInfo->GetStackAmount()) + if (dPoison && dPoison->GetStackAmount() == spellInfo->StackAmount) { Item* otherWeapon = GetWeaponForAttack(attType == BASE_ATTACK ? OFF_ATTACK : BASE_ATTACK); if (!otherWeapon) @@ -7669,9 +7569,9 @@ void Player::_HandleDeadlyPoison(Unit* Target, WeaponAttackType attType, SpellEn if (pSecondEnchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) continue; - if (SpellEntry const* combatEntry = sSpellStore.LookupEntry(pSecondEnchant->spellid[s])) - if (combatEntry->GetDispel() == DISPEL_POISON) - CastSpell(Target, combatEntry, true, otherWeapon); + SpellEntry const* combatEntry = sSpellStore.LookupEntry(pSecondEnchant->spellid[s]); + if (combatEntry && combatEntry->Dispel == DISPEL_POISON) + CastSpell(Target, combatEntry, true, otherWeapon); } } } @@ -7712,7 +7612,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) if (m_extraAttacks && IsSpellHaveEffect(spellInfo, SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return; - float chance = (float)spellInfo->GetProcChance(); + float chance = (float)spellInfo->procChance; if (spellData.SpellPPMRate) { @@ -7765,7 +7665,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) else { // Deadly Poison, unique effect needs to be handled before casting triggered spell - if (spellInfo->IsFitToFamily(SPELLFAMILY_ROGUE, UI64LIT(0x0000000000010000))) + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & UI64LIT(0x10000)) _HandleDeadlyPoison(Target, attType, spellInfo); CastSpell(Target, spellInfo->Id, true, item); @@ -7980,26 +7880,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 @@ -11241,37 +11141,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. @@ -11476,7 +11376,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->GetStartRecoveryTime(); + m_weaponChangeTimer = spellProto->StartRecoveryTime; WorldPacket data(SMSG_SPELL_COOLDOWN, 8 + 1 + 4); data << GetObjectGuid(); @@ -12930,10 +12830,10 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool DEBUG_LOG("Adding %u to stat nb %u", enchant_amount, enchant_spell_id); switch (enchant_spell_id) { - /*case ITEM_MOD_MANA: + case ITEM_MOD_MANA: DEBUG_LOG("+ %u MANA", enchant_amount); HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply); - break;*/ + break; case ITEM_MOD_HEALTH: DEBUG_LOG("+ %u HEALTH", enchant_amount); HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply); @@ -12963,6 +12863,10 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply); ApplyStatBuffMod(STAT_STAMINA, float(enchant_amount), apply); break; + case ITEM_MOD_DEFENSE_SKILL_RATING: + ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply); + DEBUG_LOG("+ %u DEFENCE", enchant_amount); + break; case ITEM_MOD_DODGE_RATING: ApplyRatingMod(CR_DODGE, enchant_amount, apply); DEBUG_LOG("+ %u DODGE", enchant_amount); @@ -12971,10 +12875,63 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool ApplyRatingMod(CR_PARRY, enchant_amount, apply); DEBUG_LOG("+ %u PARRY", enchant_amount); break; + case ITEM_MOD_BLOCK_RATING: + ApplyRatingMod(CR_BLOCK, enchant_amount, apply); + DEBUG_LOG("+ %u SHIELD_BLOCK", enchant_amount); + break; + case ITEM_MOD_HIT_MELEE_RATING: + ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); + DEBUG_LOG("+ %u MELEE_HIT", enchant_amount); + break; + case ITEM_MOD_HIT_RANGED_RATING: + ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); + DEBUG_LOG("+ %u RANGED_HIT", enchant_amount); + break; + case ITEM_MOD_HIT_SPELL_RATING: + ApplyRatingMod(CR_HIT_SPELL, enchant_amount, apply); + DEBUG_LOG("+ %u SPELL_HIT", enchant_amount); + break; + case ITEM_MOD_CRIT_MELEE_RATING: + ApplyRatingMod(CR_CRIT_MELEE, enchant_amount, apply); + DEBUG_LOG("+ %u MELEE_CRIT", enchant_amount); + break; case ITEM_MOD_CRIT_RANGED_RATING: ApplyRatingMod(CR_CRIT_RANGED, enchant_amount, apply); DEBUG_LOG("+ %u RANGED_CRIT", enchant_amount); break; + case ITEM_MOD_CRIT_SPELL_RATING: + ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); + DEBUG_LOG("+ %u SPELL_CRIT", enchant_amount); + break; +// Values from ITEM_STAT_MELEE_HA_RATING to ITEM_MOD_HASTE_RANGED_RATING are never used +// in Enchantments +// case ITEM_MOD_HIT_TAKEN_MELEE_RATING: +// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_HIT_TAKEN_RANGED_RATING: +// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); +// break; +// case ITEM_MOD_HIT_TAKEN_SPELL_RATING: +// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: +// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: +// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: +// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_HASTE_MELEE_RATING: +// ApplyRatingMod(CR_HASTE_MELEE, enchant_amount, apply); +// break; +// case ITEM_MOD_HASTE_RANGED_RATING: +// ApplyRatingMod(CR_HASTE_RANGED, enchant_amount, apply); +// break; + case ITEM_MOD_HASTE_SPELL_RATING: + ApplyRatingMod(CR_HASTE_SPELL, enchant_amount, apply); + break; case ITEM_MOD_HIT_RATING: ApplyRatingMod(CR_HIT_MELEE, enchant_amount, apply); ApplyRatingMod(CR_HIT_RANGED, enchant_amount, apply); @@ -12987,8 +12944,21 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool ApplyRatingMod(CR_CRIT_SPELL, enchant_amount, apply); DEBUG_LOG("+ %u CRITICAL", enchant_amount); break; +// Values ITEM_MOD_HIT_TAKEN_RATING and ITEM_MOD_CRIT_TAKEN_RATING are never used in Enchantment +// case ITEM_MOD_HIT_TAKEN_RATING: +// ApplyRatingMod(CR_HIT_TAKEN_MELEE, enchant_amount, apply); +// ApplyRatingMod(CR_HIT_TAKEN_RANGED, enchant_amount, apply); +// ApplyRatingMod(CR_HIT_TAKEN_SPELL, enchant_amount, apply); +// break; +// case ITEM_MOD_CRIT_TAKEN_RATING: +// ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); +// ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); +// ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); +// break; case ITEM_MOD_RESILIENCE_RATING: - ApplyRatingMod(CR_RESILIENCE_DAMAGE_TAKEN, enchant_amount, apply); + ApplyRatingMod(CR_CRIT_TAKEN_MELEE, enchant_amount, apply); + ApplyRatingMod(CR_CRIT_TAKEN_RANGED, enchant_amount, apply); + ApplyRatingMod(CR_CRIT_TAKEN_SPELL, enchant_amount, apply); DEBUG_LOG("+ %u RESILIENCE", enchant_amount); break; case ITEM_MOD_HASTE_RATING: @@ -13010,44 +12980,24 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); DEBUG_LOG("+ %u RANGED_ATTACK_POWER", enchant_amount); break; + case ITEM_MOD_MANA_REGENERATION: + ApplyManaRegenBonus(enchant_amount, apply); + DEBUG_LOG("+ %u MANA_REGENERATION", enchant_amount); + break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); + DEBUG_LOG("+ %u ARMOR PENETRATION", enchant_amount); + break; case ITEM_MOD_SPELL_POWER: ApplySpellPowerBonus(enchant_amount, apply); DEBUG_LOG("+ %u SPELL_POWER", enchant_amount); break; - case ITEM_MOD_SPELL_PENETRATION: - ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -int32(enchant_amount), apply); - m_spellPenetrationItemMod += apply ? enchant_amount : -int32(enchant_amount); - DEBUG_LOG("+ %u SPELL_PENETRATION", -int32(enchant_amount)); - break; - case ITEM_MOD_MASTERY_RATING: - ApplyRatingMod(CR_MASTERY, enchant_amount, apply); - DEBUG_LOG("+ %u MASTERY_RATING", enchant_amount); - break; - // deprecated - case ITEM_MOD_DEFENSE_SKILL_RATING: - case ITEM_MOD_BLOCK_RATING: - case ITEM_MOD_HIT_MELEE_RATING: - case ITEM_MOD_HIT_RANGED_RATING: - case ITEM_MOD_HIT_SPELL_RATING: - case ITEM_MOD_CRIT_MELEE_RATING: - case ITEM_MOD_CRIT_SPELL_RATING: - case ITEM_MOD_HIT_TAKEN_MELEE_RATING: - case ITEM_MOD_HIT_TAKEN_RANGED_RATING: - case ITEM_MOD_HIT_TAKEN_SPELL_RATING: - case ITEM_MOD_CRIT_TAKEN_MELEE_RATING: - case ITEM_MOD_CRIT_TAKEN_RANGED_RATING: - case ITEM_MOD_CRIT_TAKEN_SPELL_RATING: - case ITEM_MOD_HASTE_MELEE_RATING: - case ITEM_MOD_HASTE_RANGED_RATING: - case ITEM_MOD_HASTE_SPELL_RATING: - case ITEM_MOD_HIT_TAKEN_RATING: - case ITEM_MOD_CRIT_TAKEN_RATING: - case ITEM_MOD_FERAL_ATTACK_POWER: - case ITEM_MOD_SPELL_HEALING_DONE: - case ITEM_MOD_SPELL_DAMAGE_DONE: - case ITEM_MOD_MANA_REGENERATION: - case ITEM_MOD_ARMOR_PENETRATION_RATING: case ITEM_MOD_BLOCK_VALUE: + HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply); + break; + case ITEM_MOD_FERAL_ATTACK_POWER: + case ITEM_MOD_SPELL_HEALING_DONE: // deprecated + case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated default: break; } @@ -15383,16 +15333,6 @@ 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) @@ -15639,9 +15579,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 - //"health, power1, power2, power3, power4, power5, specCount, activeSpec, exploredZones, equipmentCache, knownTitles, actionBars, slot 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 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); if (!result) { @@ -15690,8 +15630,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8()); SetUInt32Value(PLAYER_XP, fields[7].GetUInt32()); - _LoadIntoDataField(fields[58].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); - _LoadIntoDataField(fields[60].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2); + _LoadIntoDataField(fields[60].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); + _LoadIntoDataField(fields[63].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE * 2); InitDisplayIds(); // model, scale and model data @@ -15716,12 +15656,12 @@ 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()); + SetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES, fields[47].GetUInt64()); + + SetUInt32Value(PLAYER_AMMO_ID, fields[62].GetUInt32()); // Action bars state - SetByteValue(PLAYER_FIELD_BYTES, 2, fields[61].GetUInt8()); - - m_slot = fields[62].GetUInt8(); + SetByteValue(PLAYER_FIELD_BYTES, 2, fields[64].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) @@ -15784,8 +15724,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()); @@ -16056,8 +15996,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder) _LoadMailedItems(holder->GetResult(PLAYER_LOGIN_QUERY_LOADMAILEDITEMS)); UpdateNextMailTimeAndUnreads(); - m_specsCount = fields[56].GetUInt8(); - m_activeSpec = fields[57].GetUInt8(); + m_specsCount = fields[58].GetUInt8(); + m_activeSpec = fields[59].GetUInt8(); _LoadGlyphs(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGLYPHS)); @@ -16167,12 +16107,10 @@ 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); - - static_assert(MAX_STORED_POWERS == 5, "Query not updated."); - for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) + for (uint32 i = 0; i < MAX_POWERS; ++i) { uint32 savedpower = fields[51 + i].GetUInt32(); - SetPowerByIndex(i, std::min(savedpower, GetMaxPowerByIndex(i))); + SetPower(Powers(i), savedpower > GetMaxPower(Powers(i)) ? GetMaxPower(Powers(i)) : savedpower); } DEBUG_FILTER_LOG(LOG_FILTER_PLAYER_STATS, "The value of player %s after load item and aura is: ", m_name.c_str()); @@ -16354,19 +16292,13 @@ void Player::_LoadAuras(QueryResult* result, uint32 timediff) } // prevent wrong values of remaincharges - if (uint32 procCharges = spellproto->GetProcCharges()) - { - if (remaincharges <= 0 || remaincharges > procCharges) - remaincharges = procCharges; - } - else + if (spellproto->procCharges == 0) remaincharges = 0; - uint32 defstackamount = spellproto->GetStackAmount(); - if (!defstackamount) + if (!spellproto->StackAmount) stackcount = 1; - else if (defstackamount < stackcount) - stackcount = defstackamount; + else if (spellproto->StackAmount < stackcount) + stackcount = spellproto->StackAmount; else if (!stackcount) stackcount = 1; @@ -17489,21 +17421,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, specCount, activeSpec, exploredZones, equipmentCache, knownTitles, actionBars, slot) " - "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, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, " + "?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); uberInsert.addUInt32(GetGUIDLow()); uberInsert.addUInt32(GetSession()->GetAccountId()); @@ -17582,9 +17514,9 @@ void Player::SaveToDB() uberInsert.addUInt32(GetHonorPoints()); - uberInsert.addUInt32(0); // FIXME 4x GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION) + uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_TODAY_CONTRIBUTION)); - uberInsert.addUInt32(0); // FIXME 4x GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION) + uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION)); uberInsert.addUInt32(GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS)); @@ -17594,7 +17526,7 @@ void Player::SaveToDB() uberInsert.addUInt32(GetUInt32Value(PLAYER_CHOSEN_TITLE)); - uberInsert.addUInt64(0); // FIXME 4x GetUInt64Value(PLAYER_FIELD_KNOWN_CURRENCIES) + uberInsert.addUInt64(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)); @@ -17603,9 +17535,8 @@ void Player::SaveToDB() uberInsert.addUInt32(GetHealth()); - static_assert(MAX_STORED_POWERS == 5, "Query not updated."); - for (uint32 i = 0; i < MAX_STORED_POWERS; ++i) - uberInsert.addUInt32(GetPowerByIndex(i)); + for (uint32 i = 0; i < MAX_POWERS; ++i) + uberInsert.addUInt32(GetPower(Powers(i))); uberInsert.addUInt32(uint32(m_specsCount)); uberInsert.addUInt32(uint32(m_activeSpec)); @@ -17622,7 +17553,9 @@ void Player::SaveToDB() } uberInsert.addString(ss); - for(uint32 i = 0; i < KNOWN_TITLES_SIZE*2; ++i ) //string + uberInsert.addUInt32(GetUInt32Value(PLAYER_AMMO_ID)); + + for (uint32 i = 0; i < KNOWN_TITLES_SIZE * 2; ++i) // string { ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << " "; } @@ -17630,8 +17563,6 @@ void Player::SaveToDB() uberInsert.addUInt32(uint32(GetByteValue(PLAYER_FIELD_BYTES, 2))); - uberInsert.addUInt8(m_slot); - uberInsert.Execute(); if (m_mailsUpdated) // save mails only when needed @@ -18166,11 +18097,9 @@ void Player::_SaveSkills() continue; } - 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); + uint32 valueData = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)); + uint16 value = SKILL_VALUE(valueData); + uint16 max = SKILL_MAX(valueData); switch (itr->second.uState) { @@ -18274,16 +18203,15 @@ 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" - "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, 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.addUInt32(GetGUIDLow()); stmt.addUInt32(GetMaxHealth()); - 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_POWERS; ++i) + stmt.addUInt32(GetMaxPower(Powers(i))); for (int i = 0; i < MAX_STATS; ++i) stmt.addFloat(GetStat(Stats(i))); // armor + school resistances @@ -18594,16 +18522,13 @@ void Player::RemovePet(PetSaveMode mode) pet->Unsummon(mode, this); } -void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language, const char* addonPrefix) const +void Player::BuildPlayerChat(WorldPacket* data, uint8 msgtype, const std::string& text, uint32 language) const { *data << uint8(msgtype); *data << uint32(language); - *data << GetObjectGuid(); - *data << uint32(0); // constant unknown time 4.3.4 - if (addonPrefix) - *data << addonPrefix; - else - *data << GetObjectGuid(); + *data << ObjectGuid(GetObjectGuid()); + *data << uint32(0); // 2.1.0 + *data << ObjectGuid(GetObjectGuid()); *data << uint32(text.length() + 1); *data << text; *data << uint8(GetChatTag()); @@ -18632,15 +18557,22 @@ 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); - data.Initialize(SMSG_MESSAGECHAT, 200); - rPlayer->BuildPlayerChat(&data, CHAT_MSG_WHISPER_INFORM, text, language); - 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); + } if (!isAcceptWhispers()) { @@ -18655,17 +18587,6 @@ 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(); @@ -18866,11 +18787,9 @@ void Player::AddSpellMod(Aura* aura, bool apply) val += (*itr)->GetModifier()->m_amount; } val += apply ? mod->m_amount : -(mod->m_amount); - WorldPacket data(Opcode, 4 + 4 + 1 + 1 + 4); - data << uint32(1); - data << uint32(1); - data << uint8(mod->m_miscvalue); + WorldPacket data(Opcode, (1 + 1 + 4)); data << uint8(eff); + data << uint8(mod->m_miscvalue); data << int32(val); SendDirectMessage(&data); } @@ -19312,7 +19231,7 @@ void Player::ContinueTaxiFlight() void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) { - // last check 4.3.4 + // last check 2.0.10 WorldPacket data(SMSG_SPELL_COOLDOWN, 8 + 1 + m_spells.size() * 8); data << GetObjectGuid(); data << uint8(0x0); // flags (0x1, 0x2) @@ -19519,7 +19438,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); @@ -19723,6 +19642,7 @@ void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 it // some special item spells without correct cooldown in SpellInfo // cooldown information stored in item prototype + // This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client. if (itemId) { @@ -19744,9 +19664,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->GetCategory(); - rec = spellInfo->GetRecoveryTime(); - catrec = spellInfo->GetCategoryRecoveryTime(); + cat = spellInfo->Category; + rec = spellInfo->RecoveryTime; + catrec = spellInfo->CategoryRecoveryTime; } time_t curTime = time(NULL); @@ -20476,13 +20396,14 @@ void Player::SendInitialPacketsAfterAddToMap() } if (HasAuraType(SPELL_AURA_MOD_STUN)) - SetMovement(MOVE_ROOT); + SetRoot(true); // manual send package (have code in ApplyModifier(true,true); that don't must be re-applied. if (HasAuraType(SPELL_AURA_MOD_ROOT)) { - WorldPacket data2; - BuildForceMoveRootPacket(&data2, true, 2); + WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10); + data2 << GetPackGUID(); + data2 << (uint32)2; SendMessageToSet(&data2, true); } @@ -20509,8 +20430,14 @@ 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 - data << uint8(arg); - + switch (reason) + { + case TRANSFER_ABORT_INSUF_EXPAN_LVL: + case TRANSFER_ABORT_DIFFICULTY: + case TRANSFER_ABORT_UNIQUE_MESSAGE: + data << uint8(arg); + break; + } GetSession()->SendPacket(&data); } @@ -20560,7 +20487,7 @@ void Player::ApplyEquipCooldown(Item* pItem) AddSpellCooldown(spellData.SpellId, pItem->GetEntry(), time(NULL) + 30); WorldPacket data(SMSG_ITEM_COOLDOWN, 12); - data << pItem->GetObjectGuid(); + data << ObjectGuid(pItem->GetObjectGuid()); data << uint32(spellData.SpellId); GetSession()->SendPacket(&data); } @@ -20614,13 +20541,10 @@ void Player::learnQuestRewardedSpells(Quest const* quest) bool found = false; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { - if(SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(i))) + if (spellInfo->Effect[i] == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellInfo->EffectTriggerSpell[i])) { - if(spellEffect->Effect == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellEffect->EffectTriggerSpell)) - { - found = true; - break; - } + found = true; + break; } } @@ -20629,10 +20553,8 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // prevent learn non first rank unknown profession and second specialization for same profession) - SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(EFFECT_INDEX_0); - uint32 learned_0 = spellEffect ? spellEffect->EffectTriggerSpell : 0; - - if( sSpellMgr.GetSpellRank(learned_0) > 1 && !HasSpell(learned_0) ) + uint32 learned_0 = spellInfo->EffectTriggerSpell[EFFECT_INDEX_0]; + if (sSpellMgr.GetSpellRank(learned_0) > 1 && !HasSpell(learned_0)) { // not have first rank learned (unlearned prof?) uint32 first_spell = sSpellMgr.GetFirstSpellInChain(learned_0); @@ -20644,9 +20566,7 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // specialization - 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) + if (learnedInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effect[EFFECT_INDEX_1] == 0) { // search other specialization for same prof for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) @@ -20659,9 +20579,7 @@ void Player::learnQuestRewardedSpells(Quest const* quest) return; // compare only specializations - 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)) + if (itrInfo->Effect[EFFECT_INDEX_0] != SPELL_EFFECT_TRADE_SKILL || itrInfo->Effect[EFFECT_INDEX_1] != 0) continue; // compare same chain spells @@ -20944,7 +20862,7 @@ void Player::UpdateForQuestWorldObjects() if (m_clientGUIDs.empty()) return; - UpdateData udata(GetMapId()); + UpdateData udata; WorldPacket packet; for (GuidSet::const_iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr) { @@ -21063,13 +20981,12 @@ void Player::AutoUnequipOffhandIfNeed() bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem) { - int32 itemClass = spellInfo->GetEquippedItemClass(); - if(itemClass < 0) + if (spellInfo->EquippedItemClass < 0) return true; // scan other equipped items for same requirements (mostly 2 daggers/etc) // for optimize check 2 used cases only - switch(itemClass) + switch (spellInfo->EquippedItemClass) { case ITEM_CLASS_WEAPON: { @@ -21100,7 +21017,7 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons break; } default: - sLog.outError("HasItemFitToSpellReqirements: Not handled spell requirement for item class %u", itemClass); + sLog.outError("HasItemFitToSpellReqirements: Not handled spell requirement for item class %u", spellInfo->EquippedItemClass); break; } @@ -22036,7 +21953,6 @@ 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 @@ -22074,28 +21990,9 @@ void Player::_LoadSkills(QueryResult* result) continue; } - 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); + 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); mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(count, SKILL_UNCHANGED))); @@ -22115,15 +22012,9 @@ void Player::_LoadSkills(QueryResult* result) for (; count < PLAYER_MAX_SKILLS; ++count) { - 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); + SetUInt32Value(PLAYER_SKILL_INDEX(count), 0); + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count), 0); + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count), 0); } // special settings @@ -22350,7 +22241,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)) { @@ -22366,7 +22257,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) if (!hasEnoughRank) return; } - }*/ + } // Find out how many points we have in this field uint32 spentPoints = 0; @@ -22464,7 +22355,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)) { @@ -22478,7 +22369,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; @@ -22533,18 +22424,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 == CMSG_MOVE_FALL_LAND) + if (m_lastFallTime >= minfo.GetFallTime() || m_lastFallZ <= minfo.GetPos()->z || opcode == MSG_MOVE_FALL_LAND) SetFallInformation(minfo.GetFallTime(), minfo.GetPos()->z); } @@ -23134,20 +23025,23 @@ void Player::RemoveAtLoginFlag(AtLoginFlags f, bool in_db_also /*= false*/) void Player::SendClearCooldown(uint32 spell_id, Unit* target) { - ObjectGuid guid = target->GetObjectGuid(); - - WorldPacket data(SMSG_CLEAR_COOLDOWNS, 1 + 8 + 4); - data.WriteGuidMask<1, 3, 6>(guid); - data.WriteBits(1, 24); // cooldown count - data.WriteGuidMask<7, 5, 2, 4, 0>(guid); - - data.WriteGuidBytes<7, 2, 4, 5, 1, 3>(guid); + WorldPacket data(SMSG_CLEAR_COOLDOWN, 4 + 8); data << uint32(spell_id); - data.WriteGuidBytes<0, 6>(guid); - + data << target->GetObjectGuid(); 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); @@ -23181,25 +23075,20 @@ void Player::SendDuelCountdown(uint32 counter) bool Player::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index) const { - SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(index); - if(spellEffect) + switch (spellInfo->Effect[index]) { - switch(spellEffect->Effect) - { - case SPELL_EFFECT_ATTACK_ME: - return true; - default: - break; - } - switch(spellEffect->EffectApplyAuraName) - { - case SPELL_AURA_MOD_TAUNT: - return true; - default: - break; - } + case SPELL_EFFECT_ATTACK_ME: + return true; + default: + break; + } + switch (spellInfo->EffectApplyAuraName[index]) + { + 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 91610e5e2..39cb72d9b 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -401,14 +401,6 @@ enum RaidGroupError ERR_RAID_GROUP_REQUIREMENTS_UNMATCH = 4 }; -enum PlayerMovementType -{ - MOVE_ROOT = 1, - MOVE_UNROOT = 2, - MOVE_WATER_WALK = 3, - MOVE_LAND_WALK = 4 -}; - enum DrunkenState { DRUNKEN_SOBER = 0, @@ -1899,7 +1891,8 @@ class MANGOS_DLL_SPEC Player : public Unit StopMirrorTimer(FIRE_TIMER); } - void SetMovement(PlayerMovementType pType); + void SetRoot(bool enable) override; + void SetWaterWalk(bool enable) override; void JoinedChannel(Channel* c); void LeftChannel(Channel* c); diff --git a/src/game/Unit.h b/src/game/Unit.h index 98ffedcb9..9ac2609a4 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1459,8 +1459,12 @@ class MANGOS_DLL_SPEC Unit : public WorldObject // recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens // if used additional args in ... part then floats must explicitly casted to double void SendHeartBeat(); - bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING);} - bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE);} + + bool IsLevitating() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_LEVITATING); } + bool IsWalking() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_WALK_MODE); } + bool IsRooted() const { return m_movementInfo.HasMovementFlag(MOVEFLAG_ROOT); } + virtual void SetRoot(bool enabled) {} + virtual void SetWaterWalk(bool enabled) {} void SetInFront(Unit const* target); void SetFacingTo(float ori);