*Update to Mangos 6938. (Only build for VC9)

--HG--
branch : trunk
This commit is contained in:
megamage
2008-12-24 09:58:26 -06:00
parent c81299e653
commit 3cb4e7c716
171 changed files with 11207 additions and 5092 deletions
+910
View 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
View 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
+20
View File
@@ -752,3 +752,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);
}
+1 -1
View File
@@ -34,7 +34,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()
+5 -4
View File
@@ -576,6 +576,7 @@ void BattleGround::EndBattleGround(uint32 winner)
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)
@@ -1405,10 +1406,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
+4 -3
View File
@@ -132,8 +132,6 @@ struct BattleGroundObjectInfo
uint32 spellid;
};
#define MAX_QUEUED_PLAYERS_MAP 7
enum BattleGroundTypeId
{
BATTLEGROUND_AV = 1,
@@ -143,7 +141,10 @@ 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
+4 -1
View File
@@ -1267,13 +1267,16 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg)
*data << (uint32)((BattleGroundABScore*)itr->second)->BasesDefended; // bases defended
break;
case BATTLEGROUND_EY:
*data << (uint32)0x00000001; // count of next fields
*data << (uint32)0x00000001; // count of next fields
*data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures
break;
case BATTLEGROUND_NA:
case BATTLEGROUND_BE:
case BATTLEGROUND_AA:
case BATTLEGROUND_RL:
case BATTLEGROUND_SA: // wotlk
case BATTLEGROUND_DS: // wotlk
case BATTLEGROUND_RV: // wotlk
*data << (int32)0; // 0
break;
default:
+2 -2
View File
@@ -32,9 +32,9 @@ 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
#define MAX_BATTLEGROUND_QUEUE_TYPES 8
+17
View 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
View 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
View 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);
}
+295 -54
View File
@@ -82,7 +82,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_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;
}
@@ -232,17 +234,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;
}
@@ -309,29 +310,77 @@ 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;
}
// speedup check for heroic class disabled case
uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING);
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
{
data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
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 0 then allowed creating without any characters
bool have_req_level_for_heroic = (req_level_for_heroic==0);
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 guid,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[1].GetUInt32();
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT)
{
uint8 acc_class = field[2].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;
}
}
if(!have_req_level_for_heroic)
{
uint32 acc_guid = field[0].GetUInt32();
uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);
if(acc_level >= req_level_for_heroic)
have_req_level_for_heroic = true;
}
}
// 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 );
@@ -340,20 +389,55 @@ 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[1].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[2].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;
}
}
if(!have_req_level_for_heroic)
{
uint32 acc_guid = field[0].GetUInt32();
uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid);
if(acc_level >= req_level_for_heroic)
have_req_level_for_heroic = true;
}
}
have_same_race = race_ == race;
}
delete result2;
}
}
if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic)
{
data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT;
SendPacket( &data );
return;
}
// extract other data required for player creating
uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId;
recv_data >> gender >> skin >> face;
@@ -510,9 +594,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
@@ -609,12 +695,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 );
}
}
}
@@ -658,22 +752,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);
}
@@ -903,11 +981,11 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ )
void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
{
CHECK_PACKET_SIZE(recv_data, 8+1);
uint64 guid;
std::string newname;
CHECK_PACKET_SIZE(recv_data, 8+1);
recv_data >> guid;
recv_data >> newname;
@@ -915,15 +993,15 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data)
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;
}
@@ -932,7 +1010,7 @@ 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;
}
@@ -961,7 +1039,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin
if (!result)
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
data << (uint8)CHAR_CREATE_ERROR;
data << uint8(CHAR_CREATE_ERROR);
session->SendPacket( &data );
return;
}
@@ -975,11 +1053,11 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin
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);
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());
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;
session->SendPacket(&data);
}
@@ -1073,3 +1151,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);
}
+3
View File
@@ -190,6 +190,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 },
@@ -263,6 +264,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
{ "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", 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 },
@@ -589,6 +591,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 },
+3
View File
@@ -233,6 +233,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);
@@ -434,6 +435,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);
@@ -467,6 +469,7 @@ class ChatHandler
bool HandleUnPossessCommand(const char* args);
bool HandleBindSightCommand(const char* args);
bool HandleUnbindSightCommand(const char* args);
bool HandleSpawnVehicle(const char * args);
Player* getSelectedPlayer();
Creature* getSelectedCreature();
+1 -1
View File
@@ -36,7 +36,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;
+10 -15
View File
@@ -145,11 +145,12 @@ Unit(), i_AI(NULL), i_AI_possessed(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_reactState(REACT_AGGRESSIVE),
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_reactState(REACT_AGGRESSIVE),
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_formationID(0)
{
m_regenTimer = 200;
m_valuesCount = UNIT_END;
for(int i =0; i<4; ++i)
@@ -315,7 +316,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)
@@ -765,8 +765,11 @@ bool Creature::isCanInteractWithBattleMaster(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;
}
@@ -1459,11 +1462,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;
@@ -1475,11 +1474,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
+3 -4
View File
@@ -244,9 +244,7 @@ struct NpcOptionLocale
struct EquipmentInfo
{
uint32 entry;
uint32 equipmodel[3];
uint32 equipinfo[3];
uint32 equipslot[3];
uint32 equipentry[3];
};
// from `creature` table
@@ -423,6 +421,7 @@ class TRINITY_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; }
@@ -657,11 +656,11 @@ class TRINITY_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
ReactStates m_reactState; // for AI, not charmInfo
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
+1 -1
View File
@@ -38,7 +38,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;
}
+60 -36
View File
@@ -46,7 +46,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;
@@ -127,17 +127,33 @@ 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);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id);
SetEntry(goinfo->id);
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
@@ -146,8 +162,6 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float
SetGoAnimProgress(animprogress);
SetUInt32Value (GAMEOBJECT_ARTKIT, ArtKit);
// Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER)
m_charges = goinfo->spellcaster.charges;
@@ -264,7 +278,7 @@ void GameObject::Update(uint32 /*p_time*/)
return;
}
// respawn timer
MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
GetMap()->Add(this);
break;
}
}
@@ -414,7 +428,7 @@ void GameObject::Update(uint32 /*p_time*/)
//burning flags in some battlegrounds, if you find better condition, just add it
if (GetGoAnimProgress() > 0)
{
SendObjectDeSpawnAnim(this->GetGUID());
SendObjectDeSpawnAnim(GetGUID());
//reset flags
SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags);
}
@@ -451,7 +465,7 @@ void GameObject::Refresh()
return;
if(isSpawned())
MapManager::Instance().GetMap(GetMapId(), this)->Add(this);
GetMap()->Add(this);
}
void GameObject::AddUniqueUse(Player* player)
@@ -504,7 +518,7 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask)
if (!goI)
return;
if (!m_DBTableGuid)
m_DBTableGuid = GetGUIDLow();
// update in loaded data (changing data only in this place)
@@ -517,34 +531,33 @@ 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();
data.spawnMask = spawnMask;
data.ArtKit = GetUInt32Value (GAMEOBJECT_ARTKIT);
// updated in DB
std::ostringstream ss;
ss << "INSERT INTO gameobject VALUES ( "
<< m_DBTableGuid << ", "
<< GetUInt32Value (OBJECT_FIELD_ENTRY) << ", "
<< GetEntry() << ", "
<< mapid << ", "
<< (uint32)spawnMask << ", "
<< GetFloatValue(GAMEOBJECT_POS_X) << ", "
<< 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 << ", "
<< GetGoAnimProgress() << ", "
<< GetGoState() << ")";
<< (uint32)GetGoAnimProgress() << ", "
<< (uint32)GetGoState() << ")";
WorldDatabase.BeginTransaction();
WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
@@ -563,7 +576,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
}
uint32 entry = data->id;
uint32 map_id = data->mapid;
//uint32 map_id = data->mapid; // already used before call
float x = data->posX;
float y = data->posY;
float z = data->posZ;
@@ -576,12 +589,11 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map)
uint32 animprogress = data->animprogress;
uint32 go_state = data->go_state;
uint32 ArtKit = data->ArtKit;
m_DBTableGuid = guid;
if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) )
if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state) )
return false;
switch(GetGOInfo()->type)
@@ -846,14 +858,6 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore)
}
void GameObject::SetGoArtKit(uint32 kit)
{
SetUInt32Value(GAMEOBJECT_ARTKIT, kit);
GameObjectData *data = const_cast<GameObjectData*>(objmgr.GetGOData(m_DBTableGuid));
if(data)
data->ArtKit = kit;
}
void GameObject::SwitchDoorOrButton(bool activate)
{
if(activate)
@@ -1209,7 +1213,7 @@ void GameObject::Use(Unit* user)
Player* player = (Player*)user;
if( player->isAllowUseBattleGroundObject() )
if( player->isAllowUseBattleGroundObject() )
{
// in battleground check
BattleGround *bg = player->GetBattleGround();
@@ -1247,6 +1251,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;
+19 -12
View File
@@ -336,12 +336,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
{
@@ -350,6 +350,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
@@ -504,14 +511,14 @@ class TRINITY_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);
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);
+13 -4
View File
@@ -417,10 +417,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))
{
@@ -466,6 +470,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++)
@@ -542,6 +547,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;
@@ -590,13 +597,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 )
@@ -678,9 +686,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 )
+1 -1
View File
@@ -140,7 +140,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
+7 -6
View File
@@ -66,24 +66,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
};
+19 -17
View File
@@ -688,10 +688,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)
@@ -720,7 +720,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);
}
}
@@ -754,17 +754,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)
@@ -801,7 +801,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);
}
}
@@ -824,6 +824,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;
@@ -834,6 +835,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
@@ -843,8 +845,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
@@ -858,11 +860,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
@@ -873,8 +875,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
@@ -884,10 +886,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;
}
}
+32 -6
View File
@@ -785,6 +785,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)" );
@@ -1602,7 +1603,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);
@@ -1618,10 +1633,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);
@@ -1703,7 +1729,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))
+4 -1
View File
@@ -56,7 +56,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
@@ -156,6 +157,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
+11 -7
View File
@@ -206,6 +206,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;
}
@@ -450,7 +454,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();
@@ -765,9 +769,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);
}
@@ -776,7 +780,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);
}
@@ -785,7 +789,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);
}
@@ -795,7 +799,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);
}
+20 -18
View File
@@ -148,29 +148,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
@@ -211,6 +212,7 @@ class TRINITY_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();
@@ -256,9 +258,9 @@ class TRINITY_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);
+8 -3
View File
@@ -324,7 +324,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);
@@ -349,11 +349,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;
@@ -437,7 +440,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
@@ -845,6 +849,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));
}
+70 -12
View File
@@ -57,10 +57,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
{
@@ -185,10 +193,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
{
@@ -214,10 +223,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
{
@@ -272,10 +282,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
{
@@ -310,10 +321,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
{
@@ -423,7 +436,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)
@@ -500,7 +514,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;
@@ -536,12 +553,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
@@ -563,6 +581,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
+2
View File
@@ -328,6 +328,8 @@ enum TrinityStrings
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
+154 -5
View File
@@ -950,7 +950,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);
@@ -1063,8 +1063,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);
@@ -3213,6 +3213,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)
{
@@ -3840,6 +3893,36 @@ bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/)
return true;
}
bool ChatHandler::HandleWaterwalkCommand(const char* args)
{
if(!*args)
return false;
Player *player = getSelectedPlayer();
if(!player)
{
PSendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true);
return false;
}
if (strncmp(args, "on", 3) == 0)
player->SetMovement(MOVE_WATER_WALK); // ON
else if (strncmp(args, "off", 4) == 0)
player->SetMovement(MOVE_LAND_WALK); // OFF
else
{
SendSysMessage(LANG_USE_BOL);
return false;
}
PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
if(needReportToTarget(player))
ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
return true;
}
bool ChatHandler::HandleNpcFollowCommand(const char* /*args*/)
{
Player *player = m_session->GetPlayer();
@@ -3896,6 +3979,72 @@ bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/)
return true;
}
bool ChatHandler::HandleNpcTameCommand(const char* /*args*/)
{
Creature *creatureTarget = getSelectedCreature ();
if (!creatureTarget || creatureTarget->isPet ())
{
PSendSysMessage (LANG_SELECT_CREATURE);
SetSentErrorMessage (true);
return false;
}
Player *player = m_session->GetPlayer ();
if(player->GetPetGUID ())
{
SendSysMessage (LANG_YOU_ALREADY_HAVE_PET);
SetSentErrorMessage (true);
return false;
}
CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo();
if (!cInfo->isTameable ())
{
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
SetSentErrorMessage (true);
return false;
}
// Everything looks OK, create new pet
Pet* pet = player->CreateTamedPetFrom (creatureTarget);
if (!pet)
{
PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry);
SetSentErrorMessage (true);
return false;
}
// place pet before player
float x,y,z;
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 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, level - 1);
// add to world
pet->GetMap()->Add((Creature*)pet);
// visual effect for levelup
pet->SetUInt32Value(UNIT_FIELD_LEVEL, level);
// caster have pet now
player->SetPet(pet);
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
player->PetSpellInitialize();
return true;
}
bool ChatHandler::HandleCreatePetCommand(const char* args)
{
Player *player = m_session->GetPlayer();
@@ -4055,7 +4204,7 @@ bool ChatHandler::HandlePetTpCommand(const char *args)
uint32 tp = atol(args);
pet->SetTP(tp);
//pet->SetTP(tp);
PSendSysMessage("Pet's tp changed to %u", tp);
return true;
@@ -4094,4 +4243,4 @@ bool ChatHandler::HandleActivateObjectCommand(const char *args)
PSendSysMessage("Object activated!");
return true;
}
}
+31 -46
View File
@@ -299,6 +299,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`)" );
@@ -1741,6 +1750,10 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if(!spellInfo)
continue;
// skip server-side/triggered spells
if(spellInfo->spellLevel==0)
continue;
// skip wrong class/race skills
if(!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id))
continue;
@@ -1749,8 +1762,6 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/)
if( spellInfo->SpellFamilyName != family)
continue;
//TODO: skip triggered spells
// skip spells with first rank learned as talent (and all talents then also)
uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id);
if(GetTalentSpellCost(first_rank) > 0 )
@@ -3813,36 +3824,6 @@ bool ChatHandler::HandleHoverCommand(const char* args)
return true;
}
bool ChatHandler::HandleWaterwalkCommand(const char* args)
{
if(!args)
return false;
Player *player = getSelectedPlayer();
if(!player)
{
PSendSysMessage(LANG_NO_CHAR_SELECTED);
SetSentErrorMessage(true);
return false;
}
if (strncmp(args, "on", 3) == 0)
player->SetMovement(MOVE_WATER_WALK); // ON
else if (strncmp(args, "off", 4) == 0)
player->SetMovement(MOVE_LAND_WALK); // OFF
else
{
SendSysMessage(LANG_USE_BOL);
return false;
}
PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName());
if(needReportToTarget(player))
ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName());
return true;
}
bool ChatHandler::HandleLevelUpCommand(const char* args)
{
char* px = strtok((char*)args, " ");
@@ -4458,7 +4439,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);
@@ -4503,6 +4484,7 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
player->SetLevel(1);
player->InitStatsForLevel(true);
player->InitTaxiNodesForLevel();
player->InitGlyphsForLevel();
player->InitTalentForLevel();
player->SetUInt32Value(PLAYER_XP,0);
@@ -4546,6 +4528,7 @@ bool ChatHandler::HandleResetStatsCommand(const char * args)
player->InitStatsForLevel(true);
player->InitTaxiNodesForLevel();
player->InitGlyphsForLevel();
player->InitTalentForLevel();
return true;
@@ -6608,30 +6591,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
@@ -6643,14 +6623,19 @@ 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;
}
+3 -1
View File
@@ -154,6 +154,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 );
@@ -326,7 +327,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))
@@ -495,6 +496,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;
+17
View File
@@ -41,6 +41,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");
@@ -1138,6 +1139,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;
@@ -1230,6 +1246,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);
+3
View File
@@ -297,6 +297,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;
@@ -307,6 +308,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();
@@ -320,6 +322,7 @@ inline void LoadLootTables()
LoadLootTemplates_Fishing();
LoadLootTemplates_Gameobject();
LoadLootTemplates_Item();
LoadLootTemplates_Milling();
LoadLootTemplates_Pickpocketing();
LoadLootTemplates_Skinning();
LoadLootTemplates_Disenchant();
+5 -3
View File
@@ -593,7 +593,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)
{
@@ -604,7 +604,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);
@@ -618,13 +618,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;
+253
View File
@@ -28,6 +28,7 @@ AM_CPPFLAGS =
# later.
noinst_LIBRARIES = libgame.a
<<<<<<< HEAD:src/game/Makefile.am
libgame_a_CPPFLAGS = \
$(MYSQL_INCLUDES) \
$(POSTGRE_INCLUDES) \
@@ -36,6 +37,258 @@ $(TRINI_INCLUDES) \
-I$(top_srcdir)/src/framework \
-I$(top_srcdir)/src/shared \
-I$(top_srcdir)/src/shared/vmap
=======
# libmangossgame library will later be reused by ...
libmangosgame_a_SOURCES = \
AccountMgr.cpp \
AccountMgr.h \
AchievementMgr.h \
AchievementMgr.cpp \
AddonHandler.cpp \
AddonHandler.h \
AggressorAI.cpp \
AggressorAI.h \
AnimalRandomMovementGenerator.h \
ArenaTeam.cpp \
ArenaTeam.h \
ArenaTeamHandler.cpp \
AuctionHouse.cpp \
AuctionHouseObject.h \
Bag.cpp \
Bag.h \
BattleGround.cpp \
BattleGroundAA.cpp \
BattleGroundAB.cpp \
BattleGroundAV.cpp \
BattleGroundBE.cpp \
BattleGroundEY.cpp \
BattleGroundNA.cpp \
BattleGroundRL.cpp \
BattleGroundWS.cpp \
BattleGround.h \
BattleGroundAA.h \
BattleGroundAB.h \
BattleGroundAV.h \
BattleGroundBE.h \
BattleGroundEY.h \
BattleGroundNA.h \
BattleGroundRL.h \
BattleGroundWS.h \
BattleGroundHandler.cpp \
BattleGroundMgr.cpp \
BattleGroundMgr.h \
Calendar.cpp \
Calendar.h \
CalendarHandler.cpp \
Cell.h \
CellImpl.h \
Channel.cpp \
Channel.h \
ChannelHandler.cpp \
ChannelMgr.h \
CharacterHandler.cpp \
Chat.cpp \
Chat.h \
ChatHandler.cpp \
CombatHandler.cpp \
ConfusedMovementGenerator.cpp \
ConfusedMovementGenerator.h \
Corpse.cpp \
Corpse.h \
CreatureAI.cpp \
CreatureAI.h \
CreatureAIImpl.h \
CreatureAIRegistry.cpp \
CreatureAIRegistry.h \
CreatureAISelector.cpp \
CreatureAISelector.h \
Creature.cpp \
Creature.h \
debugcmds.cpp \
DestinationHolder.cpp \
DestinationHolder.h \
DestinationHolderImp.h \
DuelHandler.cpp \
DynamicObject.cpp \
DynamicObject.h \
FleeingMovementGenerator.cpp \
FleeingMovementGenerator.h \
Formulas.h \
GameEvent.cpp \
GameEvent.h \
GameObject.cpp \
GameObject.h \
GlobalEvents.cpp \
GlobalEvents.h \
GMTicketHandler.cpp \
GMTicketMgr.cpp \
GMTicketMgr.h \
GossipDef.cpp \
GossipDef.h \
GridDefines.h \
GridNotifiers.cpp \
GridNotifiers.h \
GridNotifiersImpl.h \
GridStates.cpp \
GridStates.h \
Group.cpp \
Group.h \
GroupHandler.cpp \
GuardAI.cpp \
GuardAI.h \
Guild.cpp \
Guild.h \
GuildHandler.cpp \
HomeMovementGenerator.cpp \
HomeMovementGenerator.h \
HostilRefManager.cpp \
HostilRefManager.h \
IdleMovementGenerator.cpp \
IdleMovementGenerator.h \
InstanceData.cpp \
InstanceData.h \
InstanceSaveMgr.cpp \
InstanceSaveMgr.h \
Item.cpp \
Item.h \
ItemEnchantmentMgr.cpp \
ItemEnchantmentMgr.h \
ItemHandler.cpp \
ItemPrototype.h \
Language.h \
Level0.cpp \
Level1.cpp \
Level2.cpp \
Level3.cpp \
LFGHandler.cpp \
LootHandler.cpp \
LootMgr.cpp \
LootMgr.h \
Mail.cpp \
Mail.h \
Map.cpp \
Map.h \
MapInstanced.cpp \
MapInstanced.h \
MapManager.cpp \
MapManager.h \
MapReference.h \
MapRefManager.h \
MiscHandler.cpp \
MotionMaster.cpp \
MotionMaster.h \
MovementGenerator.cpp \
MovementGenerator.h \
MovementGeneratorImpl.h \
MovementHandler.cpp \
NPCHandler.cpp \
NPCHandler.h \
NullCreatureAI.cpp \
NullCreatureAI.h \
ObjectAccessor.cpp \
ObjectAccessor.h \
Object.cpp \
ObjectDefines.h \
ObjectGridLoader.cpp \
ObjectGridLoader.h \
Object.h \
ObjectMgr.cpp \
ObjectMgr.h \
ObjectPosSelector.cpp \
ObjectPosSelector.h \
Opcodes.cpp \
Opcodes.h \
Path.h \
PetAI.cpp \
PetAI.h \
Pet.cpp \
Pet.h \
PetHandler.cpp \
PetitionsHandler.cpp \
Player.cpp \
Player.h \
PlayerDump.cpp \
PlayerDump.h \
PointMovementGenerator.cpp \
PointMovementGenerator.h \
QueryHandler.cpp \
QuestDef.cpp \
QuestDef.h \
QuestHandler.cpp \
RandomMovementGenerator.cpp \
RandomMovementGenerator.h \
ReactorAI.cpp \
ReactorAI.h \
ScriptCalls.cpp \
ScriptCalls.h \
SharedDefines.h \
SkillHandler.cpp \
SpellAuraDefines.h \
SpellAuras.cpp \
SpellAuras.h \
Spell.cpp \
SpellEffects.cpp \
Spell.h \
SkillDiscovery.cpp \
SkillDiscovery.h \
SkillExtraItems.cpp \
SkillExtraItems.h \
SpellHandler.cpp \
SocialMgr.cpp \
SocialMgr.h \
SpellMgr.cpp \
SpellMgr.h \
StatSystem.cpp \
TargetedMovementGenerator.cpp \
TargetedMovementGenerator.h \
TaxiHandler.cpp \
TemporarySummon.cpp \
TemporarySummon.h \
tools.cpp \
Tools.h \
TotemAI.cpp \
TotemAI.h \
Totem.cpp \
Totem.h \
TradeHandler.cpp \
Transports.cpp \
Transports.h \
ThreatManager.cpp \
ThreatManager.h \
Traveller.h \
Unit.cpp \
Unit.h \
UnitEvents.h \
UpdateData.cpp \
UpdateData.h \
UpdateFields.h \
UpdateMask.h \
Vehicle.cpp \
Vehicle.h \
VoiceChatHandler.cpp \
WaypointManager.cpp \
WaypointManager.h \
WaypointMovementGenerator.cpp \
WaypointMovementGenerator.h \
Weather.cpp \
Weather.h \
World.cpp \
World.h \
WorldLog.cpp \
WorldLog.h \
WorldSession.cpp \
WorldSession.h \
WorldSocket.cpp \
WorldSocket.h \
WorldSocketMgr.cpp \
WorldSocketMgr.h \
FollowerReference.cpp \
FollowerReference.h \
FollowerRefManager.h \
GroupReference.cpp \
GroupReference.h \
GroupRefManager.h
>>>>>>> upstream/master:src/game/Makefile.am
# libmangossgame library will later be reused by ...
libgame_a_SOURCES = \
+3 -3
View File
@@ -45,7 +45,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];
@@ -257,7 +257,7 @@ template<>
void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// add to world object registry in grid
if(obj->isPet() || obj->isPossessedByPlayer())
if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).AddWorldObject<Creature>(obj, obj->GetGUID());
obj->SetCurrentCell(cell);
@@ -301,7 +301,7 @@ template<>
void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell)
{
// remove from world object registry in grid
if(obj->isPet() || obj->isPossessedByPlayer())
if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle())
{
(*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<Creature>(obj, obj->GetGUID());
}
+11
View File
@@ -224,6 +224,17 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O
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();
+4 -2
View File
@@ -175,7 +175,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;
}
@@ -280,7 +281,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)
+121 -29
View File
@@ -45,6 +45,7 @@
#include "Pet.h"
#include "SocialMgr.h"
#include "CellImpl.h"
#include "Tools.h"
void WorldSession::HandleRepopRequestOpcode( WorldPacket & /*recv_data*/ )
{
@@ -312,7 +313,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 );
@@ -349,7 +350,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" );
@@ -363,10 +364,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))
@@ -882,7 +885,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data)
if(missingItem)
SendAreaTriggerMessage(GetTrinityString(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)
@@ -894,16 +897,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)
@@ -1434,11 +1517,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_;
@@ -1508,26 +1591,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");
@@ -1594,3 +1657,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);
}
+90 -125
View File
@@ -178,64 +178,12 @@ 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);
/* 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;
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())
@@ -252,7 +200,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
Unit* pos_unit = GetPlayer()->GetCharm();
if (pos_unit && pos_unit->isPossessed()) // can be charmed but not possessed
{
HandlePossessedMovement(recv_data, movementInfo, MovementFlags);
HandlePossessedMovement(recv_data, movementInfo, movementInfo.flags);
return;
}
@@ -260,10 +208,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
return;
//Save movement flags
GetPlayer()->SetUnitMovementFlags(MovementFlags);
GetPlayer()->SetUnitMovementFlags(movementInfo.flags);
/* 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)
@@ -282,9 +230,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
{
// unmount before boarding
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
GetPlayer()->m_transport = (*iter);
(*iter)->AddPassenger(GetPlayer());
break;
@@ -301,13 +246,14 @@ 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())
GetPlayer()->HandleFallDamage(movementInfo);
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) );
@@ -316,14 +262,35 @@ 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(!_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);
@@ -396,20 +363,13 @@ void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo&
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;
@@ -420,47 +380,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);
@@ -473,7 +396,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)
@@ -486,6 +409,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;
@@ -520,20 +444,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::HandleNotActiveMoverOpcode(WorldPacket& /*recv_data*/)
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*/)
+7 -9
View File
@@ -524,13 +524,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)
{
@@ -541,8 +540,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;
@@ -592,7 +590,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
@@ -656,7 +654,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();
@@ -700,7 +698,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)
+51 -26
View File
@@ -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
@@ -292,12 +299,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)
@@ -330,12 +337,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();
}
//TrinIty 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;
@@ -384,6 +392,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)
@@ -485,7 +494,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;
@@ -508,6 +517,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;
@@ -515,9 +533,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
@@ -525,6 +546,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
@@ -540,10 +568,8 @@ 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);
}
if (GetUInt32Value(GAMEOBJECT_ARTKIT))
updateMask->SetBit(GAMEOBJECT_ARTKIT);
}
}
else //case UPDATETYPE_VALUES
@@ -554,8 +580,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);
}
}
@@ -572,7 +598,6 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if( updateMask->GetBit( index ) )
{
// remove custom flag before send
if( index == UNIT_NPC_FLAGS )
*data << uint32(m_uint32Values[ index ] & ~(UNIT_NPC_FLAG_GUARD + UNIT_NPC_FLAG_OUTDOORPVP));
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
@@ -641,7 +666,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 )
{
@@ -1093,7 +1118,7 @@ uint32 WorldObject::GetAreaId() const
InstanceData* WorldObject::GetInstanceData()
{
Map *map = MapManager::Instance().GetMap(m_mapId, this);
Map *map = GetMap();
return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL;
}
@@ -1303,7 +1328,7 @@ namespace Trinity
{
public:
MessageChatLocaleCacheDo(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID, float dist)
: i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language),
: i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language),
i_targetGUID(targetGUID), i_dist(dist)
{
}
@@ -1448,7 +1473,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;
@@ -1467,7 +1492,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;
@@ -1620,4 +1645,4 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y,
z = GetPositionZ();
UpdateGroundPositionZ(x,y,z);
}
}
+11
View File
@@ -134,6 +134,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);
}
@@ -351,6 +354,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)
{
@@ -602,6 +611,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>;
@@ -609,6 +619,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*/);
+2
View File
@@ -33,6 +33,7 @@
#include "GridDefines.h"
#include "Object.h"
#include "Player.h"
#include "Vehicle.h"
#include <set>
@@ -150,6 +151,7 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::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) ;
+4
View File
@@ -41,6 +41,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)
@@ -50,6 +51,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) )
@@ -87,6 +89,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;
@@ -106,6 +109,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";
+1 -1
View File
@@ -59,7 +59,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();
+116 -34
View File
@@ -116,6 +116,7 @@ ObjectMgr::ObjectMgr()
m_hiCharGuid = 1;
m_hiCreatureGuid = 1;
m_hiPetGuid = 1;
m_hiVehicleGuid = 1;
m_hiItemGuid = 1;
m_hiGoGuid = 1;
m_hiDoGuid = 1;
@@ -641,6 +642,22 @@ void ObjectMgr::LoadCreatureLocales()
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
@@ -1003,8 +1020,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)
@@ -1678,7 +1734,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])
@@ -1775,7 +1831,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)
@@ -1812,7 +1868,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;
@@ -1858,7 +1914,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;
@@ -1927,9 +1983,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()
@@ -2919,31 +2972,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)
@@ -4776,17 +4829,19 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team )
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
if(node)
{
if (team == ALLIANCE) mount_entry = node->alliance_mount_type;
else mount_entry = node->horde_mount_type;
CreatureInfo const *cinfo = GetCreatureTemplate(mount_entry);
if (cinfo)
if (team == ALLIANCE)
{
if(! (mount_id = cinfo->GetRandomValidModelId()))
{
sLog.outErrorDb("No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry);
return false;
}
mount_entry = node->MountCreatureID[1];
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
if(ci)
mount_id = ci->Modelid1;
}
if (team == HORDE)
{
mount_entry = node->MountCreatureID[0];
CreatureInfo const *ci = GetCreatureTemplate(mount_entry);
if(ci)
mount_id = ci->Modelid3;
}
}
@@ -5265,6 +5320,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 )
@@ -5418,6 +5475,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)
{
@@ -6380,6 +6445,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
@@ -6756,7 +6838,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;
}
@@ -6933,7 +7015,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;
@@ -6948,7 +7030,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;
}
}
+11
View File
@@ -264,6 +264,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
@@ -588,6 +590,7 @@ class ObjectMgr
void LoadNpcTextId();
void LoadVendors();
void LoadTrainerSpell();
void LoadCompletedAchievements();
std::string GeneratePetName(uint32 entry);
uint32 GetBaseXP(uint32 level);
@@ -801,6 +804,10 @@ class ObjectMgr
bool RemoveVendorItem(uint32 entry,uint32 item, bool savetodb = true); // for event
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0 ) const;
void LoadAchievementCriteriaList();
AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type);
std::set<uint32> allCompletedAchievements;
void LoadScriptNames();
ScriptNameMap &GetScriptNames() { return m_scriptNames; }
const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; }
@@ -819,6 +826,7 @@ class ObjectMgr
uint32 m_hiCharGuid;
uint32 m_hiCreatureGuid;
uint32 m_hiPetGuid;
uint32 m_hiVehicleGuid;
uint32 m_hiItemGuid;
uint32 m_hiGoGuid;
uint32 m_hiDoGuid;
@@ -929,6 +937,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 Trinity::Singleton<ObjectMgr>::Instance()
+1190 -1060
View File
File diff suppressed because it is too large Load Diff
+262 -134
View File
@@ -49,8 +49,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,
@@ -66,7 +66,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,
@@ -86,7 +86,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,
@@ -214,7 +214,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,
@@ -347,7 +347,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,
@@ -371,10 +371,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,
@@ -578,7 +578,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,
@@ -733,8 +733,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,
@@ -967,10 +967,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,
@@ -980,127 +980,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
{
+118 -277
View File
@@ -41,27 +41,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;
@@ -71,17 +50,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);
@@ -128,24 +106,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;
@@ -160,7 +140,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;
@@ -194,8 +174,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();
@@ -206,72 +186,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)
{
@@ -290,11 +265,11 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
// patch for old data where some spells have ACT_DECIDE but should have ACT_CAST
// so overwrite old state
SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_charmInfo->GetActionBarEntry(index)->SpellOrAction);
if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_CAST;
if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_ENABLED;
}
//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());
@@ -309,7 +284,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;
@@ -375,6 +353,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu
}
}
m_loading = false;
return true;
}
@@ -417,10 +396,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);
@@ -437,7 +412,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() << ", "
@@ -446,9 +421,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) << ", "
@@ -521,12 +494,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);
}
}
@@ -553,6 +526,7 @@ void Pet::Update(uint32 diff)
// unsummon pet that lost owner
Unit* owner = GetOwner();
if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && !isPossessed()) || 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;
@@ -598,14 +572,6 @@ void Pet::Update(uint32 diff)
else
m_happinessTimer -= diff;
if(m_loyaltyTimer <= diff)
{
TickLoyaltyChange();
m_loyaltyTimer = 12000;
}
else
m_loyaltyTimer -= diff;
break;
}
default:
@@ -637,83 +603,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)
@@ -724,11 +619,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;
@@ -765,82 +655,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();
@@ -903,9 +717,6 @@ void Pet::GivePetXP(uint32 xp)
}
SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP);
if(getPetType() == HUNTER_PET)
KillLoyaltyBonus(level);
}
void Pet::GivePetLevel(uint32 level)
@@ -913,9 +724,7 @@ void Pet::GivePetLevel(uint32 level)
if(!level)
return;
InitStatsForLevel( level);
SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1));
InitStatsForLevel(level);
}
bool Pet::CreateBaseAtCreature(Creature* creature)
@@ -973,16 +782,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;
}
@@ -1112,7 +917,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
case HUNTER_PET:
{
SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::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)) );
@@ -1323,10 +1128,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)
@@ -1467,7 +1268,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s
// same spells don't have autocast option
if (spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET)
active = ACT_CAST;
active = ACT_ENABLED;
PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr != m_spells.end())
@@ -1519,11 +1320,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)
{
@@ -1557,20 +1359,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)
{
@@ -1581,6 +1428,8 @@ void Pet::removeSpell(uint16 spell_id)
itr->second->state = PETSPELL_REMOVED;
RemoveAurasDueToSpell(spell_id);
return true;
}
bool Pet::_removeSpell(uint16 spell_id)
@@ -1600,7 +1449,7 @@ void Pet::InitPetCreateSpells()
m_charmInfo->InitPetActionBar();
m_spells.clear();
int32 usedtrainpoints = 0, petspellid;
int32 petspellid;
PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry());
if(CreateSpells)
{
@@ -1629,23 +1478,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)
@@ -1704,7 +1542,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);
@@ -1715,7 +1555,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);
@@ -1738,8 +1580,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);
+9 -32
View File
@@ -52,16 +52,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,
@@ -122,9 +112,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
@@ -167,14 +154,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);
@@ -194,10 +174,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; }
@@ -215,7 +193,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;
@@ -225,11 +205,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;
@@ -241,14 +220,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;
+143 -10
View File
@@ -174,9 +174,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)
@@ -257,7 +257,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
if(pet->isPossessed())
{
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:
@@ -369,7 +369,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)
@@ -542,11 +542,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)
@@ -616,11 +615,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);
// This opcode is also sent from charmed and possessed units (players and creatures)
if(!_player->GetPet() && !_player->GetCharm())
@@ -655,6 +658,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
caster->clearUnitState(UNIT_STAT_FOLLOW);
Spell *spell = new Spell(caster, spellInfo, false);
spell->m_cast_count = cast_count; // probably pending spell cast
spell->m_targets = targets;
int16 result = spell->PetCanCast(NULL);
@@ -713,3 +717,132 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec
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);
}
+4 -4
View File
@@ -199,9 +199,9 @@ 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);
@@ -565,7 +565,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))
+1011 -368
View File
File diff suppressed because it is too large Load Diff
+130 -28
View File
@@ -35,6 +35,7 @@
#include "Pet.h"
#include "MapReference.h"
#include "Util.h" // for Tokens typedef
#include "AchievementMgr.h"
#include<string>
#include<vector>
@@ -49,6 +50,8 @@ class Transport;
class UpdateMask;
class PlayerSocial;
class OutdoorPvP;
class AchievementMgr;
class Vehicle;
typedef std::deque<Mail*> PlayerMails;
@@ -80,15 +83,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;
};
@@ -224,6 +229,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)
@@ -392,7 +430,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)
@@ -481,7 +519,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
@@ -512,7 +551,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;
@@ -544,7 +584,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)
};
@@ -672,6 +712,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) {}
@@ -690,14 +748,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
@@ -711,15 +770,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;
@@ -730,17 +790,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
@@ -813,10 +873,12 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16,
PLAYER_LOGIN_QUERY_LOADGUILD = 17,
PLAYER_LOGIN_QUERY_LOADARENAINFO = 18,
MAX_PLAYER_LOGIN_QUERY
PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 19,
PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 20,
MAX_PLAYER_LOGIN_QUERY = 21
};
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
#define MAX_MONEY_AMOUNT (0x7FFFFFFF-1)
@@ -837,7 +899,7 @@ class TRINITY_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);
@@ -940,7 +1002,7 @@ class TRINITY_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;
@@ -953,10 +1015,12 @@ class TRINITY_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); }
@@ -1052,6 +1116,7 @@ class TRINITY_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); }
@@ -1130,6 +1195,11 @@ class TRINITY_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);
@@ -1285,6 +1355,7 @@ class TRINITY_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;
@@ -1423,6 +1494,12 @@ class TRINITY_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();
@@ -1431,8 +1508,6 @@ class TRINITY_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);
@@ -1589,6 +1664,10 @@ class TRINITY_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);
@@ -1759,6 +1838,8 @@ class TRINITY_DLL_SPEC Player : public Unit
void SetCanParry(bool value);
bool CanBlock() const { return m_canBlock; }
void SetCanBlock(bool 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; }
@@ -1792,7 +1873,7 @@ class TRINITY_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;
@@ -1953,6 +2034,7 @@ class TRINITY_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;
@@ -1970,6 +2052,9 @@ class TRINITY_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); }
@@ -1982,6 +2067,7 @@ class TRINITY_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; }
@@ -2080,6 +2166,18 @@ class TRINITY_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);
@@ -2216,6 +2314,7 @@ class TRINITY_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;
@@ -2249,7 +2348,6 @@ class TRINITY_DLL_SPEC Player : public Unit
bool m_DailyQuestChanged;
time_t m_lastDailyQuestTime;
uint32 m_regenTimer;
uint32 m_breathTimer;
uint32 m_drunkTimer;
uint16 m_drunk;
@@ -2268,8 +2366,10 @@ class TRINITY_DLL_SPEC Player : public Unit
uint32 m_ArmorProficiency;
bool m_canParry;
bool m_canBlock;
bool m_canTitanGrip;
uint8 m_swingErrorMsg;
float m_ammoDPS;
////////////////////Rest System/////////////////////
int time_inn_enter;
uint32 inn_pos_mapid;
@@ -2316,6 +2416,8 @@ class TRINITY_DLL_SPEC Player : public Unit
bool m_farsightVision;
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;
+35 -12
View File
@@ -33,6 +33,7 @@
#include "NPCHandler.h"
#include "ObjectAccessor.h"
#include "Pet.h"
#include "MapManager.h"
void WorldSession::SendNameQueryOpcode(Player *p)
{
@@ -185,7 +186,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->Modelid1; // Modelid1
data << (uint32)ci->Modelid2; // Modelid2
@@ -276,20 +276,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);
}
+47 -45
View File
@@ -44,88 +44,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;
+27 -20
View File
@@ -44,30 +44,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
@@ -190,6 +193,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; }
@@ -277,6 +282,8 @@ class Quest
uint32 LimitTime;
uint32 QuestFlags;
uint32 CharTitleId;
uint32 PlayersSlain;
uint32 BonusTalents;
int32 PrevQuestId;
int32 NextQuestId;
int32 ExclusiveGroup;
-6
View File
@@ -451,12 +451,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 );
+187 -122
View File
@@ -88,7 +88,8 @@ enum Classes
#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)))
@@ -134,11 +135,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
{
@@ -199,10 +201,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
enum SpellCategory
{
@@ -217,7 +220,7 @@ enum SpellCategory
#define SPELL_ATTR_UNK0 0x00000001 // 0
#define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilities 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
@@ -272,7 +275,7 @@ enum SpellCategory
#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
@@ -288,14 +291,14 @@ enum SpellCategory
#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_TAME_BEAST 0x00010000 // 16
#define SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT 0x00020000 // 17 Hunters Shot and Stings only have this flag
#define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet
@@ -413,37 +416,37 @@ enum SpellCategory
#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
{
@@ -566,7 +569,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,
@@ -586,16 +589,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,
@@ -608,10 +611,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, //unused
@@ -655,19 +658,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,
@@ -675,7 +678,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
@@ -703,7 +712,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
@@ -711,11 +721,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,
@@ -731,7 +741,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,
@@ -739,12 +749,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)| \
@@ -764,7 +775,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) )
@@ -978,9 +990,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
@@ -1547,7 +1560,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!
@@ -1601,7 +1616,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,
@@ -1611,7 +1626,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
@@ -1643,6 +1667,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
@@ -1653,7 +1679,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,
@@ -1682,22 +1708,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;
}
@@ -1709,7 +1739,6 @@ enum SkillType
SKILL_ARMS = 26,
SKILL_COMBAT = 38,
SKILL_SUBTLETY = 39,
SKILL_POISONS = 40,
SKILL_SWORDS = 43,
SKILL_AXES = 44,
SKILL_BOWS = 45,
@@ -1717,8 +1746,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,
@@ -1774,24 +1803,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,
@@ -1821,7 +1846,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,
@@ -1841,10 +1866,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)
{
@@ -1859,25 +1901,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,
@@ -1887,15 +1931,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
@@ -1905,7 +1962,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
@@ -1915,6 +1973,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
@@ -1982,9 +2041,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
@@ -2153,42 +2215,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
-4
View File
@@ -82,10 +82,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;
+323 -79
View File
@@ -237,7 +237,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)
{
@@ -357,6 +357,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
@@ -365,6 +366,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
@@ -502,6 +504,8 @@ void Spell::FillTargetMap()
case SPELL_EFFECT_TRIGGER_SPELL:
//case SPELL_EFFECT_TRIGGER_MISSILE: ??
case SPELL_EFFECT_SKILL_STEP:
case SPELL_EFFECT_PROFICIENCY:
case SPELL_EFFECT_SUMMON_OBJECT_WILD:
case SPELL_EFFECT_SELF_RESURRECT:
case SPELL_EFFECT_REPUTATION:
if(m_targets.getUnitTarget())
@@ -533,6 +537,7 @@ void Spell::FillTargetMap()
break;
case SPELL_EFFECT_SUMMON_CHANGE_ITEM:
case SPELL_EFFECT_ADD_FARSIGHT:
case SPELL_EFFECT_APPLY_GLYPH:
case SPELL_EFFECT_STUCK:
case SPELL_EFFECT_DESTROY_ALL_TOTEMS:
tmpUnitMap.push_back(m_caster);
@@ -546,6 +551,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;
@@ -1110,6 +1116,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) )
@@ -1320,6 +1337,16 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, Unit* pUnitTarget, f
if(!pUnitTarget)
return;
// 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;
}*/
//FIXME: This very like horrible hack and wrong for most spells
if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
max_range += unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
@@ -2226,6 +2253,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();
@@ -2668,7 +2703,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) )
@@ -2724,9 +2759,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:
@@ -2767,18 +2802,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()
@@ -2792,6 +2820,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));
@@ -2801,14 +2832,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);
@@ -2828,6 +2877,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());
@@ -2835,17 +2891,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);
}
@@ -2973,30 +3065,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())
@@ -3015,6 +3096,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;
}
@@ -3028,13 +3116,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);
}
@@ -3102,10 +3193,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);
}
@@ -3202,6 +3302,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
@@ -3209,6 +3315,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.
@@ -3217,11 +3433,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++)
{
@@ -3344,12 +3558,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
@@ -3686,7 +3913,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;
@@ -3711,15 +3938,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:
@@ -3734,15 +3955,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:
@@ -3845,27 +4060,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))
@@ -3922,9 +4137,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;
@@ -3935,9 +4150,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
@@ -3986,7 +4201,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:
{
@@ -4143,7 +4357,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;
@@ -4165,8 +4379,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;
}
@@ -4481,9 +4695,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;
@@ -4528,6 +4745,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)
@@ -4655,8 +4877,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++)
{
@@ -4824,13 +5045,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:
{
@@ -5003,9 +5247,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
+43 -10
View File
@@ -47,26 +47,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_UNKNOWN3 = 0x00000100
CAST_FLAG_AMMO = 0x00000020, // Projectiles visual
CAST_FLAG_UNKNOWN8 = 0x00000040,
CAST_FLAG_UNKNOWN9 = 0x00000080,
CAST_FLAG_UNKNOWN3 = 0x00000100,
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_UNKNOWN20 = 0x00100000,
CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list
};
enum SpellRangeFlag
@@ -275,6 +300,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);
@@ -292,6 +318,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);
@@ -318,6 +345,8 @@ class Spell
void EffectKillCredit(uint32 i);
void EffectQuestFail(uint32 i);
void EffectRedirectThreat(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();
@@ -328,6 +357,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();
@@ -386,6 +417,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; }
@@ -422,7 +454,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;
@@ -449,6 +481,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; }
+43 -15
View File
@@ -20,14 +20,19 @@
#ifndef TRINITY_SPELLAURADEFINES_H
#define TRINITY_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
@@ -233,7 +238,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,
@@ -275,7 +280,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,
@@ -285,28 +290,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,
+648 -241
View File
File diff suppressed because it is too large Load Diff
+24 -8
View File
@@ -100,6 +100,7 @@ class TRINITY_DLL_SPEC Aura
void HandleAuraFeatherFall(bool Apply, bool Real);
void HandleAuraHover(bool Apply, bool Real);
void HandleAddModifier(bool Apply, bool Real);
void HandleAddTargetTrigger(bool Apply, bool Real);
void HandleAuraModStun(bool Apply, bool Real);
void HandleModDamageDone(bool Apply, bool Real);
void HandleAuraUntrackable(bool Apply, bool Real);
@@ -184,10 +185,12 @@ class TRINITY_DLL_SPEC Aura
void HandleAuraGhost(bool Apply, bool Real);
void HandleAuraAllowFlight(bool Apply, bool Real);
void HandleModRating(bool apply, bool Real);
void HandleModRatingFromStat(bool apply, bool Real);
void HandleModTargetResistance(bool apply, bool Real);
void HandleAuraModAttackPowerPercent(bool apply, bool Real);
void HandleAuraModRangedAttackPowerPercent(bool apply, bool Real);
void HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real);
void HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real);
void HandleSpiritOfRedemption(bool apply, bool Real);
void HandleModManaRegen(bool apply, bool Real);
void HandleComprehendLanguage(bool apply, bool Real);
@@ -197,6 +200,7 @@ class TRINITY_DLL_SPEC Aura
void HandleModSpellDamagePercentFromStat(bool apply, bool Real);
void HandleModSpellHealingPercentFromStat(bool apply, bool Real);
void HandleAuraModDispelResist(bool apply, bool Real);
void HandleAuraControlVehicle(bool apply, bool Real);
void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real);
void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real);
void HandleAuraModPacifyAndSilence(bool Apply, bool Real);
@@ -209,6 +213,9 @@ class TRINITY_DLL_SPEC Aura
void HandlePreventFleeing(bool apply, bool Real);
void HandleManaShield(bool apply, bool Real);
void HandleArenaPreparation(bool apply, bool Real);
void HandleAuraConvertRune(bool apply, bool Real);
void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real);
void HandleNoReagentUseAura(bool Apply, bool Real);
void HandleModAttackerSpellHitChance(bool apply, bool Real);
virtual ~Aura();
@@ -231,6 +238,8 @@ class TRINITY_DLL_SPEC Aura
int32 GetAuraDuration() const { return m_duration; }
void SetAuraDuration(int32 duration) { m_duration = duration; }
time_t GetAuraApplyTime() { return m_applyTime; }
SpellModifier *getAuraSpellMod() {return m_spellmod; }
void UpdateAuraDuration();
void SendAuraDurationForCaster(Player* caster);
void UpdateSlotCounterAndDuration();
@@ -250,13 +259,19 @@ class TRINITY_DLL_SPEC Aura
uint8 GetAuraSlot() const { return m_auraSlot; }
void SetAuraSlot(uint8 slot) { m_auraSlot = slot; }
uint8 GetAuraFlags() const { return m_auraFlags; }
void SetAuraFlags(uint8 flags) { m_auraFlags = flags; }
uint8 GetAuraLevel() const { return m_auraLevel; }
void SetAuraLevel(uint8 level) { m_auraLevel = level; }
uint8 GetAuraCharges() const { return m_procCharges; }
void SetAuraCharges(uint8 charges) { m_procCharges = charges; }
void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); }
void SendAuraUpdate(bool remove);
void UpdateAuraCharges()
{
uint8 slot = GetAuraSlot();
// only aura in slot with charges and without stack limitation
if (slot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0)
SetAuraApplication(slot, m_procCharges - 1);
if (m_auraSlot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0)
SendAuraUpdate(false);
}
bool IsPositive() { return m_positive; }
@@ -300,6 +315,9 @@ class TRINITY_DLL_SPEC Aura
void PeriodicTick();
void PeriodicDummyTick();
uint32 const *getAuraSpellClassMask() const { return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; }
bool isAffectedOnSpell(SpellEntry const *spell) const;
int32 GetStackAmount() {return m_stackAmount;}
void SetStackAmount(int32 amount) {m_stackAmount=amount;}
protected:
@@ -321,6 +339,8 @@ class TRINITY_DLL_SPEC Aura
AuraRemoveMode m_removeMode;
uint8 m_auraSlot;
uint8 m_auraFlags;
uint8 m_auraLevel;
bool m_positive:1;
bool m_permanent:1;
@@ -341,10 +361,6 @@ class TRINITY_DLL_SPEC Aura
int32 m_stackAmount;
private:
void CleanupTriggeredSpells();
void SetAura(uint32 slot, bool remove) { m_target->SetUInt32Value(UNIT_FIELD_AURA + slot, remove ? 0 : GetId()); }
void SetAuraFlag(uint32 slot, bool add);
void SetAuraLevel(uint32 slot, uint32 level);
void SetAuraApplication(uint32 slot, int8 count);
};
class TRINITY_DLL_SPEC AreaAura : public Aura
+276 -54
View File
@@ -128,16 +128,16 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN
&Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT
&Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL
&Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused
&Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused
&Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
&Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID)
&Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
&Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST
&Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT
&Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move
&Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET
&Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT
&Spell::EffectSummonPossessed, // 73 SPELL_EFFECT_SUMMON_POSSESSED
&Spell::EffectSummonTotem, // 74 SPELL_EFFECT_SUMMON_TOTEM
&Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS
&Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH
&Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit
&Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
&Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT
@@ -150,10 +150,10 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK
&Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER
&Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT
&Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
&Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
&Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
&Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
&Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE
&Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR
&Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE
&Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT
&Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash
&Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
&Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM
@@ -195,21 +195,21 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
&Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT
&Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells
&Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value
&Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc)
&Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization
&Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry
&Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET
&Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT
&Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT
&Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap
&Spell::EffectUnused, //139 SPELL_EFFECT_139 unused
&Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID)
&Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST
&Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed?
&Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
&Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
&Spell::EffectNULL, //144 SPELL_EFFECT_144 Spectral Blast
&Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect
&Spell::EffectUnused, //146 SPELL_EFFECT_146 unused
&Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE
&Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail
&Spell::EffectUnused, //148 SPELL_EFFECT_148 unused
&Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop
@@ -217,6 +217,12 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2
&Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend
&Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry
&Spell::EffectNULL, //154 unused
&Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal.
&Spell::EffectNULL, //156 Add Socket
&Spell::EffectNULL, //157 create/learn random item/spell for profession
&Spell::EffectMilling, //158 milling
&Spell::EffectNULL //159 allow rename pet once again
};
void Spell::EffectNULL(uint32 /*i*/)
@@ -335,6 +341,13 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
damage = 200;
break;
}
// Intercept (warrior spell trigger)
case 20253:
case 61491:
{
damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f);
break;
}
// arcane charge. must only affect demons (also undead?)
case 45072:
{
@@ -384,6 +397,12 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
}
// Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207}
else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL)
damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f);
// Heroic Throw ${$m1+$AP*.50}
else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL)
damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f);
break;
}
case SPELLFAMILY_WARLOCK:
@@ -393,18 +412,20 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
{
// Incinerate does more dmg (dmg*0.25) if the target is Immolated.
if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
damage += int32(damage*0.25);
damage += int32(damage*0.25f);
}
break;
}
case SPELLFAMILY_DRUID:
{
// Ferocious Bite
if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587)
if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587)
{
// converts each extra point of energy into ($f1+$AP/630) additional damage
float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx];
// converts each extra point of energy into ($f1+$AP/410) additional damage
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx];
damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100);
m_caster->SetPower(POWER_ENERGY,0);
}
// Rake
@@ -480,7 +501,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
{
// Deadly poison (only attacker applied)
if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) &&
(*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() )
(*itr)->GetSpellProto()->SpellVisual[0]==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() )
{
--combo;
++doses;
@@ -506,26 +527,47 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
{
if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f);
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f));
// Eviscerate and Envenom Bonus Damage (item set effect)
if(m_caster->GetDummyAura(37169))
damage += combo*40;
}
}
// Gouge
else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000008LL)
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f);
}
// Instant Poison
else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL)
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f);
}
// Wound Poison
else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL)
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f);
}
break;
}
case SPELLFAMILY_HUNTER:
{
// Mongoose Bite
if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342)
if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342)
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2);
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
}
// Counterattack
else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL)
{
damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f);
}
// Arcane Shot
else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
{
damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15);
damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f);
}
// Steady Shot
else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
@@ -533,16 +575,16 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
}
//Explosive Trap Effect
// Explosive Trap Effect
else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
{
damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1);
damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f);
}
break;
}
case SPELLFAMILY_PALADIN:
{
//Judgement of Vengeance
// Judgement of Vengeance
if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
{
uint32 stacks = 0;
@@ -556,6 +598,38 @@ void Spell::EffectSchoolDMG(uint32 effect_idx)
else
damage *= stacks;
}
// Avenger's Shield ($m1+0.07*$SPH+0.07*$AP)
else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL)
{
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
damage += int32(ap * 0.07f) + int32(holy * 7 / 100);
}
// Exorcism ($m1+0.15*$SPH+0.15*$AP)
else if(m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL)
{
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
}
// Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP)
else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL)
{
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
}
// Holy Wrath ($m1+0.07*$SPH+0.07*$AP)
else if(m_spellInfo->SpellFamilyFlags & 0x0020000000000000LL)
{
float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) +
m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget);
damage += int32(ap * 0.15f) + int32(holy * 15 / 100);
}
break;
}
}
@@ -1155,6 +1229,12 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(m_caster, 30452, true, NULL);
return;
}
case 53341:
case 53343:
{
m_caster->CastSpell(m_caster,54586,true);
return;
}
}
//All IconID Check in there
@@ -1228,7 +1308,7 @@ void Spell::EffectDummy(uint32 i)
break;
case SPELLFAMILY_WARRIOR:
// Charge
if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867)
if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867)
{
int32 chargeBasePoints0 = damage;
m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
@@ -1515,10 +1595,8 @@ void Spell::EffectDummy(uint32 i)
mod->value = -50;
mod->type = SPELLMOD_PCT;
mod->spellId = m_spellInfo->Id;
mod->effectId = i;
mod->lastAffected = NULL;
mod->mask = 0x0000020000000000LL;
mod->charges = 0;
mod->mask2= 0LL;
((Player*)m_caster)->AddSpellMod(mod, true);
m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
@@ -2877,10 +2955,10 @@ void Spell::EffectOpenLock(uint32 /*i*/)
}
// check key
for(int i = 0; i < 5; ++i)
for(int i = 0; i < 8; ++i)
{
// type==1 This means lockInfo->key[i] is an item
if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i])
// Type==1 This means lockInfo->Index[i] is an item
if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i])
{
SendLoot(guid, loottype);
return;
@@ -2898,9 +2976,9 @@ void Spell::EffectOpenLock(uint32 /*i*/)
// skill bonus provided by casting spell (mostly item spells)
uint32 spellSkillBonus = uint32(m_currentBasePoints[0]/*+1*/);
uint32 reqSkillValue = lockInfo->requiredminingskill;
uint32 reqSkillValue = lockInfo->Skill[0];
if(lockInfo->requiredlockskill) // required pick lock skill applying
if(lockInfo->Skill[1]) // required pick lock skill applying
{
if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?)
{
@@ -2908,7 +2986,7 @@ void Spell::EffectOpenLock(uint32 /*i*/)
return;
}
reqSkillValue = lockInfo->requiredlockskill;
reqSkillValue = lockInfo->Skill[1];
}
else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target
{
@@ -3235,7 +3313,7 @@ void Spell::EffectLearnSpell(uint32 i)
Player *player = (Player*)unitTarget;
uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i];
uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i];
player->learnSpell(spellToLearn);
sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
@@ -3877,13 +3955,13 @@ void Spell::EffectEnchantItemTmp(uint32 i)
else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
duration = 1800; // 30 mins
// other cases with this SpellVisual already selected
else if(m_spellInfo->SpellVisual==215)
else if(m_spellInfo->SpellVisual[0]==215)
duration = 1800; // 30 mins
// some fishing pole bonuses
else if(m_spellInfo->SpellVisual==563)
else if(m_spellInfo->SpellVisual[0]==563)
duration = 600; // 10 mins
// shaman rockbiter enchantments
else if(m_spellInfo->SpellVisual==0)
else if(m_spellInfo->SpellVisual[0]==0)
duration = 1800; // 30 mins
else if(m_spellInfo->Id==29702)
duration = 300; // 5 mins
@@ -3946,14 +4024,16 @@ void Spell::EffectTameCreature(uint32 /*i*/)
creatureTarget->RemoveCorpse();
creatureTarget->SetHealth(0); // just for nice GM-mode view
uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->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
m_caster->SetPet(pet);
@@ -4152,7 +4232,6 @@ void Spell::EffectLearnPetSpell(uint32 i)
if(!learn_spellproto)
return;
pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id));
pet->learnSpell(learn_spellproto->Id);
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
@@ -4212,7 +4291,7 @@ void Spell::EffectWeaponDmg(uint32 i)
case SPELLFAMILY_WARRIOR:
{
// Devastate bonus and sunder armor refresh
if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508)
if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508)
{
uint32 stack = 0;
@@ -4225,7 +4304,7 @@ void Spell::EffectWeaponDmg(uint32 i)
{
int32 duration = GetSpellDuration(proto);
(*itr)->SetAuraDuration(duration);
(*itr)->UpdateAuraDuration();
(*itr)->SendAuraUpdate(false);
stack = (*itr)->GetStackAmount();
break;
}
@@ -4936,9 +5015,69 @@ void Spell::EffectScriptEffect(uint32 effIndex)
((Player*)unitTarget)->ModifyMoney(50000000);
break;
}
}
case 51770:
{
if(!unitTarget)
return;
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
unitTarget->CastSpell(unitTarget,51771,false);
break;
}
}
if( m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER )
{
switch(m_spellInfo->Id)
{
// Chimera Shot
case 53209:
{
uint32 spellId = 0;
int32 basePoint = 0;
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
Aura *aura = (*i).second;
if (aura->GetCasterGUID() != m_caster->GetGUID())
continue;
// Search only Serpent Sting, Viper Sting, Scorpid Sting auras
uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
if (!(familyFlag & 0x000000800000C000LL))
continue;
// Refresh aura duration
aura->SetAuraDuration(aura->GetAuraMaxDuration());
aura->SendAuraUpdate(false);
// Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0)
{
spellId = 53353; // 53353 Chimera Shot - Serpent
basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100;
}
// Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0)
{
spellId = 53358; // 53358 Chimera Shot - Viper
basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100;
}
// Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute.
if (familyFlag & 0x0000000000008000LL)
spellId = 53359; // 53359 Chimera Shot - Scorpid
// ?? nothing say in spell desc (possibly need addition check)
//if (familyFlag & 0x0000010000000000LL || // dot
// familyFlag & 0x0000100000000000LL) // stun
//{
// spellId = 53366; // 53366 Chimera Shot - Wyvern
//}
}
if (spellId)
m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
return;
}
default:
break;
}
}
else if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
{
switch(m_spellInfo->SpellFamilyFlags)
{
@@ -5060,7 +5199,8 @@ void Spell::EffectDuel(uint32 i)
// Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
// Don't have to check the target's map since you cannot challenge someone across maps
if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530)
uint32 mapid = caster->GetMapId();
if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609)
{
SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here
return;
@@ -5199,6 +5339,45 @@ void Spell::EffectActivateObject(uint32 effect_idx)
sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
}
void Spell::EffectApplyGlyph(uint32 i)
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
Player *player = (Player*)m_caster;
// remove old glyph
if(uint32 oldglyph = player->GetGlyph(m_glyphIndex))
{
if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
{
player->RemoveAurasDueToSpell(old_gp->SpellId);
player->SetGlyph(m_glyphIndex, 0);
}
}
// apply new one
if(uint32 glyph = m_spellInfo->EffectMiscValue[i])
{
if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex)))
{
if(gp->TypeFlags != gs->TypeFlags)
{
SendCastResult(SPELL_FAILED_INVALID_GLYPH);
return; // glyph slot missmatch
}
}
player->CastSpell(m_caster, gp->SpellId, true);
player->SetGlyph(m_glyphIndex, glyph);
if(m_CastItem)
player->DestroyItemCount(m_CastItem->GetEntry(), 1, true);
}
}
}
void Spell::EffectSummonTotem(uint32 i)
{
uint8 slot = 0;
@@ -5522,18 +5701,14 @@ void Spell::EffectAddExtraAttacks(uint32 /*i*/)
void Spell::EffectParry(uint32 /*i*/)
{
if (unitTarget->GetTypeId() == TYPEID_PLAYER)
{
if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
((Player*)unitTarget)->SetCanParry(true);
}
}
void Spell::EffectBlock(uint32 /*i*/)
{
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)unitTarget)->SetCanBlock(true);
if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
((Player*)unitTarget)->SetCanBlock(true);
}
void Spell::EffectMomentMove(uint32 i)
@@ -6083,9 +6258,9 @@ void Spell::EffectTransmitted(uint32 effIndex)
{
m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
// Orientation3
pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 );
// Orientation4
pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 );
m_caster->AddGameObject(pGameObj); // will removed at spell cancel
// end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
@@ -6180,6 +6355,28 @@ void Spell::EffectProspecting(uint32 /*i*/)
((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
}
void Spell::EffectMilling(uint32 /*i*/)
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
Player* p_caster = (Player*)m_caster;
if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS))
return;
if(itemTarget->GetCount() < 5)
return;
if( sWorld.getConfig(CONFIG_SKILL_MILLING))
{
uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION);
uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue);
}
((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING);
}
void Spell::EffectSkill(uint32 /*i*/)
{
sLog.outDebug("WORLD: SkillEFFECT");
@@ -6327,6 +6524,31 @@ void Spell::EffectQuestFail(uint32 i)
((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
}
void Spell::EffectActivateRune(uint32 i)
{
if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
Player *plr = (Player*)m_caster;
if(plr->getClass() != CLASS_DEATH_KNIGHT)
return;
for(uint32 j = 0; j < MAX_RUNES; ++j)
{
if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[i])
{
plr->SetRuneCooldown(j, 0);
}
}
}
void Spell::EffectTitanGrip(uint32 i)
{
if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER)
((Player*)unitTarget)->SetCanTitanGrip(true);
}
void Spell::EffectRedirectThreat(uint32 /*i*/)
{
if(unitTarget)
+23 -15
View File
@@ -38,15 +38,17 @@
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
// TODO: add targets.read() check
CHECK_PACKET_SIZE(recvPacket,1+1+1+1+8);
CHECK_PACKET_SIZE(recvPacket,1+1+1+4+8+4+1);
Player* pUser = _player;
uint8 bagIndex, slot;
uint8 spell_count; // number of spells at item, not used
uint8 unk_flags; // flags (if 0x02 - some additional data are received)
uint8 cast_count; // next cast if exists (single or not)
uint64 item_guid;
uint32 glyphIndex; // something to do with glyphs?
uint32 spellid; // casted spell id
recvPacket >> bagIndex >> slot >> spell_count >> cast_count >> item_guid;
recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags;
Item *pItem = pUser->GetItemByPos(bagIndex, slot);
if(!pItem)
@@ -61,7 +63,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
return;
}
sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size());
sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, recvPacket.size());
ItemPrototype const *proto = pItem->GetProto();
if(!proto)
@@ -128,14 +130,15 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
// no script or script not process request by self
// special learning case
if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN)
if((pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) || (pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN_PET))
{
uint32 learn_spell_id = pItem->GetProto()->Spells[0].SpellId;
uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN);
SpellEntry const *spellInfo = sSpellStore.LookupEntry(learn_spell_id);
if(!spellInfo)
{
sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN);
sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, learn_spell_id);
pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL);
return;
}
@@ -172,7 +175,8 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
Spell *spell = new Spell(pUser, spellInfo, (count > 0));
spell->m_CastItem = pItem;
spell->m_cast_count = cast_count; //set count of casts
spell->m_cast_count = cast_count; // set count of casts
spell->m_glyphIndex = glyphIndex; // glyph index
spell->prepare(&targets);
++count;
@@ -227,7 +231,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
}
// required picklocking
if(lockInfo->requiredlockskill || lockInfo->requiredminingskill)
if(lockInfo->Skill[1] || lockInfo->Skill[0])
{
pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL );
return;
@@ -283,15 +287,16 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data )
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
CHECK_PACKET_SIZE(recvPacket,4+1+2);
CHECK_PACKET_SIZE(recvPacket,1+4+1);
uint32 spellId;
uint8 cast_count;
recvPacket >> spellId;
uint8 cast_count, unk_flags;
recvPacket >> cast_count;
recvPacket >> spellId;
recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received)
sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i",
spellId, cast_count, recvPacket.size());
sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i",
spellId, cast_count, unk_flags, recvPacket.size());
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
@@ -334,9 +339,12 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
{
CHECK_PACKET_SIZE(recvPacket,4);
CHECK_PACKET_SIZE(recvPacket,5);
// increments with every CANCEL packet, don't use for now
uint8 counter;
uint32 spellId;
recvPacket >> counter;
recvPacket >> spellId;
//FIXME: hack, ignore unexpected client cancel Deadly Throw cast
+234 -53
View File
@@ -41,13 +41,13 @@ SpellMgr::SpellMgr()
case SPELL_EFFECT_TRANS_DOOR: //50 summon object
case SPELL_EFFECT_SUMMON_PET: //56
case SPELL_EFFECT_ADD_FARSIGHT: //72
case SPELL_EFFECT_SUMMON_POSSESSED: //73
case SPELL_EFFECT_SUMMON_TOTEM: //74
//case SPELL_EFFECT_SUMMON_POSSESSED: //73
//case SPELL_EFFECT_SUMMON_TOTEM: //74
case SPELL_EFFECT_SUMMON_OBJECT_WILD: //76
case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: //87
case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: //88
case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: //89
case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: //90
//case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: //87
//case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: //88
//case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: //89
//case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: //90
case SPELL_EFFECT_SUMMON_CRITTER: //97
case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: //104
case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: //105
@@ -318,10 +318,10 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200))
return SPELL_JUDGEMENT;
for (int i = 0; i < 3; i++)
for (int i = 0; i < 3; i++) // TODO: fix it for WotLK!!!
{
// only paladin auras have this
if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID)
return SPELL_AURA;
}
break;
@@ -339,7 +339,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
}
// only warlock armor/skin have this (in additional to family cases)
if( spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89)
if( spellInfo->SpellVisual[0] == 130 && spellInfo->SpellIconID == 89)
{
return SPELL_WARLOCK_ARMOR;
}
@@ -828,8 +828,8 @@ void SpellMgr::LoadSpellAffects()
uint32 count = 0;
// 0 1 2
QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellFamilyMask FROM spell_affect");
// 0 1 2 3 4
QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect");
if( !result )
{
@@ -876,26 +876,29 @@ void SpellMgr::LoadSpellAffects()
continue;
}
uint64 spellAffectMask = fields[2].GetUInt64();
SpellAffectEntry affect;
affect.SpellClassMask[0] = fields[2].GetUInt32();
affect.SpellClassMask[1] = fields[3].GetUInt32();
affect.SpellClassMask[2] = fields[4].GetUInt32();
// Spell.dbc have own data for low part of SpellFamilyMask
if( spellInfo->EffectItemType[effectId])
// Spell.dbc have own data
uint32 const *ptr = 0;
switch (effectId)
{
if(spellInfo->EffectItemType[effectId] == spellAffectMask)
{
sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectItemType%d) data for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
default:
continue;
}
// 24429 have wrong data in EffectItemType and overwrites by DB, possible bug in client
if(spellInfo->Id!=24429 && spellInfo->EffectItemType[effectId] != spellAffectMask)
{
sLog.outErrorDb("Spell %u listed in `spell_affect` have different low part from EffectItemType%d for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
continue;
}
}
if(ptr[0] == affect.SpellClassMask[0] || ptr[1] == affect.SpellClassMask[1] || ptr[2] == affect.SpellClassMask[2])
{
char text[]="ABC";
sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectSpellClassMask%c) data for effect index (%u) and not needed, skipped.", entry, text[effectId], effectId);
continue;
}
mSpellAffectMap.insert(SpellAffectMap::value_type((entry<<8) + effectId,spellAffectMask));
mSpellAffectMap[(entry<<8) + effectId] = affect;
++count;
} while( result->NextRow() );
@@ -903,7 +906,7 @@ void SpellMgr::LoadSpellAffects()
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u spell affect definitions", count );
sLog.outString( ">> Loaded %u custom spell affect definitions", count );
for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
{
@@ -919,7 +922,16 @@ void SpellMgr::LoadSpellAffects()
spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) )
continue;
if(spellInfo->EffectItemType[effectId] != 0)
uint32 const *ptr = 0;
switch (effectId)
{
case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
default:
continue;
}
if(ptr[0] || ptr[1] || ptr[2])
continue;
if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end())
@@ -930,33 +942,20 @@ void SpellMgr::LoadSpellAffects()
}
}
bool SpellMgr::IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const
bool SpellMgr::IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const
{
// false for spellInfo == NULL
if (!spellInfo)
if (!spellInfo || !mod)
return false;
SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId);
// false for affect_spell == NULL
if (!affect_spell)
SpellEntry const *affect_spell = sSpellStore.LookupEntry(mod->spellId);
// False if affect_spell == NULL or spellFamily not equal
if (!affect_spell || affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
return false;
// False if spellFamily not equal
if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
return false;
// If familyFlags == 0
if (!familyFlags)
{
// Get it from spellAffect table
familyFlags = GetSpellAffectMask(spellId,effectId);
// false if familyFlags == 0
if (!familyFlags)
return false;
}
// true
if (familyFlags & spellInfo->SpellFamilyFlags)
if (mod->mask & spellInfo->SpellFamilyFlags ||
mod->mask2 & spellInfo->SpellFamilyFlags2)
return true;
return false;
@@ -1250,7 +1249,7 @@ bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
{
// Paladin aura Spell
if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN
&& spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
&& spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID)
return false;
// Druid form Spell
if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID
@@ -1387,7 +1386,8 @@ SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spell
{
if( IsPositiveEffect(spellInfo->Id, i) && (
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
) )
{
needRankSelection = true;
@@ -1519,7 +1519,7 @@ void SpellMgr::LoadSpellChains()
entry.ProcFlags=SpellInfo->procFlags;
entry.SpellFamilyFlags=SpellInfo->SpellFamilyFlags;
entry.TargetAuraState=SpellInfo->TargetAuraState;
entry.SpellVisual=SpellInfo->SpellVisual;
entry.SpellVisual=SpellInfo->SpellVisual[0];
entry.ManaCost=SpellInfo->manaCost;
value.Id=spell_id;
@@ -2042,7 +2042,7 @@ void SpellMgr::LoadSpellCustomAttr()
}
}
if(spellInfo->SpellVisual == 3879)
if(spellInfo->SpellVisual[0] == 3879)
mSpellCustomAttr[i] |= SPELL_ATTR_CU_CONE_BACK;
switch(i)
@@ -2146,6 +2146,187 @@ void SpellMgr::LoadSpellLinked()
}
/// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc
void SpellMgr::LoadPetLevelupSpellMap()
{
CreatureFamilyEntry const *creatureFamily;
SpellEntry const *spell;
uint32 count = 0;
for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i)
{
creatureFamily = sCreatureFamilyStore.LookupEntry(i);
if(!creatureFamily) // not exist
continue;
if(creatureFamily->petTalentType < 0) // not hunter pet family
continue;
for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j)
{
spell = sSpellStore.LookupEntry(j);
// not exist
if(!spell)
continue;
// not hunter spell
if(spell->SpellFamilyName != SPELLFAMILY_HUNTER)
continue;
// not pet spell
if(!(spell->SpellFamilyFlags & 0x1000000000000000LL))
continue;
// not Growl or Cower (generics)
if(spell->SpellIconID != 201 && spell->SpellIconID != 958)
{
switch(creatureFamily->ID)
{
case CREATURE_FAMILY_BAT: // Bite and Sonic Blast
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577)
continue;
break;
case CREATURE_FAMILY_BEAR: // Claw and Swipe
if(spell->SpellIconID != 262 && spell->SpellIconID != 1562)
continue;
break;
case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch
if(spell->SpellIconID != 262 && spell->SpellIconID != 168)
continue;
break;
case CREATURE_FAMILY_BOAR: // Bite and Gore
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578)
continue;
break;
case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579)
continue;
break;
case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake
if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494)
continue;
break;
case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath
if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
continue;
break;
case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197)
continue;
break;
case CREATURE_FAMILY_CRAB: // Claw and Pin
if(spell->SpellIconID != 262 && spell->SpellIconID != 2679)
continue;
break;
case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581)
continue;
break;
case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite
if(spell->SpellIconID != 1680 && spell->SpellIconID != 599)
continue;
break;
case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath
if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128)
continue;
break;
case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp
if(spell->SpellIconID != 473 && spell->SpellIconID != 148)
continue;
break;
case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip
if(spell->SpellIconID != 1680 && spell->SpellIconID != 138)
continue;
break;
case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack
if(spell->SpellIconID != 1714 && spell->SpellIconID != 473)
continue;
break;
case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock
if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027)
continue;
break;
case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend
if(spell->SpellIconID != 262 && spell->SpellIconID != 245)
continue;
break;
case CREATURE_FAMILY_RAVAGER: // Bite and Ravage
if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253)
continue;
break;
case CREATURE_FAMILY_RHINO: // Smack and Stampede
if(spell->SpellIconID != 473 && spell->SpellIconID != 3066)
continue;
break;
case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison
if(spell->SpellIconID != 262 && spell->SpellIconID != 163)
continue;
break;
case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit
if(spell->SpellIconID != 1680 && spell->SpellIconID != 68)
continue;
break;
case CREATURE_FAMILY_SILITHID: // Claw and Venom Web Spray
if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013))
continue;
break;
case CREATURE_FAMILY_SPIDER: // Bite and Web
if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684))
continue;
break;
case CREATURE_FAMILY_SPIRIT_BEAST: // Claw and Prowl and Spirit Strike
if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255)
continue;
break;
case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud
if(spell->SpellIconID != 473 && spell->SpellIconID != 2681)
continue;
break;
case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud
if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000)))
continue;
break;
case CREATURE_FAMILY_TURTLE: // Bite and Shell Shield
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588)
continue;
break;
case CREATURE_FAMILY_WARP_STALKER: // Bite and Warp
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952)
continue;
break;
case CREATURE_FAMILY_WASP: // Smack and Sting
if(spell->SpellIconID != 473 && spell->SpellIconID != 110)
continue;
break;
case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath
if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
continue;
break;
case CREATURE_FAMILY_WOLF: // Bite and Furious Howl
if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573)
continue;
break;
case CREATURE_FAMILY_WORM: // Acid Spit and Bite
if(spell->SpellIconID != 636 && spell->SpellIconID != 1680)
continue;
break;
default:
sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID);
continue;
}
}
mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id;
count++;
}
}
sLog.outString();
sLog.outString( ">> Loaded %u pet levelup spells", count );
}
/// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc
bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg)
{
// not exist
@@ -2223,7 +2404,7 @@ bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg)
bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id)
{
// normal case
if( spellInfo->AreaId && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id )
if( spellInfo->AreaId > 0 && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id )
return false;
// elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup)
+214 -180
View File
@@ -29,6 +29,9 @@
#include "Database/SQLStorage.h"
#include "Utilities/UnorderedMap.h"
#include "Player.h"
#include <map>
class Player;
@@ -38,175 +41,188 @@ extern SQLStorage sSpellThreatStore;
enum SpellFailedReason
{
SPELL_FAILED_AFFECTING_COMBAT = 0x00,
SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01,
SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02,
SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03,
SPELL_FAILED_ALREADY_BEING_TAMED = 0x04,
SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05,
SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06,
SPELL_FAILED_ALREADY_OPEN = 0x07,
SPELL_FAILED_AURA_BOUNCED = 0x08,
SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09,
SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A,
SPELL_FAILED_BAD_TARGETS = 0x0B,
SPELL_FAILED_CANT_BE_CHARMED = 0x0C,
SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D,
SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E,
SPELL_FAILED_CANT_BE_PROSPECTED = 0x0F,
SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x10,
SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x11,
SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x12,
SPELL_FAILED_CANT_STEALTH = 0x13,
SPELL_FAILED_CASTER_AURASTATE = 0x14,
SPELL_FAILED_CASTER_DEAD = 0x15,
SPELL_FAILED_CHARMED = 0x16,
SPELL_FAILED_CHEST_IN_USE = 0x17,
SPELL_FAILED_CONFUSED = 0x18,
SPELL_FAILED_DONT_REPORT = 0x19,
SPELL_FAILED_EQUIPPED_ITEM = 0x1A,
SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1B,
SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1C,
SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1D,
SPELL_FAILED_ERROR = 0x1E,
SPELL_FAILED_FIZZLE = 0x1F,
SPELL_FAILED_FLEEING = 0x20,
SPELL_FAILED_FOOD_LOWLEVEL = 0x21,
SPELL_FAILED_HIGHLEVEL = 0x22,
SPELL_FAILED_HUNGER_SATIATED = 0x23,
SPELL_FAILED_IMMUNE = 0x24,
SPELL_FAILED_INTERRUPTED = 0x25,
SPELL_FAILED_INTERRUPTED_COMBAT = 0x26,
SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x27,
SPELL_FAILED_ITEM_GONE = 0x28,
SPELL_FAILED_ITEM_NOT_FOUND = 0x29,
SPELL_FAILED_ITEM_NOT_READY = 0x2A,
SPELL_FAILED_LEVEL_REQUIREMENT = 0x2B,
SPELL_FAILED_LINE_OF_SIGHT = 0x2C,
SPELL_FAILED_LOWLEVEL = 0x2D,
SPELL_FAILED_LOW_CASTLEVEL = 0x2E,
SPELL_FAILED_MAINHAND_EMPTY = 0x2F,
SPELL_FAILED_MOVING = 0x30,
SPELL_FAILED_NEED_AMMO = 0x31,
SPELL_FAILED_NEED_AMMO_POUCH = 0x32,
SPELL_FAILED_NEED_EXOTIC_AMMO = 0x33,
SPELL_FAILED_NOPATH = 0x34,
SPELL_FAILED_NOT_BEHIND = 0x35,
SPELL_FAILED_NOT_FISHABLE = 0x36,
SPELL_FAILED_NOT_FLYING = 0x37,
SPELL_FAILED_NOT_HERE = 0x38,
SPELL_FAILED_NOT_INFRONT = 0x39,
SPELL_FAILED_NOT_IN_CONTROL = 0x3A,
SPELL_FAILED_NOT_KNOWN = 0x3B,
SPELL_FAILED_NOT_MOUNTED = 0x3C,
SPELL_FAILED_NOT_ON_TAXI = 0x3D,
SPELL_FAILED_NOT_ON_TRANSPORT = 0x3E,
SPELL_FAILED_NOT_READY = 0x3F,
SPELL_FAILED_NOT_SHAPESHIFT = 0x40,
SPELL_FAILED_NOT_STANDING = 0x41,
SPELL_FAILED_NOT_TRADEABLE = 0x42,
SPELL_FAILED_NOT_TRADING = 0x43,
SPELL_FAILED_NOT_UNSHEATHED = 0x44,
SPELL_FAILED_NOT_WHILE_GHOST = 0x45,
SPELL_FAILED_NO_AMMO = 0x46,
SPELL_FAILED_NO_CHARGES_REMAIN = 0x47,
SPELL_FAILED_NO_CHAMPION = 0x48,
SPELL_FAILED_NO_COMBO_POINTS = 0x49,
SPELL_FAILED_NO_DUELING = 0x4A,
SPELL_FAILED_NO_ENDURANCE = 0x4B,
SPELL_FAILED_NO_FISH = 0x4C,
SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x4D,
SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x4E,
SPELL_FAILED_NO_PET = 0x4F,
SPELL_FAILED_NO_POWER = 0x50,
SPELL_FAILED_NOTHING_TO_DISPEL = 0x51,
SPELL_FAILED_NOTHING_TO_STEAL = 0x52,
SPELL_FAILED_ONLY_ABOVEWATER = 0x53,
SPELL_FAILED_ONLY_DAYTIME = 0x54,
SPELL_FAILED_ONLY_INDOORS = 0x55,
SPELL_FAILED_ONLY_MOUNTED = 0x56,
SPELL_FAILED_ONLY_NIGHTTIME = 0x57,
SPELL_FAILED_ONLY_OUTDOORS = 0x58,
SPELL_FAILED_ONLY_SHAPESHIFT = 0x59,
SPELL_FAILED_ONLY_STEALTHED = 0x5A,
SPELL_FAILED_ONLY_UNDERWATER = 0x5B,
SPELL_FAILED_OUT_OF_RANGE = 0x5C,
SPELL_FAILED_PACIFIED = 0x5D,
SPELL_FAILED_POSSESSED = 0x5E,
SPELL_FAILED_REAGENTS = 0x5F,
SPELL_FAILED_REQUIRES_AREA = 0x60,
SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x61,
SPELL_FAILED_ROOTED = 0x62,
SPELL_FAILED_SILENCED = 0x63,
SPELL_FAILED_SPELL_IN_PROGRESS = 0x64,
SPELL_FAILED_SPELL_LEARNED = 0x65,
SPELL_FAILED_SPELL_UNAVAILABLE = 0x66,
SPELL_FAILED_STUNNED = 0x67,
SPELL_FAILED_TARGETS_DEAD = 0x68,
SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x69,
SPELL_FAILED_TARGET_AURASTATE = 0x6A,
SPELL_FAILED_TARGET_DUELING = 0x6B,
SPELL_FAILED_TARGET_ENEMY = 0x6C,
SPELL_FAILED_TARGET_ENRAGED = 0x6D,
SPELL_FAILED_TARGET_FRIENDLY = 0x6E,
SPELL_FAILED_TARGET_IN_COMBAT = 0x6F,
SPELL_FAILED_TARGET_IS_PLAYER = 0x70,
SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x71,
SPELL_FAILED_TARGET_NOT_DEAD = 0x72,
SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x73,
SPELL_FAILED_TARGET_NOT_LOOTED = 0x74,
SPELL_FAILED_TARGET_NOT_PLAYER = 0x75,
SPELL_FAILED_TARGET_NO_POCKETS = 0x76,
SPELL_FAILED_TARGET_NO_WEAPONS = 0x77,
SPELL_FAILED_TARGET_UNSKINNABLE = 0x78,
SPELL_FAILED_THIRST_SATIATED = 0x79,
SPELL_FAILED_TOO_CLOSE = 0x7A,
SPELL_FAILED_TOO_MANY_OF_ITEM = 0x7B,
SPELL_FAILED_TOTEM_CATEGORY = 0x7C,
SPELL_FAILED_TOTEMS = 0x7D,
SPELL_FAILED_TRAINING_POINTS = 0x7E,
SPELL_FAILED_TRY_AGAIN = 0x7F,
SPELL_FAILED_UNIT_NOT_BEHIND = 0x80,
SPELL_FAILED_UNIT_NOT_INFRONT = 0x81,
SPELL_FAILED_WRONG_PET_FOOD = 0x82,
SPELL_FAILED_NOT_WHILE_FATIGUED = 0x83,
SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x84,
SPELL_FAILED_NOT_WHILE_TRADING = 0x85,
SPELL_FAILED_TARGET_NOT_IN_RAID = 0x86,
SPELL_FAILED_DISENCHANT_WHILE_LOOTING = 0x87,
SPELL_FAILED_PROSPECT_WHILE_LOOTING = 0x88,
SPELL_FAILED_PROSPECT_NEED_MORE = 0x89,
SPELL_FAILED_TARGET_FREEFORALL = 0x8A,
SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8B,
SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8C,
SPELL_FAILED_TARGET_NOT_GHOST = 0x8D,
SPELL_FAILED_TOO_MANY_SKILLS = 0x8E,
SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F,
SPELL_FAILED_WRONG_WEATHER = 0x90,
SPELL_FAILED_DAMAGE_IMMUNE = 0x91,
SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92,
SPELL_FAILED_PLAY_TIME = 0x93,
SPELL_FAILED_REPUTATION = 0x94,
SPELL_FAILED_MIN_SKILL = 0x95,
SPELL_FAILED_NOT_IN_ARENA = 0x96,
SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97,
SPELL_FAILED_NOT_ON_STEALTHED = 0x98,
SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99,
SPELL_FAILED_NOT_ON_MOUNTED = 0x9A,
SPELL_FAILED_TOO_SHALLOW = 0x9B,
SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C,
SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D,
SPELL_FAILED_BM_OR_INVISGOD = 0x9E,
SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F,
SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0,
SPELL_FAILED_NOT_IDLE = 0xA1,
SPELL_FAILED_NOT_INACTIVE = 0xA2,
SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3,
SPELL_FAILED_NO_PLAYTIME = 0xA4,
SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5,
SPELL_FAILED_ONLY_IN_ARENA = 0xA6,
SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA7,
SPELL_FAILED_UNKNOWN = 0xA8,
SPELL_FAILED_AFFECTING_COMBAT = 0,
SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 1,
SPELL_FAILED_ALREADY_AT_FULL_MANA = 2,
SPELL_FAILED_ALREADY_AT_FULL_POWER = 3,
SPELL_FAILED_ALREADY_BEING_TAMED = 4,
SPELL_FAILED_ALREADY_HAVE_CHARM = 5,
SPELL_FAILED_ALREADY_HAVE_SUMMON = 6,
SPELL_FAILED_ALREADY_OPEN = 7,
SPELL_FAILED_AURA_BOUNCED = 8,
SPELL_FAILED_AUTOTRACK_INTERRUPTED = 9,
SPELL_FAILED_BAD_IMPLICIT_TARGETS = 10,
SPELL_FAILED_BAD_TARGETS = 11,
SPELL_FAILED_CANT_BE_CHARMED = 12,
SPELL_FAILED_CANT_BE_DISENCHANTED = 13,
SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 14,
SPELL_FAILED_CANT_BE_MILLED = 15,
SPELL_FAILED_CANT_BE_PROSPECTED = 16,
SPELL_FAILED_CANT_CAST_ON_TAPPED = 17,
SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 18,
SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 19,
SPELL_FAILED_CANT_STEALTH = 20,
SPELL_FAILED_CASTER_AURASTATE = 21,
SPELL_FAILED_CASTER_DEAD = 22,
SPELL_FAILED_CHARMED = 23,
SPELL_FAILED_CHEST_IN_USE = 24,
SPELL_FAILED_CONFUSED = 25,
SPELL_FAILED_DONT_REPORT = 26,
SPELL_FAILED_EQUIPPED_ITEM = 27,
SPELL_FAILED_EQUIPPED_ITEM_CLASS = 28,
SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 29,
SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 30,
SPELL_FAILED_ERROR = 31,
SPELL_FAILED_FIZZLE = 32,
SPELL_FAILED_FLEEING = 33,
SPELL_FAILED_FOOD_LOWLEVEL = 34,
SPELL_FAILED_HIGHLEVEL = 35,
SPELL_FAILED_HUNGER_SATIATED = 36,
SPELL_FAILED_IMMUNE = 37,
SPELL_FAILED_INCORRECT_AREA = 38,
SPELL_FAILED_INTERRUPTED = 39,
SPELL_FAILED_INTERRUPTED_COMBAT = 40,
SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 41,
SPELL_FAILED_ITEM_GONE = 42,
SPELL_FAILED_ITEM_NOT_FOUND = 43,
SPELL_FAILED_ITEM_NOT_READY = 44,
SPELL_FAILED_LEVEL_REQUIREMENT = 45,
SPELL_FAILED_LINE_OF_SIGHT = 46,
SPELL_FAILED_LOWLEVEL = 47,
SPELL_FAILED_LOW_CASTLEVEL = 48,
SPELL_FAILED_MAINHAND_EMPTY = 49,
SPELL_FAILED_MOVING = 50,
SPELL_FAILED_NEED_AMMO = 51,
SPELL_FAILED_NEED_AMMO_POUCH = 52,
SPELL_FAILED_NEED_EXOTIC_AMMO = 53,
SPELL_FAILED_NEED_MORE_ITEMS = 54,
SPELL_FAILED_NOPATH = 55,
SPELL_FAILED_NOT_BEHIND = 56,
SPELL_FAILED_NOT_FISHABLE = 57,
SPELL_FAILED_NOT_FLYING = 58,
SPELL_FAILED_NOT_HERE = 59,
SPELL_FAILED_NOT_INFRONT = 60,
SPELL_FAILED_NOT_IN_CONTROL = 61,
SPELL_FAILED_NOT_KNOWN = 62,
SPELL_FAILED_NOT_MOUNTED = 63,
SPELL_FAILED_NOT_ON_TAXI = 64,
SPELL_FAILED_NOT_ON_TRANSPORT = 65,
SPELL_FAILED_NOT_READY = 66,
SPELL_FAILED_NOT_SHAPESHIFT = 67,
SPELL_FAILED_NOT_STANDING = 68,
SPELL_FAILED_NOT_TRADEABLE = 69,
SPELL_FAILED_NOT_TRADING = 70,
SPELL_FAILED_NOT_UNSHEATHED = 71,
SPELL_FAILED_NOT_WHILE_GHOST = 72,
SPELL_FAILED_NOT_WHILE_LOOTING = 73,
SPELL_FAILED_NO_AMMO = 74,
SPELL_FAILED_NO_CHARGES_REMAIN = 75,
SPELL_FAILED_NO_CHAMPION = 76,
SPELL_FAILED_NO_COMBO_POINTS = 77,
SPELL_FAILED_NO_DUELING = 78,
SPELL_FAILED_NO_ENDURANCE = 79,
SPELL_FAILED_NO_FISH = 80,
SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 81,
SPELL_FAILED_NO_MOUNTS_ALLOWED = 82,
SPELL_FAILED_NO_PET = 83,
SPELL_FAILED_NO_POWER = 84,
SPELL_FAILED_NOTHING_TO_DISPEL = 85,
SPELL_FAILED_NOTHING_TO_STEAL = 86,
SPELL_FAILED_ONLY_ABOVEWATER = 87,
SPELL_FAILED_ONLY_DAYTIME = 88,
SPELL_FAILED_ONLY_INDOORS = 89,
SPELL_FAILED_ONLY_MOUNTED = 90,
SPELL_FAILED_ONLY_NIGHTTIME = 91,
SPELL_FAILED_ONLY_OUTDOORS = 92,
SPELL_FAILED_ONLY_SHAPESHIFT = 93,
SPELL_FAILED_ONLY_STEALTHED = 94,
SPELL_FAILED_ONLY_UNDERWATER = 95,
SPELL_FAILED_OUT_OF_RANGE = 96,
SPELL_FAILED_PACIFIED = 97,
SPELL_FAILED_POSSESSED = 98,
SPELL_FAILED_REAGENTS = 99,
SPELL_FAILED_REQUIRES_AREA = 100,
SPELL_FAILED_REQUIRES_SPELL_FOCUS = 101,
SPELL_FAILED_ROOTED = 102,
SPELL_FAILED_SILENCED = 103,
SPELL_FAILED_SPELL_IN_PROGRESS = 104,
SPELL_FAILED_SPELL_LEARNED = 105,
SPELL_FAILED_SPELL_UNAVAILABLE = 106,
SPELL_FAILED_STUNNED = 107,
SPELL_FAILED_TARGETS_DEAD = 108,
SPELL_FAILED_TARGET_AFFECTING_COMBAT = 109,
SPELL_FAILED_TARGET_AURASTATE = 110,
SPELL_FAILED_TARGET_DUELING = 111,
SPELL_FAILED_TARGET_ENEMY = 112,
SPELL_FAILED_TARGET_ENRAGED = 113,
SPELL_FAILED_TARGET_FRIENDLY = 114,
SPELL_FAILED_TARGET_IN_COMBAT = 115,
SPELL_FAILED_TARGET_IS_PLAYER = 116,
SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 117,
SPELL_FAILED_TARGET_NOT_DEAD = 118,
SPELL_FAILED_TARGET_NOT_IN_PARTY = 119,
SPELL_FAILED_TARGET_NOT_LOOTED = 120,
SPELL_FAILED_TARGET_NOT_PLAYER = 121,
SPELL_FAILED_TARGET_NO_POCKETS = 122,
SPELL_FAILED_TARGET_NO_WEAPONS = 123,
SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 124,
SPELL_FAILED_TARGET_UNSKINNABLE = 125,
SPELL_FAILED_THIRST_SATIATED = 126,
SPELL_FAILED_TOO_CLOSE = 127,
SPELL_FAILED_TOO_MANY_OF_ITEM = 128,
SPELL_FAILED_TOTEM_CATEGORY = 129,
SPELL_FAILED_TOTEMS = 130,
SPELL_FAILED_TRY_AGAIN = 131,
SPELL_FAILED_UNIT_NOT_BEHIND = 132,
SPELL_FAILED_UNIT_NOT_INFRONT = 133,
SPELL_FAILED_WRONG_PET_FOOD = 134,
SPELL_FAILED_NOT_WHILE_FATIGUED = 135,
SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 136,
SPELL_FAILED_NOT_WHILE_TRADING = 137,
SPELL_FAILED_TARGET_NOT_IN_RAID = 138,
SPELL_FAILED_TARGET_FREEFORALL = 139,
SPELL_FAILED_NO_EDIBLE_CORPSES = 140,
SPELL_FAILED_ONLY_BATTLEGROUNDS = 141,
SPELL_FAILED_TARGET_NOT_GHOST = 142,
SPELL_FAILED_TRANSFORM_UNUSABLE = 143,
SPELL_FAILED_WRONG_WEATHER = 144,
SPELL_FAILED_DAMAGE_IMMUNE = 145,
SPELL_FAILED_PREVENTED_BY_MECHANIC = 146,
SPELL_FAILED_PLAY_TIME = 147,
SPELL_FAILED_REPUTATION = 148,
SPELL_FAILED_MIN_SKILL = 149,
SPELL_FAILED_NOT_IN_ARENA = 150,
SPELL_FAILED_NOT_ON_SHAPESHIFT = 151,
SPELL_FAILED_NOT_ON_STEALTHED = 152,
SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 153,
SPELL_FAILED_NOT_ON_MOUNTED = 154,
SPELL_FAILED_TOO_SHALLOW = 155,
SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 156,
SPELL_FAILED_TARGET_IS_TRIVIAL = 157,
SPELL_FAILED_BM_OR_INVISGOD = 158,
SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 159,
SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 160,
SPELL_FAILED_NOT_IDLE = 161,
SPELL_FAILED_NOT_INACTIVE = 162,
SPELL_FAILED_PARTIAL_PLAYTIME = 163,
SPELL_FAILED_NO_PLAYTIME = 164,
SPELL_FAILED_NOT_IN_BATTLEGROUND = 165,
SPELL_FAILED_NOT_IN_RAID_INSTANCE = 166,
SPELL_FAILED_ONLY_IN_ARENA = 167,
SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 168,
SPELL_FAILED_ON_USE_ENCHANT = 169,
SPELL_FAILED_NOT_ON_GROUND = 170,
SPELL_FAILED_CUSTOM_ERROR = 171,
SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 172,
SPELL_FAILED_TOO_MANY_SOCKETS = 173,
SPELL_FAILED_INVALID_GLYPH = 174,
SPELL_FAILED_UNIQUE_GLYPH = 175,
SPELL_FAILED_GLYPH_SOCKET_LOCKED = 176,
SPELL_FAILED_NO_VALID_TARGETS = 177,
SPELL_FAILED_ITEM_AT_MAX_CHARGES = 178,
SPELL_FAILED_NOT_IN_BARBERSHOP = 179,
SPELL_FAILED_FISHING_TOO_LOW = 180,
SPELL_FAILED_UNKNOWN = 181
};
enum SpellFamilyNames
@@ -223,8 +239,12 @@ enum SpellFamilyNames
SPELLFAMILY_HUNTER = 9,
SPELLFAMILY_PALADIN = 10,
SPELLFAMILY_SHAMAN = 11,
SPELLFAMILY_UNK2 = 12,
SPELLFAMILY_POTION = 13
SPELLFAMILY_UNK2 = 12, // 2 spells (silence resistance)
SPELLFAMILY_POTION = 13,
// 14 - unused
SPELLFAMILY_DEATHKNIGHT = 15,
// 16 - unused
SPELLFAMILY_PET = 17
};
enum SpellDisableTypes
@@ -397,6 +417,7 @@ inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo)
inline bool IsAreaAuraEffect(uint32 effect)
{
if( effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ||
effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID ||
effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND ||
effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY ||
effect == SPELL_EFFECT_APPLY_AREA_AURA_PET ||
@@ -469,7 +490,11 @@ bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group);
DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group);
// Spell affects related declarations (accessed using SpellMgr functions)
typedef std::map<uint32, uint64> SpellAffectMap;
struct SpellAffectEntry
{
uint32 SpellClassMask[3];
};
typedef UNORDERED_MAP<uint32, SpellAffectEntry> SpellAffectMap;
// Spell proc event related declarations (accessed using SpellMgr functions)
enum ProcFlags
@@ -687,6 +712,9 @@ typedef std::multimap<uint32, SpellLearnSpellNode> SpellLearnSpellMap;
typedef std::multimap<uint32, SkillLineAbilityEntry const*> SkillLineAbilityMap;
typedef std::map<uint32, uint32> PetLevelupSpellSet;
typedef std::map<uint32, PetLevelupSpellSet> PetLevelupSpellMap;
inline bool IsPrimaryProfessionSkill(uint32 skill)
{
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill);
@@ -727,15 +755,15 @@ class SpellMgr
// Accessors (const or static functions)
public:
// Spell affects
uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const
SpellAffectEntry const*GetSpellAffect(uint16 spellId, uint8 effectId) const
{
SpellAffectMap::const_iterator itr = mSpellAffectMap.find((spellId<<8) + effectId);
if( itr != mSpellAffectMap.end( ) )
return itr->second;
return &itr->second;
return 0;
}
bool IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const;
bool IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const;
SpellElixirMap const& GetSpellElixirMap() const { return mSpellElixirs; }
@@ -938,11 +966,6 @@ class SpellMgr
return 0;
else
return mSpellCustomAttr[spell_id];
/*SpellCustomAttrMap::const_iterator itr = mSpellCustomAttrMap.find(spell_id);
if(itr != mSpellCustomAttrMap.end())
return itr->second;
else
return 0;*/
}
const std::vector<int32> *GetSpellLinked(int32 spell_id) const
@@ -954,6 +977,15 @@ class SpellMgr
SpellEffectTargetTypes EffectTargetType[TOTAL_SPELL_EFFECTS];
SpellSelectTargetTypes SpellTargetType[TOTAL_SPELL_TARGETS];
PetLevelupSpellSet const* GetPetLevelupSpellList(uint32 petFamily) const
{
PetLevelupSpellMap::const_iterator itr = mPetLevelupSpellMap.find(petFamily);
if(itr != mPetLevelupSpellMap.end())
return &itr->second;
else
return NULL;
}
// Modifiers
public:
static SpellMgr& Instance();
@@ -973,6 +1005,7 @@ class SpellMgr
void LoadSpellPetAuras();
void LoadSpellCustomAttr();
void LoadSpellLinked();
void LoadPetLevelupSpellMap();
private:
SpellScriptTarget mSpellScriptTarget;
@@ -989,6 +1022,7 @@ class SpellMgr
SpellPetAuraMap mSpellPetAuraMap;
SpellCustomAttribute mSpellCustomAttr;
SpellLinkedMap mSpellLinkedMap;
PetLevelupSpellMap mPetLevelupSpellMap;
};
#define spellmgr SpellMgr::Instance()
+52 -14
View File
@@ -51,24 +51,17 @@ bool Player::UpdateStats(Stats stat)
switch(stat)
{
case STAT_STRENGTH:
UpdateAttackPowerAndDamage();
UpdateShieldBlockValue();
break;
case STAT_AGILITY:
UpdateArmor();
UpdateAttackPowerAndDamage(true);
if(getClass() == CLASS_ROGUE || getClass() == CLASS_HUNTER || getClass() == CLASS_DRUID && m_form==FORM_CAT)
UpdateAttackPowerAndDamage();
UpdateAllCritPercentages();
UpdateDodgePercentage();
break;
case STAT_STAMINA: UpdateMaxHealth(); break;
case STAT_INTELLECT:
UpdateMaxPower(POWER_MANA);
UpdateAllSpellCritChances();
UpdateAttackPowerAndDamage(true); //SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, only intellect currently
UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently
break;
@@ -78,8 +71,25 @@ bool Player::UpdateStats(Stats stat)
default:
break;
}
// Need update (exist AP from stat auras)
UpdateAttackPowerAndDamage();
UpdateAttackPowerAndDamage(true);
UpdateSpellDamageAndHealingBonus();
UpdateManaRegen();
// Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat
uint32 mask = 0;
AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT);
for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i)
if (Stats((*i)->GetMiscBValue()) == stat)
mask |= (*i)->GetMiscValue();
if (mask)
{
for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (mask & (1 << rating))
ApplyRatingMod(CombatRating(rating), 0, true);
}
return true;
}
@@ -255,6 +265,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
{
case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
case CLASS_DEATH_KNIGHT: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break;
case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break;
@@ -309,11 +320,20 @@ void Player::UpdateAttackPowerAndDamage(bool ranged )
float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
if( ranged && (getClassMask() & CLASSMASK_WAND_USERS)==0)
if ((getClassMask() & CLASSMASK_WAND_USERS)==0)
{
AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT);
for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i)
attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifierValue() / 100.0f);
if( ranged )
{
AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT);
for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i)
attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f);
}
else
{
AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT);
for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i)
attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f);
}
}
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
@@ -554,6 +574,24 @@ void Player::UpdateSpellCritChance(uint32 school)
SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, crit);
}
void Player::UpdateMeleeHitChances()
{
m_modMeleeHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
m_modMeleeHitChance+= GetRatingBonusValue(CR_HIT_MELEE);
}
void Player::UpdateRangedHitChances()
{
m_modRangedHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE);
m_modRangedHitChance+= GetRatingBonusValue(CR_HIT_RANGED);
}
void Player::UpdateSpellHitChances()
{
m_modSpellHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE);
m_modSpellHitChance+= GetRatingBonusValue(CR_HIT_SPELL);
}
void Player::UpdateAllSpellCritChances()
{
for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
@@ -624,9 +662,9 @@ void Player::UpdateManaRegen()
int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
if (modManaRegenInterrupt > 100)
modManaRegenInterrupt = 100;
SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f);
SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f);
SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN, power_regen_mp5 + power_regen);
SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen);
}
void Player::_ApplyAllStatBonuses()
@@ -923,7 +961,7 @@ void Pet::UpdateAttackPowerAndDamage(bool ranged)
if(getPetType() == HUNTER_PET) //hunter pets benefit from owner's attack power
{
bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f;
SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.125f));
SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f));
}
//demons benefit from warlocks shadow or fire damage
else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)
+1 -1
View File
@@ -71,7 +71,7 @@ void WorldSession::SendTaxiStatus( uint64 guid )
sLog.outDebug( "WORLD: Sent SMSG_TAXINODE_STATUS" );
}
void WorldSession::HandleTaxiQueryAvailableNodesOpcode( WorldPacket & recv_data )
void WorldSession::HandleTaxiQueryAvailableNodes( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data,8);
+6 -5
View File
@@ -137,7 +137,7 @@ void MapManager::LoadTransports()
Transport::Transport() : GameObject()
{
// 2.3.2 - 0x5A
m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION);
m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION);
}
bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags)
@@ -168,9 +168,10 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z,
SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size);
SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction);
SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id);
//SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags);
SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64));
SetUInt32Value(GAMEOBJECT_LEVEL, m_period);
SetEntry(goinfo->id);
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
@@ -179,7 +180,7 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z,
SetGoAnimProgress(animprogress);
if(dynflags)
SetUInt32Value(GAMEOBJECT_DYN_FLAGS, dynflags);
SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags));
return true;
}
+226 -105
View File
@@ -60,6 +60,7 @@ float baseMoveSpeed[MAX_MOVE_TYPE] =
3.141594f, // MOVE_TURN_RATE
7.0f, // MOVE_FLIGHT
4.5f, // MOVE_FLIGHT_BACK
3.14f // MOVE_PITCH_RATE
};
void InitTriggerAuraData();
@@ -154,7 +155,7 @@ Unit::Unit()
m_objectType |= TYPEMASK_UNIT;
m_objectTypeId = TYPEID_UNIT;
// 2.3.2 - 0x70
m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HASPOSITION);
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION);
m_attackTimer[BASE_ATTACK] = 0;
m_attackTimer[OFF_ATTACK] = 0;
@@ -1631,7 +1632,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
{
(*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
(*itr).second->UpdateAuraDuration();
(*itr).second->SendAuraUpdate(false);
}
}
}
@@ -1947,7 +1948,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
{
(*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
(*itr).second->UpdateAuraDuration();
(*itr).second->SendAuraUpdate(false);
}
}
}
@@ -2342,9 +2343,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama
case MELEE_HIT_BLOCK_CRIT:
case MELEE_HIT_CRIT:
{
//*hitInfo = 0xEA;
// 0xEA
*hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | 0x8;
*hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | HITINFO_UNK2;
// Crit bonus calc
uint32 crit_bonus;
@@ -2581,10 +2580,62 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama
}
case MELEE_HIT_GLANCING:
{
<<<<<<< HEAD:src/game/Unit.cpp
int32 leveldif = int32(pVictim->getLevel()) - int32(getLevel());
if (leveldif > 3) leveldif = 3;
*damage *= (1 - leveldif * 0.1f);
cleanDamage->damage = *damage;
=======
float reducePercent = 1.0f; //damage factor
// calculate base values and mods
float baseLowEnd = 1.3;
float baseHighEnd = 1.2;
switch(getClass()) // lowering base values for casters
{
case CLASS_SHAMAN:
case CLASS_PRIEST:
case CLASS_MAGE:
case CLASS_WARLOCK:
case CLASS_DRUID:
baseLowEnd -= 0.7;
baseHighEnd -= 0.3;
break;
}
float maxLowEnd = 0.6;
switch(getClass()) // upper for melee classes
{
case CLASS_WARRIOR:
case CLASS_ROGUE:
case CLASS_DEATH_KNIGHT:
maxLowEnd = 0.91; //If the attacker is a melee class then instead the lower value of 0.91
}
// calculate values
int32 diff = int32(pVictim->GetDefenseSkillValue(this)) - int32(GetWeaponSkillValue(attType,pVictim));
float lowEnd = baseLowEnd - ( 0.05f * diff );
float highEnd = baseHighEnd - ( 0.03f * diff );
// apply max/min bounds
if ( lowEnd < 0.01f ) //the low end must not go bellow 0.01f
lowEnd = 0.01f;
else if ( lowEnd > maxLowEnd ) //the smaller value of this and 0.6 is kept as the low end
lowEnd = maxLowEnd;
if ( highEnd < 0.2f ) //high end limits
highEnd = 0.2f;
if ( highEnd > 0.99f )
highEnd = 0.99f;
if(lowEnd > highEnd) // prevent negative range size
lowEnd = highEnd;
reducePercent = lowEnd + rand_norm() * ( highEnd - lowEnd );
*damage = uint32(reducePercent * *damage);
cleanDamage->damage += *damage;
>>>>>>> upstream/master:src/game/Unit.cpp
*hitInfo |= HITINFO_GLANCING;
break;
}
@@ -2633,7 +2684,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama
((*itr).second->GetCasterGUID() == GetGUID() && (!spellCasted || spellCasted->Id == 35395)) )
{
(*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
(*itr).second->UpdateAuraDuration();
(*itr).second->SendAuraUpdate(false);
}
}
}
@@ -2758,21 +2809,20 @@ MeleeHitOutcome Unit::RollPhysicalOutcomeAgainst (Unit const *pVictim, WeaponAtt
{
// Increase from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL aura
crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, spellInfo->SchoolMask);
if( dodge_chance != 0.0f ) // if dodge chance is already 0, ignore talents for speed
// Ignore combat result aura
AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
{
AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i)
if (!(*i)->isAffectedOnSpell(spellInfo))
continue;
switch((*i)->GetModifier()->m_miscvalue)
{
// can't be dodged rogue finishing move
if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE)
{
if(spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE))
{
dodge_chance = 0.0f;
break;
}
}
case MELEE_HIT_DODGE: dodge_chance = 0.0f; break;
case MELEE_HIT_BLOCK: block_chance = 0.0f; break;
case MELEE_HIT_PARRY: parry_chance = 0.0f; break;
default:
DEBUG_LOG("Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT have unhandled state %d", (*i)->GetId(), (*i)->GetModifier()->m_miscvalue);
break;
}
}
}
@@ -4738,7 +4788,7 @@ void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime)
iter->second->SetAuraDuration(0);
else
iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime);
iter->second->UpdateAuraDuration();
iter->second->SendAuraUpdate(false);
sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration());
}
}
@@ -4930,6 +4980,7 @@ void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage,
data.append(GetPackGUID());
data << uint32(SpellID);
data << uint32(Damage-AbsorbedDamage-Resist-Blocked);
data << uint32(0); // wotlk
data << uint8(damageSchoolMask); // spell school
data << uint32(AbsorbedDamage); // AbsorbedDamage
data << uint32(Resist); // resist
@@ -4994,31 +5045,66 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType,
sLog.outDebug("WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+45)); // we guess size
data << (uint32)HitInfo;
data << uint32(HitInfo); // flags
data.append(GetPackGUID());
data.append(target->GetPackGUID());
data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount);
data << uint32(Damage-AbsorbDamage-Resist-BlockedAmount);// damage
data << uint32(0); // overkill value
data << (uint8)SwingType; // count?
// for(i = 0; i < SwingType; ++i)
data << (uint32)damageSchoolMask;
data << (float)(Damage-AbsorbDamage-Resist-BlockedAmount);
// still need to double check damage
data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount);
data << (uint32)AbsorbDamage;
data << (uint32)Resist;
// end loop
data << (uint32)TargetState;
if(HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2))
{
// for(i = 0; i < SwingType; ++i)
data << uint32(AbsorbDamage);
// end loop
}
if( AbsorbDamage == 0 ) //also 0x3E8 = 0x3E8, check when that happens
data << (uint32)0;
else
data << (uint32)-1;
if(HitInfo & (HITINFO_RESIST | HITINFO_RESIST2))
{
// for(i = 0; i < SwingType; ++i)
data << uint32(Resist);
// end loop
}
data << (uint8)TargetState;
data << (uint32)0;
data << (uint32)BlockedAmount;
data << (uint32)0;
if(HitInfo & HITINFO_BLOCK)
{
data << uint32(BlockedAmount);
}
if(HitInfo & HITINFO_UNK3)
{
data << uint32(0);
}
if(HitInfo & HITINFO_UNK1)
{
data << uint32(0);
data << float(0);
data << float(0);
data << float(0);
data << float(0);
data << float(0);
data << float(0);
data << float(0);
data << float(0);
for(uint8 i = 0; i < 5; ++i)
{
data << float(0);
data << float(0);
}
data << uint32(0);
}
SendMessageToSet( &data, true );
}
@@ -5239,7 +5325,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
{
switch (dummySpell->Id)
{
// Eye of Eye
// Eye for an Eye
case 9799:
case 25988:
{
@@ -5856,7 +5942,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 39373;
break;
}
// Vestments of Faith (Priest Tier 3) - 4 pieces bonus
// Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus)
case 28809:
{
triggered_spell_id = 28810;
@@ -5993,6 +6079,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
}
case SPELLFAMILY_PALADIN:
{
// TODO: spell list, formula change in 3.0.3
// Seal of Righteousness - melee proc dummy
if (dummySpell->SpellFamilyFlags&0x000000008000000LL && triggeredByAura->GetEffIndex()==0)
{
@@ -6089,7 +6176,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
}
break;
}
//Seal of Vengeance
// TODO: fix basepoint calculation (changed in 3.0.3)
// Seal of Vengeance
case 31801:
{
if(effIndex != 0) // effect 1,2 used by seal unleashing code
@@ -6098,7 +6186,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
triggered_spell_id = 31803;
break;
}
// Spiritual Att.
// Spiritual Attunement
case 31785:
case 33776:
{
@@ -6282,7 +6370,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
}
// Earth Shield
if(dummySpell->SpellFamilyFlags==0x40000000000LL)
if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL)
{
if(GetTypeId() != TYPEID_PLAYER)
return false;
@@ -6320,6 +6408,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 15208: spellId = 45294; break; // Rank 10
case 25448: spellId = 45295; break; // Rank 11
case 25449: spellId = 45296; break; // Rank 12
case 49237: spellId = 49239; break; // Rank 13
case 49238: spellId = 49240; break; // Rank 14
// Chain Lightning
case 421: spellId = 45297; break; // Rank 1
case 930: spellId = 45298; break; // Rank 2
@@ -6327,6 +6417,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
case 10605: spellId = 45300; break; // Rank 4
case 25439: spellId = 45301; break; // Rank 5
case 25442: spellId = 45302; break; // Rank 6
case 49268: spellId = 49270; break; // Rank 7
case 49269: spellId = 49271; break; // Rank 8
default:
sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
return false;
@@ -6337,21 +6429,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
mod->value = -100;
mod->type = SPELLMOD_PCT;
mod->spellId = dummySpell->Id;
mod->effectId = 0;
mod->lastAffected = NULL;
mod->mask = 0x0000000000000003LL;
mod->charges = 0;
mod->mask2= 0LL;
((Player*)this)->AddSpellMod(mod, true);
// Remove cooldown (Chain Lightning - have Category Recovery time)
if (procSpell->SpellFamilyFlags & 0x0000000000000002LL)
((Player*)this)->RemoveSpellCooldown(spellId);
// Hmmm.. in most case spells already set half basepoints but...
// Lightning Bolt (2-10 rank) have full basepoint and half bonus from level
// As on wiki:
// BUG: Rank 2 to 10 (and maybe 11) of Lightning Bolt will proc another Bolt with FULL damage (not halved). This bug is known and will probably be fixed soon.
// So - no add changes :)
CastSpell(pVictim, spellId, true, castItem, triggeredByAura);
((Player*)this)->AddSpellMod(mod, false);
@@ -6624,7 +6709,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
break;
}
// Shadowguard
if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual==7958)
if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual[0]==7958)
{
switch(triggeredByAura->GetSpellProto()->Id)
{
@@ -6979,14 +7064,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
}
// Water Shield (we can't set cooldown for main spell - it's player casted spell
if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual==7358)
if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual[0]==7358)
{
target = this;
break;
}
// Lightning Shield
if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual==37)
if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual[0]==37)
{
// overwrite non existing triggered spell call in spell.dbc
switch(triggeredByAura->GetSpellProto()->Id)
@@ -7313,7 +7398,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
if (auraSpellInfo->Id==37594)
trigger_spell_id = 37595;
// Shadowguard
else if(auraSpellInfo->SpellFamilyFlags==0x100080000000LL && auraSpellInfo->SpellVisual==7958)
else if(auraSpellInfo->SpellFamilyFlags==0x100080000000LL && auraSpellInfo->SpellVisual[0]==7958)
{
switch(auraSpellInfo->Id)
{
@@ -7508,7 +7593,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
case SPELLFAMILY_SHAMAN:
{
//Lightning Shield (overwrite non existing triggered spell call in spell.dbc
if(auraSpellInfo->SpellFamilyFlags==0x00000400 && auraSpellInfo->SpellVisual==37)
if(auraSpellInfo->SpellFamilyFlags==0x00000400 && auraSpellInfo->SpellVisual[0]==37)
{
switch(auraSpellInfo->Id)
{
@@ -7720,21 +7805,21 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAur
{
case 836: // Improved Blizzard (Rank 1)
{
if (!procSpell || procSpell->SpellVisual!=9487)
if (!procSpell || procSpell->SpellVisual[0]!=9487)
return false;
triggered_spell_id = 12484;
break;
}
case 988: // Improved Blizzard (Rank 2)
{
if (!procSpell || procSpell->SpellVisual!=9487)
if (!procSpell || procSpell->SpellVisual[0]!=9487)
return false;
triggered_spell_id = 12485;
break;
}
case 989: // Improved Blizzard (Rank 3)
{
if (!procSpell || procSpell->SpellVisual!=9487)
if (!procSpell || procSpell->SpellVisual[0]!=9487)
return false;
triggered_spell_id = 12486;
break;
@@ -8390,6 +8475,9 @@ void Unit::SetPet(Pet* pet)
void Unit::SetCharm(Unit* pet)
{
SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0);
if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->m_mover = pet ? pet : this;
}
void Unit::AddPlayerToVision(Player* plr)
@@ -8468,6 +8556,7 @@ void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool c
data.append(GetPackGUID());
data << uint32(SpellID);
data << uint32(Damage);
data << uint32(0); // over healing?
data << uint8(critical ? 1 : 0);
data << uint8(0); // unused in client?
SendMessageToSet(&data, true);
@@ -8648,7 +8737,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3
CastingTime = 0;
}
// Darkmoon Card: Vengeance - 0.1%
else if (spellProto->SpellVisual == 9850 && spellProto->SpellIconID == 2230)
else if (spellProto->SpellVisual[0] == 9850 && spellProto->SpellIconID == 2230)
{
CastingTime = 3.5;
}
@@ -8916,14 +9005,8 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
{
if((*i)->GetModifier()->m_miscvalue & schoolMask)
{
SpellEntry const* iSpellProto = (*i)->GetSpellProto();
uint8 eff = (*i)->GetEffIndex();
// stat used dependent from next effect aura SPELL_AURA_MOD_SPELL_HEALING presence and misc value (stat index)
Stats usedStat = STAT_INTELLECT;
if(eff < 2 && iSpellProto->EffectApplyAuraName[eff+1]==SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT)
usedStat = Stats(iSpellProto->EffectMiscValue[eff+1]);
// stat used stored in miscValueB for this aura
Stats usedStat = Stats((*i)->GetMiscBValue());
DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifierValue() / 100.0f);
}
}
@@ -9094,7 +9177,7 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount,
AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
{
if((*i)->GetSpellProto()->SpellVisual == 9180)
if((*i)->GetSpellProto()->SpellVisual[0] == 9180)
{
// Flash of Light
if ((spellProto->SpellFamilyFlags & 0x0000000040000000LL) && (*i)->GetEffIndex() == 1)
@@ -10110,38 +10193,37 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
propagateSpeedChange();
// Send speed change packet only for player
if (GetTypeId()!=TYPEID_PLAYER)
return;
WorldPacket data;
if(!forced)
{
switch(mtype)
{
case MOVE_WALK:
data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_RUN:
data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_RUN_BACK:
data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_SWIM:
data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_SWIM_BACK:
data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_TURN_RATE:
data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_FLIGHT:
data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_FLIGHT_BACK:
data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4);
data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
break;
case MOVE_PITCH_RATE:
data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4);
break;
default:
sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype);
@@ -10149,22 +10231,26 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
}
data.append(GetPackGUID());
data << uint32(0); //movement flags
data << uint8(0); //unk
data << uint32(0); // movement flags
data << uint16(0); // unk flags
data << uint32(getMSTime());
data << float(GetPositionX());
data << float(GetPositionY());
data << float(GetPositionZ());
data << float(GetOrientation());
data << uint32(0); //flag unk
data << uint32(0); // fall time
data << float(GetSpeed(mtype));
SendMessageToSet( &data, true );
}
else
{
// register forced speed changes for WorldSession::HandleForceSpeedChangeAck
// and do it only for real sent packets and use run for run/mounted as client expected
++((Player*)this)->m_forced_speed_changes[mtype];
if(GetTypeId() == TYPEID_PLAYER)
{
// register forced speed changes for WorldSession::HandleForceSpeedChangeAck
// and do it only for real sent packets and use run for run/mounted as client expected
++((Player*)this)->m_forced_speed_changes[mtype];
}
switch(mtype)
{
case MOVE_WALK:
@@ -10191,6 +10277,9 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
case MOVE_FLIGHT_BACK:
data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16);
break;
case MOVE_PITCH_RATE:
data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16);
break;
default:
sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype);
return;
@@ -10280,6 +10369,10 @@ bool Unit::CanHaveThreatList() const
if( ((Creature*)this)->isTotem() )
return false;
// vehicles can not have threat list
if( ((Creature*)this)->isVehicle() )
return false;
// pets can not have a threat list, unless they are controlled by a creature
if( ((Creature*)this)->isPet() && IS_PLAYER_GUID(((Pet*)this)->GetOwnerGUID()) )
return false;
@@ -10528,6 +10621,8 @@ int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_in
int32 mechanic = GetEffectMechanic(spellProto, effect_index);
// Find total mod value (negative bonus)
int32 durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic);
// Modify from SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL aura (stack always ?)
durationMod_always+=target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL, spellProto->Dispel);
// Find max mod (negative bonus)
int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic);
@@ -10729,7 +10824,9 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f
case UNIT_MOD_RAGE:
case UNIT_MOD_FOCUS:
case UNIT_MOD_ENERGY:
case UNIT_MOD_HAPPINESS: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break;
case UNIT_MOD_HAPPINESS:
case UNIT_MOD_RUNE:
case UNIT_MOD_RUNIC_POWER: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break;
case UNIT_MOD_RESISTANCE_HOLY:
case UNIT_MOD_RESISTANCE_FIRE:
@@ -10842,21 +10939,18 @@ Stats Unit::GetStatByAuraGroup(UnitMods unitMod) const
Powers Unit::GetPowerTypeByAuraGroup(UnitMods unitMod) const
{
Powers power = POWER_MANA;
switch(unitMod)
{
case UNIT_MOD_MANA: power = POWER_MANA; break;
case UNIT_MOD_RAGE: power = POWER_RAGE; break;
case UNIT_MOD_FOCUS: power = POWER_FOCUS; break;
case UNIT_MOD_ENERGY: power = POWER_ENERGY; break;
case UNIT_MOD_HAPPINESS: power = POWER_HAPPINESS; break;
default:
break;
case UNIT_MOD_MANA: return POWER_MANA;
case UNIT_MOD_RAGE: return POWER_RAGE;
case UNIT_MOD_FOCUS: return POWER_FOCUS;
case UNIT_MOD_ENERGY: return POWER_ENERGY;
case UNIT_MOD_HAPPINESS: return POWER_HAPPINESS;
case UNIT_MOD_RUNE: return POWER_RUNE;
case UNIT_MOD_RUNIC_POWER:return POWER_RUNIC_POWER;
}
return power;
return POWER_MANA;
}
float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const
@@ -10955,6 +11049,12 @@ void Unit::SetPower(Powers power, uint32 val)
SetStatInt32Value(UNIT_FIELD_POWER1 + power, val);
WorldPacket data(SMSG_POWER_UPDATE);
data.append(GetPackGUID());
data << uint8(power);
data << uint32(val);
SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false);
// group update
if(GetTypeId() == TYPEID_PLAYER)
{
@@ -11068,6 +11168,7 @@ uint32 Unit::GetCreatePowers( Powers power ) const
case POWER_FOCUS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 100);
case POWER_ENERGY: return 100;
case POWER_HAPPINESS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 1050000);
case POWER_RUNIC_POWER: return 1000;
}
return 0;
@@ -11155,7 +11256,7 @@ void CharmInfo::InitEmptyActionBar(bool withAttack)
for(uint32 x = 0; x < 10; ++x)
{
PetActionBar[x].Type = ACT_CAST;
PetActionBar[x].Type = ACT_PASSIVE;
PetActionBar[x].SpellOrAction = 0;
}
if (withAttack)
@@ -11171,13 +11272,20 @@ void CharmInfo::InitPossessCreateSpells()
InitEmptyActionBar();
if(m_unit->GetTypeId() == TYPEID_UNIT)
{
for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
/*for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
{
uint32 spellid = ((Creature*)m_unit)->m_spells[i];
if(IsPassiveSpell(spellid))
m_unit->CastSpell(m_unit, spellid, true);
else
AddSpellToAB(0, spellid, ACT_CAST);
}*/
for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
{
if (IsPassiveSpell(((Creature*)m_unit)->m_spells[x]))
m_unit->CastSpell(m_unit, ((Creature*)m_unit)->m_spells[x], true);
else
AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_PASSIVE);
}
}
}
@@ -11221,7 +11329,7 @@ void CharmInfo::InitCharmCreateSpells()
if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable
newstate = ACT_DISABLED;
else
newstate = ACT_CAST;
newstate = ACT_PASSIVE;
AddSpellToAB(0, spellId, newstate);
}
@@ -11232,7 +11340,7 @@ bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate)
{
for(uint8 i = 0; i < 10; i++)
{
if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_CAST) && PetActionBar[i].SpellOrAction == oldid)
if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) && PetActionBar[i].SpellOrAction == oldid)
{
PetActionBar[i].SpellOrAction = newid;
if(!oldid)
@@ -11847,8 +11955,11 @@ void Unit::SendPetCastFail(uint32 spellid, uint8 msg)
return;
WorldPacket data(SMSG_PET_CAST_FAILED, (4+1));
data << uint8(0); // cast count?
data << uint32(spellid);
data << uint8(msg);
// uint32 for some reason
// uint32 for some reason
((Player*)owner)->GetSession()->SendPacket(&data);
}
@@ -12402,7 +12513,10 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id)
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id);
if(!pet->InitStatsForLevel(creatureTarget->getLevel()))
uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel();
pet->SetFreeTalentPoints(pet->GetMaxTalentPointsForLevel(level));
if(!pet->InitStatsForLevel(level))
{
sLog.outError("ERROR: Pet::InitStatsForLevel() failed for creature (Entry: %u)!",creatureTarget->GetEntry());
delete pet;
@@ -12533,10 +12647,8 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
mod->value = jumps-5; // negative
mod->type = SPELLMOD_FLAT;
mod->spellId = spellProto->Id;
mod->effectId = effIdx;
mod->lastAffected = NULL;
mod->mask = spellProto->SpellFamilyFlags;
mod->charges = 0;
mod->mask = spellProto->SpellFamilyFlags;
mod->mask2 = spellProto->SpellFamilyFlags2;
caster->AddSpellMod(mod, true);
CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID());
@@ -12724,6 +12836,15 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
bg->HandleKillUnit((Creature*)pVictim, player);
}
}
// achievement stuff
if ( pVictim->GetTypeId() == TYPEID_PLAYER)
{
if(GetTypeId() == TYPEID_UNIT)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
else if(GetTypeId() == TYPEID_PLAYER)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1);
}
}
void Unit::SetControlled(bool apply, UnitState state)
@@ -12793,7 +12914,7 @@ void Unit::SetStunned(bool apply)
if(apply)
{
SetUInt64Value(UNIT_FIELD_TARGET, 0);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
CastStop();
// Creature specific
@@ -12811,7 +12932,7 @@ void Unit::SetStunned(bool apply)
{
if(isAlive() && getVictim())
SetUInt64Value(UNIT_FIELD_TARGET, getVictim()->GetGUID());
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
if(!hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
{
@@ -13009,4 +13130,4 @@ void Unit::AddAura(uint32 spellId, Unit* target)
}
}
}
}
}
+100 -41
View File
@@ -149,6 +149,7 @@ enum ShapeshiftForm
FORM_BERSERKERSTANCE = 0x13,
FORM_TEST = 0x14,
FORM_ZOMBIE = 0x15,
FORM_METAMORPHOSIS = 0x16,
FORM_FLIGHT_EPIC = 0x1B,
FORM_SHADOW = 0x1C,
FORM_FLIGHT = 0x1D,
@@ -168,14 +169,14 @@ enum SheathState
// byte (1 from 0..3) of UNIT_FIELD_BYTES_2
enum UnitBytes2_Flags
{
UNIT_BYTE2_FLAG_UNK0 = 0x01,
UNIT_BYTE2_FLAG_UNK1 = 0x02,
UNIT_BYTE2_FLAG_UNK2 = 0x04,
UNIT_BYTE2_FLAG_UNK3 = 0x08,
UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel
UNIT_BYTE2_FLAG_UNK5 = 0x20,
UNIT_BYTE2_FLAG_UNK6 = 0x40,
UNIT_BYTE2_FLAG_UNK7 = 0x80
UNIT_BYTE2_FLAG_PVP = 0x01,
UNIT_BYTE2_FLAG_UNK1 = 0x02,
UNIT_BYTE2_FLAG_FFA_PVP = 0x04,
UNIT_BYTE2_FLAG_SANCTUARY = 0x08,
UNIT_BYTE2_FLAG_UNK4 = 0x10,
UNIT_BYTE2_FLAG_UNK5 = 0x20,
UNIT_BYTE2_FLAG_UNK6 = 0x40,
UNIT_BYTE2_FLAG_UNK7 = 0x80
};
// byte (2 from 0..3) of UNIT_FIELD_BYTES_2
@@ -213,16 +214,27 @@ enum HitInfo
HITINFO_UNK1 = 0x00000001, // req correct packet structure
HITINFO_NORMALSWING2 = 0x00000002,
HITINFO_LEFTSWING = 0x00000004,
HITINFO_UNK2 = 0x00000008,
HITINFO_MISS = 0x00000010,
HITINFO_ABSORB = 0x00000020, // plays absorb sound
HITINFO_RESIST = 0x00000040, // resisted at least some damage
HITINFO_CRITICALHIT = 0x00000080,
HITINFO_UNK2 = 0x00000100, // wotlk?
HITINFO_UNK3 = 0x00002000, // wotlk?
HITINFO_GLANCING = 0x00004000,
HITINFO_CRUSHING = 0x00008000,
HITINFO_NOACTION = 0x00010000,
HITINFO_SWINGNOHITSOUND = 0x00080000
HITINFO_ABSORB = 0x00000020, // absorbed damage
HITINFO_ABSORB2 = 0x00000040, // absorbed damage
HITINFO_RESIST = 0x00000080, // resisted atleast some damage
HITINFO_RESIST2 = 0x00000100, // resisted atleast some damage
HITINFO_CRITICALHIT = 0x00000200, // critical hit
// 0x00000400
// 0x00000800
// 0x00001000
HITINFO_BLOCK = 0x00002000, // blocked damage
// 0x00004000
// 0x00008000
HITINFO_GLANCING = 0x00010000,
HITINFO_CRUSHING = 0x00020000,
HITINFO_NOACTION = 0x00040000, // guessed
// 0x00080000
// 0x00100000
HITINFO_SWINGNOHITSOUND = 0x00200000, // guessed
// 0x00400000
HITINFO_UNK3 = 0x00800000
};
//i would like to remove this: (it is defined in item.h
@@ -294,11 +306,13 @@ enum UnitMods
UNIT_MOD_STAT_INTELLECT,
UNIT_MOD_STAT_SPIRIT,
UNIT_MOD_HEALTH,
UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existed order, it's accessed by index values of Powers enum.
UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_RUNIC_POWER must be in existed order, it's accessed by index values of Powers enum.
UNIT_MOD_RAGE,
UNIT_MOD_FOCUS,
UNIT_MOD_ENERGY,
UNIT_MOD_HAPPINESS,
UNIT_MOD_RUNE,
UNIT_MOD_RUNIC_POWER,
UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
UNIT_MOD_RESISTANCE_HOLY,
UNIT_MOD_RESISTANCE_FIRE,
@@ -318,7 +332,7 @@ enum UnitMods
UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR,
UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1,
UNIT_MOD_POWER_START = UNIT_MOD_MANA,
UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1
UNIT_MOD_POWER_END = UNIT_MOD_RUNIC_POWER + 1
};
enum BaseModGroup
@@ -383,9 +397,10 @@ enum UnitMoveType
MOVE_TURN_RATE = 5,
MOVE_FLIGHT = 6,
MOVE_FLIGHT_BACK = 7,
MOVE_PITCH_RATE = 8
};
#define MAX_MOVE_TYPE 8
#define MAX_MOVE_TYPE 9
extern float baseMoveSpeed[MAX_MOVE_TYPE];
@@ -423,10 +438,11 @@ enum CombatRating
CR_WEAPON_SKILL_MAINHAND = 20,
CR_WEAPON_SKILL_OFFHAND = 21,
CR_WEAPON_SKILL_RANGED = 22,
CR_EXPERTISE = 23
CR_EXPERTISE = 23,
CR_ARMOR_PENETRATION = 24
};
#define MAX_COMBAT_RATING 24
#define MAX_COMBAT_RATING 25
enum DamageEffectType
{
@@ -460,19 +476,19 @@ enum UnitFlags
UNIT_FLAG_UNKNOWN9 = 0x00000040,
UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE
UNIT_FLAG_NOT_ATTACKABLE_2 = 0x00000100, // 2.0.8
UNIT_FLAG_UNKNOWN11 = 0x00000200,
UNIT_FLAG_UNKNOWN11 = 0x00000200, // 3.0.3 - makes you unable to attack everything
UNIT_FLAG_LOOTING = 0x00000400, // loot animation
UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
UNIT_FLAG_PVP = 0x00001000,
UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8
UNIT_FLAG_UNKNOWN13 = 0x00008000,
UNIT_FLAG_UNKNOWN14 = 0x00010000,
UNIT_FLAG_PACIFIED = 0x00020000,
UNIT_FLAG_DISABLE_ROTATE = 0x00040000, // stunned, 2.1.1
UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok
UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok
UNIT_FLAG_IN_COMBAT = 0x00080000,
UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
UNIT_FLAG_DISARMED = 0x00200000, // disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
UNIT_FLAG_CONFUSED = 0x00400000,
UNIT_FLAG_FLEEING = 0x00800000,
UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet...
@@ -487,9 +503,10 @@ enum UnitFlags
// Value masks for UNIT_FIELD_FLAGS_2
enum UnitFlags2
{
UNIT_FLAG2_FEIGN_DEATH = 0x00000001,
UNIT_FLAG2_COMPREHEND_LANG= 0x00000008,
UNIT_FLAG2_FORCE_MOVE = 0x00000040
UNIT_FLAG2_FEIGN_DEATH = 0x00000001,
UNIT_FLAG2_COMPREHEND_LANG = 0x00000008,
UNIT_FLAG2_FORCE_MOVE = 0x00000040,
UNIT_FLAG2_REGENERATE_POWER = 0x00000800
};
/// Non Player Character flags
@@ -635,8 +652,18 @@ uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missC
struct UnitActionBarEntry
{
uint32 Type;
uint32 SpellOrAction;
union
{
struct
{
uint16 SpellOrAction;
uint16 Type;
};
struct
{
uint32 Raw;
};
};
};
#define MAX_DECLINED_NAME_CASES 5
@@ -658,13 +685,12 @@ enum CurrentSpellTypes
enum ActiveStates
{
ACT_ENABLED = 0xC100,
ACT_DISABLED = 0x8100,
ACT_COMMAND = 0x0700,
ACT_REACTION = 0x0600,
ACT_CAST = 0x0100,
ACT_PASSIVE = 0x0000,
ACT_DECIDE = 0x0001
ACT_PASSIVE = 0x0100, // 0x0100 - passive
ACT_DISABLED = 0x8100, // 0x8000 - castable
ACT_ENABLED = 0xC100, // 0x4000 | 0x8000 - auto cast + castable
ACT_COMMAND = 0x0700, // 0x0100 | 0x0200 | 0x0400
ACT_REACTION = 0x0600, // 0x0200 | 0x0400
ACT_DECIDE = 0x0001 // what is it?
};
enum ReactStates
@@ -754,6 +780,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
typedef std::list<DiminishingReturn> Diminishing;
typedef std::set<AuraType> AuraTypeSet;
typedef std::set<uint32> ComboPointHolderSet;
typedef std::map<uint8, uint32> VisibleAuraMap;
virtual ~Unit ( );
@@ -884,8 +911,14 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
return false;
}
bool IsPvP() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); }
void SetPvP(bool state) { if(state) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); else RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); }
bool IsPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); }
void SetPvP(bool state)
{
if(state)
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
else
RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
}
uint32 GetCreatureType() const;
uint32 GetCreatureTypeMask() const
{
@@ -1255,6 +1288,30 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ }
HostilRefManager& getHostilRefManager() { return m_HostilRefManager; }
uint32 GetVisibleAura(uint8 slot)
{
VisibleAuraMap::iterator itr = m_visibleAuras.find(slot);
if(itr != m_visibleAuras.end())
return itr->second;
return 0;
}
void SetVisibleAura(uint8 slot, uint32 spellid)
{
if(spellid == 0)
{
VisibleAuraMap::iterator itr = m_visibleAuras.find(slot);
if(itr != m_visibleAuras.end())
{
m_visibleAuras.erase(itr);
return;
}
}
else
m_visibleAuras[slot] = spellid;
}
VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; }
uint8 GetVisibleAurasCount() { return m_visibleAuras.size(); }
Aura* GetAura(uint32 spellId, uint32 effindex);
AuraMap & GetAuras() { return m_Auras; }
AuraMap const& GetAuras() const { return m_Auras; }
@@ -1446,6 +1503,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
float m_weaponDamage[MAX_ATTACK][2];
bool m_canModifyStats;
//std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem
VisibleAuraMap m_visibleAuras;
float m_speed_rate[MAX_MOVE_TYPE];
@@ -1459,6 +1517,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint32 m_unit_movement_flags;
uint32 m_reactiveTimer[MAX_REACTIVE];
uint32 m_regenTimer;
private:
void SendAttackStop(Unit* victim); // only from AttackStop(Unit*)
+1 -1
View File
@@ -108,7 +108,7 @@ bool UpdateData::BuildPacket(WorldPacket *packet, bool hasTransport)
ByteBuffer buf(m_data.size() + 10 + m_outOfRangeGUIDs.size()*8);
buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount);
buf << (uint8) (hasTransport ? 1 : 0);
//buf << (uint8) (hasTransport ? 1 : 0);
if(!m_outOfRangeGUIDs.empty())
{
+3 -2
View File
@@ -38,11 +38,12 @@ enum OBJECT_UPDATE_FLAGS
UPDATEFLAG_NONE = 0x00,
UPDATEFLAG_SELF = 0x01,
UPDATEFLAG_TRANSPORT = 0x02,
UPDATEFLAG_FULLGUID = 0x04,
UPDATEFLAG_HAS_TARGET = 0x04,
UPDATEFLAG_LOWGUID = 0x08,
UPDATEFLAG_HIGHGUID = 0x10,
UPDATEFLAG_LIVING = 0x20,
UPDATEFLAG_HASPOSITION = 0x40
UPDATEFLAG_HAS_POSITION = 0x40,
UPDATEFLAG_VEHICLE = 0x80
};
class UpdateData
+290 -241
View File
@@ -21,7 +21,7 @@
#ifndef _UPDATEFIELDS_AUTO_H
#define _UPDATEFIELDS_AUTO_H
// Auto generated for version 2, 4, 3, 8606
// Auto generated for version 3, 0, 3, 9183
enum EObjectFields
{
@@ -43,13 +43,37 @@ enum EItemFields
ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT = OBJECT_END + 0x0010, // Size: 33, Type: INT, Flags: PUBLIC
ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC
ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0032, // Size: 1, Type: INT, Flags: PUBLIC
ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0033, // Size: 1, Type: INT, Flags: OWNER_ONLY
ITEM_FIELD_DURABILITY = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_END = OBJECT_END + 0x0036,
ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC
ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC
ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER_ONLY
ITEM_FIELD_DURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2
ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE
ITEM_END = OBJECT_END + 0x003A,
};
enum EContainerFields
@@ -64,93 +88,94 @@ enum EUnitFields
{
UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_CREATEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_TARGET = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_PERSUADED = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE
UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC
UNIT_FIELD_HEALTH = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: DYNAMIC
UNIT_FIELD_POWER1 = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER2 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER3 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER4 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER5 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: DYNAMIC
UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_LEVEL = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_BYTES_0 = OBJECT_END + 0x001E, // Size: 1, Type: BYTES, Flags: PUBLIC
UNIT_VIRTUAL_ITEM_SLOT_DISPLAY = OBJECT_END + 0x001F, // Size: 3, Type: INT, Flags: PUBLIC
UNIT_VIRTUAL_ITEM_INFO = OBJECT_END + 0x0022, // Size: 6, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_FLAGS = OBJECT_END + 0x0028, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0029, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_AURA = OBJECT_END + 0x002A, // Size: 56, Type: INT, Flags: PUBLIC
UNIT_FIELD_AURAFLAGS = OBJECT_END + 0x0062, // Size: 14, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_AURALEVELS = OBJECT_END + 0x0070, // Size: 14, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_AURAAPPLICATIONS = OBJECT_END + 0x007E, // Size: 14, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_AURASTATE = OBJECT_END + 0x008C, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x008D, // Size: 2, Type: INT, Flags: PUBLIC
UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x008F, // Size: 1, Type: INT, Flags: PRIVATE
UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x0090, // Size: 1, Type: FLOAT, Flags: PUBLIC
UNIT_FIELD_COMBATREACH = OBJECT_END + 0x0091, // Size: 1, Type: FLOAT, Flags: PUBLIC
UNIT_FIELD_DISPLAYID = OBJECT_END + 0x0092, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x0094, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0095, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0096, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0097, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0098, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0099, // Size: 1, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_PETNUMBER = OBJECT_END + 0x009A, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x009C, // Size: 1, Type: INT, Flags: OWNER_ONLY
UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x009D, // Size: 1, Type: INT, Flags: OWNER_ONLY
UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x009E, // Size: 1, Type: INT, Flags: DYNAMIC
UNIT_CHANNEL_SPELL = OBJECT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_MOD_CAST_SPEED = OBJECT_END + 0x00A0, // Size: 1, Type: FLOAT, Flags: PUBLIC
UNIT_CREATED_BY_SPELL = OBJECT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_NPC_FLAGS = OBJECT_END + 0x00A2, // Size: 1, Type: INT, Flags: DYNAMIC
UNIT_NPC_EMOTESTATE = OBJECT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_TRAINING_POINTS = OBJECT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: OWNER_ONLY
UNIT_FIELD_STAT0 = OBJECT_END + 0x00A5, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT1 = OBJECT_END + 0x00A6, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT2 = OBJECT_END + 0x00A7, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT3 = OBJECT_END + 0x00A8, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT4 = OBJECT_END + 0x00A9, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x00AA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x00AB, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x00AC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x00AD, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x00AE, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x00AF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x00B0, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x00B1, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x00B2, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x00B3, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RESISTANCES = OBJECT_END + 0x00B4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x00BB, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x00C2, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_BASE_MANA = OBJECT_END + 0x00C9, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x00CA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_BYTES_2 = OBJECT_END + 0x00CB, // Size: 1, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x00CC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x00CD, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00CE, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x00CF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x00D0, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00D1, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x00D2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x00D3, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x00D4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x00DB, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x00E2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_PADDING = OBJECT_END + 0x00E3, // Size: 1, Type: INT, Flags: NONE
UNIT_END = OBJECT_END + 0x00E4,
UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0010, // Size: 1, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_HEALTH = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER1 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER2 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER3 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER4 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER5 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER6 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER7 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0021, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0028, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_LEVEL = OBJECT_END + 0x002F, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0031, // Size: 3, Type: INT, Flags: PUBLIC
UNIT_FIELD_FLAGS = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_AURASTATE = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0037, // Size: 2, Type: INT, Flags: PUBLIC
UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: PRIVATE
UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003A, // Size: 1, Type: FLOAT, Flags: PUBLIC
UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC
UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003C, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x003F, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0043, // Size: 1, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0044, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: OWNER_ONLY
UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER_ONLY
UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: DYNAMIC
UNIT_CHANNEL_SPELL = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC
UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC
UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3
UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC
UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC
UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY
UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC
UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE
UNIT_END = OBJECT_END + 0x008E,
PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
@@ -262,160 +287,184 @@ enum EUnitFields
PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x006C, // Size: 1, Type: BYTES, Flags: PRIVATE
PLAYER_QUEST_LOG_25_4 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_VISIBLE_ITEM_1_CREATOR = UNIT_END + 0x006E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x007E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0080, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x008E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0090, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x009E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A0, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00AE, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B0, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00BC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00BD, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00BE, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00C0, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00CC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00CD, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00CE, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00D0, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00DC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00DD, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00DE, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00E0, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00EC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00ED, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00EE, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x00F0, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x00FC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0100, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x010C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x010D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x010E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0110, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x011C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x011D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x011E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0120, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x012C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x012D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x012E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0130, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x013C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x013D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x013E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x0140, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x014C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x014D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x014E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x0150, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x015C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x015D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x015E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x0160, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x016C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x016D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x016E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0170, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x017C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x017D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x017E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x0180, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x018C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x0190, // Size: 12, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x019C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x019D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_CHOSEN_TITLE = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_FIELD_PAD_0 = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: NONE
PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01A0, // Size: 46, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01CE, // Size: 32, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x01EE, // Size: 56, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0226, // Size: 14, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0234, // Size: 24, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x024C, // Size: 64, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x028C, // Size: 36, Type: LONG, Flags: PRIVATE
PLAYER_FARSIGHT = UNIT_END + 0x02B0, // Size: 2, Type: LONG, Flags: PRIVATE
PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x02B2, // Size: 2, Type: LONG, Flags: PRIVATE
PLAYER_XP = UNIT_END + 0x02B4, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x02B5, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x02B6, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE
PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_TRACK_CREATURES = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_TRACK_RESOURCES = UNIT_END + 0x0439, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x043A, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x043B, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x043C, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_EXPERTISE = UNIT_END + 0x043D, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x043E, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x043F, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0440, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0441, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0442, // Size: 7, Type: FLOAT, Flags: PRIVATE
PLAYER_SHIELD_BLOCK = UNIT_END + 0x0449, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x044A, // Size: 128, Type: BYTES, Flags: PRIVATE
PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x04CA, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_COINAGE = UNIT_END + 0x04CB, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x04CC, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x04D3, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x04DA, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BYTES = UNIT_END + 0x04E4, // Size: 1, Type: BYTES, Flags: PRIVATE
PLAYER_AMMO_ID = UNIT_END + 0x04E5, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_SELF_RES_SPELL = UNIT_END + 0x04E6, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x04E8, // Size: 12, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x04F4, // Size: 12, Type: INT, Flags: PRIVATE
PLAYER_FIELD_KILLS = UNIT_END + 0x0500, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0501, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0502, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x0503, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BYTES2 = UNIT_END + 0x0504, // Size: 1, Type: BYTES, Flags: PRIVATE
PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0505, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0506, // Size: 24, Type: INT, Flags: PRIVATE
PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x051E, // Size: 18, Type: INT, Flags: PRIVATE
PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0530, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x0531, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_MANA_REGEN = UNIT_END + 0x0532, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT = UNIT_END + 0x0533, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0534, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0535, // Size: 25, Type: INT, Flags: PRIVATE
PLAYER_END = UNIT_END + 0x054E,
PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_1_SEED = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007F, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x0080, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0082, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_SEED = UNIT_END + 0x0090, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x0092, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0094, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x00A1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_SEED = UNIT_END + 0x00A2, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x00A4, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A6, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00B3, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_SEED = UNIT_END + 0x00B4, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00B5, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00B6, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B8, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00C5, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_SEED = UNIT_END + 0x00C6, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00C7, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00C8, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00CA, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00D7, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_SEED = UNIT_END + 0x00D8, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00D9, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00DA, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00DC, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00E9, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_SEED = UNIT_END + 0x00EA, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00EB, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00EC, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00EE, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00FB, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_SEED = UNIT_END + 0x00FC, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x0100, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x010D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_SEED = UNIT_END + 0x010E, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x010F, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x0110, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0112, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x011F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_SEED = UNIT_END + 0x0120, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x0121, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x0122, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0124, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x0131, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_SEED = UNIT_END + 0x0132, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x0133, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x0134, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0136, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x0143, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_SEED = UNIT_END + 0x0144, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x0145, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x0146, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0148, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x0155, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_SEED = UNIT_END + 0x0156, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x0157, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x0158, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x015A, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x0167, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_SEED = UNIT_END + 0x0168, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x0169, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x016A, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x016C, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x0179, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_SEED = UNIT_END + 0x017A, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x017B, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x017C, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x017E, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x018B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_SEED = UNIT_END + 0x018C, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0190, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x019D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_SEED = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x01A0, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x01A2, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x01AF, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_SEED = UNIT_END + 0x01B0, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x01B1, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x01B2, // Size: 2, Type: LONG, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x01B4, // Size: 13, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x01C1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_SEED = UNIT_END + 0x01C2, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x01C3, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_CHOSEN_TITLE = UNIT_END + 0x01C4, // Size: 1, Type: INT, Flags: PUBLIC
PLAYER_FIELD_PAD_0 = UNIT_END + 0x01C5, // Size: 1, Type: INT, Flags: NONE
PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01C6, // Size: 46, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01F4, // Size: 32, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x0214, // Size: 56, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x024C, // Size: 14, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x025A, // Size: 24, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x0272, // Size: 64, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x02B2, // Size: 36, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x02D6, // Size: 64, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_QUESTBAG_SLOT_1 = UNIT_END + 0x0316, // Size: 64, Type: LONG, Flags: PRIVATE
PLAYER_FARSIGHT = UNIT_END + 0x0356, // Size: 2, Type: LONG, Flags: PRIVATE
PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x0358, // Size: 2, Type: LONG, Flags: PRIVATE
PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x035A, // Size: 2, Type: LONG, Flags: PRIVATE
PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x035C, // Size: 2, Type: LONG, Flags: PRIVATE
PLAYER_XP = UNIT_END + 0x035E, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x035F, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x0360, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE
PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x04E0, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_TRACK_CREATURES = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_TRACK_RESOURCES = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x04E4, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x04E5, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x04E6, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_EXPERTISE = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x04E8, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x04E9, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x04EA, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x04EB, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x04EC, // Size: 7, Type: FLOAT, Flags: PRIVATE
PLAYER_SHIELD_BLOCK = UNIT_END + 0x04F3, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x04F4, // Size: 1, Type: FLOAT, Flags: PRIVATE
PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x04F5, // Size: 128, Type: BYTES, Flags: PRIVATE
PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x0575, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_COINAGE = UNIT_END + 0x0576, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x0577, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x057E, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x0585, // Size: 7, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x058C, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x058D, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x058E, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BYTES = UNIT_END + 0x058F, // Size: 1, Type: BYTES, Flags: PRIVATE
PLAYER_AMMO_ID = UNIT_END + 0x0590, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_SELF_RES_SPELL = UNIT_END + 0x0591, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x0592, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x0593, // Size: 12, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x059F, // Size: 12, Type: INT, Flags: PRIVATE
PLAYER_FIELD_KILLS = UNIT_END + 0x05AB, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE
PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x05AC, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x05AD, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x05AE, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_BYTES2 = UNIT_END + 0x05AF, // Size: 1, Type: BYTES, Flags: PRIVATE
PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x05B0, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x05B1, // Size: 25, Type: INT, Flags: PRIVATE
PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x05CA, // Size: 18, Type: INT, Flags: PRIVATE
PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x05DC, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x05DD, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x05DE, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x05DF, // Size: 25, Type: INT, Flags: PRIVATE
PLAYER_RUNE_REGEN_1 = UNIT_END + 0x05F8, // Size: 4, Type: FLOAT, Flags: PRIVATE
PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x05FC, // Size: 3, Type: INT, Flags: PRIVATE
PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x05FF, // Size: 8, Type: INT, Flags: PRIVATE
PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0607, // Size: 8, Type: INT, Flags: PRIVATE
PLAYER_GLYPHS_ENABLED = UNIT_END + 0x060F, // Size: 1, Type: INT, Flags: PRIVATE
PLAYER_END = UNIT_END + 0x0610,
};
enum EGameObjectFields
{
OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC
GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_STATE = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_POS_X = OBJECT_END + 0x0009, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_POS_Y = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_POS_Z = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_FACING = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_DYN_FLAGS = OBJECT_END + 0x000D, // Size: 1, Type: INT, Flags: DYNAMIC
GAMEOBJECT_FACTION = OBJECT_END + 0x000E, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_TYPE_ID = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC
GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC
GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0006, // Size: 4, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_POS_X = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_POS_Y = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_POS_Z = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_FACING = OBJECT_END + 0x000D, // Size: 1, Type: FLOAT, Flags: PUBLIC
GAMEOBJECT_DYNAMIC = OBJECT_END + 0x000E, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC
GAMEOBJECT_FACTION = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_LEVEL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_ARTKIT = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC
GAMEOBJECT_ANIMPROGRESS = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: DYNAMIC
GAMEOBJECT_PADDING = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: NONE
GAMEOBJECT_END = OBJECT_END + 0x0014,
GAMEOBJECT_BYTES_1 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC
GAMEOBJECT_END = OBJECT_END + 0x0012,
};
enum EDynamicObjectFields
+102
View File
@@ -0,0 +1,102 @@
/*
* 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 "Common.h"
#include "Log.h"
#include "WorldSession.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Vehicle.h"
#include "MapManager.h"
#include "SpellAuras.h"
#include "Unit.h"
#include "Util.h"
Vehicle::Vehicle() : Creature(), m_vehicleId(0)
{
m_isVehicle = true;
m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE);
}
Vehicle::~Vehicle()
{
if(m_uint32Values) // only for fully created Object
ObjectAccessor::Instance().RemoveObject(this);
}
void Vehicle::AddToWorld()
{
///- Register the vehicle for guid lookup
if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this);
Unit::AddToWorld();
}
void Vehicle::RemoveFromWorld()
{
///- Remove the vehicle from the accessor
if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this);
///- Don't call the function for Creature, normal mobs + totems go in a different storage
Unit::RemoveFromWorld();
}
void Vehicle::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState
{
Creature::setDeathState(s);
}
void Vehicle::Update(uint32 diff)
{
Creature::Update(diff);
}
bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team)
{
SetMapId(map->GetId());
SetInstanceId(map->GetInstanceId());
Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE);
if(!InitEntry(Entry, team))
return false;
m_defaultMovementType = IDLE_MOTION_TYPE;
AIM_Initialize();
SetVehicleId(vehicleId);
SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
CreatureInfo const *ci = GetCreatureInfo();
setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H);
SetMaxHealth(ci->maxhealth);
SelectLevel(ci);
SetHealth(GetMaxHealth());
return true;
}
void Vehicle::Dismiss()
{
SendObjectDeSpawnAnim(GetGUID());
CombatStop();
CleanupsBeforeDelete();
AddObjectToRemoveList();
}
+58
View File
@@ -0,0 +1,58 @@
/*
* 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 MANGOSSERVER_VEHICLE_H
#define MANGOSSERVER_VEHICLE_H
#include "ObjectDefines.h"
#include "Creature.h"
#include "Unit.h"
class Vehicle : public Creature
{
public:
explicit Vehicle();
virtual ~Vehicle();
void AddToWorld();
void RemoveFromWorld();
bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team);
void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState
void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update
uint32 GetVehicleId() { return m_vehicleId; }
void SetVehicleId(uint32 vehicleid) { m_vehicleId = vehicleid; }
void Dismiss();
protected:
uint32 m_vehicleId;
private:
void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called
{
assert(false);
}
void DeleteFromDB() // overwrited of Creature::DeleteFromDB - don't must be called
{
assert(false);
}
};
#endif
+67 -22
View File
@@ -232,7 +232,7 @@ World::AddSession_ (WorldSession* s)
uint32 Sessions = GetActiveAndQueuedSessionCount ();
uint32 pLimit = GetPlayerAmountLimit ();
uint32 QueueSize = GetQueueSize (); //number of players in the queue
uint32 QueueSize = GetQueueSize (); //number of players in the queue
//so we don't count the user trying to
//login as a session and queue the socket that we are using
@@ -249,10 +249,10 @@ World::AddSession_ (WorldSession* s)
WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
packet << uint8 (AUTH_OK);
packet << uint32 (0); // unknown random value...
packet << uint8 (0);
packet << uint32 (0);
packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
packet << uint32 (0); // BillingTimeRemaining
packet << uint8 (0); // BillingPlanFlags
packet << uint32 (0); // BillingTimeRested
packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
s->SendPacket (&packet);
UpdateMaxSessionCounters ();
@@ -260,7 +260,7 @@ World::AddSession_ (WorldSession* s)
// Updates the population
if (pLimit > 0)
{
float popu = GetActiveSessionCount (); //updated number of users on the server
float popu = GetActiveSessionCount (); //updated number of users on the server
popu /= pLimit;
popu *= 2;
loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
@@ -287,10 +287,10 @@ void World::AddQueuedPlayer(WorldSession* sess)
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
packet << uint8 (AUTH_WAIT_QUEUE);
packet << uint32 (0); // unknown random value...
packet << uint8 (0);
packet << uint32 (0);
packet << uint8 (sess->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
packet << uint32 (0); // BillingTimeRemaining
packet << uint8 (0); // BillingPlanFlags
packet << uint32 (0); // BillingTimeRested
packet << uint8 (sess->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account
packet << uint32(GetQueuePos (sess));
sess->SendPacket (&packet);
@@ -408,24 +408,30 @@ void World::LoadConfigSettings(bool reload)
rate_values[RATE_HEALTH] = sConfig.GetFloatDefault("Rate.Health", 1);
if(rate_values[RATE_HEALTH] < 0)
{
sLog.outError("Rate.Health (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_HEALTH]);
sLog.outError("Rate.Health (%f) must be > 0. Using 1 instead.",rate_values[RATE_HEALTH]);
rate_values[RATE_HEALTH] = 1;
}
rate_values[RATE_POWER_MANA] = sConfig.GetFloatDefault("Rate.Mana", 1);
if(rate_values[RATE_POWER_MANA] < 0)
{
sLog.outError("Rate.Mana (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]);
sLog.outError("Rate.Mana (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]);
rate_values[RATE_POWER_MANA] = 1;
}
rate_values[RATE_POWER_RAGE_INCOME] = sConfig.GetFloatDefault("Rate.Rage.Income", 1);
rate_values[RATE_POWER_RAGE_LOSS] = sConfig.GetFloatDefault("Rate.Rage.Loss", 1);
if(rate_values[RATE_POWER_RAGE_LOSS] < 0)
{
sLog.outError("Rate.Rage.Loss (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]);
sLog.outError("Rate.Rage.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]);
rate_values[RATE_POWER_RAGE_LOSS] = 1;
}
rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfig.GetFloatDefault("Rate.RunicPower.Income", 1);
rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfig.GetFloatDefault("Rate.RunicPower.Loss", 1);
if(rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0)
{
sLog.outError("Rate.RunicPower.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RUNICPOWER_LOSS]);
rate_values[RATE_POWER_RUNICPOWER_LOSS] = 1;
}
rate_values[RATE_POWER_FOCUS] = sConfig.GetFloatDefault("Rate.Focus", 1.0f);
rate_values[RATE_LOYALTY] = sConfig.GetFloatDefault("Rate.Loyalty", 1.0f);
rate_values[RATE_SKILL_DISCOVERY] = sConfig.GetFloatDefault("Rate.Skill.Discovery", 1.0f);
rate_values[RATE_DROP_ITEM_POOR] = sConfig.GetFloatDefault("Rate.Drop.Item.Poor", 1.0f);
rate_values[RATE_DROP_ITEM_NORMAL] = sConfig.GetFloatDefault("Rate.Drop.Item.Normal", 1.0f);
@@ -617,6 +623,15 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_configs[CONFIG_CHARACTERS_PER_REALM];
}
m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("HeroicCharactersPerRealm", 1);
if(m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] < 0 || m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10)
{
sLog.outError("HeroicCharactersPerRealm (%i) must be in range 0..10. Set to 1.",m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]);
m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1;
}
m_configs[CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING] = sConfig.GetIntDefault("MinLevelForHeroicCharacterCreating", 55);
m_configs[CONFIG_SKIP_CINEMATICS] = sConfig.GetIntDefault("SkipCinematics", 0);
if(m_configs[CONFIG_SKIP_CINEMATICS] < 0 || m_configs[CONFIG_SKIP_CINEMATICS] > 2)
{
@@ -651,6 +666,20 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_START_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL];
}
m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfig.GetIntDefault("StartHeroicPlayerLevel", 55);
if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1)
{
sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 55.",
m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]);
m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55;
}
else if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > m_configs[CONFIG_MAX_PLAYER_LEVEL])
{
sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.",
m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]);
m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL];
}
m_configs[CONFIG_START_PLAYER_MONEY] = sConfig.GetIntDefault("StartPlayerMoney", 0);
if(m_configs[CONFIG_START_PLAYER_MONEY] < 0)
{
@@ -723,17 +752,17 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig.GetIntDefault("MinPetitionSigns", 9);
if(m_configs[CONFIG_MIN_PETITION_SIGNS] > 9)
{
sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.",m_configs[CONFIG_MIN_PETITION_SIGNS]);
sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_configs[CONFIG_MIN_PETITION_SIGNS]);
m_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
}
m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2);
m_configs[CONFIG_GM_ACCEPT_TICKETS] = sConfig.GetIntDefault("GM.AcceptTickets",2);
m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat",2);
m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo",2);
m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState", 2);
m_configs[CONFIG_GM_ACCEPT_TICKETS] = sConfig.GetIntDefault("GM.AcceptTickets", 2);
m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat", 2);
m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo", 2);
m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList",false);
m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false);
m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList", false);
m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList", false);
m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false);
m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1);
@@ -774,6 +803,7 @@ void World::LoadConfigSettings(bool reload)
m_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfig.GetIntDefault("SkillChance.SkinningSteps",75);
m_configs[CONFIG_SKILL_PROSPECTING] = sConfig.GetBoolDefault("SkillChance.Prospecting",false);
m_configs[CONFIG_SKILL_MILLING] = sConfig.GetBoolDefault("SkillChance.Milling",false);
m_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfig.GetIntDefault("SkillGain.Crafting", 1);
if(m_configs[CONFIG_SKILL_GAIN_CRAFTING] < 0)
@@ -1059,12 +1089,18 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading InstanceTemplate" );
objmgr.LoadInstanceTemplate();
sLog.outString( "Loading AchievementCriteriaList..." );
objmgr.LoadAchievementCriteriaList();
sLog.outString( "Loading completed achievements..." );
objmgr.LoadCompletedAchievements();
sLog.outString( "Loading SkillLineAbilityMultiMap Data..." );
spellmgr.LoadSkillLineAbilityMap();
///- Clean up and pack instances
sLog.outString( "Cleaning up instances..." );
sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
sLog.outString( "Packing instances..." );
sInstanceSaveManager.PackInstances();
@@ -1190,6 +1226,9 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading spell pet auras..." );
spellmgr.LoadSpellPetAuras();
sLog.outString( "Loading pet levelup spells..." );
spellmgr.LoadPetLevelupSpellMap();
sLog.outString( "Loading spell extra attributes...(TODO)" );
spellmgr.LoadSpellCustomAttr();
@@ -1669,6 +1708,9 @@ void World::ScriptsProcess()
case HIGHGUID_PET:
source = HashMapHolder<Pet>::Find(step.sourceGUID);
break;
case HIGHGUID_VEHICLE:
source = HashMapHolder<Vehicle>::Find(step.sourceGUID);
break;
case HIGHGUID_PLAYER:
source = HashMapHolder<Player>::Find(step.sourceGUID);
break;
@@ -1698,6 +1740,9 @@ void World::ScriptsProcess()
case HIGHGUID_PET:
target = HashMapHolder<Pet>::Find(step.targetGUID);
break;
case HIGHGUID_VEHICLE:
target = HashMapHolder<Vehicle>::Find(step.targetGUID);
break;
case HIGHGUID_PLAYER: // empty GUID case also
target = HashMapHolder<Player>::Find(step.targetGUID);
break;
+6 -1
View File
@@ -102,9 +102,12 @@ enum WorldConfigs
CONFIG_CHARACTERS_CREATING_DISABLED,
CONFIG_CHARACTERS_PER_ACCOUNT,
CONFIG_CHARACTERS_PER_REALM,
CONFIG_HEROIC_CHARACTERS_PER_REALM,
CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING,
CONFIG_SKIP_CINEMATICS,
CONFIG_MAX_PLAYER_LEVEL,
CONFIG_START_PLAYER_LEVEL,
CONFIG_START_HEROIC_PLAYER_LEVEL,
CONFIG_START_PLAYER_MONEY,
CONFIG_MAX_HONOR_POINTS,
CONFIG_START_HONOR_POINTS,
@@ -183,6 +186,7 @@ enum WorldConfigs
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS,
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
CONFIG_SKILL_MILLING,
CONFIG_MAX_WHO,
CONFIG_BG_START_MUSIC,
@@ -207,6 +211,8 @@ enum Rates
RATE_POWER_MANA,
RATE_POWER_RAGE_INCOME,
RATE_POWER_RAGE_LOSS,
RATE_POWER_RUNICPOWER_INCOME,
RATE_POWER_RUNICPOWER_LOSS,
RATE_POWER_FOCUS,
RATE_SKILL_DISCOVERY,
RATE_DROP_ITEM_POOR,
@@ -250,7 +256,6 @@ enum Rates
RATE_MINING_AMOUNT,
RATE_MINING_NEXT,
RATE_TALENT,
RATE_LOYALTY,
RATE_CORPSE_DECAY_LOOTED,
RATE_INSTANCE_RESET_TIME,
RATE_TARGET_POS_RECALCULATION_RANGE,
+87
View File
@@ -525,3 +525,90 @@ void WorldSession::SendAuthWaitQue(uint32 position)
SendPacket(&packet);
}
}
void WorldSession::LoadAccountData()
{
for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i)
{
AccountData data;
m_accountData[i] = data;
}
QueryResult *result = CharacterDatabase.PQuery("SELECT type, time, data FROM account_data WHERE account='%u'", GetAccountId());
if(!result)
return;
do
{
Field *fields = result->Fetch();
uint32 type = fields[0].GetUInt32();
if(type < NUM_ACCOUNT_DATA_TYPES)
{
m_accountData[type].Time = fields[1].GetUInt32();
m_accountData[type].Data = fields[2].GetCppString();
}
} while (result->NextRow());
delete result;
}
void WorldSession::SetAccountData(uint32 type, time_t time_, std::string data)
{
m_accountData[type].Time = time_;
m_accountData[type].Data = data;
uint32 acc = GetAccountId();
CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type);
CharacterDatabase.escape_string(data);
CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str());
}
void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi)
{
CHECK_PACKET_SIZE(data, data.rpos()+4+2+4+4+4+4+4);
data >> mi->flags;
data >> mi->unk1;
data >> mi->time;
data >> mi->x;
data >> mi->y;
data >> mi->z;
data >> mi->o;
if(mi->flags & MOVEMENTFLAG_ONTRANSPORT)
{
CHECK_PACKET_SIZE(data, data.rpos()+8+4+4+4+4+4+1);
data >> mi->t_guid;
data >> mi->t_x;
data >> mi->t_y;
data >> mi->t_z;
data >> mi->t_o;
data >> mi->t_time;
data >> mi->t_seat;
}
if((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (mi->unk1 & 0x20))
{
CHECK_PACKET_SIZE(data, data.rpos()+4);
data >> mi->s_pitch;
}
CHECK_PACKET_SIZE(data, data.rpos()+4);
data >> mi->fallTime;
if(mi->flags & MOVEMENTFLAG_JUMPING)
{
CHECK_PACKET_SIZE(data, data.rpos()+4+4+4+4);
data >> mi->j_unk;
data >> mi->j_sinAngle;
data >> mi->j_cosAngle;
data >> mi->j_xyspeed;
}
if(mi->flags & MOVEMENTFLAG_SPLINE)
{
CHECK_PACKET_SIZE(data, data.rpos()+4);
data >> mi->u_unk1;
}
}
+47 -4
View File
@@ -47,6 +47,16 @@ class CharacterHandler;
#define CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S));
#define NUM_ACCOUNT_DATA_TYPES 8
struct AccountData
{
AccountData() : Time(NULL), Data("") {}
time_t Time;
std::string Data;
};
enum PartyOperation
{
PARTY_OP_INVITE = 0,
@@ -81,6 +91,8 @@ class TRINITY_DLL_SPEC WorldSession
void SizeError(WorldPacket const& packet, uint32 size) const;
void ReadMovementInfo(WorldPacket &data, MovementInfo *mi);
void SendPacket(WorldPacket const* packet);
void SendNotification(const char *format,...) ATTR_PRINTF(2,3);
void SendNotification(int32 string_id,...);
@@ -153,6 +165,11 @@ class TRINITY_DLL_SPEC WorldSession
//pet
void SendPetNameQuery(uint64 guid, uint32 petnumber);
// Account Data
AccountData *GetAccountData(uint32 type) { return &m_accountData[type]; }
void SetAccountData(uint32 type, time_t time_, std::string data);
void LoadAccountData();
//mail
//used with item_page table
bool SendItemInfo( uint32 itemid, WorldPacket data );
@@ -324,7 +341,8 @@ class TRINITY_DLL_SPEC WorldSession
void HandleMovementOpcodes(WorldPacket& recvPacket);
void HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags);
void HandleSetActiveMoverOpcode(WorldPacket &recv_data);
void HandleNotActiveMoverOpcode(WorldPacket &recv_data);
void HandleMoveNotActiveMover(WorldPacket &recv_data);
void HandleDismissControlledVehicle(WorldPacket &recv_data);
void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data);
void HandleRequestRaidInfoOpcode( WorldPacket & recv_data );
@@ -385,7 +403,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleGuildSaveEmblemOpcode(WorldPacket& recvPacket);
void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket);
void HandleTaxiQueryAvailableNodesOpcode(WorldPacket& recvPacket);
void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket);
void HandleActivateTaxiOpcode(WorldPacket& recvPacket);
void HandleActivateTaxiFarOpcode(WorldPacket& recvPacket);
void HandleTaxiNextDestinationOpcode(WorldPacket& recvPacket);
@@ -429,6 +447,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandleAuctionRemoveItem( WorldPacket & recv_data );
void HandleAuctionListOwnerItems( WorldPacket & recv_data );
void HandleAuctionPlaceBid( WorldPacket & recv_data );
void HandleAuctionListPendingSales( WorldPacket & recv_data );
void HandleGetMail( WorldPacket & recv_data );
void HandleSendMail( WorldPacket & recv_data );
@@ -543,6 +562,7 @@ class TRINITY_DLL_SPEC WorldSession
void HandlePetUnlearnOpcode( WorldPacket& recvPacket );
void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket );
void HandlePetCastSpellOpcode( WorldPacket& recvPacket );
void HandlePetLearnTalent( WorldPacket& recvPacket );
void HandleSetActionBar(WorldPacket& recv_data);
@@ -579,10 +599,9 @@ class TRINITY_DLL_SPEC WorldSession
void HandleLfmSetNoneOpcode(WorldPacket& recv_data);
void HandleLfmSetOpcode(WorldPacket& recv_data);
void HandleLfgSetCommentOpcode(WorldPacket& recv_data);
void HandleNewUnknownOpcode(WorldPacket& recv_data);
void HandleChooseTitleOpcode(WorldPacket& recv_data);
void HandleRealmStateRequestOpcode(WorldPacket& recv_data);
void HandleAllowMoveAckOpcode(WorldPacket& recv_data);
void HandleTimeSyncResp(WorldPacket& recv_data);
void HandleWhoisOpcode(WorldPacket& recv_data);
void HandleResetInstancesOpcode(WorldPacket& recv_data);
@@ -628,6 +647,29 @@ class TRINITY_DLL_SPEC WorldSession
void HandleGuildBankBuyTab(WorldPacket& recv_data);
void HandleGuildBankTabText(WorldPacket& recv_data);
void HandleGuildBankSetTabText(WorldPacket& recv_data);
// Calendar
void HandleCalendarGetCalendar(WorldPacket& recv_data);
void HandleCalendarGetEvent(WorldPacket& recv_data);
void HandleCalendarGuildFilter(WorldPacket& recv_data);
void HandleCalendarArenaTeam(WorldPacket& recv_data);
void HandleCalendarAddEvent(WorldPacket& recv_data);
void HandleCalendarUpdateEvent(WorldPacket& recv_data);
void HandleCalendarRemoveEvent(WorldPacket& recv_data);
void HandleCalendarCopyEvent(WorldPacket& recv_data);
void HandleCalendarEventInvite(WorldPacket& recv_data);
void HandleCalendarEventRsvp(WorldPacket& recv_data);
void HandleCalendarEventRemoveInvite(WorldPacket& recv_data);
void HandleCalendarEventStatus(WorldPacket& recv_data);
void HandleCalendarEventModeratorStatus(WorldPacket& recv_data);
void HandleCalendarComplain(WorldPacket& recv_data);
void HandleCalendarGetNumPending(WorldPacket& recv_data);
void HandleSpellClick(WorldPacket& recv_data);
void HandleAlterAppearance(WorldPacket& recv_data);
void HandleRemoveGlyph(WorldPacket& recv_data);
void HandleCharCustomize(WorldPacket& recv_data);
void HandleInspectAchievements(WorldPacket& recv_data);
private:
// private trade methods
void moveItems(Item* myItems[], Item* hisItems[]);
@@ -650,6 +692,7 @@ class TRINITY_DLL_SPEC WorldSession
LocaleConstant m_sessionDbcLocale;
int m_sessionDbLocaleIndex;
uint32 m_latency;
AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> _recvQueue;
};
+50 -13
View File
@@ -54,8 +54,48 @@
struct ServerPktHeader
{
uint16 size;
uint16 cmd;
/**
* size is the length of the payload _plus_ the length of the opcode
*/
ServerPktHeader(uint32 size, uint16 cmd) : size(size)
{
uint8 headerIndex=0;
if(isLargePacket())
{
sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd);
header= new uint8[5];
header[headerIndex++] = 0x80|(0xFF &(size>>16));
}
else
{
header= new uint8[4];
}
header[headerIndex++] = 0xFF &(size>>8);
header[headerIndex++] = 0xFF &size;
header[headerIndex++] = 0xFF & cmd;
header[headerIndex++] = 0xFF & (cmd>>8);
}
~ServerPktHeader()
{
delete[] header;
}
uint8 getHeaderLength()
{
// cmd = 2 bytes, size= 2||3bytes
return 2+(isLargePacket()?3:2);
}
bool isLargePacket()
{
return size > 0x7FFF;
}
const uint32 size;
uint8 *header;
};
struct ClientPktHeader
@@ -639,7 +679,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
// NOTE: ATM the socket is singlethread, have this in mind ...
uint8 digest[20];
uint32 clientSeed;
uint32 unk2;
uint32 unk2, unk3;
uint32 BuiltNumberClient;
uint32 id, security;
//uint8 expansion = 0;
@@ -661,6 +701,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
recvPacket >> BuiltNumberClient; // for now no use
recvPacket >> unk2;
recvPacket >> account;
recvPacket >> unk3;
if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20))
{
@@ -880,6 +921,8 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
m_Crypt.SetKey (&K);
m_Crypt.Init ();
m_Session->LoadAccountData();
// In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec
ACE_OS::sleep (ACE_Time_Value (0, 10000));
@@ -963,23 +1006,17 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket)
int WorldSocket::iSendPacket (const WorldPacket& pct)
{
if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader))
ServerPktHeader header(pct.size()+2, pct.GetOpcode());
if (m_OutBuffer->space () < pct.size () + header.getHeaderLength())
{
errno = ENOBUFS;
return -1;
}
ServerPktHeader header;
header.cmd = pct.GetOpcode ();
EndianConvert(header.cmd);
m_Crypt.EncryptSend ( header.header, header.getHeaderLength());
header.size = (uint16) pct.size () + 2;
EndianConvertReverse(header.size);
m_Crypt.EncryptSend ((uint8*) & header, sizeof (header));
if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1)
if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1)
ACE_ASSERT (false);
if (!pct.empty ())
+51
View File
@@ -63,6 +63,7 @@ bool ChatHandler::HandleDebugSpellFailCommand(const char* args)
uint8 failnum = (uint8)atoi(px);
WorldPacket data(SMSG_CAST_FAILED, 5);
data << uint8(0);
data << uint32(133);
data << uint8(failnum);
m_session->SendPacket(&data);
@@ -568,5 +569,55 @@ bool ChatHandler::HandleDebugHostilRefList(const char * /*args*/)
ref = ref->next();
}
SendSysMessage("End of hostil reference list.");
return true;
}
bool ChatHandler::HandleSpawnVehicle(const char* args)
{
if(!args)
return false;
char* e = strtok((char*)args, " ");
char* i = strtok(NULL, " ");
if (!e || !i)
return false;
uint32 entry = (uint32)atoi(e);
uint32 id = (uint32)atoi(i);
CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry);
if(!ci)
return false;
VehicleEntry const *ve = sVehicleStore.LookupEntry(id);
if(!ve)
return false;
Vehicle *v = new Vehicle;
Map *map = m_session->GetPlayer()->GetMap();
if(!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, entry, id, m_session->GetPlayer()->GetTeam()))
{
delete v;
return false;
}
float px, py, pz;
m_session->GetPlayer()->GetClosePoint(px, py, pz, m_session->GetPlayer()->GetObjectSize());
v->Relocate(px, py, pz, m_session->GetPlayer()->GetOrientation());
if(!v->IsPositionValid())
{
sLog.outError("ERROR: Vehicle (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
v->GetGUIDLow(), v->GetEntry(), v->GetPositionX(), v->GetPositionY());
delete v;
return false;
}
map->Add((Creature*)v);
return true;
}