Merge commit 'origin/master' into 320

Conflicts:
	src/game/DBCStructure.h
	src/game/DBCfmt.h
	src/game/MiscHandler.cpp
	src/game/ObjectMgr.cpp
This commit is contained in:
tomrus88 2009-09-04 21:16:59 +04:00
commit 4a8431f581
51 changed files with 739 additions and 612 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_8416_01_mangos_spell_learn_spell` bit(1) default NULL `required_8462_01_mangos_creature_ai_texts` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -1043,7 +1043,7 @@ CREATE TABLE `creature_ai_texts` (
`sound` mediumint(8) unsigned NOT NULL DEFAULT '0', `sound` mediumint(8) unsigned NOT NULL DEFAULT '0',
`type` tinyint(3) unsigned NOT NULL DEFAULT '0', `type` tinyint(3) unsigned NOT NULL DEFAULT '0',
`language` tinyint(3) unsigned NOT NULL DEFAULT '0', `language` tinyint(3) unsigned NOT NULL DEFAULT '0',
`emote` tinyint(3) unsigned NOT NULL DEFAULT '0', `emote` smallint(5) unsigned NOT NULL DEFAULT '0',
`comment` text, `comment` text,
PRIMARY KEY (`entry`) PRIMARY KEY (`entry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts';
@ -2720,6 +2720,7 @@ INSERT INTO `mangos_string` VALUES
(345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(347,'TaxiNode ID %u not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (347,'TaxiNode ID %u not found!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(348,'Game Object (Entry: %u) have invalid data and can\'t be spawned',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -2841,7 +2842,7 @@ INSERT INTO `mangos_string` VALUES
(519,'|cffffffff|Htele:%s|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (519,'|cffffffff|Htele:%s|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(520,'%d - |cffffffff|Hspell:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (520,'%d - |cffffffff|Hspell:%d|h[%s]|h|r ',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(521,'%d - |cffffffff|Hskill:%d|h[%s %s]|h|r %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (521,'%d - |cffffffff|Hskill:%d|h[%s %s]|h|r %s %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(522,'Game Object (GUID: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (522,'Game Object (Entry: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(523,'>> Game Object %s (GUID: %u) at %f %f %f. Orientation %f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (523,'>> Game Object %s (GUID: %u) at %f %f %f. Orientation %f.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(524,'Selected object:\n|cffffffff|Hgameobject:%d|h[%s]|h|r GUID: %u ID: %u\nX: %f Y: %f Z: %f MapId: %u\nOrientation: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (524,'Selected object:\n|cffffffff|Hgameobject:%d|h[%s]|h|r GUID: %u ID: %u\nX: %f Y: %f Z: %f MapId: %u\nOrientation: %f',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(525,'>> Add Game Object \'%i\' (%s) (GUID: %i) added at \'%f %f %f\'.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (525,'>> Add Game Object \'%i\' (%s) (GUID: %i) added at \'%f %f %f\'.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
@ -17840,6 +17841,7 @@ INSERT INTO `spell_proc_event` VALUES
(53569, 0x00000000, 10, 0x00200000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53569, 0x00000000, 10, 0x00200000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53576, 0x00000000, 10, 0x00200000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53576, 0x00000000, 10, 0x00200000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53601, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 6), (53601, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 6),
(53646, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(53671, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (53671, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(53673, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (53673, 0x00000000, 10, 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(54149, 0x00000000, 10, 0x00200000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (54149, 0x00000000, 10, 0x00200000, 0x00010000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_8416_01_mangos_spell_learn_spell required_8444_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN(348,522);
INSERT INTO mangos_string VALUES
(348,'Game Object (Entry: %u) have invalid data and can\'t be spawned',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL),
(522,'Game Object (Entry: %u) not found',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_8444_01_mangos_mangos_string required_8451_01_mangos_spell_proc_event bit;
DELETE FROM spell_proc_event WHERE entry = 53646;
INSERT INTO spell_proc_event VALUES
(53646, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,3 @@
ALTER TABLE db_version CHANGE COLUMN required_8451_01_mangos_spell_proc_event required_8462_01_mangos_creature_ai_texts bit;
ALTER TABLE creature_ai_texts CHANGE emote emote smallint(5) unsigned NOT NULL default '0';

View file

@ -96,6 +96,9 @@ pkgdata_DATA = \
8412_01_mangos_mangos_string.sql \ 8412_01_mangos_mangos_string.sql \
8416_01_mangos_spell_learn_spell.sql \ 8416_01_mangos_spell_learn_spell.sql \
8433_01_characters_character_account_data.sql \ 8433_01_characters_character_account_data.sql \
8444_01_mangos_mangos_string.sql \
8451_01_mangos_spell_proc_event.sql \
8462_01_mangos_creature_ai_texts.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -172,4 +175,7 @@ EXTRA_DIST = \
8412_01_mangos_mangos_string.sql \ 8412_01_mangos_mangos_string.sql \
8416_01_mangos_spell_learn_spell.sql \ 8416_01_mangos_spell_learn_spell.sql \
8433_01_characters_character_account_data.sql \ 8433_01_characters_character_account_data.sql \
8444_01_mangos_mangos_string.sql \
8451_01_mangos_spell_proc_event.sql \
8462_01_mangos_creature_ai_texts.sql \
README README

View file

@ -22,6 +22,7 @@
#include "Player.h" #include "Player.h"
#include "Policies/SingletonImp.h" #include "Policies/SingletonImp.h"
#include "Util.h" #include "Util.h"
#include "Auth/Sha1.h"
extern DatabaseType loginDatabase; extern DatabaseType loginDatabase;
@ -41,17 +42,12 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
normalizeString(username); normalizeString(username);
normalizeString(password); normalizeString(password);
loginDatabase.escape_string(username); if(GetId(username))
loginDatabase.escape_string(password);
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str());
if(result)
{ {
delete result;
return AOR_NAME_ALREDY_EXIST; // username does already exist return AOR_NAME_ALREDY_EXIST; // username does already exist
} }
if(!loginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1("_CONCAT3_("'%s'","':'","'%s'")"),NOW())", username.c_str(), username.c_str(), password.c_str())) if(!loginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s','%s',NOW())", username.c_str(), CalculateShaPassHash(username, password).c_str()))
return AOR_DB_INTERNAL_ERROR; // unexpected error return AOR_DB_INTERNAL_ERROR; // unexpected error
loginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL"); loginDatabase.Execute("INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist,account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL");
@ -121,9 +117,11 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
normalizeString(new_uname); normalizeString(new_uname);
normalizeString(new_passwd); normalizeString(new_passwd);
loginDatabase.escape_string(new_uname); std::string safe_new_uname = new_uname;
loginDatabase.escape_string(new_passwd); loginDatabase.escape_string(safe_new_uname);
if(!loginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1("_CONCAT3_("'%s'","':'","'%s'")") WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid))
if(!loginDatabase.PExecute("UPDATE account SET v='0',s='0',username='%s',sha_pass_hash='%s' WHERE id='%d'", safe_new_uname.c_str(),
CalculateShaPassHash(new_uname, new_passwd).c_str(), accid))
return AOR_DB_INTERNAL_ERROR; // unexpected error return AOR_DB_INTERNAL_ERROR; // unexpected error
return AOR_OK; return AOR_OK;
@ -131,18 +129,19 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd) AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
{ {
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); std::string username;
if(!result)
if(!GetName(accid, username))
return AOR_NAME_NOT_EXIST; // account doesn't exist return AOR_NAME_NOT_EXIST; // account doesn't exist
delete result;
if (utf8length(new_passwd) > MAX_ACCOUNT_STR) if (utf8length(new_passwd) > MAX_ACCOUNT_STR)
return AOR_PASS_TOO_LONG; return AOR_PASS_TOO_LONG;
normalizeString(new_passwd); normalizeString(new_passwd);
loginDatabase.escape_string(new_passwd); // also reset s and v to force update at next realmd login
if(!loginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")") WHERE id='%d'", new_passwd.c_str(), accid)) if(!loginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash='%s' WHERE id='%d'",
CalculateShaPassHash(username, new_passwd).c_str(), accid))
return AOR_DB_INTERNAL_ERROR; // unexpected error return AOR_DB_INTERNAL_ERROR; // unexpected error
return AOR_OK; return AOR_OK;
@ -190,10 +189,13 @@ bool AccountMgr::GetName(uint32 acc_id, std::string &name)
bool AccountMgr::CheckPassword(uint32 accid, std::string passwd) bool AccountMgr::CheckPassword(uint32 accid, std::string passwd)
{ {
normalizeString(passwd); std::string username;
loginDatabase.escape_string(passwd); if(!GetName(accid, username))
return false;
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")")", accid, passwd.c_str()); normalizeString(passwd);
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash='%s'", accid, CalculateShaPassHash(username, passwd).c_str());
if (result) if (result)
{ {
delete result; delete result;
@ -215,3 +217,19 @@ bool AccountMgr::normalizeString(std::string& utf8str)
return WStrToUtf8(wstr_buf,wstr_len,utf8str); return WStrToUtf8(wstr_buf,wstr_len,utf8str);
} }
std::string AccountMgr::CalculateShaPassHash(std::string& name, std::string& password)
{
Sha1Hash sha;
sha.Initialize();
sha.UpdateData(name);
sha.UpdateData(":");
sha.UpdateData(password);
sha.Finalize();
std::string encoded;
hexEncodeByteArray(sha.GetDigest(), sha.GetLength(), encoded);
return encoded;
}

View file

@ -50,6 +50,7 @@ class AccountMgr
uint32 GetId(std::string username); uint32 GetId(std::string username);
uint32 GetSecurity(uint32 acc_id); uint32 GetSecurity(uint32 acc_id);
bool GetName(uint32 acc_id, std::string &name); bool GetName(uint32 acc_id, std::string &name);
std::string CalculateShaPassHash(std::string& name, std::string& password);
static bool normalizeString(std::string& utf8str); static bool normalizeString(std::string& utf8str);
}; };

View file

@ -1017,10 +1017,22 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
{
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
continue; continue;
// those requirements couldn't be found in the dbc
AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
if(!data)
continue;
if(!data->Meets(GetPlayer(),unit))
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break; break;
}
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
if(miscvalue1 && miscvalue1!=achievementCriteria->learn_spell.spellID) if(miscvalue1 && miscvalue1!=achievementCriteria->learn_spell.spellID)
continue; continue;
@ -1279,25 +1291,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS: case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetVisibleFactionCount()); SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetVisibleFactionCount());
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
{
if (!miscvalue1)
continue;
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
continue;
// those requirements couldn't be found in the dbc
AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria);
if(!data)
continue;
if(!data->Meets(GetPlayer(),unit))
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
{ {
if (miscvalue1 && miscvalue1 != achievementCriteria->learn_skill_line.skillLine) if (miscvalue1 && miscvalue1 != achievementCriteria->learn_skill_line.skillLine)

View file

@ -119,9 +119,6 @@ class CharacterHandler
void WorldSession::HandleCharEnum(QueryResult * result) void WorldSession::HandleCharEnum(QueryResult * result)
{ {
// keys can be non cleared if player open realm list and close it by 'cancel'
loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId());
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
uint8 num = 0; uint8 num = 0;

View file

@ -1480,7 +1480,7 @@ valid examples:
bool foundName = false; bool foundName = false;
for(uint8 i=0; i<MAX_LOCALE; ++i) for(uint8 i=0; i<MAX_LOCALE; ++i)
{ {
if (*linkedAchievement->name[i], strcmp(linkedAchievement->name[i], buffer) == 0) if (*linkedAchievement->name[i] && strcmp(linkedAchievement->name[i], buffer) == 0)
{ {
foundName = true; foundName = true;
break; break;

View file

@ -1320,7 +1320,7 @@ struct SpellEntry
uint32 AttributesEx3; // 7 m_attributesExC uint32 AttributesEx3; // 7 m_attributesExC
uint32 AttributesEx4; // 8 m_attributesExD uint32 AttributesEx4; // 8 m_attributesExD
uint32 AttributesEx5; // 9 m_attributesExE uint32 AttributesEx5; // 9 m_attributesExE
//uint32 AttributesEx6; // 10 m_attributesExF not used uint32 AttributesEx6; // 10 m_attributesExF
// uint32 unk_320_1; // 11 3.2.0 (0x20 - totems, 0x4 - paladin auras, etc...) // uint32 unk_320_1; // 11 3.2.0 (0x20 - totems, 0x4 - paladin auras, etc...)
uint32 Stances; // 12 m_shapeshiftMask uint32 Stances; // 12 m_shapeshiftMask
// uint32 unk_320_2; // 13 3.2.0 // uint32 unk_320_2; // 13 3.2.0

View file

@ -83,7 +83,7 @@ const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const char SpellCastTimefmt[]="nixx"; const char SpellCastTimefmt[]="nixx";
const char SpellDurationfmt[]="niii"; const char SpellDurationfmt[]="niii";
const char SpellEntryfmt[]="niiiiiiiiixxixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxxxxx"; const char SpellEntryfmt[]="niiiiiiiiiixixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxxxxx";
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixxx"; const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixxx";
const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";

View file

@ -54,7 +54,7 @@ class MANGOS_DLL_DECL DestinationHolder
uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true); uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true);
void GetLocationNow(const Map * map, float &x, float &y, float &z, bool is3D = false) const; void GetLocationNow(const Map * map, float &x, float &y, float &z, bool is3D = false) const;
void GetLocationNowNoMicroMovement(float &x, float &y, float &z) const; // For use without micro movement void GetLocationNowNoMicroMovement(float &x, float &y, float &z) const; // For use without micro movement
float GetDistance2dFromDestSq(const WorldObject &obj) const; float GetDistance3dFromDestSq(const WorldObject &obj) const;
private: private:
void _findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y); void _findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y);

View file

@ -93,19 +93,19 @@ template<typename TRAVELLER>
bool bool
DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update, bool micro_movement) DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update, bool micro_movement)
{ {
if(!micro_movement) if (!micro_movement)
{ {
i_tracker.Update(diff); i_tracker.Update(diff);
i_timeElapsed += diff; i_timeElapsed += diff;
if( i_tracker.Passed() || force_update ) if (i_tracker.Passed() || force_update)
{ {
ResetUpdate(); ResetUpdate();
if(!i_destSet) return true; if (!i_destSet) return true;
float x,y,z; float x,y,z;
GetLocationNowNoMicroMovement(x, y, z); GetLocationNowNoMicroMovement(x, y, z);
if( x == -431602080 )
return false; if (traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y || traveller.GetTraveller().GetPositionZ() != z)
if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y )
{ {
float ori = traveller.GetTraveller().GetAngle(x, y); float ori = traveller.GetTraveller().GetAngle(x, y);
traveller.Relocation(x, y, z, ori); traveller.Relocation(x, y, z, ori);
@ -116,24 +116,21 @@ DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff,
} }
i_tracker.Update(diff); i_tracker.Update(diff);
i_timeElapsed += diff; i_timeElapsed += diff;
if( i_tracker.Passed() || force_update ) if (i_tracker.Passed() || force_update)
{ {
ResetUpdate(); ResetUpdate();
if(!i_destSet) return true; if (!i_destSet) return true;
float x,y,z;
if(!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT)) if (!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT))
return true; return true;
if(traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT)) float x,y,z;
if (traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT))
GetLocationNow(traveller.GetTraveller().GetBaseMap() ,x, y, z, true); // Should reposition Object with right Coord, so I can bypass some Grid Relocation GetLocationNow(traveller.GetTraveller().GetBaseMap() ,x, y, z, true); // Should reposition Object with right Coord, so I can bypass some Grid Relocation
else else
GetLocationNow(traveller.GetTraveller().GetBaseMap(), x, y, z, false); GetLocationNow(traveller.GetTraveller().GetBaseMap(), x, y, z, false);
if( x == -431602080 ) if (traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y || traveller.GetTraveller().GetPositionZ() != z)
return false;
if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y )
{ {
float ori = traveller.GetTraveller().GetAngle(x, y); float ori = traveller.GetTraveller().GetAngle(x, y);
traveller.Relocation(x, y, z, ori); traveller.Relocation(x, y, z, ori);
@ -160,13 +157,13 @@ template<typename TRAVELLER>
void void
DestinationHolder<TRAVELLER>::GetLocationNow(const Map * map, float &x, float &y, float &z, bool is3D) const DestinationHolder<TRAVELLER>::GetLocationNow(const Map * map, float &x, float &y, float &z, bool is3D) const
{ {
if( HasArrived() ) if (HasArrived())
{ {
x = i_destX; x = i_destX;
y = i_destY; y = i_destY;
z = i_destZ; z = i_destZ;
} }
else if(HasDestination()) else if (HasDestination())
{ {
double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime; double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime;
const float distanceX = ((i_destX - i_fromX) * percent_passed); const float distanceX = ((i_destX - i_fromX) * percent_passed);
@ -176,7 +173,7 @@ DestinationHolder<TRAVELLER>::GetLocationNow(const Map * map, float &x, float &y
y = i_fromY + distanceY; y = i_fromY + distanceY;
float z2 = i_fromZ + distanceZ; float z2 = i_fromZ + distanceZ;
// All that is not finished but previous code neither... Traveller need be able to swim. // All that is not finished but previous code neither... Traveller need be able to swim.
if(is3D) if (is3D)
z = z2; z = z2;
else else
{ {
@ -193,11 +190,11 @@ DestinationHolder<TRAVELLER>::GetLocationNow(const Map * map, float &x, float &y
template<typename TRAVELLER> template<typename TRAVELLER>
float float
DestinationHolder<TRAVELLER>::GetDistance2dFromDestSq(const WorldObject &obj) const DestinationHolder<TRAVELLER>::GetDistance3dFromDestSq(const WorldObject &obj) const
{ {
float x,y,z; float x,y,z;
obj.GetPosition(x,y,z); obj.GetPosition(x,y,z);
return (i_destX-x)*(i_destX-x)+(i_destY-y)*(i_destY-y); return (i_destX-x)*(i_destX-x)+(i_destY-y)*(i_destY-y)+(i_destZ-z)*(i_destZ-z);
} }
template<typename TRAVELLER> template<typename TRAVELLER>
@ -211,7 +208,7 @@ template<typename TRAVELLER>
void void
DestinationHolder<TRAVELLER>::GetLocationNowNoMicroMovement(float &x, float &y, float &z) const DestinationHolder<TRAVELLER>::GetLocationNowNoMicroMovement(float &x, float &y, float &z) const
{ {
if( HasArrived() ) if (HasArrived())
{ {
x = i_destX; x = i_destX;
y = i_destY; y = i_destY;

View file

@ -150,9 +150,10 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMa
SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId);
// GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3
SetGoState(go_state); SetGoState(go_state);
SetGoType(GameobjectTypes(goinfo->type)); SetGoType(GameobjectTypes(goinfo->type));
SetGoArtKit(0); // unknown what this is
SetGoAnimProgress(animprogress); SetGoAnimProgress(animprogress);
//Notify the map's instance data. //Notify the map's instance data.

File diff suppressed because it is too large Load diff

View file

@ -237,25 +237,25 @@ struct GuildBankTab
struct GuildItemPosCount struct GuildItemPosCount
{ {
GuildItemPosCount(uint8 _slot, uint32 _count) : slot(_slot), count(_count) {} GuildItemPosCount(uint8 _slot, uint32 _count) : Slot(_slot), Count(_count) {}
bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const; bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const;
uint8 slot; uint8 Slot;
uint32 count; uint32 Count;
}; };
typedef std::vector<GuildItemPosCount> GuildItemPosCountVec; typedef std::vector<GuildItemPosCount> GuildItemPosCountVec;
struct MemberSlot struct MemberSlot
{ {
uint64 logout_time; std::string Name;
std::string name; uint32 RankId;
uint8 Level;
uint8 Class;
uint32 ZoneId;
uint64 LogoutTime;
std::string Pnote; std::string Pnote;
std::string OFFnote; std::string OFFnote;
uint32 RankId;
uint32 zoneId;
uint8 level;
uint8 Class;
uint32 BankResetTimeMoney; uint32 BankResetTimeMoney;
uint32 BankRemMoney; uint32 BankRemMoney;
uint32 BankResetTimeTab[GUILD_BANK_MAX_TABS]; uint32 BankResetTimeTab[GUILD_BANK_MAX_TABS];
@ -264,7 +264,7 @@ struct MemberSlot
struct RankInfo struct RankInfo
{ {
RankInfo(const std::string& _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money) RankInfo(const std::string& _name, uint32 _rights, uint32 _money) : Name(_name), Rights(_rights), BankMoneyPerDay(_money)
{ {
for(uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i) for(uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i)
{ {
@ -273,8 +273,8 @@ struct RankInfo
} }
} }
std::string name; std::string Name;
uint32 rights; uint32 Rights;
uint32 BankMoneyPerDay; uint32 BankMoneyPerDay;
uint32 TabRight[GUILD_BANK_MAX_TABS]; uint32 TabRight[GUILD_BANK_MAX_TABS];
uint32 TabSlotPerDay[GUILD_BANK_MAX_TABS]; uint32 TabSlotPerDay[GUILD_BANK_MAX_TABS];
@ -365,7 +365,7 @@ class Guild
{ {
for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
{ {
if(itr->second.name == name) if(itr->second.Name == name)
{ {
guid = itr->first; guid = itr->first;
return &itr->second; return &itr->second;

View file

@ -59,8 +59,8 @@ enum ItemModType
ITEM_MOD_ATTACK_POWER = 38, ITEM_MOD_ATTACK_POWER = 38,
ITEM_MOD_RANGED_ATTACK_POWER = 39, ITEM_MOD_RANGED_ATTACK_POWER = 39,
ITEM_MOD_FERAL_ATTACK_POWER = 40, ITEM_MOD_FERAL_ATTACK_POWER = 40,
ITEM_MOD_SPELL_HEALING_DONE = 41, ITEM_MOD_SPELL_HEALING_DONE = 41, // deprecated
ITEM_MOD_SPELL_DAMAGE_DONE = 42, ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
ITEM_MOD_MANA_REGENERATION = 43, ITEM_MOD_MANA_REGENERATION = 43,
ITEM_MOD_ARMOR_PENETRATION_RATING = 44, ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
ITEM_MOD_SPELL_POWER = 45, ITEM_MOD_SPELL_POWER = 45,

View file

@ -331,7 +331,8 @@ enum MangosStrings
LANG_CUSTOMIZE_PLAYER = 345, LANG_CUSTOMIZE_PLAYER = 345,
LANG_CUSTOMIZE_PLAYER_GUID = 346, LANG_CUSTOMIZE_PLAYER_GUID = 346,
LANG_COMMAND_GOTAXINODENOTFOUND = 347, LANG_COMMAND_GOTAXINODENOTFOUND = 347,
// Room for more level 2 348-399 not used LANG_GAMEOBJECT_HAVE_INVALID_DATA = 348,
// Room for more level 2 349-399 not used
// level 3 chat // level 3 chat
LANG_SCRIPTS_RELOADED = 400, LANG_SCRIPTS_RELOADED = 400,

View file

@ -420,7 +420,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),""); PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),"");
if (needReportToTarget(target)) if (needReportToTarget(target))
ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str()); ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str());
// stop flight if need // stop flight if need
if (target->isInFlight()) if (target->isInFlight())

View file

@ -700,15 +700,24 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
char* spawntimeSecs = strtok(NULL, " "); char* spawntimeSecs = strtok(NULL, " ");
const GameObjectInfo *goI = objmgr.GetGameObjectInfo(id); const GameObjectInfo *gInfo = objmgr.GetGameObjectInfo(id);
if (!goI) if (!gInfo)
{ {
PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id); PSendSysMessage(LANG_GAMEOBJECT_NOT_EXIST,id);
SetSentErrorMessage(true); SetSentErrorMessage(true);
return false; return false;
} }
if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId))
{
// report to DB errors log as in loading case
sLog.outErrorDb("Gameobject (Entry %u GoType: %u) have invalid displayId (%u), not spawned.",id, gInfo->type, gInfo->displayId);
PSendSysMessage(LANG_GAMEOBJECT_HAVE_INVALID_DATA,id);
SetSentErrorMessage(true);
return false;
}
Player *chr = m_session->GetPlayer(); Player *chr = m_session->GetPlayer();
float x = float(chr->GetPositionX()); float x = float(chr->GetPositionX());
float y = float(chr->GetPositionY()); float y = float(chr->GetPositionY());
@ -719,7 +728,7 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
GameObject* pGameObj = new GameObject; GameObject* pGameObj = new GameObject;
uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) if(!pGameObj->Create(db_lowGUID, gInfo->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
{ {
delete pGameObj; delete pGameObj;
return false; return false;
@ -742,14 +751,14 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
return false; return false;
} }
sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), goI->name, db_lowGUID, x, y, z, o); sLog.outDebug(GetMangosString(LANG_GAMEOBJECT_CURRENT), gInfo->name, db_lowGUID, x, y, z, o);
map->Add(pGameObj); map->Add(pGameObj);
// TODO: is it really necessary to add both the real and DB table guid here ? // TODO: is it really necessary to add both the real and DB table guid here ?
objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID)); objmgr.AddGameobjectToGrid(db_lowGUID, objmgr.GetGOData(db_lowGUID));
PSendSysMessage(LANG_GAMEOBJECT_ADD,id,goI->name,db_lowGUID,x,y,z); PSendSysMessage(LANG_GAMEOBJECT_ADD,id,gInfo->name,db_lowGUID,x,y,z);
return true; return true;
} }

View file

@ -34,8 +34,8 @@ enum MailShowFlags
MAIL_SHOW_UNK0 = 0x0001, MAIL_SHOW_UNK0 = 0x0001,
MAIL_SHOW_DELETE = 0x0002, // forced show delete button instead return button MAIL_SHOW_DELETE = 0x0002, // forced show delete button instead return button
MAIL_SHOW_AUCTION = 0x0004, // from old comment MAIL_SHOW_AUCTION = 0x0004, // from old comment
MAIL_SHOW_COD = 0x0008, // show subject prefix MAIL_SHOW_UNK2 = 0x0008, // unknown, COD will be shown even without that flag
MAIL_SHOW_UNK4 = 0x0010, MAIL_SHOW_RETURN = 0x0010,
}; };
void MailItem::deleteItem( bool inDB ) void MailItem::deleteItem( bool inDB )
@ -321,7 +321,16 @@ void WorldSession::HandleMailDelete(WorldPacket & recv_data )
pl->m_mailsUpdated = true; pl->m_mailsUpdated = true;
Mail *m = pl->GetMail(mailId); Mail *m = pl->GetMail(mailId);
if(m) if(m)
{
// delete shouldn't show up for COD mails
if (m->COD)
{
pl->SendMailResult(mailId, MAIL_DELETED, MAIL_ERR_INTERNAL_ERROR);
return;
}
m->state = MAIL_STATE_DELETED; m->state = MAIL_STATE_DELETED;
}
pl->SendMailResult(mailId, MAIL_DELETED, MAIL_OK); pl->SendMailResult(mailId, MAIL_DELETED, MAIL_OK);
} }
@ -594,8 +603,8 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data )
show_flags |= MAIL_SHOW_DELETE; show_flags |= MAIL_SHOW_DELETE;
if ((*itr)->messageType == MAIL_AUCTION) if ((*itr)->messageType == MAIL_AUCTION)
show_flags |= MAIL_SHOW_AUCTION; show_flags |= MAIL_SHOW_AUCTION;
if ((*itr)->COD) if ((*itr)->HasItems() && (*itr)->messageType == MAIL_NORMAL)
show_flags |= MAIL_SHOW_COD; show_flags |= MAIL_SHOW_RETURN;
data << uint16(0x0040); // unknown 2.3.0, different values data << uint16(0x0040); // unknown 2.3.0, different values
data << uint32((*itr)->messageID); // Message ID data << uint32((*itr)->messageID); // Message ID

View file

@ -592,10 +592,9 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport()) if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
{ {
if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster()) if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
{
IsActivateToQuest = true; IsActivateToQuest = true;
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
} updateMask->SetBit(GAMEOBJECT_DYNAMIC);
} }
else if (isType(TYPEMASK_UNIT)) else if (isType(TYPEMASK_UNIT))
{ {
@ -711,18 +710,27 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
switch(((GameObject*)this)->GetGoType()) switch(((GameObject*)this)->GetGoType())
{ {
case GAMEOBJECT_TYPE_CHEST: case GAMEOBJECT_TYPE_CHEST:
*data << uint32(9); // enable quest object. Represent 9, but 1 for client before 2.3.0 // enable quest object. Represent 9, but 1 for client before 2.3.0
*data << uint16(9);
*data << uint16(-1);
break; break;
case GAMEOBJECT_TYPE_GOOBER: case GAMEOBJECT_TYPE_GOOBER:
*data << uint32(1); *data << uint16(1);
*data << uint16(-1);
break; break;
default: default:
*data << uint32(0); // unknown, not happen. // unknown, not happen.
*data << uint16(0);
*data << uint16(-1);
break; break;
} }
} }
else else
*data << uint32(0); // disable quest object {
// disable quest object
*data << uint16(0);
*data << uint16(-1);
}
} }
else else
*data << m_uint32Values[ index ]; // other cases *data << m_uint32Values[ index ]; // other cases

View file

@ -1220,7 +1220,7 @@ void ObjectMgr::LoadGameobjects()
uint32 entry = fields[ 1].GetUInt32(); uint32 entry = fields[ 1].GetUInt32();
GameObjectInfo const* gInfo = GetGameObjectInfo(entry); GameObjectInfo const* gInfo = GetGameObjectInfo(entry);
if(!gInfo) if (!gInfo)
{ {
sLog.outErrorDb("Table `gameobject` has gameobject (GUID: %u) with non existing gameobject entry %u, skipped.", guid, entry); sLog.outErrorDb("Table `gameobject` has gameobject (GUID: %u) with non existing gameobject entry %u, skipped.", guid, entry);
continue; continue;
@ -1232,7 +1232,7 @@ void ObjectMgr::LoadGameobjects()
continue; continue;
} }
if(gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId)) if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId))
{ {
sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) have invalid displayId (%u), not loaded.", guid, entry, gInfo->type, gInfo->displayId); sLog.outErrorDb("Gameobject (GUID: %u Entry %u GoType: %u) have invalid displayId (%u), not loaded.", guid, entry, gInfo->type, gInfo->displayId);
continue; continue;
@ -1272,13 +1272,13 @@ void ObjectMgr::LoadGameobjects()
int16 gameEvent = fields[16].GetInt16(); int16 gameEvent = fields[16].GetInt16();
int16 PoolId = fields[17].GetInt16(); int16 PoolId = fields[17].GetInt16();
if(data.rotation2 < -1.0f || data.rotation2 > 1.0f) if (data.rotation2 < -1.0f || data.rotation2 > 1.0f)
{ {
sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation2 (%f) value, skip", guid, data.id, data.rotation2); sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation2 (%f) value, skip", guid, data.id, data.rotation2);
continue; continue;
} }
if(data.rotation3 < -1.0f || data.rotation3 > 1.0f) if (data.rotation3 < -1.0f || data.rotation3 > 1.0f)
{ {
sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation3 (%f) value, skip", guid, data.id, data.rotation3); sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation3 (%f) value, skip", guid, data.id, data.rotation3);
continue; continue;
@ -1786,6 +1786,16 @@ void ObjectMgr::LoadItemPrototypes()
sLog.outErrorDb("Item (Entry: %u) has wrong stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType); sLog.outErrorDb("Item (Entry: %u) has wrong stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType);
const_cast<ItemPrototype*>(proto)->ItemStat[j].ItemStatType = 0; const_cast<ItemPrototype*>(proto)->ItemStat[j].ItemStatType = 0;
} }
switch(proto->ItemStat[j].ItemStatType)
{
case ITEM_MOD_SPELL_HEALING_DONE:
case ITEM_MOD_SPELL_DAMAGE_DONE:
sLog.outErrorDb("Item (Entry: %u) has deprecated stat_type%d (%u)",i,j+1,proto->ItemStat[j].ItemStatType);
break;
default:
break;
}
} }
for (int j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j) for (int j = 0; j < MAX_ITEM_PROTO_DAMAGES; ++j)

View file

@ -445,10 +445,10 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
for (int i = 0; i < MAX_COMBAT_RATING; ++i) for (int i = 0; i < MAX_COMBAT_RATING; ++i)
m_baseRatingValue[i] = 0; m_baseRatingValue[i] = 0;
m_baseSpellDamage = 0; m_baseSpellPower = 0;
m_baseSpellHealing = 0;
m_baseFeralAP = 0; m_baseFeralAP = 0;
m_baseManaRegen = 0; m_baseManaRegen = 0;
m_armorPenetrationPct = 0.0f;
// Honor System // Honor System
m_lastHonorUpdateTime = time(NULL); m_lastHonorUpdateTime = time(NULL);
@ -809,10 +809,10 @@ void Player::StopMirrorTimer(MirrorTimerType Type)
GetSession()->SendPacket( &data ); GetSession()->SendPacket( &data );
} }
void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage) uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
{ {
if(!isAlive() || isGameMaster()) if(!isAlive() || isGameMaster())
return; return 0;
// Absorb, resist some environmental damage type // Absorb, resist some environmental damage type
uint32 absorb = 0; uint32 absorb = 0;
@ -834,7 +834,7 @@ void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
data << uint32(resist); data << uint32(resist);
SendMessageToSet(&data, true); SendMessageToSet(&data, true);
DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); uint32 final_damage = DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
if(!isAlive()) if(!isAlive())
{ {
@ -849,6 +849,8 @@ void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type);
} }
return final_damage;
} }
int32 Player::getMaxTimer(MirrorTimerType timer) int32 Player::getMaxTimer(MirrorTimerType timer)
@ -4980,6 +4982,8 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
} }
break; break;
case CR_ARMOR_PENETRATION: case CR_ARMOR_PENETRATION:
if(affectStats)
UpdateArmorPenetration();
break; break;
} }
} }
@ -6666,12 +6670,6 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
case ITEM_MOD_FERAL_ATTACK_POWER: case ITEM_MOD_FERAL_ATTACK_POWER:
ApplyFeralAPBonus(int32(val), apply); ApplyFeralAPBonus(int32(val), apply);
break; break;
case ITEM_MOD_SPELL_HEALING_DONE:
ApplySpellHealingBonus(int32(val), apply);
break;
case ITEM_MOD_SPELL_DAMAGE_DONE:
ApplySpellDamageBonus(int32(val), apply);
break;
case ITEM_MOD_MANA_REGENERATION: case ITEM_MOD_MANA_REGENERATION:
ApplyManaRegenBonus(int32(val), apply); ApplyManaRegenBonus(int32(val), apply);
break; break;
@ -6679,8 +6677,11 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply); ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply);
break; break;
case ITEM_MOD_SPELL_POWER: case ITEM_MOD_SPELL_POWER:
ApplySpellHealingBonus(int32(val), apply); ApplySpellPowerBonus(int32(val), apply);
ApplySpellDamageBonus(int32(val), apply); break;
// depricated item mods
case ITEM_MOD_SPELL_HEALING_DONE:
case ITEM_MOD_SPELL_DAMAGE_DONE:
break; break;
} }
} }
@ -10448,9 +10449,15 @@ Item* Player::EquipItem( uint16 pos, Item *pItem, bool update )
ApplyEquipCooldown(pItem); ApplyEquipCooldown(pItem);
if( slot == EQUIPMENT_SLOT_MAINHAND ) if( slot == EQUIPMENT_SLOT_MAINHAND )
{
UpdateExpertise(BASE_ATTACK); UpdateExpertise(BASE_ATTACK);
UpdateArmorPenetration();
}
else if( slot == EQUIPMENT_SLOT_OFFHAND ) else if( slot == EQUIPMENT_SLOT_OFFHAND )
{
UpdateExpertise(OFF_ATTACK); UpdateExpertise(OFF_ATTACK);
UpdateArmorPenetration();
}
} }
else else
{ {
@ -10590,9 +10597,13 @@ void Player::RemoveItem( uint8 bag, uint8 slot, bool update )
} }
UpdateExpertise(BASE_ATTACK); UpdateExpertise(BASE_ATTACK);
UpdateArmorPenetration();
} }
else if( slot == EQUIPMENT_SLOT_OFFHAND ) else if( slot == EQUIPMENT_SLOT_OFFHAND )
{
UpdateExpertise(OFF_ATTACK); UpdateExpertise(OFF_ATTACK);
UpdateArmorPenetration();
}
} }
} }
// need update known currency // need update known currency
@ -10701,10 +10712,16 @@ void Player::DestroyItem( uint8 bag, uint8 slot, bool update )
RemoveItemDependentAurasAndCasts(pItem); RemoveItemDependentAurasAndCasts(pItem);
// update expertise // update expertise
if ( slot == EQUIPMENT_SLOT_MAINHAND ) if( slot == EQUIPMENT_SLOT_MAINHAND )
{
UpdateExpertise(BASE_ATTACK); UpdateExpertise(BASE_ATTACK);
UpdateArmorPenetration();
}
else if( slot == EQUIPMENT_SLOT_OFFHAND ) else if( slot == EQUIPMENT_SLOT_OFFHAND )
{
UpdateExpertise(OFF_ATTACK); UpdateExpertise(OFF_ATTACK);
UpdateArmorPenetration();
}
// equipment visual show // equipment visual show
SetVisibleItemSlot(slot, NULL); SetVisibleItemSlot(slot, NULL);
@ -11939,14 +11956,6 @@ void Player::ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool
((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply); ((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply);
sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount); sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount);
break; break;
case ITEM_MOD_SPELL_HEALING_DONE:
((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply);
sLog.outDebug("+ %u SPELL_HEALING_DONE", enchant_amount);
break;
case ITEM_MOD_SPELL_DAMAGE_DONE:
((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply);
sLog.outDebug("+ %u SPELL_DAMAGE_DONE", enchant_amount);
break;
case ITEM_MOD_MANA_REGENERATION: case ITEM_MOD_MANA_REGENERATION:
((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply); ((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply);
sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount); sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount);
@ -11956,10 +11965,11 @@ void Player::ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool
sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount); sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount);
break; break;
case ITEM_MOD_SPELL_POWER: case ITEM_MOD_SPELL_POWER:
((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); ((Player*)this)->ApplySpellPowerBonus(enchant_amount, apply);
((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply);
sLog.outDebug("+ %u SPELL_POWER", enchant_amount); sLog.outDebug("+ %u SPELL_POWER", enchant_amount);
break; break;
case ITEM_MOD_SPELL_HEALING_DONE: // deprecated
case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated
default: default:
break; break;
} }
@ -18690,9 +18700,9 @@ void Player::UpdateForQuestWorldObjects()
continue; continue;
SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(obj->GetEntry()); SpellClickInfoMapBounds clickPair = objmgr.GetSpellClickInfoMapBounds(obj->GetEntry());
for(SpellClickInfoMap::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr) for(SpellClickInfoMap::const_iterator _itr = clickPair.first; _itr != clickPair.second; ++_itr)
{ {
if(itr->second.questStart || itr->second.questEnd) if(_itr->second.questStart || _itr->second.questEnd)
{ {
obj->BuildCreateUpdateBlockForPlayer(&udata,this); obj->BuildCreateUpdateBlockForPlayer(&udata,this);
break; break;
@ -19914,10 +19924,11 @@ void Player::HandleFall(MovementInfo const& movementInfo)
if (GetDummyAura(43621)) if (GetDummyAura(43621))
damage = GetMaxHealth()/2; damage = GetMaxHealth()/2;
EnvironmentalDamage(DAMAGE_FALL, damage); uint32 original_health = GetHealth();
uint32 final_damage = EnvironmentalDamage(DAMAGE_FALL, damage);
// recheck alive, might have died of EnvironmentalDamage // recheck alive, might have died of EnvironmentalDamage, avoid cases when player die in fact like Spirit of Redemption case
if (isAlive()) if (isAlive() && final_damage < original_health)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100)); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100));
} }

View file

@ -1700,8 +1700,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateAttackPowerAndDamage(bool ranged = false);
void UpdateShieldBlockValue(); void UpdateShieldBlockValue();
void UpdateDamagePhysical(WeaponAttackType attType); void UpdateDamagePhysical(WeaponAttackType attType);
void ApplySpellDamageBonus(int32 amount, bool apply); void ApplySpellPowerBonus(int32 amount, bool apply);
void ApplySpellHealingBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus(); void UpdateSpellDamageAndHealingBonus();
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage); void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage);
@ -1719,8 +1718,7 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 GetRangedCritDamageReduction(uint32 damage) const; uint32 GetRangedCritDamageReduction(uint32 damage) const;
uint32 GetSpellCritDamageReduction(uint32 damage) const; uint32 GetSpellCritDamageReduction(uint32 damage) const;
uint32 GetDotDamageReduction(uint32 damage) const; uint32 GetDotDamageReduction(uint32 damage) const;
uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage;} uint32 GetBaseSpellPowerBonus() { return m_baseSpellPower; }
uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing;}
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const; float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
void UpdateBlockPercentage(); void UpdateBlockPercentage();
@ -1735,6 +1733,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateAllSpellCritChances(); void UpdateAllSpellCritChances();
void UpdateSpellCritChance(uint32 school); void UpdateSpellCritChance(uint32 school);
void UpdateExpertise(WeaponAttackType attType); void UpdateExpertise(WeaponAttackType attType);
void UpdateArmorPenetration();
void ApplyManaRegenBonus(int32 amount, bool apply); void ApplyManaRegenBonus(int32 amount, bool apply);
void UpdateManaRegen(); void UpdateManaRegen();
@ -1899,6 +1898,7 @@ class MANGOS_DLL_SPEC Player : public Unit
float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; } float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; }
void _ApplyAllStatBonuses(); void _ApplyAllStatBonuses();
void _RemoveAllStatBonuses(); void _RemoveAllStatBonuses();
float GetArmorPenetrationPct() const { return m_armorPenetrationPct; }
void _ApplyWeaponDependentAuraMods(Item *item, WeaponAttackType attackType, bool apply); void _ApplyWeaponDependentAuraMods(Item *item, WeaponAttackType attackType, bool apply);
void _ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply); void _ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, Aura* aura, bool apply);
@ -2060,7 +2060,7 @@ class MANGOS_DLL_SPEC Player : public Unit
/*** ENVIROMENTAL SYSTEM ***/ /*** ENVIROMENTAL SYSTEM ***/
/*********************************************************/ /*********************************************************/
void EnvironmentalDamage(EnviromentalDamage type, uint32 damage); uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage);
/*********************************************************/ /*********************************************************/
/*** FLOOD FILTER SYSTEM ***/ /*** FLOOD FILTER SYSTEM ***/
@ -2364,10 +2364,10 @@ class MANGOS_DLL_SPEC Player : public Unit
float m_auraBaseMod[BASEMOD_END][MOD_END]; float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING]; int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint16 m_baseSpellDamage; uint16 m_baseSpellPower;
uint16 m_baseSpellHealing;
uint16 m_baseFeralAP; uint16 m_baseFeralAP;
uint16 m_baseManaRegen; uint16 m_baseManaRegen;
float m_armorPenetrationPct;
SpellModList m_spellMods[MAX_SPELLMOD]; SpellModList m_spellMods[MAX_SPELLMOD];
int32 m_SpellModRemoveCount; int32 m_SpellModRemoveCount;

