mirror of
https://github.com/mangosfour/server.git
synced 2025-12-28 22:37:04 +00:00
Merge branch 'master' of git@github.com:mangos/mangos into procflag
This commit is contained in:
commit
bae58eb069
270 changed files with 23161 additions and 7761 deletions
|
|
@ -68,7 +68,7 @@ struct Script
|
|||
CreatureAI* (*GetAI)(Creature *_Creature);
|
||||
InstanceData* (*GetInstanceData)(Map*);
|
||||
// -----------------------------------------
|
||||
|
||||
|
||||
void registerSelf();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,114 +25,140 @@ uint32 GetSkillLevel(Player *player,uint32 trskill)
|
|||
// Returns the level of some tradetrskill known by player
|
||||
// Need to add missing spells
|
||||
|
||||
uint32 spell_apprentice = 0;
|
||||
uint32 spell_journeyman = 0;
|
||||
uint32 spell_expert = 0;
|
||||
uint32 spell_artisan = 0;
|
||||
uint32 spell_master = 0;
|
||||
uint32 spell_apprentice = 0;
|
||||
uint32 spell_journeyman = 0;
|
||||
uint32 spell_expert = 0;
|
||||
uint32 spell_artisan = 0;
|
||||
uint32 spell_master = 0;
|
||||
uint32 spell_grand_master = 0;
|
||||
|
||||
switch(trskill)
|
||||
{
|
||||
case TRADESKILL_ALCHEMY:
|
||||
spell_apprentice = 2259;
|
||||
spell_journeyman = 3101;
|
||||
spell_expert = 3464;
|
||||
spell_artisan = 11611;
|
||||
spell_master = 28596; // teached by 28597
|
||||
spell_apprentice = 2259;
|
||||
spell_journeyman = 3101;
|
||||
spell_expert = 3464;
|
||||
spell_artisan = 11611;
|
||||
spell_master = 28596; // teached by 28597
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_BLACKSMITHING:
|
||||
spell_apprentice = 2018;
|
||||
spell_journeyman = 3100;
|
||||
spell_expert = 8768;
|
||||
spell_artisan = 11454;
|
||||
spell_master = 29844; // teached by 29845
|
||||
spell_apprentice = 2018;
|
||||
spell_journeyman = 3100;
|
||||
spell_expert = 8768;
|
||||
spell_artisan = 11454;
|
||||
spell_master = 29844; // teached by 29845
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_COOKING:
|
||||
spell_apprentice = 2550;
|
||||
spell_journeyman = 3102;
|
||||
spell_expert = 3413;
|
||||
spell_artisan = 18260;
|
||||
spell_master = 33359; // teached by 33361
|
||||
spell_apprentice = 2550;
|
||||
spell_journeyman = 3102;
|
||||
spell_expert = 3413;
|
||||
spell_artisan = 18260;
|
||||
spell_master = 33359; // teached by 33361
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_ENCHANTING:
|
||||
spell_apprentice = 7411;
|
||||
spell_journeyman = 7412;
|
||||
spell_expert = 7413;
|
||||
spell_artisan = 13920;
|
||||
spell_master = 28029; // teached by 28030
|
||||
spell_apprentice = 7411;
|
||||
spell_journeyman = 7412;
|
||||
spell_expert = 7413;
|
||||
spell_artisan = 13920;
|
||||
spell_master = 28029; // teached by 28030
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_ENGINEERING:
|
||||
spell_apprentice = 4036;
|
||||
spell_journeyman = 4037;
|
||||
spell_expert = 4038;
|
||||
spell_artisan = 12656;
|
||||
spell_master = 30350; // teached by 30351
|
||||
spell_apprentice = 4036;
|
||||
spell_journeyman = 4037;
|
||||
spell_expert = 4038;
|
||||
spell_artisan = 12656;
|
||||
spell_master = 30350; // teached by 30351
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_FIRSTAID:
|
||||
spell_apprentice = 3273;
|
||||
spell_journeyman = 3274;
|
||||
spell_expert = 7924;
|
||||
spell_artisan = 10846;
|
||||
spell_master = 27028; // teached by 27029
|
||||
spell_apprentice = 3273;
|
||||
spell_journeyman = 3274;
|
||||
spell_expert = 7924;
|
||||
spell_artisan = 10846;
|
||||
spell_master = 27028; // teached by 27029
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_HERBALISM:
|
||||
spell_apprentice = 2372;
|
||||
spell_journeyman = 2373;
|
||||
spell_expert = 3571;
|
||||
spell_artisan = 11994;
|
||||
spell_master = 0;
|
||||
spell_apprentice = 2372;
|
||||
spell_journeyman = 2373;
|
||||
spell_expert = 3571;
|
||||
spell_artisan = 11994;
|
||||
spell_master = 0;
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_LEATHERWORKING:
|
||||
spell_apprentice = 2108;
|
||||
spell_journeyman = 3104;
|
||||
spell_expert = 20649;
|
||||
spell_artisan = 10662;
|
||||
spell_master = 32549; // teached by 32550
|
||||
spell_apprentice = 2108;
|
||||
spell_journeyman = 3104;
|
||||
spell_expert = 20649;
|
||||
spell_artisan = 10662;
|
||||
spell_master = 32549; // teached by 32550
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_POISONS:
|
||||
spell_apprentice = 0;
|
||||
spell_journeyman = 0;
|
||||
spell_expert = 0;
|
||||
spell_artisan = 0;
|
||||
spell_master = 0;
|
||||
spell_apprentice = 0;
|
||||
spell_journeyman = 0;
|
||||
spell_expert = 0;
|
||||
spell_artisan = 0;
|
||||
spell_master = 0;
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_TAILORING:
|
||||
spell_apprentice = 3908;
|
||||
spell_journeyman = 3909;
|
||||
spell_expert = 3910;
|
||||
spell_artisan = 12180;
|
||||
spell_master = 26790; // teached by 26791
|
||||
spell_apprentice = 3908;
|
||||
spell_journeyman = 3909;
|
||||
spell_expert = 3910;
|
||||
spell_artisan = 12180;
|
||||
spell_master = 26790; // teached by 26791
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_MINING:
|
||||
spell_apprentice = 2581;
|
||||
spell_journeyman = 2582;
|
||||
spell_expert = 3568;
|
||||
spell_artisan = 10249;
|
||||
spell_master = 29354; // teached by 29355
|
||||
spell_apprentice = 2581;
|
||||
spell_journeyman = 2582;
|
||||
spell_expert = 3568;
|
||||
spell_artisan = 10249;
|
||||
spell_master = 29354; // teached by 29355
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_FISHING:
|
||||
spell_apprentice = 7733;
|
||||
spell_journeyman = 7734;
|
||||
spell_expert = 7736;
|
||||
spell_artisan = 18249;
|
||||
spell_master = 33098; // teached by 33100
|
||||
spell_apprentice = 7733;
|
||||
spell_journeyman = 7734;
|
||||
spell_expert = 7736;
|
||||
spell_artisan = 18249;
|
||||
spell_master = 33098; // teached by 33100
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_SKINNING:
|
||||
spell_apprentice = 8615;
|
||||
spell_journeyman = 8619;
|
||||
spell_expert = 8620;
|
||||
spell_artisan = 10769;
|
||||
spell_master = 32679; // teached by 32678
|
||||
spell_apprentice = 8615;
|
||||
spell_journeyman = 8619;
|
||||
spell_expert = 8620;
|
||||
spell_artisan = 10769;
|
||||
spell_master = 32679; // teached by 32678
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_JEWELCRAFTING:
|
||||
spell_apprentice = 25229; // teached by 25245
|
||||
spell_journeyman = 25230; // teached by 25246
|
||||
spell_expert = 28894; // teached by 28896
|
||||
spell_artisan = 28895; // teached by 28899
|
||||
spell_master = 28897; // teached by 28901
|
||||
spell_apprentice = 25229; // teached by 25245
|
||||
spell_journeyman = 25230; // teached by 25246
|
||||
spell_expert = 28894; // teached by 28896
|
||||
spell_artisan = 28895; // teached by 28899
|
||||
spell_master = 28897; // teached by 28901
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
case TRADESKILL_INSCRIPTION:
|
||||
spell_apprentice = 0;
|
||||
spell_journeyman = 0;
|
||||
spell_expert = 0;
|
||||
spell_artisan = 0;
|
||||
spell_master = 0;
|
||||
spell_grand_master = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (player->HasSpell(spell_grand_master))
|
||||
return TRADESKILL_LEVEL_GRAND_MASTER;
|
||||
|
||||
if (player->HasSpell(spell_master))
|
||||
return TRADESKILL_LEVEL_MASTER;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#define TRADESKILL_FISHING 12
|
||||
#define TRADESKILL_SKINNING 13
|
||||
#define TRADESKILL_JEWELCRAFTING 14
|
||||
#define TRADESKILL_INSCRIPTION 15
|
||||
|
||||
#define TRADESKILL_LEVEL_NONE 0
|
||||
#define TRADESKILL_LEVEL_APPRENTICE 1
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
#define TRADESKILL_LEVEL_EXPERT 3
|
||||
#define TRADESKILL_LEVEL_ARTISAN 4
|
||||
#define TRADESKILL_LEVEL_MASTER 5
|
||||
#define TRADESKILL_LEVEL_GRAND_MASTER 6
|
||||
|
||||
// Gossip defines
|
||||
|
||||
|
|
|
|||
910
src/game/AchievementMgr.cpp
Normal file
910
src/game/AchievementMgr.cpp
Normal file
|
|
@ -0,0 +1,910 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "AchievementMgr.h"
|
||||
#include "Common.h"
|
||||
#include "Player.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Database/DBCEnums.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Guild.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "GameEvent.h"
|
||||
#include "World.h"
|
||||
#include "SpellMgr.h"
|
||||
|
||||
const CriteriaCastSpellRequirement AchievementMgr::criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] =
|
||||
{
|
||||
{5272, 3057, 0, 0},
|
||||
{5273, 2784, 0, 0},
|
||||
{5752, 9099, 0, 0},
|
||||
{5753, 8403, 0, 0},
|
||||
{5772, 0, 0, RACE_GNOME},
|
||||
{5774, 0, 0, RACE_BLOODELF},
|
||||
{5775, 0, 0, RACE_DRAENEI},
|
||||
{5776, 0, 0, RACE_DWARF},
|
||||
{5777, 0, 0, RACE_HUMAN},
|
||||
{5778, 0, 0, RACE_NIGHTELF},
|
||||
{5779, 0, 0, RACE_ORC},
|
||||
{5780, 0, 0, RACE_TAUREN},
|
||||
{5781, 0, 0, RACE_TROLL},
|
||||
{5782, 0, 0, RACE_UNDEAD_PLAYER},
|
||||
{6225, 5661, 0, 0},
|
||||
{6226, 26044, 0, 0},
|
||||
{6228, 739, 0, 0},
|
||||
{6229, 927, 0, 0},
|
||||
{6230, 1444, 0, 0},
|
||||
{6231, 8140, 0, 0},
|
||||
{6232, 5489, 0, 0},
|
||||
{6233,12336, 0, 0},
|
||||
{6234, 1351, 0, 0},
|
||||
{6235, 5484, 0, 0},
|
||||
{6236, 1182, 0, 0},
|
||||
{6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC},
|
||||
{6238, 0, CLASS_WARRIOR, RACE_HUMAN},
|
||||
{6239, 0, CLASS_SHAMAN, RACE_TAUREN},
|
||||
{6240, 0, CLASS_DRUID, RACE_NIGHTELF},
|
||||
{6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER},
|
||||
{6242, 0, CLASS_HUNTER, RACE_TROLL},
|
||||
{6243, 0, CLASS_MAGE, RACE_GNOME},
|
||||
{6244, 0, CLASS_PALADIN, RACE_DWARF},
|
||||
{6245, 0, CLASS_WARLOCK, RACE_BLOODELF},
|
||||
{6246, 0, CLASS_PRIEST, RACE_DRAENEI},
|
||||
{6312, 0, CLASS_WARLOCK, RACE_GNOME},
|
||||
{6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN},
|
||||
{6314, 0, CLASS_PRIEST, RACE_NIGHTELF},
|
||||
{6315, 0, CLASS_SHAMAN, RACE_ORC},
|
||||
{6316, 0, CLASS_DRUID, RACE_TAUREN},
|
||||
{6317, 0, CLASS_ROGUE, RACE_TROLL},
|
||||
{6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER},
|
||||
{6319, 0, CLASS_MAGE, RACE_BLOODELF},
|
||||
{6320, 0, CLASS_PALADIN, RACE_DRAENEI},
|
||||
{6321, 0, CLASS_HUNTER, RACE_DWARF},
|
||||
{6662, 31261, 0, 0}
|
||||
};
|
||||
|
||||
const AchievementReward AchievementMgr::achievementRewards[ACHIEVEMENT_REWARD_COUNT] =
|
||||
{
|
||||
// achievementId, horde titleid, alliance titleid, itemid
|
||||
{45, 0, 0, 43348},
|
||||
{46, 78, 78, 0},
|
||||
{230, 72, 72, 0},
|
||||
{456, 139, 139, 0},
|
||||
{614, 0, 0, 44223},
|
||||
{619, 0, 0, 44224},
|
||||
{714, 47, 47, 0},
|
||||
{762, 130, 130, 0},
|
||||
{870, 127, 126, 0},
|
||||
{871, 144, 144, 0},
|
||||
{876, 0, 0, 43349},
|
||||
{907, 48, 48, 0},
|
||||
{913, 74, 74, 0},
|
||||
{942, 79, 79, 0},
|
||||
{943, 79, 79, 0},
|
||||
{945, 131, 131, 0},
|
||||
{948, 130, 130, 0},
|
||||
{953, 132, 132, 0},
|
||||
{978, 81, 81, 0},
|
||||
{1015, 77, 77, 0},
|
||||
{1021, 0, 0, 40643},
|
||||
{1038, 75, 75, 0},
|
||||
{1039, 76, 76, 0},
|
||||
{1163, 128, 128, 0},
|
||||
{1174, 82, 82, 0},
|
||||
{1175, 72, 72, 0},
|
||||
{1250, 0, 0, 40653},
|
||||
{1400, 120, 120, 0},
|
||||
{1402, 122, 122, 0},
|
||||
{1516, 83, 83, 0},
|
||||
{1563, 84, 84, 0},
|
||||
{1656, 124, 124, 0},
|
||||
{1657, 124, 124, 0},
|
||||
{1658, 129, 129, 0},
|
||||
{1681, 125, 125, 43300},
|
||||
{1682, 125, 125, 43300},
|
||||
{1683, 133, 133, 0},
|
||||
{1684, 133, 133, 0},
|
||||
{1691, 134, 134, 0},
|
||||
{1692, 134, 134, 0},
|
||||
{1693, 135, 135, 0},
|
||||
{1707, 135, 135, 0},
|
||||
{1784, 84, 84, 0},
|
||||
{1793, 137, 137, 0},
|
||||
{1956, 0, 0, 43824},
|
||||
{2051, 140, 140, 0},
|
||||
{2054, 121, 121, 0},
|
||||
{2096, 0, 0, 44430},
|
||||
{2136, 0, 0, 0},// <- TODO: find item for spell 59961
|
||||
{2137, 0, 0, 0},// <- TODO: find item for spell 60021
|
||||
{2138, 0, 0, 0},// <- TODO: find item for spell 59976
|
||||
{2143, 0, 0, 44178},
|
||||
{2144, 0, 0, 0},// <- TODO: find item for spell 60024
|
||||
{2145, 0, 0, 0},// <- TODO: find item for spell 60024
|
||||
{2186, 141, 141, 0},
|
||||
{2187, 142, 142, 0},
|
||||
{2188, 143, 143, 0}
|
||||
};
|
||||
|
||||
AchievementMgr::AchievementMgr(Player *player)
|
||||
{
|
||||
m_player = player;
|
||||
}
|
||||
|
||||
AchievementMgr::~AchievementMgr()
|
||||
{
|
||||
}
|
||||
|
||||
void AchievementMgr::SaveToDB()
|
||||
{
|
||||
if(!m_completedAchievements.empty())
|
||||
{
|
||||
bool need_execute = false;
|
||||
std::ostringstream ssdel;
|
||||
std::ostringstream ssins;
|
||||
for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++)
|
||||
{
|
||||
if(!iter->second.changed)
|
||||
continue;
|
||||
|
||||
/// first new/changed record prefix
|
||||
if(!need_execute)
|
||||
{
|
||||
ssdel << "DELETE FROM character_achievement WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND achievement IN (";
|
||||
ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES ";
|
||||
need_execute = true;
|
||||
}
|
||||
/// next new/changed record prefix
|
||||
else
|
||||
{
|
||||
ssdel << ", ";
|
||||
ssins << ", ";
|
||||
}
|
||||
|
||||
// new/changed record data
|
||||
ssdel << iter->first;
|
||||
ssins << "("<<GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << uint64(iter->second.date) << ")";
|
||||
|
||||
/// mark as saved in db
|
||||
iter->second.changed = false;
|
||||
}
|
||||
|
||||
if(need_execute)
|
||||
ssdel << ")";
|
||||
|
||||
if(need_execute)
|
||||
{
|
||||
CharacterDatabase.BeginTransaction ();
|
||||
CharacterDatabase.Execute( ssdel.str().c_str() );
|
||||
CharacterDatabase.Execute( ssins.str().c_str() );
|
||||
CharacterDatabase.CommitTransaction ();
|
||||
}
|
||||
}
|
||||
|
||||
if(!m_criteriaProgress.empty())
|
||||
{
|
||||
/// prepare deleting and insert
|
||||
bool need_execute = false;
|
||||
std::ostringstream ssdel;
|
||||
std::ostringstream ssins;
|
||||
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||
{
|
||||
if(!iter->second.changed)
|
||||
continue;
|
||||
|
||||
/// first new/changed record prefix
|
||||
if(!need_execute)
|
||||
{
|
||||
ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN (";
|
||||
ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES ";
|
||||
need_execute = true;
|
||||
}
|
||||
/// next new/changed record prefix
|
||||
else
|
||||
{
|
||||
ssdel << ", ";
|
||||
ssins << ", ";
|
||||
}
|
||||
|
||||
// new/changed record data
|
||||
ssdel << iter->first;
|
||||
ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")";
|
||||
|
||||
/// mark as saved in db
|
||||
iter->second.changed = false;
|
||||
}
|
||||
|
||||
if(need_execute)
|
||||
ssdel << ")";
|
||||
|
||||
if(need_execute)
|
||||
{
|
||||
CharacterDatabase.BeginTransaction ();
|
||||
CharacterDatabase.Execute( ssdel.str().c_str() );
|
||||
CharacterDatabase.Execute( ssins.str().c_str() );
|
||||
CharacterDatabase.CommitTransaction ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult)
|
||||
{
|
||||
if(achievementResult)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field *fields = achievementResult->Fetch();
|
||||
CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()];
|
||||
ca.date = time_t(fields[1].GetUInt64());
|
||||
ca.changed = false;
|
||||
} while(achievementResult->NextRow());
|
||||
delete achievementResult;
|
||||
}
|
||||
|
||||
if(criteriaResult)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field *fields = criteriaResult->Fetch();
|
||||
|
||||
uint32 id = fields[0].GetUInt32();
|
||||
uint32 counter = fields[1].GetUInt32();
|
||||
time_t date = time_t(fields[2].GetUInt64());
|
||||
|
||||
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(id);
|
||||
if(!criteria || criteria->timeLimit && date + criteria->timeLimit < time(NULL))
|
||||
continue;
|
||||
|
||||
CriteriaProgress& progress = m_criteriaProgress[id];
|
||||
progress.counter = counter;
|
||||
progress.date = date;
|
||||
progress.changed = false;
|
||||
} while(criteriaResult->NextRow());
|
||||
delete criteriaResult;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
|
||||
{
|
||||
sLog.outString("AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
|
||||
|
||||
const char *msg = "|Hplayer:$N|h[$N]|h has earned the achievement $a!";
|
||||
if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()))
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
data << uint8(CHAT_MSG_ACHIEVEMENT);
|
||||
data << uint8(CHAT_MSG_GUILD_ACHIEVEMENT);
|
||||
data << uint32(LANG_UNIVERSAL);
|
||||
data << uint64(GetPlayer()->GetGUID());
|
||||
data << uint32(5);
|
||||
data << uint64(GetPlayer()->GetGUID());
|
||||
data << uint32(strlen(msg)+1);
|
||||
data << msg;
|
||||
data << uint8(0);
|
||||
data << uint32(achievement->ID);
|
||||
guild->BroadcastPacket(&data);
|
||||
}
|
||||
if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL|ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
|
||||
{
|
||||
// broadcast realm first reached
|
||||
WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, strlen(GetPlayer()->GetName())+1+8+4+4);
|
||||
data << GetPlayer()->GetName();
|
||||
data << uint64(GetPlayer()->GetGUID());
|
||||
data << uint32(achievement->ID);
|
||||
data << uint32(0); // 1=link supplied string as player name, 0=display plain string
|
||||
sWorld.SendGlobalMessage(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPacket data(SMSG_MESSAGECHAT, 200);
|
||||
data << uint8(CHAT_MSG_ACHIEVEMENT);
|
||||
data << uint32(LANG_UNIVERSAL);
|
||||
data << uint64(GetPlayer()->GetGUID());
|
||||
data << uint32(5);
|
||||
data << uint64(GetPlayer()->GetGUID());
|
||||
data << uint32(strlen(msg)+1);
|
||||
data << msg;
|
||||
data << uint8(0);
|
||||
data << uint32(achievement->ID);
|
||||
GetPlayer()->SendMessageToSet(&data, true);
|
||||
|
||||
}
|
||||
WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8);
|
||||
data.append(GetPlayer()->GetPackGUID());
|
||||
data << uint32(achievement->ID);
|
||||
data << uint32(secsToTimeBitFields(time(NULL)));
|
||||
data << uint32(0);
|
||||
GetPlayer()->SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
void AchievementMgr::SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress)
|
||||
{
|
||||
WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
|
||||
data << uint32(id);
|
||||
|
||||
// the counter is packed like a packed Guid
|
||||
data.appendPackGUID(progress->counter);
|
||||
|
||||
data.append(GetPlayer()->GetPackGUID());
|
||||
data << uint32(0);
|
||||
data << uint32(secsToTimeBitFields(progress->date));
|
||||
data << uint32(0); // timer 1
|
||||
data << uint32(0); // timer 2
|
||||
GetPlayer()->SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet
|
||||
*/
|
||||
void AchievementMgr::CheckAllAchievementCriteria()
|
||||
{
|
||||
// suppress sending packets
|
||||
for(uint32 i=0; i<ACHIEVEMENT_CRITERIA_TYPE_TOTAL; i++)
|
||||
UpdateAchievementCriteria(AchievementCriteriaTypes(i));
|
||||
}
|
||||
|
||||
/**
|
||||
* this function will be called whenever the user might have done a criteria relevant action
|
||||
*/
|
||||
void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time)
|
||||
{
|
||||
sLog.outString("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time);
|
||||
AchievementCriteriaEntryList const& achievementCriteriaList = objmgr.GetAchievementCriteriaByType(type);
|
||||
for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i)
|
||||
{
|
||||
AchievementCriteriaEntry const *achievementCriteria = (*i);
|
||||
|
||||
// don't update already completed criteria
|
||||
if(IsCompletedCriteria(achievementCriteria))
|
||||
continue;
|
||||
|
||||
if(achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup())
|
||||
continue;
|
||||
|
||||
AchievementEntry const *achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement);
|
||||
if(!achievement)
|
||||
continue;
|
||||
|
||||
if(achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_HORDE && GetPlayer()->GetTeam() != HORDE ||
|
||||
achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE)
|
||||
continue;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
||||
SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel());
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
|
||||
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(achievementCriteria->kill_creature.creatureID != miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue2, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
|
||||
if(uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID))
|
||||
SetCriteriaProgress(achievementCriteria, skillvalue);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
|
||||
{
|
||||
uint32 counter =0;
|
||||
for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++)
|
||||
if(itr->second.m_rewarded)
|
||||
counter++;
|
||||
SetCriteriaProgress(achievementCriteria, counter);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
|
||||
{
|
||||
uint32 counter =0;
|
||||
for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++)
|
||||
{
|
||||
Quest const* quest = objmgr.GetQuestTemplate(itr->first);
|
||||
if(itr->second.m_rewarded && quest->GetZoneOrSort() == achievementCriteria->complete_quests_in_zone.zoneID)
|
||||
counter++;
|
||||
}
|
||||
SetCriteriaProgress(achievementCriteria, counter);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
|
||||
if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
|
||||
SetCriteriaProgress(achievementCriteria, 1);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(miscvalue1 != achievementCriteria->killed_by_creature.creatureEntry)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
|
||||
{
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(achievement->ID == 1260)
|
||||
{
|
||||
if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED)
|
||||
continue;
|
||||
// TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc?
|
||||
if(!gameeventmgr.IsActiveEvent(26))
|
||||
continue;
|
||||
}
|
||||
// miscvalue1 is the ingame fallheight*100 as stored in dbc
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
|
||||
if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
|
||||
SetCriteriaProgress(achievementCriteria, 1);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(achievementCriteria->use_item.itemID != miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
|
||||
// speedup for non-login case
|
||||
if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true));
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
|
||||
// You _have_ to loot that item, just owning it when logging in does _not_ count!
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(miscvalue1 != achievementCriteria->own_item.itemID)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue2, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
|
||||
if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
|
||||
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
|
||||
{
|
||||
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
|
||||
continue;
|
||||
// those requirements couldn't be found in the dbc
|
||||
|
||||
const CriteriaCastSpellRequirement *requirement = NULL;
|
||||
for (uint32 i=0; i<CRITERIA_CAST_SPELL_REQ_COUNT; i++)
|
||||
{
|
||||
if (criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID)
|
||||
{
|
||||
requirement = &criteriaCastSpellRequirements[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (requirement)
|
||||
{
|
||||
if (!unit)
|
||||
continue;
|
||||
|
||||
if (requirement->creatureEntry && unit->GetEntry() != requirement->creatureEntry)
|
||||
continue;
|
||||
|
||||
if (requirement->playerRace && (unit->GetTypeId() != TYPEID_PLAYER || unit->getRace()!=requirement->playerRace))
|
||||
continue;
|
||||
|
||||
if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass))
|
||||
continue;
|
||||
}
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
|
||||
{
|
||||
uint32 spellCount = 0;
|
||||
for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
|
||||
spellIter != GetPlayer()->GetSpellMap().end();
|
||||
spellIter++)
|
||||
{
|
||||
for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first);
|
||||
skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first);
|
||||
skillIter++)
|
||||
{
|
||||
if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine)
|
||||
spellCount++;
|
||||
}
|
||||
}
|
||||
SetCriteriaProgress(achievementCriteria, spellCount);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
|
||||
{
|
||||
// skip for login case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
|
||||
{
|
||||
int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID);
|
||||
if (reputation > 0)
|
||||
SetCriteriaProgress(achievementCriteria, reputation);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
|
||||
{
|
||||
uint32 counter = 0;
|
||||
const FactionStateList factionStateList = GetPlayer()->GetFactionStateList();
|
||||
for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); iter++)
|
||||
{
|
||||
if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED)
|
||||
++counter;
|
||||
}
|
||||
SetCriteriaProgress(achievementCriteria, counter);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
|
||||
{
|
||||
WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
|
||||
if(!worldOverlayEntry)
|
||||
break;
|
||||
|
||||
int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID);
|
||||
if(exploreFlag < 0)
|
||||
break;
|
||||
|
||||
uint32 playerIndexOffset = uint32(exploreFlag) / 32;
|
||||
uint32 mask = 1<< (uint32(exploreFlag) % 32);
|
||||
|
||||
if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
|
||||
SetCriteriaProgress(achievementCriteria, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if(IsCompletedCriteria(achievementCriteria))
|
||||
CompletedCriteria(achievementCriteria);
|
||||
}
|
||||
}
|
||||
|
||||
bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria)
|
||||
{
|
||||
AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement);
|
||||
if(!achievement)
|
||||
return false;
|
||||
|
||||
// counter can never complete
|
||||
if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
|
||||
return false;
|
||||
|
||||
if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
{
|
||||
// someone on this realm has already completed that achievement
|
||||
if(objmgr.allCompletedAchievements.find(achievement->ID)!=objmgr.allCompletedAchievements.end())
|
||||
return false;
|
||||
}
|
||||
|
||||
CriteriaProgressMap::const_iterator itr = m_criteriaProgress.find(achievementCriteria->ID);
|
||||
if(itr == m_criteriaProgress.end())
|
||||
return false;
|
||||
|
||||
CriteriaProgress const* progress = &itr->second;
|
||||
|
||||
switch(achievementCriteria->requiredType)
|
||||
{
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
||||
if(achievement->ID == 467 && GetPlayer()->getClass() != CLASS_SHAMAN ||
|
||||
achievement->ID == 466 && GetPlayer()->getClass() != CLASS_DRUID ||
|
||||
achievement->ID == 465 && GetPlayer()->getClass() != CLASS_PALADIN ||
|
||||
achievement->ID == 464 && GetPlayer()->getClass() != CLASS_PRIEST ||
|
||||
achievement->ID == 463 && GetPlayer()->getClass() != CLASS_WARLOCK ||
|
||||
achievement->ID == 462 && GetPlayer()->getClass() != CLASS_HUNTER ||
|
||||
achievement->ID == 461 && GetPlayer()->getClass() != CLASS_DEATH_KNIGHT ||
|
||||
achievement->ID == 460 && GetPlayer()->getClass() != CLASS_MAGE ||
|
||||
achievement->ID == 459 && GetPlayer()->getClass() != CLASS_WARRIOR ||
|
||||
achievement->ID == 458 && GetPlayer()->getClass() != CLASS_ROGUE ||
|
||||
|
||||
achievement->ID == 1404 && GetPlayer()->getRace() != RACE_GNOME ||
|
||||
achievement->ID == 1405 && GetPlayer()->getRace() != RACE_BLOODELF ||
|
||||
achievement->ID == 1406 && GetPlayer()->getRace() != RACE_DRAENEI ||
|
||||
achievement->ID == 1407 && GetPlayer()->getRace() != RACE_DWARF ||
|
||||
achievement->ID == 1408 && GetPlayer()->getRace() != RACE_HUMAN ||
|
||||
achievement->ID == 1409 && GetPlayer()->getRace() != RACE_NIGHTELF ||
|
||||
achievement->ID == 1410 && GetPlayer()->getRace() != RACE_ORC ||
|
||||
achievement->ID == 1411 && GetPlayer()->getRace() != RACE_TAUREN ||
|
||||
achievement->ID == 1412 && GetPlayer()->getRace() != RACE_TROLL ||
|
||||
achievement->ID == 1413 && GetPlayer()->getRace() != RACE_UNDEAD_PLAYER )
|
||||
return false;
|
||||
return progress->counter >= achievementCriteria->reach_level.level;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
|
||||
return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
return progress->counter >= achievementCriteria->kill_creature.creatureCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
|
||||
return m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end();
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
|
||||
return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
|
||||
return progress->counter >= achievementCriteria->complete_quests_in_zone.questCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
|
||||
return progress->counter >= achievementCriteria->complete_daily_quest.questCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
|
||||
return progress->counter >= 1;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
|
||||
return progress->counter >= achievementCriteria->fall_without_dying.fallHeight;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
|
||||
return progress->counter >= 1;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
|
||||
return progress->counter >= achievementCriteria->use_item.itemCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
|
||||
return progress->counter >= achievementCriteria->own_item.itemCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
|
||||
return progress->counter >= achievementCriteria->loot_item.itemCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
|
||||
return progress->counter >= achievementCriteria->be_spell_target.spellCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
|
||||
return progress->counter >= achievementCriteria->cast_spell.castCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
|
||||
return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
|
||||
return progress->counter >= achievementCriteria->visit_barber.numberOfVisits;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
|
||||
return progress->counter >= achievementCriteria->gain_reputation.reputationAmount;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
|
||||
return progress->counter >= achievementCriteria->gain_exalted_reputation.numberOfExaltedFactions;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
|
||||
return progress->counter >= 1;
|
||||
|
||||
// handle all statistic-only criteria here
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria)
|
||||
{
|
||||
AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement);
|
||||
if(!achievement)
|
||||
return;
|
||||
// counter can never complete
|
||||
if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
|
||||
return;
|
||||
|
||||
if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || GetAchievementCompletionState(achievement)==ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED)
|
||||
{
|
||||
CompletedAchievement(achievement);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: achievement 705 requires 4 criteria to be fulfilled
|
||||
AchievementCompletionState AchievementMgr::GetAchievementCompletionState(AchievementEntry const* entry)
|
||||
{
|
||||
if(m_completedAchievements.find(entry->ID)!=m_completedAchievements.end())
|
||||
return ACHIEVEMENT_COMPLETED_COMPLETED_STORED;
|
||||
|
||||
bool foundOutstanding = false;
|
||||
for (uint32 entryId = 0; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
|
||||
{
|
||||
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
|
||||
if(!criteria || criteria->referredAchievement!= entry->ID)
|
||||
continue;
|
||||
|
||||
if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL)
|
||||
return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED;
|
||||
|
||||
// found an umcompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL
|
||||
if(!IsCompletedCriteria(criteria))
|
||||
foundOutstanding = true;
|
||||
}
|
||||
if(foundOutstanding)
|
||||
return ACHIEVEMENT_COMPLETED_NONE;
|
||||
else
|
||||
return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED;
|
||||
}
|
||||
|
||||
void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative)
|
||||
{
|
||||
sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue);
|
||||
CriteriaProgress *progress = NULL;
|
||||
|
||||
CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
|
||||
|
||||
if(iter == m_criteriaProgress.end())
|
||||
{
|
||||
progress = &m_criteriaProgress[entry->ID];
|
||||
progress->counter = 0;
|
||||
progress->date = time(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = &iter->second;
|
||||
if(relative)
|
||||
newValue += progress->counter;
|
||||
if(progress->counter == newValue)
|
||||
return;
|
||||
progress->counter = newValue;
|
||||
}
|
||||
|
||||
progress->changed = true;
|
||||
|
||||
if(entry->timeLimit)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if(progress->date + entry->timeLimit < now)
|
||||
{
|
||||
progress->counter = 1;
|
||||
}
|
||||
// also it seems illogical, the timeframe will be extended at every criteria update
|
||||
progress->date = now;
|
||||
}
|
||||
SendCriteriaUpdate(entry->ID,progress);
|
||||
}
|
||||
|
||||
void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||
{
|
||||
sLog.outString("AchievementMgr::CompletedAchievement(%u)", achievement->ID);
|
||||
if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end())
|
||||
return;
|
||||
|
||||
SendAchievementEarned(achievement);
|
||||
CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
|
||||
ca.date = time(NULL);
|
||||
ca.changed = true;
|
||||
|
||||
// don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement
|
||||
// TODO: where do set this instead?
|
||||
if(!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
objmgr.allCompletedAchievements.insert(achievement->ID);
|
||||
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT);
|
||||
|
||||
// reward items and titles
|
||||
AchievementReward const* reward = NULL;
|
||||
for (uint32 i=0; i<ACHIEVEMENT_REWARD_COUNT; i++)
|
||||
{
|
||||
if (achievementRewards[i].achievementId == achievement->ID)
|
||||
{
|
||||
reward = &achievementRewards[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (reward)
|
||||
{
|
||||
sLog.outString("achiev %u, title= %u, %u", reward->achievementId, reward->titleId[0], reward->titleId[1]);
|
||||
uint32 titleId = reward->titleId[GetPlayer()->GetTeam() == HORDE?0:1];
|
||||
if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
|
||||
GetPlayer()->SetTitle(titleEntry);
|
||||
|
||||
if (reward->itemId)
|
||||
{
|
||||
ItemPrototype const *pProto = objmgr.GetItemPrototype( reward->itemId );
|
||||
|
||||
if(!pProto)
|
||||
{
|
||||
GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
ItemPosCountVec dest;
|
||||
uint32 no_space = 0;
|
||||
uint8 msg = GetPlayer()->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, reward->itemId, 1, &no_space );
|
||||
|
||||
if( msg != EQUIP_ERR_OK )
|
||||
{
|
||||
GetPlayer()->SendEquipError( msg, NULL, NULL );
|
||||
return;
|
||||
}
|
||||
Item* pItem = GetPlayer()->StoreNewItem( dest, reward->itemId, true);
|
||||
|
||||
if(!pItem)
|
||||
{
|
||||
GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AchievementMgr::SendAllAchievementData()
|
||||
{
|
||||
// since we don't know the exact size of the packed GUIDs this is just an approximation
|
||||
WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, 4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4);
|
||||
BuildAllDataPacket(&data);
|
||||
GetPlayer()->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
void AchievementMgr::SendRespondInspectAchievements(Player* player)
|
||||
{
|
||||
// since we don't know the exact size of the packed GUIDs this is just an approximation
|
||||
WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 4+4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4);
|
||||
data.append(GetPlayer()->GetPackGUID());
|
||||
BuildAllDataPacket(&data);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
/**
|
||||
* used by both SMSG_ALL_ACHIEVEMENT_DATA and SMSG_RESPOND_INSPECT_ACHIEVEMENT
|
||||
*/
|
||||
void AchievementMgr::BuildAllDataPacket(WorldPacket *data)
|
||||
{
|
||||
for(CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter)
|
||||
{
|
||||
*data << uint32(iter->first);
|
||||
*data << uint32(secsToTimeBitFields(iter->second.date));
|
||||
}
|
||||
*data << int32(-1);
|
||||
|
||||
for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||
{
|
||||
*data << uint32(iter->first);
|
||||
data->appendPackGUID(iter->second.counter);
|
||||
data->append(GetPlayer()->GetPackGUID());
|
||||
*data << uint32(0);
|
||||
*data << uint32(secsToTimeBitFields(iter->second.date));
|
||||
*data << uint32(0);
|
||||
*data << uint32(0);
|
||||
}
|
||||
|
||||
*data << int32(-1);
|
||||
}
|
||||
101
src/game/AchievementMgr.h
Normal file
101
src/game/AchievementMgr.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef __MANGOS_ACHIEVEMENTMGR_H
|
||||
#define __MANGOS_ACHIEVEMENTMGR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Database/DBCEnums.h"
|
||||
#include "Database/DBCStores.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
|
||||
#define CRITERIA_CAST_SPELL_REQ_COUNT 46
|
||||
#define ACHIEVEMENT_REWARD_COUNT 57
|
||||
|
||||
struct CriteriaProgress
|
||||
{
|
||||
uint32 counter;
|
||||
time_t date;
|
||||
bool changed;
|
||||
};
|
||||
|
||||
struct CriteriaCastSpellRequirement
|
||||
{
|
||||
uint32 achievementCriteriaId;
|
||||
uint32 creatureEntry;
|
||||
uint8 playerClass;
|
||||
uint8 playerRace;
|
||||
};
|
||||
|
||||
struct AchievementReward
|
||||
{
|
||||
uint32 achievementId;
|
||||
uint32 titleId[2];
|
||||
uint32 itemId;
|
||||
};
|
||||
|
||||
struct CompletedAchievementData
|
||||
{
|
||||
time_t date;
|
||||
bool changed;
|
||||
};
|
||||
|
||||
typedef UNORDERED_MAP<uint32, CriteriaProgress> CriteriaProgressMap;
|
||||
typedef UNORDERED_MAP<uint32, CompletedAchievementData> CompletedAchievementMap;
|
||||
|
||||
class Unit;
|
||||
class Player;
|
||||
class WorldPacket;
|
||||
|
||||
enum AchievementCompletionState
|
||||
{
|
||||
ACHIEVEMENT_COMPLETED_NONE,
|
||||
ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED,
|
||||
ACHIEVEMENT_COMPLETED_COMPLETED_STORED,
|
||||
};
|
||||
|
||||
class AchievementMgr
|
||||
{
|
||||
public:
|
||||
AchievementMgr(Player* pl);
|
||||
~AchievementMgr();
|
||||
|
||||
void LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult);
|
||||
void SaveToDB();
|
||||
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0);
|
||||
void CheckAllAchievementCriteria();
|
||||
void SendAllAchievementData();
|
||||
void SendRespondInspectAchievements(Player* player);
|
||||
Player* GetPlayer() { return m_player;}
|
||||
|
||||
private:
|
||||
void SendAchievementEarned(AchievementEntry const* achievement);
|
||||
void SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress);
|
||||
void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false);
|
||||
void CompletedCriteria(AchievementCriteriaEntry const* entry);
|
||||
void CompletedAchievement(AchievementEntry const* entry);
|
||||
bool IsCompletedCriteria(AchievementCriteriaEntry const* entry);
|
||||
AchievementCompletionState GetAchievementCompletionState(AchievementEntry const* entry);
|
||||
void BuildAllDataPacket(WorldPacket *data);
|
||||
|
||||
Player* m_player;
|
||||
CriteriaProgressMap m_criteriaProgress;
|
||||
CompletedAchievementMap m_completedAchievements;
|
||||
static const CriteriaCastSpellRequirement criteriaCastSpellRequirements[];
|
||||
static const AchievementReward achievementRewards[];
|
||||
};
|
||||
#endif
|
||||
|
|
@ -44,7 +44,7 @@ ArenaTeam::~ArenaTeam()
|
|||
|
||||
}
|
||||
|
||||
bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamName)
|
||||
bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string ArenaTeamName)
|
||||
{
|
||||
if(!objmgr.GetPlayer(captainGuid)) // player not exist
|
||||
return false;
|
||||
|
|
@ -67,9 +67,9 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam
|
|||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", Id);
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) "
|
||||
"VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')",
|
||||
Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor);
|
||||
Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor);
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES "
|
||||
"('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id,stats.rating,stats.games_week,stats.wins_week,stats.games_season,stats.wins_season,stats.rank);
|
||||
"('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id, stats.rating, stats.games_week, stats.wins_week, stats.games_season, stats.wins_season, stats.rank);
|
||||
|
||||
CharacterDatabase.CommitTransaction();
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ArenaTeam::AddMember(uint64 PlayerGuid)
|
||||
bool ArenaTeam::AddMember(const uint64& PlayerGuid)
|
||||
{
|
||||
std::string plName;
|
||||
uint8 plClass;
|
||||
|
|
@ -132,39 +132,23 @@ bool ArenaTeam::AddMember(uint64 PlayerGuid)
|
|||
newmember.personal_rating = 1500;
|
||||
members.push_back(newmember);
|
||||
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid,guid) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid));
|
||||
CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", Id, GUID_LOPART(newmember.guid), newmember.personal_rating );
|
||||
|
||||
if(pl)
|
||||
{
|
||||
pl->SetInArenaTeam(Id, GetSlot());
|
||||
pl->SetArenaTeamIdInvited(0);
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating );
|
||||
|
||||
// hide promote/remove buttons
|
||||
if(CaptainGuid != PlayerGuid)
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tokens tokens;
|
||||
if(Player::LoadValuesArrayFromDB(tokens,PlayerGuid))
|
||||
{
|
||||
Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id);
|
||||
// hide promote/remove buttons
|
||||
if(CaptainGuid != PlayerGuid)
|
||||
Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
|
||||
|
||||
Player::SaveValuesArrayInDB(tokens,PlayerGuid);
|
||||
}
|
||||
pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId)
|
||||
{
|
||||
LoadStatsFromDB(ArenaTeamId);
|
||||
LoadMembersFromDB(ArenaTeamId);
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
|
||||
if(!result)
|
||||
|
|
@ -184,6 +168,21 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId)
|
|||
|
||||
delete result;
|
||||
|
||||
// only load here, so additional checks can be made
|
||||
LoadStatsFromDB(ArenaTeamId);
|
||||
LoadMembersFromDB(ArenaTeamId);
|
||||
|
||||
if(Empty())
|
||||
{
|
||||
// arena team is empty, delete from db
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -209,49 +208,37 @@ void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId)
|
|||
|
||||
void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId)
|
||||
{
|
||||
Field *fields;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId);
|
||||
// 0 1 2 3 4 5 6 7
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class "
|
||||
"FROM arena_team_member member "
|
||||
"INNER JOIN characters chars on member.guid = chars.guid "
|
||||
"WHERE member.arenateamid = '%u'", ArenaTeamId);
|
||||
if(!result)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
fields = result->Fetch();
|
||||
Field *fields = result->Fetch();
|
||||
ArenaTeamMember newmember;
|
||||
newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
LoadPlayerStats(&newmember);
|
||||
newmember.games_week = fields[1].GetUInt32();
|
||||
newmember.wins_week = fields[2].GetUInt32();
|
||||
newmember.games_season = fields[3].GetUInt32();
|
||||
newmember.wins_season = fields[4].GetUInt32();
|
||||
newmember.personal_rating = fields[5].GetUInt32();
|
||||
newmember.name = fields[6].GetCppString();
|
||||
newmember.Class = fields[7].GetUInt8();
|
||||
members.push_back(newmember);
|
||||
}while( result->NextRow() );
|
||||
delete result;
|
||||
}
|
||||
|
||||
void ArenaTeam::LoadPlayerStats(ArenaTeamMember *member)
|
||||
{
|
||||
Field *fields;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT name,class FROM characters WHERE guid = '%u'", GUID_LOPART(member->guid));
|
||||
if(!result)
|
||||
return;
|
||||
fields = result->Fetch();
|
||||
member->name = fields[0].GetCppString();
|
||||
member->Class = fields[1].GetUInt8();
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
||||
void ArenaTeam::SetCaptain(uint64 guid)
|
||||
void ArenaTeam::SetCaptain(const uint64& guid)
|
||||
{
|
||||
// disable remove/promote buttons
|
||||
Player *oldcaptain = objmgr.GetPlayer(GetCaptain());
|
||||
if(oldcaptain)
|
||||
oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
|
||||
else
|
||||
Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, GetCaptain());
|
||||
|
||||
// set new captain
|
||||
CaptainGuid = guid;
|
||||
|
|
@ -263,14 +250,11 @@ void ArenaTeam::SetCaptain(uint64 guid)
|
|||
Player *newcaptain = objmgr.GetPlayer(guid);
|
||||
if(newcaptain)
|
||||
newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0);
|
||||
else
|
||||
Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0, guid);
|
||||
}
|
||||
|
||||
void ArenaTeam::DelMember(uint64 guid)
|
||||
{
|
||||
MemberList::iterator itr;
|
||||
for (itr = members.begin(); itr != members.end(); itr++)
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if (itr->guid == guid)
|
||||
{
|
||||
|
|
@ -280,17 +264,19 @@ void ArenaTeam::DelMember(uint64 guid)
|
|||
}
|
||||
|
||||
Player *player = objmgr.GetPlayer(guid);
|
||||
|
||||
if(player)
|
||||
{
|
||||
player->SetInArenaTeam(0, GetSlot());
|
||||
player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid);
|
||||
// delete all info regarding this team
|
||||
for(int i = 0; i < 6; ++i)
|
||||
{
|
||||
player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid));
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid));
|
||||
}
|
||||
|
||||
void ArenaTeam::Disband(WorldSession *session)
|
||||
|
|
@ -300,23 +286,15 @@ void ArenaTeam::Disband(WorldSession *session)
|
|||
session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), "");
|
||||
BroadcastPacket(&data);
|
||||
|
||||
uint32 count = members.size();
|
||||
uint64 *memberGuids = new uint64[count];
|
||||
|
||||
MemberList::iterator itr;
|
||||
uint32 i=0;
|
||||
for(itr = members.begin(); itr != members.end(); itr++)
|
||||
while (!members.empty())
|
||||
{
|
||||
memberGuids[i] = itr->guid;
|
||||
++i;
|
||||
// Removing from members is done in DelMember.
|
||||
DelMember(members.front().guid);
|
||||
}
|
||||
|
||||
for(uint32 j = 0; j < count; j++)
|
||||
DelMember(memberGuids[j]);
|
||||
delete[] memberGuids;
|
||||
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id);
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member
|
||||
CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id);
|
||||
CharacterDatabase.CommitTransaction();
|
||||
objmgr.RemoveArenaTeam(this);
|
||||
|
|
@ -334,34 +312,18 @@ void ArenaTeam::Roster(WorldSession *session)
|
|||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
pl = objmgr.GetPlayer(itr->guid);
|
||||
if(pl)
|
||||
{
|
||||
data << uint64(pl->GetGUID()); // guid
|
||||
data << uint8(1); // online flag
|
||||
data << pl->GetName(); // member name
|
||||
data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown
|
||||
data << uint8(pl->getLevel()); // unknown, probably level
|
||||
data << uint8(pl->getClass()); // class
|
||||
data << uint32(itr->games_week); // played this week
|
||||
data << uint32(itr->wins_week); // wins this week
|
||||
data << uint32(itr->games_season); // played this season
|
||||
data << uint32(itr->wins_season); // wins this season
|
||||
data << uint32(itr->personal_rating); // personal rating
|
||||
}
|
||||
else
|
||||
{
|
||||
data << uint64(itr->guid); // guid
|
||||
data << uint8(0); // online flag
|
||||
data << itr->name; // member name
|
||||
data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown
|
||||
data << uint8(0); // unknown, level?
|
||||
data << uint8(itr->Class); // class
|
||||
data << uint32(itr->games_week); // played this week
|
||||
data << uint32(itr->wins_week); // wins this week
|
||||
data << uint32(itr->games_season); // played this season
|
||||
data << uint32(itr->wins_season); // wins this season
|
||||
data << uint32(itr->personal_rating); // personal rating
|
||||
}
|
||||
|
||||
data << uint64(itr->guid); // guid
|
||||
data << uint8((pl ? 1 : 0)); // online flag
|
||||
data << itr->name; // member name
|
||||
data << uint32((itr->guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
|
||||
data << uint8((pl ? pl->getLevel() : 0)); // unknown, level?
|
||||
data << uint8(itr->Class); // class
|
||||
data << uint32(itr->games_week); // played this week
|
||||
data << uint32(itr->wins_week); // wins this week
|
||||
data << uint32(itr->games_season); // played this season
|
||||
data << uint32(itr->wins_season); // wins this season
|
||||
data << uint32(itr->personal_rating); // personal rating
|
||||
}
|
||||
session->SendPacket(&data);
|
||||
sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
|
||||
|
|
@ -395,6 +357,18 @@ void ArenaTeam::Stats(WorldSession *session)
|
|||
session->SendPacket(&data);
|
||||
}
|
||||
|
||||
void ArenaTeam::NotifyStatsChanged()
|
||||
{
|
||||
// this is called after a rated match ended
|
||||
// updates arena team stats for every member of the team (not only the ones who participated!)
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
Player * plr = objmgr.GetPlayer(itr->guid);
|
||||
if(plr)
|
||||
Stats(plr->GetSession());
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::InspectStats(WorldSession *session, uint64 guid)
|
||||
{
|
||||
ArenaTeamMember* member = GetMember(guid);
|
||||
|
|
@ -408,8 +382,8 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid)
|
|||
data << uint32(stats.rating); // rating
|
||||
data << uint32(stats.games_season); // season played
|
||||
data << uint32(stats.wins_season); // season wins
|
||||
data << member->games_season; // played (count of all games, that the inspected member participated...)
|
||||
data << member->personal_rating; // personal rating
|
||||
data << uint32(member->games_season); // played (count of all games, that the inspected member participated...)
|
||||
data << uint32(member->personal_rating); // personal rating
|
||||
session->SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
@ -458,18 +432,6 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value)
|
|||
}
|
||||
}
|
||||
|
||||
uint8 ArenaTeam::GetSlot() const
|
||||
{
|
||||
uint8 slot = GetSlotByType(GetType());
|
||||
if(slot >= MAX_ARENA_SLOT)
|
||||
{
|
||||
sLog.outError("Unknown arena team type %u for arena team %u", uint32(GetType()), GetId());
|
||||
return 0; // better return existed slot to prevent untelated data curruption
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
void ArenaTeam::BroadcastPacket(WorldPacket *packet)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
|
|
@ -490,18 +452,184 @@ uint8 ArenaTeam::GetSlotByType( uint32 type )
|
|||
default:
|
||||
break;
|
||||
}
|
||||
sLog.outError("FATAL: Unknown arena team type %u for some arena team", type);
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
bool ArenaTeam::HaveMember( uint64 guid ) const
|
||||
bool ArenaTeam::HaveMember( const uint64& guid ) const
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
if(itr->guid==guid)
|
||||
if(itr->guid == guid)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 ArenaTeam::GetPoints(uint32 MemberRating)
|
||||
{
|
||||
// returns how many points would be awarded with this team type with this rating
|
||||
float points;
|
||||
|
||||
uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating;
|
||||
|
||||
if(rating<=1500)
|
||||
points = (float)rating * 0.22f + 14.0f;
|
||||
else
|
||||
points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating));
|
||||
|
||||
// type penalties for <5v5 teams
|
||||
if(Type == ARENA_TEAM_2v2)
|
||||
points *= 0.76f;
|
||||
else if(Type == ARENA_TEAM_3v3)
|
||||
points *= 0.88f;
|
||||
|
||||
return (uint32) points;
|
||||
}
|
||||
|
||||
float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating)
|
||||
{
|
||||
// returns the chance to win against a team with the given rating, used in the rating adjustment calculation
|
||||
// ELO system
|
||||
return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)enemy_rating - (float)own_rating)/400.0f));
|
||||
}
|
||||
|
||||
int32 ArenaTeam::WonAgainst(uint32 againstRating)
|
||||
{
|
||||
// called when the team has won
|
||||
//'chance' calculation - to beat the opponent
|
||||
float chance = GetChanceAgainst(stats.rating,againstRating);
|
||||
// calculate the rating modification (ELO system with k=32)
|
||||
int32 mod = (int32)floor(32.0f * (1.0f - chance));
|
||||
// modify the team stats accordingly
|
||||
stats.rating += mod;
|
||||
stats.games_week += 1;
|
||||
stats.wins_week += 1;
|
||||
stats.games_season += 1;
|
||||
stats.wins_season += 1;
|
||||
//update team's rank
|
||||
stats.rank = 1;
|
||||
ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin();
|
||||
for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i)
|
||||
{
|
||||
if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating)
|
||||
++stats.rank;
|
||||
}
|
||||
|
||||
// return the rating change, used to display it on the results screen
|
||||
return mod;
|
||||
}
|
||||
|
||||
int32 ArenaTeam::LostAgainst(uint32 againstRating)
|
||||
{
|
||||
// called when the team has lost
|
||||
//'chance' calculation - to loose to the opponent
|
||||
float chance = GetChanceAgainst(stats.rating,againstRating);
|
||||
// calculate the rating modification (ELO system with k=32)
|
||||
int32 mod = (int32)ceil(32.0f * (0.0f - chance));
|
||||
// modify the team stats accordingly
|
||||
stats.rating += mod;
|
||||
stats.games_week += 1;
|
||||
stats.games_season += 1;
|
||||
//update team's rank
|
||||
|
||||
stats.rank = 1;
|
||||
ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin();
|
||||
for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i)
|
||||
{
|
||||
if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating)
|
||||
++stats.rank;
|
||||
}
|
||||
|
||||
// return the rating change, used to display it on the results screen
|
||||
return mod;
|
||||
}
|
||||
|
||||
void ArenaTeam::MemberLost(Player * plr, uint32 againstRating)
|
||||
{
|
||||
// called for each participant of a match after losing
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if(itr->guid == plr->GetGUID())
|
||||
{
|
||||
// update personal rating
|
||||
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
|
||||
int32 mod = (int32)ceil(32.0f * (0.0f - chance));
|
||||
itr->ModifyPersonalRating(plr, mod, GetSlot());
|
||||
// update personal played stats
|
||||
itr->games_week +=1;
|
||||
itr->games_season +=1;
|
||||
// update the unit fields
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week);
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::MemberWon(Player * plr, uint32 againstRating)
|
||||
{
|
||||
// called for each participant after winning a match
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if(itr->guid == plr->GetGUID())
|
||||
{
|
||||
// update personal rating
|
||||
float chance = GetChanceAgainst(itr->personal_rating, againstRating);
|
||||
int32 mod = (int32)floor(32.0f * (1.0f - chance));
|
||||
itr->ModifyPersonalRating(plr, mod, GetSlot());
|
||||
// update personal stats
|
||||
itr->games_week +=1;
|
||||
itr->games_season +=1;
|
||||
itr->wins_season += 1;
|
||||
itr->wins_week += 1;
|
||||
// update unit fields
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week);
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& PlayerPoints)
|
||||
{
|
||||
// called after a match has ended and the stats are already modified
|
||||
// helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
|
||||
// 10 played games per week is a minimum
|
||||
if (stats.games_week < 10)
|
||||
return;
|
||||
// to get points, a player has to participate in at least 30% of the matches
|
||||
uint32 min_plays = (uint32) ceil(stats.games_week * 0.3);
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
// the player participated in enough games, update his points
|
||||
uint32 points_to_add = 0;
|
||||
if (itr->games_week >= min_plays)
|
||||
points_to_add = GetPoints(itr->personal_rating);
|
||||
// OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid);
|
||||
|
||||
std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.find(GUID_LOPART(itr->guid));
|
||||
if (plr_itr != PlayerPoints.end())
|
||||
{
|
||||
//check if there is already more points
|
||||
if (plr_itr->second < points_to_add)
|
||||
PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add;
|
||||
}
|
||||
else
|
||||
PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add;
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::SaveToDB()
|
||||
{
|
||||
// save team and member stats to db
|
||||
// called after a match has ended, or when calculating arena_points
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games_week, stats.games_season, stats.rank, stats.wins_week, stats.wins_season, GetId());
|
||||
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, Id, itr->guid);
|
||||
}
|
||||
}
|
||||
|
||||
void ArenaTeam::FinishWeek()
|
||||
{
|
||||
stats.games_week = 0; // played this week
|
||||
|
|
@ -519,18 +647,18 @@ arenateam fields (id from 2.3.3 client):
|
|||
1415 - 0=captain, 1=member
|
||||
1416 - played this week
|
||||
1417 - played this season
|
||||
1418 - unk
|
||||
1418 - unk - rank?
|
||||
1419 - personal arena rating
|
||||
1420 - arena team id 3v3
|
||||
1421 - 0=captain, 1=member
|
||||
1422 - played this week
|
||||
1423 - played this season
|
||||
1424 - unk
|
||||
1424 - unk - rank?
|
||||
1425 - personal arena rating
|
||||
1426 - arena team id 5v5
|
||||
1427 - 0=captain, 1=member
|
||||
1428 - played this week
|
||||
1429 - played this season
|
||||
1430 - unk
|
||||
1430 - unk - rank?
|
||||
1431 - personal arena rating
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ enum ArenaTeamCommandErrors
|
|||
ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM = 0x09,
|
||||
ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS = 0x0A,
|
||||
ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S = 0x0B,
|
||||
ERR_ARENA_TEAM_NOT_ALLIED = 0x0C
|
||||
ERR_ARENA_TEAM_NOT_ALLIED = 0x0C,
|
||||
ERR_ARENA_TEAM_PLAYER_TO_LOW = 0x15,
|
||||
ERR_ARENA_TEAM_FULL = 0x16
|
||||
};
|
||||
|
||||
enum ArenaTeamEvents
|
||||
|
|
@ -85,14 +87,22 @@ struct ArenaTeamMember
|
|||
{
|
||||
uint64 guid;
|
||||
std::string name;
|
||||
//uint32 unk2;
|
||||
//uint8 unk1;
|
||||
uint8 Class;
|
||||
uint32 games_week;
|
||||
uint32 wins_week;
|
||||
uint32 games_season;
|
||||
uint32 wins_season;
|
||||
uint32 personal_rating;
|
||||
|
||||
void ModifyPersonalRating(Player* plr, int32 mod, uint32 slot)
|
||||
{
|
||||
if (personal_rating + mod < 0)
|
||||
personal_rating = 0;
|
||||
else
|
||||
personal_rating += mod;
|
||||
if(plr)
|
||||
plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot*6) + 5, personal_rating);
|
||||
}
|
||||
};
|
||||
|
||||
struct ArenaTeamStats
|
||||
|
|
@ -113,58 +123,78 @@ class ArenaTeam
|
|||
ArenaTeam();
|
||||
~ArenaTeam();
|
||||
|
||||
bool create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName);
|
||||
bool Create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName);
|
||||
void Disband(WorldSession *session);
|
||||
|
||||
typedef std::list<ArenaTeamMember> MemberList;
|
||||
|
||||
uint32 GetId() const { return Id; }
|
||||
uint32 GetType() const { return Type; }
|
||||
uint8 GetSlot() const;
|
||||
uint32 GetId() const { return Id; }
|
||||
uint32 GetType() const { return Type; }
|
||||
uint8 GetSlot() const { return GetSlotByType(GetType()); }
|
||||
static uint8 GetSlotByType(uint32 type);
|
||||
const uint64& GetCaptain() const { return CaptainGuid; }
|
||||
std::string GetName() const { return Name; }
|
||||
const uint64& GetCaptain() const { return CaptainGuid; }
|
||||
std::string GetName() const { return Name; }
|
||||
const ArenaTeamStats& GetStats() const { return stats; }
|
||||
void SetStats(uint32 stat_type, uint32 value);
|
||||
uint32 GetRating() const { return stats.rating; }
|
||||
uint32 GetRating() const { return stats.rating; }
|
||||
|
||||
uint32 GetEmblemStyle() const { return EmblemStyle; }
|
||||
uint32 GetEmblemColor() const { return EmblemColor; }
|
||||
uint32 GetBorderStyle() const { return BorderStyle; }
|
||||
uint32 GetBorderColor() const { return BorderColor; }
|
||||
uint32 GetEmblemStyle() const { return EmblemStyle; }
|
||||
uint32 GetEmblemColor() const { return EmblemColor; }
|
||||
uint32 GetBorderStyle() const { return BorderStyle; }
|
||||
uint32 GetBorderColor() const { return BorderColor; }
|
||||
uint32 GetBackgroundColor() const { return BackgroundColor; }
|
||||
|
||||
void SetCaptain(uint64 guid);
|
||||
bool AddMember(uint64 PlayerGuid);
|
||||
void SetCaptain(const uint64& guid);
|
||||
bool AddMember(const uint64& PlayerGuid);
|
||||
|
||||
// Shouldn't be const uint64& ed, because than can reference guid from members on Disband
|
||||
// and this method removes given record from list. So invalid reference can happen.
|
||||
void DelMember(uint64 guid);
|
||||
|
||||
void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor);
|
||||
|
||||
uint32 GetMembersSize() const { return members.size(); }
|
||||
MemberList::iterator membersbegin(){ return members.begin(); }
|
||||
MemberList::iterator membersEnd(){ return members.end(); }
|
||||
bool HaveMember(uint64 guid) const;
|
||||
ArenaTeamMember* GetMember(uint64 guid)
|
||||
size_t GetMembersSize() const { return members.size(); }
|
||||
bool Empty() const { return members.empty(); }
|
||||
MemberList::iterator membersBegin() { return members.begin(); }
|
||||
MemberList::iterator membersEnd() { return members.end(); }
|
||||
bool HaveMember(const uint64& guid) const;
|
||||
|
||||
ArenaTeamMember* GetMember(const uint64& guid)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
if(itr->guid==guid)
|
||||
if(itr->guid == guid)
|
||||
return &(*itr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
ArenaTeamMember* GetMember(std::string& name)
|
||||
|
||||
ArenaTeamMember* GetMember(const std::string& name)
|
||||
{
|
||||
for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
if(itr->name==name)
|
||||
if(itr->name == name)
|
||||
return &(*itr);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool IsFighting() const
|
||||
{
|
||||
for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
|
||||
{
|
||||
if (Player *p = objmgr.GetPlayer(itr->guid))
|
||||
{
|
||||
if (p->GetMap()->IsBattleArena())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadArenaTeamFromDB(uint32 ArenaTeamId);
|
||||
void LoadMembersFromDB(uint32 ArenaTeamId);
|
||||
void LoadStatsFromDB(uint32 ArenaTeamId);
|
||||
void LoadPlayerStats(ArenaTeamMember* member);
|
||||
|
||||
void SaveToDB();
|
||||
|
||||
void BroadcastPacket(WorldPacket *packet);
|
||||
|
||||
|
|
@ -173,6 +203,17 @@ class ArenaTeam
|
|||
void Stats(WorldSession *session);
|
||||
void InspectStats(WorldSession *session, uint64 guid);
|
||||
|
||||
uint32 GetPoints(uint32 MemberRating);
|
||||
float GetChanceAgainst(uint32 own_rating, uint32 enemy_rating);
|
||||
int32 WonAgainst(uint32 againstRating);
|
||||
void MemberWon(Player * plr, uint32 againstRating);
|
||||
int32 LostAgainst(uint32 againstRating);
|
||||
void MemberLost(Player * plr, uint32 againstRating);
|
||||
|
||||
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
|
||||
|
||||
void NotifyStatsChanged();
|
||||
|
||||
void FinishWeek();
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("MSG_INSPECT_ARENA_TEAMS");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 8);
|
||||
|
||||
|
|
@ -54,7 +53,6 @@ void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_QUERY" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -72,7 +70,6 @@ void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_ROSTER" );
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -89,7 +86,6 @@ void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
|
|
@ -110,15 +106,13 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
|||
|
||||
if(!player)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
//SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
// can't find related opcode
|
||||
SendNotification(LANG_HIS_ARENA_LEVEL_REQ_ERROR, player->GetName());
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -141,21 +135,19 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data)
|
|||
|
||||
if(player->GetArenaTeamId(arenateam->GetSlot()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(arenateam->GetMembersSize() >= arenateam->GetType() * 2)
|
||||
{
|
||||
// should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL
|
||||
// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL);
|
||||
SendNotification(LANG_YOUR_ARENA_TEAM_FULL, player->GetName());
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,arenateam->GetName(),"",ERR_ARENA_TEAM_FULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -177,23 +169,25 @@ void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/
|
|||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited());
|
||||
if(!at)
|
||||
return;
|
||||
|
||||
if(_player->GetArenaTeamIdFromDB(_player->GetGUIDLow(), at->GetType()))
|
||||
{
|
||||
// arena team not exist
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ALREADY_IN_ARENA_TEAM); // already in arena team that size
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamId(at->GetSlot()))
|
||||
{
|
||||
// already in arena team that size
|
||||
return;
|
||||
}
|
||||
|
||||
// not let enemies sign petition
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_NOT_ALLIED);// not let enemies sign petition
|
||||
return;
|
||||
}
|
||||
|
||||
if(!at->AddMember(_player->GetGUID()))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_INTERNAL);// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
// event
|
||||
WorldPacket data;
|
||||
|
|
@ -211,7 +205,6 @@ void WorldSession::HandleArenaTeamInviteDeclineOpcode(WorldPacket & /*recv_data*
|
|||
void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_LEAVE");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -220,10 +213,7 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
|||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// send command result
|
||||
return;
|
||||
}
|
||||
if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1)
|
||||
{
|
||||
// check for correctness
|
||||
|
|
@ -245,13 +235,13 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data)
|
|||
BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEAVE_SS, 2, _player->GetName(), at->GetName(), "");
|
||||
at->BroadcastPacket(&data);
|
||||
|
||||
//SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0);
|
||||
//send you are no longer member of team
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0);
|
||||
}
|
||||
|
||||
void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_DISBAND");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
|
|
@ -260,16 +250,13 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
|||
|
||||
ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId);
|
||||
if(!at)
|
||||
{
|
||||
// arena team not found
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() != _player->GetGUID())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (at->IsFighting())
|
||||
return;
|
||||
|
||||
at->Disband(this);
|
||||
delete at;
|
||||
|
|
@ -278,7 +265,6 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_REMOVE_FROM_TEAM");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
|
|
@ -303,11 +289,14 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
|||
|
||||
ArenaTeamMember* member = at->GetMember(name);
|
||||
if(!member) // member not found
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == member->guid)
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -322,7 +311,6 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data)
|
|||
void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data)
|
||||
{
|
||||
sLog.outDebug("CMSG_ARENA_TEAM_PROMOTE_TO_CAPTAIN");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1);
|
||||
|
||||
|
|
@ -347,7 +335,10 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data
|
|||
|
||||
ArenaTeamMember* member = at->GetMember(name);
|
||||
if(!member) // member not found
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(at->GetCaptain() == member->guid) // target player already captain
|
||||
return;
|
||||
|
|
@ -360,17 +351,17 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data
|
|||
at->BroadcastPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3)
|
||||
void WorldSession::SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id)
|
||||
{
|
||||
WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4);
|
||||
data << unk1;
|
||||
data << str1;
|
||||
data << str2;
|
||||
data << unk3;
|
||||
WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4);
|
||||
data << team_action;
|
||||
data << team;
|
||||
data << player;
|
||||
data << error_id;
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3)
|
||||
void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, const std::string& str1, const std::string& str2, const std::string& str3)
|
||||
{
|
||||
data->Initialize(SMSG_ARENA_TEAM_EVENT, 1+1+1);
|
||||
*data << eventid;
|
||||
|
|
|
|||
|
|
@ -365,10 +365,15 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data )
|
|||
return;
|
||||
}
|
||||
|
||||
if (price < (auction->bid + objmgr.GetAuctionOutBid(auction->bid)))
|
||||
// cheating
|
||||
if(price <= auction->bid)
|
||||
return;
|
||||
|
||||
// price too low for next bid if not buyout
|
||||
if ((price < auction->buyout || auction->buyout == 0) &&
|
||||
price < auction->bid + objmgr.GetAuctionOutBid(auction->bid))
|
||||
{
|
||||
//auction has already higher bid, client tests it!
|
||||
//SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -745,3 +750,23 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
|
|||
data << (uint32) 300; // unk 2.3.0 const?
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data )
|
||||
{
|
||||
sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES");
|
||||
recv_data.hexlike();
|
||||
|
||||
uint32 count = 0;
|
||||
|
||||
WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4);
|
||||
data << uint32(count); // count
|
||||
/*for(uint32 i = 0; i < count; ++i)
|
||||
{
|
||||
data << ""; // string
|
||||
data << ""; // string
|
||||
data << uint32(0);
|
||||
data << uint32(0);
|
||||
data << float(0);
|
||||
}*/
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ Bag::Bag( ): Item()
|
|||
|
||||
m_valuesCount = CONTAINER_END;
|
||||
|
||||
memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); // Maximum 20 Slots
|
||||
memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE);
|
||||
}
|
||||
|
||||
Bag::~Bag()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "Language.h"
|
||||
#include "Chat.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "World.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
|
@ -47,6 +48,8 @@ BattleGround::BattleGround()
|
|||
m_Name = "";
|
||||
m_LevelMin = 0;
|
||||
m_LevelMax = 0;
|
||||
m_InBGFreeSlotQueue = false;
|
||||
m_SetDeleteThis = false;
|
||||
|
||||
m_MaxPlayersPerTeam = 0;
|
||||
m_MaxPlayers = 0;
|
||||
|
|
@ -67,21 +70,54 @@ BattleGround::BattleGround()
|
|||
m_TeamStartLocO[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamStartLocO[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0;
|
||||
m_ArenaTeamIds[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0;
|
||||
m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_BgRaids[BG_TEAM_ALLIANCE] = NULL;
|
||||
m_BgRaids[BG_TEAM_HORDE] = NULL;
|
||||
|
||||
m_PlayersCount[BG_TEAM_ALLIANCE] = 0;
|
||||
m_PlayersCount[BG_TEAM_HORDE] = 0;
|
||||
|
||||
m_PrematureCountDown = false;
|
||||
m_PrematureCountDown = 0;
|
||||
}
|
||||
|
||||
BattleGround::~BattleGround()
|
||||
{
|
||||
// remove objects and creatures
|
||||
// (this is done automatically in mapmanager update, when the instance is reset after the reset time)
|
||||
int size = m_BgCreatures.size();
|
||||
for(int i = 0; i < size; ++i)
|
||||
{
|
||||
DelCreature(i);
|
||||
}
|
||||
size = m_BgObjects.size();
|
||||
for(int i = 0; i < size; ++i)
|
||||
{
|
||||
DelObject(i);
|
||||
}
|
||||
|
||||
// delete creature and go respawn times
|
||||
WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID());
|
||||
WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID());
|
||||
// delete instance from db
|
||||
CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID());
|
||||
// remove from battlegrounds
|
||||
sBattleGroundMgr.RemoveBattleGround(GetInstanceID());
|
||||
// unload map
|
||||
if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID()))
|
||||
if(map->IsBattleGroundOrArena())
|
||||
((BattleGroundMap*)map)->SetUnload();
|
||||
// remove from bg free slot queue
|
||||
this->RemoveFromBGFreeSlotQueue();
|
||||
}
|
||||
|
||||
void BattleGround::Update(time_t diff)
|
||||
{
|
||||
|
||||
if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize())
|
||||
//BG is empty
|
||||
return;
|
||||
|
|
@ -188,6 +224,33 @@ void BattleGround::Update(time_t diff)
|
|||
m_ResurrectQueue.clear();
|
||||
}
|
||||
|
||||
// if less then minimum players are in on one side, then start premature finish timer
|
||||
if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam()))
|
||||
{
|
||||
if(!m_PrematureCountDown)
|
||||
{
|
||||
m_PrematureCountDown = true;
|
||||
m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime();
|
||||
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
|
||||
}
|
||||
else if(m_PrematureCountDownTimer < diff)
|
||||
{
|
||||
// time's up!
|
||||
EndBattleGround(0); // noone wins
|
||||
m_PrematureCountDown = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 newtime = m_PrematureCountDownTimer - diff;
|
||||
// announce every minute
|
||||
if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000)
|
||||
SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING);
|
||||
m_PrematureCountDownTimer = newtime;
|
||||
}
|
||||
}
|
||||
else if (m_PrematureCountDown)
|
||||
m_PrematureCountDown = false;
|
||||
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
{
|
||||
// remove all players from battleground after 2 minutes
|
||||
|
|
@ -239,7 +302,10 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player *
|
|||
if(!self && sender == plr)
|
||||
continue;
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
plr->GetSession()->SendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
|
@ -265,7 +331,10 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
{
|
||||
sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
|
|
@ -285,7 +354,10 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
plr->CastSpell(plr, SpellID, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -302,7 +374,10 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID)
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor);
|
||||
}
|
||||
}
|
||||
|
|
@ -324,7 +399,10 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
|
|||
continue;
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == TeamID)
|
||||
uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID());
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
if(team == TeamID)
|
||||
plr->ModifyFactionReputation(factionEntry, Reputation);
|
||||
}
|
||||
}
|
||||
|
|
@ -345,30 +423,84 @@ void BattleGround::UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player
|
|||
|
||||
void BattleGround::EndBattleGround(uint32 winner)
|
||||
{
|
||||
this->RemoveFromBGFreeSlotQueue();
|
||||
|
||||
ArenaTeam * winner_arena_team = NULL;
|
||||
ArenaTeam * loser_arena_team = NULL;
|
||||
uint32 loser_rating = 0;
|
||||
uint32 winner_rating = 0;
|
||||
WorldPacket data;
|
||||
Player *Source = NULL;
|
||||
const char *winmsg = "";
|
||||
|
||||
if(winner == ALLIANCE)
|
||||
{
|
||||
winmsg = GetMangosString(LANG_BG_A_WINS);
|
||||
if(isBattleGround())
|
||||
winmsg = GetMangosString(LANG_BG_A_WINS);
|
||||
else
|
||||
winmsg = GetMangosString(LANG_ARENA_GOLD_WINS);
|
||||
|
||||
PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound
|
||||
|
||||
SetWinner(WINNER_ALLIANCE);
|
||||
}
|
||||
else
|
||||
else if(winner == HORDE)
|
||||
{
|
||||
winmsg = GetMangosString(LANG_BG_H_WINS);
|
||||
if(isBattleGround())
|
||||
winmsg = GetMangosString(LANG_BG_H_WINS);
|
||||
else
|
||||
winmsg = GetMangosString(LANG_ARENA_GREEN_WINS);
|
||||
|
||||
PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound
|
||||
|
||||
SetWinner(WINNER_HORDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWinner(3);
|
||||
}
|
||||
|
||||
SetStatus(STATUS_WAIT_LEAVE);
|
||||
m_EndTime = 0;
|
||||
|
||||
// arena rating calculation
|
||||
if(isArena() && isRated())
|
||||
{
|
||||
if(winner == ALLIANCE)
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
}
|
||||
else if(winner == HORDE)
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
}
|
||||
if(winner_arena_team && loser_arena_team)
|
||||
{
|
||||
loser_rating = loser_arena_team->GetStats().rating;
|
||||
winner_rating = winner_arena_team->GetStats().rating;
|
||||
int32 winner_change = winner_arena_team->WonAgainst(loser_rating);
|
||||
int32 loser_change = loser_arena_team->LostAgainst(winner_rating);
|
||||
sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change);
|
||||
if(winner == ALLIANCE)
|
||||
{
|
||||
SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change);
|
||||
SetArenaTeamRatingChangeForTeam(HORDE, loser_change);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetArenaTeamRatingChangeForTeam(HORDE, winner_change);
|
||||
SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetArenaTeamRatingChangeForTeam(ALLIANCE, 0);
|
||||
SetArenaTeamRatingChangeForTeam(HORDE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
Player *plr = objmgr.GetPlayer(itr->first);
|
||||
|
|
@ -378,13 +510,29 @@ void BattleGround::EndBattleGround(uint32 winner)
|
|||
continue;
|
||||
}
|
||||
|
||||
// should remove spirit of redemption
|
||||
if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
||||
plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
|
||||
|
||||
if(!plr->isAlive())
|
||||
{
|
||||
plr->ResurrectPlayer(1.0f);
|
||||
plr->SpawnCorpseBones();
|
||||
}
|
||||
|
||||
if(plr->GetTeam() == winner)
|
||||
uint32 team = itr->second.Team;
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
// per player calculation
|
||||
if(isArena() && isRated() && winner_arena_team && loser_arena_team)
|
||||
{
|
||||
if(team == winner)
|
||||
winner_arena_team->MemberWon(plr,loser_rating);
|
||||
else
|
||||
loser_arena_team->MemberLost(plr,winner_rating);
|
||||
}
|
||||
|
||||
if(team == winner)
|
||||
{
|
||||
if(!Source)
|
||||
Source = plr;
|
||||
|
|
@ -404,10 +552,29 @@ void BattleGround::EndBattleGround(uint32 winner)
|
|||
sBattleGroundMgr.BuildPvpLogDataPacket(&data, this);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime());
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
|
||||
}
|
||||
|
||||
if(isArena() && isRated() && winner_arena_team && loser_arena_team)
|
||||
{
|
||||
// update arena points only after increasing the player's match count!
|
||||
//obsolete: winner_arena_team->UpdateArenaPointsHelper();
|
||||
//obsolete: loser_arena_team->UpdateArenaPointsHelper();
|
||||
// save the stat changes
|
||||
winner_arena_team->SaveToDB();
|
||||
loser_arena_team->SaveToDB();
|
||||
// send updated arena team stats to players
|
||||
// this way all arena team members will get notified, not only the ones who participated in this match
|
||||
winner_arena_team->NotifyStatsChanged();
|
||||
loser_arena_team->NotifyStatsChanged();
|
||||
}
|
||||
|
||||
// inform invited players about the removal
|
||||
sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
|
||||
|
||||
if(Source)
|
||||
{
|
||||
ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg);
|
||||
|
|
@ -558,12 +725,16 @@ void BattleGround::BlockMovement(Player *plr)
|
|||
|
||||
void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket)
|
||||
{
|
||||
uint32 team = GetPlayerTeam(guid);
|
||||
bool participant = false;
|
||||
// Remove from lists/maps
|
||||
std::map<uint64, BattleGroundPlayer>::iterator itr = m_Players.find(guid);
|
||||
if(itr != m_Players.end())
|
||||
{
|
||||
UpdatePlayersCountByTeam(itr->second.Team, true); // -1 player
|
||||
UpdatePlayersCountByTeam(team, true); // -1 player
|
||||
m_Players.erase(itr);
|
||||
// check if the player was a participant of the match, or only entered through gm command (goname)
|
||||
participant = true;
|
||||
}
|
||||
|
||||
std::map<uint64, BattleGroundScore*>::iterator itr2 = m_PlayerScores.find(guid);
|
||||
|
|
@ -577,6 +748,10 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
|
|||
|
||||
Player *plr = objmgr.GetPlayer(guid);
|
||||
|
||||
// should remove spirit of redemption
|
||||
if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
||||
plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT);
|
||||
|
||||
if(plr && !plr->isAlive()) // resurrect on exit
|
||||
{
|
||||
plr->ResurrectPlayer(1.0f);
|
||||
|
|
@ -589,66 +764,106 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac
|
|||
{
|
||||
plr->ClearAfkReports();
|
||||
|
||||
if(isArena())
|
||||
if(participant) // if the player was a match participant, remove auras, calc rating, update queue
|
||||
{
|
||||
if(!sWorld.IsFFAPvPRealm())
|
||||
plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
|
||||
}
|
||||
if(!team) team = plr->GetTeam();
|
||||
|
||||
WorldPacket data;
|
||||
if(SendPacket)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
|
||||
plr->RemoveBattleGroundQueueId(m_TypeID);
|
||||
|
||||
DecreaseInvitedCount(plr->GetTeam());
|
||||
//we should update battleground queue, but only if bg isn't ending
|
||||
if (GetQueueType() < MAX_BATTLEGROUND_QUEUES)
|
||||
sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType());
|
||||
|
||||
if(!plr->GetBattleGroundId())
|
||||
return;
|
||||
|
||||
Group * group = plr->GetGroup();
|
||||
|
||||
// remove from raid group if exist
|
||||
if(group && group == GetBgRaid(plr->GetTeam()))
|
||||
{
|
||||
if(!group->RemoveMember(guid, 0)) // group was disbanded
|
||||
uint32 bgTypeId = GetTypeID();
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType());
|
||||
// if arena, remove the specific arena auras
|
||||
if(isArena())
|
||||
{
|
||||
SetBgRaid(plr->GetTeam(), NULL);
|
||||
delete group;
|
||||
plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out
|
||||
bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing)
|
||||
|
||||
// summon old pet if there was one and there isn't a current pet
|
||||
if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber())
|
||||
{
|
||||
Pet* NewPet = new Pet;
|
||||
if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true))
|
||||
delete NewPet;
|
||||
|
||||
(plr)->SetTemporaryUnsummonedPetNumber(0);
|
||||
}
|
||||
|
||||
if(isRated() && GetStatus() == STATUS_IN_PROGRESS)
|
||||
{
|
||||
//left a rated match while the encounter was in progress, consider as loser
|
||||
ArenaTeam * winner_arena_team = 0;
|
||||
ArenaTeam * loser_arena_team = 0;
|
||||
if(team == HORDE)
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
}
|
||||
else
|
||||
{
|
||||
winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE));
|
||||
loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE));
|
||||
}
|
||||
if(winner_arena_team && loser_arena_team)
|
||||
{
|
||||
loser_arena_team->MemberLost(plr,winner_arena_team->GetRating());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data;
|
||||
if(SendPacket)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0);
|
||||
plr->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
// this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg
|
||||
plr->RemoveBattleGroundQueueId(bgQueueTypeId);
|
||||
|
||||
DecreaseInvitedCount(team);
|
||||
//we should update battleground queue, but only if bg isn't ending
|
||||
if (GetQueueType() < MAX_BATTLEGROUND_QUEUES)
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType());
|
||||
|
||||
Group * group = plr->GetGroup();
|
||||
// remove from raid group if exist
|
||||
if(group && group == GetBgRaid(team))
|
||||
{
|
||||
if(!group->RemoveMember(guid, 0)) // group was disbanded
|
||||
{
|
||||
SetBgRaid(team, NULL);
|
||||
delete group;
|
||||
}
|
||||
}
|
||||
|
||||
// Let others know
|
||||
sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr);
|
||||
SendPacketToTeam(team, &data, plr, false);
|
||||
}
|
||||
|
||||
// Do next only if found in battleground
|
||||
plr->SetBattleGroundId(0); // We're not in BG.
|
||||
|
||||
// Let others know
|
||||
sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr);
|
||||
SendPacketToTeam(plr->GetTeam(), &data, plr, false);
|
||||
// reset destination bg team
|
||||
plr->SetBGTeam(0);
|
||||
|
||||
if(Transport)
|
||||
{
|
||||
plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO());
|
||||
//sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O);
|
||||
}
|
||||
|
||||
// Log
|
||||
sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName());
|
||||
}
|
||||
|
||||
/// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist
|
||||
// we always should check if BG is in that queue before adding..
|
||||
|
||||
if(!GetPlayersSize())
|
||||
if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE))
|
||||
{
|
||||
Reset();
|
||||
// if no players left AND no invitees left, set this bg to delete in next update
|
||||
// direct deletion could cause crashes
|
||||
m_SetDeleteThis = true;
|
||||
// return to prevent addition to freeslotqueue
|
||||
return;
|
||||
}
|
||||
|
||||
// a player exited the battleground, so there are free slots. add to queue
|
||||
this->AddToBGFreeSlotQueue();
|
||||
}
|
||||
|
||||
// this method is called when no players remains in battleground
|
||||
|
|
@ -660,6 +875,8 @@ void BattleGround::Reset()
|
|||
SetStartTime(0);
|
||||
SetEndTime(0);
|
||||
SetLastResurrectTime(0);
|
||||
SetArenaType(0);
|
||||
SetRated(false);
|
||||
|
||||
m_Events = 0;
|
||||
|
||||
|
|
@ -668,6 +885,7 @@ void BattleGround::Reset()
|
|||
|
||||
m_InvitedAlliance = 0;
|
||||
m_InvitedHorde = 0;
|
||||
m_InBGFreeSlotQueue = false;
|
||||
|
||||
m_Players.clear();
|
||||
m_PlayerScores.clear();
|
||||
|
|
@ -704,10 +922,11 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data, plr);
|
||||
SendPacketToTeam(team, &data, plr, false);
|
||||
|
||||
// add arena specific auras
|
||||
if(isArena())
|
||||
{
|
||||
plr->RemoveArenaSpellCooldowns();
|
||||
//plr->RemoveArenaAuras();
|
||||
plr->RemoveArenaAuras();
|
||||
plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT);
|
||||
if(team == ALLIANCE) // gold
|
||||
{
|
||||
|
|
@ -726,6 +945,19 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
|
||||
plr->DestroyConjuredItems(true);
|
||||
|
||||
Pet* pet = plr->GetPet();
|
||||
if(pet)
|
||||
{
|
||||
if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET)
|
||||
{
|
||||
(plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber());
|
||||
(plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL));
|
||||
}
|
||||
(plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT);
|
||||
}
|
||||
else
|
||||
(plr)->SetTemporaryUnsummonedPetNumber(0);
|
||||
|
||||
if(GetStatus() == STATUS_WAIT_JOIN) // not started yet
|
||||
{
|
||||
plr->CastSpell(plr, SPELL_ARENA_PREPARATION, true);
|
||||
|
|
@ -740,9 +972,6 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells.
|
||||
}
|
||||
|
||||
if(isArena())
|
||||
plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP);
|
||||
|
||||
// Log
|
||||
sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName());
|
||||
}
|
||||
|
|
@ -750,13 +979,20 @@ void BattleGround::AddPlayer(Player *plr)
|
|||
/* This method should be called only once ... it adds pointer to queue */
|
||||
void BattleGround::AddToBGFreeSlotQueue()
|
||||
{
|
||||
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);
|
||||
// make sure to add only once
|
||||
if(!m_InBGFreeSlotQueue)
|
||||
{
|
||||
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this);
|
||||
m_InBGFreeSlotQueue = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/
|
||||
void BattleGround::RemoveFromBGFreeSlotQueue()
|
||||
{
|
||||
/* uncomment this code when battlegrounds will work like instances
|
||||
// set to be able to re-add if needed
|
||||
m_InBGFreeSlotQueue = false;
|
||||
// uncomment this code when battlegrounds will work like instances
|
||||
for (std::deque<BattleGround*>::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr)
|
||||
{
|
||||
if ((*itr)->GetInstanceID() == m_InstanceID)
|
||||
|
|
@ -764,30 +1000,69 @@ void BattleGround::RemoveFromBGFreeSlotQueue()
|
|||
sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr);
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
this method should decide, if we can invite new player of certain team to BG, it is based on BATTLEGROUND_STATUS
|
||||
*/
|
||||
bool BattleGround::HasFreeSlotsForTeam(uint32 Team) const
|
||||
// get the number of free slots for team
|
||||
// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group
|
||||
uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const
|
||||
{
|
||||
//if BG is starting ... invite anyone:
|
||||
//if BG is starting ... invite anyone
|
||||
if (GetStatus() == STATUS_WAIT_JOIN)
|
||||
return GetInvitedCount(Team) < GetMaxPlayersPerTeam();
|
||||
return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
|
||||
//if BG is already started .. do not allow to join too much players of one faction
|
||||
uint32 otherTeam;
|
||||
uint32 otherIn;
|
||||
if (Team == ALLIANCE)
|
||||
{
|
||||
otherTeam = GetInvitedCount(HORDE);
|
||||
otherIn = GetPlayersCountByTeam(HORDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
otherTeam = GetInvitedCount(ALLIANCE);
|
||||
otherIn = GetPlayersCountByTeam(ALLIANCE);
|
||||
}
|
||||
if (GetStatus() == STATUS_IN_PROGRESS)
|
||||
return (GetInvitedCount(Team) <= otherTeam && GetInvitedCount(Team) < GetMaxPlayersPerTeam());
|
||||
{
|
||||
// difference based on ppl invited (not necessarily entered battle)
|
||||
// default: allow 0
|
||||
uint32 diff = 0;
|
||||
// allow join one person if the sides are equal (to fill up bg to minplayersperteam)
|
||||
if (otherTeam == GetInvitedCount(Team))
|
||||
diff = 1;
|
||||
// allow join more ppl if the other side has more players
|
||||
else if(otherTeam > GetInvitedCount(Team))
|
||||
diff = otherTeam - GetInvitedCount(Team);
|
||||
|
||||
return false;
|
||||
// difference based on max players per team (don't allow inviting more)
|
||||
uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0;
|
||||
|
||||
// difference based on players who already entered
|
||||
// default: allow 0
|
||||
uint32 diff3 = 0;
|
||||
// allow join one person if the sides are equal (to fill up bg minplayersperteam)
|
||||
if (otherIn == GetPlayersCountByTeam(Team))
|
||||
diff3 = 1;
|
||||
// allow join more ppl if the other side has more players
|
||||
else if (otherIn > GetPlayersCountByTeam(Team))
|
||||
diff3 = otherIn - GetPlayersCountByTeam(Team);
|
||||
// or other side has less than minPlayersPerTeam
|
||||
else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam())
|
||||
diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1;
|
||||
|
||||
// return the minimum of the 3 differences
|
||||
|
||||
// min of diff and diff 2
|
||||
diff = diff < diff2 ? diff : diff2;
|
||||
|
||||
// min of diff, diff2 and diff3
|
||||
return diff < diff3 ? diff : diff3 ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* this method isn't called already, it will be useful when more battlegrounds of one type will be available */
|
||||
bool BattleGround::HasFreeSlots() const
|
||||
{
|
||||
return GetPlayersSize() < GetMaxPlayers();
|
||||
|
|
@ -813,9 +1088,13 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value)
|
|||
itr->second->HonorableKills += value;
|
||||
break;
|
||||
case SCORE_BONUS_HONOR: // Honor bonus
|
||||
// reward honor instantly
|
||||
if(Source->RewardHonor(NULL, 1, value))
|
||||
itr->second->BonusHonor += value;
|
||||
// do not add honor in arenas
|
||||
if(isBattleGround())
|
||||
{
|
||||
// reward honor instantly
|
||||
if(Source->RewardHonor(NULL, 1, value))
|
||||
itr->second->BonusHonor += value;
|
||||
}
|
||||
break;
|
||||
//used only in EY, but in MSG_PVP_LOG_DATA opcode
|
||||
case SCORE_DAMAGE_DONE: // Damage Done
|
||||
|
|
@ -871,15 +1150,26 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid)
|
|||
|
||||
bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime)
|
||||
{
|
||||
GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry);
|
||||
if(!goinfo)
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
|
||||
if(!map)
|
||||
return false;
|
||||
|
||||
// must be created this way, adding to godatamap would add it to the base map of the instance
|
||||
// and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created
|
||||
// so we must create it specific for this instance
|
||||
GameObject * go = new GameObject;
|
||||
if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1))
|
||||
{
|
||||
sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry);
|
||||
sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry);
|
||||
delete go;
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
uint32 guid = go->GetGUIDLow();
|
||||
|
||||
uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
|
||||
|
||||
// without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata
|
||||
// iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed
|
||||
GameObjectData& data = objmgr.NewGOData(guid);
|
||||
|
||||
data.id = entry;
|
||||
|
|
@ -893,13 +1183,13 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float
|
|||
data.rotation2 = rotation2;
|
||||
data.rotation3 = rotation3;
|
||||
data.spawntimesecs = respawnTime;
|
||||
data.spawnMask = 1;
|
||||
data.animprogress = 100;
|
||||
data.go_state = 1;
|
||||
data.spawnMask = 1;
|
||||
objmgr.AddGameobjectToGrid(guid, &data);
|
||||
|
||||
m_BgObjects[type] = MAKE_NEW_GUID(guid, entry, HIGHGUID_GAMEOBJECT);
|
||||
|
||||
*/
|
||||
// add to world, so it can be later looked up from HashMapHolder
|
||||
go->AddToWorld();
|
||||
m_BgObjects[type] = go->GetGUID();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -941,6 +1231,9 @@ void BattleGround::DoorOpen(uint32 type)
|
|||
|
||||
void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
|
||||
{
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
|
||||
if(!map)
|
||||
return;
|
||||
if( respawntime == 0 )
|
||||
{
|
||||
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
|
||||
|
|
@ -949,30 +1242,27 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime)
|
|||
//we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again
|
||||
if( obj->getLootState() == GO_JUST_DEACTIVATED )
|
||||
obj->SetLootState(GO_READY);
|
||||
obj->Respawn();
|
||||
obj->SetRespawnTime(0);
|
||||
map->Add(obj);
|
||||
}
|
||||
else
|
||||
objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]);
|
||||
if(obj)
|
||||
{
|
||||
map->Add(obj);
|
||||
obj->SetRespawnTime(respawntime);
|
||||
obj->SetLootState(GO_JUST_DEACTIVATED);
|
||||
}
|
||||
else
|
||||
objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime);
|
||||
}
|
||||
}
|
||||
|
||||
Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o)
|
||||
Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime)
|
||||
{
|
||||
// note: this should normally be FindMap
|
||||
// but it's a hack to allow the battlegrounds to initialize at server startup
|
||||
Map * map = MapManager::Instance().GetMap(GetMapId(), 0);
|
||||
if(!map) return NULL;
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID());
|
||||
if(!map)
|
||||
return NULL;
|
||||
|
||||
Creature* pCreature = new Creature;
|
||||
if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval))
|
||||
|
|
@ -996,9 +1286,39 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f
|
|||
|
||||
map->Add(pCreature);
|
||||
m_BgCreatures[type] = pCreature->GetGUID();
|
||||
|
||||
return pCreature;
|
||||
}
|
||||
/*
|
||||
void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime)
|
||||
{
|
||||
Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId());
|
||||
if(!map)
|
||||
return false;
|
||||
|
||||
if(respawntime == 0)
|
||||
{
|
||||
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
|
||||
if(obj)
|
||||
{
|
||||
//obj->Respawn(); // bugged
|
||||
obj->SetRespawnTime(0);
|
||||
objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0);
|
||||
map->Add(obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Creature *obj = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
|
||||
if(obj)
|
||||
{
|
||||
obj->setDeathState(DEAD);
|
||||
obj->SetRespawnTime(respawntime);
|
||||
map->Add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
bool BattleGround::DelCreature(uint32 type)
|
||||
{
|
||||
Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]);
|
||||
|
|
@ -1048,10 +1368,10 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float
|
|||
|
||||
pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID());
|
||||
// aura
|
||||
pCreature->SetUInt32Value(UNIT_FIELD_AURA, SPELL_SPIRIT_HEAL_CHANNEL);
|
||||
pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
|
||||
pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
|
||||
pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
|
||||
pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
|
||||
//pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009);
|
||||
//pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C);
|
||||
//pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF);
|
||||
// casting visual effect
|
||||
pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL);
|
||||
// correct cast speed
|
||||
|
|
@ -1079,8 +1399,11 @@ void BattleGround::SendMessageToAll(int32 entry)
|
|||
|
||||
void BattleGround::EndNow()
|
||||
{
|
||||
RemoveFromBGFreeSlotQueue();
|
||||
SetStatus(STATUS_WAIT_LEAVE);
|
||||
SetEndTime(TIME_TO_AUTOREMOVE);
|
||||
// inform invited players about the removal
|
||||
sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this);
|
||||
}
|
||||
|
||||
// Battleground messages are localized using the dbc lang, they are not client language dependent
|
||||
|
|
@ -1158,3 +1481,28 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer )
|
|||
// to be able to remove insignia
|
||||
player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE );
|
||||
}
|
||||
|
||||
// return the player's team based on battlegroundplayer info
|
||||
// used in same faction arena matches mainly
|
||||
uint32 BattleGround::GetPlayerTeam(uint64 guid)
|
||||
{
|
||||
std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid);
|
||||
if(itr!=m_Players.end())
|
||||
return itr->second.Team;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const
|
||||
{
|
||||
int count = 0;
|
||||
for(std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
|
||||
{
|
||||
if(itr->second.Team == Team)
|
||||
{
|
||||
Player * pl = objmgr.GetPlayer(itr->first);
|
||||
if(pl && pl->isAlive())
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ enum BattleGroundTimeIntervals
|
|||
{
|
||||
RESURRECTION_INTERVAL = 30000, // ms
|
||||
REMIND_INTERVAL = 30000, // ms
|
||||
INVITE_ACCEPT_WAIT_TIME = 120000, // ms
|
||||
INVITE_ACCEPT_WAIT_TIME = 80000, // ms
|
||||
TIME_TO_AUTOREMOVE = 120000, // ms
|
||||
MAX_OFFLINE_TIME = 300000, // ms
|
||||
START_DELAY0 = 120000, // ms
|
||||
|
|
@ -129,8 +129,6 @@ struct BattleGroundObjectInfo
|
|||
uint32 spellid;
|
||||
};
|
||||
|
||||
#define MAX_QUEUED_PLAYERS_MAP 7
|
||||
|
||||
enum BattleGroundTypeId
|
||||
{
|
||||
BATTLEGROUND_AV = 1,
|
||||
|
|
@ -140,7 +138,22 @@ enum BattleGroundTypeId
|
|||
BATTLEGROUND_BE = 5,
|
||||
BATTLEGROUND_AA = 6,
|
||||
BATTLEGROUND_EY = 7,
|
||||
BATTLEGROUND_RL = 8
|
||||
BATTLEGROUND_RL = 8,
|
||||
BATTLEGROUND_SA = 9,
|
||||
BATTLEGROUND_DS = 10,
|
||||
BATTLEGROUND_RV = 11
|
||||
};
|
||||
|
||||
// handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time
|
||||
enum BattleGroundQueueTypeId
|
||||
{
|
||||
BATTLEGROUND_QUEUE_AV = 1,
|
||||
BATTLEGROUND_QUEUE_WS = 2,
|
||||
BATTLEGROUND_QUEUE_AB = 3,
|
||||
BATTLEGROUND_QUEUE_EY = 4,
|
||||
BATTLEGROUND_QUEUE_2v2 = 5,
|
||||
BATTLEGROUND_QUEUE_3v3 = 6,
|
||||
BATTLEGROUND_QUEUE_5v5 = 7,
|
||||
};
|
||||
|
||||
enum ScoreType
|
||||
|
|
@ -195,6 +208,20 @@ enum BattleGroundTeamId
|
|||
BG_TEAM_HORDE = 1
|
||||
};
|
||||
|
||||
enum BattleGroundJoinError
|
||||
{
|
||||
BG_JOIN_ERR_OK = 0,
|
||||
BG_JOIN_ERR_OFFLINE_MEMBER = 1,
|
||||
BG_JOIN_ERR_GROUP_TOO_MANY = 2,
|
||||
BG_JOIN_ERR_MIXED_FACTION = 3,
|
||||
BG_JOIN_ERR_MIXED_LEVELS = 4,
|
||||
BG_JOIN_ERR_MIXED_ARENATEAM = 5,
|
||||
BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE = 6,
|
||||
BG_JOIN_ERR_GROUP_DESERTER = 7,
|
||||
BG_JOIN_ERR_ALL_QUEUES_USED = 8,
|
||||
BG_JOIN_ERR_GROUP_NOT_ENOUGH = 9
|
||||
};
|
||||
|
||||
class BattleGroundScore
|
||||
{
|
||||
public:
|
||||
|
|
@ -224,6 +251,7 @@ class BattleGround
|
|||
public:
|
||||
/* Construction */
|
||||
BattleGround();
|
||||
/*BattleGround(const BattleGround& bg);*/
|
||||
virtual ~BattleGround();
|
||||
virtual void Update(time_t diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version
|
||||
virtual bool SetupBattleGround() // must be implemented in BG subclass
|
||||
|
|
@ -296,6 +324,7 @@ class BattleGround
|
|||
}
|
||||
bool HasFreeSlotsForTeam(uint32 Team) const;
|
||||
bool HasFreeSlots() const;
|
||||
uint32 GetFreeSlotsForTeam(uint32 Team) const;
|
||||
|
||||
bool isArena() const { return m_IsArena; }
|
||||
bool isBattleGround() const { return !m_IsArena; }
|
||||
|
|
@ -366,6 +395,7 @@ class BattleGround
|
|||
|
||||
uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; }
|
||||
uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; }
|
||||
uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases
|
||||
void UpdatePlayersCountByTeam(uint32 Team, bool remove)
|
||||
{
|
||||
if(remove)
|
||||
|
|
@ -374,6 +404,12 @@ class BattleGround
|
|||
++m_PlayersCount[GetTeamIndexByTeamId(Team)];
|
||||
}
|
||||
|
||||
// used for rated arena battles
|
||||
void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; }
|
||||
uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; }
|
||||
void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; }
|
||||
int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; }
|
||||
|
||||
/* Triggers handle */
|
||||
// must be implemented in BG subclass
|
||||
virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {}
|
||||
|
|
@ -390,6 +426,7 @@ class BattleGround
|
|||
virtual WorldSafeLocsEntry const* GetClosestGraveYard(float /*x*/, float /*y*/, float /*z*/, uint32 /*team*/) { return NULL; }
|
||||
|
||||
virtual void AddPlayer(Player *plr); // must be implemented in BG subclass
|
||||
|
||||
virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket);
|
||||
// can be extended in in BG subclass
|
||||
|
||||
|
|
@ -402,7 +439,8 @@ class BattleGround
|
|||
BGCreatures m_BgCreatures;
|
||||
void SpawnBGObject(uint32 type, uint32 respawntime);
|
||||
bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0);
|
||||
Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o);
|
||||
// void SpawnBGCreature(uint32 type, uint32 respawntime);
|
||||
Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0);
|
||||
bool DelCreature(uint32 type);
|
||||
bool DelObject(uint32 type);
|
||||
bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team);
|
||||
|
|
@ -411,6 +449,13 @@ class BattleGround
|
|||
void DoorClose(uint32 type);
|
||||
const char *GetMangosString(int32 entry);
|
||||
|
||||
virtual bool HandlePlayerUnderMap(Player * plr) {return false;}
|
||||
|
||||
// since arenas can be AvA or Hvh, we have to get the "temporary" team of a player
|
||||
uint32 GetPlayerTeam(uint64 guid);
|
||||
|
||||
void SetDeleteThis() {m_SetDeleteThis = true;}
|
||||
|
||||
protected:
|
||||
//this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround
|
||||
void EndNow();
|
||||
|
|
@ -443,6 +488,8 @@ class BattleGround
|
|||
uint32 m_LastResurrectTime;
|
||||
uint32 m_Queue_type;
|
||||
uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5
|
||||
bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque
|
||||
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
|
||||
// this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless
|
||||
//uint8 m_BattleGroundType; // 3=BG, 4=arena
|
||||
//instead of uint8 (in previous line) is bool used
|
||||
|
|
@ -450,6 +497,8 @@ class BattleGround
|
|||
uint8 m_Winner; // 0=alliance, 1=horde, 2=none
|
||||
int32 m_StartDelayTime;
|
||||
bool m_IsRated; // is this battle rated?
|
||||
bool m_PrematureCountDown;
|
||||
uint32 m_PrematureCountDownTimer;
|
||||
char const *m_Name;
|
||||
|
||||
/* Player lists */
|
||||
|
|
@ -468,6 +517,11 @@ class BattleGround
|
|||
/* Players count by team */
|
||||
uint32 m_PlayersCount[2];
|
||||
|
||||
/* Arena team ids by team */
|
||||
uint32 m_ArenaTeamIds[2];
|
||||
|
||||
int32 m_ArenaTeamRatingChanges[2];
|
||||
|
||||
/* Limits */
|
||||
uint32 m_LevelMin;
|
||||
uint32 m_LevelMax;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,13 @@ void BattleGroundAB::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ...");
|
||||
|
||||
// despawn banners, auras and buffs
|
||||
|
|
@ -377,6 +384,7 @@ void BattleGroundAB::_NodeOccupied(uint8 node,Team team)
|
|||
{
|
||||
if( !AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team) )
|
||||
sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team);
|
||||
// SpawnBGCreature(node,RESPAWN_IMMEDIATELY);
|
||||
|
||||
uint8 capturedNodes = 0;
|
||||
for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ void BattleGroundBE::Update(time_t diff)
|
|||
if (!(m_Events & 0x01))
|
||||
{
|
||||
m_Events |= 0x01;
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++)
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
|
|
@ -86,6 +92,11 @@ void BattleGroundBE::Update(time_t diff)
|
|||
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
||||
if(Player *plr = objmgr.GetPlayer(itr->first))
|
||||
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
|
||||
|
||||
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,11 +113,23 @@ void BattleGroundBE::AddPlayer(Player *plr)
|
|||
BattleGroundBEScore* sc = new BattleGroundBEScore;
|
||||
|
||||
m_PlayerScores[plr->GetGUID()] = sc;
|
||||
|
||||
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
|
||||
}
|
||||
|
||||
void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
|
||||
{
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
return;
|
||||
|
||||
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
|
||||
void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
|
||||
|
|
@ -120,17 +143,27 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer)
|
|||
return;
|
||||
}
|
||||
|
||||
BattleGround::HandleKillPlayer(player, killer);
|
||||
BattleGround::HandleKillPlayer(player,killer);
|
||||
|
||||
uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());
|
||||
UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
++m_TeamKills[killer_team_index]; // add kills to killer's team
|
||||
|
||||
if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(killer->GetTeam());
|
||||
EndBattleGround(HORDE);
|
||||
}
|
||||
else if(!GetAlivePlayersCountByTeam(HORDE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleGroundBE::HandlePlayerUnderMap(Player *player)
|
||||
{
|
||||
player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
||||
|
|
@ -159,10 +192,16 @@ void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
|||
// HandleTriggerBuff(buff_guid,Source);
|
||||
}
|
||||
|
||||
void BattleGroundBE::FillInitialWorldStates(WorldPacket &data)
|
||||
{
|
||||
data << uint32(0x9f1) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7
|
||||
data << uint32(0x9f0) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8
|
||||
data << uint32(0x9f3) << uint32(1); // 9
|
||||
}
|
||||
|
||||
void BattleGroundBE::ResetBGSubclass()
|
||||
{
|
||||
m_TeamKills[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamKills[BG_TEAM_HORDE] = 0;
|
||||
|
||||
}
|
||||
|
||||
bool BattleGroundBE::SetupBattleGround()
|
||||
|
|
|
|||
|
|
@ -64,12 +64,11 @@ class BattleGroundBE : public BattleGround
|
|||
void HandleAreaTrigger(Player *Source, uint32 Trigger);
|
||||
bool SetupBattleGround();
|
||||
void ResetBGSubclass();
|
||||
virtual void FillInitialWorldStates(WorldPacket &d);
|
||||
void HandleKillPlayer(Player* player, Player *killer);
|
||||
bool HandlePlayerUnderMap(Player * plr);
|
||||
|
||||
/* Scorekeeping */
|
||||
void UpdatePlayerScore(Player *Source, uint32 type, uint32 value);
|
||||
|
||||
private:
|
||||
uint32 m_TeamKills[2]; // count of kills for each team
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -54,9 +54,18 @@ void BattleGroundEY::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY);
|
||||
SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY);
|
||||
|
||||
// SpawnBGCreature(EY_SPIRIT_MAIN_ALLIANCE, RESPAWN_IMMEDIATELY);
|
||||
// SpawnBGCreature(EY_SPIRIT_MAIN_HORDE, RESPAWN_IMMEDIATELY);
|
||||
for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i)
|
||||
SpawnBGObject(i, RESPAWN_ONE_DAY);
|
||||
|
||||
|
|
@ -572,7 +581,17 @@ void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer)
|
|||
|
||||
void BattleGroundEY::EventPlayerDroppedFlag(Player *Source)
|
||||
{
|
||||
// Drop allowed in any BG state
|
||||
if(GetStatus() != STATUS_IN_PROGRESS)
|
||||
{
|
||||
// if not running, do not cast things at the dropper player, neither send unnecessary messages
|
||||
// just take off the aura
|
||||
if(IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID())
|
||||
{
|
||||
SetFlagPicker(0);
|
||||
Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!IsFlagPickedup())
|
||||
return;
|
||||
|
|
@ -744,6 +763,8 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point)
|
|||
sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u",
|
||||
Point, Team, m_CapturingPointTypes[Point].GraveYardId);
|
||||
|
||||
// SpawnBGCreature(Point,RESPAWN_IMMEDIATELY);
|
||||
|
||||
UpdatePointsIcons(Team, Point);
|
||||
UpdatePointsCount(Team);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,11 @@
|
|||
#include "MapManager.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Object.h"
|
||||
#include "Chat.h"
|
||||
#include "BattleGroundMgr.h"
|
||||
#include "BattleGroundWS.h"
|
||||
#include "BattleGround.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "Language.h"
|
||||
|
||||
void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data )
|
||||
|
|
@ -76,18 +78,25 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
|
|||
uint32 bgTypeId;
|
||||
uint32 instanceId;
|
||||
uint8 joinAsGroup;
|
||||
Group * grp;
|
||||
|
||||
recv_data >> guid; // battlemaster guid
|
||||
recv_data >> bgTypeId; // battleground type id (DBC id)
|
||||
recv_data >> instanceId; // instance id, 0 if First Available selected
|
||||
recv_data >> joinAsGroup; // join as group
|
||||
|
||||
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT " for BG (Type: %u)", guid, bgTypeId);
|
||||
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating?
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES)
|
||||
{
|
||||
sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow());
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore if we already in BG or BG queue
|
||||
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid);
|
||||
|
||||
// can do this, since it's battleground, not arena
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0);
|
||||
|
||||
// ignore if player is already in BG
|
||||
if(_player->InBattleGround())
|
||||
return;
|
||||
|
||||
|
|
@ -98,74 +107,82 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
|
|||
if(!unit->isBattleMaster()) // it's not battlemaster
|
||||
return;
|
||||
|
||||
// check Deserter debuff
|
||||
if( !_player->CanJoinToBattleground() )
|
||||
// get bg instance or bg template if instance not found
|
||||
BattleGround * bg = 0;
|
||||
if(instanceId)
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId);
|
||||
|
||||
if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId)))
|
||||
{
|
||||
WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
|
||||
data << (uint32) 0xFFFFFFFE;
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
sLog.outError("Battleground: no available bg / template found");
|
||||
return;
|
||||
}
|
||||
|
||||
// check existence
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);
|
||||
if(!bg)
|
||||
return;
|
||||
|
||||
if(joinAsGroup && _player->GetGroup())
|
||||
// check queueing conditions
|
||||
if(!joinAsGroup)
|
||||
{
|
||||
Group *grp = _player->GetGroup();
|
||||
// check Deserter debuff
|
||||
if( !_player->CanJoinToBattleground() )
|
||||
{
|
||||
WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
|
||||
data << (uint32) 0xFFFFFFFE;
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
return;
|
||||
}
|
||||
// check if already in queue
|
||||
if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
//player is already in this queue
|
||||
return;
|
||||
// check if has free queue slots
|
||||
if(!_player->HasFreeBattleGroundQueueId())
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
grp = _player->GetGroup();
|
||||
// no group found, error
|
||||
if(!grp)
|
||||
return;
|
||||
uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0);
|
||||
if (err != BG_JOIN_ERR_OK)
|
||||
{
|
||||
SendBattleGroundOrArenaJoinError(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if we're here, then the conditions to join a bg are met. We can proceed in joining.
|
||||
|
||||
// _player->GetGroup() was already checked, grp is already initialized
|
||||
if(joinAsGroup /* && _player->GetGroup()*/)
|
||||
{
|
||||
sLog.outDebug("Battleground: the following players are joining as group:");
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
|
||||
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
if(!member) continue;
|
||||
if(!member) continue; // this should never happen
|
||||
|
||||
if( !member->CanJoinToBattleground() )
|
||||
{
|
||||
WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
|
||||
data << (uint32) 0xFFFFFFFE;
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
continue;
|
||||
}
|
||||
if (member->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
//player is already in this queue
|
||||
continue;
|
||||
|
||||
WorldPacket data;
|
||||
// add to queue
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
// fill data packet
|
||||
//member->GetSession()->SendPacket(data);
|
||||
continue;
|
||||
}
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue
|
||||
|
||||
// store entry point coords (same as leader entry point)
|
||||
member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
WorldPacket data;
|
||||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo);
|
||||
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
|
||||
}
|
||||
sLog.outDebug("Battleground: group end");
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_player->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
//player is already in this queue
|
||||
return;
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
WorldPacket data;
|
||||
// fill data packet
|
||||
//SendPacket(data);
|
||||
return;
|
||||
}
|
||||
|
||||
// already checked if queueSlot is valid, now just get it
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId);
|
||||
// store entry point coords
|
||||
_player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
|
|
@ -173,7 +190,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data )
|
|||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId);
|
||||
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel());
|
||||
sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -247,12 +268,11 @@ void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data )
|
|||
uint32 bgTypeId;
|
||||
recv_data >> bgTypeId; // id from DBC
|
||||
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating?
|
||||
return;
|
||||
|
||||
// can't be received if player not in BG queue
|
||||
if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES)
|
||||
{
|
||||
sLog.outError("Battleground: invalid bgtype received.");
|
||||
return;
|
||||
}
|
||||
|
||||
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
|
||||
|
||||
|
|
@ -270,80 +290,201 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data )
|
|||
|
||||
sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message");
|
||||
|
||||
uint8 unk1;
|
||||
uint8 type; // arenatype if arena
|
||||
uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1
|
||||
uint32 instanceId;
|
||||
uint32 bgTypeId; // type id from dbc
|
||||
uint16 unk; // 0x1F90 constant?
|
||||
uint8 action; // enter battle 0x1, leave queue 0x0
|
||||
|
||||
recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action;
|
||||
recv_data >> type >> unk2 >> bgTypeId >> unk >> action;
|
||||
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating?
|
||||
return;
|
||||
|
||||
if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId))
|
||||
return;
|
||||
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId);
|
||||
if(!bg)
|
||||
return;
|
||||
|
||||
uint32 queueSlot = 0;
|
||||
WorldPacket data;
|
||||
switch(action)
|
||||
if(bgTypeId >= MAX_BATTLEGROUND_TYPES)
|
||||
{
|
||||
case 1: // port to battleground
|
||||
// cheating?
|
||||
if(!_player->IsInvitedForBattleGroundType(bgTypeId))
|
||||
return;
|
||||
|
||||
// check if player is not deserter
|
||||
if( !_player->CanJoinToBattleground() )
|
||||
sLog.outError("Battleground: invalid bgtype received.");
|
||||
// update battleground slots for the player to fix his UI and sent data.
|
||||
// this is a HACK, I don't know why the client starts sending invalid packets in the first place.
|
||||
// it usually happens with extremely high latency (if debugging / stepping in the code for example)
|
||||
if(_player->InBattleGroundQueue())
|
||||
{
|
||||
// update all queues, send invitation info if player is invited, queue info if queued
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
WorldPacket data2;
|
||||
data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4);
|
||||
data2 << (uint32) 0xFFFFFFFE;
|
||||
SendPacket(&data2);
|
||||
return;
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i);
|
||||
if(!queue_id)
|
||||
continue;
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
// if the player is not in queue, contine
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
continue;
|
||||
|
||||
// no group information, this should never happen
|
||||
if(!itrPlayerStatus->second.GroupInfo)
|
||||
continue;
|
||||
|
||||
BattleGround * bg = NULL;
|
||||
|
||||
// get possibly needed data from groupinfo
|
||||
bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId;
|
||||
uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
|
||||
uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated;
|
||||
uint8 status = 0;
|
||||
|
||||
|
||||
if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID)
|
||||
{
|
||||
// not invited to bg, get template
|
||||
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
status = STATUS_WAIT_QUEUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the bg we're invited to
|
||||
BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID);
|
||||
status = STATUS_WAIT_JOIN;
|
||||
}
|
||||
|
||||
// if bg not found, then continue
|
||||
if(!bg)
|
||||
continue;
|
||||
|
||||
// don't invite if already in the instance
|
||||
if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID())
|
||||
continue;
|
||||
|
||||
// re - invite player with proper data
|
||||
WorldPacket data;
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if the player is dead, resurrect him before teleport
|
||||
if(!_player->isAlive())
|
||||
{
|
||||
_player->ResurrectPlayer(1.0f);
|
||||
_player->SpawnCorpseBones();
|
||||
}
|
||||
uint32 bgQueueTypeId = 0;
|
||||
// get the bg what we were invited to
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus;
|
||||
bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type);
|
||||
itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
|
||||
// leave current group
|
||||
_player->RemoveFromGroup();
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
{
|
||||
sLog.outError("Battleground: itrplayerstatus not found.");
|
||||
return;
|
||||
}
|
||||
instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID;
|
||||
|
||||
// packet to player about BG status
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
// if action == 1, then instanceId is _required_
|
||||
if(!instanceId && action == 1)
|
||||
{
|
||||
sLog.outError("Battleground: instance not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// remove battleground queue status from BGmgr
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false);
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId);
|
||||
|
||||
// this is still needed here if battleground "jumping" shouldn't add deserter debuff
|
||||
// also this required to prevent stuck at old battleground after SetBattleGroundId set to new
|
||||
if (BattleGround *currentBg = _player->GetBattleGround())
|
||||
currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
|
||||
// bg template might and must be used in case of leaving queue, when instance is not created yet
|
||||
if(!bg && action == 0)
|
||||
bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
|
||||
_player->SetBattleGroundId(bg->GetTypeID());
|
||||
sBattleGroundMgr.SendToBattleGround(_player, bgTypeId);
|
||||
bg->AddPlayer(_player);
|
||||
break;
|
||||
case 0: // leave queue
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId);
|
||||
_player->RemoveBattleGroundQueueId(bgTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true);
|
||||
SendPacket(&data);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Battleground port: unknown action %u", action);
|
||||
break;
|
||||
if(!bg)
|
||||
{
|
||||
sLog.outError("Battleground: bg not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
bgTypeId = bg->GetTypeID();
|
||||
|
||||
if(_player->InBattleGroundQueue())
|
||||
{
|
||||
uint32 queueSlot = 0;
|
||||
uint32 team = 0;
|
||||
uint32 arenatype = 0;
|
||||
uint32 israted = 0;
|
||||
uint32 rating = 0;
|
||||
uint32 opponentsRating = 0;
|
||||
// get the team info from the queue
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()
|
||||
&& pitr->second.GroupInfo )
|
||||
{
|
||||
team = pitr->second.GroupInfo->Team;
|
||||
arenatype = pitr->second.GroupInfo->ArenaType;
|
||||
israted = pitr->second.GroupInfo->IsRated;
|
||||
rating = pitr->second.GroupInfo->ArenaTeamRating;
|
||||
opponentsRating = pitr->second.GroupInfo->OpponentsTeamRating;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Battleground: Invalid player queue info!");
|
||||
return;
|
||||
}
|
||||
WorldPacket data;
|
||||
switch(action)
|
||||
{
|
||||
case 1: // port to battleground
|
||||
if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId))
|
||||
return; // cheating?
|
||||
// resurrect the player
|
||||
if(!_player->isAlive())
|
||||
{
|
||||
_player->ResurrectPlayer(1.0f);
|
||||
_player->SpawnCorpseBones();
|
||||
}
|
||||
// stop taxi flight at port
|
||||
if(_player->isInFlight())
|
||||
{
|
||||
_player->GetMotionMaster()->MovementExpired();
|
||||
_player->m_taxi.ClearTaxiDestinations();
|
||||
}
|
||||
_player->RemoveFromGroup();
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
|
||||
_player->GetSession()->SendPacket(&data);
|
||||
// remove battleground queue status from BGmgr
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false);
|
||||
// this is still needed here if battleground "jumping" shouldn't add deserter debuff
|
||||
// also this required to prevent stuck at old battleground after SetBattleGroundId set to new
|
||||
if( BattleGround *currentBg = _player->GetBattleGround() )
|
||||
currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true);
|
||||
|
||||
// set the destination instance id
|
||||
_player->SetBattleGroundId(bg->GetInstanceID());
|
||||
// set the destination team
|
||||
_player->SetBGTeam(team);
|
||||
// bg->HandleBeforeTeleportToBattleGround(_player);
|
||||
sBattleGroundMgr.SendToBattleGround(_player, instanceId);
|
||||
// add only in HandleMoveWorldPortAck()
|
||||
// bg->AddPlayer(_player,team);
|
||||
sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId);
|
||||
break;
|
||||
case 0: // leave queue
|
||||
queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
|
||||
/*
|
||||
if player leaves rated arena match before match start, it is counted as he played but he lost
|
||||
*/
|
||||
if (israted)
|
||||
{
|
||||
ArenaTeam * at = objmgr.GetArenaTeamById(team);
|
||||
if (at)
|
||||
{
|
||||
sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating);
|
||||
at->MemberLost(_player, opponentsRating);
|
||||
at->SaveToDB();
|
||||
}
|
||||
}
|
||||
_player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true);
|
||||
// player left queue, we should update it, maybe now his group fits in
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(),arenatype,israted,rating);
|
||||
SendPacket(&data);
|
||||
sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Battleground port: unknown action %u", action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -384,7 +525,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
|
|||
BattleGround *bg = _player->GetBattleGround();
|
||||
if(bg)
|
||||
{
|
||||
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID());
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType());
|
||||
uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId);
|
||||
if((bg->GetStatus() <= STATUS_IN_PROGRESS))
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime());
|
||||
|
|
@ -392,15 +534,25 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
|
|||
}
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i);
|
||||
if (i == queueSlot || !queue_id)
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong
|
||||
uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id);
|
||||
uint8 isRated = 0;
|
||||
if (i == queueSlot || !queue_id) // we need to get the instance ids
|
||||
continue;
|
||||
BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id);
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
continue;
|
||||
if(itrPlayerStatus->second.GroupInfo)
|
||||
{
|
||||
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
|
||||
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
|
||||
}
|
||||
BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); // try this
|
||||
if(bg2)
|
||||
{
|
||||
//in this call is small bug, this call should be filled by player's waiting time in queue
|
||||
//this call nulls all timers for client :
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
|
@ -411,16 +563,36 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ )
|
|||
// we should update all queues? .. i'm not sure if this code is correct
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
if(uint32 queue_id = _player->GetBattleGroundQueueId(i))
|
||||
uint32 queue_id = _player->GetBattleGroundQueueId(i);
|
||||
if(!queue_id)
|
||||
continue;
|
||||
uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id);
|
||||
uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id);
|
||||
uint8 isRated = 0;
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId);
|
||||
BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID());
|
||||
if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end())
|
||||
continue;
|
||||
if(itrPlayerStatus->second.GroupInfo)
|
||||
{
|
||||
if(BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id))
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0);
|
||||
SendPacket(&data);
|
||||
}
|
||||
arenatype = itrPlayerStatus->second.GroupInfo->ArenaType;
|
||||
isRated = itrPlayerStatus->second.GroupInfo->IsRated;
|
||||
}
|
||||
if(bg && queue_id)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else // not sure if it needed...
|
||||
{
|
||||
for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0);
|
||||
SendPacket(&data);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data )
|
||||
|
|
@ -480,16 +652,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
|
|||
if(_player->InBattleGround())
|
||||
return;
|
||||
|
||||
for(int qId = 0; qId < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qId)
|
||||
{
|
||||
if(_player->GetBattleGroundQueueId(qId) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
uint64 guid; // arena Battlemaster guid
|
||||
uint8 type; // 2v2, 3v3 or 5v5
|
||||
uint8 asGroup; // asGroup
|
||||
uint8 isRated; // isRated
|
||||
Group * grp;
|
||||
|
||||
recv_data >> guid >> type >> asGroup >> isRated;
|
||||
|
||||
Creature *unit = ObjectAccessor::GetCreature(*_player, guid);
|
||||
|
|
@ -500,6 +668,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
|
|||
return;
|
||||
|
||||
uint8 arenatype = 0;
|
||||
uint32 arenaRating = 0;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
|
|
@ -517,88 +686,118 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data )
|
|||
return;
|
||||
}
|
||||
|
||||
if(isRated && !_player->GetArenaTeamId(type)) // player not in arena team of that size
|
||||
//check existance
|
||||
BattleGround* bg = NULL;
|
||||
if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) )
|
||||
{
|
||||
_player->GetSession()->SendNotInArenaTeamPacket(arenatype);
|
||||
sLog.outError("Battleground: template bg (all arenas) not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if(asGroup && !_player->GetGroup()) // player not in group
|
||||
return;
|
||||
uint8 bgTypeId = bg->GetTypeID();
|
||||
uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype);
|
||||
|
||||
// check existence
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA);
|
||||
if(!bg)
|
||||
return;
|
||||
|
||||
bg->SetArenaType(arenatype);
|
||||
bg->SetRated(isRated);
|
||||
|
||||
if(asGroup && _player->GetGroup())
|
||||
// check queueing conditions
|
||||
if(!asGroup)
|
||||
{
|
||||
Group *grp = _player->GetGroup();
|
||||
// check if already in queue
|
||||
if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
//player is already in this queue
|
||||
return;
|
||||
// check if has free queue slots
|
||||
if(!_player->HasFreeBattleGroundQueueId())
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
grp = _player->GetGroup();
|
||||
// no group found, error
|
||||
if(!grp)
|
||||
return;
|
||||
uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type);
|
||||
if (err != BG_JOIN_ERR_OK)
|
||||
{
|
||||
SendBattleGroundOrArenaJoinError(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 ateamId = 0;
|
||||
|
||||
if(isRated)
|
||||
{
|
||||
ateamId = _player->GetArenaTeamId(type);
|
||||
// check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice)
|
||||
ArenaTeam * at = objmgr.GetArenaTeamById(ateamId);
|
||||
if(!at)
|
||||
{
|
||||
_player->GetSession()->SendNotInArenaTeamPacket(arenatype);
|
||||
return;
|
||||
}
|
||||
// get the team rating for queueing
|
||||
arenaRating = at->GetRating();
|
||||
// the arenateam id must match for everyone in the group
|
||||
// get the personal ratings for queueing
|
||||
uint32 avg_pers_rating = 0;
|
||||
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
|
||||
// calc avg personal rating
|
||||
avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5);
|
||||
}
|
||||
|
||||
if( arenatype )
|
||||
avg_pers_rating /= arenatype;
|
||||
|
||||
// if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating
|
||||
if(avg_pers_rating + 150 < arenaRating)
|
||||
arenaRating = avg_pers_rating;
|
||||
}
|
||||
|
||||
if(asGroup)
|
||||
{
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId);
|
||||
sLog.outDebug("Battleground: arena join as group start");
|
||||
if(isRated)
|
||||
sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype);
|
||||
for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
if(!member) continue;
|
||||
|
||||
/*if (!member->CanJoinToBattleground())
|
||||
//player has deserter aura .. do nothing
|
||||
*/
|
||||
|
||||
if (member->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA))
|
||||
//player is already in this queue
|
||||
continue;
|
||||
|
||||
// add to queue
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
WorldPacket data;
|
||||
//fill data
|
||||
//member->GetSession()->SendPacket(data);
|
||||
continue;
|
||||
}
|
||||
uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue
|
||||
|
||||
// store entry point coords (same as leader entry point)
|
||||
member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
WorldPacket data;
|
||||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA);
|
||||
sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId);
|
||||
member->GetSession()->SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo);
|
||||
sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName());
|
||||
}
|
||||
sLog.outDebug("Battleground: arena join as group end");
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*if (!member->CanJoinToBattleground())
|
||||
//player has deserter aura .. do nothing
|
||||
*/
|
||||
|
||||
if (_player->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA))
|
||||
//player is already in this queue
|
||||
return;
|
||||
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA);
|
||||
if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES)
|
||||
{
|
||||
WorldPacket data;
|
||||
//fill data (player is in 3 queues already)
|
||||
//SendPacket(data);
|
||||
return;
|
||||
}
|
||||
uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId);
|
||||
|
||||
// store entry point coords
|
||||
_player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation());
|
||||
|
||||
WorldPacket data;
|
||||
// send status packet (in queue)
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0);
|
||||
sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated);
|
||||
SendPacket(&data);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA);
|
||||
GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo);
|
||||
sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating);
|
||||
sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -620,3 +819,41 @@ void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data )
|
|||
|
||||
reportedPlayer->ReportedAfkBy(_player);
|
||||
}
|
||||
|
||||
void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err)
|
||||
{
|
||||
WorldPacket data;
|
||||
int32 msg;
|
||||
switch (err)
|
||||
{
|
||||
case BG_JOIN_ERR_OFFLINE_MEMBER:
|
||||
msg = LANG_BG_GROUP_OFFLINE_MEMBER;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_TOO_MANY:
|
||||
msg = LANG_BG_GROUP_TOO_LARGE;
|
||||
break;
|
||||
case BG_JOIN_ERR_MIXED_FACTION:
|
||||
msg = LANG_BG_GROUP_MIXED_FACTION;
|
||||
break;
|
||||
case BG_JOIN_ERR_MIXED_LEVELS:
|
||||
msg = LANG_BG_GROUP_MIXED_LEVELS;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE:
|
||||
msg = LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_DESERTER:
|
||||
msg = LANG_BG_GROUP_MEMBER_DESERTER;
|
||||
break;
|
||||
case BG_JOIN_ERR_ALL_QUEUES_USED:
|
||||
msg = LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS;
|
||||
break;
|
||||
case BG_JOIN_ERR_GROUP_NOT_ENOUGH:
|
||||
case BG_JOIN_ERR_MIXED_ARENATEAM:
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(msg), NULL);
|
||||
SendPacket(&data);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -30,55 +30,103 @@ typedef std::map<uint32, BattleGround*> BattleGroundSet;
|
|||
//typedef std::map<uint32, BattleGroundQueue*> BattleGroundQueueSet;
|
||||
typedef std::deque<BattleGround*> BGFreeSlotQueueType;
|
||||
|
||||
#define MAX_BATTLEGROUND_QUEUES 7 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70+
|
||||
#define MAX_BATTLEGROUND_QUEUES 8 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70-79, 80+
|
||||
|
||||
#define MAX_BATTLEGROUND_TYPES 9 // each BG type will be in array
|
||||
#define MAX_BATTLEGROUND_TYPES 12 // each BG type will be in array
|
||||
|
||||
struct PlayerQueueInfo
|
||||
#define MAX_BATTLEGROUND_QUEUE_TYPES 8
|
||||
|
||||
#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day
|
||||
|
||||
struct GroupQueueInfo; // type predefinition
|
||||
struct PlayerQueueInfo // stores information for players in queue
|
||||
{
|
||||
uint32 InviteTime; // first invite time
|
||||
uint32 LastInviteTime; // last invite time
|
||||
uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG
|
||||
uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes
|
||||
GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo
|
||||
};
|
||||
|
||||
struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!)
|
||||
{
|
||||
std::map<uint64, PlayerQueueInfo*> Players; // player queue info map
|
||||
uint32 Team; // Player team (ALLIANCE/HORDE)
|
||||
bool IsRated;
|
||||
bool AsGroup; // uint32 GroupId;
|
||||
uint8 ArenaType;
|
||||
};
|
||||
|
||||
struct PlayersCount
|
||||
{
|
||||
uint32 Alliance;
|
||||
uint32 Horde;
|
||||
};
|
||||
|
||||
template<class _Kty, class _Ty> class bgqueue: public std::map<_Kty, _Ty>
|
||||
{
|
||||
public:
|
||||
uint32 Alliance;
|
||||
uint32 Horde;
|
||||
//bool Ready; // not used now
|
||||
//uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players)
|
||||
uint32 BgTypeId; // battleground type id
|
||||
bool IsRated; // rated
|
||||
uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG
|
||||
uint32 ArenaTeamId; // team id if rated match
|
||||
uint32 JoinTime; // time when group was added
|
||||
uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG
|
||||
uint32 ArenaTeamRating; // if rated match, inited to the rating of the team
|
||||
uint32 OpponentsTeamRating; // for rated arena matches
|
||||
};
|
||||
|
||||
class BattleGround;
|
||||
class BattleGroundQueue
|
||||
{
|
||||
public:
|
||||
BattleGroundQueue();
|
||||
~BattleGroundQueue();
|
||||
/*
|
||||
uint32 GetType();
|
||||
void SetType(uint32 type);*/
|
||||
|
||||
void Update(uint32 bgTypeId, uint32 queue_id);
|
||||
void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0);
|
||||
|
||||
void AddPlayer(Player *plr, uint32 bgTypeId);
|
||||
GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0);
|
||||
void AddPlayer(Player *plr, GroupQueueInfo *ginfo);
|
||||
void RemovePlayer(uint64 guid, bool decreaseInvitedCount);
|
||||
void DecreaseGroupLength(uint32 queueId, uint32 AsGroup);
|
||||
void BGEndedRemoveInvites(BattleGround * bg);
|
||||
|
||||
typedef bgqueue<uint64, PlayerQueueInfo> QueuedPlayersMap;
|
||||
typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap;
|
||||
QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES];
|
||||
typedef std::list<uint64> PlayerGuidsSortedByTimeQueue;
|
||||
PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES];
|
||||
|
||||
typedef std::list<GroupQueueInfo*> QueuedGroupsList;
|
||||
QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES];
|
||||
|
||||
// class to hold pointers to the groups eligible for a specific selection pool building mode
|
||||
class EligibleGroups : public std::list<GroupQueueInfo *>
|
||||
{
|
||||
public:
|
||||
void Init(QueuedGroupsList * source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0);
|
||||
void RemoveGroup(GroupQueueInfo * ginfo);
|
||||
};
|
||||
|
||||
EligibleGroups m_EligibleGroups;
|
||||
|
||||
// class to select and invite groups to bg
|
||||
class SelectionPool
|
||||
{
|
||||
public:
|
||||
void Init();
|
||||
void AddGroup(GroupQueueInfo * group);
|
||||
GroupQueueInfo * GetMaximalGroup();
|
||||
void RemoveGroup(GroupQueueInfo * group);
|
||||
uint32 GetPlayerCount() const {return PlayerCount;}
|
||||
public:
|
||||
std::list<GroupQueueInfo *> SelectedGroups;
|
||||
private:
|
||||
uint32 PlayerCount;
|
||||
GroupQueueInfo * MaxGroup;
|
||||
};
|
||||
|
||||
enum SelectionPoolBuildMode
|
||||
{
|
||||
NORMAL_ALLIANCE,
|
||||
NORMAL_HORDE,
|
||||
ONESIDE_ALLIANCE_TEAM1,
|
||||
ONESIDE_ALLIANCE_TEAM2,
|
||||
ONESIDE_HORDE_TEAM1,
|
||||
ONESIDE_HORDE_TEAM2,
|
||||
|
||||
NUM_SELECTION_POOL_TYPES
|
||||
};
|
||||
|
||||
SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES];
|
||||
|
||||
bool BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0);
|
||||
|
||||
private:
|
||||
|
||||
bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -96,7 +144,6 @@ class BGQueueInviteEvent : public BasicEvent
|
|||
private:
|
||||
uint64 m_PlayerGuid;
|
||||
uint32 m_BgInstanceGUID;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -116,7 +163,6 @@ class BGQueueRemoveEvent : public BasicEvent
|
|||
uint32 m_PlayersTeam;
|
||||
};
|
||||
|
||||
|
||||
class BattleGroundMgr
|
||||
{
|
||||
public:
|
||||
|
|
@ -132,18 +178,18 @@ class BattleGroundMgr
|
|||
void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId);
|
||||
void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value);
|
||||
void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg);
|
||||
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2);
|
||||
void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0);
|
||||
void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid);
|
||||
|
||||
/* Player invitation */
|
||||
// called from Queue update, or from Addplayer to queue
|
||||
void InvitePlayer(Player* plr, uint32 bgInstanceGUID);
|
||||
void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team);
|
||||
|
||||
/* Battlegrounds */
|
||||
BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); };
|
||||
BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); };
|
||||
|
||||
BattleGround* GetBattleGround(uint8 ID)
|
||||
BattleGround* GetBattleGround(uint32 ID)
|
||||
{
|
||||
BattleGroundSet::iterator i = m_BattleGrounds.find(ID);
|
||||
if(i != m_BattleGrounds.end())
|
||||
|
|
@ -152,9 +198,13 @@ class BattleGroundMgr
|
|||
return NULL;
|
||||
};
|
||||
|
||||
BattleGround * GetBattleGroundTemplate(uint32 bgTypeId);
|
||||
BattleGround * CreateNewBattleGround(uint32 bgTypeId);
|
||||
|
||||
uint32 CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO);
|
||||
|
||||
inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; };
|
||||
void RemoveBattleGround(uint32 instanceID);
|
||||
|
||||
void CreateInitialBattleGrounds();
|
||||
|
||||
|
|
@ -162,16 +212,39 @@ class BattleGroundMgr
|
|||
|
||||
/* Battleground queues */
|
||||
//these queues are instantiated when creating BattlegroundMrg
|
||||
BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_TYPES]; // public, because we need to access them in BG handler code
|
||||
BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; // public, because we need to access them in BG handler code
|
||||
|
||||
BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES];
|
||||
|
||||
void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid);
|
||||
|
||||
bool IsArenaType(uint32 bgTypeId) const;
|
||||
bool IsBattleGroundType(uint32 bgTypeId) const;
|
||||
uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const;
|
||||
uint32 BGTemplateId(uint32 bgQueueTypeId) const;
|
||||
uint8 BGArenaType(uint32 bgQueueTypeId) const;
|
||||
|
||||
uint32 GetMaxRatingDifference() const {return m_MaxRatingDifference;}
|
||||
uint32 GetRatingDiscardTimer() const {return m_RatingDiscardTimer;}
|
||||
|
||||
void InitAutomaticArenaPointDistribution();
|
||||
void DistributeArenaPoints();
|
||||
uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;}
|
||||
void ToggleArenaTesting();
|
||||
const bool isArenaTesting() const { return m_ArenaTesting; }
|
||||
|
||||
private:
|
||||
|
||||
/* Battlegrounds */
|
||||
BattleGroundSet m_BattleGrounds;
|
||||
uint32 m_MaxRatingDifference;
|
||||
uint32 m_RatingDiscardTimer;
|
||||
uint32 m_NextRatingDiscardUpdate;
|
||||
bool m_AutoDistributePoints;
|
||||
uint64 m_NextAutoDistributionTime;
|
||||
uint32 m_AutoDistributionTimeChecker;
|
||||
uint32 m_PrematureFinishTimer;
|
||||
bool m_ArenaTesting;
|
||||
};
|
||||
|
||||
#define sBattleGroundMgr MaNGOS::Singleton<BattleGroundMgr>::Instance()
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ void BattleGroundNA::Update(time_t diff)
|
|||
if (!(m_Events & 0x01))
|
||||
{
|
||||
m_Events |= 0x01;
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++)
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
|
|
@ -73,6 +79,9 @@ void BattleGroundNA::Update(time_t diff)
|
|||
for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++)
|
||||
DoorOpen(i);
|
||||
|
||||
for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++)
|
||||
SpawnBGObject(i, 60);
|
||||
|
||||
SendMessageToAll(LANG_ARENA_BEGUN);
|
||||
SetStatus(STATUS_IN_PROGRESS);
|
||||
SetStartDelayTime(0);
|
||||
|
|
@ -80,6 +89,11 @@ void BattleGroundNA::Update(time_t diff)
|
|||
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
||||
if(Player *plr = objmgr.GetPlayer(itr->first))
|
||||
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
|
||||
|
||||
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,11 +110,23 @@ void BattleGroundNA::AddPlayer(Player *plr)
|
|||
BattleGroundNAScore* sc = new BattleGroundNAScore;
|
||||
|
||||
m_PlayerScores[plr->GetGUID()] = sc;
|
||||
|
||||
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
|
||||
}
|
||||
|
||||
void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
|
||||
{
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
return;
|
||||
|
||||
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
|
||||
void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
|
||||
|
|
@ -114,17 +140,27 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer)
|
|||
return;
|
||||
}
|
||||
|
||||
BattleGround::HandleKillPlayer(player, killer);
|
||||
BattleGround::HandleKillPlayer(player,killer);
|
||||
|
||||
uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());
|
||||
UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
++m_TeamKills[killer_team_index]; // add kills to killer's team
|
||||
|
||||
if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(killer->GetTeam());
|
||||
EndBattleGround(HORDE);
|
||||
}
|
||||
else if(!GetAlivePlayersCountByTeam(HORDE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleGroundNA::HandlePlayerUnderMap(Player *player)
|
||||
{
|
||||
player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
||||
|
|
@ -149,19 +185,28 @@ void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
|||
// HandleTriggerBuff(buff_guid,Source);
|
||||
}
|
||||
|
||||
void BattleGroundNA::FillInitialWorldStates(WorldPacket &data)
|
||||
{
|
||||
data << uint32(0xa0f) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7
|
||||
data << uint32(0xa10) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8
|
||||
data << uint32(0xa11) << uint32(1); // 9
|
||||
}
|
||||
|
||||
void BattleGroundNA::ResetBGSubclass()
|
||||
{
|
||||
m_TeamKills[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamKills[BG_TEAM_HORDE] = 0;
|
||||
|
||||
}
|
||||
|
||||
bool BattleGroundNA::SetupBattleGround()
|
||||
{
|
||||
// gates
|
||||
if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY))
|
||||
if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY)
|
||||
// buffs
|
||||
|| !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120)
|
||||
|| !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120))
|
||||
{
|
||||
sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ enum BattleGroundNAObjectTypes
|
|||
BG_NA_OBJECT_DOOR_2 = 1,
|
||||
BG_NA_OBJECT_DOOR_3 = 2,
|
||||
BG_NA_OBJECT_DOOR_4 = 3,
|
||||
BG_NA_OBJECT_MAX = 4
|
||||
BG_NA_OBJECT_BUFF_1 = 4,
|
||||
BG_NA_OBJECT_BUFF_2 = 5,
|
||||
BG_NA_OBJECT_MAX = 6
|
||||
};
|
||||
|
||||
enum BattleGroundNAObjects
|
||||
|
|
@ -34,7 +36,9 @@ enum BattleGroundNAObjects
|
|||
BG_NA_OBJECT_TYPE_DOOR_1 = 183978,
|
||||
BG_NA_OBJECT_TYPE_DOOR_2 = 183980,
|
||||
BG_NA_OBJECT_TYPE_DOOR_3 = 183977,
|
||||
BG_NA_OBJECT_TYPE_DOOR_4 = 183979
|
||||
BG_NA_OBJECT_TYPE_DOOR_4 = 183979,
|
||||
BG_NA_OBJECT_TYPE_BUFF_1 = 184663,
|
||||
BG_NA_OBJECT_TYPE_BUFF_2 = 184664
|
||||
};
|
||||
|
||||
class BattleGroundNAScore : public BattleGroundScore
|
||||
|
|
@ -61,9 +65,8 @@ class BattleGroundNA : public BattleGround
|
|||
void HandleAreaTrigger(Player *Source, uint32 Trigger);
|
||||
bool SetupBattleGround();
|
||||
virtual void ResetBGSubclass();
|
||||
virtual void FillInitialWorldStates(WorldPacket &d);
|
||||
void HandleKillPlayer(Player* player, Player *killer);
|
||||
|
||||
private:
|
||||
uint32 m_TeamKills[2]; // count of kills for each team
|
||||
bool HandlePlayerUnderMap(Player * plr);
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -47,6 +47,13 @@ void BattleGroundRL::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
|
|
@ -73,6 +80,9 @@ void BattleGroundRL::Update(time_t diff)
|
|||
for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++)
|
||||
DoorOpen(i);
|
||||
|
||||
for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++)
|
||||
SpawnBGObject(i, 60);
|
||||
|
||||
SendMessageToAll(LANG_ARENA_BEGUN);
|
||||
SetStatus(STATUS_IN_PROGRESS);
|
||||
SetStartDelayTime(0);
|
||||
|
|
@ -80,6 +90,11 @@ void BattleGroundRL::Update(time_t diff)
|
|||
for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
|
||||
if(Player *plr = objmgr.GetPlayer(itr->first))
|
||||
plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION);
|
||||
|
||||
if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,11 +111,23 @@ void BattleGroundRL::AddPlayer(Player *plr)
|
|||
BattleGroundRLScore* sc = new BattleGroundRLScore;
|
||||
|
||||
m_PlayerScores[plr->GetGUID()] = sc;
|
||||
|
||||
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
|
||||
}
|
||||
|
||||
void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/)
|
||||
{
|
||||
if(GetStatus() == STATUS_WAIT_LEAVE)
|
||||
return;
|
||||
|
||||
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE))
|
||||
EndBattleGround(HORDE);
|
||||
else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE))
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
|
||||
void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
|
||||
|
|
@ -114,17 +141,27 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer)
|
|||
return;
|
||||
}
|
||||
|
||||
BattleGround::HandleKillPlayer(player, killer);
|
||||
BattleGround::HandleKillPlayer(player,killer);
|
||||
|
||||
uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam());
|
||||
UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE));
|
||||
UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE));
|
||||
|
||||
++m_TeamKills[killer_team_index]; // add kills to killer's team
|
||||
|
||||
if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam()))
|
||||
if(!GetAlivePlayersCountByTeam(ALLIANCE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(killer->GetTeam());
|
||||
EndBattleGround(HORDE);
|
||||
}
|
||||
else if(!GetAlivePlayersCountByTeam(HORDE))
|
||||
{
|
||||
// all opponents killed
|
||||
EndBattleGround(ALLIANCE);
|
||||
}
|
||||
}
|
||||
|
||||
bool BattleGroundRL::HandlePlayerUnderMap(Player *player)
|
||||
{
|
||||
player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
||||
|
|
@ -150,17 +187,26 @@ void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger)
|
|||
// HandleTriggerBuff(buff_guid,Source);
|
||||
}
|
||||
|
||||
void BattleGroundRL::FillInitialWorldStates(WorldPacket &data)
|
||||
{
|
||||
data << uint32(0xbb8) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7
|
||||
data << uint32(0xbb9) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8
|
||||
data << uint32(0xbba) << uint32(1); // 9
|
||||
}
|
||||
|
||||
void BattleGroundRL::ResetBGSubclass()
|
||||
{
|
||||
m_TeamKills[BG_TEAM_ALLIANCE] = 0;
|
||||
m_TeamKills[BG_TEAM_HORDE] = 0;
|
||||
|
||||
}
|
||||
|
||||
bool BattleGroundRL::SetupBattleGround()
|
||||
{
|
||||
// gates
|
||||
if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY))
|
||||
if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY)
|
||||
|| !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY)
|
||||
// buffs
|
||||
|| !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120)
|
||||
|| !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120))
|
||||
{
|
||||
sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!");
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -24,13 +24,17 @@ enum BattleGroundRLObjectTypes
|
|||
{
|
||||
BG_RL_OBJECT_DOOR_1 = 0,
|
||||
BG_RL_OBJECT_DOOR_2 = 1,
|
||||
BG_RL_OBJECT_MAX = 2
|
||||
BG_RL_OBJECT_BUFF_1 = 2,
|
||||
BG_RL_OBJECT_BUFF_2 = 3,
|
||||
BG_RL_OBJECT_MAX = 4
|
||||
};
|
||||
|
||||
enum BattleGroundRLObjects
|
||||
{
|
||||
BG_RL_OBJECT_TYPE_DOOR_1 = 185918,
|
||||
BG_RL_OBJECT_TYPE_DOOR_2 = 185917
|
||||
BG_RL_OBJECT_TYPE_DOOR_2 = 185917,
|
||||
BG_RL_OBJECT_TYPE_BUFF_1 = 184663,
|
||||
BG_RL_OBJECT_TYPE_BUFF_2 = 184664
|
||||
};
|
||||
|
||||
class BattleGroundRLScore : public BattleGroundScore
|
||||
|
|
@ -57,9 +61,8 @@ class BattleGroundRL : public BattleGround
|
|||
void HandleAreaTrigger(Player *Source, uint32 Trigger);
|
||||
bool SetupBattleGround();
|
||||
virtual void ResetBGSubclass();
|
||||
virtual void FillInitialWorldStates(WorldPacket &d);
|
||||
void HandleKillPlayer(Player* player, Player *killer);
|
||||
|
||||
private:
|
||||
uint32 m_TeamKills[2]; // count of kills for each team
|
||||
bool HandlePlayerUnderMap(Player * plr);
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -49,6 +49,16 @@ void BattleGroundWS::Update(time_t diff)
|
|||
{
|
||||
m_Events |= 0x01;
|
||||
|
||||
// setup here, only when at least one player has ported to the map
|
||||
if(!SetupBattleGround())
|
||||
{
|
||||
EndNow();
|
||||
return;
|
||||
}
|
||||
|
||||
// for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++)
|
||||
// SpawnBGCreature(i, RESPAWN_IMMEDIATELY);
|
||||
|
||||
for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++)
|
||||
{
|
||||
SpawnBGObject(i, RESPAWN_IMMEDIATELY);
|
||||
|
|
@ -285,7 +295,32 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source)
|
|||
|
||||
void BattleGroundWS::EventPlayerDroppedFlag(Player *Source)
|
||||
{
|
||||
// Drop allowed in any BG state
|
||||
if(GetStatus() != STATUS_IN_PROGRESS)
|
||||
{
|
||||
// if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages
|
||||
// just take off the aura
|
||||
if(Source->GetTeam() == ALLIANCE)
|
||||
{
|
||||
if(!this->IsHordeFlagPickedup())
|
||||
return;
|
||||
if(GetHordeFlagPickerGUID() == Source->GetGUID())
|
||||
{
|
||||
SetHordeFlagPicker(0);
|
||||
Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!this->IsAllianceFlagPickedup())
|
||||
return;
|
||||
if(GetAllianceFlagPickerGUID() == Source->GetGUID())
|
||||
{
|
||||
SetAllianceFlagPicker(0);
|
||||
Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const char *message = "";
|
||||
uint8 type = 0;
|
||||
|
|
|
|||
17
src/game/Calendar.cpp
Normal file
17
src/game/Calendar.cpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
26
src/game/Calendar.h
Normal file
26
src/game/Calendar.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOS_CALENDAR_H
|
||||
#define MANGOS_CALENDAR_H
|
||||
|
||||
class Calendar
|
||||
{
|
||||
|
||||
};
|
||||
#endif
|
||||
118
src/game/CalendarHandler.cpp
Normal file
118
src/game/CalendarHandler.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Log.h"
|
||||
#include "Player.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include "Opcodes.h"
|
||||
|
||||
void WorldSession::HandleCalendarGetCalendar(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_GET_CALENDAR");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarGetEvent(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_GET_EVENT");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarGuildFilter(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_GUILD_FILTER");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarArenaTeam(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_ARENA_TEAM");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarComplain(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN");
|
||||
recv_data.hexlike();
|
||||
}
|
||||
|
||||
void WorldSession::HandleCalendarGetNumPending(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CALENDAR_GET_NUM_PENDING");
|
||||
recv_data.hexlike();
|
||||
|
||||
WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4);
|
||||
data << uint32(0); // 0 - no pending invites, 1 - some pending invites
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include "World.h"
|
||||
#include "SocialMgr.h"
|
||||
|
||||
Channel::Channel(std::string name, uint32 channel_id)
|
||||
Channel::Channel(const std::string& name, uint32 channel_id)
|
||||
: m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0)
|
||||
{
|
||||
// set special flags if built-in channel
|
||||
|
|
@ -626,7 +626,7 @@ void Channel::Invite(uint64 p, const char *newname)
|
|||
SendToOne(&data, newp->GetGUID());
|
||||
data.clear();
|
||||
}
|
||||
MakePlayerInvited(&data, newp->GetGUID());
|
||||
MakePlayerInvited(&data, newp->GetName());
|
||||
SendToOne(&data, p);
|
||||
}
|
||||
|
||||
|
|
@ -773,7 +773,7 @@ void Channel::MakeOwnerChanged(WorldPacket *data, uint64 guid)
|
|||
}
|
||||
|
||||
// done 0x09
|
||||
void Channel::MakePlayerNotFound(WorldPacket *data, std::string name)
|
||||
void Channel::MakePlayerNotFound(WorldPacket *data, const std::string& name)
|
||||
{
|
||||
MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE);
|
||||
*data << name;
|
||||
|
|
@ -916,13 +916,8 @@ void Channel::MakeNotModerated(WorldPacket *data)
|
|||
}
|
||||
|
||||
// done 0x1D
|
||||
void Channel::MakePlayerInvited(WorldPacket *data, uint64 guid)
|
||||
void Channel::MakePlayerInvited(WorldPacket *data, const std::string& name)
|
||||
{
|
||||
std::string name;
|
||||
|
||||
if(!objmgr.GetPlayerNameByGUID(guid, name) || name.empty())
|
||||
return; // player name not found
|
||||
|
||||
MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE);
|
||||
*data << name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ class Channel
|
|||
void MakeNotModerator(WorldPacket *data); //? 0x06
|
||||
void MakePasswordChanged(WorldPacket *data, uint64 guid); //+ 0x07
|
||||
void MakeOwnerChanged(WorldPacket *data, uint64 guid); //? 0x08
|
||||
void MakePlayerNotFound(WorldPacket *data, std::string name); //+ 0x09
|
||||
void MakePlayerNotFound(WorldPacket *data, const std::string& name); //+ 0x09
|
||||
void MakeNotOwner(WorldPacket *data); //? 0x0A
|
||||
void MakeChannelOwner(WorldPacket *data); //? 0x0B
|
||||
void MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags); //+ 0x0C
|
||||
|
|
@ -190,7 +190,7 @@ class Channel
|
|||
void MakeWrongFaction(WorldPacket *data); //? 0x1A
|
||||
void MakeInvalidName(WorldPacket *data); //? 0x1B
|
||||
void MakeNotModerated(WorldPacket *data); //? 0x1C
|
||||
void MakePlayerInvited(WorldPacket *data, uint64 guid); //+ 0x1D
|
||||
void MakePlayerInvited(WorldPacket *data, const std::string& name); //+ 0x1D
|
||||
void MakePlayerInviteBanned(WorldPacket *data, uint64 guid); //? 0x1E
|
||||
void MakeThrottled(WorldPacket *data); //? 0x1F
|
||||
void MakeNotInArea(WorldPacket *data); //? 0x20
|
||||
|
|
@ -244,14 +244,14 @@ class Channel
|
|||
}
|
||||
|
||||
public:
|
||||
Channel(std::string name, uint32 channel_id);
|
||||
Channel(const std::string& name, uint32 channel_id);
|
||||
std::string GetName() const { return m_name; }
|
||||
uint32 GetChannelId() const { return m_channelId; }
|
||||
bool IsConstant() const { return m_channelId != 0; }
|
||||
bool IsAnnounce() const { return m_announce; }
|
||||
bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; }
|
||||
std::string GetPassword() const { return m_password; }
|
||||
void SetPassword(std::string npassword) { m_password = npassword; }
|
||||
void SetPassword(const std::string& npassword) { m_password = npassword; }
|
||||
void SetAnnounce(bool nannounce) { m_announce = nannounce; }
|
||||
uint32 GetNumPlayers() const { return players.size(); }
|
||||
uint8 GetFlags() const { return m_flags; }
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class ChannelMgr
|
|||
delete itr->second;
|
||||
channels.clear();
|
||||
}
|
||||
Channel *GetJoinChannel(std::string name, uint32 channel_id)
|
||||
Channel *GetJoinChannel(const std::string& name, uint32 channel_id)
|
||||
{
|
||||
if(channels.count(name) == 0)
|
||||
{
|
||||
|
|
@ -45,7 +45,7 @@ class ChannelMgr
|
|||
}
|
||||
return channels[name];
|
||||
}
|
||||
Channel *GetChannel(std::string name, Player *p)
|
||||
Channel *GetChannel(const std::string& name, Player *p)
|
||||
{
|
||||
ChannelMap::const_iterator i = channels.find(name);
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ class ChannelMgr
|
|||
else
|
||||
return i->second;
|
||||
}
|
||||
void LeftChannel(std::string name)
|
||||
void LeftChannel(const std::string& name)
|
||||
{
|
||||
ChannelMap::const_iterator i = channels.find(name);
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ class ChannelMgr
|
|||
}
|
||||
private:
|
||||
ChannelMap channels;
|
||||
void MakeNotOnPacket(WorldPacket *data, std::string name)
|
||||
void MakeNotOnPacket(WorldPacket *data, const std::string& name)
|
||||
{
|
||||
data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size
|
||||
(*data) << (uint8)0x05 << name;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "PlayerDump.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "Util.h"
|
||||
#include "ArenaTeam.h"
|
||||
#include "Language.h"
|
||||
|
||||
class LoginQueryHolder : public SqlQueryHolder
|
||||
|
|
@ -59,7 +60,7 @@ bool LoginQueryHolder::Initialize()
|
|||
|
||||
// NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure.
|
||||
// !!! NOTE: including unused `zone`,`online`
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
|
|
@ -79,6 +80,9 @@ bool LoginQueryHolder::Initialize()
|
|||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid));
|
||||
// in other case still be dummy query
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -228,17 +232,16 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
|||
if (raceEntry->addon > Expansion())
|
||||
{
|
||||
data << (uint8)CHAR_CREATE_EXPANSION;
|
||||
sLog.outError("Not Expansion 1 account:[%d] but tried to Create character with expansion 1 race (%u)",GetAccountId(),race_);
|
||||
sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent character creating Expansion class without Expansion account
|
||||
// TODO: use possible addon field in ChrClassesEntry in next dbc version
|
||||
if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT)
|
||||
if (classEntry->addon > Expansion())
|
||||
{
|
||||
data << (uint8)CHAR_CREATE_EXPANSION;
|
||||
sLog.outError("Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_);
|
||||
data << (uint8)CHAR_CREATE_EXPANSION_CLASS;
|
||||
sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->addon,class_);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
|
@ -305,29 +308,56 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
|||
}
|
||||
}
|
||||
|
||||
// speedup check for heroic class disabled case
|
||||
uint32 heroic_free_slots = sWorld.getConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
|
||||
if(heroic_free_slots==0 && GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER;
|
||||
uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS);
|
||||
|
||||
bool have_same_race = false;
|
||||
if(!AllowTwoSideAccounts || skipCinematics == 1)
|
||||
if(!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1");
|
||||
QueryResult *result2 = CharacterDatabase.PQuery("SELECT race,class FROM characters WHERE account = '%u' %s",
|
||||
GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1");
|
||||
if(result2)
|
||||
{
|
||||
uint32 team_= Player::TeamForRace(race_);
|
||||
|
||||
Field* field = result2->Fetch();
|
||||
uint8 race = field[0].GetUInt32();
|
||||
uint8 acc_race = field[0].GetUInt32();
|
||||
|
||||
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
uint8 acc_class = field[1].GetUInt32();
|
||||
if(acc_class == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
if(heroic_free_slots > 0)
|
||||
--heroic_free_slots;
|
||||
|
||||
if(heroic_free_slots==0)
|
||||
{
|
||||
data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// need to check team only for first character
|
||||
// TODO: what to if account already has characters of both races?
|
||||
if (!AllowTwoSideAccounts)
|
||||
{
|
||||
uint32 team=0;
|
||||
if(race > 0)
|
||||
team = Player::TeamForRace(race);
|
||||
uint32 acc_team=0;
|
||||
if(acc_race > 0)
|
||||
acc_team = Player::TeamForRace(acc_race);
|
||||
|
||||
if(team != team_)
|
||||
if(acc_team != team_)
|
||||
{
|
||||
data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION;
|
||||
SendPacket( &data );
|
||||
|
|
@ -336,15 +366,35 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data )
|
|||
}
|
||||
}
|
||||
|
||||
if (skipCinematics == 1)
|
||||
// search same race for cinematic or same class if need
|
||||
// TODO: check if cinematic already shown? (already logged in?; cinematic field)
|
||||
while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
// TODO: check if cinematic already shown? (already logged in?; cinematic field)
|
||||
while (race_ != race && result2->NextRow())
|
||||
if(!result2->NextRow())
|
||||
break;
|
||||
|
||||
field = result2->Fetch();
|
||||
acc_race = field[0].GetUInt32();
|
||||
|
||||
if(!have_same_race)
|
||||
have_same_race = race_ == acc_race;
|
||||
|
||||
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
field = result2->Fetch();
|
||||
race = field[0].GetUInt32();
|
||||
uint8 acc_class = field[1].GetUInt32();
|
||||
if(acc_class == CLASS_DEATH_KNIGHT)
|
||||
{
|
||||
if(heroic_free_slots > 0)
|
||||
--heroic_free_slots;
|
||||
|
||||
if(heroic_free_slots==0)
|
||||
{
|
||||
data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT;
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
have_same_race = race_ == race;
|
||||
}
|
||||
delete result2;
|
||||
}
|
||||
|
|
@ -411,7 +461,7 @@ void WorldSession::HandleCharDeleteOpcode( WorldPacket & recv_data )
|
|||
}
|
||||
|
||||
// is arena team captain
|
||||
if(objmgr.GetArenaTeamByCapitan(guid))
|
||||
if(objmgr.GetArenaTeamByCaptain(guid))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_DELETE, 1);
|
||||
data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN;
|
||||
|
|
@ -453,6 +503,12 @@ void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data )
|
|||
{
|
||||
CHECK_PACKET_SIZE(recv_data,8);
|
||||
|
||||
if(PlayerLoading() || GetPlayer() != NULL)
|
||||
{
|
||||
sLog.outError("Player tryes to login again, AccountId = %d",GetAccountId());
|
||||
return;
|
||||
}
|
||||
|
||||
m_playerLoading = true;
|
||||
uint64 playerGuid = 0;
|
||||
|
||||
|
|
@ -500,9 +556,11 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
|
|||
data << pCurrChar->GetOrientation();
|
||||
SendPacket(&data);
|
||||
|
||||
data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 128 );
|
||||
for(int i = 0; i < 32; i++)
|
||||
data << uint32(0);
|
||||
data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 4+1+8*4 ); // changed in WotLK
|
||||
data << uint32(time(NULL)); // unix time of something
|
||||
data << uint8(1);
|
||||
for(int i = 0; i < NUM_ACCOUNT_DATA_TYPES; i++)
|
||||
data << uint32(GetAccountData(i)->Time); // also unix time
|
||||
SendPacket(&data);
|
||||
|
||||
data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0
|
||||
|
|
@ -599,12 +657,20 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
|
|||
{
|
||||
pCurrChar->setCinematic(1);
|
||||
|
||||
ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace());
|
||||
if(rEntry)
|
||||
if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass()))
|
||||
{
|
||||
data.Initialize( SMSG_TRIGGER_CINEMATIC,4 );
|
||||
data << uint32(rEntry->startmovie);
|
||||
SendPacket( &data );
|
||||
if(cEntry->CinematicSequence)
|
||||
{
|
||||
data.Initialize(SMSG_TRIGGER_CINEMATIC, 4);
|
||||
data << uint32(cEntry->CinematicSequence);
|
||||
SendPacket( &data );
|
||||
}
|
||||
else if(ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()))
|
||||
{
|
||||
data.Initialize(SMSG_TRIGGER_CINEMATIC, 4);
|
||||
data << uint32(rEntry->CinematicSequence);
|
||||
SendPacket( &data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -648,22 +714,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
|
|||
pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form)
|
||||
pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?)
|
||||
|
||||
//pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326);
|
||||
//pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584);
|
||||
//pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238);
|
||||
//pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514);
|
||||
//pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535);
|
||||
//pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825);
|
||||
//if (pCurrChar->getRace() == RACE_NIGHTELF)
|
||||
//{
|
||||
// pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true);
|
||||
// pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true);
|
||||
// pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true);
|
||||
//}
|
||||
pCurrChar->SetMovement(MOVE_WATER_WALK);
|
||||
}
|
||||
|
||||
|
|
@ -893,53 +943,27 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ )
|
|||
|
||||
void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data,8+1);
|
||||
CHECK_PACKET_SIZE(recv_data, 8+1);
|
||||
|
||||
uint64 guid;
|
||||
std::string newname;
|
||||
std::string oldname;
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 8+1);
|
||||
|
||||
recv_data >> guid;
|
||||
recv_data >> newname;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT at_login, name FROM characters WHERE guid ='%u'", GUID_LOPART(guid));
|
||||
if (!result)
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||
data << (uint8)CHAR_CREATE_ERROR;
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 at_loginFlags;
|
||||
Field *fields = result->Fetch();
|
||||
at_loginFlags = fields[0].GetUInt32();
|
||||
oldname = fields[1].GetCppString();
|
||||
delete result;
|
||||
|
||||
if (!(at_loginFlags & AT_LOGIN_RENAME))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||
data << (uint8)CHAR_CREATE_ERROR;
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent character rename to invalid name
|
||||
if(!normalizePlayerName(newname))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||
data << (uint8)CHAR_NAME_NO_NAME;
|
||||
data << uint8(CHAR_NAME_NO_NAME);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ObjectMgr::IsValidName(newname,true))
|
||||
if(!ObjectMgr::IsValidName(newname, true))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||
data << (uint8)CHAR_NAME_INVALID_CHARACTER;
|
||||
data << uint8(CHAR_NAME_INVALID_CHARACTER);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
|
@ -948,41 +972,56 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
|
|||
if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||
data << (uint8)CHAR_NAME_RESERVED;
|
||||
data << uint8(CHAR_NAME_RESERVED);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist
|
||||
std::string escaped_newname = newname;
|
||||
CharacterDatabase.escape_string(escaped_newname);
|
||||
|
||||
// make sure that the character belongs to the current account, that rename at login is enabled
|
||||
// and that there is no character with the desired new name
|
||||
CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack,
|
||||
GetAccountId(), newname,
|
||||
"SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')",
|
||||
GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname)
|
||||
{
|
||||
WorldSession * session = sWorld.FindSession(accountId);
|
||||
if(!session)
|
||||
{
|
||||
if(result) delete result;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||
data << (uint8)CHAR_CREATE_ERROR;
|
||||
SendPacket( &data );
|
||||
data << uint8(CHAR_CREATE_ERROR);
|
||||
session->SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
if(newname == oldname) // checked by client
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1);
|
||||
data << (uint8)CHAR_NAME_FAILURE;
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
uint32 guidLow = result->Fetch()[0].GetUInt32();
|
||||
uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER);
|
||||
std::string oldname = result->Fetch()[1].GetCppString();
|
||||
|
||||
// we have to check character at_login_flag & AT_LOGIN_RENAME also (fake packets hehe)
|
||||
delete result;
|
||||
|
||||
CharacterDatabase.escape_string(newname);
|
||||
CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME),GUID_LOPART(guid));
|
||||
CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid));
|
||||
CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow);
|
||||
CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow);
|
||||
|
||||
std::string IP_str = GetRemoteAddress();
|
||||
sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",GetAccountId(),IP_str.c_str(),oldname.c_str(),GUID_LOPART(guid),newname.c_str());
|
||||
sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str());
|
||||
|
||||
WorldPacket data(SMSG_CHAR_RENAME,1+8+(newname.size()+1));
|
||||
data << (uint8)RESPONSE_SUCCESS;
|
||||
data << guid;
|
||||
WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1));
|
||||
data << uint8(RESPONSE_SUCCESS);
|
||||
data << uint64(guid);
|
||||
data << newname;
|
||||
SendPacket(&data);
|
||||
session->SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data)
|
||||
|
|
@ -1074,3 +1113,166 @@ void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data)
|
|||
data << uint64(guid);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleAlterAppearance( WorldPacket & recv_data )
|
||||
{
|
||||
sLog.outDebug("CMSG_ALTER_APPEARANCE");
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+4+4);
|
||||
|
||||
uint32 Hair, Color, FacialHair;
|
||||
recv_data >> Hair >> Color >> FacialHair;
|
||||
|
||||
BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair);
|
||||
|
||||
if(!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender())
|
||||
return;
|
||||
|
||||
BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair);
|
||||
|
||||
if(!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender())
|
||||
return;
|
||||
|
||||
uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id);
|
||||
|
||||
// 0 - ok
|
||||
// 1,3 - not enough money
|
||||
// 2 - you have to seat on barber chair
|
||||
if(_player->GetMoney() < Cost)
|
||||
{
|
||||
WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4);
|
||||
data << uint32(1); // no money
|
||||
SendPacket(&data);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4);
|
||||
data << uint32(0); // ok
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
_player->SetMoney(_player->GetMoney() - Cost); // it isn't free
|
||||
|
||||
_player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id));
|
||||
_player->SetByteValue(PLAYER_BYTES, 3, uint8(Color));
|
||||
_player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id));
|
||||
|
||||
_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1);
|
||||
|
||||
_player->SetStandState(0); // stand up
|
||||
}
|
||||
|
||||
void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data )
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 slot;
|
||||
recv_data >> slot;
|
||||
|
||||
if(slot > 5)
|
||||
{
|
||||
sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot);
|
||||
return;
|
||||
}
|
||||
|
||||
if(uint32 glyph = _player->GetGlyph(slot))
|
||||
{
|
||||
if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
|
||||
{
|
||||
_player->RemoveAurasDueToSpell(gp->SpellId);
|
||||
_player->SetGlyph(slot, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleCharCustomize(WorldPacket& recv_data)
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data, 8+1);
|
||||
|
||||
uint64 guid;
|
||||
std::string newname;
|
||||
|
||||
recv_data >> guid;
|
||||
recv_data >> newname;
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1+1+1+1+1);
|
||||
|
||||
uint8 gender, skin, face, hairStyle, hairColor, facialHair;
|
||||
recv_data >> gender >> skin >> face >> hairStyle >> hairColor >> facialHair;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid));
|
||||
if (!result)
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||
data << uint8(CHAR_CREATE_ERROR);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
Field *fields = result->Fetch();
|
||||
uint32 at_loginFlags = fields[0].GetUInt32();
|
||||
delete result;
|
||||
|
||||
if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||
data << uint8(CHAR_CREATE_ERROR);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent character rename to invalid name
|
||||
if(!normalizePlayerName(newname))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||
data << uint8(CHAR_NAME_NO_NAME);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ObjectMgr::IsValidName(newname,true))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||
data << uint8(CHAR_NAME_INVALID_CHARACTER);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
// check name limitations
|
||||
if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname))
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||
data << uint8(CHAR_NAME_RESERVED);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist
|
||||
{
|
||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1);
|
||||
data << uint8(CHAR_CREATE_NAME_IN_USE);
|
||||
SendPacket( &data );
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterDatabase.escape_string(newname);
|
||||
Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair);
|
||||
CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid));
|
||||
CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid));
|
||||
|
||||
std::string IP_str = GetRemoteAddress();
|
||||
sLog.outChar("Account: %d (IP: %s), Character guid: %u Customized to: %s", GetAccountId(), IP_str.c_str(), GUID_LOPART(guid), newname.c_str());
|
||||
|
||||
WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6);
|
||||
data << uint8(RESPONSE_SUCCESS);
|
||||
data << uint64(guid);
|
||||
data << newname;
|
||||
data << uint8(gender);
|
||||
data << uint8(skin);
|
||||
data << uint8(face);
|
||||
data << uint8(hairStyle);
|
||||
data << uint8(hairColor);
|
||||
data << uint8(facialHair);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,6 +185,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "sellerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSellErrorCommand, "", NULL },
|
||||
{ "buyerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBuyErrorCommand, "", NULL },
|
||||
{ "sendopcode", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendOpcodeCommand, "", NULL },
|
||||
{ "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSpawnVehicle, "", NULL },
|
||||
{ "uws", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUpdateWorldStateCommand, "", NULL },
|
||||
{ "ps", SEC_ADMINISTRATOR, false, &ChatHandler::HandlePlaySound2Command, "", NULL },
|
||||
{ "scn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendChannelNotifyCommand, "", NULL },
|
||||
|
|
@ -197,6 +198,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMod32Value, "", NULL },
|
||||
{ "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL },
|
||||
{ "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL },
|
||||
{ "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
||||
|
|
@ -257,6 +259,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
|
||||
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
|
||||
{ "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", NULL },
|
||||
{ "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL },
|
||||
{ "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL },
|
||||
{ "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL },
|
||||
{ "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL },
|
||||
|
|
@ -553,6 +556,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "sendmail", SEC_MODERATOR, true, &ChatHandler::HandleSendMailCommand, "", NULL },
|
||||
{ "sendmoney", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMoneyCommand, "", NULL },
|
||||
{ "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleRenameCommand, "", NULL },
|
||||
{ "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCustomizeCommand, "", NULL },
|
||||
{ "loadscripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLoadScriptsCommand, "", NULL },
|
||||
{ "mute", SEC_GAMEMASTER, true, &ChatHandler::HandleMuteCommand, "", NULL },
|
||||
{ "unmute", SEC_GAMEMASTER, true, &ChatHandler::HandleUnmuteCommand, "", NULL },
|
||||
|
|
@ -560,6 +564,7 @@ ChatCommand * ChatHandler::getCommandTable()
|
|||
{ "cometome", SEC_ADMINISTRATOR, false, &ChatHandler::HandleComeToMeCommand, "", NULL },
|
||||
{ "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL },
|
||||
{ "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL },
|
||||
{ "flusharenapoints", SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL },
|
||||
{ "chardelete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeleteCommand, "", NULL },
|
||||
{ "sendmessage", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL },
|
||||
{ "repairitems", SEC_GAMEMASTER, false, &ChatHandler::HandleRepairitemsCommand, "", NULL },
|
||||
|
|
@ -706,7 +711,7 @@ void ChatHandler::PSendSysMessage(const char *format, ...)
|
|||
SendSysMessage(str);
|
||||
}
|
||||
|
||||
bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcmd)
|
||||
bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcmd)
|
||||
{
|
||||
char const* oldtext = text;
|
||||
std::string cmd = "";
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class ChatHandler
|
|||
|
||||
void SendGlobalSysMessage(const char *str);
|
||||
|
||||
bool ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcommand);
|
||||
bool ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcommand);
|
||||
bool ShowHelpForCommand(ChatCommand *table, const char* cmd);
|
||||
bool ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd);
|
||||
|
||||
|
|
@ -225,6 +225,7 @@ class ChatHandler
|
|||
bool HandleReloadLootTemplatesFishingCommand(const char* args);
|
||||
bool HandleReloadLootTemplatesGameobjectCommand(const char* args);
|
||||
bool HandleReloadLootTemplatesItemCommand(const char* args);
|
||||
bool HandleReloadLootTemplatesMillingCommand(const char* args);
|
||||
bool HandleReloadLootTemplatesPickpocketingCommand(const char* args);
|
||||
bool HandleReloadLootTemplatesProspectingCommand(const char* args);
|
||||
bool HandleReloadLootTemplatesReferenceCommand(const char* args);
|
||||
|
|
@ -405,6 +406,7 @@ class ChatHandler
|
|||
bool HandleSendChannelNotifyCommand(const char* args);
|
||||
bool HandleSendChatMsgCommand(const char* args);
|
||||
bool HandleRenameCommand(const char * args);
|
||||
bool HandleCustomizeCommand(const char * args);
|
||||
bool HandleLoadPDumpCommand(const char *args);
|
||||
bool HandleWritePDumpCommand(const char *args);
|
||||
bool HandleCastCommand(const char *args);
|
||||
|
|
@ -415,6 +417,7 @@ class ChatHandler
|
|||
bool HandleComeToMeCommand(const char *args);
|
||||
bool HandleCombatStopCommand(const char *args);
|
||||
bool HandleSendMessageCommand(const char * args);
|
||||
bool HandleFlushArenaPointsCommand(const char *args);
|
||||
bool HandleRepairitemsCommand(const char* args);
|
||||
bool HandleWaterwalkCommand(const char* args);
|
||||
|
||||
|
|
@ -429,6 +432,8 @@ class ChatHandler
|
|||
bool HandleSaveAllCommand(const char* args);
|
||||
bool HandleGetItemState(const char * args);
|
||||
bool HandleGetLootRecipient(const char * args);
|
||||
bool HandleDebugArenaCommand(const char * args);
|
||||
bool HandleSpawnVehicle(const char * args);
|
||||
|
||||
Player* getSelectedPlayer();
|
||||
Creature* getSelectedCreature();
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Corpse::Corpse(CorpseType type) : WorldObject()
|
|||
m_objectType |= TYPEMASK_CORPSE;
|
||||
m_objectTypeId = TYPEID_CORPSE;
|
||||
// 2.3.2 - 0x58
|
||||
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
|
||||
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
|
||||
|
||||
m_valuesCount = CORPSE_END;
|
||||
|
||||
|
|
|
|||
|
|
@ -117,11 +117,12 @@ Unit(), i_AI(NULL),
|
|||
lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0),
|
||||
m_lootMoney(0), m_lootRecipient(0),
|
||||
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
|
||||
m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false),
|
||||
m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
|
||||
m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_isVehicle(false),
|
||||
m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
|
||||
m_AlreadyCallAssistance(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
|
||||
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0)
|
||||
{
|
||||
m_regenTimer = 200;
|
||||
m_valuesCount = UNIT_END;
|
||||
|
||||
for(int i =0; i<4; ++i)
|
||||
|
|
@ -265,7 +266,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
|
|||
|
||||
// creatures always have melee weapon ready if any
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_AURAS );
|
||||
|
||||
SelectLevel(GetCreatureInfo());
|
||||
if (team == HORDE)
|
||||
|
|
@ -671,8 +671,11 @@ bool Creature::isCanIneractWithBattleMaster(Player* pPlayer, bool msg) const
|
|||
case BATTLEGROUND_NA:
|
||||
case BATTLEGROUND_BE:
|
||||
case BATTLEGROUND_AA:
|
||||
case BATTLEGROUND_RL: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break;
|
||||
break;
|
||||
case BATTLEGROUND_RL:
|
||||
case BATTLEGROUND_SA:
|
||||
case BATTLEGROUND_DS:
|
||||
case BATTLEGROUND_RV: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break;
|
||||
default: break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1351,11 +1354,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force)
|
|||
if (force)
|
||||
{
|
||||
for (uint8 i = 0; i < 3; i++)
|
||||
{
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, 0);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), 0);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, 0);
|
||||
}
|
||||
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0);
|
||||
m_equipmentId = 0;
|
||||
}
|
||||
return;
|
||||
|
|
@ -1367,11 +1366,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force)
|
|||
|
||||
m_equipmentId = equip_entry;
|
||||
for (uint8 i = 0; i < 3; i++)
|
||||
{
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, einfo->equipmodel[i]);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), einfo->equipinfo[i]);
|
||||
SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, einfo->equipslot[i]);
|
||||
}
|
||||
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->equipentry[i]);
|
||||
}
|
||||
|
||||
bool Creature::hasQuest(uint32 quest_id) const
|
||||
|
|
|
|||
|
|
@ -237,9 +237,7 @@ struct NpcOptionLocale
|
|||
struct EquipmentInfo
|
||||
{
|
||||
uint32 entry;
|
||||
uint32 equipmodel[3];
|
||||
uint32 equipinfo[3];
|
||||
uint32 equipslot[3];
|
||||
uint32 equipentry[3];
|
||||
};
|
||||
|
||||
// from `creature` table
|
||||
|
|
@ -414,6 +412,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
uint32 GetEquipmentId() const { return m_equipmentId; }
|
||||
|
||||
bool isPet() const { return m_isPet; }
|
||||
bool isVehicle() const { return m_isVehicle; }
|
||||
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
|
||||
bool isTotem() const { return m_isTotem; }
|
||||
bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
|
||||
|
|
@ -626,10 +625,10 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
|
||||
uint8 m_emoteState;
|
||||
bool m_isPet; // set only in Pet::Pet
|
||||
bool m_isVehicle; // set only in Vehicle::Vehicle
|
||||
bool m_isTotem; // set only in Totem::Totem
|
||||
void RegenerateMana();
|
||||
void RegenerateHealth();
|
||||
uint32 m_regenTimer;
|
||||
MovementGeneratorType m_defaultMovementType;
|
||||
Cell m_currentCell; // store current cell where creature listed
|
||||
uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ DynamicObject::DynamicObject() : WorldObject()
|
|||
m_objectType |= TYPEMASK_DYNAMICOBJECT;
|
||||
m_objectTypeId = TYPEID_DYNAMICOBJECT;
|
||||
// 2.3.2 - 0x58
|
||||
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
|
||||
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
|
||||
|
||||
m_valuesCount = DYNAMICOBJECT_END;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class GMTicket
|
|||
{
|
||||
}
|
||||
|
||||
GMTicket(uint32 guid, std::string text, time_t update) : m_guid(guid), m_text(text), m_lastUpdate(update)
|
||||
GMTicket(uint32 guid, const std::string& text, time_t update) : m_guid(guid), m_text(text), m_lastUpdate(update)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ uint32 GameEvent::Update() // return the next e
|
|||
{
|
||||
uint32 nextEventDelay = max_ge_check_delay; // 1 day
|
||||
uint32 calcDelay;
|
||||
for (uint16 itr = 1; itr < mGameEvent.size(); itr++)
|
||||
for (uint16 itr = 1; itr < mGameEvent.size(); ++itr)
|
||||
{
|
||||
//sLog.outErrorDb("Checking event %u",itr);
|
||||
if (CheckOneGameEvent(itr))
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ GameObject::GameObject() : WorldObject()
|
|||
m_objectType |= TYPEMASK_GAMEOBJECT;
|
||||
m_objectTypeId = TYPEID_GAMEOBJECT;
|
||||
// 2.3.2 - 0x58
|
||||
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
|
||||
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
|
||||
|
||||
m_valuesCount = GAMEOBJECT_END;
|
||||
m_respawnTime = 0;
|
||||
|
|
@ -123,10 +123,26 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float
|
|||
SetFloatValue(GAMEOBJECT_POS_Z, z);
|
||||
SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle
|
||||
|
||||
SetFloatValue (GAMEOBJECT_ROTATION, rotation0);
|
||||
SetFloatValue (GAMEOBJECT_ROTATION+1, rotation1);
|
||||
SetFloatValue (GAMEOBJECT_ROTATION+2, rotation2);
|
||||
SetFloatValue (GAMEOBJECT_ROTATION+3, rotation3);
|
||||
int64 rotation = 0;
|
||||
|
||||
float f_rot1 = sin(ang / 2.0f);
|
||||
int64 i_rot1 = f_rot1 / atan(pow(2.0f, -20.0f));
|
||||
rotation |= (i_rot1 << 43 >> 43) & 0x00000000001FFFFF;
|
||||
|
||||
//float f_rot2 = sin(0.0f / 2.0f);
|
||||
//int64 i_rot2 = f_rot2 / atan(pow(2.0f, -20.0f));
|
||||
//rotation |= (((i_rot2 << 22) >> 32) >> 11) & 0x000003FFFFE00000;
|
||||
|
||||
//float f_rot3 = sin(0.0f / 2.0f);
|
||||
//int64 i_rot3 = f_rot3 / atan(pow(2.0f, -21.0f));
|
||||
//rotation |= (i_rot3 >> 42) & 0x7FFFFC0000000000;
|
||||
|
||||
SetUInt64Value(GAMEOBJECT_ROTATION, rotation);
|
||||
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0);
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1);
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2);
|
||||
SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3);
|
||||
|
||||
SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size);
|
||||
|
||||
|
|
@ -510,10 +526,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
|
|||
data.posY = GetFloatValue(GAMEOBJECT_POS_Y);
|
||||
data.posZ = GetFloatValue(GAMEOBJECT_POS_Z);
|
||||
data.orientation = GetFloatValue(GAMEOBJECT_FACING);
|
||||
data.rotation0 = GetFloatValue(GAMEOBJECT_ROTATION+0);
|
||||
data.rotation1 = GetFloatValue(GAMEOBJECT_ROTATION+1);
|
||||
data.rotation2 = GetFloatValue(GAMEOBJECT_ROTATION+2);
|
||||
data.rotation3 = GetFloatValue(GAMEOBJECT_ROTATION+3);
|
||||
data.rotation0 = GetFloatValue(GAMEOBJECT_PARENTROTATION+0);
|
||||
data.rotation1 = GetFloatValue(GAMEOBJECT_PARENTROTATION+1);
|
||||
data.rotation2 = GetFloatValue(GAMEOBJECT_PARENTROTATION+2);
|
||||
data.rotation3 = GetFloatValue(GAMEOBJECT_PARENTROTATION+3);
|
||||
data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime;
|
||||
data.animprogress = GetGoAnimProgress();
|
||||
data.go_state = GetGoState();
|
||||
|
|
@ -530,10 +546,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
|
|||
<< GetFloatValue(GAMEOBJECT_POS_Y) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_POS_Z) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_FACING) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION+1) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION+2) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_ROTATION+3) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION+1) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION+2) << ", "
|
||||
<< GetFloatValue(GAMEOBJECT_PARENTROTATION+3) << ", "
|
||||
<< m_respawnDelayTime << ", "
|
||||
<< (uint32)GetGoAnimProgress() << ", "
|
||||
<< (uint32)GetGoState() << ")";
|
||||
|
|
@ -1222,6 +1238,26 @@ void GameObject::Use(Unit* user)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case GAMEOBJECT_TYPE_BARBER_CHAIR: //32
|
||||
{
|
||||
GameObjectInfo const* info = GetGOInfo();
|
||||
if(!info)
|
||||
return;
|
||||
|
||||
if(user->GetTypeId()!=TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Player* player = (Player*)user;
|
||||
|
||||
// fallback, will always work
|
||||
player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET);
|
||||
|
||||
WorldPacket data(SMSG_ENABLE_BARBER_SHOP, 0);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
|
||||
player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->barberChair.chairheight);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
sLog.outDebug("Unknown Object Type %u", GetGoType());
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -334,12 +334,12 @@ struct GameObjectInfo
|
|||
uint32 mapID; //0
|
||||
uint32 difficulty; //1
|
||||
} dungeonDifficulty;
|
||||
//32 GAMEOBJECT_TYPE_DO_NOT_USE_YET
|
||||
//32 GAMEOBJECT_TYPE_BARBER_CHAIR
|
||||
struct
|
||||
{
|
||||
uint32 mapID; //0
|
||||
uint32 difficulty; //1
|
||||
} doNotUseYet;
|
||||
uint32 chairheight; //0
|
||||
uint32 heightOffset; //1
|
||||
} barberChair;
|
||||
//33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
|
||||
struct
|
||||
{
|
||||
|
|
@ -348,6 +348,13 @@ struct GameObjectInfo
|
|||
uint32 state1Name; //2
|
||||
uint32 state2Name; //3
|
||||
} destructibleBuilding;
|
||||
//34 GAMEOBJECT_TYPE_TRAPDOOR
|
||||
struct
|
||||
{
|
||||
uint32 whenToPause; // 0
|
||||
uint32 startOpen; // 1
|
||||
uint32 autoClose; // 2
|
||||
} trapDoor;
|
||||
|
||||
// not use for specific field access (only for output with loop by all filed), also this determinate max union size
|
||||
struct // GAMEOBJECT_TYPE_SPELLCASTER
|
||||
|
|
@ -500,14 +507,14 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
|
|||
void SetSpellId(uint32 id) { m_spellId = id;}
|
||||
uint32 GetSpellId() const { return m_spellId;}
|
||||
void getFishLoot(Loot *loot);
|
||||
GameobjectTypes GetGoType() const { return GameobjectTypes(GetUInt32Value(GAMEOBJECT_TYPE_ID)); }
|
||||
void SetGoType(GameobjectTypes type) { SetUInt32Value(GAMEOBJECT_TYPE_ID, type); }
|
||||
uint32 GetGoState() const { return GetUInt32Value(GAMEOBJECT_STATE); }
|
||||
void SetGoState(uint32 state) { SetUInt32Value(GAMEOBJECT_STATE, state); }
|
||||
uint32 GetGoArtKit() const { return GetUInt32Value(GAMEOBJECT_ARTKIT); }
|
||||
void SetGoArtKit(uint32 artkit) { SetUInt32Value(GAMEOBJECT_ARTKIT, artkit); }
|
||||
uint32 GetGoAnimProgress() const { return GetUInt32Value(GAMEOBJECT_ANIMPROGRESS); }
|
||||
void SetGoAnimProgress(uint32 animprogress) { SetUInt32Value(GAMEOBJECT_ANIMPROGRESS, animprogress); }
|
||||
GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
|
||||
void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
|
||||
uint8 GetGoState() const { return GetByteValue(GAMEOBJECT_BYTES_1, 0); }
|
||||
void SetGoState(uint8 state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); }
|
||||
uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); }
|
||||
void SetGoArtKit(uint8 artkit) { SetByteValue(GAMEOBJECT_BYTES_1, 2, artkit); }
|
||||
uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); }
|
||||
void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); }
|
||||
|
||||
void Use(Unit* user);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ GossipMenu::~GossipMenu()
|
|||
ClearMenu();
|
||||
}
|
||||
|
||||
void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded)
|
||||
void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded)
|
||||
{
|
||||
ASSERT( m_gItems.size() <= GOSSIP_MAX_MENU_ITEMS );
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, u
|
|||
m_gItems.push_back(gItem);
|
||||
}
|
||||
|
||||
void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, bool Coded)
|
||||
void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, bool Coded)
|
||||
{
|
||||
AddMenuItem( Icon, Message, 0, 0, "", 0, Coded);
|
||||
}
|
||||
|
|
@ -341,7 +341,7 @@ void QuestMenu::ClearMenu()
|
|||
m_qItems.clear();
|
||||
}
|
||||
|
||||
void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID )
|
||||
void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, const std::string& Title, uint64 npcGUID )
|
||||
{
|
||||
WorldPacket data( SMSG_QUESTGIVER_QUEST_LIST, 100 ); // guess size
|
||||
data << uint64(npcGUID);
|
||||
|
|
@ -415,10 +415,14 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID
|
|||
}
|
||||
|
||||
data << uint64(npcGUID);
|
||||
data << uint64(0); // wotlk, something todo with quest sharing?
|
||||
data << uint32(pQuest->GetQuestId());
|
||||
data << Title << Details << Objectives;
|
||||
data << Title;
|
||||
data << Details;
|
||||
data << Objectives;
|
||||
data << uint32(ActivateAccept);
|
||||
data << uint32(pQuest->GetSuggestedPlayers());
|
||||
data << uint8(0); // new wotlk
|
||||
|
||||
if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
|
||||
{
|
||||
|
|
@ -464,6 +468,7 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID
|
|||
data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0)
|
||||
data << uint32(pQuest->GetRewSpellCast()); // casted spell
|
||||
data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
|
||||
data << uint32(pQuest->GetBonusTalents()); // bonus talents
|
||||
|
||||
data << uint32(QUEST_EMOTE_COUNT);
|
||||
for (uint32 i=0; i < QUEST_EMOTE_COUNT; i++)
|
||||
|
|
@ -540,6 +545,8 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
|
|||
data << uint32(pQuest->GetSrcItemId());
|
||||
data << uint32(pQuest->GetFlags() & 0xFFFF);
|
||||
data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
|
||||
data << uint32(pQuest->GetPlayersSlain()); // players slain
|
||||
data << uint32(pQuest->GetBonusTalents()); // bonus talents
|
||||
|
||||
int iI;
|
||||
|
||||
|
|
@ -588,13 +595,14 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest )
|
|||
data << uint32(pQuest->ReqCreatureOrGOCount[iI]);
|
||||
data << uint32(pQuest->ReqItemId[iI]);
|
||||
data << uint32(pQuest->ReqItemCount[iI]);
|
||||
data << uint32(0); // added in WotLK, dunno if offset if correct
|
||||
}
|
||||
|
||||
for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++)
|
||||
data << ObjectiveText[iI];
|
||||
|
||||
pSession->SendPacket( &data );
|
||||
sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() );
|
||||
sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", pQuest->GetQuestId() );
|
||||
}
|
||||
|
||||
void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext )
|
||||
|
|
@ -676,9 +684,10 @@ void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID,
|
|||
data << uint32(0x08); // unused by client?
|
||||
data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0)
|
||||
data << uint32(pQuest->GetRewSpellCast()); // casted spell
|
||||
data << uint32(0x00); // unk, NOT honor
|
||||
data << uint32(0); // unknown
|
||||
data << uint32(pQuest->GetBonusTalents()); // bonus talents
|
||||
pSession->SendPacket( &data );
|
||||
sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() );
|
||||
sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId() );
|
||||
}
|
||||
|
||||
void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel )
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ class MANGOS_DLL_SPEC GossipMenu
|
|||
GossipMenu();
|
||||
~GossipMenu();
|
||||
|
||||
void AddMenuItem(uint8 Icon, std::string Message, bool Coded = false);
|
||||
void AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded = false);
|
||||
void AddMenuItem(uint8 Icon, const std::string& Message, bool Coded = false);
|
||||
void AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded = false);
|
||||
|
||||
// for using from scripts, don't must be inlined
|
||||
void AddMenuItem(uint8 Icon, char const* Message, bool Coded = false);
|
||||
|
|
@ -195,7 +195,7 @@ class MANGOS_DLL_SPEC PlayerMenu
|
|||
/*********************************************************/
|
||||
void SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID );
|
||||
|
||||
void SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID );
|
||||
void SendQuestGiverQuestList( QEmote eEmote, const std::string& Title, uint64 npcGUID );
|
||||
|
||||
void SendQuestQueryResponse ( Quest const *pQuest );
|
||||
void SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept);
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ VisibleNotifier::Notify()
|
|||
// send data at target visibility change (adding to client)
|
||||
for(std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr)
|
||||
if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT))
|
||||
i_player.SendAuraDurationsForTarget((Unit*)(*vItr));
|
||||
i_player.SendAurasForTarget((Unit*)(*vItr));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1308,6 +1308,54 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed )
|
|||
SendUpdate();
|
||||
}
|
||||
|
||||
uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot)
|
||||
{
|
||||
// check for min / max count
|
||||
uint32 memberscount = GetMembersCount();
|
||||
if(memberscount < MinPlayerCount)
|
||||
return BG_JOIN_ERR_GROUP_NOT_ENOUGH;
|
||||
if(memberscount > MaxPlayerCount)
|
||||
return BG_JOIN_ERR_GROUP_TOO_MANY;
|
||||
|
||||
// get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.)
|
||||
Player * reference = GetFirstMember()->getSource();
|
||||
// no reference found, can't join this way
|
||||
if(!reference)
|
||||
return BG_JOIN_ERR_OFFLINE_MEMBER;
|
||||
|
||||
uint32 bgQueueId = reference->GetBattleGroundQueueIdFromLevel();
|
||||
uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot);
|
||||
uint32 team = reference->GetTeam();
|
||||
|
||||
// check every member of the group to be able to join
|
||||
for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
{
|
||||
Player *member = itr->getSource();
|
||||
// offline member? don't let join
|
||||
if(!member)
|
||||
return BG_JOIN_ERR_OFFLINE_MEMBER;
|
||||
// don't allow cross-faction join as group
|
||||
if(member->GetTeam() != team)
|
||||
return BG_JOIN_ERR_MIXED_FACTION;
|
||||
// not in the same battleground level braket, don't let join
|
||||
if(member->GetBattleGroundQueueIdFromLevel() != bgQueueId)
|
||||
return BG_JOIN_ERR_MIXED_LEVELS;
|
||||
// don't let join rated matches if the arena team id doesn't match
|
||||
if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId)
|
||||
return BG_JOIN_ERR_MIXED_ARENATEAM;
|
||||
// don't let join if someone from the group is already in that bg queue
|
||||
if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueType))
|
||||
return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE;
|
||||
// check for deserter debuff in case not arena queue
|
||||
if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground())
|
||||
return BG_JOIN_ERR_GROUP_DESERTER;
|
||||
// check if member can join any more battleground queues
|
||||
if(!member->HasFreeBattleGroundQueueId())
|
||||
return BG_JOIN_ERR_ALL_QUEUES_USED;
|
||||
}
|
||||
return BG_JOIN_ERR_OK;
|
||||
}
|
||||
|
||||
//===================================================
|
||||
//============== Roll ===============================
|
||||
//===================================================
|
||||
|
|
|
|||
|
|
@ -64,24 +64,25 @@ enum GroupUpdateFlags
|
|||
{
|
||||
GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing
|
||||
GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16, flags
|
||||
GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint16
|
||||
GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint16
|
||||
GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32
|
||||
GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32
|
||||
GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8
|
||||
GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // uint16
|
||||
GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // uint16
|
||||
GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16
|
||||
GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16
|
||||
GROUP_UPDATE_FLAG_POSITION = 0x00000100, // uint16, uint16
|
||||
GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint16 spellid + uint8 unk
|
||||
GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint32 spellid + uint8 unk
|
||||
GROUP_UPDATE_FLAG_PET_GUID = 0x00000400, // uint64 pet guid
|
||||
GROUP_UPDATE_FLAG_PET_NAME = 0x00000800, // pet name, NULL terminated string
|
||||
GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00001000, // uint16, model id
|
||||
GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint16 pet cur health
|
||||
GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint16 pet max health
|
||||
GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint32 pet cur health
|
||||
GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint32 pet max health
|
||||
GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00008000, // uint8 pet power type
|
||||
GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00010000, // uint16 pet cur power
|
||||
GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00020000, // uint16 pet max power
|
||||
GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint16 spellid + uint8 unk, pet auras...
|
||||
GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras...
|
||||
GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc)
|
||||
GROUP_UPDATE_PET = 0x0007FC00, // all pet flags
|
||||
GROUP_UPDATE_FULL = 0x0007FFFF, // all known flags
|
||||
};
|
||||
|
|
@ -247,6 +248,7 @@ class MANGOS_DLL_SPEC Group
|
|||
void ConvertToRaid();
|
||||
|
||||
void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; }
|
||||
uint32 CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot);
|
||||
|
||||
void ChangeMembersGroup(const uint64 &guid, const uint8 &group);
|
||||
void ChangeMembersGroup(Player *player, const uint8 &group);
|
||||
|
|
|
|||
|
|
@ -680,10 +680,10 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
|
|||
}
|
||||
|
||||
if (mask & GROUP_UPDATE_FLAG_CUR_HP)
|
||||
*data << (uint16) player->GetHealth();
|
||||
*data << (uint32) player->GetHealth();
|
||||
|
||||
if (mask & GROUP_UPDATE_FLAG_MAX_HP)
|
||||
*data << (uint16) player->GetMaxHealth();
|
||||
*data << (uint32) player->GetMaxHealth();
|
||||
|
||||
Powers powerType = player->getPowerType();
|
||||
if (mask & GROUP_UPDATE_FLAG_POWER_TYPE)
|
||||
|
|
@ -712,7 +712,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
|
|||
{
|
||||
if(auramask & (uint64(1) << i))
|
||||
{
|
||||
*data << uint16(player->GetUInt32Value(UNIT_FIELD_AURA + i));
|
||||
*data << uint32(player->GetVisibleAura(i));
|
||||
*data << uint8(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -746,17 +746,17 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
|
|||
if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP)
|
||||
{
|
||||
if(pet)
|
||||
*data << (uint16) pet->GetHealth();
|
||||
*data << (uint32) pet->GetHealth();
|
||||
else
|
||||
*data << (uint16) 0;
|
||||
*data << (uint32) 0;
|
||||
}
|
||||
|
||||
if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP)
|
||||
{
|
||||
if(pet)
|
||||
*data << (uint16) pet->GetMaxHealth();
|
||||
*data << (uint32) pet->GetMaxHealth();
|
||||
else
|
||||
*data << (uint16) 0;
|
||||
*data << (uint32) 0;
|
||||
}
|
||||
|
||||
if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE)
|
||||
|
|
@ -793,7 +793,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke
|
|||
{
|
||||
if(auramask & (uint64(1) << i))
|
||||
{
|
||||
*data << uint16(pet->GetUInt32Value(UNIT_FIELD_AURA + i));
|
||||
*data << uint32(pet->GetVisibleAura(i));
|
||||
*data << uint8(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -816,6 +816,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
|
|||
if(!player)
|
||||
{
|
||||
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2);
|
||||
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
|
||||
data.appendPackGUID(Guid);
|
||||
data << (uint32) GROUP_UPDATE_FLAG_STATUS;
|
||||
data << (uint16) MEMBER_STATUS_OFFLINE;
|
||||
|
|
@ -826,6 +827,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
|
|||
Pet *pet = player->GetPet();
|
||||
|
||||
WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8);
|
||||
data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related
|
||||
data.append(player->GetPackGUID());
|
||||
|
||||
uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF
|
||||
|
|
@ -835,8 +837,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
|
|||
Powers powerType = player->getPowerType();
|
||||
data << (uint32) mask1; // group update mask
|
||||
data << (uint16) MEMBER_STATUS_ONLINE; // member's online status
|
||||
data << (uint16) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP
|
||||
data << (uint16) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP
|
||||
data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP
|
||||
data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP
|
||||
data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE
|
||||
data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER
|
||||
data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER
|
||||
|
|
@ -850,11 +852,11 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
|
|||
data << (uint64) auramask; // placeholder
|
||||
for(uint8 i = 0; i < MAX_AURAS; ++i)
|
||||
{
|
||||
if(uint32 aura = player->GetUInt32Value(UNIT_FIELD_AURA + i))
|
||||
if(uint32 aura = player->GetVisibleAura(i))
|
||||
{
|
||||
auramask |= (uint64(1) << i);
|
||||
data << uint16(aura);
|
||||
data << uint8(1);
|
||||
data << (uint32) aura;
|
||||
data << (uint8) 1;
|
||||
}
|
||||
}
|
||||
data.put<uint64>(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS
|
||||
|
|
@ -865,8 +867,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
|
|||
data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID
|
||||
data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME
|
||||
data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID
|
||||
data << (uint16) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP
|
||||
data << (uint16) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP
|
||||
data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP
|
||||
data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP
|
||||
data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE
|
||||
data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER
|
||||
data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER
|
||||
|
|
@ -876,10 +878,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data )
|
|||
data << (uint64) petauramask; // placeholder
|
||||
for(uint8 i = 0; i < MAX_AURAS; ++i)
|
||||
{
|
||||
if(uint32 petaura = pet->GetUInt32Value(UNIT_FIELD_AURA + i))
|
||||
if(uint32 petaura = pet->GetVisibleAura(i))
|
||||
{
|
||||
petauramask |= (uint64(1) << i);
|
||||
data << (uint16) petaura;
|
||||
data << (uint32) petaura;
|
||||
data << (uint8) 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -359,28 +359,41 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot)
|
|||
}
|
||||
else
|
||||
{
|
||||
if(!objmgr.GetPlayerNameByGUID(guid, plName)) // player doesn't exist
|
||||
return false;
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT name,data,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid));
|
||||
if(!result)
|
||||
return false; // player doesn't exist
|
||||
|
||||
plLevel = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL, guid);
|
||||
if(plLevel<1||plLevel>255) // can be at broken `data` field
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
plName = fields[0].GetCppString();
|
||||
|
||||
Tokens data = StrSplit(fields[1].GetCppString(), " ");
|
||||
plLevel = Player::GetUInt32ValueFromArray(data,UNIT_FIELD_LEVEL);
|
||||
|
||||
plZone = fields[2].GetUInt32();
|
||||
plClass = fields[3].GetUInt32();
|
||||
delete result;
|
||||
|
||||
if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field
|
||||
{
|
||||
sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid));
|
||||
return false;
|
||||
}
|
||||
plZone = Player::GetZoneIdFromDB(guid);
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(guid));
|
||||
if(!result)
|
||||
return false;
|
||||
plClass = (*result)[0].GetUInt32();
|
||||
if(!plZone)
|
||||
{
|
||||
sLog.outError("Player (GUID: %u) has broken zone-data",GUID_LOPART(guid));
|
||||
//here it will also try the same, to get the zone from characters-table, but additional it tries to find
|
||||
plZone = Player::GetZoneIdFromDB(guid);
|
||||
//the zone through xy coords.. this is a bit redundant, but
|
||||
//shouldn't be called often
|
||||
}
|
||||
|
||||
if(plClass<CLASS_WARRIOR||plClass>=MAX_CLASSES) // can be at broken `class` field
|
||||
{
|
||||
sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid));
|
||||
return false;
|
||||
}
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
||||
memslot->name = plName;
|
||||
|
|
@ -517,7 +530,7 @@ void Guild::SetOFFNOTE(uint64 guid,std::string offnote)
|
|||
CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), itr->first);
|
||||
}
|
||||
|
||||
void Guild::BroadcastToGuild(WorldSession *session, std::string msg, uint32 language)
|
||||
void Guild::BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language)
|
||||
{
|
||||
if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK))
|
||||
{
|
||||
|
|
@ -534,7 +547,7 @@ void Guild::BroadcastToGuild(WorldSession *session, std::string msg, uint32 lang
|
|||
}
|
||||
}
|
||||
|
||||
void Guild::BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language)
|
||||
void Guild::BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language)
|
||||
{
|
||||
if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_OFFCHATSPEAK))
|
||||
{
|
||||
|
|
@ -593,7 +606,7 @@ void Guild::CreateRank(std::string name_,uint32 rights)
|
|||
CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", Id, m_ranks.size(), name_.c_str(), rights );
|
||||
}
|
||||
|
||||
void Guild::AddRank(std::string name_,uint32 rights, uint32 money)
|
||||
void Guild::AddRank(const std::string& name_,uint32 rights, uint32 money)
|
||||
{
|
||||
m_ranks.push_back(RankInfo(name_,rights,money));
|
||||
}
|
||||
|
|
@ -754,6 +767,7 @@ void Guild::Query(WorldSession *session)
|
|||
data << uint32(BorderStyle);
|
||||
data << uint32(BorderColor);
|
||||
data << uint32(BackgroundColor);
|
||||
data << uint32(0); // something new in WotLK
|
||||
|
||||
session->SendPacket( &data );
|
||||
sLog.outDebug( "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)" );
|
||||
|
|
@ -1571,7 +1585,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
|
|||
{
|
||||
data << uint8((*itr)->LogEntry);
|
||||
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
|
||||
data << uint32((*itr)->ItemOrMoney);
|
||||
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK2)
|
||||
{
|
||||
data << uint32((*itr)->ItemOrMoney);
|
||||
}
|
||||
else
|
||||
{
|
||||
data << uint32((*itr)->ItemOrMoney);
|
||||
data << uint32((*itr)->ItemStackCount);
|
||||
if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
|
||||
data << uint8((*itr)->DestTabId); // moved tab
|
||||
}
|
||||
data << uint32(time(NULL)-(*itr)->TimeStamp);
|
||||
}
|
||||
session->SendPacket(&data);
|
||||
|
|
@ -1587,10 +1615,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId)
|
|||
{
|
||||
data << uint8((*itr)->LogEntry);
|
||||
data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER));
|
||||
data << uint32((*itr)->ItemOrMoney);
|
||||
data << uint8((*itr)->ItemStackCount);
|
||||
if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
|
||||
data << uint8((*itr)->DestTabId); // moved tab
|
||||
if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK1 ||
|
||||
(*itr)->LogEntry == GUILD_BANK_LOG_UNK2)
|
||||
{
|
||||
data << uint32((*itr)->ItemOrMoney);
|
||||
}
|
||||
else
|
||||
{
|
||||
data << uint32((*itr)->ItemOrMoney);
|
||||
data << uint32((*itr)->ItemStackCount);
|
||||
if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2)
|
||||
data << uint8((*itr)->DestTabId); // moved tab
|
||||
}
|
||||
data << uint32(time(NULL)-(*itr)->TimeStamp);
|
||||
}
|
||||
session->SendPacket(&data);
|
||||
|
|
@ -1672,7 +1711,7 @@ void Guild::AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *t
|
|||
// SuffixFactor +4
|
||||
data << (uint32) pItem->GetItemSuffixFactor();
|
||||
// +12 // ITEM_FIELD_STACK_COUNT
|
||||
data << uint8(pItem->GetCount());
|
||||
data << uint32(pItem->GetCount());
|
||||
data << uint32(0); // +16 // Unknown value
|
||||
data << uint8(0); // unknown 2.4.2
|
||||
if (uint32 Enchant0 = pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT))
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ enum GuildRankRights
|
|||
GR_RIGHT_REPAIR_FROM_GUILD = 0x00020000, // unused in 2.4.x?, Remove money withdraw capacity
|
||||
GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair
|
||||
GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold
|
||||
GR_RIGHT_ALL = 0x000FF1FF
|
||||
GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk
|
||||
GR_RIGHT_ALL = 0x001FF1FF
|
||||
};
|
||||
|
||||
enum Typecommand
|
||||
|
|
@ -154,6 +155,8 @@ enum GuildBankLogEntries
|
|||
GUILD_BANK_LOG_WITHDRAW_MONEY = 5,
|
||||
GUILD_BANK_LOG_REPAIR_MONEY = 6,
|
||||
GUILD_BANK_LOG_MOVE_ITEM2 = 7,
|
||||
GUILD_BANK_LOG_UNK1 = 8,
|
||||
GUILD_BANK_LOG_UNK2 = 9,
|
||||
};
|
||||
|
||||
enum GuildEventLogEntryTypes
|
||||
|
|
@ -242,7 +245,7 @@ struct MemberSlot
|
|||
|
||||
struct RankInfo
|
||||
{
|
||||
RankInfo(std::string _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money)
|
||||
RankInfo(const std::string& _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money)
|
||||
{
|
||||
for(uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
|
||||
{
|
||||
|
|
@ -307,8 +310,8 @@ class Guild
|
|||
bool FillPlayerData(uint64 guid, MemberSlot* memslot);
|
||||
void LoadPlayerStatsByGuid(uint64 guid);
|
||||
|
||||
void BroadcastToGuild(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL);
|
||||
void BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL);
|
||||
void BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL);
|
||||
void BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL);
|
||||
void BroadcastPacketToRank(WorldPacket *packet, uint32 rankId);
|
||||
void BroadcastPacket(WorldPacket *packet);
|
||||
|
||||
|
|
@ -405,7 +408,7 @@ class Guild
|
|||
bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry );
|
||||
|
||||
protected:
|
||||
void AddRank(std::string name,uint32 rights,uint32 money);
|
||||
void AddRank(const std::string& name,uint32 rights,uint32 money);
|
||||
|
||||
uint32 Id;
|
||||
std::string name;
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@ void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/)
|
|||
guild->Roster(this);
|
||||
}
|
||||
|
||||
void WorldSession::SendGuildCommandResult(uint32 typecmd,std::string str,uint32 cmdresult)
|
||||
void WorldSession::SendGuildCommandResult(uint32 typecmd, const std::string& str,uint32 cmdresult)
|
||||
{
|
||||
WorldPacket data(SMSG_GUILD_COMMAND_RESULT, (8+str.size()+1));
|
||||
data << typecmd;
|
||||
|
|
|
|||
|
|
@ -204,6 +204,10 @@ bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProt
|
|||
if(!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
case ITEM_SUBCLASS_INSCRIPTION_CONTAINER:
|
||||
if(!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP))
|
||||
return false;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -448,7 +452,7 @@ uint32 Item::GetSkill()
|
|||
|
||||
const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] =
|
||||
{
|
||||
0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0
|
||||
0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0,0
|
||||
};
|
||||
|
||||
ItemPrototype const* proto = GetProto();
|
||||
|
|
@ -763,9 +767,9 @@ void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint
|
|||
if((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
|
||||
return;
|
||||
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
|
||||
SetState(ITEM_CHANGED);
|
||||
}
|
||||
|
||||
|
|
@ -774,7 +778,7 @@ void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration)
|
|||
if(GetEnchantmentDuration(slot) == duration)
|
||||
return;
|
||||
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration);
|
||||
SetState(ITEM_CHANGED);
|
||||
}
|
||||
|
||||
|
|
@ -783,7 +787,7 @@ void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
|
|||
if(GetEnchantmentCharges(slot) == charges)
|
||||
return;
|
||||
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges);
|
||||
SetState(ITEM_CHANGED);
|
||||
}
|
||||
|
||||
|
|
@ -793,7 +797,7 @@ void Item::ClearEnchantment(EnchantmentSlot slot)
|
|||
return;
|
||||
|
||||
for(uint8 x = 0; x < 3; ++x)
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x, 0);
|
||||
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + x, 0);
|
||||
SetState(ITEM_CHANGED);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,29 +146,30 @@ enum SellFailure
|
|||
// -1 from client enchantment slot number
|
||||
enum EnchantmentSlot
|
||||
{
|
||||
PERM_ENCHANTMENT_SLOT = 0,
|
||||
TEMP_ENCHANTMENT_SLOT = 1,
|
||||
SOCK_ENCHANTMENT_SLOT = 2,
|
||||
SOCK_ENCHANTMENT_SLOT_2 = 3,
|
||||
SOCK_ENCHANTMENT_SLOT_3 = 4,
|
||||
BONUS_ENCHANTMENT_SLOT = 5,
|
||||
MAX_INSPECTED_ENCHANTMENT_SLOT = 6,
|
||||
PERM_ENCHANTMENT_SLOT = 0,
|
||||
TEMP_ENCHANTMENT_SLOT = 1,
|
||||
SOCK_ENCHANTMENT_SLOT = 2,
|
||||
SOCK_ENCHANTMENT_SLOT_2 = 3,
|
||||
SOCK_ENCHANTMENT_SLOT_3 = 4,
|
||||
BONUS_ENCHANTMENT_SLOT = 5,
|
||||
WOTLK_ENCHANTMENT_SLOT = 6,
|
||||
MAX_INSPECTED_ENCHANTMENT_SLOT = 7,
|
||||
|
||||
PROP_ENCHANTMENT_SLOT_0 = 6, // used with RandomSuffix
|
||||
PROP_ENCHANTMENT_SLOT_1 = 7, // used with RandomSuffix
|
||||
PROP_ENCHANTMENT_SLOT_2 = 8, // used with RandomSuffix and RandomProperty
|
||||
PROP_ENCHANTMENT_SLOT_3 = 9, // used with RandomProperty
|
||||
PROP_ENCHANTMENT_SLOT_4 = 10, // used with RandomProperty
|
||||
MAX_ENCHANTMENT_SLOT = 11
|
||||
PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix
|
||||
PROP_ENCHANTMENT_SLOT_1 = 8, // used with RandomSuffix
|
||||
PROP_ENCHANTMENT_SLOT_2 = 9, // used with RandomSuffix and RandomProperty
|
||||
PROP_ENCHANTMENT_SLOT_3 = 10, // used with RandomProperty
|
||||
PROP_ENCHANTMENT_SLOT_4 = 11, // used with RandomProperty
|
||||
MAX_ENCHANTMENT_SLOT = 12
|
||||
};
|
||||
|
||||
#define MAX_VISIBLE_ITEM_OFFSET 16 // 16 fields per visible item (creator(2) + enchantments(12) + properties(1) + pad(1))
|
||||
#define MAX_VISIBLE_ITEM_OFFSET 18 // 18 fields per visible item (creator(2) + enchantments(13) + properties(1) + seed(1) + pad(1))
|
||||
|
||||
enum EnchantmentOffset
|
||||
{
|
||||
ENCHANTMENT_ID_OFFSET = 0,
|
||||
ENCHANTMENT_DURATION_OFFSET = 1,
|
||||
ENCHANTMENT_CHARGES_OFFSET = 2
|
||||
ENCHANTMENT_CHARGES_OFFSET = 2 // now here not only charges, but something new in wotlk
|
||||
};
|
||||
|
||||
#define MAX_ENCHANTMENT_OFFSET 3
|
||||
|
|
@ -209,6 +210,7 @@ class MANGOS_DLL_SPEC Item : public Object
|
|||
|
||||
void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED,val); }
|
||||
bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED); }
|
||||
bool IsAccountBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BOA); }
|
||||
bool IsBindedNotWith(uint64 guid) const { return IsSoulBound() && GetOwnerGUID()!= guid; }
|
||||
bool IsBoundByEnchant() const;
|
||||
virtual void SaveToDB();
|
||||
|
|
@ -254,9 +256,9 @@ class MANGOS_DLL_SPEC Item : public Object
|
|||
void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration);
|
||||
void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges);
|
||||
void ClearEnchantment(EnchantmentSlot slot);
|
||||
uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);}
|
||||
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);}
|
||||
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);}
|
||||
uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);}
|
||||
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);}
|
||||
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);}
|
||||
|
||||
void SendTimeUpdate(Player* owner);
|
||||
void UpdateDuration(Player* owner, uint32 diff);
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
|
|||
data << pProto->ItemId;
|
||||
data << pProto->Class;
|
||||
data << pProto->SubClass;
|
||||
data << uint32(-1); // new 2.0.3, not exist in wdb cache?
|
||||
data << pProto->Unk0; // new 2.0.3, not exist in wdb cache?
|
||||
data << Name;
|
||||
data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
|
||||
data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
|
||||
|
|
@ -347,11 +347,14 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
|
|||
data << pProto->MaxCount;
|
||||
data << pProto->Stackable;
|
||||
data << pProto->ContainerSlots;
|
||||
for(int i = 0; i < 10; i++)
|
||||
data << pProto->StatsCount; // item stats count
|
||||
for(int i = 0; i < pProto->StatsCount; i++)
|
||||
{
|
||||
data << pProto->ItemStat[i].ItemStatType;
|
||||
data << pProto->ItemStat[i].ItemStatValue;
|
||||
}
|
||||
data << pProto->ScalingStatDistribution; // scaling stats distribution
|
||||
data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
data << pProto->Damage[i].DamageMin;
|
||||
|
|
@ -435,7 +438,8 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
|
|||
data << pProto->GemProperties;
|
||||
data << pProto->RequiredDisenchantSkill;
|
||||
data << pProto->ArmorDamageModifier;
|
||||
data << uint32(0); // added in 2.4.2.8209, duration (seconds)
|
||||
data << pProto->Duration; // added in 2.4.2.8209, duration (seconds)
|
||||
data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory
|
||||
SendPacket( &data );
|
||||
}
|
||||
else
|
||||
|
|
@ -843,6 +847,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/)
|
|||
if (_player->GetMoney() < price)
|
||||
return;
|
||||
|
||||
_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT, slot);
|
||||
_player->SetByteValue(PLAYER_BYTES_2, 2, slot);
|
||||
_player->ModifyMoney(-int32(price));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,10 +55,18 @@ enum ItemModType
|
|||
ITEM_MOD_CRIT_TAKEN_RATING = 34,
|
||||
ITEM_MOD_RESILIENCE_RATING = 35,
|
||||
ITEM_MOD_HASTE_RATING = 36,
|
||||
ITEM_MOD_EXPERTISE_RATING = 37
|
||||
ITEM_MOD_EXPERTISE_RATING = 37,
|
||||
ITEM_MOD_ATTACK_POWER = 38,
|
||||
ITEM_MOD_RANGED_ATTACK_POWER = 39,
|
||||
ITEM_MOD_FERAL_ATTACK_POWER = 40,
|
||||
ITEM_MOD_SPELL_HEALING_DONE = 41,
|
||||
ITEM_MOD_SPELL_DAMAGE_DONE = 42,
|
||||
ITEM_MOD_MANA_REGENERATION = 43,
|
||||
ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
|
||||
ITEM_MOD_SPELL_POWER = 45
|
||||
};
|
||||
|
||||
#define MAX_ITEM_MOD 38
|
||||
#define MAX_ITEM_MOD 46
|
||||
|
||||
enum ItemSpelltriggerType
|
||||
{
|
||||
|
|
@ -183,10 +191,11 @@ enum ItemClass
|
|||
ITEM_CLASS_QUEST = 12,
|
||||
ITEM_CLASS_KEY = 13,
|
||||
ITEM_CLASS_PERMANENT = 14,
|
||||
ITEM_CLASS_JUNK = 15
|
||||
ITEM_CLASS_MISC = 15,
|
||||
ITEM_CLASS_GLYPH = 16
|
||||
};
|
||||
|
||||
#define MAX_ITEM_CLASS 16
|
||||
#define MAX_ITEM_CLASS 17
|
||||
|
||||
enum ItemSubclassConsumable
|
||||
{
|
||||
|
|
@ -212,10 +221,11 @@ enum ItemSubclassContainer
|
|||
ITEM_SUBCLASS_ENGINEERING_CONTAINER = 4,
|
||||
ITEM_SUBCLASS_GEM_CONTAINER = 5,
|
||||
ITEM_SUBCLASS_MINING_CONTAINER = 6,
|
||||
ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7
|
||||
ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7,
|
||||
ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8
|
||||
};
|
||||
|
||||
#define MAX_ITEM_SUBCLASS_CONTAINER 8
|
||||
#define MAX_ITEM_SUBCLASS_CONTAINER 9
|
||||
|
||||
enum ItemSubclassWeapon
|
||||
{
|
||||
|
|
@ -270,10 +280,11 @@ enum ItemSubclassArmor
|
|||
ITEM_SUBCLASS_ARMOR_SHIELD = 6,
|
||||
ITEM_SUBCLASS_ARMOR_LIBRAM = 7,
|
||||
ITEM_SUBCLASS_ARMOR_IDOL = 8,
|
||||
ITEM_SUBCLASS_ARMOR_TOTEM = 9
|
||||
ITEM_SUBCLASS_ARMOR_TOTEM = 9,
|
||||
ITEM_SUBCLASS_ARMOR_SIGIL = 10
|
||||
};
|
||||
|
||||
#define MAX_ITEM_SUBCLASS_ARMOR 10
|
||||
#define MAX_ITEM_SUBCLASS_ARMOR 11
|
||||
|
||||
enum ItemSubclassReagent
|
||||
{
|
||||
|
|
@ -308,10 +319,12 @@ enum ItemSubclassTradeGoods
|
|||
ITEM_SUBCLASS_ELEMENTAL = 10,
|
||||
ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11,
|
||||
ITEM_SUBCLASS_ENCHANTING = 12,
|
||||
ITEM_SUBCLASS_MATERIAL = 13 // Added in 2.4.2
|
||||
ITEM_SUBCLASS_MATERIAL = 13,
|
||||
ITEM_SUBCLASS_ARMOR_ENCHANTMENT = 14,
|
||||
ITEM_SUBCLASS_WEAPON_ENCHANTMENT = 15
|
||||
};
|
||||
|
||||
#define MAX_ITEM_SUBCLASS_TRADE_GOODS 14
|
||||
#define MAX_ITEM_SUBCLASS_TRADE_GOODS 16
|
||||
|
||||
enum ItemSubclassGeneric
|
||||
{
|
||||
|
|
@ -421,7 +434,8 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] =
|
|||
MAX_ITEM_SUBCLASS_QUEST,
|
||||
MAX_ITEM_SUBCLASS_KEY,
|
||||
MAX_ITEM_SUBCLASS_PERMANENT,
|
||||
MAX_ITEM_SUBCLASS_JUNK
|
||||
MAX_ITEM_SUBCLASS_JUNK,
|
||||
MAX_ITEM_SUBCLASS_GLYPH
|
||||
};
|
||||
|
||||
inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemSubClass)
|
||||
|
|
@ -498,7 +512,10 @@ struct ItemPrototype
|
|||
uint32 MaxCount;
|
||||
uint32 Stackable;
|
||||
uint32 ContainerSlots;
|
||||
uint32 StatsCount;
|
||||
_ItemStat ItemStat[10];
|
||||
uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc
|
||||
uint32 ScalingStatValue; // mask for selecting column in ScalingStatValues.dbc
|
||||
_Damage Damage[5];
|
||||
uint32 Armor;
|
||||
uint32 HolyRes;
|
||||
|
|
@ -534,12 +551,13 @@ struct ItemPrototype
|
|||
uint32 GemProperties; // id from GemProperties.dbc
|
||||
uint32 RequiredDisenchantSkill;
|
||||
float ArmorDamageModifier;
|
||||
int32 Duration; // negative = realtime, positive = ingame time
|
||||
uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc
|
||||
uint32 ScriptId;
|
||||
uint32 DisenchantID;
|
||||
uint32 FoodType;
|
||||
uint32 MinMoneyLoot;
|
||||
uint32 MaxMoneyLoot;
|
||||
int32 Duration; // negative = realtime, positive = ingame time
|
||||
|
||||
// helpers
|
||||
bool CanChangeEquipStateInCombat() const
|
||||
|
|
@ -561,6 +579,46 @@ struct ItemPrototype
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetScalingStatValuesColumn() const
|
||||
{
|
||||
if(ScalingStatValue & 0x00000001) // stat mod
|
||||
return 0;
|
||||
if(ScalingStatValue & 0x00000002) // stat mod
|
||||
return 1;
|
||||
if(ScalingStatValue & 0x00000004) // stat mod
|
||||
return 2;
|
||||
if(ScalingStatValue & 0x00000008) // stat mod
|
||||
return 3;
|
||||
if(ScalingStatValue & 0x00000010) // stat mod
|
||||
return 4;
|
||||
if(ScalingStatValue & 0x00000020) // armor mod
|
||||
return 5;
|
||||
if(ScalingStatValue & 0x00000040) // armor mod
|
||||
return 6;
|
||||
if(ScalingStatValue & 0x00000080) // armor mod
|
||||
return 7;
|
||||
if(ScalingStatValue & 0x00000100) // armor mod
|
||||
return 8;
|
||||
if(ScalingStatValue & 0x00000200) // damage mod
|
||||
return 9;
|
||||
if(ScalingStatValue & 0x00000400) // damage mod
|
||||
return 10;
|
||||
if(ScalingStatValue & 0x00000800) // damage mod
|
||||
return 11;
|
||||
if(ScalingStatValue & 0x00001000) // damage mod
|
||||
return 12;
|
||||
if(ScalingStatValue & 0x00002000) // damage mod
|
||||
return 13;
|
||||
if(ScalingStatValue & 0x00004000) // damage mod
|
||||
return 14;
|
||||
if(ScalingStatValue & 0x00008000) // spell power
|
||||
return 15;
|
||||
if(ScalingStatValue & 0x00020000) // feral AP
|
||||
return 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct ItemLocale
|
||||
|
|
|
|||
|
|
@ -326,6 +326,8 @@ enum MangosStrings
|
|||
LANG_CREATURE_NOT_FOLLOW_YOU_NOW = 342,
|
||||
LANG_CREATURE_NON_TAMEABLE = 343,
|
||||
LANG_YOU_ALREADY_HAVE_PET = 344,
|
||||
LANG_CUSTOMIZE_PLAYER = 345,
|
||||
LANG_CUSTOMIZE_PLAYER_GUID = 346,
|
||||
// Room for more level 2 345-399 not used
|
||||
|
||||
// level 3 chat
|
||||
|
|
@ -641,11 +643,30 @@ enum MangosStrings
|
|||
LANG_BG_QUEUE_ANNOUNCE_SELF = 711,
|
||||
LANG_BG_QUEUE_ANNOUNCE_WORLD = 712,
|
||||
|
||||
|
||||
LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713,
|
||||
LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714,
|
||||
// LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714, an opcode exists for this
|
||||
LANG_YOUR_BG_LEVEL_REQ_ERROR = 715,
|
||||
LANG_YOUR_ARENA_TEAM_FULL = 716,
|
||||
// Room for BG/ARENA 717-799 not used
|
||||
// LANG_YOUR_ARENA_TEAM_FULL = 716, an opcode exists for this
|
||||
|
||||
LANG_BG_GROUP_TOO_LARGE = 1122, // "Your group is too large for this battleground. Please regroup to join."
|
||||
LANG_ARENA_GROUP_TOO_LARGE = 1123, // "Your group is too large for this arena. Please regroup to join."
|
||||
LANG_ARENA_YOUR_TEAM_ONLY = 1124, // "Your group has members not in your arena team. Please regroup to join."
|
||||
LANG_ARENA_NOT_ENOUGH_PLAYERS = 1125, // "Your group does not have enough players to join this match."
|
||||
LANG_ARENA_GOLD_WINS = 1126, // "The Gold Team wins!"
|
||||
LANG_ARENA_GREEN_WINS = 1127, // "The Green Team wins!"
|
||||
LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 1128, // The battleground will end soon, because there aren't enough players. Get more ppl or win already!
|
||||
LANG_BG_GROUP_OFFLINE_MEMBER = 1129, // "Your group has an offline member. Please remove him before joining."
|
||||
LANG_BG_GROUP_MIXED_FACTION = 1130, // "Your group has players from the opposing faction. You can't join the battleground as a group."
|
||||
LANG_BG_GROUP_MIXED_LEVELS = 1131, // "Your group has players from different battleground brakets. You can't join as group."
|
||||
LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 1132, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group."
|
||||
LANG_BG_GROUP_MEMBER_DESERTER = 1133, // "Someone in your party is Deserter. You can't join as group."
|
||||
LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 1134, // "Someone in your party is already in three battleground queues. You cannot join as group."
|
||||
|
||||
LANG_CANNOT_TELE_TO_BG = 1135, // "You cannot teleport to a battleground or arena map."
|
||||
LANG_CANNOT_SUMMON_TO_BG = 1136, // "You cannot summon players to a battleground or arena map."
|
||||
LANG_CANNOT_GO_TO_BG_GM = 1137, // "You must be in GM mode to teleport to a player in a battleground."
|
||||
LANG_CANNOT_GO_TO_BG_FROM_BG = 1138, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first."
|
||||
|
||||
// in game strings
|
||||
// = 800, not used
|
||||
|
|
|
|||
|
|
@ -351,7 +351,14 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
|
|||
|
||||
Map* pMap = m_session->GetPlayer()->GetMap();
|
||||
|
||||
if(pMap->Instanceable())
|
||||
if(pMap->IsBattleGroundOrArena())
|
||||
{
|
||||
// cannot summon to bg
|
||||
PSendSysMessage(LANG_CANNOT_SUMMON_TO_BG,chr->GetName());
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
else if(pMap->IsDungeon())
|
||||
{
|
||||
Map* cMap = chr->GetMap();
|
||||
if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() )
|
||||
|
|
@ -435,6 +442,28 @@ bool ChatHandler::HandleGonameCommand(const char* args)
|
|||
Player *chr = objmgr.GetPlayer(name.c_str());
|
||||
if (chr)
|
||||
{
|
||||
Map* cMap = chr->GetMap();
|
||||
if(cMap->IsBattleGroundOrArena())
|
||||
{
|
||||
// only allow if gm mode is on
|
||||
if (!_player->isGameMaster())
|
||||
{
|
||||
PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chr->GetName());
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
// if already in a bg, don't let port to other
|
||||
else if (_player->GetBattleGroundId())
|
||||
{
|
||||
PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chr->GetName());
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
// all's well, set bg id
|
||||
// when porting out from the bg, it will be reset to 0
|
||||
_player->SetBattleGroundId(chr->GetBattleGroundId());
|
||||
}
|
||||
else if(cMap->IsDungeon())
|
||||
Map* cMap = chr->GetMap();
|
||||
if(cMap->Instanceable())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -949,7 +949,7 @@ bool ChatHandler::HandleNpcDeleteCommand(const char* args)
|
|||
else
|
||||
unit = getSelectedCreature();
|
||||
|
||||
if(!unit || unit->isPet() || unit->isTotem())
|
||||
if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle())
|
||||
{
|
||||
SendSysMessage(LANG_SELECT_CREATURE);
|
||||
SetSentErrorMessage(true);
|
||||
|
|
@ -1062,8 +1062,8 @@ bool ChatHandler::HandleTurnObjectCommand(const char* args)
|
|||
obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o);
|
||||
|
||||
obj->SetFloatValue(GAMEOBJECT_FACING, o);
|
||||
obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2);
|
||||
obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3);
|
||||
obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2);
|
||||
obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3);
|
||||
|
||||
map->Add(obj);
|
||||
|
||||
|
|
@ -3137,7 +3137,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
|
|||
}
|
||||
}while(result->NextRow());
|
||||
// set "wpguid" column to "empty" - no visual waypoint spawned
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'");
|
||||
WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'");
|
||||
|
||||
if( hasError )
|
||||
{
|
||||
|
|
@ -3356,6 +3356,59 @@ bool ChatHandler::HandleRenameCommand(const char* args)
|
|||
return true;
|
||||
}
|
||||
|
||||
// customize characters
|
||||
bool ChatHandler::HandleCustomizeCommand(const char* args)
|
||||
{
|
||||
Player* target = NULL;
|
||||
uint64 targetGUID = 0;
|
||||
std::string oldname;
|
||||
|
||||
char* px = strtok((char*)args, " ");
|
||||
|
||||
if(px)
|
||||
{
|
||||
oldname = px;
|
||||
|
||||
if(!normalizePlayerName(oldname))
|
||||
{
|
||||
SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
target = objmgr.GetPlayer(oldname.c_str());
|
||||
|
||||
if (!target)
|
||||
targetGUID = objmgr.GetPlayerGUIDByName(oldname);
|
||||
}
|
||||
|
||||
if(!target && !targetGUID)
|
||||
{
|
||||
target = getSelectedPlayer();
|
||||
}
|
||||
|
||||
if(!target && !targetGUID)
|
||||
{
|
||||
SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||||
SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(target)
|
||||
{
|
||||
PSendSysMessage(LANG_CUSTOMIZE_PLAYER, target->GetName());
|
||||
target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE);
|
||||
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow());
|
||||
}
|
||||
else
|
||||
{
|
||||
PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID));
|
||||
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//spawn go
|
||||
bool ChatHandler::HandleGameObjectCommand(const char* args)
|
||||
{
|
||||
|
|
@ -4109,17 +4162,20 @@ bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
|
|||
player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE);
|
||||
pet->Relocate (x,y,z,M_PI-player->GetOrientation ());
|
||||
|
||||
// set pet to defensive mode by default (some classes can't control contolled pets in fact).
|
||||
// set pet to defensive mode by default (some classes can't control controlled pets in fact).
|
||||
pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
|
||||
|
||||
// calculate proper level
|
||||
uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel();
|
||||
|
||||
// prepare visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1);
|
||||
|
||||
// add to world
|
||||
pet->GetMap()->Add((Creature*)pet);
|
||||
|
||||
// visual effect for levelup
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
|
||||
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
|
||||
|
||||
// caster have pet now
|
||||
player->SetPet(pet);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "Config/ConfigEnv.h"
|
||||
#include "Util.h"
|
||||
#include "ItemEnchantmentMgr.h"
|
||||
#include "BattleGroundMgr.h"
|
||||
#include "InstanceSaveMgr.h"
|
||||
#include "InstanceData.h"
|
||||
|
||||
|
|
@ -294,6 +295,15 @@ bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*)
|
||||
{
|
||||
sLog.outString( "Re-Loading Loot Tables... (`milling_loot_template`)" );
|
||||
LoadLootTemplates_Milling();
|
||||
LootTemplates_Milling.CheckLootRefs();
|
||||
SendGlobalSysMessage("DB table `milling_loot_template` reloaded.");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*)
|
||||
{
|
||||
sLog.outString( "Re-Loading Loot Tables... (`pickpocketing_loot_template`)" );
|
||||
|
|
@ -3805,8 +3815,8 @@ bool ChatHandler::HandleLevelUpCommand(const char* args)
|
|||
int32 newlevel = oldlevel + addlevel;
|
||||
if(newlevel < 1)
|
||||
newlevel = 1;
|
||||
if(newlevel > 255) // hardcoded maximum level
|
||||
newlevel = 255;
|
||||
if(newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level
|
||||
newlevel = STRONG_MAX_LEVEL;
|
||||
|
||||
if(chr)
|
||||
{
|
||||
|
|
@ -4349,7 +4359,7 @@ static bool HandleResetStatsOrLevelHelper(Player* player)
|
|||
|
||||
// set UNIT_FIELD_BYTES_1 to init state but preserve m_form value
|
||||
player->SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield);
|
||||
player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5 );
|
||||
player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP );
|
||||
player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form);
|
||||
|
||||
player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
|
|
@ -4394,6 +4404,7 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
|
|||
player->SetLevel(1);
|
||||
player->InitStatsForLevel(true);
|
||||
player->InitTaxiNodesForLevel();
|
||||
player->InitGlyphsForLevel();
|
||||
player->InitTalentForLevel();
|
||||
player->SetUInt32Value(PLAYER_XP,0);
|
||||
|
||||
|
|
@ -4437,6 +4448,7 @@ bool ChatHandler::HandleResetStatsCommand(const char * args)
|
|||
|
||||
player->InitStatsForLevel(true);
|
||||
player->InitTaxiNodesForLevel();
|
||||
player->InitGlyphsForLevel();
|
||||
player->InitTalentForLevel();
|
||||
|
||||
return true;
|
||||
|
|
@ -4564,7 +4576,7 @@ bool ChatHandler::HandleResetAllCommand(const char * args)
|
|||
return false;
|
||||
}
|
||||
|
||||
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u'",atLogin);
|
||||
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE (at_login & '%u') = '0'",atLogin,atLogin);
|
||||
HashMapHolder<Player>::MapType const& plist = ObjectAccessor::Instance().GetPlayers();
|
||||
for(HashMapHolder<Player>::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr)
|
||||
itr->second->SetAtLoginFlag(atLogin);
|
||||
|
|
@ -6479,6 +6491,12 @@ bool ChatHandler::HandleSendMessageCommand(const char* args)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/)
|
||||
{
|
||||
sBattleGroundMgr.DistributeArenaPoints();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleModifyGenderCommand(const char *args)
|
||||
{
|
||||
if(!*args)
|
||||
|
|
@ -6493,30 +6511,27 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args)
|
|||
return false;
|
||||
}
|
||||
|
||||
PlayerInfo const* info = objmgr.GetPlayerInfo(player->getRace(), player->getClass());
|
||||
if(!info)
|
||||
return false;
|
||||
|
||||
char const* gender_str = (char*)args;
|
||||
int gender_len = strlen(gender_str);
|
||||
|
||||
uint32 displayId = player->GetNativeDisplayId();
|
||||
char const* gender_full = NULL;
|
||||
uint32 new_displayId = displayId;
|
||||
Gender gender;
|
||||
|
||||
if(!strncmp(gender_str,"male",gender_len)) // MALE
|
||||
if(!strncmp(gender_str, "male", gender_len)) // MALE
|
||||
{
|
||||
if(player->getGender() == GENDER_MALE)
|
||||
return true;
|
||||
|
||||
gender_full = "male";
|
||||
new_displayId = player->getRace() == RACE_BLOODELF ? displayId+1 : displayId-1;
|
||||
gender = GENDER_MALE;
|
||||
}
|
||||
else if (!strncmp(gender_str,"female",gender_len)) // FEMALE
|
||||
else if (!strncmp(gender_str, "female", gender_len)) // FEMALE
|
||||
{
|
||||
if(player->getGender() == GENDER_FEMALE)
|
||||
return true;
|
||||
|
||||
gender_full = "female";
|
||||
new_displayId = player->getRace() == RACE_BLOODELF ? displayId-1 : displayId+1;
|
||||
gender = GENDER_FEMALE;
|
||||
}
|
||||
else
|
||||
|
|
@ -6528,13 +6543,18 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args)
|
|||
|
||||
// Set gender
|
||||
player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender);
|
||||
player->SetByteValue(PLAYER_BYTES_3, 0, gender);
|
||||
|
||||
// Change display ID
|
||||
player->SetDisplayId(new_displayId);
|
||||
player->SetNativeDisplayId(new_displayId);
|
||||
player->SetDisplayId(gender ? info->displayId_f : info->displayId_m);
|
||||
player->SetNativeDisplayId(gender ? info->displayId_f : info->displayId_m);
|
||||
|
||||
char const* gender_full = gender ? "female" : "male";
|
||||
|
||||
PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(), gender_full);
|
||||
|
||||
PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(),gender_full);
|
||||
if (needReportToTarget(player))
|
||||
ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full,GetName());
|
||||
ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetName());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data )
|
|||
--loot->unlootedCount;
|
||||
|
||||
player->SendNewItem(newitem, uint32(item->count), false, false, true);
|
||||
player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count);
|
||||
}
|
||||
else
|
||||
player->SendEquipError( msg, NULL, NULL );
|
||||
|
|
@ -314,7 +315,7 @@ void WorldSession::DoLootRelease( uint64 lguid )
|
|||
int32 ReqValue = 175;
|
||||
LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId);
|
||||
if(lockInfo)
|
||||
ReqValue = lockInfo->requiredminingskill;
|
||||
ReqValue = lockInfo->Skill[0];
|
||||
float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25);
|
||||
double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses));
|
||||
if(roll_chance_f(100*chance+skill))
|
||||
|
|
@ -483,6 +484,7 @@ void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data )
|
|||
// not move item from loot to target inventory
|
||||
Item * newitem = target->StoreNewItem( dest, item.itemid, true, item.randomPropertyId );
|
||||
target->SendNewItem(newitem, uint32(item.count), false, false, true );
|
||||
target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count);
|
||||
|
||||
// mark as looted
|
||||
item.count=0;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenc
|
|||
LootStore LootTemplates_Fishing( "fishing_loot_template", "area id");
|
||||
LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry");
|
||||
LootStore LootTemplates_Item( "item_loot_template", "item entry");
|
||||
LootStore LootTemplates_Milling( "milling_loot_template", "item entry");
|
||||
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid");
|
||||
LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry");
|
||||
LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id");
|
||||
|
|
@ -1135,6 +1136,21 @@ void LoadLootTemplates_Item()
|
|||
LootTemplates_Item.ReportUnusedIds(ids_set);
|
||||
}
|
||||
|
||||
void LoadLootTemplates_Milling()
|
||||
{
|
||||
LootIdSet ids_set;
|
||||
LootTemplates_Milling.LoadAndCollectLootIds(ids_set);
|
||||
|
||||
// remove real entries and check existence loot
|
||||
for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i )
|
||||
if(ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i))
|
||||
if(ids_set.count(proto->ItemId))
|
||||
ids_set.erase(proto->ItemId);
|
||||
|
||||
// output error for any still listed (not referenced from appropriate table) ids
|
||||
LootTemplates_Milling.ReportUnusedIds(ids_set);
|
||||
}
|
||||
|
||||
void LoadLootTemplates_Pickpocketing()
|
||||
{
|
||||
LootIdSet ids_set, ids_setUsed;
|
||||
|
|
@ -1227,6 +1243,7 @@ void LoadLootTemplates_Reference()
|
|||
LootTemplates_Fishing.CheckLootRefs(&ids_set);
|
||||
LootTemplates_Gameobject.CheckLootRefs(&ids_set);
|
||||
LootTemplates_Item.CheckLootRefs(&ids_set);
|
||||
LootTemplates_Milling.CheckLootRefs(&ids_set);
|
||||
LootTemplates_Pickpocketing.CheckLootRefs(&ids_set);
|
||||
LootTemplates_Skinning.CheckLootRefs(&ids_set);
|
||||
LootTemplates_Disenchant.CheckLootRefs(&ids_set);
|
||||
|
|
|
|||
|
|
@ -295,6 +295,7 @@ extern LootStore LootTemplates_Creature;
|
|||
extern LootStore LootTemplates_Fishing;
|
||||
extern LootStore LootTemplates_Gameobject;
|
||||
extern LootStore LootTemplates_Item;
|
||||
extern LootStore LootTemplates_Milling;
|
||||
extern LootStore LootTemplates_Pickpocketing;
|
||||
extern LootStore LootTemplates_Skinning;
|
||||
extern LootStore LootTemplates_Disenchant;
|
||||
|
|
@ -305,6 +306,7 @@ void LoadLootTemplates_Creature();
|
|||
void LoadLootTemplates_Fishing();
|
||||
void LoadLootTemplates_Gameobject();
|
||||
void LoadLootTemplates_Item();
|
||||
void LoadLootTemplates_Milling();
|
||||
void LoadLootTemplates_Pickpocketing();
|
||||
void LoadLootTemplates_Skinning();
|
||||
void LoadLootTemplates_Disenchant();
|
||||
|
|
@ -318,6 +320,7 @@ inline void LoadLootTables()
|
|||
LoadLootTemplates_Fishing();
|
||||
LoadLootTemplates_Gameobject();
|
||||
LoadLootTemplates_Item();
|
||||
LoadLootTemplates_Milling();
|
||||
LoadLootTemplates_Pickpocketing();
|
||||
LoadLootTemplates_Skinning();
|
||||
LoadLootTemplates_Disenchant();
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ void WorldSession::HandleReturnToSender(WorldPacket & recv_data )
|
|||
pl->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, 0);
|
||||
}
|
||||
|
||||
void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, std::string subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId )
|
||||
void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, const std::string& subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId )
|
||||
{
|
||||
if(messageType != MAIL_NORMAL) // return only to players
|
||||
{
|
||||
|
|
@ -591,7 +591,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data )
|
|||
data << (uint32) (*itr)->mailTemplateId; // mail template (MailTemplate.dbc)
|
||||
data << (*itr)->subject; // Subject string - once 00, when mail type = 3
|
||||
|
||||
data << (uint8) item_count;
|
||||
data << (uint8) item_count; // client limit is 0x10
|
||||
|
||||
for(uint8 i = 0; i < item_count; ++i)
|
||||
{
|
||||
|
|
@ -602,7 +602,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data )
|
|||
data << (uint32) (item ? item->GetGUIDLow() : 0);
|
||||
// entry
|
||||
data << (uint32) (item ? item->GetEntry() : 0);
|
||||
for(uint8 j = 0; j < 6; ++j)
|
||||
for(uint8 j = 0; j < 7; ++j)
|
||||
{
|
||||
// unsure
|
||||
data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0);
|
||||
|
|
@ -616,13 +616,15 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data )
|
|||
// unk
|
||||
data << (uint32) (item ? item->GetItemSuffixFactor() : 0);
|
||||
// stack count
|
||||
data << (uint8) (item ? item->GetCount() : 0);
|
||||
data << (uint32) (item ? item->GetCount() : 0);
|
||||
// charges
|
||||
data << (uint32) (item ? item->GetSpellCharges() : 0);
|
||||
// durability
|
||||
data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0);
|
||||
// durability
|
||||
data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0);
|
||||
// unknown wotlk
|
||||
data << (uint8) 0;
|
||||
}
|
||||
|
||||
mails_count += 1;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ noinst_LIBRARIES = libmangosgame.a
|
|||
libmangosgame_a_SOURCES = \
|
||||
AccountMgr.cpp \
|
||||
AccountMgr.h \
|
||||
AchievementMgr.h \
|
||||
AchievementMgr.cpp \
|
||||
AddonHandler.cpp \
|
||||
AddonHandler.h \
|
||||
AggressorAI.cpp \
|
||||
|
|
@ -63,6 +65,9 @@ libmangosgame_a_SOURCES = \
|
|||
BattleGroundHandler.cpp \
|
||||
BattleGroundMgr.cpp \
|
||||
BattleGroundMgr.h \
|
||||
Calendar.cpp \
|
||||
Calendar.h \
|
||||
CalendarHandler.cpp \
|
||||
Cell.h \
|
||||
CellImpl.h \
|
||||
Channel.cpp \
|
||||
|
|
@ -246,6 +251,8 @@ libmangosgame_a_SOURCES = \
|
|||
UpdateData.h \
|
||||
UpdateFields.h \
|
||||
UpdateMask.h \
|
||||
Vehicle.cpp \
|
||||
Vehicle.h \
|
||||
VoiceChatHandler.cpp \
|
||||
WaypointManager.cpp \
|
||||
WaypointManager.h \
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
#define MAX_GRID_LOAD_TIME 50
|
||||
|
||||
// magic *.map header
|
||||
const char MAP_MAGIC[] = "MAP_2.00";
|
||||
const char MAP_MAGIC[] = "MAP_2.01";
|
||||
|
||||
GridState* si_GridStates[MAX_GRID_STATE];
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ template<>
|
|||
void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell)
|
||||
{
|
||||
// add to world object registry in grid
|
||||
if(obj->isPet())
|
||||
if(obj->isPet() || obj->isVehicle())
|
||||
{
|
||||
(*grid)(cell.CellX(), cell.CellY()).AddWorldObject<Creature>(obj, obj->GetGUID());
|
||||
obj->SetCurrentCell(cell);
|
||||
|
|
@ -298,7 +298,7 @@ template<>
|
|||
void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell)
|
||||
{
|
||||
// remove from world object registry in grid
|
||||
if(obj->isPet())
|
||||
if(obj->isPet() || obj->isVehicle())
|
||||
{
|
||||
(*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<Creature>(obj, obj->GetGUID());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,6 +221,17 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
|
|||
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
|
||||
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
|
||||
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
|
||||
bool GetEntrancePos(int32 &mapid, float &x, float &y)
|
||||
{
|
||||
if(!i_mapEntry)
|
||||
return false;
|
||||
if(i_mapEntry->entrance_map < 0)
|
||||
return false;
|
||||
mapid = i_mapEntry->entrance_map;
|
||||
x = i_mapEntry->entrance_x;
|
||||
y = i_mapEntry->entrance_y;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AddObjectToRemoveList(WorldObject *obj);
|
||||
void DoDelayedMovesAndRemoves();
|
||||
|
|
|
|||
|
|
@ -141,7 +141,17 @@ Map* MapInstanced::GetInstance(const WorldObject* obj)
|
|||
uint32 NewInstanceId = 0; // instanceId of the resulting map
|
||||
Player* player = (Player*)obj;
|
||||
|
||||
// TODO: battlegrounds and arenas
|
||||
if(IsBattleGroundOrArena())
|
||||
{
|
||||
// instantiate or find existing bg map for player
|
||||
// the instance id is set in battlegroundid
|
||||
NewInstanceId = player->GetBattleGroundId();
|
||||
assert(NewInstanceId);
|
||||
map = _FindMap(NewInstanceId);
|
||||
if(!map)
|
||||
map = CreateBattleGround(NewInstanceId);
|
||||
return map;
|
||||
}
|
||||
|
||||
InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty());
|
||||
InstanceSave *pSave = pBind ? pBind->save : NULL;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ MapManager::_GetBaseMap(uint32 id)
|
|||
Guard guard(*this);
|
||||
|
||||
const MapEntry* entry = sMapStore.LookupEntry(id);
|
||||
if (entry && entry->IsDungeon())
|
||||
if (entry && entry->Instanceable())
|
||||
{
|
||||
m = new MapInstanced(id, i_gridCleanUpDelay);
|
||||
}
|
||||
|
|
@ -173,7 +173,8 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player)
|
|||
//The player has a heroic mode and tries to enter into instance which has no a heroic mode
|
||||
if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC)
|
||||
{
|
||||
player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY2); //Send aborted message
|
||||
//Send aborted message
|
||||
player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -278,7 +279,8 @@ bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y)
|
|||
bool MapManager::IsValidMAP(uint32 mapid)
|
||||
{
|
||||
MapEntry const* mEntry = sMapStore.LookupEntry(mapid);
|
||||
return mEntry && (!mEntry->Instanceable() || objmgr.GetInstanceTemplate(mapid));
|
||||
return mEntry && (!mEntry->IsDungeon() || objmgr.GetInstanceTemplate(mapid));
|
||||
// TODO: add check for battleground template
|
||||
}
|
||||
|
||||
void MapManager::LoadGrid(int mapid, float x, float y, const WorldObject* obj, bool no_unload)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "SpellAuras.h"
|
||||
#include "Pet.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "Tools.h"
|
||||
|
||||
void WorldSession::HandleRepopRequestOpcode( WorldPacket & /*recv_data*/ )
|
||||
{
|
||||
|
|
@ -80,7 +81,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data )
|
|||
std::string player_name, guild_name;
|
||||
|
||||
recv_data >> level_min; // maximal player level, default 0
|
||||
recv_data >> level_max; // minimal player level, default 100
|
||||
recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL)
|
||||
recv_data >> player_name; // player name, case sensitive...
|
||||
|
||||
// recheck
|
||||
|
|
@ -145,8 +146,8 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data )
|
|||
|
||||
// client send in case not set max level value 100 but mangos support 255 max level,
|
||||
// update it to show GMs with characters after 100 level
|
||||
if(level_max >= 100)
|
||||
level_max = 255;
|
||||
if(level_max >= MAX_LEVEL)
|
||||
level_max = STRONG_MAX_LEVEL;
|
||||
|
||||
uint32 team = _player->GetTeam();
|
||||
uint32 security = GetSecurity();
|
||||
|
|
@ -306,7 +307,7 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ )
|
|||
data.append(GetPlayer()->GetPackGUID());
|
||||
data << (uint32)2;
|
||||
SendPacket( &data );
|
||||
GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
|
||||
GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||
}
|
||||
|
||||
WorldPacket data( SMSG_LOGOUT_RESPONSE, 5 );
|
||||
|
|
@ -343,7 +344,7 @@ void WorldSession::HandleLogoutCancelOpcode( WorldPacket & /*recv_data*/ )
|
|||
GetPlayer()->SetStandState(PLAYER_STATE_NONE);
|
||||
|
||||
//! DISABLE_ROTATE
|
||||
GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
|
||||
GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||
}
|
||||
|
||||
sLog.outDebug( "WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message" );
|
||||
|
|
@ -357,10 +358,12 @@ void WorldSession::HandleTogglePvP( WorldPacket & recv_data )
|
|||
bool newPvPStatus;
|
||||
recv_data >> newPvPStatus;
|
||||
GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus);
|
||||
GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP);
|
||||
GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER);
|
||||
}
|
||||
|
||||
if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP))
|
||||
|
|
@ -866,7 +869,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
|
|||
if(missingItem)
|
||||
SendAreaTriggerMessage(GetMangosString(LANG_LEVEL_MINREQUIRED_AND_ITEM), at->requiredLevel, objmgr.GetItemPrototype(missingItem)->Name1);
|
||||
else if(missingKey)
|
||||
GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY2);
|
||||
GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC);
|
||||
else if(missingQuest)
|
||||
SendAreaTriggerMessage(at->requiredFailedText.c_str());
|
||||
else if(missingLevel)
|
||||
|
|
@ -878,16 +881,96 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
|
|||
GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT);
|
||||
}
|
||||
|
||||
void WorldSession::HandleUpdateAccountData(WorldPacket &/*recv_data*/)
|
||||
void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4+4+4);
|
||||
|
||||
uint32 type, timestamp, decompressedSize;
|
||||
recv_data >> type >> timestamp >> decompressedSize;
|
||||
|
||||
sLog.outDebug("UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize);
|
||||
|
||||
if(type > NUM_ACCOUNT_DATA_TYPES)
|
||||
return;
|
||||
|
||||
if(decompressedSize == 0) // erase
|
||||
{
|
||||
SetAccountData(type, timestamp, "");
|
||||
|
||||
WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4);
|
||||
data << uint32(type);
|
||||
data << uint32(0);
|
||||
SendPacket(&data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(decompressedSize > 0xFFFF)
|
||||
{
|
||||
sLog.outError("UAD: Account data packet too big, size %u", decompressedSize);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer dest;
|
||||
dest.resize(decompressedSize);
|
||||
|
||||
uLongf realSize = decompressedSize;
|
||||
if(uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK)
|
||||
{
|
||||
sLog.outError("UAD: Failed to decompress account data");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string adata;
|
||||
dest >> adata;
|
||||
|
||||
SetAccountData(type, timestamp, adata);
|
||||
|
||||
WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4);
|
||||
data << uint32(type);
|
||||
data << uint32(0);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleRequestAccountData(WorldPacket& /*recv_data*/)
|
||||
void WorldSession::HandleRequestAccountData(WorldPacket& recv_data)
|
||||
{
|
||||
sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA");
|
||||
//recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 4);
|
||||
|
||||
uint32 type;
|
||||
recv_data >> type;
|
||||
|
||||
sLog.outDebug("RAD: type %u", type);
|
||||
|
||||
if(type > NUM_ACCOUNT_DATA_TYPES)
|
||||
return;
|
||||
|
||||
AccountData *adata = GetAccountData(type);
|
||||
|
||||
uint32 size = adata->Data.size();
|
||||
|
||||
ByteBuffer dest;
|
||||
dest.resize(size);
|
||||
|
||||
uLongf destSize = size;
|
||||
if(compress(const_cast<uint8*>(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK)
|
||||
{
|
||||
sLog.outDebug("RAD: Failed to compress account data");
|
||||
return;
|
||||
}
|
||||
|
||||
dest.resize(destSize);
|
||||
|
||||
WorldPacket data (SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize);
|
||||
data << uint64(_player->GetGUID()); // player guid
|
||||
data << uint32(type); // type (0-7)
|
||||
data << uint32(adata->Time); // unix time
|
||||
data << uint32(size); // decompressed length
|
||||
data.append(dest); // compressed data
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data)
|
||||
|
|
@ -1406,11 +1489,11 @@ void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data )
|
|||
GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title);
|
||||
}
|
||||
|
||||
void WorldSession::HandleAllowMoveAckOpcode( WorldPacket & recv_data )
|
||||
void WorldSession::HandleTimeSyncResp( WorldPacket & recv_data )
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data, 4+4);
|
||||
|
||||
sLog.outDebug("CMSG_ALLOW_MOVE_ACK");
|
||||
sLog.outDebug("CMSG_TIME_SYNC_RESP");
|
||||
|
||||
uint32 counter, time_;
|
||||
recv_data >> counter >> time_;
|
||||
|
|
@ -1480,26 +1563,6 @@ void WorldSession::HandleDungeonDifficultyOpcode( WorldPacket & recv_data )
|
|||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleNewUnknownOpcode( WorldPacket & recv_data )
|
||||
{
|
||||
sLog.outDebug("New Unknown Opcode %u", recv_data.GetOpcode());
|
||||
recv_data.hexlike();
|
||||
/*
|
||||
New Unknown Opcode 837
|
||||
STORAGE_SIZE: 60
|
||||
02 00 00 00 00 00 00 00 | 00 00 00 00 01 20 00 00
|
||||
89 EB 33 01 71 5C 24 C4 | 15 03 35 45 74 47 8B 42
|
||||
BA B8 1B 40 00 00 00 00 | 00 00 00 00 77 66 42 BF
|
||||
23 91 26 3F 00 00 60 41 | 00 00 00 00
|
||||
|
||||
New Unknown Opcode 837
|
||||
STORAGE_SIZE: 44
|
||||
02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00
|
||||
7B 80 34 01 84 EA 2B C4 | 5F A1 36 45 C9 39 1C 42
|
||||
BA B8 1B 40 CE 06 00 00 | 00 00 80 3F
|
||||
*/
|
||||
}
|
||||
|
||||
void WorldSession::HandleDismountOpcode( WorldPacket & /*recv_data*/ )
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA");
|
||||
|
|
@ -1566,3 +1629,32 @@ void WorldSession::HandleSetTaxiBenchmarkOpcode( WorldPacket & recv_data )
|
|||
|
||||
sLog.outDebug("Client used \"/timetest %d\" command", mode);
|
||||
}
|
||||
|
||||
void WorldSession::HandleSpellClick( WorldPacket & recv_data )
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data, 8);
|
||||
|
||||
uint64 guid;
|
||||
recv_data >> guid;
|
||||
|
||||
Vehicle *vehicle = ObjectAccessor::GetVehicle(guid);
|
||||
|
||||
if(!vehicle)
|
||||
return;
|
||||
|
||||
_player->EnterVehicle(vehicle);
|
||||
}
|
||||
|
||||
void WorldSession::HandleInspectAchievements( WorldPacket & recv_data )
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data, 1);
|
||||
uint64 guid;
|
||||
if(!readGUID(recv_data, guid))
|
||||
return;
|
||||
|
||||
Player *player = objmgr.GetPlayer(guid);
|
||||
if(!player)
|
||||
return;
|
||||
|
||||
player->GetAchievementMgr().SendRespondInspectAchievements(_player);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,8 +150,17 @@ MotionMaster::MoveTargetedHome()
|
|||
}
|
||||
else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID())
|
||||
{
|
||||
sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home",
|
||||
DEBUG_LOG("Pet or controlled creature (Entry: %u GUID: %u) targeting home",
|
||||
i_owner->GetEntry(), i_owner->GetGUIDLow() );
|
||||
Unit *target = ((Creature*)i_owner)->GetCharmerOrOwner();
|
||||
if(target)
|
||||
{
|
||||
i_owner->addUnitState(UNIT_STAT_FOLLOW);
|
||||
DEBUG_LOG("Following %s (GUID: %u)",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature",
|
||||
target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() );
|
||||
Mutate(new TargetedMovementGenerator<Creature>(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -130,22 +130,28 @@ void WorldSession::HandleMoveWorldportAckOpcode()
|
|||
_player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
|
||||
|
||||
// battleground state prepare
|
||||
if(_player->InBattleGround())
|
||||
// only add to bg group and object, if the player was invited (else he entered through command)
|
||||
if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId()))
|
||||
{
|
||||
BattleGround *bg = _player->GetBattleGround();
|
||||
if(bg)
|
||||
{
|
||||
bg->AddPlayer(_player);
|
||||
if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg
|
||||
{
|
||||
if(!bg->GetBgRaid(_player->GetTeam())) // first player joined
|
||||
// get the team this way, because arenas might 'override' the teams.
|
||||
uint32 team = bg->GetPlayerTeam(_player->GetGUID());
|
||||
if(!team)
|
||||
team = _player->GetTeam();
|
||||
if(!bg->GetBgRaid(team)) // first player joined
|
||||
{
|
||||
Group *group = new Group;
|
||||
bg->SetBgRaid(_player->GetTeam(), group);
|
||||
bg->SetBgRaid(team, group);
|
||||
group->Create(_player->GetGUIDLow(), _player->GetName());
|
||||
}
|
||||
else // raid already exist
|
||||
{
|
||||
bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName());
|
||||
bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -170,70 +176,15 @@ void WorldSession::HandleMoveWorldportAckOpcode()
|
|||
|
||||
void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4);
|
||||
uint32 opcode = recv_data.GetOpcode();
|
||||
sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
|
||||
|
||||
if(GetPlayer()->GetDontMove())
|
||||
return;
|
||||
|
||||
/* extract packet */
|
||||
MovementInfo movementInfo;
|
||||
uint32 MovementFlags;
|
||||
|
||||
recv_data >> MovementFlags;
|
||||
recv_data >> movementInfo.unk1;
|
||||
recv_data >> movementInfo.time;
|
||||
recv_data >> movementInfo.x;
|
||||
recv_data >> movementInfo.y;
|
||||
recv_data >> movementInfo.z;
|
||||
recv_data >> movementInfo.o;
|
||||
|
||||
//Save movement flags
|
||||
_player->SetUnitMovementFlags(MovementFlags);
|
||||
|
||||
if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4);
|
||||
|
||||
recv_data >> movementInfo.t_guid;
|
||||
recv_data >> movementInfo.t_x;
|
||||
recv_data >> movementInfo.t_y;
|
||||
recv_data >> movementInfo.t_z;
|
||||
recv_data >> movementInfo.t_o;
|
||||
recv_data >> movementInfo.t_time;
|
||||
}
|
||||
|
||||
if(MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
|
||||
|
||||
recv_data >> movementInfo.s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up
|
||||
}
|
||||
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
|
||||
|
||||
recv_data >> movementInfo.fallTime; // duration of last jump (when in jump duration from jump begin to now)
|
||||
|
||||
if(MovementFlags & MOVEMENTFLAG_JUMPING)
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4);
|
||||
|
||||
recv_data >> movementInfo.j_unk; // constant, but different when jumping in water and on land?
|
||||
recv_data >> movementInfo.j_sinAngle; // sin of angle between orientation0 and players orientation
|
||||
recv_data >> movementInfo.j_cosAngle; // cos of angle between orientation0 and players orientation
|
||||
recv_data >> movementInfo.j_xyspeed; // speed of xy movement
|
||||
}
|
||||
|
||||
if(MovementFlags & MOVEMENTFLAG_SPLINE)
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
|
||||
|
||||
recv_data >> movementInfo.u_unk1; // unknown
|
||||
}
|
||||
ReadMovementInfo(recv_data, &movementInfo);
|
||||
/*----------------*/
|
||||
|
||||
if(recv_data.size() != recv_data.rpos())
|
||||
|
|
@ -247,7 +198,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
return;
|
||||
|
||||
/* handle special cases */
|
||||
if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT)
|
||||
if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
|
||||
{
|
||||
// transports size limited
|
||||
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
|
||||
|
|
@ -266,9 +217,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
{
|
||||
if ((*iter)->GetGUID() == movementInfo.t_guid)
|
||||
{
|
||||
// unmount before boarding
|
||||
_player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
|
||||
|
||||
GetPlayer()->m_transport = (*iter);
|
||||
(*iter)->AddPassenger(GetPlayer());
|
||||
break;
|
||||
|
|
@ -285,10 +233,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
movementInfo.t_z = 0.0f;
|
||||
movementInfo.t_o = 0.0f;
|
||||
movementInfo.t_time = 0;
|
||||
movementInfo.t_seat = -1;
|
||||
}
|
||||
|
||||
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
|
||||
if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())
|
||||
if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())
|
||||
{
|
||||
// calculate total z distance of the fall
|
||||
float z_diff = GetPlayer()->m_lastFallZ - movementInfo.z;
|
||||
|
|
@ -324,28 +273,19 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
damage = target->GetMaxHealth()/2;
|
||||
|
||||
target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage);
|
||||
|
||||
// recheck alive, might have died of EnvironmentalDamage
|
||||
if (target->isAlive())
|
||||
target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100));
|
||||
}
|
||||
|
||||
//Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction
|
||||
DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, target->GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall);
|
||||
}
|
||||
}
|
||||
|
||||
//handle fall and logout at the same time (logout started before fall finished)
|
||||
/* outdated and create problems with sit at stun sometime
|
||||
if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE))
|
||||
{
|
||||
target->SetStandState(PLAYER_STATE_SIT);
|
||||
// Can't move
|
||||
WorldPacket data( SMSG_FORCE_MOVE_ROOT, 12 );
|
||||
data.append(target->GetPackGUID());
|
||||
data << (uint32)2;
|
||||
SendPacket( &data );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater())
|
||||
if(((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater())
|
||||
{
|
||||
// now client not include swimming flag in case jumping under water
|
||||
GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
|
||||
|
|
@ -354,15 +294,36 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
/*----------------------*/
|
||||
|
||||
/* process position-change */
|
||||
recv_data.put<uint32>(5, getMSTime()); // offset flags(4) + unk(1)
|
||||
WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size()));
|
||||
data.append(GetPlayer()->GetPackGUID());
|
||||
Unit *mover = _player->m_mover;
|
||||
recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2)
|
||||
WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size()));
|
||||
data.append(_player->m_mover->GetPackGUID()); // use mover guid
|
||||
data.append(recv_data.contents(), recv_data.size());
|
||||
GetPlayer()->SendMessageToSet(&data, false);
|
||||
|
||||
GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
|
||||
GetPlayer()->m_movementInfo = movementInfo;
|
||||
if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z)
|
||||
if(!_player->GetCharmGUID()) // nothing is charmed
|
||||
{
|
||||
_player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
|
||||
_player->m_movementInfo = movementInfo;
|
||||
_player->SetUnitMovementFlags(movementInfo.flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mover->GetTypeId() != TYPEID_PLAYER) // unit, creature, pet, vehicle...
|
||||
{
|
||||
if(Map *map = mover->GetMap())
|
||||
map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
|
||||
mover->SetUnitMovementFlags(movementInfo.flags);
|
||||
}
|
||||
else // player
|
||||
{
|
||||
((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
|
||||
((Player*)mover)->m_movementInfo = movementInfo;
|
||||
((Player*)mover)->SetUnitMovementFlags(movementInfo.flags);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND)
|
||||
GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z);
|
||||
|
||||
if(GetPlayer()->isMovingOrTurning())
|
||||
|
|
@ -370,39 +331,41 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
|
||||
if(movementInfo.z < -500.0f)
|
||||
{
|
||||
// NOTE: this is actually called many times while falling
|
||||
// even after the player has been teleported away
|
||||
// TODO: discard movement packets after the player is rooted
|
||||
if(GetPlayer()->isAlive())
|
||||
if(GetPlayer()->InBattleGround()
|
||||
&& GetPlayer()->GetBattleGround()
|
||||
&& GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player))
|
||||
{
|
||||
GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
|
||||
// change the death state to CORPSE to prevent the death timer from
|
||||
// starting in the next player update
|
||||
GetPlayer()->KillPlayer();
|
||||
GetPlayer()->BuildPlayerRepop();
|
||||
// do nothing, the handle already did if returned true
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: this is actually called many times while falling
|
||||
// even after the player has been teleported away
|
||||
// TODO: discard movement packets after the player is rooted
|
||||
if(GetPlayer()->isAlive())
|
||||
{
|
||||
GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
|
||||
// change the death state to CORPSE to prevent the death timer from
|
||||
// starting in the next player update
|
||||
GetPlayer()->KillPlayer();
|
||||
GetPlayer()->BuildPlayerRepop();
|
||||
}
|
||||
|
||||
// cancel the death timer here if started
|
||||
GetPlayer()->RepopAtGraveyard();
|
||||
// cancel the death timer here if started
|
||||
GetPlayer()->RepopAtGraveyard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
|
||||
{
|
||||
CHECK_PACKET_SIZE(recv_data, 8+4+4+1+4+4+4+4+4);
|
||||
sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode());
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4);
|
||||
|
||||
/* extract packet */
|
||||
uint64 guid;
|
||||
uint8 unkB;
|
||||
uint32 unk1, flags, time, fallTime;
|
||||
float x, y, z, orientation;
|
||||
|
||||
uint64 t_GUID;
|
||||
float t_x, t_y, t_z, t_o;
|
||||
uint32 t_time;
|
||||
float s_pitch;
|
||||
float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed;
|
||||
float u_unk1;
|
||||
uint32 unk1;
|
||||
float newspeed;
|
||||
|
||||
recv_data >> guid;
|
||||
|
|
@ -413,47 +376,10 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
|
|||
|
||||
// continue parse packet
|
||||
|
||||
recv_data >> unk1;
|
||||
recv_data >> flags >> unkB >> time;
|
||||
recv_data >> x >> y >> z >> orientation;
|
||||
if (flags & MOVEMENTFLAG_ONTRANSPORT)
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4);
|
||||
recv_data >> unk1; // counter or moveEvent
|
||||
|
||||
recv_data >> t_GUID;
|
||||
recv_data >> t_x >> t_y >> t_z >> t_o >> t_time;
|
||||
}
|
||||
if (flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
|
||||
|
||||
recv_data >> s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up
|
||||
}
|
||||
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
|
||||
|
||||
recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now)
|
||||
|
||||
if ((flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING))
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4);
|
||||
|
||||
recv_data >> j_unk1; // ?constant, but different when jumping in water and on land?
|
||||
recv_data >> j_sinAngle >> j_cosAngle; // sin + cos of angle between orientation0 and players orientation
|
||||
recv_data >> j_xyspeed; // speed of xy movement
|
||||
}
|
||||
|
||||
if(flags & MOVEMENTFLAG_SPLINE)
|
||||
{
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
|
||||
|
||||
recv_data >> u_unk1; // unknown
|
||||
}
|
||||
MovementInfo movementInfo;
|
||||
ReadMovementInfo(recv_data, &movementInfo);
|
||||
|
||||
// recheck
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4);
|
||||
|
|
@ -466,7 +392,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
|
|||
UnitMoveType move_type;
|
||||
UnitMoveType force_move_type;
|
||||
|
||||
static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack" };
|
||||
static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" };
|
||||
|
||||
uint16 opcode = recv_data.GetOpcode();
|
||||
switch(opcode)
|
||||
|
|
@ -479,6 +405,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
|
|||
case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break;
|
||||
case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break;
|
||||
case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break;
|
||||
case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break;
|
||||
default:
|
||||
sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode);
|
||||
return;
|
||||
|
|
@ -513,15 +440,61 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
|
|||
void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
|
||||
recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data,8);
|
||||
CHECK_PACKET_SIZE(recv_data, 8);
|
||||
|
||||
uint64 guid;
|
||||
recv_data >> guid;
|
||||
|
||||
WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement
|
||||
data << uint32(0x00000000); // on blizz it increments periodically
|
||||
SendPacket(&data);
|
||||
if(_player->m_mover->GetGUID() != guid)
|
||||
{
|
||||
sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, _player->m_mover->GetGUID(), guid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER");
|
||||
recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8);
|
||||
|
||||
uint64 old_mover_guid;
|
||||
recv_data >> old_mover_guid;
|
||||
|
||||
if(_player->m_mover->GetGUID() == old_mover_guid)
|
||||
{
|
||||
sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid);
|
||||
return;
|
||||
}
|
||||
|
||||
MovementInfo mi;
|
||||
ReadMovementInfo(recv_data, &mi);
|
||||
_player->m_movementInfo = mi;
|
||||
}
|
||||
|
||||
void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
|
||||
{
|
||||
sLog.outDebug("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE");
|
||||
recv_data.hexlike();
|
||||
|
||||
uint64 vehicleGUID = _player->GetCharmGUID();
|
||||
|
||||
if(!vehicleGUID) // something wrong here...
|
||||
return;
|
||||
|
||||
MovementInfo mi;
|
||||
ReadMovementInfo(recv_data, &mi);
|
||||
_player->m_movementInfo = mi;
|
||||
|
||||
// using charm guid, because we don't have vehicle guid...
|
||||
if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
|
||||
{
|
||||
_player->ExitVehicle(vehicle);
|
||||
vehicle->Dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/)
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ void WorldSession::SendTrainerList( uint64 guid )
|
|||
SendTrainerList( guid, str );
|
||||
}
|
||||
|
||||
void WorldSession::SendTrainerList( uint64 guid,std::string strTitle )
|
||||
void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle )
|
||||
{
|
||||
sLog.outDebug( "WORLD: SendTrainerList" );
|
||||
|
||||
|
|
@ -518,13 +518,12 @@ void WorldSession::SendStablePet(uint64 guid )
|
|||
data << uint32(pet->GetEntry());
|
||||
data << uint32(pet->getLevel());
|
||||
data << pet->GetName(); // petname
|
||||
data << uint32(pet->GetLoyaltyLevel()); // loyalty
|
||||
data << uint8(0x01); // client slot 1 == current pet (0)
|
||||
data << uint8(0x01); // flags?, client slot 1 == current pet (0)
|
||||
++num;
|
||||
}
|
||||
|
||||
// 0 1 2 3 4 5 6
|
||||
QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow());
|
||||
// 0 1 2 3 4 5
|
||||
QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow());
|
||||
|
||||
if(result)
|
||||
{
|
||||
|
|
@ -535,8 +534,7 @@ void WorldSession::SendStablePet(uint64 guid )
|
|||
data << uint32(fields[2].GetUInt32()); // petnumber
|
||||
data << uint32(fields[3].GetUInt32()); // creature entry
|
||||
data << uint32(fields[4].GetUInt32()); // level
|
||||
data << fields[6].GetString(); // name
|
||||
data << uint32(fields[5].GetUInt32()); // loyalty
|
||||
data << fields[5].GetString(); // name
|
||||
data << uint8(fields[1].GetUInt32()+1); // slot
|
||||
|
||||
++num;
|
||||
|
|
@ -586,7 +584,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data )
|
|||
|
||||
uint32 free_slot = 1;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow());
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5 ORDER BY slot ",_player->GetGUIDLow());
|
||||
if(result)
|
||||
{
|
||||
do
|
||||
|
|
@ -650,7 +648,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
|
|||
|
||||
Pet *newpet = NULL;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber);
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber);
|
||||
if(result)
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
|
@ -694,7 +692,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
|
|||
|
||||
WorldPacket data(SMSG_STABLE_RESULT, 200);
|
||||
|
||||
if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2
|
||||
if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4
|
||||
{
|
||||
StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
|
||||
if(_player->GetMoney() >= SlotPrice->Price)
|
||||
|
|
|
|||
|
|
@ -146,15 +146,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c
|
|||
|
||||
/** lower flag1 **/
|
||||
if(target == this) // building packet for oneself
|
||||
{
|
||||
flags |= UPDATEFLAG_SELF;
|
||||
|
||||
/*** temporary reverted - until real source of stack corruption will not found
|
||||
updatetype = UPDATETYPE_CREATE_OBJECT2;
|
||||
****/
|
||||
}
|
||||
|
||||
if(flags & UPDATEFLAG_HASPOSITION)
|
||||
if(flags & UPDATEFLAG_HAS_POSITION)
|
||||
{
|
||||
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
|
||||
if(isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER))
|
||||
|
|
@ -180,6 +174,12 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isType(TYPEMASK_UNIT))
|
||||
{
|
||||
if(((Unit*)this)->getVictim())
|
||||
flags |= UPDATEFLAG_HAS_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
//sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2);
|
||||
|
|
@ -251,11 +251,18 @@ void Object::DestroyForPlayer(Player *target) const
|
|||
|
||||
WorldPacket data(SMSG_DESTROY_OBJECT, 8);
|
||||
data << GetGUID();
|
||||
data << uint8(0); // WotLK (bool)
|
||||
target->GetSession()->SendPacket( &data );
|
||||
}
|
||||
|
||||
void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const
|
||||
void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2) const
|
||||
{
|
||||
uint16 unk_flags = ((GetTypeId() == TYPEID_PLAYER) ? ((Player*)this)->m_movementInfo.unk1 : 0);
|
||||
|
||||
if(GetTypeId() == TYPEID_UNIT)
|
||||
if(((Creature*)this)->isVehicle())
|
||||
unk_flags |= 0x20; // always allow pitch
|
||||
|
||||
*data << (uint8)flags; // update flags
|
||||
|
||||
// 0x20
|
||||
|
|
@ -290,12 +297,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
|
|||
}
|
||||
|
||||
*data << uint32(flags2); // movement flags
|
||||
*data << uint8(0); // unk 2.3.0
|
||||
*data << uint16(unk_flags); // unknown 2.3.0
|
||||
*data << uint32(getMSTime()); // time (in milliseconds)
|
||||
}
|
||||
|
||||
// 0x40
|
||||
if (flags & UPDATEFLAG_HASPOSITION)
|
||||
if (flags & UPDATEFLAG_HAS_POSITION)
|
||||
{
|
||||
// 0x02
|
||||
if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT)
|
||||
|
|
@ -328,12 +335,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
|
|||
*data << (float)((Player*)this)->GetTransOffsetZ();
|
||||
*data << (float)((Player*)this)->GetTransOffsetO();
|
||||
*data << (uint32)((Player*)this)->GetTransTime();
|
||||
*data << (int8)((Player*)this)->GetTransSeat();
|
||||
}
|
||||
//MaNGOS currently not have support for other than player on transport
|
||||
}
|
||||
|
||||
// 0x02200000
|
||||
if(flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
|
||||
if((flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (unk_flags & 0x20))
|
||||
{
|
||||
if(GetTypeId() == TYPEID_PLAYER)
|
||||
*data << (float)((Player*)this)->m_movementInfo.s_pitch;
|
||||
|
|
@ -382,6 +390,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
|
|||
*data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT );
|
||||
*data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT_BACK );
|
||||
*data << ((Unit*)this)->GetSpeed( MOVE_TURN_RATE );
|
||||
*data << ((Unit*)this)->GetSpeed( MOVE_PITCH_RATE );
|
||||
|
||||
// 0x08000000
|
||||
if(flags2 & MOVEMENTFLAG_SPLINE2)
|
||||
|
|
@ -483,7 +492,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
|
|||
break;
|
||||
case TYPEID_PLAYER:
|
||||
if(flags & UPDATEFLAG_SELF)
|
||||
*data << uint32(0x00000015); // unk, can be 0x15 or 0x22
|
||||
*data << uint32(0x0000002F); // unk, can be 0x15 or 0x22
|
||||
else
|
||||
*data << uint32(0x00000008); // unk, can be 0x7 or 0x8
|
||||
break;
|
||||
|
|
@ -506,6 +515,15 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
|
|||
case TYPEID_CORPSE:
|
||||
*data << uint32(GetGUIDHigh()); // GetGUIDHigh()
|
||||
break;
|
||||
case TYPEID_UNIT:
|
||||
*data << uint32(0x0000000B); // unk, can be 0xB or 0xC
|
||||
break;
|
||||
case TYPEID_PLAYER:
|
||||
if(flags & UPDATEFLAG_SELF)
|
||||
*data << uint32(0x0000002F); // unk, can be 0x15 or 0x22
|
||||
else
|
||||
*data << uint32(0x00000008); // unk, can be 0x7 or 0x8
|
||||
break;
|
||||
default:
|
||||
*data << uint32(0x00000000); // unk
|
||||
break;
|
||||
|
|
@ -513,9 +531,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
|
|||
}
|
||||
|
||||
// 0x4
|
||||
if(flags & UPDATEFLAG_FULLGUID)
|
||||
if(flags & UPDATEFLAG_HAS_TARGET) // packed guid (current target guid)
|
||||
{
|
||||
*data << uint8(0); // packed guid (probably target guid)
|
||||
if(Unit *victim = ((Unit*)this)->getVictim())
|
||||
data->append(victim->GetPackGUID());
|
||||
else
|
||||
*data << uint8(0);
|
||||
}
|
||||
|
||||
// 0x2
|
||||
|
|
@ -523,6 +544,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
|
|||
{
|
||||
*data << uint32(getMSTime()); // ms time
|
||||
}
|
||||
|
||||
// 0x80
|
||||
if(flags & UPDATEFLAG_VEHICLE) // unused for now
|
||||
{
|
||||
*data << uint32(((Vehicle*)this)->GetVehicleId()); // vehicle id
|
||||
*data << float(0); // facing adjustment
|
||||
}
|
||||
}
|
||||
|
||||
void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const
|
||||
|
|
@ -538,7 +566,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
|
|||
if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
|
||||
{
|
||||
IsActivateToQuest = true;
|
||||
updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
|
||||
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -550,8 +578,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
|
|||
{
|
||||
IsActivateToQuest = true;
|
||||
}
|
||||
updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
|
||||
updateMask->SetBit(GAMEOBJECT_ANIMPROGRESS);
|
||||
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
|
||||
updateMask->SetBit(GAMEOBJECT_BYTES_1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -612,7 +640,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
|
|||
if( updateMask->GetBit( index ) )
|
||||
{
|
||||
// send in current format (float as float, uint32 as uint32)
|
||||
if ( index == GAMEOBJECT_DYN_FLAGS )
|
||||
if ( index == GAMEOBJECT_DYNAMIC )
|
||||
{
|
||||
if(IsActivateToQuest )
|
||||
{
|
||||
|
|
@ -1371,7 +1399,7 @@ void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const
|
|||
data->Initialize(MSG_MOVE_HEARTBEAT, 32);
|
||||
data->append(GetPackGUID());
|
||||
*data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags
|
||||
*data << uint8(0); // 2.3.0
|
||||
*data << uint16(0); // 2.3.0
|
||||
*data << getMSTime(); // time
|
||||
*data << m_positionX;
|
||||
*data << m_positionY;
|
||||
|
|
@ -1390,7 +1418,7 @@ void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float
|
|||
data->append(GetPackGUID());
|
||||
*data << uint32(0); // this value increments every time
|
||||
*data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags
|
||||
*data << uint8(0); // 2.3.0
|
||||
*data << uint16(0); // 2.3.0
|
||||
*data << getMSTime(); // time
|
||||
*data << x;
|
||||
*data << y;
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
|
|||
InstanceData* GetInstanceData();
|
||||
|
||||
const char* GetName() const { return m_name.c_str(); }
|
||||
void SetName(std::string newname) { m_name=newname; }
|
||||
void SetName(const std::string& newname) { m_name=newname; }
|
||||
|
||||
virtual const char* GetNameForLocaleIdx(int32 /*locale_idx*/) const { return GetName(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,9 @@ ObjectAccessor::GetCreatureOrPet(WorldObject const &u, uint64 guid)
|
|||
if(Creature *unit = GetPet(guid))
|
||||
return unit;
|
||||
|
||||
if(Creature *unit = GetVehicle(guid))
|
||||
return unit;
|
||||
|
||||
return GetCreature(u, guid);
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +352,12 @@ ObjectAccessor::GetPet(uint64 guid)
|
|||
return GetObjectInWorld(guid, (Pet*)NULL);
|
||||
}
|
||||
|
||||
Vehicle*
|
||||
ObjectAccessor::GetVehicle(uint64 guid)
|
||||
{
|
||||
return GetObjectInWorld(guid, (Vehicle*)NULL);
|
||||
}
|
||||
|
||||
Corpse*
|
||||
ObjectAccessor::GetCorpseForPlayerGUID(uint64 guid)
|
||||
{
|
||||
|
|
@ -554,6 +563,7 @@ template <class T> ZThread::FastMutex HashMapHolder<T>::i_lock;
|
|||
|
||||
template class HashMapHolder<Player>;
|
||||
template class HashMapHolder<Pet>;
|
||||
template class HashMapHolder<Vehicle>;
|
||||
template class HashMapHolder<GameObject>;
|
||||
template class HashMapHolder<DynamicObject>;
|
||||
template class HashMapHolder<Creature>;
|
||||
|
|
@ -561,6 +571,7 @@ template class HashMapHolder<Corpse>;
|
|||
|
||||
template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/);
|
||||
template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/);
|
||||
template Vehicle* ObjectAccessor::GetObjectInWorld<Vehicle>(uint32 mapid, float x, float y, uint64 guid, Vehicle* /*fake*/);
|
||||
template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/);
|
||||
template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/);
|
||||
template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "GridDefines.h"
|
||||
#include "Object.h"
|
||||
#include "Player.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
|
|
@ -148,6 +149,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
|
|||
static DynamicObject* GetDynamicObject(Unit const &, uint64);
|
||||
static Corpse* GetCorpse(WorldObject const &u, uint64 guid);
|
||||
static Pet* GetPet(uint64 guid);
|
||||
static Vehicle* GetVehicle(uint64 guid);
|
||||
static Player* FindPlayer(uint64);
|
||||
|
||||
Player* FindPlayerByName(const char *name) ;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ enum HighGuid
|
|||
HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT)
|
||||
HIGHGUID_UNIT = 0xF130, // blizz F130
|
||||
HIGHGUID_PET = 0xF140, // blizz F140
|
||||
HIGHGUID_VEHICLE = 0xF150, // blizz F550
|
||||
HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100
|
||||
HIGHGUID_CORPSE = 0xF101, // blizz F100
|
||||
HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT)
|
||||
|
|
@ -48,6 +49,7 @@ enum HighGuid
|
|||
|
||||
#define IS_CREATURE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_UNIT )
|
||||
#define IS_PET_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PET )
|
||||
#define IS_VEHICLE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_VEHICLE )
|
||||
#define IS_CREATURE_OR_PET_GUID(Guid)( IS_CREATURE_GUID(Guid) || IS_PET_GUID(Guid) )
|
||||
#define IS_PLAYER_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid!=0 )
|
||||
#define IS_UNIT_GUID(Guid) ( IS_CREATURE_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid) )
|
||||
|
|
@ -85,6 +87,7 @@ inline bool IsGuidHaveEnPart(uint64 const& guid)
|
|||
case HIGHGUID_TRANSPORT:
|
||||
case HIGHGUID_UNIT:
|
||||
case HIGHGUID_PET:
|
||||
case HIGHGUID_VEHICLE:
|
||||
case HIGHGUID_MO_TRANSPORT:
|
||||
default:
|
||||
return true;
|
||||
|
|
@ -104,6 +107,7 @@ inline char const* GetLogNameForGuid(uint64 guid)
|
|||
case HIGHGUID_TRANSPORT: return "transport";
|
||||
case HIGHGUID_UNIT: return "creature";
|
||||
case HIGHGUID_PET: return "pet";
|
||||
case HIGHGUID_VEHICLE: return "vehicle";
|
||||
case HIGHGUID_DYNAMICOBJECT:return "dynobject";
|
||||
case HIGHGUID_CORPSE: return "corpse";
|
||||
case HIGHGUID_MO_TRANSPORT: return "mo_transport";
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ ObjectGridRespawnMover::Visit(CreatureMapType &m)
|
|||
|
||||
Creature * c = iter->getSource();
|
||||
|
||||
assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets");
|
||||
assert((!c->isPet() || !c->isVehicle()) && "ObjectGridRespawnMover don't must be called for pets");
|
||||
|
||||
Cell const& cur_cell = c->GetCurrentCell();
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ ObjectMgr::ObjectMgr()
|
|||
m_hiCharGuid = 1;
|
||||
m_hiCreatureGuid = 1;
|
||||
m_hiPetGuid = 1;
|
||||
m_hiVehicleGuid = 1;
|
||||
m_hiItemGuid = 1;
|
||||
m_hiGoGuid = 1;
|
||||
m_hiDoGuid = 1;
|
||||
|
|
@ -137,13 +138,13 @@ ObjectMgr::ObjectMgr()
|
|||
|
||||
ObjectMgr::~ObjectMgr()
|
||||
{
|
||||
for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++ i )
|
||||
for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++i )
|
||||
{
|
||||
delete i->second;
|
||||
}
|
||||
mQuestTemplates.clear( );
|
||||
|
||||
for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++ i )
|
||||
for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++i )
|
||||
{
|
||||
delete i->second;
|
||||
}
|
||||
|
|
@ -151,7 +152,7 @@ ObjectMgr::~ObjectMgr()
|
|||
|
||||
mAreaTriggers.clear();
|
||||
|
||||
for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++ i )
|
||||
for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++i )
|
||||
{
|
||||
delete[] i->second;
|
||||
}
|
||||
|
|
@ -199,7 +200,7 @@ Guild * ObjectMgr::GetGuildById(const uint32 GuildId) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Guild * ObjectMgr::GetGuildByName(std::string guildname) const
|
||||
Guild * ObjectMgr::GetGuildByName(const std::string& guildname) const
|
||||
{
|
||||
for(GuildSet::const_iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); ++itr)
|
||||
if ((*itr)->GetName() == guildname)
|
||||
|
|
@ -226,33 +227,43 @@ Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 ArenaTeamId) const
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 arenateamid) const
|
||||
{
|
||||
for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr)
|
||||
if ((*itr)->GetId() == ArenaTeamId)
|
||||
return *itr;
|
||||
ArenaTeamMap::const_iterator itr = mArenaTeamMap.find(arenateamid);
|
||||
if (itr != mArenaTeamMap.end())
|
||||
return itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamByName(std::string arenateamname) const
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamByName(const std::string& arenateamname) const
|
||||
{
|
||||
for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr)
|
||||
if ((*itr)->GetName() == arenateamname)
|
||||
return *itr;
|
||||
for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
|
||||
if (itr->second->GetName() == arenateamname)
|
||||
return itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamByCapitan(uint64 const& guid) const
|
||||
ArenaTeam* ObjectMgr::GetArenaTeamByCaptain(uint64 const& guid) const
|
||||
{
|
||||
for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr)
|
||||
if ((*itr)->GetCaptain() == guid)
|
||||
return *itr;
|
||||
for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
|
||||
if (itr->second->GetCaptain() == guid)
|
||||
return itr->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ObjectMgr::AddArenaTeam(ArenaTeam* arenaTeam)
|
||||
{
|
||||
mArenaTeamMap[arenaTeam->GetId()] = arenaTeam;
|
||||
}
|
||||
|
||||
void ObjectMgr::RemoveArenaTeam(ArenaTeam* arenaTeam)
|
||||
{
|
||||
mArenaTeamMap.erase( arenaTeam->GetId() );
|
||||
}
|
||||
|
||||
AuctionHouseObject * ObjectMgr::GetAuctionsMap( uint32 location )
|
||||
{
|
||||
switch ( location )
|
||||
|
|
@ -568,7 +579,23 @@ void ObjectMgr::LoadCreatureLocales()
|
|||
sLog.outString();
|
||||
sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() );
|
||||
}
|
||||
|
||||
|
||||
void ObjectMgr::LoadCompletedAchievements()
|
||||
{
|
||||
QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
|
||||
|
||||
if(!result)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
allCompletedAchievements.insert(fields[0].GetUInt32());
|
||||
} while(result->NextRow());
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadNpcOptionLocales()
|
||||
{
|
||||
mNpcOptionLocaleMap.clear(); // need for reload case
|
||||
|
|
@ -915,8 +942,47 @@ void ObjectMgr::LoadEquipmentTemplates()
|
|||
{
|
||||
sEquipmentStorage.Load();
|
||||
|
||||
for(uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i)
|
||||
{
|
||||
EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry<EquipmentInfo>(i);
|
||||
|
||||
if(!eqInfo)
|
||||
continue;
|
||||
|
||||
for(uint8 j=0; j<3; j++)
|
||||
{
|
||||
if(!eqInfo->equipentry[j])
|
||||
continue;
|
||||
|
||||
ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]);
|
||||
|
||||
if(!dbcitem)
|
||||
{
|
||||
sLog.outErrorDb("Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0.", eqInfo->equipentry[j], j+1, i);
|
||||
const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(dbcitem->InventoryType != INVTYPE_WEAPON &&
|
||||
dbcitem->InventoryType != INVTYPE_SHIELD &&
|
||||
dbcitem->InventoryType != INVTYPE_RANGED &&
|
||||
dbcitem->InventoryType != INVTYPE_2HWEAPON &&
|
||||
dbcitem->InventoryType != INVTYPE_WEAPONMAINHAND &&
|
||||
dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND &&
|
||||
dbcitem->InventoryType != INVTYPE_HOLDABLE &&
|
||||
dbcitem->InventoryType != INVTYPE_THROWN &&
|
||||
dbcitem->InventoryType != INVTYPE_RANGEDRIGHT)
|
||||
{
|
||||
sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i);
|
||||
const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
sLog.outString( ">> Loaded %u equipment template", sEquipmentStorage.RecordCount );
|
||||
sLog.outString();
|
||||
|
||||
// This DBC is currently only used for item templates and creature equipments checks.
|
||||
sItemStore.Clear();
|
||||
}
|
||||
|
||||
CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelid)
|
||||
|
|
@ -1380,7 +1446,7 @@ uint32 ObjectMgr::GetPlayerAccountIdByGUID(const uint64 &guid) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(std::string name) const
|
||||
uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(const std::string& name) const
|
||||
{
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", name.c_str());
|
||||
if(result)
|
||||
|
|
@ -1573,7 +1639,7 @@ void ObjectMgr::LoadItemPrototypes()
|
|||
if(proto->Class >= MAX_ITEM_CLASS)
|
||||
{
|
||||
sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class);
|
||||
const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_JUNK;
|
||||
const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_MISC;
|
||||
}
|
||||
|
||||
if(proto->SubClass >= MaxItemSubclassValues[proto->Class])
|
||||
|
|
@ -1670,7 +1736,7 @@ void ObjectMgr::LoadItemPrototypes()
|
|||
}
|
||||
|
||||
// special format
|
||||
if(proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN)
|
||||
if((proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) || (proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN_PET))
|
||||
{
|
||||
// spell_1
|
||||
if(proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE)
|
||||
|
|
@ -1707,7 +1773,7 @@ void ObjectMgr::LoadItemPrototypes()
|
|||
const_cast<ItemPrototype*>(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE;
|
||||
}
|
||||
// allowed only in special format
|
||||
else if(proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN)
|
||||
else if((proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN_PET))
|
||||
{
|
||||
sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,1+1,proto->Spells[1].SpellId);
|
||||
const_cast<ItemPrototype*>(proto)->Spells[0].SpellId = 0;
|
||||
|
|
@ -1753,7 +1819,7 @@ void ObjectMgr::LoadItemPrototypes()
|
|||
const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0;
|
||||
}
|
||||
// allowed only in special format
|
||||
else if(proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN)
|
||||
else if((proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN_PET))
|
||||
{
|
||||
sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,j+1,proto->Spells[j].SpellId);
|
||||
const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0;
|
||||
|
|
@ -1822,9 +1888,6 @@ void ObjectMgr::LoadItemPrototypes()
|
|||
const_cast<ItemPrototype*>(proto)->FoodType = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// this DBC used currently only for check item templates in DB.
|
||||
sItemStore.Clear();
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadAuctionItems()
|
||||
|
|
@ -1909,8 +1972,8 @@ void ObjectMgr::LoadPetLevelInfo()
|
|||
uint32 current_level = fields[1].GetUInt32();
|
||||
if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
if(current_level > 255) // hardcoded level maximum
|
||||
sLog.outErrorDb("Wrong (> 255) level %u in `pet_levelstats` table, ignoring.",current_level);
|
||||
if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
|
||||
sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level);
|
||||
else
|
||||
sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `pet_levelstats` table, ignoring.",current_level);
|
||||
continue;
|
||||
|
|
@ -2089,6 +2152,8 @@ void ObjectMgr::LoadPlayerInfo()
|
|||
{
|
||||
barGoLink bar( 1 );
|
||||
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString( ">> Loaded %u custom player create items", count );
|
||||
}
|
||||
|
|
@ -2286,8 +2351,8 @@ void ObjectMgr::LoadPlayerInfo()
|
|||
uint32 current_level = fields[1].GetUInt32();
|
||||
if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
if(current_level > 255) // hardcoded level maximum
|
||||
sLog.outErrorDb("Wrong (> 255) level %u in `player_classlevelstats` table, ignoring.",current_level);
|
||||
if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
|
||||
sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level);
|
||||
else
|
||||
sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level);
|
||||
continue;
|
||||
|
|
@ -2381,8 +2446,8 @@ void ObjectMgr::LoadPlayerInfo()
|
|||
uint32 current_level = fields[2].GetUInt32();
|
||||
if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
if(current_level > 255) // hardcoded level maximum
|
||||
sLog.outErrorDb("Wrong (> 255) level %u in `player_levelstats` table, ignoring.",current_level);
|
||||
if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum
|
||||
sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level);
|
||||
else
|
||||
sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_levelstats` table, ignoring.",current_level);
|
||||
continue;
|
||||
|
|
@ -2808,31 +2873,31 @@ void ObjectMgr::LoadQuests()
|
|||
QueryResult *result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue,"
|
||||
// 9 10 11 12 13 14 15 16
|
||||
"RepObjectiveFaction, RepObjectiveValue, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime,"
|
||||
// 17 18 19 20 21 22 23 24 25 26
|
||||
"QuestFlags, SpecialFlags, CharTitleId, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell,"
|
||||
// 27 28 29 30 31 32 33 34 35 36
|
||||
// 17 18 19 20 21 22 23 24 25 26 27 28
|
||||
"QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell,"
|
||||
// 29 30 31 32 33 34 35 36 37 38
|
||||
"Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4,"
|
||||
// 37 38 39 40 41 42 43 44
|
||||
// 39 40 41 42 43 44 45 46
|
||||
"ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4,"
|
||||
// 45 46 47 48 49 50 51 52 53 54 54 55
|
||||
// 47 48 49 50 51 52 53 54 55 56 57 58
|
||||
"ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4,"
|
||||
// 57 58 59 60 61 62 63 64
|
||||
// 59 60 61 62 63 64 65 66
|
||||
"ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4,"
|
||||
// 65 66 67 68
|
||||
// 67 68 69 70
|
||||
"ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4,"
|
||||
// 69 70 71 72 73 74
|
||||
// 71 72 73 74 75 76
|
||||
"RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6,"
|
||||
// 75 76 77 78 79 80
|
||||
// 77 78 79 80 81 82
|
||||
"RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6,"
|
||||
// 81 82 83 84 85 86 87 88
|
||||
// 83 84 85 86 87 88 89 90
|
||||
"RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4,"
|
||||
// 89 90 91 92 93 94 95 96 97 98
|
||||
// 91 92 93 94 95 96 97 98 99 100
|
||||
"RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5,"
|
||||
// 99 100 101 102 103 104 105 106 107 108 109
|
||||
// 101 102 103 104 105 106 107 108 109 110 111
|
||||
"RewHonorableKills, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt,"
|
||||
// 110 111 112 113 114 115 116 117 118 119
|
||||
// 112 113 114 115 116 117 118 119 120 121
|
||||
"DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4,"
|
||||
// 120 121
|
||||
// 122 123
|
||||
"StartScript, CompleteScript"
|
||||
" FROM quest_template");
|
||||
if(result == NULL)
|
||||
|
|
@ -4203,7 +4268,7 @@ void ObjectMgr::AddGossipText(GossipText *pGText)
|
|||
GossipText *ObjectMgr::GetGossipText(uint32 Text_ID)
|
||||
{
|
||||
GossipTextMap::const_iterator itr;
|
||||
for (itr = mGossipText.begin(); itr != mGossipText.end(); itr++)
|
||||
for (itr = mGossipText.begin(); itr != mGossipText.end(); ++itr)
|
||||
{
|
||||
if(itr->second->Text_ID == Text_ID)
|
||||
return itr->second;
|
||||
|
|
@ -4654,14 +4719,14 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
|
|||
{
|
||||
if (team == ALLIANCE)
|
||||
{
|
||||
mount_entry = node->alliance_mount_type;
|
||||
mount_entry = node->MountCreatureID[1];
|
||||
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
|
||||
if(ci)
|
||||
mount_id = ci->DisplayID_A;
|
||||
}
|
||||
if (team == HORDE)
|
||||
{
|
||||
mount_entry = node->horde_mount_type;
|
||||
mount_entry = node->MountCreatureID[0];
|
||||
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
|
||||
if(ci)
|
||||
mount_id = ci->DisplayID_H;
|
||||
|
|
@ -5095,6 +5160,8 @@ void ObjectMgr::SetHighestGuids()
|
|||
|
||||
// pet guids are not saved to DB, set to 0 (pet guid != pet id)
|
||||
m_hiPetGuid = 0;
|
||||
// same for vehicles
|
||||
m_hiVehicleGuid = 0;
|
||||
|
||||
result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" );
|
||||
if( result )
|
||||
|
|
@ -5248,6 +5315,14 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
|
|||
World::StopNow(ERROR_EXIT_CODE);
|
||||
}
|
||||
return m_hiPetGuid++;
|
||||
case HIGHGUID_VEHICLE:
|
||||
++m_hiVehicleGuid;
|
||||
if(m_hiVehicleGuid>=0x00FFFFFF)
|
||||
{
|
||||
sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. ");
|
||||
World::StopNow(ERROR_EXIT_CODE);
|
||||
}
|
||||
return m_hiVehicleGuid++;
|
||||
case HIGHGUID_PLAYER:
|
||||
if(m_hiCharGuid>=0xFFFFFFFE)
|
||||
{
|
||||
|
|
@ -6135,7 +6210,7 @@ bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ObjectMgr::IsValidName( std::string name, bool create )
|
||||
bool ObjectMgr::IsValidName( const std::string& name, bool create )
|
||||
{
|
||||
std::wstring wname;
|
||||
if(!Utf8toWStr(name,wname))
|
||||
|
|
@ -6149,7 +6224,7 @@ bool ObjectMgr::IsValidName( std::string name, bool create )
|
|||
return isValidString(wname,strictMask,false,create);
|
||||
}
|
||||
|
||||
bool ObjectMgr::IsValidCharterName( std::string name )
|
||||
bool ObjectMgr::IsValidCharterName( const std::string& name )
|
||||
{
|
||||
std::wstring wname;
|
||||
if(!Utf8toWStr(name,wname))
|
||||
|
|
@ -6163,7 +6238,7 @@ bool ObjectMgr::IsValidCharterName( std::string name )
|
|||
return isValidString(wname,strictMask,true);
|
||||
}
|
||||
|
||||
bool ObjectMgr::IsValidPetName( std::string name )
|
||||
bool ObjectMgr::IsValidPetName( const std::string& name )
|
||||
{
|
||||
std::wstring wname;
|
||||
if(!Utf8toWStr(name,wname))
|
||||
|
|
@ -6210,6 +6285,23 @@ int ObjectMgr::GetOrNewIndexForLocale( LocaleConstant loc )
|
|||
return m_LocalForIndex.size()-1;
|
||||
}
|
||||
|
||||
AchievementCriteriaEntryList const& ObjectMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type)
|
||||
{
|
||||
return m_AchievementCriteriasByType[type];
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadAchievementCriteriaList()
|
||||
{
|
||||
for (uint32 entryId = 0; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++)
|
||||
{
|
||||
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId);
|
||||
if(!criteria)
|
||||
continue;
|
||||
|
||||
m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadBattleMastersEntry()
|
||||
{
|
||||
mBattleMastersMap.clear(); // need for reload case
|
||||
|
|
@ -6541,7 +6633,7 @@ bool PlayerCondition::Meets(Player const * player) const
|
|||
{
|
||||
Unit::AuraMap const& auras = player->GetAuras();
|
||||
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||
if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual==3580)
|
||||
if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual[0]==3580)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -6709,7 +6801,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
|
|||
return SKILL_RANGE_MONO;
|
||||
case SKILL_CATEGORY_ARMOR:
|
||||
case SKILL_CATEGORY_CLASS:
|
||||
if(pSkill->id != SKILL_POISONS && pSkill->id != SKILL_LOCKPICKING)
|
||||
if(pSkill->id != SKILL_LOCKPICKING)
|
||||
return SKILL_RANGE_MONO;
|
||||
else
|
||||
return SKILL_RANGE_LEVEL;
|
||||
|
|
@ -6724,7 +6816,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
|
|||
return SKILL_RANGE_MONO;
|
||||
default:
|
||||
case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc
|
||||
case SKILL_CATEGORY_NOT_DISPLAYED: //only GENEREC(DND)
|
||||
case SKILL_CATEGORY_GENERIC: //only GENERIC(DND)
|
||||
return SKILL_RANGE_NONE;
|
||||
}
|
||||
}
|
||||
|
|
@ -6792,7 +6884,7 @@ void ObjectMgr::LoadGameTele()
|
|||
sLog.outString( ">> Loaded %u game tele's", count );
|
||||
}
|
||||
|
||||
GameTele const* ObjectMgr::GetGameTele(std::string name) const
|
||||
GameTele const* ObjectMgr::GetGameTele(const std::string& name) const
|
||||
{
|
||||
// explicit name case
|
||||
std::wstring wname;
|
||||
|
|
@ -6835,7 +6927,7 @@ bool ObjectMgr::AddGameTele(GameTele& tele)
|
|||
new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str());
|
||||
}
|
||||
|
||||
bool ObjectMgr::DeleteGameTele(std::string name)
|
||||
bool ObjectMgr::DeleteGameTele(const std::string& name)
|
||||
{
|
||||
// explicit name case
|
||||
std::wstring wname;
|
||||
|
|
@ -7243,7 +7335,7 @@ uint32 ObjectMgr::GetScriptId(const char *name)
|
|||
if(!name) return 0;
|
||||
ScriptNameMap::const_iterator itr =
|
||||
std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name);
|
||||
if(itr == m_scriptNames.end()) return 0;
|
||||
if(itr == m_scriptNames.end() || *itr != name) return 0;
|
||||
return itr - m_scriptNames.begin();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -242,6 +242,8 @@ typedef std::list<GossipOption> CacheNpcOptionList;
|
|||
typedef UNORDERED_MAP<uint32, VendorItemData> CacheVendorItemMap;
|
||||
typedef UNORDERED_MAP<uint32, TrainerSpellData> CacheTrainerSpellMap;
|
||||
|
||||
typedef std::list<const AchievementCriteriaEntry*> AchievementCriteriaEntryList;
|
||||
|
||||
enum SkillRangeType
|
||||
{
|
||||
SKILL_RANGE_LANGUAGE, // 300..300
|
||||
|
|
@ -282,11 +284,11 @@ class ObjectMgr
|
|||
|
||||
typedef std::set< Group * > GroupSet;
|
||||
typedef std::set< Guild * > GuildSet;
|
||||
typedef std::set< ArenaTeam * > ArenaTeamSet;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, ArenaTeam* > ArenaTeamMap;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, Quest*> QuestMap;
|
||||
|
||||
|
||||
typedef UNORDERED_MAP<uint32, AreaTrigger> AreaTriggerMap;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, uint32> AreaTriggerScriptMap;
|
||||
|
|
@ -313,16 +315,18 @@ class ObjectMgr
|
|||
|
||||
Guild* GetGuildByLeader(uint64 const&guid) const;
|
||||
Guild* GetGuildById(const uint32 GuildId) const;
|
||||
Guild* GetGuildByName(std::string guildname) const;
|
||||
Guild* GetGuildByName(const std::string& guildname) const;
|
||||
std::string GetGuildNameById(const uint32 GuildId) const;
|
||||
void AddGuild(Guild* guild) { mGuildSet.insert( guild ); }
|
||||
void RemoveGuild(Guild* guild) { mGuildSet.erase( guild ); }
|
||||
|
||||
ArenaTeam* GetArenaTeamById(const uint32 ArenaTeamId) const;
|
||||
ArenaTeam* GetArenaTeamByName(std::string ArenaTeamName) const;
|
||||
ArenaTeam* GetArenaTeamByCapitan(uint64 const& guid) const;
|
||||
void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); }
|
||||
void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); }
|
||||
ArenaTeam* GetArenaTeamById(const uint32 arenateamid) const;
|
||||
ArenaTeam* GetArenaTeamByName(const std::string& arenateamname) const;
|
||||
ArenaTeam* GetArenaTeamByCaptain(uint64 const& guid) const;
|
||||
void AddArenaTeam(ArenaTeam* arenaTeam);
|
||||
void RemoveArenaTeam(ArenaTeam* arenaTeam);
|
||||
ArenaTeamMap::iterator GetArenaTeamMapBegin() { return mArenaTeamMap.begin(); }
|
||||
ArenaTeamMap::iterator GetArenaTeamMapEnd() { return mArenaTeamMap.end(); }
|
||||
|
||||
static CreatureInfo const *GetCreatureTemplate( uint32 id );
|
||||
CreatureModelInfo const *GetCreatureModelInfo( uint32 modelid );
|
||||
|
|
@ -405,7 +409,7 @@ class ObjectMgr
|
|||
bool GetPlayerNameByGUID(const uint64 &guid, std::string &name) const;
|
||||
uint32 GetPlayerTeamByGUID(const uint64 &guid) const;
|
||||
uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const;
|
||||
uint32 GetPlayerAccountIdByPlayerName(std::string name) const;
|
||||
uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const;
|
||||
|
||||
uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid );
|
||||
void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost);
|
||||
|
|
@ -562,6 +566,7 @@ class ObjectMgr
|
|||
void LoadNpcTextId();
|
||||
void LoadVendors();
|
||||
void LoadTrainerSpell();
|
||||
void LoadCompletedAchievements();
|
||||
|
||||
std::string GeneratePetName(uint32 entry);
|
||||
uint32 GetBaseXP(uint32 level);
|
||||
|
|
@ -698,15 +703,15 @@ class ObjectMgr
|
|||
|
||||
// reserved names
|
||||
void LoadReservedPlayersNames();
|
||||
bool IsReservedName(std::string name) const
|
||||
bool IsReservedName(const std::string& name) const
|
||||
{
|
||||
return m_ReservedNames.find(name) != m_ReservedNames.end();
|
||||
}
|
||||
|
||||
// name with valid structure and symbols
|
||||
static bool IsValidName( std::string name, bool create = false );
|
||||
static bool IsValidCharterName( std::string name );
|
||||
static bool IsValidPetName( std::string name );
|
||||
static bool IsValidName( const std::string& name, bool create = false );
|
||||
static bool IsValidCharterName( const std::string& name );
|
||||
static bool IsValidPetName( const std::string& name );
|
||||
|
||||
static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names);
|
||||
|
||||
|
|
@ -730,10 +735,10 @@ class ObjectMgr
|
|||
if(itr==m_GameTeleMap.end()) return NULL;
|
||||
return &itr->second;
|
||||
}
|
||||
GameTele const* GetGameTele(std::string name) const;
|
||||
GameTele const* GetGameTele(const std::string& name) const;
|
||||
GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; }
|
||||
bool AddGameTele(GameTele& data);
|
||||
bool DeleteGameTele(std::string name);
|
||||
bool DeleteGameTele(const std::string& name);
|
||||
|
||||
CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; }
|
||||
|
||||
|
|
@ -766,6 +771,9 @@ class ObjectMgr
|
|||
void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost);
|
||||
bool RemoveVendorItem(uint32 entry,uint32 item);
|
||||
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL ) const;
|
||||
void LoadAchievementCriteriaList();
|
||||
AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type);
|
||||
std::set<uint32> allCompletedAchievements;
|
||||
|
||||
void LoadScriptNames();
|
||||
ScriptNameMap &GetScriptNames() { return m_scriptNames; }
|
||||
|
|
@ -785,6 +793,7 @@ class ObjectMgr
|
|||
uint32 m_hiCharGuid;
|
||||
uint32 m_hiCreatureGuid;
|
||||
uint32 m_hiPetGuid;
|
||||
uint32 m_hiVehicleGuid;
|
||||
uint32 m_hiItemGuid;
|
||||
uint32 m_hiGoGuid;
|
||||
uint32 m_hiDoGuid;
|
||||
|
|
@ -801,7 +810,7 @@ class ObjectMgr
|
|||
|
||||
GroupSet mGroupSet;
|
||||
GuildSet mGuildSet;
|
||||
ArenaTeamSet mArenaTeamSet;
|
||||
ArenaTeamMap mArenaTeamMap;
|
||||
|
||||
ItemMap mItems;
|
||||
ItemMap mAitems;
|
||||
|
|
@ -892,6 +901,9 @@ class ObjectMgr
|
|||
CacheNpcTextIdMap m_mCacheNpcTextIdMap;
|
||||
CacheVendorItemMap m_mCacheVendorItemMap;
|
||||
CacheTrainerSpellMap m_mCacheTrainerSpellMap;
|
||||
|
||||
// store achievement criterias by type to speed up lookup
|
||||
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
|
||||
};
|
||||
|
||||
#define objmgr MaNGOS::Singleton<ObjectMgr>::Instance()
|
||||
|
|
|
|||
2250
src/game/Opcodes.cpp
2250
src/game/Opcodes.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
#include "Common.h"
|
||||
|
||||
// Note: this include need for be sure have full definition of class WorldSession
|
||||
// if this class definition not complite then VS for x64 release use different size for
|
||||
// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from
|
||||
// table opcodeTable in source when Opcode.h included but WorldSession.h not included
|
||||
#include "WorldSession.h"
|
||||
|
||||
/// List of Opcodes
|
||||
enum Opcodes
|
||||
{
|
||||
|
|
@ -41,8 +47,8 @@ enum Opcodes
|
|||
CMSG_ZONE_MAP = 0x00A,
|
||||
SMSG_ZONE_MAP = 0x00B,
|
||||
CMSG_DEBUG_CHANGECELLZONE = 0x00C,
|
||||
CMSG_EMBLAZON_TABARD_OBSOLETE = 0x00D,
|
||||
CMSG_UNEMBLAZON_TABARD_OBSOLETE = 0x00E,
|
||||
CMSG_MOVE_CHARACTER_CHEAT = 0x00D,
|
||||
SMSG_MOVE_CHARACTER_CHEAT = 0x00E,
|
||||
CMSG_RECHARGE = 0x00F,
|
||||
CMSG_LEARN_SPELL = 0x010,
|
||||
CMSG_CREATEMONSTER = 0x011,
|
||||
|
|
@ -58,7 +64,7 @@ enum Opcodes
|
|||
SMSG_FORCEACTIONSHOW = 0x01B,
|
||||
CMSG_PETGODMODE = 0x01C,
|
||||
SMSG_PETGODMODE = 0x01D,
|
||||
SMSG_DEBUGINFOSPELLMISS_OBSOLETE = 0x01E,
|
||||
SMSG_REFER_A_FRIEND_EXPIRED = 0x01E,
|
||||
CMSG_WEATHER_SPEED_CHEAT = 0x01F,
|
||||
CMSG_UNDRESSPLAYER = 0x020,
|
||||
CMSG_BEASTMASTER = 0x021,
|
||||
|
|
@ -78,7 +84,7 @@ enum Opcodes
|
|||
SMSG_DEBUG_AISTATE = 0x02F,
|
||||
CMSG_DISABLE_PVP_CHEAT = 0x030,
|
||||
CMSG_ADVANCE_SPAWN_TIME = 0x031,
|
||||
CMSG_PVP_PORT_OBSOLETE = 0x032,
|
||||
SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032,
|
||||
CMSG_AUTH_SRP6_BEGIN = 0x033,
|
||||
CMSG_AUTH_SRP6_PROOF = 0x034,
|
||||
CMSG_AUTH_SRP6_RECODE = 0x035,
|
||||
|
|
@ -206,7 +212,7 @@ enum Opcodes
|
|||
SMSG_READ_ITEM_FAILED = 0x0AF,
|
||||
SMSG_ITEM_COOLDOWN = 0x0B0,
|
||||
CMSG_GAMEOBJ_USE = 0x0B1,
|
||||
CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE = 0x0B2,
|
||||
CMSG_DESTROY_ITEMS = 0x0B2,
|
||||
SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3,
|
||||
CMSG_AREATRIGGER = 0x0B4,
|
||||
MSG_MOVE_START_FORWARD = 0x0B5,
|
||||
|
|
@ -339,7 +345,7 @@ enum Opcodes
|
|||
SMSG_SPELL_COOLDOWN = 0x134,
|
||||
SMSG_COOLDOWN_EVENT = 0x135,
|
||||
CMSG_CANCEL_AURA = 0x136,
|
||||
SMSG_UPDATE_AURA_DURATION = 0x137,
|
||||
SMSG_UPDATE_AURA_DURATION_OBSOLETE = 0x137,
|
||||
SMSG_PET_CAST_FAILED = 0x138,
|
||||
MSG_CHANNEL_START = 0x139,
|
||||
MSG_CHANNEL_UPDATE = 0x13A,
|
||||
|
|
@ -363,10 +369,10 @@ enum Opcodes
|
|||
SMSG_DAMAGE_DONE_OBSOLETE = 0x14C,
|
||||
SMSG_DAMAGE_TAKEN_OBSOLETE = 0x14D,
|
||||
SMSG_CANCEL_COMBAT = 0x14E,
|
||||
SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE = 0x14F,
|
||||
SMSG_SPELLBREAKLOG = 0x14F,
|
||||
SMSG_SPELLHEALLOG = 0x150,
|
||||
SMSG_SPELLENERGIZELOG = 0x151,
|
||||
CMSG_SHEATHE_OBSOLETE = 0x152,
|
||||
SMSG_BREAK_TARGET = 0x152,
|
||||
CMSG_SAVE_PLAYER = 0x153,
|
||||
CMSG_SETDEATHBINDPOINT = 0x154,
|
||||
SMSG_BINDPOINTUPDATE = 0x155,
|
||||
|
|
@ -570,7 +576,7 @@ enum Opcodes
|
|||
SMSG_GMTICKET_SYSTEMSTATUS = 0x21B,
|
||||
CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C,
|
||||
CMSG_SET_STAT_CHEAT = 0x21D,
|
||||
SMSG_SET_REST_START = 0x21E,
|
||||
SMSG_SET_REST_START_OBSOLETE = 0x21E,
|
||||
CMSG_SKILL_BUY_STEP = 0x21F,
|
||||
CMSG_SKILL_BUY_RANK = 0x220,
|
||||
CMSG_XP_CHEAT = 0x221,
|
||||
|
|
@ -725,8 +731,8 @@ enum Opcodes
|
|||
SMSG_SCRIPT_MESSAGE = 0x2B6,
|
||||
SMSG_DUEL_COUNTDOWN = 0x2B7,
|
||||
SMSG_AREA_TRIGGER_MESSAGE = 0x2B8,
|
||||
CMSG_TOGGLE_HELM = 0x2B9,
|
||||
CMSG_TOGGLE_CLOAK = 0x2BA,
|
||||
CMSG_SHOWING_HELM = 0x2B9,
|
||||
CMSG_SHOWING_CLOAK = 0x2BA,
|
||||
SMSG_MEETINGSTONE_JOINFAILED = 0x2BB,
|
||||
SMSG_PLAYER_SKINNED = 0x2BC,
|
||||
SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD,
|
||||
|
|
@ -959,10 +965,10 @@ enum Opcodes
|
|||
SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0,
|
||||
CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1,
|
||||
SMSG_VOICE_SET_TALKER_MUTED = 0x3A2,
|
||||
SMSG_INIT_EXTRA_AURA_INFO = 0x3A3,
|
||||
SMSG_SET_EXTRA_AURA_INFO = 0x3A4,
|
||||
SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE = 0x3A5,
|
||||
SMSG_CLEAR_EXTRA_AURA_INFO = 0x3A6,
|
||||
SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE = 0x3A3,
|
||||
SMSG_SET_EXTRA_AURA_INFO_OBSOLETE = 0x3A4,
|
||||
SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE = 0x3A5,
|
||||
SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE = 0x3A6,
|
||||
MSG_MOVE_START_DESCEND = 0x3A7,
|
||||
CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8,
|
||||
SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9,
|
||||
|
|
@ -972,127 +978,255 @@ enum Opcodes
|
|||
MSG_MOVE_UPDATE_CAN_FLY = 0x3AD,
|
||||
MSG_RAID_READY_CHECK_CONFIRM = 0x3AE,
|
||||
CMSG_VOICE_SESSION_ENABLE = 0x3AF,
|
||||
SMSG_VOICE_PARENTAL_CONTROLS = 0x3B0,
|
||||
CMSG_GM_WHISPER = 0x3B1,
|
||||
SMSG_GM_MESSAGECHAT = 0x3B2,
|
||||
MSG_GM_GEARRATING = 0x3B3,
|
||||
CMSG_COMMENTATOR_ENABLE = 0x3B4,
|
||||
SMSG_COMMENTATOR_STATE_CHANGED = 0x3B5,
|
||||
CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B6,
|
||||
SMSG_COMMENTATOR_MAP_INFO = 0x3B7,
|
||||
CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B8,
|
||||
SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9,
|
||||
SMSG_COMMENTATOR_PLAYER_INFO = 0x3BA,
|
||||
CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BB,
|
||||
CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BC,
|
||||
CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BD,
|
||||
SMSG_CLEAR_TARGET = 0x3BE,
|
||||
CMSG_BOT_DETECTED = 0x3BF,
|
||||
SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C0,
|
||||
CMSG_CHEAT_PLAYER_LOGIN = 0x3C1,
|
||||
CMSG_CHEAT_PLAYER_LOOKUP = 0x3C2,
|
||||
SMSG_CHEAT_PLAYER_LOOKUP = 0x3C3,
|
||||
SMSG_KICK_REASON = 0x3C4,
|
||||
MSG_RAID_READY_CHECK_FINISHED = 0x3C5,
|
||||
CMSG_COMPLAIN = 0x3C6,
|
||||
SMSG_COMPLAIN_RESULT = 0x3C7,
|
||||
SMSG_FEATURE_SYSTEM_STATUS = 0x3C8,
|
||||
CMSG_GM_SHOW_COMPLAINTS = 0x3C9,
|
||||
CMSG_GM_UNSQUELCH = 0x3CA,
|
||||
CMSG_CHANNEL_SILENCE_VOICE = 0x3CB,
|
||||
CMSG_CHANNEL_SILENCE_ALL = 0x3CC,
|
||||
CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CD,
|
||||
CMSG_CHANNEL_UNSILENCE_ALL = 0x3CE,
|
||||
CMSG_TARGET_CAST = 0x3CF,
|
||||
CMSG_TARGET_SCRIPT_CAST = 0x3D0,
|
||||
CMSG_CHANNEL_DISPLAY_LIST = 0x3D1,
|
||||
CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D2,
|
||||
CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D3,
|
||||
SMSG_CHANNEL_MEMBER_COUNT = 0x3D4,
|
||||
CMSG_CHANNEL_VOICE_ON = 0x3D5,
|
||||
CMSG_CHANNEL_VOICE_OFF = 0x3D6,
|
||||
CMSG_DEBUG_LIST_TARGETS = 0x3D7,
|
||||
SMSG_DEBUG_LIST_TARGETS = 0x3D8,
|
||||
SMSG_AVAILABLE_VOICE_CHANNEL = 0x3D9,
|
||||
CMSG_ADD_VOICE_IGNORE = 0x3DA,
|
||||
CMSG_DEL_VOICE_IGNORE = 0x3DB,
|
||||
CMSG_PARTY_SILENCE = 0x3DC,
|
||||
CMSG_PARTY_UNSILENCE = 0x3DD,
|
||||
MSG_NOTIFY_PARTY_SQUELCH = 0x3DE,
|
||||
SMSG_COMSAT_RECONNECT_TRY = 0x3DF,
|
||||
SMSG_COMSAT_DISCONNECT = 0x3E0,
|
||||
SMSG_COMSAT_CONNECT_FAIL = 0x3E1,
|
||||
SMSG_VOICE_CHAT_STATUS = 0x3E2,
|
||||
CMSG_REPORT_PVP_AFK = 0x3E3,
|
||||
CMSG_REPORT_PVP_AFK_RESULT = 0x3E4,
|
||||
CMSG_GUILD_BANKER_ACTIVATE = 0x3E5,
|
||||
CMSG_GUILD_BANK_QUERY_TAB = 0x3E6,
|
||||
SMSG_GUILD_BANK_LIST = 0x3E7,
|
||||
CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E8,
|
||||
CMSG_GUILD_BANK_BUY_TAB = 0x3E9,
|
||||
CMSG_GUILD_BANK_UPDATE_TAB = 0x3EA,
|
||||
CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EB,
|
||||
CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3EC,
|
||||
MSG_GUILD_BANK_LOG_QUERY = 0x3ED,
|
||||
CMSG_SET_CHANNEL_WATCH = 0x3EE,
|
||||
SMSG_USERLIST_ADD = 0x3EF,
|
||||
SMSG_USERLIST_REMOVE = 0x3F0,
|
||||
SMSG_USERLIST_UPDATE = 0x3F1,
|
||||
CMSG_CLEAR_CHANNEL_WATCH = 0x3F2,
|
||||
SMSG_INSPECT_TALENT = 0x3F3,
|
||||
SMSG_GOGOGO_OBSOLETE = 0x3F4,
|
||||
SMSG_ECHO_PARTY_SQUELCH = 0x3F5,
|
||||
CMSG_SET_TITLE_SUFFIX = 0x3F6,
|
||||
CMSG_SPELLCLICK = 0x3F7,
|
||||
SMSG_LOOT_LIST = 0x3F8,
|
||||
CMSG_GM_CHARACTER_RESTORE = 0x3F9,
|
||||
CMSG_GM_CHARACTER_SAVE = 0x3FA,
|
||||
SMSG_VOICESESSION_FULL = 0x3FB,
|
||||
MSG_GUILD_PERMISSIONS = 0x3FC,
|
||||
MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FD,
|
||||
MSG_GUILD_EVENT_LOG_QUERY = 0x3FE,
|
||||
CMSG_MAELSTROM_RENAME_GUILD = 0x3FF,
|
||||
CMSG_GET_MIRRORIMAGE_DATA = 0x400,
|
||||
SMSG_MIRRORIMAGE_DATA = 0x401,
|
||||
SMSG_FORCE_DISPLAY_UPDATE = 0x402,
|
||||
SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x403,
|
||||
CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x404,
|
||||
SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405,
|
||||
CMSG_KEEP_ALIVE = 0x406,
|
||||
SMSG_RAID_READY_CHECK_ERROR = 0x407,
|
||||
CMSG_OPT_OUT_OF_LOOT = 0x408,
|
||||
MSG_QUERY_GUILD_BANK_TEXT = 0x409,
|
||||
CMSG_SET_GUILD_BANK_TEXT = 0x40A,
|
||||
CMSG_SET_GRANTABLE_LEVELS = 0x40B,
|
||||
CMSG_GRANT_LEVEL = 0x40C,
|
||||
CMSG_REFER_A_FRIEND = 0x40D,
|
||||
MSG_GM_CHANGE_ARENA_RATING = 0x40E,
|
||||
CMSG_DECLINE_CHANNEL_INVITE = 0x40F,
|
||||
CMSG_GROUPACTION_THROTTLED = 0x410,
|
||||
SMSG_OVERRIDE_LIGHT = 0x411,
|
||||
SMSG_TOTEM_CREATED = 0x412,
|
||||
CMSG_TOTEM_DESTROYED = 0x413,
|
||||
CMSG_EXPIRE_RAID_INSTANCE = 0x414,
|
||||
CMSG_NO_SPELL_VARIANCE = 0x415,
|
||||
CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x416,
|
||||
SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x417,
|
||||
CMSG_SET_PLAYER_DECLINED_NAMES = 0x418,
|
||||
SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x419,
|
||||
CMSG_QUERY_SERVER_BUCK_DATA = 0x41A,
|
||||
CMSG_CLEAR_SERVER_BUCK_DATA = 0x41B,
|
||||
SMSG_SERVER_BUCK_DATA = 0x41C,
|
||||
SMSG_SEND_UNLEARN_SPELLS = 0x41D,
|
||||
SMSG_PROPOSE_LEVEL_GRANT = 0x41E,
|
||||
CMSG_ACCEPT_LEVEL_GRANT = 0x41F,
|
||||
SMSG_REFER_A_FRIEND_FAILURE = 0x420,
|
||||
SMSG_SPLINE_MOVE_SET_FLYING = 0x421,
|
||||
SMSG_SPLINE_MOVE_UNSET_FLYING = 0x422,
|
||||
SMSG_SUMMON_CANCEL = 0x423
|
||||
SMSG_VOICE_SESSION_ENABLE = 0x3B0,
|
||||
SMSG_VOICE_PARENTAL_CONTROLS = 0x3B1,
|
||||
CMSG_GM_WHISPER = 0x3B2,
|
||||
SMSG_GM_MESSAGECHAT = 0x3B3,
|
||||
MSG_GM_GEARRATING = 0x3B4,
|
||||
CMSG_COMMENTATOR_ENABLE = 0x3B5,
|
||||
SMSG_COMMENTATOR_STATE_CHANGED = 0x3B6,
|
||||
CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B7,
|
||||
SMSG_COMMENTATOR_MAP_INFO = 0x3B8,
|
||||
CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9,
|
||||
SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3BA,
|
||||
SMSG_COMMENTATOR_PLAYER_INFO = 0x3BB,
|
||||
CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BC,
|
||||
CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BD,
|
||||
CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BE,
|
||||
SMSG_CLEAR_TARGET = 0x3BF,
|
||||
CMSG_BOT_DETECTED = 0x3C0,
|
||||
SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C1,
|
||||
CMSG_CHEAT_PLAYER_LOGIN = 0x3C2,
|
||||
CMSG_CHEAT_PLAYER_LOOKUP = 0x3C3,
|
||||
SMSG_CHEAT_PLAYER_LOOKUP = 0x3C4,
|
||||
SMSG_KICK_REASON = 0x3C5,
|
||||
MSG_RAID_READY_CHECK_FINISHED = 0x3C6,
|
||||
CMSG_COMPLAIN = 0x3C7,
|
||||
SMSG_COMPLAIN_RESULT = 0x3C8,
|
||||
SMSG_FEATURE_SYSTEM_STATUS = 0x3C9,
|
||||
CMSG_GM_SHOW_COMPLAINTS = 0x3CA,
|
||||
CMSG_GM_UNSQUELCH = 0x3CB,
|
||||
CMSG_CHANNEL_SILENCE_VOICE = 0x3CC,
|
||||
CMSG_CHANNEL_SILENCE_ALL = 0x3CD,
|
||||
CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CE,
|
||||
CMSG_CHANNEL_UNSILENCE_ALL = 0x3CF,
|
||||
CMSG_TARGET_CAST = 0x3D0,
|
||||
CMSG_TARGET_SCRIPT_CAST = 0x3D1,
|
||||
CMSG_CHANNEL_DISPLAY_LIST = 0x3D2,
|
||||
CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D3,
|
||||
CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D4,
|
||||
SMSG_CHANNEL_MEMBER_COUNT = 0x3D5,
|
||||
CMSG_CHANNEL_VOICE_ON = 0x3D6,
|
||||
CMSG_CHANNEL_VOICE_OFF = 0x3D7,
|
||||
CMSG_DEBUG_LIST_TARGETS = 0x3D8,
|
||||
SMSG_DEBUG_LIST_TARGETS = 0x3D9,
|
||||
SMSG_AVAILABLE_VOICE_CHANNEL = 0x3DA,
|
||||
CMSG_ADD_VOICE_IGNORE = 0x3DB,
|
||||
CMSG_DEL_VOICE_IGNORE = 0x3DC,
|
||||
CMSG_PARTY_SILENCE = 0x3DD,
|
||||
CMSG_PARTY_UNSILENCE = 0x3DE,
|
||||
MSG_NOTIFY_PARTY_SQUELCH = 0x3DF,
|
||||
SMSG_COMSAT_RECONNECT_TRY = 0x3E0,
|
||||
SMSG_COMSAT_DISCONNECT = 0x3E1,
|
||||
SMSG_COMSAT_CONNECT_FAIL = 0x3E2,
|
||||
SMSG_VOICE_CHAT_STATUS = 0x3E3,
|
||||
CMSG_REPORT_PVP_AFK = 0x3E4,
|
||||
CMSG_REPORT_PVP_AFK_RESULT = 0x3E5,
|
||||
CMSG_GUILD_BANKER_ACTIVATE = 0x3E6,
|
||||
CMSG_GUILD_BANK_QUERY_TAB = 0x3E7,
|
||||
SMSG_GUILD_BANK_LIST = 0x3E8,
|
||||
CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E9,
|
||||
CMSG_GUILD_BANK_BUY_TAB = 0x3EA,
|
||||
CMSG_GUILD_BANK_UPDATE_TAB = 0x3EB,
|
||||
CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EC,
|
||||
CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3ED,
|
||||
MSG_GUILD_BANK_LOG_QUERY = 0x3EE,
|
||||
CMSG_SET_CHANNEL_WATCH = 0x3EF,
|
||||
SMSG_USERLIST_ADD = 0x3F0,
|
||||
SMSG_USERLIST_REMOVE = 0x3F1,
|
||||
SMSG_USERLIST_UPDATE = 0x3F2,
|
||||
CMSG_CLEAR_CHANNEL_WATCH = 0x3F3,
|
||||
SMSG_INSPECT_TALENT = 0x3F4,
|
||||
SMSG_GOGOGO_OBSOLETE = 0x3F5,
|
||||
SMSG_ECHO_PARTY_SQUELCH = 0x3F6,
|
||||
CMSG_SET_TITLE_SUFFIX = 0x3F7,
|
||||
CMSG_SPELLCLICK = 0x3F8,
|
||||
SMSG_LOOT_LIST = 0x3F9,
|
||||
CMSG_GM_CHARACTER_RESTORE = 0x3FA,
|
||||
CMSG_GM_CHARACTER_SAVE = 0x3FB,
|
||||
SMSG_VOICESESSION_FULL = 0x3FC,
|
||||
MSG_GUILD_PERMISSIONS = 0x3FD,
|
||||
MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FE,
|
||||
MSG_GUILD_EVENT_LOG_QUERY = 0x3FF,
|
||||
CMSG_MAELSTROM_RENAME_GUILD = 0x400,
|
||||
CMSG_GET_MIRRORIMAGE_DATA = 0x401,
|
||||
SMSG_MIRRORIMAGE_DATA = 0x402,
|
||||
SMSG_FORCE_DISPLAY_UPDATE = 0x403,
|
||||
SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x404,
|
||||
CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405,
|
||||
SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x406,
|
||||
CMSG_KEEP_ALIVE = 0x407,
|
||||
SMSG_RAID_READY_CHECK_ERROR = 0x408,
|
||||
CMSG_OPT_OUT_OF_LOOT = 0x409,
|
||||
MSG_QUERY_GUILD_BANK_TEXT = 0x40A,
|
||||
CMSG_SET_GUILD_BANK_TEXT = 0x40B,
|
||||
CMSG_SET_GRANTABLE_LEVELS = 0x40C,
|
||||
CMSG_GRANT_LEVEL = 0x40D,
|
||||
CMSG_REFER_A_FRIEND = 0x40E,
|
||||
MSG_GM_CHANGE_ARENA_RATING = 0x40F,
|
||||
CMSG_DECLINE_CHANNEL_INVITE = 0x410,
|
||||
CMSG_GROUPACTION_THROTTLED = 0x411,
|
||||
SMSG_OVERRIDE_LIGHT = 0x412,
|
||||
SMSG_TOTEM_CREATED = 0x413,
|
||||
CMSG_TOTEM_DESTROYED = 0x414,
|
||||
CMSG_EXPIRE_RAID_INSTANCE = 0x415,
|
||||
CMSG_NO_SPELL_VARIANCE = 0x416,
|
||||
CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x417,
|
||||
SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x418,
|
||||
CMSG_SET_PLAYER_DECLINED_NAMES = 0x419,
|
||||
SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x41A,
|
||||
CMSG_QUERY_SERVER_BUCK_DATA = 0x41B,
|
||||
CMSG_CLEAR_SERVER_BUCK_DATA = 0x41C,
|
||||
SMSG_SERVER_BUCK_DATA = 0x41D,
|
||||
SMSG_SEND_UNLEARN_SPELLS = 0x41E,
|
||||
SMSG_PROPOSE_LEVEL_GRANT = 0x41F,
|
||||
CMSG_ACCEPT_LEVEL_GRANT = 0x420,
|
||||
SMSG_REFER_A_FRIEND_FAILURE = 0x421,
|
||||
SMSG_SPLINE_MOVE_SET_FLYING = 0x422,
|
||||
SMSG_SPLINE_MOVE_UNSET_FLYING = 0x423,
|
||||
SMSG_SUMMON_CANCEL = 0x424,
|
||||
CMSG_CHANGE_PERSONAL_ARENA_RATING = 0x425,
|
||||
CMSG_ALTER_APPEARANCE = 0x426,
|
||||
SMSG_ENABLE_BARBER_SHOP = 0x427,
|
||||
SMSG_BARBER_SHOP_RESULT = 0x428,
|
||||
CMSG_CALENDAR_GET_CALENDAR = 0x429,
|
||||
CMSG_CALENDAR_GET_EVENT = 0x42A,
|
||||
CMSG_CALENDAR_GUILD_FILTER = 0x42B,
|
||||
CMSG_CALENDAR_ARENA_TEAM = 0x42C,
|
||||
CMSG_CALENDAR_ADD_EVENT = 0x42D,
|
||||
CMSG_CALENDAR_UPDATE_EVENT = 0x42E,
|
||||
CMSG_CALENDAR_REMOVE_EVENT = 0x42F,
|
||||
CMSG_CALENDAR_COPY_EVENT = 0x430,
|
||||
CMSG_CALENDAR_EVENT_INVITE = 0x431,
|
||||
CMSG_CALENDAR_EVENT_RSVP = 0x432,
|
||||
CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x433,
|
||||
CMSG_CALENDAR_EVENT_STATUS = 0x434,
|
||||
CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x435,
|
||||
SMSG_CALENDAR_SEND_CALENDAR = 0x436,
|
||||
SMSG_CALENDAR_SEND_EVENT = 0x437,
|
||||
SMSG_CALENDAR_FILTER_GUILD = 0x438,
|
||||
SMSG_CALENDAR_ARENA_TEAM = 0x439,
|
||||
SMSG_CALENDAR_EVENT_INVITE = 0x43A,
|
||||
SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x43B,
|
||||
SMSG_CALENDAR_EVENT_STATUS = 0x43C,
|
||||
SMSG_CALENDAR_COMMAND_RESULT = 0x43D,
|
||||
SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x43E,
|
||||
SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x43F,
|
||||
SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x440,
|
||||
SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x441,
|
||||
SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x442,
|
||||
SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x443,
|
||||
SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444,
|
||||
SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445,
|
||||
CMSG_CALENDAR_COMPLAIN = 0x446,
|
||||
CMSG_CALENDAR_GET_NUM_PENDING = 0x447,
|
||||
SMSG_CALENDAR_SEND_NUM_PENDING = 0x448,
|
||||
CMSG_SAVE_DANCE = 0x449,
|
||||
SMSG_NOTIFY_DANCE = 0x44A,
|
||||
CMSG_PLAY_DANCE = 0x44B,
|
||||
SMSG_PLAY_DANCE = 0x44C,
|
||||
CMSG_LOAD_DANCES = 0x44D,
|
||||
CMSG_STOP_DANCE = 0x44E,
|
||||
SMSG_STOP_DANCE = 0x44F,
|
||||
CMSG_SYNC_DANCE = 0x450,
|
||||
CMSG_DANCE_QUERY = 0x451,
|
||||
SMSG_DANCE_QUERY_RESPONSE = 0x452,
|
||||
SMSG_INVALIDATE_DANCE = 0x453,
|
||||
CMSG_DELETE_DANCE = 0x454,
|
||||
SMSG_LEARNED_DANCE_MOVES = 0x455,
|
||||
CMSG_LEARN_DANCE_MOVE = 0x456,
|
||||
CMSG_UNLEARN_DANCE_MOVE = 0x457,
|
||||
CMSG_SET_RUNE_COUNT = 0x458,
|
||||
CMSG_SET_RUNE_COOLDOWN = 0x459,
|
||||
MSG_MOVE_SET_PITCH_RATE_CHEAT = 0x45A,
|
||||
MSG_MOVE_SET_PITCH_RATE = 0x45B,
|
||||
SMSG_FORCE_PITCH_RATE_CHANGE = 0x45C,
|
||||
CMSG_FORCE_PITCH_RATE_CHANGE_ACK = 0x45D,
|
||||
SMSG_SPLINE_SET_PITCH_RATE = 0x45E,
|
||||
SMSG_MOVE_ABANDON_TRANSPORT = 0x45F,
|
||||
MSG_MOVE_ABANDON_TRANSPORT = 0x460,
|
||||
CMSG_MOVE_ABANDON_TRANSPORT_ACK = 0x461,
|
||||
CMSG_UPDATE_MISSILE_TRAJECTORY = 0x462,
|
||||
SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x463,
|
||||
SMSG_TRIGGER_MOVIE = 0x464,
|
||||
CMSG_COMPLETE_MOVIE = 0x465,
|
||||
CMSG_SET_GLYPH_SLOT = 0x466,
|
||||
CMSG_SET_GLYPH = 0x467,
|
||||
SMSG_ACHIEVEMENT_EARNED = 0x468,
|
||||
SMSG_DYNAMIC_DROP_ROLL_RESULT = 0x469,
|
||||
SMSG_CRITERIA_UPDATE = 0x46A,
|
||||
CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x46B,
|
||||
SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x46C,
|
||||
CMSG_DISMISS_CONTROLLED_VEHICLE = 0x46D,
|
||||
CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x46E,
|
||||
SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x46F,
|
||||
CMSG_SET_CRITERIA_CHEAT = 0x470,
|
||||
SMSG_GROUP_SWAP_FAILED = 0x471,
|
||||
CMSG_UNITANIMTIER_CHEAT = 0x472,
|
||||
CMSG_CHAR_CUSTOMIZE = 0x473,
|
||||
SMSG_CHAR_CUSTOMIZE = 0x474,
|
||||
SMSG_PET_RENAMEABLE = 0x475,
|
||||
CMSG_REQUEST_VEHICLE_EXIT = 0x476,
|
||||
CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x477,
|
||||
CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x478,
|
||||
CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x479,
|
||||
CMSG_PET_LEARN_TALENT = 0x47A,
|
||||
CMSG_PET_UNLEARN_TALENTS = 0x47B,
|
||||
SMSG_SET_PHASE_SHIFT = 0x47C,
|
||||
SMSG_ALL_ACHIEVEMENT_DATA = 0x47D,
|
||||
CMSG_FORCE_SAY_CHEAT = 0x47E,
|
||||
SMSG_HEALTH_UPDATE = 0x47F,
|
||||
SMSG_POWER_UPDATE = 0x480,
|
||||
CMSG_GAMEOBJ_REPORT_USE = 0x481,
|
||||
SMSG_HIGHEST_THREAT_UPDATE = 0x482,
|
||||
SMSG_THREAT_UPDATE = 0x483,
|
||||
SMSG_THREAT_REMOVE = 0x484,
|
||||
SMSG_THREAT_CLEAR = 0x485,
|
||||
SMSG_CONVERT_RUNE = 0x486,
|
||||
SMSG_RESYNC_RUNES = 0x487,
|
||||
SMSG_ADD_RUNE_POWER = 0x488,
|
||||
CMSG_START_QUEST = 0x489,
|
||||
CMSG_REMOVE_GLYPH = 0x48A,
|
||||
CMSG_DUMP_OBJECTS = 0x48B,
|
||||
SMSG_DUMP_OBJECTS_DATA = 0x48C,
|
||||
CMSG_DISMISS_CRITTER = 0x48D,
|
||||
SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x48E,
|
||||
CMSG_AUCTION_LIST_PENDING_SALES = 0x48F,
|
||||
SMSG_AUCTION_LIST_PENDING_SALES = 0x490,
|
||||
SMSG_MODIFY_COOLDOWN = 0x491,
|
||||
SMSG_PET_UPDATE_COMBO_POINTS = 0x492,
|
||||
CMSG_ENABLETAXI = 0x493,
|
||||
SMSG_PRE_RESURRECT = 0x494,
|
||||
SMSG_AURA_UPDATE_ALL = 0x495,
|
||||
SMSG_AURA_UPDATE = 0x496,
|
||||
CMSG_FLOOD_GRACE_CHEAT = 0x497,
|
||||
SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498,
|
||||
SMSG_PET_LEARNED_SPELL = 0x499,
|
||||
SMSG_PET_REMOVED_SPELL = 0x49A,
|
||||
CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x49B,
|
||||
CMSG_HEARTH_AND_RESURRECT = 0x49C,
|
||||
SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x49D,
|
||||
SMSG_CRITERIA_DELETED = 0x49E,
|
||||
SMSG_ACHIEVEMENT_DELETED = 0x49F,
|
||||
CMSG_SERVER_INFO_QUERY = 0x4A0,
|
||||
SMSG_SERVER_INFO_RESPONSE = 0x4A1,
|
||||
CMSG_CHECK_LOGIN_CRITERIA = 0x4A2,
|
||||
SMSG_SERVER_BUCK_DATA_START = 0x4A3,
|
||||
CMSG_QUERY_VEHICLE_STATUS = 0x4A4,
|
||||
SMSG_PET_GUIDS = 0x4A5,
|
||||
NUM_MSG_TYPES = 0x4A6
|
||||
};
|
||||
|
||||
// Don't forget to change this value and add opcode name to Opcodes.cpp when you add new opcode!
|
||||
#define NUM_MSG_TYPES 0x424
|
||||
|
||||
/// Player state
|
||||
enum SessionStatus
|
||||
{
|
||||
|
|
@ -1102,7 +1236,6 @@ enum SessionStatus
|
|||
STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only)
|
||||
};
|
||||
|
||||
class WorldSession;
|
||||
class WorldPacket;
|
||||
|
||||
struct OpcodeHandler
|
||||
|
|
|
|||
392
src/game/Pet.cpp
392
src/game/Pet.cpp
|
|
@ -39,27 +39,6 @@ char const* petTypeSuffix[MAX_PET_TYPE] =
|
|||
"'s Companion" // MINI_PET
|
||||
};
|
||||
|
||||
//numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy)
|
||||
uint32 const LevelUpLoyalty[6] =
|
||||
{
|
||||
5500,
|
||||
11500,
|
||||
17000,
|
||||
23500,
|
||||
31000,
|
||||
39500,
|
||||
};
|
||||
|
||||
uint32 const LevelStartLoyalty[6] =
|
||||
{
|
||||
2000,
|
||||
4500,
|
||||
7000,
|
||||
10000,
|
||||
13500,
|
||||
17500,
|
||||
};
|
||||
|
||||
Pet::Pet(PetType type) : Creature()
|
||||
{
|
||||
m_isPet = true;
|
||||
|
|
@ -69,17 +48,16 @@ Pet::Pet(PetType type) : Creature()
|
|||
m_removed = false;
|
||||
m_regenTimer = 4000;
|
||||
m_happinessTimer = 7500;
|
||||
m_loyaltyTimer = 12000;
|
||||
m_duration = 0;
|
||||
m_bonusdamage = 0;
|
||||
|
||||
m_loyaltyPoints = 0;
|
||||
m_TrainingPoints = 0;
|
||||
m_resetTalentsCost = 0;
|
||||
m_resetTalentsTime = 0;
|
||||
|
||||
m_auraUpdateMask = 0;
|
||||
|
||||
m_loading = false;
|
||||
|
||||
// pets always have a charminfo, even if they are not actually charmed
|
||||
CharmInfo* charmInfo = InitCharmInfo(this);
|
||||
|
||||
|
|
@ -125,24 +103,26 @@ void Pet::RemoveFromWorld()
|
|||
|
||||
bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current )
|
||||
{
|
||||
m_loading = true;
|
||||
|
||||
uint32 ownerid = owner->GetGUIDLow();
|
||||
|
||||
QueryResult *result;
|
||||
|
||||
if(petnumber)
|
||||
// known petnumber entry 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber);
|
||||
// known petnumber entry 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber);
|
||||
else if(current)
|
||||
// current pet (slot 0) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
|
||||
// current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid );
|
||||
else if(petentry)
|
||||
// known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets)
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
|
||||
// 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry );
|
||||
else
|
||||
// any current or other non-stabled pet (for hunter "call pet")
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
|
||||
// 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20
|
||||
result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid);
|
||||
|
||||
if(!result)
|
||||
return false;
|
||||
|
|
@ -157,7 +137,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32 summon_spell_id = fields[21].GetUInt32();
|
||||
uint32 summon_spell_id = fields[19].GetUInt32();
|
||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id);
|
||||
|
||||
bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0;
|
||||
|
|
@ -191,8 +171,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
return false;
|
||||
}
|
||||
|
||||
setPetType(PetType(fields[22].GetUInt8()));
|
||||
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
|
||||
setPetType(PetType(fields[20].GetUInt8()));
|
||||
SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction());
|
||||
SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id);
|
||||
|
||||
CreatureInfo const *cinfo = GetCreatureInfo();
|
||||
|
|
@ -203,72 +183,67 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
delete result;
|
||||
return true;
|
||||
}
|
||||
if(getPetType()==HUNTER_PET || (getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
|
||||
|
||||
if(getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK))
|
||||
m_charmInfo->SetPetNumber(pet_number, true);
|
||||
else
|
||||
m_charmInfo->SetPetNumber(pet_number, false);
|
||||
SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner->GetGUID());
|
||||
|
||||
SetOwnerGUID(owner->GetGUID());
|
||||
SetDisplayId(fields[3].GetUInt32());
|
||||
SetNativeDisplayId(fields[3].GetUInt32());
|
||||
uint32 petlevel=fields[4].GetUInt32();
|
||||
SetUInt32Value(UNIT_NPC_FLAGS , 0);
|
||||
SetName(fields[11].GetString());
|
||||
uint32 petlevel = fields[4].GetUInt32();
|
||||
SetUInt32Value(UNIT_NPC_FLAGS, 0);
|
||||
SetName(fields[9].GetString());
|
||||
|
||||
switch(getPetType())
|
||||
{
|
||||
|
||||
case SUMMON_PET:
|
||||
petlevel=owner->getLevel();
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
// this enables popup window (pet dismiss, cancel)
|
||||
break;
|
||||
case HUNTER_PET:
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[8].GetUInt32());
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
|
||||
if(fields[12].GetBool())
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
|
||||
else
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[7].GetUInt32());
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[10].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED);
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
// this enables popup window (pet abandon, cancel)
|
||||
SetTP(fields[9].GetInt32());
|
||||
SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
|
||||
SetPower( POWER_HAPPINESS,fields[15].GetUInt32());
|
||||
SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
|
||||
SetPower(POWER_HAPPINESS, fields[13].GetUInt32());
|
||||
setPowerType(POWER_FOCUS);
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType());
|
||||
sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType());
|
||||
}
|
||||
InitStatsForLevel( petlevel);
|
||||
|
||||
InitStatsForLevel(petlevel);
|
||||
SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32());
|
||||
SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID());
|
||||
SetCreatorGUID(owner->GetGUID());
|
||||
|
||||
m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() ));
|
||||
m_loyaltyPoints = fields[7].GetInt32();
|
||||
m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8()));
|
||||
|
||||
uint32 savedhealth = fields[13].GetUInt32();
|
||||
uint32 savedmana = fields[14].GetUInt32();
|
||||
uint32 savedhealth = fields[11].GetUInt32();
|
||||
uint32 savedmana = fields[12].GetUInt32();
|
||||
|
||||
// set current pet as current
|
||||
if(fields[10].GetUInt32() != 0)
|
||||
if(fields[8].GetUInt32() != 0)
|
||||
{
|
||||
CharacterDatabase.BeginTransaction();
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'",ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'",ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber());
|
||||
CharacterDatabase.CommitTransaction();
|
||||
}
|
||||
|
||||
if(!is_temporary_summoned)
|
||||
{
|
||||
// permanent controlled pets store state in DB
|
||||
Tokens tokens = StrSplit(fields[16].GetString(), " ");
|
||||
Tokens tokens = StrSplit(fields[14].GetString(), " ");
|
||||
|
||||
if(tokens.size() != 20)
|
||||
{
|
||||
|
|
@ -286,7 +261,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
}
|
||||
|
||||
//init teach spells
|
||||
tokens = StrSplit(fields[17].GetString(), " ");
|
||||
tokens = StrSplit(fields[15].GetString(), " ");
|
||||
for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index)
|
||||
{
|
||||
uint32 tmp = atol((*iter).c_str());
|
||||
|
|
@ -301,7 +276,10 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
}
|
||||
|
||||
// since last save (in seconds)
|
||||
uint32 timediff = (time(NULL) - fields[18].GetUInt32());
|
||||
uint32 timediff = (time(NULL) - fields[16].GetUInt32());
|
||||
|
||||
m_resetTalentsCost = fields[17].GetUInt32();
|
||||
m_resetTalentsTime = fields[18].GetUInt64();
|
||||
|
||||
delete result;
|
||||
|
||||
|
|
@ -367,6 +345,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
|
|||
}
|
||||
}
|
||||
|
||||
m_loading = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -409,10 +388,6 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
case PET_SAVE_IN_STABLE_SLOT_2:
|
||||
case PET_SAVE_NOT_IN_SLOT:
|
||||
{
|
||||
uint32 loyalty =1;
|
||||
if(getPetType()!=HUNTER_PET)
|
||||
loyalty = GetLoyaltyLevel();
|
||||
|
||||
uint32 owner = GUID_LOPART(GetOwnerGUID());
|
||||
std::string name = m_name;
|
||||
CharacterDatabase.escape_string(name);
|
||||
|
|
@ -429,7 +404,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner );
|
||||
// save pet
|
||||
std::ostringstream ss;
|
||||
ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) "
|
||||
ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) "
|
||||
<< "VALUES ("
|
||||
<< m_charmInfo->GetPetNumber() << ", "
|
||||
<< GetEntry() << ", "
|
||||
|
|
@ -438,9 +413,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
<< getLevel() << ", "
|
||||
<< GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", "
|
||||
<< uint32(m_charmInfo->GetReactState()) << ", "
|
||||
<< m_loyaltyPoints << ", "
|
||||
<< GetLoyaltyLevel() << ", "
|
||||
<< m_TrainingPoints << ", "
|
||||
<< uint32(GetFreeTalentPoints()) << ", "
|
||||
<< uint32(mode) << ", '"
|
||||
<< name.c_str() << "', "
|
||||
<< uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", "
|
||||
|
|
@ -513,12 +486,12 @@ void Pet::setDeathState(DeathState s) // overwrite virtual
|
|||
if(!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND))
|
||||
ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE);
|
||||
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||
}
|
||||
}
|
||||
else if(getDeathState()==ALIVE)
|
||||
{
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
|
||||
CastPetAuras(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -544,7 +517,7 @@ void Pet::Update(uint32 diff)
|
|||
{
|
||||
// unsummon pet that lost owner
|
||||
Unit* owner = GetOwner();
|
||||
if(!owner || !IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) || isControlled() && !owner->GetPetGUID())
|
||||
if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID()))
|
||||
{
|
||||
Remove(PET_SAVE_NOT_IN_SLOT, true);
|
||||
return;
|
||||
|
|
@ -590,14 +563,6 @@ void Pet::Update(uint32 diff)
|
|||
else
|
||||
m_happinessTimer -= diff;
|
||||
|
||||
if(m_loyaltyTimer <= diff)
|
||||
{
|
||||
TickLoyaltyChange();
|
||||
m_loyaltyTimer = 12000;
|
||||
}
|
||||
else
|
||||
m_loyaltyTimer -= diff;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -629,83 +594,12 @@ void Pet::LooseHappiness()
|
|||
uint32 curValue = GetPower(POWER_HAPPINESS);
|
||||
if (curValue <= 0)
|
||||
return;
|
||||
int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
|
||||
int32 addvalue = 670; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs)
|
||||
if(isInCombat()) //we know in combat happiness fades faster, multiplier guess
|
||||
addvalue = int32(addvalue * 1.5);
|
||||
ModifyPower(POWER_HAPPINESS, -addvalue);
|
||||
}
|
||||
|
||||
void Pet::ModifyLoyalty(int32 addvalue)
|
||||
{
|
||||
uint32 loyaltylevel = GetLoyaltyLevel();
|
||||
|
||||
if(addvalue > 0) //only gain influenced, not loss
|
||||
addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY));
|
||||
|
||||
if(loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel)))
|
||||
return;
|
||||
|
||||
m_loyaltyPoints += addvalue;
|
||||
|
||||
if(m_loyaltyPoints < 0)
|
||||
{
|
||||
if(loyaltylevel > REBELLIOUS)
|
||||
{
|
||||
//level down
|
||||
--loyaltylevel;
|
||||
SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
|
||||
m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
|
||||
SetTP(m_TrainingPoints - int32(getLevel()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_loyaltyPoints = 0;
|
||||
Unit* owner = GetOwner();
|
||||
if(owner && owner->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_BROKEN, 0);
|
||||
((Player*)owner)->GetSession()->SendPacket(&data);
|
||||
|
||||
//run away
|
||||
((Player*)owner)->RemovePet(this,PET_SAVE_AS_DELETED);
|
||||
}
|
||||
}
|
||||
}
|
||||
//level up
|
||||
else if(m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel)))
|
||||
{
|
||||
++loyaltylevel;
|
||||
SetLoyaltyLevel(LoyaltyLevel(loyaltylevel));
|
||||
m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel);
|
||||
SetTP(m_TrainingPoints + getLevel());
|
||||
}
|
||||
}
|
||||
|
||||
void Pet::TickLoyaltyChange()
|
||||
{
|
||||
int32 addvalue;
|
||||
|
||||
switch(GetHappinessState())
|
||||
{
|
||||
case HAPPY: addvalue = 20; break;
|
||||
case CONTENT: addvalue = 10; break;
|
||||
case UNHAPPY: addvalue = -20; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
ModifyLoyalty(addvalue);
|
||||
}
|
||||
|
||||
void Pet::KillLoyaltyBonus(uint32 level)
|
||||
{
|
||||
if(level > 100)
|
||||
return;
|
||||
|
||||
//at lower levels gain is faster | the lower loyalty the more loyalty is gained
|
||||
uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel()));
|
||||
ModifyLoyalty(bonus);
|
||||
}
|
||||
|
||||
HappinessState Pet::GetHappinessState()
|
||||
{
|
||||
if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE)
|
||||
|
|
@ -716,11 +610,6 @@ HappinessState Pet::GetHappinessState()
|
|||
return CONTENT;
|
||||
}
|
||||
|
||||
void Pet::SetLoyaltyLevel(LoyaltyLevel level)
|
||||
{
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, 1, level);
|
||||
}
|
||||
|
||||
bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
|
||||
{
|
||||
uint8 activecount = 1;
|
||||
|
|
@ -757,82 +646,6 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Pet::HasTPForSpell(uint32 spellid)
|
||||
{
|
||||
int32 neededtrainp = GetTPForSpell(spellid);
|
||||
if((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 Pet::GetTPForSpell(uint32 spellid)
|
||||
{
|
||||
uint32 basetrainp = 0;
|
||||
|
||||
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid);
|
||||
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid);
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
|
||||
{
|
||||
if(!_spell_idx->second->reqtrainpoints)
|
||||
return 0;
|
||||
|
||||
basetrainp = _spell_idx->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 spenttrainp = 0;
|
||||
uint32 chainstart = spellmgr.GetFirstSpellInChain(spellid);
|
||||
|
||||
for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
|
||||
{
|
||||
if(itr->second->state == PETSPELL_REMOVED)
|
||||
continue;
|
||||
|
||||
if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart)
|
||||
{
|
||||
SkillLineAbilityMap::const_iterator _lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first);
|
||||
SkillLineAbilityMap::const_iterator _upper = spellmgr.GetEndSkillLineAbilityMap(itr->first);
|
||||
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2)
|
||||
{
|
||||
if(_spell_idx2->second->reqtrainpoints > spenttrainp)
|
||||
{
|
||||
spenttrainp = _spell_idx2->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return int32(basetrainp) - int32(spenttrainp);
|
||||
}
|
||||
|
||||
uint32 Pet::GetMaxLoyaltyPoints(uint32 level)
|
||||
{
|
||||
return LevelUpLoyalty[level - 1];
|
||||
}
|
||||
|
||||
uint32 Pet::GetStartLoyaltyPoints(uint32 level)
|
||||
{
|
||||
return LevelStartLoyalty[level - 1];
|
||||
}
|
||||
|
||||
void Pet::SetTP(int32 TP)
|
||||
{
|
||||
m_TrainingPoints = TP;
|
||||
SetUInt32Value(UNIT_TRAINING_POINTS, (uint32)GetDispTP());
|
||||
}
|
||||
|
||||
int32 Pet::GetDispTP()
|
||||
{
|
||||
if(getPetType()!= HUNTER_PET)
|
||||
return(0);
|
||||
if(m_TrainingPoints < 0)
|
||||
return -m_TrainingPoints;
|
||||
else
|
||||
return -(m_TrainingPoints + 1);
|
||||
}
|
||||
|
||||
void Pet::Remove(PetSaveMode mode, bool returnreagent)
|
||||
{
|
||||
Unit* owner = GetOwner();
|
||||
|
|
@ -895,9 +708,6 @@ void Pet::GivePetXP(uint32 xp)
|
|||
}
|
||||
|
||||
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP);
|
||||
|
||||
if(getPetType() == HUNTER_PET)
|
||||
KillLoyaltyBonus(level);
|
||||
}
|
||||
|
||||
void Pet::GivePetLevel(uint32 level)
|
||||
|
|
@ -905,9 +715,7 @@ void Pet::GivePetLevel(uint32 level)
|
|||
if(!level)
|
||||
return;
|
||||
|
||||
InitStatsForLevel( level);
|
||||
|
||||
SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1));
|
||||
InitStatsForLevel(level);
|
||||
}
|
||||
|
||||
bool Pet::CreateBaseAtCreature(Creature* creature)
|
||||
|
|
@ -965,16 +773,12 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
|
|||
else
|
||||
SetName(creature->GetName());
|
||||
|
||||
m_loyaltyPoints = 1000;
|
||||
if(cinfo->type == CREATURE_TYPE_BEAST)
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED);
|
||||
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) );
|
||||
SetLoyaltyLevel(REBELLIOUS);
|
||||
SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1104,7 +908,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
|
|||
case HUNTER_PET:
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(petlevel))/4));
|
||||
|
||||
learnLevelupSpells();
|
||||
//these formula may not be correct; however, it is designed to be close to what it should be
|
||||
//this makes dps 0.5 of pets level
|
||||
SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) );
|
||||
|
|
@ -1315,10 +1119,6 @@ void Pet::_LoadAuras(uint32 timediff)
|
|||
for (int i = 0; i < TOTAL_AURAS; i++)
|
||||
m_modAuras[i].clear();
|
||||
|
||||
// all aura related fields
|
||||
for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i)
|
||||
SetUInt32Value(i, 0);
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
|
||||
|
||||
if(result)
|
||||
|
|
@ -1507,11 +1307,12 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
|
|||
ToggleAutocast(itr->first, false);
|
||||
|
||||
oldspell_id = itr->first;
|
||||
removeSpell(itr->first);
|
||||
unlearnSpell(itr->first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 tmpslot=slot_id;
|
||||
uint16 tmpslot = slot_id;
|
||||
|
||||
if (tmpslot == 0xffff)
|
||||
{
|
||||
|
|
@ -1545,20 +1346,65 @@ bool Pet::learnSpell(uint16 spell_id)
|
|||
if (!addSpell(spell_id))
|
||||
return false;
|
||||
|
||||
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if(!m_loading)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_LEARNED_SPELL, 2);
|
||||
data << uint16(spell_id);
|
||||
((Player*)GetOwner())->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
Unit* owner = GetOwner();
|
||||
if(owner->GetTypeId()==TYPEID_PLAYER)
|
||||
if(owner->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)owner)->PetSpellInitialize();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pet::removeSpell(uint16 spell_id)
|
||||
void Pet::learnLevelupSpells()
|
||||
{
|
||||
PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family);
|
||||
if(!levelupSpells)
|
||||
return;
|
||||
|
||||
uint32 level = getLevel();
|
||||
|
||||
for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr)
|
||||
{
|
||||
if(itr->first <= level)
|
||||
learnSpell(itr->second);
|
||||
else
|
||||
unlearnSpell(itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
bool Pet::unlearnSpell(uint16 spell_id)
|
||||
{
|
||||
if(removeSpell(spell_id))
|
||||
{
|
||||
if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if(!m_loading)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_REMOVED_SPELL, 2);
|
||||
data << uint16(spell_id);
|
||||
((Player*)GetOwner())->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Pet::removeSpell(uint16 spell_id)
|
||||
{
|
||||
PetSpellMap::iterator itr = m_spells.find(spell_id);
|
||||
if (itr == m_spells.end())
|
||||
return;
|
||||
return false;
|
||||
|
||||
if(itr->second->state == PETSPELL_REMOVED)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if(itr->second->state == PETSPELL_NEW)
|
||||
{
|
||||
|
|
@ -1569,6 +1415,8 @@ void Pet::removeSpell(uint16 spell_id)
|
|||
itr->second->state = PETSPELL_REMOVED;
|
||||
|
||||
RemoveAurasDueToSpell(spell_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pet::_removeSpell(uint16 spell_id)
|
||||
|
|
@ -1588,7 +1436,7 @@ void Pet::InitPetCreateSpells()
|
|||
m_charmInfo->InitPetActionBar();
|
||||
|
||||
m_spells.clear();
|
||||
int32 usedtrainpoints = 0, petspellid;
|
||||
int32 petspellid;
|
||||
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
|
||||
if(CreateSpells)
|
||||
{
|
||||
|
|
@ -1617,23 +1465,12 @@ void Pet::InitPetCreateSpells()
|
|||
petspellid = learn_spellproto->Id;
|
||||
|
||||
addSpell(petspellid);
|
||||
|
||||
SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
|
||||
SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]);
|
||||
|
||||
for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
|
||||
{
|
||||
usedtrainpoints += _spell_idx->second->reqtrainpoints;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LearnPetPassives();
|
||||
|
||||
CastPetAuras(false);
|
||||
|
||||
SetTP(-usedtrainpoints);
|
||||
}
|
||||
|
||||
void Pet::CheckLearning(uint32 spellid)
|
||||
|
|
@ -1687,7 +1524,9 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
|
|||
|
||||
if(apply)
|
||||
{
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++);
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++)
|
||||
; // just search
|
||||
|
||||
if (i == m_autospells.size())
|
||||
{
|
||||
m_autospells.push_back(spellid);
|
||||
|
|
@ -1698,7 +1537,9 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply)
|
|||
else
|
||||
{
|
||||
AutoSpellList::iterator itr2 = m_autospells.begin();
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++);
|
||||
for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++)
|
||||
; // just search
|
||||
|
||||
if (i < m_autospells.size())
|
||||
{
|
||||
m_autospells.erase(itr2);
|
||||
|
|
@ -1721,8 +1562,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
|
|||
if(!InitEntry(Entry))
|
||||
return false;
|
||||
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 );
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE);
|
||||
|
||||
if(getPetType() == MINI_PET) // always non-attackable
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
|
|
|||
|
|
@ -50,16 +50,6 @@ enum HappinessState
|
|||
HAPPY = 3
|
||||
};
|
||||
|
||||
enum LoyaltyLevel
|
||||
{
|
||||
REBELLIOUS = 1,
|
||||
UNRULY = 2,
|
||||
SUBMISSIVE = 3,
|
||||
DEPENDABLE = 4,
|
||||
FAITHFUL = 5,
|
||||
BEST_FRIEND = 6
|
||||
};
|
||||
|
||||
enum PetSpellState
|
||||
{
|
||||
PETSPELL_UNCHANGED = 0,
|
||||
|
|
@ -120,9 +110,6 @@ typedef std::vector<uint32> AutoSpellList;
|
|||
|
||||
#define HAPPINESS_LEVEL_SIZE 333000
|
||||
|
||||
extern const uint32 LevelUpLoyalty[6];
|
||||
extern const uint32 LevelStartLoyalty[6];
|
||||
|
||||
#define ACTIVE_SPELLS_MAX 4
|
||||
|
||||
#define OWNER_MAX_DISTANCE 100
|
||||
|
|
@ -165,14 +152,7 @@ class Pet : public Creature
|
|||
|
||||
void RegenerateFocus();
|
||||
void LooseHappiness();
|
||||
void TickLoyaltyChange();
|
||||
void ModifyLoyalty(int32 addvalue);
|
||||
HappinessState GetHappinessState();
|
||||
uint32 GetMaxLoyaltyPoints(uint32 level);
|
||||
uint32 GetStartLoyaltyPoints(uint32 level);
|
||||
void KillLoyaltyBonus(uint32 level);
|
||||
uint32 GetLoyaltyLevel() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
|
||||
void SetLoyaltyLevel(LoyaltyLevel level);
|
||||
void GivePetXP(uint32 xp);
|
||||
void GivePetLevel(uint32 level);
|
||||
bool InitStatsForLevel(uint32 level);
|
||||
|
|
@ -192,10 +172,8 @@ class Pet : public Creature
|
|||
void UpdateAttackPowerAndDamage(bool ranged = false);
|
||||
void UpdateDamagePhysical(WeaponAttackType attType);
|
||||
|
||||
bool CanTakeMoreActiveSpells(uint32 SpellIconID);
|
||||
void ToggleAutocast(uint32 spellid, bool apply);
|
||||
bool HasTPForSpell(uint32 spellid);
|
||||
int32 GetTPForSpell(uint32 spellid);
|
||||
bool CanTakeMoreActiveSpells(uint32 SpellIconID);
|
||||
void ToggleAutocast(uint32 spellid, bool apply);
|
||||
|
||||
bool HasSpell(uint32 spell) const;
|
||||
void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; }
|
||||
|
|
@ -213,7 +191,9 @@ class Pet : public Creature
|
|||
|
||||
bool addSpell(uint16 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, uint16 slot_id=0xffff, PetSpellType type = PETSPELL_NORMAL);
|
||||
bool learnSpell(uint16 spell_id);
|
||||
void removeSpell(uint16 spell_id);
|
||||
void learnLevelupSpells();
|
||||
bool unlearnSpell(uint16 spell_id);
|
||||
bool removeSpell(uint16 spell_id);
|
||||
bool _removeSpell(uint16 spell_id);
|
||||
|
||||
PetSpellMap m_spells;
|
||||
|
|
@ -223,11 +203,10 @@ class Pet : public Creature
|
|||
void InitPetCreateSpells();
|
||||
void CheckLearning(uint32 spellid);
|
||||
uint32 resetTalentsCost() const;
|
||||
uint8 GetMaxTalentPointsForLevel(uint32 level) { return (level >= 20) ? ((level - 16) / 4) : 0; }
|
||||
uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); }
|
||||
void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); }
|
||||
|
||||
void SetTP(int32 TP);
|
||||
int32 GetDispTP();
|
||||
|
||||
int32 m_TrainingPoints;
|
||||
uint32 m_resetTalentsCost;
|
||||
time_t m_resetTalentsTime;
|
||||
|
||||
|
|
@ -242,14 +221,12 @@ class Pet : public Creature
|
|||
|
||||
bool m_removed; // prevent overwrite pet state in DB at next Pet::Update if pet already removed(saved)
|
||||
protected:
|
||||
uint32 m_regenTimer;
|
||||
uint32 m_happinessTimer;
|
||||
uint32 m_loyaltyTimer;
|
||||
PetType m_petType;
|
||||
int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets)
|
||||
int32 m_loyaltyPoints;
|
||||
int32 m_bonusdamage;
|
||||
uint64 m_auraUpdateMask;
|
||||
bool m_loading;
|
||||
|
||||
DeclinedName *m_declinedname;
|
||||
|
||||
|
|
|
|||
|
|
@ -157,9 +157,9 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case ACT_DISABLED: //0x8100 spell (disabled), ignore
|
||||
case ACT_CAST: //0x0100
|
||||
case ACT_ENABLED: //0xc100 spell
|
||||
case ACT_DISABLED: // 0x8100 spell (disabled), ignore
|
||||
case ACT_PASSIVE: // 0x0100
|
||||
case ACT_ENABLED: // 0xC100 spell
|
||||
{
|
||||
Unit* unit_target;
|
||||
if(guid2)
|
||||
|
|
@ -240,7 +240,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
|
|||
if(pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
|
||||
{
|
||||
WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
|
||||
data << uint32(spellid) << uint8(2) << uint8(result);
|
||||
data << uint8(0) << uint32(spellid) << uint8(result);
|
||||
switch (result)
|
||||
{
|
||||
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
|
||||
|
|
@ -352,7 +352,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
|
|||
sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state);
|
||||
|
||||
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
|
||||
if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_CAST) && spell_id && !pet->HasSpell(spell_id)))
|
||||
if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id)))
|
||||
{
|
||||
//sign for autocast
|
||||
if(act_state == ACT_ENABLED && spell_id)
|
||||
|
|
@ -522,11 +522,10 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket)
|
|||
{
|
||||
uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell
|
||||
++itr;
|
||||
pet->removeSpell(spell_id);
|
||||
//pet->removeSpell(spell_id);
|
||||
pet->unlearnSpell(spell_id);
|
||||
}
|
||||
|
||||
pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1));
|
||||
|
||||
for(uint8 i = 0; i < 10; i++)
|
||||
{
|
||||
if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED)
|
||||
|
|
@ -596,11 +595,15 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
|
|||
{
|
||||
sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL");
|
||||
|
||||
CHECK_PACKET_SIZE(recvPacket,8+4);
|
||||
CHECK_PACKET_SIZE(recvPacket,8+1+4+1);
|
||||
uint64 guid;
|
||||
uint32 spellid;
|
||||
uint8 cast_count;
|
||||
uint8 unk_flags; // flags (if 0x02 - some additional data are received)
|
||||
|
||||
recvPacket >> guid >> spellid;
|
||||
recvPacket >> guid >> cast_count >> spellid >> unk_flags;
|
||||
|
||||
sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags);
|
||||
|
||||
if(!_player->GetPet() && !_player->GetCharm())
|
||||
return;
|
||||
|
|
@ -637,6 +640,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
|
|||
pet->clearUnitState(UNIT_STAT_FOLLOW);
|
||||
|
||||
Spell *spell = new Spell(pet, spellInfo, false);
|
||||
spell->m_cast_count = cast_count; // probably pending spell cast
|
||||
spell->m_targets = targets;
|
||||
|
||||
int16 result = spell->PetCanCast(NULL);
|
||||
|
|
@ -668,7 +672,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
|
|||
}
|
||||
}
|
||||
|
||||
void WorldSession::SendPetNameInvalid(uint32 error, std::string name, DeclinedName *declinedName)
|
||||
void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName)
|
||||
{
|
||||
WorldPacket data(SMSG_PET_NAME_INVALID, 4 + name.size() + 1 + 1);
|
||||
data << uint32(error);
|
||||
|
|
@ -683,3 +687,132 @@ void WorldSession::SendPetNameInvalid(uint32 error, std::string name, DeclinedNa
|
|||
data << uint8(0);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data )
|
||||
{
|
||||
sLog.outDebug("WORLD: CMSG_PET_LEARN_TALENT");
|
||||
recv_data.hexlike();
|
||||
|
||||
CHECK_PACKET_SIZE(recv_data, 8+4+4);
|
||||
|
||||
uint64 guid;
|
||||
uint32 talent_id, requested_rank;
|
||||
recv_data >> guid >> talent_id >> requested_rank;
|
||||
|
||||
Pet *pet = _player->GetPet();
|
||||
|
||||
if(!pet)
|
||||
return;
|
||||
|
||||
if(guid != pet->GetGUID())
|
||||
return;
|
||||
|
||||
uint32 CurTalentPoints = pet->GetFreeTalentPoints();
|
||||
|
||||
if(CurTalentPoints == 0)
|
||||
return;
|
||||
|
||||
if (requested_rank > 4)
|
||||
return;
|
||||
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry(talent_id);
|
||||
|
||||
if(!talentInfo)
|
||||
return;
|
||||
|
||||
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
|
||||
|
||||
if(!talentTabInfo)
|
||||
return;
|
||||
|
||||
CreatureInfo const *ci = pet->GetCreatureInfo();
|
||||
|
||||
if(!ci)
|
||||
return;
|
||||
|
||||
CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
|
||||
|
||||
if(!pet_family)
|
||||
return;
|
||||
|
||||
if(pet_family->petTalentType < 0) // not hunter pet
|
||||
return;
|
||||
|
||||
// prevent learn talent for different family (cheating)
|
||||
if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask))
|
||||
return;
|
||||
|
||||
// prevent skip talent ranks (cheating)
|
||||
if(requested_rank > 0 && !pet->HasSpell(talentInfo->RankID[requested_rank-1]))
|
||||
return;
|
||||
|
||||
// Check if it requires another talent
|
||||
if (talentInfo->DependsOn > 0)
|
||||
{
|
||||
if(TalentEntry const *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn))
|
||||
{
|
||||
bool hasEnoughRank = false;
|
||||
for (int i = talentInfo->DependsOnRank; i <= 4; i++)
|
||||
{
|
||||
if (depTalentInfo->RankID[i] != 0)
|
||||
if (pet->HasSpell(depTalentInfo->RankID[i]))
|
||||
hasEnoughRank = true;
|
||||
}
|
||||
if (!hasEnoughRank)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Find out how many points we have in this field
|
||||
uint32 spentPoints = 0;
|
||||
|
||||
uint32 tTab = talentInfo->TalentTab;
|
||||
if (talentInfo->Row > 0)
|
||||
{
|
||||
unsigned int numRows = sTalentStore.GetNumRows();
|
||||
for (unsigned int i = 0; i < numRows; i++) // Loop through all talents.
|
||||
{
|
||||
// Someday, someone needs to revamp
|
||||
const TalentEntry *tmpTalent = sTalentStore.LookupEntry(i);
|
||||
if (tmpTalent) // the way talents are tracked
|
||||
{
|
||||
if (tmpTalent->TalentTab == tTab)
|
||||
{
|
||||
for (int j = 0; j <= 4; j++)
|
||||
{
|
||||
if (tmpTalent->RankID[j] != 0)
|
||||
{
|
||||
if (pet->HasSpell(tmpTalent->RankID[j]))
|
||||
{
|
||||
spentPoints += j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not have required min points spent in talent tree
|
||||
if(spentPoints < (talentInfo->Row * 3))
|
||||
return;
|
||||
|
||||
// spell not set in talent.dbc
|
||||
uint32 spellid = talentInfo->RankID[requested_rank];
|
||||
if( spellid == 0 )
|
||||
{
|
||||
sLog.outError("Talent.dbc have for talent: %u Rank: %u spell id = 0", talent_id, requested_rank);
|
||||
return;
|
||||
}
|
||||
|
||||
// already known
|
||||
if(pet->HasSpell(spellid))
|
||||
return;
|
||||
|
||||
// learn! (other talent ranks will unlearned at learning)
|
||||
pet->learnSpell(spellid);
|
||||
sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid);
|
||||
|
||||
// update free talent points
|
||||
pet->SetFreeTalentPoints(CurTalentPoints - 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,18 +111,10 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
// TODO: find correct opcode
|
||||
if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
SendNotification(LANG_ARENA_ONE_TOOLOW, 70);
|
||||
SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint8 i = 0; i < MAX_ARENA_SLOT; i++)
|
||||
{
|
||||
if(_player->GetArenaTeamId(i) && (i == (unk10-1)))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch(unk10)
|
||||
{
|
||||
case 1:
|
||||
|
|
@ -144,6 +136,12 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
sLog.outDebug("unknown selection at buy petition: %u", unk10);
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamId(unk10-1))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(type == 9)
|
||||
|
|
@ -153,12 +151,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(name))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(name))
|
||||
if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -171,12 +164,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(name))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(name))
|
||||
if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -209,13 +197,15 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
|
|||
if(!charter)
|
||||
return;
|
||||
|
||||
charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow());
|
||||
// ITEM_FIELD_ENCHANTMENT is guild/arenateam id
|
||||
// ITEM_FIELD_ENCHANTMENT+1 is current signatures count (showed on item)
|
||||
charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
|
||||
// ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
|
||||
// ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
|
||||
charter->SetState(ITEM_CHANGED, _player);
|
||||
_player->SendNewItem(charter, 1, true, false);
|
||||
|
||||
// a petition is invalid, if both the owner and the type matches
|
||||
// we checked above, if this player is in an arenateam, so this must be
|
||||
// datacorruption
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type);
|
||||
|
||||
std::ostringstream ssInvalidPetitionGUIDs;
|
||||
|
|
@ -260,15 +250,16 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data)
|
|||
// solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)
|
||||
uint32 petitionguid_low = GUID_LOPART(petitionguid);
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid, type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
|
||||
if(!result)
|
||||
{
|
||||
sLog.outError("any petition on server...");
|
||||
return;
|
||||
}
|
||||
Field *fields = result->Fetch();
|
||||
uint32 type = fields[1].GetUInt32();
|
||||
uint32 type = fields[0].GetUInt32();
|
||||
delete result;
|
||||
|
||||
// if guild petition and has guild => error, return;
|
||||
if(type==9 && _player->GetGuildId())
|
||||
return;
|
||||
|
|
@ -326,7 +317,8 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
|
|||
|
||||
QueryResult *result = CharacterDatabase.PQuery(
|
||||
"SELECT ownerguid, name, "
|
||||
" (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs "
|
||||
" (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
|
||||
" type "
|
||||
"FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
|
||||
|
||||
if(result)
|
||||
|
|
@ -335,6 +327,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
|
|||
ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
name = fields[1].GetCppString();
|
||||
signs = fields[2].GetUInt8();
|
||||
type = fields[3].GetUInt32();
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
|
|
@ -343,20 +336,6 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
|
|||
return;
|
||||
}
|
||||
|
||||
QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
|
||||
if(result2)
|
||||
{
|
||||
Field* fields = result2->Fetch();
|
||||
type = fields[0].GetUInt32();
|
||||
delete result2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
|
||||
return;
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13));
|
||||
data << GUID_LOPART(petitionguid); // guild/team guid (in mangos always same as GUID_LOPART(petition guid)
|
||||
data << ownerguid; // charter owner guid
|
||||
|
|
@ -408,13 +387,13 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
|
|||
if(!item)
|
||||
return;
|
||||
|
||||
QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
|
||||
if(result2)
|
||||
if(result)
|
||||
{
|
||||
Field* fields = result2->Fetch();
|
||||
Field* fields = result->Fetch();
|
||||
type = fields[0].GetUInt32();
|
||||
delete result2;
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -429,12 +408,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
|
|||
SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(newname))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(newname))
|
||||
if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
|
||||
{
|
||||
SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -447,12 +421,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
|
|||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
|
||||
return;
|
||||
}
|
||||
if(objmgr.IsReservedName(newname))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
}
|
||||
if(!ObjectMgr::IsValidCharterName(newname))
|
||||
if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
|
||||
return;
|
||||
|
|
@ -480,17 +449,14 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
|
|||
|
||||
Field *fields;
|
||||
uint64 petitionguid;
|
||||
uint32 type;
|
||||
uint8 unk;
|
||||
uint64 ownerguid;
|
||||
recv_data >> petitionguid; // petition guid
|
||||
recv_data >> unk;
|
||||
|
||||
uint8 signs = 0;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery(
|
||||
"SELECT ownerguid, "
|
||||
" (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs "
|
||||
" (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
|
||||
" type "
|
||||
"FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
|
||||
|
||||
if(!result)
|
||||
|
|
@ -500,8 +466,9 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
|
|||
}
|
||||
|
||||
fields = result->Fetch();
|
||||
ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
signs = fields[1].GetUInt8();
|
||||
uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
|
||||
uint8 signs = fields[1].GetUInt8();
|
||||
uint32 type = fields[2].GetUInt32();
|
||||
|
||||
delete result;
|
||||
|
||||
|
|
@ -511,31 +478,53 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
|
|||
|
||||
// not let enemies sign guild charter
|
||||
if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid))
|
||||
return;
|
||||
|
||||
QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
|
||||
if(result2)
|
||||
{
|
||||
Field* fields = result2->Fetch();
|
||||
type = fields[0].GetUInt32();
|
||||
delete result2;
|
||||
if(type != 9)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
else
|
||||
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
if(type != 9)
|
||||
{
|
||||
if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 slot = ArenaTeam::GetSlotByType(type);
|
||||
if(slot >= MAX_ARENA_SLOT)
|
||||
return;
|
||||
|
||||
if(_player->GetArenaTeamId(slot))
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(_player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
|
||||
return;
|
||||
if(_player->GetGuildId())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
|
||||
return;
|
||||
}
|
||||
if(_player->GetGuildIdInvited())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(type != 9 && _player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
// player is too low level to join an arena team
|
||||
SendNotification(LANG_YOUR_ARENA_LEVEL_REQ_ERROR,sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
|
||||
return;
|
||||
}
|
||||
|
||||
signs += 1;
|
||||
if(signs > type) // client signs maximum
|
||||
if(++signs > type) // client signs maximum
|
||||
return;
|
||||
|
||||
//client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
|
||||
|
|
@ -574,7 +563,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
|
|||
// update signs count on charter, required testing...
|
||||
//Item *item = _player->GetItemByGuid(petitionguid));
|
||||
//if(item)
|
||||
// item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1, signs);
|
||||
// item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
|
||||
|
||||
// update for owner if online
|
||||
if(Player *owner = objmgr.GetPlayer(ownerguid))
|
||||
|
|
@ -619,29 +608,75 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
|
|||
|
||||
uint8 signs = 0;
|
||||
uint64 petitionguid, plguid;
|
||||
uint32 petitiontype;
|
||||
uint32 type, junk;
|
||||
Player *player;
|
||||
recv_data >> petitiontype; // 2.0.8 - petition type?
|
||||
recv_data >> junk; // this is not petition type!
|
||||
recv_data >> petitionguid; // petition guid
|
||||
recv_data >> plguid; // player guid
|
||||
sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", petitiontype, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
|
||||
|
||||
player = ObjectAccessor::FindPlayer(plguid);
|
||||
if(!player || player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
// not let offer to enemies
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
Field *fields = result->Fetch();
|
||||
type = fields[0].GetUInt32();
|
||||
delete result;
|
||||
|
||||
sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
|
||||
|
||||
if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
|
||||
return;
|
||||
|
||||
QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
if(!result)
|
||||
{
|
||||
sLog.outError("any petition on server...");
|
||||
if(type != 9)
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
|
||||
else
|
||||
SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
|
||||
return;
|
||||
}
|
||||
|
||||
delete result;
|
||||
if(type != 9)
|
||||
{
|
||||
if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
// player is too low level to join an arena team
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 slot = ArenaTeam::GetSlotByType(type);
|
||||
if(slot >= MAX_ARENA_SLOT)
|
||||
return;
|
||||
|
||||
if(player->GetArenaTeamId(slot))
|
||||
{
|
||||
// player is already in an arena team
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetArenaTeamIdInvited())
|
||||
{
|
||||
SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(player->GetGuildId())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
|
||||
return;
|
||||
}
|
||||
|
||||
if(player->GetGuildIdInvited())
|
||||
{
|
||||
SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
|
||||
// result==NULL also correct charter without signs
|
||||
|
|
@ -811,7 +846,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
|
|||
else // or arena team
|
||||
{
|
||||
ArenaTeam* at = new ArenaTeam;
|
||||
if(!at->create(_player->GetGUID(), type, name))
|
||||
if(!at->Create(_player->GetGUID(), type, name))
|
||||
{
|
||||
sLog.outError("PetitionsHandler: arena team create failed.");
|
||||
delete at;
|
||||
|
|
|
|||
1561
src/game/Player.cpp
1561
src/game/Player.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -33,6 +33,7 @@
|
|||
#include "Pet.h"
|
||||
#include "MapReference.h"
|
||||
#include "Util.h" // for Tokens typedef
|
||||
#include "AchievementMgr.h"
|
||||
|
||||
#include<string>
|
||||
#include<vector>
|
||||
|
|
@ -46,6 +47,8 @@ class PlayerMenu;
|
|||
class Transport;
|
||||
class UpdateMask;
|
||||
class PlayerSocial;
|
||||
class AchievementMgr;
|
||||
class Vehicle;
|
||||
|
||||
typedef std::deque<Mail*> PlayerMails;
|
||||
|
||||
|
|
@ -77,15 +80,17 @@ struct PlayerSpell
|
|||
|
||||
#define SPELL_WITHOUT_SLOT_ID uint16(-1)
|
||||
|
||||
// Spell modifier (used for modify other spells)
|
||||
struct SpellModifier
|
||||
{
|
||||
SpellModifier() : charges(0), lastAffected(NULL) {}
|
||||
SpellModOp op : 8;
|
||||
SpellModType type : 8;
|
||||
int16 charges : 16;
|
||||
int32 value;
|
||||
uint64 mask;
|
||||
uint64 mask2;
|
||||
uint32 spellId;
|
||||
uint32 effectId;
|
||||
Spell const* lastAffected;
|
||||
};
|
||||
|
||||
|
|
@ -221,6 +226,39 @@ struct Areas
|
|||
float y2;
|
||||
};
|
||||
|
||||
#define MAX_RUNES 6
|
||||
#define RUNE_COOLDOWN 5 // 5*2=10 sec
|
||||
|
||||
enum RuneType
|
||||
{
|
||||
RUNE_BLOOD = 0,
|
||||
RUNE_UNHOLY = 1,
|
||||
RUNE_FROST = 2,
|
||||
RUNE_DEATH = 3,
|
||||
NUM_RUNE_TYPES = 4
|
||||
};
|
||||
|
||||
struct RuneInfo
|
||||
{
|
||||
uint8 BaseRune;
|
||||
uint8 CurrentRune;
|
||||
uint8 Cooldown;
|
||||
};
|
||||
|
||||
struct Runes
|
||||
{
|
||||
RuneInfo runes[MAX_RUNES];
|
||||
uint8 runeState; // mask of available runes
|
||||
|
||||
void SetRuneState(uint8 index, bool set = true)
|
||||
{
|
||||
if(set)
|
||||
runeState |= (1 << index); // usable
|
||||
else
|
||||
runeState &= ~(1 << index); // on cooldown
|
||||
}
|
||||
};
|
||||
|
||||
enum FactionFlags
|
||||
{
|
||||
FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction)
|
||||
|
|
@ -389,7 +427,7 @@ enum PlayerFlags
|
|||
PLAYER_FLAGS_UNK3 = 0x00008000, // strange visual effect (2.0.1), looks like PLAYER_FLAGS_GHOST flag
|
||||
PLAYER_FLAGS_SANCTUARY = 0x00010000, // player entered sanctuary
|
||||
PLAYER_FLAGS_UNK4 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1)
|
||||
PLAYER_UNK = 0x00040000, // 2.0.8...
|
||||
PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually)
|
||||
};
|
||||
|
||||
// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
|
||||
|
|
@ -478,7 +516,8 @@ enum LootType
|
|||
LOOT_DISENCHANTING = 5, // unsupported by client, sending LOOT_SKINNING instead
|
||||
LOOT_PROSPECTING = 6, // unsupported by client, sending LOOT_SKINNING instead
|
||||
LOOT_INSIGNIA = 7, // unsupported by client, sending LOOT_SKINNING instead
|
||||
LOOT_FISHINGHOLE = 8 // unsupported by client, sending LOOT_FISHING instead
|
||||
LOOT_FISHINGHOLE = 8, // unsupported by client, sending LOOT_FISHING instead
|
||||
LOOT_MILLING = 9 // unsupported by client, sending LOOT_SKINNING instead
|
||||
};
|
||||
|
||||
enum MirrorTimerType
|
||||
|
|
@ -509,7 +548,8 @@ enum AtLoginFlags
|
|||
AT_LOGIN_NONE = 0,
|
||||
AT_LOGIN_RENAME = 1,
|
||||
AT_LOGIN_RESET_SPELLS = 2,
|
||||
AT_LOGIN_RESET_TALENTS = 4
|
||||
AT_LOGIN_RESET_TALENTS = 4,
|
||||
AT_LOGIN_CUSTOMIZE = 8
|
||||
};
|
||||
|
||||
typedef std::map<uint32, QuestStatusData> QuestStatusMap;
|
||||
|
|
@ -541,7 +581,7 @@ enum PlayerSlots
|
|||
// first slot for item stored (in any way in player m_items data)
|
||||
PLAYER_SLOT_START = 0,
|
||||
// last+1 slot for item stored (in any way in player m_items data)
|
||||
PLAYER_SLOT_END = 118,
|
||||
PLAYER_SLOT_END = 200,
|
||||
PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START)
|
||||
};
|
||||
|
||||
|
|
@ -669,6 +709,24 @@ enum KeyRingSlots
|
|||
KEYRING_SLOT_END = 118
|
||||
};
|
||||
|
||||
enum VanityPetSlots
|
||||
{
|
||||
VANITYPET_SLOT_START = 118,
|
||||
VANITYPET_SLOT_END = 136
|
||||
};
|
||||
|
||||
enum CurrencyTokenSlots
|
||||
{
|
||||
CURRENCYTOKEN_SLOT_START = 136,
|
||||
CURRENCYTOKEN_SLOT_END = 168
|
||||
};
|
||||
|
||||
enum QuestBagSlots
|
||||
{
|
||||
QUESTBAG_SLOT_START = 168,
|
||||
QUESTBAG_SLOT_END = 200
|
||||
};
|
||||
|
||||
struct ItemPosCount
|
||||
{
|
||||
ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {}
|
||||
|
|
@ -687,14 +745,15 @@ enum TradeSlots
|
|||
|
||||
enum TransferAbortReason
|
||||
{
|
||||
TRANSFER_ABORT_MAX_PLAYERS = 0x0001, // Transfer Aborted: instance is full
|
||||
TRANSFER_ABORT_NOT_FOUND = 0x0002, // Transfer Aborted: instance not found
|
||||
TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x0003, // You have entered too many instances recently.
|
||||
TRANSFER_ABORT_ZONE_IN_COMBAT = 0x0005, // Unable to zone in while an encounter is in progress.
|
||||
TRANSFER_ABORT_INSUF_EXPAN_LVL1 = 0x0106, // You must have TBC expansion installed to access this area.
|
||||
TRANSFER_ABORT_DIFFICULTY1 = 0x0007, // Normal difficulty mode is not available for %s.
|
||||
TRANSFER_ABORT_DIFFICULTY2 = 0x0107, // Heroic difficulty mode is not available for %s.
|
||||
TRANSFER_ABORT_DIFFICULTY3 = 0x0207 // Epic difficulty mode is not available for %s.
|
||||
TRANSFER_ABORT_ERROR = 0x00,
|
||||
TRANSFER_ABORT_MAX_PLAYERS = 0x01, // Transfer Aborted: instance is full
|
||||
TRANSFER_ABORT_NOT_FOUND = 0x02, // Transfer Aborted: instance not found
|
||||
TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x03, // You have entered too many instances recently.
|
||||
TRANSFER_ABORT_ZONE_IN_COMBAT = 0x05, // Unable to zone in while an encounter is in progress.
|
||||
TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x06, // You must have <TBC,WotLK> expansion installed to access this area.
|
||||
TRANSFER_ABORT_DIFFICULTY = 0x07, // <Normal,Heroic,Epic> difficulty mode is not available for %s.
|
||||
TRANSFER_ABORT_UNIQUE_MESSAGE = 0x08, // Until you've escaped TLK's grasp, you cannot leave this place!
|
||||
TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x09 // Additional instances cannot be launched, please try again later.
|
||||
};
|
||||
|
||||
enum InstanceResetWarningType
|
||||
|
|
@ -708,15 +767,16 @@ enum InstanceResetWarningType
|
|||
struct MovementInfo
|
||||
{
|
||||
// common
|
||||
//uint32 flags;
|
||||
uint8 unk1;
|
||||
uint32 flags;
|
||||
uint16 unk1;
|
||||
uint32 time;
|
||||
float x, y, z, o;
|
||||
// transport
|
||||
uint64 t_guid;
|
||||
float t_x, t_y, t_z, t_o;
|
||||
uint32 t_time;
|
||||
// swimming and unk
|
||||
int8 t_seat;
|
||||
// swimming and unknown
|
||||
float s_pitch;
|
||||
// last fall time
|
||||
uint32 fallTime;
|
||||
|
|
@ -727,17 +787,17 @@ struct MovementInfo
|
|||
|
||||
MovementInfo()
|
||||
{
|
||||
//flags =
|
||||
flags = 0;
|
||||
time = t_time = fallTime = 0;
|
||||
unk1 = 0;
|
||||
x = y = z = o = t_x = t_y = t_z = t_o = s_pitch = j_unk = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f;
|
||||
t_guid = 0;
|
||||
}
|
||||
|
||||
/*void SetMovementFlags(uint32 _flags)
|
||||
void SetMovementFlags(uint32 _flags)
|
||||
{
|
||||
flags = _flags;
|
||||
}*/
|
||||
}
|
||||
};
|
||||
|
||||
// flags that use in movement check for example at spell casting
|
||||
|
|
@ -809,9 +869,12 @@ enum PlayerLoginQueryIndex
|
|||
PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15,
|
||||
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16,
|
||||
PLAYER_LOGIN_QUERY_LOADGUILD = 17,
|
||||
PLAYER_LOGIN_QUERY_LOADARENAINFO = 18,
|
||||
PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 19,
|
||||
PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 20,
|
||||
MAX_PLAYER_LOGIN_QUERY = 21
|
||||
};
|
||||
|
||||
#define MAX_PLAYER_LOGIN_QUERY 18
|
||||
|
||||
// Player summoning auto-decline time (in secs)
|
||||
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
|
||||
|
|
@ -833,7 +896,7 @@ class MANGOS_DLL_SPEC PlayerTaxi
|
|||
PlayerTaxi();
|
||||
~PlayerTaxi() {}
|
||||
// Nodes
|
||||
void InitTaxiNodesForLevel(uint32 race, uint32 level);
|
||||
void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level);
|
||||
void LoadTaxiMask(const char* data);
|
||||
void SaveTaxiMask(const char* data);
|
||||
|
||||
|
|
@ -859,7 +922,7 @@ class MANGOS_DLL_SPEC PlayerTaxi
|
|||
void AppendTaximaskTo(ByteBuffer& data,bool all);
|
||||
|
||||
// Destinations
|
||||
bool LoadTaxiDestinationsFromString(std::string values);
|
||||
bool LoadTaxiDestinationsFromString(const std::string& values);
|
||||
std::string SaveTaxiDestinationsToString();
|
||||
|
||||
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
|
||||
|
|
@ -912,7 +975,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
}
|
||||
void SummonIfPossible(bool agree);
|
||||
|
||||
bool Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId );
|
||||
bool Create( uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId );
|
||||
|
||||
void Update( uint32 time );
|
||||
|
||||
|
|
@ -925,7 +988,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
|
||||
void SendInitialPacketsBeforeAddToMap();
|
||||
void SendInitialPacketsAfterAddToMap();
|
||||
void SendTransferAborted(uint32 mapid, uint16 reason);
|
||||
void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0);
|
||||
void SendInstanceResetWarning(uint32 mapid, uint32 time);
|
||||
|
||||
bool CanInteractWithNPCs(bool alive = true) const;
|
||||
|
|
@ -938,10 +1001,12 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
std::string afkMsg;
|
||||
std::string dndMsg;
|
||||
|
||||
uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair);
|
||||
|
||||
PlayerSocial *GetSocial() { return m_social; }
|
||||
|
||||
PlayerTaxi m_taxi;
|
||||
void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(),getLevel()); }
|
||||
void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); }
|
||||
bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_id = 0 , Creature* npc = NULL);
|
||||
// mount_id can be used in scripting calls
|
||||
bool isAcceptTickets() const { return GetSession()->GetSecurity() >= SEC_GAMEMASTER && (m_ExtraFlags & PLAYER_EXTRA_GM_ACCEPT_TICKETS); }
|
||||
|
|
@ -1004,11 +1069,11 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
GuardianPetList const& GetGuardians() const { return m_guardianPets; }
|
||||
void Uncharm();
|
||||
|
||||
void Say(std::string text, const uint32 language);
|
||||
void Yell(std::string text, const uint32 language);
|
||||
void TextEmote(std::string text);
|
||||
void Whisper(std::string text, const uint32 language,uint64 receiver);
|
||||
void BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const;
|
||||
void Say(const std::string& text, const uint32 language);
|
||||
void Yell(const std::string& text, const uint32 language);
|
||||
void TextEmote(const std::string& text);
|
||||
void Whisper(const std::string& text, const uint32 language,uint64 receiver);
|
||||
void BuildPlayerChat(WorldPacket *data, uint8 msgtype, const std::string& text, uint32 language) const;
|
||||
|
||||
/*********************************************************/
|
||||
/*** STORAGE SYSTEM ***/
|
||||
|
|
@ -1037,6 +1102,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
bool HasBankBagSlot( uint8 slot ) const;
|
||||
bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const;
|
||||
bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL);
|
||||
bool CanNoReagentCast(SpellEntry const* spellInfo) const;
|
||||
Item* GetItemOrItemWithGemEquipped( uint32 item ) const;
|
||||
uint8 CanTakeMoreSimilarItems(Item* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(),pItem->GetCount(),pItem); }
|
||||
uint8 CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry,count,NULL); }
|
||||
|
|
@ -1053,7 +1119,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
|
||||
}
|
||||
uint8 CanStoreItems( Item **pItem,int count) const;
|
||||
uint8 CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, uint32 count, bool swap ) const;
|
||||
uint8 CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, bool swap ) const;
|
||||
uint8 CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading = true ) const;
|
||||
uint8 CanUnequipItems( uint32 item, uint32 count ) const;
|
||||
uint8 CanUnequipItem( uint16 src, bool swap ) const;
|
||||
|
|
@ -1064,10 +1130,10 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
uint8 CanUseAmmo( uint32 item ) const;
|
||||
Item* StoreNewItem( ItemPosCountVec const& pos, uint32 item, bool update,int32 randomPropertyId = 0 );
|
||||
Item* StoreItem( ItemPosCountVec const& pos, Item *pItem, bool update );
|
||||
Item* EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update );
|
||||
Item* EquipNewItem( uint16 pos, uint32 item, bool update );
|
||||
Item* EquipItem( uint16 pos, Item *pItem, bool update );
|
||||
void AutoUnequipOffhandIfNeed();
|
||||
bool StoreNewItemInBestSlot(uint32 item_id, uint32 item_count);
|
||||
bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count);
|
||||
|
||||
uint8 _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const;
|
||||
uint8 _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const;
|
||||
|
|
@ -1115,6 +1181,11 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
// disarm applied only to mainhand weapon
|
||||
return !IsInFeralForm() && (!mainhand || !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED) );
|
||||
}
|
||||
bool IsTwoHandUsed() const
|
||||
{
|
||||
Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
|
||||
return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip();
|
||||
}
|
||||
void SendNewItem( Item *item, uint32 count, bool received, bool created, bool broadcast = false );
|
||||
bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot);
|
||||
|
||||
|
|
@ -1270,6 +1341,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
static void SetFloatValueInArray(Tokens& data,uint16 index, float value);
|
||||
static void SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid);
|
||||
static void SetFloatValueInDB(uint16 index, float value, uint64 guid);
|
||||
static void Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair);
|
||||
static void SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint32 zone,uint64 guid);
|
||||
|
||||
bool m_mailsLoaded;
|
||||
|
|
@ -1408,6 +1480,12 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
uint32 resetTalentsCost() const;
|
||||
void InitTalentForLevel();
|
||||
|
||||
void InitGlyphsForLevel();
|
||||
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
|
||||
uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
|
||||
void SetGlyph(uint8 slot, uint32 glyph) { SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); }
|
||||
uint32 GetGlyph(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot); }
|
||||
|
||||
uint32 GetFreePrimaryProffesionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); }
|
||||
void SetFreePrimaryProffesions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2,profs); }
|
||||
void InitPrimaryProffesions();
|
||||
|
|
@ -1416,8 +1494,6 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
PlayerSpellMap & GetSpellMap() { return m_spells; }
|
||||
|
||||
void AddSpellMod(SpellModifier* mod, bool apply);
|
||||
int32 GetTotalFlatMods(uint32 spellId, SpellModOp op);
|
||||
int32 GetTotalPctMods(uint32 spellId, SpellModOp op);
|
||||
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
|
||||
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
|
||||
void RemoveSpellMods(Spell const* spell);
|
||||
|
|
@ -1517,7 +1593,6 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot)
|
||||
{
|
||||
SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId);
|
||||
SaveDataFieldToDB(); // needed?
|
||||
}
|
||||
uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6)); }
|
||||
static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot);
|
||||
|
|
@ -1575,6 +1650,10 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void UpdateAllCritPercentages();
|
||||
void UpdateParryPercentage();
|
||||
void UpdateDodgePercentage();
|
||||
void UpdateMeleeHitChances();
|
||||
void UpdateRangedHitChances();
|
||||
void UpdateSpellHitChances();
|
||||
|
||||
void UpdateAllSpellCritChances();
|
||||
void UpdateSpellCritChance(uint32 school);
|
||||
void UpdateExpertise(WeaponAttackType attType);
|
||||
|
|
@ -1748,6 +1827,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void SetCanBlock(bool value);
|
||||
bool CanDualWield() const { return m_canDualWield; }
|
||||
void SetCanDualWield(bool value) { m_canDualWield = value; }
|
||||
bool CanTitanGrip() const { return m_canTitanGrip ; }
|
||||
void SetCanTitanGrip(bool value) { m_canTitanGrip = value; }
|
||||
|
||||
void SetRegularAttackTime();
|
||||
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
|
||||
|
|
@ -1781,7 +1862,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void SendUpdateWorldState(uint32 Field, uint32 Value);
|
||||
void SendDirectMessage(WorldPacket *data);
|
||||
|
||||
void SendAuraDurationsForTarget(Unit* target);
|
||||
void SendAurasForTarget(Unit *target);
|
||||
|
||||
PlayerMenu* PlayerTalkClass;
|
||||
std::vector<ItemSetEffect *> ItemSetEff;
|
||||
|
|
@ -1804,24 +1885,32 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
static uint32 GetMaxLevelForBattleGroundQueueId(uint32 queue_id);
|
||||
uint32 GetBattleGroundQueueIdFromLevel() const;
|
||||
|
||||
uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgType; }
|
||||
uint32 GetBattleGroundQueueIndex(uint32 bgType) const
|
||||
bool InBattleGroundQueue() const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgType == bgType)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType != 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgQueueType; }
|
||||
uint32 GetBattleGroundQueueIndex(uint32 bgQueueType) const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType)
|
||||
return i;
|
||||
return PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
bool IsInvitedForBattleGroundType(uint32 bgType) const
|
||||
bool IsInvitedForBattleGroundQueueType(uint32 bgQueueType) const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgType == bgType)
|
||||
return m_bgBattleGroundQueueID[i].invited;
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType)
|
||||
return m_bgBattleGroundQueueID[i].invitedToInstance != 0;
|
||||
return PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
bool InBattleGroundQueueForBattleGroundType(uint32 bgType) const
|
||||
bool InBattleGroundQueueForBattleGroundQueueType(uint32 bgQueueType) const
|
||||
{
|
||||
return GetBattleGroundQueueIndex(bgType) < PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
return GetBattleGroundQueueIndex(bgQueueType) < PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
|
||||
void SetBattleGroundId(uint32 val) { m_bgBattleGroundID = val; }
|
||||
|
|
@ -1829,34 +1918,47 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
if (m_bgBattleGroundQueueID[i].bgType == 0 || m_bgBattleGroundQueueID[i].bgType == val)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == 0 || m_bgBattleGroundQueueID[i].bgQueueType == val)
|
||||
{
|
||||
m_bgBattleGroundQueueID[i].bgType = val;
|
||||
m_bgBattleGroundQueueID[i].invited = false;
|
||||
m_bgBattleGroundQueueID[i].bgQueueType = val;
|
||||
m_bgBattleGroundQueueID[i].invitedToInstance = 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return PLAYER_MAX_BATTLEGROUND_QUEUES;
|
||||
}
|
||||
bool HasFreeBattleGroundQueueId()
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
void RemoveBattleGroundQueueId(uint32 val)
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
{
|
||||
if (m_bgBattleGroundQueueID[i].bgType == val)
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == val)
|
||||
{
|
||||
m_bgBattleGroundQueueID[i].bgType = 0;
|
||||
m_bgBattleGroundQueueID[i].invited = false;
|
||||
m_bgBattleGroundQueueID[i].bgQueueType = 0;
|
||||
m_bgBattleGroundQueueID[i].invitedToInstance = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SetInviteForBattleGroundType(uint32 bgType)
|
||||
void SetInviteForBattleGroundQueueType(uint32 bgQueueType, uint32 instanceId)
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].bgType == bgType)
|
||||
m_bgBattleGroundQueueID[i].invited = true;
|
||||
if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType)
|
||||
m_bgBattleGroundQueueID[i].invitedToInstance = instanceId;
|
||||
}
|
||||
bool IsInvitedForBattleGroundInstance(uint32 instanceId) const
|
||||
{
|
||||
for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++)
|
||||
if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; }
|
||||
float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; }
|
||||
float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; }
|
||||
|
|
@ -1912,6 +2014,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
MovementInfo m_movementInfo;
|
||||
uint32 m_lastFallTime;
|
||||
float m_lastFallZ;
|
||||
Unit *m_mover;
|
||||
void SetFallInformation(uint32 time, float z)
|
||||
{
|
||||
m_lastFallTime = time;
|
||||
|
|
@ -1927,6 +2030,9 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
|
||||
void SetClientControl(Unit* target, uint8 allowMove);
|
||||
|
||||
void EnterVehicle(Vehicle *vehicle);
|
||||
void ExitVehicle(Vehicle *vehicle);
|
||||
|
||||
uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); }
|
||||
void SetFarSight(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); }
|
||||
|
||||
|
|
@ -1939,6 +2045,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
float GetTransOffsetZ() const { return m_movementInfo.t_z; }
|
||||
float GetTransOffsetO() const { return m_movementInfo.t_o; }
|
||||
uint32 GetTransTime() const { return m_movementInfo.t_time; }
|
||||
int8 GetTransSeat() const { return m_movementInfo.t_seat; }
|
||||
|
||||
uint32 GetSaveTimer() const { return m_nextSave; }
|
||||
void SetSaveTimer(uint32 timer) { m_nextSave = timer; }
|
||||
|
|
@ -2036,6 +2143,18 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
|
||||
|
||||
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
|
||||
uint8 GetRunesState() const { return m_runes->runeState; }
|
||||
uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; }
|
||||
uint8 GetCurrentRune(uint8 index) const { return m_runes->runes[index].CurrentRune; }
|
||||
uint8 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
|
||||
void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; }
|
||||
void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
|
||||
void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); }
|
||||
void ConvertRune(uint8 index, uint8 newType);
|
||||
void ResyncRunes(uint8 count);
|
||||
void AddRunePower(uint8 index);
|
||||
void InitRunes();
|
||||
AchievementMgr& GetAchievementMgr() { return m_achievementMgr; }
|
||||
bool HasTitle(uint32 bitIndex);
|
||||
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
|
||||
void SetTitle(CharTitlesEntry const* title);
|
||||
|
|
@ -2053,8 +2172,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
*/
|
||||
struct BgBattleGroundQueueID_Rec
|
||||
{
|
||||
uint32 bgType;
|
||||
bool invited;
|
||||
uint32 bgQueueType;
|
||||
uint32 invitedToInstance;
|
||||
};
|
||||
BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES];
|
||||
uint32 m_bgEntryPointMap;
|
||||
|
|
@ -2099,6 +2218,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
void _LoadFriendList(QueryResult *result);
|
||||
bool _LoadHomeBind(QueryResult *result);
|
||||
void _LoadDeclinedNames(QueryResult *result);
|
||||
void _LoadArenaTeamInfo(QueryResult *result);
|
||||
|
||||
/*********************************************************/
|
||||
/*** SAVE SYSTEM ***/
|
||||
|
|
@ -2171,6 +2291,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
ActionButtonList m_actionButtons;
|
||||
|
||||
float m_auraBaseMod[BASEMOD_END][MOD_END];
|
||||
int16 m_baseRatingValue[MAX_COMBAT_RATING];
|
||||
|
||||
SpellModList m_spellMods[MAX_SPELLMOD];
|
||||
int32 m_SpellModRemoveCount;
|
||||
|
|
@ -2204,7 +2325,6 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
bool m_DailyQuestChanged;
|
||||
time_t m_lastDailyQuestTime;
|
||||
|
||||
uint32 m_regenTimer;
|
||||
uint32 m_breathTimer;
|
||||
uint32 m_drunkTimer;
|
||||
uint16 m_drunk;
|
||||
|
|
@ -2224,8 +2344,10 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
bool m_canParry;
|
||||
bool m_canBlock;
|
||||
bool m_canDualWield;
|
||||
bool m_canTitanGrip;
|
||||
uint8 m_swingErrorMsg;
|
||||
float m_ammoDPS;
|
||||
|
||||
////////////////////Rest System/////////////////////
|
||||
int time_inn_enter;
|
||||
uint32 inn_pos_mapid;
|
||||
|
|
@ -2270,6 +2392,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
WorldLocation m_teleport_dest;
|
||||
|
||||
DeclinedName *m_declinedname;
|
||||
Runes *m_runes;
|
||||
AchievementMgr m_achievementMgr;
|
||||
private:
|
||||
// internal common parts for CanStore/StoreItem functions
|
||||
uint8 _CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool swap, Item *pSrcItem ) const;
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ std::string PlayerDumpWriter::GetDump(uint32 guid)
|
|||
return dump;
|
||||
}
|
||||
|
||||
DumpReturn PlayerDumpWriter::WriteDump(std::string file, uint32 guid)
|
||||
DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid)
|
||||
{
|
||||
FILE *fout = fopen(file.c_str(), "w");
|
||||
if (!fout)
|
||||
|
|
@ -353,7 +353,7 @@ DumpReturn PlayerDumpWriter::WriteDump(std::string file, uint32 guid)
|
|||
// Reading - High-level functions
|
||||
#define ROLLBACK(DR) {CharacterDatabase.RollbackTransaction(); fclose(fin); return (DR);}
|
||||
|
||||
DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::string name, uint32 guid)
|
||||
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid)
|
||||
{
|
||||
// check character count
|
||||
{
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ class PlayerDumpWriter : public PlayerDump
|
|||
PlayerDumpWriter() {}
|
||||
|
||||
std::string GetDump(uint32 guid);
|
||||
DumpReturn WriteDump(std::string file, uint32 guid);
|
||||
DumpReturn WriteDump(const std::string& file, uint32 guid);
|
||||
private:
|
||||
typedef std::set<uint32> GUIDs;
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ class PlayerDumpReader : public PlayerDump
|
|||
public:
|
||||
PlayerDumpReader() {}
|
||||
|
||||
DumpReturn LoadDump(std::string file, uint32 account, std::string name, uint32 guid);
|
||||
DumpReturn LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "NPCHandler.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Pet.h"
|
||||
#include "MapManager.h"
|
||||
|
||||
void WorldSession::SendNameQueryOpcode(Player *p)
|
||||
{
|
||||
|
|
@ -183,7 +184,6 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
|
|||
data << (uint32)ci->type;
|
||||
data << (uint32)ci->family; // family wdbFeild9
|
||||
data << (uint32)ci->rank; // rank wdbFeild10
|
||||
data << (uint32)0; // unknown wdbFeild11
|
||||
data << (uint32)ci->PetSpellDataId; // Id from CreatureSpellData.dbc wdbField12
|
||||
data << (uint32)ci->DisplayID_A; // modelid_male1
|
||||
data << (uint32)ci->DisplayID_H; // modelid_female1 ?
|
||||
|
|
@ -275,20 +275,43 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/)
|
|||
|
||||
Corpse *corpse = GetPlayer()->GetCorpse();
|
||||
|
||||
uint8 found = 1;
|
||||
if(!corpse)
|
||||
found = 0;
|
||||
|
||||
WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4)));
|
||||
data << uint8(found);
|
||||
if(found)
|
||||
{
|
||||
data << corpse->GetMapId();
|
||||
data << corpse->GetPositionX();
|
||||
data << corpse->GetPositionY();
|
||||
data << corpse->GetPositionZ();
|
||||
data << _player->GetMapId();
|
||||
WorldPacket data(MSG_CORPSE_QUERY, 1);
|
||||
data << uint8(0); // corpse not found
|
||||
SendPacket(&data);
|
||||
return;
|
||||
}
|
||||
|
||||
int32 mapid = corpse->GetMapId();
|
||||
float x = corpse->GetPositionX();
|
||||
float y = corpse->GetPositionY();
|
||||
float z = corpse->GetPositionZ();
|
||||
int32 corpsemapid = _player->GetMapId();
|
||||
|
||||
if(Map *map = corpse->GetMap())
|
||||
{
|
||||
if(map->IsDungeon())
|
||||
{
|
||||
if(!map->GetEntrancePos(mapid, x, y))
|
||||
return;
|
||||
|
||||
Map *entrance_map = MapManager::Instance().GetMap(mapid, _player);
|
||||
if(!entrance_map)
|
||||
return;
|
||||
|
||||
z = entrance_map->GetHeight(x, y, MAX_HEIGHT);
|
||||
corpsemapid = corpse->GetMapId();
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data(MSG_CORPSE_QUERY, 1+(5*4));
|
||||
data << uint8(1); // corpse found
|
||||
data << int32(mapid);
|
||||
data << float(x);
|
||||
data << float(y);
|
||||
data << float(z);
|
||||
data << int32(corpsemapid);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,88 +42,90 @@ Quest::Quest(Field * questRecord)
|
|||
QuestFlags = questRecord[17].GetUInt16();
|
||||
uint32 SpecialFlags = questRecord[18].GetUInt16();
|
||||
CharTitleId = questRecord[19].GetUInt32();
|
||||
PrevQuestId = questRecord[20].GetInt32();
|
||||
NextQuestId = questRecord[21].GetInt32();
|
||||
ExclusiveGroup = questRecord[22].GetInt32();
|
||||
NextQuestInChain = questRecord[23].GetUInt32();
|
||||
SrcItemId = questRecord[24].GetUInt32();
|
||||
SrcItemCount = questRecord[25].GetUInt32();
|
||||
SrcSpell = questRecord[26].GetUInt32();
|
||||
Title = questRecord[27].GetCppString();
|
||||
Details = questRecord[28].GetCppString();
|
||||
Objectives = questRecord[29].GetCppString();
|
||||
OfferRewardText = questRecord[30].GetCppString();
|
||||
RequestItemsText = questRecord[31].GetCppString();
|
||||
EndText = questRecord[32].GetCppString();
|
||||
PlayersSlain = questRecord[20].GetUInt32();
|
||||
BonusTalents = questRecord[21].GetUInt32();
|
||||
PrevQuestId = questRecord[22].GetInt32();
|
||||
NextQuestId = questRecord[23].GetInt32();
|
||||
ExclusiveGroup = questRecord[24].GetInt32();
|
||||
NextQuestInChain = questRecord[25].GetUInt32();
|
||||
SrcItemId = questRecord[26].GetUInt32();
|
||||
SrcItemCount = questRecord[27].GetUInt32();
|
||||
SrcSpell = questRecord[28].GetUInt32();
|
||||
Title = questRecord[29].GetCppString();
|
||||
Details = questRecord[30].GetCppString();
|
||||
Objectives = questRecord[31].GetCppString();
|
||||
OfferRewardText = questRecord[32].GetCppString();
|
||||
RequestItemsText = questRecord[33].GetCppString();
|
||||
EndText = questRecord[34].GetCppString();
|
||||
|
||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
||||
ObjectiveText[i] = questRecord[33+i].GetCppString();
|
||||
ObjectiveText[i] = questRecord[35+i].GetCppString();
|
||||
|
||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
||||
ReqItemId[i] = questRecord[37+i].GetUInt32();
|
||||
ReqItemId[i] = questRecord[39+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
||||
ReqItemCount[i] = questRecord[41+i].GetUInt32();
|
||||
ReqItemCount[i] = questRecord[43+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
|
||||
ReqSourceId[i] = questRecord[45+i].GetUInt32();
|
||||
ReqSourceId[i] = questRecord[47+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
|
||||
ReqSourceCount[i] = questRecord[49+i].GetUInt32();
|
||||
ReqSourceCount[i] = questRecord[51+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i)
|
||||
ReqSourceRef[i] = questRecord[53+i].GetUInt32();
|
||||
ReqSourceRef[i] = questRecord[55+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
||||
ReqCreatureOrGOId[i] = questRecord[57+i].GetInt32();
|
||||
ReqCreatureOrGOId[i] = questRecord[59+i].GetInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
||||
ReqCreatureOrGOCount[i] = questRecord[61+i].GetUInt32();
|
||||
ReqCreatureOrGOCount[i] = questRecord[63+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
||||
ReqSpell[i] = questRecord[65+i].GetUInt32();
|
||||
ReqSpell[i] = questRecord[67+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
RewChoiceItemId[i] = questRecord[69+i].GetUInt32();
|
||||
RewChoiceItemId[i] = questRecord[71+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
|
||||
RewChoiceItemCount[i] = questRecord[75+i].GetUInt32();
|
||||
RewChoiceItemCount[i] = questRecord[77+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
RewItemId[i] = questRecord[81+i].GetUInt32();
|
||||
RewItemId[i] = questRecord[83+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||
RewItemCount[i] = questRecord[85+i].GetUInt32();
|
||||
RewItemCount[i] = questRecord[87+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
RewRepFaction[i] = questRecord[89+i].GetUInt32();
|
||||
RewRepFaction[i] = questRecord[91+i].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i)
|
||||
RewRepValue[i] = questRecord[94+i].GetInt32();
|
||||
RewRepValue[i] = questRecord[96+i].GetInt32();
|
||||
|
||||
RewHonorableKills = questRecord[99].GetUInt32();
|
||||
RewOrReqMoney = questRecord[100].GetInt32();
|
||||
RewMoneyMaxLevel = questRecord[101].GetUInt32();
|
||||
RewSpell = questRecord[102].GetUInt32();
|
||||
RewSpellCast = questRecord[103].GetUInt32();
|
||||
RewMailTemplateId = questRecord[104].GetUInt32();
|
||||
RewMailDelaySecs = questRecord[105].GetUInt32();
|
||||
PointMapId = questRecord[106].GetUInt32();
|
||||
PointX = questRecord[107].GetFloat();
|
||||
PointY = questRecord[108].GetFloat();
|
||||
PointOpt = questRecord[109].GetUInt32();
|
||||
RewHonorableKills = questRecord[101].GetUInt32();
|
||||
RewOrReqMoney = questRecord[102].GetInt32();
|
||||
RewMoneyMaxLevel = questRecord[103].GetUInt32();
|
||||
RewSpell = questRecord[104].GetUInt32();
|
||||
RewSpellCast = questRecord[105].GetUInt32();
|
||||
RewMailTemplateId = questRecord[106].GetUInt32();
|
||||
RewMailDelaySecs = questRecord[107].GetUInt32();
|
||||
PointMapId = questRecord[108].GetUInt32();
|
||||
PointX = questRecord[109].GetFloat();
|
||||
PointY = questRecord[110].GetFloat();
|
||||
PointOpt = questRecord[111].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
|
||||
DetailsEmote[i] = questRecord[110+i].GetUInt32();
|
||||
DetailsEmote[i] = questRecord[112+i].GetUInt32();
|
||||
|
||||
IncompleteEmote = questRecord[114].GetUInt32();
|
||||
CompleteEmote = questRecord[115].GetUInt32();
|
||||
IncompleteEmote = questRecord[116].GetUInt32();
|
||||
CompleteEmote = questRecord[117].GetUInt32();
|
||||
|
||||
for (int i = 0; i < QUEST_EMOTE_COUNT; ++i)
|
||||
OfferRewardEmote[i] = questRecord[116+i].GetInt32();
|
||||
OfferRewardEmote[i] = questRecord[118+i].GetInt32();
|
||||
|
||||
QuestStartScript = questRecord[120].GetUInt32();
|
||||
QuestCompleteScript = questRecord[121].GetUInt32();
|
||||
QuestStartScript = questRecord[122].GetUInt32();
|
||||
QuestCompleteScript = questRecord[123].GetUInt32();
|
||||
|
||||
QuestFlags |= SpecialFlags << 16;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,30 +42,33 @@ class ObjectMgr;
|
|||
enum QuestFailedReasons
|
||||
{
|
||||
INVALIDREASON_DONT_HAVE_REQ = 0,
|
||||
INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, //You are not high enough level for that quest.
|
||||
INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, //That quest is not available to your race.
|
||||
INVALIDREASON_QUEST_ALREADY_DONE = 7, //You have completed that quest.
|
||||
INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, //You can only be on one timed quest at a time.
|
||||
INVALIDREASON_QUEST_ALREADY_ON = 13, //You are already on that quest
|
||||
INVALIDREASON_QUEST_FAILED_EXPANSION = 16, //This quest requires an expansion enabled account.
|
||||
INVALIDREASON_QUEST_ALREADY_ON2 = 18, //You are already on that quest
|
||||
INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, //You don't have the required items with you. Check storage.
|
||||
INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, //You don't have enough money for that quest.
|
||||
INVALIDREASON_DAILY_QUESTS_REMAINING = 26, //You have already completed 10 daily quests today
|
||||
INVALIDREASON_QUEST_FAILED_CAIS = 27, //You cannot complete quests once you have reached tired time
|
||||
INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, // You are not high enough level for that quest.
|
||||
INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, // That quest is not available to your race.
|
||||
INVALIDREASON_QUEST_ALREADY_DONE = 7, // You have completed that quest.
|
||||
INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, // You can only be on one timed quest at a time.
|
||||
INVALIDREASON_QUEST_ALREADY_ON = 13, // You are already on that quest.
|
||||
INVALIDREASON_QUEST_FAILED_EXPANSION = 16, // This quest requires an expansion enabled account.
|
||||
INVALIDREASON_QUEST_ALREADY_ON2 = 18, // You are already on that quest.
|
||||
INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, // You don't have the required items with you. Check storage.
|
||||
INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, // You don't have enough money for that quest.
|
||||
INVALIDREASON_DAILY_QUESTS_REMAINING = 26, // You have already completed 25 daily quests today.
|
||||
INVALIDREASON_QUEST_FAILED_CAIS = 27, // You cannot complete quests once you have reached tired time.
|
||||
INVALIDREASON_DAILY_QUEST_COMPLETED_TODAY = 29 // You have completed that daily quest today.
|
||||
};
|
||||
|
||||
enum QuestShareMessages
|
||||
{
|
||||
QUEST_PARTY_MSG_SHARING_QUEST = 0,
|
||||
QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1,
|
||||
QUEST_PARTY_MSG_ACCEPT_QUEST = 2,
|
||||
QUEST_PARTY_MSG_REFUSE_QUEST = 3,
|
||||
QUEST_PARTY_MSG_TOO_FAR = 4,
|
||||
QUEST_PARTY_MSG_BUSY = 5,
|
||||
QUEST_PARTY_MSG_LOG_FULL = 6,
|
||||
QUEST_PARTY_MSG_HAVE_QUEST = 7,
|
||||
QUEST_PARTY_MSG_FINISH_QUEST = 8,
|
||||
QUEST_PARTY_MSG_SHARING_QUEST = 0,
|
||||
QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1,
|
||||
QUEST_PARTY_MSG_ACCEPT_QUEST = 2,
|
||||
QUEST_PARTY_MSG_DECLINE_QUEST = 3,
|
||||
QUEST_PARTY_MSG_BUSY = 4,
|
||||
QUEST_PARTY_MSG_LOG_FULL = 5,
|
||||
QUEST_PARTY_MSG_HAVE_QUEST = 6,
|
||||
QUEST_PARTY_MSG_FINISH_QUEST = 7,
|
||||
QUEST_PARTY_MSG_CANT_BE_SHARED_TODAY = 8,
|
||||
QUEST_PARTY_MSG_SHARING_TIMER_EXPIRED = 9,
|
||||
QUEST_PARTY_MSG_NOT_IN_PARTY = 10
|
||||
};
|
||||
|
||||
enum __QuestTradeSkill
|
||||
|
|
@ -188,6 +191,8 @@ class Quest
|
|||
int32 GetExclusiveGroup() const { return ExclusiveGroup; }
|
||||
uint32 GetNextQuestInChain() const { return NextQuestInChain; }
|
||||
uint32 GetCharTitleId() const { return CharTitleId; }
|
||||
uint32 GetPlayersSlain() const { return PlayersSlain; }
|
||||
uint32 GetBonusTalents() const { return BonusTalents; }
|
||||
uint32 GetSrcItemId() const { return SrcItemId; }
|
||||
uint32 GetSrcItemCount() const { return SrcItemCount; }
|
||||
uint32 GetSrcSpell() const { return SrcSpell; }
|
||||
|
|
@ -275,6 +280,8 @@ class Quest
|
|||
uint32 LimitTime;
|
||||
uint32 QuestFlags;
|
||||
uint32 CharTitleId;
|
||||
uint32 PlayersSlain;
|
||||
uint32 BonusTalents;
|
||||
int32 PrevQuestId;
|
||||
int32 NextQuestId;
|
||||
int32 ExclusiveGroup;
|
||||
|
|
|
|||
|
|
@ -441,12 +441,6 @@ void WorldSession::HandleQuestPushToParty(WorldPacket& recvPacket)
|
|||
|
||||
_player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST);
|
||||
|
||||
if( _player->GetDistance( pPlayer ) > 10 )
|
||||
{
|
||||
_player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_TOO_FAR );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !pPlayer->SatisfyQuestStatus( pQuest, false ) )
|
||||
{
|
||||
_player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_HAVE_QUEST );
|
||||
|
|
|
|||
|
|
@ -40,16 +40,24 @@ enum Races
|
|||
RACE_TAUREN = 6,
|
||||
RACE_GNOME = 7,
|
||||
RACE_TROLL = 8,
|
||||
RACE_GOBLIN = 9,
|
||||
//RACE_GOBLIN = 9,
|
||||
RACE_BLOODELF = 10,
|
||||
RACE_DRAENEI = 11,
|
||||
RACE_FEL_ORC = 12,
|
||||
RACE_NAGA = 13,
|
||||
RACE_BROKEN = 14,
|
||||
RACE_SKELETON = 15,
|
||||
MAX_RACES = 16
|
||||
//RACE_FEL_ORC = 12,
|
||||
//RACE_NAGA = 13,
|
||||
//RACE_BROKEN = 14,
|
||||
//RACE_SKELETON = 15,
|
||||
//RACE_VRYKUL = 16,
|
||||
//RACE_TUSKARR = 17,
|
||||
//RACE_FOREST_TROLL = 18,
|
||||
//RACE_TAUNKA = 19,
|
||||
//RACE_NORTHREND_SKELETON = 20,
|
||||
//RACE_ICE_TROLL = 21
|
||||
};
|
||||
|
||||
// max+1 for player race
|
||||
#define MAX_RACES 12
|
||||
|
||||
#define RACEMASK_ALL_PLAYABLE \
|
||||
((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \
|
||||
(1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \
|
||||
|
|
@ -70,13 +78,16 @@ enum Classes
|
|||
CLASS_WARLOCK = 9,
|
||||
// CLASS_UNK2 = 10,unused
|
||||
CLASS_DRUID = 11,
|
||||
MAX_CLASSES = 12
|
||||
};
|
||||
|
||||
// max+1 for player class
|
||||
#define MAX_CLASSES 12
|
||||
|
||||
#define CLASSMASK_ALL_PLAYABLE \
|
||||
((1<<(CLASS_WARRIOR-1))|(1<<(CLASS_PALADIN-1))|(1<<(CLASS_HUNTER-1))| \
|
||||
(1<<(CLASS_ROGUE-1)) |(1<<(CLASS_PRIEST-1)) |(1<<(CLASS_SHAMAN-1))| \
|
||||
(1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) )
|
||||
(1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) | \
|
||||
(1<<(CLASS_DEATH_KNIGHT-1)) )
|
||||
|
||||
#define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1)))
|
||||
|
||||
|
|
@ -122,11 +133,12 @@ enum Powers
|
|||
POWER_FOCUS = 2,
|
||||
POWER_ENERGY = 3,
|
||||
POWER_HAPPINESS = 4,
|
||||
POWER_RUNES = 5,
|
||||
POWER_RUNE = 5,
|
||||
POWER_RUNIC_POWER = 6,
|
||||
POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value)
|
||||
};
|
||||
|
||||
#define MAX_POWERS 5 // not count POWER_RUNES for now
|
||||
#define MAX_POWERS 7
|
||||
|
||||
enum SpellSchools
|
||||
{
|
||||
|
|
@ -187,10 +199,11 @@ enum ItemQualities
|
|||
ITEM_QUALITY_RARE = 3, //BLUE
|
||||
ITEM_QUALITY_EPIC = 4, //PURPLE
|
||||
ITEM_QUALITY_LEGENDARY = 5, //ORANGE
|
||||
ITEM_QUALITY_ARTIFACT = 6 //LIGHT YELLOW
|
||||
ITEM_QUALITY_ARTIFACT = 6, //LIGHT YELLOW
|
||||
ITEM_QUALITY_HEIRLOOM = 7
|
||||
};
|
||||
|
||||
#define MAX_ITEM_QUALITY 7
|
||||
#define MAX_ITEM_QUALITY 8
|
||||
|
||||
// ***********************************
|
||||
// Spell Attributes definitions
|
||||
|
|
@ -199,7 +212,7 @@ enum ItemQualities
|
|||
#define SPELL_ATTR_UNK0 0x00000001 // 0
|
||||
#define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilites have this flag
|
||||
#define SPELL_ATTR_ON_NEXT_SWING_1 0x00000004 // 2 on next swing
|
||||
#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 2.4.2
|
||||
#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 3.0.3
|
||||
#define SPELL_ATTR_UNK4 0x00000010 // 4
|
||||
#define SPELL_ATTR_UNK5 0x00000020 // 5 trade spells?
|
||||
#define SPELL_ATTR_PASSIVE 0x00000040 // 6 Passive spell
|
||||
|
|
@ -254,7 +267,7 @@ enum ItemQualities
|
|||
#define SPELL_ATTR_EX_REQ_COMBO_POINTS2 0x00400000 // 22 Req combo points on target
|
||||
#define SPELL_ATTR_EX_UNK23 0x00800000 // 23
|
||||
#define SPELL_ATTR_EX_UNK24 0x01000000 // 24 Req fishing pole??
|
||||
#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX_UNK25 0x02000000 // 25
|
||||
#define SPELL_ATTR_EX_UNK26 0x04000000 // 26
|
||||
#define SPELL_ATTR_EX_UNK27 0x08000000 // 27
|
||||
#define SPELL_ATTR_EX_UNK28 0x10000000 // 28
|
||||
|
|
@ -270,14 +283,14 @@ enum ItemQualities
|
|||
#define SPELL_ATTR_EX2_UNK5 0x00000020 // 5
|
||||
#define SPELL_ATTR_EX2_UNK6 0x00000040 // 6
|
||||
#define SPELL_ATTR_EX2_UNK7 0x00000080 // 7
|
||||
#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX2_UNK9 0x00000200 // 9
|
||||
#define SPELL_ATTR_EX2_UNK10 0x00000400 // 10
|
||||
#define SPELL_ATTR_EX2_HEALTH_FUNNEL 0x00000800 // 11
|
||||
#define SPELL_ATTR_EX2_UNK12 0x00001000 // 12
|
||||
#define SPELL_ATTR_EX2_UNK13 0x00002000 // 13
|
||||
#define SPELL_ATTR_EX2_UNK14 0x00004000 // 14
|
||||
#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX2_UNK16 0x00010000 // 16
|
||||
#define SPELL_ATTR_EX2_UNK17 0x00020000 // 17 Hunters Shot and Stings only have this flag
|
||||
#define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet
|
||||
|
|
@ -395,37 +408,37 @@ enum ItemQualities
|
|||
#define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster
|
||||
|
||||
#define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag
|
||||
#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK2 0x00000004 // 2
|
||||
#define SPELL_ATTR_EX6_UNK3 0x00000008 // 3
|
||||
#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4
|
||||
#define SPELL_ATTR_EX6_UNK5 0x00000020 // 5
|
||||
#define SPELL_ATTR_EX6_UNK6 0x00000040 // 6
|
||||
#define SPELL_ATTR_EX6_UNK7 0x00000080 // 7
|
||||
#define SPELL_ATTR_EX6_UNK8 0x00000100 // 8
|
||||
#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9
|
||||
#define SPELL_ATTR_EX6_UNK10 0x00000400 // 10
|
||||
#define SPELL_ATTR_EX6_UNK11 0x00000800 // 11
|
||||
#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 2.4.2
|
||||
#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12
|
||||
#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13
|
||||
#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14
|
||||
#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16
|
||||
#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17
|
||||
#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18
|
||||
#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19
|
||||
#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20
|
||||
#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21
|
||||
#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22
|
||||
#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3
|
||||
#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3
|
||||
|
||||
enum SheathTypes
|
||||
{
|
||||
|
|
@ -548,7 +561,7 @@ enum SpellEffects
|
|||
SPELL_EFFECT_SUMMON_GUARDIAN = 42,
|
||||
SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER= 43,
|
||||
SPELL_EFFECT_SKILL_STEP = 44,
|
||||
SPELL_EFFECT_UNDEFINED_45 = 45,
|
||||
SPELL_EFFECT_ADD_HONOR = 45,
|
||||
SPELL_EFFECT_SPAWN = 46,
|
||||
SPELL_EFFECT_TRADE_SKILL = 47,
|
||||
SPELL_EFFECT_STEALTH = 48,
|
||||
|
|
@ -568,16 +581,16 @@ enum SpellEffects
|
|||
SPELL_EFFECT_POWER_BURN = 62,
|
||||
SPELL_EFFECT_THREAT = 63,
|
||||
SPELL_EFFECT_TRIGGER_SPELL = 64,
|
||||
SPELL_EFFECT_HEALTH_FUNNEL = 65,
|
||||
SPELL_EFFECT_POWER_FUNNEL = 66,
|
||||
SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65,
|
||||
SPELL_EFFECT_CREATE_MANA_GEM = 66,
|
||||
SPELL_EFFECT_HEAL_MAX_HEALTH = 67,
|
||||
SPELL_EFFECT_INTERRUPT_CAST = 68,
|
||||
SPELL_EFFECT_DISTRACT = 69,
|
||||
SPELL_EFFECT_PULL = 70,
|
||||
SPELL_EFFECT_PICKPOCKET = 71,
|
||||
SPELL_EFFECT_ADD_FARSIGHT = 72,
|
||||
SPELL_EFFECT_SUMMON_POSSESSED = 73,
|
||||
SPELL_EFFECT_SUMMON_TOTEM = 74,
|
||||
SPELL_EFFECT_UNTRAIN_TALENTS = 73,
|
||||
SPELL_EFFECT_APPLY_GLYPH = 74,
|
||||
SPELL_EFFECT_HEAL_MECHANICAL = 75,
|
||||
SPELL_EFFECT_SUMMON_OBJECT_WILD = 76,
|
||||
SPELL_EFFECT_SCRIPT_EFFECT = 77,
|
||||
|
|
@ -590,10 +603,10 @@ enum SpellEffects
|
|||
SPELL_EFFECT_STUCK = 84,
|
||||
SPELL_EFFECT_SUMMON_PLAYER = 85,
|
||||
SPELL_EFFECT_ACTIVATE_OBJECT = 86,
|
||||
SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87,
|
||||
SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88,
|
||||
SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89,
|
||||
SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90,
|
||||
SPELL_EFFECT_WMO_DAMAGE = 87,
|
||||
SPELL_EFFECT_WMO_REPAIR = 88,
|
||||
SPELL_EFFECT_WMO_CHANGE = 89,
|
||||
SPELL_EFFECT_KILL_CREDIT = 90,
|
||||
SPELL_EFFECT_THREAT_ALL = 91,
|
||||
SPELL_EFFECT_ENCHANT_HELD_ITEM = 92,
|
||||
SPELL_EFFECT_SUMMON_PHANTASM = 93,
|
||||
|
|
@ -637,19 +650,19 @@ enum SpellEffects
|
|||
SPELL_EFFECT_131 = 131,
|
||||
SPELL_EFFECT_132 = 132,
|
||||
SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133,
|
||||
SPELL_EFFECT_KILL_CREDIT = 134,
|
||||
SPELL_EFFECT_KILL_CREDIT2 = 134,
|
||||
SPELL_EFFECT_135 = 135,
|
||||
SPELL_EFFECT_HEAL_PCT = 136,
|
||||
SPELL_EFFECT_ENERGIZE_PCT = 137,
|
||||
SPELL_EFFECT_138 = 138,
|
||||
SPELL_EFFECT_139 = 139,
|
||||
SPELL_EFFECT_CLEAR_QUEST = 139,
|
||||
SPELL_EFFECT_FORCE_CAST = 140,
|
||||
SPELL_EFFECT_141 = 141,
|
||||
SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142,
|
||||
SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143,
|
||||
SPELL_EFFECT_144 = 144,
|
||||
SPELL_EFFECT_145 = 145,
|
||||
SPELL_EFFECT_146 = 146,
|
||||
SPELL_EFFECT_ACTIVATE_RUNE = 146,
|
||||
SPELL_EFFECT_QUEST_FAIL = 147,
|
||||
SPELL_EFFECT_148 = 148,
|
||||
SPELL_EFFECT_149 = 149,
|
||||
|
|
@ -657,7 +670,13 @@ enum SpellEffects
|
|||
SPELL_EFFECT_TRIGGER_SPELL_2 = 151,
|
||||
SPELL_EFFECT_152 = 152,
|
||||
SPELL_EFFECT_153 = 153,
|
||||
TOTAL_SPELL_EFFECTS = 154
|
||||
SPELL_EFFECT_154 = 154,
|
||||
SPELL_EFFECT_TITAN_GRIP = 155,
|
||||
SPELL_EFFECT_ADD_SOCKET = 156,
|
||||
SPELL_EFFECT_157 = 157,
|
||||
SPELL_EFFECT_MILLING = 158,
|
||||
SPELL_EFFECT_ALLOW_RENAME_PET = 159,
|
||||
TOTAL_SPELL_EFFECTS = 160
|
||||
};
|
||||
|
||||
// Spell aura states
|
||||
|
|
@ -685,7 +704,8 @@ enum AuraState
|
|||
AURA_STATE_DEADLY_POISON = 16, // T |
|
||||
AURA_STATE_FORBEARANCE = 17, // c t|
|
||||
AURA_STATE_WEAKENED_SOUL = 18, // t|
|
||||
AURA_STATE_HYPOTHERMIA = 19 // c |
|
||||
AURA_STATE_HYPOTHERMIA = 19, // c |
|
||||
AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | not implemented yet
|
||||
};
|
||||
|
||||
// Spell mechanics
|
||||
|
|
@ -693,11 +713,11 @@ enum Mechanics
|
|||
{
|
||||
MECHANIC_NONE = 0,
|
||||
MECHANIC_CHARM = 1,
|
||||
MECHANIC_CONFUSED = 2,
|
||||
MECHANIC_DISORIENTED = 2,
|
||||
MECHANIC_DISARM = 3,
|
||||
MECHANIC_DISTRACT = 4,
|
||||
MECHANIC_FEAR = 5,
|
||||
MECHANIC_FUMBLE = 6,
|
||||
MECHANIC_GRIP = 6,
|
||||
MECHANIC_ROOT = 7,
|
||||
MECHANIC_PACIFY = 8, //0 spells use this mechanic
|
||||
MECHANIC_SILENCE = 9,
|
||||
|
|
@ -713,7 +733,7 @@ enum Mechanics
|
|||
MECHANIC_SHIELD = 19,
|
||||
MECHANIC_SHACKLE = 20,
|
||||
MECHANIC_MOUNT = 21,
|
||||
MECHANIC_PERSUADE = 22, //0 spells use this mechanic
|
||||
MECHANIC_INFECTED = 22,
|
||||
MECHANIC_TURN = 23,
|
||||
MECHANIC_HORROR = 24,
|
||||
MECHANIC_INVULNERABILITY = 25,
|
||||
|
|
@ -721,12 +741,13 @@ enum Mechanics
|
|||
MECHANIC_DAZE = 27,
|
||||
MECHANIC_DISCOVERY = 28,
|
||||
MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block
|
||||
MECHANIC_SAPPED = 30
|
||||
MECHANIC_SAPPED = 30,
|
||||
MECHANIC_ENRAGED = 31
|
||||
};
|
||||
|
||||
// Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967da6)
|
||||
#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK ( \
|
||||
(1<<MECHANIC_CHARM )|(1<<MECHANIC_CONFUSED )|(1<<MECHANIC_FEAR )| \
|
||||
(1<<MECHANIC_CHARM )|(1<<MECHANIC_DISORIENTED )|(1<<MECHANIC_FEAR )| \
|
||||
(1<<MECHANIC_ROOT )|(1<<MECHANIC_PACIFY )|(1<<MECHANIC_SLEEP )| \
|
||||
(1<<MECHANIC_SNARE )|(1<<MECHANIC_STUN )|(1<<MECHANIC_FREEZE)| \
|
||||
(1<<MECHANIC_KNOCKOUT)|(1<<MECHANIC_POLYMORPH)|(1<<MECHANIC_BANISH)| \
|
||||
|
|
@ -746,7 +767,8 @@ enum DispelType
|
|||
DISPEL_ALL = 7,
|
||||
DISPEL_SPE_NPC_ONLY = 8,
|
||||
DISPEL_ENRAGE = 9,
|
||||
DISPEL_ZG_TICKET = 10
|
||||
DISPEL_ZG_TICKET = 10,
|
||||
DESPEL_OLD_UNUSED = 11
|
||||
};
|
||||
|
||||
#define DISPEL_ALL_MASK ( (1<<DISPEL_MAGIC) | (1<<DISPEL_CURSE) | (1<<DISPEL_DISEASE) | (1<<DISPEL_POISON) )
|
||||
|
|
@ -894,9 +916,10 @@ enum GameobjectTypes
|
|||
GAMEOBJECT_TYPE_BARBER_CHAIR = 32,
|
||||
GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING = 33,
|
||||
GAMEOBJECT_TYPE_GUILD_BANK = 34,
|
||||
GAMEOBJECT_TYPE_TRAPDOOR = 35
|
||||
};
|
||||
|
||||
#define MAX_GAMEOBJECT_TYPE 35 // sending to client this or greater value can crash client.
|
||||
#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client.
|
||||
|
||||
#define GAMEOBJECT_FISHINGNODE_ENTRY 35591 // Better to define it somewhere instead of hardcoding everywhere
|
||||
|
||||
|
|
@ -1463,7 +1486,9 @@ enum LockType
|
|||
LOCKTYPE_BLASTING = 16,
|
||||
LOCKTYPE_SLOW_OPEN = 17,
|
||||
LOCKTYPE_SLOW_CLOSE = 18,
|
||||
LOCKTYPE_FISHING = 19
|
||||
LOCKTYPE_FISHING = 19,
|
||||
LOCKTYPE_INSCRIPTION = 20,
|
||||
LOCKTYPE_OPEN_FROM_VEHICLE = 21
|
||||
};
|
||||
|
||||
enum TrainerType // this is important type for npcs!
|
||||
|
|
@ -1517,7 +1542,7 @@ enum CreatureFamily
|
|||
CREATURE_FAMILY_IMP = 23,
|
||||
CREATURE_FAMILY_BAT = 24,
|
||||
CREATURE_FAMILY_HYENA = 25,
|
||||
CREATURE_FAMILY_OWL = 26,
|
||||
CREATURE_FAMILY_BIRD_OF_PREY = 26,
|
||||
CREATURE_FAMILY_WIND_SERPENT = 27,
|
||||
CREATURE_FAMILY_REMOTE_CONTROL = 28,
|
||||
CREATURE_FAMILY_FELGUARD = 29,
|
||||
|
|
@ -1527,7 +1552,16 @@ enum CreatureFamily
|
|||
CREATURE_FAMILY_SPOREBAT = 33,
|
||||
CREATURE_FAMILY_NETHER_RAY = 34,
|
||||
CREATURE_FAMILY_SERPENT = 35,
|
||||
CREATURE_FAMILY_SEA_LION = 36
|
||||
CREATURE_FAMILY_MOTH = 37,
|
||||
CREATURE_FAMILY_CHIMAERA = 38,
|
||||
CREATURE_FAMILY_DEVILSAUR = 39,
|
||||
CREATURE_FAMILY_GHOUL = 40,
|
||||
CREATURE_FAMILY_SILITHID = 41,
|
||||
CREATURE_FAMILY_WORM = 42,
|
||||
CREATURE_FAMILY_RHINO = 43,
|
||||
CREATURE_FAMILY_WASP = 44,
|
||||
CREATURE_FAMILY_CORE_HOUND = 45,
|
||||
CREATURE_FAMILY_SPIRIT_BEAST = 46
|
||||
};
|
||||
|
||||
enum CreatureTypeFlags
|
||||
|
|
@ -1559,6 +1593,8 @@ enum QuestTypes
|
|||
QUEST_TYPE_LEGENDARY = 83,
|
||||
QUEST_TYPE_ESCORT = 84,
|
||||
QUEST_TYPE_HEROIC = 85,
|
||||
QUEST_TYPE_RAID_10 = 88,
|
||||
QUEST_TYPE_RAID_25 = 89
|
||||
};
|
||||
|
||||
// values based at QuestSort.dbc
|
||||
|
|
@ -1569,7 +1605,7 @@ enum QuestSort
|
|||
QUEST_SORT_SEASONAL = 22,
|
||||
QUEST_SORT_UNDERCITY_OLD = 23,
|
||||
QUEST_SORT_HERBALISM = 24,
|
||||
QUEST_SORT_SCARLET_MONASTERY_OLD= 25,
|
||||
QUEST_SORT_BATTLEGROUNDS = 25,
|
||||
QUEST_SORT_ULDAMN_OLD = 41,
|
||||
QUEST_SORT_WARLOCK = 61,
|
||||
QUEST_SORT_WARRIOR = 81,
|
||||
|
|
@ -1598,22 +1634,26 @@ enum QuestSort
|
|||
QUEST_SORT_REPUTATION = 367,
|
||||
QUEST_SORT_INVASION = 368,
|
||||
QUEST_SORT_MIDSUMMER = 369,
|
||||
QUEST_SORT_BREWFEST = 370
|
||||
QUEST_SORT_BREWFEST = 370,
|
||||
QUEST_SORT_INSCRIPTION = 371,
|
||||
QUEST_SORT_DEATH_KNIGHT = 372,
|
||||
QUEST_SORT_JEWELCRAFTING = 373
|
||||
};
|
||||
|
||||
inline uint8 ClassByQuestSort(int32 QuestSort)
|
||||
{
|
||||
switch(QuestSort)
|
||||
{
|
||||
case QUEST_SORT_WARLOCK: return CLASS_WARLOCK;
|
||||
case QUEST_SORT_WARRIOR: return CLASS_WARRIOR;
|
||||
case QUEST_SORT_SHAMAN: return CLASS_SHAMAN;
|
||||
case QUEST_SORT_PALADIN: return CLASS_PALADIN;
|
||||
case QUEST_SORT_MAGE: return CLASS_MAGE;
|
||||
case QUEST_SORT_ROGUE: return CLASS_ROGUE;
|
||||
case QUEST_SORT_HUNTER: return CLASS_HUNTER;
|
||||
case QUEST_SORT_PRIEST: return CLASS_PRIEST;
|
||||
case QUEST_SORT_DRUID: return CLASS_DRUID;
|
||||
case QUEST_SORT_WARLOCK: return CLASS_WARLOCK;
|
||||
case QUEST_SORT_WARRIOR: return CLASS_WARRIOR;
|
||||
case QUEST_SORT_SHAMAN: return CLASS_SHAMAN;
|
||||
case QUEST_SORT_PALADIN: return CLASS_PALADIN;
|
||||
case QUEST_SORT_MAGE: return CLASS_MAGE;
|
||||
case QUEST_SORT_ROGUE: return CLASS_ROGUE;
|
||||
case QUEST_SORT_HUNTER: return CLASS_HUNTER;
|
||||
case QUEST_SORT_PRIEST: return CLASS_PRIEST;
|
||||
case QUEST_SORT_DRUID: return CLASS_DRUID;
|
||||
case QUEST_SORT_DEATH_KNIGHT: return CLASS_DEATH_KNIGHT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1625,7 +1665,6 @@ enum SkillType
|
|||
SKILL_ARMS = 26,
|
||||
SKILL_COMBAT = 38,
|
||||
SKILL_SUBTLETY = 39,
|
||||
SKILL_POISONS = 40,
|
||||
SKILL_SWORDS = 43,
|
||||
SKILL_AXES = 44,
|
||||
SKILL_BOWS = 45,
|
||||
|
|
@ -1633,8 +1672,8 @@ enum SkillType
|
|||
SKILL_BEAST_MASTERY = 50,
|
||||
SKILL_SURVIVAL = 51,
|
||||
SKILL_MACES = 54,
|
||||
SKILL_HOLY = 56,
|
||||
SKILL_2H_SWORDS = 55,
|
||||
SKILL_HOLY = 56,
|
||||
SKILL_SHADOW = 78,
|
||||
SKILL_DEFENSE = 95,
|
||||
SKILL_LANG_COMMON = 98,
|
||||
|
|
@ -1690,24 +1729,20 @@ enum SkillType
|
|||
SKILL_PET_BOAR = 211,
|
||||
SKILL_PET_CROCILISK = 212,
|
||||
SKILL_PET_CARRION_BIRD = 213,
|
||||
SKILL_PET_GORILLA = 215,
|
||||
SKILL_PET_CRAB = 214,
|
||||
SKILL_PET_GORILLA = 215,
|
||||
SKILL_PET_RAPTOR = 217,
|
||||
SKILL_PET_TALLSTRIDER = 218,
|
||||
SKILL_RACIAL_UNDED = 220,
|
||||
SKILL_WEAPON_TALENTS = 222,
|
||||
SKILL_CROSSBOWS = 226,
|
||||
SKILL_SPEARS = 227,
|
||||
SKILL_WANDS = 228,
|
||||
SKILL_POLEARMS = 229,
|
||||
SKILL_PET_SCORPID = 236,
|
||||
SKILL_ARCANE = 237,
|
||||
SKILL_OPEN_LOCK = 242,
|
||||
SKILL_PET_TURTLE = 251,
|
||||
SKILL_ASSASSINATION = 253,
|
||||
SKILL_FURY = 256,
|
||||
SKILL_PROTECTION = 257,
|
||||
SKILL_BEAST_TRAINING = 261,
|
||||
SKILL_PROTECTION2 = 267,
|
||||
SKILL_PET_TALENTS = 270,
|
||||
SKILL_PLATE_MAIL = 293,
|
||||
|
|
@ -1737,7 +1772,7 @@ enum SkillType
|
|||
SKILL_LOCKPICKING = 633,
|
||||
SKILL_PET_BAT = 653,
|
||||
SKILL_PET_HYENA = 654,
|
||||
SKILL_PET_OWL = 655,
|
||||
SKILL_PET_BIRD_OF_PREY = 655,
|
||||
SKILL_PET_WIND_SERPENT = 656,
|
||||
SKILL_LANG_GUTTERSPEAK = 673,
|
||||
SKILL_RIDING_KODO = 713,
|
||||
|
|
@ -1757,10 +1792,27 @@ enum SkillType
|
|||
SKILL_PET_WARP_STALKER = 766,
|
||||
SKILL_PET_RAVAGER = 767,
|
||||
SKILL_PET_SERPENT = 768,
|
||||
SKILL_INTERNAL = 769
|
||||
SKILL_INTERNAL = 769,
|
||||
SKILL_DK_BLOOD = 770,
|
||||
SKILL_DK_FROST = 771,
|
||||
SKILL_DK_UNHOLY = 772,
|
||||
SKILL_INSCRIPTION = 773,
|
||||
SKILL_PET_MOTH = 775,
|
||||
SKILL_RUNEFORGING = 776,
|
||||
SKILL_MOUNTS = 777,
|
||||
SKILL_COMPANIONS = 778,
|
||||
SKILL_PET_EXOTIC_CHIMAERA = 780,
|
||||
SKILL_PET_EXOTIC_DEVILSAUR = 781,
|
||||
SKILL_PET_GHOUL = 782,
|
||||
SKILL_PET_EXOTIC_SILITHID = 783,
|
||||
SKILL_PET_EXOTIC_WORM = 784,
|
||||
SKILL_PET_WASP = 785,
|
||||
SKILL_PET_EXOTIC_RHINO = 786,
|
||||
SKILL_PET_EXOTIC_CORE_HOUND = 787,
|
||||
SKILL_PET_EXOTIC_SPIRIT_BEAST = 788
|
||||
};
|
||||
|
||||
#define MAX_SKILL_TYPE 770
|
||||
#define MAX_SKILL_TYPE 789
|
||||
|
||||
inline uint32 SkillByQuestSort(int32 QuestSort)
|
||||
{
|
||||
|
|
@ -1775,25 +1827,27 @@ inline uint32 SkillByQuestSort(int32 QuestSort)
|
|||
case QUEST_SORT_TAILORING: return SKILL_TAILORING;
|
||||
case QUEST_SORT_COOKING: return SKILL_COOKING;
|
||||
case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID;
|
||||
case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING;
|
||||
case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum SkillCategory
|
||||
{
|
||||
SKILL_CATEGORY_ATTRIBUTES = 5,
|
||||
SKILL_CATEGORY_WEAPON = 6,
|
||||
SKILL_CATEGORY_CLASS = 7,
|
||||
SKILL_CATEGORY_ARMOR = 8,
|
||||
SKILL_CATEGORY_SECONDARY = 9, // secondary professions
|
||||
SKILL_CATEGORY_ATTRIBUTES = 5,
|
||||
SKILL_CATEGORY_WEAPON = 6,
|
||||
SKILL_CATEGORY_CLASS = 7,
|
||||
SKILL_CATEGORY_ARMOR = 8,
|
||||
SKILL_CATEGORY_SECONDARY = 9, // secondary professions
|
||||
SKILL_CATEGORY_LANGUAGES = 10,
|
||||
SKILL_CATEGORY_PROFESSION = 11, // primary professions
|
||||
SKILL_CATEGORY_NOT_DISPLAYED = 12
|
||||
SKILL_CATEGORY_GENERIC = 12
|
||||
};
|
||||
|
||||
enum TotemCategory
|
||||
{
|
||||
TC_SKINNING_SKIFE = 1,
|
||||
TC_SKINNING_SKIFE_OLD = 1,
|
||||
TC_EARTH_TOTEM = 2,
|
||||
TC_AIR_TOTEM = 3,
|
||||
TC_FIRE_TOTEM = 4,
|
||||
|
|
@ -1803,15 +1857,28 @@ enum TotemCategory
|
|||
TC_GOLDEN_ROD = 8,
|
||||
TC_TRUESILVER_ROD = 9,
|
||||
TC_ARCANITE_ROD = 10,
|
||||
TC_MINING_PICK = 11,
|
||||
TC_MINING_PICK_OLD = 11,
|
||||
TC_PHILOSOPHERS_STONE = 12,
|
||||
TC_BLACKSMITH_HAMMER = 13,
|
||||
TC_BLACKSMITH_HAMMER_OLD = 13,
|
||||
TC_ARCLIGHT_SPANNER = 14,
|
||||
TC_GYROMATIC_MA = 15,
|
||||
TC_MASTER_TOTEM = 21,
|
||||
TC_FEL_IRON_ROD = 41,
|
||||
TC_ADAMANTITE_ROD = 62,
|
||||
TC_ETERNIUM_ROD = 63
|
||||
TC_ETERNIUM_ROD = 63,
|
||||
TC_HOLLOW_QUILL = 81,
|
||||
TC_RUNED_AZURITE_ROD = 101,
|
||||
TC_VIRTUOSO_INKING_SET = 121,
|
||||
TC_DRUMS = 141,
|
||||
TC_GNOMISH_ARMY_KNIFE = 161,
|
||||
TC_BLACKSMITH_HAMMER = 162,
|
||||
TC_MINING_PICK = 165,
|
||||
TC_SKINNING_KNIFE = 166,
|
||||
TC_HAMMER_PICK = 167,
|
||||
TC_BLADED_PICKAXE = 168,
|
||||
TC_FLINT_AND_TINDER = 169,
|
||||
TC_RUNED_COBALT_ROD = 189,
|
||||
TC_RUNED_TITANIUM_ROD = 190
|
||||
};
|
||||
|
||||
enum UnitDynFlags
|
||||
|
|
@ -1821,7 +1888,8 @@ enum UnitDynFlags
|
|||
UNIT_DYNFLAG_OTHER_TAGGER = 0x0004,
|
||||
UNIT_DYNFLAG_ROOTED = 0x0008,
|
||||
UNIT_DYNFLAG_SPECIALINFO = 0x0010,
|
||||
UNIT_DYNFLAG_DEAD = 0x0020
|
||||
UNIT_DYNFLAG_DEAD = 0x0020,
|
||||
UNIT_DYNFLAG_REFER_A_FRIEND = 0x0040
|
||||
};
|
||||
|
||||
enum CorpseDynFlags
|
||||
|
|
@ -1831,6 +1899,7 @@ enum CorpseDynFlags
|
|||
|
||||
// Passive Spell codes explicit used in code
|
||||
#define SPELL_ID_GENERIC_LEARN 483
|
||||
#define SPELL_ID_GENERIC_LEARN_PET 55884 // used for learning mounts and companions
|
||||
#define SPELL_ID_PASSIVE_BATTLE_STANCE 2457
|
||||
#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007
|
||||
#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_5s 6119
|
||||
|
|
@ -1898,9 +1967,12 @@ enum ChatMsg
|
|||
CHAT_MSG_BATTLEGROUND = 0x2C,
|
||||
CHAT_MSG_BATTLEGROUND_LEADER = 0x2D,
|
||||
CHAT_MSG_RESTRICTED = 0x2E,
|
||||
CHAT_MSG_BN = 0x2F,
|
||||
CHAT_MSG_ACHIEVEMENT = 0x30,
|
||||
CHAT_MSG_GUILD_ACHIEVEMENT = 0x31
|
||||
};
|
||||
|
||||
#define MAX_CHAT_MSG_TYPE 0x2F
|
||||
#define MAX_CHAT_MSG_TYPE 0x32
|
||||
|
||||
// Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask
|
||||
enum PetDiet
|
||||
|
|
@ -2069,42 +2141,45 @@ enum ResponseCodes
|
|||
CHAR_CREATE_SERVER_QUEUE = 0x37,
|
||||
CHAR_CREATE_ONLY_EXISTING = 0x38,
|
||||
CHAR_CREATE_EXPANSION = 0x39,
|
||||
CHAR_CREATE_EXPANSION_CLASS = 0x3A,
|
||||
CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B,
|
||||
CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C,
|
||||
|
||||
CHAR_DELETE_IN_PROGRESS = 0x3A,
|
||||
CHAR_DELETE_SUCCESS = 0x3B,
|
||||
CHAR_DELETE_FAILED = 0x3C,
|
||||
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x3D,
|
||||
CHAR_DELETE_FAILED_GUILD_LEADER = 0x3E,
|
||||
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x3F,
|
||||
CHAR_DELETE_IN_PROGRESS = 0x3D,
|
||||
CHAR_DELETE_SUCCESS = 0x3E,
|
||||
CHAR_DELETE_FAILED = 0x3F,
|
||||
CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x40,
|
||||
CHAR_DELETE_FAILED_GUILD_LEADER = 0x41,
|
||||
CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x42,
|
||||
|
||||
CHAR_LOGIN_IN_PROGRESS = 0x40,
|
||||
CHAR_LOGIN_SUCCESS = 0x41,
|
||||
CHAR_LOGIN_NO_WORLD = 0x42,
|
||||
CHAR_LOGIN_DUPLICATE_CHARACTER = 0x43,
|
||||
CHAR_LOGIN_NO_INSTANCES = 0x44,
|
||||
CHAR_LOGIN_FAILED = 0x45,
|
||||
CHAR_LOGIN_DISABLED = 0x46,
|
||||
CHAR_LOGIN_NO_CHARACTER = 0x47,
|
||||
CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x48,
|
||||
CHAR_LOGIN_LOCKED_BY_BILLING = 0x49,
|
||||
CHAR_LOGIN_IN_PROGRESS = 0x43,
|
||||
CHAR_LOGIN_SUCCESS = 0x44,
|
||||
CHAR_LOGIN_NO_WORLD = 0x45,
|
||||
CHAR_LOGIN_DUPLICATE_CHARACTER = 0x46,
|
||||
CHAR_LOGIN_NO_INSTANCES = 0x47,
|
||||
CHAR_LOGIN_FAILED = 0x48,
|
||||
CHAR_LOGIN_DISABLED = 0x49,
|
||||
CHAR_LOGIN_NO_CHARACTER = 0x4A,
|
||||
CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x4B,
|
||||
CHAR_LOGIN_LOCKED_BY_BILLING = 0x4C,
|
||||
|
||||
CHAR_NAME_SUCCESS = 0x4A,
|
||||
CHAR_NAME_FAILURE = 0x4B,
|
||||
CHAR_NAME_NO_NAME = 0x4C,
|
||||
CHAR_NAME_TOO_SHORT = 0x4D,
|
||||
CHAR_NAME_TOO_LONG = 0x4E,
|
||||
CHAR_NAME_INVALID_CHARACTER = 0x4F,
|
||||
CHAR_NAME_MIXED_LANGUAGES = 0x50,
|
||||
CHAR_NAME_PROFANE = 0x51,
|
||||
CHAR_NAME_RESERVED = 0x52,
|
||||
CHAR_NAME_INVALID_APOSTROPHE = 0x53,
|
||||
CHAR_NAME_MULTIPLE_APOSTROPHES = 0x54,
|
||||
CHAR_NAME_THREE_CONSECUTIVE = 0x55,
|
||||
CHAR_NAME_INVALID_SPACE = 0x56,
|
||||
CHAR_NAME_CONSECUTIVE_SPACES = 0x57,
|
||||
CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x58,
|
||||
CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59,
|
||||
CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5A,
|
||||
CHAR_NAME_SUCCESS = 0x4D,
|
||||
CHAR_NAME_FAILURE = 0x4E,
|
||||
CHAR_NAME_NO_NAME = 0x4F,
|
||||
CHAR_NAME_TOO_SHORT = 0x50,
|
||||
CHAR_NAME_TOO_LONG = 0x51,
|
||||
CHAR_NAME_INVALID_CHARACTER = 0x52,
|
||||
CHAR_NAME_MIXED_LANGUAGES = 0x53,
|
||||
CHAR_NAME_PROFANE = 0x54,
|
||||
CHAR_NAME_RESERVED = 0x55,
|
||||
CHAR_NAME_INVALID_APOSTROPHE = 0x56,
|
||||
CHAR_NAME_MULTIPLE_APOSTROPHES = 0x57,
|
||||
CHAR_NAME_THREE_CONSECUTIVE = 0x58,
|
||||
CHAR_NAME_INVALID_SPACE = 0x59,
|
||||
CHAR_NAME_CONSECUTIVE_SPACES = 0x5A,
|
||||
CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x5B,
|
||||
CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x5C,
|
||||
CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5D
|
||||
};
|
||||
|
||||
/// Ban function modes
|
||||
|
|
|
|||
|
|
@ -80,10 +80,6 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data )
|
|||
}
|
||||
}
|
||||
|
||||
// Check if it requires spell
|
||||
if( talentInfo->DependsOnSpell && !player->HasSpell(talentInfo->DependsOnSpell) )
|
||||
return;
|
||||
|
||||
// Find out how many points we have in this field
|
||||
uint32 spentPoints = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ struct FriendInfo
|
|||
Note = "";
|
||||
}
|
||||
|
||||
FriendInfo(uint32 flags, std::string note)
|
||||
FriendInfo(uint32 flags, const std::string& note)
|
||||
{
|
||||
Status = FRIEND_STATUS_OFFLINE;
|
||||
Flags = flags;
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ void SpellCastTargets::write ( WorldPacket * data )
|
|||
{
|
||||
*data << uint32(m_targetMask);
|
||||
|
||||
if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) )
|
||||
if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) )
|
||||
{
|
||||
if(m_targetMask & TARGET_FLAG_UNIT)
|
||||
{
|
||||
|
|
@ -339,6 +339,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
|
|||
gameObjTarget = NULL;
|
||||
focusObject = NULL;
|
||||
m_cast_count = 0;
|
||||
m_glyphIndex = 0;
|
||||
m_triggeredByAuraSpell = NULL;
|
||||
|
||||
//Auto Shot & Shoot
|
||||
|
|
@ -347,6 +348,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
|
|||
else
|
||||
m_autoRepeat = false;
|
||||
|
||||
m_runesState = 0;
|
||||
m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before.
|
||||
m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before.
|
||||
m_timer = 0; // will set to castime in prepare
|
||||
|
|
@ -535,7 +537,6 @@ void Spell::FillTargetMap()
|
|||
case SPELL_EFFECT_LEARN_SPELL:
|
||||
case SPELL_EFFECT_SKILL_STEP:
|
||||
case SPELL_EFFECT_PROFICIENCY:
|
||||
case SPELL_EFFECT_SUMMON_POSSESSED:
|
||||
case SPELL_EFFECT_SUMMON_OBJECT_WILD:
|
||||
case SPELL_EFFECT_SELF_RESURRECT:
|
||||
case SPELL_EFFECT_REPUTATION:
|
||||
|
|
@ -578,6 +579,7 @@ void Spell::FillTargetMap()
|
|||
case SPELL_EFFECT_SUMMON_GUARDIAN:
|
||||
case SPELL_EFFECT_TRANS_DOOR:
|
||||
case SPELL_EFFECT_ADD_FARSIGHT:
|
||||
case SPELL_EFFECT_APPLY_GLYPH:
|
||||
case SPELL_EFFECT_STUCK:
|
||||
case SPELL_EFFECT_DESTROY_ALL_TOTEMS:
|
||||
case SPELL_EFFECT_SUMMON_DEMON:
|
||||
|
|
@ -593,6 +595,7 @@ void Spell::FillTargetMap()
|
|||
case SPELL_EFFECT_DISENCHANT:
|
||||
case SPELL_EFFECT_FEED_PET:
|
||||
case SPELL_EFFECT_PROSPECTING:
|
||||
case SPELL_EFFECT_MILLING:
|
||||
if(m_targets.getItemTarget())
|
||||
AddItemTarget(m_targets.getItemTarget(), i);
|
||||
break;
|
||||
|
|
@ -1142,6 +1145,17 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
|||
return;
|
||||
}
|
||||
|
||||
if (unit->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id);
|
||||
((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
|
||||
}
|
||||
|
||||
if(m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit);
|
||||
}
|
||||
|
||||
if( m_caster != unit )
|
||||
{
|
||||
if( !m_caster->IsFriendlyTo(unit) )
|
||||
|
|
@ -1354,7 +1368,15 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
|
|||
if(Player* modOwner = m_originalCaster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this);
|
||||
|
||||
// Get spell max affected targets
|
||||
uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets;
|
||||
Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
|
||||
for(Unit::AuraList::const_iterator m = mod.begin(); m != mod.end(); ++m)
|
||||
{
|
||||
if (!(*m)->isAffectedOnSpell(m_spellInfo))
|
||||
continue;
|
||||
unMaxTargets+=(*m)->GetModifier()->m_amount;
|
||||
}
|
||||
switch(cur)
|
||||
{
|
||||
case TARGET_TOTEM_EARTH:
|
||||
|
|
@ -1734,7 +1756,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
|
|||
cell.data.Part.reserved = ALL_DISTRICT;
|
||||
cell.SetNoCreate();
|
||||
|
||||
bool inFront = m_spellInfo->SpellVisual != 3879;
|
||||
bool inFront = m_spellInfo->SpellVisual[0] != 3879;
|
||||
MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE);
|
||||
|
||||
TypeContainerVisitor<MaNGOS::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
|
||||
|
|
@ -2267,6 +2289,14 @@ void Spell::cast(bool skipCheck)
|
|||
// set to real guid to be sent later to the client
|
||||
m_targets.updateTradeSlotItem();
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (m_CastItem)
|
||||
((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry());
|
||||
|
||||
((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id);
|
||||
}
|
||||
|
||||
// CAST SPELL
|
||||
SendSpellCooldown();
|
||||
|
||||
|
|
@ -2675,7 +2705,7 @@ void Spell::finish(bool ok)
|
|||
{
|
||||
SpellEntry const *auraSpellInfo = (*i)->GetSpellProto();
|
||||
uint32 auraSpellIdx = (*i)->GetEffIndex();
|
||||
if (IsAffectedBy(auraSpellInfo, auraSpellIdx))
|
||||
if (IsAffectedByAura((*i)))
|
||||
{
|
||||
for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
|
||||
if( ihit->effectMask & (1<<auraSpellIdx) )
|
||||
|
|
@ -2747,9 +2777,9 @@ void Spell::SendCastResult(uint8 result)
|
|||
if(result != 0)
|
||||
{
|
||||
WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
|
||||
data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
|
||||
data << uint32(m_spellInfo->Id);
|
||||
data << uint8(result); // problem
|
||||
data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
|
||||
switch (result)
|
||||
{
|
||||
case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
|
||||
|
|
@ -2790,18 +2820,11 @@ void Spell::SendCastResult(uint8 result)
|
|||
case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
|
||||
data << uint32(m_spellInfo->EquippedItemClass);
|
||||
data << uint32(m_spellInfo->EquippedItemSubClassMask);
|
||||
data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
|
||||
//data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
|
||||
break;
|
||||
}
|
||||
((Player*)m_caster)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO, (8+4));
|
||||
data.append(m_caster->GetPackGUID());
|
||||
data << uint32(m_spellInfo->Id);
|
||||
((Player*)m_caster)->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
void Spell::SendSpellStart()
|
||||
|
|
@ -2815,6 +2838,9 @@ void Spell::SendSpellStart()
|
|||
if(IsRangedSpell())
|
||||
castFlags |= CAST_FLAG_AMMO;
|
||||
|
||||
if(m_spellInfo->runeCostID)
|
||||
castFlags |= CAST_FLAG_UNKNOWN10;
|
||||
|
||||
Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster;
|
||||
|
||||
WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
|
||||
|
|
@ -2824,14 +2850,32 @@ void Spell::SendSpellStart()
|
|||
data.append(m_caster->GetPackGUID());
|
||||
|
||||
data.append(m_caster->GetPackGUID());
|
||||
data << uint32(m_spellInfo->Id);
|
||||
data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
|
||||
data << uint16(castFlags);
|
||||
data << uint32(m_timer);
|
||||
data << uint8(m_cast_count); // pending spell cast?
|
||||
data << uint32(m_spellInfo->Id); // spellId
|
||||
data << uint32(castFlags); // cast flags
|
||||
data << uint32(m_timer); // delay?
|
||||
|
||||
m_targets.write(&data);
|
||||
|
||||
if( castFlags & CAST_FLAG_AMMO )
|
||||
if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power?
|
||||
data << uint32(0);
|
||||
|
||||
if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list
|
||||
{
|
||||
uint8 v1 = 0;//m_runesState;
|
||||
uint8 v2 = 0;//((Player*)m_caster)->GetRunesState();
|
||||
data << uint8(v1); // runes state before
|
||||
data << uint8(v2); // runes state after
|
||||
for(uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
uint8 m = (1 << i);
|
||||
if(m & v1) // usable before...
|
||||
if(!(m & v2)) // ...but on cooldown now...
|
||||
data << uint8(0); // some unknown byte (time?)
|
||||
}
|
||||
}
|
||||
|
||||
if ( castFlags & CAST_FLAG_AMMO )
|
||||
WriteAmmoToPacket(&data);
|
||||
|
||||
m_caster->SendMessageToSet(&data, true);
|
||||
|
|
@ -2851,6 +2895,13 @@ void Spell::SendSpellGo()
|
|||
if(IsRangedSpell())
|
||||
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
|
||||
|
||||
if((m_caster->GetTypeId() == TYPEID_PLAYER) && (m_caster->getClass() == CLASS_DEATH_KNIGHT) && m_spellInfo->runeCostID)
|
||||
{
|
||||
castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START
|
||||
castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible
|
||||
castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns list
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_SPELL_GO, 50); // guess size
|
||||
if(m_CastItem)
|
||||
data.append(m_CastItem->GetPackGUID());
|
||||
|
|
@ -2858,17 +2909,53 @@ void Spell::SendSpellGo()
|
|||
data.append(m_caster->GetPackGUID());
|
||||
|
||||
data.append(m_caster->GetPackGUID());
|
||||
data << uint32(m_spellInfo->Id);
|
||||
data << uint16(castFlags);
|
||||
data << uint8(m_cast_count); // pending spell cast?
|
||||
data << uint32(m_spellInfo->Id); // spellId
|
||||
data << uint32(castFlags); // cast flags
|
||||
data << uint32(getMSTime()); // timestamp
|
||||
|
||||
WriteSpellGoTargets(&data);
|
||||
|
||||
m_targets.write(&data);
|
||||
|
||||
if( castFlags & CAST_FLAG_AMMO )
|
||||
if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power?
|
||||
data << uint32(0);
|
||||
|
||||
if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list
|
||||
{
|
||||
uint8 v1 = m_runesState;
|
||||
uint8 v2 = ((Player*)m_caster)->GetRunesState();
|
||||
data << uint8(v1); // runes state before
|
||||
data << uint8(v2); // runes state after
|
||||
for(uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
uint8 m = (1 << i);
|
||||
if(m & v1) // usable before...
|
||||
if(!(m & v2)) // ...but on cooldown now...
|
||||
data << uint8(0); // some unknown byte (time?)
|
||||
}
|
||||
}
|
||||
|
||||
if ( castFlags & CAST_FLAG_UNKNOWN4 ) // unknown wotlk
|
||||
{
|
||||
data << float(0);
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
if ( castFlags & CAST_FLAG_AMMO )
|
||||
WriteAmmoToPacket(&data);
|
||||
|
||||
if ( castFlags & CAST_FLAG_UNKNOWN5 ) // unknown wotlk
|
||||
{
|
||||
data << uint32(0);
|
||||
data << uint32(0);
|
||||
}
|
||||
|
||||
if ( m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION )
|
||||
{
|
||||
data << uint8(0);
|
||||
}
|
||||
|
||||
m_caster->SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
|
|
@ -2996,30 +3083,19 @@ void Spell::SendLogExecute()
|
|||
data << uint8(0);
|
||||
break;
|
||||
case SPELL_EFFECT_CREATE_ITEM:
|
||||
case SPELL_EFFECT_157:
|
||||
data << uint32(m_spellInfo->EffectItemType[0]);
|
||||
break;
|
||||
case SPELL_EFFECT_SUMMON:
|
||||
case SPELL_EFFECT_SUMMON_WILD:
|
||||
case SPELL_EFFECT_SUMMON_GUARDIAN:
|
||||
case SPELL_EFFECT_TRANS_DOOR:
|
||||
case SPELL_EFFECT_SUMMON_PET:
|
||||
case SPELL_EFFECT_SUMMON_POSSESSED:
|
||||
case SPELL_EFFECT_SUMMON_TOTEM:
|
||||
case SPELL_EFFECT_SUMMON_OBJECT_WILD:
|
||||
case SPELL_EFFECT_CREATE_HOUSE:
|
||||
case SPELL_EFFECT_DUEL:
|
||||
case SPELL_EFFECT_SUMMON_TOTEM_SLOT1:
|
||||
case SPELL_EFFECT_SUMMON_TOTEM_SLOT2:
|
||||
case SPELL_EFFECT_SUMMON_TOTEM_SLOT3:
|
||||
case SPELL_EFFECT_SUMMON_TOTEM_SLOT4:
|
||||
case SPELL_EFFECT_SUMMON_PHANTASM:
|
||||
case SPELL_EFFECT_SUMMON_CRITTER:
|
||||
case SPELL_EFFECT_SUMMON_OBJECT_SLOT1:
|
||||
case SPELL_EFFECT_SUMMON_OBJECT_SLOT2:
|
||||
case SPELL_EFFECT_SUMMON_OBJECT_SLOT3:
|
||||
case SPELL_EFFECT_SUMMON_OBJECT_SLOT4:
|
||||
case SPELL_EFFECT_SUMMON_DEMON:
|
||||
case SPELL_EFFECT_150:
|
||||
if(Unit *unit = m_targets.getUnitTarget())
|
||||
data.append(unit->GetPackGUID());
|
||||
else if(m_targets.getItemTargetGUID())
|
||||
|
|
@ -3038,6 +3114,13 @@ void Spell::SendLogExecute()
|
|||
else
|
||||
data << uint8(0);
|
||||
break;
|
||||
case SPELL_EFFECT_RESURRECT:
|
||||
case SPELL_EFFECT_RESURRECT_NEW:
|
||||
if(Unit *unit = m_targets.getUnitTarget())
|
||||
data.append(unit->GetPackGUID());
|
||||
else
|
||||
data << uint8(0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
@ -3051,13 +3134,16 @@ void Spell::SendInterrupted(uint8 result)
|
|||
{
|
||||
WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1));
|
||||
data.append(m_caster->GetPackGUID());
|
||||
data << m_spellInfo->Id;
|
||||
data << result;
|
||||
data << uint8(m_cast_count);
|
||||
data << uint32(m_spellInfo->Id);
|
||||
data << uint8(result);
|
||||
m_caster->SendMessageToSet(&data, true);
|
||||
|
||||
data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4));
|
||||
data.append(m_caster->GetPackGUID());
|
||||
data << m_spellInfo->Id;
|
||||
data << uint8(m_cast_count);
|
||||
data << uint32(m_spellInfo->Id);
|
||||
data << uint8(result);
|
||||
m_caster->SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
|
|
@ -3125,10 +3211,19 @@ void Spell::SendChannelStart(uint32 duration)
|
|||
|
||||
void Spell::SendResurrectRequest(Player* target)
|
||||
{
|
||||
WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4));
|
||||
data << m_caster->GetGUID();
|
||||
data << uint32(1) << uint16(0) << uint32(1);
|
||||
// Both players and NPCs can resurrect using spells - have a look at creature 28487 for example
|
||||
// However, the packet structure differs slightly
|
||||
|
||||
const char* sentName = m_caster->GetTypeId()==TYPEID_PLAYER ?"":m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex());
|
||||
|
||||
WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+strlen(sentName)+1+1+1));
|
||||
data << uint64(m_caster->GetGUID());
|
||||
data << uint32(strlen(sentName)+1);
|
||||
|
||||
data << sentName;
|
||||
data << uint8(0);
|
||||
|
||||
data << uint8(m_caster->GetTypeId()==TYPEID_PLAYER ?0:1);
|
||||
target->GetSession()->SendPacket(&data);
|
||||
}
|
||||
|
||||
|
|
@ -3225,6 +3320,12 @@ void Spell::TakePower()
|
|||
|
||||
Powers powerType = Powers(m_spellInfo->powerType);
|
||||
|
||||
if(powerType == POWER_RUNE)
|
||||
{
|
||||
TakeRunePower();
|
||||
return;
|
||||
}
|
||||
|
||||
m_caster->ModifyPower(powerType, -(int32)m_powerCost);
|
||||
|
||||
// Set the five second timer
|
||||
|
|
@ -3232,6 +3333,116 @@ void Spell::TakePower()
|
|||
m_caster->SetLastManaUse(getMSTime());
|
||||
}
|
||||
|
||||
uint8 Spell::CheckRuneCost(uint32 runeCostID)
|
||||
{
|
||||
if(m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return 0;
|
||||
|
||||
Player *plr = (Player*)m_caster;
|
||||
|
||||
if(plr->getClass() != CLASS_DEATH_KNIGHT)
|
||||
return 0;
|
||||
|
||||
SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(runeCostID);
|
||||
|
||||
if(!src)
|
||||
return 0;
|
||||
|
||||
if(src->NoRuneCost())
|
||||
return 0;
|
||||
|
||||
int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death
|
||||
|
||||
for(uint32 i = 0; i < RUNE_DEATH; ++i)
|
||||
{
|
||||
runeCost[i] = src->RuneCost[i];
|
||||
}
|
||||
|
||||
runeCost[RUNE_DEATH] = 0; // calculated later
|
||||
|
||||
for(uint32 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
uint8 rune = plr->GetCurrentRune(i);
|
||||
if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
|
||||
{
|
||||
runeCost[rune]--;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32 i = 0; i < RUNE_DEATH; ++i)
|
||||
{
|
||||
if(runeCost[i] > 0)
|
||||
{
|
||||
runeCost[RUNE_DEATH] += runeCost[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(runeCost[RUNE_DEATH] > 0)
|
||||
return SPELL_FAILED_NO_POWER; // not sure if result code is correct
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Spell::TakeRunePower()
|
||||
{
|
||||
if(m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Player *plr = (Player*)m_caster;
|
||||
|
||||
if(plr->getClass() != CLASS_DEATH_KNIGHT)
|
||||
return;
|
||||
|
||||
SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(m_spellInfo->runeCostID);
|
||||
|
||||
if(!src || (src->NoRuneCost() && src->NoRunicPowerGain()))
|
||||
return;
|
||||
|
||||
m_runesState = plr->GetRunesState(); // store previous state
|
||||
|
||||
int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death
|
||||
|
||||
for(uint32 i = 0; i < RUNE_DEATH; ++i)
|
||||
{
|
||||
runeCost[i] = src->RuneCost[i];
|
||||
}
|
||||
|
||||
runeCost[RUNE_DEATH] = 0; // calculated later
|
||||
|
||||
for(uint32 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
uint8 rune = plr->GetCurrentRune(i);
|
||||
if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
|
||||
{
|
||||
plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
|
||||
runeCost[rune]--;
|
||||
}
|
||||
}
|
||||
|
||||
runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST];
|
||||
|
||||
if(runeCost[RUNE_DEATH] > 0)
|
||||
{
|
||||
for(uint32 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
uint8 rune = plr->GetCurrentRune(i);
|
||||
if((plr->GetRuneCooldown(i) == 0) && (rune == RUNE_DEATH))
|
||||
{
|
||||
plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec
|
||||
runeCost[rune]--;
|
||||
plr->ConvertRune(i, plr->GetBaseRune(i));
|
||||
if(runeCost[RUNE_DEATH] == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// you can gain some runic power when use runes
|
||||
float rp = src->runePowerGain;;
|
||||
rp *= sWorld.getRate(RATE_POWER_RUNICPOWER_INCOME);
|
||||
plr->ModifyPower(POWER_RUNIC_POWER, (int32)rp);
|
||||
}
|
||||
|
||||
void Spell::TakeReagents()
|
||||
{
|
||||
if(m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed.
|
||||
|
|
@ -3240,11 +3451,9 @@ void Spell::TakeReagents()
|
|||
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
if (m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP &&
|
||||
m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION))
|
||||
return;
|
||||
|
||||
Player* p_caster = (Player*)m_caster;
|
||||
if (p_caster->CanNoReagentCast(m_spellInfo))
|
||||
return;
|
||||
|
||||
for(uint32 x=0;x<8;x++)
|
||||
{
|
||||
|
|
@ -3367,12 +3576,25 @@ uint8 Spell::CanCast(bool strict)
|
|||
// for now, ignore triggered spells
|
||||
if( strict && !m_IsTriggeredSpell)
|
||||
{
|
||||
// Cannot be used in this stance/form
|
||||
if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form))
|
||||
return shapeError;
|
||||
bool checkForm = true;
|
||||
// Ignore form req aura
|
||||
Unit::AuraList const& ignore = m_caster->GetAurasByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT);
|
||||
for(Unit::AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
|
||||
{
|
||||
if (!(*i)->isAffectedOnSpell(m_spellInfo))
|
||||
continue;
|
||||
checkForm = false;
|
||||
break;
|
||||
}
|
||||
if (checkForm)
|
||||
{
|
||||
// Cannot be used in this stance/form
|
||||
if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form))
|
||||
return shapeError;
|
||||
|
||||
if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura()))
|
||||
return SPELL_FAILED_ONLY_STEALTHED;
|
||||
if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura()))
|
||||
return SPELL_FAILED_ONLY_STEALTHED;
|
||||
}
|
||||
}
|
||||
|
||||
// caster state requirements
|
||||
|
|
@ -3708,7 +3930,7 @@ uint8 Spell::CanCast(bool strict)
|
|||
case SPELL_EFFECT_SCHOOL_DAMAGE:
|
||||
{
|
||||
// Hammer of Wrath
|
||||
if(m_spellInfo->SpellVisual == 7250)
|
||||
if(m_spellInfo->SpellVisual[0] == 7250)
|
||||
{
|
||||
if (!m_targets.getUnitTarget())
|
||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||
|
|
@ -3753,15 +3975,9 @@ uint8 Spell::CanCast(bool strict)
|
|||
if(!learn_spellproto)
|
||||
return SPELL_FAILED_NOT_KNOWN;
|
||||
|
||||
if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
|
||||
return SPELL_FAILED_TOO_MANY_SKILLS;
|
||||
|
||||
if(m_spellInfo->spellLevel > pet->getLevel())
|
||||
return SPELL_FAILED_LOWLEVEL;
|
||||
|
||||
if(!pet->HasTPForSpell(learn_spellproto->Id))
|
||||
return SPELL_FAILED_TRAINING_POINTS;
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_LEARN_PET_SPELL:
|
||||
|
|
@ -3776,15 +3992,9 @@ uint8 Spell::CanCast(bool strict)
|
|||
if(!learn_spellproto)
|
||||
return SPELL_FAILED_NOT_KNOWN;
|
||||
|
||||
if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
|
||||
return SPELL_FAILED_TOO_MANY_SKILLS;
|
||||
|
||||
if(m_spellInfo->spellLevel > pet->getLevel())
|
||||
return SPELL_FAILED_LOWLEVEL;
|
||||
|
||||
if(!pet->HasTPForSpell(learn_spellproto->Id))
|
||||
return SPELL_FAILED_TRAINING_POINTS;
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_FEED_PET:
|
||||
|
|
@ -3887,27 +4097,27 @@ uint8 Spell::CanCast(bool strict)
|
|||
{
|
||||
// check for lock - key pair (checked by client also, just prevent cheating
|
||||
bool ok_key = false;
|
||||
for(int it = 0; it < 5; ++it)
|
||||
for(int it = 0; it < 8; ++it)
|
||||
{
|
||||
switch(lockInfo->keytype[it])
|
||||
switch(lockInfo->Type[it])
|
||||
{
|
||||
case LOCK_KEY_NONE:
|
||||
break;
|
||||
case LOCK_KEY_ITEM:
|
||||
{
|
||||
if(lockInfo->key[it])
|
||||
if(lockInfo->Index[it])
|
||||
{
|
||||
if(m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it])
|
||||
if(m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it])
|
||||
ok_key =true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case LOCK_KEY_SKILL:
|
||||
{
|
||||
if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->key[it])
|
||||
if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->Index[it])
|
||||
break;
|
||||
|
||||
switch(lockInfo->key[it])
|
||||
switch(lockInfo->Index[it])
|
||||
{
|
||||
case LOCKTYPE_HERBALISM:
|
||||
if(((Player*)m_caster)->HasSkill(SKILL_HERBALISM))
|
||||
|
|
@ -3964,9 +4174,9 @@ uint8 Spell::CanCast(bool strict)
|
|||
{
|
||||
// check for lock - key pair
|
||||
bool ok = false;
|
||||
for(int it = 0; it < 5; ++it)
|
||||
for(int it = 0; it < 8; ++it)
|
||||
{
|
||||
if(lockInfo->keytype[it]==LOCK_KEY_ITEM && lockInfo->key[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it])
|
||||
if(lockInfo->Type[it]==LOCK_KEY_ITEM && lockInfo->Index[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it])
|
||||
{
|
||||
// if so, we're good to go
|
||||
ok = true;
|
||||
|
|
@ -3977,9 +4187,9 @@ uint8 Spell::CanCast(bool strict)
|
|||
break;
|
||||
|
||||
if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK)
|
||||
ReqValue = lockInfo->requiredlockskill;
|
||||
ReqValue = lockInfo->Skill[1];
|
||||
else
|
||||
ReqValue = lockInfo->requiredminingskill;
|
||||
ReqValue = lockInfo->Skill[0];
|
||||
}
|
||||
|
||||
// skill doesn't meet the required value
|
||||
|
|
@ -4027,7 +4237,6 @@ uint8 Spell::CanCast(bool strict)
|
|||
}
|
||||
// Don't make this check for SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN.
|
||||
// These won't show up in m_caster->GetPetGUID()
|
||||
case SPELL_EFFECT_SUMMON_POSSESSED:
|
||||
case SPELL_EFFECT_SUMMON_PHANTASM:
|
||||
case SPELL_EFFECT_SUMMON_DEMON:
|
||||
{
|
||||
|
|
@ -4163,7 +4372,7 @@ uint8 Spell::CanCast(bool strict)
|
|||
if( form == FORM_CAT || form == FORM_TREE || form == FORM_TRAVEL ||
|
||||
form == FORM_AQUA || form == FORM_BEAR || form == FORM_DIREBEAR ||
|
||||
form == FORM_CREATUREBEAR || form == FORM_GHOSTWOLF || form == FORM_FLIGHT ||
|
||||
form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN )
|
||||
form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN || form == FORM_METAMORPHOSIS )
|
||||
return SPELL_FAILED_NOT_SHAPESHIFT;
|
||||
|
||||
break;
|
||||
|
|
@ -4185,8 +4394,8 @@ uint8 Spell::CanCast(bool strict)
|
|||
// not allow cast fly spells at old maps by players (all spells is self target)
|
||||
if(m_caster->GetTypeId()==TYPEID_PLAYER)
|
||||
{
|
||||
if( !((Player*)m_caster)->isGameMaster() &&
|
||||
GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530)
|
||||
uint32 v_map = GetVirtualMapForMapAndZone(m_caster->GetMapId(), m_caster->GetZoneId());
|
||||
if( !((Player*)m_caster)->isGameMaster() && v_map != 530 && !(v_map == 571 && ((Player*)m_caster)->HasSpell(54197)))
|
||||
return SPELL_FAILED_NOT_HERE;
|
||||
}
|
||||
|
||||
|
|
@ -4504,9 +4713,12 @@ int32 Spell::CalculatePowerCost()
|
|||
case POWER_FOCUS:
|
||||
case POWER_ENERGY:
|
||||
case POWER_HAPPINESS:
|
||||
// case POWER_RUNES:
|
||||
powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetMaxPower(Powers(m_spellInfo->powerType)) / 100;
|
||||
break;
|
||||
case POWER_RUNE:
|
||||
case POWER_RUNIC_POWER:
|
||||
sLog.outDebug("Spell::CalculateManaCost: Not implemented yet!");
|
||||
break;
|
||||
default:
|
||||
sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id);
|
||||
return 0;
|
||||
|
|
@ -4551,6 +4763,11 @@ uint8 Spell::CheckPower()
|
|||
sLog.outError("Spell::CheckMana: Unknown power type '%d'", m_spellInfo->powerType);
|
||||
return SPELL_FAILED_UNKNOWN;
|
||||
}
|
||||
|
||||
uint8 failReason = CheckRuneCost(m_spellInfo->runeCostID);
|
||||
if(failReason)
|
||||
return failReason;
|
||||
|
||||
// Check power amount
|
||||
Powers powerType = Powers(m_spellInfo->powerType);
|
||||
if(m_caster->GetPower(powerType) < m_powerCost)
|
||||
|
|
@ -4590,6 +4807,8 @@ uint8 Spell::CheckItems()
|
|||
uint32 ItemClass = proto->Class;
|
||||
if (ItemClass == ITEM_CLASS_CONSUMABLE && m_targets.getUnitTarget())
|
||||
{
|
||||
// such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example
|
||||
uint8 failReason = 0;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster
|
||||
|
|
@ -4597,21 +4816,43 @@ uint8 Spell::CheckItems()
|
|||
continue;
|
||||
|
||||
if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL)
|
||||
{
|
||||
if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth())
|
||||
return (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH;
|
||||
{
|
||||
failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
failReason = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Mana Potion, Rage Potion, Thistle Tea(Rogue), ...
|
||||
if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE)
|
||||
{
|
||||
if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
|
||||
return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
|
||||
{
|
||||
failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
|
||||
continue;
|
||||
}
|
||||
|
||||
Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
|
||||
|
||||
if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power))
|
||||
return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
|
||||
{
|
||||
failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
failReason = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (failReason)
|
||||
return failReason;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4654,8 +4895,7 @@ uint8 Spell::CheckItems()
|
|||
focusObject = ok; // game object found in range
|
||||
}
|
||||
|
||||
if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP &&
|
||||
m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)))
|
||||
if (!p_caster->CanNoReagentCast(m_spellInfo))
|
||||
{
|
||||
for(uint32 i=0;i<8;i++)
|
||||
{
|
||||
|
|
@ -4823,13 +5063,36 @@ uint8 Spell::CheckItems()
|
|||
return SPELL_FAILED_LOW_CASTLEVEL;
|
||||
//make sure the player has the required ores in inventory
|
||||
if(m_targets.getItemTarget()->GetCount() < 5)
|
||||
return SPELL_FAILED_PROSPECT_NEED_MORE;
|
||||
return SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
if(!LootTemplates_Prospecting.HaveLootFor(m_targets.getItemTargetEntry()))
|
||||
return SPELL_FAILED_CANT_BE_PROSPECTED;
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_MILLING:
|
||||
{
|
||||
if(!m_targets.getItemTarget())
|
||||
return SPELL_FAILED_CANT_BE_MILLED;
|
||||
//ensure item is a millable herb
|
||||
if(!(m_targets.getItemTarget()->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS) || m_targets.getItemTarget()->GetProto()->Class != ITEM_CLASS_TRADE_GOODS)
|
||||
return SPELL_FAILED_CANT_BE_MILLED;
|
||||
//prevent milling in trade slot
|
||||
if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() )
|
||||
return SPELL_FAILED_CANT_BE_MILLED;
|
||||
//Check for enough skill in inscription
|
||||
uint32 item_millingskilllevel = m_targets.getItemTarget()->GetProto()->RequiredSkillRank;
|
||||
if(item_millingskilllevel >p_caster->GetSkillValue(SKILL_INSCRIPTION))
|
||||
return SPELL_FAILED_LOW_CASTLEVEL;
|
||||
//make sure the player has the required herbs in inventory
|
||||
if(m_targets.getItemTarget()->GetCount() < 5)
|
||||
return SPELL_FAILED_NEED_MORE_ITEMS;
|
||||
|
||||
if(!LootTemplates_Milling.HaveLootFor(m_targets.getItemTargetEntry()))
|
||||
return SPELL_FAILED_CANT_BE_MILLED;
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_WEAPON_DAMAGE:
|
||||
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
|
||||
{
|
||||
|
|
@ -5002,9 +5265,9 @@ void Spell::UpdatePointers()
|
|||
m_targets.Update(m_caster);
|
||||
}
|
||||
|
||||
bool Spell::IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId)
|
||||
bool Spell::IsAffectedByAura(Aura *aura)
|
||||
{
|
||||
return spellmgr.IsAffectedBySpell(m_spellInfo,spellInfo->Id,effectId,spellInfo->EffectItemType[effectId]);
|
||||
return spellmgr.IsAffectedByMod(m_spellInfo, aura->getAuraSpellMod());
|
||||
}
|
||||
|
||||
bool Spell::CheckTargetCreatureType(Unit* target) const
|
||||
|
|
|
|||
|
|
@ -45,32 +45,51 @@ enum SpellCastTargetFlags
|
|||
TARGET_FLAG_RESURRECTABLE = 0x8000*/
|
||||
|
||||
TARGET_FLAG_SELF = 0x00000000,
|
||||
TARGET_FLAG_UNUSED1 = 0x00000001, // not used in any spells as of 3.0.3 (can be set dynamically)
|
||||
TARGET_FLAG_UNIT = 0x00000002, // pguid
|
||||
TARGET_FLAG_UNUSED2 = 0x00000004, // not used in any spells as of 3.0.3 (can be set dynamically)
|
||||
TARGET_FLAG_UNUSED3 = 0x00000008, // not used in any spells as of 3.0.3 (can be set dynamically)
|
||||
TARGET_FLAG_ITEM = 0x00000010, // pguid
|
||||
TARGET_FLAG_SOURCE_LOCATION = 0x00000020, // 3 float
|
||||
TARGET_FLAG_DEST_LOCATION = 0x00000040, // 3 float
|
||||
TARGET_FLAG_OBJECT_UNK = 0x00000080, // ?
|
||||
TARGET_FLAG_OBJECT_UNK = 0x00000080, // used in 7 spells only
|
||||
TARGET_FLAG_UNIT_UNK = 0x00000100, // looks like self target (480 spells)
|
||||
TARGET_FLAG_PVP_CORPSE = 0x00000200, // pguid
|
||||
TARGET_FLAG_OBJECT = 0x00000800, // pguid
|
||||
TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid
|
||||
TARGET_FLAG_STRING = 0x00002000, // string
|
||||
TARGET_FLAG_UNK1 = 0x00004000, // ?
|
||||
TARGET_FLAG_CORPSE = 0x00008000, // pguid
|
||||
TARGET_FLAG_UNK2 = 0x00010000 // pguid
|
||||
TARGET_FLAG_UNIT_CORPSE = 0x00000400, // 10 spells (gathering professions)
|
||||
TARGET_FLAG_OBJECT = 0x00000800, // pguid, 2 spells
|
||||
TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid, 0 spells
|
||||
TARGET_FLAG_STRING = 0x00002000, // string, 0 spells
|
||||
TARGET_FLAG_UNK1 = 0x00004000, // 199 spells, opening object/lock
|
||||
TARGET_FLAG_CORPSE = 0x00008000, // pguid, resurrection spells
|
||||
TARGET_FLAG_UNK2 = 0x00010000, // pguid, not used in any spells as of 3.0.3 (can be set dynamically)
|
||||
TARGET_FLAG_GLYPH = 0x00020000 // used in glyph spells
|
||||
};
|
||||
|
||||
enum SpellCastFlags
|
||||
{
|
||||
CAST_FLAG_NONE = 0x00000000,
|
||||
CAST_FLAG_UNKNOWN0 = 0x00000001, // may be pending spell cast
|
||||
CAST_FLAG_UNKNOWN1 = 0x00000002,
|
||||
CAST_FLAG_UNKNOWN11 = 0x00000004,
|
||||
CAST_FLAG_UNKNOWN12 = 0x00000008,
|
||||
CAST_FLAG_UNKNOWN2 = 0x00000010,
|
||||
CAST_FLAG_AMMO = 0x00000020,
|
||||
CAST_FLAG_AMMO = 0x00000020, // Projectiles visual
|
||||
CAST_FLAG_UNKNOWN8 = 0x00000040,
|
||||
CAST_FLAG_UNKNOWN9 = 0x00000080,
|
||||
CAST_FLAG_UNKNOWN3 = 0x00000100,
|
||||
CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk
|
||||
CAST_FLAG_UNKNOWN13 = 0x00000200,
|
||||
CAST_FLAG_UNKNOWN14 = 0x00000400,
|
||||
CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk, trigger rune cooldown
|
||||
CAST_FLAG_UNKNOWN15 = 0x00001000,
|
||||
CAST_FLAG_UNKNOWN16 = 0x00002000,
|
||||
CAST_FLAG_UNKNOWN17 = 0x00004000,
|
||||
CAST_FLAG_UNKNOWN18 = 0x00008000,
|
||||
CAST_FLAG_UNKNOWN19 = 0x00010000,
|
||||
CAST_FLAG_UNKNOWN4 = 0x00020000, // wotlk
|
||||
CAST_FLAG_UNKNOWN10 = 0x00040000,
|
||||
CAST_FLAG_UNKNOWN5 = 0x00080000, // wotlk
|
||||
CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk
|
||||
CAST_FLAG_UNKNOWN20 = 0x00100000,
|
||||
CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list
|
||||
};
|
||||
|
||||
enum SpellNotifyPushType
|
||||
|
|
@ -252,6 +271,7 @@ class Spell
|
|||
void EffectStuck(uint32 i);
|
||||
void EffectSummonPlayer(uint32 i);
|
||||
void EffectActivateObject(uint32 i);
|
||||
void EffectApplyGlyph(uint32 i);
|
||||
void EffectSummonTotem(uint32 i);
|
||||
void EffectEnchantHeldItem(uint32 i);
|
||||
void EffectSummonObject(uint32 i);
|
||||
|
|
@ -269,6 +289,7 @@ class Spell
|
|||
void EffectSkinning(uint32 i);
|
||||
void EffectCharge(uint32 i);
|
||||
void EffectProspecting(uint32 i);
|
||||
void EffectMilling(uint32 i);
|
||||
void EffectSendTaxi(uint32 i);
|
||||
void EffectSummonCritter(uint32 i);
|
||||
void EffectKnockBack(uint32 i);
|
||||
|
|
@ -294,6 +315,8 @@ class Spell
|
|||
void EffectTriggerRitualOfSummoning(uint32 i);
|
||||
void EffectKillCredit(uint32 i);
|
||||
void EffectQuestFail(uint32 i);
|
||||
void EffectActivateRune(uint32 i);
|
||||
void EffectTitanGrip(uint32 i);
|
||||
|
||||
Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL );
|
||||
~Spell();
|
||||
|
|
@ -304,6 +327,8 @@ class Spell
|
|||
void cast(bool skipCheck = false);
|
||||
void finish(bool ok = true);
|
||||
void TakePower();
|
||||
uint8 CheckRuneCost(uint32 runeCostID);
|
||||
void TakeRunePower();
|
||||
void TakeReagents();
|
||||
void TakeCastItem();
|
||||
void TriggerSpell();
|
||||
|
|
@ -362,6 +387,7 @@ class Spell
|
|||
int32 m_currentBasePoints[3]; // cache SpellEntry::EffectBasePoints and use for set custom base points
|
||||
Item* m_CastItem;
|
||||
uint8 m_cast_count;
|
||||
uint32 m_glyphIndex;
|
||||
SpellCastTargets m_targets;
|
||||
|
||||
int32 GetCastTime() const { return m_casttime; }
|
||||
|
|
@ -397,7 +423,7 @@ class Spell
|
|||
|
||||
void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc)
|
||||
|
||||
bool IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId);
|
||||
bool IsAffectedByAura(Aura *aura);
|
||||
|
||||
bool CheckTargetCreatureType(Unit* target) const;
|
||||
|
||||
|
|
@ -424,6 +450,7 @@ class Spell
|
|||
int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare
|
||||
bool m_canReflect; // can reflect this spell?
|
||||
bool m_autoRepeat;
|
||||
uint8 m_runesState;
|
||||
|
||||
uint8 m_delayAtDamageCount;
|
||||
int32 GetNextDelayAtDamageMsTime() { return m_delayAtDamageCount < 5 ? 1000 - (m_delayAtDamageCount++)* 200 : 200; }
|
||||
|
|
|
|||
|
|
@ -18,14 +18,19 @@
|
|||
#ifndef MANGOS_SPELLAURADEFINES_H
|
||||
#define MANGOS_SPELLAURADEFINES_H
|
||||
|
||||
#define MAX_AURAS 56
|
||||
#define MAX_POSITIVE_AURAS 40
|
||||
#define MAX_AURAS 64 // client support up to 255, but it will cause problems with group auras updating
|
||||
|
||||
enum AURA_FLAGS
|
||||
{
|
||||
AFLAG_NEGATIVE = 0x09,
|
||||
AFLAG_POSITIVE = 0x1F,
|
||||
AFLAG_MASK = 0xFF
|
||||
AFLAG_NONE = 0x00,
|
||||
AFLAG_EFF_INDEX_0 = 0x01,
|
||||
AFLAG_EFF_INDEX_1 = 0x02,
|
||||
AFLAG_EFF_INDEX_2 = 0x04,
|
||||
AFLAG_NOT_CASTER = 0x08,
|
||||
AFLAG_POSITIVE = 0x10,
|
||||
AFLAG_DURATION = 0x20,
|
||||
AFLAG_UNK2 = 0x40,
|
||||
AFLAG_NEGATIVE = 0x80
|
||||
};
|
||||
|
||||
//m_schoolAbsorb
|
||||
|
|
@ -231,7 +236,7 @@ enum AuraType
|
|||
SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191,
|
||||
SPELL_AURA_HASTE_MELEE = 192,
|
||||
SPELL_AURA_MELEE_SLOW = 193,
|
||||
SPELL_AURA_MOD_DEPRICATED_1 = 194, // not used now, old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT
|
||||
SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL = 194,
|
||||
SPELL_AURA_MOD_DEPRICATED_2 = 195, // not used now, old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT
|
||||
SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath
|
||||
SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197,
|
||||
|
|
@ -273,7 +278,7 @@ enum AuraType
|
|||
SPELL_AURA_233 = 233,
|
||||
SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234,
|
||||
SPELL_AURA_MOD_DISPEL_RESIST = 235,
|
||||
SPELL_AURA_236 = 236,
|
||||
SPELL_AURA_CONTROL_VEHICLE = 236,
|
||||
SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237,
|
||||
SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238,
|
||||
SPELL_AURA_MOD_SCALE_2 = 239,
|
||||
|
|
@ -283,28 +288,51 @@ enum AuraType
|
|||
SPELL_AURA_243 = 243,
|
||||
SPELL_AURA_COMPREHEND_LANGUAGE = 244,
|
||||
SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245,
|
||||
SPELL_AURA_246 = 246,
|
||||
SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL = 246,
|
||||
SPELL_AURA_247 = 247,
|
||||
SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248,
|
||||
SPELL_AURA_249 = 249,
|
||||
SPELL_AURA_CONVERT_RUNE = 249,
|
||||
SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250,
|
||||
SPELL_AURA_MOD_ENEMY_DODGE = 251,
|
||||
SPELL_AURA_252 = 252,
|
||||
SPELL_AURA_253 = 253,
|
||||
SPELL_AURA_254 = 254,
|
||||
SPELL_AURA_255 = 255,
|
||||
SPELL_AURA_256 = 256,
|
||||
SPELL_AURA_257 = 257,
|
||||
SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253,
|
||||
SPELL_AURA_MOD_DISARM_SHIELD = 254,
|
||||
SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT = 255,
|
||||
SPELL_AURA_NO_REAGENT_USE = 256,
|
||||
SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257,
|
||||
SPELL_AURA_258 = 258,
|
||||
SPELL_AURA_259 = 259,
|
||||
SPELL_AURA_260 = 260,
|
||||
SPELL_AURA_261 = 261,
|
||||
TOTAL_AURAS=262
|
||||
SPELL_AURA_262 = 262,
|
||||
SPELL_AURA_ALLOW_ONLY_ABILITY = 263,
|
||||
SPELL_AURA_264 = 264,
|
||||
SPELL_AURA_265 = 265,
|
||||
SPELL_AURA_266 = 266,
|
||||
SPELL_AURA_267 = 267,
|
||||
SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268,
|
||||
SPELL_AURA_269 = 269,
|
||||
SPELL_AURA_270 = 270,
|
||||
SPELL_AURA_271 = 271,
|
||||
SPELL_AURA_272 = 272,
|
||||
SPELL_AURA_273 = 273,
|
||||
SPELL_AURA_274 = 274,
|
||||
SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275,
|
||||
SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done
|
||||
SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277,
|
||||
SPELL_AURA_MOD_DISARM_RANGED = 278,
|
||||
SPELL_AURA_279 = 279,
|
||||
SPELL_AURA_MOD_TARGET_ARMOR_PCT = 280,
|
||||
SPELL_AURA_MOD_HONOR_GAIN = 281,
|
||||
SPELL_AURA_MOD_BASE_HEALTH_PCT = 282,
|
||||
SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells
|
||||
TOTAL_AURAS = 284
|
||||
};
|
||||
|
||||
enum AreaAuraType
|
||||
{
|
||||
AREA_AURA_PARTY,
|
||||
AREA_AURA_RAID,
|
||||
AREA_AURA_FRIEND,
|
||||
AREA_AURA_ENEMY,
|
||||
AREA_AURA_PET,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue