diff options
Diffstat (limited to 'src')
21 files changed, 256 insertions, 112 deletions
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 2a10da29c20..dc5a2768668 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -678,6 +678,9 @@ enum RBACPermissions RBAC_PERM_COMMAND_WP_UNLOAD = 772, RBAC_PERM_COMMAND_WP_RELOAD = 773, RBAC_PERM_COMMAND_WP_SHOW = 774, + RBAC_PERM_COMMAND_MODIFY_CURRENCY = 775, // only 4.3.4 + RBAC_PERM_COMMAND_DEBUG_PHASE = 776, // only 4.3.4 + RBAC_PERM_COMMAND_MAILBOX = 777, // custom permissions 1000+ RBAC_PERM_MAX diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4dab652d732..61768b0f84c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5127,7 +5127,10 @@ void Player::BuildPlayerRepop() // BG - remove insignia related RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); -// SendCorpseReclaimDelay(); + int32 corpseReclaimDelay = CalculateCorpseReclaimDelay(); + + if (corpseReclaimDelay >= 0) + SendCorpseReclaimDelay(corpseReclaimDelay); // to prevent cheating corpse->ResetGhostTime(); @@ -5235,7 +5238,11 @@ void Player::KillPlayer() m_deathTimer = 6 * MINUTE * IN_MILLISECONDS; UpdateCorpseReclaimDelay(); // dependent at use SetDeathPvP() call before kill - SendCorpseReclaimDelay(); + + int32 corpseReclaimDelay = CalculateCorpseReclaimDelay(); + + if (corpseReclaimDelay >= 0) + SendCorpseReclaimDelay(corpseReclaimDelay); // don't create corpse at this moment, player might be falling @@ -17452,8 +17459,9 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) UpdateHonorFields(); m_deathExpireTime = time_t(fields[36].GetUInt32()); - if (m_deathExpireTime > now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP) - m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP-1; + + if (m_deathExpireTime > now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP) + m_deathExpireTime = now + MAX_DEATH_COUNT * DEATH_EXPIRE_STEP - 1; // clear channel spell data (if saved at channel spell casting) SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0); @@ -23844,7 +23852,7 @@ uint32 Player::GetCorpseReclaimDelay(bool pvp) const time_t now = time(NULL); // 0..2 full period // should be ceil(x)-1 but not floor(x) - uint64 count = (now < m_deathExpireTime - 1) ? (m_deathExpireTime - 1 - now)/DEATH_EXPIRE_STEP : 0; + uint64 count = (now < m_deathExpireTime - 1) ? (m_deathExpireTime - 1 - now) / DEATH_EXPIRE_STEP : 0; return copseReclaimDelay[count]; } @@ -23857,65 +23865,66 @@ void Player::UpdateCorpseReclaimDelay() return; time_t now = time(NULL); + if (now < m_deathExpireTime) { // full and partly periods 1..3 - uint64 count = (m_deathExpireTime - now)/DEATH_EXPIRE_STEP +1; + uint64 count = (m_deathExpireTime - now) / DEATH_EXPIRE_STEP + 1; + if (count < MAX_DEATH_COUNT) - m_deathExpireTime = now+(count+1)*DEATH_EXPIRE_STEP; + m_deathExpireTime = now+(count + 1) * DEATH_EXPIRE_STEP; else - m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP; + m_deathExpireTime = now + MAX_DEATH_COUNT*DEATH_EXPIRE_STEP; } else - m_deathExpireTime = now+DEATH_EXPIRE_STEP; + m_deathExpireTime = now + DEATH_EXPIRE_STEP; } -void Player::SendCorpseReclaimDelay(bool load) +int32 Player::CalculateCorpseReclaimDelay(bool load) { Corpse* corpse = GetCorpse(); + if (load && !corpse) - return; + return -1; - bool pvp; - if (corpse) - pvp = (corpse->GetType() == CORPSE_RESURRECTABLE_PVP); - else - pvp = (m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH); + bool pvp = corpse ? corpse->GetType() == CORPSE_RESURRECTABLE_PVP : m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH; + + uint32 delay; - time_t delay; if (load) { if (corpse->GetGhostTime() > m_deathExpireTime) - return; + return -1; + + uint64 count = 0; - uint64 count; if ((pvp && sWorld->getBoolConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP)) || (!pvp && sWorld->getBoolConfig(CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE))) { - count = (m_deathExpireTime-corpse->GetGhostTime())/DEATH_EXPIRE_STEP; + count = (m_deathExpireTime - corpse->GetGhostTime()) / DEATH_EXPIRE_STEP; + if (count >= MAX_DEATH_COUNT) - count = MAX_DEATH_COUNT-1; + count = MAX_DEATH_COUNT - 1; } - else - count=0; - - time_t expected_time = corpse->GetGhostTime()+copseReclaimDelay[count]; + time_t expected_time = corpse->GetGhostTime() + copseReclaimDelay[count]; time_t now = time(NULL); + if (now >= expected_time) - return; + return -1; - delay = expected_time-now; + delay = expected_time - now; } else delay = GetCorpseReclaimDelay(pvp); - if (!delay) - return; + return delay * IN_MILLISECONDS; +} - //! corpse reclaim delay 30 * 1000ms or longer at often deaths +void Player::SendCorpseReclaimDelay(uint32 delay) +{ WorldPacket data(SMSG_CORPSE_RECLAIM_DELAY, 4); - data << uint32(delay*IN_MILLISECONDS); + data << uint32(delay); GetSession()->SendPacket(&data); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index cd73f38823e..1f5f9fee7d4 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1936,7 +1936,8 @@ class Player : public Unit, public GridObject<Player> uint32 GetDeathTimer() const { return m_deathTimer; } uint32 GetCorpseReclaimDelay(bool pvp) const; void UpdateCorpseReclaimDelay(); - void SendCorpseReclaimDelay(bool load = false); + int32 CalculateCorpseReclaimDelay(bool load = false); + void SendCorpseReclaimDelay(uint32 delay); uint32 GetShieldBlockValue() const; // overwrite Unit version (virtual) bool CanParry() const { return m_canParry; } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 151f20d09f9..9eef3b023e0 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -683,7 +683,8 @@ enum NPCFlags UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click) - UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000 // players with mounts that have vehicle data should have it set + UNIT_NPC_FLAG_PLAYER_VEHICLE = 0x02000000, // players with mounts that have vehicle data should have it set + UNIT_NPC_FLAG_MAILBOX = 0x04000000 // }; enum MovementFlags diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index fba575ee84e..45d4d221d06 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -235,18 +235,20 @@ void WorldSession::HandleCalendarAddEvent(WorldPacket& recvData) recvData.ReadPackedTime(unkPackedTime); recvData >> flags; - CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, 0, CalendarEventType(type), dungeonId, + CalendarEvent 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 = new CalendarInvite(0, calendarEvent->GetEventId(), 0, guid, 946684800, CALENDAR_STATUS_NOT_SIGNED_UP, CALENDAR_RANK_PLAYER, ""); - sCalendarMgr->AddInvite(calendarEvent, invite); + 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); } else { @@ -262,12 +264,12 @@ 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); + CalendarInvite* invite = new CalendarInvite(sCalendarMgr->GetFreeInviteId(), calendarEvent.GetEventId(), invitee, guid, 946684800, CalendarInviteStatus(status), CalendarModerationRank(rank), ""); + sCalendarMgr->AddInvite(&calendarEvent, invite); } } - sCalendarMgr->AddEvent(calendarEvent, CALENDAR_SENDTYPE_ADD); + sCalendarMgr->AddEvent(new CalendarEvent(calendarEvent, calendarEvent.GetEventId()), CALENDAR_SENDTYPE_ADD); } void WorldSession::HandleCalendarUpdateEvent(WorldPacket& recvData) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 94e9306b29f..4c7d1669233 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1590,9 +1590,6 @@ void WorldSession::HandleEquipmentSetDelete(WorldPacket &recvData) void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData) { - if (_player->IsInCombat()) - return; - TC_LOG_DEBUG("network", "CMSG_EQUIPMENT_SET_USE"); for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) @@ -1609,6 +1606,10 @@ void WorldSession::HandleEquipmentSetUse(WorldPacket &recvData) if (itemGuid == 1) continue; + // Only equip weapons in combat + if (_player->IsInCombat() && i != EQUIPMENT_SLOT_MAINHAND && i != EQUIPMENT_SLOT_OFFHAND && i != EQUIPMENT_SLOT_RANGED) + continue; + Item* item = _player->GetItemByGuid(itemGuid); uint16 dstpos = i | (INVENTORY_SLOT_BAG_0 << 8); diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 5ab24f44a22..10ef7810d1d 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -29,6 +29,32 @@ #include "Item.h" #include "AccountMgr.h" +bool WorldSession::CanOpenMailBox(uint64 guid) +{ + if (guid == _player->GetGUID()) + { + if (!HasPermission(rbac::RBAC_PERM_COMMAND_MAILBOX)) + { + TC_LOG_WARN("cheat", "%s attempt open mailbox in cheating way.", _player->GetName().c_str()); + return false; + } + } + else if (IS_GAMEOBJECT_GUID(guid)) + { + if (!_player->GetGameObjectIfCanInteractWith(guid, GAMEOBJECT_TYPE_MAILBOX)) + return false; + } + else if (IS_CRE_OR_VEH_OR_PET_GUID(guid)) + { + if (!_player->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_MAILBOX)) + return false; + } + else + return false; + + return true; +} + void WorldSession::HandleSendMail(WorldPacket& recvData) { uint64 mailbox, unk3; @@ -62,7 +88,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) // packet read complete, now do check - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; if (receiverName.empty()) @@ -307,7 +333,7 @@ void WorldSession::HandleMailMarkAsRead(WorldPacket& recvData) recvData >> mailbox; recvData >> mailId; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -331,7 +357,7 @@ void WorldSession::HandleMailDelete(WorldPacket& recvData) recvData >> mailId; recvData.read_skip<uint32>(); // mailTemplateId - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Mail* m = _player->GetMail(mailId); @@ -359,7 +385,7 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData) recvData >> mailId; recvData.read_skip<uint64>(); // original sender GUID for return to, not used - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -424,7 +450,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData) recvData >> mailId; recvData >> itemId; // item guid low - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -518,7 +544,7 @@ void WorldSession::HandleMailTakeMoney(WorldPacket& recvData) recvData >> mailbox; recvData >> mailId; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -555,7 +581,7 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData) uint64 mailbox; recvData >> mailbox; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; @@ -678,7 +704,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData) recvData >> mailbox; recvData >> mailId; - if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) + if (!CanOpenMailBox(mailbox)) return; Player* player = _player; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 8b92706bd06..fcec4f38852 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -734,34 +734,34 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket& recvData) uint64 guid; recvData >> guid; - if (GetPlayer()->IsAlive()) + if (_player->IsAlive()) return; // do not allow corpse reclaim in arena - if (GetPlayer()->InArena()) + if (_player->InArena()) return; // body not released yet - if (!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + if (!_player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) return; - Corpse* corpse = GetPlayer()->GetCorpse(); + Corpse* corpse = _player->GetCorpse(); if (!corpse) return; // prevent resurrect before 30-sec delay after body release not finished - if (time_t(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP)) > time_t(time(NULL))) + if (time_t(corpse->GetGhostTime() + _player->GetCorpseReclaimDelay(corpse->GetType() == CORPSE_RESURRECTABLE_PVP)) > time_t(time(NULL))) return; - if (!corpse->IsWithinDistInMap(GetPlayer(), CORPSE_RECLAIM_RADIUS, true)) + if (!corpse->IsWithinDistInMap(_player, CORPSE_RECLAIM_RADIUS, true)) return; // resurrect - GetPlayer()->ResurrectPlayer(GetPlayer()->InBattleground() ? 1.0f : 0.5f); + _player->ResurrectPlayer(_player->InBattleground() ? 1.0f : 0.5f); // spawn bones - GetPlayer()->SpawnCorpseBones(); + _player->SpawnCorpseBones(); } void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index df6703980d1..4d78064423c 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -103,6 +103,13 @@ void WorldSession::SendShowBank(uint64 guid) SendPacket(&data); } +void WorldSession::SendShowMailBox(uint64 guid) +{ + WorldPacket data(SMSG_SHOW_MAILBOX, 8); + data << guid; + SendPacket(&data); +} + void WorldSession::HandleTrainerListOpcode(WorldPacket& recvData) { uint64 guid; diff --git a/src/server/game/Handlers/TicketHandler.cpp b/src/server/game/Handlers/TicketHandler.cpp index b9949ac631d..688d7e58b6c 100644 --- a/src/server/game/Handlers/TicketHandler.cpp +++ b/src/server/game/Handlers/TicketHandler.cpp @@ -49,13 +49,23 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData) // Player must not have ticket if (!ticket || ticket->IsClosed()) { - ticket = new GmTicket(GetPlayer(), recvData); - + uint32 mapId; + float x, y, z; + std::string message; + uint32 needResponse; + bool needMoreHelp; uint32 count; std::list<uint32> times; uint32 decompressedSize; std::string chatLog; + recvData >> mapId; + recvData >> x >> y >> z; + recvData >> message; + + recvData >> needResponse; + recvData >> needMoreHelp; + recvData >> count; for (uint32 i = 0; i < count; i++) @@ -77,19 +87,25 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData) if (uncompress(dest.contents(), &realSize, recvData.contents() + pos, recvData.size() - pos) == Z_OK) { dest >> chatLog; - ticket->SetChatLog(times, chatLog); } else { TC_LOG_ERROR("network", "CMSG_GMTICKET_CREATE possibly corrupt. Uncompression failed."); recvData.rfinish(); - delete ticket; return; } recvData.rfinish(); // Will still have compressed data in buffer. } + ticket = new GmTicket(GetPlayer()); + ticket->SetPosition(mapId, x, y, z); + ticket->SetMessage(message); + ticket->SetGmAction(needResponse, needMoreHelp); + + if (!chatLog.empty()) + ticket->SetChatLog(times, chatLog); + sTicketMgr->AddTicket(ticket); sTicketMgr->UpdateLastChange(); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 97e81de7ecf..ea02b83f2e8 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -931,7 +931,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL }, /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, - /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode }, + /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode }, /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide }, /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode }, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 8b00cb9432e..904006e174d 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -275,6 +275,8 @@ class WorldSession void SendTrainerList(uint64 guid, std::string const& strTitle); void SendListInventory(uint64 guid); void SendShowBank(uint64 guid); + bool CanOpenMailBox(uint64 guid); + void SendShowMailBox(uint64 guid); void SendTabardVendorActivate(uint64 guid); void SendSpiritResurrect(); void SendBindPoint(Creature* npc); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 5cb86244aa1..1273b92596f 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -6106,8 +6106,10 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (target != caster && GetSpellInfo()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL) { uint32 funnelDamage = GetSpellInfo()->ManaPerSecond; // damage is not affected by spell power - if ((int32)funnelDamage > gain) + + if ((int32)funnelDamage > gain && gain > 0) funnelDamage = gain; + uint32 funnelAbsorb = 0; caster->DealDamageMods(caster, funnelDamage, &funnelAbsorb); caster->SendSpellNonMeleeDamageLog(caster, GetId(), funnelDamage, GetSpellInfo()->GetSchoolMask(), funnelAbsorb, 0, false, 0, false); diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index 83c049363d4..7337f44e620 100644 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -34,26 +34,13 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; } // GM ticket GmTicket::GmTicket() : _id(0), _playerGuid(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), - _needResponse(false), _haveTicket(false) { } + _needResponse(false), _needMoreHelp(false) { } -GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _haveTicket(false) +GmTicket::GmTicket(Player* player) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needMoreHelp(false) { _id = sTicketMgr->GenerateTicketId(); _playerName = player->GetName(); _playerGuid = player->GetGUID(); - - uint32 mapId; - recvData >> mapId; // Map is sent as UInt32! - _mapId = mapId; - - recvData >> _posX; - recvData >> _posY; - recvData >> _posZ; - recvData >> _message; - uint32 needResponse; - recvData >> needResponse; - _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) - recvData >> _haveTicket; // Requests further GM interaction on a ticket to which a GM has already responded. Basically means "has a new ticket" } GmTicket::~GmTicket() { } @@ -80,7 +67,7 @@ bool GmTicket::LoadFromDB(Field* fields) _completed = fields[++index].GetBool(); _escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8()); _viewed = fields[++index].GetBool(); - _haveTicket = fields[++index].GetBool(); + _needMoreHelp = fields[++index].GetBool(); return true; } @@ -107,7 +94,7 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const stmt->setBool (++index, _completed); stmt->setUInt8 (++index, uint8(_escalatedStatus)); stmt->setBool (++index, _viewed); - stmt->setBool (++index, _haveTicket); + stmt->setBool (++index, _needMoreHelp); CharacterDatabase.ExecuteOrAppend(trans, stmt); } @@ -124,7 +111,7 @@ void GmTicket::WritePacket(WorldPacket& data) const data << uint32(GMTICKET_STATUS_HASTEXT); data << uint32(_id); data << _message; - data << uint8(_haveTicket); + data << uint8(_needMoreHelp); data << GetAge(_lastModifiedTime); if (GmTicket* ticket = sTicketMgr->GetOldestOpenTicket()) data << GetAge(ticket->GetLastModifiedTime()); @@ -220,6 +207,20 @@ void GmTicket::SetUnassigned() } } +void GmTicket::SetPosition(uint32 mapId, float x, float y, float z) +{ + _mapId = mapId; + _posX = x; + _posY = y; + _posZ = z; +} + +void GmTicket::SetGmAction(uint32 needResponse, bool needMoreHelp) +{ + _needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default) + _needMoreHelp = needMoreHelp; // Requests further GM interaction on a ticket to which a GM has already responded. Basically means "has a new ticket" +} + void GmTicket::TeleportTo(Player* player) const { player->TeleportTo(_mapId, _posX, _posY, _posZ, 0.0f, 0); diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index 3dd048189d7..5bfe78abbba 100644 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -82,7 +82,7 @@ class GmTicket { public: GmTicket(); - GmTicket(Player* player, WorldPacket& recvData); + GmTicket(Player* player); ~GmTicket(); bool IsClosed() const { return _closedBy; } @@ -129,6 +129,8 @@ public: void SetComment(std::string const& comment) { _comment = comment; } void SetViewed() { _viewed = true; } void SetUnassigned(); + void SetPosition(uint32 mapId, float x, float y, float z); + void SetGmAction(uint32 needResponse, bool needMoreHelp); void AppendResponse(std::string const& response) { _response += response; } @@ -164,7 +166,7 @@ private: GMTicketEscalationStatus _escalatedStatus; bool _viewed; bool _needResponse; /// @todo find out the use of this, and then store it in DB - bool _haveTicket; + bool _needMoreHelp; std::string _response; std::string _chatLog; // No need to store in db, will be refreshed every session client side }; diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 55e22a8c99a..498ee68ba11 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -198,33 +198,34 @@ public: //Enable\Disable Invisible mode static bool HandleGMVisibleCommand(ChatHandler* handler, char const* args) { + Player* _player = handler->GetSession()->GetPlayer(); + if (!*args) { - handler->PSendSysMessage(LANG_YOU_ARE, handler->GetSession()->GetPlayer()->isGMVisible() ? handler->GetTrinityString(LANG_VISIBLE) : handler->GetTrinityString(LANG_INVISIBLE)); + handler->PSendSysMessage(LANG_YOU_ARE, _player->isGMVisible() ? handler->GetTrinityString(LANG_VISIBLE) : handler->GetTrinityString(LANG_INVISIBLE)); return true; } const uint32 VISUAL_AURA = 37800; std::string param = (char*)args; - Player* player = handler->GetSession()->GetPlayer(); if (param == "on") { - if (player->HasAura(VISUAL_AURA, 0)) - player->RemoveAurasDueToSpell(VISUAL_AURA); + if (_player->HasAura(VISUAL_AURA, 0)) + _player->RemoveAurasDueToSpell(VISUAL_AURA); - player->SetGMVisible(true); + _player->SetGMVisible(true); + _player->UpdateObjectVisibility(); handler->GetSession()->SendNotification(LANG_INVISIBLE_VISIBLE); return true; } if (param == "off") { + _player->AddAura(VISUAL_AURA, _player); + _player->SetGMVisible(false); + _player->UpdateObjectVisibility(); handler->GetSession()->SendNotification(LANG_INVISIBLE_INVISIBLE); - player->SetGMVisible(false); - - player->AddAura(VISUAL_AURA, player); - return true; } @@ -236,12 +237,11 @@ public: //Enable\Disable GM Mode static bool HandleGMCommand(ChatHandler* handler, char const* args) { + Player* _player = handler->GetSession()->GetPlayer(); + if (!*args) { - if (handler->GetSession()->GetPlayer()->IsGameMaster()) - handler->GetSession()->SendNotification(LANG_GM_ON); - else - handler->GetSession()->SendNotification(LANG_GM_OFF); + handler->GetSession()->SendNotification(_player->IsGameMaster() ? LANG_GM_ON : LANG_GM_OFF); return true; } @@ -249,9 +249,9 @@ public: if (param == "on") { - handler->GetSession()->GetPlayer()->SetGameMaster(true); + _player->SetGameMaster(true); handler->GetSession()->SendNotification(LANG_GM_ON); - handler->GetSession()->GetPlayer()->UpdateTriggerVisibility(); + _player->UpdateTriggerVisibility(); #ifdef _DEBUG_VMAPS VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); vMapManager->processCommand("stoplog"); @@ -261,9 +261,9 @@ public: if (param == "off") { - handler->GetSession()->GetPlayer()->SetGameMaster(false); + _player->SetGameMaster(false); handler->GetSession()->SendNotification(LANG_GM_OFF); - handler->GetSession()->GetPlayer()->UpdateTriggerVisibility(); + _player->UpdateTriggerVisibility(); #ifdef _DEBUG_VMAPS VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); vMapManager->processCommand("startlog"); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index eb45e8f49f5..094e45d91a2 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -94,6 +94,7 @@ public: { "unpossess", rbac::RBAC_PERM_COMMAND_UNPOSSESS, false, &HandleUnPossessCommand, "", NULL }, { "unstuck", rbac::RBAC_PERM_COMMAND_UNSTUCK, true, &HandleUnstuckCommand, "", NULL }, { "wchange", rbac::RBAC_PERM_COMMAND_WCHANGE, false, &HandleChangeWeather, "", NULL }, + { "mailbox", rbac::RBAC_PERM_COMMAND_MAILBOX, false, &HandleMailBoxCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; return commandTable; @@ -2477,6 +2478,14 @@ public: player->StopCastingBindSight(); return true; } + + static bool HandleMailBoxCommand(ChatHandler* handler, char const* /*args*/) + { + Player* player = handler->GetSession()->GetPlayer(); + + handler->GetSession()->SendShowMailBox(player->GetGUID()); + return true; + } }; void AddSC_misc_commandscript() diff --git a/src/server/scripts/Kalimdor/zone_ashenvale.cpp b/src/server/scripts/Kalimdor/zone_ashenvale.cpp index 41c0441bca5..ec28ee42625 100644 --- a/src/server/scripts/Kalimdor/zone_ashenvale.cpp +++ b/src/server/scripts/Kalimdor/zone_ashenvale.cpp @@ -198,7 +198,7 @@ public: void sQuestAccept(Player* player, Quest const* quest) { - if (quest->GetQuestId() == QUEST_TOREK_ASSULT) + if (quest->GetQuestId() == QUEST_FREEDOM_TO_RUUL) { me->setFaction(FACTION_QUEST); npc_escortAI::Start(true, false, player->GetGUID()); diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 419a289aed4..4dd06b762a1 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -2241,6 +2241,47 @@ class spell_q12919_gymers_throw : public SpellScriptLoader } }; +enum Quest_The_Hunter_And_The_Prince +{ + SPELL_ILLIDAN_KILL_CREDIT = 61748 +}; + +class spell_q13400_illidan_kill_master : public SpellScriptLoader +{ + public: + spell_q13400_illidan_kill_master() : SpellScriptLoader("spell_q13400_illidan_kill_master") { } + + class spell_q13400_illidan_kill_master_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q13400_illidan_kill_master_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_ILLIDAN_KILL_CREDIT)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + if (caster->IsVehicle()) + if (Unit* passenger = caster->GetVehicleKit()->GetPassenger(0)) + passenger->CastSpell(passenger, SPELL_ILLIDAN_KILL_CREDIT, true); + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_q13400_illidan_kill_master_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_q13400_illidan_kill_master_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -2295,4 +2336,5 @@ void AddSC_quest_spell_scripts() new spell_q12619_emblazon_runeblade_effect(); new spell_q12919_gymers_grab(); new spell_q12919_gymers_throw(); + new spell_q13400_illidan_kill_master(); } diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp index f4da4093dfa..b4d57f065b0 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.cpp +++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp @@ -62,6 +62,13 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor // Install the unhandled exception filter function m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); m_hProcess = GetCurrentProcess(); + if (!IsDebuggerPresent()) + { + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } } //============ @@ -566,6 +573,9 @@ PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; + if (!hMod) + return FALSE; + if (!GetModuleFileName((HMODULE)hMod, szModule, len)) return FALSE; @@ -708,7 +718,7 @@ bool bWriteVariables, HANDLE pThreadHandle) } // Get the source line for this stack frame entry - IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE) }; + IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) }; DWORD dwLineDisplacement; if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo)) @@ -746,11 +756,11 @@ ULONG /*SymbolSize*/, PVOID UserContext) { - char szBuffer[2048]; + char szBuffer[4092]; __try { - if (FormatSymbolValue(pSymInfo, (STACKFRAME*)UserContext, + if (FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext, szBuffer, sizeof(szBuffer))) _tprintf(_T("\t%s\r\n"), szBuffer); } @@ -769,7 +779,7 @@ PVOID UserContext) ////////////////////////////////////////////////////////////////////////////// bool WheatyExceptionReport::FormatSymbolValue( PSYMBOL_INFO pSym, -STACKFRAME * sf, +STACKFRAME64 * sf, char * pszBuffer, unsigned /*cbBuffer*/) { @@ -782,7 +792,7 @@ unsigned /*cbBuffer*/) pszCurrBuffer += sprintf(pszCurrBuffer, "Local "); // If it's a function, don't do anything. - if (pSym->Tag == 5) // SymTagFunction from CVCONST.H from the DIA SDK + if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK return false; DWORD_PTR pVariable = 0; // Will point to the variable's data in memory @@ -791,7 +801,11 @@ unsigned /*cbBuffer*/) { // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) { // This may change!!! +#ifdef _M_IX86 pVariable = sf->AddrFrame.Offset; +#elif _M_X64 + pVariable = sf->AddrStack.Offset; +#endif pVariable += (DWORD_PTR)pSym->Address; } // else @@ -889,6 +903,12 @@ char* /*Name*/) // Iterate through each of the children for (unsigned i = 0; i < dwChildrenCount; i++) { + DWORD symTag; + SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag); + + if (symTag == SymTagFunction || symTag == SymTagTypedef) + continue; + // Add appropriate indentation level (since this routine is recursive) for (unsigned j = 0; j <= nestingLevel+1; j++) pszCurrBuffer += sprintf(pszCurrBuffer, "\t"); @@ -1017,7 +1037,7 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase) //============================================================================ int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) { - TCHAR szBuff[1024]; + TCHAR szBuff[4092]; int retValue; DWORD cbWritten; va_list argptr; diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h index 582f1f157b8..a4ba69d3ff3 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.h +++ b/src/server/shared/Debugging/WheatyExceptionReport.h @@ -98,7 +98,7 @@ class WheatyExceptionReport static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID); - static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer); + static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *, char * pszBuffer, unsigned cbBuffer); static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, char*); |