*Fix raise dead spell - original patch by Astellar, thanks for some help in conversion for Azrael

*Correctly apply spell cooldown for spells with cooldown starting after pet unsummon.

--HG--
branch : trunk
This commit is contained in:
QAston
2009-06-18 14:17:11 +02:00
parent 56620e0962
commit 30d0b2ed5f
7 changed files with 134 additions and 23 deletions

View File

@@ -259,6 +259,21 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
CharacterDatabase.CommitTransaction();
}
// Send fake summon spell cast - this is needed for correct cooldown application for spells
// Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside
// TODO: pets should be summoned from real cast instead of just faking it?
if (GetUInt32Value(UNIT_CREATED_BY_SPELL))
{
WorldPacket data(SMSG_SPELL_GO, (8+8+4+4+2));
data.append(owner->GetPackGUID());
data.append(owner->GetPackGUID());
data << uint8(0);
data << uint32(GetUInt32Value(UNIT_CREATED_BY_SPELL));
data << uint32(256); // CAST_FLAG_UNKNOWN3
data << uint32(0);
SendMessageToSet(&data, true);
}
owner->SetMinion(this, true);
map->Add((Creature*)this);
@@ -766,6 +781,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
return true;
}
// TODO: Move stat mods code to pet passive auras
bool Guardian::InitStatsForLevel(uint32 petlevel)
{
CreatureInfo const *cinfo = GetCreatureInfo();
@@ -949,7 +965,6 @@ bool Guardian::InitStatsForLevel(uint32 petlevel)
SetHealth(GetMaxHealth());
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
return true;
}

View File

@@ -2152,8 +2152,8 @@ void Spell::SetTargetMap(uint32 i, uint32 cur)
radius = GetSpellRadius(m_spellInfo, i, true);
targetType = SPELL_TARGETS_ALLY;
break;
case TARGET_UNIT_AREA_ENTRY_SRC:
case TARGET_UNIT_AREA_ENTRY_DST:
case TARGET_UNIT_AREA_ENTRY_SRC:
case TARGET_UNIT_CONE_ENTRY: // fix me
radius = GetSpellRadius(m_spellInfo, i, IsPositiveSpell(m_spellInfo->Id));
targetType = SPELL_TARGETS_ENTRY;
@@ -2175,14 +2175,36 @@ void Spell::SetTargetMap(uint32 i, uint32 cur)
SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
if(lower == upper)
{
sLog.outDebug("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry());
// Custom entries
// TODO: move these to sql
switch (m_spellInfo->Id)
{
case 46584: // Raise Dead
{
// TODO: change visual of corpses which gave ghoul?
// Allow corpses to be ghouled only once?
m_targets.m_targetMask &= ~TARGET_FLAG_DEST_LOCATION;
WorldObject* result = FindCorpseUsing<MaNGOS::RaiseDeadObjectCheck> ();
if(result)
{
switch(result->GetTypeId())
{
case TYPEID_UNIT:
m_targets.setDestination(result);
}
}
break;
}
default:
sLog.outDebug("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry());
if(m_spellInfo->Effect[i] == SPELL_EFFECT_TELEPORT_UNITS)
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, 0);
else if(IsPositiveEffect(m_spellInfo->Id, i))
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY);
else
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY);
if(m_spellInfo->Effect[i] == SPELL_EFFECT_TELEPORT_UNITS)
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, 0);
else if(IsPositiveEffect(m_spellInfo->Id, i))
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY);
else
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY);
}
}
// let it be done in one check?
else
@@ -2448,6 +2470,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura
triggeredByAura->GetParentAura()->SetAuraDuration(0);
}
SendCastResult(result);
finish(false);
return;
}

View File

@@ -6924,9 +6924,6 @@ void AuraEffect::PeriodicDummyTick()
caster->CastCustomSpell(m_target, 52212, &m_amount, NULL, NULL, true, 0, this);
return;
}
// Raise Dead
// if (spell->SpellFamilyFlags & 0x0000000000001000LL)
// return;
// Chains of Ice
if (spell->SpellFamilyFlags[1] & 0x00004000)
{

View File

@@ -703,6 +703,8 @@ void Spell::EffectDummy(uint32 i)
uint32 spell_id = 0;
int32 bp = 0;
bool triggered = true;
SpellCastTargets targets;
// selection by spell family
switch(m_spellInfo->SpellFamilyName)
@@ -1908,17 +1910,52 @@ void Spell::EffectDummy(uint32 i)
}
return;
}
// Hungering Cold
if (m_spellInfo->SpellFamilyFlags[1] & 0x1000)
{
unitTarget->CastSpell(m_caster, 51209, true);
return;
}
// Death Grip
if(m_spellInfo->Id == 49560)
{
unitTarget->CastSpell(m_caster, damage, true);
return;
}
// Hungering Cold
if (m_spellInfo->SpellFamilyFlags[1] & 0x1000)
else if(m_spellInfo->Id == 46584) // Raise dead
{
unitTarget->CastSpell(m_caster, 51209, true);
return;
if ( m_caster->GetTypeId() != TYPEID_PLAYER)
return;
// Do we have talent Master of Ghouls?
if(m_caster->HasAura(52143))
// summon as pet
bp = 52150;
else
// or guardian
bp = 46585;
if (m_targets.HasDst())
{
targets.setDestination(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
}
else
{
targets.setDestination(m_caster);
// Corpse not found - take reagents ( only not triggered cast can take them)
triggered = false;
}
// Remove cooldown - summon spellls have category
((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true);
spell_id=48289;
}
// Raise dead - take reagents and trigger summon spells
else if (m_spellInfo->Id ==48289)
{
if (m_targets.HasDst())
targets.setDestination(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
spell_id = m_currentBasePoints[0];
}
break;
}
@@ -1934,10 +1971,9 @@ void Spell::EffectDummy(uint32 i)
return;
}
Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true);
if(bp) spell->m_currentBasePoints[0] = bp;
SpellCastTargets targets;
targets.setUnitTarget(unitTarget);
Spell* spell = new Spell(m_caster, spellInfo, triggered, m_originalCasterGUID, NULL, true);
if(bp) spell->m_currentBasePoints[0] = bp;
spell->prepare(&targets);
}
@@ -5379,6 +5415,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
m_caster->CastSpell(unitTarget, 55095, true);
}
}
break;
}
}

