Core/Creatures: reworked tempoary summon creation
* all stats and values will now be set before summons are getting added to map * cleaned up summon spell effect handler to reduce duplicade code * summoner guids will no longer be set for every minion and correctly handle assigning creator guids instead. These values will serve as fallback guid if there is no summoner guid * friendly tempsummons will now inherit the guild data of their player and pass them on to further allied summons. This fixes guild specific visuals for creatures such as Guild Battle Standards and Guild Heralds. Todo: check for regressions
This commit is contained in:
1 parent
bc1a69caa3
commit
d30c811d9e
19 files changed
+145
-276
No files matched your search
@@ -1849,8 +1849,6 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
if (Player* modOwner = m_originalCaster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
|
||||
|
||||
TempSummon* summon = nullptr;
|
||||
|
||||
// determine how many units should be summoned
|
||||
uint32 numSummons = std::max(1, damage);
|
||||
|
||||
@@ -1865,129 +1863,46 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
if ((m_spellInfo->HasAttribute(SPELL_ATTR8_UNK21) && !m_spellInfo->HasAttribute(SPELL_ATTR8_UNK13)) || m_spellInfo->HasAttribute(SPELL_ATTR10_UNK6))
|
||||
numSummons = 1;
|
||||
|
||||
switch (properties->Control)
|
||||
// Some totems are being summoned with a certain amount of health
|
||||
uint32 health = (properties->Flags & SUMMON_PROP_FLAG_TOTEM) != 0 && damage ? damage : 0;
|
||||
|
||||
if (numSummons == 1)
|
||||
{
|
||||
case SUMMON_CATEGORY_WILD:
|
||||
case SUMMON_CATEGORY_ALLY:
|
||||
case SUMMON_CATEGORY_UNK:
|
||||
if (properties->Flags & 512)
|
||||
{
|
||||
SummonGuardian(effIndex, entry, properties, numSummons, personalSpawn);
|
||||
break;
|
||||
}
|
||||
switch (SummonTitle(properties->Title))
|
||||
{
|
||||
case SummonTitle::Pet:
|
||||
case SummonTitle::Guardian:
|
||||
case SummonTitle::Runeblade:
|
||||
case SummonTitle::Minion:
|
||||
SummonGuardian(effIndex, entry, properties, numSummons, personalSpawn);
|
||||
break;
|
||||
// Summons a vehicle, but doesn't force anyone to enter it (see SUMMON_CATEGORY_VEHICLE)
|
||||
case SummonTitle::Vehicle:
|
||||
case SummonTitle::Mount:
|
||||
summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
|
||||
break;
|
||||
case SummonTitle::Lightwell:
|
||||
case SummonTitle::Totem:
|
||||
{
|
||||
summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
|
||||
if (!summon || !summon->IsTotem())
|
||||
return;
|
||||
|
||||
// Mana Tide Totem
|
||||
if (m_spellInfo->Id == 16190)
|
||||
damage = m_caster->CountPctFromMaxHealth(10);
|
||||
|
||||
if (damage) // if not spell info, DB values used
|
||||
{
|
||||
summon->SetMaxHealth(damage);
|
||||
summon->SetHealth(damage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SummonTitle::Companion:
|
||||
{
|
||||
summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
|
||||
if (!summon || !summon->HasUnitTypeMask(UNIT_MASK_MINION))
|
||||
return;
|
||||
|
||||
summon->SelectLevel(); // some summoned creaters have different from 1 DB data for level/hp
|
||||
summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureTemplate()->npcflag);
|
||||
|
||||
summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
float radius = m_spellInfo->Effects[effIndex].CalcRadius();
|
||||
|
||||
for (uint32 count = 0; count < numSummons; ++count)
|
||||
{
|
||||
Position pos;
|
||||
if (count == 0)
|
||||
pos = *destTarget;
|
||||
else
|
||||
// randomize position for multiple summons
|
||||
pos = m_caster->GetRandomPoint(*destTarget, radius);
|
||||
|
||||
summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
|
||||
if (!summon)
|
||||
continue;
|
||||
|
||||
ExecuteLogEffectSummonObject(effIndex, summon);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}//switch
|
||||
break;
|
||||
case SUMMON_CATEGORY_PET:
|
||||
SummonGuardian(effIndex, entry, properties, numSummons, personalSpawn);
|
||||
break;
|
||||
case SUMMON_CATEGORY_PUPPET:
|
||||
summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn);
|
||||
break;
|
||||
case SUMMON_CATEGORY_VEHICLE:
|
||||
// Summoning spells (usually triggered by npc_spellclick) that spawn a vehicle and that cause the clicker
|
||||
// to cast a ride vehicle spell on the summoned unit.
|
||||
summon = m_originalCaster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_caster, m_spellInfo->Id, 0, personalSpawn);
|
||||
if (!summon || !summon->IsVehicle())
|
||||
return;
|
||||
|
||||
// The spell that this effect will trigger. It has SPELL_AURA_CONTROL_VEHICLE
|
||||
uint32 spellId = VEHICLE_SPELL_RIDE_HARDCODED;
|
||||
int32 basePoints = m_spellInfo->Effects[effIndex].CalcValue();
|
||||
if (basePoints > MAX_VEHICLE_SEATS)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(basePoints);
|
||||
if (spellInfo && spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
|
||||
spellId = spellInfo->Id;
|
||||
}
|
||||
|
||||
// if we have small value, it indicates seat position
|
||||
if (basePoints > 0 && basePoints < MAX_VEHICLE_SEATS)
|
||||
m_originalCaster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, basePoints, summon, true);
|
||||
else
|
||||
m_originalCaster->CastSpell(summon, spellId, true);
|
||||
|
||||
uint32 faction = properties->Faction;
|
||||
if (!faction)
|
||||
faction = m_originalCaster->GetFaction();
|
||||
|
||||
summon->SetFaction(faction);
|
||||
break;
|
||||
}
|
||||
|
||||
if (summon)
|
||||
{
|
||||
if (entry == ENTRY_GHOUL)
|
||||
if (TempSummon* summon = m_caster->GetMap()->SummonCreature(entry, *destTarget, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn, health))
|
||||
{
|
||||
summon->CastSpell(summon, SPELL_PET_RISEN_GHOUL_SPAWN_IN, true);
|
||||
summon->CastSpell(summon, SPELL_PET_RISEN_GHOUL_SELF_STUN, true);
|
||||
}
|
||||
ExecuteLogEffectSummonObject(effIndex, summon);
|
||||
|
||||
summon->SetCreatorGUID(m_originalCaster->GetGUID());
|
||||
ExecuteLogEffectSummonObject(effIndex, summon);
|
||||
// Summoned vehicles shall be mounted right away if possible
|
||||
if (summon->IsVehicle())
|
||||
{
|
||||
// The spell that this effect will trigger. It has SPELL_AURA_CONTROL_VEHICLE
|
||||
uint32 spellId = VEHICLE_SPELL_RIDE_HARDCODED;
|
||||
int32 basePoints = m_spellInfo->Effects[effIndex].CalcValue();
|
||||
if (basePoints > MAX_VEHICLE_SEATS)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(basePoints);
|
||||
if (spellInfo && spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
|
||||
spellId = spellInfo->Id;
|
||||
}
|
||||
|
||||
// if we have small value, it indicates seat position
|
||||
if (basePoints > 0 && basePoints < MAX_VEHICLE_SEATS)
|
||||
m_originalCaster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, basePoints, summon, true);
|
||||
else
|
||||
m_originalCaster->CastSpell(summon, spellId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float radius = m_spellInfo->Effects[effIndex].CalcRadius();
|
||||
for (uint8 i = 0; i < numSummons; ++i)
|
||||
{
|
||||
// Multiple summons are summoned at random points within the destination radius
|
||||
Position pos = m_caster->GetRandomPoint(*destTarget, radius);
|
||||
if (TempSummon* summon = m_caster->GetMap()->SummonCreature(entry, pos, properties, duration, m_originalCaster, m_spellInfo->Id, 0, personalSpawn, health))
|
||||
ExecuteLogEffectSummonObject(effIndex, summon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2558,18 +2473,19 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
|
||||
if (!owner && m_originalCaster->IsTotem())
|
||||
owner = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
}
|
||||
|
||||
// SUMMON_PET SummonPet's entries are at MiscValue, HunterPetSlot at BasePoints
|
||||
uint32 petentry = (m_spellInfo->Effects[effIndex].MiscValue == 0 && m_spellInfo->Effects[effIndex].BasePoints <= PET_SLOT_LAST_ACTIVE_SLOT) ?
|
||||
m_spellInfo->Effects[effIndex].BasePoints : m_spellInfo->Effects[effIndex].MiscValue;
|
||||
|
||||
PetType petType = (m_spellInfo->Effects[effIndex].MiscValue == 0 && m_spellInfo->Effects[effIndex].BasePoints <= PET_SLOT_LAST_ACTIVE_SLOT) ?
|
||||
HUNTER_PET : SUMMON_PET;
|
||||
PetType petType = (m_spellInfo->Effects[effIndex].MiscValue == 0 && m_spellInfo->Effects[effIndex].BasePoints <= PET_SLOT_LAST_ACTIVE_SLOT) ? HUNTER_PET : SUMMON_PET;
|
||||
|
||||
// Pet is summoned by a npc
|
||||
if (!owner)
|
||||
{
|
||||
SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67);
|
||||
if (properties)
|
||||
SummonGuardian(effIndex, petentry, properties, 1);
|
||||
if (SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(67))
|
||||
if (TempSummon* summon = m_caster->GetMap()->SummonCreature(petentry, *destTarget, properties, m_spellInfo->GetDuration(), m_originalCaster, m_spellInfo->Id, false))
|
||||
ExecuteLogEffectSummonObject(effIndex, summon);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4424,7 +4340,7 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex)
|
||||
if (!unitTarget)
|
||||
return;
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER || m_caster->GetOwnerGUID().IsPlayer() || m_caster->IsHunterPet())
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER || m_caster->GetOwnerOrCreatorGUID().IsPlayer() || m_caster->IsHunterPet())
|
||||
if (Creature* creatureTarget = unitTarget->ToCreature())
|
||||
if (creatureTarget->isWorldBoss() || creatureTarget->IsDungeonBoss())
|
||||
return;
|
||||
@@ -5316,76 +5232,6 @@ void Spell::EffectGameObjectSetDestructionState(SpellEffIndex effIndex)
|
||||
gameObjTarget->SetDestructibleState(GameObjectDestructibleState(m_spellInfo->Effects[effIndex].MiscValue), player, true);
|
||||
}
|
||||
|
||||
void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numGuardians, bool visibleBySummonerOny /*= false*/)
|
||||
{
|
||||
Unit* caster = m_originalCaster;
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
if (caster->IsTotem())
|
||||
caster = caster->ToTotem()->GetOwner();
|
||||
|
||||
// in another case summon new
|
||||
uint8 level = caster->getLevel();
|
||||
|
||||
// level of pet summoned using engineering item based at engineering skill level
|
||||
if (m_CastItem && caster->GetTypeId() == TYPEID_PLAYER)
|
||||
if (ItemTemplate const* proto = m_CastItem->GetTemplate())
|
||||
if (proto->GetRequiredSkill() == SKILL_ENGINEERING)
|
||||
if (uint16 skill202 = caster->ToPlayer()->GetSkillValue(SKILL_ENGINEERING))
|
||||
level = skill202 / 5;
|
||||
|
||||
float radius = 5.0f;
|
||||
int32 duration = m_spellInfo->GetDuration();
|
||||
|
||||
if (Player* modOwner = m_originalCaster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
|
||||
|
||||
//TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
|
||||
Map* map = caster->GetMap();
|
||||
|
||||
for (uint32 count = 0; count < numGuardians; ++count)
|
||||
{
|
||||
Position pos;
|
||||
if (count == 0)
|
||||
pos = *destTarget;
|
||||
else
|
||||
// randomize position for multiple summons
|
||||
pos = m_caster->GetRandomPoint(*destTarget, radius);
|
||||
|
||||
TempSummon* summon = map->SummonCreature(entry, pos, properties, duration, caster, m_spellInfo->Id, 0, visibleBySummonerOny);
|
||||
if (!summon)
|
||||
return;
|
||||
|
||||
if (summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
|
||||
{
|
||||
((Guardian*)summon)->InitStatsForLevel(level);
|
||||
((Guardian*)summon)->UpdateAllStats();
|
||||
summon->SetPower(POWER_MANA, summon->GetMaxPower(POWER_MANA));
|
||||
summon->SetFullHealth();
|
||||
}
|
||||
|
||||
if (properties && properties->Control == SUMMON_CATEGORY_ALLY)
|
||||
summon->SetFaction(caster->GetFaction());
|
||||
|
||||
if (summon->HasUnitTypeMask(UNIT_MASK_MINION) && m_targets.HasDst())
|
||||
((Minion*)summon)->SetFollowAngle(m_caster->GetAngle(summon));
|
||||
|
||||
if (summon->GetEntry() == 27893)
|
||||
{
|
||||
if (uint32 weapon = m_caster->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID))
|
||||
{
|
||||
summon->SetDisplayId(11686); // modelid2
|
||||
summon->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, weapon);
|
||||
}
|
||||
else
|
||||
summon->SetDisplayId(1126); // modelid1
|
||||
}
|
||||
|
||||
ExecuteLogEffectSummonObject(i, summon);
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::EffectRenamePet(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
|
||||
Reference in new issue
Block a user