Conflicts:
	src/server/game/Entities/Player/Player.cpp
	src/server/game/Handlers/TicketHandler.cpp
	src/server/game/Tickets/TicketMgr.cpp
	src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
This commit is contained in:
Subv
2012-10-16 21:55:01 -05:00
12 changed files with 142 additions and 218 deletions
+2
View File
@@ -1514,9 +1514,11 @@ CREATE TABLE `gm_tickets` (
`closedBy` int(10) NOT NULL DEFAULT '0',
`assignedTo` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'GUID of admin to whom ticket is assigned',
`comment` text NOT NULL,
`response` text NOT NULL,
`completed` tinyint(3) unsigned NOT NULL DEFAULT '0',
`escalated` tinyint(3) unsigned NOT NULL DEFAULT '0',
`viewed` tinyint(3) unsigned NOT NULL DEFAULT '0',
`haveTicket` tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`ticketId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
/*!40101 SET character_set_client = @saved_cs_client */;
@@ -0,0 +1,3 @@
ALTER TABLE `gm_tickets`
ADD COLUMN `response` text NOT NULL AFTER `comment`,
ADD COLUMN `haveTicket` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `viewed`;
@@ -0,0 +1,4 @@
ALTER TABLE `spell_area` ADD COLUMN `quest_start_status` INT(11) NOT NULL DEFAULT 64; -- default is QUEST_STATUS_REWARDED
ALTER TABLE `spell_area` ADD COLUMN `quest_end_status` INT(11) NOT NULL DEFAULT 11; -- default is QUEST_STATUS_COMPLETE | QUEST_STATUS_NONE | QUEST_STATUS_INCOMPLETE
UPDATE spell_area SET `quest_start_status` = (1 << 6) | (1 << 3) | (1 << 1) WHERE `quest_start_active` = 1;
ALTER TABLE spell_area DROP COLUMN `quest_start_active`;
+35 -145
View File
@@ -9170,7 +9170,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
{
// data depends on zoneid/mapid...
Battleground* bg = GetBattleground();
uint16 NumberOfFields = 0;
uint32 mapid = GetMapId();
OutdoorPvP* pvp = sOutdoorPvPMgr->GetOutdoorPvPToZoneId(zoneid);
InstanceScript* instance = GetInstanceScript();
@@ -9178,91 +9177,12 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
sLog->outDebug(LOG_FILTER_NETWORKIO, "Sending SMSG_INIT_WORLD_STATES to Map: %u, Zone: %u", mapid, zoneid);
// may be exist better way to do this...
switch (zoneid)
{
case 0:
case 1:
case 4:
case 8:
case 10:
case 11:
case 12:
case 36:
case 38:
case 40:
case 41:
case 51:
case 267:
case 1519:
case 1537:
case 2257:
case 2918:
NumberOfFields = 8;
break;
case 1377:
NumberOfFields = 15;
break;
case 2597:
NumberOfFields = 83;
break;
case 3277:
NumberOfFields = 18;
break;
case 3358:
case 3820:
NumberOfFields = 40;
break;
case 3483:
NumberOfFields = 27;
break;
case 3518:
NumberOfFields = 39;
break;
case 3519:
NumberOfFields = 38;
break;
case 3521:
NumberOfFields = 37;
break;
case 3698:
case 3702:
case 3968:
case 4378:
case 3703:
NumberOfFields = 11;
break;
case 4384:
NumberOfFields = 30;
break;
case 4710:
NumberOfFields = 28;
break;
case 4812: // Icecrown Citadel
case 4100: // The Culling of Stratholme
NumberOfFields = 13;
break;
case 4987: // The Ruby Sanctum
NumberOfFields = 3;
break;
case 4273: // Ulduar
NumberOfFields = 10;
break;
case 4197: // Wintergrasp
/// Use the max here, and fill with zeros if missing.
NumberOfFields = 10 + WG_MAX_OBJ + WG_MAX_WORKSHOP;
break;
default:
NumberOfFields = 12;
break;
}
WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+4+2+(NumberOfFields*8)));
WorldPacket data(SMSG_INIT_WORLD_STATES, (4+4+4+2+(12*8)));
data << uint32(mapid); // mapid
data << uint32(zoneid); // zone id
data << uint32(areaid); // area id, new 2.1.0
size_t countPos = data.wpos();
data << uint16(NumberOfFields); // count of uint64 blocks
data << uint16(0); // count of uint64 blocks
data << uint32(0x8d8) << uint32(0x0); // 1
data << uint32(0x8d7) << uint32(0x0); // 2
data << uint32(0x8d6) << uint32(0x0); // 3
@@ -9806,8 +9726,6 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
bf->FillInitialWorldStates(data);
break;
}
else
data.put<uint16>(countPos, 12);
// No break here, intended.
default:
data << uint32(0x914) << uint32(0x0); // 7
@@ -9816,6 +9734,10 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(0x915) << uint32(0x0); // 10
break;
}
uint16 length = (data.wpos() - countPos) / 8;
data.put<uint16>(countPos, length);
GetSession()->SendPacket(&data);
SendBGWeekendWorldStates();
SendBattlefieldWorldStates();
@@ -15001,24 +14923,6 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
if (questGiver && quest->GetQuestStartScript() != 0)
GetMap()->ScriptsStart(sQuestStartScripts, quest->GetQuestStartScript(), questGiver, this);
// Some spells applied at quest activation
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, true);
if (saBounds.first != saBounds.second)
{
uint32 zone, area;
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
PhaseUpdateData phaseUdateData;
phaseUdateData.AddQuestUpdate(quest_id);
phaseMgr.NotifyConditionChanged(phaseUdateData);
UpdateForQuestWorldObjects();
}
@@ -15187,11 +15091,6 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
m_RewardedQuests.insert(quest_id);
m_RewardedQuestsSave[quest_id] = true;
PhaseUpdateData phaseUdateData;
phaseUdateData.AddQuestUpdate(quest_id);
phaseMgr.NotifyConditionChanged(phaseUdateData);
// StoreNewItem, mail reward, etc. save data directly to the database
// to prevent exploitable data desynchronisation we save the quest status to the database too
// (to prevent rewarding this quest another time while rewards were already given out)
@@ -15212,33 +15111,6 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId());
uint32 zone = 0;
uint32 area = 0;
// remove auras from spells with quest reward state limitations
SpellAreaForQuestMapBounds saEndBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id);
if (saEndBounds.first != saEndBounds.second)
{
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr)
if (!itr->second->IsFitToRequirements(this, zone, area))
RemoveAurasDueToSpell(itr->second->spellId);
}
// Some spells applied at quest reward
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, false);
if (saBounds.first != saBounds.second)
{
if (!zone || !area)
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
}
@@ -15786,6 +15658,30 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
phaseMgr.NotifyConditionChanged(phaseUdateData);
uint32 zone = 0, area = 0;
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id);
if (saBounds.first != saBounds.second)
{
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id);
if (saBounds.first != saBounds.second)
{
if (!zone || !area)
GetZoneAndAreaId(zone, area);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (!itr->second->IsFitToRequirements(this, zone, area))
RemoveAurasDueToSpell(itr->second->spellId);
}
UpdateForQuestWorldObjects();
}
@@ -23866,21 +23762,15 @@ bool Player::CanUseBattlegroundObject()
// TODO : some spells gives player ForceReaction to one faction (ReputationMgr::ApplyForceReaction)
// maybe gameobject code should handle that ForceReaction usage
// BUG: sometimes when player clicks on flag in AB - client won't send gameobject_use, only gameobject_report_use packet
return (//InBattleground() && // in battleground - not need, check in other cases
//!IsMounted() && - not correct, player is dismounted when he clicks on flag
//player cannot use object when he is invulnerable (immune)
!isTotalImmune() && // not totally immune
//i'm not sure if these two are correct, because invisible players should get visible when they click on flag
!HasStealthAura() && // not stealthed
!HasInvisibilityAura() && // not invisible
!HasAura(SPELL_RECENTLY_DROPPED_FLAG) && // can't pickup
isAlive() // live player
);
// Note: Mount, stealth and invisibility will be removed when used
return (!isTotalImmune() && // Damage immune
!HasAura(SPELL_RECENTLY_DROPPED_FLAG) && // Still has recently held flag debuff
isAlive()); // Alive
}
bool Player::CanCaptureTowerPoint()
{
return (!HasStealthAura() && // not stealthed
return (!HasStealthAura() && // not stealthed
!HasInvisibilityAura() && // not invisible
isAlive() // live player
);
+1 -1
View File
@@ -6345,7 +6345,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (GetTypeId() != TYPEID_PLAYER)
{
beaconTarget = triggeredByAura->GetBase()->GetCaster();
if (beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID())))
if (!beaconTarget || beaconTarget == this || !(beaconTarget->GetAura(53563, victim->GetGUID())))
return false;
basepoints0 = int32(damage);
triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654;
+41 -1
View File
@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "zlib.h"
#include "Language.h"
#include "WorldPacket.h"
#include "Common.h"
@@ -26,7 +27,7 @@
#include "WorldSession.h"
#include "Util.h"
void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recvData)
void WorldSession::HandleGMTicketCreateOpcode(WorldPacket& recvData)
{
// Don't accept tickets if the ticket queue is disabled. (Ticket UI is greyed out but not fully dependable)
if (sTicketMgr->GetStatus() == GMTICKET_QUEUE_STATUS_DISABLED)
@@ -43,6 +44,45 @@ void WorldSession::HandleGMTicketCreateOpcode(WorldPacket & recvData)
if (!sTicketMgr->GetTicketByPlayer(GetPlayer()->GetGUID()))
{
GmTicket* ticket = new GmTicket(GetPlayer(), recvData);
uint32 count;
std::list<uint32> times;
uint32 decompressedSize;
std::string chatLog;
recvData >> count;
for (uint32 i = 0; i < count; i++)
{
uint32 time;
recvData >> time;
times.push_back(time);
}
recvData >> decompressedSize;
if (count && decompressedSize && decompressedSize < 0xFFFF)
{
uint32 pos = recvData.rpos();
ByteBuffer dest;
dest.resize(decompressedSize);
uLongf realSize = decompressedSize;
if (uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recvData.contents() + pos), recvData.size() - pos) == Z_OK)
{
dest >> chatLog;
ticket->SetChatLog(times, chatLog);
}
else
{
sLog->outError(LOG_FILTER_NETWORKIO, "CMSG_GMTICKET_CREATE possibly corrupt. Uncompression failed.");
recvData.rfinish();
return;
}
recvData.rfinish(); // Will still have compressed data in buffer.
}
sTicketMgr->AddTicket(ticket);
sTicketMgr->UpdateLastChange();
+15 -29
View File
@@ -1061,12 +1061,9 @@ SpellAreaMapBounds SpellMgr::GetSpellAreaMapBounds(uint32 spell_id) const
return SpellAreaMapBounds(mSpellAreaMap.lower_bound(spell_id), mSpellAreaMap.upper_bound(spell_id));
}
SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const
SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id) const
{
if (active)
return SpellAreaForQuestMapBounds(mSpellAreaForActiveQuestMap.lower_bound(quest_id), mSpellAreaForActiveQuestMap.upper_bound(quest_id));
else
return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id), mSpellAreaForQuestMap.upper_bound(quest_id));
return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id), mSpellAreaForQuestMap.upper_bound(quest_id));
}
SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const
@@ -1099,11 +1096,11 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
return false;
if (questStart) // not in expected required quest state
if (!player || ((!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart)))
if (!player || (((1 << player->GetQuestStatus(questStart)) & questStartStatus) == 0))
return false;
if (questEnd) // not in expected forbidden quest state
if (!player || player->GetQuestRewardStatus(questEnd))
if (!player || (((1 << player->GetQuestStatus(questEnd)) & questEndStatus) == 0))
return false;
if (auraSpell) // not have expected aura
@@ -2433,12 +2430,11 @@ void SpellMgr::LoadSpellAreas()
mSpellAreaMap.clear(); // need for reload case
mSpellAreaForQuestMap.clear();
mSpellAreaForActiveQuestMap.clear();
mSpellAreaForQuestEndMap.clear();
mSpellAreaForAuraMap.clear();
// 0 1 2 3 4 5 6 7 8
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_active, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
if (!result)
{
@@ -2457,12 +2453,13 @@ void SpellMgr::LoadSpellAreas()
spellArea.spellId = spell;
spellArea.areaId = fields[1].GetUInt32();
spellArea.questStart = fields[2].GetUInt32();
spellArea.questStartCanActive = fields[3].GetBool();
spellArea.questEnd = fields[4].GetUInt32();
spellArea.auraSpell = fields[5].GetInt32();
spellArea.raceMask = fields[6].GetUInt32();
spellArea.gender = Gender(fields[7].GetUInt8());
spellArea.autocast = fields[8].GetBool();
spellArea.questStartStatus = fields[3].GetUInt32();
spellArea.questEndStatus = fields[4].GetUInt32();
spellArea.questEnd = fields[5].GetUInt32();
spellArea.auraSpell = fields[6].GetInt32();
spellArea.raceMask = fields[7].GetUInt32();
spellArea.gender = Gender(fields[8].GetUInt8());
spellArea.autocast = fields[9].GetBool();
if (SpellInfo const* spellInfo = GetSpellInfo(spell))
{
@@ -2494,7 +2491,7 @@ void SpellMgr::LoadSpellAreas()
continue;
// duplicate by requirements
ok =false;
ok = false;
break;
}
@@ -2524,12 +2521,6 @@ void SpellMgr::LoadSpellAreas()
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have wrong end quest (%u) requirement", spell, spellArea.questEnd);
continue;
}
if (spellArea.questEnd == spellArea.questStart && !spellArea.questStartCanActive)
{
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have quest (%u) requirement for start and end in same time", spell, spellArea.questEnd);
continue;
}
}
if (spellArea.auraSpell)
@@ -2605,12 +2596,7 @@ void SpellMgr::LoadSpellAreas()
// for search at quest start/reward
if (spellArea.questStart)
{
if (spellArea.questStartCanActive)
mSpellAreaForActiveQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
else
mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
}
mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
// for search at quest start/reward
if (spellArea.questEnd)
+3 -3
View File
@@ -495,7 +495,8 @@ struct SpellArea
int32 auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case
uint32 raceMask; // can be applied only to races
Gender gender; // can be applied only to gender
bool questStartCanActive; // if true then quest start can be active (not only rewarded)
uint32 questStartStatus; // QuestStatus that quest_start must have in order to keep the spell
uint32 questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped)
bool autocast; // if true then auto applied at area enter, in other case just allowed to cast
// helpers
@@ -681,7 +682,7 @@ class SpellMgr
// Spell area
SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const;
SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const;
SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id) const;
SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const;
SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const;
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const;
@@ -740,7 +741,6 @@ class SpellMgr
EnchantCustomAttribute mEnchantCustomAttr;
SpellAreaMap mSpellAreaMap;
SpellAreaForQuestMap mSpellAreaForQuestMap;
SpellAreaForQuestMap mSpellAreaForActiveQuestMap;
SpellAreaForQuestMap mSpellAreaForQuestEndMap;
SpellAreaForAuraMap mSpellAreaForAuraMap;
SpellAreaForAreaMap mSpellAreaForAreaMap;
+30 -36
View File
@@ -31,7 +31,7 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; }
// GM ticket
GmTicket::GmTicket() { }
GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED)
GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _haveTicket(false)
{
_id = sTicketMgr->GenerateTicketId();
_playerName = player->GetName();
@@ -47,29 +47,16 @@ GmTicket::GmTicket(Player* player, WorldPacket& recvData) : _createTime(time(NUL
recvData >> _message;
uint32 needResponse;
recvData >> needResponse;
_needResponse = (needResponse == 17); // Requires GM response. 17 = true, 1 = false (17 is default)
uint8 unk1;
recvData >> unk1; // Requests further GM interaction on a ticket to which a GM has already responded
recvData.rfinish();
/*
recvData >> count; // text lines
for (int i = 0; i < count; i++)
recvData >> uint32();
if (something)
recvData >> uint32();
else
compressed uint32 + string;
*/
_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() { }
bool GmTicket::LoadFromDB(Field* fields)
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket
uint8 index = 0;
_id = fields[ index].GetUInt32();
_playerGuid = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER);
@@ -84,9 +71,11 @@ bool GmTicket::LoadFromDB(Field* fields)
_closedBy = fields[++index].GetInt32();
_assignedTo = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER);
_comment = fields[++index].GetString();
_response = fields[++index].GetString();
_completed = fields[++index].GetBool();
_escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8());
_viewed = fields[++index].GetBool();
_haveTicket = fields[++index].GetBool();
return true;
}
@@ -109,9 +98,11 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const
stmt->setInt32 (++index, GUID_LOPART(_closedBy));
stmt->setUInt32(++index, GUID_LOPART(_assignedTo));
stmt->setString(++index, _comment);
stmt->setString(++index, _response);
stmt->setBool (++index, _completed);
stmt->setUInt8 (++index, uint8(_escalatedStatus));
stmt->setBool (++index, _viewed);
stmt->setBool (++index, _haveTicket);
CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
@@ -125,6 +116,10 @@ void GmTicket::DeleteFromDB()
void GmTicket::WritePacket(WorldPacket& data) const
{
data << uint32(GMTICKET_STATUS_HASTEXT);
data << uint32(_id);
data << _message;
data << uint8(_haveTicket);
data << GetAge(_lastModifiedTime);
if (GmTicket* ticket = sTicketMgr->GetOldestOpenTicket())
data << GetAge(ticket->GetLastModifiedTime());
@@ -223,6 +218,20 @@ void GmTicket::TeleportTo(Player* player) const
player->TeleportTo(_mapId, _posX, _posY, _posZ, 0.0f, 0);
}
void GmTicket::SetChatLog(std::list<uint32> time, std::string const& log)
{
std::stringstream ss(log);
std::stringstream newss;
std::string line;
while (std::getline(ss, line))
{
newss << secsToTimeString(time.front()) << ": " << line << "\n";
time.pop_front();
}
_chatLog = newss.str();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Ticket manager
TicketMgr::TicketMgr() : _status(true), _lastTicketId(0), _lastSurveyId(0), _openTicketCount(0), _lastChange(time(NULL)) { }
@@ -365,27 +374,12 @@ void TicketMgr::ShowEscalatedList(ChatHandler& handler) const
void TicketMgr::SendTicket(WorldSession* session, GmTicket* ticket) const
{
uint32 status = GMTICKET_STATUS_DEFAULT;
std::string message;
if (ticket)
{
message = ticket->GetMessage();
status = GMTICKET_STATUS_HASTEXT;
}
WorldPacket data(SMSG_GMTICKET_GETTICKET, (4 + (ticket ? 4 + message.length() + 1 + 4 + 4 + 4 + 1 + 1 : 0)));
data << uint32(status); // standard 0x0A, 0x06 if text present
WorldPacket data(SMSG_GMTICKET_GETTICKET, (ticket ? (4 + 4 + 1 + 4 + 4 + 4 + 1 + 1) : 4));
if (ticket)
{
data << uint32(ticket->GetId()); // ticketID
data << message.c_str(); // ticket text
data << uint8(0x7); // ticket category; why is this hardcoded? does it make a diff re: client?
// we've got the easy stuff done by now.
// Now we need to go through the client logic for displaying various levels of ticket load
ticket->WritePacket(data);
}
else
data << uint32(GMTICKET_STATUS_DEFAULT);
session->SendPacket(&data);
}
+5
View File
@@ -142,6 +142,9 @@ public:
std::string FormatMessageString(ChatHandler& handler, bool detailed = false) const;
std::string FormatMessageString(ChatHandler& handler, const char* szClosedName, const char* szAssignedToName, const char* szUnassignedName, const char* szDeletedName) const;
void SetChatLog(std::list<uint32> time, std::string const& log);
std::string GetChatLog() const { return _chatLog; }
private:
uint32 _id;
uint64 _playerGuid;
@@ -160,7 +163,9 @@ private:
GMTicketEscalationStatus _escalatedStatus;
bool _viewed;
bool _needResponse; // TODO: find out the use of this, and then store it in DB
bool _haveTicket;
std::string _response;
std::string _chatLog; // No need to store in db, will be refreshed every session client side
};
typedef std::map<uint32, GmTicket*> GmTicketList;
@@ -695,7 +695,7 @@ class npc_halion_controller : public CreatureScript
halion->AI()->Talk(SAY_INTRO);
break;
case EVENT_TWILIGHT_MENDING:
if (ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_HALION)))
if (ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_HALION))) // Just check if physical Halion is spawned
if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_TWILIGHT_HALION)))
twilightHalion->CastSpell((Unit*)NULL, SPELL_TWILIGHT_MENDING, true);
break;
@@ -350,8 +350,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC)
// GM Tickets
PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed FROM gm_tickets", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket FROM gm_tickets", CONNECTION_SYNCH)
PREPARE_STATEMENT(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_GM_TICKET, "DELETE FROM gm_tickets WHERE ticketId = ?", CONNECTION_ASYNC)
PREPARE_STATEMENT(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_tickets WHERE guid = ?", CONNECTION_ASYNC)