void HandleScriptEffect(SpellEffIndex effIndex) { Unit* caster = GetCaster(); Unit* unitTarget = GetHitUnit(); if (!unitTarget) return; uint32 spellId = 0; int32 basePoint = 0; Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras(); for (Unit::AuraApplicationMap::iterator i = Auras.begin(); i != Auras.end(); ++i) { Aura* aura = i->second->GetBase(); if (aura->GetCasterGUID() != caster->GetGUID()) continue; // Search only Serpent Sting, Viper Sting, Scorpid Sting auras flag96 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000)) continue; if (AuraEffect const * aurEff = aura->GetEffect(0)) { // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. if (familyFlag[0] & 0x4000) { int32 TickCount = aurEff->GetTotalTicks(); spellId = HUNTER_SPELL_CHIMERA_SHOT_SERPENT; basePoint = aurEff->GetAmount() * TickCount * 40 / 100; } // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. else if (familyFlag[1] & 0x00000080) { int32 TickCount = aura->GetEffect(0)->GetTotalTicks(); spellId = HUNTER_SPELL_CHIMERA_SHOT_VIPER; // Amount of one aura tick basePoint = aurEff->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 100 ; int32 casterBasePoint = aurEff->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 50 ; if (basePoint > casterBasePoint) basePoint = casterBasePoint; basePoint = basePoint * TickCount * 60 / 100; } // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. else if (familyFlag[0] & 0x00008000) spellId = HUNTER_SPELL_CHIMERA_SHOT_SCORPID; // ?? nothing say in spell desc (possibly need addition check) //if (familyFlag & 0x0000010000000000LL || // dot // familyFlag & 0x0000100000000000LL) // stun //{ // spellId = 53366; // 53366 Chimera Shot - Wyvern //} // Refresh aura duration aura->RefreshDuration(); } break; } if (spellId) caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); }
bool AuraInterface::BuildAuraUpdateAllPacket(WorldPacket* data) { if(!m_auras.size()) return false; bool res = false; Aura* aur = NULL; for (uint32 i=0; i<MAX_AURAS; i++) { if(m_auras.find(i) != m_auras.end()) { res = true; aur = m_auras.at(i); aur->BuildAuraUpdate(); uint8 flags = aur->GetAuraFlags(); *data << uint8(aur->m_auraSlot); int32 stack = aur->stackSize; if(aur->procCharges > stack && stack != 0) stack = aur->procCharges; if(stack < 0) { *data << uint32(0); continue; } *data << uint32(aur->GetSpellId()); *data << uint8(flags); *data << uint8(aur->GetUnitCaster() ? aur->GetUnitCaster()->getLevel() : 0); *data << uint8(stack); if(!(flags & AFLAG_NOT_GUID)) FastGUIDPack(*data, aur->GetCasterGUID()); if(flags & AFLAG_HAS_DURATION) { *data << aur->GetDuration(); *data << aur->GetTimeLeft(); } } } return res; }
void HandleScriptEffect(SpellEffIndex /*effIndex*/) { Unit* caster = GetCaster(); if (Unit* unitTarget = GetHitUnit()) { uint32 spellId = 0; int32 basePoint = 0; Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras(); for (Unit::AuraApplicationMap::iterator i = Auras.begin(); i != Auras.end(); ++i) { Aura* aura = i->second->GetBase(); if (aura->GetCasterGUID() != caster->GetGUID()) continue; // Search only Serpent Sting, Viper Sting, Scorpid Sting auras flag96 familyFlag = aura->GetSpellInfo()->SpellFamilyFlags; if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000)) continue; if (AuraEffect* aurEff = aura->GetEffect(0)) { // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. if (familyFlag[0] & 0x4000) { int32 TickCount = aurEff->GetTotalTicks(); spellId = SPELL_HUNTER_CHIMERA_SHOT_SERPENT; basePoint = (aurEff->GetAmount() + aurEff->GetBonusAmount()) * aurEff->GetDonePct(); ApplyPct(basePoint, TickCount * 40); basePoint = unitTarget->SpellDamageBonusTaken(caster, aura->GetSpellInfo(), basePoint, DOT, aura->GetStackAmount()); if (Player* modOwner = caster->GetSpellModOwner()) modOwner->ApplySpellMod(aura->GetSpellInfo()->Id, SPELLMOD_DOT, basePoint); aurEff->SetBonusAmount(caster->SpellDamageBonusDone(unitTarget, aurEff->GetSpellInfo(), 0, DOT)); } // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. else if (familyFlag[1] & 0x00000080) { int32 TickCount = aura->GetEffect(0)->GetTotalTicks(); spellId = SPELL_HUNTER_CHIMERA_SHOT_VIPER; // Amount of one aura tick basePoint = int32(CalculatePct(unitTarget->GetMaxPower(POWER_MANA), aurEff->GetAmount())); int32 casterBasePoint = aurEff->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 50; /// @todo WTF? caster uses unitTarget? if (basePoint > casterBasePoint) basePoint = casterBasePoint; ApplyPct(basePoint, TickCount * 60); } // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. else if (familyFlag[0] & 0x00008000) spellId = SPELL_HUNTER_CHIMERA_SHOT_SCORPID; // ?? nothing say in spell desc (possibly need addition check) //if (familyFlag & 0x0000010000000000LL || // dot // familyFlag & 0x0000100000000000LL) // stun //{ // spellId = 53366; // 53366 Chimera Shot - Wyvern //} // Refresh aura duration aura->RefreshDuration(); } break; } if (spellId) caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, true); if (spellId == SPELL_HUNTER_CHIMERA_SHOT_SCORPID && caster->ToPlayer()) // Scorpid Sting - Add 1 minute cooldown caster->GetSpellHistory()->AddCooldown(spellId, 0, std::chrono::minutes(1)); } }
void AuraInterface::AddAura(Aura* aur) { uint32 x,delslot = 0; Unit* pCaster = NULLUNIT; if(aur->GetUnitTarget() != NULL) pCaster = aur->GetUnitCaster(); else if( aur->GetCasterGUID() == m_Unit->GetGUID() ) pCaster = m_Unit; else if( m_Unit->GetMapMgr() && aur->GetCasterGUID()) pCaster = m_Unit->GetMapMgr()->GetUnit( aur->GetCasterGUID()); if(pCaster == NULL) return; if( !aur->IsPassive() ) { uint32 maxStack = aur->GetSpellProto()->maxstack; if( m_Unit->IsPlayer() && TO_PLAYER(m_Unit)->stack_cheat ) maxStack = 255; SpellEntry * info = aur->GetSpellProto(); bool deleteAur = false; Aura* curAura = NULLAURA; //check if we already have this aura by this caster -> update duration // Nasty check for Blood Fury debuff (spell system based on namehashes is bs anyways) if( !info->always_apply ) { for( x = 0; x < MAX_AURAS; x++ ) { if(m_auras.find(x) == m_auras.end()) continue; curAura = m_auras.at(x); if( curAura != NULL && !curAura->m_deleted ) { if( curAura->GetSpellProto()->Id != aur->GetSpellId() && ( aur->pSpellId != curAura->GetSpellProto()->Id )) //if this is a proc spell then it should not remove it's mother : test with combustion later { if( info->buffType > 0 && m_auras.at(x)->GetSpellProto()->buffType > 0 && (info->buffType & m_auras.at(x)->GetSpellProto()->buffType) ) { if( m_auras.at(x)->GetSpellProto()->buffType & SPELL_TYPE_BLESSING ) { // stupid blessings // if you have better idea correct bool ispair = false; switch( info->NameHash ) { case SPELL_HASH_BLESSING_OF_MIGHT: case SPELL_HASH_GREATER_BLESSING_OF_MIGHT: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_MIGHT || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_MIGHT ) ispair = true; }break; case SPELL_HASH_BLESSING_OF_WISDOM: case SPELL_HASH_GREATER_BLESSING_OF_WISDOM: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_WISDOM || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_WISDOM ) ispair = true; }break; case SPELL_HASH_BLESSING_OF_KINGS: case SPELL_HASH_GREATER_BLESSING_OF_KINGS: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_KINGS || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_KINGS ) ispair = true; }break; case SPELL_HASH_BLESSING_OF_SANCTUARY: case SPELL_HASH_GREATER_BLESSING_OF_SANCTUARY: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_SANCTUARY || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_SANCTUARY ) ispair = true; }break; } if( m_auras.at(x)->GetUnitCaster() == aur->GetUnitCaster() || ispair ) { RemoveAuraBySlot(x); continue; } } else if( m_auras.at(x)->GetSpellProto()->buffType & SPELL_TYPE_AURA ) { if( m_auras.at(x)->GetUnitCaster() == aur->GetUnitCaster() || m_auras.at(x)->GetSpellProto()->NameHash == info->NameHash ) { RemoveAuraBySlot(x); continue; } } else { RemoveAuraBySlot(x); continue; } } else if( info->poison_type > 0 && m_auras.at(x)->GetSpellProto()->poison_type == info->poison_type ) { if( m_auras.at(x)->GetSpellProto()->RankNumber < info->RankNumber || maxStack == 0) { RemoveAuraBySlot(x); continue; } else if( m_auras.at(x)->GetSpellProto()->RankNumber > info->RankNumber ) { RemoveAuraBySlot(x); break; } } else if( m_auras.at(x)->GetSpellProto()->NameHash == info->NameHash ) { if( m_auras.at(x)->GetUnitCaster() == aur->GetUnitCaster() ) { RemoveAuraBySlot(x); continue; } else if( m_auras.at(x)->GetSpellProto()->Unique ) { if( m_auras.at(x)->GetSpellProto()->RankNumber < info->RankNumber ) { RemoveAuraBySlot(x); continue; } else { delslot = x; deleteAur = true; break; } } } } else if( curAura->GetSpellId() == aur->GetSpellId() ) { if( !aur->IsPositive() && curAura->GetCasterGUID() != aur->GetCasterGUID() && maxStack == 0 && !info->Unique ) continue; // target already has this aura. Update duration, time left, procCharges curAura->SetDuration(aur->GetDuration()); curAura->SetTimeLeft(aur->GetDuration()); curAura->procCharges = curAura->GetMaxProcCharges(pCaster); curAura->UpdateModifiers(); curAura->ModStackSize(1); // increment stack size return; } } } } if(deleteAur) { sEventMgr.RemoveEvents(aur); RemoveAuraBySlot(delslot); return; } } //////////////////////////////////////////////////////// if( aur->m_auraSlot != 255 && aur->m_auraSlot < TOTAL_AURAS) { if( m_auras.find(aur->m_auraSlot) != m_auras.end() ) RemoveAuraBySlot(aur->m_auraSlot); } aur->m_auraSlot = 255; Unit* target = aur->GetUnitTarget(); if(target == NULL) return; // Should never happen. aur->SetAuraFlags(AFLAG_VISIBLE | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2 | AFLAG_NOT_GUID | (aur->GetDuration() ? AFLAG_HAS_DURATION : AFLAG_NONE) | (aur->IsPositive() ? (AFLAG_POSITIVE) : (AFLAG_NEGATIVE))); aur->SetAuraLevel(aur->GetUnitCaster() != NULL ? aur->GetUnitCaster()->getLevel() : MAXIMUM_ATTAINABLE_LEVEL); if(!aur->IsPassive()) { aur->AddAuraVisual(); if(aur->m_auraSlot == 255) { //add to invisible slot for(x = MAX_AURAS; x < TOTAL_AURAS; x++) { if(m_auras.find(x) == m_auras.end()) { m_auras.insert(make_pair(x, aur)); aur->m_auraSlot = x; break; } } if(aur->m_auraSlot == 255) { DEBUG_LOG("Unit","AddAura error in active aura. removing. SpellId: %u", aur->GetSpellProto()->Id); RemoveAura(aur); return; } } else { m_auras.insert(make_pair(aur->m_auraSlot, aur)); } } else { if(aur->m_spellProto->AttributesEx & 1024) aur->AddAuraVisual(); for(x = MAX_AURAS; x < TOTAL_AURAS; x++) { if(m_auras.find(x) == m_auras.end()) { m_auras.insert(make_pair(x, aur)); aur->m_auraSlot = x; break; } } if(aur->m_auraSlot == 255) { DEBUG_LOG("Unit","AddAura error in passive aura. removing. SpellId: %u", aur->GetSpellProto()->Id); RemoveAura(aur); return; } } if(aur->GetSpellId() == 15007) //Resurrection sickness { aur->SetNegative(100); //we're negative aur->SetDuration(target->getLevel() > 19 ? 600000 : 60000); } aur->ApplyModifiers(true); // We add 500ms here to allow for the last tick in DoT spells. This is a dirty hack, but at least it doesn't crash like my other method. // - Burlex, Crow: Changed to 400ms if(aur->GetDuration() > 0) { uint32 addTime = 400; for(uint32 spx = 0; spx < 3; spx++) { if( aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_STUN || aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_FEAR || aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_ROOT || aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_CHARM ) addTime = 50; } sEventMgr.AddAuraEvent(m_Unit, &Unit::RemoveAuraBySlot, uint8(aur->m_auraSlot), aur->GetDuration() + addTime, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT | EVENT_FLAG_DELETES_OBJECT, aur->GetSpellId()); } aur->RelocateEvents(); // Send log to client if (target != NULL) { //send the aura log WorldPacket data(SMSG_AURACASTLOG, 28); data << aur->GetCasterGUID(); data << aur->GetTargetGUID(); data << aur->m_spellProto->Id; data << uint64(0); target->SendMessageToSet(&data, true); } m_Unit->m_chargeSpellsInUse = true; if( aur->procCharges > 0 && !(aur->GetSpellProto()->procflags2 & PROC_REMOVEONUSE)) m_Unit->m_chargeSpells.push_back(aur); m_Unit->m_chargeSpellsInUse = false; aur->m_added = true; // Reaction from enemy AI if( !aur->IsPositive() && CanAgroHash( aur->GetSpellProto()->NameHash ) ) { if(pCaster != NULL && m_Unit->isAlive()) { pCaster->CombatStatus.OnDamageDealt(TO_UNIT(this), 1); if(m_Unit->IsCreature()) m_Unit->GetAIInterface()->AttackReaction(pCaster, 1, aur->GetSpellId()); } } if (aur->GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_ON_INVINCIBLE) { if( pCaster != NULL ) { pCaster->RemoveStealth(); pCaster->RemoveInvisibility(); pCaster->m_AuraInterface.RemoveAllAurasByNameHash(SPELL_HASH_ICE_BLOCK, false); pCaster->m_AuraInterface.RemoveAllAurasByNameHash(SPELL_HASH_DIVINE_SHIELD, false); pCaster->m_AuraInterface.RemoveAllAurasByNameHash(SPELL_HASH_BLESSING_OF_PROTECTION, false); } } }
void AuraInterface::SaveAuras(stringstream& ss) { for(uint32 x = 0; x < MAX_AURAS; x++) // Crow: Changed to max auras in r1432, since we skip passive auras. { if(m_auras.find(x) != m_auras.end()) { Aura* aur = m_auras.at(x); // skipped spells due to bugs switch(aur->m_spellProto->Id) { case 642: case 1020: // Divine Shield case 11129: // Combustion case 12043: // Presence of mind case 16188: // Natures Swiftness case 17116: // Natures Swiftness case 23333: // WSG case 23335: // WSG case 28682: // Combustion proc case 31665: // Master of Subtlety (buff) case 32724: // Gold Team case 32725: // Green Team case 32727: // Arena Preparation case 32728: // Arena Preparation case 32071: // Hellfire Superority case 32049: // Hellfire Superority case 34936: // Backlash case 35076: // Blessing of A'dal case 35774: // Gold Team case 35775: // Green Team case 44521: // Preparation? case 44683: // Team A case 44684: // Team B case 45438: // Ice Block case 48418: // Master Shapeshifter Damage (buff) case 48420: // Master Shapeshifter Critical Strike (buff) case 48421: // Master Shapeshifter Spell Damage (buff) case 48422: // Master Shapeshifter Healing (buff) continue; break; } bool stop = false; for(uint32 i = 0; i < 3; i++) { if(!stop) { if((aur->m_spellProto->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA && aur->GetCasterGUID() != m_Unit->GetGUID()) || aur->m_spellProto->Effect[i] == SPELL_EFFECT_APPLY_AURA_128 || aur->m_spellProto->Effect[i] == SPELL_EFFECT_ADD_FARSIGHT) { stop = true; break; } } } if(stop) continue; // We are going to cast passive spells anyway on login so no need to save auras for them if( aur->IsPassive() || aur->m_spellProto->c_is_flags & SPELL_FLAG_IS_EXPIREING_WITH_PET || aur->m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_ON_STAND_UP ) continue; // To prevent food/drink bug ss << aur->GetSpellId() << "," << aur->GetTimeLeft() << ","; } } }