View File

@@ -387,13 +387,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field
SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field
Pet *pet = GetPet(); //update pet's AP
//automatically update weapon damage after attack power modification
if(ranged)
{
UpdateDamagePhysical(RANGED_ATTACK);
Pet *pet = GetPet(); //update pet's AP
if(pet)
if(pet && pet->isHunterPet()) // At ranged attack change for hunter pet
pet->UpdateAttackPowerAndDamage();
}
else
@@ -403,6 +402,9 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
UpdateDamagePhysical(OFF_ATTACK);
if(getClass() == CLASS_SHAMAN) // mental quickness
UpdateSpellDamageAndHealingBonus();
if(pet && pet->IsPetGhoul()) // At ranged attack change for hunter pet
pet->UpdateAttackPowerAndDamage();
}
}
@@ -952,6 +954,11 @@ bool Guardian::UpdateStats(Stats stat)
if(owner->getClass() == CLASS_WARLOCK || owner->getClass() == CLASS_MAGE)
value += float(owner->GetStat(stat)) * 0.3f;
}
else if ( stat == STAT_STRENGTH )
{
if (IsPetGhoul())
value += float(owner->GetStat(stat)) * 0.3f;
}
SetStat(stat, int32(value));
@@ -1089,6 +1096,11 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f;
SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f));
}
else if (IsPetGhoul()) //ghouls benefit from deathknight's attack power (may be summon pet or not)
{
bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.22f;
SetBonusDamage( int32(owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.1287f));
}
//demons benefit from warlocks shadow or fire damage
else if(isPet())
{

View File

@@ -54,6 +54,7 @@ class Minion : public TempSummon
void InitSummon();
void RemoveFromWorld();
Unit *GetOwner() { return m_owner; }
bool IsPetGhoul() const {return GetEntry() == 26125;} // Ghoul may be guardian or pet
protected:
Unit * const m_owner;
};

View File

@@ -1821,7 +1821,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEnt
// Apply Player CR_ARMOR_PENETRATION rating
if (GetTypeId()==TYPEID_PLAYER)
armor *= 1.0f - ((Player*)this)->GetRatingBonusValue(CR_ARMOR_PENETRATION) / 100.0f;
armor *= 1.0f - (((Player*)this)->GetRatingBonusValue(CR_ARMOR_PENETRATION) / 100.0f);
if (armor < 0.0f) armor=0.0f;
@@ -8685,6 +8685,22 @@ void Unit::SetMinion(Minion *minion, bool apply)
if(GetTypeId() == TYPEID_PLAYER && minion->HasSummonMask(SUMMON_MASK_PET))
for(int i = 0; i < MAX_MOVE_TYPE; ++i)
minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
// Ghoul pets have energy instead of mana (is anywhere better place for this code?)
if (minion->IsPetGhoul())
{
minion->setPowerType(POWER_ENERGY);
}
if (GetTypeId() == TYPEID_PLAYER)
{
// Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
SpellEntry const *spellInfo = sSpellStore.LookupEntry(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
if (spellInfo && (spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE))
{
((Player*)this)->AddSpellAndCategoryCooldowns(spellInfo, 0, NULL ,true);
}
}
}
else
{
@@ -8702,6 +8718,16 @@ void Unit::SetMinion(Minion *minion, bool apply)
SetPetGUID(0);
}
if (GetTypeId() == TYPEID_PLAYER)
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
// Remove infinity cooldown
if (spellInfo && (spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE))
{
((Player*)this)->SendCooldownEvent(spellInfo);
}
}
//if(minion->HasSummonMask(SUMMON_MASK_GUARDIAN))
{
if(RemoveUInt64Value(UNIT_FIELD_SUMMON, minion->GetGUID()))