diff --git a/src/game/Object.h b/src/game/Object.h index e65f14d43..974e6b0b3 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -241,8 +241,6 @@ class MANGOS_DLL_SPEC Object { ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); ASSERT( offset < 4 ); - //return *(((uint16*)&m_uint32Values[ index ])+offset); - //return (((uint8*)m_uint32Values[index])[offset] & flag) != 0; return (((uint8*)&m_uint32Values[index])[offset] & flag) != 0; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b19d90096..fd7ca3b9d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18899,7 +18899,29 @@ void Player::SetTitle(CharTitlesEntry const* title) void Player::ConvertRune(uint8 index, uint8 newType) { SetCurrentRune(index, newType); - // SMSG_CONVERT_RUNE + + WorldPacket data(SMSG_CONVERT_RUNE, 2); + data << uint8(index); + data << uint8(newType); + GetSession()->SendPacket(&data); +} + +void Player::ResyncRunes(uint8 count) +{ + WorldPacket data(SMSG_RESYNC_RUNES, count * 2); + for(uint32 i = 0; i < count; ++i) + { + data << uint8(GetCurrentRune(i)); // rune type + data << uint8(255 - (GetRuneCooldown(i) * 51)); // passed cooldown time (0-255) + } + GetSession()->SendPacket(&data); +} + +void Player::AddRunePower(uint8 index) +{ + WorldPacket data(SMSG_ADD_RUNE_POWER, 4); + data << uint32(1 << index); // mask (0x00-0x3F probably) + GetSession()->SendPacket(&data); } void Player::InitRunes() @@ -18909,11 +18931,14 @@ void Player::InitRunes() m_runes = new Runes; + m_runes->runeState = 0; + for(uint32 i = 0; i < MAX_RUNES; ++i) { SetBaseRune(i, i / 2); // init base types SetCurrentRune(i, i / 2); // init current types SetRuneCooldown(i, 0); // reset cooldowns + m_runes->SetRuneState(i); } for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i) diff --git a/src/game/Player.h b/src/game/Player.h index bd6d63c39..2682149f6 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -230,8 +230,8 @@ struct Areas enum RuneType { RUNE_BLOOD = 0, - RUNE_FROST = 1, - RUNE_UNHOLY = 2, + RUNE_UNHOLY = 1, + RUNE_FROST = 2, RUNE_DEATH = 3, NUM_RUNE_TYPES = 4 }; @@ -246,6 +246,15 @@ struct RuneInfo struct Runes { RuneInfo runes[6]; + uint8 runeState; // mask of available runes + + void SetRuneState(uint8 index, bool set = true) + { + if(set) + runeState |= (1 << index); // usable + else + runeState &= ~(1 << index); // on cooldown + } }; enum FactionFlags @@ -2092,13 +2101,16 @@ class MANGOS_DLL_SPEC Player : public Unit WorldLocation& GetTeleportDest() { return m_teleport_dest; } DeclinedName const* GetDeclinedNames() const { return m_declinedname; } + uint8 GetRunesState() const { return m_runes->runeState; } uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; } uint8 GetCurrentRune(uint8 index) const { return m_runes->runes[index].CurrentRune; } uint8 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; } void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; } void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; } - void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; } + void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); } void ConvertRune(uint8 index, uint8 newType); + void ResyncRunes(uint8 count); + void AddRunePower(uint8 index); void InitRunes(); AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } bool HasTitle(uint32 bitIndex); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 337273e21..509f9d389 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -346,6 +346,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi else m_autoRepeat = false; + m_runesState = 0; m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before. m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before. m_timer = 0; // will set to castime in prepare @@ -2652,6 +2653,9 @@ void Spell::SendSpellStart() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; + if(m_runesState) + castFlags |= CAST_FLAG_UNKNOWN10; + Unit *target; if(!m_targets.getUnitTarget()) target = m_caster; @@ -2672,19 +2676,26 @@ void Spell::SendSpellStart() m_targets.write(&data); - if ( castFlags & CAST_FLAG_UNKNOWN6 ) + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power? data << uint32(0); - if ( castFlags & CAST_FLAG_UNKNOWN7 ) + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns { - uint8 v1 = 0; - uint8 v2 = 0; - data << v1; // v1 - data << v2; // v2 - for(uint8 i = 0; i < 6; ++i) - if((1 << i) & v1) - if(!(1 << i) & v2) - data << uint8(0); + uint8 v1 = 0;//m_runesState; + uint8 v2 = 0;//((Player*)m_caster)->GetRunesState(); + data << uint8(v1); // runes state before + data << uint8(v2); // runes state after + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + uint8 m = (1 << i); + if(m & v1) // usable before... + { + if(!(m & v2)) // ...but on cooldown now... + { + data << uint8(0); // some unknown byte (time?) + } + } + } } if ( castFlags & CAST_FLAG_AMMO ) @@ -2709,7 +2720,14 @@ void Spell::SendSpellGo() uint32 castFlags = CAST_FLAG_UNKNOWN3; if(IsRangedSpell()) - castFlags |= CAST_FLAG_AMMO; + castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual + + if(m_runesState) + { + castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START + castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible + castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns + } WorldPacket data(SMSG_SPELL_GO, 50); // guess size if(m_CastItem) @@ -2727,19 +2745,26 @@ void Spell::SendSpellGo() m_targets.write(&data); - if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power? data << uint32(0); - if ( castFlags & CAST_FLAG_UNKNOWN7 ) + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns? { - uint8 v1 = 0; - uint8 v2 = 0; - data << v1; // v1 - data << v2; // v2 - for(uint8 i = 0; i < 6; ++i) - if((1 << i) & v1) - if(!(1 << i) & v2) - data << uint8(0); + uint8 v1 = m_runesState; + uint8 v2 = ((Player*)m_caster)->GetRunesState(); + data << uint8(v1); // runes state before + data << uint8(v2); // runes state after + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + uint8 m = (1 << i); + if(m & v1) // usable before... + { + if(!(m & v2)) // ...but on cooldown now... + { + data << uint8(0); // some unknown byte (time?) + } + } + } } if ( castFlags & CAST_FLAG_UNKNOWN4 ) // unknown wotlk @@ -3204,6 +3229,8 @@ void Spell::TakeRunePower() if(!src || (src->NoRuneCost() && src->NoRunicPowerGain())) return; + m_runesState = plr->GetRunesState(); // store previous state + int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death for(uint32 i = 0; i < RUNE_DEATH; ++i) @@ -3223,7 +3250,7 @@ void Spell::TakeRunePower() } } - runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_FROST] + runeCost[RUNE_UNHOLY]; + runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST]; if(runeCost[RUNE_DEATH] > 0) { diff --git a/src/game/Spell.h b/src/game/Spell.h index d14293cde..ac71da5b4 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -67,16 +67,29 @@ enum SpellCastTargetFlags enum SpellCastFlags { + CAST_FLAG_NONE = 0x00000000, + CAST_FLAG_UNKNOWN0 = 0x00000001, // may be pending spell cast CAST_FLAG_UNKNOWN1 = 0x00000002, + CAST_FLAG_UNKNOWN11 = 0x00000004, + CAST_FLAG_UNKNOWN12 = 0x00000008, CAST_FLAG_UNKNOWN2 = 0x00000010, - CAST_FLAG_AMMO = 0x00000020, + CAST_FLAG_AMMO = 0x00000020, // Projectiles visual CAST_FLAG_UNKNOWN8 = 0x00000040, CAST_FLAG_UNKNOWN9 = 0x00000080, CAST_FLAG_UNKNOWN3 = 0x00000100, - CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk + CAST_FLAG_UNKNOWN13 = 0x00000200, + CAST_FLAG_UNKNOWN14 = 0x00000400, + CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk, trigger rune cooldown + CAST_FLAG_UNKNOWN15 = 0x00001000, + CAST_FLAG_UNKNOWN16 = 0x00002000, + CAST_FLAG_UNKNOWN17 = 0x00004000, + CAST_FLAG_UNKNOWN18 = 0x00008000, + CAST_FLAG_UNKNOWN19 = 0x00010000, CAST_FLAG_UNKNOWN4 = 0x00020000, // wotlk + CAST_FLAG_UNKNOWN10 = 0x00040000, CAST_FLAG_UNKNOWN5 = 0x00080000, // wotlk - CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk + CAST_FLAG_UNKNOWN20 = 0x00100000, + CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list }; enum SpellNotifyPushType @@ -436,6 +449,7 @@ class Spell int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare bool m_canReflect; // can reflect this spell? bool m_autoRepeat; + uint8 m_runesState; uint8 m_delayAtDamageCount; int32 GetNextDelayAtDamageMsTime() { return m_delayAtDamageCount < 5 ? 1000 - (m_delayAtDamageCount++)* 200 : 200; }