void SpellHit(Unit* pAttacker, const SpellEntry* Spell) { if (!m_creature->IsNonMeleeSpellCasted(false)) return; for (uint8 i = 0; i < 3; ++i) { SpellEffectEntry const* pSpellEffect = Spell->GetSpellEffect(SpellEffectIndex(i)); if (!pSpellEffect) continue; //We only care about inturrupt effects and only if they are durring a spell currently being casted if (pSpellEffect->Effect != SPELL_EFFECT_INTERRUPT_CAST) return; } //Inturrupt effect m_creature->InterruptNonMeleeSpells(false); //Normally we would set the cooldown equal to the spell duration //but we do not have access to the DurationStore switch (m_uiCurrentNormalSpell) { case SPELL_ARCMISSLE: m_uiArcaneCooldown = 5000; break; case SPELL_FIREBALL: m_uiFireCooldown = 5000; break; case SPELL_FROSTBOLT: m_uiFrostCooldown = 5000; break; } }
bool EquippedOk(Player* pPlayer, uint32 spellId) { SpellEntry const* spell = GetSpellStore()->LookupEntry(spellId); if (!spell) return false; for (int i = 0; i < 3; ++i) { SpellEffectEntry const* pSpellEffect = spell->GetSpellEffect(SpellEffectIndex(i)); if (!pSpellEffect) continue; uint32 reqSpell = pSpellEffect->EffectTriggerSpell;; if (!reqSpell) continue; Item* pItem; for (int j = EQUIPMENT_SLOT_START; j < EQUIPMENT_SLOT_END; ++j) { pItem = pPlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, j); if (pItem) if (pItem->GetProto()->RequiredSpell == reqSpell) { // pPlayer has item equipped that require specialty. Not allow to unlearn, player has to unequip first debug_log("SD2: player attempt to unlearn spell %u, but item %u is equipped.", reqSpell, pItem->GetProto()->ItemId); return false; } } } return true; }
void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) { uint32 spellId; recvPacket >> spellId; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) return; if (spellInfo->HasAttribute(SPELL_ATTR_CANT_CANCEL)) return; if (IsPassiveSpell(spellInfo)) return; if (!IsPositiveSpell(spellId)) { // ignore for remote control state if (!_player->IsSelfMover()) { // except own aura spells bool allow = false; for (int k = 0; k < MAX_EFFECT_INDEX; ++k) { SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(k)); if (spellEffect && (spellEffect->EffectApplyAuraName == SPELL_AURA_MOD_POSSESS || spellEffect->EffectApplyAuraName == SPELL_AURA_MOD_POSSESS_PET)) { allow = true; break; } } // this also include case when aura not found if (!allow) return; } else return; } // channeled spell case (it currently casted then) if (IsChanneledSpell(spellInfo)) { if (Spell* curSpell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) if (curSpell->m_spellInfo->Id == spellId) _player->InterruptSpell(CURRENT_CHANNELED_SPELL); return; } SpellAuraHolder* holder = _player->GetSpellAuraHolder(spellId); // not own area auras can't be cancelled (note: maybe need to check for aura on holder and not general on spell) if (holder && holder->GetCasterGuid() != _player->GetObjectGuid() && HasAreaAuraEffect(holder->GetSpellProto())) return; // non channeled case _player->RemoveAurasDueToSpellByCancel(spellId); }
uint8 playersInsideCircles() { uint32 tmpAuras[5] = { SPELL_VIMGOL_POP_TEST_A, SPELL_VIMGOL_POP_TEST_B, SPELL_VIMGOL_POP_TEST_C, SPELL_VIMGOL_POP_TEST_D, SPELL_VIMGOL_POP_TEST_E }; uint8 tmpCounter = 0; if (m_uiBunnyGuids.size() < 5 && m_pMap) { m_uiBunnyGuids.clear(); m_pMap->GetCreatureGuidVectorFromStorage(NPC_VIMGOL_VISUAL_BUNNY, m_uiBunnyGuids); } for (int i = 0; i < 5; i++) m_uiActiveCircles[i] = false; std::list<Player*> playerList; GetPlayerListWithEntryInWorld(playerList, m_creature, 30); for (auto itr = playerList.begin(); itr != playerList.end(); ++itr) { if (!(*itr)->HasAura(SPELL_VIMGOL_POP_TEST_A) && !(*itr)->HasAura(SPELL_VIMGOL_POP_TEST_B) && !(*itr)->HasAura(SPELL_VIMGOL_POP_TEST_C) && !(*itr)->HasAura(SPELL_VIMGOL_POP_TEST_D) && !(*itr)->HasAura(SPELL_VIMGOL_POP_TEST_E)) continue; for (auto it = m_uiBunnyGuids.begin(); it != m_uiBunnyGuids.end(); ++it) { for (int i = 0; i < 5; ++i) { if (!(*itr)->GetAura(tmpAuras[i], SpellEffectIndex(0))) continue; if ((*it) != (*itr)->GetAura(tmpAuras[i], SpellEffectIndex(0))->GetCasterGuid()) continue; m_uiActiveCircles[std::distance(m_uiBunnyGuids.begin(), it)] = true; } } } for (int i = 0; i < 5; i++) if (m_uiActiveCircles[i]) ++tmpCounter; return tmpCounter; }
void Player::UpdateMasteryAuras() { if (!HasAuraType(SPELL_AURA_MASTERY)) { SetFloatValue(PLAYER_MASTERY, 0.0f); return; } float masteryValue = GetTotalAuraModifier(SPELL_AURA_MASTERY) + GetRatingBonusValue(CR_MASTERY); SetFloatValue(PLAYER_MASTERY, masteryValue); std::vector<uint32> const* masterySpells = GetTalentTreeMasterySpells(m_talentsPrimaryTree[m_activeSpec]); if (!masterySpells) return; for (uint32 i = 0; i < masterySpells->size(); ++i) { SpellAuraHolder* holder = GetSpellAuraHolder(masterySpells->at(i)); if (!holder) continue; SpellEntry const* spellEntry = holder->GetSpellProto(); // calculate mastery scaling coef int32 masteryCoef = GetMasteryCoefficient(spellEntry); if (!masteryCoef) continue; // update aura modifiers for (uint32 j = 0; j < MAX_EFFECT_INDEX; ++j) { Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(j)); if (!aura) continue; if (spellEntry->CalculateSimpleValue(SpellEffectIndex(j))) continue; aura->ApplyModifier(false, false); aura->GetModifier()->m_amount = int32(masteryValue * masteryCoef / 100.0f); aura->ApplyModifier(true, false); } } }
bool BSWScriptedAI::_doAura(uint32 SpellID, Unit* pTarget) { if (!pTarget) pTarget = m_creature; bool result = true; for(int i = 0; i < MAX_EFFECT_INDEX; ++i) result = result && _doAura(SpellID, pTarget, SpellEffectIndex(i), 0, !i); return result; };
bool BSWScriptedAI::_doAura(uint8 m_uiSpellIdx, Unit* pTarget, SpellEffectIndex index) { SpellTable* pSpell = &m_BossSpell[m_uiSpellIdx]; if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) { error_log("BSW: FAILED adding aura of spell number %u - no target or target not in map or target is dead",pSpell->m_uiSpellEntry[currentDifficulty]); return false; } if (_hasAura(m_uiSpellIdx,pTarget)) debug_log("BSW: adding aura stack from spell %u index %u",pSpell->m_uiSpellEntry[currentDifficulty], index); else debug_log("BSW: adding new aura from spell %u index %u",pSpell->m_uiSpellEntry[currentDifficulty], index); SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty]); if (spell && spell->Effect[index] < TOTAL_SPELL_EFFECTS) { if (IsSpellAppliesAura(spell, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) || IsSpellHaveEffect(spell, SPELL_EFFECT_PERSISTENT_AREA_AURA)) { SpellAuraHolder *holder = CreateSpellAuraHolder(spell, pTarget, pTarget); int32 basepoint = pSpell->varData ? pSpell->varData - 1 : spell->EffectBasePoints[index] + 1; if ( IsAreaAuraEffect(spell->Effect[index]) || spell->Effect[index] == SPELL_EFFECT_APPLY_AURA || spell->Effect[index] == SPELL_EFFECT_PERSISTENT_AREA_AURA ) { Aura *aura = CreateAura(spell, SpellEffectIndex(index), &basepoint, holder, pTarget); holder->AddAura(aura, SpellEffectIndex(index)); return true; } } } error_log("BSW: FAILED adding aura from spell %u index %u",pSpell->m_uiSpellEntry[currentDifficulty], index); return false; };
bool BSWScriptedAI::_doAura(uint8 m_uiSpellIdx, Unit* pTarget) { BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; if (!pTarget) pTarget = m_creature; bool result = true; for(int i = 0; i < MAX_EFFECT_INDEX; ++i) result = result && _doAura(m_uiSpellIdx, pTarget, SpellEffectIndex(i), !i); return result; };
void CastDoom() { SpellEntry *spellInfo = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_DOOM); if (spellInfo) //target without tank if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) { if (pTarget->GetTypeId() == TYPEID_PLAYER) { for(uint8 i=0; i< MAX_EFFECT_INDEX; ++i) { uint8 eff = spellInfo->Effect[SpellEffectIndex(i)]; if (eff >= TOTAL_SPELL_EFFECTS) continue; //uint8 i=1; /*pTarget->AddAura(new AzgalorDoom(spellInfo, SpellEffectIndex(i), NULL, pTarget, pTarget));*/ } } else DoomTimer = 1000; } }
void CastMark() { SpellEntry *spellInfo = (SpellEntry *)GetSpellStore()->LookupEntry(SPELL_MARK); if (spellInfo) { std::list<HostileReference *> t_list = m_creature->getThreatManager().getThreatList(); for(std::list<HostileReference *>::iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { Unit *target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); if (target && target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() == POWER_MANA) { for(uint32 i=0; i < MAX_EFFECT_INDEX; ++i) { uint8 eff = spellInfo->Effect[SpellEffectIndex(i)]; if (eff >= TOTAL_SPELL_EFFECTS) continue; /*target->AddAura(new KazrogalMark(spellInfo, SpellEffectIndex(i), NULL, target, target));*/ } } } } }
void DynamicObject::Delay(int32 delaytime) { m_aliveDuration -= delaytime; for(AffectedSet::iterator iter = m_affected.begin(); iter != m_affected.end(); ) { Unit *target = GetMap()->GetUnit((*iter)); if (target) { SpellAuraHolder *holder = target->GetSpellAuraHolder(m_spellId, GetCasterGuid().GetRawValue()); if (!holder) { ++iter; continue; } bool foundAura = false; for (int32 i = m_effIndex + 1; i < MAX_EFFECT_INDEX; ++i) { SpellEffectEntry const* effect = holder->GetSpellProto()->GetSpellEffect(SpellEffectIndex(i)); if(!effect) continue; if ((effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA || effect->Effect == SPELL_EFFECT_ADD_FARSIGHT) && holder->m_auras[i]) { foundAura = true; break; } } if (foundAura) { ++iter; continue; } target->DelaySpellAuraHolder(m_spellId, delaytime, GetCasterGuid().GetRawValue()); ++iter; } else m_affected.erase(iter++); } }
bool EffectDummyCreature_spell_dummy_npc(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget) { switch (uiSpellId) { case SPELL_ADMINISTER_ANTIDOTE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_HELBOAR) return true; // possible needs check for quest state, to not have any effect when quest really complete pCreatureTarget->UpdateEntry(NPC_DREADTUSK); return true; } return true; } case SPELL_APPLY_SALVE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; if (pCreatureTarget->GetEntry() != NPC_SICKLY_DEER && pCreatureTarget->GetEntry() != NPC_SICKLY_GAZELLE) return true; // Update entry, remove aura, set the kill credit and despawn uint32 uiUpdateEntry = pCreatureTarget->GetEntry() == NPC_SICKLY_DEER ? NPC_CURED_DEER : NPC_CURED_GAZELLE; pCreatureTarget->RemoveAurasDueToSpell(SPELL_SICKLY_AURA); pCreatureTarget->UpdateEntry(uiUpdateEntry); ((Player*)pCaster)->KilledMonsterCredit(uiUpdateEntry); pCreatureTarget->ForcedDespawn(20000); return true; } return true; } case SPELL_DARKMENDER_TINCTURE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; // TODO: find/fix visual for effect, no related spells found doing this pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_CORRUPTED_SCARLET, true); ((Player*)pCaster)->KilledMonsterCredit(NPC_CORPSES_RISE_CREDIT_BUNNY); pCreatureTarget->ForcedDespawn(); return true; } return true; } case SPELL_DISCIPLINING_ROD: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->getStandState() == UNIT_STAND_STATE_STAND) return true; switch (urand(1, 2)) { case 1: { switch (urand(1, 3)) { case 1: DoScriptText(SAY_RAND_ATTACK1, pCreatureTarget); break; case 2: DoScriptText(SAY_RAND_ATTACK2, pCreatureTarget); break; case 3: DoScriptText(SAY_RAND_ATTACK3, pCreatureTarget); break; } pCreatureTarget->SetStandState(UNIT_STAND_STATE_STAND); pCreatureTarget->AI()->AttackStart(pCaster); break; } case 2: { switch (urand(1, 3)) { case 1: DoScriptText(SAY_RAND_WORK1, pCreatureTarget); break; case 2: DoScriptText(SAY_RAND_WORK2, pCreatureTarget); break; case 3: DoScriptText(SAY_RAND_WORK3, pCreatureTarget); break; } pCreatureTarget->SetStandState(UNIT_STAND_STATE_STAND); pCreatureTarget->HandleEmote(EMOTE_STATE_WORK); break; } } return true; } return true; } case SPELL_INOCULATE_OWLKIN: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_OWLKIN) return true; pCreatureTarget->UpdateEntry(NPC_OWLKIN_INOC); ((Player*)pCaster)->KilledMonsterCredit(NPC_OWLKIN_INOC); // set despawn timer, since we want to remove creature after a short time pCreatureTarget->ForcedDespawn(15000); return true; } return true; } case SPELL_LIQUID_FIRE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() == TYPEID_PLAYER) { if (pCreatureTarget->HasAura(SPELL_LIQUID_FIRE_AURA)) return true; if (pCreatureTarget->GetEntry() == NPC_ELK) { pCreatureTarget->CastSpell(pCreatureTarget, SPELL_LIQUID_FIRE_AURA, true); ((Player*)pCaster)->KilledMonsterCredit(NPC_ELK_BUNNY); } else if (pCreatureTarget->GetEntry() == NPC_GRIZZLY) { pCreatureTarget->CastSpell(pCreatureTarget, SPELL_LIQUID_FIRE_AURA, true); ((Player*)pCaster)->KilledMonsterCredit(NPC_GRIZZLY_BUNNY); } } return true; } return true; } case SPELL_MODIFIED_MOJO: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_PROPHET_OF_SSERATUS) return true; // Apparently done before updateEntry, so need to make a way to handle that // "Mmm, more mojo" // "%s drinks the Mojo" // "NOOOOOOOOOOOOooooooo...............!" pCreatureTarget->UpdateEntry(NPC_WEAK_PROPHET_OF_SSERATUS); return true; } return true; } case SPELL_FEL_SIPHON_DUMMY: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_FELBLOOD_INITIATE) return true; pCreatureTarget->UpdateEntry(NPC_EMACIATED_FELBLOOD); return true; } return true; } case SPELL_SACRED_CLEANSING: { if (uiEffIndex == EFFECT_INDEX_1) { if (pCreatureTarget->GetEntry() != NPC_MORBENT) return true; pCreatureTarget->UpdateEntry(NPC_WEAKENED_MORBENT); return true; } return true; } case SPELL_SEEDS_OF_NATURES_WRATH: { if (uiEffIndex == EFFECT_INDEX_0) { uint32 uiNewEntry = 0; switch (pCreatureTarget->GetEntry()) { case NPC_REANIMATED_FROSTWYRM: uiNewEntry = NPC_WEAK_REANIMATED_FROSTWYRM; break; case NPC_TURGID: uiNewEntry = NPC_WEAK_TURGID; break; case NPC_DEATHGAZE: uiNewEntry = NPC_WEAK_DEATHGAZE; break; } if (uiNewEntry) pCreatureTarget->UpdateEntry(uiNewEntry); return true; } return true; } case SPELL_STRENGTH_ANCIENTS: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() == TYPEID_PLAYER) { if (urand(0, 1)) { DoScriptText(EMOTE_AGGRO, pCreatureTarget); pCreatureTarget->setFaction(FACTION_HOSTILE); pCreatureTarget->AI()->AttackStart(pCaster); } else { DoScriptText(EMOTE_CREATE, pCreatureTarget); pCaster->CastSpell(pCaster, SPELL_CREATE_BARK_WALKERS, true); pCreatureTarget->ForcedDespawn(5000); } } return true; } return true; } case SPELL_TAG_MURLOC_PROC: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() == NPC_BLACKSILT_MURLOC) pCreatureTarget->UpdateEntry(NPC_TAGGED_MURLOC); } return true; } case SPELL_THROW_BOULDER: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; if (pCreatureTarget->GetEntry() != NPC_IRON_RUNESHAPER && pCreatureTarget->GetEntry() != NPC_RUNE_REAVER) return true; pCreatureTarget->CastSpell(pCreatureTarget, SPELL_BOULBER_IMPACT, true); pCaster->CastSpell(pCaster, SPELL_BOULDER_TOSS_CREDIT, true); return true; } return true; } case SPELL_ULTRASONIC_SCREWDRIVER: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->IsCorpse()) { uint32 newSpellId = 0; switch (pCreatureTarget->GetEntry()) { case NPC_COLLECT_A_TRON: newSpellId = SPELL_SUMMON_COLLECT_A_TRON; break; case NPC_DEFENDO_TANK: newSpellId = SPELL_SUMMON_DEFENDO_TANK; break; case NPC_SCAVENGE_A8: newSpellId = SPELL_SUMMON_SCAVENGE_A8; break; case NPC_SCAVENGE_B6: newSpellId = SPELL_SUMMON_SCAVENGE_B6; break; case NPC_SENTRY_BOT: newSpellId = SPELL_SUMMON_SENTRY_BOT; break; } if (const SpellEntry* pSpell = GetSpellStore()->LookupEntry(newSpellId)) { pCaster->CastSpell(pCreatureTarget, pSpell->Id, true); if (Pet* pPet = pCaster->FindGuardianWithEntry(pSpell->GetEffectMiscValue(SpellEffectIndex(uiEffIndex)))) pPet->CastSpell(pCaster, SPELL_REPROGRAM_KILL_CREDIT, true); pCreatureTarget->ForcedDespawn(); } } return true; } return true; } case SPELL_ORB_OF_MURLOC_CONTROL: { pCreatureTarget->CastSpell(pCaster, SPELL_GREENGILL_SLAVE_FREED, true); // Freed Greengill Slave pCreatureTarget->UpdateEntry(NPC_FREED_GREENGILL_SLAVE); pCreatureTarget->CastSpell(pCreatureTarget, SPELL_ENRAGE, true); return true; } case SPELL_FUMPING: { if (uiEffIndex == EFFECT_INDEX_2) { switch (urand(0, 2)) { case 0: { pCaster->CastSpell(pCreatureTarget, SPELL_SUMMON_HAISHULUD, true); break; } case 1: { for (int i = 0; i < 2; ++i) { if (Creature* pSandGnome = pCaster->SummonCreature(NPC_SAND_GNOME, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OOC_DESPAWN, 30000)) pSandGnome->AI()->AttackStart(pCaster); } break; } case 2: { for (int i = 0; i < 2; ++i) { if (Creature* pMatureBoneSifter = pCaster->SummonCreature(NPC_MATURE_BONE_SIFTER, pCreatureTarget->GetPositionX(), pCreatureTarget->GetPositionY(), pCreatureTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OOC_DESPAWN, 30000)) pMatureBoneSifter->AI()->AttackStart(pCaster); } break; } } pCreatureTarget->ForcedDespawn(); } return true; } case SPELL_AHUNAES_KNIFE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; ((Player*)pCaster)->KilledMonsterCredit(NPC_SCALPS_KILL_CREDIT_BUNNY); pCreatureTarget->ForcedDespawn(); return true; } return true; } case SPELL_TAILS_UP_GENDER_MASTER: { if (uiEffIndex == EFFECT_INDEX_0) { bool isMale = urand(0, 1); Player* pPlayer = pCreatureTarget->GetLootRecipient(); if (isMale) DoScriptText(SAY_ITS_MALE, pCreatureTarget, pPlayer); else DoScriptText(SAY_ITS_FEMALE, pCreatureTarget, pPlayer); switch (pCreatureTarget->GetEntry()) { case NPC_FROST_LEOPARD: { if (isMale) pCreatureTarget->CastSpell(pCreatureTarget, SPELL_TAILS_UP_AURA, true); else { pPlayer->KilledMonsterCredit(NPC_LEOPARD_KILL_CREDIT, pCreatureTarget->GetObjectGuid()); pCreatureTarget->CastSpell(pPlayer, SPELL_FORCE_LEOPARD_SUMMON, true); pCreatureTarget->ForcedDespawn(); } break; } case NPC_ICEPAW_BEAR: { if (isMale) pCreatureTarget->CastSpell(pCreatureTarget, SPELL_TAILS_UP_AURA, true); else { pPlayer->KilledMonsterCredit(NPC_BEAR_KILL_CREDIT, pCreatureTarget->GetObjectGuid()); pCreatureTarget->CastSpell(pPlayer, SPELL_FORCE_BEAR_SUMMON, true); pCreatureTarget->ForcedDespawn(); } break; } } return true; } return true; } case SPELL_THROW_GORDAWG_BOULDER: { if (uiEffIndex == EFFECT_INDEX_0) { for (int i = 0; i < 3; ++i) { if (irand(i, 2)) // 2-3 summons pCreatureTarget->SummonCreature(NPC_MINION_OF_GUROK, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 5000); } if (pCreatureTarget->getVictim()) { pCaster->DealDamage(pCreatureTarget, pCreatureTarget->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return true; } // If not in combat, no xp or loot pCreatureTarget->SetDeathState(JUST_DIED); pCreatureTarget->SetHealth(0); return true; } return true; } case SPELL_HIT_APPLE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() == TYPEID_PLAYER) ((Player*)pCaster)->KilledMonsterCredit(pCreatureTarget->GetEntry(), pCreatureTarget->GetObjectGuid()); pCreatureTarget->CastSpell(pCreatureTarget, SPELL_APPLE_FALLS_TO_GROUND, false); if (Creature* pLuckyWilhelm = GetClosestCreatureWithEntry(pCreatureTarget, NPC_LUCKY_WILHELM, 2 * INTERACTION_DISTANCE)) DoScriptText(SAY_LUCKY_HIT_APPLE, pLuckyWilhelm); } return true; } case SPELL_MISS_APPLE: { if (uiEffIndex == EFFECT_INDEX_0) { switch (urand(1, 3)) { case 1: DoScriptText(SAY_LUCKY_HIT_1, pCreatureTarget); break; case 2: DoScriptText(SAY_LUCKY_HIT_2, pCreatureTarget); break; case 3: DoScriptText(SAY_LUCKY_HIT_3, pCreatureTarget); break; } if (Creature* pDrostan = GetClosestCreatureWithEntry(pCreatureTarget, NPC_DROSTAN, 4 * INTERACTION_DISTANCE)) DoScriptText(urand(0, 1) ? SAY_DROSTAN_GOT_LUCKY_1 : SAY_DROSTAN_GOT_LUCKY_2, pDrostan); } return true; } case SPELL_MISS_APPLE_HIT_BIRD: { if (uiEffIndex == EFFECT_INDEX_0) { if (Creature* pDrostan = GetClosestCreatureWithEntry(pCreatureTarget, NPC_DROSTAN, 5 * INTERACTION_DISTANCE)) DoScriptText(urand(0, 1) ? SAY_DROSTAN_HIT_BIRD_1 : SAY_DROSTAN_HIT_BIRD_2, pDrostan); pCreatureTarget->DealDamage(pCreatureTarget, pCreatureTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } return true; } case SPELL_LURIELLES_PENDANT: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_CHILL_NYMPH || pCaster->GetTypeId() != TYPEID_PLAYER) return true; switch (urand(0, 2)) { case 0: DoScriptText(SAY_FREE_1, pCreatureTarget); break; case 1: DoScriptText(SAY_FREE_2, pCreatureTarget); break; case 2: DoScriptText(SAY_FREE_3, pCreatureTarget); break; } ((Player*)pCaster)->KilledMonsterCredit(NPC_LURIELLE); pCreatureTarget->SetFactionTemporary(FACTION_FRIENDLY, TEMPFACTION_RESTORE_RESPAWN); pCreatureTarget->DeleteThreatList(); pCreatureTarget->AttackStop(true); pCreatureTarget->GetMotionMaster()->MoveFleeing(pCaster, 7); pCreatureTarget->ForcedDespawn(7 * IN_MILLISECONDS); } return true; } case SPELL_SAMPLING_ENERGY: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER) return true; ((Player*)pCaster)->KilledMonsterCredit(pCreatureTarget->GetEntry()); } return true; } case SPELL_EXPOSE_RAZORTHORN_ROOT: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCreatureTarget->GetEntry() != NPC_RAZORTHORN_RAVAGER) return true; if (GameObject* pMound = GetClosestGameObjectWithEntry(pCreatureTarget, GO_RAZORTHORN_DIRT_MOUND, 20.0f)) { if (pMound->GetRespawnTime() != 0) return true; pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_RAZORTHORN_ROOT, true); pMound->SetLootState(GO_JUST_DEACTIVATED); } } return true; } case SPELL_MELODIOUS_RAPTURE: { if (uiEffIndex == EFFECT_INDEX_0) { if (pCaster->GetTypeId() != TYPEID_PLAYER && pCreatureTarget->GetEntry() != NPC_DEEPRUN_RAT) return true; pCreatureTarget->UpdateEntry(NPC_ENTHRALLED_DEEPRUN_RAT); pCreatureTarget->CastSpell(pCreatureTarget, SPELL_MELODIOUS_RAPTURE_VISUAL, false); pCreatureTarget->GetMotionMaster()->MoveFollow(pCaster, frand(0.5f, 3.0f), frand(M_PI_F * 0.8f, M_PI_F * 1.2f)); ((Player*)pCaster)->KilledMonsterCredit(NPC_ENTHRALLED_DEEPRUN_RAT); } return true; } } return false; }
void UpdateAI(const uint32 diff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (m_uiEvadeCheckCooldown < diff) { if (m_creature->GetDistance2d(3307.02f, -3476.27f) > 125.0f) EnterEvadeMode(); m_uiEvadeCheckCooldown = 2000; } else m_uiEvadeCheckCooldown -= diff; //Berserk_Timer if (Berserk_Timer < diff) { DoCast(m_creature,SPELL_BERSERK); Berserk_Timer = 300000; }else Berserk_Timer -= diff; if (m_bIsRegularMode) { //SumonFirstCryptGuard_Timer if (SummonFirst_Timer < diff) { if (CryptGuard_count < MAX_CRYPT_GUARDS) m_creature->SummonCreature(MOB_CRYPT_GUARD,3330.0f,-3477.0f,288.0f,3.2f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,10000); SummonFirst_Timer = 2000000; }else SummonFirst_Timer -= diff; } //RiseFromCorpse_Timer if (RiseFromCorpse_Timer < diff) { RiseFromCorpse_Timer = 60000 + (rand()%10000); const Map::PlayerList &players = m_creature->GetMap()->GetPlayers(); if (players.isEmpty()) return; for(Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) if (Player* pPlayer = i->getSource()) { if (pPlayer->isGameMaster()) continue; if (pPlayer->isDead()) pPlayer->CastSpell(pPlayer,SPELL_SELF_SPAWN_5,true); } }else RiseFromCorpse_Timer -= diff; if(!swarm) { //Impale_Timer if (Impale_Timer < diff) { //Cast Impale on a random target //Do NOT cast it when we are afflicted by locust swarm if (!m_creature->HasAura(SPELL_LOCUSTSWARM,SpellEffectIndex(1))) if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,SpellEffectIndex(1))) DoCast(target,m_bIsRegularMode ? SPELL_IMPALE : SPELL_IMPALE_H); Impale_Timer = 15000; }else Impale_Timer -= diff; //LocustSwarm_Timer if (LocustSwarm_Timer < diff) { //Cast Locust Swarm buff on ourselves DoCast(m_creature, !m_bIsRegularMode ? SPELL_LOCUSTSWARM_H:SPELL_LOCUSTSWARM); swarm = true; //Summon Crypt Guard immidietly after Locust Swarm if (CryptGuard_count < MAX_CRYPT_GUARDS) m_creature->SummonCreature(MOB_CRYPT_GUARD,3330.0f,-3477.0f,288.0f,3.2f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,10000); LocustSwarm_Timer = 20000; }else LocustSwarm_Timer -= diff; } else { if (LocustSwarm_Timer < diff) { swarm = false; LocustSwarm_Timer = 85000; }else LocustSwarm_Timer -= diff; } if (Ach_Timer<diff) { if (m_bIsRegularMode && m_ach_10ppl) CheckAch(); else if (!m_bIsRegularMode && m_ach_25ppl) CheckAch(); Ach_Timer = 10000; }else Ach_Timer -= diff; DoMeleeAttackIfReady(); }
void WorldSession::HandlePetAction(WorldPacket& recv_data) { ObjectGuid petGuid; uint32 data; ObjectGuid targetGuid; float x, y, z; recv_data >> petGuid; recv_data >> data; recv_data >> targetGuid; recv_data >> x >> y >> z; uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data); uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); // delete = 0x07 CastSpell = C1 DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str()); // used also for charmed creature/player Unit* pet = _player->GetMap()->GetUnit(petGuid); if (!pet) { sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str()); return; } if (GetPlayer()->GetObjectGuid() != pet->GetCharmerOrOwnerGuid()) { sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str()); return; } if (!pet->isAlive()) return; if (pet->GetTypeId() == TYPEID_PLAYER) { // controller player can only do melee attack if (!(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) return; } else if (((Creature*)pet)->IsPet()) { // pet can have action bar disabled if (((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) return; } CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } switch (flag) { case ACT_COMMAND: // 0x07 switch (spellid) { case COMMAND_STAY: // flat=1792 // STAY pet->StopMoving(); pet->GetMotionMaster()->Clear(false); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState(COMMAND_STAY); break; case COMMAND_FOLLOW: // spellid=1792 // FOLLOW pet->AttackStop(); pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); charmInfo->SetCommandState(COMMAND_FOLLOW); break; case COMMAND_ATTACK: // spellid=1792 // ATTACK { Unit* TargetUnit = _player->GetMap()->GetUnit(targetGuid); if (!TargetUnit) return; // not let attack friendly units. if (GetPlayer()->IsFriendlyTo(TargetUnit)) return; // Not let attack through obstructions if (!pet->IsWithinLOSInMap(TargetUnit)) return; // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != TargetUnit) { if (pet->getVictim()) pet->AttackStop(); if (pet->hasUnitState(UNIT_STAT_CONTROLLED)) { pet->Attack(TargetUnit, true); pet->SendPetAIReaction(); } else { pet->GetMotionMaster()->Clear(); if (((Creature*)pet)->AI()) ((Creature*)pet)->AI()->AttackStart(TargetUnit); // 10% chance to play special pet attack talk, else growl if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && roll_chance_i(10)) pet->SendPetTalk((uint32)PET_TALK_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature pet->SendPetAIReaction(); } } } break; } case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) if (((Creature*)pet)->IsPet()) { Pet* p = (Pet*)pet; if (p->getPetType() == HUNTER_PET) p->Unsummon(PET_SAVE_AS_DELETED, _player); else // dismissing a summoned pet is like killing them (this prevents returning a soulshard...) p->SetDeathState(CORPSE); } else // charmed _player->Uncharm(); break; default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } break; case ACT_REACTION: // 0x6 switch (spellid) { case REACT_PASSIVE: // passive case REACT_DEFENSIVE: // recovery case REACT_AGGRESSIVE: // activete charmInfo->SetReactState(ReactStates(spellid)); break; } break; case ACT_DISABLED: // 0x81 spell (disabled), ignore case ACT_PASSIVE: // 0x01 case ACT_ENABLED: // 0xC1 spell { Unit* unit_target = NULL; if (targetGuid) unit_target = _player->GetMap()->GetUnit(targetGuid); // do not cast unknown spells SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) return; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(i)); if (!spellEffect) continue; if (spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) return; } // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) return; pet->clearUnitState(UNIT_STAT_MOVING); Spell* spell = new Spell(pet, spellInfo, false); SpellCastResult result = spell->CheckPetCast(unit_target); // auto turn to target unless possessed if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { if (unit_target) { pet->SetInFront(unit_target); if (unit_target->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target); } else if (Unit* unit_target2 = spell->m_targets.getUnitTarget()) { pet->SetInFront(unit_target2); if (unit_target2->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target2); } if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)powner); result = SPELL_CAST_OK; } if (result == SPELL_CAST_OK) { ((Creature*)pet)->AddCreatureSpellCooldown(spellid); unit_target = spell->m_targets.getUnitTarget(); // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (((Creature*)pet)->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else { pet->SendPetAIReaction(); } if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != unit_target) { if (pet->getVictim()) pet->AttackStop(); pet->GetMotionMaster()->Clear(); if (((Creature*)pet)->AI()) ((Creature*)pet)->AI()->AttackStart(unit_target); } } spell->prepare(&(spell->m_targets)); } else { if (pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) Spell::SendCastResult(GetPlayer(), spellInfo, 0, result); else { Unit* owner = pet->GetCharmerOrOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER) Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true); } if (!((Creature*)pet)->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); spell->finish(false); delete spell; } break; } default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } }
void FillSpellSummary() { SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()]; SpellEntry const* pTempSpell; for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i) { SpellSummary[i].Effects = 0; SpellSummary[i].Targets = 0; pTempSpell = GetSpellStore()->LookupEntry(i); //This spell doesn't exist if (!pTempSpell) continue; for (uint8 j = 0; j < 3; ++j) { SpellEffectEntry const* spellEffect = pTempSpell->GetSpellEffect(SpellEffectIndex(j)); if (!spellEffect) continue; //Spell targets self if (spellEffect->EffectImplicitTargetA == TARGET_SELF) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1); //Spell targets a single enemy if (spellEffect->EffectImplicitTargetA == TARGET_CHAIN_DAMAGE || spellEffect->EffectImplicitTargetA == TARGET_CURRENT_ENEMY_COORDINATES) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1); //Spell targets AoE at enemy if (spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellEffect->EffectImplicitTargetA == TARGET_CASTER_COORDINATES || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); //Spell targets an enemy if (spellEffect->EffectImplicitTargetA == TARGET_CHAIN_DAMAGE || spellEffect->EffectImplicitTargetA == TARGET_CURRENT_ENEMY_COORDINATES || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellEffect->EffectImplicitTargetA == TARGET_CASTER_COORDINATES || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); //Spell targets a single friend(or self) if (spellEffect->EffectImplicitTargetA == TARGET_SELF || spellEffect->EffectImplicitTargetA == TARGET_SINGLE_FRIEND || spellEffect->EffectImplicitTargetA == TARGET_SINGLE_PARTY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1); //Spell targets aoe friends if (spellEffect->EffectImplicitTargetA == TARGET_ALL_PARTY_AROUND_CASTER || spellEffect->EffectImplicitTargetA == TARGET_AREAEFFECT_PARTY || spellEffect->EffectImplicitTargetA == TARGET_CASTER_COORDINATES) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); //Spell targets any friend(or self) if (spellEffect->EffectImplicitTargetA == TARGET_SELF || spellEffect->EffectImplicitTargetA == TARGET_SINGLE_FRIEND || spellEffect->EffectImplicitTargetA == TARGET_SINGLE_PARTY || spellEffect->EffectImplicitTargetA == TARGET_ALL_PARTY_AROUND_CASTER || spellEffect->EffectImplicitTargetA == TARGET_AREAEFFECT_PARTY || spellEffect->EffectImplicitTargetA == TARGET_CASTER_COORDINATES) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); //Make sure that this spell includes a damage effect if (spellEffect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE || spellEffect->Effect == SPELL_EFFECT_INSTAKILL || spellEffect->Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || spellEffect->Effect == SPELL_EFFECT_HEALTH_LEECH) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1); //Make sure that this spell includes a healing effect (or an apply aura with a periodic heal) if (spellEffect->Effect == SPELL_EFFECT_HEAL || spellEffect->Effect == SPELL_EFFECT_HEAL_MAX_HEALTH || spellEffect->Effect == SPELL_EFFECT_HEAL_MECHANICAL || (spellEffect->Effect == SPELL_EFFECT_APPLY_AURA && spellEffect->EffectApplyAuraName== 8)) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1); //Make sure that this spell applies an aura if (spellEffect->Effect == SPELL_EFFECT_APPLY_AURA) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1); } } }
void UpdateAI(const uint32 uiDiff) { if (m_pInstance->GetData(TYPE_ICHORON) == SPECIAL && !MovementStarted) { m_creature->GetMotionMaster()->MovePoint(0, PortalLoc[0].x, PortalLoc[0].y, PortalLoc[0].z); m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); MovementStarted = true; } //Return since we have no target if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; if (!m_bIsFrenzy) { if (m_uiBuubleChecker_Timer < uiDiff) { if (!m_bIsExploded) { if (!m_creature->HasAura(SPELL_PROTECTIVE_BUBBLE, SpellEffectIndex(0))) { DoCast(m_creature, m_bIsRegularMode ? SPELL_WATER_BLAST_H : SPELL_WATER_BLAST); //DoCast(m_creature, SPELL_DRAINED); m_bIsExploded = true; m_uiShowup_Counter = 0; DoCast(m_creature, SPELL_PROTECTIVE_BUBBLE); m_creature->AttackStop(); // m_creature->SetVisibility(VISIBILITY_OFF); for(uint8 i = 0; i < 10; i++) { int tmp = urand(0, 5); m_creature->SummonCreature(NPC_ICHOR_GLOBULE, PortalLoc[tmp].x, PortalLoc[tmp].y, PortalLoc[tmp].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); //m_creature->SummonCreature(NPC_ICHOR_GLOBULE, m_creature->GetPositionX()-10+rand()%20, m_creature->GetPositionY()-10+rand()%20, m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 0); } } m_uiBuubleChecker_Timer = 3000; } else { bool bIsWaterElementsAlive = false; ++m_uiShowup_Counter; if (!m_lWaterElementsGUIDList.empty()) { for(std::list<ObjectGuid>::iterator itr = m_lWaterElementsGUIDList.begin(); itr != m_lWaterElementsGUIDList.end(); ++itr) if (Creature* pTemp = (Creature*)m_creature->GetMap()->GetUnit(*itr)) if (pTemp->isAlive()) bIsWaterElementsAlive = true; } if (!bIsWaterElementsAlive || m_uiShowup_Counter > 20) { m_bIsExploded = false; m_uiShowup_Counter = 0; // m_creature->SetVisibility(VISIBILITY_ON); m_creature->SetInCombatWithZone(); m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); } m_uiBuubleChecker_Timer = 1000; } } else m_uiBuubleChecker_Timer -= uiDiff; } if (!m_bIsExploded) { if (m_uiWaterBoltVolley_Timer < uiDiff) { DoCast(m_creature, m_bIsRegularMode ? SPELL_WATER_BOLT_VOLLEY_H : SPELL_WATER_BOLT_VOLLEY); m_uiWaterBoltVolley_Timer = urand(10000, 15000); } else m_uiWaterBoltVolley_Timer -= uiDiff; if (!m_bIsFrenzy && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25) { DoCast(m_creature, m_bIsRegularMode ? SPELL_FRENZY_H : SPELL_FRENZY); m_bIsFrenzy = true; } } DoMeleeAttackIfReady(); }
void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; LocaleNameStr const* defaultLocaleNameStr = NULL; uint32 build = ReadDBCBuild(dbcPath,defaultLocaleNameStr); // Check the expected DBC version if (!IsAcceptableClientBuild(build)) { if (build) sLog.outError("Found DBC files for build %u but StrawberryWorld expected DBC for one from builds: %s Please extract correct DBC files.", build, AcceptableClientBuildsListStr().c_str()); else sLog.outError("Incorrect DataDir value in StrawberryWorld.conf or not found build info (outdated DBC files). Required one from builds: %s Please extract correct DBC files.",AcceptableClientBuildsListStr().c_str()); Log::WaitBeforeContinueIfNeed(); exit(1); } const uint32 DBCFilesCount = 102; BarGoLink bar(DBCFilesCount); StoreProblemList bad_dbc_files; LocalData availableDbcLocales(build,defaultLocaleNameStr->locale); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaStore, dbcPath,"AreaTable.dbc"); // must be after sAreaStore loading for (uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) // areaflag numbered from 0 { if (AreaTableEntry const* area = sAreaStore.LookupEntry(i)) { // fill AreaId->DBC records sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID),area->exploreFlag)); // fill MapId->DBC records ( skip sub zones and continents ) if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 && area->mapid != 571 ) sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid,area->exploreFlag)); } } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementStore, dbcPath,"Achievement.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementCriteriaStore, dbcPath,"Achievement_Criteria.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaGroupStore, dbcPath,"AreaGroup.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAuctionHouseStore, dbcPath,"AuctionHouse.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBarberShopStyleStore, dbcPath,"BarberShopStyle.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrPowerTypesStore, dbcPath, "ChrClassesXPowerTypes.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrRacesStore, dbcPath,"ChrRaces.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCinematicSequencesStore, dbcPath,"CinematicSequences.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoExtraStore,dbcPath,"CreatureDisplayInfoExtra.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDungeonEncounterStore, dbcPath,"DungeonEncounter.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesStore, dbcPath,"Emotes.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc"); for (uint32 i=0;i<sFactionStore.GetNumRows(); ++i) { FactionEntry const * faction = sFactionStore.LookupEntry(i); if (faction && faction->team) { SimpleFactionsList &flist = sFactionTeamMap[faction->team]; flist.push_back(i); } } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGameObjectDisplayInfoStore,dbcPath,"GameObjectDisplayInfo.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphPropertiesStore, dbcPath,"GlyphProperties.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphSlotStore, dbcPath,"GlyphSlot.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtBarberShopCostBaseStore,dbcPath,"gtBarberShopCostBase.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritStore, dbcPath,"gtChanceToMeleeCrit.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritBaseStore, dbcPath,"gtChanceToSpellCritBase.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritStore, dbcPath,"gtChanceToSpellCrit.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTClassCombatRatingScalarStore,dbcPath,"gtOCTClassCombatRatingScalar.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenHPStore, dbcPath,"gtOCTRegenHP.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sHolidaysStore, dbcPath,"Holidays.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemBagFamilyStore, dbcPath,"ItemBagFamily.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemClassStore, dbcPath,"ItemClass.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemExtendedCostStore, dbcPath,"ItemExtendedCost.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemLimitCategoryStore, dbcPath,"ItemLimitCategory.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomPropertiesStore,dbcPath,"ItemRandomProperties.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomSuffixStore, dbcPath,"ItemRandomSuffix.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemSetStore, dbcPath,"ItemSet.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapDifficultyStore, dbcPath,"MapDifficulty.dbc"); // fill data for(uint32 i = 1; i < sMapDifficultyStore.GetNumRows(); ++i) if(MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i)) sMapDifficultyMap[MAKE_PAIR32(entry->MapId,entry->Difficulty)] = MapDifficulty(entry->resetTime,entry->maxPlayers); sMapDifficultyStore.Clear(); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMovieStore, dbcPath,"Movie.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sOverrideSpellDataStore, dbcPath,"OverrideSpellData.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestFactionRewardStore, dbcPath,"QuestFactionReward.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestXPLevelStore, dbcPath,"QuestXP.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sPvPDifficultyStore, dbcPath,"PvpDifficulty.dbc"); for(uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) if (entry->bracketId > MAX_BATTLEGROUND_BRACKETS) STRAWBERRY_ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatDistributionStore, dbcPath,"ScalingStatDistribution.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatValuesStore, dbcPath,"ScalingStatValues.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillRaceClassInfoStore, dbcPath,"SkillRaceClassInfo.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc"); for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) { if(SpellEntry const * spell = sSpellStore.LookupEntry(i)) { if(SpellCategoriesEntry const* category = spell->GetSpellCategories()) if(uint32 cat = category->Category) sSpellCategoryStore[cat].insert(i); // DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields // uint32 field already converted to bigendian if need, but must be swapped for correct uint64 bigendian view #if STRAWBERRY_ENDIAN == STRAWBERRY_BIGENDIAN std::swap(*((uint32*)(&spell->SpellFamilyFlags)),*(((uint32*)(&spell->SpellFamilyFlags))+1)); #endif } } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellAuraOptionsStore, dbcPath,"SpellAuraOptions.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellAuraRestrictionsStore, dbcPath,"SpellAuraRestrictions.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCastingRequirementsStore, dbcPath,"SpellCastingRequirements.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCategoriesStore, dbcPath,"SpellCategories.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellClassOptionsStore, dbcPath,"SpellClassOptions.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCooldownsStore, dbcPath,"SpellCooldowns.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellEffectStore, dbcPath,"SpellEffect.dbc"); /*for(uint32 i = 1; i < sSpellEffectStore.GetNumRows(); ++i) { if(SpellEffectEntry const *spellEffect = sSpellEffectStore.LookupEntry(i)) sSpellEffectMap[spellEffect->EffectSpellId].effects[spellEffect->EffectIndex] = spellEffect; }*/ LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellEquippedItemsStore, dbcPath,"SpellEquippedItems.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellInterruptsStore, dbcPath,"SpellInterrupts.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellLevelsStore, dbcPath,"SpellLevels.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellMiscStore, dbcPath,"SpellMisc.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellPowerStore, dbcPath,"SpellPower.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellReagentsStore, dbcPath,"SpellReagents.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellScalingStore, dbcPath,"SpellScaling.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshift.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellTargetRestrictionsStore, dbcPath,"SpellTargetRestrictions.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellTotemsStore, dbcPath,"SpellTotems.dbc"); for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); if(!skillLine) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId); SpellMiscEntry const* spellMisc = sSpellMiscStore.LookupEntry(skillLine->spellId); if (!spellMisc) continue; if(spellInfo && spellMisc->Attributes & 0x1D0 == 0x1D0) { for (unsigned int i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i) { CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i); if(!cFamily) continue; if(skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1]) continue; sPetFamilySpellsStore[i].insert(spellInfo->Id); } } } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCastTimesStore, dbcPath,"SpellCastTimes.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellDurationStore, dbcPath,"SpellDuration.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellFocusObjectStore, dbcPath,"SpellFocusObject.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentStore,dbcPath,"SpellItemEnchantment.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRuneCostStore, dbcPath,"SpellRuneCost.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftFormStore, dbcPath,"SpellShapeshiftForm.dbc"); //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc"); // create talent spells set for (unsigned int i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; for (int j = 0; j < MAX_TALENT_RANK; j++) if(talentInfo->RankID[j]) sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i,j); } //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentTabStore, dbcPath,"TalentTab.dbc"); // prepare fast data access to bit pos of talent ranks for use at inspecting { // now have all max ranks (and then bit amount used for store talent ranks in inspect) for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId) { TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentTabId ); if(!talentTabInfo) continue; // prevent memory corruption; otherwise cls will become 12 below if ((talentTabInfo->ClassMask & CLASSMASK_ALL_PLAYABLE)==0) continue; // store class talent tab pages uint32 cls = 1; for(uint32 m=1;!(m & talentTabInfo->ClassMask) && cls < MAX_CLASSES;m <<=1, ++cls) {} sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId; } } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc"); for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID,entry->price); uint32 pathCount = sTaxiPathStore.GetNumRows(); //## TaxiPathNode.dbc ## Loaded only for initialization different structures LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathNodeStore, dbcPath,"TaxiPathNode.dbc"); // Calculate path nodes count std::vector<uint32> pathLength; pathLength.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) { if (pathLength[entry->path] < entry->index + 1) pathLength[entry->path] = entry->index + 1; } // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) sTaxiPathNodesByPath[i].resize(pathLength[i]); // fill data (pointers to sTaxiPathNodeStore elements for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) sTaxiPathNodesByPath[entry->path].set(entry->index, entry); // Initialize global taxinodes mask // include existing nodes that have at least single not spell base (scripted) path { std::set<uint32> spellPaths; for(uint32 i = 1; i < sSpellStore.GetNumRows (); ++i) if(SpellEntry const* sInfo = sSpellStore.LookupEntry (i)) for(int j=0; j < MAX_EFFECT_INDEX; ++j) if(SpellEffectEntry const* effect = sInfo->GetSpellEffect(SpellEffectIndex(j))) if(effect->Effect==123 /*SPELL_EFFECT_SEND_TAXI*/) spellPaths.insert(effect->EffectMiscValue); memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask)); memset(sOldContinentsNodesMask,0,sizeof(sTaxiNodesMask)); for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) { TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); if(!node) continue; TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(i); if(src_i!=sTaxiPathSetBySource.end() && !src_i->second.empty()) { bool ok = false; for(TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin();dest_i != src_i->second.end(); ++dest_i) { // not spell path if(spellPaths.find(dest_i->second.ID)==spellPaths.end()) { ok = true; break; } } if(!ok) continue; } // valid taxi network node uint8 field = (uint8)((i - 1) / 32); uint32 submask = 1<<((i-1)%32); sTaxiNodesMask[field] |= submask; // old continent node (+ nodes virtually at old continents, check explicitly to avoid loading map files for zone info) if (node->map_id < 2 || i == 82 || i == 83 || i == 93 || i == 94) sOldContinentsNodesMask[field] |= submask; } } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleStore, dbcPath,"Vehicle.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleSeatStore, dbcPath,"VehicleSeat.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWMOAreaTableStore, dbcPath,"WMOAreaTable.dbc"); for(uint32 i = 0; i < sWMOAreaTableStore.GetNumRows(); ++i) { if(WMOAreaTableEntry const* entry = sWMOAreaTableStore.LookupEntry(i)) { sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->rootId, entry->adtId, entry->groupId), entry)); } } LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapOverlayStore, dbcPath,"WorldMapOverlay.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc"); // error checks if (bad_dbc_files.size() >= DBCFilesCount ) { sLog.outError("\nIncorrect DataDir value in StrawberryWorld.conf or ALL required *.dbc files (%d) not found by path: %sdbc",DBCFilesCount,dataPath.c_str()); Log::WaitBeforeContinueIfNeed(); exit(1); } else if (!bad_dbc_files.empty() ) { std::string str; for(std::list<std::string>::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i) str += *i + "\n"; sLog.outError("\nSome required *.dbc files (%u from %d) not found or not compatible:\n%s",(uint32)bad_dbc_files.size(),DBCFilesCount,str.c_str()); Log::WaitBeforeContinueIfNeed(); exit(1); } // Check loaded DBC files proper version if (!sAreaStore.LookupEntry(4975) || // last area (areaflag) added in 5.0.1 Beta !sCharTitlesStore.LookupEntry(287) || // last char title added in 5.0.1 Beta !sGemPropertiesStore.LookupEntry(2272) || // last gem property added in 5.0.1 Beta !sMapStore.LookupEntry(1051) || // last map added in 5.0.1 Beta !sSpellStore.LookupEntry(122523) ) // last added spell in 5.0.1 Beta { sLog.outError("\nYou have mixed version DBC files. Please re-extract DBC files for one from client build: %s",AcceptableClientBuildsListStr().c_str()); Log::WaitBeforeContinueIfNeed(); exit(1); } sLog.outString(); sLog.outString( ">> Initialized %d data stores", DBCFilesCount ); }
void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacket* data) { uint32 mask = player->GetGroupUpdateFlag(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) // same for pets mask |= (GROUP_UPDATE_FLAG_PET_CUR_POWER | GROUP_UPDATE_FLAG_PET_MAX_POWER); uint32 byteCount = 0; for (int i = 1; i < GROUP_UPDATE_FLAGS_COUNT; ++i) if (mask & (1 << i)) byteCount += GroupUpdateLength[i]; data->Initialize(SMSG_PARTY_MEMBER_STATS, 8 + 4 + byteCount); *data << player->GetPackGUID(); *data << uint32(mask); if (mask & GROUP_UPDATE_FLAG_STATUS) { if (player->IsPvP()) *data << uint16(MEMBER_STATUS_ONLINE | MEMBER_STATUS_PVP); else *data << uint16(MEMBER_STATUS_ONLINE); } if (mask & GROUP_UPDATE_FLAG_CUR_HP) *data << uint32(player->GetHealth()); if (mask & GROUP_UPDATE_FLAG_MAX_HP) *data << uint32(player->GetMaxHealth()); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) *data << uint8(powerType); if (mask & GROUP_UPDATE_FLAG_CUR_POWER) *data << uint16(player->GetPower(powerType)); if (mask & GROUP_UPDATE_FLAG_MAX_POWER) *data << uint16(player->GetMaxPower(powerType)); if (mask & GROUP_UPDATE_FLAG_LEVEL) *data << uint16(player->getLevel()); if (mask & GROUP_UPDATE_FLAG_ZONE) *data << uint16(player->GetZoneId()); if (mask & GROUP_UPDATE_FLAG_UNK) *data << uint16(0); if (mask & GROUP_UPDATE_FLAG_POSITION) *data << uint16(player->GetPositionX()) << uint16(player->GetPositionY()) << uint16(player->GetPositionZ()); if (mask & GROUP_UPDATE_FLAG_AURAS) { *data << uint8(0); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below const uint64& auramask = player->GetAuraUpdateMask(); *data << uint64(auramask); *data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { if (SpellAuraHolder* holder = player->GetVisibleAura(i)) { *data << uint32(holder->GetId()); *data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) *data << int32(aura->GetModifier()->m_amount); else *data << int32(0); } else { *data << uint32(0); *data << uint16(0); } } } } Pet* pet = player->GetPet(); if (mask & GROUP_UPDATE_FLAG_PET_GUID) *data << (pet ? pet->GetObjectGuid() : ObjectGuid()); if (mask & GROUP_UPDATE_FLAG_PET_NAME) { if (pet) *data << pet->GetName(); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_MODEL_ID) { if (pet) *data << uint16(pet->GetDisplayId()); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if (pet) *data << uint32(pet->GetHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if (pet) *data << uint32(pet->GetMaxHealth()); else *data << uint32(0); } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) { if (pet) *data << uint8(pet->getPowerType()); else *data << uint8(0); } if (mask & GROUP_UPDATE_FLAG_PET_CUR_POWER) { if (pet) *data << uint16(pet->GetPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_MAX_POWER) { if (pet) *data << uint16(pet->GetMaxPower(pet->getPowerType())); else *data << uint16(0); } if (mask & GROUP_UPDATE_FLAG_PET_AURAS) { if (pet) { *data << uint8(0); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below const uint64& auramask = pet->GetAuraUpdateMask(); *data << uint64(auramask); *data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint32 i = 0; i < MAX_AURAS; ++i) { if (auramask & (uint64(1) << i)) { if (SpellAuraHolder* holder = pet->GetVisibleAura(i)) { *data << uint32(holder->GetId()); *data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) *data << int32(aura->GetModifier()->m_amount); else *data << int32(0); } else { *data << uint32(0); *data << uint16(0); } } } } else { *data << uint8(0); *data << uint64(0); *data << uint32(0); } } if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) *data << int32(0); if (mask & GROUP_UPDATE_FLAG_PHASE) { *data << uint32(8); *data << uint32(0); *data << uint8(0); } }
void WorldSession::HandlePetAction(WorldPacket& recv_data) { ObjectGuid petGuid; uint32 data; ObjectGuid targetGuid; float x, y, z; recv_data >> petGuid; recv_data >> data; recv_data >> targetGuid; recv_data >> x >> y >> z; uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data); uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); // delete = 0x07 CastSpell = C1 DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str()); // used also for charmed creature/player Unit* pet = _player->GetMap()->GetUnit(petGuid); if (!pet) { sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str()); return; } if (_player->GetObjectGuid() != pet->GetCharmerOrOwnerGuid()) { sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), _player->GetGuidStr().c_str()); return; } if (!pet->isAlive()) return; if (pet->GetTypeId() == TYPEID_PLAYER && pet->GetCharmer()->GetTypeId() == TYPEID_PLAYER) { // controller player cannot use controlled player's spells if (flag != (ACT_COMMAND || ACT_REACTION)) return; } else if (((Creature*)pet)->IsPet()) { // pet can have action bar disabled if (((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) return; } CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } switch (flag) { case ACT_COMMAND: // 0x07 switch (spellid) { case COMMAND_STAY: // flat=1792 // STAY { pet->StopMoving(); pet->AttackStop(true, true); pet->GetMotionMaster()->Clear(); ((Pet*)pet)->SetStayPosition(true); ((Pet*)pet)->SetIsRetreating(); ((Pet*)pet)->SetSpellOpener(); charmInfo->SetCommandState(COMMAND_STAY); break; } case COMMAND_FOLLOW: // spellid=1792 // FOLLOW { pet->StopMoving(); pet->AttackStop(true, true); pet->GetMotionMaster()->Clear(); ((Pet*)pet)->SetStayPosition(); ((Pet*)pet)->SetIsRetreating(true); ((Pet*)pet)->SetSpellOpener(); charmInfo->SetCommandState(COMMAND_FOLLOW); break; } case COMMAND_ATTACK: // spellid=1792 // ATTACK { ((Pet*)pet)->SetIsRetreating(); ((Pet*)pet)->SetSpellOpener(); Unit* targetUnit = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr; if (targetUnit && targetUnit != pet && targetUnit->isTargetableForAttack() && targetUnit->isInAccessablePlaceFor((Creature*)pet)) { _player->SetInCombatState(true, targetUnit); // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != targetUnit) { pet->AttackStop(); pet->GetMotionMaster()->Clear(); if (((Creature*)pet)->AI()) { ((Creature*)pet)->AI()->AttackStart(targetUnit); // 10% chance to play special warlock pet attack talk, else growl if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && roll_chance_i(10)) pet->SendPetTalk((uint32)PET_TALK_ATTACK); pet->SendPetAIReaction(); } else pet->Attack(targetUnit, true); } } break; } case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) { Creature* petC = (Creature*)pet; if (petC->IsPet()) { Pet* p = (Pet*)petC; if (p->getPetType() == HUNTER_PET) p->Unsummon(PET_SAVE_AS_DELETED, _player); else // dismissing a summoned pet is like killing them (this prevents returning a soulshard...) p->SetDeathState(CORPSE); } else // charmed _player->Uncharm(); if (petC->IsTemporarySummon()) // special case when pet was temporary summon through DoSummonPossesed { petC->ForcedDespawn(); return; } ((Pet*)pet)->SetStayPosition(); break; } default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } break; case ACT_REACTION: // 0x6 switch (spellid) { case REACT_PASSIVE: // passive { pet->AttackStop(true, true); ((Pet*)pet)->SetSpellOpener(); } case REACT_DEFENSIVE: // recovery case REACT_AGGRESSIVE: // activete { charmInfo->SetReactState(ReactStates(spellid)); break; } } break; case ACT_DISABLED: // 0x81 spell (disabled), ignore case ACT_PASSIVE: // 0x01 case ACT_ENABLED: // 0xC1 spell { ((Pet*)pet)->SetIsRetreating(); ((Pet*)pet)->SetSpellOpener(); Unit* unit_target = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr; // do not cast unknown spells SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) return; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(i)); if (!spellEffect) continue; if (spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellEffect->EffectImplicitTargetA == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) return; } // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) return; pet->clearUnitState(UNIT_STAT_MOVING); Spell* spell = new Spell(pet, spellInfo, false); SpellCastResult result = spell->CheckPetCast(unit_target); const SpellRangeEntry* sRange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); if (unit_target && !(pet->IsWithinDistInMap(unit_target, sRange->maxRange) && pet->IsWithinLOSInMap(unit_target)) && !(GetPlayer()->IsFriendlyTo(unit_target) || pet->HasAuraType(SPELL_AURA_MOD_POSSESS))) { ((Pet*)pet)->SetSpellOpener(spellid, sRange->minRange, sRange->maxRange); spell->finish(false); delete spell; pet->AttackStop(); pet->GetMotionMaster()->Clear(); ((Creature*)pet)->AI()->AttackStart(unit_target); // 10% chance to play special warlock pet attack talk, else growl if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10)) pet->SendPetTalk((uint32)PET_TALK_ATTACK); pet->SendPetAIReaction(); return; } // auto turn to target unless possessed if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { if (unit_target) { pet->SetInFront(unit_target); if (unit_target->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target); } else if (Unit* unit_target2 = spell->m_targets.getUnitTarget()) { pet->SetInFront(unit_target2); if (unit_target2->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target2); } if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)powner); result = SPELL_CAST_OK; } if (result == SPELL_CAST_OK) { ((Creature*)pet)->AddCreatureSpellCooldown(spellid); unit_target = spell->m_targets.getUnitTarget(); if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { // This is true if pet has no target or has target but targets differs. if (pet->getVictim() != unit_target) { pet->AttackStop(); pet->GetMotionMaster()->Clear(); _player->SetInCombatState(true, unit_target); if (((Creature*)pet)->AI()) { ((Creature*)pet)->AI()->AttackStart(unit_target); // 10% chance to play special warlock pet attack talk, else growl if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10)) pet->SendPetTalk((uint32)PET_TALK_ATTACK); pet->SendPetAIReaction(); } else pet->Attack(unit_target, true); } } ((Pet*)pet)->SetSpellOpener(); spell->SpellStart(&(spell->m_targets)); } else { if (pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) Spell::SendCastResult(GetPlayer(), spellInfo, 0, result); else { Unit* owner = pet->GetCharmerOrOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER) Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true); } if (!((Creature*)pet)->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); ((Pet*)pet)->SetSpellOpener(); spell->finish(false); delete spell; } break; } default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } }
/*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_REQUEST_PARTY_MEMBER_STATS"); ObjectGuid guid; recv_data >> guid; Player* player = ObjectAccessor::FindPlayer(guid, false); if (!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3 + 4 + 2); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << guid.WriteAsPacked(); data << uint32(GROUP_UPDATE_FLAG_STATUS); data << uint16(MEMBER_STATUS_OFFLINE); SendPacket(&data); return; } Pet* pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4 + 2 + 2 + 2 + 1 + 2 * 6 + 8 + 1 + 8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data << player->GetPackGUID(); uint32 mask1 = GROUP_UPDATE_FLAG_STATUS | GROUP_UPDATE_FLAG_CUR_HP | GROUP_UPDATE_FLAG_MAX_HP | GROUP_UPDATE_FLAG_POWER_TYPE | GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER | GROUP_UPDATE_FLAG_LEVEL | GROUP_UPDATE_FLAG_ZONE | GROUP_UPDATE_FLAG_POSITION | GROUP_UPDATE_FLAG_AURAS | GROUP_UPDATE_FLAG_PET_NAME | GROUP_UPDATE_FLAG_PET_AURAS | GROUP_UPDATE_FLAG_PHASE; if (pet) mask1 = 0x7FEFFEFF; // full mask & ~(GROUP_UPDATE_FLAG_VEHICLE_SEAT | GROUP_UPDATE_FLAG_UNK) Powers powerType = player->getPowerType(); data << uint32(mask1); // group update mask data << uint16(MEMBER_STATUS_ONLINE); // member's online status data << uint32(player->GetHealth()); // GROUP_UPDATE_FLAG_CUR_HP data << uint32(player->GetMaxHealth()); // GROUP_UPDATE_FLAG_MAX_HP data << uint8(powerType); // GROUP_UPDATE_FLAG_POWER_TYPE data << uint16(player->GetPower(powerType)); // GROUP_UPDATE_FLAG_CUR_POWER data << uint16(player->GetMaxPower(powerType)); // GROUP_UPDATE_FLAG_MAX_POWER data << uint16(player->getLevel()); // GROUP_UPDATE_FLAG_LEVEL // verify player coordinates and zoneid to send to teammates uint16 iZoneId = 0; uint16 iCoordX = 0; uint16 iCoordY = 0; uint16 iCoordZ = 0; if (player->IsInWorld()) { iZoneId = player->GetZoneId(); iCoordX = player->GetPositionX(); iCoordY = player->GetPositionY(); iCoordZ = player->GetPositionZ(); } else if (player->IsBeingTeleported()) // Player is in teleportation { WorldLocation& loc = player->GetTeleportDest(); // So take teleportation destination iZoneId = sTerrainMgr.GetZoneId(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); iCoordX = loc.coord_x; iCoordY = loc.coord_y; iCoordZ = loc.coord_z; } else { // unknown player status. } data << uint16(iZoneId); // GROUP_UPDATE_FLAG_ZONE data << uint16(iCoordX); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordY); // GROUP_UPDATE_FLAG_POSITION data << uint16(iCoordZ); // GROUP_UPDATE_FLAG_POSITION data << uint8(1); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below uint64 auramask = 0; size_t maskPos = data.wpos(); data << uint64(auramask); // placeholder, server sends 0xFFFFFFFFFFFFFFFF here, but with 1 above it seems no difference data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolder* holder = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) data << int32(aura->GetModifier()->m_amount); else data << int32(0); } } data.put<uint64>(maskPos, auramask); // GROUP_UPDATE_FLAG_AURAS if (pet) { Powers petpowertype = pet->getPowerType(); data << pet->GetObjectGuid(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << uint16(pet->GetDisplayId()); // GROUP_UPDATE_FLAG_PET_MODEL_ID data << uint32(pet->GetHealth()); // GROUP_UPDATE_FLAG_PET_CUR_HP data << uint32(pet->GetMaxHealth()); // GROUP_UPDATE_FLAG_PET_MAX_HP data << uint8(petpowertype); // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << uint16(pet->GetPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << uint16(pet->GetMaxPower(petpowertype)); // GROUP_UPDATE_FLAG_PET_MAX_POWER data << uint8(1); // if true, client clears all auras that are not in auramask and whose index is lower amount sent below uint64 petauramask = 0; size_t petMaskPos = data.wpos(); data << uint64(petauramask); // placeholder, server sends 0xFFFFFFFFFFFFFFFF here, but with 1 above it seems no difference data << uint32(MAX_AURAS); // server sends here number of visible auras, but client checks // if aura is in auramask, so it seems no difference if there will be MAX_AURAS for (uint8 i = 0; i < MAX_AURAS; ++i) { if (SpellAuraHolder* holder = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); data << uint32(holder->GetId()); data << uint16(holder->GetAuraFlags()); if (holder->GetAuraFlags() & AFLAG_EFFECT_AMOUNT_SEND) for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) if (Aura* aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i))) data << int32(aura->GetModifier()->m_amount); else data << int32(0); } } data.put<uint64>(petMaskPos, petauramask); // GROUP_UPDATE_FLAG_PET_AURAS } else { data << uint8(0); // GROUP_UPDATE_FLAG_PET_NAME data << uint8(1); // GROUP_UPDATE_FLAG_PET_AURAS data << uint64(0); // GROUP_UPDATE_FLAG_PET_AURAS data << uint32(0); // GROUP_UPDATE_FLAG_PET_AURAS } data << uint32(8); // GROUP_UPDATE_FLAG_PHASE data << uint32(0); // GROUP_UPDATE_FLAG_PHASE data << uint8(0); // GROUP_UPDATE_FLAG_PHASE SendPacket(&data); }