View file

@ -179,11 +179,6 @@ enum SpellSchoolMask
SPELL_SCHOOL_MASK_ALL = ( SPELL_SCHOOL_MASK_NORMAL | SPELL_SCHOOL_MASK_MAGIC ) SPELL_SCHOOL_MASK_ALL = ( SPELL_SCHOOL_MASK_NORMAL | SPELL_SCHOOL_MASK_MAGIC )
}; };
#define SPELL_SCHOOL_MASK_MAGIC \
( SPELL_SCHOOL_MASK_HOLY | SPELL_SCHOOL_MASK_FIRE | SPELL_SCHOOL_MASK_NATURE | \
SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW | \
SPELL_SCHOOL_MASK_ARCANE )
inline SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask) inline SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask)
{ {
for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
@ -422,7 +417,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = {
#define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster #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_UNK0 0x00000001 // 0 Only Move spell have this flag
#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 3.0.3 #define SPELL_ATTR_EX6_ONLY_IN_ARENA 0x00000002 // 1 only usable in arena, not used in 3.2.0a and early
#define SPELL_ATTR_EX6_UNK2 0x00000004 // 2 #define SPELL_ATTR_EX6_UNK2 0x00000004 // 2
#define SPELL_ATTR_EX6_UNK3 0x00000008 // 3 #define SPELL_ATTR_EX6_UNK3 0x00000008 // 3
#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 #define SPELL_ATTR_EX6_UNK4 0x00000010 // 4
@ -432,7 +427,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = {
#define SPELL_ATTR_EX6_UNK8 0x00000100 // 8 #define SPELL_ATTR_EX6_UNK8 0x00000100 // 8
#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX6_UNK9 0x00000200 // 9
#define SPELL_ATTR_EX6_UNK10 0x00000400 // 10 #define SPELL_ATTR_EX6_UNK10 0x00000400 // 10
#define SPELL_ATTR_EX6_UNK11 0x00000800 // 11 #define SPELL_ATTR_EX6_NOT_IN_RAID_INSTANCE 0x00000800 // 11 not usable in raid instance
#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 #define SPELL_ATTR_EX6_UNK12 0x00001000 // 12
#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX6_UNK13 0x00002000 // 13
#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 #define SPELL_ATTR_EX6_UNK14 0x00004000 // 14

View file

@ -330,7 +330,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
&Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Use SpellClassMask for spell select &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Use SpellClassMask for spell select
&Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon &Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
&Aura::HandleNULL, //279 visual effects? 58836 and 57507 &Aura::HandleNULL, //279 visual effects? 58836 and 57507
&Aura::HandleNULL, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT &Aura::HandleModTargetArmorPct, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
&Aura::HandleNULL, //281 SPELL_AURA_MOD_HONOR_GAIN &Aura::HandleNULL, //281 SPELL_AURA_MOD_HONOR_GAIN
&Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
&Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
@ -7287,3 +7287,11 @@ bool Aura::IsCritFromAbilityAura(Unit* caster, uint32& damage)
} }
return false; return false;
} }
void Aura::HandleModTargetArmorPct(bool apply, bool Real)
{
if(m_target->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)m_target)->UpdateArmorPenetration();
}

