From d30c811d9e6ebf456604f3707cd65a55c40b2546 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Tue, 21 Apr 2020 15:28:17 +0200 Subject: [PATCH] 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 --- src/server/game/AI/CoreAI/PetAI.cpp | 2 +- src/server/game/Conditions/ConditionMgr.cpp | 2 +- .../game/Entities/Creature/Creature.cpp | 2 +- .../Entities/Creature/TemporarySummon.cpp | 58 +++-- src/server/game/Entities/Object/Object.cpp | 24 +- src/server/game/Entities/Pet/Pet.cpp | 20 +- src/server/game/Entities/Player/Player.cpp | 2 +- src/server/game/Entities/Totem/Totem.cpp | 3 + src/server/game/Entities/Unit/Unit.cpp | 35 ++- src/server/game/Entities/Unit/Unit.h | 1 + src/server/game/Handlers/PetHandler.cpp | 4 +- src/server/game/Maps/Map.h | 2 +- src/server/game/Spells/Spell.h | 1 - src/server/game/Spells/SpellEffects.cpp | 242 ++++-------------- .../the_scarlet_enclave_chapter_1.cpp | 2 +- .../DragonSoul/boss_madness_of_deathwing.cpp | 2 +- src/server/scripts/Pet/pet_dk.cpp | 2 +- src/server/scripts/Spells/spell_dk.cpp | 4 +- src/server/scripts/Spells/spell_generic.cpp | 13 +- 19 files changed, 145 insertions(+), 276 deletions(-) diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index c6162e36a5c..f3401d8398f 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -597,7 +597,7 @@ bool PetAI::CanAttack(Unit* target) void PetAI::ReceiveEmote(Player* player, uint32 emote) { - if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID()) + if (me->GetOwnerOrCreatorGUID() && me->GetOwnerOrCreatorGUID() == player->GetGUID()) switch (emote) { case TEXT_EMOTE_COWER: diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index f372408e7c3..ed6d30f7812 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -358,7 +358,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const condMeets = unit->IsInRaidWith(toUnit); break; case RELATION_OWNED_BY: - condMeets = unit->GetOwnerGUID() == toUnit->GetGUID(); + condMeets = unit->GetOwnerOrCreatorGUID() == toUnit->GetGUID(); break; case RELATION_PASSENGER_OF: condMeets = unit->IsOnVehicle(toUnit); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index bae24fcf593..1f966e602a5 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2047,7 +2047,7 @@ void Creature::LoadTemplateImmunities() ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, 1 << i, false); // don't inherit immunities for hunter pets - if (GetOwnerGUID().IsPlayer() && IsHunterPet()) + if (GetOwnerOrCreatorGUID().IsPlayer() && IsHunterPet()) return; if (uint32 mask = GetCreatureTemplate()->MechanicImmuneMask) diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp index d9f33d3bb33..ba7fd7d8d68 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.cpp +++ b/src/server/game/Entities/Creature/TemporarySummon.cpp @@ -194,40 +194,38 @@ void TempSummon::InitStats(uint32 duration) owner->m_SummonSlot[slot] = GetGUID(); } - if (m_Properties->Control == SUMMON_CATEGORY_ALLY) + if (m_Properties->Control == SUMMON_CATEGORY_ALLY || m_Properties->Control == SUMMON_CATEGORY_PET) { if (!m_Properties->Faction) SetFaction(owner->GetFaction()); - switch (SummonTitle(m_Properties->Title)) - { + // Creator guid is always set for allied summons + SetCreatorGUID(owner->GetGUID()); - case SummonTitle::Pet: - case SummonTitle::Guardian: - case SummonTitle::Runeblade: - case SummonTitle::Minion: - case SummonTitle::Vehicle: - case SummonTitle::Mount: - case SummonTitle::Lightwell: - case SummonTitle::Totem: - case SummonTitle::Companion: - break; - default: - SetOwnerGUID(owner->GetGUID()); - break; + // Summons inherit their player summoner's guild data + if (owner && (owner->IsPlayer() || owner->IsTotem())) + { + ObjectGuid guildGUID = owner->GetGuidValue(OBJECT_FIELD_DATA); + if (guildGUID) + { + SetGuidValue(OBJECT_FIELD_DATA, owner->GetGuidValue(OBJECT_FIELD_DATA)); + SetUInt16Value(OBJECT_FIELD_TYPE, 1, 1); // Has guild data + } } } + + if (owner->IsTotem()) + owner->m_Controlled.insert(this); } - // If property has a faction defined, use it. Otherwise fallback to owner faction whe summon is a vehicle + // If property has a faction defined, use it. if (m_Properties->Faction) SetFaction(m_Properties->Faction); } void TempSummon::InitSummon() { - Unit* owner = GetSummoner(); - if (owner) + if (Unit* owner = GetSummoner()) { if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled) owner->ToCreature()->AI()->JustSummoned(this); @@ -265,8 +263,14 @@ void TempSummon::UnSummon(uint32 msTime) } Unit* owner = GetSummoner(); - if (owner && owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled) - owner->ToCreature()->AI()->SummonedCreatureDespawn(this); + if (owner) + { + if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled) + owner->ToCreature()->AI()->SummonedCreatureDespawn(this); + + if (owner->IsTotem()) + owner->m_Controlled.erase(this); + } AddObjectToRemoveList(); } @@ -314,13 +318,11 @@ Minion::Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorl void Minion::InitStats(uint32 duration) { TempSummon::InitStats(duration); - SetReactState(REACT_PASSIVE); - SetCreatorGUID(GetOwner()->GetGUID()); - SetFaction(GetOwner()->GetFaction()); - - GetOwner()->SetMinion(this, true); + // Only controlable guardians and companions get a owner guid + if (HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) || (m_Properties && m_Properties->Title == AsUnderlyingType(SummonTitle::Companion))) + GetOwner()->SetMinion(this, true); } void Minion::RemoveFromWorld() @@ -328,7 +330,9 @@ void Minion::RemoveFromWorld() if (!IsInWorld()) return; - GetOwner()->SetMinion(this, false); + if (HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN) || (m_Properties && m_Properties->Title == AsUnderlyingType(SummonTitle::Companion))) + GetOwner()->SetMinion(this, false); + TempSummon::RemoveFromWorld(); } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 3ada098954b..11d8fd8b522 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -739,7 +739,7 @@ uint32 Object::GetUpdateFieldData(Player const* target, uint32*& flags) const { Player* plr = ToUnit()->GetCharmerOrOwnerPlayerOrPlayerItself(); flags = UnitUpdateFieldFlags; - if (ToUnit()->GetOwnerGUID() == target->GetGUID()) + if (ToUnit()->GetOwnerOrCreatorGUID() == target->GetGUID()) visibleFlag |= UF_FLAG_OWNER; if (HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO)) @@ -2036,7 +2036,7 @@ void WorldObject::AddObjectToRemoveList() map->AddObjectToRemoveList(this); } -TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= NULL*/, uint32 duration /*= 0*/, Unit* summoner /*= NULL*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, bool visibleBySummonerOnly /*= false*/) +TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, Unit* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, bool visibleBySummonerOnly /*= false*/, uint32 health /*= 0*/) { uint32 mask = UNIT_MASK_SUMMON; if (properties) @@ -2077,7 +2077,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert default: if (properties->Flags & 512) // Mirror Image, Summon Gargoyle mask = UNIT_MASK_GUARDIAN; - break; + break; } break; } @@ -2106,12 +2106,14 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert break; } + // Create creature entity if (!summon->Create(GenerateLowGuid(), this, entry, pos, nullptr, vehId, true)) { delete summon; return nullptr; } + // Add summon to transport if summoner is on a transport as well if (summon->GetTransGUID().IsEmpty() && summoner) { if (Transport* transport = summoner->GetTransport()) @@ -2129,11 +2131,27 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert if (summoner) PhasingHandler::InheritPhaseShift(summon, summoner); + // Initialize tempsummon fields summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId); summon->SetHomePosition(pos); summon->InitStats(duration); summon->SetVisibleBySummonerOnly(visibleBySummonerOnly); + // Handle health argument (totem health via base points) + if (health) + { + summon->SetMaxHealth(health); + summon->SetHealth(health); + } + + // Initialize guardian stats + if (summon->HasUnitTypeMask(UNIT_MASK_GUARDIAN) && summoner) + { + ((Guardian*)summon)->UpdateAllStats(); + summon->SetPower(POWER_MANA, summon->GetMaxPower(POWER_MANA)); + summon->SetFullHealth(); + } + AddToMap(summon->ToCreature()); summon->InitSummon(); diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 1a77bb1980f..b989ed7b3e0 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -384,7 +384,7 @@ void Pet::SavePetToDB(PetSaveMode mode) return; // not save not player pets - if (!GetOwnerGUID().IsPlayer()) + if (!GetOwnerOrCreatorGUID().IsPlayer()) return; uint32 curhealth = GetHealth(); @@ -423,7 +423,7 @@ void Pet::SavePetToDB(PetSaveMode mode) // whole pet is saved to DB if (mode >= PET_SAVE_CURRENT_STATE) { - ObjectGuid::LowType ownerLowGUID = GetOwnerGUID().GetCounter(); + ObjectGuid::LowType ownerLowGUID = GetOwnerOrCreatorGUID().GetCounter(); std::string name = m_name; CharacterDatabase.EscapeString(name); trans = CharacterDatabase.BeginTransaction(); @@ -925,16 +925,22 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) } case ENTRY_EARTH_ELEMENTAL: { - SetCreateHealth(100 + 120 * petlevel); - SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4))); - SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel + (petlevel / 4))); + if (Unit* owner = m_owner->GetOwner()) + SetCreateHealth(owner->CountPctFromMaxHealth(75)); + + SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel)); + SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel)); break; } case ENTRY_FIRE_ELEMENTAL: { - SetCreateHealth(m_owner->CountPctFromMaxHealth(75)); + if (Unit* owner = m_owner->GetOwner()) + { + SetCreateHealth(owner->CountPctFromMaxHealth(75)); + SetBonusDamage(int32(owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) * 0.5f)); + } + SetCreateMana(28 + 10 * petlevel); - SetBonusDamage(int32(GetOwner()->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) * 0.5f)); SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel * 4 - petlevel)); SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, float(petlevel * 4 + petlevel)); break; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index eecd344d548..a8463a0da1f 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -21018,7 +21018,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) m_temporaryUnsummonedPetNumber = 0; } - if (!pet || pet->GetOwnerGUID() != GetGUID()) + if (!pet || pet->GetOwnerOrCreatorGUID() != GetGUID()) return; pet->CombatStop(); diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index e2204ff28cc..5cbbb88bf61 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -135,6 +135,9 @@ void Totem::UnSummon(uint32 msTime) } } + // Despawn elementals + RemoveAllControlled(); + // any totem unsummon look like as totem kill, req. for proper animation if (IsAlive()) setDeathState(DEAD); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 60bf5d6a122..232576fc800 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -904,7 +904,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (victim->GetTypeId() == TYPEID_PLAYER && victim->ToPlayer()->duel && damage >= (health-1)) { // prevent kill only if killed in duel and killed by opponent or opponent controlled creature - if (victim->ToPlayer()->duel->opponent == this || victim->ToPlayer()->duel->opponent->GetGUID() == GetOwnerGUID()) + if (victim->ToPlayer()->duel->opponent == this || victim->ToPlayer()->duel->opponent->GetGUID() == GetOwnerOrCreatorGUID()) damage = health - 1; duel_hasEnded = true; @@ -5965,8 +5965,9 @@ void Unit::SetOwnerGUID(ObjectGuid owner) Unit* Unit::GetOwner() const { - if (ObjectGuid ownerGUID = GetOwnerGUID()) - return ObjectAccessor::GetUnit(*this, ownerGUID); + // Fall back to creator guid of owner guid is not available + if (ObjectGuid guid = GetOwnerOrCreatorGUID()) + return ObjectAccessor::GetUnit(*this, guid); return nullptr; } @@ -6108,11 +6109,7 @@ void Unit::SetMinion(Minion* minion, bool apply) } if (minion->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN)) - { - if (AddGuidValue(UNIT_FIELD_SUMMON, minion->GetGUID())) - { - } - } + AddGuidValue(UNIT_FIELD_SUMMON, minion->GetGUID()); if (minion->m_Properties && SummonTitle(minion->m_Properties->Title) == SummonTitle::Companion) SetCritterGUID(minion->GetGUID()); @@ -6306,7 +6303,7 @@ void Unit::SetCharm(Unit* charm, bool apply) if (charm->GetTypeId() == TYPEID_PLAYER || !charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_MINION) - || charm->GetOwnerGUID() != GetGUID()) + || charm->GetOwnerOrCreatorGUID() != GetGUID()) { m_Controlled.erase(charm); } @@ -6438,7 +6435,7 @@ void Unit::RemoveAllControlled() m_Controlled.erase(m_Controlled.begin()); if (target->GetCharmerGUID() == GetGUID()) target->RemoveCharmAuras(); - else if (target->GetOwnerGUID() == GetGUID() && target->IsSummon()) + else if (target->GetOwnerOrCreatorGUID() == GetGUID() && target->IsSummon()) target->ToTempSummon()->UnSummon(); else TC_LOG_ERROR("entities.unit", "Unit %u is trying to release unit %u which is neither charmed nor owned by it", GetEntry(), target->GetEntry()); @@ -7060,7 +7057,7 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto { //! Mobs can't crit with spells. Player Totems can //! Fire Elemental (from totem) can too - but this part is a hack and needs more research - if (GetGUID().IsCreatureOrVehicle() && !(IsTotem() && GetOwnerGUID().IsPlayer()) && GetEntry() != 15438) + if (GetGUID().IsCreatureOrVehicle() && !(IsTotem() && GetOwnerOrCreatorGUID().IsPlayer()) && GetEntry() != 15438) return 0.0f; // not critting spell @@ -9079,7 +9076,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype) if (float minSpeedMod = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MINIMUM_SPEED)) { float baseMinSpeed = 1.0f; - if (!GetOwnerGUID().IsPlayer() && !IsHunterPet() && GetTypeId() == TYPEID_UNIT) + if (!GetOwnerOrCreatorGUID().IsPlayer() && !IsHunterPet() && GetTypeId() == TYPEID_UNIT) baseMinSpeed = ToCreature()->GetCreatureTemplate()->speed_run; float min_speed = CalculatePct(baseMinSpeed, minSpeedMod); @@ -9228,7 +9225,7 @@ bool Unit::CanHaveThreatList(bool skipAliveCheck) const // return false; // summons can not have a threat list, unless they are controlled by a creature - if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Pet*)this)->GetOwnerGUID().IsPlayer()) + if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Pet*)this)->GetOwnerOrCreatorGUID().IsPlayer()) return false; return true; @@ -10051,7 +10048,7 @@ float Unit::GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange typ bool Unit::CanFreeMove() const { return !HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | - UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && GetOwnerGUID().IsEmpty(); + UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED) && GetOwnerOrCreatorGUID().IsEmpty(); } void Unit::SetLevel(uint8 lvl) @@ -10964,7 +10961,7 @@ SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const ObjectGuid Unit::GetCharmerOrOwnerGUID() const { - return GetCharmerGUID() ? GetCharmerGUID() : GetOwnerGUID(); + return GetCharmerGUID() ? GetCharmerGUID() : GetOwnerOrCreatorGUID(); } ObjectGuid Unit::GetCharmerOrOwnerOrOwnGUID() const @@ -11650,7 +11647,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) player = creature->GetLootRecipient(); // Exploit fix - if (creature && creature->IsPet() && creature->GetOwnerGUID().IsPlayer()) + if (creature && creature->IsPet() && creature->GetOwnerOrCreatorGUID().IsPlayer()) isRewardAllowed = false; // Reward player, his pets, and group/raid members @@ -13307,7 +13304,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) Unit* caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this; Unit* target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this; - ObjectGuid origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID(); + ObjectGuid origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerOrCreatorGUID() : clicker->GetGUID(); SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId); // if (!spellEntry) should be checked at npc_spellclick load @@ -14056,7 +14053,7 @@ void Unit::OutDebugInfo() const { TC_LOG_ERROR("entities.unit", "Unit::OutDebugInfo"); TC_LOG_DEBUG("entities.unit", "%s name %s", GetGUID().ToString().c_str(), GetName().c_str()); - TC_LOG_DEBUG("entities.unit", "Owner %s, Minion %s, Charmer %s, Charmed %s", GetOwnerGUID().ToString().c_str(), GetMinionGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str(), GetCharmGUID().ToString().c_str()); + TC_LOG_DEBUG("entities.unit", "Owner %s, Minion %s, Charmer %s, Charmed %s", GetOwnerOrCreatorGUID().ToString().c_str(), GetMinionGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str(), GetCharmGUID().ToString().c_str()); TC_LOG_DEBUG("entities.unit", "In world %u, unit type mask %u", (uint32)(IsInWorld() ? 1 : 0), m_unitTypeMask); if (IsInWorld()) TC_LOG_DEBUG("entities.unit", "Mapid %u", GetMapId()); @@ -14492,7 +14489,7 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) updateMask.SetCount(valCount); Player* plr = GetCharmerOrOwnerPlayerOrPlayerItself(); - if (GetOwnerGUID() == target->GetGUID()) + if (GetOwnerOrCreatorGUID() == target->GetGUID()) visibleFlag |= UF_FLAG_OWNER; if (HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO)) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index a3262474bec..c222a450703 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1376,6 +1376,7 @@ class TC_GAME_API Unit : public WorldObject ObjectGuid GetPetGUID() const { return m_SummonSlot[SUMMON_SLOT_PET]; } void SetCritterGUID(ObjectGuid guid) { SetGuidValue(UNIT_FIELD_CRITTER, guid); } ObjectGuid GetCritterGUID() const { return GetGuidValue(UNIT_FIELD_CRITTER); } + ObjectGuid GetOwnerOrCreatorGUID() const { return GetOwnerGUID() ? GetOwnerGUID() : GetCreatorGUID(); } bool IsControlledByPlayer() const { return m_ControlledByPlayer; } ObjectGuid GetCharmerOrOwnerGUID() const; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 40ba6ecc1d0..32241b5cb41 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -254,7 +254,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) if (pet->GetCharmerGUID() == GetPlayer()->GetGUID()) _player->StopCastingCharm(); - else if (pet->GetOwnerGUID() == GetPlayer()->GetGUID()) + else if (pet->GetOwnerOrCreatorGUID() == GetPlayer()->GetGUID()) { ASSERT(pet->GetTypeId() == TYPEID_UNIT); if (pet->IsPet()) @@ -622,7 +622,7 @@ void WorldSession::HandlePetRename(WorldPacket& recvData) // check it! if (!pet || !pet->IsPet() || !((Pet*)pet)->IsHunterPet() || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_PET_FLAGS, UNIT_CAN_BE_RENAMED) || - pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) + pet->GetOwnerOrCreatorGUID() != _player->GetGUID() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name, GetSessionDbcLocale()); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 3974427c363..de9f3256ff7 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -515,7 +515,7 @@ class TC_GAME_API Map : public GridRefManager void UpdateIteratorBack(Player* player); - TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = NULL, uint32 duration = 0, Unit* summoner = NULL, uint32 spellId = 0, uint32 vehId = 0, bool visibleOnlyBySummoner = false); + TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = nullptr, uint32 duration = 0, Unit* summoner = nullptr, uint32 spellId = 0, uint32 vehId = 0, bool visibleOnlyBySummoner = false, uint32 health = 0); void SummonCreatureGroup(uint8 group, std::list* list = nullptr); Player* GetPlayer(ObjectGuid const& guid); AreaTrigger* GetAreaTrigger(ObjectGuid const& guid); diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index d25cbe517e3..421cefb8b93 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -749,7 +749,6 @@ class TC_GAME_API Spell HitTriggerSpellList m_hitTriggerSpells; // effect helpers - void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons, bool visibleBySummonerOnly = false); void CalculateJumpSpeeds(uint8 i, float dist, float & speedxy, float & speedz); void UpdateSpellCastDataTargets(WorldPackets::Spells::SpellHitInfo& data); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index a46e4197f9c..dc175d74355 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -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) diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp index a48c2f0e3e2..ee92ffb63b9 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/the_scarlet_enclave_chapter_1.cpp @@ -549,7 +549,7 @@ public: { if (m_bIsDuelInProgress && pDoneBy->IsControlledByPlayer()) { - if (pDoneBy->GetGUID() != m_uiDuelerGUID && pDoneBy->GetOwnerGUID() != m_uiDuelerGUID) // other players cannot help + if (pDoneBy->GetGUID() != m_uiDuelerGUID && pDoneBy->GetOwnerOrCreatorGUID() != m_uiDuelerGUID) // other players cannot help uiDamage = 0; else if (uiDamage >= me->GetHealth()) { diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DragonSoul/boss_madness_of_deathwing.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/DragonSoul/boss_madness_of_deathwing.cpp index 6203efc6844..2b284e4fa3e 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/DragonSoul/boss_madness_of_deathwing.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/DragonSoul/boss_madness_of_deathwing.cpp @@ -1672,7 +1672,7 @@ class spell_madness_of_deathwing_presence_of_the_aspects : public SpellScript if (target->IsCreature()) if (TempSummon* summon = target->ToUnit()->ToTempSummon()) - return !summon->GetOwnerGUID().IsPlayer(); + return !summon->GetOwnerOrCreatorGUID().IsPlayer(); return true; }); diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp index f9734d9cbbd..dc197a520e8 100644 --- a/src/server/scripts/Pet/pet_dk.cpp +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -48,7 +48,7 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript void InitializeAI() override { CasterAI::InitializeAI(); - ObjectGuid ownerGuid = me->GetOwnerGUID(); + ObjectGuid ownerGuid = me->GetOwnerOrCreatorGUID(); if (!ownerGuid) return; diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 1e05ea10616..e3bcaee3f87 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -420,7 +420,7 @@ class spell_dk_death_pact : public SpellScript for (Unit::ControlList::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr) if (Creature* undeadPet = (*itr)->ToCreature()) if (undeadPet->IsAlive() && - undeadPet->GetOwnerGUID() == player->GetGUID() && + undeadPet->GetOwnerOrCreatorGUID() == player->GetGUID() && undeadPet->GetCreatureType() == CREATURE_TYPE_UNDEAD && undeadPet->IsWithinDist(player, 100.0f, false)) return SPELL_CAST_OK; @@ -435,7 +435,7 @@ class spell_dk_death_pact : public SpellScript { if (Unit* unit = (*itr)->ToUnit()) { - if (unit->GetOwnerGUID() == GetCaster()->GetGUID() && unit->GetCreatureType() == CREATURE_TYPE_UNDEAD) + if (unit->GetOwnerOrCreatorGUID() == GetCaster()->GetGUID() && unit->GetCreatureType() == CREATURE_TYPE_UNDEAD) { target = unit; break; diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index a71d0147570..0ff1fbe63d6 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -5248,16 +5248,11 @@ class spell_gen_guild_battle_standard_buff : public SpellScript void FilterTargets(std::list& targets) { - TempSummon* summon = GetCaster()->ToTempSummon(); - Unit* summoner = summon->GetSummoner(); - if (Player* player = summoner->ToPlayer()) + ObjectGuid guildGuid = GetCaster()->GetGuidValue(OBJECT_FIELD_DATA); + targets.remove_if([guildGuid](WorldObject* target)->bool { - uint32 guildId = player->GetGuildId(); - targets.remove_if([guildId](WorldObject* target)->bool - { - return !target->IsPlayer() || target->ToPlayer()->GetGuildId() != guildId; - }); - } + return !target->IsPlayer() || target->ToPlayer()->GetGuidValue(OBJECT_FIELD_DATA) != guildGuid; + }); } void Register() override