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