View file

@ -211,6 +211,7 @@ class MANGOS_DLL_SPEC Aura
void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real); void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real);
void HandleNoReagentUseAura(bool Apply, bool Real); void HandleNoReagentUseAura(bool Apply, bool Real);
void HandlePhase(bool Apply, bool Real); void HandlePhase(bool Apply, bool Real);
void HandleModTargetArmorPct(bool Apply, bool Real);
virtual ~Aura(); virtual ~Aura();

View file

@ -5102,7 +5102,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
return; return;
} }
case 55693: // Remove Collapsing Cave Aura case 55693: // Remove Collapsing Cave Aura
if(unitTarget) if(!unitTarget)
return; return;
unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(effIndex)); unitTarget->RemoveAurasDueToSpell(m_spellInfo->CalculateSimpleValue(effIndex));
break; break;

View file

@ -708,8 +708,6 @@ void SpellMgr::LoadSpellTargetPositions()
bar.step(); bar.step();
++count;
uint32 Spell_ID = fields[0].GetUInt32(); uint32 Spell_ID = fields[0].GetUInt32();
SpellTargetPosition st; SpellTargetPosition st;
@ -756,6 +754,7 @@ void SpellMgr::LoadSpellTargetPositions()
} }
mSpellTargetPositions[Spell_ID] = st; mSpellTargetPositions[Spell_ID] = st;
++count;
} while( result->NextRow() ); } while( result->NextRow() );
@ -2747,7 +2746,7 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
while (groupEntry) while (groupEntry)
{ {
for (uint32 i=0; i<6; ++i) for (uint32 i=0; i<6; ++i)
if( groupEntry->AreaId[i] == zone_id || groupEntry->AreaId[i] == area_id ) if (groupEntry->AreaId[i] == zone_id || groupEntry->AreaId[i] == area_id)
found = true; found = true;
if (found || !groupEntry->nextGroup) if (found || !groupEntry->nextGroup)
break; break;
@ -2755,7 +2754,7 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
groupEntry = sAreaGroupStore.LookupEntry(groupEntry->nextGroup); groupEntry = sAreaGroupStore.LookupEntry(groupEntry->nextGroup);
} }
if(!found) if (!found)
return SPELL_FAILED_INCORRECT_AREA; return SPELL_FAILED_INCORRECT_AREA;
} }
@ -2764,10 +2763,18 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
{ {
uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id); uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id);
MapEntry const* mapEntry = sMapStore.LookupEntry(v_map); MapEntry const* mapEntry = sMapStore.LookupEntry(v_map);
if(!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent()) if (!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent())
return SPELL_FAILED_INCORRECT_AREA; return SPELL_FAILED_INCORRECT_AREA;
} }
// raid instance limitation
if (spellInfo->AttributesEx6 & SPELL_ATTR_EX6_NOT_IN_RAID_INSTANCE)
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if (!mapEntry || mapEntry->IsRaid())
return SPELL_FAILED_NOT_IN_RAID_INSTANCE;
}
// DB base check (if non empty then must fit at least single for allow) // DB base check (if non empty then must fit at least single for allow)
SpellAreaMapBounds saBounds = spellmgr.GetSpellAreaMapBounds(spellInfo->Id); SpellAreaMapBounds saBounds = spellmgr.GetSpellAreaMapBounds(spellInfo->Id);
if (saBounds.first != saBounds.second) if (saBounds.first != saBounds.second)

