From 91052574acb49a791ebfc958c0776e19dd578a71 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Sat, 7 Jun 2014 23:43:11 +0100 Subject: Core/Auras: Expanding functionality of SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT to be able to take care of aura effects inside their handlers Currently handled: - SPELL_AURA_MOD_RESISTANCE_PCT - SPELL_AURA_MOD_STAT - SPELL_AURA_MELEE_SLOW - SPELL_AURA_MOD_MELEE_HASTE - SPELL_AURA_MOD_DAMAGE_PERCENT_DONE Necessary to allow stack rules such as BoK/BoS/Bok-Drums and others to be all in a target with all of the aura effects, yet with only the 'highest' effect active --- src/server/game/Entities/Unit/Unit.cpp | 24 +++++++++ src/server/game/Entities/Unit/Unit.h | 2 + src/server/game/Spells/Auras/SpellAuraEffects.cpp | 62 +++++++++++++++++++++-- src/server/game/Spells/SpellMgr.cpp | 9 ++++ src/server/game/Spells/SpellMgr.h | 1 + 5 files changed, 93 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4efa1374ec7..5083e08e26f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17692,3 +17692,27 @@ void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns c data << uint32(itr->second); } } + +int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool sameMiscValue /*= false*/) const +{ + int32 val = 0; + SpellSpellGroupMapBounds spellGroup = sSpellMgr->GetSpellSpellGroupMapBounds(aurEff->GetSpellInfo()->GetFirstRankSpell()->Id); + for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second ; ++itr) + { + if (sSpellMgr->GetSpellGroupStackRule(itr->second) == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT) + { + AuraEffectList const& auraEffList = GetAuraEffectsByType(auraType); + for (AuraEffectList::const_iterator auraItr = auraEffList.begin(); auraItr != auraEffList.end(); ++auraItr) + { + if (aurEff != (*auraItr) && (!sameMiscValue || aurEff->GetMiscValue() == (*auraItr)->GetMiscValue()) && + sSpellMgr->IsSpellMemberOfSpellGroup((*auraItr)->GetSpellInfo()->Id, itr->second)) + { + // absolute value only + if (abs(val) < abs((*auraItr)->GetAmount())) + val = (*auraItr)->GetAmount(); + } + } + } + } + return val; +} diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 1735d1a8b8c..2cce1a852cf 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2152,6 +2152,8 @@ class Unit : public WorldObject time_t GetLastDamagedTime() const { return _lastDamagedTime; } void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; } + int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool sameMiscValue = false) const; + protected: explicit Unit (bool isWorldObject); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 07691e14e4f..dbd687a09d8 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3497,11 +3497,23 @@ void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 return; Unit* target = aurApp->GetTarget(); + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_RESISTANCE_PCT); + if (abs(spellGroupVal) >= abs(GetAmount())) + return; for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) { if (GetMiscValue() & int32(1<HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, (float)spellGroupVal, !apply); + if (target->GetTypeId() == TYPEID_PLAYER || target->IsPet()) + { + target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)spellGroupVal, !apply); + target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)spellGroupVal, !apply); + } + } target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply); if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet()) { @@ -3561,19 +3573,29 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; - Unit* target = aurApp->GetTarget(); - if (GetMiscValue() < -2 || GetMiscValue() > 4) { TC_LOG_ERROR("spells", "WARNING: Spell %u effect %u has an unsupported misc value (%i) for SPELL_AURA_MOD_STAT ", GetId(), GetEffIndex(), GetMiscValue()); return; } + Unit* target = aurApp->GetTarget(); + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_STAT, true); + if (abs(spellGroupVal) >= abs(GetAmount())) + return; + for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) { // -1 or -2 is all stats (misc < -2 checked in function beginning) if (GetMiscValue() < 0 || GetMiscValue() == i) { + if (spellGroupVal) + { + target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(spellGroupVal), !apply); + if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet()) + target->ApplyStatBuffMod(Stats(i), float(spellGroupVal), !apply); + } + //target->ApplyStatMod(Stats(i), m_amount, apply); target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply); if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->IsPet()) @@ -4099,7 +4121,17 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo return; Unit* target = aurApp->GetTarget(); + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MELEE_SLOW); + if (abs(spellGroupVal) >= abs(GetAmount())) + return; + if (spellGroupVal) + { + target->ApplyCastTimePercentMod(float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply); + } target->ApplyCastTimePercentMod(float(m_amount), apply); target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); @@ -4123,7 +4155,15 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod return; Unit* target = aurApp->GetTarget(); + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_MELEE_HASTE); + if (abs(spellGroupVal) >= abs(GetAmount())) + return; + if (spellGroupVal) + { + target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), !apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), !apply); + } target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); } @@ -4360,7 +4400,8 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 return; Unit* target = aurApp->GetTarget(); - if (!target) + int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + if (abs(spellGroupVal) >= abs(GetAmount())) return; if (target->GetTypeId() == TYPEID_PLAYER) @@ -4372,12 +4413,23 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)) { + if (spellGroupVal) + { + target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(spellGroupVal), !apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(spellGroupVal), !apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(spellGroupVal), !apply); + } target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply); target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply); - if (target->GetTypeId() == TYPEID_PLAYER) - target->ToPlayer()->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float (GetAmount()), apply); + if (Player* player = target->ToPlayer()) + { + if (spellGroupVal) + player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(spellGroupVal), !apply); + + player->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float(GetAmount()), apply); + } } else { diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 9eadd178eb3..04de93bae0c 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -765,6 +765,15 @@ SpellGroupStackRule SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellIn return rule; } +SpellGroupStackRule SpellMgr::GetSpellGroupStackRule(SpellGroup group) const +{ + SpellGroupStackMap::const_iterator itr = mSpellGroupStack.find(group); + if (itr != mSpellGroupStack.end()) + return itr->second; + + return SPELL_GROUP_STACK_RULE_DEFAULT; +} + SpellProcEventEntry const* SpellMgr::GetSpellProcEvent(uint32 spellId) const { SpellProcEventMap::const_iterator itr = mSpellProcEventMap.find(spellId); diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 7b54aca3759..9108618176f 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -655,6 +655,7 @@ class SpellMgr // Spell Group Stack Rules table bool AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, int32 amount, std::map& groups) const; SpellGroupStackRule CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const; + SpellGroupStackRule GetSpellGroupStackRule(SpellGroup groupid) const; // Spell proc event table SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const; -- cgit v1.2.3 From f81635ebe516633d7cd1d45ef905b5b60958779d Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 9 Jun 2014 21:08:19 +0200 Subject: Core/Vehicles: Fixed channeled spells being interrupted for passengers when vehicle moves --- src/server/game/Entities/Unit/Unit.cpp | 4 +++- src/server/game/Handlers/MovementHandler.cpp | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b5ea898dc00..2b6cb9dd8ba 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17079,12 +17079,14 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel bool turn = (GetOrientation() != orientation); bool relocated = (teleport || GetPositionX() != x || GetPositionY() != y || GetPositionZ() != z); + // TODO: Check if orientation transport offset changed instead of only global orientation if (turn) RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); if (relocated) { - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE); + if (!GetVehicle()) + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE); // move and update visible state if need if (GetTypeId() == TYPEID_PLAYER) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 5fc6ada6fb2..cef414163bd 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -30,6 +30,7 @@ #include "WaypointMovementGenerator.h" #include "InstanceSaveMgr.h" #include "ObjectMgr.h" +#include "Vehicle.h" #define MOVEMENT_PACKET_TIME_DELAY 0 @@ -370,10 +371,20 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) mover->m_movementInfo = movementInfo; - // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() - if (mover->GetVehicle()) + // Some vehicles allow the passenger to turn by himself + if (Vehicle* vehicle = mover->GetVehicle()) { - mover->SetOrientation(movementInfo.pos.GetOrientation()); + if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover)) + { + if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING) + { + if (movementInfo.pos.GetOrientation() != mover->GetOrientation()) + { + mover->SetOrientation(movementInfo.pos.GetOrientation()); + mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); + } + } + } return; } -- cgit v1.2.3 From d52eb14bb6f0fbfb9d75cc0f16793eefb74666c7 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Mon, 9 Jun 2014 21:35:59 +0200 Subject: Core/NetworkIO: Adjust more packet throttling values Ignore some opcodes that don't cause any trouble. Remove old Allow/Disable Anti-DoS system since it's no longer required. --- src/server/game/Handlers/GroupHandler.cpp | 2 - src/server/game/Server/WorldSession.cpp | 384 +++++++++++++++--------------- src/server/game/Server/WorldSession.h | 12 - 3 files changed, 194 insertions(+), 204 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index eae95d20610..97867e2f352 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -638,8 +638,6 @@ void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData) recvData >> apply; group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_ASSISTANT); - - group->SendUpdate(); } void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index f8df683d90c..3ac31da3eb1 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1246,6 +1246,12 @@ void WorldSession::InvalidateRBACData() bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) const { + uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode()); + + // Return true if there no limit for the opcode + if (!maxPacketCounterAllowed) + return true; + PacketCounter& packetCounter = _PacketThrottlingMap[p.GetOpcode()]; if (packetCounter.lastReceiveTime != time) { @@ -1253,29 +1259,14 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co packetCounter.amountCounter = 0; } - uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode()); - - bool dosTriggered = false; // Check if player is flooding some packets if (++packetCounter.amountCounter > maxPacketCounterAllowed) { - dosTriggered = true; TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)", Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(), opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter); } - // Then check if player is sending packets not allowed - if (!IsOpcodeAllowed(p.GetOpcode())) - { - dosTriggered = true; - // Opcode not allowed, let the punishment begin - TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)", - Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size()); - } - - // Return true if everything is fine, otherwise apply the configured policy - if (!dosTriggered) return true; switch (_policy) @@ -1312,207 +1303,220 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co uint32 maxPacketCounterAllowed; switch (opcode) { - // These opcodes are spammed by few addons so a very high limit is required - case CMSG_QUEST_QUERY: - case CMSG_MESSAGECHAT: - case CMSG_ITEM_QUERY_SINGLE: - case CMSG_ITEM_NAME_QUERY: - case CMSG_GAMEOBJECT_QUERY: - case CMSG_NAME_QUERY: - case CMSG_PET_NAME_QUERY: - case CMSG_CREATURE_QUERY: - case CMSG_NPC_TEXT_QUERY: - case CMSG_QUESTGIVER_STATUS_QUERY: + // CPU usage sending 2000 packets/second on a 3.70 GHz 4 cores on Win x64 + // [% CPU mysqld] [%CPU worldserver RelWithDebInfo] + case CMSG_PLAYER_LOGIN: // 0 0.5 + case CMSG_NAME_QUERY: // 0 1 + case CMSG_PET_NAME_QUERY: // 0 1 + case CMSG_NPC_TEXT_QUERY: // 0 1 + case CMSG_ATTACKSTOP: // 0 1 + case CMSG_QUERY_QUESTS_COMPLETED: // 0 1 + case CMSG_QUERY_TIME: // 0 1 + case CMSG_CORPSE_MAP_POSITION_QUERY: // 0 1 + case CMSG_MOVE_TIME_SKIPPED: // 0 1 + case MSG_QUERY_NEXT_MAIL_TIME: // 0 1 + case CMSG_SETSHEATHED: // 0 1 + case MSG_RAID_TARGET_UPDATE: // 0 1 + case CMSG_PLAYER_LOGOUT: // 0 1 + case CMSG_LOGOUT_REQUEST: // 0 1 + case CMSG_PET_RENAME: // 0 1 + case CMSG_QUESTGIVER_CANCEL: // 0 1 + case CMSG_QUESTGIVER_REQUEST_REWARD: // 0 1 + case CMSG_COMPLETE_CINEMATIC: // 0 1 + case CMSG_BANKER_ACTIVATE: // 0 1 + case CMSG_BUY_BANK_SLOT: // 0 1 + case CMSG_OPT_OUT_OF_LOOT: // 0 1 + case CMSG_DUEL_ACCEPTED: // 0 1 + case CMSG_DUEL_CANCELLED: // 0 1 + case CMSG_CALENDAR_COMPLAIN: // 0 1 + case CMSG_QUEST_QUERY: // 0 1.5 + case CMSG_ITEM_QUERY_SINGLE: // 0 1.5 + case CMSG_ITEM_NAME_QUERY: // 0 1.5 + case CMSG_GAMEOBJECT_QUERY: // 0 1.5 + case CMSG_CREATURE_QUERY: // 0 1.5 + case CMSG_QUESTGIVER_STATUS_QUERY: // 0 1.5 + case CMSG_GUILD_QUERY: // 0 1.5 + case CMSG_ARENA_TEAM_QUERY: // 0 1.5 + case CMSG_TAXINODE_STATUS_QUERY: // 0 1.5 + case CMSG_TAXIQUERYAVAILABLENODES: // 0 1.5 + case CMSG_QUESTGIVER_QUERY_QUEST: // 0 1.5 + case CMSG_PAGE_TEXT_QUERY: // 0 1.5 + case MSG_QUERY_GUILD_BANK_TEXT: // 0 1.5 + case MSG_CORPSE_QUERY: // 0 1.5 + case MSG_MOVE_SET_FACING: // 0 1.5 + case CMSG_REQUEST_PARTY_MEMBER_STATS: // 0 1.5 + case CMSG_QUESTGIVER_COMPLETE_QUEST: // 0 1.5 + case CMSG_SET_ACTION_BUTTON: // 0 1.5 + case CMSG_RESET_INSTANCES: // 0 1.5 + case CMSG_HEARTH_AND_RESURRECT: // 0 1.5 + case CMSG_TOGGLE_PVP: // 0 1.5 + case CMSG_PET_ABANDON: // 0 1.5 + case CMSG_ACTIVATETAXIEXPRESS: // 0 1.5 + case CMSG_ACTIVATETAXI: // 0 1.5 + case CMSG_SELF_RES: // 0 1.5 + case CMSG_UNLEARN_SKILL: // 0 1.5 + case CMSG_EQUIPMENT_SET_SAVE: // 0 1.5 + case CMSG_DELETEEQUIPMENT_SET: // 0 1.5 + case CMSG_DISMISS_CRITTER: // 0 1.5 + case CMSG_REPOP_REQUEST: // 0 1.5 + case CMSG_GROUP_INVITE: // 0 1.5 + case CMSG_GROUP_DECLINE: // 0 1.5 + case CMSG_GROUP_ACCEPT: // 0 1.5 + case CMSG_GROUP_UNINVITE_GUID: // 0 1.5 + case CMSG_GROUP_UNINVITE: // 0 1.5 + case CMSG_GROUP_DISBAND: // 0 1.5 + case CMSG_BATTLEMASTER_JOIN_ARENA: // 0 1.5 + case CMSG_LEAVE_BATTLEFIELD: // 0 1.5 + case MSG_GUILD_BANK_LOG_QUERY: // 0 2 + case CMSG_LOGOUT_CANCEL: // 0 2 + case CMSG_REALM_SPLIT: // 0 2 + case CMSG_ALTER_APPEARANCE: // 0 2 + case CMSG_QUEST_CONFIRM_ACCEPT: // 0 2 + case MSG_GUILD_EVENT_LOG_QUERY: // 0 2.5 + case CMSG_READY_FOR_ACCOUNT_DATA_TIMES: // 0 2.5 + case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY: // 0 2.5 + case CMSG_BEGIN_TRADE: // 0 2.5 + case CMSG_INITIATE_TRADE: // 0 3 + case CMSG_MESSAGECHAT: // 0 3.5 + case CMSG_INSPECT: // 0 3.5 + case CMSG_AREA_SPIRIT_HEALER_QUERY: // not profiled { - maxPacketCounterAllowed = 5000; + // "0" is a magic number meaning there's no limit for the opcode. + // All the opcodes above must cause little CPU usage and no sync/async database queries at all + maxPacketCounterAllowed = 0; break; } - case CMSG_ATTACKSTOP: - case CMSG_GUILD_QUERY: - case CMSG_ARENA_TEAM_QUERY: - case CMSG_TAXINODE_STATUS_QUERY: - case CMSG_TAXIQUERYAVAILABLENODES: - case CMSG_QUESTGIVER_QUERY_QUEST: - case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY: - case CMSG_QUERY_QUESTS_COMPLETED: - case CMSG_QUEST_POI_QUERY: - case CMSG_QUERY_TIME: - case CMSG_PAGE_TEXT_QUERY: - case CMSG_PETITION_QUERY: - case CMSG_QUERY_INSPECT_ACHIEVEMENTS: - case CMSG_AREA_SPIRIT_HEALER_QUERY: - case CMSG_CORPSE_MAP_POSITION_QUERY: - case CMSG_MOVE_TIME_SKIPPED: - case CMSG_GUILD_BANK_QUERY_TAB: - case MSG_GUILD_BANK_LOG_QUERY: - case MSG_QUERY_GUILD_BANK_TEXT: - case MSG_CORPSE_QUERY: - case MSG_QUERY_NEXT_MAIL_TIME: - case MSG_GUILD_EVENT_LOG_QUERY: - case MSG_MOVE_SET_FACING: - case CMSG_INSPECT: + case CMSG_QUESTGIVER_ACCEPT_QUEST: // 0 4 + case CMSG_QUESTLOG_REMOVE_QUEST: // 0 4 + case CMSG_QUESTGIVER_CHOOSE_REWARD: // 0 4 + case CMSG_CONTACT_LIST: // 0 5 + case CMSG_LEARN_PREVIEW_TALENTS: // 0 6 + case CMSG_AUTOBANK_ITEM: // 0 6 + case CMSG_AUTOSTORE_BANK_ITEM: // 0 6 + case CMSG_WHO: // 0 7 + case CMSG_PLAYER_VEHICLE_ENTER: // 0 8 + case CMSG_LEARN_PREVIEW_TALENTS_PET: // not profiled + case MSG_MOVE_HEARTBEAT: { - maxPacketCounterAllowed = 500; + maxPacketCounterAllowed = 200; break; } - case CMSG_REQUEST_PARTY_MEMBER_STATS: - case CMSG_WHO: - case CMSG_SETSHEATHED: - case CMSG_CONTACT_LIST: - case CMSG_GUILD_SET_PUBLIC_NOTE: - case CMSG_GUILD_SET_OFFICER_NOTE: + case CMSG_GUILD_SET_PUBLIC_NOTE: // 1 2 1 async db query + case CMSG_GUILD_SET_OFFICER_NOTE: // 1 2 1 async db query + case CMSG_SET_CONTACT_NOTES: // 1 2.5 1 async db query + case CMSG_CALENDAR_GET_CALENDAR: // 0 1.5 medium upload bandwidth usage + case CMSG_GUILD_BANK_QUERY_TAB: // 0 3.5 medium upload bandwidth usage + case CMSG_QUERY_INSPECT_ACHIEVEMENTS: // 0 13 high upload bandwidth usage { maxPacketCounterAllowed = 50; break; } - case CMSG_SPELLCLICK: - case CMSG_GAMEOBJ_USE: - case CMSG_GAMEOBJ_REPORT_USE: - case MSG_RAID_TARGET_UPDATE: - case CMSG_QUESTGIVER_COMPLETE_QUEST: - case CMSG_PLAYER_VEHICLE_ENTER: - case CMSG_PETITION_SIGN: + case CMSG_QUEST_POI_QUERY: // 0 25 very high upload bandwidth usage + { + maxPacketCounterAllowed = MAX_QUEST_LOG_SIZE; + break; + } + + case CMSG_GM_REPORT_LAG: // 1 3 1 async db query + case CMSG_SPELLCLICK: // not profiled + case CMSG_GAMEOBJ_USE: // not profiled + case CMSG_GAMEOBJ_REPORT_USE: // not profiled + case CMSG_REMOVE_GLYPH: // not profiled { maxPacketCounterAllowed = 20; break; } - case CMSG_PLAYER_LOGOUT: - case CMSG_LOGOUT_REQUEST: - case CMSG_LOGOUT_CANCEL: - case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: - case CMSG_REQUEST_VEHICLE_PREV_SEAT: - case CMSG_REQUEST_VEHICLE_NEXT_SEAT: - case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: - case CMSG_TOGGLE_PVP: - case CMSG_ADD_FRIEND: - case CMSG_DEL_FRIEND: - case CMSG_SET_CONTACT_NOTES: - case CMSG_RESET_INSTANCES: - case CMSG_HEARTH_AND_RESURRECT: - case CMSG_CHAR_CREATE: - case CMSG_READY_FOR_ACCOUNT_DATA_TIMES: - case CMSG_CHAR_ENUM: - case CMSG_REALM_SPLIT: - case CMSG_CHAR_DELETE: - case CMSG_PLAYER_LOGIN: - case CMSG_PET_ABANDON: - case CMSG_PET_RENAME: - case CMSG_CHAR_RENAME: - case CMSG_CHAR_CUSTOMIZE: - case CMSG_CHAR_RACE_CHANGE: - case CMSG_CHAR_FACTION_CHANGE: - case CMSG_GMTICKET_CREATE: - case CMSG_GMTICKET_UPDATETEXT: - case CMSG_GMTICKET_DELETETICKET: - case CMSG_GMSURVEY_SUBMIT: - case CMSG_GM_REPORT_LAG: - case CMSG_BUG: - case CMSG_GMRESPONSE_RESOLVE: - case CMSG_ACTIVATETAXIEXPRESS: - case CMSG_ACTIVATETAXI: - case CMSG_SELF_RES: - case CMSG_INITIATE_TRADE: - case CMSG_BEGIN_TRADE: - case CMSG_UNLEARN_SKILL: - case CMSG_DISMISS_CONTROLLED_VEHICLE: - case CMSG_REQUEST_VEHICLE_EXIT: - case CMSG_LEARN_PREVIEW_TALENTS: - case CMSG_LEARN_PREVIEW_TALENTS_PET: - case CMSG_CONTROLLER_EJECT_PASSENGER: - case CMSG_EQUIPMENT_SET_SAVE: - case CMSG_DELETEEQUIPMENT_SET: - case CMSG_REMOVE_GLYPH: - case CMSG_ALTER_APPEARANCE: - case CMSG_QUESTGIVER_ACCEPT_QUEST: - case CMSG_QUESTGIVER_CHOOSE_REWARD: - case CMSG_QUESTGIVER_REQUEST_REWARD: - case CMSG_QUESTGIVER_CANCEL: - case CMSG_QUESTLOG_REMOVE_QUEST: - case CMSG_QUEST_CONFIRM_ACCEPT: - case CMSG_DISMISS_CRITTER: - case CMSG_REPOP_REQUEST: - case CMSG_PETITION_BUY: - case CMSG_TURN_IN_PETITION: - case CMSG_COMPLETE_CINEMATIC: - case CMSG_ITEM_REFUND: - case CMSG_SOCKET_GEMS: - case CMSG_WRAP_ITEM: - case CMSG_BUY_BANK_SLOT: - case CMSG_GROUP_ACCEPT: - case CMSG_GROUP_DECLINE: - case CMSG_GROUP_UNINVITE_GUID: - case CMSG_GROUP_UNINVITE: - case CMSG_GROUP_SET_LEADER: - case CMSG_GROUP_DISBAND: - case CMSG_GROUP_RAID_CONVERT: - case CMSG_GROUP_CHANGE_SUB_GROUP: - case CMSG_GROUP_ASSISTANT_LEADER: - case CMSG_OPT_OUT_OF_LOOT: - case CMSG_BATTLEMASTER_JOIN_ARENA: - case CMSG_LEAVE_BATTLEFIELD: - case CMSG_REPORT_PVP_AFK: - case CMSG_DUEL_ACCEPTED: - case CMSG_DUEL_CANCELLED: - case CMSG_CALENDAR_GET_CALENDAR: - case CMSG_CALENDAR_ADD_EVENT: - case CMSG_CALENDAR_UPDATE_EVENT: - case CMSG_CALENDAR_REMOVE_EVENT: - case CMSG_CALENDAR_COPY_EVENT: - case CMSG_CALENDAR_EVENT_INVITE: - case CMSG_CALENDAR_EVENT_SIGNUP: - case CMSG_CALENDAR_EVENT_RSVP: - case CMSG_CALENDAR_EVENT_REMOVE_INVITE: - case CMSG_CALENDAR_EVENT_MODERATOR_STATUS: - case CMSG_CALENDAR_COMPLAIN: - case CMSG_ARENA_TEAM_INVITE: - case CMSG_ARENA_TEAM_ACCEPT: - case CMSG_ARENA_TEAM_DECLINE: - case CMSG_ARENA_TEAM_LEAVE: - case CMSG_ARENA_TEAM_DISBAND: - case CMSG_ARENA_TEAM_REMOVE: - case CMSG_ARENA_TEAM_LEADER: - case CMSG_LOOT_METHOD: - case CMSG_GUILD_INVITE: - case CMSG_GUILD_ACCEPT: - case CMSG_GUILD_DECLINE: - case CMSG_GUILD_LEAVE: - case CMSG_GUILD_DISBAND: - case CMSG_GUILD_LEADER: - case CMSG_GUILD_MOTD: - case CMSG_GUILD_RANK: - case CMSG_GUILD_ADD_RANK: - case CMSG_GUILD_DEL_RANK: - case CMSG_GUILD_INFO_TEXT: - case CMSG_GUILD_BANK_DEPOSIT_MONEY: - case CMSG_GUILD_BANK_WITHDRAW_MONEY: - case CMSG_GUILD_BANK_BUY_TAB: - case CMSG_GUILD_BANK_UPDATE_TAB: - case CMSG_SET_GUILD_BANK_TEXT: - case MSG_SAVE_GUILD_EMBLEM: - case MSG_PETITION_RENAME: - case MSG_PETITION_DECLINE: - case MSG_TALENT_WIPE_CONFIRM: - case MSG_SET_DUNGEON_DIFFICULTY: - case MSG_SET_RAID_DIFFICULTY: - case MSG_RANDOM_ROLL: - case MSG_PARTY_ASSIGNMENT: - case MSG_RAID_READY_CHECK: + case CMSG_PETITION_SIGN: // 9 4 2 sync 1 async db queries + case CMSG_TURN_IN_PETITION: // 8 5.5 2 sync db query + case CMSG_GROUP_CHANGE_SUB_GROUP: // 6 5 1 sync 1 async db queries + case CMSG_PETITION_QUERY: // 4 3.5 1 sync db query + case CMSG_CHAR_RACE_CHANGE: // 5 4 1 sync db query + case CMSG_CHAR_CUSTOMIZE: // 5 5 1 sync db query + case CMSG_CHAR_FACTION_CHANGE: // 5 5 1 sync db query + case CMSG_CHAR_DELETE: // 4 4 1 sync db query + case CMSG_DEL_FRIEND: // 7 5 1 async db query + case CMSG_ADD_FRIEND: // 6 4 1 async db query + case CMSG_CHAR_RENAME: // 5 3 1 async db query + case CMSG_GMSURVEY_SUBMIT: // 2 3 1 async db query + case CMSG_BUG: // 1 1 1 async db query + case CMSG_GROUP_SET_LEADER: // 1 2 1 async db query + case CMSG_GROUP_RAID_CONVERT: // 1 5 1 async db query + case CMSG_GROUP_ASSISTANT_LEADER: // 1 2 1 async db query + case CMSG_CALENDAR_ADD_EVENT: // 21 10 2 async db query + case CMSG_PETITION_BUY: // not profiled 1 sync 1 async db queries + case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: // not profiled + case CMSG_REQUEST_VEHICLE_PREV_SEAT: // not profiled + case CMSG_REQUEST_VEHICLE_NEXT_SEAT: // not profiled + case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: // not profiled + case CMSG_DISMISS_CONTROLLED_VEHICLE: // not profiled + case CMSG_REQUEST_VEHICLE_EXIT: // not profiled + case CMSG_CONTROLLER_EJECT_PASSENGER: // not profiled + case CMSG_ITEM_REFUND: // not profiled + case CMSG_SOCKET_GEMS: // not profiled + case CMSG_WRAP_ITEM: // not profiled + case CMSG_REPORT_PVP_AFK: // not profiled { - maxPacketCounterAllowed = 3; + maxPacketCounterAllowed = 10; break; } - case CMSG_SET_ACTION_BUTTON: + case CMSG_CHAR_CREATE: // 7 5 3 async db queries + case CMSG_CHAR_ENUM: // 22 3 2 async db queries + case CMSG_GMTICKET_CREATE: // 1 25 1 async db query + case CMSG_GMTICKET_UPDATETEXT: // 0 15 1 async db query + case CMSG_GMTICKET_DELETETICKET: // 1 25 1 async db query + case CMSG_GMRESPONSE_RESOLVE: // 1 25 1 async db query + case CMSG_CALENDAR_UPDATE_EVENT: // not profiled + case CMSG_CALENDAR_REMOVE_EVENT: // not profiled + case CMSG_CALENDAR_COPY_EVENT: // not profiled + case CMSG_CALENDAR_EVENT_INVITE: // not profiled + case CMSG_CALENDAR_EVENT_SIGNUP: // not profiled + case CMSG_CALENDAR_EVENT_RSVP: // not profiled + case CMSG_CALENDAR_EVENT_REMOVE_INVITE: // not profiled + case CMSG_CALENDAR_EVENT_MODERATOR_STATUS: // not profiled + case CMSG_ARENA_TEAM_INVITE: // not profiled + case CMSG_ARENA_TEAM_ACCEPT: // not profiled + case CMSG_ARENA_TEAM_DECLINE: // not profiled + case CMSG_ARENA_TEAM_LEAVE: // not profiled + case CMSG_ARENA_TEAM_DISBAND: // not profiled + case CMSG_ARENA_TEAM_REMOVE: // not profiled + case CMSG_ARENA_TEAM_LEADER: // not profiled + case CMSG_LOOT_METHOD: // not profiled + case CMSG_GUILD_INVITE: // not profiled + case CMSG_GUILD_ACCEPT: // not profiled + case CMSG_GUILD_DECLINE: // not profiled + case CMSG_GUILD_LEAVE: // not profiled + case CMSG_GUILD_DISBAND: // not profiled + case CMSG_GUILD_LEADER: // not profiled + case CMSG_GUILD_MOTD: // not profiled + case CMSG_GUILD_RANK: // not profiled + case CMSG_GUILD_ADD_RANK: // not profiled + case CMSG_GUILD_DEL_RANK: // not profiled + case CMSG_GUILD_INFO_TEXT: // not profiled + case CMSG_GUILD_BANK_DEPOSIT_MONEY: // not profiled + case CMSG_GUILD_BANK_WITHDRAW_MONEY: // not profiled + case CMSG_GUILD_BANK_BUY_TAB: // not profiled + case CMSG_GUILD_BANK_UPDATE_TAB: // not profiled + case CMSG_SET_GUILD_BANK_TEXT: // not profiled + case MSG_SAVE_GUILD_EMBLEM: // not profiled + case MSG_PETITION_RENAME: // not profiled + case MSG_PETITION_DECLINE: // not profiled + case MSG_TALENT_WIPE_CONFIRM: // not profiled + case MSG_SET_DUNGEON_DIFFICULTY: // not profiled + case MSG_SET_RAID_DIFFICULTY: // not profiled + case MSG_RANDOM_ROLL: // not profiled + case MSG_PARTY_ASSIGNMENT: // not profiled + case MSG_RAID_READY_CHECK: // not profiled { - maxPacketCounterAllowed = MAX_ACTION_BUTTONS; + maxPacketCounterAllowed = 3; break; } - case CMSG_ITEM_REFUND_INFO: + case CMSG_ITEM_REFUND_INFO: // not profiled { maxPacketCounterAllowed = PLAYER_SLOTS_COUNT; break; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 2f5f17952db..61d2fa6d106 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -937,7 +937,6 @@ class WorldSession public: DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) { } bool EvaluateOpcode(WorldPacket& p, time_t time) const; - void AllowOpcode(uint16 opcode, bool allow) { _isOpcodeAllowed[opcode] = allow; } protected: enum Policy { @@ -946,22 +945,11 @@ class WorldSession POLICY_BAN, }; - bool IsOpcodeAllowed(uint16 opcode) const - { - OpcodeStatusMap::const_iterator itr = _isOpcodeAllowed.find(opcode); - if (itr == _isOpcodeAllowed.end()) - return true; // No presence in the map indicates this is the first time the opcode was sent this session, so allow - - return itr->second; - } - uint32 GetMaxPacketCounterAllowed(uint16 opcode) const; WorldSession* Session; private: - typedef std::unordered_map OpcodeStatusMap; - OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes Policy _policy; typedef std::unordered_map PacketThrottlingMap; // mark this member as "mutable" so it can be modified even in const functions -- cgit v1.2.3 From 87692078541ca5ab14a59f97380486a4a66ce8f0 Mon Sep 17 00:00:00 2001 From: Golrag Date: Tue, 18 Mar 2014 08:07:08 +0100 Subject: Core/Spells: Fixed Shadowstep taking the caster out of combat while it shouldn't --- src/server/game/Entities/Player/Player.cpp | 3 ++- src/server/game/Spells/SpellEffects.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 433551104b9..04451d9aa8a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7486,7 +7486,8 @@ void Player::UpdateArea(uint32 newArea) { SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); pvpInfo.IsInNoPvPArea = true; - CombatStopWithPets(); + if (!duel) + CombatStopWithPets(); } else RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 5b68d244457..6108bf87478 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1096,7 +1096,7 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/) TC_LOG_DEBUG("spells", "Spell::EffectTeleportUnits - teleport unit to %u %f %f %f %f\n", mapid, x, y, z, orientation); if (unitTarget->GetTypeId() == TYPEID_PLAYER) - unitTarget->ToPlayer()->TeleportTo(mapid, x, y, z, orientation, unitTarget == m_caster ? TELE_TO_SPELL : 0); + unitTarget->ToPlayer()->TeleportTo(mapid, x, y, z, orientation, unitTarget == m_caster ? TELE_TO_SPELL | TELE_TO_NOT_LEAVE_COMBAT : 0); else if (mapid == unitTarget->GetMapId()) unitTarget->NearTeleportTo(x, y, z, orientation, unitTarget == m_caster); else -- cgit v1.2.3 From eb414532fe42d4bc725cb98b41965b392fb130ce Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Fri, 9 May 2014 10:19:44 +0100 Subject: Core/CreatureAI: Implement CreatureAI::TalkToMap for all your map-wide talking needs. Could also replace Battleground::SendChatMessage --- src/server/game/AI/CreatureAI.cpp | 5 +++++ src/server/game/AI/CreatureAI.h | 1 + .../CullingOfStratholme/instance_culling_of_stratholme.cpp | 2 +- src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp | 5 ++--- 4 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index dd8b42deb9f..ac9de00cd10 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -43,6 +43,11 @@ void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= NULL*/) sCreatureTextMgr->SendChat(me, id, whisperTarget); } +void CreatureAI::TalkToMap(uint8 id, WorldObject const* whisperTarget /*= NULL*/) +{ + sCreatureTextMgr->SendChat(me, id, whisperTarget, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); +} + void CreatureAI::DoZoneInCombat(Creature* creature /*= NULL*/, float maxRangeToNearestTarget /* = 50.0f*/) { if (!creature) diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index 6357ac33f1e..209995d359d 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -79,6 +79,7 @@ class CreatureAI : public UnitAI public: void Talk(uint8 id, WorldObject const* whisperTarget = NULL); + void TalkToMap(uint8 id, WorldObject const* whisperTarget = NULL); explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), m_MoveInLineOfSight_locked(false) { } virtual ~CreatureAI() { } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp index dbd844aa34c..503166e0b12 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -187,7 +187,7 @@ class instance_culling_of_stratholme : public InstanceMapScript // Summon Chromie and global whisper if (Creature* chromie = instance->SummonCreature(NPC_CHROMIE_2, ChromieSummonPos)) if (!instance->GetPlayers().isEmpty()) - sCreatureTextMgr->SendChat(chromie, SAY_CRATES_COMPLETED, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); + chromie->AI()->TalkToMap(SAY_CRATES_COMPLETED); } DoUpdateWorldState(WORLDSTATE_CRATES_REVEALED, _crateCount); break; diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 192249955cf..fefdfa633ea 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -664,7 +664,7 @@ public: Talk(SAY_BUFF_SPARK); } else if (spell->Id == SPELL_MALYGOS_BERSERK) - sCreatureTextMgr->SendChat(me, EMOTE_HIT_BERSERKER_TIMER, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); + TalkToMap(EMOTE_HIT_BERSERKER_TIMER); } void MoveInLineOfSight(Unit* who) override @@ -1113,8 +1113,7 @@ public: npc_power_sparkAI(Creature* creature) : ScriptedAI(creature) { _instance = creature->GetInstanceScript(); - // Talk range was not enough for this encounter - sCreatureTextMgr->SendChat(me, EMOTE_POWER_SPARK_SUMMONED, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); + TalkToMap(EMOTE_POWER_SPARK_SUMMONED); MoveToMalygos(); } -- cgit v1.2.3 From 95a94f89b23e5db2b77f3fcd1117cf62123cef1e Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 15 May 2014 17:02:14 +0100 Subject: Core/Spells: Fix Cheat Death formula --- src/server/game/Entities/Unit/Unit.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4efa1374ec7..a84cdbef1b3 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -10280,9 +10280,10 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui case 2109: if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) { - if (GetTypeId() != TYPEID_PLAYER) - continue; - float mod = ToPlayer()->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE) * (-8.0f); + // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap + // is 22.5% critical strike damage reduction, or 444 resilience. + // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%) + float mod = -1.0f * GetMeleeCritDamageReduction(400); AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount()))); } break; @@ -11364,9 +11365,10 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT case 2109: if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) { - if (GetTypeId() != TYPEID_PLAYER) - continue; - float mod = ToPlayer()->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE) * (-8.0f); + // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap + // is 22.5% critical strike damage reduction, or 444 resilience. + // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%) + float mod = -1.0f * GetMeleeCritDamageReduction(400); AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount()))); } break; -- cgit v1.2.3 From c755a51ce0a91aa58bd9a0a930cea94813442300 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Tue, 3 Jun 2014 00:39:20 +0100 Subject: Core/Auras: Update model overwriting rules for SPELL_AURA_TRANSFORM --- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 2096f21e5a1..07691e14e4f 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1672,9 +1672,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo if (aurApp->GetRemoveMode()) return; - if (modelid > 0) - target->SetDisplayId(modelid); - if (PowerType != POWER_MANA) { uint32 oldPower = target->GetPower(PowerType); @@ -1725,6 +1722,12 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo return; target->SetShapeshiftForm(form); + if (modelid > 0) + { + SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm()); + if (!transformSpellInfo || !GetSpellInfo()->IsPositive()) + target->SetDisplayId(modelid); + } } else { @@ -1847,9 +1850,11 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, if (apply) { - // update active transform spell only when transform or shapeshift not set or not overwriting negative by positive case - if (!target->GetModelForForm(target->GetShapeshiftForm()) || !GetSpellInfo()->IsPositive()) + // update active transform spell only when transform not set or not overwriting negative by positive case + SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm()); + if (!transformSpellInfo || !GetSpellInfo()->IsPositive() || transformSpellInfo->IsPositive()) { + target->setTransForm(GetId()); // special case (spell specific functionality) if (GetMiscValue() == 0) { @@ -2018,11 +2023,6 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode, } } - // update active transform spell only when transform or shapeshift not set or not overwriting negative by positive case - SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm()); - if (!transformSpellInfo || !GetSpellInfo()->IsPositive() || transformSpellInfo->IsPositive()) - target->setTransForm(GetId()); - // polymorph case if ((mode & AURA_EFFECT_HANDLE_REAL) && target->GetTypeId() == TYPEID_PLAYER && target->IsPolymorphed()) { -- cgit v1.2.3 From 94b6c1b5443c9def94c3dbf4fa79fff059a31c1a Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Tue, 3 Jun 2014 00:57:36 +0100 Subject: Core/Maps: Allow logging players to enter in instances that have an encounter in progress --- src/server/game/Entities/Player/Player.cpp | 5 +++++ src/server/game/Entities/Player/Player.h | 2 ++ src/server/game/Maps/Map.cpp | 7 +++---- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 04451d9aa8a..fca7b79e8e0 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -26758,3 +26758,8 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy return pet; } + +bool Player::IsLoading() const +{ + return GetSession()->PlayerLoading(); +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 52674032c0a..94175834969 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2303,6 +2303,8 @@ class Player : public Unit, public GridObject std::string GetMapAreaAndZoneString(); std::string GetCoordsMapAreaAndZoneString(); + bool IsLoading() const; + protected: // Gamemaster whisper whitelist WhisperListContainer WhisperList; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index ba271235330..d3be33cb441 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2854,10 +2854,9 @@ bool InstanceMap::CanEnter(Player* player) return false; } - // cannot enter while an encounter is in progress on raids - /*Group* group = player->GetGroup(); - if (!player->IsGameMaster() && group && group->InCombatToInstance(GetInstanceId()) && player->GetMapId() != GetId())*/ - if (IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress()) + // cannot enter while an encounter is in progress + // allow if just loading + if (!player->IsLoading() && IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress()) { player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT); return false; -- cgit v1.2.3 From ca6e9112e95956949b3afd2d5f0ea9c99a0b39e5 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Tue, 3 Jun 2014 01:12:34 +0100 Subject: Core/WorldSession: After sudden disconnects, session should persist for a minute - With this change, if a player alt-f4, he'll only fade from world after a minute --- src/server/game/Server/WorldSession.cpp | 16 ++++++++++++---- src/server/game/Server/WorldSession.h | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 9f052b75386..61a2e05d9be 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -121,7 +121,9 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 m_TutorialsChanged(false), recruiterId(recruiter), isRecruiter(isARecruiter), - _RBACData(NULL) + _RBACData(NULL), + expireTime(60000), // 1 min after socket loss, session is deleted + forceExit(false) { memset(m_Tutorials, 0, sizeof(m_Tutorials)); @@ -419,8 +421,12 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) ///- Cleanup socket pointer if need if (m_Socket && m_Socket->IsClosed()) { - m_Socket->RemoveReference(); - m_Socket = NULL; + expireTime -= expireTime > diff ? diff : expireTime; + if (expireTime < diff || forceExit) + { + m_Socket->RemoveReference(); + m_Socket = NULL; + } } if (!m_Socket) @@ -446,7 +452,6 @@ void WorldSession::LogoutPlayer(bool save) DoLootRelease(lguid); ///- If the player just died before logging out, make him appear as a ghost - //FIXME: logout must be delayed in case lost connection with client in time of combat if (_player->GetDeathTimer()) { _player->getHostileRefManager().deleteReferences(); @@ -576,7 +581,10 @@ void WorldSession::LogoutPlayer(bool save) void WorldSession::KickPlayer() { if (m_Socket) + { m_Socket->CloseSocket(); + forceExit = true; + } } void WorldSession::SendNotification(const char *format, ...) diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 968f5a229ba..82125aafd6d 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -1021,6 +1021,8 @@ class WorldSession bool isRecruiter; ACE_Based::LockedQueue _recvQueue; rbac::RBACData* _RBACData; + uint32 expireTime; + bool forceExit; WorldSession(WorldSession const& right) = delete; WorldSession& operator=(WorldSession const& right) = delete; -- cgit v1.2.3 From 3a9c73008315a0eaa114937eaa1c85b44bc1f9da Mon Sep 17 00:00:00 2001 From: jackpoz Date: Wed, 4 Jun 2014 19:45:02 +0200 Subject: Core/Tickets: Don't try to save the same sub-survey more than once --- src/server/game/Handlers/TicketHandler.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index 1378f9b3f2d..a2aa426c096 100644 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -187,6 +187,7 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData) uint32 mainSurvey; // GMSurveyCurrentSurvey.dbc, column 1 (all 9) ref to GMSurveySurveys.dbc recvData >> mainSurvey; + std::unordered_set surveyIds; SQLTransaction trans = CharacterDatabase.BeginTransaction(); // sub_survey1, r1, comment1, sub_survey2, r2, comment2, sub_survey3, r3, comment3, sub_survey4, r4, comment4, sub_survey5, r5, comment5, sub_survey6, r6, comment6, sub_survey7, r7, comment7, sub_survey8, r8, comment8, sub_survey9, r9, comment9, sub_survey10, r10, comment10, for (uint8 i = 0; i < 10; i++) @@ -201,6 +202,10 @@ void WorldSession::HandleGMSurveySubmit(WorldPacket& recvData) std::string comment; // comment ("Usage: GMSurveyAnswerSubmit(question, rank, comment)") recvData >> comment; + // make sure the same sub survey is not added to DB twice + if (!surveyIds.insert(subSurveyId).second) + continue; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GM_SUBSURVEY); stmt->setUInt32(0, nextSurveyID); stmt->setUInt32(1, subSurveyId); -- cgit v1.2.3 From fbae790c1dd46ac24f3c46976c2dc4a09963a319 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Wed, 4 Jun 2014 19:12:02 +0100 Subject: Warning fix --- src/server/game/Entities/Player/Player.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index fca7b79e8e0..b470bd1e26b 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5964,6 +5964,8 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) ApplyCastTimePercentMod(oldVal, false); ApplyCastTimePercentMod(newVal, true); break; + default: // shut up compiler warnings + break; } } -- cgit v1.2.3 From e0d08f5afb959131719796e552bb7f5fa41a7896 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 5 Jun 2014 11:35:32 +0100 Subject: Core/Spells: Corpse Explosion should not be able to pick the Ghoul out of implicit targets --- src/server/scripts/Spells/spell_dk.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 6a6ee144aac..5ae0e1601c5 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -322,13 +322,14 @@ class spell_dk_blood_gorged : public SpellScriptLoader class CorpseExplosionCheck { public: - explicit CorpseExplosionCheck(uint64 casterGUID) : _casterGUID(casterGUID) { } + explicit CorpseExplosionCheck(uint64 casterGUID, bool allowGhoul) : _casterGUID(casterGUID), + _allowGhoul(allowGhoul) { } bool operator()(WorldObject* obj) const { if (Unit* target = obj->ToUnit()) { - if ((target->isDead() || (target->GetEntry() == NPC_DK_GHOUL && target->GetOwnerGUID() == _casterGUID)) + if ((target->isDead() || (_allowGhoul && target->GetEntry() == NPC_DK_GHOUL && target->GetOwnerGUID() == _casterGUID)) && !(target->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL) && target->GetDisplayId() == target->GetNativeDisplayId()) return false; @@ -339,6 +340,7 @@ public: private: uint64 _casterGUID; + bool _allowGhoul; }; // 49158 - Corpse Explosion (51325, 51326, 51327, 51328) @@ -369,7 +371,7 @@ class spell_dk_corpse_explosion : public SpellScriptLoader void CheckTarget(WorldObject*& target) { - if (CorpseExplosionCheck(GetCaster()->GetGUID())(target)) + if (CorpseExplosionCheck(GetCaster()->GetGUID(), true)(target)) target = NULL; _target = target; @@ -380,7 +382,7 @@ class spell_dk_corpse_explosion : public SpellScriptLoader WorldObject* target = _target; if (!target) { - targets.remove_if(CorpseExplosionCheck(GetCaster()->GetGUID())); + targets.remove_if(CorpseExplosionCheck(GetCaster()->GetGUID(), false)); if (targets.empty()) { FinishCast(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW); -- cgit v1.2.3 From e3b8cd5c7e0fcd1d73c67769abb67a7a029964c2 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 5 Jun 2014 11:37:24 +0100 Subject: Scripts/ToCr: Bosses shouldn't despawn so quickly --- .../CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h index 562105c0866..8a62453d7c1 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -40,7 +40,7 @@ enum SpellIds enum MiscData { - DESPAWN_TIME = 300000, + DESPAWN_TIME = 1200000, DISPLAYID_DESTROYED_FLOOR = 9060 }; -- cgit v1.2.3 From 3dce4fabae92db5195287d861b459080f6cd0371 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 5 Jun 2014 11:43:59 +0100 Subject: Core/Spells: Swift Retribution should be reapplied when needed to be able to gain spellmods --- src/server/scripts/Spells/spell_paladin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index bf4f1b77a19..447cb645e76 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -866,8 +866,8 @@ class spell_pal_improved_aura : public SpellScriptLoader void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { Unit* target = GetTarget(); - if (!target->GetOwnedAura(_spellId)) - target->CastSpell(target, _spellId, true); + GetTarget()->RemoveOwnedAura(_spellId, GetCasterGUID()); // need to remove to reapply spellmods + target->CastSpell(target, _spellId, true); } void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) -- cgit v1.2.3 From 281527a9c33429ccc8fd552ea231857120a6017d Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 5 Jun 2014 11:48:43 +0100 Subject: Core/Spells: *Properly* solve the Disarm vs Bladestorm issue --- src/server/game/Spells/Spell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index efdc3ca532f..f5d90bc3612 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -567,7 +567,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme m_spellState = SPELL_STATE_NULL; _triggeredCastFlags = triggerFlags; if (info->AttributesEx4 & SPELL_ATTR4_TRIGGERED) - _triggeredCastFlags = TRIGGERED_FULL_MASK; + _triggeredCastFlags = TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT); m_CastItem = NULL; m_castItemGUID = 0; -- cgit v1.2.3 From 1e545eaa70a0a64592ba4e20f0224e0a27a28937 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Thu, 5 Jun 2014 22:19:02 +0200 Subject: Core/Talents: Align server checks to Client limits Set the max amount of talents to process in CMSG_LEARN_PREVIEW_TALENTS to 150 ( 44 talents for 3 trees rounded up ). --- src/server/game/Handlers/SkillHandler.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index fe893314b87..b7e918ee05b 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -45,7 +45,10 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) uint32 talentId, talentRank; - for (uint32 i = 0; i < talentsCount; ++i) + // Client has max 44 talents for tree for 3 trees, rounded up : 150 + const int MaxTalentsCount = 150; + + for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i) { recvPacket >> talentId >> talentRank; @@ -53,6 +56,8 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) } _player->SendTalentsInfoData(false); + + recvPacket.rfinish(); } void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData) -- cgit v1.2.3 From 9c240c14ecd691e1e6506dfeca4bb2e85c6b0418 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Thu, 5 Jun 2014 22:50:11 +0200 Subject: Core/Talents: Align server checks to Client limits Set the max amount of talents to process in CMSG_LEARN_PREVIEW_TALENTS_PET to 30 ( 24 talents rounded up ). --- src/server/game/Handlers/PetHandler.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 616ea9c7326..98dfe1af22c 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -868,7 +868,10 @@ void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData) uint32 talentId, talentRank; - for (uint32 i = 0; i < talentsCount; ++i) + // Client has max 24 talents, rounded up : 30 + const int MaxTalentsCount = 30; + + for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i) { recvData >> talentId >> talentRank; @@ -876,4 +879,6 @@ void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData) } _player->SendTalentsInfoData(true); + + recvData.rfinish(); } -- cgit v1.2.3 From 46c752408408c6a3435dd0294173840deeaf3b4e Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Fri, 6 Jun 2014 10:41:45 +0100 Subject: Core/Players: Improve quest item adding/removal checks, solves cases where quest item removal (under specific conditions) incorrectly incompletes quests --- src/server/game/Entities/Player/Player.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b470bd1e26b..297114e14d2 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -16384,12 +16384,8 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) uint16 curitemcount = q_status.ItemCount[j]; if (curitemcount < reqitemcount) { - uint16 additemcount = curitemcount + count <= reqitemcount ? count : reqitemcount - curitemcount; - q_status.ItemCount[j] += additemcount; - + q_status.ItemCount[j] = std::min(q_status.ItemCount[j] + count, reqitemcount); m_QuestStatusSave[questid] = true; - - SendQuestUpdateAddItem(qInfo, j, additemcount); } if (CanCompleteQuest(questid)) CompleteQuest(questid); @@ -16407,9 +16403,11 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count) uint32 questid = GetQuestSlotQuestId(i); if (!questid) continue; + Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); if (!qInfo) continue; + if (!qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) continue; @@ -16421,18 +16419,17 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count) QuestStatusData& q_status = m_QuestStatus[questid]; uint32 reqitemcount = qInfo->RequiredItemCount[j]; - uint16 curitemcount; - if (q_status.Status != QUEST_STATUS_COMPLETE) - curitemcount = q_status.ItemCount[j]; - else - curitemcount = GetItemCount(entry, true); - if (curitemcount < reqitemcount + count) - { - uint16 remitemcount = curitemcount <= reqitemcount ? count : count + reqitemcount - curitemcount; - q_status.ItemCount[j] = (curitemcount <= remitemcount) ? 0 : curitemcount - remitemcount; + uint16 curitemcount = q_status.ItemCount[j]; - m_QuestStatusSave[questid] = true; + if (q_status.ItemCount[j] >= reqitemcount) // we may have more than what the status shows + curitemcount = GetItemCount(entry, false); + uint16 newItemCount = (count > curitemcount) ? 0 : curitemcount - count; + newItemCount = std::min(newItemCount, reqitemcount); + if (newItemCount != q_status.ItemCount[j]) + { + q_status.ItemCount[j] = newItemCount; + m_QuestStatusSave[questid] = true; IncompleteQuest(questid); } return; -- cgit v1.2.3 From 78f1cbfba522882acdfd5ddea2edefd88881c3c6 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Fri, 6 Jun 2014 11:01:36 +0100 Subject: Scripts/Items: Imp in a Ball --- sql/updates/world/2014_06_06_00_world_misc.sql | 92 ++++++++++++++++++++++++++ src/server/game/Texts/CreatureTextMgr.cpp | 13 ++++ src/server/scripts/World/npcs_special.cpp | 56 ++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 sql/updates/world/2014_06_06_00_world_misc.sql (limited to 'src') diff --git a/sql/updates/world/2014_06_06_00_world_misc.sql b/sql/updates/world/2014_06_06_00_world_misc.sql new file mode 100644 index 00000000000..a1d4dd621c0 --- /dev/null +++ b/sql/updates/world/2014_06_06_00_world_misc.sql @@ -0,0 +1,92 @@ + +UPDATE creature_template SET ScriptName="npc_imp_in_a_ball" WHERE entry=23224; + +SET @COUNT := 0; +DELETE FROM creature_text WHERE entry=23224; +INSERT INTO creature_text (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`, `BroadcastTextID`) VALUES +(23224, 0, @COUNT := @COUNT + 1, 'Yes, unless I have anything to do with it.', 15, 0, 100, 0, 0, 0, '', 21157), +(23224, 0, @COUNT := @COUNT + 1, 'I see that happening sometime between tomorrow and the next decade. Definitely.', 15, 0, 100, 0, 0, 0, '', 21158), +(23224, 0, @COUNT := @COUNT + 1, 'Looks good for you...and bad for me.', 15, 0, 100, 0, 0, 0, '', 21160), +(23224, 0, @COUNT := @COUNT + 1, 'I\'ve consulted my fellow imps, and we think YES, except for that one imp.', 15, 0, 100, 0, 0, 0, '', 21161), +(23224, 0, @COUNT := @COUNT + 1, 'The outlook is positive, but I\'m still negative.', 15, 0, 100, 0, 0, 0, '', 21162), +(23224, 0, @COUNT := @COUNT + 1, 'It pains me to say this, but "Yes".', 15, 0, 100, 0, 0, 0, '', 21163), +(23224, 0, @COUNT := @COUNT + 1, 'When dwarves fly! They do? Then yes!', 15, 0, 100, 0, 0, 0, '', 21164), +(23224, 0, @COUNT := @COUNT + 1, 'Sure, but you\'re not going to like it.', 15, 0, 100, 0, 0, 0, '', 21165), +(23224, 0, @COUNT := @COUNT + 1, 'Be quiet \'bout what you hear and see around here, $r.', 15, 0, 100, 0, 0, 0, '', 21166), +(23224, 0, @COUNT := @COUNT + 1, 'Unfortunately... yes.', 15, 0, 100, 0, 0, 0, '', 21169), +(23224, 0, @COUNT := @COUNT + 1, 'I can\'t see why not, although, I can\'t see a lot of things right now.', 15, 0, 100, 0, 0, 0, '', 21170), +(23224, 0, @COUNT := @COUNT + 1, 'I would bet your soul on it.', 15, 0, 100, 0, 0, 0, '', 21171), +(23224, 0, @COUNT := @COUNT + 1, 'Yes, but if anyone asks... It wasn\'t me who told you.', 15, 0, 100, 0, 0, 0, '', 21172), +(23224, 0, @COUNT := @COUNT + 1, 'Didn\'t you already ask that once? Yes already!', 15, 0, 100, 0, 0, 0, '', 21173), +(23224, 0, @COUNT := @COUNT + 1, 'Please... Is Kil\'jaeden red?', 15, 0, 100, 0, 0, 0, '', 21175), +(23224, 0, @COUNT := @COUNT + 1, 'Yeah, sure. You just keep thinking that.', 15, 0, 100, 0, 0, 0, '', 21176), +(23224, 0, @COUNT := @COUNT + 1, 'I suppose.', 15, 0, 100, 0, 0, 0, '', 21177), +(23224, 0, @COUNT := @COUNT + 1, 'Definitely.', 15, 0, 100, 0, 0, 0, '', 21178), +(23224, 0, @COUNT := @COUNT + 1, 'Jump three times and dance for ten minutes and it will definitely happen!', 15, 0, 100, 0, 0, 0, '', 21179), +(23224, 0, @COUNT := @COUNT + 1, 'Word on the peninsula is YES!', 15, 0, 100, 0, 0, 0, '', 21180), +(23224, 0, @COUNT := @COUNT + 1, 'Oh, that one\'s for sure.', 15, 0, 100, 0, 0, 0, '', 21181), +(23224, 0, @COUNT := @COUNT + 1, 'Yes, but not in the way you imagine.', 15, 0, 100, 0, 0, 0, '', 21182), +(23224, 0, @COUNT := @COUNT + 1, 'Yes, yes, a thousand times, yes already!', 15, 0, 100, 0, 0, 0, '', 21183), +(23224, 0, @COUNT := @COUNT + 1, 'Yes, now stop pestering me!', 15, 0, 100, 0, 0, 0, '', 21184), +(23224, 0, @COUNT := @COUNT + 1, 'The answer will be a yes if you let me out of here.', 15, 0, 100, 0, 0, 0, '', 21185), +(23224, 0, @COUNT := @COUNT + 1, 'It\'s as sure as the warts on my backside!', 15, 0, 100, 0, 0, 0, '', 21186), +(23224, 0, @COUNT := @COUNT + 1, 'The answer is yes in here, I don\'t see why it would be any different out there.', 15, 0, 100, 0, 0, 0, '', 21187), +(23224, 0, @COUNT := @COUNT + 1, 'Three words - "ab - so - lutely"!', 15, 0, 100, 0, 0, 0, '', 21188), +(23224, 0, @COUNT := @COUNT + 1, 'Yes, but I hoped I would never have to answer that.', 15, 0, 100, 0, 0, 0, '', 21189), +(23224, 0, @COUNT := @COUNT + 1, 'Ask me again later - I\'m trying to scratch my nose and it\'s hard to concentrate.', 15, 0, 100, 0, 0, 0, '', 21190), +(23224, 0, @COUNT := @COUNT + 1, 'Why should I answer that? Do you tell fortunes when people shake YOU?', 15, 0, 100, 0, 0, 0, '', 21191), +(23224, 0, @COUNT := @COUNT + 1, 'Yes, it will rain. That\'s not what you asked? Too bad!', 15, 0, 100, 0, 0, 0, '', 21192), +(23224, 0, @COUNT := @COUNT + 1, 'I\'m sorry, I can only speak Demonic.', 15, 0, 100, 0, 0, 0, '', 21193), +(23224, 0, @COUNT := @COUNT + 1, 'Yes! I mean no! I mean... which answer gets me out of here?', 15, 0, 100, 0, 0, 0, '', 21194), +(23224, 0, @COUNT := @COUNT + 1, 'Yes, No, Maybe so.', 15, 0, 100, 0, 0, 0, '', 21195), +(23224, 0, @COUNT := @COUNT + 1, 'It won\'t matter, you\'ll be dead by tomorrow.', 15, 0, 100, 0, 0, 0, '', 21196), +(23224, 0, @COUNT := @COUNT + 1, 'You should be asking "Is that rogue behind me going to kill me?"', 15, 0, 100, 0, 0, 0, '', 21197), +(23224, 0, @COUNT := @COUNT + 1, 'It\'s times like these that I wish I had a longer cooldown.', 15, 0, 100, 0, 0, 0, '', 21198), +(23224, 0, @COUNT := @COUNT + 1, '%s shrugs. Who knows?', 15, 0, 100, 0, 0, 0, '', 21199), +(23224, 0, @COUNT := @COUNT + 1, 'It\'s like my mother always said: [Demonic] "Razxx khaj jhashxx xashjx."', 15, 0, 100, 0, 0, 0, '', 21205), +(23224, 0, @COUNT := @COUNT + 1, '%s is ignoring you.', 15, 0, 100, 0, 0, 0, '', 21206), +(23224, 0, @COUNT := @COUNT + 1, 'Why me? Why not a goblin, or a gnome...', 15, 0, 100, 0, 0, 0, '', 21207), +(23224, 0, @COUNT := @COUNT + 1, 'What happens in the twisting nether, stays in the twisting nether.', 15, 0, 100, 0, 0, 0, '', 21208), +(23224, 0, @COUNT := @COUNT + 1, 'Avoid taking unnecessary gambles. Your lucky numbers are two, two and half, and eleven-teen.', 15, 0, 100, 0, 0, 0, '', 21209), +(23224, 0, @COUNT := @COUNT + 1, 'Wouldn\'t you like to know?', 15, 0, 100, 0, 0, 0, '', 21210), +(23224, 0, @COUNT := @COUNT + 1, 'Oh, oh, oh! I can see this one clearly... Nah, lost it.', 15, 0, 100, 0, 0, 0, '', 21211), +(23224, 0, @COUNT := @COUNT + 1, 'This was NOT in my contract!', 15, 0, 100, 0, 0, 0, '', 21212), +(23224, 0, @COUNT := @COUNT + 1, 'XRA RAHKI MAZIZRA!', 15, 0, 100, 0, 0, 0, '', 21213), +(23224, 0, @COUNT := @COUNT + 1, '4 8 15 16 23 42', 15, 0, 100, 0, 0, 0, '', 21214), +(23224, 0, @COUNT := @COUNT + 1, 'Are you making fun of me?', 15, 0, 100, 0, 0, 0, '', 21215), +(23224, 0, @COUNT := @COUNT + 1, 'What kind of imp do you think I am?', 15, 0, 100, 0, 0, 0, '', 21216), +(23224, 0, @COUNT := @COUNT + 1, 'Say please.', 15, 0, 100, 0, 0, 0, '', 21217), +(23224, 0, @COUNT := @COUNT + 1, 'Want to trade places?', 15, 0, 100, 0, 0, 0, '', 21218), +(23224, 0, @COUNT := @COUNT + 1, 'Do you ask this question to everything that\'s trapped in a ball?', 15, 0, 100, 0, 0, 0, '', 21219), +(23224, 0, @COUNT := @COUNT + 1, 'Hey! You try arranging furniture with some jerk shaking your house!', 15, 0, 100, 0, 0, 0, '', 21220), +(23224, 0, @COUNT := @COUNT + 1, 'I can make that happen. Just sign below the dotted line...', 15, 0, 100, 0, 0, 0, '', 21221), +(23224, 0, @COUNT := @COUNT + 1, 'Reply hazy and slightly damp. Dry thoroughly and try again.', 15, 0, 100, 0, 0, 0, '', 21222), +(23224, 0, @COUNT := @COUNT + 1, 'Concentrate (on releasing me from this infernal prison) and try again later.', 15, 0, 100, 0, 0, 0, '', 21223), +(23224, 0, @COUNT := @COUNT + 1, 'Please insert 25 silver pieces and try again.', 15, 0, 100, 0, 0, 0, '', 21224), +(23224, 0, @COUNT := @COUNT + 1, 'Are you my pal, Danny?', 15, 0, 100, 0, 0, 0, '', 21225), +(23224, 0, @COUNT := @COUNT + 1, 'You remember the time you tried to drill that hole in your head?', 15, 0, 100, 0, 0, 0, '', 21226), +(23224, 0, @COUNT := @COUNT + 1, 'Oh that\'s right, don\'t make any effort to make your own fortune!', 15, 0, 100, 0, 0, 0, '', 21227), +(23224, 0, @COUNT := @COUNT + 1, 'Two words - imp-possible!', 15, 0, 100, 0, 0, 0, '', 21228), +(23224, 0, @COUNT := @COUNT + 1, 'You need Arcane Intellect, because that answer is obvious! NO!', 15, 0, 100, 0, 0, 0, '', 21229), +(23224, 0, @COUNT := @COUNT + 1, 'Not on your life!', 15, 0, 100, 0, 0, 0, '', 21230), +(23224, 0, @COUNT := @COUNT + 1, 'I don\'t have to be a fortune-telling imp to know the answer to that one - NO!', 15, 0, 100, 0, 0, 0, '', 21231), +(23224, 0, @COUNT := @COUNT + 1, 'The odds are 32.33 (repeating of course) percent chance of success.', 15, 0, 100, 0, 0, 0, '', 21232), +(23224, 0, @COUNT := @COUNT + 1, 'When Blackrock freezes over!', 15, 0, 100, 0, 0, 0, '', 21233), +(23224, 0, @COUNT := @COUNT + 1, 'Hahahaha, you\'re kidding right?', 15, 0, 100, 0, 0, 0, '', 21234), +(23224, 0, @COUNT := @COUNT + 1, 'Inconceivable!', 15, 0, 100, 0, 0, 0, '', 21235), +(23224, 0, @COUNT := @COUNT + 1, 'My sources say "no". Before the torture, that is.', 15, 0, 100, 0, 0, 0, '', 21236), +(23224, 0, @COUNT := @COUNT + 1, 'That\'s about as likely as me getting out of this ball.', 15, 0, 100, 0, 0, 0, '', 21237), +(23224, 0, @COUNT := @COUNT + 1, 'You picked the wrong time to shake me today, buddy! Prepare for disappointment.', 15, 0, 100, 0, 0, 0, '', 21238), +(23224, 0, @COUNT := @COUNT + 1, 'Not unless you\'re some kind of super-person. And don\'t kid yourself, you\'re not.', 15, 0, 100, 0, 0, 0, '', 21239), +(23224, 0, @COUNT := @COUNT + 1, 'That\'s about as likely as me getting a date with a succubus.', 15, 0, 100, 0, 0, 0, '', 21240), +(23224, 0, @COUNT := @COUNT + 1, 'My fortune telling powers are immeasurable - your chances are though: NO CHANCE', 15, 0, 100, 0, 0, 0, '', 21241), +(23224, 0, @COUNT := @COUNT + 1, 'NO - and don\'t try shaking me again for a better answer!', 15, 0, 100, 0, 0, 0, '', 21242), +(23224, 0, @COUNT := @COUNT + 1, 'Yes is my answer...', 15, 0, 100, 0, 0, 0, '', 21243), +(23224, 0, @COUNT := @COUNT + 1, '...NOT!', 15, 0, 100, 0, 0, 0, '', 21244), +(23224, 0, @COUNT := @COUNT + 1, 'I\'m gonna have to give this one the big N-O.', 15, 0, 100, 0, 0, 0, '', 21245), +(23224, 0, @COUNT := @COUNT + 1, 'The outlook is very bad - for YOU that is! Haha, take it!', 15, 0, 100, 0, 0, 0, '', 21246), +(23224, 0, @COUNT := @COUNT + 1, 'Survey says: BZZZT!', 15, 0, 100, 0, 0, 0, '', 21247); + +DELETE FROM spell_linked_spell WHERE spell_trigger=40527 AND spell_effect=40528; +INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(40527, 40528, 0, 'Imp in a Bottle'); diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp index 57690d7e5c1..8bd7a5a5e71 100644 --- a/src/server/game/Texts/CreatureTextMgr.cpp +++ b/src/server/game/Texts/CreatureTextMgr.cpp @@ -24,6 +24,7 @@ #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "CreatureTextMgr.h" +#include "Group.h" class CreatureTextBuilder { @@ -346,6 +347,18 @@ void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data, } break; } + case CHAT_MSG_MONSTER_PARTY: + if (!whisperTarget) + return; + + if (Player const* player = whisperTarget->ToPlayer()) + { + if (Group* group = const_cast(player->GetGroup())) + for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + if (Player* member = itr->GetSource()) + member->GetSession()->SendPacket(data); + } + return; default: break; } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index bb7da1b7042..c32edff09bc 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -56,6 +56,7 @@ EndContentData */ #include "CellImpl.h" #include "SpellAuras.h" #include "Pet.h" +#include "CreatureTextMgr.h" /*######## # npc_air_force_bots @@ -2353,6 +2354,60 @@ public: }; }; +class npc_imp_in_a_ball : public CreatureScript +{ +private: + enum + { + SAY_RANDOM, + + EVENT_TALK = 1, + }; + +public: + npc_imp_in_a_ball() : CreatureScript("npc_imp_in_a_ball") { } + + struct npc_imp_in_a_ballAI : public ScriptedAI + { + npc_imp_in_a_ballAI(Creature* creature) : ScriptedAI(creature) + { + summonerGUID = 0; + } + + void IsSummonedBy(Unit* summoner) override + { + if (summoner->GetTypeId() == TYPEID_PLAYER) + { + summonerGUID = summoner->GetGUID(); + events.ScheduleEvent(EVENT_TALK, 3000); + } + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + if (events.ExecuteEvent() == EVENT_TALK) + { + if (Player* owner = ObjectAccessor::GetPlayer(*me, summonerGUID)) + { + sCreatureTextMgr->SendChat(me, SAY_RANDOM, owner, + owner->GetGroup() ? CHAT_MSG_MONSTER_PARTY : CHAT_MSG_MONSTER_WHISPER, LANG_ADDON, TEXT_RANGE_NORMAL); + } + } + } + + private: + EventMap events; + uint64 summonerGUID; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_imp_in_a_ballAI(creature); + } +}; + void AddSC_npcs_special() { new npc_air_force_bots(); @@ -2375,4 +2430,5 @@ void AddSC_npcs_special() new npc_experience(); new npc_firework(); new npc_spring_rabbit(); + new npc_imp_in_a_ball(); } -- cgit v1.2.3 From f14be42e0c034e315bf4c240e518b658db99e5f6 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Fri, 6 Jun 2014 11:14:32 +0100 Subject: Core/Utils: Move EventMap to Util.h --- src/server/game/AI/CreatureAIImpl.h | 349 ------------------------------------ src/server/shared/Utilities/Util.h | 349 ++++++++++++++++++++++++++++++++++++ 2 files changed, 349 insertions(+), 349 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/CreatureAIImpl.h b/src/server/game/AI/CreatureAIImpl.h index 378d3ca18ab..838171a544e 100644 --- a/src/server/game/AI/CreatureAIImpl.h +++ b/src/server/game/AI/CreatureAIImpl.h @@ -311,355 +311,6 @@ const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, c } } -class EventMap -{ - /** - * Internal storage type. - * Key: Time as uint32 when the event should occur. - * Value: The event data as uint32. - * - * Structure of event data: - * - Bit 0 - 15: Event Id. - * - Bit 16 - 23: Group - * - Bit 24 - 31: Phase - * - Pattern: 0xPPGGEEEE - */ - typedef std::multimap EventStore; - - public: - EventMap() : _time(0), _phase(0), _lastEvent(0) { } - - /** - * @name Reset - * @brief Removes all scheduled events and resets time and phase. - */ - void Reset() - { - _eventMap.clear(); - _time = 0; - _phase = 0; - } - - /** - * @name Update - * @brief Updates the timer of the event map. - * @param time Value to be added to time. - */ - void Update(uint32 time) - { - _time += time; - } - - /** - * @name GetTimer - * @return Current timer value. - */ - uint32 GetTimer() const - { - return _time; - } - - /** - * @name GetPhaseMask - * @return Active phases as mask. - */ - uint8 GetPhaseMask() const - { - return _phase; - } - - /** - * @name Empty - * @return True, if there are no events scheduled. - */ - bool Empty() const - { - return _eventMap.empty(); - } - - /** - * @name SetPhase - * @brief Sets the phase of the map (absolute). - * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase. - */ - void SetPhase(uint8 phase) - { - if (!phase) - _phase = 0; - else if (phase <= 8) - _phase = (1 << (phase - 1)); - } - - /** - * @name AddPhase - * @brief Activates the given phase (bitwise). - * @param phase Phase which should be activated. Values: 1 - 8 - */ - void AddPhase(uint8 phase) - { - if (phase && phase <= 8) - _phase |= (1 << (phase - 1)); - } - - /** - * @name RemovePhase - * @brief Deactivates the given phase (bitwise). - * @param phase Phase which should be deactivated. Values: 1 - 8. - */ - void RemovePhase(uint8 phase) - { - if (phase && phase <= 8) - _phase &= ~(1 << (phase - 1)); - } - - /** - * @name ScheduleEvent - * @brief Creates new event entry in map. - * @param eventId The id of the new event. - * @param time The time in milliseconds until the event occurs. - * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. - * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. - */ - void ScheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0) - { - if (group && group <= 8) - eventId |= (1 << (group + 15)); - - if (phase && phase <= 8) - eventId |= (1 << (phase + 23)); - - _eventMap.insert(EventStore::value_type(_time + time, eventId)); - } - - /** - * @name RescheduleEvent - * @brief Cancels the given event and reschedules it. - * @param eventId The id of the event. - * @param time The time in milliseconds until the event occurs. - * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. - * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. - */ - void RescheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0) - { - CancelEvent(eventId); - ScheduleEvent(eventId, time, group, phase); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event. - * @param time Time until the event occurs. - */ - void Repeat(uint32 time) - { - _eventMap.insert(EventStore::value_type(_time + time, _lastEvent)); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event. - * @param time Time until the event occurs. Equivalent to Repeat(urand(minTime, maxTime). - */ - void Repeat(uint32 minTime, uint32 maxTime) - { - Repeat(urand(minTime, maxTime)); - } - - /** - * @name ExecuteEvent - * @brief Returns the next event to execute and removes it from map. - * @return Id of the event to execute. - */ - uint32 ExecuteEvent() - { - while (!Empty()) - { - EventStore::iterator itr = _eventMap.begin(); - - if (itr->first > _time) - return 0; - else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase)) - _eventMap.erase(itr); - else - { - uint32 eventId = (itr->second & 0x0000FFFF); - _lastEvent = itr->second; // include phase/group - _eventMap.erase(itr); - return eventId; - } - } - - return 0; - } - - /** - * @name DelayEvents - * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0. - * @param delay Amount of delay. - */ - void DelayEvents(uint32 delay) - { - _time = delay < _time ? _time - delay : 0; - } - - /** - * @name DelayEvents - * @brief Delay all events of the same group. - * @param delay Amount of delay. - * @param group Group of the events. - */ - void DelayEvents(uint32 delay, uint32 group) - { - if (!group || group > 8 || Empty()) - return; - - EventStore delayed; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (itr->second & (1 << (group + 15))) - { - delayed.insert(EventStore::value_type(itr->first + delay, itr->second)); - _eventMap.erase(itr++); - } - else - ++itr; - } - - _eventMap.insert(delayed.begin(), delayed.end()); - } - - /** - * @name CancelEvent - * @brief Cancels all events of the specified id. - * @param eventId Event id to cancel. - */ - void CancelEvent(uint32 eventId) - { - if (Empty()) - return; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (eventId == (itr->second & 0x0000FFFF)) - _eventMap.erase(itr++); - else - ++itr; - } - } - - /** - * @name CancelEventGroup - * @brief Cancel events belonging to specified group. - * @param group Group to cancel. - */ - void CancelEventGroup(uint32 group) - { - if (!group || group > 8 || Empty()) - return; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (itr->second & (1 << (group + 15))) - _eventMap.erase(itr++); - else - ++itr; - } - } - - /** - * @name GetNextEventTime - * @brief Returns closest occurence of specified event. - * @param eventId Wanted event id. - * @return Time of found event. - */ - uint32 GetNextEventTime(uint32 eventId) const - { - if (Empty()) - return 0; - - for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) - if (eventId == (itr->second & 0x0000FFFF)) - return itr->first; - - return 0; - } - - /** - * @name GetNextEventTime - * @return Time of next event. - */ - uint32 GetNextEventTime() const - { - return Empty() ? 0 : _eventMap.begin()->first; - } - - /** - * @name IsInPhase - * @brief Returns wether event map is in specified phase or not. - * @param phase Wanted phase. - * @return True, if phase of event map contains specified phase. - */ - bool IsInPhase(uint8 phase) - { - return phase <= 8 && (!phase || _phase & (1 << (phase - 1))); - } - - /** - * @name GetTimeUntilEvent - * @brief Returns time in milliseconds until next event. - * @param Id of the event. - * @return Time of next event. - */ - uint32 GetTimeUntilEvent(uint32 eventId) const - { - for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) - if (eventId == (itr->second & 0x0000FFFF)) - return itr->first - _time; - - return std::numeric_limits::max(); - } - - private: - /** - * @name _time - * @brief Internal timer. - * - * This does not represent the real date/time value. - * It's more like a stopwatch: It can run, it can be stopped, - * it can be resetted and so on. Events occur when this timer - * has reached their time value. Its value is changed in the - * Update method. - */ - uint32 _time; - - /** - * @name _phase - * @brief Phase mask of the event map. - * - * Contains the phases the event map is in. Multiple - * phases from 1 to 8 can be set with SetPhase or - * AddPhase. RemovePhase deactives a phase. - */ - uint8 _phase; - - /** - * @name _eventMap - * @brief Internal event storage map. Contains the scheduled events. - * - * See typedef at the beginning of the class for more - * details. - */ - EventStore _eventMap; - - - /** - * @name _lastEvent - * @brief Stores information on the most recently executed event - */ - uint32 _lastEvent; -}; - enum AITarget { AITARGET_SELF, diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index b086a28134c..96d5a2abfea 100644 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -565,4 +565,353 @@ bool CompareValues(ComparisionType type, T val1, T val2) } } +class EventMap +{ + /** + * Internal storage type. + * Key: Time as uint32 when the event should occur. + * Value: The event data as uint32. + * + * Structure of event data: + * - Bit 0 - 15: Event Id. + * - Bit 16 - 23: Group + * - Bit 24 - 31: Phase + * - Pattern: 0xPPGGEEEE + */ + typedef std::multimap EventStore; + + public: + EventMap() : _time(0), _phase(0), _lastEvent(0) { } + + /** + * @name Reset + * @brief Removes all scheduled events and resets time and phase. + */ + void Reset() + { + _eventMap.clear(); + _time = 0; + _phase = 0; + } + + /** + * @name Update + * @brief Updates the timer of the event map. + * @param time Value to be added to time. + */ + void Update(uint32 time) + { + _time += time; + } + + /** + * @name GetTimer + * @return Current timer value. + */ + uint32 GetTimer() const + { + return _time; + } + + /** + * @name GetPhaseMask + * @return Active phases as mask. + */ + uint8 GetPhaseMask() const + { + return _phase; + } + + /** + * @name Empty + * @return True, if there are no events scheduled. + */ + bool Empty() const + { + return _eventMap.empty(); + } + + /** + * @name SetPhase + * @brief Sets the phase of the map (absolute). + * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase. + */ + void SetPhase(uint8 phase) + { + if (!phase) + _phase = 0; + else if (phase <= 8) + _phase = (1 << (phase - 1)); + } + + /** + * @name AddPhase + * @brief Activates the given phase (bitwise). + * @param phase Phase which should be activated. Values: 1 - 8 + */ + void AddPhase(uint8 phase) + { + if (phase && phase <= 8) + _phase |= (1 << (phase - 1)); + } + + /** + * @name RemovePhase + * @brief Deactivates the given phase (bitwise). + * @param phase Phase which should be deactivated. Values: 1 - 8. + */ + void RemovePhase(uint8 phase) + { + if (phase && phase <= 8) + _phase &= ~(1 << (phase - 1)); + } + + /** + * @name ScheduleEvent + * @brief Creates new event entry in map. + * @param eventId The id of the new event. + * @param time The time in milliseconds until the event occurs. + * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. + * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. + */ + void ScheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0) + { + if (group && group <= 8) + eventId |= (1 << (group + 15)); + + if (phase && phase <= 8) + eventId |= (1 << (phase + 23)); + + _eventMap.insert(EventStore::value_type(_time + time, eventId)); + } + + /** + * @name RescheduleEvent + * @brief Cancels the given event and reschedules it. + * @param eventId The id of the event. + * @param time The time in milliseconds until the event occurs. + * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. + * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. + */ + void RescheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0) + { + CancelEvent(eventId); + ScheduleEvent(eventId, time, group, phase); + } + + /** + * @name RepeatEvent + * @brief Repeats the mostly recently executed event. + * @param time Time until the event occurs. + */ + void Repeat(uint32 time) + { + _eventMap.insert(EventStore::value_type(_time + time, _lastEvent)); + } + + /** + * @name RepeatEvent + * @brief Repeats the mostly recently executed event. + * @param time Time until the event occurs. Equivalent to Repeat(urand(minTime, maxTime). + */ + void Repeat(uint32 minTime, uint32 maxTime) + { + Repeat(urand(minTime, maxTime)); + } + + /** + * @name ExecuteEvent + * @brief Returns the next event to execute and removes it from map. + * @return Id of the event to execute. + */ + uint32 ExecuteEvent() + { + while (!Empty()) + { + EventStore::iterator itr = _eventMap.begin(); + + if (itr->first > _time) + return 0; + else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase)) + _eventMap.erase(itr); + else + { + uint32 eventId = (itr->second & 0x0000FFFF); + _lastEvent = itr->second; // include phase/group + _eventMap.erase(itr); + return eventId; + } + } + + return 0; + } + + /** + * @name DelayEvents + * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0. + * @param delay Amount of delay. + */ + void DelayEvents(uint32 delay) + { + _time = delay < _time ? _time - delay : 0; + } + + /** + * @name DelayEvents + * @brief Delay all events of the same group. + * @param delay Amount of delay. + * @param group Group of the events. + */ + void DelayEvents(uint32 delay, uint32 group) + { + if (!group || group > 8 || Empty()) + return; + + EventStore delayed; + + for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) + { + if (itr->second & (1 << (group + 15))) + { + delayed.insert(EventStore::value_type(itr->first + delay, itr->second)); + _eventMap.erase(itr++); + } + else + ++itr; + } + + _eventMap.insert(delayed.begin(), delayed.end()); + } + + /** + * @name CancelEvent + * @brief Cancels all events of the specified id. + * @param eventId Event id to cancel. + */ + void CancelEvent(uint32 eventId) + { + if (Empty()) + return; + + for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) + { + if (eventId == (itr->second & 0x0000FFFF)) + _eventMap.erase(itr++); + else + ++itr; + } + } + + /** + * @name CancelEventGroup + * @brief Cancel events belonging to specified group. + * @param group Group to cancel. + */ + void CancelEventGroup(uint32 group) + { + if (!group || group > 8 || Empty()) + return; + + for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) + { + if (itr->second & (1 << (group + 15))) + _eventMap.erase(itr++); + else + ++itr; + } + } + + /** + * @name GetNextEventTime + * @brief Returns closest occurence of specified event. + * @param eventId Wanted event id. + * @return Time of found event. + */ + uint32 GetNextEventTime(uint32 eventId) const + { + if (Empty()) + return 0; + + for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) + if (eventId == (itr->second & 0x0000FFFF)) + return itr->first; + + return 0; + } + + /** + * @name GetNextEventTime + * @return Time of next event. + */ + uint32 GetNextEventTime() const + { + return Empty() ? 0 : _eventMap.begin()->first; + } + + /** + * @name IsInPhase + * @brief Returns wether event map is in specified phase or not. + * @param phase Wanted phase. + * @return True, if phase of event map contains specified phase. + */ + bool IsInPhase(uint8 phase) + { + return phase <= 8 && (!phase || _phase & (1 << (phase - 1))); + } + + /** + * @name GetTimeUntilEvent + * @brief Returns time in milliseconds until next event. + * @param Id of the event. + * @return Time of next event. + */ + uint32 GetTimeUntilEvent(uint32 eventId) const + { + for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) + if (eventId == (itr->second & 0x0000FFFF)) + return itr->first - _time; + + return std::numeric_limits::max(); + } + + private: + /** + * @name _time + * @brief Internal timer. + * + * This does not represent the real date/time value. + * It's more like a stopwatch: It can run, it can be stopped, + * it can be resetted and so on. Events occur when this timer + * has reached their time value. Its value is changed in the + * Update method. + */ + uint32 _time; + + /** + * @name _phase + * @brief Phase mask of the event map. + * + * Contains the phases the event map is in. Multiple + * phases from 1 to 8 can be set with SetPhase or + * AddPhase. RemovePhase deactives a phase. + */ + uint8 _phase; + + /** + * @name _eventMap + * @brief Internal event storage map. Contains the scheduled events. + * + * See typedef at the beginning of the class for more + * details. + */ + EventStore _eventMap; + + + /** + * @name _lastEvent + * @brief Stores information on the most recently executed event + */ + uint32 _lastEvent; +}; + #endif -- cgit v1.2.3 From eac01c3f2ae27047997576d647bbaf1accd49353 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 6 Jun 2014 19:41:57 +0200 Subject: Core/NetworkIO: Added latency info for opcodes overflow log --- src/server/game/Handlers/CharacterHandler.cpp | 2 +- src/server/game/Handlers/PetHandler.cpp | 2 +- src/server/game/Handlers/SkillHandler.cpp | 2 +- src/server/game/Server/WorldSession.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 7d9d83abfde..d4af17ca78b 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -761,7 +761,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) { if (PlayerLoading() || GetPlayer() != NULL) { - TC_LOG_ERROR("network", "Player tryes to login again, AccountId = %d", GetAccountId()); + TC_LOG_ERROR("network", "Player tries to login again, AccountId = %d", GetAccountId()); KickPlayer(); return; } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 98dfe1af22c..d64f21f2028 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -869,7 +869,7 @@ void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData) uint32 talentId, talentRank; // Client has max 24 talents, rounded up : 30 - const int MaxTalentsCount = 30; + uint32 const MaxTalentsCount = 30; for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i) { diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index b7e918ee05b..f90dfef2684 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -46,7 +46,7 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) uint32 talentId, talentRank; // Client has max 44 talents for tree for 3 trees, rounded up : 150 - const int MaxTalentsCount = 150; + uint32 const MaxTalentsCount = 150; for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i) { diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 61a2e05d9be..eda7b8917a7 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1259,8 +1259,8 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co if (++packetCounter.amountCounter > maxPacketCounterAllowed) { dosTriggered = true; - TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Character: %s, flooding packet (opc: %s (0x%X), count: %u)", - Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetPlayerName().c_str(), + TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)", + Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(), opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter); } -- cgit v1.2.3 From 28974765176d88f6a96e9e76f62d68cd03c8b558 Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 7 Jun 2014 00:30:08 +0200 Subject: Core: Fix non pch build --- src/server/shared/Utilities/Util.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index 96d5a2abfea..d6ead607c55 100644 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -26,6 +26,7 @@ #include #include #include +#include #include // Searcher for map of structs -- cgit v1.2.3 From be518159bf58e98047f1ac74a70736f7961aa3ca Mon Sep 17 00:00:00 2001 From: joschiwald Date: Sat, 7 Jun 2014 17:04:20 +0200 Subject: Core/Spells: add missing spellradius to spell "Achievement Check" (fixes hor achievments) --- src/server/game/Spells/SpellMgr.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 4aced0c92dd..9eadd178eb3 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3385,6 +3385,9 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd break; + case 72830: // Achievement Check + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + break; case 72900: // Start Halls of Reflection Quest AE spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; -- cgit v1.2.3 From 3aa5b01d4d374b19e90da22dcb1996944ce514bd Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Sat, 7 Jun 2014 17:58:45 +0100 Subject: Core/GOs: When unlinking Fishing Bobber from player to prevent despawning, unlink from spell as well to prevent removing unwanted auras --- src/server/game/Entities/GameObject/GameObject.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 4cf7d34cc11..370696474ae 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1404,6 +1404,7 @@ void GameObject::Use(Unit* user) // prevent removing GO at spell cancel RemoveFromOwner(); SetOwnerGUID(player->GetGUID()); + SetSpellId(0); // prevent removing unintended auras at Unit::RemoveGameObject /// @todo find reasonable value for fishing hole search GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE); -- cgit v1.2.3 From 77c29e8feb5a69a8b435269659b320cf906d9ce1 Mon Sep 17 00:00:00 2001 From: aletuna Date: Sat, 7 Jun 2014 19:02:39 +0200 Subject: Scripts/Blackrock Depths: Converted to eventmap+minor coding style changes Closes #11730 --- .../BlackrockDepths/boss_ambassador_flamelash.cpp | 101 +++++---- .../BlackrockDepths/boss_anubshiah.cpp | 149 ++++++------- .../boss_emperor_dagran_thaurissan.cpp | 139 ++++++------ .../BlackrockDepths/boss_general_angerforge.cpp | 163 +++++++------- .../BlackrockDepths/boss_gorosh_the_dervish.cpp | 88 ++++---- .../BlackrockDepths/boss_grizzle.cpp | 99 +++++---- .../boss_high_interrogator_gerstahn.cpp | 118 +++++----- .../BlackrockDepths/boss_magmus.cpp | 114 ++++++---- .../BlackrockDepths/boss_moira_bronzebeard.cpp | 103 +++++---- .../BlackrockDepths/boss_tomb_of_seven.cpp | 240 +++++++++++---------- 10 files changed, 706 insertions(+), 608 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp index 4ac039e9138..3e4097daf20 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -24,64 +23,74 @@ enum Spells SPELL_FIREBLAST = 15573 }; -class boss_ambassador_flamelash : public CreatureScript +enum Events { -public: - boss_ambassador_flamelash() : CreatureScript("boss_ambassador_flamelash") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_ambassador_flamelashAI(creature); - } - - struct boss_ambassador_flamelashAI : public ScriptedAI - { - boss_ambassador_flamelashAI(Creature* creature) : ScriptedAI(creature) { } + EVENT_FIREBLAST = 1, + EVENT_SUMMON_SPIRITS = 2 +}; - uint32 FireBlast_Timer; - uint32 Spirit_Timer; +class boss_ambassador_flamelash : public CreatureScript +{ + public: + boss_ambassador_flamelash() : CreatureScript("boss_ambassador_flamelash") { } - void Reset() override + struct boss_ambassador_flamelashAI : public ScriptedAI { - FireBlast_Timer = 2000; - Spirit_Timer = 24000; - } + boss_ambassador_flamelashAI(Creature* creature) : ScriptedAI(creature) { } - void EnterCombat(Unit* /*who*/) override { } - - void SummonSpirits(Unit* victim) - { - if (Creature* Spirit = DoSpawnCreature(9178, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) - Spirit->AI()->AttackStart(victim); - } + void Reset() override + { + _events.Reset(); + } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; + void EnterCombat(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_FIREBLAST, 2000); + _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 24000); + } - //FireBlast_Timer - if (FireBlast_Timer <= diff) + void SummonSpirit(Unit* victim) { - DoCastVictim(SPELL_FIREBLAST); - FireBlast_Timer = 7000; - } else FireBlast_Timer -= diff; + if (Creature* spirit = DoSpawnCreature(9178, frand(-9, 9), frand(-9, 9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000)) + spirit->AI()->AttackStart(victim); + } - //Spirit_Timer - if (Spirit_Timer <= diff) + void UpdateAI(uint32 diff) override { - SummonSpirits(me->GetVictim()); - SummonSpirits(me->GetVictim()); - SummonSpirits(me->GetVictim()); - SummonSpirits(me->GetVictim()); + if (!UpdateVictim()) + return; - Spirit_Timer = 30000; - } else Spirit_Timer -= diff; + _events.Update(diff); - DoMeleeAttackIfReady(); + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FIREBLAST: + DoCastVictim(SPELL_FIREBLAST); + _events.ScheduleEvent(EVENT_FIREBLAST, 7000); + break; + case EVENT_SUMMON_SPIRITS: + for (uint32 i = 0; i < 4; ++i) + SummonSpirit(me->GetVictim()); + _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 30000); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_ambassador_flamelashAI(creature); } - }; }; void AddSC_boss_ambassador_flamelash() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp index fd8b77ea8d4..1a2e8bba805 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -21,90 +20,94 @@ enum Spells { - SPELL_SHADOWBOLT = 17228, - SPELL_CURSEOFTONGUES = 15470, - SPELL_CURSEOFWEAKNESS = 17227, - SPELL_DEMONARMOR = 11735, - SPELL_ENVELOPINGWEB = 15471 + SPELL_SHADOWBOLT = 17228, + SPELL_CURSEOFTONGUES = 15470, + SPELL_CURSEOFWEAKNESS = 17227, + SPELL_DEMONARMOR = 11735, + SPELL_ENVELOPINGWEB = 15471 }; -class boss_anubshiah : public CreatureScript +enum Events { -public: - boss_anubshiah() : CreatureScript("boss_anubshiah") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_anubshiahAI(creature); - } - - struct boss_anubshiahAI : public ScriptedAI - { - boss_anubshiahAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 ShadowBolt_Timer; - uint32 CurseOfTongues_Timer; - uint32 CurseOfWeakness_Timer; - uint32 DemonArmor_Timer; - uint32 EnvelopingWeb_Timer; - - void Reset() override - { - ShadowBolt_Timer = 7000; - CurseOfTongues_Timer = 24000; - CurseOfWeakness_Timer = 12000; - DemonArmor_Timer = 3000; - EnvelopingWeb_Timer = 16000; - } + EVENT_SHADOWBOLT = 1, + EVENT_CURSE_OF_TONGUES = 2, + EVENT_CURSE_OF_WEAKNESS = 3, + EVENT_DEMON_ARMOR = 4, + EVENT_ENVELOPING_WEB = 5 +}; - void EnterCombat(Unit* /*who*/) override { } +class boss_anubshiah : public CreatureScript +{ + public: + boss_anubshiah() : CreatureScript("boss_anubshiah") { } - void UpdateAI(uint32 diff) override + struct boss_anubshiahAI : public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; - - //ShadowBolt_Timer - if (ShadowBolt_Timer <= diff) - { - DoCastVictim(SPELL_SHADOWBOLT); - ShadowBolt_Timer = 7000; - } else ShadowBolt_Timer -= diff; - - //CurseOfTongues_Timer - if (CurseOfTongues_Timer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CURSEOFTONGUES); - CurseOfTongues_Timer = 18000; - } else CurseOfTongues_Timer -= diff; + boss_anubshiahAI(Creature* creature) : ScriptedAI(creature) { } - //CurseOfWeakness_Timer - if (CurseOfWeakness_Timer <= diff) + void Reset() override { - DoCastVictim(SPELL_CURSEOFWEAKNESS); - CurseOfWeakness_Timer = 45000; - } else CurseOfWeakness_Timer -= diff; + _events.Reset(); + } - //DemonArmor_Timer - if (DemonArmor_Timer <= diff) + void EnterCombat(Unit* /*who*/) override { - DoCast(me, SPELL_DEMONARMOR); - DemonArmor_Timer = 300000; - } else DemonArmor_Timer -= diff; - - //EnvelopingWeb_Timer - if (EnvelopingWeb_Timer <= diff) + _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000); + _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 24000); + _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 12000); + _events.ScheduleEvent(EVENT_DEMON_ARMOR, 3000); + _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 16000); + } + + void UpdateAI(uint32 diff) override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_ENVELOPINGWEB); - EnvelopingWeb_Timer = 12000; - } else EnvelopingWeb_Timer -= diff; - - DoMeleeAttackIfReady(); + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHADOWBOLT: + DoCast(me, SPELL_SHADOWBOLT); + _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000); + break; + case EVENT_CURSE_OF_TONGUES: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_CURSEOFTONGUES); + _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 18000); + break; + case EVENT_CURSE_OF_WEAKNESS: + DoCastVictim(SPELL_CURSEOFWEAKNESS); + _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 45000); + break; + case EVENT_DEMON_ARMOR: + DoCast(me, SPELL_DEMONARMOR); + _events.ScheduleEvent(EVENT_DEMON_ARMOR, 300000); + break; + case EVENT_ENVELOPING_WEB: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_ENVELOPINGWEB); + _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 12000); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_anubshiahAI(creature); } - }; }; void AddSC_boss_anubshiah() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp index fffdf9c7514..cec29bcd4d1 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -32,89 +31,89 @@ enum Spells SPELL_AVATAROFFLAME = 15636 }; -class boss_emperor_dagran_thaurissan : public CreatureScript +enum Events { -public: - boss_emperor_dagran_thaurissan() : CreatureScript("boss_emperor_dagran_thaurissan") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } - - struct boss_draganthaurissanAI : public ScriptedAI - { - boss_draganthaurissanAI(Creature* creature) : ScriptedAI(creature) - { - instance = me->GetInstanceScript(); - } - - InstanceScript* instance; - uint32 HandOfThaurissan_Timer; - uint32 AvatarOfFlame_Timer; - //uint32 Counter; + EVENT_HANDOFTHAURISSAN = 1, + EVENT_AVATAROFFLAME = 2 +}; - void Reset() override - { - HandOfThaurissan_Timer = 4000; - AvatarOfFlame_Timer = 25000; - //Counter= 0; - } +class boss_emperor_dagran_thaurissan : public CreatureScript +{ + public: + boss_emperor_dagran_thaurissan() : CreatureScript("boss_emperor_dagran_thaurissan") { } - void EnterCombat(Unit* /*who*/) override + struct boss_draganthaurissanAI : public ScriptedAI { - Talk(SAY_AGGRO); - me->CallForHelp(VISIBLE_RANGE); - } + boss_draganthaurissanAI(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + } - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_SLAY); - } + void Reset() override + { + _events.Reset(); + } - void JustDied(Unit* /*killer*/) override - { - if (Creature* Moira = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MOIRA))) + void EnterCombat(Unit* /*who*/) override { - Moira->AI()->EnterEvadeMode(); - Moira->setFaction(35); + Talk(SAY_AGGRO); + me->CallForHelp(VISIBLE_RANGE); + _events.ScheduleEvent(EVENT_HANDOFTHAURISSAN, 4000); + _events.ScheduleEvent(EVENT_AVATAROFFLAME, 25000); } - } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; + void KilledUnit(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (HandOfThaurissan_Timer <= diff) + void JustDied(Unit* /*killer*/) override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_HANDOFTHAURISSAN); - - //3 Hands of Thaurissan will be cast - //if (Counter < 3) - //{ - // HandOfThaurissan_Timer = 1000; - // ++Counter; - //} - //else - //{ - HandOfThaurissan_Timer = 5000; - //Counter = 0; - //} - } else HandOfThaurissan_Timer -= diff; - - //AvatarOfFlame_Timer - if (AvatarOfFlame_Timer <= diff) + if (Creature* moira = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MOIRA))) + { + moira->AI()->EnterEvadeMode(); + moira->setFaction(35); + } + } + + void UpdateAI(uint32 diff) override { - DoCastVictim(SPELL_AVATAROFFLAME); - AvatarOfFlame_Timer = 18000; - } else AvatarOfFlame_Timer -= diff; + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_HANDOFTHAURISSAN: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_HANDOFTHAURISSAN); + _events.ScheduleEvent(EVENT_HANDOFTHAURISSAN, 5000); + break; + case EVENT_AVATAROFFLAME: + DoCastVictim(SPELL_AVATAROFFLAME); + _events.ScheduleEvent(EVENT_AVATAROFFLAME, 18000); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + InstanceScript* _instance; + EventMap _events; + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); } - }; }; void AddSC_boss_draganthaurissan() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp index 34ce2276a54..79ffedc8c17 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -26,101 +25,113 @@ enum Spells SPELL_CLEAVE = 20691 }; -class boss_general_angerforge : public CreatureScript +enum Events { -public: - boss_general_angerforge() : CreatureScript("boss_general_angerforge") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_general_angerforgeAI(creature); - } - - struct boss_general_angerforgeAI : public ScriptedAI - { - boss_general_angerforgeAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 MightyBlow_Timer; - uint32 HamString_Timer; - uint32 Cleave_Timer; - uint32 Adds_Timer; - bool Medics; - - void Reset() override - { - MightyBlow_Timer = 8000; - HamString_Timer = 12000; - Cleave_Timer = 16000; - Adds_Timer = 0; - Medics = false; - } - - void EnterCombat(Unit* /*who*/) override { } + EVENT_MIGHTYBLOW = 1, + EVENT_HAMSTRING = 2, + EVENT_CLEAVE = 3, + EVENT_MEDIC = 4, + EVENT_ADDS = 5 +}; - void SummonAdds(Unit* victim) - { - if (Creature* SummonedAdd = DoSpawnCreature(8901, float(irand(-14, 14)), float(irand(-14, 14)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedAdd->AI()->AttackStart(victim); - } +enum Phases +{ + PHASE_ONE = 1, + PHASE_TWO = 2 +}; - void SummonMedics(Unit* victim) - { - if (Creature* SummonedMedic = DoSpawnCreature(8894, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) - SummonedMedic->AI()->AttackStart(victim); - } +class boss_general_angerforge : public CreatureScript +{ + public: + boss_general_angerforge() : CreatureScript("boss_general_angerforge") { } - void UpdateAI(uint32 diff) override + struct boss_general_angerforgeAI : public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; + boss_general_angerforgeAI(Creature* creature) : ScriptedAI(creature) { } - //MightyBlow_Timer - if (MightyBlow_Timer <= diff) + void Reset() override { - DoCastVictim(SPELL_MIGHTYBLOW); - MightyBlow_Timer = 18000; - } else MightyBlow_Timer -= diff; + _events.Reset(); + } - //HamString_Timer - if (HamString_Timer <= diff) + void EnterCombat(Unit* /*who*/) override { - DoCastVictim(SPELL_HAMSTRING); - HamString_Timer = 15000; - } else HamString_Timer -= diff; + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_MIGHTYBLOW, 8000); + _events.ScheduleEvent(EVENT_HAMSTRING, 12000); + _events.ScheduleEvent(EVENT_CLEAVE, 16000); + } - //Cleave_Timer - if (Cleave_Timer <= diff) + void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - DoCastVictim(SPELL_CLEAVE); - Cleave_Timer = 9000; - } else Cleave_Timer -= diff; + if (me->HealthBelowPctDamaged(20, damage) && _events.IsInPhase(PHASE_ONE)) + { + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_MEDIC, 0, 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_ADDS, 0, 0, PHASE_TWO); + } + } - //Adds_Timer - if (HealthBelowPct(21)) + void SummonAdd(Unit* victim) { - if (Adds_Timer <= diff) - { - // summon 3 Adds every 25s - SummonAdds(me->GetVictim()); - SummonAdds(me->GetVictim()); - SummonAdds(me->GetVictim()); + if (Creature* SummonedAdd = DoSpawnCreature(8901, float(irand(-14, 14)), float(irand(-14, 14)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedAdd->AI()->AttackStart(victim); + } - Adds_Timer = 25000; - } else Adds_Timer -= diff; + void SummonMedic(Unit* victim) + { + if (Creature* SummonedMedic = DoSpawnCreature(8894, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000)) + SummonedMedic->AI()->AttackStart(victim); } - //Summon Medics - if (!Medics && HealthBelowPct(21)) + void UpdateAI(uint32 diff) override { - SummonMedics(me->GetVictim()); - SummonMedics(me->GetVictim()); - Medics = true; + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MIGHTYBLOW: + DoCastVictim(SPELL_MIGHTYBLOW); + _events.ScheduleEvent(EVENT_MIGHTYBLOW, 18000); + break; + case EVENT_HAMSTRING: + DoCastVictim(SPELL_HAMSTRING); + _events.ScheduleEvent(EVENT_HAMSTRING, 15000); + break; + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + _events.ScheduleEvent(EVENT_CLEAVE, 9000); + break; + case EVENT_MEDIC: + for (uint8 i = 0; i < 2; ++i) + SummonMedic(me->GetVictim()); + break; + case EVENT_ADDS: + for (uint8 i = 0; i < 3; ++i) + SummonAdd(me->GetVictim()); + _events.ScheduleEvent(EVENT_ADDS, 25000, 0, PHASE_TWO); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_general_angerforgeAI(creature); } - }; }; void AddSC_boss_general_angerforge() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp index b5998576f24..e9034e17d83 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -25,56 +24,67 @@ enum Spells SPELL_MORTALSTRIKE = 24573 }; +enum Events +{ + EVENT_WHIRLWIND = 1, + EVENT_MORTALSTRIKE = 2 +}; + class boss_gorosh_the_dervish : public CreatureScript { -public: - boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { } + public: + boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_gorosh_the_dervishAI(creature); - } + struct boss_gorosh_the_dervishAI : public ScriptedAI + { + boss_gorosh_the_dervishAI(Creature* creature) : ScriptedAI(creature) { } - struct boss_gorosh_the_dervishAI : public ScriptedAI - { - boss_gorosh_the_dervishAI(Creature* creature) : ScriptedAI(creature) { } + void Reset() override + { + _events.Reset(); + } - uint32 WhirlWind_Timer; - uint32 MortalStrike_Timer; + void EnterCombat(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_WHIRLWIND, 12000); + _events.ScheduleEvent(EVENT_MORTALSTRIKE, 22000); + } - void Reset() override - { - WhirlWind_Timer = 12000; - MortalStrike_Timer = 22000; - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - void EnterCombat(Unit* /*who*/) override - { - } + _events.Update(diff); - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_WHIRLWIND: + DoCast(me, SPELL_WHIRLWIND); + _events.ScheduleEvent(EVENT_WHIRLWIND, 15000); + break; + case EVENT_MORTALSTRIKE: + DoCastVictim(SPELL_MORTALSTRIKE); + _events.ScheduleEvent(EVENT_MORTALSTRIKE, 15000); + break; + default: + break; + } + } - //WhirlWind_Timer - if (WhirlWind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - WhirlWind_Timer = 15000; - } else WhirlWind_Timer -= diff; + DoMeleeAttackIfReady(); + } - //MortalStrike_Timer - if (MortalStrike_Timer <= diff) - { - DoCastVictim(SPELL_MORTALSTRIKE); - MortalStrike_Timer = 15000; - } else MortalStrike_Timer -= diff; + private: + EventMap _events; + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_gorosh_the_dervishAI(creature); } - }; }; void AddSC_boss_gorosh_the_dervish() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp index c4277c2447e..f46c0c118b1 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -26,59 +25,83 @@ enum Grizzle EMOTE_FRENZY_KILL = 0 }; -class boss_grizzle : public CreatureScript +enum Events { -public: - boss_grizzle() : CreatureScript("boss_grizzle") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_grizzleAI(creature); - } + EVENT_GROUNDTREMOR = 1, + EVENT_FRENZY = 2 +}; - struct boss_grizzleAI : public ScriptedAI - { - boss_grizzleAI(Creature* creature) : ScriptedAI(creature) { } +enum Phases +{ + PHASE_ONE = 1, + PHASE_TWO = 2 +}; - uint32 GroundTremor_Timer; - uint32 Frenzy_Timer; +class boss_grizzle : public CreatureScript +{ + public: + boss_grizzle() : CreatureScript("boss_grizzle") { } - void Reset() override + struct boss_grizzleAI : public ScriptedAI { - GroundTremor_Timer = 12000; - Frenzy_Timer =0; - } + boss_grizzleAI(Creature* creature) : ScriptedAI(creature) { } - void EnterCombat(Unit* /*who*/) override { } + void Reset() override + { + _events.Reset(); + } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; + void EnterCombat(Unit* /*who*/) override + { + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_GROUNDTREMOR, 12000); + } - //GroundTremor_Timer - if (GroundTremor_Timer <= diff) + void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - DoCastVictim(SPELL_GROUNDTREMOR); - GroundTremor_Timer = 8000; - } else GroundTremor_Timer -= diff; + if (me->HealthBelowPctDamaged(50, damage) && _events.IsInPhase(PHASE_ONE)) + { + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_FRENZY, 0, 0, PHASE_TWO); + } + } - //Frenzy_Timer - if (HealthBelowPct(51)) + void UpdateAI(uint32 diff) override { - if (Frenzy_Timer <= diff) + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) { - DoCast(me, SPELL_FRENZY); - Talk(EMOTE_FRENZY_KILL); + switch (eventId) + { + case EVENT_GROUNDTREMOR: + DoCastVictim(SPELL_GROUNDTREMOR); + _events.ScheduleEvent(EVENT_GROUNDTREMOR, 8000); + break; + case EVENT_FRENZY: + DoCast(me, SPELL_FRENZY); + Talk(EMOTE_FRENZY_KILL); + _events.ScheduleEvent(EVENT_FRENZY, 15000, 0, PHASE_TWO); + break; + default: + break; + } + } - Frenzy_Timer = 15000; - } else Frenzy_Timer -= diff; + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_grizzleAI(creature); } - }; }; void AddSC_boss_grizzle() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp index 6aa89aa491d..7105d78f2ee 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -27,74 +26,81 @@ enum Spells SPELL_SHADOWSHIELD = 22417 }; -class boss_high_interrogator_gerstahn : public CreatureScript +enum Events { -public: - boss_high_interrogator_gerstahn() : CreatureScript("boss_high_interrogator_gerstahn") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_high_interrogator_gerstahnAI(creature); - } - - struct boss_high_interrogator_gerstahnAI : public ScriptedAI - { - boss_high_interrogator_gerstahnAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 ShadowWordPain_Timer; - uint32 ManaBurn_Timer; - uint32 PsychicScream_Timer; - uint32 ShadowShield_Timer; - - void Reset() override - { - ShadowWordPain_Timer = 4000; - ManaBurn_Timer = 14000; - PsychicScream_Timer = 32000; - ShadowShield_Timer = 8000; - } + EVENT_SHADOW_WORD_PAIN = 1, + EVENT_MANABURN = 2, + EVENT_PSYCHIC_SCREAM = 3, + EVENT_SHADOWSHIELD = 4 +}; - void EnterCombat(Unit* /*who*/) override { } +class boss_high_interrogator_gerstahn : public CreatureScript +{ + public: + boss_high_interrogator_gerstahn() : CreatureScript("boss_high_interrogator_gerstahn") { } - void UpdateAI(uint32 diff) override + struct boss_high_interrogator_gerstahnAI : public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; + boss_high_interrogator_gerstahnAI(Creature* creature) : ScriptedAI(creature) { } - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) + void Reset() override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 7000; - } else ShadowWordPain_Timer -= diff; + _events.Reset(); + } - //ManaBurn_Timer - if (ManaBurn_Timer <= diff) + void EnterCombat(Unit* /*who*/) override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_MANABURN); - ManaBurn_Timer = 10000; - } else ManaBurn_Timer -= diff; + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 4000); + _events.ScheduleEvent(EVENT_MANABURN, 14000); + _events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, 32000); + _events.ScheduleEvent(EVENT_SHADOWSHIELD, 8000); + } - //PsychicScream_Timer - if (PsychicScream_Timer <= diff) + void UpdateAI(uint32 diff) override { - DoCastVictim(SPELL_PSYCHICSCREAM); - PsychicScream_Timer = 30000; - } else PsychicScream_Timer -= diff; + if (!UpdateVictim()) + return; - //ShadowShield_Timer - if (ShadowShield_Timer <= diff) - { - DoCast(me, SPELL_SHADOWSHIELD); - ShadowShield_Timer = 25000; - } else ShadowShield_Timer -= diff; + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHADOW_WORD_PAIN: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_SHADOWWORDPAIN); + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 7000); + break; + case EVENT_PSYCHIC_SCREAM: + DoCastVictim(SPELL_PSYCHICSCREAM); + _events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, 30000); + break; + case EVENT_MANABURN: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_MANABURN); + _events.ScheduleEvent(EVENT_MANABURN, 10000); + break; + case EVENT_SHADOWSHIELD: + DoCast(me, SPELL_SHADOWSHIELD); + _events.ScheduleEvent(EVENT_SHADOWSHIELD, 25000); + break; + default: + break; + } + } - DoMeleeAttackIfReady(); + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_high_interrogator_gerstahnAI(creature); } - }; }; void AddSC_boss_high_interrogator_gerstahn() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp index 4cf968ad3b7..efc9a6e793b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -18,75 +17,96 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "blackrock_depths.h" enum Spells { - SPELL_FIERYBURST = 13900, - SPELL_WARSTOMP = 24375 + SPELL_FIERYBURST = 13900, + SPELL_WARSTOMP = 24375 }; -enum Misc +enum Events { - DATA_THRONE_DOOR = 24 // not id or guid of doors but number of enum in blackrock_depths.h + EVENT_FIERY_BURST = 1, + EVENT_WARSTOMP = 2 }; -class boss_magmus : public CreatureScript +enum Phases { -public: - boss_magmus() : CreatureScript("boss_magmus") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_magmusAI(creature); - } - - struct boss_magmusAI : public ScriptedAI - { - boss_magmusAI(Creature* creature) : ScriptedAI(creature) { } + PHASE_ONE = 1, + PHASE_TWO = 2 +}; - uint32 FieryBurst_Timer; - uint32 WarStomp_Timer; +class boss_magmus : public CreatureScript +{ + public: + boss_magmus() : CreatureScript("boss_magmus") { } - void Reset() override + struct boss_magmusAI : public ScriptedAI { - FieryBurst_Timer = 5000; - WarStomp_Timer =0; - } + boss_magmusAI(Creature* creature) : ScriptedAI(creature) { } - void EnterCombat(Unit* /*who*/) override { } + void Reset() override + { + _events.Reset(); + } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; + void EnterCombat(Unit* /*who*/) override + { + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_FIERY_BURST, 5000); + } - //FieryBurst_Timer - if (FieryBurst_Timer <= diff) + void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - DoCastVictim(SPELL_FIERYBURST); - FieryBurst_Timer = 6000; - } else FieryBurst_Timer -= diff; + if (me->HealthBelowPctDamaged(50, damage) && _events.IsInPhase(PHASE_ONE)) + { + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_WARSTOMP, 0, 0, PHASE_TWO); + } + } - //WarStomp_Timer - if (HealthBelowPct(51)) + void UpdateAI(uint32 diff) override { - if (WarStomp_Timer <= diff) + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) { - DoCastVictim(SPELL_WARSTOMP); - WarStomp_Timer = 8000; - } else WarStomp_Timer -= diff; + switch (eventId) + { + case EVENT_FIERY_BURST: + DoCastVictim(SPELL_FIERYBURST); + _events.ScheduleEvent(EVENT_FIERY_BURST, 6000); + break; + case EVENT_WARSTOMP: + DoCastVictim(SPELL_WARSTOMP); + _events.ScheduleEvent(EVENT_WARSTOMP, 8000, 0, PHASE_TWO); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - // When he die open door to last chamber - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override + { + if (InstanceScript* instance = me->GetInstanceScript()) + instance->HandleGameObject(instance->GetData64(DATA_THRONE_DOOR), true); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override { - if (InstanceScript* instance = killer->GetInstanceScript()) - instance->HandleGameObject(instance->GetData64(DATA_THRONE_DOOR), true); + return new boss_magmusAI(creature); } - }; }; void AddSC_boss_magmus() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp index 98f5f75ae3f..0c36fe9696d 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 * * 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 @@ -29,63 +28,73 @@ enum Spells SPELL_SMITE = 10934 }; -class boss_moira_bronzebeard : public CreatureScript +enum Events { -public: - boss_moira_bronzebeard() : CreatureScript("boss_moira_bronzebeard") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_moira_bronzebeardAI(creature); - } - - struct boss_moira_bronzebeardAI : public ScriptedAI - { - boss_moira_bronzebeardAI(Creature* creature) : ScriptedAI(creature) { } - - uint32 Heal_Timer; - uint32 MindBlast_Timer; - uint32 ShadowWordPain_Timer; - uint32 Smite_Timer; - - void Reset() override - { - Heal_Timer = 12000; //These times are probably wrong - MindBlast_Timer = 16000; - ShadowWordPain_Timer = 2000; - Smite_Timer = 8000; - } + EVENT_MINDBLAST = 1, + EVENT_SHADOW_WORD_PAIN = 2, + EVENT_SMITE = 3, + EVENT_HEAL = 4 // not used atm +}; - void EnterCombat(Unit* /*who*/) override { } +class boss_moira_bronzebeard : public CreatureScript +{ + public: + boss_moira_bronzebeard() : CreatureScript("boss_moira_bronzebeard") { } - void UpdateAI(uint32 diff) override + struct boss_moira_bronzebeardAI : public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; + boss_moira_bronzebeardAI(Creature* creature) : ScriptedAI(creature) { } - //MindBlast_Timer - if (MindBlast_Timer <= diff) + void Reset() override { - DoCastVictim(SPELL_MINDBLAST); - MindBlast_Timer = 14000; - } else MindBlast_Timer -= diff; + _events.Reset(); + } - //ShadowWordPain_Timer - if (ShadowWordPain_Timer <= diff) + void EnterCombat(Unit* /*who*/) override { - DoCastVictim(SPELL_SHADOWWORDPAIN); - ShadowWordPain_Timer = 18000; - } else ShadowWordPain_Timer -= diff; + //_events.ScheduleEvent(EVENT_HEAL, 12000); // not used atm // These times are probably wrong + _events.ScheduleEvent(EVENT_MINDBLAST, 16000); + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 2000); + _events.ScheduleEvent(EVENT_SMITE, 8000); + } - //Smite_Timer - if (Smite_Timer <= diff) + void UpdateAI(uint32 diff) override { - DoCastVictim(SPELL_SMITE); - Smite_Timer = 10000; - } else Smite_Timer -= diff; + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_MINDBLAST: + DoCastVictim(SPELL_MINDBLAST); + _events.ScheduleEvent(EVENT_MINDBLAST, 14000); + break; + case EVENT_SHADOW_WORD_PAIN: + DoCastVictim(SPELL_SHADOWWORDPAIN); + _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 18000); + break; + case EVENT_SMITE: + DoCastVictim(SPELL_SMITE); + _events.ScheduleEvent(EVENT_SMITE, 10000); + break; + default: + break; + } + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_moira_bronzebeardAI(creature); } - }; }; void AddSC_boss_moira_bronzebeard() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp index cbcafa32a89..83464c12230 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp @@ -24,18 +24,24 @@ enum Spells { - SPELL_SMELT_DARK_IRON = 14891, - SPELL_LEARN_SMELT = 14894, + SPELL_SMELT_DARK_IRON = 14891, + SPELL_LEARN_SMELT = 14894, }; enum Quests { - QUEST_SPECTRAL_CHALICE = 4083 + QUEST_SPECTRAL_CHALICE = 4083 }; enum Misc { - DATA_SKILLPOINT_MIN = 230 + DATA_SKILLPOINT_MIN = 230 +}; + +enum Phases +{ + PHASE_ONE = 1, + PHASE_TWO = 2 }; #define GOSSIP_ITEM_TEACH_1 "Teach me the art of smelting dark iron" @@ -99,149 +105,151 @@ enum DoomrelSpells SPELL_SUMMON_VOIDWALKERS = 15092 }; +enum DoomrelEvents +{ + EVENT_SHADOW_BOLT_VOLLEY = 1, + EVENT_IMMOLATE = 2, + EVENT_CURSE_OF_WEAKNESS = 3, + EVENT_DEMONARMOR = 4, + EVENT_SUMMON_VOIDWALKERS = 5 +}; + #define GOSSIP_ITEM_CHALLENGE "Your bondage is at an end, Doom'rel. I challenge you!" #define GOSSIP_SELECT_DOOMREL "[PH] Continue..." class boss_doomrel : public CreatureScript { -public: - boss_doomrel() : CreatureScript("boss_doomrel") { } + public: + boss_doomrel() : CreatureScript("boss_doomrel") { } - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(2605, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->CLOSE_GOSSIP_MENU(); - //start event here - creature->setFaction(FACTION_HOSTILE); - creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - creature->AI()->AttackStart(player); - InstanceScript* instance = creature->GetInstanceScript(); - if (instance) - instance->SetData64(DATA_EVENSTARTER, player->GetGUID()); - break; + player->PlayerTalkClass->ClearMenus(); + switch (action) + { + case GOSSIP_ACTION_INFO_DEF+1: + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->SEND_GOSSIP_MENU(2605, creature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF+2: + player->CLOSE_GOSSIP_MENU(); + //start event here + creature->setFaction(FACTION_HOSTILE); + creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + creature->AI()->AttackStart(player); + InstanceScript* instance = creature->GetInstanceScript(); + if (instance) + instance->SetData64(DATA_EVENSTARTER, player->GetGUID()); + break; + } + return true; } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(2601, creature->GetGUID()); - return true; - } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } - - struct boss_doomrelAI : public ScriptedAI - { - boss_doomrelAI(Creature* creature) : ScriptedAI(creature) + bool OnGossipHello(Player* player, Creature* creature) override { - instance = creature->GetInstanceScript(); - } + player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(2601, creature->GetGUID()); - InstanceScript* instance; - uint32 ShadowVolley_Timer; - uint32 Immolate_Timer; - uint32 CurseOfWeakness_Timer; - uint32 DemonArmor_Timer; - bool Voidwalkers; + return true; + } - void Reset() override + struct boss_doomrelAI : public ScriptedAI { - ShadowVolley_Timer = 10000; - Immolate_Timer = 18000; - CurseOfWeakness_Timer = 5000; - DemonArmor_Timer = 16000; - Voidwalkers = false; + boss_doomrelAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } - me->setFaction(FACTION_FRIEND); + void Reset() override + { + _voidwalkers = false; - // was set before event start, so set again - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + me->setFaction(FACTION_FRIEND); - if (instance->GetData(DATA_GHOSTKILL) >= 7) - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); - else - me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } + // was set before event start, so set again + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - void EnterCombat(Unit* /*who*/) override - { - } - - void EnterEvadeMode() override - { - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->LoadCreaturesAddon(); - if (me->IsAlive()) - me->GetMotionMaster()->MoveTargetedHome(); - me->SetLootRecipient(NULL); - instance->SetData64(DATA_EVENSTARTER, 0); - } - - void JustDied(Unit* /*killer*/) override - { - instance->SetData(DATA_GHOSTKILL, 1); - } + if (_instance->GetData(DATA_GHOSTKILL) >= 7) + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + else + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void EnterCombat(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 10000); + _events.ScheduleEvent(EVENT_IMMOLATE, 18000); + _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 5000); + _events.ScheduleEvent(EVENT_DEMONARMOR, 16000); + } - //ShadowVolley_Timer - if (ShadowVolley_Timer <= diff) + void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override { - DoCastVictim(SPELL_SHADOWBOLTVOLLEY); - ShadowVolley_Timer = 12000; - } else ShadowVolley_Timer -= diff; + if (!_voidwalkers && !HealthAbovePct(50)) + { + DoCastVictim(SPELL_SUMMON_VOIDWALKERS, true); + _voidwalkers = true; + } + } - //Immolate_Timer - if (Immolate_Timer <= diff) + void EnterEvadeMode() override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_IMMOLATE); + ScriptedAI::EnterEvadeMode(); - Immolate_Timer = 25000; - } else Immolate_Timer -= diff; + _instance->SetData64(DATA_EVENSTARTER, 0); + } - //CurseOfWeakness_Timer - if (CurseOfWeakness_Timer <= diff) + void JustDied(Unit* /*killer*/) override { - DoCastVictim(SPELL_CURSEOFWEAKNESS); - CurseOfWeakness_Timer = 45000; - } else CurseOfWeakness_Timer -= diff; + _instance->SetData(DATA_GHOSTKILL, 1); + } - //DemonArmor_Timer - if (DemonArmor_Timer <= diff) + void UpdateAI(uint32 diff) override { - DoCast(me, SPELL_DEMONARMOR); - DemonArmor_Timer = 300000; - } else DemonArmor_Timer -= diff; + if (!UpdateVictim()) + return; - //Summon Voidwalkers - if (!Voidwalkers && HealthBelowPct(51)) - { - DoCastVictim(SPELL_SUMMON_VOIDWALKERS, true); - Voidwalkers = true; + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHADOW_BOLT_VOLLEY: + DoCastVictim(SPELL_SHADOWBOLTVOLLEY); + _events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 12000); + break; + case EVENT_IMMOLATE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_IMMOLATE); + _events.ScheduleEvent(EVENT_IMMOLATE, 25000); + break; + case EVENT_CURSE_OF_WEAKNESS: + DoCastVictim(SPELL_CURSEOFWEAKNESS); + _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 45000); + break; + case EVENT_DEMONARMOR: + DoCast(me, SPELL_DEMONARMOR); + _events.ScheduleEvent(EVENT_DEMONARMOR, 300000); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); + private: + InstanceScript* _instance; + EventMap _events; + bool _voidwalkers; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); } - }; }; void AddSC_boss_tomb_of_seven() -- cgit v1.2.3 From f80384a1f26dde4ee81c7373ee048dea905c78f5 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Sat, 7 Jun 2014 18:06:22 +0100 Subject: Core/Spells: Anti-Magic shell should give immunity to all spells that belong to SPELL_SCHOOL_MASK_MAGIC regardless of dispel type --- src/server/game/Entities/Unit/Unit.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a84cdbef1b3..83ed1fdf7cc 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11112,8 +11112,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons // Check for immune to application of harmful magical effects AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL); for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter) - if (spellInfo->Dispel == DISPEL_MAGIC && // Magic debuff - ((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school + if (((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school !spellInfo->IsPositiveEffect(index)) // Harmful return true; } -- cgit v1.2.3 From b651789cb05c304248f427ded09e0a0e43dad317 Mon Sep 17 00:00:00 2001 From: Unholychick Date: Wed, 4 Jun 2014 15:49:48 +0200 Subject: Core/Spells: Implement Periodic mechanics Change behaviour of single target periodic aura ticks to be more blizzlike Also add some missing handling of SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE Fixes Deep wounds and Chimera Shot Serpent Remove an ancient hack with Drain Soul, spell id 100001 can now be deleted from spell_dbc table Allows Rolling dot mechanics and allows DK's to roll diseases with pestilence, see link for info: http://forums.elitistjerks.com/topic/82503-frost-dps-in-333this-will-be-a-day-long-remembered/page-88 --- src/server/game/Entities/Unit/Unit.cpp | 440 ++++++++++++---------- src/server/game/Entities/Unit/Unit.h | 13 +- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 91 +++-- src/server/game/Spells/Auras/SpellAuraEffects.h | 12 +- src/server/game/Spells/Auras/SpellAuras.cpp | 90 ++++- src/server/game/Spells/Auras/SpellAuras.h | 3 +- src/server/game/Spells/Spell.cpp | 4 +- src/server/game/Spells/SpellEffects.cpp | 31 +- src/server/scripts/Spells/spell_hunter.cpp | 9 +- src/server/scripts/Spells/spell_priest.cpp | 11 +- src/server/scripts/Spells/spell_warlock.cpp | 13 +- src/server/scripts/Spells/spell_warrior.cpp | 15 +- 12 files changed, 457 insertions(+), 275 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 83ed1fdf7cc..63f67571f9f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3385,6 +3385,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask) return; aura->HandleAuraSpecificMods(aurApp, caster, true, false); + aura->HandleAuraSpecificPeriodics(aurApp, caster); // apply effects of the aura for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -8159,23 +8160,14 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg if (GetTypeId() != TYPEID_PLAYER) return false; + float averageDmg = 0; // now compute approximate weapon damage by formula from wowwiki.com - Item* item = NULL; if (procFlags & PROC_FLAG_DONE_OFFHAND_ATTACK) - item = ToPlayer()->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + averageDmg = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE)) / 2; else - item = ToPlayer()->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); - - // dunno if it's really needed but will prevent any possible crashes - if (!item) - return false; + averageDmg = (GetFloatValue(UNIT_FIELD_MINDAMAGE) + GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2; - ItemTemplate const* weapon = item->GetTemplate(); - - float weaponDPS = weapon->getDPS(); - float attackPower = GetTotalAttackPowerValue(BASE_ATTACK) / 14.0f; - float weaponSpeed = float(weapon->Delay) / 1000.0f; - basepoints0 = int32((weaponDPS + attackPower) * weaponSpeed); + basepoints0 = int32(averageDmg); break; } // Persistent Shield (Scarab Brooch trinket) @@ -9853,39 +9845,164 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin if (Unit* owner = GetOwner()) return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype); - // Done total percent damage auras - float DoneTotalMod = 1.0f; float ApCoeffMod = 1.0f; int32 DoneTotal = 0; - // Pet damage? - if (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsPet()) - DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank); + uint32 creatureTypeMask = victim->GetCreatureTypeMask(); - // Some spells don't benefit from pct done mods - if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS)) + // done scripted mod (take it from owner) + Unit const* owner = GetOwner() ? GetOwner() : this; + AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { - AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) + if (!(*i)->IsAffectedOnSpell(spellProto)) + continue; + + switch ((*i)->GetMiscValue()) { - if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization) - continue; + case 4418: // Increased Shock Damage + case 4554: // Increased Lightning Damage + case 4555: // Improved Moonfire + case 5142: // Increased Lightning Damage + case 5147: // Improved Consecration / Libram of Resurgence + case 5148: // Idol of the Shooting Star + case 6008: // Increased Lightning Damage + case 8627: // Totem of Hex + { + DoneTotal += (*i)->GetAmount(); + break; + } + } + } - if ((*i)->GetMiscValue() & spellProto->GetSchoolMask()) + // Custom scripted damage + switch (spellProto->SpellFamilyName) + { + case SPELLFAMILY_DEATHKNIGHT: + // Impurity (dummy effect) + if (GetTypeId() == TYPEID_PLAYER) { - if ((*i)->GetSpellInfo()->EquippedItemClass == -1) - AddPct(DoneTotalMod, (*i)->GetAmount()); - else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0)) - AddPct(DoneTotalMod, (*i)->GetAmount()); - else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo())) - AddPct(DoneTotalMod, (*i)->GetAmount()); + PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr) + { + if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) + continue; + switch (itr->first) + { + case 49220: + case 49633: + case 49635: + case 49636: + case 49638: + if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first)) + AddPct(ApCoeffMod, proto->Effects[0].CalcValue()); + break; + } + } + } + break; + } + + // Done fixed damage bonus auras + int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask()); + // Pets just add their bonus damage to their spell damage + // note that their spell damage is just gain of their own auras + if (HasUnitTypeMask(UNIT_MASK_GUARDIAN)) + DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage(); + + // Check for table values + float coeff = 0; + SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); + if (bonus) + { + if (damagetype == DOT) + { + coeff = bonus->dot_damage; + if (bonus->ap_dot_bonus > 0) + { + WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; + float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); + APbonus += GetTotalAttackPowerValue(attType); + DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus); + } + } + else + { + coeff = bonus->direct_damage; + if (bonus->ap_bonus > 0) + { + WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; + float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); + APbonus += GetTotalAttackPowerValue(attType); + DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus); } } } + // Default calculation + if (DoneAdvertisedBenefit) + { + if (!bonus || coeff < 0) + coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack); + + float factorMod = CalculateLevelPenalty(spellProto) * stack; + + if (Player* modOwner = GetSpellModOwner()) + { + coeff *= 100.0f; + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff); + coeff /= 100.0f; + } + DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); + } + + // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods. + float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype)); + // apply spellmod to Done damage (flat and pct) + if (Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage); + + return uint32(std::max(tmpDamage, 0.0f)); +} + +float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const +{ + if (!spellProto || !victim || damagetype == DIRECT_DAMAGE) + return 1.0f; + + // Some spells don't benefit from pct done mods + if (spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) + return 1.0f; + + // For totems pct done mods are calculated when its calculation is run on the player in SpellDamageBonusDone. + if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem()) + return 1.0f; + + // Done total percent damage auras + float DoneTotalMod = 1.0f; + + // Pet damage? + if (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsPet()) + DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank); + + AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) + { + if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization) + continue; + + if ((*i)->GetMiscValue() & spellProto->GetSchoolMask()) + { + if ((*i)->GetSpellInfo()->EquippedItemClass == -1) + AddPct(DoneTotalMod, (*i)->GetAmount()); + else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0)) + AddPct(DoneTotalMod, (*i)->GetAmount()); + else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo())) + AddPct(DoneTotalMod, (*i)->GetAmount()); + } + } uint32 creatureTypeMask = victim->GetCreatureTypeMask(); - // Add flat bonus from spell damage versus - DoneTotal += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask); + AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i) if (creatureTypeMask & uint32((*i)->GetMiscValue())) @@ -9899,7 +10016,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin // done scripted mod (take it from owner) Unit const* owner = GetOwner() ? GetOwner() : this; - AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { if (!(*i)->IsAffectedOnSpell(spellProto)) @@ -9956,18 +10073,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin AddPct(DoneTotalMod, (*i)->GetAmount()); break; } - case 4418: // Increased Shock Damage - case 4554: // Increased Lightning Damage - case 4555: // Improved Moonfire - case 5142: // Increased Lightning Damage - case 5147: // Improved Consecration / Libram of Resurgence - case 5148: // Idol of the Shooting Star - case 6008: // Increased Lightning Damage - case 8627: // Totem of Hex - { - DoneTotal += (*i)->GetAmount(); - break; - } // Tundra Stalker // Merciless Combat case 7277: @@ -10133,14 +10238,14 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin break; } } - // Drain Soul - increased damage for targets under 25 % HP - if (spellProto->SpellFamilyFlags[0] & 0x00004000) - if (HasAura(100001)) - DoneTotalMod *= 4; // Shadow Bite (15% increase from each dot) if (spellProto->SpellFamilyFlags[1] & 0x00400000 && IsPet()) if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID())) AddPct(DoneTotalMod, 15 * count); + + // Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage + if (spellProto->SpellFamilyFlags[0] & 0x00004000 && !victim->HealthAbovePct(25)) + DoneTotalMod *= 4; break; case SPELLFAMILY_HUNTER: // Steady Shot @@ -10155,101 +10260,15 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2721, 0)) AddPct(DoneTotalMod, aurEff->GetAmount()); - // Sigil of the Vengeful Heart - if (spellProto->SpellFamilyFlags[0] & 0x2000) - if (AuraEffect* aurEff = GetAuraEffect(64962, EFFECT_1)) - AddPct(DoneTotal, aurEff->GetAmount()); - // Glacier Rot if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6) if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0)) if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0) AddPct(DoneTotalMod, aurEff->GetAmount()); - - // Impurity (dummy effect) - if (GetTypeId() == TYPEID_PLAYER) - { - PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr) - { - if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) - continue; - switch (itr->first) - { - case 49220: - case 49633: - case 49635: - case 49636: - case 49638: - { - if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first)) - AddPct(ApCoeffMod, proto->Effects[0].CalcValue()); - } - break; - } - } - } break; } - // Done fixed damage bonus auras - int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask()); - // Pets just add their bonus damage to their spell damage - // note that their spell damage is just gain of their own auras - if (HasUnitTypeMask(UNIT_MASK_GUARDIAN)) - DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage(); - - // Check for table values - float coeff = 0; - SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id); - if (bonus) - { - if (damagetype == DOT) - { - coeff = bonus->dot_damage; - if (bonus->ap_dot_bonus > 0) - { - WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; - float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); - APbonus += GetTotalAttackPowerValue(attType); - DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus); - } - } - else - { - coeff = bonus->direct_damage; - if (bonus->ap_bonus > 0) - { - WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; - float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); - APbonus += GetTotalAttackPowerValue(attType); - DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus); - } - } - } - // Default calculation - if (DoneAdvertisedBenefit) - { - if (!bonus || coeff < 0) - coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack); - - float factorMod = CalculateLevelPenalty(spellProto) * stack; - - if (Player* modOwner = GetSpellModOwner()) - { - coeff *= 100.0f; - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff); - coeff /= 100.0f; - } - DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); - } - - float tmpDamage = (int32(pdamage) + DoneTotal) * DoneTotalMod; - // apply spellmod to Done damage (flat and pct) - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage); - - return uint32(std::max(tmpDamage, 0.0f)); + return DoneTotalMod; } uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) const @@ -10407,16 +10426,21 @@ int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const return TakenAdvertisedBenefit; } -bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) const +bool Unit::IsSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) const +{ + return roll_chance_f(GetUnitSpellCriticalChance(victim, spellProto, schoolMask, attackType)); +} + +float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) const { //! Mobs can't crit with spells. Player Totems can //! Fire Elemental (from totem) can too - but this part is a hack and needs more research - if (IS_CREATURE_GUID(GetGUID()) && !(IsTotem() && IS_PLAYER_GUID(GetOwnerGUID())) && GetEntry() != 15438) - return false; + if (IS_CRE_OR_VEH_GUID(GetGUID()) && !(IsTotem() && IS_PLAYER_GUID(GetOwnerGUID())) && GetEntry() != 15438) + return 0.0f; // not critting spell if ((spellProto->AttributesEx2 & SPELL_ATTR2_CANT_CRIT)) - return false; + return 0.0f; float crit_chance = 0.0f; switch (spellProto->DmgClass) @@ -10432,7 +10456,7 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas case 71646: // Item - Bauble of True Blood 25m break; default: - return false; + return 0.0f; } // Do not add a break here, case fallthrough is intentional! Adding a break will make above spells unable to crit. case SPELL_DAMAGE_CLASS_MAGIC: @@ -10534,7 +10558,7 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas else if (spellProto->GetCategory() == 19) { if (victim->GetCreatureTypeMask() & CREATURE_TYPEMASK_DEMON_OR_UNDEAD) - return true; + return 100.0f; break; } break; @@ -10544,7 +10568,7 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas { if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0, 0, GetGUID())) if (victim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE) > -100) - return true; + return 100.0f; break; } break; @@ -10592,17 +10616,14 @@ bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMas break; } default: - return false; + return 0.0f; } // percent done // only players use intelligence for critical chance computations if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance); - crit_chance = crit_chance > 0.0f ? crit_chance : 0.0f; - if (roll_chance_f(crit_chance)) - return true; - return false; + return crit_chance > 0.0f ? crit_chance : 0.0f; } uint32 Unit::SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim) @@ -10686,14 +10707,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui if (spellProto->SpellFamilyName == SPELLFAMILY_POTION) return healamount; - float DoneTotalMod = 1.0f; int32 DoneTotal = 0; - // Healing done percent - AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); - for (AuraEffectList::const_iterator i = mHealingDonePct.begin(); i != mHealingDonePct.end(); ++i) - AddPct(DoneTotalMod, (*i)->GetAmount()); - // done scripted mod (take it from owner) Unit const* owner = GetOwner() ? GetOwner() : this; AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); @@ -10708,43 +10723,6 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind DoneTotal += (*i)->GetAmount(); break; - case 21: // Test of Faith - case 6935: - case 6918: - if (victim->HealthBelowPct(50)) - AddPct(DoneTotalMod, (*i)->GetAmount()); - break; - case 7798: // Glyph of Regrowth - { - if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0)) - AddPct(DoneTotalMod, (*i)->GetAmount()); - break; - } - case 8477: // Nourish Heal Boost - { - int32 stepPercent = (*i)->GetAmount(); - int32 modPercent = 0; - AuraApplicationMap const& victimAuras = victim->GetAppliedAuras(); - for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) - { - Aura const* aura = itr->second->GetBase(); - if (aura->GetCasterGUID() != GetGUID()) - continue; - SpellInfo const* m_spell = aura->GetSpellInfo(); - if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID || - !(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50)) - continue; - modPercent += stepPercent * aura->GetStackAmount(); - } - AddPct(DoneTotalMod, modPercent); - break; - } - case 7871: // Glyph of Lesser Healing Wave - { - if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID())) - AddPct(DoneTotalMod, (*i)->GetAmount()); - break; - } default: break; } @@ -10817,8 +10795,8 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal = 0; } - // use float as more appropriate for negative values and percent applying - float heal = float(int32(healamount) + DoneTotal) * DoneTotalMod; + // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods. + float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto)); // apply spellmod to Done amount if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal); @@ -10826,6 +10804,78 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui return uint32(std::max(heal, 0.0f)); } +float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const +{ + // For totems pct done mods are calculated when its calculation is run on the player in SpellHealingBonusDone. + if (GetTypeId() == TYPEID_UNIT && IsTotem()) + if (Unit* owner = GetOwner()) + return 1.0f; + + // No bonus healing for potion spells + if (spellProto->SpellFamilyName == SPELLFAMILY_POTION) + return 1.0f; + + float DoneTotalMod = 1.0f; + + // Healing done percent + AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); + for (AuraEffectList::const_iterator i = mHealingDonePct.begin(); i != mHealingDonePct.end(); ++i) + AddPct(DoneTotalMod, (*i)->GetAmount()); + + // done scripted mod (take it from owner) + Unit const* owner = GetOwner() ? GetOwner() : this; + AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) + { + if (!(*i)->IsAffectedOnSpell(spellProto)) + continue; + switch ((*i)->GetMiscValue()) + { + case 21: // Test of Faith + case 6935: + case 6918: + if (victim->HealthBelowPct(50)) + AddPct(DoneTotalMod, (*i)->GetAmount()); + break; + case 7798: // Glyph of Regrowth + { + if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0)) + AddPct(DoneTotalMod, (*i)->GetAmount()); + break; + } + case 8477: // Nourish Heal Boost + { + int32 stepPercent = (*i)->GetAmount(); + int32 modPercent = 0; + AuraApplicationMap const& victimAuras = victim->GetAppliedAuras(); + for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) + { + Aura const* aura = itr->second->GetBase(); + if (aura->GetCasterGUID() != GetGUID()) + continue; + SpellInfo const* m_spell = aura->GetSpellInfo(); + if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID || + !(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50)) + continue; + modPercent += stepPercent * aura->GetStackAmount(); + } + AddPct(DoneTotalMod, modPercent); + break; + } + case 7871: // Glyph of Lesser Healing Wave + { + if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0, GetGUID())) + AddPct(DoneTotalMod, (*i)->GetAmount()); + break; + } + default: + break; + } + } + + return DoneTotalMod; +} + uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack) const { float TakenTotalMod = 1.0f; @@ -11181,7 +11231,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType // Some spells don't benefit from pct done mods if (spellProto) - if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !spellProto->IsRankOf(sSpellMgr->GetSpellInfo(12162))) + if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS)) { AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 1735d1a8b8c..dbb463585f0 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1972,13 +1972,15 @@ class Unit : public WorldObject Unit* GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo); Unit* GetMeleeHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo = NULL); - int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const; - int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const; + int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const; + int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const; uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const; + float SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype) const; uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1) const; - int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const; - int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const; + int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const; + int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const; uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const; + float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const; uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1) const; uint32 MeleeDamageBonusDone(Unit* pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const* spellProto = NULL); @@ -1986,7 +1988,8 @@ class Unit : public WorldObject bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK); bool isBlockCritical(); - bool isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; + bool IsSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; + float GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK) const; uint32 SpellCriticalDamageBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim); uint32 SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damage, Unit* victim); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 07691e14e4f..138e6b84d0a 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -380,7 +380,7 @@ AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* cast m_base(base), m_spellInfo(base->GetSpellInfo()), m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), -m_canBeRecalculated(true), m_isPeriodic(false) +m_canBeRecalculated(true), m_isPeriodic(false), m_damage(0), m_critChance(0.0f), m_donePct(1.0f) { CalculatePeriodic(caster, true, false); @@ -890,19 +890,15 @@ void AuraEffect::UpdatePeriodic(Unit* caster) GetBase()->CallScriptEffectUpdatePeriodicHandlers(this); } -bool AuraEffect::IsPeriodicTickCrit(Unit* target, Unit const* caster) const +bool AuraEffect::CanPeriodicTickCrit(Unit* target, Unit const* caster) const { ASSERT(caster); - Unit::AuraEffectList const& mPeriodicCritAuras= caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_PERIODIC_CRIT); - for (Unit::AuraEffectList::const_iterator itr = mPeriodicCritAuras.begin(); itr != mPeriodicCritAuras.end(); ++itr) - { - if ((*itr)->IsAffectedOnSpell(m_spellInfo) && caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask())) - return true; - } + if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, m_spellInfo)) + return true; // Rupture - since 3.3.3 can crit if (m_spellInfo->SpellIconID == 500 && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE) - return caster->isSpellCrit(target, m_spellInfo, m_spellInfo->GetSchoolMask()); + return true; return false; } @@ -5780,15 +5776,19 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const uint32 resist = 0; CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - // ignore non positive values (can be result apply spellmods to aura damage - uint32 damage = std::max(GetAmount(), 0); + // AOE spells are not affected by the new periodic system. + bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + // ignore negative values (can be result apply spellmods to aura damage + uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations - sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + if (isAreaAura) + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE) { - damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); + if (isAreaAura) + damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT); damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); // Calculate armor mitigation @@ -5844,14 +5844,19 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const else damage = uint32(target->CountPctFromMaxHealth(damage)); - if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) - { - damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - if (caster->GetTypeId() != TYPEID_PLAYER) - damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); - } + if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) + if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura) + { + damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); + if (caster->GetTypeId() != TYPEID_PLAYER) + damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); + } + + bool crit = false; + + if (CanPeriodicTickCrit(target, caster)) + crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance); - bool crit = IsPeriodicTickCrit(target, caster); if (crit) damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target); @@ -5906,23 +5911,42 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c uint32 resist = 0; CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - uint32 damage = std::max(GetAmount(), 0); + bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + // ignore negative values (can be result apply spellmods to aura damage + uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; - damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); + if (isAreaAura) + { + // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT); + } damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); - bool crit = IsPeriodicTickCrit(target, caster); - if (crit) - damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target); - // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), m_effIndex)) + if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) { uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo()); cleanDamage.mitigated_damage += damage - damageReductedArmor; damage = damageReductedArmor; } + if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) + if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura) + { + damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); + if (caster->GetTypeId() != TYPEID_PLAYER) + damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); + } + + bool crit = false; + + if (CanPeriodicTickCrit(target, caster)) + crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance); + + if (crit) + damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target); + int32 dmg = damage; if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL); @@ -6007,8 +6031,9 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (GetBase()->IsPermanent() && target->IsFullHealth()) return; + bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage - int32 damage = std::max(m_amount, 0); + int32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH) { @@ -6056,12 +6081,16 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const damage += addition; } - - damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); + if (isAreaAura) + damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellHealingPctDone(target, m_spellInfo); damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); } - bool crit = IsPeriodicTickCrit(target, caster); + bool crit = false; + + if (CanPeriodicTickCrit(target, caster)) + crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance); + if (crit) damage = caster->SpellCriticalHealingBonus(m_spellInfo, damage, target); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 0887ce123e2..c8c6ad7fad7 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -70,6 +70,13 @@ class AuraEffect void HandleEffect(Unit* target, uint8 mode, bool apply); void ApplySpellMod(Unit* target, bool apply); + void SetDamage(int32 val) { m_damage = val; } + int32 GetDamage() const { return m_damage; } + void SetCritChance(float val) { m_critChance = val; } + float GetCritChance() const { return m_critChance; } + void SetDonePct(float val) { m_donePct = val; } + float GetDonePct() const { return m_donePct; } + void Update(uint32 diff, Unit* caster); void UpdatePeriodic(Unit* caster); @@ -98,6 +105,9 @@ class AuraEffect int32 const m_baseAmount; int32 m_amount; + int32 m_damage; + float m_critChance; + float m_donePct; SpellModifier* m_spellmod; @@ -109,7 +119,7 @@ class AuraEffect bool m_canBeRecalculated; bool m_isPeriodic; private: - bool IsPeriodicTickCrit(Unit* target, Unit const* caster) const; + bool CanPeriodicTickCrit(Unit* target, Unit const* caster) const; public: // aura effect apply/remove handlers diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 3e1763e6c5b..683059b8e99 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -746,9 +746,20 @@ void Aura::SetDuration(int32 duration, bool withMods) SetNeedClientUpdateForTargets(); } -void Aura::RefreshDuration() +void Aura::RefreshDuration(bool withMods) { - SetDuration(GetMaxDuration()); + if (withMods) + { + int32 duration = m_spellInfo->GetMaxDuration(); + // Calculate duration of periodics affected by haste. + if (GetCaster()->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) + duration = int32(duration * GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED)); + + SetMaxDuration(duration); + SetDuration(duration); + } + else + SetDuration(GetMaxDuration()); if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel) m_timeCla = 1 * IN_MILLISECONDS; @@ -825,7 +836,10 @@ void Aura::SetStackAmount(uint8 stackAmount) for (std::list::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr) if (!(*apptItr)->GetRemoveMode()) + { HandleAuraSpecificMods(*apptItr, caster, true, true); + HandleAuraSpecificPeriodics(*apptItr, caster); + } SetNeedClientUpdateForTargets(); } @@ -1631,26 +1645,62 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b break; } break; - case SPELLFAMILY_WARLOCK: - // Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage - if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000) + } +} + +void Aura::HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster) +{ + Unit* target = aurApp->GetTarget(); + + if (!caster || aurApp->GetRemoveMode()) + return; + + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (!HasEffect(i)) + continue; + + if (m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + continue; + + switch (m_spellInfo->Effects[i].ApplyAuraName) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_PERIODIC_LEECH: { - if (!caster) - break; - if (apply) - { - if (target != caster && !target->HealthAbovePct(25)) - caster->CastSpell(caster, 100001, true); - } - else - { - if (target != caster) - caster->RemoveAurasDueToSpell(GetId()); - else - caster->RemoveAurasDueToSpell(100001); - } + AuraEffect* aurEff = GetEffect(i); + + // ignore non positive values (can be result apply spellmods to aura damage + uint32 damage = std::max(aurEff->GetAmount(), 0); + + // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + + aurEff->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT)); // Calculate done percentage first! + aurEff->SetDamage(caster->SpellDamageBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct()); + aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); + break; } - break; + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_OBS_MOD_HEALTH: + { + AuraEffect* aurEff = GetEffect(i); + + // ignore non positive values (can be result apply spellmods to aura damage + uint32 damage = std::max(aurEff->GetAmount(), 0); + + // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + + aurEff->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo)); // Calculate done percentage first! + aurEff->SetDamage(caster->SpellHealingBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct()); + aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); + break; + } + default: + break; + } } } diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index f62b1ff47b4..669d2a529a1 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -129,7 +129,7 @@ class Aura int32 CalcMaxDuration(Unit* caster) const; int32 GetDuration() const { return m_duration; } void SetDuration(int32 duration, bool withMods = false); - void RefreshDuration(); + void RefreshDuration(bool withMods = false); void RefreshTimers(); bool IsExpired() const { return !GetDuration();} bool IsPermanent() const { return GetMaxDuration() == -1; } @@ -190,6 +190,7 @@ class Aura void SetNeedClientUpdateForTargets() const; void HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply); + void HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* caster); bool CanBeAppliedOn(Unit* target); bool CheckAreaTarget(Unit* target); bool CanStackWith(Aura const* existingAura) const; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index f5d90bc3612..ca170187e82 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2340,7 +2340,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Do healing and triggers if (m_healing > 0) { - bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask); + bool crit = caster->IsSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask); uint32 addhealth = m_healing; if (crit) { @@ -6729,7 +6729,7 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) } } - targetInfo.crit = m_caster->isSpellCrit(unit, m_spellInfo, m_spellSchoolMask, m_attackType); + targetInfo.crit = m_caster->IsSpellCrit(unit, m_spellInfo, m_spellSchoolMask, m_attackType); } SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 6108bf87478..48c73cf39ca 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4056,15 +4056,40 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) { // Get diseases on target of spell if (m_targets.GetUnitTarget() && // Glyph of Disease - cast on unit target too to refresh aura - (m_targets.GetUnitTarget() != unitTarget || m_caster->GetAura(63334))) + (m_targets.GetUnitTarget() != unitTarget || m_caster->HasAura(63334))) { // And spread them on target // Blood Plague - if (m_targets.GetUnitTarget()->GetAura(55078)) + if (m_targets.GetUnitTarget()->HasAura(55078)) + { + AuraEffect* aurEffOld = m_targets.GetUnitTarget()->GetAura(55078)->GetEffect(0); + float donePct = aurEffOld->GetDonePct(); + float critChance = aurEffOld->GetCritChance(); + m_caster->CastSpell(unitTarget, 55078, true); + + if (unitTarget->HasAura(55078)) + if (AuraEffect* aurEffNew = unitTarget->GetAura(55078)->GetEffect(0)) + { + aurEffNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9. + aurEffNew->SetDonePct(donePct); + aurEffNew->SetDamage(m_caster->SpellDamageBonusDone(unitTarget, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); + } + } // Frost Fever - if (m_targets.GetUnitTarget()->GetAura(55095)) + if (m_targets.GetUnitTarget()->HasAura(55095)) + { + float donePct = m_targets.GetUnitTarget()->GetAura(55095)->GetEffect(0)->GetDonePct(); + m_caster->CastSpell(unitTarget, 55095, true); + + if (unitTarget->HasAura(55095)) + if (AuraEffect* aurEffNew = unitTarget->GetAura(55095)->GetEffect(0)) + { + aurEffNew->SetDonePct(donePct); + aurEffNew->SetDamage(m_caster->SpellDamageBonusDone(unitTarget, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); + } + } } } break; diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 725312eafce..c3f994135aa 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -202,16 +202,21 @@ class spell_hun_chimera_shot : public SpellScriptLoader flag96 familyFlag = aura->GetSpellInfo()->SpellFamilyFlags; if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000)) continue; - if (AuraEffect const* aurEff = aura->GetEffect(0)) + if (AuraEffect* aurEff = aura->GetEffect(0)) { // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. if (familyFlag[0] & 0x4000) { int32 TickCount = aurEff->GetTotalTicks(); spellId = SPELL_HUNTER_CHIMERA_SHOT_SERPENT; - basePoint = caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), aurEff->GetAmount(), DOT, aura->GetStackAmount()); + basePoint = aurEff->GetDamage(); ApplyPct(basePoint, TickCount * 40); basePoint = unitTarget->SpellDamageBonusTaken(caster, aura->GetSpellInfo(), basePoint, DOT, aura->GetStackAmount()); + + // Recalculate bonus damage on roll. + uint32 damage = std::max(aurEff->GetAmount(), 0); + sScriptMgr->ModifyPeriodicDamageAurasTick(unitTarget, caster, damage); + aurEff->SetDamage(caster->SpellDamageBonusDone(unitTarget, aurEff->GetSpellInfo(), damage, DOT) * aurEff->GetDonePct()); } // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. else if (familyFlag[1] & 0x00000080) diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index dea67b5222d..76781e0fdc2 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -531,10 +531,17 @@ class spell_pri_pain_and_suffering_proc : public SpellScriptLoader void HandleEffectScriptEffect(SpellEffIndex /*effIndex*/) { + Unit* caster = GetCaster(); // Refresh Shadow Word: Pain on target - if (Unit* unitTarget = GetHitUnit()) - if (AuraEffect* aur = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetCaster()->GetGUID())) + if (Unit* target = GetHitUnit()) + if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, caster->GetGUID())) + { + uint32 damage = std::max(aur->GetAmount(), 0); + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + aur->SetDamage(caster->SpellDamageBonusDone(target, aur->GetSpellInfo(), damage, DOT) * aur->GetDonePct()); + aur->CalculatePeriodic(caster, false, false); aur->GetBase()->RefreshDuration(); + } } void Register() override diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 18979d24ecb..3f935077b22 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -405,10 +405,17 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader void HandleScriptEffect(SpellEffIndex /*effIndex*/) { - if (Unit* unitTarget = GetHitUnit()) + Unit* caster = GetCaster(); + if (Unit* target = GetHitUnit()) // Refresh corruption on target - if (AuraEffect* aur = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, GetCaster()->GetGUID())) - aur->GetBase()->RefreshDuration(); + if (AuraEffect* aur = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, caster->GetGUID())) + { + uint32 damage = std::max(aur->GetAmount(), 0); + sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); + aur->SetDamage(caster->SpellDamageBonusDone(target, aur->GetSpellInfo(), damage, DOT) * aur->GetDonePct()); + aur->CalculatePeriodic(caster, false, false); + aur->GetBase()->RefreshDuration(true); + } } void Register() override diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index fd1c785cf50..40d939c6394 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -36,7 +36,7 @@ enum WarriorSpells SPELL_WARRIOR_DEEP_WOUNDS_RANK_1 = 12162, SPELL_WARRIOR_DEEP_WOUNDS_RANK_2 = 12850, SPELL_WARRIOR_DEEP_WOUNDS_RANK_3 = 12868, - SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC = 12721, + SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC = 12721, SPELL_WARRIOR_EXECUTE = 20647, SPELL_WARRIOR_GLYPH_OF_EXECUTION = 58367, SPELL_WARRIOR_GLYPH_OF_VIGILANCE = 63326, @@ -268,23 +268,18 @@ class spell_warr_deep_wounds : public SpellScriptLoader Unit* caster = GetCaster(); if (Unit* target = GetHitUnit()) { - // apply percent damage mods - damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE); - ApplyPct(damage, 16 * GetSpellInfo()->GetRank()); - damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE); - - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC); + SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC); uint32 ticks = spellInfo->GetDuration() / spellInfo->Effects[EFFECT_0].Amplitude; // Add remaining ticks to damage done - if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC, EFFECT_0, caster->GetGUID())) - damage += aurEff->GetAmount() * (ticks - aurEff->GetTickNumber()); + if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC, EFFECT_0, caster->GetGUID())) + damage += aurEff->GetDamage() * (ticks - aurEff->GetTickNumber()); damage /= ticks; - caster->CastCustomSpell(target, SPELL_WARRIOR_DEEP_WOUNDS_RANK_PERIODIC, &damage, NULL, NULL, true); + caster->CastCustomSpell(target, SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC, &damage, NULL, NULL, true); } } -- cgit v1.2.3 From 6afd62a6bdda4fb6740fa66a35459f772b9afde2 Mon Sep 17 00:00:00 2001 From: Aokromes Date: Sat, 7 Jun 2014 22:13:42 +0200 Subject: Core/Database: Update log for incorrect db structure --- src/server/shared/Database/DatabaseWorkerPool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 3665a388854..9c56c75bf71 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -99,7 +99,7 @@ class DatabaseWorkerPool (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC])); else TC_LOG_ERROR("sql.driver", "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile " - "for specific errors.", GetDatabaseName()); + "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", GetDatabaseName()); return res; } -- cgit v1.2.3 From 6dc76223fbf2946ab262bc1c9a9a89bd9411090b Mon Sep 17 00:00:00 2001 From: jackpoz Date: Sat, 7 Jun 2014 22:47:50 +0200 Subject: Core/Banks: Fix some bank exploits Re-implement the cheat checks removed in a12501fb5e6f827d905e0eeba5bc908f8279880a and check if Player can interact with the Banker when handling bank-related opcodes. --- src/server/game/Handlers/ItemHandler.cpp | 62 ++++++++++++++++++++++++++++---- src/server/game/Handlers/NPCHandler.cpp | 1 + src/server/game/Server/WorldSession.cpp | 3 +- src/server/game/Server/WorldSession.h | 3 ++ 4 files changed, 62 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 0ca7885b82b..3ef99cc2fc1 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -85,6 +85,18 @@ void WorldSession::HandleSwapInvItemOpcode(WorldPacket& recvData) return; } + if (_player->IsBankPos(INVENTORY_SLOT_BAG_0, srcslot) && !CanUseBank()) + { + TC_LOG_DEBUG("network", "WORLD: HandleSwapInvItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID))); + return; + } + + if (_player->IsBankPos(INVENTORY_SLOT_BAG_0, dstslot) && !CanUseBank()) + { + TC_LOG_DEBUG("network", "WORLD: HandleSwapInvItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID))); + return; + } + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); @@ -137,6 +149,18 @@ void WorldSession::HandleSwapItem(WorldPacket& recvData) return; } + if (_player->IsBankPos(srcbag, srcslot) && !CanUseBank()) + { + TC_LOG_DEBUG("network", "WORLD: HandleSwapItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID))); + return; + } + + if (_player->IsBankPos(dstbag, dstslot) && !CanUseBank()) + { + TC_LOG_DEBUG("network", "WORLD: HandleSwapItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID))); + return; + } + _player->SwapItem(src, dst); } @@ -858,15 +882,11 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket) uint64 guid; recvPacket >> guid; - // cheating protection - /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command. - Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER); - if (!creature) + if (!CanUseBank(guid)) { - TC_LOG_DEBUG("WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); + TC_LOG_DEBUG("network", "WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid))); return; } - */ uint32 slot = _player->GetBankBagSlotCount(); @@ -912,6 +932,12 @@ void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket) recvPacket >> srcbag >> srcslot; TC_LOG_DEBUG("network", "STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + if (!CanUseBank()) + { + TC_LOG_DEBUG("network", "WORLD: HandleAutoBankItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID))); + return; + } + Item* pItem = _player->GetItemByPos(srcbag, srcslot); if (!pItem) return; @@ -943,6 +969,12 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) recvPacket >> srcbag >> srcslot; TC_LOG_DEBUG("network", "STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot); + if (!CanUseBank()) + { + TC_LOG_DEBUG("network", "WORLD: HandleAutoStoreBankItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID))); + return; + } + Item* pItem = _player->GetItemByPos(srcbag, srcslot); if (!pItem) return; @@ -1441,3 +1473,21 @@ void WorldSession::HandleItemTextQuery(WorldPacket& recvData ) SendPacket(&data); } + +bool WorldSession::CanUseBank(uint64 bankerGUID) const +{ + // bankerGUID parameter is optional, set to 0 by default. + if (!bankerGUID) + bankerGUID = m_currentBankerGUID; + + bool isUsingBankCommand = (bankerGUID == GetPlayer()->GetGUID() && bankerGUID == m_currentBankerGUID); + + if (!isUsingBankCommand) + { + Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(bankerGUID, UNIT_NPC_FLAG_BANKER); + if (!creature) + return false; + } + + return true; +} \ No newline at end of file diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index fc14797ea94..d8a518a24db 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -100,6 +100,7 @@ void WorldSession::SendShowBank(uint64 guid) { WorldPacket data(SMSG_SHOW_BANK, 8); data << guid; + m_currentBankerGUID = guid; SendPacket(&data); } diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index eda7b8917a7..a0ff8b98e43 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -123,7 +123,8 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 isRecruiter(isARecruiter), _RBACData(NULL), expireTime(60000), // 1 min after socket loss, session is deleted - forceExit(false) + forceExit(false), + m_currentBankerGUID(0) { memset(m_Tutorials, 0, sizeof(m_Tutorials)); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 82125aafd6d..2f5f17952db 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -975,6 +975,8 @@ class WorldSession // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); + bool CanUseBank(uint64 bankerGUID = 0) const; + // logging helper void LogUnexpectedOpcode(WorldPacket* packet, const char* status, const char *reason); void LogUnprocessedTail(WorldPacket* packet); @@ -1023,6 +1025,7 @@ class WorldSession rbac::RBACData* _RBACData; uint32 expireTime; bool forceExit; + uint64 m_currentBankerGUID; WorldSession(WorldSession const& right) = delete; WorldSession& operator=(WorldSession const& right) = delete; -- cgit v1.2.3 From 3be5178304226215246415bafb6547c41d193ac5 Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 7 Jun 2014 23:56:13 +0200 Subject: Core/Misc: Kill Whitespace ... --- src/server/authserver/Main.cpp | 16 ++++++++-------- src/server/game/Entities/Player/Player.cpp | 2 +- src/server/game/Entities/Player/Player.h | 4 ++-- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Handlers/MiscHandler.cpp | 2 +- src/server/game/Server/WorldSession.cpp | 2 +- src/server/game/Spells/SpellMgr.cpp | 12 ++++++------ .../BlackrockDepths/boss_anubshiah.cpp | 2 +- .../BlackrockDepths/boss_general_angerforge.cpp | 2 +- .../BlackrockMountain/BlackrockDepths/boss_grizzle.cpp | 2 +- .../boss_high_interrogator_gerstahn.cpp | 2 +- .../BlackrockMountain/BlackrockDepths/boss_magmus.cpp | 2 +- .../BlackrockDepths/boss_moira_bronzebeard.cpp | 2 +- .../HallsOfReflection/halls_of_reflection.cpp | 8 ++++---- src/server/shared/Debugging/WheatyExceptionReport.cpp | 2 +- src/server/shared/Debugging/WheatyExceptionReport.h | 2 +- src/server/shared/Packets/ByteBuffer.h | 12 ++++++------ src/server/worldserver/Master.cpp | 18 +++++++++--------- 18 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index d1b2b614037..be6623c7fa3 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -179,24 +179,24 @@ extern int main(int argc, char** argv) Handler.register_handler(SIGTERM, &SignalTERM); #if defined(_WIN32) || defined(__linux__) - + ///- Handle affinity for multiple processors and process priority uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0); bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false); #ifdef _WIN32 // Windows - + HANDLE hProcess = GetCurrentProcess(); if (affinity > 0) { ULONG_PTR appAff; ULONG_PTR sysAff; - + if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) { // remove non accessible processors ULONG_PTR currentAffinity = affinity & appAff; - + if (!currentAffinity) TC_LOG_ERROR("server.authserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the authserver. Accessible processors bitmask (hex): %x", affinity, appAff); else if (SetProcessAffinityMask(hProcess, currentAffinity)) @@ -205,7 +205,7 @@ extern int main(int argc, char** argv) TC_LOG_ERROR("server.authserver", "Can't set used processors (hex): %x", currentAffinity); } } - + if (highPriority) { if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) @@ -213,9 +213,9 @@ extern int main(int argc, char** argv) else TC_LOG_ERROR("server.authserver", "Can't set authserver process priority class."); } - + #else // Linux - + if (affinity > 0) { cpu_set_t mask; @@ -242,7 +242,7 @@ extern int main(int argc, char** argv) else TC_LOG_INFO("server.authserver", "authserver process priority class set to %i", getpriority(PRIO_PROCESS, 0)); } - + #endif #endif diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 297114e14d2..c7f36aff92b 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -689,7 +689,7 @@ Player::Player(WorldSession* session): Unit(true) m_areaUpdateId = 0; m_team = 0; - + m_needsZoneUpdate = false; m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 94175834969..aeac9db98aa 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1676,7 +1676,7 @@ class Player : public Unit, public GridObject void UpdateZone(uint32 newZone, uint32 newArea); void UpdateArea(uint32 newArea); void SetNeedsZoneUpdate(bool needsUpdate) { m_needsZoneUpdate = needsUpdate; } - + void UpdateZoneDependentAuras(uint32 zone_id); // zones void UpdateAreaDependentAuras(uint32 area_id); // subzones @@ -2564,7 +2564,7 @@ class Player : public Unit, public GridObject bool IsAlwaysDetectableFor(WorldObject const* seer) const; uint8 m_grantableLevels; - + bool m_needsZoneUpdate; private: diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 63f67571f9f..2c589a27f9c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -10279,7 +10279,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui int32 TakenTotal = 0; float TakenTotalMod = 1.0f; float TakenTotalCasterMod = 0.0f; - + // Mod damage from spell mechanic if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask()) { diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 11fa89d9d6b..c4ff2581e75 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -502,7 +502,7 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket& recvData) // use server side data, but only after update the player position. See Player::UpdatePosition(). GetPlayer()->SetNeedsZoneUpdate(true); - + //GetPlayer()->SendInitWorldStates(true, newZone); } diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index a0ff8b98e43..f8df683d90c 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1264,7 +1264,7 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(), opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter); } - + // Then check if player is sending packets not allowed if (!IsOpcodeAllowed(p.GetOpcode())) { diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 9eadd178eb3..b94d0def3dd 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -784,14 +784,14 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell bool hasFamilyMask = false; - /** - + /** + * @brief Check auras procced by periodics *Only damaging Dots can proc auras with PROC_FLAG_TAKEN_DAMAGE *Only Dots can proc if ONLY has PROC_FLAG_DONE_PERIODIC or PROC_FLAG_TAKEN_PERIODIC. - + *Hots can proc if ONLY has PROC_FLAG_DONE_PERIODIC and spellfamily != 0 *Only Dots can proc auras with PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG or PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG @@ -806,7 +806,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell * @param procFlags proc_flags of spellProc * @param procExtra proc_EX of procSpell * @param EventProcFlag proc_flags of aura to be procced - * @param spellProto SpellInfo of aura to be procced + * @param spellProto SpellInfo of aura to be procced */ @@ -815,7 +815,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell return true; if (procFlags & PROC_FLAG_DONE_PERIODIC && EventProcFlag & PROC_FLAG_DONE_PERIODIC) - { + { if (procExtra & PROC_EX_INTERNAL_HOT) { if (EventProcFlag == PROC_FLAG_DONE_PERIODIC) @@ -835,7 +835,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell } if (procFlags & PROC_FLAG_TAKEN_PERIODIC && EventProcFlag & PROC_FLAG_TAKEN_PERIODIC) - { + { if (procExtra & PROC_EX_INTERNAL_HOT) { /// No aura that only has PROC_FLAG_TAKEN_PERIODIC can proc from a HOT. diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp index 1a2e8bba805..894b528c03c 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp @@ -50,7 +50,7 @@ class boss_anubshiah : public CreatureScript _events.Reset(); } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* /*who*/) override { _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000); _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 24000); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp index 79ffedc8c17..d5b8d1deadd 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp @@ -54,7 +54,7 @@ class boss_general_angerforge : public CreatureScript _events.Reset(); } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* /*who*/) override { _events.SetPhase(PHASE_ONE); _events.ScheduleEvent(EVENT_MIGHTYBLOW, 8000); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp index f46c0c118b1..f53fd0f65b3 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp @@ -51,7 +51,7 @@ class boss_grizzle : public CreatureScript _events.Reset(); } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* /*who*/) override { _events.SetPhase(PHASE_ONE); _events.ScheduleEvent(EVENT_GROUNDTREMOR, 12000); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp index 7105d78f2ee..c41ddf9d98b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp @@ -48,7 +48,7 @@ class boss_high_interrogator_gerstahn : public CreatureScript _events.Reset(); } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* /*who*/) override { _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 4000); _events.ScheduleEvent(EVENT_MANABURN, 14000); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp index efc9a6e793b..e6bbbaa73a9 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp @@ -51,7 +51,7 @@ class boss_magmus : public CreatureScript _events.Reset(); } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* /*who*/) override { _events.SetPhase(PHASE_ONE); _events.ScheduleEvent(EVENT_FIERY_BURST, 5000); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp index 0c36fe9696d..8342bef682b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp @@ -50,7 +50,7 @@ class boss_moira_bronzebeard : public CreatureScript _events.Reset(); } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* /*who*/) override { //_events.ScheduleEvent(EVENT_HEAL, 12000); // not used atm // These times are probably wrong _events.ScheduleEvent(EVENT_MINDBLAST, 16000); diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index ccdd92ae4ba..4303026ba64 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -1100,7 +1100,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript Talk(SAY_JAINA_ESCAPE_9); if (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetData64(DATA_GUNSHIP))) gunship->EnableMovement(true); - _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, DONE); + _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, DONE); break; case EVENT_ESCAPE_17: if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) @@ -1139,7 +1139,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript struct npc_the_lich_king_escape_horAI : public ScriptedAI { - npc_the_lich_king_escape_horAI(Creature* creature) : ScriptedAI(creature) + npc_the_lich_king_escape_horAI(Creature* creature) : ScriptedAI(creature) { _instance = me->GetInstanceScript(); _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, NOT_STARTED); @@ -1248,12 +1248,12 @@ class npc_the_lich_king_escape_hor : public CreatureScript _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 66000); _events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 14000); Talk(SAY_LK_ESCAPE_ICEWALL_SUMMONED_4); - break; + break; default: break; } } - + void EnterEvadeMode() override { if (_despawn) diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp index 3b6bd3d2cc8..81825c9055b 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.cpp +++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp @@ -45,7 +45,7 @@ inline LPTSTR ErrorMessage(DWORD dw) sprintf(msgBuf, "Unknown error: %u", dw); return msgBuf; } - + } //============================== Global Variables ============================= diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h index f6d6b7f4b9e..e1cc3050929 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.h +++ b/src/server/shared/Debugging/WheatyExceptionReport.h @@ -83,7 +83,7 @@ struct SymbolPair bool operator<(const SymbolPair& other) const { - return _offset < other._offset || + return _offset < other._offset || (_offset == other._offset && _type < other._type); } diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 9f766a72d19..11e835566e9 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -382,18 +382,18 @@ class ByteBuffer return *this; } - uint8 * contents() - { + uint8 * contents() + { if (_storage.empty()) throw ByteBufferException(); - return &_storage[0]; + return &_storage[0]; } - const uint8 *contents() const - { + const uint8 *contents() const + { if (_storage.empty()) throw ByteBufferException(); - return &_storage[0]; + return &_storage[0]; } size_t size() const { return _storage.size(); } diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index c5424374f5a..6e4214603cb 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -201,24 +201,24 @@ int Master::Run() ACE_Based::Thread rarThread(new RARunnable); #if defined(_WIN32) || defined(__linux__) - + ///- Handle affinity for multiple processors and process priority uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0); bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false); #ifdef _WIN32 // Windows - + HANDLE hProcess = GetCurrentProcess(); - + if (affinity > 0) { ULONG_PTR appAff; ULONG_PTR sysAff; - + if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) { ULONG_PTR currentAffinity = affinity & appAff; // remove non accessible processors - + if (!currentAffinity) TC_LOG_ERROR("server.worldserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the worldserver. Accessible processors bitmask (hex): %x", affinity, appAff); else if (SetProcessAffinityMask(hProcess, currentAffinity)) @@ -227,7 +227,7 @@ int Master::Run() TC_LOG_ERROR("server.worldserver", "Can't set used processors (hex): %x", currentAffinity); } } - + if (highPriority) { if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) @@ -235,9 +235,9 @@ int Master::Run() else TC_LOG_ERROR("server.worldserver", "Can't set worldserver process priority class."); } - + #else // Linux - + if (affinity > 0) { cpu_set_t mask; @@ -264,7 +264,7 @@ int Master::Run() else TC_LOG_INFO("server.worldserver", "worldserver process priority class set to %i", getpriority(PRIO_PROCESS, 0)); } - + #endif #endif -- cgit v1.2.3 From ecbf6fdd6c1d092e3be24c6e3699295f775078f9 Mon Sep 17 00:00:00 2001 From: Gacko Date: Wed, 4 Jun 2014 10:26:42 +0200 Subject: Script: Minor optimization in spell_unlocking_zuluheds_chains --- src/server/scripts/Outland/zone_shadowmoon_valley.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 116beb3d081..cfcc05a625c 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -1813,7 +1813,6 @@ public: enum ZuluhedChains { - QUEST_ZULUHED = 10866, NPC_KARYNAKU = 22112, }; @@ -1828,9 +1827,9 @@ class spell_unlocking_zuluheds_chains : public SpellScriptLoader void HandleAfterHit() { - if (GetCaster()->GetTypeId() == TYPEID_PLAYER) - if (Creature* karynaku = GetCaster()->FindNearestCreature(NPC_KARYNAKU, 15.0f)) - GetCaster()->ToPlayer()->KilledMonsterCredit(NPC_KARYNAKU, karynaku->GetGUID()); + if (Player* caster = GetCaster()->ToPlayer()) + if (Creature* karynaku = caster->FindNearestCreature(NPC_KARYNAKU, 15.0f)) + caster->KilledMonsterCredit(NPC_KARYNAKU, karynaku->GetGUID()); } void Register() override -- cgit v1.2.3 From 3c8503bea70e99821bf4faac4c508c18ebc72fcd Mon Sep 17 00:00:00 2001 From: jackpoz Date: Sun, 8 Jun 2014 17:18:07 +0200 Subject: Revert "Core/Calendar: Fix memory leak when malformed CMSG_CALENDAR_ADD_EVENT is received" This partially reverts commit 51e38872c72e16bb0f09e660c2660759021b2176. The stack-initialized variable calendarEvent would have called CalendarMgr::FreeEventId() when it went out of scope, marking the current event id as free and allowing next event to overwrite current event. This doesn't fix the memory leak issue which still needs to be addressed in a proper way. --- src/server/game/Handlers/CalendarHandler.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 278c180c380..02cb4f0087f 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -235,20 +235,20 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) recvData.ReadPackedTime(unkPackedTime); recvData >> flags; - CalendarEvent calendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, + CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, time_t(eventPackedTime), flags, time_t(unkPackedTime), title, description); - if (calendarEvent.IsGuildEvent() || calendarEvent.IsGuildAnnouncement()) + if (calendarEvent->IsGuildEvent() || calendarEvent->IsGuildAnnouncement()) if (Player* creator = ObjectAccessor::FindPlayer(guid)) - calendarEvent.SetGuildId(creator->GetGuildId()); + calendarEvent->SetGuildId(creator->GetGuildId()); - if (calendarEvent.IsGuildAnnouncement()) + if (calendarEvent->IsGuildAnnouncement()) { // 946684800 is 01/01/2000 00:00:00 - default response time - CalendarInvite invite(0, calendarEvent.GetEventId(), 0, guid, 946684800, CALENDAR_STATUS_NOT_SIGNED_UP, CALENDAR_RANK_PLAYER, ""); + CalendarInvite invite(0, calendarEvent->GetEventId(), 0, guid, 946684800, CALENDAR_STATUS_NOT_SIGNED_UP, CALENDAR_RANK_PLAYER, ""); // WARNING: By passing pointer to a local variable, the underlying method(s) must NOT perform any kind // of storage of the pointer as it will lead to memory corruption - sCalendarMgr->AddInvite(&calendarEvent, &invite); + sCalendarMgr->AddInvite(calendarEvent, &invite); } else { @@ -271,15 +271,15 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) recvData >> status >> rank; // 946684800 is 01/01/2000 00:00:00 - default response time - CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent.GetEventId(), invitee, guid, 946684800, CalendarInviteStatus(status), CalendarModerationRank(rank), ""); - sCalendarMgr->AddInvite(&calendarEvent, invite, trans); + CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent->GetEventId(), invitee, guid, 946684800, CalendarInviteStatus(status), CalendarModerationRank(rank), ""); + sCalendarMgr->AddInvite(calendarEvent, invite, trans); } if (inviteCount > 1) CharacterDatabase.CommitTransaction(trans); } - sCalendarMgr->AddEvent(new CalendarEvent(calendarEvent, calendarEvent.GetEventId()), CALENDAR_SENDTYPE_ADD); + sCalendarMgr->AddEvent(calendarEvent, CALENDAR_SENDTYPE_ADD); } void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recvData) -- cgit v1.2.3 From bd4be27aeb9ac5750479f7ebefd9ee909fc02983 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Sun, 8 Jun 2014 17:33:17 +0200 Subject: Core/Calendar: Sanitize calendar event parameters Prevent events added in the past which in some conditions would cause an infinite loop in the client. --- src/server/game/Handlers/CalendarHandler.cpp | 32 ++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 02cb4f0087f..0a797f0e008 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -235,6 +235,14 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) recvData.ReadPackedTime(unkPackedTime); recvData >> flags; + // prevent events in the past + // To Do: properly handle timezones and remove the "- time_t(86400L)" hack + if (time_t(eventPackedTime) < (time(NULL) - time_t(86400L))) + { + recvData.rfinish(); + return; + } + CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, time_t(eventPackedTime), flags, time_t(unkPackedTime), title, description); @@ -304,6 +312,14 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recvData) recvData.ReadPackedTime(timeZoneTime); recvData >> flags; + // prevent events in the past + // To Do: properly handle timezones and remove the "- time_t(86400L)" hack + if (time_t(eventPackedTime) < (time(NULL) - time_t(86400L))) + { + recvData.rfinish(); + return; + } + TC_LOG_DEBUG("network", "CMSG_CALENDAR_UPDATE_EVENT [" UI64FMTD "] EventId [" UI64FMTD "], InviteId [" UI64FMTD "] Title %s, Description %s, type %u " "Repeatable %u, MaxInvites %u, Dungeon ID %d, Time %u " @@ -346,17 +362,25 @@ void WorldSession::HandleCalendarCopyEvent(WorldPacket& recvData) uint64 guid = _player->GetGUID(); uint64 eventId; uint64 inviteId; - uint32 time; + uint32 eventTime; recvData >> eventId >> inviteId; - recvData.ReadPackedTime(time); + recvData.ReadPackedTime(eventTime); TC_LOG_DEBUG("network", "CMSG_CALENDAR_COPY_EVENT [" UI64FMTD "], EventId [" UI64FMTD - "] inviteId [" UI64FMTD "] Time: %u", guid, eventId, inviteId, time); + "] inviteId [" UI64FMTD "] Time: %u", guid, eventId, inviteId, eventTime); + + // prevent events in the past + // To Do: properly handle timezones and remove the "- time_t(86400L)" hack + if (time_t(eventTime) < (time(NULL) - time_t(86400L))) + { + recvData.rfinish(); + return; + } if (CalendarEvent* oldEvent = sCalendarMgr->GetEvent(eventId)) { CalendarEvent* newEvent = new CalendarEvent(*oldEvent, sCalendarMgr->GetFreeEventId()); - newEvent->SetEventTime(time_t(time)); + newEvent->SetEventTime(time_t(eventTime)); sCalendarMgr->AddEvent(newEvent, CALENDAR_SENDTYPE_COPY); CalendarInviteStore invites = sCalendarMgr->GetEventInvites(eventId); -- cgit v1.2.3 From d1e276845088d9d493476b742a08e12e0dd50139 Mon Sep 17 00:00:00 2001 From: Lucas Date: Sun, 8 Jun 2014 21:07:52 +0200 Subject: Fix Warnings --- src/server/game/Entities/Unit/Unit.cpp | 5 +---- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 10 +++++----- src/server/game/Spells/Auras/SpellAuraEffects.h | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2c589a27f9c..b5ea898dc00 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9848,8 +9848,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin float ApCoeffMod = 1.0f; int32 DoneTotal = 0; - uint32 creatureTypeMask = victim->GetCreatureTypeMask(); - // done scripted mod (take it from owner) Unit const* owner = GetOwner() ? GetOwner() : this; AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); @@ -10808,8 +10806,7 @@ float Unit::SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const { // For totems pct done mods are calculated when its calculation is run on the player in SpellHealingBonusDone. if (GetTypeId() == TYPEID_UNIT && IsTotem()) - if (Unit* owner = GetOwner()) - return 1.0f; + return 1.0f; // No bonus healing for potion spells if (spellProto->SpellFamilyName == SPELLFAMILY_POTION) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 138e6b84d0a..a0883c895d3 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -380,7 +380,7 @@ AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* cast m_base(base), m_spellInfo(base->GetSpellInfo()), m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), -m_canBeRecalculated(true), m_isPeriodic(false), m_damage(0), m_critChance(0.0f), m_donePct(1.0f) +m_canBeRecalculated(true), m_damage(0), m_critChance(0.0f), m_donePct(1.0f), m_isPeriodic(false) { CalculatePeriodic(caster, true, false); @@ -890,7 +890,7 @@ void AuraEffect::UpdatePeriodic(Unit* caster) GetBase()->CallScriptEffectUpdatePeriodicHandlers(this); } -bool AuraEffect::CanPeriodicTickCrit(Unit* target, Unit const* caster) const +bool AuraEffect::CanPeriodicTickCrit(Unit const* caster) const { ASSERT(caster); if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_ABILITY_PERIODIC_CRIT, m_spellInfo)) @@ -5854,7 +5854,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const bool crit = false; - if (CanPeriodicTickCrit(target, caster)) + if (CanPeriodicTickCrit(caster)) crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance); if (crit) @@ -5941,7 +5941,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c bool crit = false; - if (CanPeriodicTickCrit(target, caster)) + if (CanPeriodicTickCrit(caster)) crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance); if (crit) @@ -6088,7 +6088,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const bool crit = false; - if (CanPeriodicTickCrit(target, caster)) + if (CanPeriodicTickCrit(caster)) crit = roll_chance_f(isAreaAura ? caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask()) : m_critChance); if (crit) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index c8c6ad7fad7..5eec9021291 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -119,7 +119,7 @@ class AuraEffect bool m_canBeRecalculated; bool m_isPeriodic; private: - bool CanPeriodicTickCrit(Unit* target, Unit const* caster) const; + bool CanPeriodicTickCrit(Unit const* caster) const; public: // aura effect apply/remove handlers -- cgit v1.2.3 From b96b7c291a0c58b55d13d90e6baac08686f2e631 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Sun, 8 Jun 2014 23:11:42 +0100 Subject: Core/Handlers: Move a couple of logs to debug, they can appear without anything abnormal due to client latency --- src/server/game/Handlers/MovementHandler.cpp | 2 +- src/server/game/Handlers/PetHandler.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 0c2eae849b8..5fc6ada6fb2 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -496,7 +496,7 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recvData) if (GetPlayer()->IsInWorld()) { if (_player->m_mover->GetGUID() != guid) - TC_LOG_ERROR("network", "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, guid, GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID()); + TC_LOG_DEBUG("network", "HandleSetActiveMoverOpcode: incorrect mover guid: mover is " UI64FMTD " (%s - Entry: %u) and should be " UI64FMTD, guid, GetLogNameForGuid(guid), GUID_ENPART(guid), _player->m_mover->GetGUID()); } } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index d64f21f2028..3cc445ff81b 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -74,13 +74,13 @@ void WorldSession::HandlePetAction(WorldPacket& recvData) if (!pet) { - TC_LOG_ERROR("network", "HandlePetAction: Pet (GUID: %u) doesn't exist for player %s (GUID: %u)", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); + TC_LOG_DEBUG("network", "HandlePetAction: Pet (GUID: %u) doesn't exist for player %s (GUID: %u)", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); return; } if (pet != GetPlayer()->GetFirstControlled()) { - TC_LOG_ERROR("network", "HandlePetAction: Pet (GUID: %u) does not belong to player %s (GUID: %u)", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); + TC_LOG_DEBUG("network", "HandlePetAction: Pet (GUID: %u) does not belong to player %s (GUID: %u)", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName().c_str(), GUID_LOPART(GetPlayer()->GetGUID())); return; } @@ -144,7 +144,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint32 spellid CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { - TC_LOG_ERROR("network", "WorldSession::HandlePetAction(petGuid: " UI64FMTD ", tagGuid: " UI64FMTD ", spellId: %u, flag: %u): object (GUID: %u Entry: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", + TC_LOG_DEBUG("network", "WorldSession::HandlePetAction(petGuid: " UI64FMTD ", tagGuid: " UI64FMTD ", spellId: %u, flag: %u): object (GUID: %u Entry: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", guid1, guid2, spellid, flag, pet->GetGUIDLow(), pet->GetEntry(), pet->GetTypeId()); return; } -- cgit v1.2.3 From b5278ef16008998ce63fe7583974e96055441512 Mon Sep 17 00:00:00 2001 From: Shauren Date: Mon, 9 Jun 2014 21:08:19 +0200 Subject: Core/Vehicles: Fixed channeled spells being interrupted for passengers when vehicle moves --- src/server/game/Entities/Unit/Unit.cpp | 4 +++- src/server/game/Handlers/MovementHandler.cpp | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b5ea898dc00..2b6cb9dd8ba 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -17079,12 +17079,14 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel bool turn = (GetOrientation() != orientation); bool relocated = (teleport || GetPositionX() != x || GetPositionY() != y || GetPositionZ() != z); + // TODO: Check if orientation transport offset changed instead of only global orientation if (turn) RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); if (relocated) { - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE); + if (!GetVehicle()) + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOVE); // move and update visible state if need if (GetTypeId() == TYPEID_PLAYER) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 5fc6ada6fb2..cef414163bd 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -30,6 +30,7 @@ #include "WaypointMovementGenerator.h" #include "InstanceSaveMgr.h" #include "ObjectMgr.h" +#include "Vehicle.h" #define MOVEMENT_PACKET_TIME_DELAY 0 @@ -370,10 +371,20 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) mover->m_movementInfo = movementInfo; - // this is almost never true (not sure why it is sometimes, but it is), normally use mover->IsVehicle() - if (mover->GetVehicle()) + // Some vehicles allow the passenger to turn by himself + if (Vehicle* vehicle = mover->GetVehicle()) { - mover->SetOrientation(movementInfo.pos.GetOrientation()); + if (VehicleSeatEntry const* seat = vehicle->GetSeatForPassenger(mover)) + { + if (seat->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING) + { + if (movementInfo.pos.GetOrientation() != mover->GetOrientation()) + { + mover->SetOrientation(movementInfo.pos.GetOrientation()); + mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TURNING); + } + } + } return; } -- cgit v1.2.3 From 5ebf24281c35ce785d712d87f85880089a559aeb Mon Sep 17 00:00:00 2001 From: jackpoz Date: Mon, 9 Jun 2014 21:35:59 +0200 Subject: Core/NetworkIO: Adjust more packet throttling values Ignore some opcodes that don't cause any trouble. Remove old Allow/Disable Anti-DoS system since it's no longer required. --- src/server/game/Handlers/GroupHandler.cpp | 2 - src/server/game/Server/WorldSession.cpp | 384 +++++++++++++++--------------- src/server/game/Server/WorldSession.h | 12 - 3 files changed, 194 insertions(+), 204 deletions(-) (limited to 'src') diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index eae95d20610..97867e2f352 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -638,8 +638,6 @@ void WorldSession::HandleGroupAssistantLeaderOpcode(WorldPacket& recvData) recvData >> apply; group->SetGroupMemberFlag(guid, apply, MEMBER_FLAG_ASSISTANT); - - group->SendUpdate(); } void WorldSession::HandlePartyAssignmentOpcode(WorldPacket& recvData) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index f8df683d90c..3ac31da3eb1 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1246,6 +1246,12 @@ void WorldSession::InvalidateRBACData() bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) const { + uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode()); + + // Return true if there no limit for the opcode + if (!maxPacketCounterAllowed) + return true; + PacketCounter& packetCounter = _PacketThrottlingMap[p.GetOpcode()]; if (packetCounter.lastReceiveTime != time) { @@ -1253,29 +1259,14 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co packetCounter.amountCounter = 0; } - uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode()); - - bool dosTriggered = false; // Check if player is flooding some packets if (++packetCounter.amountCounter > maxPacketCounterAllowed) { - dosTriggered = true; TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)", Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(), opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter); } - // Then check if player is sending packets not allowed - if (!IsOpcodeAllowed(p.GetOpcode())) - { - dosTriggered = true; - // Opcode not allowed, let the punishment begin - TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)", - Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size()); - } - - // Return true if everything is fine, otherwise apply the configured policy - if (!dosTriggered) return true; switch (_policy) @@ -1312,207 +1303,220 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co uint32 maxPacketCounterAllowed; switch (opcode) { - // These opcodes are spammed by few addons so a very high limit is required - case CMSG_QUEST_QUERY: - case CMSG_MESSAGECHAT: - case CMSG_ITEM_QUERY_SINGLE: - case CMSG_ITEM_NAME_QUERY: - case CMSG_GAMEOBJECT_QUERY: - case CMSG_NAME_QUERY: - case CMSG_PET_NAME_QUERY: - case CMSG_CREATURE_QUERY: - case CMSG_NPC_TEXT_QUERY: - case CMSG_QUESTGIVER_STATUS_QUERY: + // CPU usage sending 2000 packets/second on a 3.70 GHz 4 cores on Win x64 + // [% CPU mysqld] [%CPU worldserver RelWithDebInfo] + case CMSG_PLAYER_LOGIN: // 0 0.5 + case CMSG_NAME_QUERY: // 0 1 + case CMSG_PET_NAME_QUERY: // 0 1 + case CMSG_NPC_TEXT_QUERY: // 0 1 + case CMSG_ATTACKSTOP: // 0 1 + case CMSG_QUERY_QUESTS_COMPLETED: // 0 1 + case CMSG_QUERY_TIME: // 0 1 + case CMSG_CORPSE_MAP_POSITION_QUERY: // 0 1 + case CMSG_MOVE_TIME_SKIPPED: // 0 1 + case MSG_QUERY_NEXT_MAIL_TIME: // 0 1 + case CMSG_SETSHEATHED: // 0 1 + case MSG_RAID_TARGET_UPDATE: // 0 1 + case CMSG_PLAYER_LOGOUT: // 0 1 + case CMSG_LOGOUT_REQUEST: // 0 1 + case CMSG_PET_RENAME: // 0 1 + case CMSG_QUESTGIVER_CANCEL: // 0 1 + case CMSG_QUESTGIVER_REQUEST_REWARD: // 0 1 + case CMSG_COMPLETE_CINEMATIC: // 0 1 + case CMSG_BANKER_ACTIVATE: // 0 1 + case CMSG_BUY_BANK_SLOT: // 0 1 + case CMSG_OPT_OUT_OF_LOOT: // 0 1 + case CMSG_DUEL_ACCEPTED: // 0 1 + case CMSG_DUEL_CANCELLED: // 0 1 + case CMSG_CALENDAR_COMPLAIN: // 0 1 + case CMSG_QUEST_QUERY: // 0 1.5 + case CMSG_ITEM_QUERY_SINGLE: // 0 1.5 + case CMSG_ITEM_NAME_QUERY: // 0 1.5 + case CMSG_GAMEOBJECT_QUERY: // 0 1.5 + case CMSG_CREATURE_QUERY: // 0 1.5 + case CMSG_QUESTGIVER_STATUS_QUERY: // 0 1.5 + case CMSG_GUILD_QUERY: // 0 1.5 + case CMSG_ARENA_TEAM_QUERY: // 0 1.5 + case CMSG_TAXINODE_STATUS_QUERY: // 0 1.5 + case CMSG_TAXIQUERYAVAILABLENODES: // 0 1.5 + case CMSG_QUESTGIVER_QUERY_QUEST: // 0 1.5 + case CMSG_PAGE_TEXT_QUERY: // 0 1.5 + case MSG_QUERY_GUILD_BANK_TEXT: // 0 1.5 + case MSG_CORPSE_QUERY: // 0 1.5 + case MSG_MOVE_SET_FACING: // 0 1.5 + case CMSG_REQUEST_PARTY_MEMBER_STATS: // 0 1.5 + case CMSG_QUESTGIVER_COMPLETE_QUEST: // 0 1.5 + case CMSG_SET_ACTION_BUTTON: // 0 1.5 + case CMSG_RESET_INSTANCES: // 0 1.5 + case CMSG_HEARTH_AND_RESURRECT: // 0 1.5 + case CMSG_TOGGLE_PVP: // 0 1.5 + case CMSG_PET_ABANDON: // 0 1.5 + case CMSG_ACTIVATETAXIEXPRESS: // 0 1.5 + case CMSG_ACTIVATETAXI: // 0 1.5 + case CMSG_SELF_RES: // 0 1.5 + case CMSG_UNLEARN_SKILL: // 0 1.5 + case CMSG_EQUIPMENT_SET_SAVE: // 0 1.5 + case CMSG_DELETEEQUIPMENT_SET: // 0 1.5 + case CMSG_DISMISS_CRITTER: // 0 1.5 + case CMSG_REPOP_REQUEST: // 0 1.5 + case CMSG_GROUP_INVITE: // 0 1.5 + case CMSG_GROUP_DECLINE: // 0 1.5 + case CMSG_GROUP_ACCEPT: // 0 1.5 + case CMSG_GROUP_UNINVITE_GUID: // 0 1.5 + case CMSG_GROUP_UNINVITE: // 0 1.5 + case CMSG_GROUP_DISBAND: // 0 1.5 + case CMSG_BATTLEMASTER_JOIN_ARENA: // 0 1.5 + case CMSG_LEAVE_BATTLEFIELD: // 0 1.5 + case MSG_GUILD_BANK_LOG_QUERY: // 0 2 + case CMSG_LOGOUT_CANCEL: // 0 2 + case CMSG_REALM_SPLIT: // 0 2 + case CMSG_ALTER_APPEARANCE: // 0 2 + case CMSG_QUEST_CONFIRM_ACCEPT: // 0 2 + case MSG_GUILD_EVENT_LOG_QUERY: // 0 2.5 + case CMSG_READY_FOR_ACCOUNT_DATA_TIMES: // 0 2.5 + case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY: // 0 2.5 + case CMSG_BEGIN_TRADE: // 0 2.5 + case CMSG_INITIATE_TRADE: // 0 3 + case CMSG_MESSAGECHAT: // 0 3.5 + case CMSG_INSPECT: // 0 3.5 + case CMSG_AREA_SPIRIT_HEALER_QUERY: // not profiled { - maxPacketCounterAllowed = 5000; + // "0" is a magic number meaning there's no limit for the opcode. + // All the opcodes above must cause little CPU usage and no sync/async database queries at all + maxPacketCounterAllowed = 0; break; } - case CMSG_ATTACKSTOP: - case CMSG_GUILD_QUERY: - case CMSG_ARENA_TEAM_QUERY: - case CMSG_TAXINODE_STATUS_QUERY: - case CMSG_TAXIQUERYAVAILABLENODES: - case CMSG_QUESTGIVER_QUERY_QUEST: - case CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY: - case CMSG_QUERY_QUESTS_COMPLETED: - case CMSG_QUEST_POI_QUERY: - case CMSG_QUERY_TIME: - case CMSG_PAGE_TEXT_QUERY: - case CMSG_PETITION_QUERY: - case CMSG_QUERY_INSPECT_ACHIEVEMENTS: - case CMSG_AREA_SPIRIT_HEALER_QUERY: - case CMSG_CORPSE_MAP_POSITION_QUERY: - case CMSG_MOVE_TIME_SKIPPED: - case CMSG_GUILD_BANK_QUERY_TAB: - case MSG_GUILD_BANK_LOG_QUERY: - case MSG_QUERY_GUILD_BANK_TEXT: - case MSG_CORPSE_QUERY: - case MSG_QUERY_NEXT_MAIL_TIME: - case MSG_GUILD_EVENT_LOG_QUERY: - case MSG_MOVE_SET_FACING: - case CMSG_INSPECT: + case CMSG_QUESTGIVER_ACCEPT_QUEST: // 0 4 + case CMSG_QUESTLOG_REMOVE_QUEST: // 0 4 + case CMSG_QUESTGIVER_CHOOSE_REWARD: // 0 4 + case CMSG_CONTACT_LIST: // 0 5 + case CMSG_LEARN_PREVIEW_TALENTS: // 0 6 + case CMSG_AUTOBANK_ITEM: // 0 6 + case CMSG_AUTOSTORE_BANK_ITEM: // 0 6 + case CMSG_WHO: // 0 7 + case CMSG_PLAYER_VEHICLE_ENTER: // 0 8 + case CMSG_LEARN_PREVIEW_TALENTS_PET: // not profiled + case MSG_MOVE_HEARTBEAT: { - maxPacketCounterAllowed = 500; + maxPacketCounterAllowed = 200; break; } - case CMSG_REQUEST_PARTY_MEMBER_STATS: - case CMSG_WHO: - case CMSG_SETSHEATHED: - case CMSG_CONTACT_LIST: - case CMSG_GUILD_SET_PUBLIC_NOTE: - case CMSG_GUILD_SET_OFFICER_NOTE: + case CMSG_GUILD_SET_PUBLIC_NOTE: // 1 2 1 async db query + case CMSG_GUILD_SET_OFFICER_NOTE: // 1 2 1 async db query + case CMSG_SET_CONTACT_NOTES: // 1 2.5 1 async db query + case CMSG_CALENDAR_GET_CALENDAR: // 0 1.5 medium upload bandwidth usage + case CMSG_GUILD_BANK_QUERY_TAB: // 0 3.5 medium upload bandwidth usage + case CMSG_QUERY_INSPECT_ACHIEVEMENTS: // 0 13 high upload bandwidth usage { maxPacketCounterAllowed = 50; break; } - case CMSG_SPELLCLICK: - case CMSG_GAMEOBJ_USE: - case CMSG_GAMEOBJ_REPORT_USE: - case MSG_RAID_TARGET_UPDATE: - case CMSG_QUESTGIVER_COMPLETE_QUEST: - case CMSG_PLAYER_VEHICLE_ENTER: - case CMSG_PETITION_SIGN: + case CMSG_QUEST_POI_QUERY: // 0 25 very high upload bandwidth usage + { + maxPacketCounterAllowed = MAX_QUEST_LOG_SIZE; + break; + } + + case CMSG_GM_REPORT_LAG: // 1 3 1 async db query + case CMSG_SPELLCLICK: // not profiled + case CMSG_GAMEOBJ_USE: // not profiled + case CMSG_GAMEOBJ_REPORT_USE: // not profiled + case CMSG_REMOVE_GLYPH: // not profiled { maxPacketCounterAllowed = 20; break; } - case CMSG_PLAYER_LOGOUT: - case CMSG_LOGOUT_REQUEST: - case CMSG_LOGOUT_CANCEL: - case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: - case CMSG_REQUEST_VEHICLE_PREV_SEAT: - case CMSG_REQUEST_VEHICLE_NEXT_SEAT: - case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: - case CMSG_TOGGLE_PVP: - case CMSG_ADD_FRIEND: - case CMSG_DEL_FRIEND: - case CMSG_SET_CONTACT_NOTES: - case CMSG_RESET_INSTANCES: - case CMSG_HEARTH_AND_RESURRECT: - case CMSG_CHAR_CREATE: - case CMSG_READY_FOR_ACCOUNT_DATA_TIMES: - case CMSG_CHAR_ENUM: - case CMSG_REALM_SPLIT: - case CMSG_CHAR_DELETE: - case CMSG_PLAYER_LOGIN: - case CMSG_PET_ABANDON: - case CMSG_PET_RENAME: - case CMSG_CHAR_RENAME: - case CMSG_CHAR_CUSTOMIZE: - case CMSG_CHAR_RACE_CHANGE: - case CMSG_CHAR_FACTION_CHANGE: - case CMSG_GMTICKET_CREATE: - case CMSG_GMTICKET_UPDATETEXT: - case CMSG_GMTICKET_DELETETICKET: - case CMSG_GMSURVEY_SUBMIT: - case CMSG_GM_REPORT_LAG: - case CMSG_BUG: - case CMSG_GMRESPONSE_RESOLVE: - case CMSG_ACTIVATETAXIEXPRESS: - case CMSG_ACTIVATETAXI: - case CMSG_SELF_RES: - case CMSG_INITIATE_TRADE: - case CMSG_BEGIN_TRADE: - case CMSG_UNLEARN_SKILL: - case CMSG_DISMISS_CONTROLLED_VEHICLE: - case CMSG_REQUEST_VEHICLE_EXIT: - case CMSG_LEARN_PREVIEW_TALENTS: - case CMSG_LEARN_PREVIEW_TALENTS_PET: - case CMSG_CONTROLLER_EJECT_PASSENGER: - case CMSG_EQUIPMENT_SET_SAVE: - case CMSG_DELETEEQUIPMENT_SET: - case CMSG_REMOVE_GLYPH: - case CMSG_ALTER_APPEARANCE: - case CMSG_QUESTGIVER_ACCEPT_QUEST: - case CMSG_QUESTGIVER_CHOOSE_REWARD: - case CMSG_QUESTGIVER_REQUEST_REWARD: - case CMSG_QUESTGIVER_CANCEL: - case CMSG_QUESTLOG_REMOVE_QUEST: - case CMSG_QUEST_CONFIRM_ACCEPT: - case CMSG_DISMISS_CRITTER: - case CMSG_REPOP_REQUEST: - case CMSG_PETITION_BUY: - case CMSG_TURN_IN_PETITION: - case CMSG_COMPLETE_CINEMATIC: - case CMSG_ITEM_REFUND: - case CMSG_SOCKET_GEMS: - case CMSG_WRAP_ITEM: - case CMSG_BUY_BANK_SLOT: - case CMSG_GROUP_ACCEPT: - case CMSG_GROUP_DECLINE: - case CMSG_GROUP_UNINVITE_GUID: - case CMSG_GROUP_UNINVITE: - case CMSG_GROUP_SET_LEADER: - case CMSG_GROUP_DISBAND: - case CMSG_GROUP_RAID_CONVERT: - case CMSG_GROUP_CHANGE_SUB_GROUP: - case CMSG_GROUP_ASSISTANT_LEADER: - case CMSG_OPT_OUT_OF_LOOT: - case CMSG_BATTLEMASTER_JOIN_ARENA: - case CMSG_LEAVE_BATTLEFIELD: - case CMSG_REPORT_PVP_AFK: - case CMSG_DUEL_ACCEPTED: - case CMSG_DUEL_CANCELLED: - case CMSG_CALENDAR_GET_CALENDAR: - case CMSG_CALENDAR_ADD_EVENT: - case CMSG_CALENDAR_UPDATE_EVENT: - case CMSG_CALENDAR_REMOVE_EVENT: - case CMSG_CALENDAR_COPY_EVENT: - case CMSG_CALENDAR_EVENT_INVITE: - case CMSG_CALENDAR_EVENT_SIGNUP: - case CMSG_CALENDAR_EVENT_RSVP: - case CMSG_CALENDAR_EVENT_REMOVE_INVITE: - case CMSG_CALENDAR_EVENT_MODERATOR_STATUS: - case CMSG_CALENDAR_COMPLAIN: - case CMSG_ARENA_TEAM_INVITE: - case CMSG_ARENA_TEAM_ACCEPT: - case CMSG_ARENA_TEAM_DECLINE: - case CMSG_ARENA_TEAM_LEAVE: - case CMSG_ARENA_TEAM_DISBAND: - case CMSG_ARENA_TEAM_REMOVE: - case CMSG_ARENA_TEAM_LEADER: - case CMSG_LOOT_METHOD: - case CMSG_GUILD_INVITE: - case CMSG_GUILD_ACCEPT: - case CMSG_GUILD_DECLINE: - case CMSG_GUILD_LEAVE: - case CMSG_GUILD_DISBAND: - case CMSG_GUILD_LEADER: - case CMSG_GUILD_MOTD: - case CMSG_GUILD_RANK: - case CMSG_GUILD_ADD_RANK: - case CMSG_GUILD_DEL_RANK: - case CMSG_GUILD_INFO_TEXT: - case CMSG_GUILD_BANK_DEPOSIT_MONEY: - case CMSG_GUILD_BANK_WITHDRAW_MONEY: - case CMSG_GUILD_BANK_BUY_TAB: - case CMSG_GUILD_BANK_UPDATE_TAB: - case CMSG_SET_GUILD_BANK_TEXT: - case MSG_SAVE_GUILD_EMBLEM: - case MSG_PETITION_RENAME: - case MSG_PETITION_DECLINE: - case MSG_TALENT_WIPE_CONFIRM: - case MSG_SET_DUNGEON_DIFFICULTY: - case MSG_SET_RAID_DIFFICULTY: - case MSG_RANDOM_ROLL: - case MSG_PARTY_ASSIGNMENT: - case MSG_RAID_READY_CHECK: + case CMSG_PETITION_SIGN: // 9 4 2 sync 1 async db queries + case CMSG_TURN_IN_PETITION: // 8 5.5 2 sync db query + case CMSG_GROUP_CHANGE_SUB_GROUP: // 6 5 1 sync 1 async db queries + case CMSG_PETITION_QUERY: // 4 3.5 1 sync db query + case CMSG_CHAR_RACE_CHANGE: // 5 4 1 sync db query + case CMSG_CHAR_CUSTOMIZE: // 5 5 1 sync db query + case CMSG_CHAR_FACTION_CHANGE: // 5 5 1 sync db query + case CMSG_CHAR_DELETE: // 4 4 1 sync db query + case CMSG_DEL_FRIEND: // 7 5 1 async db query + case CMSG_ADD_FRIEND: // 6 4 1 async db query + case CMSG_CHAR_RENAME: // 5 3 1 async db query + case CMSG_GMSURVEY_SUBMIT: // 2 3 1 async db query + case CMSG_BUG: // 1 1 1 async db query + case CMSG_GROUP_SET_LEADER: // 1 2 1 async db query + case CMSG_GROUP_RAID_CONVERT: // 1 5 1 async db query + case CMSG_GROUP_ASSISTANT_LEADER: // 1 2 1 async db query + case CMSG_CALENDAR_ADD_EVENT: // 21 10 2 async db query + case CMSG_PETITION_BUY: // not profiled 1 sync 1 async db queries + case CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE: // not profiled + case CMSG_REQUEST_VEHICLE_PREV_SEAT: // not profiled + case CMSG_REQUEST_VEHICLE_NEXT_SEAT: // not profiled + case CMSG_REQUEST_VEHICLE_SWITCH_SEAT: // not profiled + case CMSG_DISMISS_CONTROLLED_VEHICLE: // not profiled + case CMSG_REQUEST_VEHICLE_EXIT: // not profiled + case CMSG_CONTROLLER_EJECT_PASSENGER: // not profiled + case CMSG_ITEM_REFUND: // not profiled + case CMSG_SOCKET_GEMS: // not profiled + case CMSG_WRAP_ITEM: // not profiled + case CMSG_REPORT_PVP_AFK: // not profiled { - maxPacketCounterAllowed = 3; + maxPacketCounterAllowed = 10; break; } - case CMSG_SET_ACTION_BUTTON: + case CMSG_CHAR_CREATE: // 7 5 3 async db queries + case CMSG_CHAR_ENUM: // 22 3 2 async db queries + case CMSG_GMTICKET_CREATE: // 1 25 1 async db query + case CMSG_GMTICKET_UPDATETEXT: // 0 15 1 async db query + case CMSG_GMTICKET_DELETETICKET: // 1 25 1 async db query + case CMSG_GMRESPONSE_RESOLVE: // 1 25 1 async db query + case CMSG_CALENDAR_UPDATE_EVENT: // not profiled + case CMSG_CALENDAR_REMOVE_EVENT: // not profiled + case CMSG_CALENDAR_COPY_EVENT: // not profiled + case CMSG_CALENDAR_EVENT_INVITE: // not profiled + case CMSG_CALENDAR_EVENT_SIGNUP: // not profiled + case CMSG_CALENDAR_EVENT_RSVP: // not profiled + case CMSG_CALENDAR_EVENT_REMOVE_INVITE: // not profiled + case CMSG_CALENDAR_EVENT_MODERATOR_STATUS: // not profiled + case CMSG_ARENA_TEAM_INVITE: // not profiled + case CMSG_ARENA_TEAM_ACCEPT: // not profiled + case CMSG_ARENA_TEAM_DECLINE: // not profiled + case CMSG_ARENA_TEAM_LEAVE: // not profiled + case CMSG_ARENA_TEAM_DISBAND: // not profiled + case CMSG_ARENA_TEAM_REMOVE: // not profiled + case CMSG_ARENA_TEAM_LEADER: // not profiled + case CMSG_LOOT_METHOD: // not profiled + case CMSG_GUILD_INVITE: // not profiled + case CMSG_GUILD_ACCEPT: // not profiled + case CMSG_GUILD_DECLINE: // not profiled + case CMSG_GUILD_LEAVE: // not profiled + case CMSG_GUILD_DISBAND: // not profiled + case CMSG_GUILD_LEADER: // not profiled + case CMSG_GUILD_MOTD: // not profiled + case CMSG_GUILD_RANK: // not profiled + case CMSG_GUILD_ADD_RANK: // not profiled + case CMSG_GUILD_DEL_RANK: // not profiled + case CMSG_GUILD_INFO_TEXT: // not profiled + case CMSG_GUILD_BANK_DEPOSIT_MONEY: // not profiled + case CMSG_GUILD_BANK_WITHDRAW_MONEY: // not profiled + case CMSG_GUILD_BANK_BUY_TAB: // not profiled + case CMSG_GUILD_BANK_UPDATE_TAB: // not profiled + case CMSG_SET_GUILD_BANK_TEXT: // not profiled + case MSG_SAVE_GUILD_EMBLEM: // not profiled + case MSG_PETITION_RENAME: // not profiled + case MSG_PETITION_DECLINE: // not profiled + case MSG_TALENT_WIPE_CONFIRM: // not profiled + case MSG_SET_DUNGEON_DIFFICULTY: // not profiled + case MSG_SET_RAID_DIFFICULTY: // not profiled + case MSG_RANDOM_ROLL: // not profiled + case MSG_PARTY_ASSIGNMENT: // not profiled + case MSG_RAID_READY_CHECK: // not profiled { - maxPacketCounterAllowed = MAX_ACTION_BUTTONS; + maxPacketCounterAllowed = 3; break; } - case CMSG_ITEM_REFUND_INFO: + case CMSG_ITEM_REFUND_INFO: // not profiled { maxPacketCounterAllowed = PLAYER_SLOTS_COUNT; break; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 2f5f17952db..61d2fa6d106 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -937,7 +937,6 @@ class WorldSession public: DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) { } bool EvaluateOpcode(WorldPacket& p, time_t time) const; - void AllowOpcode(uint16 opcode, bool allow) { _isOpcodeAllowed[opcode] = allow; } protected: enum Policy { @@ -946,22 +945,11 @@ class WorldSession POLICY_BAN, }; - bool IsOpcodeAllowed(uint16 opcode) const - { - OpcodeStatusMap::const_iterator itr = _isOpcodeAllowed.find(opcode); - if (itr == _isOpcodeAllowed.end()) - return true; // No presence in the map indicates this is the first time the opcode was sent this session, so allow - - return itr->second; - } - uint32 GetMaxPacketCounterAllowed(uint16 opcode) const; WorldSession* Session; private: - typedef std::unordered_map OpcodeStatusMap; - OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes Policy _policy; typedef std::unordered_map PacketThrottlingMap; // mark this member as "mutable" so it can be modified even in const functions -- cgit v1.2.3 From ae46affe4e8d69219a28df7b5557a323a2b1f248 Mon Sep 17 00:00:00 2001 From: phoenixfight Date: Sat, 10 May 2014 21:35:05 +0800 Subject: [core/database]Repair fishing spell result fish escape edit fish junk sql formart Optimized code, remove some useless brackets fix default fish result ,just like Off the coast of Storm Peaks. cleaned the sql part thx Kinzcool fix todo now --- .../world/2014_05_10_fish_junk_loot_template.sql | 20 +++++++++++ src/server/game/Entities/GameObject/GameObject.cpp | 39 ++++++++++++++++++---- src/server/game/Entities/GameObject/GameObject.h | 1 + src/server/game/Entities/Player/Player.cpp | 5 ++- src/server/game/Loot/LootMgr.h | 3 +- src/server/game/Miscellaneous/SharedDefines.h | 3 +- 6 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 sql/updates/world/2014_05_10_fish_junk_loot_template.sql (limited to 'src') diff --git a/sql/updates/world/2014_05_10_fish_junk_loot_template.sql b/sql/updates/world/2014_05_10_fish_junk_loot_template.sql new file mode 100644 index 00000000000..bbbe42aa695 --- /dev/null +++ b/sql/updates/world/2014_05_10_fish_junk_loot_template.sql @@ -0,0 +1,20 @@ +SET @FISH_JUNK_GROUP := 11799; +SET @FISH_JUNK_LOOTMODE := 32768; + +DELETE FROM fishing_loot_template WHERE `item`=@FISH_JUNK_GROUP; +INSERT INTO fishing_loot_template (`entry`, `item`, `ChanceOrQuestChance`, `lootmode`, `groupid`, `mincountOrRef`, `maxcount`) VALUES +(1, @FISH_JUNK_GROUP, 100, @FISH_JUNK_LOOTMODE, 1, -@FISH_JUNK_GROUP, 1); + +DELETE FROM reference_loot_template WHERE `entry`=@FISH_JUNK_GROUP; +INSERT INTO reference_loot_template (`entry`, `item`, `ChanceOrQuestChance`, `lootmode`, `groupid`, `mincountOrRef`, `maxcount`) VALUES +(@FISH_JUNK_GROUP, 45190, 15, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Driftwood] +(@FISH_JUNK_GROUP, 45191, 2, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Water Snail] +(@FISH_JUNK_GROUP, 45194, 15, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Tangled Fishing Line] +(@FISH_JUNK_GROUP, 45195, 5, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Empty Rum Bottle] +(@FISH_JUNK_GROUP, 45196, 15, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Tattered Cloth] +(@FISH_JUNK_GROUP, 45197, 5, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Tree Branch] +(@FISH_JUNK_GROUP, 45198, 15, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Weeds] +(@FISH_JUNK_GROUP, 45199, 5, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Old Boot] +(@FISH_JUNK_GROUP, 45200, 15, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Sickly Fish] +(@FISH_JUNK_GROUP, 45201, 3, @FISH_JUNK_LOOTMODE, 1, 1, 1), -- [Rock] +(@FISH_JUNK_GROUP, 45202, 5, @FISH_JUNK_LOOTMODE, 1, 1, 1); -- [Water Snail] diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 8051c757bf2..868aa87c26f 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -694,12 +694,39 @@ void GameObject::getFishLoot(Loot* fishloot, Player* loot_owner) fishloot->clear(); uint32 zone, subzone; + uint32 defaultzone = 1; GetZoneAndAreaId(zone, subzone); // if subzone loot exist use it - if (!fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true)) - // else use zone loot (must exist in like case) - fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true); + fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true); + if (fishloot->empty()) //use this becase if zone or subzone has set LOOT_MODE_JUNK_FISH,Even if no normal drop, fishloot->FillLoot return true. it wrong. + { + //subzone no result,use zone loot + fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true); + //use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks. + if (fishloot->empty()) + fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true); + } +} + +void GameObject::getFishLootJunk(Loot* fishloot, Player* loot_owner) +{ + fishloot->clear(); + + uint32 zone, subzone; + uint32 defaultzone = 1; + GetZoneAndAreaId(zone, subzone); + + // if subzone loot exist use it + fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH); + if (fishloot->empty()) //use this becase if zone or subzone has normal mask drop, then fishloot->FillLoot return true. + { + //use zone loot + fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH); + if (fishloot->empty()) + //use zone 1 as default + fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH); + } } void GameObject::SaveToDB() @@ -1413,10 +1440,8 @@ void GameObject::Use(Unit* user) else player->SendLoot(GetGUID(), LOOT_FISHING); } - /// @todo else: junk - else - m_respawnTime = time(NULL); - + else // else: junk + player->SendLoot(GetGUID(), LOOT_FISHING_JUNK); break; } case GO_JUST_DEACTIVATED: // nothing to do, will be deleted at next update diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index a99c5db93aa..7aa3a01016b 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -713,6 +713,7 @@ class GameObject : public WorldObject, public GridObject, public Map void Refresh(); void Delete(); void getFishLoot(Loot* loot, Player* loot_owner); + void getFishLootJunk(Loot* loot, Player* loot_owner); GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e7d14d68377..354bc7f2b21 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8756,7 +8756,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) // not check distance for GO in case owned GO (fishing bobber case, for example) // And permit out of range GO with no owner in case fishing hole - if (!go || (loot_type != LOOT_FISHINGHOLE && (loot_type != LOOT_FISHING || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this, INTERACTION_DISTANCE)) || (loot_type == LOOT_CORPSE && go->GetRespawnTime() && go->isSpawnedByDefault())) + if (!go || (loot_type != LOOT_FISHINGHOLE && ((loot_type != LOOT_FISHING && loot_type != LOOT_FISHING_JUNK) || go->GetOwnerGUID() != GetGUID()) && !go->IsWithinDistInMap(this, INTERACTION_DISTANCE)) || (loot_type == LOOT_CORPSE && go->GetRespawnTime() && go->isSpawnedByDefault())) { SendLootRelease(guid); return; @@ -8794,6 +8794,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type) if (loot_type == LOOT_FISHING) go->getFishLoot(loot, this); + else if (loot_type == LOOT_FISHING_JUNK) + go->getFishLootJunk(loot, this); if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules) { @@ -9036,6 +9038,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) { case LOOT_INSIGNIA: loot_type = LOOT_SKINNING; break; case LOOT_FISHINGHOLE: loot_type = LOOT_FISHING; break; + case LOOT_FISHING_JUNK: loot_type = LOOT_FISHING; break; default: break; } diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index ed0f3b9717b..9be745e622d 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -86,7 +86,8 @@ enum LootType LOOT_MILLING = 8, LOOT_FISHINGHOLE = 20, // unsupported by client, sending LOOT_FISHING instead - LOOT_INSIGNIA = 21 // unsupported by client, sending LOOT_CORPSE instead + LOOT_INSIGNIA = 21, // unsupported by client, sending LOOT_CORPSE instead + LOOT_FISHING_JUNK = 22 // unsupported by client, sending LOOT_FISHING instead }; // type of Loot Item in Loot View diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index b52e640afc7..6b42b5bc211 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -41,7 +41,8 @@ enum LootModes LOOT_MODE_HARD_MODE_1 = 0x2, LOOT_MODE_HARD_MODE_2 = 0x4, LOOT_MODE_HARD_MODE_3 = 0x8, - LOOT_MODE_HARD_MODE_4 = 0x10 + LOOT_MODE_HARD_MODE_4 = 0x10, + LOOT_MODE_JUNK_FISH = 0x8000 }; enum Expansions -- cgit v1.2.3 From 48f426abc545a209a4f3038bd4a4fc820f953d7f Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Tue, 10 Jun 2014 20:51:28 +0100 Subject: Core/Auras: Correct a typo that caused bad stacking of SPELL_AURA_MOD_MELEE_HASTE --- src/server/game/Spells/Auras/SpellAuraEffects.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 97a2db796d5..8fd37b86307 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -4157,8 +4157,8 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod if (spellGroupVal) { - target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), !apply); - target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), !apply); + target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply); } target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); -- cgit v1.2.3 From f19c6f4091406a42fd75f2cef73a2189cf856ba8 Mon Sep 17 00:00:00 2001 From: jackpoz Date: Tue, 10 Jun 2014 22:50:24 +0200 Subject: Core/PetAI: Fix memory leak Fix memory leak added in e7f0808d467210c2e0ca455cf810e52700518849 Valgrind log: 395,712 (390,216 direct, 5,496 indirect) bytes in 229 blocks are definitely lost in loss record 65 of 67 at operator new(unsigned long) (vg_replace_malloc.c:320) by PetAI::UpdateAI(unsigned int) (PetAI.cpp:167) by Creature::Update(unsigned int) (Creature.cpp:541) by TempSummon::Update(unsigned int) (TemporarySummon.cpp:47) --- src/server/game/AI/CoreAI/PetAI.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 7c640f9a66d..8032568434f 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -183,7 +183,11 @@ void PetAI::UpdateAI(uint32 diff) } if (spellInfo->HasEffect(SPELL_EFFECT_JUMP_DEST)) + { + if (!spellUsed) + delete spell; continue; // Pets must only jump to target + } // No enemy, check friendly if (!spellUsed) -- cgit v1.2.3 From 2ba05406ce0632d30498b05981a02f2b7d4f75da Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 11 Jun 2014 18:21:00 +0200 Subject: Fixed typo, spotted by @Gooyeth --- src/server/game/Server/WorldSession.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 3ac31da3eb1..4d51ccb91c9 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1267,8 +1267,6 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter); } - return true; - switch (_policy) { case POLICY_LOG: -- cgit v1.2.3 From 06962b16f147275cf3ef23caf2f41ce0d25c25ef Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 11 Jun 2014 19:28:25 +0200 Subject: Core/PacketIO: Fixed logic in DosProtection::EvaluateOpcode --- src/server/game/Server/WorldSession.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 4d51ccb91c9..9f8b3785e92 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1260,12 +1260,12 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co } // Check if player is flooding some packets - if (++packetCounter.amountCounter > maxPacketCounterAllowed) - { - TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)", - Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(), - opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter); - } + if (++packetCounter.amountCounter <= maxPacketCounterAllowed) + return true; + + TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)", + Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(), + opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter); switch (_policy) { -- cgit v1.2.3 From 52c0fc96bb4a8a62218bd383f360c0e1350ef62a Mon Sep 17 00:00:00 2001 From: Unholychick Date: Wed, 11 Jun 2014 19:59:50 +0200 Subject: Move pestilence to spellscripts Fixes crash and warnings introduced in d4bbc26261d7ce1e01292470f77390ab3c2f5e98 Fixes a bug that allowed dks to spread diseases using another dks diseases Closes: https://github.com/TrinityCore/TrinityCore/issues/12245 --- .../2014_06_11_01_world_spell_script_names.sql | 3 + src/server/game/Spells/Auras/SpellAuraEffects.cpp | 3 +- src/server/game/Spells/SpellEffects.cpp | 45 ----------- src/server/scripts/Spells/spell_dk.cpp | 89 ++++++++++++++++++++++ 4 files changed, 94 insertions(+), 46 deletions(-) create mode 100644 sql/updates/world/2014_06_11_01_world_spell_script_names.sql (limited to 'src') diff --git a/sql/updates/world/2014_06_11_01_world_spell_script_names.sql b/sql/updates/world/2014_06_11_01_world_spell_script_names.sql new file mode 100644 index 00000000000..433f1cf8b09 --- /dev/null +++ b/sql/updates/world/2014_06_11_01_world_spell_script_names.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `spell_script_names` WHERE `spell_id` = 50842; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (50842, 'spell_dk_pestilence'); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index a0883c895d3..8b9d581cd10 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -379,8 +379,9 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster): m_base(base), m_spellInfo(base->GetSpellInfo()), m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints), +m_damage(0), m_critChance(0.0f), m_donePct(1.0f), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), -m_canBeRecalculated(true), m_damage(0), m_critChance(0.0f), m_donePct(1.0f), m_isPeriodic(false) +m_canBeRecalculated(true), m_isPeriodic(false) { CalculatePeriodic(caster, true, false); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 48c73cf39ca..1b1730c9aaa 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4049,51 +4049,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) } break; } - case SPELLFAMILY_DEATHKNIGHT: - { - // Pestilence - if (m_spellInfo->SpellFamilyFlags[1]&0x10000) - { - // Get diseases on target of spell - if (m_targets.GetUnitTarget() && // Glyph of Disease - cast on unit target too to refresh aura - (m_targets.GetUnitTarget() != unitTarget || m_caster->HasAura(63334))) - { - // And spread them on target - // Blood Plague - if (m_targets.GetUnitTarget()->HasAura(55078)) - { - AuraEffect* aurEffOld = m_targets.GetUnitTarget()->GetAura(55078)->GetEffect(0); - float donePct = aurEffOld->GetDonePct(); - float critChance = aurEffOld->GetCritChance(); - - m_caster->CastSpell(unitTarget, 55078, true); - - if (unitTarget->HasAura(55078)) - if (AuraEffect* aurEffNew = unitTarget->GetAura(55078)->GetEffect(0)) - { - aurEffNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9. - aurEffNew->SetDonePct(donePct); - aurEffNew->SetDamage(m_caster->SpellDamageBonusDone(unitTarget, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); - } - } - // Frost Fever - if (m_targets.GetUnitTarget()->HasAura(55095)) - { - float donePct = m_targets.GetUnitTarget()->GetAura(55095)->GetEffect(0)->GetDonePct(); - - m_caster->CastSpell(unitTarget, 55095, true); - - if (unitTarget->HasAura(55095)) - if (AuraEffect* aurEffNew = unitTarget->GetAura(55095)->GetEffect(0)) - { - aurEffNew->SetDonePct(donePct); - aurEffNew->SetDamage(m_caster->SpellDamageBonusDone(unitTarget, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); - } - } - } - } - break; - } } // normal DB scripted effect diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 5ae0e1601c5..cc32e773b60 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -39,9 +39,11 @@ enum DeathKnightSpells SPELL_DK_DEATH_COIL_DAMAGE = 47632, SPELL_DK_DEATH_COIL_HEAL = 47633, SPELL_DK_DEATH_STRIKE_HEAL = 45470, + SPELL_DK_FROST_FEVER = 55095, SPELL_DK_FROST_PRESENCE = 48263, SPELL_DK_FROST_PRESENCE_TRIGGERED = 61261, SPELL_DK_GHOUL_EXPLODE = 47496, + SPELL_DK_GLYPH_OF_DISEASE = 63334, SPELL_DK_GLYPH_OF_ICEBOUND_FORTITUDE = 58625, SPELL_DK_IMPROVED_BLOOD_PRESENCE_R1 = 50365, SPELL_DK_IMPROVED_FROST_PRESENCE_R1 = 50384, @@ -51,6 +53,7 @@ enum DeathKnightSpells SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962, SPELL_DK_ITEM_T8_MELEE_4P_BONUS = 64736, SPELL_DK_MASTER_OF_GHOULS = 52143, + SPELL_DK_BLOOD_PLAGUE = 55078, SPELL_DK_RAISE_DEAD_USE_REAGENT = 48289, SPELL_DK_RUNIC_POWER_ENERGIZE = 49088, SPELL_DK_SCENT_OF_BLOOD = 50422, @@ -933,6 +936,91 @@ class spell_dk_improved_unholy_presence : public SpellScriptLoader } }; +// ID - 50842 Pestilence +class spell_dk_pestilence : public SpellScriptLoader +{ + public: + spell_dk_pestilence() : SpellScriptLoader("spell_dk_pestilence") { } + + class spell_dk_pestilence_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dk_pestilence_SpellScript); + + bool Validate(SpellInfo const* spellInfo) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_GLYPH_OF_DISEASE) + || !sSpellMgr->GetSpellInfo(SPELL_DK_BLOOD_PLAGUE) + || !sSpellMgr->GetSpellInfo(SPELL_DK_FROST_FEVER)) + return false; + return true; + } + + void OnHit(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + Unit* hitUnit = GetHitUnit(); + Unit* victim = GetExplTargetUnit(); + + if (!victim) + return; + + if (victim != hitUnit || caster->HasAura(SPELL_DK_GLYPH_OF_DISEASE)) + { + if (Aura* aurOld = victim->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID())) // Check Blood Plague application on victim. + { + if (AuraEffect* aurEffOld = aurOld->GetEffect(EFFECT_0)) + { + float donePct = aurEffOld->GetDonePct(); + float critChance = aurEffOld->GetCritChance(); + + caster->CastSpell(hitUnit, SPELL_DK_BLOOD_PLAGUE, true); // Spread the disease to hitUnit. + + if (Aura* aurNew = hitUnit->GetAura(SPELL_DK_BLOOD_PLAGUE, caster->GetGUID())) // Check Blood Plague application on hitUnit. + { + if (AuraEffect* aurEffNew = aurNew->GetEffect(EFFECT_0)) + { + aurEffNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9. + aurEffNew->SetDonePct(donePct); + aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), NULL), DOT) * donePct); + } + } + } + } + + if (Aura* aurOld = victim->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID())) // Check Frost Fever application on victim. + { + if (AuraEffect* aurEffOld = aurOld->GetEffect(EFFECT_0)) + { + float donePct = aurEffOld->GetDonePct(); + + caster->CastSpell(hitUnit, SPELL_DK_FROST_FEVER, true); // Spread the disease to hitUnit. + + if (Aura* aurNew = hitUnit->GetAura(SPELL_DK_FROST_FEVER, caster->GetGUID())) // Check Frost Fever application on hitUnit. + { + if (AuraEffect* aurEffNew = aurNew->GetEffect(EFFECT_0)) + { + aurEffNew->SetDonePct(donePct); + aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), NULL), DOT) * donePct); + } + } + } + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_dk_pestilence_SpellScript::OnHit, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_dk_pestilence_SpellScript(); + } +}; + + // 48266 - Blood Presence // 48263 - Frost Presence // 48265 - Unholy Presence @@ -1467,6 +1555,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_improved_blood_presence(); new spell_dk_improved_frost_presence(); new spell_dk_improved_unholy_presence(); + new spell_dk_pestilence(); new spell_dk_presence(); new spell_dk_raise_dead(); new spell_dk_rune_tap_party(); -- cgit v1.2.3 From 26a7916faf3d22d6de99d2f3a0bd49a7444021ac Mon Sep 17 00:00:00 2001 From: jackpoz Date: Wed, 11 Jun 2014 21:26:21 +0200 Subject: Core/Misc: Fix gcc build --- src/server/scripts/Spells/spell_dk.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index cc32e773b60..245ec7e88cf 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -946,7 +946,7 @@ class spell_dk_pestilence : public SpellScriptLoader { PrepareSpellScript(spell_dk_pestilence_SpellScript); - bool Validate(SpellInfo const* spellInfo) override + bool Validate(SpellInfo const* /*spellInfo*/) override { if (!sSpellMgr->GetSpellInfo(SPELL_DK_GLYPH_OF_DISEASE) || !sSpellMgr->GetSpellInfo(SPELL_DK_BLOOD_PLAGUE) @@ -981,7 +981,7 @@ class spell_dk_pestilence : public SpellScriptLoader { aurEffNew->SetCritChance(critChance); // Blood Plague can crit if caster has T9. aurEffNew->SetDonePct(donePct); - aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), NULL), DOT) * donePct); + aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); } } } @@ -1000,7 +1000,7 @@ class spell_dk_pestilence : public SpellScriptLoader if (AuraEffect* aurEffNew = aurNew->GetEffect(EFFECT_0)) { aurEffNew->SetDonePct(donePct); - aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), NULL), DOT) * donePct); + aurEffNew->SetDamage(caster->SpellDamageBonusDone(hitUnit, aurEffNew->GetSpellInfo(), std::max(aurEffNew->GetAmount(), 0), DOT) * donePct); } } } -- cgit v1.2.3 From e55555ed8c17e62822768050446bdd448ad74e20 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 11 Jun 2014 23:08:32 +0200 Subject: Fixed windows nopch build --- src/server/shared/Utilities/Util.cpp | 9 +++++++++ src/server/shared/Utilities/Util.h | 9 +-------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp index ffef61557fc..28bbe831a69 100644 --- a/src/server/shared/Utilities/Util.cpp +++ b/src/server/shared/Utilities/Util.cpp @@ -547,3 +547,12 @@ std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse return ss.str(); } + +uint32 EventMap::GetTimeUntilEvent(uint32 eventId) const +{ + for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) + if (eventId == (itr->second & 0x0000FFFF)) + return itr->first - _time; + + return std::numeric_limits::max(); +} diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index d6ead607c55..648edf39abe 100644 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -866,14 +866,7 @@ class EventMap * @param Id of the event. * @return Time of next event. */ - uint32 GetTimeUntilEvent(uint32 eventId) const - { - for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) - if (eventId == (itr->second & 0x0000FFFF)) - return itr->first - _time; - - return std::numeric_limits::max(); - } + uint32 GetTimeUntilEvent(uint32 eventId) const; private: /** -- cgit v1.2.3 From 4992c0290b2b43c3d4c744833ca9ba6f74af85ad Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 12 Jun 2014 20:03:52 +0100 Subject: Core/Spells: Change haste benefit to cast time formulas, may need further correction - With these changes, Paladin/Death Knight mount summons will no longer benefit from haste --- src/server/game/Entities/Unit/Unit.cpp | 37 +++++++++++++++++++++++++--------- src/server/game/Spells/Spell.cpp | 9 +++------ 2 files changed, 30 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e0c880334ea..b1a99f2337a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12883,20 +12883,37 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in return std::max(duration, 0); } -void Unit::ModSpellCastTime(SpellInfo const* spellProto, int32 & castTime, Spell* spell) +void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell* spell) { - if (!spellProto || castTime < 0) + if (!spellInfo || castTime < 0) return; + + if (spellInfo->IsChanneled() && !spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) + return; + // called from caster if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CASTING_TIME, castTime, spell); - - if (!(spellProto->Attributes & (SPELL_ATTR0_ABILITY|SPELL_ATTR0_TRADESPELL)) && ((GetTypeId() == TYPEID_PLAYER && spellProto->SpellFamilyName) || GetTypeId() == TYPEID_UNIT)) - castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); - else if (spellProto->Attributes & SPELL_ATTR0_REQ_AMMO && !(spellProto->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)) - castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]); - else if (spellProto->SpellVisual[0] == 3881 && HasAura(67556)) // cooking with Chef Hat. - castTime = 500; + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell); + + switch (spellInfo->DmgClass) + { + case SPELL_DAMAGE_CLASS_NONE: + if (spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) // required double check + castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); + else if (spellInfo->SpellVisual[0] == 3881 && HasAura(67556)) // cooking with Chef Hat. + castTime = 500; + break; + case SPELL_DAMAGE_CLASS_MELEE: + break; // no known cases + case SPELL_DAMAGE_CLASS_MAGIC: + castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); + break; + case SPELL_DAMAGE_CLASS_RANGED: + castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]); + break; + default: + break; + } } DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ca170187e82..c85fb0584cc 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2607,10 +2607,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA // Haste modifies duration of channeled spells if (m_spellInfo->IsChanneled()) - { - if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) - m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this); - } + m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this); // and duration of auras affected by SPELL_AURA_PERIODIC_HASTE else if (m_originalCaster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, aurSpellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) duration = int32(duration * m_originalCaster->GetFloatValue(UNIT_MOD_CAST_SPEED)); @@ -3234,9 +3231,9 @@ void Spell::handle_immediate() // Apply duration mod if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); + // Apply haste mods - if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) - m_caster->ModSpellCastTime(m_spellInfo, duration, this); + m_caster->ModSpellCastTime(m_spellInfo, duration, this); m_spellState = SPELL_STATE_CASTING; m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags); -- cgit v1.2.3 From 12b8bf037ff69d58d4be5751fc676a3e0a5e3e04 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 12 Jun 2014 20:13:07 +0100 Subject: Quick fixup for previous commit --- src/server/game/Entities/Unit/Unit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b1a99f2337a..c3ee6c0288f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12888,7 +12888,7 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell* if (!spellInfo || castTime < 0) return; - if (spellInfo->IsChanneled() && !spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) + if (spellInfo->IsChanneled() && !(spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)) return; // called from caster -- cgit v1.2.3 From c75b7942a8f6b5ff7879238fefa3519f6fdd13eb Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Thu, 12 Jun 2014 21:23:37 +0100 Subject: Core/Spells: Partially revert 4992c0290b2b43c3d4c744833ca9ba6f74af85ad, and further implement SPELL_ATTR3_NO_DONE_BONUS (which is the correct way of doing this) --- src/server/game/Entities/Unit/Unit.cpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c3ee6c0288f..e82790df46a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12895,25 +12895,13 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell* if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell); - switch (spellInfo->DmgClass) - { - case SPELL_DAMAGE_CLASS_NONE: - if (spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION) // required double check - castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); - else if (spellInfo->SpellVisual[0] == 3881 && HasAura(67556)) // cooking with Chef Hat. - castTime = 500; - break; - case SPELL_DAMAGE_CLASS_MELEE: - break; // no known cases - case SPELL_DAMAGE_CLASS_MAGIC: - castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); - break; - case SPELL_DAMAGE_CLASS_RANGED: - castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]); - break; - default: - break; - } + if (!((spellInfo->Attributes & (SPELL_ATTR0_ABILITY | SPELL_ATTR0_TRADESPELL)) || (spellInfo->AttributesEx3 & SPELL_ATTR3_NO_DONE_BONUS)) && + ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT)) + castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); + else if (spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO && !(spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)) + castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]); + else if (spellInfo->SpellVisual[0] == 3881 && HasAura(67556)) // cooking with Chef Hat. + castTime = 500; } DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) -- cgit v1.2.3 From 58043720420a0f59e95a5e7d226fec3ee98ebfa4 Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 13 Jun 2014 11:16:17 +0200 Subject: Core/Transports: Fixed crash happening during teleporting transports Closes #11793 --- .../game/Entities/DynamicObject/DynamicObject.cpp | 15 -------- .../game/Entities/DynamicObject/DynamicObject.h | 2 -- src/server/game/Entities/GameObject/GameObject.cpp | 14 ++------ src/server/game/Entities/Object/Object.cpp | 5 ++- src/server/game/Entities/Player/Player.cpp | 34 +++++++----------- src/server/game/Entities/Transport/Transport.cpp | 41 ++++++++++++++++------ src/server/game/Entities/Transport/Transport.h | 11 +++--- src/server/game/Entities/Unit/Unit.cpp | 7 +--- src/server/game/Entities/Unit/Unit.h | 2 +- src/server/game/Grids/Notifiers/GridNotifiers.cpp | 7 +++- src/server/game/Handlers/MovementHandler.cpp | 23 +++--------- src/server/game/Maps/Map.cpp | 8 +---- 12 files changed, 71 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp index 7cc94d992a1..e008146bb85 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp +++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp @@ -48,18 +48,6 @@ DynamicObject::~DynamicObject() delete _removedAura; } -void DynamicObject::CleanupsBeforeDelete(bool finalCleanup /* = true */) -{ - WorldObject::CleanupsBeforeDelete(finalCleanup); - - if (Transport* transport = GetTransport()) - { - transport->RemovePassenger(this); - SetTransport(NULL); - m_movementInfo.transport.Reset(); - } -} - void DynamicObject::AddToWorld() { ///- Register the dynamicObject for guid lookup and for caster @@ -124,14 +112,11 @@ bool DynamicObject::CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spe Transport* transport = caster->GetTransport(); if (transport) { - m_movementInfo.transport.guid = GetGUID(); - float x, y, z, o; pos.GetPosition(x, y, z, o); transport->CalculatePassengerOffset(x, y, z, &o); m_movementInfo.transport.pos.Relocate(x, y, z, o); - SetTransport(transport); // This object must be added to transport before adding to map for the client to properly display it transport->AddPassenger(this); } diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h index f52c86afdee..c9fd1d29f8b 100644 --- a/src/server/game/Entities/DynamicObject/DynamicObject.h +++ b/src/server/game/Entities/DynamicObject/DynamicObject.h @@ -41,8 +41,6 @@ class DynamicObject : public WorldObject, public GridObject, publ void AddToWorld(); void RemoveFromWorld(); - void CleanupsBeforeDelete(bool finalCleanup = true) override; - bool CreateDynamicObject(uint32 guidlow, Unit* caster, uint32 spellId, Position const& pos, float radius, DynamicObjectType type); void Update(uint32 p_time); void Remove(); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index c6b4039621a..69b15c2b56b 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -98,20 +98,12 @@ std::string GameObject::GetAIName() const return ""; } -void GameObject::CleanupsBeforeDelete(bool /*finalCleanup*/) +void GameObject::CleanupsBeforeDelete(bool finalCleanup) { - if (IsInWorld()) - RemoveFromWorld(); + WorldObject::CleanupsBeforeDelete(finalCleanup); if (m_uint32Values) // field array can be not exist if GameOBject not loaded RemoveFromOwner(); - - if (GetTransport() && !ToTransport()) - { - GetTransport()->RemovePassenger(this); - SetTransport(NULL); - m_movementInfo.transport.Reset(); - } } void GameObject::RemoveFromOwner() @@ -705,7 +697,7 @@ void GameObject::getFishLoot(Loot* fishloot, Player* loot_owner) { //subzone no result,use zone loot fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true); - //use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks. + //use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks. if (fishloot->empty()) fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true); } diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index f2215fa2d6d..4ff0153dea8 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1163,6 +1163,9 @@ void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/) { if (IsInWorld()) RemoveFromWorld(); + + if (Transport* transport = GetTransport()) + transport->RemovePassenger(this); } void WorldObject::_Create(uint32 guidlow, HighGuid guidhigh, uint32 phaseMask) @@ -1215,7 +1218,7 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool float sizefactor = GetObjectSize() + obj->GetObjectSize(); float maxdist = dist2compare + sizefactor; - if (m_transport && obj->GetTransport() && obj->GetTransport()->GetGUIDLow() == m_transport->GetGUIDLow()) + if (GetTransport() && obj->GetTransport() && obj->GetTransport()->GetGUIDLow() == GetTransport()->GetGUIDLow()) { float dtx = m_movementInfo.transport.pos.m_positionX - obj->m_movementInfo.transport.pos.m_positionX; float dty = m_movementInfo.transport.pos.m_positionY - obj->m_movementInfo.transport.pos.m_positionY; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 977142c8b21..8ceb6c00808 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2131,11 +2131,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { TC_LOG_DEBUG("maps", "Player %s using client without required expansion tried teleport to non accessible map %u", GetName().c_str(), mapid); - if (GetTransport()) + if (Transport* transport = GetTransport()) { - m_transport->RemovePassenger(this); - m_transport = NULL; - m_movementInfo.transport.Reset(); + transport->RemovePassenger(this); RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) } @@ -2153,16 +2151,12 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati SetUnitMovementFlags(GetUnitMovementFlags() & MOVEMENTFLAG_MASK_HAS_PLAYER_STATUS_OPCODE); DisableSpline(); - if (m_transport) + if (Transport* transport = GetTransport()) { if (options & TELE_TO_NOT_LEAVE_TRANSPORT) AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); else - { - m_transport->RemovePassenger(this); - m_transport = NULL; - m_movementInfo.transport.Reset(); - } + transport->RemovePassenger(this); } // The player was ported to another map and loses the duel immediately. @@ -2297,8 +2291,8 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // send transfer packets WorldPacket data(SMSG_TRANSFER_PENDING, 4 + 4 + 4); data << uint32(mapid); - if (m_transport) - data << m_transport->GetEntry() << GetMapId(); + if (Transport* transport = GetTransport()) + data << transport->GetEntry() << GetMapId(); GetSession()->SendPacket(&data); } @@ -2316,7 +2310,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { WorldPacket data(SMSG_NEW_WORLD, 4 + 4 + 4 + 4 + 4); data << uint32(mapid); - if (m_transport) + if (GetTransport()) data << m_movementInfo.transport.pos.PositionXYZOStream(); else data << m_teleport_dest.PositionXYZOStream(); @@ -17401,15 +17395,15 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) { uint64 transGUID = MAKE_NEW_GUID(transLowGUID, 0, HIGHGUID_MO_TRANSPORT); + Transport* transport = NULL; if (GameObject* go = HashMapHolder::Find(transGUID)) - m_transport = go->ToTransport(); + transport = go->ToTransport(); - if (m_transport) + if (transport) { - m_movementInfo.transport.guid = transGUID; float x = fields[26].GetFloat(), y = fields[27].GetFloat(), z = fields[28].GetFloat(), o = fields[29].GetFloat(); m_movementInfo.transport.pos.Relocate(x, y, z, o); - m_transport->CalculatePassengerPosition(x, y, z, &o); + transport->CalculatePassengerPosition(x, y, z, &o); if (!Trinity::IsValidMapCoord(x, y, z, o) || // transport size limited @@ -17420,7 +17414,6 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) TC_LOG_ERROR("entities.player", "Player (guidlow %d) have invalid transport coordinates (X: %f Y: %f Z: %f O: %f). Teleport to bind location.", guid, x, y, z, o); - m_transport = NULL; m_movementInfo.transport.Reset(); RelocateToHomebind(); @@ -17428,10 +17421,9 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) else { Relocate(x, y, z, o); - mapId = m_transport->GetMapId(); + mapId = transport->GetMapId(); - m_transport->AddPassenger(this); - AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); + transport->AddPassenger(this); } } else diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 8bc07732bb6..d907274f8d1 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -35,7 +35,7 @@ Transport::Transport() : GameObject(), _transportInfo(NULL), _isMoving(true), _pendingStop(false), - _triggeredArrivalEvent(false), _triggeredDepartureEvent(false) + _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), _passengerTeleportItr(_passengers.begin()) { m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION; } @@ -107,9 +107,6 @@ void Transport::CleanupsBeforeDelete(bool finalCleanup /*= true*/) while (!_passengers.empty()) { WorldObject* obj = *_passengers.begin(); - obj->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT); - obj->m_movementInfo.transport.Reset(); - obj->SetTransport(NULL); RemovePassenger(obj); } @@ -231,6 +228,9 @@ void Transport::AddPassenger(WorldObject* passenger) if (_passengers.insert(passenger).second) { + passenger->SetTransport(this); + passenger->m_movementInfo.AddMovementFlag(MOVEMENTFLAG_ONTRANSPORT); + passenger->m_movementInfo.transport.guid = GetGUID(); TC_LOG_DEBUG("entities.transport", "Object %s boarded transport %s.", passenger->GetName().c_str(), GetName().c_str()); if (Player* plr = passenger->ToPlayer()) @@ -240,8 +240,27 @@ void Transport::AddPassenger(WorldObject* passenger) void Transport::RemovePassenger(WorldObject* passenger) { - if (_passengers.erase(passenger) || _staticPassengers.erase(passenger)) // static passenger can remove itself in case of grid unload + bool erased = false; + if (_passengerTeleportItr != _passengers.end()) { + PassengerSet::iterator itr = _passengers.find(passenger); + if (itr != _passengers.end()) + { + if (itr == _passengerTeleportItr) + ++_passengerTeleportItr; + + _passengers.erase(itr); + erased = true; + } + } + else + erased = _passengers.erase(passenger) > 0; + + if (erased || _staticPassengers.erase(passenger)) // static passenger can remove itself in case of grid unload + { + passenger->SetTransport(NULL); + passenger->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT); + passenger->m_movementInfo.transport.Reset(); TC_LOG_DEBUG("entities.transport", "Object %s removed from transport %s.", passenger->GetName().c_str(), GetName().c_str()); if (Player* plr = passenger->ToPlayer()) @@ -570,9 +589,9 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl GetMap()->RemoveFromMap(this, false); SetMap(newMap); - for (std::set::iterator itr = _passengers.begin(); itr != _passengers.end();) + for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();) { - WorldObject* obj = (*itr++); + WorldObject* obj = (*_passengerTeleportItr++); float destX, destY, destZ, destO; obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); @@ -595,7 +614,7 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl } case TYPEID_PLAYER: if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT)) - _passengers.erase(obj); + RemovePassenger(obj); break; case TYPEID_DYNAMICOBJECT: obj->AddObjectToRemoveList(); @@ -613,7 +632,7 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl else { // Teleport players, they need to know it - for (std::set::iterator itr = _passengers.begin(); itr != _passengers.end(); ++itr) + for (PassengerSet::iterator itr = _passengers.begin(); itr != _passengers.end(); ++itr) { if ((*itr)->GetTypeId() == TYPEID_PLAYER) { @@ -630,9 +649,9 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl } } -void Transport::UpdatePassengerPositions(std::set& passengers) +void Transport::UpdatePassengerPositions(PassengerSet& passengers) { - for (std::set::iterator itr = passengers.begin(); itr != passengers.end(); ++itr) + for (PassengerSet::iterator itr = passengers.begin(); itr != passengers.end(); ++itr) { WorldObject* passenger = *itr; // transport teleported but passenger not yet (can happen for players) diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 293d4334a2e..e644417f1ac 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -31,6 +31,8 @@ class Transport : public GameObject, public TransportBase Transport(); public: + typedef std::set PassengerSet; + ~Transport(); bool Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress); @@ -42,7 +44,7 @@ class Transport : public GameObject, public TransportBase void AddPassenger(WorldObject* passenger); void RemovePassenger(WorldObject* passenger); - std::set const& GetPassengers() const { return _passengers; } + PassengerSet const& GetPassengers() const { return _passengers; } Creature* CreateNPCPassenger(uint32 guid, CreatureData const* data); GameObject* CreateGOPassenger(uint32 guid, GameObjectData const* data); @@ -99,7 +101,7 @@ class Transport : public GameObject, public TransportBase void MoveToNextWaypoint(); float CalculateSegmentPos(float perc); bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o); - void UpdatePassengerPositions(std::set& passengers); + void UpdatePassengerPositions(PassengerSet& passengers); void DoEventIfAny(KeyFrame const& node, bool departure); //! Helpers to know if stop frame was reached @@ -118,8 +120,9 @@ class Transport : public GameObject, public TransportBase bool _triggeredArrivalEvent; bool _triggeredDepartureEvent; - std::set _passengers; - std::set _staticPassengers; + PassengerSet _passengers; + PassengerSet::iterator _passengerTeleportItr; + PassengerSet _staticPassengers; }; #endif diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e82790df46a..c0f179eb504 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13555,12 +13555,7 @@ void Unit::CleanupsBeforeDelete(bool finalCleanup) { CleanupBeforeRemoveFromMap(finalCleanup); - if (GetTransport()) - { - GetTransport()->RemovePassenger(this); - SetTransport(NULL); - m_movementInfo.transport.Reset(); - } + WorldObject::CleanupsBeforeDelete(finalCleanup); } void Unit::UpdateCharmAI() diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 20c987c5105..103f6b596d9 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1289,7 +1289,7 @@ class Unit : public WorldObject void RemoveFromWorld(); void CleanupBeforeRemoveFromMap(bool finalCleanup); - void CleanupsBeforeDelete(bool finalCleanup = true); // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) + void CleanupsBeforeDelete(bool finalCleanup = true) override; // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) DiminishingLevels GetDiminishing(DiminishingGroup group); void IncrDiminishing(DiminishingGroup group); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index 472497ea5f2..270d598d53a 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -35,7 +35,8 @@ void VisibleNotifier::SendToSelf() // at this moment i_clientGUIDs have guids that not iterate at grid level checks // but exist one case when this possible and object not out of range: transports if (Transport* transport = i_player.GetTransport()) - for (std::set::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end();++itr) + { + for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) { if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) { @@ -54,11 +55,15 @@ void VisibleNotifier::SendToSelf() case TYPEID_UNIT: i_player.UpdateVisibilityOf((*itr)->ToCreature(), i_data, i_visibleNow); break; + case TYPEID_DYNAMICOBJECT: + i_player.UpdateVisibilityOf((*itr)->ToDynObject(), i_data, i_visibleNow); + break; default: break; } } } + } for (Player::ClientGUIDs::const_iterator it = vis_guids.begin();it != vis_guids.end(); ++it) { diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index cef414163bd..6fedc481a14 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -285,7 +285,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) } /* handle special cases */ - if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) + if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) @@ -308,27 +308,15 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) if (!plrMover->GetTransport()) { if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid)) - { - plrMover->m_transport = transport; transport->AddPassenger(plrMover); - } } else if (plrMover->GetTransport()->GetGUID() != movementInfo.transport.guid) { - bool foundNewTransport = false; - plrMover->m_transport->RemovePassenger(plrMover); + plrMover->GetTransport()->RemovePassenger(plrMover); if (Transport* transport = plrMover->GetMap()->GetTransport(movementInfo.transport.guid)) - { - foundNewTransport = true; - plrMover->m_transport = transport; transport->AddPassenger(plrMover); - } - - if (!foundNewTransport) - { - plrMover->m_transport = NULL; + else movementInfo.transport.Reset(); - } } } @@ -336,13 +324,12 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) { GameObject* go = mover->GetMap()->GetGameObject(movementInfo.transport.guid); if (!go || go->GetGoType() != GAMEOBJECT_TYPE_TRANSPORT) - movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; + movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT); } } else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave { - plrMover->m_transport->RemovePassenger(plrMover); - plrMover->m_transport = NULL; + plrMover->GetTransport()->RemovePassenger(plrMover); movementInfo.transport.Reset(); } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index d3be33cb441..01e3af149dc 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2506,15 +2506,9 @@ void Map::SendInitSelf(Player* player) // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map if (Transport* transport = player->GetTransport()) - { - for (std::set::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) - { + for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) if (player != (*itr) && player->HaveAtClient(*itr)) - { (*itr)->BuildCreateUpdateBlockForPlayer(&data, player); - } - } - } WorldPacket packet; data.BuildPacket(&packet); -- cgit v1.2.3 From e9c9e362657f77dd6cc1d51543de68f9de7f8689 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 14 Jun 2014 11:48:07 +0200 Subject: Scripts/Icecrown Citadel: Fixed possible crash in blood nova target selection --- .../IcecrownCitadel/boss_deathbringer_saurfang.cpp | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 16d1531e890..e1658e564ec 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -1227,9 +1227,9 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader if (targets.empty()) return; - // select one random target, with preference of ranged targets + // select one random target, preferring ranged targets uint32 targetsAtRange = 0; - uint32 const minTargets = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 10 : 4); + uint32 const minTargets = uint32(GetCaster()->GetMap()->Is25ManRaid() ? 10 : 4); targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); // get target count at range @@ -1237,18 +1237,12 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader if ((*itr)->GetDistance(GetCaster()) < 12.0f) break; - // set the upper cap + // If not enough ranged targets are present just select anyone if (targetsAtRange < minTargets) - targetsAtRange = std::min(targets.size() - 1, minTargets); - - if (!targetsAtRange) - { - targets.clear(); - return; - } + targetsAtRange = uint32(targets.size()); std::list::const_iterator itr = targets.begin(); - std::advance(itr, urand(0, targetsAtRange)); + std::advance(itr, urand(0, targetsAtRange - 1)); target = *itr; targets.clear(); targets.push_back(target); -- cgit v1.2.3 From 08edc7d630b46145c348ae5834b3dc0c606e82b2 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 14 Jun 2014 17:09:35 +0200 Subject: Core/Vehicles: Fixed power issues * Regenerate powers only if vehicle has UNIT_FLAG2_REGENERATE_POWER * Removed old pyrite power hack * Apply creature_template.ManaMod to all power types Closes #12141 --- src/server/game/Entities/Creature/Creature.cpp | 8 ++++---- src/server/game/Entities/Unit/Unit.cpp | 17 +++++++++++------ src/server/game/Entities/Vehicle/Vehicle.cpp | 4 ++++ 3 files changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 90527912efd..264cae7fa7b 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -567,13 +567,13 @@ void Creature::Update(uint32 diff) if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed())) // regenerate health if not in combat or if polymorphed RegenerateHealth(); - if (getPowerType() == POWER_ENERGY) + if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER)) { - if (!IsVehicle() || GetVehicleKit()->GetVehicleInfo()->m_powerDisplayId != POWER_PYRITE) + if (getPowerType() == POWER_ENERGY) Regenerate(POWER_ENERGY); + else + RegenerateMana(); } - else - RegenerateMana(); /*if (!bIsPolymorphed) // only increase the timer if not polymorphed m_regenTimer += CREATURE_REGEN_INTERVAL - diff; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c0f179eb504..2e984685a01 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8645,25 +8645,30 @@ void Unit::setPowerType(Powers new_powertype) } } + float powerMultiplier = 1.0f; + if (!IsPet()) + if (Creature* creature = ToCreature()) + powerMultiplier = creature->GetCreatureTemplate()->ModMana; + switch (new_powertype) { default: case POWER_MANA: break; case POWER_RAGE: - SetMaxPower(POWER_RAGE, GetCreatePowers(POWER_RAGE)); + SetMaxPower(POWER_RAGE, uint32(std::ceilf(GetCreatePowers(POWER_RAGE) * powerMultiplier))); SetPower(POWER_RAGE, 0); break; case POWER_FOCUS: - SetMaxPower(POWER_FOCUS, GetCreatePowers(POWER_FOCUS)); - SetPower(POWER_FOCUS, GetCreatePowers(POWER_FOCUS)); + SetMaxPower(POWER_FOCUS, uint32(std::ceilf(GetCreatePowers(POWER_FOCUS) * powerMultiplier))); + SetPower(POWER_FOCUS, uint32(std::ceilf(GetCreatePowers(POWER_FOCUS) * powerMultiplier))); break; case POWER_ENERGY: - SetMaxPower(POWER_ENERGY, GetCreatePowers(POWER_ENERGY)); + SetMaxPower(POWER_ENERGY, uint32(std::ceilf(GetCreatePowers(POWER_ENERGY) * powerMultiplier))); break; case POWER_HAPPINESS: - SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); - SetPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); + SetMaxPower(POWER_HAPPINESS, uint32(std::ceilf(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier))); + SetPower(POWER_HAPPINESS, uint32(std::ceilf(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier))); break; } } diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 4c3724a8860..f3b4e6de70c 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -77,8 +77,12 @@ Vehicle::~Vehicle() void Vehicle::Install() { if (_me->GetTypeId() == TYPEID_UNIT) + { if (PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(_vehicleInfo->m_powerDisplayId)) _me->setPowerType(Powers(powerDisplay->PowerType)); + else if (_me->getClass() == CLASS_ROGUE) + _me->setPowerType(POWER_ENERGY); + } _status = STATUS_INSTALLED; if (GetBase()->GetTypeId() == TYPEID_UNIT) -- cgit v1.2.3 From 2d5b54a69d2bf3efb8eb2fd798e91fc0c2e0c69f Mon Sep 17 00:00:00 2001 From: Shauren Date: Sat, 14 Jun 2014 17:27:28 +0200 Subject: Replaced calls to ceilf (msvc extension) with ceil - fixes build --- src/server/game/Entities/Unit/Unit.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2e984685a01..433352b642a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8656,19 +8656,19 @@ void Unit::setPowerType(Powers new_powertype) case POWER_MANA: break; case POWER_RAGE: - SetMaxPower(POWER_RAGE, uint32(std::ceilf(GetCreatePowers(POWER_RAGE) * powerMultiplier))); + SetMaxPower(POWER_RAGE, uint32(std::ceil(GetCreatePowers(POWER_RAGE) * powerMultiplier))); SetPower(POWER_RAGE, 0); break; case POWER_FOCUS: - SetMaxPower(POWER_FOCUS, uint32(std::ceilf(GetCreatePowers(POWER_FOCUS) * powerMultiplier))); - SetPower(POWER_FOCUS, uint32(std::ceilf(GetCreatePowers(POWER_FOCUS) * powerMultiplier))); + SetMaxPower(POWER_FOCUS, uint32(std::ceil(GetCreatePowers(POWER_FOCUS) * powerMultiplier))); + SetPower(POWER_FOCUS, uint32(std::ceil(GetCreatePowers(POWER_FOCUS) * powerMultiplier))); break; case POWER_ENERGY: - SetMaxPower(POWER_ENERGY, uint32(std::ceilf(GetCreatePowers(POWER_ENERGY) * powerMultiplier))); + SetMaxPower(POWER_ENERGY, uint32(std::ceil(GetCreatePowers(POWER_ENERGY) * powerMultiplier))); break; case POWER_HAPPINESS: - SetMaxPower(POWER_HAPPINESS, uint32(std::ceilf(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier))); - SetPower(POWER_HAPPINESS, uint32(std::ceilf(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier))); + SetMaxPower(POWER_HAPPINESS, uint32(std::ceil(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier))); + SetPower(POWER_HAPPINESS, uint32(std::ceil(GetCreatePowers(POWER_HAPPINESS) * powerMultiplier))); break; } } -- cgit v1.2.3 From 86b3298a47be32e990beedd27bddbcaf01c08c78 Mon Sep 17 00:00:00 2001 From: MitchesD Date: Sat, 14 Jun 2014 17:48:47 +0200 Subject: Scripts/Misc: random fixes --- .../BlackrockMountain/MoltenCore/boss_golemagg.cpp | 2 +- .../AzjolNerub/Ahnkahet/instance_ahnkahet.cpp | 18 ++++++------- .../Northrend/DraktharonKeep/boss_novos.cpp | 8 +++--- .../Northrend/Naxxramas/boss_anubrekhan.cpp | 1 - .../scripts/Northrend/Naxxramas/boss_faerlina.cpp | 1 - .../scripts/Northrend/Naxxramas/boss_gluth.cpp | 1 - .../Northrend/Naxxramas/instance_naxxramas.cpp | 4 +-- .../Northrend/Nexus/Oculus/instance_oculus.cpp | 4 +-- .../Ulduar/HallsOfLightning/boss_bjarngrim.cpp | 8 +++--- .../Ulduar/HallsOfLightning/boss_ionar.cpp | 4 +-- .../Ulduar/HallsOfLightning/boss_volkhan.cpp | 10 +++---- .../Ulduar/HallsOfStone/boss_maiden_of_grief.cpp | 2 +- .../scripts/Northrend/zone_crystalsong_forest.cpp | 14 +++++----- src/server/scripts/Northrend/zone_dalaran.cpp | 1 - src/server/scripts/Northrend/zone_dragonblight.cpp | 9 +++---- src/server/scripts/World/areatrigger_scripts.cpp | 31 ++++------------------ src/server/scripts/World/go_scripts.cpp | 5 ++-- src/server/scripts/World/guards.cpp | 6 ++--- src/server/scripts/World/mob_generic_creature.cpp | 2 +- src/server/scripts/World/npc_innkeeper.cpp | 2 +- src/server/scripts/World/npcs_special.cpp | 1 - 21 files changed, 50 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp index 2a473754ce6..f9757997731 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp @@ -144,7 +144,7 @@ class npc_core_rager : public CreatureScript if (HealthAbovePct(50) || !instance) return; - if (Creature* pGolemagg = instance->instance->GetCreature(instance->GetData64(BOSS_GOLEMAGG_THE_INCINERATOR))) + if (Creature* pGolemagg = ObjectAccessor::GetCreature(*me, instance->GetData64(BOSS_GOLEMAGG_THE_INCINERATOR))) { if (pGolemagg->IsAlive()) { diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp index 4aa59e72556..bf7b4355ea6 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp @@ -141,9 +141,9 @@ class instance_ahnkahet : public InstanceMapScript SwitchTrigger = data; break; case DATA_JEDOGA_RESET_INITIANDS: - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - if (Creature* creature = instance->GetCreature(*itr)) + if (Creature* creature = instance->GetCreature(guid)) { creature->Respawn(); if (!creature->IsInEvadeMode()) @@ -164,9 +164,9 @@ class instance_ahnkahet : public InstanceMapScript case DATA_SPHERE_2: return SpheresState[type - DATA_SPHERE_1]; case DATA_ALL_INITIAND_DEAD: - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - Creature* cr = instance->GetCreature(*itr); + Creature* cr = instance->GetCreature(guid); if (!cr || cr->IsAlive()) return 0; } @@ -214,11 +214,11 @@ class instance_ahnkahet : public InstanceMapScript { std::vector vInitiands; vInitiands.clear(); - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - Creature* cr = instance->GetCreature(*itr); + Creature* cr = instance->GetCreature(guid); if (cr && cr->IsAlive()) - vInitiands.push_back(*itr); + vInitiands.push_back(guid); } if (vInitiands.empty()) return 0; @@ -245,9 +245,9 @@ class instance_ahnkahet : public InstanceMapScript case DATA_JEDOGA_SHADOWSEEKER: if (state == DONE) { - for (std::set::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + for (uint64 guid : InitiandGUIDs) { - if (Creature* cr = instance->GetCreature(*itr)) + if (Creature* cr = instance->GetCreature(guid)) cr->DespawnOrUnsummon(); } } diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp index 63b1359a406..4e9462a447f 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -208,7 +208,7 @@ public: { for (uint8 i = 0; i < 4; i++) if (uint64 guid = instance->GetData64(summoners[i].data)) - if (Creature* crystalChannelTarget = instance->instance->GetCreature(guid)) + if (Creature* crystalChannelTarget = ObjectAccessor::GetCreature(*me, guid)) { if (active) crystalChannelTarget->AI()->SetData(summoners[i].spell, summoners[i].timer); @@ -221,7 +221,7 @@ public: { for (uint8 i = 0; i < 4; i++) if (uint64 guid = instance->GetData64(DATA_NOVOS_CRYSTAL_1 + i)) - if (GameObject* crystal = instance->instance->GetGameObject(guid)) + if (GameObject* crystal = ObjectAccessor::GetGameObject(*me, guid)) SetCrystalStatus(crystal, active); } @@ -241,7 +241,7 @@ public: { for (uint8 i = 0; i < 4; i++) if (uint64 guid = instance->GetData64(DATA_NOVOS_CRYSTAL_1 + i)) - if (GameObject* crystal = instance->instance->GetGameObject(guid)) + if (GameObject* crystal = ObjectAccessor::GetGameObject(*me, guid)) if (crystal->GetGoState() == GO_STATE_ACTIVE) { SetCrystalStatus(crystal, false); @@ -258,7 +258,7 @@ public: events.ScheduleEvent(EVENT_SUMMON_MINIONS, 15000); } else if (uint64 guid = instance->GetData64(DATA_NOVOS_SUMMONER_4)) - if (Creature* crystalChannelTarget = instance->instance->GetCreature(guid)) + if (Creature* crystalChannelTarget = ObjectAccessor::GetCreature(*me, guid)) crystalChannelTarget->AI()->SetData(SPELL_SUMMON_CRYSTAL_HANDLER, 15000); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index d3b4a285af6..d4f00414b7d 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -120,7 +120,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER) { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index 02bafa8d10d..3d42827c0a8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -84,7 +84,6 @@ class boss_faerlina : public CreatureScript } void MoveInLineOfSight(Unit* who) override - { if (!_introDone && who->GetTypeId() == TYPEID_PLAYER) { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index 3a0e3ce7c73..381be8d5cd1 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -70,7 +70,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { if (who->GetEntry() == NPC_ZOMBIE && me->IsWithinDistInMap(who, 7)) { diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 1331c25de17..e8ed181da5a 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -368,9 +368,9 @@ class instance_naxxramas : public InstanceMapScript if (i == section) continue; - for (std::set::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr) + for (uint64 guid : HeiganEruptionGUID[i]) { - if (GameObject* heiganEruption = instance->GetGameObject(*itr)) + if (GameObject* heiganEruption = instance->GetGameObject(guid)) { heiganEruption->SendCustomAnim(heiganEruption->GetGoAnimProgress()); heiganEruption->CastSpell(NULL, SPELL_ERUPTION); diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index bf84a267a27..2b15ddf32c4 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -281,8 +281,8 @@ class instance_oculus : public InstanceMapScript void GreaterWhelps() { - for (std::list::const_iterator itr = GreaterWhelpList.begin(); itr != GreaterWhelpList.end(); ++itr) - if (Creature* gwhelp = instance->GetCreature(*itr)) + for (uint64 guid : GreaterWhelpList) + if (Creature* gwhelp = instance->GetCreature(guid)) gwhelp->SetPhaseMask(1, true); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index 24d145f097f..13ea815febc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -164,11 +164,9 @@ public: for (uint8 i = 0; i < 2; ++i) { - if (Creature* pStormforgedLieutenant = (ObjectAccessor::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) - { + if (Creature* pStormforgedLieutenant = ObjectAccessor::GetCreature(*me, m_auiStormforgedLieutenantGUID[i])) if (!pStormforgedLieutenant->IsAlive()) pStormforgedLieutenant->Respawn(); - } } if (m_uiStance != STANCE_DEFENSIVE) @@ -411,7 +409,7 @@ public: void EnterCombat(Unit* who) override { - if (Creature* pBjarngrim = instance->instance->GetCreature(instance->GetData64(DATA_BJARNGRIM))) + if (Creature* pBjarngrim = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BJARNGRIM))) { if (pBjarngrim->IsAlive() && !pBjarngrim->GetVictim()) pBjarngrim->AI()->AttackStart(who); @@ -434,7 +432,7 @@ public: if (m_uiRenewSteel_Timer <= uiDiff) { - if (Creature* pBjarngrim = instance->instance->GetCreature(instance->GetData64(DATA_BJARNGRIM))) + if (Creature* pBjarngrim = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BJARNGRIM))) { if (pBjarngrim->IsAlive()) DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index aac315cda0d..83082b18d73 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -165,9 +165,9 @@ public: Position pos = me->GetPosition(); - for (std::list::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) + for (uint64 guid : lSparkList) { - if (Creature* pSpark = ObjectAccessor::GetCreature(*me, *itr)) + if (Creature* pSpark = ObjectAccessor::GetCreature(*me, guid)) { if (pSpark->IsAlive()) { diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index d0b8f75e711..b424ce01b06 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -162,13 +162,11 @@ public: if (m_lGolemGUIDList.empty()) return; - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + for (uint64 guid : m_lGolemGUIDList) { - if (Creature* temp = ObjectAccessor::GetCreature(*me, *itr)) - { + if (Creature* temp = ObjectAccessor::GetCreature(*me, guid)) if (temp->IsAlive()) temp->DespawnOrUnsummon(); - } } m_lGolemGUIDList.clear(); @@ -179,9 +177,9 @@ public: if (m_lGolemGUIDList.empty()) return; - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + for (uint64 guid : m_lGolemGUIDList) { - if (Creature* temp = ObjectAccessor::GetCreature(*me, *itr)) + if (Creature* temp = ObjectAccessor::GetCreature(*me, guid)) { // Only shatter brittle golems if (temp->IsAlive() && temp->GetEntry() == NPC_BRITTLE_GOLEM) diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp index eec08c3c429..796299cc952 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp @@ -37,7 +37,7 @@ enum Spells enum Events { - EVENT_PARTING_SORROW = 1, + EVENT_PARTING_SORROW = 1, EVENT_STORM_OF_GRIEF, EVENT_SHOCK_OF_SORROW, EVENT_PILLAR_OF_WOE diff --git a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp index e4bd9c469fb..7d680ecd071 100644 --- a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp +++ b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp @@ -76,20 +76,18 @@ public: GetCreatureListWithEntryInGrid(orbList, me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f); if (!orbList.empty()) { - for (std::list::const_iterator itr = orbList.begin(); itr != orbList.end(); ++itr) + for (Creature* orb : orbList) { - if (Creature* pOrb = *itr) + if (orb->GetPositionY() < 1000) { - if (pOrb->GetPositionY() < 1000) - { - targetGUID = pOrb->GetGUID(); - break; - } + targetGUID = orb->GetGUID(); + break; } } } } - }else + } + else { if (!targetGUID) if (Creature* pOrb = GetClosestCreatureWithEntry(me, NPC_TRANSITUS_SHIELD_DUMMY, 32.0f)) diff --git a/src/server/scripts/Northrend/zone_dalaran.cpp b/src/server/scripts/Northrend/zone_dalaran.cpp index 21fc93578ae..1e8da70bbbf 100644 --- a/src/server/scripts/Northrend/zone_dalaran.cpp +++ b/src/server/scripts/Northrend/zone_dalaran.cpp @@ -73,7 +73,6 @@ public: void AttackStart(Unit* /*who*/) override { } void MoveInLineOfSight(Unit* who) override - { if (!who || !who->IsInWorld() || who->GetZoneId() != 4395) return; diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index bda6d953d9f..59c9b21a220 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -246,13 +246,10 @@ class npc_commander_eligor_dawnbringer : public CreatureScript { std::list creatureList; GetCreatureListWithEntryInGrid(creatureList, me, AudienceMobs[ii], 15.0f); - for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + for (Creature* creature : creatureList) { - if (Creature* creatureList = *itr) - { - audienceList[creaturecount] = creatureList->GetGUID(); - ++creaturecount; - } + audienceList[creaturecount] = creature->GetGUID(); + ++creaturecount; } } diff --git a/src/server/scripts/World/areatrigger_scripts.cpp b/src/server/scripts/World/areatrigger_scripts.cpp index fb438c38efb..4393f72eb1b 100644 --- a/src/server/scripts/World/areatrigger_scripts.cpp +++ b/src/server/scripts/World/areatrigger_scripts.cpp @@ -51,11 +51,7 @@ enum CoilfangGOs class AreaTrigger_at_coilfang_waterfall : public AreaTriggerScript { public: - - AreaTrigger_at_coilfang_waterfall() - : AreaTriggerScript("at_coilfang_waterfall") - { - } + AreaTrigger_at_coilfang_waterfall() : AreaTriggerScript("at_coilfang_waterfall") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -83,11 +79,7 @@ enum LegionTeleporter class AreaTrigger_at_legion_teleporter : public AreaTriggerScript { public: - - AreaTrigger_at_legion_teleporter() - : AreaTriggerScript("at_legion_teleporter") - { - } + AreaTrigger_at_legion_teleporter() : AreaTriggerScript("at_legion_teleporter") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -125,11 +117,7 @@ enum StormwrightShelf class AreaTrigger_at_stormwright_shelf : public AreaTriggerScript { public: - - AreaTrigger_at_stormwright_shelf() - : AreaTriggerScript("at_stormwright_shelf") - { - } + AreaTrigger_at_stormwright_shelf() : AreaTriggerScript("at_stormwright_shelf") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -153,11 +141,7 @@ enum ScentLarkorwi class AreaTrigger_at_scent_larkorwi : public AreaTriggerScript { public: - - AreaTrigger_at_scent_larkorwi() - : AreaTriggerScript("at_scent_larkorwi") - { - } + AreaTrigger_at_scent_larkorwi() : AreaTriggerScript("at_scent_larkorwi") { } bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override { @@ -184,11 +168,7 @@ enum AtLastRites class AreaTrigger_at_last_rites : public AreaTriggerScript { public: - - AreaTrigger_at_last_rites() - : AreaTriggerScript("at_last_rites") - { - } + AreaTrigger_at_last_rites() : AreaTriggerScript("at_last_rites") { } bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) override { @@ -246,7 +226,6 @@ enum Waygate class AreaTrigger_at_sholazar_waygate : public AreaTriggerScript { public: - AreaTrigger_at_sholazar_waygate() : AreaTriggerScript("at_sholazar_waygate") { } bool OnTrigger(Player* player, AreaTriggerEntry const* trigger) override diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index ca00b0fc352..4bb88a560bb 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -118,7 +118,8 @@ public: enum GildedBrazier { - NPC_STILLBLADE = 17716, + NPC_STILLBLADE = 17716, + QUEST_THE_FIRST_TRIAL = 9678 }; class go_gilded_brazier : public GameObjectScript @@ -130,7 +131,7 @@ public: { if (go->GetGoType() == GAMEOBJECT_TYPE_GOOBER) { - if (player->GetQuestStatus(9678) == QUEST_STATUS_INCOMPLETE) + if (player->GetQuestStatus(QUEST_THE_FIRST_TRIAL) == QUEST_STATUS_INCOMPLETE) { if (Creature* Stillblade = player->SummonCreature(NPC_STILLBLADE, 8106.11f, -7542.06f, 151.775f, 3.02598f, TEMPSUMMON_DEAD_DESPAWN, 60000)) Stillblade->AI()->AttackStart(player); diff --git a/src/server/scripts/World/guards.cpp b/src/server/scripts/World/guards.cpp index 21a81d37868..a156a41fcef 100644 --- a/src/server/scripts/World/guards.cpp +++ b/src/server/scripts/World/guards.cpp @@ -387,7 +387,7 @@ public: void AddSC_guards() { - new guard_generic; - new guard_shattrath_aldor; - new guard_shattrath_scryer; + new guard_generic(); + new guard_shattrath_aldor(); + new guard_shattrath_scryer(); } diff --git a/src/server/scripts/World/mob_generic_creature.cpp b/src/server/scripts/World/mob_generic_creature.cpp index 30666d5d2ea..2eb91b7b8fe 100644 --- a/src/server/scripts/World/mob_generic_creature.cpp +++ b/src/server/scripts/World/mob_generic_creature.cpp @@ -229,6 +229,6 @@ public: void AddSC_generic_creature() { //new generic_creature; - new trigger_periodic; + new trigger_periodic(); //new trigger_death; } diff --git a/src/server/scripts/World/npc_innkeeper.cpp b/src/server/scripts/World/npc_innkeeper.cpp index b647cccf8ea..be56e57cc9d 100644 --- a/src/server/scripts/World/npc_innkeeper.cpp +++ b/src/server/scripts/World/npc_innkeeper.cpp @@ -134,6 +134,6 @@ public: void AddSC_npc_innkeeper() { - new npc_innkeeper; + new npc_innkeeper(); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index c32edff09bc..b3dc57cf028 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -185,7 +185,6 @@ public: } void MoveInLineOfSight(Unit* who) override - { if (!SpawnAssoc) return; -- cgit v1.2.3 From 2596f1f35d01a8a6c8a555a5952c055a4d4dc239 Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 14 Jun 2014 19:55:25 +0200 Subject: Core/SAI: Added SMART_ACTION_CAST support for gameobject cast --- src/server/game/AI/SmartScripts/SmartScript.cpp | 54 +++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 2647368559c..0946ad3ef16 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -488,45 +488,47 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_CAST: { - if (!me) - break; - ObjectList* targets = GetTargets(e, unit); if (!targets) break; for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { - if (!IsUnit(*itr)) - continue; - - if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) + if (IsUnit(*itr)) { - if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) - me->InterruptNonMeleeSpells(false); - - if (e.action.cast.flags & SMARTCAST_COMBAT_MOVE) + if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) { - // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed - // unless target is outside spell range, out of mana, or LOS. + if (me) + { + if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) + me->InterruptNonMeleeSpells(false); - bool _allowMove = false; - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); - int32 mana = me->GetPower(POWER_MANA); + if (e.action.cast.flags & SMARTCAST_COMBAT_MOVE) + { + // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed + // unless target is outside spell range, out of mana, or LOS. - if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) || - me->GetDistance(*itr) < spellInfo->GetMinRange(true) || - !me->IsWithinLOSInMap(*itr) || - mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask())) - _allowMove = true; + bool _allowMove = false; + SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); + int32 mana = me->GetPower(POWER_MANA); - CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); - } + if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) || + me->GetDistance(*itr) < spellInfo->GetMinRange(true) || + !me->IsWithinLOSInMap(*itr) || + mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask())) + _allowMove = true; - me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); + CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); + } + + me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); + } + else if (go) + go->CastSpell((*itr)->ToUnit(), e.action.cast.spell); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: Creature %u casts spell %u on target %u with castflags %u", - me->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: %s: %u casts spell %u on target %u with castflags %u", + GetLogNameForGuid(me ? me->GetGUID() : go->GetGUID()), me ? me->GetGUIDLow() : go->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); + } } else TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); -- cgit v1.2.3 From cd3977edf9f688187a426e0e050d04d80815a7ef Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 14 Jun 2014 20:03:55 +0200 Subject: DB/Misc: Convert ulduar teleporter in sql --- sql/updates/world/2014_06_14_01_world_misc.sql | 49 ++++++++ src/server/scripts/Northrend/CMakeLists.txt | 1 - .../Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp | 124 --------------------- 3 files changed, 49 insertions(+), 125 deletions(-) create mode 100644 sql/updates/world/2014_06_14_01_world_misc.sql delete mode 100644 src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp (limited to 'src') diff --git a/sql/updates/world/2014_06_14_01_world_misc.sql b/sql/updates/world/2014_06_14_01_world_misc.sql new file mode 100644 index 00000000000..05261164241 --- /dev/null +++ b/sql/updates/world/2014_06_14_01_world_misc.sql @@ -0,0 +1,49 @@ +DELETE FROM `gossip_menu_option` WHERE `menu_id`=10389; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `box_coded`, `box_money`, `box_text`) VALUES +(10389, 0, 0, 'Teleport to the Expedition Base Camp.', 33919, 1, 0, 0, ''), -- 194569 +(10389, 1, 0, 'Teleport to the Formation Grounds.', 33920, 1, 0, 0, ''), -- 194569 +(10389, 3, 0, 'Teleport to the Colossal Forge.', 33921, 1, 0, 0, ''), -- 194569 +(10389, 4, 0, 'Teleport to the Scrapyard.', 33922, 1, 0, 0, ''), -- 194569 +(10389, 5, 0, 'Teleport to the Antechamber of Ulduar.', 33923, 1, 0, 0, ''), -- 194569 +(10389, 6, 0, 'Teleport to the Shattered Walkway.', 33924, 1, 0, 0, ''), -- 194569 +(10389, 10, 0, 'Teleport to the Conservatory of Life.', 33926, 1, 0, 0, ''), -- 194569 +(10389, 12, 0, 'Teleport to the Spark of Imagination.', 33927, 1, 0, 0, ''), -- 194569 +(10389, 15, 0, 'Teleport to the Prison of Yogg-Saron.', 33928, 1, 0, 0, ''); -- 194569 + +UPDATE `gameobject_template` SET AIName = 'SmartGameObjectAI', `ScriptName` = '' WHERE `entry`=194569; + +SET @Entry := 194569; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@Entry; +DELETE FROM `smart_scripts` WHERE `source_type`=9 AND `entryorguid`=@Script; +INSERT INTO `smart_scripts` VALUES +-- Expedition Base Camp Teleport +(@ENTRY,1,0,9,62,0,100,0,10389,0,0,0,11,64014,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 0 - Cast "Expedition Base Camp Teleport"'), +-- Formation Grounds Teleport +(@ENTRY,1,1,9,62,0,100,0,10389,1,0,0,11,64032,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 1 - Cast "Formation Grounds Teleport"'), +-- Colossal Forge Teleport +(@ENTRY,1,2,9,62,0,100,0,10389,3,0,0,11,64028,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 3 - Cast "Colossal Forge Teleport"'), +-- Scrapyard Teleport +(@ENTRY,1,3,9,62,0,100,0,10389,4,0,0,11,64031,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 4 - Cast "Scrapyard Teleport"'), +-- Antechamber Teleport +(@ENTRY,1,4,9,62,0,100,0,10389,5,0,0,11,64030,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 5 - Cast "Antechamber Teleport"'), +-- Shattered Walkway Teleport +(@ENTRY,1,5,9,62,0,100,0,10389,6,0,0,11,64029,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 6 - Cast "Shattered Walkway Teleport"'), +-- Conservatory Teleport +(@ENTRY,1,6,9,62,0,100,0,10389,10,0,0,11,64024,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 10 - Cast "Conservatory Teleport"'), +-- Halls of Invention Teleport +(@ENTRY,1,7,9,62,0,100,0,10389,12,0,0,11,64025,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 12 - Cast "Halls of Invention Teleport"'), +-- Prison of Yogg-Saron Teleport +(@ENTRY,1,8,9,62,0,100,0,10389,15,0,0,11,65042,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - On gossip select 15 - Cast "Prison of Yogg-Saron Teleport"'), +-- Close gossip +(@ENTRY,1,9,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ulduar Teleporter - Linked with Previous Event - Close gossip'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=10389; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(15, 10389, 1, 0, 0, 13, 1, 20, 2, 0, 0, 0, 0, '', 'Show options for gossip only if 2 Collossus death'), +(15, 10389, 3, 0, 0, 13, 1, 0, 3, 2, 0, 0, 0, '', 'Show options for gossip only if BOSS_LEVIATHAN done'), +(15, 10389, 4, 0, 0, 13, 1, 3, 3, 2, 0, 0, 0, '', 'Show options for gossip only if BOSS_XT002 done'), +(15, 10389, 5, 0, 0, 13, 1, 3, 3, 2, 0, 0, 0, '', 'Show options for gossip only if BOSS_XT002 done'), +(15, 10389, 6, 0, 0, 13, 1, 5, 3, 2, 0, 0, 0, '', 'Show options for gossip only if BOSS_KOLOGARN done'), +(15, 10389, 12, 0, 0, 13, 1, 5, 3, 2, 0, 0, 0, '', 'Show options for gossip only if BOSS_KOLOGARN done'), +(15, 10389, 10, 0, 0, 13, 1, 6, 3, 2, 0, 0, 0, '', 'Show options for gossip only if BOSS_AURIAYA done'), +(15, 10389, 15, 0, 0, 13, 1, 14, 3, 2, 0, 0, 0, '', 'Show options for gossip only if BOSS_VEZAX done'); diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index aff3c0a9528..8401ea4b9a5 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -20,7 +20,6 @@ set(scripts_STAT_SRCS Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp Northrend/Ulduar/HallsOfLightning/boss_loken.cpp Northrend/Ulduar/Ulduar/boss_general_vezax.cpp - Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp Northrend/Ulduar/Ulduar/boss_thorim.cpp Northrend/Ulduar/Ulduar/boss_ignis.cpp Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp deleted file mode 100644 index 9fc0e4056fa..00000000000 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 - * - * 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 . - */ - -#include "ScriptMgr.h" -#include "ScriptedGossip.h" -#include "InstanceScript.h" -#include "Player.h" -#include "ulduar.h" - -/* -The teleporter appears to be active and stable. - -- Expedition Base Camp -- Formation Grounds -- Colossal Forge -- Scrapyard -- Antechamber of Ulduar -- Shattered Walkway -- Conservatory of Life -*/ - -enum UlduarTeleporter -{ - BASE_CAMP = 200, - GROUNDS = 201, - FORGE = 202, - SCRAPYARD = 203, - ANTECHAMBER = 204, - WALKWAY = 205, - CONSERVATORY = 206, -}; - -class ulduar_teleporter : public GameObjectScript -{ - public: - ulduar_teleporter() : GameObjectScript("ulduar_teleporter") { } - - bool OnGossipSelect(Player* player, GameObject* /*gameObject*/, uint32 sender, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (sender != GOSSIP_SENDER_MAIN) - return false; - if (!player->getAttackers().empty()) - return false; - - switch (action) - { - case BASE_CAMP: - player->TeleportTo(603, -706.122f, -92.6024f, 429.876f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case GROUNDS: - player->TeleportTo(603, 131.248f, -35.3802f, 409.804f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case FORGE: - player->TeleportTo(603, 553.233f, -12.3247f, 409.679f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case SCRAPYARD: - player->TeleportTo(603, 926.292f, -11.4635f, 418.595f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case ANTECHAMBER: - player->TeleportTo(603, 1498.09f, -24.246f, 420.967f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case WALKWAY: - player->TeleportTo(603, 1859.45f, -24.1f, 448.9f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - case CONSERVATORY: - player->TeleportTo(603, 2086.27f, -24.3134f, 421.239f, 0.0f); - player->CLOSE_GOSSIP_MENU(); - break; - } - - return true; - } - - bool OnGossipHello(Player* player, GameObject* gameObject) override - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Expedition Base Camp", GOSSIP_SENDER_MAIN, BASE_CAMP); - if (InstanceScript* instance = gameObject->GetInstanceScript()) - { - if (instance->GetData(DATA_COLOSSUS) == 2) //count of 2 collossus death - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Formation Grounds", GOSSIP_SENDER_MAIN, GROUNDS); - if (instance->GetBossState(BOSS_LEVIATHAN) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Colossal Forge", GOSSIP_SENDER_MAIN, FORGE); - if (instance->GetBossState(BOSS_XT002) == DONE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Scrapyard", GOSSIP_SENDER_MAIN, SCRAPYARD); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Antechamber of Ulduar", GOSSIP_SENDER_MAIN, ANTECHAMBER); - } - if (instance->GetBossState(BOSS_KOLOGARN) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Shattered Walkway", GOSSIP_SENDER_MAIN, WALKWAY); - if (instance->GetBossState(BOSS_AURIAYA) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport to the Conservatory of Life", GOSSIP_SENDER_MAIN, CONSERVATORY); - } - - player->SEND_GOSSIP_MENU(gameObject->GetGOInfo()->GetGossipMenuId(), gameObject->GetGUID()); - return true; - } -}; - -void AddSC_ulduar_teleporter() -{ - new ulduar_teleporter(); -} -- cgit v1.2.3 From 880253a833b8cc3061064d0c9d51385a42fe0ddb Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 14 Jun 2014 20:12:38 +0200 Subject: Core/SAI: Fix typo in 2596f1f35d01a8a6c8a555a5952c055a4d4dc239 --- src/server/game/AI/SmartScripts/SmartScript.cpp | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 0946ad3ef16..d44ef3c7d86 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -494,41 +494,41 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { - if (IsUnit(*itr)) + if (!IsUnit(*itr)) + continue; + + if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) { - if (!(e.action.cast.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.cast.spell)) + if (me) { - if (me) - { - if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) - me->InterruptNonMeleeSpells(false); + if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS) + me->InterruptNonMeleeSpells(false); - if (e.action.cast.flags & SMARTCAST_COMBAT_MOVE) - { - // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed - // unless target is outside spell range, out of mana, or LOS. + if (e.action.cast.flags & SMARTCAST_COMBAT_MOVE) + { + // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed + // unless target is outside spell range, out of mana, or LOS. - bool _allowMove = false; - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); - int32 mana = me->GetPower(POWER_MANA); + bool _allowMove = false; + SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); + int32 mana = me->GetPower(POWER_MANA); - if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) || - me->GetDistance(*itr) < spellInfo->GetMinRange(true) || - !me->IsWithinLOSInMap(*itr) || - mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask())) - _allowMove = true; + if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) || + me->GetDistance(*itr) < spellInfo->GetMinRange(true) || + !me->IsWithinLOSInMap(*itr) || + mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask())) + _allowMove = true; - CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); - } - - me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); + CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); } - else if (go) - go->CastSpell((*itr)->ToUnit(), e.action.cast.spell); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: %s: %u casts spell %u on target %u with castflags %u", - GetLogNameForGuid(me ? me->GetGUID() : go->GetGUID()), me ? me->GetGUIDLow() : go->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); + me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); } + else if (go) + go->CastSpell((*itr)->ToUnit(), e.action.cast.spell); + + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: %s: %u casts spell %u on target %u with castflags %u", + GetLogNameForGuid(me ? me->GetGUID() : go->GetGUID()), me ? me->GetGUIDLow() : go->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); } else TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); -- cgit v1.2.3 From 69135ba056e68d32fea3621d123d2da88454b95e Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 14 Jun 2014 20:14:17 +0200 Subject: Core: Fix build --- src/server/game/Scripting/ScriptLoader.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 7365d592a62..07db809c124 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -469,7 +469,6 @@ void AddSC_boss_xt002(); void AddSC_boss_kologarn(); void AddSC_boss_assembly_of_iron(); void AddSC_boss_general_vezax(); -void AddSC_ulduar_teleporter(); void AddSC_boss_mimiron(); void AddSC_boss_hodir(); void AddSC_boss_freya(); @@ -1309,7 +1308,6 @@ void AddNorthrendScripts() AddSC_boss_general_vezax(); AddSC_boss_assembly_of_iron(); AddSC_boss_kologarn(); - AddSC_ulduar_teleporter(); AddSC_boss_mimiron(); AddSC_boss_hodir(); AddSC_boss_freya(); -- cgit v1.2.3 From 53caf7959efb6a7f410b17306a5cc23028824fa5 Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 14 Jun 2014 22:01:50 +0200 Subject: Core/Ulduar: Added IsInCombat check for ulduar teleporter --- .../2014_06_14_02_world_spell_script_names.sql | 9 ++++++ src/server/game/AI/SmartScripts/SmartScript.cpp | 2 +- src/server/game/Entities/GameObject/GameObject.cpp | 10 +++--- src/server/game/Entities/GameObject/GameObject.h | 2 +- .../Northrend/Ulduar/Ulduar/instance_ulduar.cpp | 36 ++++++++++++++++++++++ 5 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 sql/updates/world/2014_06_14_02_world_spell_script_names.sql (limited to 'src') diff --git a/sql/updates/world/2014_06_14_02_world_spell_script_names.sql b/sql/updates/world/2014_06_14_02_world_spell_script_names.sql new file mode 100644 index 00000000000..53b1f2f6286 --- /dev/null +++ b/sql/updates/world/2014_06_14_02_world_spell_script_names.sql @@ -0,0 +1,9 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_ulduar_teleporter'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(64014, 'spell_ulduar_teleporter'), +(64032, 'spell_ulduar_teleporter'), +(64028, 'spell_ulduar_teleporter'), +(64030, 'spell_ulduar_teleporter'), +(64029, 'spell_ulduar_teleporter'), +(64025, 'spell_ulduar_teleporter'), +(65042, 'spell_ulduar_teleporter'); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index d44ef3c7d86..114a48c60ca 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -525,7 +525,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); } else if (go) - go->CastSpell((*itr)->ToUnit(), e.action.cast.spell); + go->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: %s: %u casts spell %u on target %u with castflags %u", GetLogNameForGuid(me ? me->GetGUID() : go->GetGUID()), me ? me->GetGUIDLow() : go->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 69b15c2b56b..0eb47820837 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1312,7 +1312,7 @@ void GameObject::Use(Unit* user) } else if (info->goober.gossipID) { - player->PrepareGossipMenu(this, info->goober.gossipID); + player->PrepareGossipMenu(this, info->goober.gossipID, true); player->SendPreparedGossip(this); } @@ -1747,7 +1747,7 @@ void GameObject::Use(Unit* user) CastSpell(user, spellId); } -void GameObject::CastSpell(Unit* target, uint32 spellId) +void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /*= true*/) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) @@ -1766,7 +1766,7 @@ void GameObject::CastSpell(Unit* target, uint32 spellId) if (self) { if (target) - target->CastSpell(target, spellInfo, true); + target->CastSpell(target, spellInfo, triggered); return; } @@ -1780,14 +1780,14 @@ void GameObject::CastSpell(Unit* target, uint32 spellId) trigger->setFaction(owner->getFaction()); // needed for GO casts for proper target validation checks trigger->SetOwnerGUID(owner->GetGUID()); - trigger->CastSpell(target ? target : trigger, spellInfo, true, 0, 0, owner->GetGUID()); + trigger->CastSpell(target ? target : trigger, spellInfo, triggered, 0, 0, owner->GetGUID()); } else { trigger->setFaction(14); // 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); + trigger->CastSpell(target ? target : trigger, spellInfo, triggered, 0, 0, target ? target->GetGUID() : 0); } } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 7aa3a01016b..8f70fc0e907 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -791,7 +791,7 @@ class GameObject : public WorldObject, public GridObject, public Map GameObject* LookupFishingHoleAround(float range); - void CastSpell(Unit* target, uint32 spell); + void CastSpell(Unit* target, uint32 spell, bool triggered = true); void SendCustomAnim(uint32 anim); bool IsInRange(float x, float y, float z, float radius) const; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index d728bc2a898..38bccf0bd15 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -1094,7 +1094,43 @@ class instance_ulduar : public InstanceMapScript } }; +class spell_ulduar_teleporter : public SpellScriptLoader +{ + public: + spell_ulduar_teleporter() : SpellScriptLoader("spell_ulduar_teleporter") { } + + class spell_ulduar_teleporter_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ulduar_teleporter_SpellScript); + + SpellCastResult CheckRequirement() + { + if (GetExplTargetUnit()->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_DONT_REPORT; + + if (GetExplTargetUnit()->IsInCombat()) + { + Spell::SendCastResult(GetExplTargetUnit()->ToPlayer(), GetSpellInfo(), 0, SPELL_FAILED_AFFECTING_COMBAT); + return SPELL_FAILED_AFFECTING_COMBAT; + } + + return SPELL_CAST_OK; + } + + void Register() override + { + OnCheckCast += SpellCheckCastFn(spell_ulduar_teleporter_SpellScript::CheckRequirement); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ulduar_teleporter_SpellScript(); + } +}; + void AddSC_instance_ulduar() { new instance_ulduar(); + new spell_ulduar_teleporter(); } -- cgit v1.2.3 From b7e0c2251e650a7a526ef9f0742024fd2db09ddb Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 14 Jun 2014 22:04:24 +0200 Subject: Core: Fix fail --- src/server/game/Entities/GameObject/GameObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 0eb47820837..ae08a4251a5 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1312,7 +1312,7 @@ void GameObject::Use(Unit* user) } else if (info->goober.gossipID) { - player->PrepareGossipMenu(this, info->goober.gossipID, true); + player->PrepareGossipMenu(this, info->goober.gossipID); player->SendPreparedGossip(this); } -- cgit v1.2.3 From 3a8b5179fa552c31062f412d1b4e27438941c362 Mon Sep 17 00:00:00 2001 From: MitchesD Date: Sat, 14 Jun 2014 21:41:54 +0200 Subject: Scripts/Commands: added option to show flags_extra (.npc info) --- .../world/2014_06_14_04_world_trinity_string.sql | 3 +++ src/server/game/Miscellaneous/Language.h | 3 ++- src/server/scripts/Commands/cs_npc.cpp | 25 ++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 sql/updates/world/2014_06_14_04_world_trinity_string.sql (limited to 'src') diff --git a/sql/updates/world/2014_06_14_04_world_trinity_string.sql b/sql/updates/world/2014_06_14_04_world_trinity_string.sql new file mode 100644 index 00000000000..b110a7de6d2 --- /dev/null +++ b/sql/updates/world/2014_06_14_04_world_trinity_string.sql @@ -0,0 +1,3 @@ +DELETE FROM `trinity_string` WHERE `entry`=11009; +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(11009, 'Flags Extra: %u'); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 34871085157..3a680e30217 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1224,7 +1224,8 @@ enum TrinityStrings LANG_BAN_ACCOUNT_YOUBANNEDMESSAGE_WORLD = 11006, LANG_BAN_ACCOUNT_YOUPERMBANNEDMESSAGE_WORLD = 11007, - LANG_NPCINFO_INHABIT_TYPE = 11008 + LANG_NPCINFO_INHABIT_TYPE = 11008, + LANG_NPCINFO_FLAGS_EXTRA = 11009 // NOT RESERVED IDS 12000-1999999999 // `db_script_string` table index 2000000000-2000009999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 28d49fe11aa..9cf8c041883 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -43,6 +43,7 @@ struct EnumName #define CREATE_NAMED_ENUM(VALUE) { VALUE, STRINGIZE(VALUE) } #define NPCFLAG_COUNT 24 +#define FLAGS_EXTRA_COUNT 16 EnumName const npcFlagTexts[NPCFLAG_COUNT] = { @@ -144,6 +145,26 @@ EnumName const unitFlags[MAX_UNIT_FLAGS] = CREATE_NAMED_ENUM(UNIT_FLAG_UNK_31) }; +EnumName const flagsExtra[FLAGS_EXTRA_COUNT] = +{ + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_INSTANCE_BIND), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_CIVILIAN), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_PARRY), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_BLOCK), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_CRUSH), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_XP_AT_KILL), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_TRIGGER), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_TAUNT), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_WORLDEVENT), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_GUARD), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_CRIT), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_NO_SKILLGAIN), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_TAUNT_DIMINISH), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_ALL_DIMINISH), + CREATE_NAMED_ENUM(CREATURE_FLAG_EXTRA_DUNGEON_BOSS) +}; + class npc_commandscript : public CommandScript { public: @@ -730,6 +751,10 @@ public: handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); handler->PSendSysMessage(LANG_NPCINFO_POSITION, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()); handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str()); + handler->PSendSysMessage(LANG_NPCINFO_FLAGS_EXTRA, cInfo->flags_extra); + for (uint8 i = 0; i < FLAGS_EXTRA_COUNT; ++i) + if (cInfo->flags_extra & flagsExtra[i].Value) + handler->PSendSysMessage("%s (0x%X)", flagsExtra[i].Name, flagsExtra[i].Value); for (uint8 i = 0; i < NPCFLAG_COUNT; i++) if (npcflags & npcFlagTexts[i].Value) -- cgit v1.2.3 From 1c80e441a06160f8f13398955e9681112bb744ae Mon Sep 17 00:00:00 2001 From: Vincent-Michael Date: Sat, 14 Jun 2014 23:33:20 +0200 Subject: Core: Fix non pch build --- sql/updates/world/2014_06_14_03_world_smart_scripts.sql | 1 + sql/updates/world/2014_06_14_03_world_spell_smart_scripts.sql | 1 - src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 sql/updates/world/2014_06_14_03_world_smart_scripts.sql delete mode 100644 sql/updates/world/2014_06_14_03_world_spell_smart_scripts.sql (limited to 'src') diff --git a/sql/updates/world/2014_06_14_03_world_smart_scripts.sql b/sql/updates/world/2014_06_14_03_world_smart_scripts.sql new file mode 100644 index 00000000000..ffd0ed03963 --- /dev/null +++ b/sql/updates/world/2014_06_14_03_world_smart_scripts.sql @@ -0,0 +1 @@ +UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=6221 AND `id` IN (9,10); diff --git a/sql/updates/world/2014_06_14_03_world_spell_smart_scripts.sql b/sql/updates/world/2014_06_14_03_world_spell_smart_scripts.sql deleted file mode 100644 index ffd0ed03963..00000000000 --- a/sql/updates/world/2014_06_14_03_world_spell_smart_scripts.sql +++ /dev/null @@ -1 +0,0 @@ -UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=6221 AND `id` IN (9,10); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 38bccf0bd15..6437a76ee95 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -18,9 +18,10 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "InstanceScript.h" -#include "ulduar.h" #include "Player.h" #include "WorldPacket.h" +#include "SpellScript.h" +#include "ulduar.h" static DoorData const doorData[] = { -- cgit v1.2.3 From 4615aa60a55bd6e117e2907869ee91a86427dad4 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Sun, 15 Jun 2014 14:49:03 +0100 Subject: Core/Spells: Define and implement CAST_FLAG_NO_GCD --- src/server/game/Spells/Spell.cpp | 12 ++++++------ src/server/game/Spells/Spell.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index c85fb0584cc..1bee73156c5 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3231,7 +3231,7 @@ void Spell::handle_immediate() // Apply duration mod if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); - + // Apply haste mods m_caster->ModSpellCastTime(m_spellInfo, duration, this); @@ -3762,7 +3762,7 @@ void Spell::SendSpellStart() castFlags |= CAST_FLAG_POWER_LEFT_SELF; if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE) - castFlags |= CAST_FLAG_UNKNOWN_19; + castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); if (m_CastItem) @@ -3820,19 +3820,19 @@ void Spell::SendSpellGo() && m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE) { - castFlags |= CAST_FLAG_UNKNOWN_19; // same as in SMSG_SPELL_START + castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list } if (m_spellInfo->HasEffect(SPELL_EFFECT_ACTIVATE_RUNE)) - { castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list - castFlags |= CAST_FLAG_UNKNOWN_19; // same as in SMSG_SPELL_START - } if (m_targets.HasTraj()) castFlags |= CAST_FLAG_ADJUST_MISSILE; + if (!m_spellInfo->StartRecoveryTime) + castFlags |= CAST_FLAG_NO_GCD; + WorldPacket data(SMSG_SPELL_GO, 50); // guess size if (m_CastItem) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 341867ff787..584c20fdfb3 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -57,7 +57,7 @@ enum SpellCastFlags CAST_FLAG_UNKNOWN_16 = 0x00008000, CAST_FLAG_UNKNOWN_17 = 0x00010000, CAST_FLAG_ADJUST_MISSILE = 0x00020000, - CAST_FLAG_UNKNOWN_19 = 0x00040000, + CAST_FLAG_NO_GCD = 0x00040000, // no GCD for spell casts from charm/summon (vehicle spells is an example) CAST_FLAG_VISUAL_CHAIN = 0x00080000, CAST_FLAG_UNKNOWN_21 = 0x00100000, CAST_FLAG_RUNE_LIST = 0x00200000, -- cgit v1.2.3 From 4e81e3c194d74e0330812c9da7dd9b1863941c6e Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Sun, 15 Jun 2014 14:57:04 +0100 Subject: Core/Vehicles: Define and implement VEHICLE_SEAT_FLAG_B_KEEP_PET --- src/server/game/DataStores/DBCEnums.h | 1 + src/server/game/Entities/Vehicle/Vehicle.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index ec048e167ac..8e186e9d094 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -442,6 +442,7 @@ enum VehicleSeatFlagsB VEHICLE_SEAT_FLAG_B_EJECTABLE = 0x00000020, // ejectable VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 = 0x00000040, VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 = 0x00000100, + VEHICLE_SEAT_FLAG_B_KEEP_PET = 0x00020000, 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/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index f3b4e6de70c..915e6016e22 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -779,6 +779,8 @@ bool VehicleJoinEvent::Execute(uint64, uint32) Passenger->InterruptNonMeleeSpells(false); Passenger->RemoveAurasByType(SPELL_AURA_MOUNTED); + VehicleSeatEntry const* veSeat = Seat->second.SeatInfo; + Player* player = Passenger->ToPlayer(); if (player) { @@ -789,14 +791,14 @@ bool VehicleJoinEvent::Execute(uint64, uint32) player->StopCastingCharm(); player->StopCastingBindSight(); player->SendOnCancelExpectedVehicleRideAura(); - player->UnsummonPetTemporaryIfAny(); + if (!(veSeat->m_flagsB & VEHICLE_SEAT_FLAG_B_KEEP_PET)) + player->UnsummonPetTemporaryIfAny(); } if (Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE) Passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Passenger->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); - VehicleSeatEntry const* veSeat = Seat->second.SeatInfo; Passenger->m_movementInfo.transport.pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); Passenger->m_movementInfo.transport.time = 0; Passenger->m_movementInfo.transport.seat = Seat->first; -- cgit v1.2.3 From aca3795fa7be19ffaf25d919c79e4a98bef87148 Mon Sep 17 00:00:00 2001 From: Trisjdc Date: Sun, 15 Jun 2014 15:00:56 +0100 Subject: Core/Spells: Skip adding CAST_FLAG_RUNE_LIST to rune spells if it's a triggered cast. Solves some of the occasional Death Knight rune visual issues --- src/server/game/Spells/Spell.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1bee73156c5..48c2a76578d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3818,7 +3818,8 @@ void Spell::SendSpellGo() if ((m_caster->GetTypeId() == TYPEID_PLAYER) && (m_caster->getClass() == CLASS_DEATH_KNIGHT) && m_spellInfo->RuneCostID - && m_spellInfo->PowerType == POWER_RUNE) + && m_spellInfo->PowerType == POWER_RUNE + && !(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)) { castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list -- cgit v1.2.3 From 7b3141bfde021f09d9d28eda2467262026a30ba1 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Sun, 15 Jun 2014 17:41:42 +0200 Subject: Scripts/Gurtogg: * fixed bloodboil targeting * fel rage should only hit players Closes #12193 --- .../2014_06_15_00_world_spell_script_names.sql | 3 + .../scripts/Outland/BlackTemple/boss_bloodboil.cpp | 333 --------------------- .../Outland/BlackTemple/boss_gurtogg_bloodboil.cpp | 318 ++++++++++++++++++++ src/server/scripts/Outland/CMakeLists.txt | 2 +- 4 files changed, 322 insertions(+), 334 deletions(-) create mode 100644 sql/updates/world/2014_06_15_00_world_spell_script_names.sql delete mode 100644 src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp (limited to 'src') diff --git a/sql/updates/world/2014_06_15_00_world_spell_script_names.sql b/sql/updates/world/2014_06_15_00_world_spell_script_names.sql new file mode 100644 index 00000000000..84123740083 --- /dev/null +++ b/sql/updates/world/2014_06_15_00_world_spell_script_names.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `spell_id`=42005; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(42005, 'spell_gurtogg_bloodboil_bloodboil'); diff --git a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp deleted file mode 100644 index 0004df68016..00000000000 --- a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 - * - * 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 . - */ - -/* ScriptData -SDName: Boss_Bloodboil -SD%Complete: 80 -SDComment: Bloodboil not working correctly, missing enrage -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "black_temple.h" - -enum Bloodboil -{ - //Speech'n'Sound - SAY_AGGRO = 0, - SAY_SLAY = 1, - SAY_SPECIAL = 2, - SAY_ENRAGE = 3, - SAY_DEATH = 4, - - //Spells - SPELL_ACID_GEYSER = 40630, - SPELL_ACIDIC_WOUND = 40481, - SPELL_ARCING_SMASH = 40599, - SPELL_BLOODBOIL = 42005, // This spell is AoE whereas it shouldn't be - SPELL_FEL_ACID = 40508, - SPELL_FEL_RAGE_SELF = 40594, - SPELL_FEL_RAGE_TARGET = 40604, - SPELL_FEL_RAGE_2 = 40616, - SPELL_FEL_RAGE_3 = 41625, - SPELL_BEWILDERING_STRIKE = 40491, - SPELL_EJECT1 = 40486, // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) - SPELL_EJECT2 = 40597, // 1000 Physical damage + Stun (used in phase 2?) - SPELL_TAUNT_GURTOGG = 40603, - SPELL_INSIGNIFIGANCE = 40618, - SPELL_BERSERK = 45078 -}; - - -//This is used to sort the players by distance in preparation for the Bloodboil cast. - -class boss_gurtogg_bloodboil : public CreatureScript -{ -public: - boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } - - struct boss_gurtogg_bloodboilAI : public ScriptedAI - { - boss_gurtogg_bloodboilAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; - - uint64 TargetGUID; - - float TargetThreat; - - uint32 BloodboilTimer; - uint32 BloodboilCount; - uint32 AcidGeyserTimer; - uint32 AcidicWoundTimer; - uint32 ArcingSmashTimer; - uint32 EnrageTimer; - uint32 FelAcidTimer; - uint32 EjectTimer; - uint32 BewilderingStrikeTimer; - uint32 PhaseChangeTimer; - - bool Phase1; - - void Reset() override - { - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, NOT_STARTED); - - TargetGUID = 0; - - TargetThreat = 0; - - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidGeyserTimer = 1000; - AcidicWoundTimer = 6000; - ArcingSmashTimer = 19000; - EnrageTimer = 600000; - FelAcidTimer = 25000; - EjectTimer = 10000; - BewilderingStrikeTimer = 15000; - PhaseChangeTimer = 60000; - - Phase1 = true; - - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); - } - - void EnterCombat(Unit* /*who*/) override - { - DoZoneInCombat(); - Talk(SAY_AGGRO); - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_SLAY); - } - - void JustDied(Unit* /*killer*/) override - { - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, DONE); - - Talk(SAY_DEATH); - } - - // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. - void CastBloodboil() - { - // Get the Threat List - std::list m_threatlist = me->getThreatManager().getThreatList(); - - if (m_threatlist.empty()) // He doesn't have anyone in his threatlist, useless to continue - return; - - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container - { - Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (target && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER) - targets.push_back(target); - } - - //Sort the list of players - targets.sort(Trinity::ObjectDistanceOrderPred(me, false)); - //Resize so we only get top 5 - targets.resize(5); - - //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp - /*SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_BLOODBOIL); - if (spellInfo) - { - for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - { - Unit* target = *itr; - if (!target) return; - for (uint32 i = 0; i<3; ++i) - { - uint8 eff = spellInfo->Effect[i]; - if (eff >= TOTAL_SPELL_EFFECTS) - continue; - - Aura* Aur = new Aura(spellInfo, i, target, target, target); - target->AddAura(Aur); - } - } - }*/ - } - - void RevertThreatOnTarget(uint64 guid) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, guid)) - { - if (DoGetThreat(unit)) - DoModifyThreatPercent(unit, -100); - if (TargetThreat) - me->AddThreat(unit, TargetThreat); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (ArcingSmashTimer <= diff) - { - DoCastVictim(SPELL_ARCING_SMASH); - ArcingSmashTimer = 10000; - } else ArcingSmashTimer -= diff; - - if (FelAcidTimer <= diff) - { - DoCastVictim(SPELL_FEL_ACID); - FelAcidTimer = 25000; - } else FelAcidTimer -= diff; - - if (!me->HasAura(SPELL_BERSERK)) - { - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - Talk(SAY_ENRAGE); - } else EnrageTimer -= diff; - } - - if (Phase1) - { - if (BewilderingStrikeTimer <= diff) - { - DoCastVictim(SPELL_BEWILDERING_STRIKE); - float mt_threat = DoGetThreat(me->GetVictim()); - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) - me->AddThreat(target, mt_threat); - BewilderingStrikeTimer = 20000; - } else BewilderingStrikeTimer -= diff; - - if (EjectTimer <= diff) - { - DoCastVictim(SPELL_EJECT1); - DoModifyThreatPercent(me->GetVictim(), -40); - EjectTimer = 15000; - } else EjectTimer -= diff; - - if (AcidicWoundTimer <= diff) - { - DoCastVictim(SPELL_ACIDIC_WOUND); - AcidicWoundTimer = 10000; - } else AcidicWoundTimer -= diff; - - if (BloodboilTimer <= diff) - { - if (BloodboilCount < 5) // Only cast it five times. - { - //CastBloodboil(); // Causes issues on windows, so is commented out. - DoCastVictim(SPELL_BLOODBOIL); - ++BloodboilCount; - BloodboilTimer = 10000*BloodboilCount; - } - } else BloodboilTimer -= diff; - } - - if (!Phase1) - { - if (AcidGeyserTimer <= diff) - { - DoCastVictim(SPELL_ACID_GEYSER); - AcidGeyserTimer = 30000; - } else AcidGeyserTimer -= diff; - - if (EjectTimer <= diff) - { - DoCastVictim(SPELL_EJECT2); - EjectTimer = 15000; - } else EjectTimer -= diff; - } - - if (PhaseChangeTimer <= diff) - { - if (Phase1) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - Phase1 = false; - - TargetThreat = DoGetThreat(target); - TargetGUID = target->GetGUID(); - target->CastSpell(me, SPELL_TAUNT_GURTOGG, true); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -100); - me->AddThreat(target, 50000000.0f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); - // If VMaps are disabled, this spell can call the whole instance - DoCast(me, SPELL_INSIGNIFIGANCE, true); - DoCast(target, SPELL_FEL_RAGE_TARGET, true); - DoCast(target, SPELL_FEL_RAGE_2, true); - /* These spells do not work, comment them out for now. - DoCast(target, SPELL_FEL_RAGE_2, true); - DoCast(target, SPELL_FEL_RAGE_3, true);*/ - - //Cast this without triggered so that it appears in combat logs and shows visual. - DoCast(me, SPELL_FEL_RAGE_SELF); - - Talk(SAY_SPECIAL); - - AcidGeyserTimer = 1000; - PhaseChangeTimer = 30000; - } - } - else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage - { - if (TargetGUID) - RevertThreatOnTarget(TargetGUID); - TargetGUID = 0; - Phase1 = true; - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidicWoundTimer += 2000; - ArcingSmashTimer += 2000; - FelAcidTimer += 2000; - EjectTimer += 2000; - PhaseChangeTimer = 60000; - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); - } - } else PhaseChangeTimer -= diff; - - DoMeleeAttackIfReady(); - } - }; - -}; - -void AddSC_boss_gurtogg_bloodboil() -{ - new boss_gurtogg_bloodboil(); -} diff --git a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp new file mode 100644 index 00000000000..f03caa37cb2 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * Copyright (C) 2006-2009 ScriptDev2 + * + * 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 . + */ + +/* ScriptData +Name: Boss_Bloodboil +Complete: 80 +Category: Black Temple +EndScriptData */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "black_temple.h" + +enum Bloodboil +{ + //Speech'n'Sound + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_SPECIAL = 2, + SAY_ENRAGE = 3, + SAY_DEATH = 4, + + //Spells + SPELL_ACID_GEYSER = 40630, + SPELL_ACIDIC_WOUND = 40481, + SPELL_ARCING_SMASH = 40599, + SPELL_BLOODBOIL = 42005, // This spell is AoE whereas it shouldn't be + SPELL_FEL_ACID = 40508, + SPELL_FEL_RAGE_SELF = 40594, + SPELL_FEL_RAGE_TARGET = 40604, + SPELL_FEL_RAGE_2 = 40616, + SPELL_FEL_RAGE_3 = 41625, + SPELL_BEWILDERING_STRIKE = 40491, + SPELL_EJECT1 = 40486, // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) + SPELL_EJECT2 = 40597, // 1000 Physical damage + Stun (used in phase 2?) + SPELL_TAUNT_GURTOGG = 40603, + SPELL_INSIGNIFIGANCE = 40618, + SPELL_BERSERK = 45078 +}; + +class boss_gurtogg_bloodboil : public CreatureScript +{ +public: + boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { } + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } + + struct boss_gurtogg_bloodboilAI : public ScriptedAI + { + boss_gurtogg_bloodboilAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + } + + InstanceScript* instance; + + uint64 TargetGUID; + + float TargetThreat; + + uint32 BloodboilTimer; + uint32 BloodboilCount; + uint32 AcidGeyserTimer; + uint32 AcidicWoundTimer; + uint32 ArcingSmashTimer; + uint32 EnrageTimer; + uint32 FelAcidTimer; + uint32 EjectTimer; + uint32 BewilderingStrikeTimer; + uint32 PhaseChangeTimer; + + bool Phase1; + + void Reset() override + { + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, NOT_STARTED); + + TargetGUID = 0; + + TargetThreat = 0; + + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidGeyserTimer = 1000; + AcidicWoundTimer = 6000; + ArcingSmashTimer = 19000; + EnrageTimer = 600000; + FelAcidTimer = 25000; + EjectTimer = 10000; + BewilderingStrikeTimer = 15000; + PhaseChangeTimer = 60000; + + Phase1 = true; + + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + Talk(SAY_AGGRO); + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_SLAY); + } + + void JustDied(Unit* /*killer*/) override + { + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, DONE); + + Talk(SAY_DEATH); + } + + void RevertThreatOnTarget(uint64 guid) + { + if (Unit* unit = ObjectAccessor::GetUnit(*me, guid)) + { + if (DoGetThreat(unit)) + DoModifyThreatPercent(unit, -100); + if (TargetThreat) + me->AddThreat(unit, TargetThreat); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (ArcingSmashTimer <= diff) + { + DoCastVictim(SPELL_ARCING_SMASH); + ArcingSmashTimer = 10000; + } else ArcingSmashTimer -= diff; + + if (FelAcidTimer <= diff) + { + DoCastVictim(SPELL_FEL_ACID); + FelAcidTimer = 25000; + } else FelAcidTimer -= diff; + + if (!me->HasAura(SPELL_BERSERK)) + { + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + Talk(SAY_ENRAGE); + } else EnrageTimer -= diff; + } + + if (Phase1) + { + if (BewilderingStrikeTimer <= diff) + { + DoCastVictim(SPELL_BEWILDERING_STRIKE); + float mt_threat = DoGetThreat(me->GetVictim()); + if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) + me->AddThreat(target, mt_threat); + BewilderingStrikeTimer = 20000; + } else BewilderingStrikeTimer -= diff; + + if (EjectTimer <= diff) + { + DoCastVictim(SPELL_EJECT1); + DoModifyThreatPercent(me->GetVictim(), -40); + EjectTimer = 15000; + } else EjectTimer -= diff; + + if (AcidicWoundTimer <= diff) + { + DoCastVictim(SPELL_ACIDIC_WOUND); + AcidicWoundTimer = 10000; + } else AcidicWoundTimer -= diff; + + if (BloodboilTimer <= diff) + { + if (BloodboilCount < 5) // Only cast it five times. + { + DoCastAOE(SPELL_BLOODBOIL); + ++BloodboilCount; + BloodboilTimer = 10000*BloodboilCount; + } + } else BloodboilTimer -= diff; + } + + if (!Phase1) + { + if (AcidGeyserTimer <= diff) + { + DoCastVictim(SPELL_ACID_GEYSER); + AcidGeyserTimer = 30000; + } else AcidGeyserTimer -= diff; + + if (EjectTimer <= diff) + { + DoCastVictim(SPELL_EJECT2); + EjectTimer = 15000; + } else EjectTimer -= diff; + } + + if (PhaseChangeTimer <= diff) + { + if (Phase1) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + { + Phase1 = false; + + TargetThreat = DoGetThreat(target); + TargetGUID = target->GetGUID(); + target->CastSpell(me, SPELL_TAUNT_GURTOGG, true); + if (DoGetThreat(target)) + DoModifyThreatPercent(target, -100); + me->AddThreat(target, 50000000.0f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + // If VMaps are disabled, this spell can call the whole instance + DoCast(me, SPELL_INSIGNIFIGANCE, true); + DoCast(target, SPELL_FEL_RAGE_TARGET, true); + DoCast(target, SPELL_FEL_RAGE_2, true); + /* These spells do not work, comment them out for now. + DoCast(target, SPELL_FEL_RAGE_2, true); + DoCast(target, SPELL_FEL_RAGE_3, true);*/ + + //Cast this without triggered so that it appears in combat logs and shows visual. + DoCast(me, SPELL_FEL_RAGE_SELF); + + Talk(SAY_SPECIAL); + + AcidGeyserTimer = 1000; + PhaseChangeTimer = 30000; + } + } + else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage + { + if (TargetGUID) + RevertThreatOnTarget(TargetGUID); + TargetGUID = 0; + Phase1 = true; + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidicWoundTimer += 2000; + ArcingSmashTimer += 2000; + FelAcidTimer += 2000; + EjectTimer += 2000; + PhaseChangeTimer = 60000; + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + } else PhaseChangeTimer -= diff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +// 42005 - Bloodboil +class spell_gurtogg_bloodboil_bloodboil : public SpellScriptLoader +{ + public: + spell_gurtogg_bloodboil_bloodboil() : SpellScriptLoader("spell_gurtogg_bloodboil_bloodboil") { } + + class spell_gurtogg_bloodboil_bloodboil_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gurtogg_bloodboil_bloodboil_SpellScript); + + void FilterTargets(std::list& targets) + { + if (targets.size() <= 5) + return; + + // Sort the list of players + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); + // Resize so we only get top 5 + targets.resize(5); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gurtogg_bloodboil_bloodboil_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gurtogg_bloodboil_bloodboil_SpellScript(); + } +}; + +void AddSC_boss_gurtogg_bloodboil() +{ + new boss_gurtogg_bloodboil(); + new spell_gurtogg_bloodboil_bloodboil(); +} diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt index 414a3bce14a..0c69a236ef8 100644 --- a/src/server/scripts/Outland/CMakeLists.txt +++ b/src/server/scripts/Outland/CMakeLists.txt @@ -112,7 +112,7 @@ set(scripts_STAT_SRCS Outland/BlackTemple/instance_black_temple.cpp Outland/BlackTemple/boss_reliquary_of_souls.cpp Outland/BlackTemple/boss_warlord_najentus.cpp - Outland/BlackTemple/boss_bloodboil.cpp + Outland/BlackTemple/boss_gurtogg_bloodboil.cpp Outland/BlackTemple/boss_illidan.cpp Outland/zone_shadowmoon_valley.cpp Outland/zone_blades_edge_mountains.cpp -- cgit v1.2.3 From e55835a6a9ae09dd4b65de494cba712c322a2419 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Sun, 15 Jun 2014 17:49:17 +0200 Subject: Core/Creature: load correct vehicleid of difficulty mode npcs if set otherwise inherit from normal mode entry Closes #8783 --- .../2014_06_15_01_world_creature_template.sql | 7 ++++++ src/server/game/Entities/Creature/Creature.cpp | 16 +++++++++---- src/server/game/Globals/ObjectMgr.cpp | 26 +++++++++++----------- 3 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 sql/updates/world/2014_06_15_01_world_creature_template.sql (limited to 'src') diff --git a/sql/updates/world/2014_06_15_01_world_creature_template.sql b/sql/updates/world/2014_06_15_01_world_creature_template.sql new file mode 100644 index 00000000000..48358811c94 --- /dev/null +++ b/sql/updates/world/2014_06_15_01_world_creature_template.sql @@ -0,0 +1,7 @@ +-- inherit vehicleid and accessory from normal mode npc +UPDATE `creature_template` SET `VehicleId`=0 WHERE `entry` IN ( +30935, -- Drakkari Rhino (1) +31749, -- Hover Disk (1) +31748, -- Hover Disk (1) +37626 -- Iceborn Proto-Drake (1) +); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 264cae7fa7b..c81ba409495 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1173,14 +1173,22 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 entry, CreatureData const* SetOriginalEntry(entry); - if (!vehId) - vehId = cinfo->VehicleId; - - Object::_Create(guidlow, entry, vehId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT); + Object::_Create(guidlow, entry, (vehId || cinfo->VehicleId) ? HIGHGUID_VEHICLE : HIGHGUID_UNIT); if (!UpdateEntry(entry, data)) return false; + if (!vehId) + { + if (GetCreatureTemplate()->VehicleId) + { + vehId = GetCreatureTemplate()->VehicleId; + entry = GetCreatureTemplate()->Entry; + } + else + vehId = cinfo->VehicleId; + } + if (vehId) CreateVehicleKit(vehId, entry); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 207f80eabe7..72ea1b16864 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2951,32 +2951,32 @@ void ObjectMgr::LoadVehicleTemplateAccessories() { Field* fields = result->Fetch(); - uint32 uiEntry = fields[0].GetUInt32(); - uint32 uiAccessory = fields[1].GetUInt32(); - int8 uiSeat = int8(fields[2].GetInt8()); - bool bMinion = fields[3].GetBool(); - uint8 uiSummonType = fields[4].GetUInt8(); - uint32 uiSummonTimer= fields[5].GetUInt32(); + uint32 entry = fields[0].GetUInt32(); + uint32 accessory = fields[1].GetUInt32(); + int8 seatId = fields[2].GetInt8(); + bool isMinion = fields[3].GetBool(); + uint8 summonType = fields[4].GetUInt8(); + uint32 summonTimer = fields[5].GetUInt32(); - if (!sObjectMgr->GetCreatureTemplate(uiEntry)) + if (!sObjectMgr->GetCreatureTemplate(entry)) { - TC_LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: creature template entry %u does not exist.", uiEntry); + TC_LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: creature template entry %u does not exist.", entry); continue; } - if (!sObjectMgr->GetCreatureTemplate(uiAccessory)) + if (!sObjectMgr->GetCreatureTemplate(accessory)) { - TC_LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: Accessory %u does not exist.", uiAccessory); + TC_LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: Accessory %u does not exist.", accessory); continue; } - if (_spellClickInfoStore.find(uiEntry) == _spellClickInfoStore.end()) + if (_spellClickInfoStore.find(entry) == _spellClickInfoStore.end()) { - TC_LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: creature template entry %u has no data in npc_spellclick_spells", uiEntry); + TC_LOG_ERROR("sql.sql", "Table `vehicle_template_accessory`: creature template entry %u has no data in npc_spellclick_spells", entry); continue; } - _vehicleTemplateAccessoryStore[uiEntry].push_back(VehicleAccessory(uiAccessory, uiSeat, bMinion, uiSummonType, uiSummonTimer)); + _vehicleTemplateAccessoryStore[entry].push_back(VehicleAccessory(accessory, seatId, isMinion, summonType, summonTimer)); ++count; } -- cgit v1.2.3