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,
`creature_ai_version` varchar(120) default NULL,
`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';
--
@ -1043,7 +1043,7 @@ CREATE TABLE `creature_ai_texts` (
`sound` mediumint(8) unsigned NOT NULL DEFAULT '0',
`type` 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,
PRIMARY KEY (`entry`)
) 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),
(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),
(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),
(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),
@ -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),
(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),
(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),
(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),
@ -17840,6 +17841,7 @@ INSERT INTO `spell_proc_event` VALUES
(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),
(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),
(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),

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 \
8416_01_mangos_spell_learn_spell.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
## Additional files to include when running 'make dist'
@ -172,4 +175,7 @@ EXTRA_DIST = \
8412_01_mangos_mangos_string.sql \
8416_01_mangos_spell_learn_spell.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

View file

@ -22,6 +22,7 @@
#include "Player.h"
#include "Policies/SingletonImp.h"
#include "Util.h"
#include "Auth/Sha1.h"
extern DatabaseType loginDatabase;
@ -41,17 +42,12 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass
normalizeString(username);
normalizeString(password);
loginDatabase.escape_string(username);
loginDatabase.escape_string(password);
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str());
if(result)
if(GetId(username))
{
delete result;
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
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_passwd);
loginDatabase.escape_string(new_uname);
loginDatabase.escape_string(new_passwd);
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))
std::string safe_new_uname = new_uname;
loginDatabase.escape_string(safe_new_uname);
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_OK;
@ -131,18 +129,19 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname,
AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
{
QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid);
if(!result)
std::string username;
if(!GetName(accid, username))
return AOR_NAME_NOT_EXIST; // account doesn't exist
delete result;
if (utf8length(new_passwd) > MAX_ACCOUNT_STR)
return AOR_PASS_TOO_LONG;
normalizeString(new_passwd);
loginDatabase.escape_string(new_passwd);
if(!loginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")") WHERE id='%d'", new_passwd.c_str(), accid))
// also reset s and v to force update at next realmd login
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_OK;
@ -190,10 +189,13 @@ bool AccountMgr::GetName(uint32 acc_id, std::string &name)
bool AccountMgr::CheckPassword(uint32 accid, std::string passwd)
{
normalizeString(passwd);
loginDatabase.escape_string(passwd);
std::string username;
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)
{
delete result;
@ -215,3 +217,19 @@ bool AccountMgr::normalizeString(std::string& 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 GetSecurity(uint32 acc_id);
bool GetName(uint32 acc_id, std::string &name);
std::string CalculateShaPassHash(std::string& name, std::string& password);
static bool normalizeString(std::string& utf8str);
};

View file

@ -1017,10 +1017,22 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
{
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_SPELL:
if(miscvalue1 && miscvalue1!=achievementCriteria->learn_spell.spellID)
continue;
@ -1279,25 +1291,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetVisibleFactionCount());
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:
{
if (miscvalue1 && miscvalue1 != achievementCriteria->learn_skill_line.skillLine)

View file

@ -119,9 +119,6 @@ class CharacterHandler
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
uint8 num = 0;

View file

@ -1480,7 +1480,7 @@ valid examples:
bool foundName = false;
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;
break;

View file

@ -1320,7 +1320,7 @@ struct SpellEntry
uint32 AttributesEx3; // 7 m_attributesExC
uint32 AttributesEx4; // 8 m_attributesExD
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 Stances; // 12 m_shapeshiftMask
// uint32 unk_320_2; // 13 3.2.0

View file

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

View file

@ -54,7 +54,7 @@ class MANGOS_DLL_DECL DestinationHolder
uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true);
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
float GetDistance2dFromDestSq(const WorldObject &obj) const;
float GetDistance3dFromDestSq(const WorldObject &obj) const;
private:
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
DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update, bool micro_movement)
{
if(!micro_movement)
if (!micro_movement)
{
i_tracker.Update(diff);
i_timeElapsed += diff;
if( i_tracker.Passed() || force_update )
if (i_tracker.Passed() || force_update)
{
ResetUpdate();
if(!i_destSet) return true;
if (!i_destSet) return true;
float x,y,z;
GetLocationNowNoMicroMovement(x, y, z);
if( x == -431602080 )
return false;
if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y )
if (traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y || traveller.GetTraveller().GetPositionZ() != z)
{
float ori = traveller.GetTraveller().GetAngle(x, y);
traveller.Relocation(x, y, z, ori);
@ -116,24 +116,21 @@ DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff,
}
i_tracker.Update(diff);
i_timeElapsed += diff;
if( i_tracker.Passed() || force_update )
if (i_tracker.Passed() || force_update)
{
ResetUpdate();
if(!i_destSet) return true;
float x,y,z;
if (!i_destSet) return true;
if(!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT))
if (!traveller.GetTraveller().hasUnitState(UNIT_STAT_MOVING | UNIT_STAT_IN_FLIGHT))
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
else
GetLocationNow(traveller.GetTraveller().GetBaseMap(), x, y, z, false);
if( x == -431602080 )
return false;
if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y )
if (traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y || traveller.GetTraveller().GetPositionZ() != z)
{
float ori = traveller.GetTraveller().GetAngle(x, y);
traveller.Relocation(x, y, z, ori);
@ -160,13 +157,13 @@ template<typename TRAVELLER>
void
DestinationHolder<TRAVELLER>::GetLocationNow(const Map * map, float &x, float &y, float &z, bool is3D) const
{
if( HasArrived() )
if (HasArrived())
{
x = i_destX;
y = i_destY;
z = i_destZ;
}
else if(HasDestination())
else if (HasDestination())
{
double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime;
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;
float z2 = i_fromZ + distanceZ;
// All that is not finished but previous code neither... Traveller need be able to swim.
if(is3D)
if (is3D)
z = z2;
else
{
@ -193,11 +190,11 @@ DestinationHolder<TRAVELLER>::GetLocationNow(const Map * map, float &x, float &y
template<typename TRAVELLER>
float
DestinationHolder<TRAVELLER>::GetDistance2dFromDestSq(const WorldObject &obj) const
DestinationHolder<TRAVELLER>::GetDistance3dFromDestSq(const WorldObject &obj) const
{
float 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>
@ -211,7 +208,7 @@ template<typename TRAVELLER>
void
DestinationHolder<TRAVELLER>::GetLocationNowNoMicroMovement(float &x, float &y, float &z) const
{
if( HasArrived() )
if (HasArrived())
{
x = i_destX;
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);
// GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3
SetGoState(go_state);
SetGoType(GameobjectTypes(goinfo->type));
SetGoArtKit(0); // unknown what this is
SetGoAnimProgress(animprogress);
//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
{
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;
uint8 slot;
uint32 count;
uint8 Slot;
uint32 Count;
};
typedef std::vector<GuildItemPosCount> GuildItemPosCountVec;
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 OFFnote;
uint32 RankId;
uint32 zoneId;
uint8 level;
uint8 Class;
uint32 BankResetTimeMoney;
uint32 BankRemMoney;
uint32 BankResetTimeTab[GUILD_BANK_MAX_TABS];
@ -264,7 +264,7 @@ struct MemberSlot
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)
{
@ -273,8 +273,8 @@ struct RankInfo
}
}
std::string name;
uint32 rights;
std::string Name;
uint32 Rights;
uint32 BankMoneyPerDay;
uint32 TabRight[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)
{
if(itr->second.name == name)
if(itr->second.Name == name)
{
guid = itr->first;
return &itr->second;

View file

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

View file

@ -331,7 +331,8 @@ enum MangosStrings
LANG_CUSTOMIZE_PLAYER = 345,
LANG_CUSTOMIZE_PLAYER_GUID = 346,
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
LANG_SCRIPTS_RELOADED = 400,

View file

@ -420,7 +420,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args)
PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),"");
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
if (target->isInFlight())

View file

@ -700,15 +700,24 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
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);
SetSentErrorMessage(true);
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();
float x = float(chr->GetPositionX());
float y = float(chr->GetPositionY());
@ -719,7 +728,7 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
GameObject* pGameObj = new 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;
return false;
@ -742,14 +751,14 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
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);
// TODO: is it really necessary to add both the real and DB table guid here ?
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;
}

View file

@ -34,8 +34,8 @@ enum MailShowFlags
MAIL_SHOW_UNK0 = 0x0001,
MAIL_SHOW_DELETE = 0x0002, // forced show delete button instead return button
MAIL_SHOW_AUCTION = 0x0004, // from old comment
MAIL_SHOW_COD = 0x0008, // show subject prefix
MAIL_SHOW_UNK4 = 0x0010,
MAIL_SHOW_UNK2 = 0x0008, // unknown, COD will be shown even without that flag
MAIL_SHOW_RETURN = 0x0010,
};
void MailItem::deleteItem( bool inDB )
@ -321,7 +321,16 @@ void WorldSession::HandleMailDelete(WorldPacket & recv_data )
pl->m_mailsUpdated = true;
Mail *m = pl->GetMail(mailId);
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;
}
pl->SendMailResult(mailId, MAIL_DELETED, MAIL_OK);
}
@ -594,8 +603,8 @@ void WorldSession::HandleGetMailList(WorldPacket & recv_data )
show_flags |= MAIL_SHOW_DELETE;
if ((*itr)->messageType == MAIL_AUCTION)
show_flags |= MAIL_SHOW_AUCTION;
if ((*itr)->COD)
show_flags |= MAIL_SHOW_COD;
if ((*itr)->HasItems() && (*itr)->messageType == MAIL_NORMAL)
show_flags |= MAIL_SHOW_RETURN;
data << uint16(0x0040); // unknown 2.3.0, different values
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 ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
{
IsActivateToQuest = true;
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
}
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
}
else if (isType(TYPEMASK_UNIT))
{
@ -711,18 +710,27 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
switch(((GameObject*)this)->GetGoType())
{
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;
case GAMEOBJECT_TYPE_GOOBER:
*data << uint32(1);
*data << uint16(1);
*data << uint16(-1);
break;
default:
*data << uint32(0); // unknown, not happen.
// unknown, not happen.
*data << uint16(0);
*data << uint16(-1);
break;
}
}
else
*data << uint32(0); // disable quest object
{
// disable quest object
*data << uint16(0);
*data << uint16(-1);
}
}
else
*data << m_uint32Values[ index ]; // other cases

View file

@ -1220,7 +1220,7 @@ void ObjectMgr::LoadGameobjects()
uint32 entry = fields[ 1].GetUInt32();
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);
continue;
@ -1232,7 +1232,7 @@ void ObjectMgr::LoadGameobjects()
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);
continue;
@ -1272,13 +1272,13 @@ void ObjectMgr::LoadGameobjects()
int16 gameEvent = fields[16].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);
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);
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);
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)

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)
m_baseRatingValue[i] = 0;
m_baseSpellDamage = 0;
m_baseSpellHealing = 0;
m_baseSpellPower = 0;
m_baseFeralAP = 0;
m_baseManaRegen = 0;
m_armorPenetrationPct = 0.0f;
// Honor System
m_lastHonorUpdateTime = time(NULL);
@ -809,10 +809,10 @@ void Player::StopMirrorTimer(MirrorTimerType Type)
GetSession()->SendPacket( &data );
}
void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
{
if(!isAlive() || isGameMaster())
return;
return 0;
// Absorb, resist some environmental damage type
uint32 absorb = 0;
@ -834,7 +834,7 @@ void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
data << uint32(resist);
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())
{
@ -849,6 +849,8 @@ void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type);
}
return final_damage;
}
int32 Player::getMaxTimer(MirrorTimerType timer)
@ -4980,6 +4982,8 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply)
}
break;
case CR_ARMOR_PENETRATION:
if(affectStats)
UpdateArmorPenetration();
break;
}
}
@ -6666,12 +6670,6 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
case ITEM_MOD_FERAL_ATTACK_POWER:
ApplyFeralAPBonus(int32(val), apply);
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:
ApplyManaRegenBonus(int32(val), apply);
break;
@ -6679,8 +6677,11 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl
ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply);
break;
case ITEM_MOD_SPELL_POWER:
ApplySpellHealingBonus(int32(val), apply);
ApplySpellDamageBonus(int32(val), apply);
ApplySpellPowerBonus(int32(val), apply);
break;
// depricated item mods
case ITEM_MOD_SPELL_HEALING_DONE:
case ITEM_MOD_SPELL_DAMAGE_DONE:
break;
}
}
@ -10448,9 +10449,15 @@ Item* Player::EquipItem( uint16 pos, Item *pItem, bool update )
ApplyEquipCooldown(pItem);
if( slot == EQUIPMENT_SLOT_MAINHAND )
{
UpdateExpertise(BASE_ATTACK);
UpdateArmorPenetration();
}
else if( slot == EQUIPMENT_SLOT_OFFHAND )
{
UpdateExpertise(OFF_ATTACK);
UpdateArmorPenetration();
}
}
else
{
@ -10590,9 +10597,13 @@ void Player::RemoveItem( uint8 bag, uint8 slot, bool update )
}
UpdateExpertise(BASE_ATTACK);
UpdateArmorPenetration();
}
else if( slot == EQUIPMENT_SLOT_OFFHAND )
{
UpdateExpertise(OFF_ATTACK);
UpdateArmorPenetration();
}
}
}
// need update known currency
@ -10701,10 +10712,16 @@ void Player::DestroyItem( uint8 bag, uint8 slot, bool update )
RemoveItemDependentAurasAndCasts(pItem);
// update expertise
if ( slot == EQUIPMENT_SLOT_MAINHAND )
if( slot == EQUIPMENT_SLOT_MAINHAND )
{
UpdateExpertise(BASE_ATTACK);
UpdateArmorPenetration();
}
else if( slot == EQUIPMENT_SLOT_OFFHAND )
{
UpdateExpertise(OFF_ATTACK);
UpdateArmorPenetration();
}
// equipment visual show
SetVisibleItemSlot(slot, NULL);
@ -11939,14 +11956,6 @@ void Player::ApplyEnchantment(Item *item, EnchantmentSlot slot, bool apply, bool
((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply);
sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount);
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:
((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply);
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);
break;
case ITEM_MOD_SPELL_POWER:
((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply);
((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply);
((Player*)this)->ApplySpellPowerBonus(enchant_amount, apply);
sLog.outDebug("+ %u SPELL_POWER", enchant_amount);
break;
case ITEM_MOD_SPELL_HEALING_DONE: // deprecated
case ITEM_MOD_SPELL_DAMAGE_DONE: // deprecated
default:
break;
}
@ -18690,9 +18700,9 @@ void Player::UpdateForQuestWorldObjects()
continue;
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);
break;
@ -19914,10 +19924,11 @@ void Player::HandleFall(MovementInfo const& movementInfo)
if (GetDummyAura(43621))
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
if (isAlive())
// recheck alive, might have died of EnvironmentalDamage, avoid cases when player die in fact like Spirit of Redemption case
if (isAlive() && final_damage < original_health)
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 UpdateShieldBlockValue();
void UpdateDamagePhysical(WeaponAttackType attType);
void ApplySpellDamageBonus(int32 amount, bool apply);
void ApplySpellHealingBonus(int32 amount, bool apply);
void ApplySpellPowerBonus(int32 amount, bool apply);
void UpdateSpellDamageAndHealingBonus();
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 GetSpellCritDamageReduction(uint32 damage) const;
uint32 GetDotDamageReduction(uint32 damage) const;
uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage;}
uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing;}
uint32 GetBaseSpellPowerBonus() { return m_baseSpellPower; }
float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const;
void UpdateBlockPercentage();
@ -1735,6 +1733,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void UpdateAllSpellCritChances();
void UpdateSpellCritChance(uint32 school);
void UpdateExpertise(WeaponAttackType attType);
void UpdateArmorPenetration();
void ApplyManaRegenBonus(int32 amount, bool apply);
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]; }
void _ApplyAllStatBonuses();
void _RemoveAllStatBonuses();
float GetArmorPenetrationPct() const { return m_armorPenetrationPct; }
void _ApplyWeaponDependentAuraMods(Item *item, WeaponAttackType attackType, 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 ***/
/*********************************************************/
void EnvironmentalDamage(EnviromentalDamage type, uint32 damage);
uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage);
/*********************************************************/
/*** FLOOD FILTER SYSTEM ***/
@ -2364,10 +2364,10 @@ class MANGOS_DLL_SPEC Player : public Unit
float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint16 m_baseSpellDamage;
uint16 m_baseSpellHealing;
uint16 m_baseSpellPower;
uint16 m_baseFeralAP;
uint16 m_baseManaRegen;
float m_armorPenetrationPct;
SpellModList m_spellMods[MAX_SPELLMOD];
int32 m_SpellModRemoveCount;

View file

@ -179,11 +179,6 @@ enum SpellSchoolMask
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)
{
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_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_UNK3 0x00000008 // 3
#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_UNK9 0x00000200 // 9
#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_UNK13 0x00002000 // 13
#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::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
&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::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
&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;
}
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 HandleNoReagentUseAura(bool Apply, bool Real);
void HandlePhase(bool Apply, bool Real);
void HandleModTargetArmorPct(bool Apply, bool Real);
virtual ~Aura();

View file

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

View file

@ -708,8 +708,6 @@ void SpellMgr::LoadSpellTargetPositions()
bar.step();
++count;
uint32 Spell_ID = fields[0].GetUInt32();
SpellTargetPosition st;
@ -756,6 +754,7 @@ void SpellMgr::LoadSpellTargetPositions()
}
mSpellTargetPositions[Spell_ID] = st;
++count;
} while( result->NextRow() );
@ -2747,7 +2746,7 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
while (groupEntry)
{
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;
if (found || !groupEntry->nextGroup)
break;
@ -2755,7 +2754,7 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
groupEntry = sAreaGroupStore.LookupEntry(groupEntry->nextGroup);
}
if(!found)
if (!found)
return SPELL_FAILED_INCORRECT_AREA;
}
@ -2764,10 +2763,18 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
{
uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id);
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;
}
// 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)
SpellAreaMapBounds saBounds = spellmgr.GetSpellAreaMapBounds(spellInfo->Id);
if (saBounds.first != saBounds.second)

View file

@ -91,17 +91,12 @@ bool Player::UpdateStats(Stats stat)
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
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)
ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, amount, apply);;
}
@ -137,6 +132,7 @@ bool Player::UpdateAllStats()
UpdateAllSpellCritChances();
UpdateDefenseBonusesMod();
UpdateShieldBlockValue();
UpdateArmorPenetration();
UpdateSpellDamageAndHealingBonus();
UpdateManaRegen();
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)
{
m_baseManaRegen+= apply ? amount : -amount;

View file

@ -136,7 +136,7 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
return true;
// 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())
owner.StopMoving();
@ -149,9 +149,9 @@ TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
Traveller<T> traveller(owner);
if( !i_destinationHolder.HasDestination() )
if (!i_destinationHolder.HasDestination())
_setTargetLocation(owner);
if( owner.IsStopped() && !i_destinationHolder.HasArrived() )
if (owner.IsStopped() && !i_destinationHolder.HasArrived())
{
owner.addUnitState(UNIT_STAT_CHASE);
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.
// 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::
_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
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());
if(( owner.IsStopped() && !i_destinationHolder.HasArrived() ) || i_recalculateTravel )
if ((owner.IsStopped() && !i_destinationHolder.HasArrived()) || i_recalculateTravel)
{
i_recalculateTravel = false;
//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;
float armor = pVictim->GetArmor();
// Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
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)
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();
if ( levelModifier > 59 )
if (levelModifier > 59)
levelModifier = levelModifier + (4.5f * (levelModifier-59));
float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40);
tmpvalue = tmpvalue/(1.0f + tmpvalue);
if(tmpvalue < 0.0f)
if (tmpvalue < 0.0f)
tmpvalue = 0.0f;
if(tmpvalue > 0.75f)
if (tmpvalue > 0.75f)
tmpvalue = 0.75f;
newdamage = uint32(damage - (damage * tmpvalue));
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
uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
Unit* target = NULL;
int32 basepoints0 = 0;
int32 basepoints[3] = {0, 0, 0};
if(triggeredByAura->GetModifier()->m_auraname == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE)
basepoints0 = triggerAmount;
basepoints[0] = triggerAmount;
Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((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)
{
// Pct value stored in dummy
basepoints0 = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100;
basepoints[0] = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100;
target = pVictim;
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);
// Drain Soul
CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
CastCustomSpell(this, 18371, &basepoints[0], NULL, NULL, true, castItem, triggeredByAura);
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);
return false;
}
basepoints0 = damage * triggerAmount / 100 / 3;
basepoints[0] = damage * triggerAmount / 100 / 3;
target = this;
}
break;
@ -6574,7 +6577,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
{
if (triggerAmount == 0)
return false;
basepoints0 = triggerAmount * GetMaxHealth() / 100;
basepoints[0] = triggerAmount * GetMaxHealth() / 100;
trigger_spell_id = 34299;
}
break;
@ -6643,7 +6646,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
}
// percent stored in effect 1 (class scripts) base points
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;
target = this;
}
@ -6732,7 +6735,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
{
if(!procSpell)
return false;
basepoints0 = procSpell->manaCost * 35 / 100;
basepoints[0] = procSpell->manaCost * 35 / 100;
trigger_spell_id = 23571;
target = this;
}
@ -6746,7 +6749,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
if(pVictim && pVictim->isAlive())
pVictim->getThreatManager().modifyThreatPercent(this,-10);
basepoints0 = triggerAmount * GetMaxHealth() / 100;
basepoints[0] = triggerAmount * GetMaxHealth() / 100;
trigger_spell_id = 31616;
target = this;
}
@ -6781,7 +6784,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
if (!((Player*)this)->isHonorOrXPTarget(pVictim))
return false;
trigger_spell_id = 50475;
basepoints0 = damage * triggerAmount / 100;
basepoints[0] = damage * triggerAmount / 100;
}
break;
}
@ -6811,7 +6814,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// This spell originally trigger 13567 - Dummy Trigger (vs dummy efect)
case 26467:
{
basepoints0 = damage * 15 / 100;
basepoints[0] = damage * 15 / 100;
target = pVictim;
trigger_spell_id = 26470;
break;
@ -6917,13 +6920,13 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
// Bloodthirst (($m/100)% of max health)
case 23880:
{
basepoints0 = int32(GetMaxHealth() * triggerAmount / 100);
basepoints[0] = int32(GetMaxHealth() * triggerAmount / 100);
break;
}
// Shamanistic Rage triggered spell
case 30824:
{
basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100);
basepoints[0] = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100);
break;
}
// Enlightenment (trigger only from mana cost spells)
@ -6933,6 +6936,34 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return false;
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
case 50227:
{
@ -7018,8 +7049,12 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
if(!target || target!=this && !target->isAlive())
return false;
if(basepoints0)
CastCustomSpell(target,trigger_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
if(basepoints[0] || basepoints[1] || basepoints[2])
CastCustomSpell(target,trigger_spell_id,
basepoints[0] ? &basepoints[0] : NULL,
basepoints[1] ? &basepoints[1] : NULL,
basepoints[2] ? &basepoints[2] : NULL,
true,castItem,triggeredByAura);
else
CastSpell(target,trigger_spell_id,true,castItem,triggeredByAura);
@ -8267,7 +8302,7 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
if (GetTypeId() == TYPEID_PLAYER)
{
// Base value
DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellDamageBonus();
DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellPowerBonus();
// Damage bonus from stats
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)
{
// Base value
AdvertisedBenefit +=((Player*)this)->GetBaseSpellHealingBonus();
AdvertisedBenefit +=((Player*)this)->GetBaseSpellPowerBonus();
// Healing bonus from stats
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()))
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
if(creatureNotInCombat && ((Creature*)this)->AI())
((Creature*)this)->AI()->EnterCombat(enemy);
if (creatureNotInCombat)
{
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
if (((Creature*)this)->AI())
((Creature*)this)->AI()->EnterCombat(enemy);
}
}
void Unit::ClearInCombat()
@ -9182,8 +9222,13 @@ void Unit::ClearInCombat()
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
// 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);
}
else
((Player*)this)->UpdatePotionCooldown();
}
@ -9193,7 +9238,11 @@ bool Unit::isTargetableForAttack() const
if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster())
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 IsInWorld() && isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;

View file

@ -491,38 +491,38 @@ enum UnitVisibility
// Value masks for UNIT_FIELD_FLAGS
enum UnitFlags
{
UNIT_FLAG_UNK_0 = 0x00000001,
UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable
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_RENAME = 0x00000010,
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_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_UNK_9 = 0x00000200, // 3.0.3 - makes you unable to attack everything
UNIT_FLAG_LOOTING = 0x00000400, // loot animation
UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8
UNIT_FLAG_UNK_15 = 0x00008000,
UNIT_FLAG_UNK_16 = 0x00010000,
UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok
UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok
UNIT_FLAG_IN_COMBAT = 0x00080000,
UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
UNIT_FLAG_CONFUSED = 0x00400000,
UNIT_FLAG_FLEEING = 0x00800000,
UNIT_FLAG_PLAYER_CONTROLLED= 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature
UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
UNIT_FLAG_SKINNABLE = 0x04000000,
UNIT_FLAG_MOUNT = 0x08000000,
UNIT_FLAG_UNK_28 = 0x10000000,
UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell
UNIT_FLAG_SHEATHE = 0x40000000,
UNIT_FLAG_UNK_31 = 0x80000000
UNIT_FLAG_UNK_0 = 0x00000001,
UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable
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_RENAME = 0x00000010,
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_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE
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_LOOTING = 0x00000400, // loot animation
UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3
UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8
UNIT_FLAG_UNK_15 = 0x00008000,
UNIT_FLAG_UNK_16 = 0x00010000,
UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok
UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok
UNIT_FLAG_IN_COMBAT = 0x00080000,
UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
UNIT_FLAG_CONFUSED = 0x00400000,
UNIT_FLAG_FLEEING = 0x00800000,
UNIT_FLAG_PLAYER_CONTROLLED = 0x01000000, // used in spell Eyes of the Beast for pet... let attack by controlled creature
UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
UNIT_FLAG_SKINNABLE = 0x04000000,
UNIT_FLAG_MOUNT = 0x08000000,
UNIT_FLAG_UNK_28 = 0x10000000,
UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell
UNIT_FLAG_SHEATHE = 0x40000000,
UNIT_FLAG_UNK_31 = 0x80000000
};
// Value masks for UNIT_FIELD_FLAGS_2

View file

@ -112,8 +112,9 @@ World::~World()
m_weathers.clear();
while (!cliCmdQueue.empty())
delete cliCmdQueue.next();
CliCommandHolder* command;
while (cliCmdQueue.next(command))
delete command;
VMAP::VMapFactory::clear();
@ -2004,11 +2005,9 @@ void World::SendServerMessage(ServerMessageType type, const char *text, Player*
void World::UpdateSessions( uint32 diff )
{
///- Add new sessions
while(!addSessQueue.empty())
{
WorldSession* sess = addSessQueue.next ();
WorldSession* sess;
while(addSessQueue.next(sess))
AddSession_ (sess);
}
///- Then send an update signal to remaining ones
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
void World::ProcessCliCommands()
{
if (cliCmdQueue.empty())
return;
CliCommandHolder::Print* zprint = NULL;
CliCommandHolder::Print* zprint;
while (!cliCmdQueue.empty())
CliCommandHolder* command;
while (cliCmdQueue.next(command))
{
sLog.outDebug("CLI command under processing...");
CliCommandHolder *command = cliCmdQueue.next();
zprint = command->m_print;
CliHandler(zprint).ParseCommands(command->m_command);
delete command;
}
// print the console message here so it looks right
zprint("mangos>");
if (zprint)
zprint("mangos>");
}
void World::InitResultQueue()

View file

@ -69,11 +69,9 @@ WorldSession::~WorldSession()
}
///- empty incoming packet queue
while(!_recvQueue.empty())
{
WorldPacket *packet = _recvQueue.next ();
WorldPacket* packet;
while(_recvQueue.next(packet))
delete packet;
}
}
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
/// 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
sLog.outError( "MOEP: %s (0x%.4X)",
LookupOpcodeName(packet->GetOpcode()),

View file

@ -766,7 +766,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
LocaleConstant locale;
std::string account;
Sha1Hash sha1;
BigNumber v, s, g, N, x, I;
BigNumber v, s, g, N;
WorldPacket packet, SendAddonPacked;
BigNumber K;
@ -799,12 +799,11 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
"sessionkey, " //2
"last_ip, " //3
"locked, " //4
"sha_pass_hash, " //5
"v, " //6
"s, " //7
"expansion, " //8
"mutetime, " //9
"locale " //10
"v, " //5
"s, " //6
"expansion, " //7
"mutetime, " //8
"locale " //9
"FROM account "
"WHERE username = '%s'",
safe_account.c_str ());
@ -823,57 +822,21 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
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");
g.SetDword (7);
I.SetHexStr (fields[5].GetString ());
//In case of leading zeros in the I hash, restore them
uint8 mDigest[SHA_DIGEST_LENGTH];
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);
v.SetHexStr(fields[5].GetString());
s.SetHexStr (fields[6].GetString ());
const char* sStr = s.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,
vold,
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*) vStr);
@ -899,9 +862,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
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)
locale = LOCALE_enUS;
@ -909,13 +872,10 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
// Re-check account ban (same check as in realmd)
QueryResult *banresult =
loginDatabase.PQuery ("SELECT "
"bandate, "
"unbandate "
"FROM account_banned "
"WHERE id = '%u' "
"AND active = 1",
id);
loginDatabase.PQuery ("SELECT 1 FROM account_banned WHERE id = %u AND active = 1 "
"UNION "
"SELECT 1 FROM ip_banned WHERE ip = '%s'",
id, GetRemoteAddress().c_str());
if (banresult) // if account banned
{

View file

@ -246,7 +246,6 @@ void AuthSocket::OnAccept()
sLog.outBasic("Accepting connection from '%s:%d'",
GetRemoteAddress().c_str(), GetRemotePort());
s.SetRand(s_BYTE_SIZE * 8);
}
/// Read the packet from the client
@ -295,6 +294,8 @@ void AuthSocket::OnRead()
/// Make the SRP6 calculation from hash in dB
void AuthSocket::_SetVSFields(const std::string& rI)
{
s.SetRand(s_BYTE_SIZE * 8);
BigNumber I;
I.SetHexStr(rI.c_str());
@ -396,7 +397,7 @@ bool AuthSocket::_HandleLogonChallenge()
///- Get the account details from the account table
// 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 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
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);
BigNumber gmod = g.ModExp(b, N);
@ -591,8 +606,13 @@ bool AuthSocket::_HandleLogonProof()
///- Continue the SRP6 calculation based on data received from the client
BigNumber A;
A.SetBinary(lp.A, 32);
// SRP safeguard: abort if A==0
if (A.isZero())
return false;
Sha1Hash sha;
sha.UpdateBigNumbers(&A, &B, NULL);
sha.Finalize();
@ -603,7 +623,7 @@ bool AuthSocket::_HandleLogonProof()
uint8 t[32];
uint8 t1[16];
uint8 vK[40];
memcpy(t, S.AsByteArray(), 32);
memcpy(t, S.AsByteArray(32), 32);
for (int i = 0; i < 16; ++i)
{
t1[i] = t[i * 2];
@ -905,8 +925,6 @@ bool AuthSocket::_HandleRealmList()
SendBuf((char const*)hdr.contents(), hdr.size());
// Set check field before possible relogin to realm
_SetVSFields(rI);
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);
return 1;
}
sLog.Initialize();
sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
sLog.outString( "<Ctrl-C> to stop.\n" );

View file

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

View file

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

View file

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

View file

@ -220,12 +220,12 @@ bool Database::CheckRequiredField( char const* table_name, char const* required_
delete result;
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);
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;
}

View file

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

View file

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

View file

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

View file

@ -441,3 +441,23 @@ void vutf8printf(FILE *out, const char *str, va_list* ap)
vfprintf(out, str, *ap);
#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);
uint32 CreatePIDFile(const std::string& filename);
void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result);
#endif

View file

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

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#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"
#endif // __REVISION_SQL_H__