View file

@ -91,17 +91,12 @@ bool Player::UpdateStats(Stats stat)
return true; return true;
} }
void Player::ApplySpellDamageBonus(int32 amount, bool apply) void Player::ApplySpellPowerBonus(int32 amount, bool apply)
{ {
m_baseSpellDamage+=apply?amount:-amount; m_baseSpellPower+=apply?amount:-amount;
// For speed just update for client // For speed just update for client
ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply); ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply);
}
void Player::ApplySpellHealingBonus(int32 amount, bool apply)
{
m_baseSpellHealing+=apply?amount:-amount;
// For speed just update for client
for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, amount, apply);; ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, amount, apply);;
} }
@ -137,6 +132,7 @@ bool Player::UpdateAllStats()
UpdateAllSpellCritChances(); UpdateAllSpellCritChances();
UpdateDefenseBonusesMod(); UpdateDefenseBonusesMod();
UpdateShieldBlockValue(); UpdateShieldBlockValue();
UpdateArmorPenetration();
UpdateSpellDamageAndHealingBonus(); UpdateSpellDamageAndHealingBonus();
UpdateManaRegen(); UpdateManaRegen();
UpdateExpertise(BASE_ATTACK); UpdateExpertise(BASE_ATTACK);
@ -653,6 +649,33 @@ void Player::UpdateExpertise(WeaponAttackType attack)
} }
} }
void Player::UpdateArmorPenetration()
{
m_armorPenetrationPct = GetRatingBonusValue(CR_ARMOR_PENETRATION);
AuraList const& armorAuras = GetAurasByType(SPELL_AURA_MOD_TARGET_ARMOR_PCT);
for(AuraList::const_iterator itr = armorAuras.begin(); itr != armorAuras.end(); ++itr)
{
// affects all weapons
if((*itr)->GetSpellProto()->EquippedItemClass == -1)
{
m_armorPenetrationPct += (*itr)->GetModifier()->m_amount;
continue;
}
// dependent on weapon class
for(uint8 i = 0; i < MAX_ATTACK; ++i)
{
Item *weapon = GetWeaponForAttack(WeaponAttackType(i));
if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto()))
{
m_armorPenetrationPct += (*itr)->GetModifier()->m_amount;
break;
}
}
}
}
void Player::ApplyManaRegenBonus(int32 amount, bool apply) void Player::ApplyManaRegenBonus(int32 amount, bool apply)
{ {
m_baseManaRegen+= apply ? amount : -amount; m_baseManaRegen+= apply ? amount : -amount;

View file

@ -136,7 +136,7 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
return true; return true;
// prevent movement while casting spells with cast time or channel time // prevent movement while casting spells with cast time or channel time
if ( owner.IsNonMeleeSpellCasted(false, false, true)) if (owner.IsNonMeleeSpellCasted(false, false, true))
{ {
if (!owner.IsStopped()) if (!owner.IsStopped())
owner.StopMoving(); owner.StopMoving();
@ -149,9 +149,9 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
Traveller<T> traveller(owner); Traveller<T> traveller(owner);
if( !i_destinationHolder.HasDestination() ) if (!i_destinationHolder.HasDestination())
_setTargetLocation(owner); _setTargetLocation(owner);
if( owner.IsStopped() && !i_destinationHolder.HasArrived() ) if (owner.IsStopped() && !i_destinationHolder.HasArrived())
{ {
owner.addUnitState(UNIT_STAT_CHASE); owner.addUnitState(UNIT_STAT_CHASE);
if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly()) if (owner.GetTypeId() == TYPEID_UNIT && ((Creature*)&owner)->canFly())
@ -172,16 +172,16 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
//More distance let have better performance, less distance let have more sensitive reaction at target move. //More distance let have better performance, less distance let have more sensitive reaction at target move.
// try to counter precision differences // try to counter precision differences
if( i_destinationHolder.GetDistance2dFromDestSq(*i_target.getTarget()) >= dist * dist) if (i_destinationHolder.GetDistance3dFromDestSq(*i_target.getTarget()) >= dist * dist)
{ {
owner.SetInFront(i_target.getTarget()); // Set new Angle For Map:: owner.SetInFront(i_target.getTarget()); // Set new Angle For Map::
_setTargetLocation(owner); //Calculate New Dest and Send data To Player _setTargetLocation(owner); //Calculate New Dest and Send data To Player
} }
// Update the Angle of the target only for Map::, no need to send packet for player // Update the Angle of the target only for Map::, no need to send packet for player
else if ( !i_angle && !owner.HasInArc( 0.01f, i_target.getTarget() ) ) else if (!i_angle && !owner.HasInArc(0.01f, i_target.getTarget()))
owner.SetInFront(i_target.getTarget()); owner.SetInFront(i_target.getTarget());
if(( owner.IsStopped() && !i_destinationHolder.HasArrived() ) || i_recalculateTravel ) if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
{ {
i_recalculateTravel = false; i_recalculateTravel = false;
//Angle update will take place into owner.StopMoving() //Angle update will take place into owner.StopMoving()

View file

@ -1565,26 +1565,29 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage)
{ {
uint32 newdamage = 0; uint32 newdamage = 0;
float armor = pVictim->GetArmor(); float armor = pVictim->GetArmor();
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL); armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL);
// Apply Player CR_ARMOR_PENETRATION rating // Apply Player CR_ARMOR_PENETRATION rating and percent talents
if (GetTypeId()==TYPEID_PLAYER) if (GetTypeId()==TYPEID_PLAYER)
armor *= 1.0f - ((Player*)this)->GetRatingBonusValue(CR_ARMOR_PENETRATION) / 100.0f; armor *= 1.0f - ((Player*)this)->GetArmorPenetrationPct() / 100.0f;
if (armor < 0.0f) armor=0.0f; if (armor < 0.0f)
armor = 0.0f;
float levelModifier = getLevel(); float levelModifier = getLevel();
if ( levelModifier > 59 ) if (levelModifier > 59)
levelModifier = levelModifier + (4.5f * (levelModifier-59)); levelModifier = levelModifier + (4.5f * (levelModifier-59));
float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40); float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40);
tmpvalue = tmpvalue/(1.0f + tmpvalue); tmpvalue = tmpvalue/(1.0f + tmpvalue);
if(tmpvalue < 0.0f) if (tmpvalue < 0.0f)
tmpvalue = 0.0f; tmpvalue = 0.0f;
if(tmpvalue > 0.75f) if (tmpvalue > 0.75f)
tmpvalue = 0.75f; tmpvalue = 0.75f;
newdamage = uint32(damage - (damage * tmpvalue)); newdamage = uint32(damage - (damage * tmpvalue));
return (newdamage > 1) ? newdamage : 1; return (newdamage > 1) ? newdamage : 1;
@ -6288,10 +6291,10 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// Set trigger spell id, target, custom basepoints // Set trigger spell id, target, custom basepoints
uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()]; uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
Unit* target = NULL; Unit* target = NULL;
int32 basepoints0 = 0; int32 basepoints[3] = {0, 0, 0};
if(triggeredByAura->GetModifier()->m_auraname == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE) if(triggeredByAura->GetModifier()->m_auraname == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE)
basepoints0 = triggerAmount; basepoints[0] = triggerAmount;
Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
@ -6329,7 +6332,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
else if (auraSpellInfo->Id==43820) // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) else if (auraSpellInfo->Id==43820) // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket)
{ {
// Pct value stored in dummy // Pct value stored in dummy
basepoints0 = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100; basepoints[0] = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100;
target = pVictim; target = pVictim;
break; break;
} }
@ -6499,7 +6502,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
{ {
int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this); int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this);
// Drain Soul // Drain Soul
CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); CastCustomSpell(this, 18371, &basepoints[0], NULL, NULL, true, castItem, triggeredByAura);
break; break;
} }
} }
@ -6545,7 +6548,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id); sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id);
return false; return false;
} }
basepoints0 = damage * triggerAmount / 100 / 3; basepoints[0] = damage * triggerAmount / 100 / 3;
target = this; target = this;
} }
break; break;
@ -6574,7 +6577,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
{ {
if (triggerAmount == 0) if (triggerAmount == 0)
return false; return false;
basepoints0 = triggerAmount * GetMaxHealth() / 100; basepoints[0] = triggerAmount * GetMaxHealth() / 100;
trigger_spell_id = 34299; trigger_spell_id = 34299;
} }
break; break;
@ -6643,7 +6646,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
} }
// percent stored in effect 1 (class scripts) base points // percent stored in effect 1 (class scripts) base points
int32 cost = originalSpell->manaCost + originalSpell->ManaCostPercentage * GetCreateMana() / 100; int32 cost = originalSpell->manaCost + originalSpell->ManaCostPercentage * GetCreateMana() / 100;
basepoints0 = cost*auraSpellInfo->CalculateSimpleValue(1)/100; basepoints[0] = cost*auraSpellInfo->CalculateSimpleValue(1)/100;
trigger_spell_id = 20272; trigger_spell_id = 20272;
target = this; target = this;
} }
@ -6732,7 +6735,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
{ {
if(!procSpell) if(!procSpell)
return false; return false;
basepoints0 = procSpell->manaCost * 35 / 100; basepoints[0] = procSpell->manaCost * 35 / 100;
trigger_spell_id = 23571; trigger_spell_id = 23571;
target = this; target = this;
} }
@ -6746,7 +6749,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
if(pVictim && pVictim->isAlive()) if(pVictim && pVictim->isAlive())
pVictim->getThreatManager().modifyThreatPercent(this,-10); pVictim->getThreatManager().modifyThreatPercent(this,-10);
basepoints0 = triggerAmount * GetMaxHealth() / 100; basepoints[0] = triggerAmount * GetMaxHealth() / 100;
trigger_spell_id = 31616; trigger_spell_id = 31616;
target = this; target = this;
} }
@ -6781,7 +6784,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
if (!((Player*)this)->isHonorOrXPTarget(pVictim)) if (!((Player*)this)->isHonorOrXPTarget(pVictim))
return false; return false;
trigger_spell_id = 50475; trigger_spell_id = 50475;
basepoints0 = damage * triggerAmount / 100; basepoints[0] = damage * triggerAmount / 100;
} }
break; break;
} }
@ -6811,7 +6814,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// This spell originally trigger 13567 - Dummy Trigger (vs dummy efect) // This spell originally trigger 13567 - Dummy Trigger (vs dummy efect)
case 26467: case 26467:
{ {
basepoints0 = damage * 15 / 100; basepoints[0] = damage * 15 / 100;
target = pVictim; target = pVictim;
trigger_spell_id = 26470; trigger_spell_id = 26470;
break; break;
@ -6917,13 +6920,13 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// Bloodthirst (($m/100)% of max health) // Bloodthirst (($m/100)% of max health)
case 23880: case 23880:
{ {
basepoints0 = int32(GetMaxHealth() * triggerAmount / 100); basepoints[0] = int32(GetMaxHealth() * triggerAmount / 100);
break; break;
} }
// Shamanistic Rage triggered spell // Shamanistic Rage triggered spell
case 30824: case 30824:
{ {
basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100); basepoints[0] = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100);
break; break;
} }
// Enlightenment (trigger only from mana cost spells) // Enlightenment (trigger only from mana cost spells)
@ -6933,6 +6936,34 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false; return false;
break; break;
} }
// Demonic Pact
case 48090:
{
// As the spell is proced from pet's attack - find owner
Unit* owner = GetOwner();
if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
return false;
// This spell doesn't stack, but refreshes duration. So we receive current bonuses to minus them later.
int32 curBonus = 0;
if (Aura* aur = owner->GetAura(48090,0))
curBonus = aur->GetModifier()->m_amount;
int32 spellDamage = owner->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_MAGIC) - curBonus;
if(spellDamage <= 0)
return false;
// percent stored in owner talent dummy
AuraList const& dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
for (AuraList::const_iterator i = dummyAuras.begin(); i != dummyAuras.end(); ++i)
{
if ((*i)->GetSpellProto()->SpellIconID == 3220)
{
basepoints[0] = basepoints[1] = int32(spellDamage * (*i)->GetModifier()->m_amount / 100);
break;
}
}
break;
}
// Sword and Board // Sword and Board
case 50227: case 50227:
{ {
@ -7018,8 +7049,12 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
if(!target || target!=this && !target->isAlive()) if(!target || target!=this && !target->isAlive())
return false; return false;
if(basepoints0) if(basepoints[0] || basepoints[1] || basepoints[2])
CastCustomSpell(target,trigger_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); CastCustomSpell(target,trigger_spell_id,
basepoints[0] ? &basepoints[0] : NULL,
basepoints[1] ? &basepoints[1] : NULL,
basepoints[2] ? &basepoints[2] : NULL,
true,castItem,triggeredByAura);
else else
CastSpell(target,trigger_spell_id,true,castItem,triggeredByAura); CastSpell(target,trigger_spell_id,true,castItem,triggeredByAura);
@ -8267,7 +8302,7 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
if (GetTypeId() == TYPEID_PLAYER) if (GetTypeId() == TYPEID_PLAYER)
{ {
// Base value // Base value
DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellDamageBonus(); DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellPowerBonus();
// Damage bonus from stats // Damage bonus from stats
AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT); AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
@ -8714,7 +8749,7 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask)
if (GetTypeId() == TYPEID_PLAYER) if (GetTypeId() == TYPEID_PLAYER)
{ {
// Base value // Base value
AdvertisedBenefit +=((Player*)this)->GetBaseSpellHealingBonus(); AdvertisedBenefit +=((Player*)this)->GetBaseSpellPowerBonus();
// Healing bonus from stats // Healing bonus from stats
AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT); AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
@ -9169,8 +9204,13 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
if(isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet())) if(isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet()))
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
if(creatureNotInCombat && ((Creature*)this)->AI()) if (creatureNotInCombat)
((Creature*)this)->AI()->EnterCombat(enemy); {
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
if (((Creature*)this)->AI())
((Creature*)this)->AI()->EnterCombat(enemy);
}
} }
void Unit::ClearInCombat() void Unit::ClearInCombat()
@ -9182,8 +9222,13 @@ void Unit::ClearInCombat()
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
// Player's state will be cleared in Player::UpdateContestedPvP // Player's state will be cleared in Player::UpdateContestedPvP
if(GetTypeId()!=TYPEID_PLAYER) if (GetTypeId() != TYPEID_PLAYER)
{
if (((Creature*)this)->GetCreatureInfo()->unit_flags & UNIT_FLAG_OOC_NOT_ATTACKABLE)
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
clearUnitState(UNIT_STAT_ATTACK_PLAYER); clearUnitState(UNIT_STAT_ATTACK_PLAYER);
}
else else
((Player*)this)->UpdatePotionCooldown(); ((Player*)this)->UpdatePotionCooldown();
} }
@ -9193,7 +9238,11 @@ bool Unit::isTargetableForAttack() const
if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster()) if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster())
return false; return false;
if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
return false;
// to be removed if unit by any reason enter combat
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE))
return false; return false;
return IsInWorld() && isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; return IsInWorld() && isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;

