diff options
Diffstat (limited to 'src')
88 files changed, 1302 insertions, 799 deletions
diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp index 252bcbabca5..6e2326ca9d5 100755 --- a/src/server/game/AI/CoreAI/GuardAI.cpp +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -23,7 +23,7 @@ #include "World.h" #include "CreatureAIImpl.h" -int GuardAI::Permissible(const Creature* creature) +int GuardAI::Permissible(Creature const* creature) { if (creature->isGuard()) return PERMIT_BASE_SPECIAL; @@ -31,7 +31,7 @@ int GuardAI::Permissible(const Creature* creature) return PERMIT_BASE_NO; } -GuardAI::GuardAI(Creature* creature) : ScriptedAI(creature), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK) +GuardAI::GuardAI(Creature* creature) : ScriptedAI(creature) { } @@ -40,108 +40,35 @@ bool GuardAI::CanSeeAlways(WorldObject const* obj) if (!obj->isType(TYPEMASK_UNIT)) return false; - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - if (Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid())) - if (unit == obj) - return true; - } + std::list<HostileReference*> threatList = me->getThreatManager().getThreatList(); + for (std::list<HostileReference*>::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) + if ((*itr)->getUnitGuid() == obj->GetGUID()) + return true; return false; } -void GuardAI::MoveInLineOfSight(Unit* unit) -{ - // Ignore Z for flying creatures - if (!me->CanFly() && me->GetDistanceZ(unit) > CREATURE_Z_ATTACK_RANGE) - return; - - if (!me->getVictim() && me->IsValidAttackTarget(unit) && - (unit->IsHostileToPlayers() || me->IsHostileTo(unit)) && - unit->isInAccessiblePlaceFor(me)) - { - float attackRadius = me->GetAttackDistance(unit); - if (me->IsWithinDistInMap(unit, attackRadius)) - { - //Need add code to let guard support player - AttackStart(unit); - //u->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); - } - } -} - void GuardAI::EnterEvadeMode() { if (!me->isAlive()) { - sLog->outStaticDebug("Creature stopped attacking because he is dead [guid=%u]", me->GetGUIDLow()); me->GetMotionMaster()->MoveIdle(); - - i_state = STATE_NORMAL; - - i_victimGuid = 0; me->CombatStop(true); me->DeleteThreatList(); return; } - Unit* victim = ObjectAccessor::GetUnit(*me, i_victimGuid); - - if (!victim) - { - sLog->outStaticDebug("Creature stopped attacking because victim does not exist [guid=%u]", me->GetGUIDLow()); - } - else if (!victim->isAlive()) - { - sLog->outStaticDebug("Creature stopped attacking because victim is dead [guid=%u]", me->GetGUIDLow()); - } - else if (victim->HasStealthAura()) - { - sLog->outStaticDebug("Creature stopped attacking because victim is using stealth [guid=%u]", me->GetGUIDLow()); - } - else if (victim->isInFlight()) - { - sLog->outStaticDebug("Creature stopped attacking because victim is flying away [guid=%u]", me->GetGUIDLow()); - } - else - { - sLog->outStaticDebug("Creature stopped attacking because victim outran him [guid=%u]", me->GetGUIDLow()); - } + sLog->outDebug(LOG_FILTER_UNITS, "Guard entry: %u enters evade mode.", me->GetEntry()); me->RemoveAllAuras(); me->DeleteThreatList(); - i_victimGuid = 0; me->CombatStop(true); - i_state = STATE_NORMAL; // Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) me->GetMotionMaster()->MoveTargetedHome(); } -void GuardAI::UpdateAI(const uint32 /*diff*/) -{ - // update i_victimGuid if me->getVictim() !=0 and changed - if (!UpdateVictim()) - return; - - Unit* const victim = me->getVictim(); - if (!victim) - return; - - i_victimGuid = victim->GetGUID(); - - if (me->isAttackReady()) - { - if (me->IsWithinMeleeRange(victim)) - { - me->AttackerStateUpdate(victim); - me->resetAttackTimer(); - } - } -} - void GuardAI::JustDied(Unit* killer) { if (Player* player = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) diff --git a/src/server/game/AI/CoreAI/GuardAI.h b/src/server/game/AI/CoreAI/GuardAI.h index c80c5a6c343..c8dd9d54921 100755 --- a/src/server/game/AI/CoreAI/GuardAI.h +++ b/src/server/game/AI/CoreAI/GuardAI.h @@ -20,34 +20,19 @@ #define TRINITY_GUARDAI_H #include "ScriptedCreature.h" -#include "Timer.h" class Creature; class GuardAI : public ScriptedAI { - enum GuardState - { - STATE_NORMAL = 1, - STATE_LOOK_AT_VICTIM = 2 - }; - public: + explicit GuardAI(Creature* creature); - explicit GuardAI(Creature* c); - - void MoveInLineOfSight(Unit*); - void EnterEvadeMode(); - void JustDied(Unit*); + static int Permissible(Creature const* creature); bool CanSeeAlways(WorldObject const* obj); - void UpdateAI(const uint32); - static int Permissible(const Creature*); - - private: - uint64 i_victimGuid; - GuardState i_state; - TimeTracker i_tracker; + void EnterEvadeMode(); + void JustDied(Unit* killer); }; #endif diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index bcec8d273b9..160b406a6ea 100755 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -153,40 +153,56 @@ void PetAI::UpdateAI(const uint32 diff) if (spellInfo->IsPositive()) { - // non combat spells allowed - // only pet spells have IsNonCombatSpell and not fit this reqs: - // Consume Shadows, Lesser Invisibility, so ignore checks for its if (spellInfo->CanBeUsedInCombat()) { - // allow only spell without spell cost or with spell cost but not duration limit - int32 duration = spellInfo->GetDuration(); - if ((spellInfo->ManaCost || spellInfo->ManaCostPercentage || spellInfo->ManaPerSecond) && duration > 0) + // check spell cooldown + if (me->HasSpellCooldown(spellInfo->Id)) continue; - // allow only spell without cooldown > duration - int32 cooldown = spellInfo->GetRecoveryTime(); - if (cooldown >= 0 && duration >= 0 && cooldown > duration) + // Check if we're in combat or commanded to attack + if (!me->isInCombat() && !me->GetCharmInfo()->IsCommandAttack()) continue; } Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0); - bool spellUsed = false; - for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) - { - Unit* target = ObjectAccessor::GetUnit(*me, *tar); - //only buff targets that are in combat, unless the spell can only be cast while out of combat - if (!target) - continue; + // Some spells can target enemy or friendly (DK Ghoul's Leap) + // Check for enemy first (pet then owner) + Unit* target = me->getAttackerForHelper(); + if (!target && owner) + target = owner->getAttackerForHelper(); - if (spell->CanAutoCast(target)) + if (target) + { + if (CanAttack(target) && spell->CanAutoCast(target)) { targetSpellStore.push_back(std::make_pair(target, spell)); spellUsed = true; - break; } } + + // No enemy, check friendly + if (!spellUsed) + { + for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) + { + Unit* ally = ObjectAccessor::GetUnit(*me, *tar); + + //only buff targets that are in combat, unless the spell can only be cast while out of combat + if (!ally) + continue; + + if (spell->CanAutoCast(ally)) + { + targetSpellStore.push_back(std::make_pair(ally, spell)); + spellUsed = true; + break; + } + } + } + + // No valid targets at all if (!spellUsed) delete spell; } diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp index 517e55af457..a863f2f89cf 100755 --- a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp +++ b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp @@ -204,12 +204,17 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() temp.raw.param3 = fields[8].GetInt32(); temp.raw.param4 = fields[9].GetInt32(); + CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); //Creature does not exist in database - if (!sObjectMgr->GetCreatureTemplate(temp.creature_id)) + if (!cInfo) { - sLog->outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, temp.creature_id); + sLog->outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, creature_id); continue; } + + // Only on the first script + if (cInfo->AIName != "EventAI" && m_CreatureEventAI_Event_Map[creature_id].empty()) + sLog->outErrorDb("Creature entry %u has EventAI scripts, but its AIName is not 'EventAI' - possible AI-mismatch?", temp.creature_id); //No chance of this event occuring if (temp.event_chance == 0) @@ -735,18 +740,6 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() } while (result->NextRow()); - for (CreatureEventAI_Event_Map::const_iterator itr = m_CreatureEventAI_Event_Map.begin(); itr != m_CreatureEventAI_Event_Map.end(); ++itr) - { - if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(itr->first)) - { - if (cInfo->AIName != "EventAI") - { - sLog->outErrorDb("Creature entry %u has EventAI scripts, but its AIName is not 'EventAI', changing to EventAI", itr->first); - const_cast<CreatureTemplate*>(cInfo)->AIName = "EventAI"; - } - } - } - sLog->outString(">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index bfd1c7b9d41..435aa176d4d 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -62,6 +62,7 @@ class SmartAI : public CreatureAI void RemoveEscortState(uint32 uiEscortState) { mEscortState &= ~uiEscortState; } void SetAutoAttack(bool on) { mCanAutoAttack = on; } void SetCombatMove(bool on); + bool CanCombatMove() { return mCanCombatMove; } void SetFollow(Unit* target, float dist = 0.0f, float angle = 0.0f, uint32 credit = 0, uint32 end = 0, uint32 creditType = 0); void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); @@ -224,7 +225,6 @@ class SmartAI : public CreatureAI bool mCanCombatMove; bool mForcedPaused; uint32 mInvincibilityHpLevel; - bool AssistPlayerInCombat(Unit* who); uint32 mDespawnTime; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 85b117ccd8c..21dc92b25d1 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -789,7 +789,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!IsUnit((*itr))) continue; - (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + if (e.action.removeAura.spell == 0) + (*itr)->ToUnit()->RemoveAllAuras(); + else + (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit %u, spell %u", (*itr)->GetGUIDLow(), e.action.removeAura.spell); } @@ -1534,6 +1538,27 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u case SMART_ACTION_CALL_SCRIPT_RESET: OnReset(); break; + case SMART_ACTION_SET_RANGED_MOVEMENT: + { + if (!IsSmart()) + break; + + float attackDistance = (float)e.action.setRangedMovement.distance; + float attackAngle = e.action.setRangedMovement.angle / 180.0f * M_PI; + + ObjectList* targets = GetTargets(e, unit); + if (targets) + { + for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (Creature* target = (*itr)->ToCreature()) + if (IsSmart(target) && target->getVictim()) + if (CAST_AI(SmartAI, target->AI())->CanCombatMove()) + target->GetMotionMaster()->MoveChase(target->getVictim(), attackDistance, attackAngle); + + delete targets; + } + break; + } case SMART_ACTION_CALL_TIMED_ACTIONLIST: { if (e.GetTargetType() == SMART_TARGET_NONE) diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index a7149f37480..d529479d9dd 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -709,7 +709,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; break; case SMART_ACTION_REMOVEAURASFROMSPELL: - if (!IsSpellValid(e, e.action.removeAura.spell)) + if (e.action.removeAura.spell != 0 && !IsSpellValid(e, e.action.removeAura.spell)) return false; break; case SMART_ACTION_RANDOM_PHASE: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index bde7768f036..5b54a4d3048 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -398,7 +398,7 @@ enum SMART_ACTION SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID SMART_ACTION_CALL_CASTEDCREATUREORGO = 27, // CreatureId, SpellId - SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid + SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid, 0 removes all auras SMART_ACTION_FOLLOW = 29, // Distance (0 = default), Angle (0 = default), EndCreatureEntry, credit, creditType (0monsterkill, 1event) SMART_ACTION_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3... SMART_ACTION_RANDOM_PHASE_RANGE = 31, // PhaseMin, PhaseMax @@ -451,7 +451,7 @@ enum SMART_ACTION SMART_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT = 76, // WARNING: CAN CRASH CORE, do not use if you dont know what you are doing SMART_ACTION_RESET_SCRIPT_BASE_OBJECT = 77, // none SMART_ACTION_CALL_SCRIPT_RESET = 78, // none - // Unused = 79, + SMART_ACTION_SET_RANGED_MOVEMENT = 79, // Distance, angle SMART_ACTION_CALL_TIMED_ACTIONLIST = 80, // ID (overwrites already running actionlist), stop after combat?(0/1), timer update type(0-OOC, 1-IC, 2-ALWAYS) SMART_ACTION_SET_NPC_FLAG = 81, // Flags SMART_ACTION_ADD_NPC_FLAG = 82, // Flags @@ -895,6 +895,12 @@ struct SmartAction struct { + float distance; + float angle; + } setRangedMovement; + + struct + { uint32 param1; uint32 param2; uint32 param3; diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 9d5858e1ca4..85bbd2f3b89 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -850,9 +850,8 @@ void Battleground::EndBattleground(uint32 winner) if (team == winner) { // update achievement BEFORE personal rating update - ArenaTeamMember* member = winner_arena_team->GetMember(player->GetGUID()); - if (member) - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, 1); + uint32 rating = player->GetArenaPersonalRating(winner_arena_team->GetSlot()); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1); winner_arena_team->MemberWon(player, loser_matchmaker_rating, winner_matchmaker_change); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 52d2cdefd65..d28f5ddfe6a 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -290,7 +290,7 @@ int32 BattlegroundAB::_GetNodeNameId(uint8 node) case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL; case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE; default: - ASSERT(0); + ASSERT(false); } return 0; } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index 977897b8d48..133a0aec560 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -720,8 +720,13 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) DelCreature(BG_SA_MAXNPC + i); GraveyardStatus[i] = Source->GetTeamId(); - WorldSafeLocsEntry const* sg = NULL; - sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); + WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]); + if (!sg) + { + sLog->outError("BattlegroundSA::CaptureGraveyard: non-existant GY entry: %u", BG_SA_GYEntries[i]); + return; + } + AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], (GraveyardStatus[i] == TEAM_ALLIANCE? ALLIANCE : HORDE)); uint32 npc = 0; uint32 flag = 0; @@ -781,7 +786,7 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source) SendWarningToAll(LANG_BG_SA_H_GY_SOUTH); break; default: - ASSERT(0); + ASSERT(false); break; }; } diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp index cef68891890..62bc0ab3205 100644 --- a/src/server/game/Calendar/CalendarMgr.cpp +++ b/src/server/game/Calendar/CalendarMgr.cpp @@ -95,9 +95,9 @@ CalendarEventIdList const& CalendarMgr::GetPlayerEvents(uint64 guid) CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId) { - CalendarInviteMap::iterator it = _invites.find(inviteId); - if (it != _invites.end()) - return &(it->second); + CalendarInviteMap::iterator itr = _invites.find(inviteId); + if (itr != _invites.end()) + return &(itr->second); sLog->outError("CalendarMgr::GetInvite: [" UI64FMTD "] not found!", inviteId); return NULL; @@ -105,9 +105,9 @@ CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId) CalendarEvent* CalendarMgr::GetEvent(uint64 eventId) { - CalendarEventMap::iterator it = _events.find(eventId); - if (it != _events.end()) - return &(it->second); + CalendarEventMap::iterator itr = _events.find(eventId); + if (itr != _events.end()) + return &(itr->second); sLog->outError("CalendarMgr::GetEvent: [" UI64FMTD "] not found!", eventId); return NULL; @@ -316,11 +316,6 @@ void CalendarMgr::AddAction(CalendarAction const& action) if (!calendarEvent) return; - CalendarInviteIdList const& inviteIds = calendarEvent->GetInviteIdList(); - for (CalendarInviteIdList::const_iterator it = inviteIds.begin(); it != inviteIds.end(); ++it) - if (uint64 invitee = RemoveInvite(*it)) - SendCalendarEventRemovedAlert(invitee, *calendarEvent); - RemoveEvent(eventId); break; } @@ -464,8 +459,6 @@ bool CalendarMgr::RemoveEvent(uint64 eventId) return false; } - _events.erase(itr); - bool val = true; CalendarInviteIdList const& invites = itr->second.GetInviteIdList(); @@ -474,8 +467,13 @@ bool CalendarMgr::RemoveEvent(uint64 eventId) CalendarInvite* invite = GetInvite(*itrInvites); if (!invite || !RemovePlayerEvent(invite->GetInvitee(), eventId)) val = false; + + if (uint64 invitee = RemoveInvite(*itrInvites)) + SendCalendarEventRemovedAlert(invitee, itr->second); } + _events.erase(itr); + return val; } diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index 30562bb9662..4b2f1c5e7bb 100755 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -1144,15 +1144,20 @@ bool ChatHandler::HandleLookupQuestCommand(const char *args) { QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - if (status == QUEST_STATUS_COMPLETE) + switch (status) { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else + case QUEST_STATUS_COMPLETE: statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + break; + case QUEST_STATUS_INCOMPLETE: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + break; + case QUEST_STATUS_REWARDED: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + break; + default: + break; } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); } if (m_session) @@ -1187,15 +1192,20 @@ bool ChatHandler::HandleLookupQuestCommand(const char *args) { QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - if (status == QUEST_STATUS_COMPLETE) + switch (status) { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else + case QUEST_STATUS_COMPLETE: statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + break; + case QUEST_STATUS_INCOMPLETE: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + break; + case QUEST_STATUS_REWARDED: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + break; + default: + break; } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); } if (m_session) diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 80949effa0c..e73480cb4de 100755 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -245,7 +245,7 @@ enum AreaFlags AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?) AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag) AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled) - AREA_FLAG_NEED_FLY = 0x00001000, // Unknown + AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag) AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area) @@ -260,7 +260,7 @@ enum AreaFlags AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors - AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Same as AREA_FLAG_WINTERGRASP except for The Sunken Ring and Western Bridge. + AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area AREA_FLAG_NO_FLY_ZONE = 0x20000000 // Marks zones where you cannot fly }; @@ -416,16 +416,27 @@ enum SummonPropFlags enum VehicleSeatFlags { + VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER = 0x00000001, + VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_RIDE = 0x00000002, + VEHICLE_SEAT_FLAG_SHOULD_USE_VEH_SEAT_EXIT_ANIM_ON_VOLUNTARY_EXIT = 0x00000008, VEHICLE_SEAT_FLAG_HIDE_PASSENGER = 0x00000200, // Passenger is hidden - VEHICLE_SEAT_FLAG_UNK1 = 0x00000400, // needed for CGCamera__SyncFreeLookFacing + VEHICLE_SEAT_FLAG_ALLOW_TURNING = 0x00000400, // needed for CGCamera__SyncFreeLookFacing VEHICLE_SEAT_FLAG_CAN_CONTROL = 0x00000800, // Lua_UnitInVehicleControlSeat VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL = 0x00001000, // Can cast spells with SPELL_AURA_MOUNTED from seat (possibly 4.x only, 0 seats on 3.3.5a) VEHICLE_SEAT_FLAG_UNCONTROLLED = 0x00002000, // can override !& VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT VEHICLE_SEAT_FLAG_CAN_ATTACK = 0x00004000, // Can attack, cast spells and use items from vehicle + VEHICLE_SEAT_FLAG_SHOULD_USE_VEH_SEAT_EXIT_ANIMN_ON_FORCED_EXIT = 0x00008000, + VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_VOLUNTARY_EXIT = 0x00040000, + VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_FORCED_EXIT = 0x00080000, + VEHICLE_SEAT_FLAG_REC_HAS_VEHICLE_ENTER_ANIM = 0x00400000, + VEHICLE_SEAT_FLAG_ENABLE_VEHICLE_ZOOM = 0x01000000, VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT = 0x02000000, // Lua_CanExitVehicle - can enter and exit at free will VEHICLE_SEAT_FLAG_CAN_SWITCH = 0x04000000, // Lua_CanSwitchVehicleSeats + VEHICLE_SEAT_FLAG_HAS_START_WARITING_FOR_VEH_TRANSITION_ANIM_ENTER = 0x08000000, + VEHICLE_SEAT_FLAG_HAS_START_WARITING_FOR_VEH_TRANSITION_ANIM_EXIT = 0x10000000, VEHICLE_SEAT_FLAG_CAN_CAST = 0x20000000, // Lua_UnitHasVehicleUI VEHICLE_SEAT_FLAG_UNK2 = 0x40000000, // checked in conjunction with 0x800 in CastSpell2 + VEHICLE_SEAT_FLAG_ALLOWS_INTERACTION = 0x80000000, }; enum VehicleSeatFlagsB @@ -437,6 +448,7 @@ enum VehicleSeatFlagsB VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 = 0x00000040, VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 = 0x00000100, VEHICLE_SEAT_FLAG_B_USABLE_FORCED_4 = 0x02000000, + VEHICLE_SEAT_FLAG_B_CAN_SWITCH = 0x04000000, VEHICLE_SEAT_FLAG_B_VEHICLE_PLAYERFRAME_UI = 0x80000000, // Lua_UnitHasVehiclePlayerFrameUI - actually checked for flagsb &~ 0x80000000 }; diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 5b7c40e5494..4613a3554db 100755 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -89,7 +89,7 @@ bool Corpse::Create(uint32 guidlow, Player* owner) WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask()); - SetFloatValue(OBJECT_FIELD_SCALE_X, 1); + SetObjectScale(1); SetUInt64Value(CORPSE_FIELD_OWNER, owner->GetGUID()); _gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY()); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index d120713636d..e8ec686daf5 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -333,7 +333,7 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data SetSpeed(MOVE_SWIM, 1.0f); // using 1.0 rate SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate - SetFloatValue(OBJECT_FIELD_SCALE_X, cinfo->scale); + SetObjectScale(cinfo->scale); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, cinfo->HoverHeight); @@ -1668,8 +1668,8 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo) if (!spellInfo) return false; - // Spells that don't have effectMechanics. - if (!spellInfo->HasAnyEffectMechanic() && GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1))) + // Creature is immune to main mechanic of the spell + if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1))) return true; // This check must be done instead of 'if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1)))' for not break diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index f6021a7d7ec..c8ebf1aa13b 100755 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -677,6 +677,11 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature void GetHomePosition(float &x, float &y, float &z, float &ori) { m_homePosition.GetPosition(x, y, z, ori); } Position GetHomePosition() { return m_homePosition; } + void SetTransportHomePosition(float x, float y, float z, float o) { m_transportHomePosition.Relocate(x, y, z, o); } + void SetTransportHomePosition(const Position &pos) { m_transportHomePosition.Relocate(pos); } + void GetTransportHomePosition(float &x, float &y, float &z, float &ori) { m_transportHomePosition.GetPosition(x, y, z, ori); } + Position GetTransportHomePosition() { return m_transportHomePosition; } + uint32 GetWaypointPath(){return m_path_id;} void LoadPath(uint32 pathid) { m_path_id = pathid; } @@ -750,6 +755,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature uint32 m_originalEntry; Position m_homePosition; + Position m_transportHomePosition; bool DisableReputationGain; diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index abeae0656ee..76d4cb6624b 100755 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -92,7 +92,7 @@ bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spe WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask()); SetEntry(spellId); - SetFloatValue(OBJECT_FIELD_SCALE_X, 1); + SetObjectScale(1); SetUInt64Value(DYNAMICOBJECT_CASTER, caster->GetGUID()); // The lower word of DYNAMICOBJECT_BYTES must be 0x0001. This value means that the visual radius will be overriden diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 10136c5fbd7..5101d01899d 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -206,7 +206,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa UpdateRotationFields(rotation2, rotation3); // GAMEOBJECT_FACING, GAMEOBJECT_ROTATION, GAMEOBJECT_PARENTROTATION+2/3 - SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); + SetObjectScale(goinfo->size); SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); @@ -1674,7 +1674,7 @@ void GameObject::CastSpell(Unit* target, uint32 spellId) else { trigger->setFaction(14); - // Set owner guid for target if no owner avalible - needed by trigger auras + // Set owner guid for target if no owner available - needed by trigger auras // - trigger gets despawned and there's no caster avalible (see AuraEffect::TriggerSpell()) trigger->CastSpell(target ? target : trigger, spellInfo, true, 0, 0, target ? target->GetGUID() : 0); } diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp index 4eede93bd37..c4d4adeb6f2 100755 --- a/src/server/game/Entities/Item/Container/Bag.cpp +++ b/src/server/game/Entities/Item/Container/Bag.cpp @@ -78,7 +78,7 @@ bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner) Object::_Create(guidlow, 0, HIGHGUID_CONTAINER); SetEntry(itemid); - SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + SetObjectScale(1.0f); SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0); SetUInt64Value(ITEM_FIELD_CONTAINED, owner ? owner->GetGUID() : 0); diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index f2b893896dc..209fdae8ce6 100755 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -258,7 +258,7 @@ bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner) Object::_Create(guidlow, 0, HIGHGUID_ITEM); SetEntry(itemid); - SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + SetObjectScale(1.0f); SetUInt64Value(ITEM_FIELD_OWNER, owner ? owner->GetGUID() : 0); SetUInt64Value(ITEM_FIELD_CONTAINED, owner ? owner->GetGUID() : 0); @@ -274,7 +274,7 @@ bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner) for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) SetSpellCharges(i, itemProto->Spells[i].SpellCharges); - SetUInt32Value(ITEM_FIELD_DURATION, abs(itemProto->Duration)); + SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Duration); SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, 0); return true; } @@ -400,7 +400,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entr // Set entry, MUST be before proto check SetEntry(entry); - SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + SetObjectScale(1.0f); ItemTemplate const* proto = GetTemplate(); if (!proto) @@ -420,7 +420,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entr // update duration if need, and remove if not need if ((proto->Duration == 0) != (duration == 0)) { - SetUInt32Value(ITEM_FIELD_DURATION, abs(proto->Duration)); + SetUInt32Value(ITEM_FIELD_DURATION, proto->Duration); need_save = true; } diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h index 2eae7234229..1b5eec7fbaf 100755 --- a/src/server/game/Entities/Item/ItemPrototype.h +++ b/src/server/game/Entities/Item/ItemPrototype.h @@ -192,6 +192,12 @@ enum ItemFlagsExtra ITEM_FLAGS_EXTRA_NEED_ROLL_DISABLED = 0x00000100 }; +enum ItemFlagsCustom +{ + ITEM_FLAGS_CU_DURATION_REAL_TIME = 0x0001, // Item duration will tick even if player is offline + ITEM_FLAGS_CU_IGNORE_QUEST_STATUS = 0x0002, // No quest status will be checked when this item drops +}; + enum BAG_FAMILY_MASK { BAG_FAMILY_MASK_NONE = 0x00000000, @@ -644,7 +650,7 @@ struct ItemTemplate uint32 GemProperties; // id from GemProperties.dbc uint32 RequiredDisenchantSkill; float ArmorDamageModifier; - int32 Duration; // negative = realtime, positive = ingame time + uint32 Duration; uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc uint32 HolidayId; // id from Holidays.dbc uint32 ScriptId; @@ -652,6 +658,7 @@ struct ItemTemplate uint32 FoodType; uint32 MinMoneyLoot; uint32 MaxMoneyLoot; + uint32 FlagsCu; // helpers bool CanChangeEquipStateInCombat() const diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 3693f683b24..5a6a5799fee 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -34,11 +34,11 @@ #define CONTACT_DISTANCE 0.5f #define INTERACTION_DISTANCE 5.0f #define ATTACK_DISTANCE 5.0f -#define MAX_VISIBILITY_DISTANCE 500.0f // max distance for visible objects +#define MAX_VISIBILITY_DISTANCE SIZE_OF_GRIDS // max distance for visible objects #define SIGHT_RANGE_UNIT 50.0f -#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents -#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards -#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards +#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents +#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards +#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards #define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects #define DEFAULT_COMBAT_REACH 1.5f @@ -137,6 +137,8 @@ class Object uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); } void SetEntry(uint32 entry) { SetUInt32Value(OBJECT_FIELD_ENTRY, entry); } + void SetObjectScale(float scale) { SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } + TypeID GetTypeId() const { return m_objectTypeId; } bool isType(uint16 mask) const { return (mask & m_objectType); } diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index f3a736daceb..75deb8b4216 100755 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -870,7 +870,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel) else scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale); - SetFloatValue(OBJECT_FIELD_SCALE_X, scale); + SetObjectScale(scale); } // Resistance diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index f5f336a2402..4cf6d4ad979 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3153,7 +3153,7 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // reset size before reapply auras - SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + SetObjectScale(1.0f); // save base values (bonuses already included in stored stats for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) @@ -10157,7 +10157,8 @@ uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const if (inBankAlso) { - for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i) + // checking every item from 39 to 74 (including bank bags) + for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i) if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pItem != skipItem && pItem->GetEntry() == item) count += pItem->GetCount(); @@ -10197,7 +10198,7 @@ uint32 Player::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipIte if (Bag* pBag = GetBagByPos(i)) count += pBag->GetItemCountWithLimitCategory(limitCategory, skipItem); - for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i) + for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i) if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pItem != skipItem) if (ItemTemplate const* pProto = pItem->GetTemplate()) @@ -10223,7 +10224,7 @@ Item* Player::GetItemByGuid(uint64 guid) const if (pItem->GetGUID() == guid) return pItem; - for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i) + for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i) if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pItem->GetGUID() == guid) return pItem; @@ -12180,11 +12181,6 @@ Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update pItem->SetItemRandomProperties(randomPropertyId); pItem = StoreItem(dest, pItem, update); - const ItemTemplate* proto = pItem->GetTemplate(); - for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger - CastSpell(this, proto->Spells[i].SpellId, true, pItem); - if (allowedLooters.size() > 1 && pItem->GetTemplate()->GetMaxStackSize() == 1 && pItem->IsSoulBound()) { pItem->SetSoulboundTradeable(allowedLooters); @@ -12290,6 +12286,14 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool AddEnchantmentDurations(pItem); AddItemDurations(pItem); + + const ItemTemplate* proto = pItem->GetTemplate(); + for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger + if (bag == INVENTORY_SLOT_BAG_0 || (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)) + if (!HasAura(proto->Spells[i].SpellId)) + CastSpell(this, proto->Spells[i].SpellId, true, pItem); + return pItem; } else @@ -12326,6 +12330,13 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool pItem2->SetState(ITEM_CHANGED, this); + const ItemTemplate* proto = pItem2->GetTemplate(); + for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) + if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger + if (bag == INVENTORY_SLOT_BAG_0 || (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END)) + if (!HasAura(proto->Spells[i].SpellId)) + CastSpell(this, proto->Spells[i].SpellId, true, pItem2); + return pItem2; } } @@ -13654,7 +13665,7 @@ void Player::UpdateItemDuration(uint32 time, bool realtimeonly) Item* item = *itr; ++itr; // current element can be erased in UpdateDuration - if ((realtimeonly && item->GetTemplate()->Duration < 0) || !realtimeonly) + if (!realtimeonly || item->GetTemplate()->FlagsCu & ITEM_FLAGS_CU_DURATION_REAL_TIME) item->UpdateDuration(this, time); } } diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 9578605ac6f..95c6d308626 100755 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -214,7 +214,7 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa m_goInfo = goinfo; - SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); + SetObjectScale(goinfo->size); SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); @@ -656,6 +656,7 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, o + GetOrientation()); creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); + creature->SetTransportHomePosition(creature->m_movementInfo.t_pos); if (!creature->IsPositionValid()) { @@ -698,11 +699,33 @@ void Transport::UpdateNPCPositions() Creature* npc = *itr; float x, y, z, o; - o = GetOrientation() + npc->m_movementInfo.t_pos.m_orientation; - x = GetPositionX() + (npc->m_movementInfo.t_pos.m_positionX * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionY * sin(GetOrientation() + M_PI)); - y = GetPositionY() + (npc->m_movementInfo.t_pos.m_positionY * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionX * sin(GetOrientation())); - z = GetPositionZ() + npc->m_movementInfo.t_pos.m_positionZ; - npc->SetHomePosition(x, y, z, o); + npc->m_movementInfo.t_pos.GetPosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, o); GetMap()->CreatureRelocation(npc, x, y, z, o, false); + npc->GetTransportHomePosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, o); + npc->SetHomePosition(x, y, z, o); } } + +//! This method transforms supplied transport offsets into global coordinates +void Transport::CalculatePassengerPosition(float& x, float& y, float& z, float& o) +{ + float inx = x, iny = y, inz = z, ino = o; + o = GetOrientation() + ino; + x = GetPositionX() + (inx * cos(GetOrientation()) + iny * sin(GetOrientation() + M_PI)); + y = GetPositionY() + (iny * cos(GetOrientation()) + inx * sin(GetOrientation())); + z = GetPositionZ() + inz; +} + +//! This method transforms supplied global coordinates into local offsets +void Transport::CalculatePassengerOffset(float& x, float& y, float& z, float& o) +{ + o -= GetOrientation(); + z -= GetPositionZ(); + y -= GetPositionY(); // y = searchedY * cos(o) + searchedX * sin(o) + x -= GetPositionX(); // x = searchedX * cos(o) + searchedY * sin(o + pi) + float inx = x, iny = y; + y = (iny - inx * tan(GetOrientation())) / (cos(GetOrientation()) - sin(GetOrientation() + M_PI) * tan(GetOrientation())); + x = (inx - iny * sin(GetOrientation() + M_PI) / cos(GetOrientation())) / (cos(GetOrientation()) - tan(GetOrientation()) * sin(GetOrientation() + M_PI)); +} diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 518dcf6359d..4b0c42c9071 100755 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -47,6 +47,8 @@ class Transport : public GameObject uint32 AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, float z, float o, uint32 anim=0); void UpdatePosition(MovementInfo* mi); void UpdateNPCPositions(); + void CalculatePassengerPosition(float& x, float& y, float& z, float& o); + void CalculatePassengerOffset(float& x, float& y, float& z, float& o); void BuildStartMovePacket(Map const* targetMap); void BuildStopMovePacket(Map const* targetMap); uint32 GetScriptId() const { return ScriptId; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ba481176d23..bb2d057bfaa 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -396,10 +396,25 @@ void Unit::UpdateSplineMovement(uint32 t_diff) m_movesplineTimer.Reset(POSITION_UPDATE_DELAY); Movement::Location loc = movespline->ComputePosition(); - if (GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->UpdatePosition(loc.x,loc.y,loc.z,loc.orientation); - else - GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation); + if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { + Position& pos = m_movementInfo.t_pos; + pos.m_positionX = loc.x; + pos.m_positionY = loc.y; + pos.m_positionZ = loc.z; + pos.m_orientation = loc.orientation; + if (Unit* vehicle = GetVehicleBase()) + { + loc.x += vehicle->GetPositionX(); + loc.y += vehicle->GetPositionY(); + loc.z += vehicle->GetPositionZMinusOffset(); + loc.orientation = vehicle->GetOrientation(); + } + else if (Transport* trans = GetTransport()) + trans->CalculatePassengerPosition(loc.x, loc.y, loc.z, loc.orientation); + } + + UpdatePosition(loc.x, loc.y, loc.z, loc.orientation); } } @@ -414,13 +429,13 @@ void Unit::SendMonsterMoveExitVehicle(Position const* newPos) WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size()); data.append(GetPackGUID()); - data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // new in 3.1, bool + data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) data << GetPositionX() << GetPositionY() << GetPositionZ(); data << getMSTime(); data << uint8(SPLINETYPE_FACING_ANGLE); data << float(GetOrientation()); // guess - data << uint32(SPLINEFLAG_EXIT_VEHICLE); + data << uint32(SPLINEFLAG_TRANSPORT_EXIT); data << uint32(0); // Time in between points data << uint32(1); // 1 single waypoint data << newPos->GetPositionX(); @@ -437,7 +452,7 @@ void Unit::SendMonsterMoveTransport(Unit* vehicleOwner) data.append(GetPackGUID()); data.append(vehicleOwner->GetPackGUID()); data << int8(GetTransSeat()); - data << uint8(0); + data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) data << GetPositionX() - vehicleOwner->GetPositionX(); data << GetPositionY() - vehicleOwner->GetPositionY(); data << GetPositionZ() - vehicleOwner->GetPositionZ(); @@ -7366,30 +7381,16 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (procSpell->SpellIconID != 2019) return false; - AuraEffect* aurEffA = NULL; - AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE); - for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) + if (Creature* totem = GetMap()->GetCreature(m_SummonSlot[1])) // Fire totem summon slot { - SpellInfo const* spell = (*i)->GetSpellInfo(); - if (spell->SpellFamilyName == uint32(SPELLFAMILY_SHAMAN) && spell->SpellFamilyFlags.HasFlag(0, 0x02000000, 0)) + if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(totem->m_spells[0])) { - if ((*i)->GetCasterGUID() != GetGUID()) - continue; - if (spell->Id == 63283) - continue; - aurEffA = (*i); - break; + int32 bp0 = CalculatePctN(totemSpell->Effects[EFFECT_0].CalcValue(), triggerAmount); + int32 bp1 = CalculatePctN(totemSpell->Effects[EFFECT_1].CalcValue(), triggerAmount); + CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true); + return true; } } - if (aurEffA) - { - int32 bp0 = 0, bp1 = 0; - bp0 = CalculatePctN(triggerAmount, aurEffA->GetAmount()); - if (AuraEffect* aurEffB = aurEffA->GetBase()->GetEffect(EFFECT_1)) - bp1 = CalculatePctN(triggerAmount, aurEffB->GetAmount()); - CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true, NULL, triggeredByAura); - return true; - } return false; } break; @@ -7786,17 +7787,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } } } - // Item - Death Knight T10 Melee 4P Bonus - if (dummySpell->Id == 70656) - { - Player* player = ToPlayer(); - if (!player) - return false; - - for (uint32 i = 0; i < MAX_RUNES; ++i) - if (player->GetRuneCooldown(i) == 0) - return false; - } break; } case SPELLFAMILY_POTION: @@ -8064,7 +8054,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp *handled = true; if (victim && victim->HasAura(53601)) { - int32 bp0 = CalculatePctN(int32(damage / 12), dummySpell->Effects[EFFECT_2]. CalcValue()); + int32 bp0 = CalculatePctN(int32(damage / 12), dummySpell->Effects[EFFECT_2].CalcValue()); // Item - Paladin T9 Holy 4P Bonus if (AuraEffect const* aurEff = GetAuraEffect(67191, 0)) AddPctN(bp0, aurEff->GetAmount()); @@ -8724,6 +8714,16 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg trigger_spell_id = 50475; basepoints0 = CalculatePctN(int32(damage), triggerAmount); } + // Item - Death Knight T10 Melee 4P Bonus + else if (auraSpellInfo->Id == 70656) + { + if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT) + return false; + + for (uint8 i = 0; i < MAX_RUNES; ++i) + if (ToPlayer()->GetRuneCooldown(i) == 0) + return false; + } break; } case SPELLFAMILY_ROGUE: @@ -10206,7 +10206,7 @@ Unit* Unit::GetFirstControlled() const // Sequence: charmed, pet, other guardians Unit* unit = GetCharm(); if (!unit) - if (uint64 guid = GetUInt64Value(UNIT_FIELD_SUMMON)) + if (uint64 guid = GetMinionGUID()) unit = ObjectAccessor::GetUnit(*this, guid); return unit; @@ -12677,7 +12677,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) { // Set creature speed rate from CreatureInfo if (GetTypeId() == TYPEID_UNIT) - speed *= ToCreature()->GetCreatureTemplate()->speed_walk; + speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached // Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need // TODO: possible affect only on MOVE_RUN @@ -12997,8 +12997,7 @@ void Unit::TauntFadeOut(Unit* taunter) return; } - //m_ThreatManager.tauntFadeOut(taunter); - target = m_ThreatManager.getHostilTarget(); + target = creature->SelectVictim(); // might have more taunt auras remaining if (target && target != taunter) { @@ -14796,6 +14795,7 @@ void Unit::StopMoving() return; Movement::MoveSplineInit init(*this); + init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); init.SetFacing(GetOrientation()); init.Launch(); } @@ -17033,7 +17033,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) } if (IsInMap(caster)) - caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID); + caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, false, NULL, NULL, origCasterGUID); else // This can happen during Player::_LoadAuras { int32 bp0 = seatId; @@ -17043,7 +17043,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) else { if (IsInMap(caster)) - caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID); + caster->CastSpell(target, spellEntry, false, NULL, NULL, origCasterGUID); else Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID); } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index f246f595dec..65a165b40d2 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -737,15 +737,48 @@ enum MovementFlags2 enum SplineFlags { - SPLINEFLAG_WALKMODE = 0x00001000, - SPLINEFLAG_FLYING = 0x00002000, - SPLINEFLAG_TRANSPORT = 0x00800000, - SPLINEFLAG_EXIT_VEHICLE = 0x01000000, + SPLINEFLAG_NONE = 0x00000000, + SPLINEFLAG_FORWARD = 0x00000001, + SPLINEFLAG_BACKWARD = 0x00000002, + SPLINEFLAG_STRAFE_LEFT = 0x00000004, + SPLINEFLAG_STRAFE_RIGHT = 0x00000008, + SPLINEFLAG_TURN_LEFT = 0x00000010, + SPLINEFLAG_TURN_RIGHT = 0x00000020, + SPLINEFLAG_PITCH_UP = 0x00000040, + SPLINEFLAG_PITCH_DOWN = 0x00000080, + SPLINEFLAG_DONE = 0x00000100, + SPLINEFLAG_FALLING = 0x00000200, + SPLINEFLAG_NO_SPLINE = 0x00000400, + SPLINEFLAG_TRAJECTORY = 0x00000800, + SPLINEFLAG_WALK_MODE = 0x00001000, + SPLINEFLAG_FLYING = 0x00002000, + SPLINEFLAG_KNOCKBACK = 0x00004000, + SPLINEFLAG_FINAL_POINT = 0x00008000, + SPLINEFLAG_FINAL_TARGET = 0x00010000, + SPLINEFLAG_FINAL_FACING = 0x00020000, + SPLINEFLAG_CATMULL_ROM = 0x00040000, + SPLINEFLAG_CYCLIC = 0x00080000, + SPLINEFLAG_ENTER_CYCLE = 0x00100000, + SPLINEFLAG_ANIMATION_TIER = 0x00200000, + SPLINEFLAG_FROZEN = 0x00400000, + SPLINEFLAG_TRANSPORT = 0x00800000, + SPLINEFLAG_TRANSPORT_EXIT = 0x01000000, + SPLINEFLAG_UNKNOWN7 = 0x02000000, + SPLINEFLAG_UNKNOWN8 = 0x04000000, + SPLINEFLAG_ORIENTATION_INVERTED = 0x08000000, + SPLINEFLAG_USE_PATH_SMOOTHING = 0x10000000, + SPLINEFLAG_ANIMATION = 0x20000000, + SPLINEFLAG_UNCOMPRESSED_PATH = 0x40000000, + SPLINEFLAG_UNKNOWN10 = 0x80000000, }; enum SplineType { - SPLINETYPE_FACING_ANGLE = 4, + SPLINETYPE_NORMAL = 0, + SPLINETYPE_STOP = 1, + SPLINETYPE_FACING_SPOT = 2, + SPLINETYPE_FACING_TARGET = 3, + SPLINETYPE_FACING_ANGLE = 4, }; enum UnitTypeMask diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index c297ce1e792..04bcfdcc375 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -338,7 +338,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) } } - if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_UNK1)) + if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)) unit->AddUnitState(UNIT_STATE_ONVEHICLE); unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 9dea557f650..df6018faf39 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2111,9 +2111,9 @@ void ObjectMgr::LoadItemTemplates() // 118 119 120 121 122 123 124 125 "TotemCategory, socketColor_1, socketContent_1, socketColor_2, socketContent_2, socketColor_3, socketContent_3, socketBonus, " // 126 127 128 129 130 131 132 133 - "GemProperties, RequiredDisenchantSkill, ArmorDamageModifier, Duration, ItemLimitCategory, HolidayId, ScriptName, DisenchantID, " + "GemProperties, RequiredDisenchantSkill, ArmorDamageModifier, duration, ItemLimitCategory, HolidayId, ScriptName, DisenchantID, " // 134 135 136 - "FoodType, minMoneyLoot, maxMoneyLoot FROM item_template"); + "FoodType, minMoneyLoot, maxMoneyLoot, flagsCustom FROM item_template"); if (!result) { @@ -2230,7 +2230,7 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.GemProperties = fields[126].GetUInt32(); itemTemplate.RequiredDisenchantSkill = uint32(fields[127].GetInt16()); itemTemplate.ArmorDamageModifier = fields[128].GetFloat(); - itemTemplate.Duration = fields[129].GetInt32(); + itemTemplate.Duration = fields[129].GetUInt32(); itemTemplate.ItemLimitCategory = uint32(fields[130].GetInt16()); itemTemplate.HolidayId = fields[131].GetUInt32(); itemTemplate.ScriptId = sObjectMgr->GetScriptId(fields[132].GetCString()); @@ -2238,6 +2238,7 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.FoodType = uint32(fields[134].GetUInt8()); itemTemplate.MinMoneyLoot = fields[135].GetUInt32(); itemTemplate.MaxMoneyLoot = fields[136].GetUInt32(); + itemTemplate.FlagsCu = fields[137].GetUInt32(); // Checks @@ -2645,6 +2646,12 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.HolidayId = 0; } + if (itemTemplate.FlagsCu & ITEM_FLAGS_CU_DURATION_REAL_TIME && !itemTemplate.Duration) + { + sLog->outErrorDb("Item (Entry %u) has flag ITEM_FLAGS_CU_DURATION_REAL_TIME but it does not have duration limit", entry); + itemTemplate.FlagsCu &= ~ITEM_FLAGS_CU_DURATION_REAL_TIME; + } + ++count; } while (result->NextRow()); @@ -2731,7 +2738,7 @@ void ObjectMgr::LoadItemSetNames() if (setEntry->itemId[i]) itemSetItems.insert(setEntry->itemId[i]); } - + // 0 1 2 QueryResult result = WorldDatabase.Query("SELECT `entry`, `name`, `InventoryType` FROM `item_set_names`"); @@ -6247,74 +6254,54 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) switch (guidhigh) { case HIGHGUID_ITEM: - if (_hiItemGuid >= 0xFFFFFFFE) - { - sLog->outError("Item guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiItemGuid < 0xFFFFFFFE && "Item guid overflow!"); return _hiItemGuid++; + } case HIGHGUID_UNIT: - if (_hiCreatureGuid >= 0x00FFFFFE) - { - sLog->outError("Creature guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiCreatureGuid < 0x00FFFFFE && "Creature guid overflow!"); return _hiCreatureGuid++; + } case HIGHGUID_PET: - if (_hiPetGuid >= 0x00FFFFFE) - { - sLog->outError("Pet guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiPetGuid < 0x00FFFFFE && "Pet guid overflow!"); return _hiPetGuid++; + } case HIGHGUID_VEHICLE: - if (_hiVehicleGuid >= 0x00FFFFFF) - { - sLog->outError("Vehicle guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiVehicleGuid < 0x00FFFFFF && "Vehicle guid overflow!"); return _hiVehicleGuid++; + } case HIGHGUID_PLAYER: - if (_hiCharGuid >= 0xFFFFFFFE) - { - sLog->outError("Players guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiCharGuid < 0xFFFFFFFE && "Player guid overflow!"); return _hiCharGuid++; + } case HIGHGUID_GAMEOBJECT: - if (_hiGoGuid >= 0x00FFFFFE) - { - sLog->outError("Gameobject guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiGoGuid < 0x00FFFFFE && "Gameobject guid overflow!"); return _hiGoGuid++; + } case HIGHGUID_CORPSE: - if (_hiCorpseGuid >= 0xFFFFFFFE) - { - sLog->outError("Corpse guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiCorpseGuid < 0xFFFFFFFE && "Corpse guid overflow!"); return _hiCorpseGuid++; + } case HIGHGUID_DYNAMICOBJECT: - if (_hiDoGuid >= 0xFFFFFFFE) - { - sLog->outError("DynamicObject guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiDoGuid < 0xFFFFFFFE && "DynamicObject guid overflow!"); return _hiDoGuid++; + } case HIGHGUID_MO_TRANSPORT: - if (_hiMoTransGuid >= 0xFFFFFFFE) - { - sLog->outError("MO Transport guid overflow!! Can't continue, shutting down server. "); - World::StopNow(ERROR_EXIT_CODE); - } + { + ASSERT(_hiMoTransGuid < 0xFFFFFFFE && "MO Transport guid overflow!"); return _hiMoTransGuid++; + } default: - ASSERT(0); + ASSERT(false && "ObjectMgr::GenerateLowGuid - Unknown HIGHGUID type"); + return 0; } - - ASSERT(0); - return 0; } void ObjectMgr::LoadGameObjectLocales() diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp index 9a3e756dda3..49027bdf497 100755 --- a/src/server/game/Handlers/AuthHandler.cpp +++ b/src/server/game/Handlers/AuthHandler.cpp @@ -31,7 +31,7 @@ void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos) if (!shortForm) { packet << uint32(queuePos); // Queue position - packet << uint8(0); // Unk 3.3.0 + packet << uint8(0); // Realm has a free character migration - bool } SendPacket(&packet); diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index d1277d154cc..298c742fc3a 100755 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -20,7 +20,7 @@ ----- Opcodes Not Used yet ----- SMSG_CALENDAR_CLEAR_PENDING_ACTION SendCalendarClearPendingAction() -SMSG_CALENDAR_RAID_LOCKOUT_UPDATED SendCalendarRaidLockoutUpdated(InstanceSave const* save) <--- Structure unknown, using LOCKOUT_ADDED +SMSG_CALENDAR_RAID_LOCKOUT_UPDATED SendCalendarRaidLockoutUpdated(InstanceSave const* save) ----- Opcodes without Sniffs ----- SMSG_CALENDAR_FILTER_GUILD [ for (... uint32(count) { packguid(???), uint8(???) } ] @@ -74,7 +74,11 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/) else { sLog->outError("SMSG_CALENDAR_SEND_CALENDAR: No Invite found with id [" UI64FMTD "]", *it); - data << uint64(0) << uint64(0) << uint8(0) << uint8(0); + data << uint64(0); + data << uint64(0); + data << uint8(0); + data << uint8(0); + data << uint8(0); data.appendPackGUID(0); } } @@ -96,8 +100,12 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/) else { sLog->outError("SMSG_CALENDAR_SEND_CALENDAR: No Event found with id [" UI64FMTD "]", *it); - data << uint64(0) << uint8(0) << uint32(0) - << uint32(0) << uint32(0) << uint32(0); + data << uint64(0); + data << uint8(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); data.appendPackGUID(0); } } @@ -835,26 +843,6 @@ void WorldSession::SendCalendarClearPendingAction() SendPacket(&data); } -void WorldSession::SendCalendarRaidLockoutUpdated(InstanceSave const* save) -{ - if (!save) - return; - - uint64 guid = _player->GetGUID(); - sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_CALENDAR_RAID_LOCKOUT_UPDATED [" UI64FMTD - "] Map: %u, Difficulty %u", guid, save->GetMapId(), save->GetDifficulty()); - - time_t cur_time = time_t(time(NULL)); - - WorldPacket data(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, 4 + 4 + 4 + 4 + 8); - data << secsToTimeBitFields(cur_time); - data << uint32(save->GetMapId()); - data << uint32(save->GetDifficulty()); - data << uint32(save->GetResetTime() - cur_time); - data << uint64(save->GetInstanceId()); - SendPacket(&data); -} - void WorldSession::SendCalendarCommandResult(CalendarError err, char const* param /*= NULL*/) { uint64 guid = _player->GetGUID(); @@ -898,3 +886,23 @@ void WorldSession::SendCalendarRaidLockout(InstanceSave const* save, bool add) data << uint64(save->GetInstanceId()); SendPacket(&data); } + +void WorldSession::SendCalendarRaidLockoutUpdated(InstanceSave const* save) +{ + if (!save) + return; + + uint64 guid = _player->GetGUID(); + sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_CALENDAR_RAID_LOCKOUT_UPDATED [" UI64FMTD + "] Map: %u, Difficulty %u", guid, save->GetMapId(), save->GetDifficulty()); + + time_t cur_time = time_t(time(NULL)); + + WorldPacket data(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, 4 + 4 + 4 + 4 + 8); + data << secsToTimeBitFields(cur_time); + data << uint32(save->GetMapId()); + data << uint32(save->GetDifficulty()); + data << uint32(0); // Amount of seconds that has changed to the reset time + data << uint32(save->GetResetTime() - cur_time); + SendPacket(&data); +} diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index d537fc5b4aa..a569c914be0 100755 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -423,7 +423,7 @@ void WorldSession::HandleItemQuerySingleOpcode(WorldPacket & recv_data) data << pProto->GemProperties; data << pProto->RequiredDisenchantSkill; data << pProto->ArmorDamageModifier; - data << uint32(abs(pProto->Duration)); // added in 2.4.2.8209, duration (seconds) + data << pProto->Duration; // added in 2.4.2.8209, duration (seconds) data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory data << pProto->HolidayId; // Holiday.dbc? SendPacket(&data); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 35872f8c63f..11f0857ca2b 100755 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -51,6 +51,7 @@ #include "GameObjectAI.h" #include "Group.h" #include "AccountMgr.h" +#include "Spell.h" void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data) { @@ -429,6 +430,10 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LOGOUT_CANCEL Message"); + // Player have already logged out serverside, too late to cancel + if (!GetPlayer()) + return; + LogoutRequest(0); WorldPacket data(SMSG_LOGOUT_CANCEL_ACK, 0); @@ -489,7 +494,7 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) uint32 newZone; recv_data >> newZone; - sLog->outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd ZONE_UPDATE: %u", newZone); // use server size data uint32 newzone, newarea; @@ -725,7 +730,7 @@ void WorldSession::HandleBugOpcode(WorldPacket & recv_data) void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) { - sLog->outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RECLAIM_CORPSE"); uint64 guid; recv_data >> guid; @@ -762,7 +767,7 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) { - sLog->outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RESURRECT_RESPONSE"); uint64 guid; uint8 status; @@ -933,7 +938,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) { - sLog->outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); uint32 type, timestamp, decompressedSize; recv_data >> type >> timestamp >> decompressedSize; @@ -988,7 +993,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) { - sLog->outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); uint32 type; recv_data >> type; @@ -1067,18 +1072,18 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) void WorldSession::HandleCompleteCinematic(WorldPacket & /*recv_data*/) { - sLog->outStaticDebug("WORLD: Player is watching cinema"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_COMPLETE_CINEMATIC"); } void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recv_data*/) { - sLog->outStaticDebug("WORLD: Which movie to play"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_NEXT_CINEMATIC_CAMERA"); } void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) { /* WorldSession::Update(getMSTime());*/ - sLog->outStaticDebug("WORLD: Time Lag/Synchronization Resent/Update"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_TIME_SKIPPED"); uint64 guid; recv_data.readPackGUID(guid); @@ -1100,7 +1105,7 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) { - sLog->outStaticDebug("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); // no used recv_data.rfinish(); // prevent warnings spam @@ -1188,13 +1193,17 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) { uint64 guid; recv_data >> guid; - sLog->outStaticDebug("Inspected guid is " UI64FMTD, guid); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_INSPECT"); _player->SetSelection(guid); Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) // wrong player + if (!player) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_INSPECT: No player found from GUID: " UI64FMTD, guid); return; + } uint32 talent_points = 0x47; uint32 guid_size = player->GetPackGUID().wpos(); @@ -1225,7 +1234,7 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) if (!player) { - sLog->outError("InspectHonorStats: WTF, player not found..."); + sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_INSPECT_HONOR_STATS: No player found from GUID: " UI64FMTD, guid); return; } @@ -1241,10 +1250,6 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) { - // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180 - // Received opcode CMSG_WORLD_TELEPORT - // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593 - uint32 time; uint32 mapid; float PositionX; @@ -1259,20 +1264,20 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) recv_data >> PositionZ; recv_data >> Orientation; // o (3.141593 = 180 degrees) - //sLog->outDebug("Received opcode CMSG_WORLD_TELEPORT"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_WORLD_TELEPORT"); + if (GetPlayer()->isInFlight()) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) in flight, ignore worldport command.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); return; } - sLog->outStaticDebug("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time/1000, mapid, PositionX, PositionY, PositionZ, Orientation); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_WORLD_TELEPORT: Player = %s, Time = %u, map = %u, x = %f, y = %f, z = %f, o = %f", GetPlayer()->GetName(), time, mapid, PositionX, PositionY, PositionZ, Orientation); if (AccountMgr::IsAdminAccount(GetSecurity())) GetPlayer()->TeleportTo(mapid, PositionX, PositionY, PositionZ, Orientation); else SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received worldport command from player %s", GetPlayer()->GetName()); } void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) @@ -1714,3 +1719,47 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket) _player->SetPendingBind(0, 0); } + +void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket) +{ + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY"); + + uint64 guid; + uint32 spellId; + float elevation, speed; + float curX, curY, curZ; + float targetX, targetY, targetZ; + uint8 moveStop; + + recvPacket >> guid >> spellId >> elevation >> speed; + recvPacket >> curX >> curY >> curZ; + recvPacket >> targetX >> targetY >> targetZ; + recvPacket >> moveStop; + + Unit* caster = ObjectAccessor::GetUnit(*_player, guid); + Spell* spell = caster ? caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) : NULL; + if (!spell || spell->m_spellInfo->Id != spellId || !spell->m_targets.HasDst() || !spell->m_targets.HasSrc()) + { + recvPacket.rfinish(); + return; + } + + Position pos = *spell->m_targets.GetSrcPos(); + pos.Relocate(curX, curY, curZ); + spell->m_targets.ModSrc(pos); + + pos = *spell->m_targets.GetDstPos(); + pos.Relocate(targetX, targetY, targetZ); + spell->m_targets.ModDst(pos); + + spell->m_targets.SetElevation(elevation); + spell->m_targets.SetSpeed(speed); + + if (moveStop) + { + uint32 opcode; + recvPacket >> opcode; + recvPacket.SetOpcode(opcode); + HandleMovementOpcodes(recvPacket); + } +} diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index b3d663e1850..ff9030f04d5 100755 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -64,10 +64,9 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->m_InstanceValid = true; Map* oldMap = GetPlayer()->GetMap(); - ASSERT(oldMap); if (GetPlayer()->IsInWorld()) { - sLog->outCrash("Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName(), oldMap->GetId(), loc.GetMapId()); + sLog->outError("Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName(), oldMap->GetId(), loc.GetMapId()); oldMap->RemovePlayerFromMap(GetPlayer(), false); } @@ -200,8 +199,7 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) sLog->outStaticDebug("Guid " UI64FMTD, guid); sLog->outStaticDebug("Flags %u, time %u", flags, time/IN_MILLISECONDS); - Unit* mover = _player->m_mover; - Player* plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; + Player* plMover = _player->m_mover->ToPlayer(); if (!plMover || !plMover->IsBeingTeleportedNear()) return; @@ -240,33 +238,33 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) GetPlayer()->ProcessDelayedOperations(); } -void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) +void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) { - uint16 opcode = recv_data.GetOpcode(); + uint16 opcode = recvData.GetOpcode(); Unit* mover = _player->m_mover; - ASSERT(mover != NULL); // there must always be a mover + ASSERT(mover != NULL); // there must always be a mover - Player* plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; + Player* plrMover = mover->ToPlayer(); // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck - if (plMover && plMover->IsBeingTeleported()) + if (plrMover && plrMover->IsBeingTeleported()) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } /* extract packet */ uint64 guid; - recv_data.readPackGUID(guid); + recvData.readPackGUID(guid); MovementInfo movementInfo; movementInfo.guid = guid; - ReadMovementInfo(recv_data, &movementInfo); + ReadMovementInfo(recvData, &movementInfo); - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam // prevent tampered movement data if (guid != mover->GetGUID()) @@ -274,7 +272,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) if (!movementInfo.pos.IsPositionValid()) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } @@ -285,28 +283,54 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) if (movementInfo.t_pos.GetPositionX() > 50 || movementInfo.t_pos.GetPositionY() > 50 || movementInfo.t_pos.GetPositionZ() > 50) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(), movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation())) { - recv_data.rfinish(); // prevent warnings spam + recvData.rfinish(); // prevent warnings spam return; } // if we boarded a transport, add us to it - if (plMover && !plMover->GetTransport()) + if (plrMover) { - // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list - for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) + if (!plrMover->GetTransport()) + { + // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list + for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) + { + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + plrMover->m_transport = *iter; + (*iter)->AddPassenger(plrMover); + break; + } + } + } + else if (plrMover->GetTransport()->GetGUID() != movementInfo.t_guid) { - if ((*iter)->GetGUID() == movementInfo.t_guid) + bool foundNewTransport = false; + plrMover->m_transport->RemovePassenger(plrMover); + for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) + { + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + foundNewTransport = true; + plrMover->m_transport = *iter; + (*iter)->AddPassenger(plrMover); + break; + } + } + + if (!foundNewTransport) { - plMover->m_transport = (*iter); - (*iter)->AddPassenger(plMover); - break; + plrMover->m_transport = NULL; + movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); + movementInfo.t_time = 0; + movementInfo.t_seat = -1; } } } @@ -318,29 +342,29 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; } } - else if (plMover && plMover->GetTransport()) // if we were on a transport, leave + else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave { - plMover->m_transport->RemovePassenger(plMover); - plMover->m_transport = NULL; + plrMover->m_transport->RemovePassenger(plrMover); + plrMover->m_transport = NULL; movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); movementInfo.t_time = 0; movementInfo.t_seat = -1; } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight()) - plMover->HandleFall(movementInfo); + if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->isInFlight()) + plrMover->HandleFall(movementInfo); - if (plMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plMover->IsInWater()) + if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water - plMover->SetInWater(!plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); + plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } /*----------------------*/ /* process position-change */ - WorldPacket data(opcode, recv_data.size()); + WorldPacket data(opcode, recvData.size()); movementInfo.time = getMSTime(); movementInfo.guid = mover->GetGUID(); WriteMovementInfo(&data, &movementInfo); @@ -357,27 +381,25 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data) mover->UpdatePosition(movementInfo.pos); - if (plMover) // nothing is charmed, or player charmed + if (plrMover) // nothing is charmed, or player charmed { - plMover->UpdateFallInformationIfNeed(movementInfo, opcode); + plrMover->UpdateFallInformationIfNeed(movementInfo, opcode); if (movementInfo.pos.GetPositionZ() < -500.0f) { - if (!(plMover->InBattleground() - && plMover->GetBattleground() - && plMover->GetBattleground()->HandlePlayerUnderMap(_player))) + if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player))) { // NOTE: this is actually called many times while falling // even after the player has been teleported away // TODO: discard movement packets after the player is rooted - if (plMover->isAlive()) + if (plrMover->isAlive()) { - plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); + plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); // player can be alive if GM/etc // change the death state to CORPSE to prevent the death timer from // starting in the next player update - if (!plMover->isAlive()) - plMover->KillPlayer(); + if (!plrMover->isAlive()) + plrMover->KillPlayer(); } } } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index e54bee96b8b..321c0ada247 100755 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -339,9 +339,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid if (unit_target2->GetTypeId() == TYPEID_PLAYER) pet->SendUpdateToPlayer((Player*)unit_target2); } + if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer(powner->ToPlayer()); + pet->SendUpdateToPlayer(powner->ToPlayer()); + result = SPELL_CAST_OK; } @@ -741,7 +743,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { - sLog->outDetail("WORLD: CMSG_PET_CAST_SPELL"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_CAST_SPELL"); uint64 guid; uint8 castCount; diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 628cdbbdd5e..4fb90bed10b 100755 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -113,7 +113,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) ObjectMgr::GetLocaleString(cl->SubName, loc_idx, SubName); } } - sLog->outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); // guess size WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); data << uint32(entry); // creature entry @@ -179,7 +179,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) ObjectMgr::GetLocaleString(gl->CastBarCaption, loc_idx, CastBarCaption); } } - sLog->outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); data << uint32(entry); data << uint32(info->type); @@ -209,7 +209,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) { - sLog->outDetail("WORLD: Received MSG_CORPSE_QUERY"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_CORPSE_QUERY"); Corpse* corpse = GetPlayer()->GetCorpse(); @@ -264,7 +264,7 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) uint64 guid; recv_data >> textID; - sLog->outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); recv_data >> guid; GetPlayer()->SetSelection(guid); @@ -344,7 +344,7 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) /// Only _static_ data is sent in this packet !!! void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) { - sLog->outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PAGE_TEXT_QUERY"); uint32 pageID; recv_data >> pageID; diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index b2d52c85467..c02bb43a353 100755 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -99,7 +99,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) return; } - sLog->outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size()); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size()); ItemTemplate const* proto = pItem->GetTemplate(); if (!proto) @@ -175,7 +175,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) { - sLog->outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); Player* pUser = _player; @@ -650,18 +650,30 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) uint8 castCount; float x, y, z; // Position of missile hit - recvPacket.readPackGUID(casterGuid); + recvPacket >> casterGuid; recvPacket >> spellId; recvPacket >> castCount; recvPacket >> x; recvPacket >> y; recvPacket >> z; + Unit* caster = ObjectAccessor::GetUnit(*_player, casterGuid); + if (!caster) + return; + + Spell* spell = caster->FindCurrentSpellBySpellId(spellId); + if (!spell || !spell->m_targets.HasDst()) + return; + + Position pos = *spell->m_targets.GetDstPos(); + pos.Relocate(x, y, z); + spell->m_targets.ModDst(pos); + WorldPacket data(SMSG_SET_PROJECTILE_POSITION, 21); data << uint64(casterGuid); data << uint8(castCount); data << float(x); data << float(y); data << float(z); - SendPacket(&data); + caster->SendMessageToSet(&data, true); } diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index dc26aaa42ca..9d7fa7da396 100755 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -531,7 +531,7 @@ void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/) void WorldSession::SendCancelTrade() { - if (m_playerRecentlyLogout) + if (PlayerRecentlyLoggedOut() || PlayerLogout()) return; SendTradeStatus(TRADE_STATUS_TRADE_CANCELED); diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 75065158ef6..a5ad46c9ec4 100755 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -356,18 +356,9 @@ bool LootItem::AllowedForPlayer(Player const* player) const if ((pProto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE) return false; - if (needs_quest) - { - // Checking quests for quest-only drop (check only quests requirements in this case) - if (!player->HasQuestForItem(itemid)) - return false; - } - else - { - // Not quest only drop (check quest starting items for already accepted non-repeatable quests) - if (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE && !player->HasQuestForItem(itemid)) - return false; - } + // check quest requirements + if (!(pProto->FlagsCu & ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && ((needs_quest || (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE)) && !player->HasQuestForItem(itemid))) + return false; return true; } diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index c0e1eb842ae..bc0570bb73b 100755 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -298,7 +298,7 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z) } } -void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed) +void MotionMaster::MoveLand(uint32 id, Position const& pos) { float x, y, z; pos.GetPosition(x, y, z); @@ -307,13 +307,12 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed) Movement::MoveSplineInit init(*_owner); init.MoveTo(x,y,z); - init.SetVelocity(speed); init.SetAnimation(Movement::ToGround); init.Launch(); Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); } -void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed) +void MotionMaster::MoveTakeoff(uint32 id, Position const& pos) { float x, y, z; pos.GetPosition(x, y, z); @@ -322,7 +321,6 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed) Movement::MoveSplineInit init(*_owner); init.MoveTo(x,y,z); - init.SetVelocity(speed); init.SetAnimation(Movement::ToFly); init.Launch(); Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index d6144bfcc3a..727f626cdea 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -157,8 +157,8 @@ class MotionMaster //: private std::stack<MovementGenerator *> void MovePoint(uint32 id, float x, float y, float z); // These two movement types should only be used with creatures having landing/takeoff animations - void MoveLand(uint32 id, Position const& pos, float speed); - void MoveTakeoff(uint32 id, Position const& pos, float speed); + void MoveLand(uint32 id, Position const& pos); + void MoveTakeoff(uint32 id, Position const& pos); void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE); void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index 91b4ff08250..b1c25aedfd7 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -203,7 +203,7 @@ bool MoveSplineInitArgs::Validate() const return false;\ } CHECK(path.size() > 1); - CHECK(velocity > 0.f); + CHECK(velocity > 0.1f); CHECK(time_perc >= 0.f && time_perc <= 1.f); //CHECK(_checkPathBounds()); return true; diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index e586cb4f4f9..c5f959e2f1d 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -20,6 +20,8 @@ #include "MoveSpline.h" #include "MovementPacketBuilder.h" #include "Unit.h" +#include "Transport.h" +#include "Vehicle.h" namespace Movement { @@ -58,17 +60,25 @@ namespace Movement { MoveSpline& move_spline = *unit.movespline; - Location real_position(unit.GetPositionX(),unit.GetPositionY(),unit.GetPositionZMinusOffset(),unit.GetOrientation()); - // there is a big chane that current position is unknown if current state is not finalized, need compute it + bool transport = false; + Location real_position(unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZMinusOffset(), unit.GetOrientation()); + if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { + transport = true; + real_position.x = unit.GetTransOffsetX(); + real_position.y = unit.GetTransOffsetY(); + real_position.z = unit.GetTransOffsetZ(); + real_position.orientation = unit.GetTransOffsetO(); + } + + // there is a big chance that current position is unknown if current state is not finalized, need compute it // this also allows calculate spline position and update map position in much greater intervals if (!move_spline.Finalized()) real_position = move_spline.ComputePosition(); + // should i do the things that user should do? - no. if (args.path.empty()) - { - // should i do the things that user should do? - MoveTo(real_position); - } + return; // corrent first vertex args.path[0] = real_position; @@ -82,7 +92,7 @@ namespace Movement moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD); - if (args.velocity == 0.f) + if (!args.HasVelocity) args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags)); if (!args.Validate()) @@ -94,8 +104,20 @@ namespace Movement unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags); move_spline.Initialize(args); - WorldPacket data(SMSG_MONSTER_MOVE, 64); + WorldPacket data(!transport ? SMSG_MONSTER_MOVE : SMSG_MONSTER_MOVE_TRANSPORT, 64); data.append(unit.GetPackGUID()); + if (transport) + { + if (unit.GetVehicle()) + data.appendPackGUID(unit.GetVehicleBase()->GetGUID()); + else if (unit.GetTransport()) + data.appendPackGUID(unit.GetTransGUID()); + else + data << uint8(0); + + data << int8(unit.GetTransSeat()); + } + PacketBuilder::WriteMonsterMove(move_spline, data); unit.SendMessageToSet(&data,true); } @@ -116,7 +138,44 @@ namespace Movement void MoveSplineInit::SetFacing(float angle) { + if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { + if (Unit* vehicle = unit.GetVehicleBase()) + angle -= vehicle->GetOrientation(); + else if (Transport* transport = unit.GetTransport()) + angle -= transport->GetOrientation(); + } + args.facing.angle = G3D::wrap(angle, 0.f, (float)G3D::twoPi()); args.flags.EnableFacingAngle(); } + + void MoveSplineInit::MoveTo(Vector3 const& dest) + { + args.path_Idx_offset = 0; + args.path.resize(2); + TransportPathTransform transform(unit); + args.path[1] = transform(dest); + } + + Vector3 TransportPathTransform::operator()(Vector3 input) + { + if (_owner.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { + if (Unit* vehicle = _owner.GetVehicleBase()) + { + input.x -= vehicle->GetPositionX(); + input.y -= vehicle->GetPositionY(); + input.z -= vehicle->GetPositionZMinusOffset(); + } + else if (Transport* transport = _owner.GetTransport()) + { + float unused = 0.0f; + transport->CalculatePassengerOffset(input.x, input.y, input.z, unused); + } + } + + return input; + } + } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 7ef6cd7a120..786324e3f77 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -33,6 +33,17 @@ namespace Movement FlyToGround = 3, // 463 = FlyToGround }; + // Transforms coordinates from global to transport offsets + class TransportPathTransform + { + public: + TransportPathTransform(Unit& owner) : _owner(owner) { } + Vector3 operator()(Vector3 input); + + private: + Unit& _owner; + }; + /* Initializes and launches spline movement */ class MoveSplineInit @@ -123,14 +134,15 @@ namespace Movement inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();} inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;} inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();} - inline void MoveSplineInit::SetVelocity(float vel){ args.velocity = vel;} + inline void MoveSplineInit::SetVelocity(float vel) { args.velocity = vel; args.HasVelocity = true; } inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;} inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;} inline void MoveSplineInit::MovebyPath(const PointsArray& controls, int32 path_offset) { args.path_Idx_offset = path_offset; - args.path.assign(controls.begin(),controls.end()); + args.path.resize(controls.size()); + std::transform(controls.begin(), controls.end(), args.path.begin(), TransportPathTransform(unit)); } inline void MoveSplineInit::MoveTo(float x, float y, float z) @@ -139,13 +151,6 @@ namespace Movement MoveTo(v); } - inline void MoveSplineInit::MoveTo(const Vector3& dest) - { - args.path_Idx_offset = 0; - args.path.resize(2); - args.path[1] = dest; - } - inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift) { args.time_perc = time_shift; @@ -161,9 +166,11 @@ namespace Movement inline void MoveSplineInit::SetFacing(Vector3 const& spot) { - args.facing.f.x = spot.x; - args.facing.f.y = spot.y; - args.facing.f.z = spot.z; + TransportPathTransform transform(unit); + Vector3 finalSpot = transform(spot); + args.facing.f.x = finalSpot.x; + args.facing.f.y = finalSpot.y; + args.facing.f.z = finalSpot.z; args.flags.EnableFacingPoint(); } } diff --git a/src/server/game/Movement/Spline/MoveSplineInitArgs.h b/src/server/game/Movement/Spline/MoveSplineInitArgs.h index 26fbbdd0fcc..74409c9562b 100644 --- a/src/server/game/Movement/Spline/MoveSplineInitArgs.h +++ b/src/server/game/Movement/Spline/MoveSplineInitArgs.h @@ -42,7 +42,7 @@ namespace Movement struct MoveSplineInitArgs { MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0), - velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f) + velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), HasVelocity(false) { path.reserve(path_capacity); } @@ -56,6 +56,7 @@ namespace Movement float time_perc; uint32 splineId; float initialOrientation; + bool HasVelocity; /** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */ bool Validate() const; diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp index 0260767dbe2..16f06a25058 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp @@ -44,20 +44,8 @@ namespace Movement void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data) { MoveSplineFlag splineflags = move_spline.splineflags; - /*if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - { - data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); - if (unit->GetVehicle()) - data << unit->GetVehicle()->GetBase()->GetPackGUID(); - else if (unit->GetTransport()) - data << unit->GetTransport()->GetPackGUID(); - else - data << uint64(0); - - data << int8(unit->GetTransSeat()); - }*/ - data << uint8(0); + data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) data << move_spline.spline.getPoint(move_spline.spline.first()); data << move_spline.GetId(); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 517935acbd2..8fb8ea0298b 100755 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -104,7 +104,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode }, /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode }, + /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode }, /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNameQueryOpcode }, /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, @@ -310,7 +310,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode }, /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode }, /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode }, - /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode}, + /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode }, /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode }, /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode }, /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode }, @@ -1148,7 +1148,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x45F*/ { "CMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL }, /*0x460*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x461*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL }, + /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory }, /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL }, diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 3c77ced6741..65e7b3597ce 100755 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -1248,8 +1248,8 @@ enum Opcodes SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x4BB, SMSG_EQUIPMENT_SET_LIST = 0x4BC, // equipment manager list? CMSG_EQUIPMENT_SET_SAVE = 0x4BD, - CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE, // uint64 caster, uint32 spellId, uint8 castId, vector3 position - SMSG_SET_PROJECTILE_POSITION = 0x4BF, // uint64 caster, uint8 castId, vector3 position + CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE, + SMSG_SET_PROJECTILE_POSITION = 0x4BF, SMSG_TALENTS_INFO = 0x4C0, CMSG_LEARN_PREVIEW_TALENTS = 0x4C1, CMSG_LEARN_PREVIEW_TALENTS_PET = 0x4C2, @@ -1354,7 +1354,7 @@ enum SessionStatus STATUS_AUTHED = 0, // Player authenticated (_player == NULL, m_playerRecentlyLogout = false or will be reset before handler call, m_GUID have garbage) STATUS_LOGGEDIN, // Player in game (_player != NULL, m_GUID == _player->GetGUID(), inWorld()) STATUS_TRANSFER, // Player transferring to another map (_player != NULL, m_GUID == _player->GetGUID(), !inWorld()) - STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, // _player!= NULL or _player == NULL && m_playerRecentlyLogout, m_GUID store last _player guid) + STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, // _player != NULL or _player == NULL && m_playerRecentlyLogout && m_playerLogout, m_GUID store last _player guid) STATUS_NEVER, // Opcode not accepted from client (deprecated or server side only) STATUS_UNHANDLED, // Opcode not handled yet }; diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp new file mode 100644 index 00000000000..bede48ace87 --- /dev/null +++ b/src/server/game/Server/Protocol/PacketLog.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "PacketLog.h" +#include "Config.h" +#include "ByteBuffer.h" + +PacketLog::PacketLog() : _file(NULL) +{ + Initialize(); +} + +PacketLog::~PacketLog() +{ + if (_file) + fclose(_file); + + _file = NULL; +} + +void PacketLog::Initialize() +{ + std::string logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); + + if (!logsDir.empty()) + if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) + logsDir.push_back('/'); + + std::string logname = ConfigMgr::GetStringDefault("PacketLogFile", ""); + if (!logname.empty()) + _file = fopen((logsDir + logname).c_str(), "wb"); +} + +void PacketLog::LogPacket(WorldPacket const& packet, Direction direction) +{ + ByteBuffer data(4+4+4+1+packet.size()); + data << int32(packet.GetOpcode()); + data << int32(packet.size()); + data << int32(time(NULL)); + data << uint8(direction); + + for (uint32 i = 0; i < packet.size(); i++) + data << const_cast<WorldPacket&>(packet)[i]; + + fwrite(data.contents(), 1, data.size(), _file); + fflush(_file); +} diff --git a/src/server/game/Server/Protocol/WorldLog.h b/src/server/game/Server/Protocol/PacketLog.h index fb344f195de..b899daae198 100755..100644 --- a/src/server/game/Server/Protocol/WorldLog.h +++ b/src/server/game/Server/Protocol/PacketLog.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,46 +15,36 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/// \addtogroup u2w -/// @{ -/// \file - -#ifndef TRINITY_WORLDLOG_H -#define TRINITY_WORLDLOG_H +#ifndef TRINITY_PACKETLOG_H +#define TRINITY_PACKETLOG_H #include "Common.h" #include <ace/Singleton.h> -#include "Errors.h" -#include <stdarg.h> +enum Direction +{ + CLIENT_TO_SERVER, + SERVER_TO_CLIENT +}; + +class WorldPacket; -/// %Log packets to a file -class WorldLog +class PacketLog { - friend class ACE_Singleton<WorldLog, ACE_Thread_Mutex>; + friend class ACE_Singleton<PacketLog, ACE_Thread_Mutex>; private: - WorldLog(); - ~WorldLog(); - WorldLog(const WorldLog &); - WorldLog& operator=(const WorldLog &); - ACE_Thread_Mutex Lock; + PacketLog(); + ~PacketLog(); public: void Initialize(); - /// Is the world logger active? - bool LogWorld(void) const { return (i_file != NULL); } - /// %Log to the file - void outLog(char const* fmt, ...); - void outTimestampLog(char const* fmt, ...); + bool CanLogPacket() const { return (_file != NULL); } + void LogPacket(WorldPacket const& packet, Direction direction); private: - FILE* i_file; - - bool m_dbWorld; + FILE* _file; }; -#define sWorldLog ACE_Singleton<WorldLog, ACE_Thread_Mutex>::instance() +#define sPacketLog ACE_Singleton<PacketLog, ACE_Thread_Mutex>::instance() #endif -/// @} - diff --git a/src/server/game/Server/Protocol/WorldLog.cpp b/src/server/game/Server/Protocol/WorldLog.cpp deleted file mode 100755 index 38b13dff095..00000000000 --- a/src/server/game/Server/Protocol/WorldLog.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/** \file - \ingroup u2w -*/ - -#include "WorldLog.h" -#include "Config.h" -#include "Log.h" -#include "DatabaseWorkerPool.h" - -WorldLog::WorldLog() : i_file(NULL) -{ - Initialize(); -} - -WorldLog::~WorldLog() -{ - if (i_file != NULL) - fclose(i_file); - - i_file = NULL; -} - -/// Open the log file (if specified so in the configuration file) -void WorldLog::Initialize() -{ - std::string logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); - - if (!logsDir.empty()) - { - if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) - logsDir.push_back('/'); - } - - std::string logname = ConfigMgr::GetStringDefault("WorldLogFile", ""); - if (!logname.empty()) - { - i_file = fopen((logsDir+logname).c_str(), "w"); - } - - m_dbWorld = ConfigMgr::GetBoolDefault("LogDB.World", false); // can be VERY heavy if enabled -} - -void WorldLog::outTimestampLog(char const* fmt, ...) -{ - if (LogWorld()) - { - TRINITY_GUARD(ACE_Thread_Mutex, Lock); - ASSERT(i_file); - - Log::outTimestamp(i_file); - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog->GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog->outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} - -void WorldLog::outLog(char const* fmt, ...) -{ - if (LogWorld()) - { - TRINITY_GUARD(ACE_Thread_Mutex, Lock); - ASSERT(i_file); - - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog->GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog->outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 88248b7bc55..81ec5495421 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -208,7 +208,7 @@ void WorldSession::QueuePacket(WorldPacket* new_packet) /// Logging helper for unexpected opcodes void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char* status, const char *reason) { - sLog->outError("SESSION (account: %u, guidlow: %u, char: %s): received unexpected opcode %s (0x%.4X, status: %s) %s", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION (account: %u, guidlow: %u, char: %s): received unexpected opcode %s (0x%.4X, status: %s) %s", GetAccountId(), m_GUIDLow, _player ? _player->GetName() : "<none>", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode(), status, reason); } @@ -216,7 +216,7 @@ void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char* status, /// Logging helper for unexpected opcodes void WorldSession::LogUnprocessedTail(WorldPacket* packet) { - sLog->outError("SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode(), uint32(packet->rpos()), uint32(packet->wpos())); packet->print_storage(); } @@ -290,7 +290,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer break; case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT: - if (!_player && !m_playerRecentlyLogout) + if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT", "the player has not logged in yet and not recently logout"); else @@ -323,9 +323,9 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) break; } - // single from authed time opcodes send in to after logout time - // and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes. - if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) + // some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes + // however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process. + if (packet->GetOpcode() == CMSG_CHAR_ENUM) m_playerRecentlyLogout = false; sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); @@ -334,7 +334,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) LogUnprocessedTail(packet); break; case STATUS_NEVER: - sLog->outError("SESSION (account: %u, guidlow: %u, char: %s): received not allowed opcode %s (0x%.4X)", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION (account: %u, guidlow: %u, char: %s): received not allowed opcode %s (0x%.4X)", GetAccountId(), m_GUIDLow, _player ? _player->GetName() : "<none>", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode()); break; @@ -404,7 +404,7 @@ void WorldSession::LogoutPlayer(bool Save) if (_player) { - if (uint64 lguid = GetPlayer()->GetLootGUID()) + if (uint64 lguid = _player->GetLootGUID()) DoLootRelease(lguid); ///- If the player just died before logging out, make him appear as a ghost @@ -518,21 +518,21 @@ void WorldSession::LogoutPlayer(bool Save) if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket) _player->RemoveFromGroup(); - ///- Send update to group and reset stored max enchanting level + //! Send update to group and reset stored max enchanting level if (_player->GetGroup()) { _player->GetGroup()->SendUpdate(); _player->GetGroup()->ResetMaxEnchantingLevel(); } - ///- Broadcast a logout message to the player's friends + //! Broadcast a logout message to the player's friends sSocialMgr->SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); sSocialMgr->RemovePlayerSocial(_player->GetGUIDLow()); - // Call script hook before deletion - sScriptMgr->OnPlayerLogout(GetPlayer()); + //! Call script hook before deletion + sScriptMgr->OnPlayerLogout(_player); - ///- Remove the player from the world + //! Remove the player from the world // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes @@ -540,22 +540,19 @@ void WorldSession::LogoutPlayer(bool Save) sLog->outChar("Account: %d (IP: %s) Logout Character:[%s] (GUID: %u) Level: %d", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName(), _player->GetGUIDLow(), _player->getLevel()); if (Map* _map = _player->FindMap()) _map->RemovePlayerFromMap(_player, true); - SetPlayer(NULL); // deleted in Remove call - ///- Send the 'logout complete' packet to the client + SetPlayer(NULL); //! Pointer already deleted during RemovePlayerFromMap + + //! Send the 'logout complete' packet to the client + //! Client will respond by sending 3x CMSG_CANCEL_TRADE, which we currently dont handle WorldPacket data(SMSG_LOGOUT_COMPLETE, 0); SendPacket(&data); + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); - ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline - //No SQL injection as AccountId is uint32 - + //! Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ACCOUNT_ONLINE); - stmt->setUInt32(0, GetAccountId()); - CharacterDatabase.Execute(stmt); - - sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); } m_playerLogout = false; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index bb54a0ae19e..00d5a8b5a86 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -221,6 +221,7 @@ class WorldSession bool PlayerLoading() const { return m_playerLoading; } bool PlayerLogout() const { return m_playerLogout; } bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; } + bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; } void SizeError(WorldPacket const& packet, uint32 size) const; @@ -785,6 +786,7 @@ class WorldSession void HandleResetInstancesOpcode(WorldPacket& recv_data); void HandleHearthAndResurrect(WorldPacket& recv_data); void HandleInstanceLockResponse(WorldPacket& recvPacket); + void HandleUpdateMissileTrajectory(WorldPacket& recvPacket); // Looking for Dungeon/Raid void HandleLfgSetCommentOpcode(WorldPacket& recv_data); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 64137dfe7c7..74e414a43a9 100755 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -42,7 +42,7 @@ #include "WorldSession.h" #include "WorldSocketMgr.h" #include "Log.h" -#include "WorldLog.h" +#include "PacketLog.h" #include "ScriptMgr.h" #include "AccountMgr.h" @@ -152,7 +152,7 @@ const std::string& WorldSocket::GetRemoteAddress (void) const return m_Address; } -int WorldSocket::SendPacket(const WorldPacket& pct) +int WorldSocket::SendPacket(WorldPacket const& pct) { ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); @@ -160,24 +160,8 @@ int WorldSocket::SendPacket(const WorldPacket& pct) return -1; // Dump outgoing packet. - if (sWorldLog->LogWorld()) - { - sWorldLog->outTimestampLog ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - pct.size(), - LookupOpcodeName (pct.GetOpcode()), - pct.GetOpcode()); - - uint32 p = 0; - while (p < pct.size()) - { - for (uint32 j = 0; j < 16 && p < pct.size(); j++) - sWorldLog->outLog("%.2X ", const_cast<WorldPacket&>(pct)[p++]); - - sWorldLog->outLog("\n"); - } - sWorldLog->outLog("\n"); - } + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(pct, SERVER_TO_CLIENT); // Create a copy of the original packet; this is to avoid issues if a hook modifies it. sScriptMgr->OnPacketSend(this, WorldPacket(pct)); @@ -674,7 +658,7 @@ int WorldSocket::schedule_wakeup_output (GuardType& g) return 0; } -int WorldSocket::ProcessIncoming (WorldPacket* new_pct) +int WorldSocket::ProcessIncoming(WorldPacket* new_pct) { ACE_ASSERT (new_pct); @@ -687,24 +671,8 @@ int WorldSocket::ProcessIncoming (WorldPacket* new_pct) return -1; // Dump received packet. - if (sWorldLog->LogWorld()) - { - sWorldLog->outTimestampLog ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - new_pct->size(), - LookupOpcodeName (new_pct->GetOpcode()), - new_pct->GetOpcode()); - - uint32 p = 0; - while (p < new_pct->size()) - { - for (uint32 j = 0; j < 16 && p < new_pct->size(); j++) - sWorldLog->outLog ("%.2X ", (*new_pct)[p++]); - - sWorldLog->outLog ("\n"); - } - sWorldLog->outLog ("\n"); - } + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(*new_pct, CLIENT_TO_SERVER); try { @@ -955,6 +923,8 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) sha.UpdateBigNumbers (&k, NULL); sha.Finalize(); + std::string address = GetRemoteAddress(); + if (memcmp (sha.GetDigest(), digest, 20)) { packet.Initialize (SMSG_AUTH_RESPONSE, 1); @@ -962,13 +932,11 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) SendPacket(packet); - sLog->outError("WorldSocket::HandleAuthSession: Sent Auth Response (authentification failed)."); + sLog->outError("WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, account.c_str(), address.c_str()); return -1; } - std::string address = GetRemoteAddress(); - - sLog->outStaticDebug ("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", + sLog->outStaticDebug("WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", account.c_str(), address.c_str()); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index d28ba9e1e19..05114c8bc07 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -660,19 +660,23 @@ int32 AuraEffect::CalculateAmount(Unit* caster) } break; case SPELL_AURA_PERIODIC_ENERGIZE: - if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC) + switch (m_spellInfo->Id) { - // Replenishment (0.25% from max) - // Infinite Replenishment - if (m_spellInfo->SpellIconID == 3184 && m_spellInfo->SpellVisual[0] == 12495) - amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 25 / 10000; - } - // Innervate - else if (m_spellInfo->Id == 29166) + case 57669: // Replenishment (0.2% from max) + amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.002f; + break; + case 61782: // Infinite Replenishment + amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.0025f; + break; + case 29166: // Innervate ApplyPctF(amount, float(GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA)) / GetTotalTicks()); - // Owlkin Frenzy - else if (m_spellInfo->Id == 48391) + break; + case 48391: // Owlkin Frenzy ApplyPctU(amount, GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA)); + break; + default: + break; + } break; case SPELL_AURA_PERIODIC_HEAL: if (!caster) @@ -2421,7 +2425,7 @@ void AuraEffect::HandleAuraCloneCaster(AuraApplication const* aurApp, uint8 mode // What must be cloned? at least display and scale target->SetDisplayId(caster->GetDisplayId()); - //target->SetFloatValue(OBJECT_FIELD_SCALE_X, caster->GetFloatValue(OBJECT_FIELD_SCALE_X)); // we need retail info about how scaling is handled (aura maybe?) + //target->SetObjectScale(caster->GetFloatValue(OBJECT_FIELD_SCALE_X)); // we need retail info about how scaling is handled (aura maybe?) target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE); } else diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index de432229e2c..58a89f75fd3 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -585,9 +585,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme CleanupEffectExecuteData(); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { m_destTargets[i] = SpellDestination(*m_caster); - } } Spell::~Spell() @@ -4837,8 +4835,9 @@ SpellCastResult Spell::CheckCast(bool strict) if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER) && !target->HasInArc(static_cast<float>(M_PI), m_caster)) return SPELL_FAILED_NOT_INFRONT; - if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target)) - return SPELL_FAILED_LINE_OF_SIGHT; + if (m_caster->GetEntry() != WORLD_TRIGGER) // Ignore LOS for gameobjects casts (wrongly casted by a trigger) + if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target)) + return SPELL_FAILED_LINE_OF_SIGHT; } else { diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 07bea5f980c..17e79501d16 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3565,7 +3565,7 @@ void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/) if (!unitTarget || !unitTarget->isAlive()) return; - int32 addhealth; + int32 addhealth = 0; if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN) // Lay on Hands { if (m_caster->GetGUID() == unitTarget->GetGUID()) @@ -3582,11 +3582,7 @@ void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/) else addhealth = unitTarget->GetMaxHealth() - unitTarget->GetHealth(); - if (m_originalCaster) - { - uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL); - m_healing += unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL); - } + m_healing += addhealth; } void Spell::EffectInterruptCast(SpellEffIndex effIndex) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 06e4978eb58..05566bdf712 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3043,6 +3043,7 @@ void SpellMgr::LoadDbcDataCorrections() case 61588: // Blazing Harpoon case 52479: // Gift of the Harvester case 48246: // Ball of Flame + case 36384: // Skartax Purple Beam spellInfo->MaxAffectedTargets = 1; break; case 41376: // Spite @@ -3084,7 +3085,7 @@ void SpellMgr::LoadDbcDataCorrections() case 50312: // Unholy Frenzy spellInfo->MaxAffectedTargets = 15; break; - case 33711: //Murmur's Touch + case 33711: // Murmur's Touch case 38794: spellInfo->MaxAffectedTargets = 1; spellInfo->EffectTriggerSpell[0] = 33760; @@ -3238,6 +3239,9 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->EffectDieSides[0] = 0; // was 1, that should probably mean seat 0, but instead it's treated as spell 1 spellInfo->EffectBasePoints[0] = 52391; // Ride Vehicle (forces seat 0) break; + case 45602: // Ride Carpet + spellInfo->EffectBasePoints[EFFECT_0] = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)" + break; case 64745: // Item - Death Knight T8 Tank 4P Bonus case 64936: // Item - Warrior T8 Protection 4P Bonus spellInfo->EffectBasePoints[0] = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit) diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 521070f7879..dcf3c38fe4f 100755 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -605,7 +605,7 @@ class SpellMgr // Accessors (const or static functions) public: - // Spell correctess for client using + // Spell correctness for client using static bool IsSpellValid(SpellInfo const* spellInfo, Player* player = NULL, bool msg = true); // Spell difficulty diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index b6feccc10c6..3e04cb48af4 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -718,7 +718,7 @@ public: (ChatHandler(player)).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, handler->GetNameLink().c_str(), Scale); } - target->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale); + target->SetObjectScale(Scale); return true; } diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index f29dd8a5069..99ec263b8f9 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -949,7 +949,7 @@ public: if (target) { wpCreature->SetDisplayId(target->GetDisplayId()); - wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); + wpCreature->SetObjectScale(0.5f); wpCreature->SetLevel(point > STRONG_MAX_LEVEL ? STRONG_MAX_LEVEL : point); } } @@ -1003,7 +1003,7 @@ public: if (target) { creature->SetDisplayId(target->GetDisplayId()); - creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); + creature->SetObjectScale(0.5f); } return true; @@ -1052,7 +1052,7 @@ public: if (target) { creature->SetDisplayId(target->GetDisplayId()); - creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5f); + creature->SetObjectScale(0.5f); } return true; diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h index beef71ea857..0af2af948d3 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/blackrock_spire.h @@ -33,7 +33,8 @@ enum Data DATA_WARCHIEF_REND_BLACKHAND, DATA_GYTH, DATA_THE_BEAST, - DATA_GENERAL_DRAKKISATH + DATA_GENERAL_DRAKKISATH, + DATA_DRAGONSPIRE_ROOM, }; enum Npc { @@ -51,6 +52,9 @@ enum Npc NPC_GYTH = 10339, NPC_THE_BEAST = 10430, NPC_GENERAL_DRAKKISATH = 10363, + NPC_BLACKHAND_DREADWEAVER = 9817, + NPC_BLACKHAND_SUMMONER = 9818, + NPC_BLACKHAND_VETERAN = 9819, }; enum AdditionalData @@ -58,6 +62,9 @@ enum AdditionalData SPELL_SUMMON_ROOKERY_WHELP = 15745, MAX_ENCOUNTER = 14, MAX_DRAGONSPIRE_HALL_RUNES = 7, + EVENT_PYROGUARD_EMBERSEER = 4884, + AREATRIGGER_ENTER_UBRS = 2046, + AREATRIGGER_STADIUM = 2026, }; enum GameObjects diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp index 411b800cd03..0279f3e2834 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp @@ -20,11 +20,24 @@ #include "ScriptedCreature.h" #include "blackrock_spire.h" +enum Text +{ + EMOTE_ONE_STACK = 0, + EMOTE_TEN_STACK = 1, + EMOTE_FREE_OF_BONDS = 2, + YELL_FREE_OF_BONDS = 3, +}; + enum Spells { - SPELL_FIRENOVA = 23462, - SPELL_FLAMEBUFFET = 23341, - SPELL_PYROBLAST = 17274, + SPELL_ENCAGED_EMBERSEER = 15282, // Self on spawn + SPELL_FIRE_SHIELD_TRIGGER = 13377, // Self on spawn missing from 335 dbc + SPELL_FREEZE_ANIM = 16245, // Self on event start + SPELL_EMBERSEER_GROWING = 16048, // Self on event start + SPELL_EMBERSEER_FULL_STRENGTH = 16047, // Emberseer Full Strength + SPELL_FIRENOVA = 23462, // Combat + SPELL_FLAMEBUFFET = 23341, // Combat + SPELL_PYROBLAST = 17274, // Combat }; enum Events @@ -51,6 +64,12 @@ public: void Reset() { + if(instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS) + OpenDoors(false); + instance->SetBossState(DATA_PYROGAURD_EMBERSEER,NOT_STARTED); + // respawn any dead Blackhand Incarcerators + DoCast(me, SPELL_ENCAGED_EMBERSEER); + //DoCast(me, SPELL_FIRE_SHIELD_TRIGGER); _Reset(); } @@ -64,12 +83,26 @@ public: void JustDied(Unit* /*killer*/) { + instance->SetBossState(DATA_PYROGAURD_EMBERSEER,DONE); + OpenDoors(true); _JustDied(); } + void OpenDoors(bool Boss_Killed) + { + if (GameObject* door1 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_IN))) + door1->SetGoState(GO_STATE_ACTIVE); + if (GameObject* door2 = me->GetMap()->GetGameObject(instance->GetData64(GO_DOORS))) + door2->SetGoState(GO_STATE_ACTIVE); + if (Boss_Killed) + if (GameObject* door3 = me->GetMap()->GetGameObject(instance->GetData64(GO_EMBERSEER_OUT))) + door3->SetGoState(GO_STATE_ACTIVE); + } + void UpdateAI(uint32 const diff) { if (!UpdateVictim()) + return; events.Update(diff); diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp index b5b1b34a593..fdb73fe1196 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/instance_blackrock_spire.cpp @@ -49,6 +49,12 @@ public: uint64 Gyth; uint64 TheBeast; uint64 GeneralDrakkisath; + uint64 go_emberseerin; + uint64 go_doors; + uint64 go_emberseerout; + uint64 go_roomrunes[MAX_DRAGONSPIRE_HALL_RUNES]; + uint8 Runemaxprotectors[MAX_DRAGONSPIRE_HALL_RUNES]; + uint8 Runeprotectorsdead[MAX_DRAGONSPIRE_HALL_RUNES]; void Initialize() { @@ -67,6 +73,9 @@ public: Gyth = 0; TheBeast = 0; GeneralDrakkisath = 0; + go_emberseerin = 0; + go_doors = 0; + go_emberseerout = 0; } bool IsEncounterInProgress() const @@ -125,7 +134,11 @@ public: case NPC_GENERAL_DRAKKISATH: GeneralDrakkisath = creature->GetGUID(); break; - } + case NPC_BLACKHAND_DREADWEAVER: + case NPC_BLACKHAND_SUMMONER: + case NPC_BLACKHAND_VETERAN: + break; + } } void OnGameObjectCreate(GameObject* go) @@ -135,6 +148,36 @@ public: case GO_WHELP_SPAWNER: go->CastSpell(NULL, SPELL_SUMMON_ROOKERY_WHELP); break; + case GO_EMBERSEER_IN: + go_emberseerin = go->GetGUID(); + break; + case GO_DOORS: + go_doors = go->GetGUID(); + break; + case GO_EMBERSEER_OUT: + go_emberseerout = go->GetGUID(); + break; + case GO_ROOM_1_RUNE: + go_roomrunes[0] = go->GetGUID(); + break; + case GO_ROOM_2_RUNE: + go_roomrunes[1] = go->GetGUID(); + break; + case GO_ROOM_3_RUNE: + go_roomrunes[2] = go->GetGUID(); + break; + case GO_ROOM_4_RUNE: + go_roomrunes[3] = go->GetGUID(); + break; + case GO_ROOM_5_RUNE: + go_roomrunes[4] = go->GetGUID(); + break; + case GO_ROOM_6_RUNE: + go_roomrunes[5] = go->GetGUID(); + break; + case GO_ROOM_7_RUNE: + go_roomrunes[6] = go->GetGUID(); + break; } } @@ -167,6 +210,18 @@ public: return true; } + void ProcessEvent(WorldObject* /*gameObject*/, uint32 eventId) + { + switch (eventId) + { + case EVENT_PYROGUARD_EMBERSEER: + SetBossState(DATA_PYROGAURD_EMBERSEER,IN_PROGRESS); + break; + default: + break; + } + } + uint64 GetData64(uint32 type) { switch (type) @@ -199,6 +254,26 @@ public: return TheBeast; case DATA_GENERAL_DRAKKISATH: return GeneralDrakkisath; + case GO_EMBERSEER_IN: + return go_emberseerin; + case GO_DOORS: + return go_doors; + case GO_EMBERSEER_OUT: + return go_emberseerout; + case GO_ROOM_1_RUNE: + return go_roomrunes[0]; + case GO_ROOM_2_RUNE: + return go_roomrunes[1]; + case GO_ROOM_3_RUNE: + return go_roomrunes[2]; + case GO_ROOM_4_RUNE: + return go_roomrunes[3]; + case GO_ROOM_5_RUNE: + return go_roomrunes[4]; + case GO_ROOM_6_RUNE: + return go_roomrunes[5]; + case GO_ROOM_7_RUNE: + return go_roomrunes[6]; } return 0; @@ -247,30 +322,7 @@ public: }; -uint8 ActivatedRunes = 0; - -class go_dragonspire_hall_rune : public GameObjectScript -{ -public: - go_dragonspire_hall_rune() : GameObjectScript("go_dragonspire_hall_rune") { } - - void OnGameObjectStateChanged(GameObject* go, uint32 state) - { - if (state == GO_STATE_READY) - { - if (++ActivatedRunes == MAX_DRAGONSPIRE_HALL_RUNES) - { - if (GameObject* door1 = GetClosestGameObjectWithEntry(go, GO_EMBERSEER_IN, 150.0f)) - door1->SetGoState(GO_STATE_ACTIVE); - if (GameObject* door2 = GetClosestGameObjectWithEntry(go, GO_DOORS, 150.0f)) - door2->SetGoState(GO_STATE_ACTIVE); - } - } - } -}; - void AddSC_instance_blackrock_spire() { new instance_blackrock_spire(); - new go_dragonspire_hall_rune; } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp index 783ac6baad1..2bba875ad1f 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp @@ -185,7 +185,7 @@ public: pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim()); pAttumen->SetTarget(pAttumen->getVictim()->GetGUID()); } - pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X, 1); + pAttumen->SetObjectScale(1); } } else Mount_Timer -= diff; } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp index 9a9f37d165f..a715dbfce9d 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -332,7 +332,7 @@ class boss_akilzon : public CreatureScript CloudGUID = Cloud->GetGUID(); Cloud->SetUnitMovementFlags(MOVEMENTFLAG_DISABLE_GRAVITY); Cloud->StopMoving(); - Cloud->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + Cloud->SetObjectScale(1.0f); Cloud->setFaction(35); Cloud->SetMaxHealth(9999999); Cloud->SetHealth(9999999); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp index ce6b3b37ef8..3da74d16dc3 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp @@ -197,7 +197,7 @@ class boss_thekal : public CreatureScript if (Resurrect_Timer <= diff) { DoCast(me, SPELL_TIGER_FORM); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f); + me->SetObjectScale(2.00f); me->SetStandState(UNIT_STAND_STATE_STAND); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetFullHealth(); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index 328d1ab1cd4..cf3c4274e48 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -354,7 +354,7 @@ public: //! HACK: Creature's can't have MOVEMENTFLAG_FLYING me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); me->setFaction(16); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); + me->SetObjectScale(1.0f); DoCast(me, SPELL_FLAME_SPHERE_VISUAL); DoCast(me, SPELL_FLAME_SPHERE_SPAWN_EFFECT); DoCast(me, SPELL_FLAME_SPHERE_PERIODIC); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index f329b940e1f..e4dcf978574 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -615,7 +615,7 @@ class mob_frost_sphere : public CreatureScript me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); DoCast(SPELL_PERMAFROST_VISUAL); DoCast(SPELL_PERMAFROST); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + me->SetObjectScale(2.0f); break; } } @@ -659,6 +659,11 @@ public: m_uiTargetGUID = 0; } + bool CanAIAttack(Unit const* victim) const + { + return victim->GetTypeId() == TYPEID_PLAYER; + } + void EnterCombat(Unit* who) { m_uiTargetGUID = who->GetGUID(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index 1d4961eb8b4..2643b8d60c7 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -439,7 +439,7 @@ class npc_fizzlebang_toc : public CreatureScript if (Unit* pTrigger = me->SummonCreature(NPC_TRIGGER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.69494f, TEMPSUMMON_MANUAL_DESPAWN)) { m_uiTriggerGUID = pTrigger->GetGUID(); - pTrigger->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + pTrigger->SetObjectScale(2.0f); pTrigger->SetDisplayId(22862); pTrigger->CastSpell(pTrigger, SPELL_WILFRED_PORTAL, false); } @@ -456,7 +456,7 @@ class npc_fizzlebang_toc : public CreatureScript if (Creature* pPortal = me->SummonCreature(NPC_WILFRED_PORTAL, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 4.71239f, TEMPSUMMON_MANUAL_DESPAWN)) { pPortal->SetReactState(REACT_PASSIVE); - pPortal->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + pPortal->SetObjectScale(2.0f); pPortal->CastSpell(pPortal, SPELL_WILFRED_PORTAL, false); m_uiPortalGUID = pPortal->GetGUID(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index f086e8dc9cf..ee966256e2b 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -149,7 +149,7 @@ class boss_blood_queen_lana_thel : public CreatureScript events.ScheduleEvent(EVENT_SWARMING_SHADOWS, 30500, EVENT_GROUP_NORMAL); events.ScheduleEvent(EVENT_TWILIGHT_BLOODBOLT, urand(20000, 25000), EVENT_GROUP_NORMAL); events.ScheduleEvent(EVENT_AIR_PHASE, 124000 + uint32(Is25ManRaid() ? 3000 : 0)); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNCONTROLLABLE_FRENZY); + CleanAuras(); me->SetSpeed(MOVE_FLIGHT, 0.642857f, true); _offtank = NULL; _vampires.clear(); @@ -170,6 +170,7 @@ class boss_blood_queen_lana_thel : public CreatureScript DoZoneInCombat(); Talk(SAY_AGGRO); instance->SetBossState(DATA_BLOOD_QUEEN_LANA_THEL, IN_PROGRESS); + CleanAuras(); DoCast(me, SPELL_SHROUD_OF_SORROW, true); DoCast(me, SPELL_FRENZIED_BLOODTHIRST_VISUAL, true); @@ -180,15 +181,7 @@ class boss_blood_queen_lana_thel : public CreatureScript { _JustDied(); Talk(SAY_DEATH); - instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN); - instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN_PLR); - instance->DoRemoveAurasDueToSpellOnPlayers(FRENZIED_BLOODTHIRST); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNCONTROLLABLE_FRENZY); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DAMAGE); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_VISUAL); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DUMMY); - instance->DoRemoveAurasDueToSpellOnPlayers(DELIRIOUS_SLASH); - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN); + CleanAuras(); // Blah, credit the quest if (_creditBloodQuickening) { @@ -207,6 +200,19 @@ class boss_blood_queen_lana_thel : public CreatureScript } } + void CleanAuras() + { + instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN); + instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN_PLR); + instance->DoRemoveAurasDueToSpellOnPlayers(FRENZIED_BLOODTHIRST); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNCONTROLLABLE_FRENZY); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DAMAGE); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_VISUAL); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DUMMY); + instance->DoRemoveAurasDueToSpellOnPlayers(DELIRIOUS_SLASH); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN); + } + void DoAction(int32 const action) { if (action != ACTION_KILL_MINCHAR) @@ -227,6 +233,7 @@ class boss_blood_queen_lana_thel : public CreatureScript void EnterEvadeMode() { _EnterEvadeMode(); + CleanAuras(); if (_killMinchar) { _killMinchar = false; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index afc7c503bee..494be259baa 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -631,9 +631,7 @@ class npc_high_overlord_saurfang_icc : public CreatureScript _events.ScheduleEvent(EVENT_OUTRO_HORDE_4, 24000); // cast _events.ScheduleEvent(EVENT_OUTRO_HORDE_5, 30000); // move me->SetDisableGravity(false); - me->SendMovementFlagUpdate(); - me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f); - me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f); + me->GetMotionMaster()->MoveFall(); for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr) (*itr)->AI()->DoAction(ACTION_DESPAWN); break; @@ -838,9 +836,7 @@ class npc_muradin_bronzebeard_icc : public CreatureScript me->RemoveAurasDueToSpell(SPELL_GRIP_OF_AGONY); Talk(SAY_OUTRO_ALLIANCE_1); me->SetDisableGravity(false); - me->SendMovementFlagUpdate(); - me->Relocate(me->GetPositionX(), me->GetPositionY(), 539.2917f); - me->MonsterMoveWithSpeed(me->GetPositionX(), me->GetPositionY(), 539.2917f, 0.0f); + me->GetMotionMaster()->MoveFall(); for (std::list<Creature*>::iterator itr = _guardList.begin(); itr != _guardList.end(); ++itr) (*itr)->AI()->DoAction(ACTION_DESPAWN); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 6039ace44ab..734639a8b51 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -167,7 +167,7 @@ class FrostwyrmLandEvent : public BasicEvent bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) { - _owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest, 8.247422f); + _owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest); return true; } @@ -481,7 +481,7 @@ class boss_sindragosa : public CreatureScript Position pos; pos.Relocate(me); pos.m_positionZ += 17.0f; - me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos, 8.30078125f); + me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos); events.CancelEventGroup(EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_AIR_PHASE, 110000); break; @@ -523,7 +523,7 @@ class boss_sindragosa : public CreatureScript events.ScheduleEvent(EVENT_FROST_BREATH, urand(10000, 15000), EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(12000, 17000), EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_ICY_GRIP, urand(35000, 40000), EVENT_GROUP_LAND_PHASE); - me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos, 0.0f); + me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos); break; case EVENT_THIRD_PHASE_CHECK: { diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index fab9a5f0740..6fd3cd2a294 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -1926,7 +1926,7 @@ class spell_svalna_revive_champion : public SpellScriptLoader //pos.m_positionZ = caster->GetBaseMap()->GetHeight(caster->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), caster->GetPositionZ(), true, 50.0f); //pos.m_positionZ += 0.05f; caster->SetHomePosition(pos); - caster->GetMotionMaster()->MoveLand(POINT_LAND, pos, caster->GetSpeed(MOVE_FLIGHT)); + caster->GetMotionMaster()->MoveLand(POINT_LAND, pos); } void Register() diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 4d6bfc578ff..0a4fdec7222 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -299,7 +299,7 @@ public: for (itr = chained.begin(); itr != chained.end(); ++itr) { if (Player* charmed = Unit::GetPlayer(*me, (*itr).first)) - charmed->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + charmed->SetObjectScale((*itr).second); } chained.clear(); @@ -347,7 +347,7 @@ public: for (itr = chained.begin(); itr != chained.end(); ++itr) { if (Player* player = Unit::GetPlayer(*me, (*itr).first)) - player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + player->SetObjectScale((*itr).second); } chained.clear(); } @@ -512,7 +512,7 @@ public: DoCast(target, SPELL_CHAINS_OF_KELTHUZAD); float scale = target->GetFloatValue(OBJECT_FIELD_SCALE_X); chained.insert(std::make_pair(target->GetGUID(), scale)); - target->SetFloatValue(OBJECT_FIELD_SCALE_X, scale * 2); + target->SetObjectScale(scale * 2); events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm } } @@ -530,7 +530,7 @@ public: { if (!player->isCharmed()) { - player->SetFloatValue(OBJECT_FIELD_SCALE_X, (*itr).second); + player->SetObjectScale((*itr).second); std::map<uint64, float>::iterator next = itr; ++next; chained.erase(itr); diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp index 29b8f2e7f48..44cd1184098 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp @@ -276,7 +276,7 @@ public: arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false); pos.Relocate(me); pos.m_positionZ += 8.0f; - me->GetMotionMaster()->MoveTakeoff(0, pos, 3.30078125f); + me->GetMotionMaster()->MoveTakeoff(0, pos); // spectators flee event if (instance) { @@ -333,7 +333,7 @@ public: pos.m_positionX = me->GetHomePosition().GetPositionX(); pos.m_positionY = me->GetHomePosition().GetPositionY(); pos.m_positionZ = 90.6065f; - me->GetMotionMaster()->MoveLand(0, pos, 6.247422f); + me->GetMotionMaster()->MoveLand(0, pos); me->SetDisableGravity(false, true); me->SetHover(true); ++introPhase; diff --git a/src/server/scripts/Northrend/dragonblight.cpp b/src/server/scripts/Northrend/dragonblight.cpp index 4cbe280a9f2..1b339b24549 100644 --- a/src/server/scripts/Northrend/dragonblight.cpp +++ b/src/server/scripts/Northrend/dragonblight.cpp @@ -69,7 +69,106 @@ public: } }; +/*###### +## Quest Strengthen the Ancients (12096|12092) +######*/ + +enum StrengthenAncientsMisc +{ + SAY_WALKER_FRIENDLY = 0, + SAY_WALKER_ENEMY = 1, + SAY_LOTHALOR = 0, + + SPELL_CREATE_ITEM_BARK = 47550, + SPELL_CONFUSED = 47044, + + NPC_LOTHALOR = 26321, + + FACTION_WALKER_ENEMY = 14, +}; + +class spell_q12096_q12092_dummy : public SpellScriptLoader // Strengthen the Ancients: On Interact Dummy to Woodlands Walker +{ +public: + spell_q12096_q12092_dummy() : SpellScriptLoader("spell_q12096_q12092_dummy") { } + + class spell_q12096_q12092_dummy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_dummy_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 roll = rand() % 2; + + Creature* tree = GetHitCreature(); + Player* player = GetCaster()->ToPlayer(); + + if (!tree || !player) + return; + + tree->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + + if (roll == 1) // friendly version + { + tree->CastSpell(player, SPELL_CREATE_ITEM_BARK); + tree->AI()->Talk(SAY_WALKER_FRIENDLY, player->GetGUID()); + tree->DespawnOrUnsummon(1000); + } + else if (roll == 0) // enemy version + { + tree->AI()->Talk(SAY_WALKER_ENEMY, player->GetGUID()); + tree->setFaction(FACTION_WALKER_ENEMY); + tree->Attack(player, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_dummy_SpellScript(); + } +}; + +class spell_q12096_q12092_bark : public SpellScriptLoader // Bark of the Walkers +{ +public: + spell_q12096_q12092_bark() : SpellScriptLoader("spell_q12096_q12092_bark") { } + + class spell_q12096_q12092_bark_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_bark_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Creature* lothalor = GetHitCreature(); + if (!lothalor || lothalor->GetEntry() != NPC_LOTHALOR) + return; + + lothalor->AI()->Talk(SAY_LOTHALOR); + lothalor->RemoveAura(SPELL_CONFUSED); + lothalor->DespawnOrUnsummon(4000); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_bark_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_bark_SpellScript(); + } +}; + void AddSC_dragonblight() { new npc_alexstrasza_wr_gate; + new spell_q12096_q12092_dummy; + new spell_q12096_q12092_bark; } diff --git a/src/server/scripts/Northrend/sholazar_basin.cpp b/src/server/scripts/Northrend/sholazar_basin.cpp index 93d0182ea08..afab9b90a4a 100644 --- a/src/server/scripts/Northrend/sholazar_basin.cpp +++ b/src/server/scripts/Northrend/sholazar_basin.cpp @@ -746,6 +746,130 @@ public: } }; +/*###### +## Quest Kick, What Kick? (12589) +######*/ + +enum KickWhatKick +{ + NPC_LUCKY_WILHELM = 28054, + NPC_APPLE = 28053, + NPC_DROSTAN = 28328, + NPC_CRUNCHY = 28346, + NPC_THICKBIRD = 28093, + + SPELL_HIT_APPLE = 51331, + SPELL_MISS_APPLE = 51332, + SPELL_MISS_BIRD_APPLE = 51366, + SPELL_APPLE_FALL = 51371, + SPELL_BIRD_FALL = 51369, + + EVENT_MISS = 0, + EVENT_HIT = 1, + EVENT_MISS_BIRD = 2, + + SAY_WILHELM_MISS = 0, + SAY_WILHELM_HIT = 1, + SAY_DROSTAN_REPLY_MISS = 0, +}; + +class spell_q12589_shoot_rjr : public SpellScriptLoader +{ +public: + spell_q12589_shoot_rjr() : SpellScriptLoader("spell_q12589_shoot_rjr") { } + + class spell_q12589_shoot_rjr_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12589_shoot_rjr_SpellScript); + + SpellCastResult CheckCast() + { + if (Unit* target = GetExplTargetUnit()) + if (target->GetEntry() == NPC_LUCKY_WILHELM) + return SPELL_CAST_OK; + + SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_TARGET_WILHELM); + return SPELL_FAILED_CUSTOM_ERROR; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 roll = urand(1, 100); + + uint8 ev; + if (roll <= 50) + ev = EVENT_MISS; + else if (roll <= 83) + ev = EVENT_HIT; + else + ev = EVENT_MISS_BIRD; + + Unit* shooter = GetCaster(); + Creature* wilhelm = GetHitUnit()->ToCreature(); + Creature* apple = shooter->FindNearestCreature(NPC_APPLE, 30); + Creature* drostan = shooter->FindNearestCreature(NPC_DROSTAN, 30); + + if (!wilhelm || !apple || !drostan) + return; + + switch (ev) + { + case EVENT_MISS_BIRD: + { + Creature* crunchy = shooter->FindNearestCreature(NPC_CRUNCHY, 30); + Creature* bird = shooter->FindNearestCreature(NPC_THICKBIRD, 30); + + if (!bird || !crunchy) + ; // fall to EVENT_MISS + else + { + shooter->CastSpell(bird, SPELL_MISS_BIRD_APPLE); + bird->CastSpell(bird, SPELL_BIRD_FALL); + wilhelm->AI()->Talk(SAY_WILHELM_MISS); + drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS); + + bird->Kill(bird); + crunchy->GetMotionMaster()->MovePoint(0, bird->GetPositionX(), bird->GetPositionY(), + bird->GetMap()->GetWaterOrGroundLevel(bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); + // TODO: Make crunchy perform emote eat when he reaches the bird + + break; + } + } + case EVENT_MISS: + { + shooter->CastSpell(wilhelm, SPELL_MISS_APPLE); + wilhelm->AI()->Talk(SAY_WILHELM_MISS); + drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS); + break; + } + case EVENT_HIT: + { + shooter->CastSpell(apple, SPELL_HIT_APPLE); + apple->CastSpell(apple, SPELL_APPLE_FALL); + wilhelm->AI()->Talk(SAY_WILHELM_HIT); + if (Player* player = shooter->ToPlayer()) + player->KilledMonsterCredit(NPC_APPLE, 0); + apple->DespawnOrUnsummon(); + + break; + } + } + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_q12589_shoot_rjr_SpellScript::CheckCast); + OnEffectHitTarget += SpellEffectFn(spell_q12589_shoot_rjr_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12589_shoot_rjr_SpellScript(); + } +}; + void AddSC_sholazar_basin() { new npc_injured_rainspeaker_oracle(); @@ -756,4 +880,5 @@ void AddSC_sholazar_basin() new npc_adventurous_dwarf(); new npc_jungle_punch_target(); new spell_q12620_the_lifewarden_wrath(); + new spell_q12589_shoot_rjr(); } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp index 206ba3d9455..3937b213e7e 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp @@ -691,7 +691,7 @@ public: Creature* Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); if (Cyclone) { - CAST_CRE(Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); + CAST_CRE(Cyclone)->SetObjectScale(3.0f); Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Cyclone->setFaction(me->getFaction()); Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 77c07f5fe4d..25207073708 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -409,7 +409,7 @@ class boss_alar : public CreatureScript if (Summoned) { Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); + Summoned->SetObjectScale(Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); Summoned->SetDisplayId(11686); Summoned->setFaction(me->getFaction()); Summoned->SetLevel(me->getLevel()); diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index c0203150789..d202fdd2f44 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -140,7 +140,7 @@ class boss_high_astromancer_solarian : public CreatureScript me->SetArmor(defaultarmor); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetVisible(true); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetObjectScale(defaultsize); me->SetDisplayId(MODEL_HUMAN); Summons.DespawnAll(); @@ -153,7 +153,7 @@ class boss_high_astromancer_solarian : public CreatureScript void JustDied(Unit* /*killer*/) { - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetObjectScale(defaultsize); me->SetDisplayId(MODEL_HUMAN); DoScriptText(SAY_DEATH, me); if (instance) @@ -397,7 +397,7 @@ class boss_high_astromancer_solarian : public CreatureScript DoScriptText(SAY_VOIDB, me); me->SetArmor(WV_ARMOR); me->SetDisplayId(MODEL_VOIDWALKER); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); + me->SetObjectScale(defaultsize*2.5f); } DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Outland/blades_edge_mountains.cpp b/src/server/scripts/Outland/blades_edge_mountains.cpp index cf0955ed89c..4ec1d04b6ad 100644 --- a/src/server/scripts/Outland/blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/blades_edge_mountains.cpp @@ -774,7 +774,7 @@ class npc_simon_bunny : public CreatureScript colorSequence.clear(); playableSequence.clear(); playerSequence.clear(); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, large ? 2.0f : 1.0f); + me->SetObjectScale(large ? 2.0f : 1.0f); std::list<WorldObject*> ClusterList; Trinity::AllWorldObjectsInRange objects(me, searchDistance); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 0c879cfb029..e23e21cf2cd 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -2052,9 +2052,9 @@ class spell_gen_defend : public SpellScriptLoader public: spell_gen_defend() : SpellScriptLoader("spell_gen_defend") { } - class spell_gen_defendAuraScript : public AuraScript + class spell_gen_defend_AuraScript : public AuraScript { - PrepareAuraScript(spell_gen_defendAuraScript); + PrepareAuraScript(spell_gen_defend_AuraScript); bool Validate(SpellInfo const* /*spellEntry*/) { @@ -2103,26 +2103,26 @@ class spell_gen_defend : public SpellScriptLoader // Defend spells casted by NPCs (add visuals) if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) { - AfterEffectApply += AuraEffectApplyFn(spell_gen_defendAuraScript::RefreshVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_gen_defendAuraScript::RemoveVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); } // Remove Defend spell from player when he dismounts if (spell->Effects[EFFECT_2].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) - OnEffectRemove += AuraEffectRemoveFn(spell_gen_defendAuraScript::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); // Defend spells casted by players (add/remove visuals) if (spell->Effects[EFFECT_1].ApplyAuraName == SPELL_AURA_DUMMY) { - AfterEffectApply += AuraEffectApplyFn(spell_gen_defendAuraScript::RefreshVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_gen_defendAuraScript::RemoveVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); } } }; AuraScript* GetAuraScript() const { - return new spell_gen_defendAuraScript(); + return new spell_gen_defend_AuraScript(); } }; @@ -2326,9 +2326,9 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader public: spell_gen_on_tournament_mount() : SpellScriptLoader("spell_gen_on_tournament_mount") { } - class spell_gen_on_tournament_mountAuraScript : public AuraScript + class spell_gen_on_tournament_mount_AuraScript : public AuraScript { - PrepareAuraScript(spell_gen_on_tournament_mountAuraScript); + PrepareAuraScript(spell_gen_on_tournament_mount_AuraScript); uint32 _pennantSpellId; @@ -2468,14 +2468,14 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader void Register() { - AfterEffectApply += AuraEffectApplyFn(spell_gen_on_tournament_mountAuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_gen_on_tournament_mountAuraScript::HandleRemoveEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_gen_on_tournament_mount_AuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_on_tournament_mount_AuraScript::HandleRemoveEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); } }; AuraScript* GetAuraScript() const { - return new spell_gen_on_tournament_mountAuraScript(); + return new spell_gen_on_tournament_mount_AuraScript(); } }; @@ -2484,9 +2484,9 @@ class spell_gen_tournament_pennant : public SpellScriptLoader public: spell_gen_tournament_pennant() : SpellScriptLoader("spell_gen_tournament_pennant") { } - class spell_gen_tournament_pennantAuraScript : public AuraScript + class spell_gen_tournament_pennant_AuraScript : public AuraScript { - PrepareAuraScript(spell_gen_tournament_pennantAuraScript); + PrepareAuraScript(spell_gen_tournament_pennant_AuraScript); bool Load() { @@ -2502,13 +2502,13 @@ class spell_gen_tournament_pennant : public SpellScriptLoader void Register() { - OnEffectApply += AuraEffectApplyFn(spell_gen_tournament_pennantAuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectApply += AuraEffectApplyFn(spell_gen_tournament_pennant_AuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); } }; AuraScript* GetAuraScript() const { - return new spell_gen_tournament_pennantAuraScript(); + return new spell_gen_tournament_pennant_AuraScript(); } }; @@ -2688,6 +2688,63 @@ public: } }; +class spell_gen_touch_the_nightmare : public SpellScriptLoader +{ +public: + spell_gen_touch_the_nightmare() : SpellScriptLoader("spell_gen_touch_the_nightmare") { } + + class spell_gen_touch_the_nightmare_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_touch_the_nightmare_SpellScript); + + void HandleDamageCalc(SpellEffIndex effIndex) + { + uint32 bp = GetCaster()->GetMaxHealth() * 0.3f; + SetHitDamage(bp); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_touch_the_nightmare_SpellScript::HandleDamageCalc, EFFECT_2, SPELL_EFFECT_SCHOOL_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_touch_the_nightmare_SpellScript(); + } +}; + +class spell_gen_dream_funnel: public SpellScriptLoader +{ +public: + spell_gen_dream_funnel() : SpellScriptLoader("spell_gen_dream_funnel") { } + + class spell_gen_dream_funnel_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_dream_funnel_AuraScript); + + void HandleEffectCalcAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + if (GetCaster()) + amount = GetCaster()->GetMaxHealth() * 0.05f; + + canBeRecalculated = false; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_dream_funnel_AuraScript::HandleEffectCalcAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_dream_funnel_AuraScript::HandleEffectCalcAmount, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_dream_funnel_AuraScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -2742,4 +2799,6 @@ void AddSC_generic_spell_scripts() new spell_gen_count_pct_from_max_hp("spell_gen_default_count_pct_from_max_hp"); new spell_gen_count_pct_from_max_hp("spell_gen_50pct_count_pct_from_max_hp", 50); new spell_gen_despawn_self(); + new spell_gen_touch_the_nightmare(); + new spell_gen_dream_funnel(); } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 09ff5935b6e..4e2eb633662 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -1535,7 +1535,7 @@ class spell_item_impale_leviroth : public SpellScriptLoader void HandleDummy(SpellEffIndex /* effIndex */) { if (Unit* target = GetHitCreature()) - if (target->GetEntry() == NPC_LEVIROTH && target->HealthBelowPct(95)) + if (target->GetEntry() == NPC_LEVIROTH && !target->HealthBelowPct(95)) target->CastSpell(target, SPELL_LEVIROTH_SELF_IMPALE, true); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index ecd1a439a58..57a65423b6f 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -47,6 +47,7 @@ EndContentData */ #include "ObjectMgr.h" #include "ScriptMgr.h" #include "World.h" +#include "PetAI.h" /*######## # npc_air_force_bots @@ -2100,16 +2101,18 @@ class npc_shadowfiend : public CreatureScript public: npc_shadowfiend() : CreatureScript("npc_shadowfiend") { } - struct npc_shadowfiendAI : public ScriptedAI + struct npc_shadowfiendAI : public PetAI { - npc_shadowfiendAI(Creature* creature) : ScriptedAI(creature) {} + npc_shadowfiendAI(Creature* creature) : PetAI(creature) {} - void DamageTaken(Unit* /*killer*/, uint32& damage) + void JustDied(Unit* killer) { if (me->isSummon()) if (Unit* owner = me->ToTempSummon()->GetSummoner()) - if (owner->HasAura(GLYPH_OF_SHADOWFIEND) && damage >= me->GetHealth()) + if (owner->HasAura(GLYPH_OF_SHADOWFIEND)) owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true); + + PetAI::JustDied(killer); } }; @@ -2988,6 +2991,31 @@ public: }; }; +/*###### +## npc_generic_harpoon_cannon +######*/ + +class npc_generic_harpoon_cannon : public CreatureScript +{ +public: + npc_generic_harpoon_cannon() : CreatureScript("npc_generic_harpoon_cannon") { } + + struct npc_generic_harpoon_cannonAI : public ScriptedAI + { + npc_generic_harpoon_cannonAI(Creature* creature) : ScriptedAI(creature) {} + + void Reset() + { + me->SetUnitMovementFlags(MOVEMENTFLAG_ROOT); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_generic_harpoon_cannonAI(creature); + } +}; + void AddSC_npcs_special() { new npc_air_force_bots(); @@ -3020,4 +3048,5 @@ void AddSC_npcs_special() new npc_earth_elemental(); new npc_firework(); new npc_spring_rabbit(); + new npc_generic_harpoon_cannon(); } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 5d837100b0e..b14038c9571 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -483,12 +483,13 @@ LogFileLevel = 0 DebugLogMask = 0 # -# WorldLogFile -# Description: Packet logging file for the world server. -# Example: "World.log" - (Enabled) +# PacketLogFile +# Description: Binary packet logging file for the world server. +# Filename extension must be .bin to be parsable with WowPacketParser. +# Example: "World.bin" - (Enabled) # Default: "" - (Disabled) -WorldLogFile = "" +PacketLogFile = "" # # DBErrorLogFile @@ -2024,17 +2025,17 @@ Visibility.GroupMode = 1 # Visibility.Distance.Instances # Visibility.Distance.BGArenas # Description: Visibility distance to see other players or gameobjects. -# Visibility on continents on retail ~90 yards. In BG/Arenas ~180. -# For instances default ~120. -# Max limited by active player zone: ~ 333 +# Visibility on continents on retail ~90 yards. In BG/Arenas ~533. +# For instances default ~170. +# Max limited by grid size: 533.33333 # Min limit is max aggro radius (45) * Rate.Creature.Aggro # Default: 90 - (Visibility.Distance.Continents) -# 120 - (Visibility.Distance.Instances) -# 180 - (Visibility.Distance.BGArenas) +# 170 - (Visibility.Distance.Instances) +# 533 - (Visibility.Distance.BGArenas) Visibility.Distance.Continents = 90 -Visibility.Distance.Instances = 120 -Visibility.Distance.BGArenas = 180 +Visibility.Distance.Instances = 170 +Visibility.Distance.BGArenas = 533 # # Visibility.Notify.Period.OnContinents |