From 068c67b9325ad1a66b3d61176e0e0070692bf214 Mon Sep 17 00:00:00 2001 From: Charles A Edwards Date: Wed, 14 Sep 2016 13:21:23 +0100 Subject: [PATCH] Cmangos commits applied Cmangos commits applied --- src/game/ChatCommands/Level1.cpp | 2 +- src/game/ChatCommands/Level3.cpp | 2 +- src/game/Object/Pet.cpp | 32 +--- src/game/Object/Pet.h | 15 +- src/game/Object/PetAI.cpp | 235 ++++++++++++++++++------- src/game/Object/Player.cpp | 4 +- src/game/WorldHandlers/MiscHandler.cpp | 4 + src/game/WorldHandlers/PetHandler.cpp | 84 +++++---- src/game/WorldHandlers/Spell.cpp | 6 + src/game/WorldHandlers/World.cpp | 7 +- src/game/WorldHandlers/World.h | 1 + src/mangosd/mangosd.conf.dist.in | 7 + 12 files changed, 261 insertions(+), 138 deletions(-) diff --git a/src/game/ChatCommands/Level1.cpp b/src/game/ChatCommands/Level1.cpp index c679c8b5e..29cc30b1a 100644 --- a/src/game/ChatCommands/Level1.cpp +++ b/src/game/ChatCommands/Level1.cpp @@ -987,7 +987,7 @@ bool ChatHandler::HandleModifyTalentCommand(char* args) else if (((Creature*)target)->IsPet()) { Unit* owner = target->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet*)target)->IsPermanentPetFor((Player*)owner)) + if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet*)target)->isControlled()) { // check online security if (HasLowerSecurity((Player*)owner)) diff --git a/src/game/ChatCommands/Level3.cpp b/src/game/ChatCommands/Level3.cpp index bffd5b9e3..25bdad6ac 100644 --- a/src/game/ChatCommands/Level3.cpp +++ b/src/game/ChatCommands/Level3.cpp @@ -5281,7 +5281,7 @@ bool ChatHandler::HandleResetTalentsCommand(char* args) if (!*args && creature && creature->IsPet()) { Unit* owner = creature->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet*)creature)->IsPermanentPetFor((Player*)owner)) + if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet*)creature)->isControlled()) { ((Pet*)creature)->resetTalents(true); ((Player*)owner)->SendTalentsInfoData(true); diff --git a/src/game/Object/Pet.cpp b/src/game/Object/Pet.cpp index 4602c4011..6eb008d40 100644 --- a/src/game/Object/Pet.cpp +++ b/src/game/Object/Pet.cpp @@ -190,7 +190,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c return true; } - m_charmInfo->SetPetNumber(pet_number, IsPermanentPetFor(owner)); + m_charmInfo->SetPetNumber(pet_number, isControlled()); SetOwnerGuid(owner->GetObjectGuid()); SetDisplayId(fields[3].GetUInt32()); @@ -722,6 +722,8 @@ void Pet::GivePetXP(uint32 xp) if (level >= maxlevel) return; + xp *= sWorld.getConfig(CONFIG_FLOAT_RATE_PET_XP_KILL); + uint32 nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); uint32 curXP = GetUInt32Value(UNIT_FIELD_PETEXPERIENCE); uint32 newXP = curXP + xp; @@ -1914,29 +1916,6 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) } } -bool Pet::IsPermanentPetFor(Player* owner) -{ - switch (getPetType()) - { - case SUMMON_PET: - switch (owner->getClass()) - { - // oddly enough, Mage's Water Elemental is still treated as temporary pet with Glyph of Eternal Water - // i.e. does not unsummon at mounting, gets dismissed at teleport etc. - case CLASS_WARLOCK: - return GetCreatureInfo()->CreatureType == CREATURE_TYPE_DEMON; - case CLASS_DEATH_KNIGHT: - return GetCreatureInfo()->CreatureType == CREATURE_TYPE_UNDEAD; - default: - return false; - } - case HUNTER_PET: - return true; - default: - return false; - } -} - bool Pet::Create(uint32 guidlow, CreatureCreatePos& cPos, CreatureInfo const* cinfo, uint32 pet_number) { SetMap(cPos.GetMap()); @@ -1989,10 +1968,11 @@ void Pet::LearnPetPassives() void Pet::CastPetAuras(bool current) { - Unit* owner = GetOwner(); - if (!owner || owner->GetTypeId() != TYPEID_PLAYER) + if (!isControlled()) return; + Unit* owner = GetOwner(); + for (PetAuraSet::const_iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end();) { PetAura const* pa = *itr; diff --git a/src/game/Object/Pet.h b/src/game/Object/Pet.h index c2408d653..a9b010bbc 100644 --- a/src/game/Object/Pet.h +++ b/src/game/Object/Pet.h @@ -56,12 +56,17 @@ enum PetSaveMode // There might be a lot more enum PetModeFlags { - PET_MODE_UNKNOWN_0 = 0x0000001, - PET_MODE_UNKNOWN_2 = 0x0000100, + PET_MODE_STAY = 0x0000000, + PET_MODE_FOLLOW = 0x0000001, + PET_MODE_ATTACK = 0x0000002, + PET_MODE_PASSIVE = 0x0000000, + PET_MODE_DEFENSIVE = 0x0000100, + PET_MODE_AGGRESSIVE = 0x0000200, + PET_MODE_DISABLE_ACTIONS = 0x8000000, // autoset in client at summon - PET_MODE_DEFAULT = PET_MODE_UNKNOWN_0 | PET_MODE_UNKNOWN_2, + PET_MODE_DEFAULT = PET_MODE_FOLLOW | PET_MODE_DEFENSIVE, }; enum PetSpellState @@ -146,9 +151,7 @@ class Pet : public Creature void setPetType(PetType type) { m_petType = type; } bool isControlled() const { return getPetType() == SUMMON_PET || getPetType() == HUNTER_PET; } bool isTemporarySummoned() const { return m_duration > 0; } - - bool IsPermanentPetFor(Player* owner); // pet have tab in character windows and set UNIT_FIELD_PETNUMBER - + bool Create(uint32 guidlow, CreatureCreatePos& cPos, CreatureInfo const* cinfo, uint32 pet_number); bool CreateBaseAtCreature(Creature* creature); bool LoadPetFromDB(Player* owner, uint32 petentry = 0, uint32 petnumber = 0, bool current = false); diff --git a/src/game/Object/PetAI.cpp b/src/game/Object/PetAI.cpp index 934c19da0..36da35e93 100644 --- a/src/game/Object/PetAI.cpp +++ b/src/game/Object/PetAI.cpp @@ -128,6 +128,15 @@ void PetAI::UpdateAI(const uint32 diff) return; Unit* owner = m_creature->GetCharmerOrOwner(); + Unit* victim = nullptr; + + if (!((Pet*)m_creature)->isControlled()) + m_creature->SelectHostileTarget(); + + // Creature pets and guardians will always look in threat list for victim + if (!(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE) + || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS))) + victim = m_creature->getVictim(); if (m_updateAlliesTimer <= diff) // UpdateAllies self set update timer @@ -135,62 +144,68 @@ void PetAI::UpdateAI(const uint32 diff) else m_updateAlliesTimer -= diff; - if (inCombat && (!m_creature->getVictim() || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS))) - _stopAttack(); - - // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. - if (m_creature->getVictim()) + if (inCombat && !victim) { - if (_needToStop()) - { - DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow()); - _stopAttack(); - return; - } - - bool meleeReach = m_creature->CanReachWithMeleeAttack(m_creature->getVictim()); - - if (m_creature->IsStopped() || meleeReach) - { - // required to be stopped cases - if (m_creature->IsStopped() && m_creature->IsNonMeleeSpellCasted(false)) - { - if (m_creature->hasUnitState(UNIT_STAT_FOLLOW_MOVE)) - m_creature->InterruptNonMeleeSpells(false); - else - return; - } - // not required to be stopped case - else if (DoMeleeAttackIfReady()) - { - if (!m_creature->getVictim()) - return; - - // if pet misses its target, it will also be the first in threat list - m_creature->getVictim()->AddThreat(m_creature); - - if (_needToStop()) - _stopAttack(); - } - } + m_creature->AttackStop(true); + inCombat = false; } - else if (owner && m_creature->GetCharmInfo()) + + if (((Pet*)m_creature)->GetIsRetreating()) { - if (owner->IsInCombat() && !(m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) || m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY))) - { - AttackStart(owner->getAttackerForHelper()); - } - else if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW)) + if (!owner->IsWithinDistInMap(m_creature, (PET_FOLLOW_DIST * 2))) { if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW)) - { m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - } - } - } + return; + } + else + ((Pet*)m_creature)->SetIsRetreating(); + } + else if (((Pet*)m_creature)->GetSpellOpener() != 0) // have opener stored + { + uint32 minRange = ((Pet*)m_creature)->GetSpellOpenerMinRange(); + + if (!(victim = m_creature->getVictim()) + || (minRange != 0 && m_creature->IsWithinDistInMap(victim, minRange))) + ((Pet*)m_creature)->SetSpellOpener(); + else if (m_creature->IsWithinDistInMap(victim, ((Pet*)m_creature)->GetSpellOpenerMaxRange()) + && m_creature->IsWithinLOSInMap(victim)) + { + // stop moving + m_creature->clearUnitState(UNIT_STAT_MOVING); + + // auto turn to target + m_creature->SetInFront(victim); + + if (victim->GetTypeId() == TYPEID_PLAYER) + m_creature->SendCreateUpdateToPlayer((Player*)victim); + + if (owner->GetTypeId() == TYPEID_PLAYER) + m_creature->SendCreateUpdateToPlayer((Player*)owner); + + uint32 spell_id = ((Pet*)m_creature)->GetSpellOpener(); + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); + + Spell* spell = new Spell(m_creature, spellInfo, false); + + SpellCastResult result = spell->CheckPetCast(victim); + + if (result == SPELL_CAST_OK) + { + m_creature->AddCreatureSpellCooldown(spell_id); + spell->SpellStart(&(spell->m_targets)); + } + else + delete spell; + + ((Pet*)m_creature)->SetSpellOpener(); + } + else + return; + } // Autocast (casted only in combat or persistent spells in any state) - if (!m_creature->IsNonMeleeSpellCasted(false)) + else if (!m_creature->IsNonMeleeSpellCasted(false)) { typedef std::vector > TargetSpellList; TargetSpellList targetSpellStore; @@ -220,7 +235,6 @@ void PetAI::UpdateAI(const uint32 diff) // Consume Shadows, Lesser Invisibility, so ignore checks for its if (!IsNonCombatSpell(spellInfo)) { - // allow only spell without spell cost or with spell cost but not duration limit int32 duration = GetSpellDuration(spellInfo); SpellPowerEntry const* spellPower = spellInfo->GetSpellPower(); if (spellPower && (spellPower->manaCost || spellPower->ManaCostPercentage || spellPower->manaPerSecond) && duration > 0) @@ -228,22 +242,21 @@ void PetAI::UpdateAI(const uint32 diff) // allow only spell without cooldown > duration int32 cooldown = GetSpellRecoveryTime(spellInfo); - if (cooldown >= 0 && duration >= 0 && cooldown > duration) + + // allow only spell not on cooldown + if (cooldown != 0 && duration < cooldown) continue; } } - else - { - // just ignore non-combat spells - if (IsNonCombatSpell(spellInfo)) - continue; - } + // just ignore non-combat spells + else if (IsNonCombatSpell(spellInfo)) + continue; Spell* spell = new Spell(m_creature, spellInfo, false); - if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim())) + if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(victim)) { - targetSpellStore.push_back(TargetSpellList::value_type(m_creature->getVictim(), spell)); + targetSpellStore.push_back(TargetSpellList::value_type(victim, spell)); continue; } else @@ -301,6 +314,105 @@ void PetAI::UpdateAI(const uint32 diff) for (TargetSpellList::const_iterator itr = targetSpellStore.begin(); itr != targetSpellStore.end(); ++itr) delete itr->second; } + + // Guardians will always look in threat list for victim + if (!((Pet*)m_creature)->isControlled()) + m_creature->SelectHostileTarget(); + + if (!(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE) + || (m_creature->IsPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS))) + victim = m_creature->getVictim(); + + // Stop here if casting spell (No melee and no movement) + if (m_creature->IsNonMeleeSpellCasted(false)) + return; + + if (victim) + { + // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. + // This is needed for charmed creatures, as once their target was reset other effects can trigger threat + if ((m_creature->IsCharmed() && victim == m_creature->GetCharmer()) || !victim->IsTargetableForAttack()) + { + DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "PetAI (guid = %u) is stopping attack.", m_creature->GetGUIDLow()); + m_creature->CombatStop(); + inCombat = false; + + return; + } + + // if pet misses its target, it will also be the first in threat list + if (!(m_creature->GetCreatureInfo()->ExtraFlags & CREATURE_EXTRA_FLAG_NO_MELEE) + && m_creature->CanReachWithMeleeAttack(victim)) + { + if (!m_creature->HasInArc(2 * M_PI_F / 3, victim)) + { + m_creature->SetInFront(victim); + if (victim->GetTypeId() == TYPEID_PLAYER) + m_creature->SendCreateUpdateToPlayer((Player*)victim); + + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + m_creature->SendCreateUpdateToPlayer((Player*)owner); + } + + if (DoMeleeAttackIfReady()) + victim->AddThreat(m_creature); + } + else if (!(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE) + || m_creature->hasUnitState(UNIT_STAT_MOVING))) + AttackStart(victim); + } + else if (owner) + { + CharmInfo* charmInfo = m_creature->GetCharmInfo(); + + if (owner->IsInCombat() && !(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE) + || (charmInfo && charmInfo->HasReactState(REACT_PASSIVE)))) + AttackStart(owner->getAttackerForHelper()); + else if (!m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + { + if (charmInfo && charmInfo->HasCommandState(COMMAND_STAY)) + { + if (Pet* pet = (Pet*)m_creature) + { + //if stay command is set but we dont have stay pos set then we need to establish current pos as stay position + if (!pet->IsStayPosSet()) + pet->SetStayPosition(true); + + float stayPosX = pet->GetStayPosX(); + float stayPosY = pet->GetStayPosY(); + float stayPosZ = pet->GetStayPosZ(); + + if (m_creature->GetPositionX() == stayPosX + && m_creature->GetPositionY() == stayPosY + && m_creature->GetPositionZ() == stayPosZ) + { + float StayPosO = pet->GetStayPosO(); + + if (m_creature->hasUnitState(UNIT_STAT_MOVING)) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + } + else if (m_creature->GetOrientation() != StayPosO) + m_creature->SetOrientation(StayPosO); + } + else + pet->GetMotionMaster()->MovePoint(0, stayPosX, stayPosY, stayPosZ, false); + } + } + else if (m_creature->hasUnitState(UNIT_STAT_FOLLOW)) + { + if (owner->IsWithinDistInMap(m_creature, PET_FOLLOW_DIST)) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + } + } + else if (charmInfo && charmInfo->HasCommandState(COMMAND_FOLLOW) + && !owner->IsWithinDistInMap(m_creature, (PET_FOLLOW_DIST * 2))) + m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + } + } } bool PetAI::_isVisible(Unit* u) const @@ -350,8 +462,9 @@ void PetAI::UpdateAllies() void PetAI::AttackedBy(Unit* attacker) { - // when attacked, fight back in case 1)no victim already AND 2)not set to passive AND 3)not set to stay, unless can it can reach attacker with melee attack anyway - if (!m_creature->getVictim() && m_creature->GetCharmInfo() && !m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) && - (!m_creature->GetCharmInfo()->HasCommandState(COMMAND_STAY) || m_creature->CanReachWithMeleeAttack(attacker))) + // when attacked, fight back if no victim unless we have a charm state set to passive + if (!(m_creature->getVictim() || ((Pet*)m_creature)->GetIsRetreating() == true) + && !(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE) + || (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE)))) AttackStart(attacker); } diff --git a/src/game/Object/Player.cpp b/src/game/Object/Player.cpp index e2cbc2a88..43f41859a 100644 --- a/src/game/Object/Player.cpp +++ b/src/game/Object/Player.cpp @@ -18416,7 +18416,7 @@ void Player::PetSpellInitialize() uint8 addlist = 0; data << uint8(addlist); // placeholder - if (pet->IsPermanentPetFor(this)) + if (pet->isControlled()) { // spells loop for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) @@ -21328,7 +21328,7 @@ struct UpdateZoneDependentPetsHelper explicit UpdateZoneDependentPetsHelper(Player* _owner, uint32 zone, uint32 area) : owner(_owner), zone_id(zone), area_id(area) {} void operator()(Unit* unit) const { - if (unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->IsPet() && !((Pet*)unit)->IsPermanentPetFor(owner)) + if (unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->IsPet() && !((Pet*)unit)->isControlled()) if (uint32 spell_id = unit->GetUInt32Value(UNIT_CREATED_BY_SPELL)) if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(spell_id)) if (sSpellMgr.GetSpellAllowedInLocationError(spellEntry, owner->GetMapId(), zone_id, area_id, owner) != SPELL_CAST_OK) diff --git a/src/game/WorldHandlers/MiscHandler.cpp b/src/game/WorldHandlers/MiscHandler.cpp index f6963c652..eb1e57748 100644 --- a/src/game/WorldHandlers/MiscHandler.cpp +++ b/src/game/WorldHandlers/MiscHandler.cpp @@ -251,6 +251,10 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recv_data) if (!s_show) continue; + // 49 is maximum player count sent to client + if (++matchcount > 49) + continue; + ++displaycount; data << pname; // player name diff --git a/src/game/WorldHandlers/PetHandler.cpp b/src/game/WorldHandlers/PetHandler.cpp index 0df67d89f..019eada63 100644 --- a/src/game/WorldHandlers/PetHandler.cpp +++ b/src/game/WorldHandlers/PetHandler.cpp @@ -95,17 +95,27 @@ void WorldSession::HandlePetAction(WorldPacket& recv_data) switch (spellid) { case COMMAND_STAY: // flat=1792 // STAY - pet->clearUnitState(UNIT_STAT_MOVING); + { pet->StopMoving(); - pet->GetMotionMaster()->Clear(false); - pet->GetMotionMaster()->MoveIdle(); + pet->AttackStop(true); + pet->GetMotionMaster()->Clear(); + ((Pet*)pet)->SetStayPosition(true); + ((Pet*)pet)->SetIsRetreating(); + ((Pet*)pet)->SetSpellOpener(); charmInfo->SetCommandState(COMMAND_STAY); break; + } case COMMAND_FOLLOW: // spellid=1792 // FOLLOW - pet->AttackStop(); - pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + { + pet->StopMoving(); + pet->AttackStop(true); + pet->GetMotionMaster()->Clear(); + ((Pet*)pet)->SetStayPosition(); + ((Pet*)pet)->SetIsRetreating(true); + ((Pet*)pet)->SetSpellOpener(); charmInfo->SetCommandState(COMMAND_FOLLOW); break; + } case COMMAND_ATTACK: // spellid=1792 // ATTACK { Unit* TargetUnit = _player->GetMap()->GetUnit(targetGuid); @@ -182,10 +192,16 @@ void WorldSession::HandlePetAction(WorldPacket& recv_data) switch (spellid) { case REACT_PASSIVE: // passive + { + pet->AttackStop(true); + ((Pet*)pet)->SetSpellOpener(); + } case REACT_DEFENSIVE: // recovery case REACT_AGGRESSIVE: // activete + { charmInfo->SetReactState(ReactStates(spellid)); break; + } } break; case ACT_DISABLED: // 0x81 spell (disabled), ignore @@ -226,6 +242,28 @@ void WorldSession::HandlePetAction(WorldPacket& recv_data) SpellCastResult result = spell->CheckPetCast(unit_target); + const SpellRangeEntry* sRange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); + + if (unit_target && !(pet->IsWithinDistInMap(unit_target, sRange->maxRange) && pet->IsWithinLOSInMap(unit_target)) + && !(GetPlayer()->IsFriendlyTo(unit_target) || pet->HasAuraType(SPELL_AURA_MOD_POSSESS))) + { + ((Pet*)pet)->SetSpellOpener(spellid, sRange->minRange, sRange->maxRange); + spell->finish(false); + delete spell; + + pet->AttackStop(); + pet->GetMotionMaster()->Clear(); + + ((Creature*)pet)->AI()->AttackStart(unit_target); + // 10% chance to play special warlock pet attack talk, else growl + if (((Creature*)pet)->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10)) + pet->SendPetTalk((uint32)PET_TALK_ATTACK); + + pet->SendPetAIReaction(); + + return; + } + // auto turn to target unless possessed if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) { @@ -253,28 +291,7 @@ void WorldSession::HandlePetAction(WorldPacket& recv_data) unit_target = spell->m_targets.getUnitTarget(); - // 10% chance to play special pet attack talk, else growl - // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (((Creature*)pet)->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); - else - { - pet->SendPetAIReaction(); - } - - if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS)) - { - // This is true if pet has no target or has target but targets differs. - if (pet->getVictim() != unit_target) - { - if (pet->getVictim()) - pet->AttackStop(); - pet->GetMotionMaster()->Clear(); - if (((Creature*)pet)->AI()) - ((Creature*)pet)->AI()->AttackStart(unit_target); - } - } - + ((Pet*)pet)->SetSpellOpener(); spell->SpellStart(&(spell->m_targets)); } else @@ -291,6 +308,7 @@ void WorldSession::HandlePetAction(WorldPacket& recv_data) if (!((Creature*)pet)->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); + ((Pet*)pet)->SetSpellOpener(); spell->finish(false); delete spell; } @@ -702,20 +720,10 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) spell->m_cast_count = cast_count; // probably pending spell cast spell->m_targets = targets; - SpellCastResult result = triggeredByAura ? SPELL_CAST_OK : spell->CheckPetCast(NULL); + SpellCastResult result = triggeredByAura ? SPELL_CAST_OK : spell->CheckPetCast(nullptr); if (result == SPELL_CAST_OK) { pet->AddCreatureSpellCooldown(spellid); - if (pet->IsPet()) - { - // 10% chance to play special pet attack talk, else growl - // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell - if (((Pet*)pet)->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) - pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); - else - pet->SendPetAIReaction(); - } - spell->SpellStart(&(spell->m_targets), triggeredByAura); } else diff --git a/src/game/WorldHandlers/Spell.cpp b/src/game/WorldHandlers/Spell.cpp index cd4d40f39..6e4c6a842 100644 --- a/src/game/WorldHandlers/Spell.cpp +++ b/src/game/WorldHandlers/Spell.cpp @@ -7497,6 +7497,11 @@ void Spell::UpdatePointers() UpdateOriginalCasterPointer(); m_targets.Update(m_caster); + + if (m_caster->GetTypeId() == TYPEID_PLAYER) + m_CastItem = ((Player *)m_caster)->GetItemByGuid(m_CastItemGuid); + else + m_CastItem = NULL; } bool Spell::CheckTargetCreatureType(Unit* target) const @@ -8063,6 +8068,7 @@ void Spell::ClearCastItem() m_targets.setItemTarget(NULL); m_CastItem = NULL; + m_CastItemGuid.Clear(); } bool Spell::HasGlobalCooldown() diff --git a/src/game/WorldHandlers/World.cpp b/src/game/WorldHandlers/World.cpp index 320d58933..4e413818d 100644 --- a/src/game/WorldHandlers/World.cpp +++ b/src/game/WorldHandlers/World.cpp @@ -470,9 +470,10 @@ void World::LoadConfigSettings(bool reload) setConfigPos(CONFIG_FLOAT_RATE_DROP_MONEY, "Rate.Drop.Money", 1.0f); setConfigPos(CONFIG_FLOAT_RATE_DROP_CURRENCY, "Rate.Drop.Currency", 1.0f); setConfigPos(CONFIG_FLOAT_RATE_DROP_CURRENCY_AMOUNT, "Rate.Drop.Currency.Amount", 1.0f); - setConfig(CONFIG_FLOAT_RATE_XP_KILL, "Rate.XP.Kill", 1.0f); - setConfig(CONFIG_FLOAT_RATE_XP_QUEST, "Rate.XP.Quest", 1.0f); - setConfig(CONFIG_FLOAT_RATE_XP_EXPLORE, "Rate.XP.Explore", 1.0f); + setConfig(CONFIG_FLOAT_RATE_PET_XP_KILL, "Rate.Pet.XP.Kill", 1.0f); + setConfig(CONFIG_FLOAT_RATE_XP_KILL, "Rate.XP.Kill", 1.0f); + setConfig(CONFIG_FLOAT_RATE_XP_QUEST, "Rate.XP.Quest", 1.0f); + setConfig(CONFIG_FLOAT_RATE_XP_EXPLORE, "Rate.XP.Explore", 1.0f); setConfig(CONFIG_FLOAT_RATE_REPUTATION_GAIN, "Rate.Reputation.Gain", 1.0f); setConfig(CONFIG_FLOAT_RATE_REPUTATION_LOWLEVEL_KILL, "Rate.Reputation.LowLevel.Kill", 1.0f); setConfig(CONFIG_FLOAT_RATE_REPUTATION_LOWLEVEL_QUEST, "Rate.Reputation.LowLevel.Quest", 1.0f); diff --git a/src/game/WorldHandlers/World.h b/src/game/WorldHandlers/World.h index 5f85f4363..79fc87099 100644 --- a/src/game/WorldHandlers/World.h +++ b/src/game/WorldHandlers/World.h @@ -267,6 +267,7 @@ enum eConfigFloatValues CONFIG_FLOAT_RATE_DROP_MONEY, CONFIG_FLOAT_RATE_DROP_CURRENCY, CONFIG_FLOAT_RATE_DROP_CURRENCY_AMOUNT, + CONFIG_FLOAT_RATE_PET_XP_KILL, CONFIG_FLOAT_RATE_XP_KILL, CONFIG_FLOAT_RATE_XP_QUEST, CONFIG_FLOAT_RATE_XP_EXPLORE, diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 6177001cb..6da300937 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -203,6 +203,10 @@ BindIP = "0.0.0.0" # Default: 1 (Enable) # 0 (Disabled) # +# MaxWhoListReturns +# Set the max number of players returned in the /who list and interface (0 means unlimited) +# Default: 49 - (stable) +# ################################################################################ UseProcessors = 0 @@ -231,6 +235,7 @@ UpdateUptimeInterval = 10 MaxCoreStuckTime = 0 AddonChannel = 1 CleanCharacterDB = 1 +MaxWhoListReturns = 49 ################################################################################ # SERVER LOGGING @@ -1282,6 +1287,7 @@ Visibility.AIRelocationNotifyDelay = 1000 # Drop rate for currency amount # Default: 1 # +# Rate.Pet.XP.Kill # Rate.XP.Kill # Rate.XP.Quest # Rate.XP.Explore @@ -1428,6 +1434,7 @@ Rate.Drop.Item.Quest = 1 Rate.Drop.Money = 1 Rate.Drop.Currency = 1 Rate.Drop.Currency.Amount = 1 +Rate.Pet.XP.Kill = 1 Rate.XP.Kill = 1 Rate.XP.Quest = 1 Rate.XP.Explore = 1