View file

@ -491,38 +491,38 @@ enum UnitVisibility
// Value masks for UNIT_FIELD_FLAGS // Value masks for UNIT_FIELD_FLAGS
enum UnitFlags enum UnitFlags
{ {
UNIT_FLAG_UNK_0 = 0x00000001, UNIT_FLAG_UNK_0 = 0x00000001,
UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable
UNIT_FLAG_DISABLE_MOVE = 0x00000004, UNIT_FLAG_DISABLE_MOVE = 0x00000004,
UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state
UNIT_FLAG_RENAME = 0x00000010, UNIT_FLAG_RENAME = 0x00000010,
UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP
UNIT_FLAG_UNK_6 = 0x00000040, UNIT_FLAG_UNK_6 = 0x00000040,
UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE
UNIT_FLAG_UNK_8 = 0x00000100, // 2.0.8 UNIT_FLAG_OOC_NOT_ATTACKABLE = 0x00000100, // 2.0.8 - (OOC Out Of Combat) Can not be attacked when not in combat. Removed if unit for some reason enter combat.
UNIT_FLAG_UNK_9 = 0x00000200, // 3.0.3 - makes you unable to attack everything UNIT_FLAG_UNK_9 = 0x00000200, // 3.0.3 - makes you unable to attack everything
UNIT_FLAG_LOOTING = 0x00000400, // loot animation UNIT_FLAG_LOOTING = 0x00000400, // loot animation
UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8 UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8
UNIT_FLAG_UNK_15 = 0x00008000, UNIT_FLAG_UNK_15 = 0x00008000,
UNIT_FLAG_UNK_16 = 0x00010000, UNIT_FLAG_UNK_16 = 0x00010000,
UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok
UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok
UNIT_FLAG_IN_COMBAT = 0x00080000, 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_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, 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_CONFUSED = 0x00400000,
UNIT_FLAG_FLEEING = 0x00800000, UNIT_FLAG_FLEEING = 0x00800000,
UNIT_FLAG_PLAYER_CONTROLLED= 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature UNIT_FLAG_PLAYER_CONTROLLED = 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature
UNIT_FLAG_NOT_SELECTABLE = 0x02000000, UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
UNIT_FLAG_SKINNABLE = 0x04000000, UNIT_FLAG_SKINNABLE = 0x04000000,
UNIT_FLAG_MOUNT = 0x08000000, UNIT_FLAG_MOUNT = 0x08000000,
UNIT_FLAG_UNK_28 = 0x10000000, UNIT_FLAG_UNK_28 = 0x10000000,
UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell
UNIT_FLAG_SHEATHE = 0x40000000, UNIT_FLAG_SHEATHE = 0x40000000,
UNIT_FLAG_UNK_31 = 0x80000000 UNIT_FLAG_UNK_31 = 0x80000000
}; };
// Value masks for UNIT_FIELD_FLAGS_2 // Value masks for UNIT_FIELD_FLAGS_2

View file

@ -112,8 +112,9 @@ World::~World()
m_weathers.clear(); m_weathers.clear();
while (!cliCmdQueue.empty()) CliCommandHolder* command;
delete cliCmdQueue.next(); while (cliCmdQueue.next(command))
delete command;
VMAP::VMapFactory::clear(); VMAP::VMapFactory::clear();
@ -2004,11 +2005,9 @@ void World::SendServerMessage(ServerMessageType type, const char *text, Player*
void World::UpdateSessions( uint32 diff ) void World::UpdateSessions( uint32 diff )
{ {
///- Add new sessions ///- Add new sessions
while(!addSessQueue.empty()) WorldSession* sess;
{ while(addSessQueue.next(sess))
WorldSession* sess = addSessQueue.next ();
AddSession_ (sess); AddSession_ (sess);
}
///- Then send an update signal to remaining ones ///- Then send an update signal to remaining ones
for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next) for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
@ -2032,25 +2031,20 @@ void World::UpdateSessions( uint32 diff )
// This handles the issued and queued CLI commands // This handles the issued and queued CLI commands
void World::ProcessCliCommands() void World::ProcessCliCommands()
{ {
if (cliCmdQueue.empty()) CliCommandHolder::Print* zprint = NULL;
return;
CliCommandHolder::Print* zprint; CliCommandHolder* command;
while (cliCmdQueue.next(command))
while (!cliCmdQueue.empty())
{ {
sLog.outDebug("CLI command under processing..."); sLog.outDebug("CLI command under processing...");
CliCommandHolder *command = cliCmdQueue.next();
zprint = command->m_print; zprint = command->m_print;
CliHandler(zprint).ParseCommands(command->m_command); CliHandler(zprint).ParseCommands(command->m_command);
delete command; delete command;
} }
// print the console message here so it looks right // print the console message here so it looks right
zprint("mangos>"); if (zprint)
zprint("mangos>");
} }
void World::InitResultQueue() void World::InitResultQueue()

View file

@ -69,11 +69,9 @@ WorldSession::~WorldSession()
} }
///- empty incoming packet queue ///- empty incoming packet queue
while(!_recvQueue.empty()) WorldPacket* packet;
{ while(_recvQueue.next(packet))
WorldPacket *packet = _recvQueue.next ();
delete packet; delete packet;
}
} }
void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const void WorldSession::SizeError(WorldPacket const& packet, uint32 size) const
@ -163,10 +161,9 @@ bool WorldSession::Update(uint32 /*diff*/)
{ {
///- Retrieve packets from the receive queue and call the appropriate handlers ///- Retrieve packets from the receive queue and call the appropriate handlers
/// not proccess packets if socket already closed /// not proccess packets if socket already closed
while (!_recvQueue.empty() && m_Socket && !m_Socket->IsClosed ()) WorldPacket* packet;
while (_recvQueue.next(packet) && m_Socket && !m_Socket->IsClosed ())
{ {
WorldPacket *packet = _recvQueue.next();
/*#if 1 /*#if 1
sLog.outError( "MOEP: %s (0x%.4X)", sLog.outError( "MOEP: %s (0x%.4X)",
LookupOpcodeName(packet->GetOpcode()), LookupOpcodeName(packet->GetOpcode()),

View file

@ -766,7 +766,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
LocaleConstant locale; LocaleConstant locale;
std::string account; std::string account;
Sha1Hash sha1; Sha1Hash sha1;
BigNumber v, s, g, N, x, I; BigNumber v, s, g, N;
WorldPacket packet, SendAddonPacked; WorldPacket packet, SendAddonPacked;
BigNumber K; BigNumber K;
@ -799,12 +799,11 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
"sessionkey, " //2 "sessionkey, " //2
"last_ip, " //3 "last_ip, " //3
"locked, " //4 "locked, " //4
"sha_pass_hash, " //5 "v, " //5
"v, " //6 "s, " //6
"s, " //7 "expansion, " //7
"expansion, " //8 "mutetime, " //8
"mutetime, " //9 "locale " //9
"locale " //10
"FROM account " "FROM account "
"WHERE username = '%s'", "WHERE username = '%s'",
safe_account.c_str ()); safe_account.c_str ());
@ -823,57 +822,21 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
Field* fields = result->Fetch (); Field* fields = result->Fetch ();
expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[8].GetUInt8()) ? fields[8].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION)); expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[7].GetUInt8()) ? fields[7].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION));
N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
g.SetDword (7); g.SetDword (7);
I.SetHexStr (fields[5].GetString ());
//In case of leading zeros in the I hash, restore them v.SetHexStr(fields[5].GetString());
uint8 mDigest[SHA_DIGEST_LENGTH]; s.SetHexStr (fields[6].GetString ());
memset (mDigest, 0, SHA_DIGEST_LENGTH);
if (I.GetNumBytes () <= SHA_DIGEST_LENGTH)
memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ());
std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH);
s.SetHexStr (fields[7].GetString ());
sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ());
sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH);
sha1.Finalize ();
x.SetBinary (sha1.GetDigest (), sha1.GetLength ());
v = g.ModExp (x, N);
const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free() const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free()
const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free() const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free()
const char* vold = fields[6].GetString ();
DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v_old: %s v_new: %s", DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s",
sStr, sStr,
vold,
vStr); vStr);
loginDatabase.PExecute ("UPDATE account "
"SET "
"v = '0', "
"s = '0' "
"WHERE username = '%s'",
safe_account.c_str ());
if (!vold || strcmp (vStr, vold))
{
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
SendPacket (packet);
delete result;
OPENSSL_free ((void*) sStr);
OPENSSL_free ((void*) vStr);
sLog.outBasic ("WorldSocket::HandleAuthSession: User not logged.");
return -1;
}
OPENSSL_free ((void*) sStr); OPENSSL_free ((void*) sStr);
OPENSSL_free ((void*) vStr); OPENSSL_free ((void*) vStr);
@ -899,9 +862,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
K.SetHexStr (fields[2].GetString ()); K.SetHexStr (fields[2].GetString ());
time_t mutetime = time_t (fields[9].GetUInt64 ()); time_t mutetime = time_t (fields[8].GetUInt64 ());
locale = LocaleConstant (fields[10].GetUInt8 ()); locale = LocaleConstant (fields[9].GetUInt8 ());
if (locale >= MAX_LOCALE) if (locale >= MAX_LOCALE)
locale = LOCALE_enUS; locale = LOCALE_enUS;
@ -909,13 +872,10 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
// Re-check account ban (same check as in realmd) // Re-check account ban (same check as in realmd)
QueryResult *banresult = QueryResult *banresult =
loginDatabase.PQuery ("SELECT " loginDatabase.PQuery ("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 "
"bandate, " "UNION "
"unbandate " "SELECT 1 FROM ip_banned WHERE ip = '%s'",
"FROM account_banned " id, GetRemoteAddress().c_str());
"WHERE id = '%u' "
"AND active = 1",
id);
if (banresult) // if account banned if (banresult) // if account banned
{ {

View file

@ -246,7 +246,6 @@ void AuthSocket::OnAccept()
sLog.outBasic("Accepting connection from '%s:%d'", sLog.outBasic("Accepting connection from '%s:%d'",
GetRemoteAddress().c_str(), GetRemotePort()); GetRemoteAddress().c_str(), GetRemotePort());
s.SetRand(s_BYTE_SIZE * 8);
} }
/// Read the packet from the client /// Read the packet from the client
@ -295,6 +294,8 @@ void AuthSocket::OnRead()
/// Make the SRP6 calculation from hash in dB /// Make the SRP6 calculation from hash in dB
void AuthSocket::_SetVSFields(const std::string& rI) void AuthSocket::_SetVSFields(const std::string& rI)
{ {
s.SetRand(s_BYTE_SIZE * 8);
BigNumber I; BigNumber I;
I.SetHexStr(rI.c_str()); I.SetHexStr(rI.c_str());
@ -396,7 +397,7 @@ bool AuthSocket::_HandleLogonChallenge()
///- Get the account details from the account table ///- Get the account details from the account table
// No SQL injection (escaped user name) // No SQL injection (escaped user name)
result = loginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '%s'",_safelogin.c_str ()); result = loginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s FROM account WHERE username = '%s'",_safelogin.c_str ());
if( result ) if( result )
{ {
///- If the IP is 'locked', check that the player comes indeed from the correct IP address ///- If the IP is 'locked', check that the player comes indeed from the correct IP address
@ -446,7 +447,21 @@ bool AuthSocket::_HandleLogonChallenge()
{ {
///- Get the password from the account table, upper it, and make the SRP6 calculation ///- Get the password from the account table, upper it, and make the SRP6 calculation
std::string rI = (*result)[0].GetCppString(); std::string rI = (*result)[0].GetCppString();
_SetVSFields(rI);
///- Don't calculate (v, s) if there are already some in the database
std::string databaseV = (*result)[5].GetCppString();
std::string databaseS = (*result)[6].GetCppString();
sLog.outDebug("database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str());
// multiply with 2, bytes are stored as hexstring
if(databaseV.size() != s_BYTE_SIZE*2 || databaseS.size() != s_BYTE_SIZE*2)
_SetVSFields(rI);
else
{
s.SetHexStr(databaseS.c_str());
v.SetHexStr(databaseV.c_str());
}
b.SetRand(19 * 8); b.SetRand(19 * 8);
BigNumber gmod = g.ModExp(b, N); BigNumber gmod = g.ModExp(b, N);
@ -591,8 +606,13 @@ bool AuthSocket::_HandleLogonProof()
///- Continue the SRP6 calculation based on data received from the client ///- Continue the SRP6 calculation based on data received from the client
BigNumber A; BigNumber A;
A.SetBinary(lp.A, 32); A.SetBinary(lp.A, 32);
// SRP safeguard: abort if A==0
if (A.isZero())
return false;
Sha1Hash sha; Sha1Hash sha;
sha.UpdateBigNumbers(&A, &B, NULL); sha.UpdateBigNumbers(&A, &B, NULL);
sha.Finalize(); sha.Finalize();
@ -603,7 +623,7 @@ bool AuthSocket::_HandleLogonProof()
uint8 t[32]; uint8 t[32];
uint8 t1[16]; uint8 t1[16];
uint8 vK[40]; uint8 vK[40];
memcpy(t, S.AsByteArray(), 32); memcpy(t, S.AsByteArray(32), 32);
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
{ {
t1[i] = t[i * 2]; t1[i] = t[i * 2];
@ -905,8 +925,6 @@ bool AuthSocket::_HandleRealmList()
SendBuf((char const*)hdr.contents(), hdr.size()); SendBuf((char const*)hdr.contents(), hdr.size());
// Set check field before possible relogin to realm
_SetVSFields(rI);
return true; return true;
} }

View file

@ -145,6 +145,7 @@ extern int main(int argc, char **argv)
sLog.outError("Could not find configuration file %s.", cfg_file); sLog.outError("Could not find configuration file %s.", cfg_file);
return 1; return 1;
} }
sLog.Initialize();
sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) ); sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
sLog.outString( "<Ctrl-C> to stop.\n" ); sLog.outString( "<Ctrl-C> to stop.\n" );

View file

@ -159,6 +159,11 @@ uint32 BigNumber::AsDword()
return (uint32)BN_get_word(_bn); return (uint32)BN_get_word(_bn);
} }
bool BigNumber::isZero() const
{
return BN_is_zero(_bn)!=0;
}
uint8 *BigNumber::AsByteArray(int minSize) uint8 *BigNumber::AsByteArray(int minSize)
{ {
int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes();

View file

@ -72,6 +72,8 @@ class BigNumber
return t %= bn; return t %= bn;
} }
bool isZero() const;
BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2); BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2);
BigNumber Exp(const BigNumber &); BigNumber Exp(const BigNumber &);

View file

@ -42,8 +42,6 @@ class Sha1Hash
uint8 *GetDigest(void) { return mDigest; }; uint8 *GetDigest(void) { return mDigest; };
int GetLength(void) { return SHA_DIGEST_LENGTH; }; int GetLength(void) { return SHA_DIGEST_LENGTH; };
BigNumber GetBigNumber();
private: private:
SHA_CTX mC; SHA_CTX mC;
uint8 mDigest[SHA_DIGEST_LENGTH]; uint8 mDigest[SHA_DIGEST_LENGTH];

View file

@ -220,12 +220,12 @@ bool Database::CheckRequiredField( char const* table_name, char const* required_
delete result; delete result;
if(!reqName.empty()) if(!reqName.empty())
{
sLog.outErrorDb("Table `%s` have field `%s` but expected `%s`! Not all sql updates applied?",table_name,reqName.c_str(),required_name); sLog.outErrorDb("Table `%s` have field `%s` but expected `%s`! Not all sql updates applied?",table_name,reqName.c_str(),required_name);
return false; else
} sLog.outErrorDb("Table `%s` not have required_* field but expected `%s`! Not all sql updates applied?",table_name,required_name);
} }
else
sLog.outErrorDb("Table `%s` fields list query fail but expected have `%s`! No records in `%s`?",table_name,required_name,table_name);
sLog.outErrorDb("Table `%s` not have required_* field but expected `%s`! Not all sql updates applied?",table_name,required_name);
return false; return false;
} }

View file

@ -26,7 +26,6 @@ SqlDelayThread::SqlDelayThread(Database* db) : m_dbEngine(db), m_running(true)
void SqlDelayThread::run() void SqlDelayThread::run()
{ {
SqlOperation* s;
#ifndef DO_POSTGRESQL #ifndef DO_POSTGRESQL
mysql_thread_init(); mysql_thread_init();
#endif #endif
@ -36,9 +35,9 @@ void SqlDelayThread::run()
// if the running state gets turned off while sleeping // if the running state gets turned off while sleeping
// empty the queue before exiting // empty the queue before exiting
ACE_Based::Thread::Sleep(10); ACE_Based::Thread::Sleep(10);
while (!m_sqlQueue.empty()) SqlOperation* s;
while (m_sqlQueue.next(s))
{ {
s = m_sqlQueue.next();
s->Execute(m_dbEngine); s->Execute(m_dbEngine);
delete s; delete s;
} }

View file

@ -71,9 +71,9 @@ void SqlQuery::Execute(Database *db)
void SqlResultQueue::Update() void SqlResultQueue::Update()
{ {
/// execute the callbacks waiting in the synchronization queue /// execute the callbacks waiting in the synchronization queue
while(!empty()) MaNGOS::IQueryCallback* callback;
while (next(callback))
{ {
MaNGOS::IQueryCallback * callback = next();
callback->Execute(); callback->Execute();
delete callback; delete callback;
} }

View file

@ -30,99 +30,65 @@ namespace ACE_Based
template <class T, class LockType, typename StorageType=std::deque<T> > template <class T, class LockType, typename StorageType=std::deque<T> >
class LockedQueue class LockedQueue
{ {
//! Serialize access to the Queue //! Lock access to the queue.
LockType _lock; LockType _lock;
//! Storage backing the queue //! Storage backing the queue.
StorageType _queue; StorageType _queue;
//! Cancellation flag //! Cancellation flag.
volatile bool _canceled; /*volatile*/ bool _canceled;
public: public:
//! Create a LockedQueue //! Create a LockedQueue.
LockedQueue() : _canceled(false) {} LockedQueue() : _canceled(false) {}
//! Destroy a LockedQueue //! Destroy a LockedQueue.
virtual ~LockedQueue() { } virtual ~LockedQueue() { }
/** //! Adds an item to the queue.
* @see Queue::add(const T& item)
*/
void add(const T& item) void add(const T& item)
{ {
ACE_Guard<LockType> g(this->_lock); ACE_Guard<LockType> g(this->_lock);
ASSERT(!this->_canceled); //ASSERT(!this->_canceled);
// throw Cancellation_Exception(); // throw Cancellation_Exception();
this->_queue.push_back(item); _queue.push_back(item);
} }
/** //! Gets the next result in the queue, if any.
* @see Queue::next() bool next(T& result)
*/
T next()
{ {
ACE_Guard<LockType> g(this->_lock); ACE_Guard<LockType> g(this->_lock);
ASSERT (!_queue.empty() || !this->_canceled); if (_queue.empty())
return false;
//ASSERT (!_queue.empty() || !this->_canceled);
// throw Cancellation_Exception(); // throw Cancellation_Exception();
T item = this->_queue.front(); result = _queue.front();
this->_queue.pop_front(); _queue.pop_front();
return item; return true;
} }
T front() //! Cancels the queue.
{
ACE_Guard<LockType> g(this->_lock);
ASSERT (!this->_queue.empty());
// throw NoSuchElement_Exception();
return this->_queue.front();
}
/**
* @see Queue::cancel()
*/
void cancel() void cancel()
{ {
ACE_Guard<LockType> g(this->_lock); ACE_Guard<LockType> g(this->_lock);
this->_canceled = true; _canceled = true;
} }
/** //! Checks if the queue is cancelled.
* @see Queue::isCanceled() bool cancelled()
*/
bool isCanceled()
{
// Faster check since the queue will not become un-canceled
if(this->_canceled)
return true;
ACE_Guard<LockType> g(this->_lock);
return this->_canceled;
}
/**
* @see Queue::size()
*/
size_t size()
{ {
ACE_Guard<LockType> g(this->_lock); ACE_Guard<LockType> g(this->_lock);
return this->_queue.size();
}
bool empty() return _canceled;
{
ACE_Guard<LockType> g(this->_lock);
return this->_queue.empty();
} }
}; };
} }

View file

@ -441,3 +441,23 @@ void vutf8printf(FILE *out, const char *str, va_list* ap)
vfprintf(out, str, *ap); vfprintf(out, str, *ap);
#endif #endif
} }
void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result)
{
std::ostringstream ss;
for(uint32 i=0; i<arrayLen; ++i)
{
for(uint8 j=0; j<2; ++j)
{
unsigned char nibble = 0x0F & (bytes[i]>>((1-j)*4));
char encodedNibble;
if(nibble < 0x0A)
encodedNibble = '0'+nibble;
else
encodedNibble = 'A'+nibble-0x0A;
ss << encodedNibble;
}
}
result = ss.str();
}

View file

@ -289,4 +289,5 @@ void vutf8printf(FILE *out, const char *str, va_list* ap);
bool IsIPAddress(char const* ipaddress); bool IsIPAddress(char const* ipaddress);
uint32 CreatePIDFile(const std::string& filename); uint32 CreatePIDFile(const std::string& filename);
void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result);
#endif #endif

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "8441" #define REVISION_NR "8467"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_8433_01_characters_character_account_data" #define REVISION_DB_CHARACTERS "required_8433_01_characters_character_account_data"
#define REVISION_DB_MANGOS "required_8416_01_mangos_spell_learn_spell" #define REVISION_DB_MANGOS "required_8462_01_mangos_creature_ai_texts"
#define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__