diff options
Diffstat (limited to 'src')
56 files changed, 1817 insertions, 1573 deletions
diff --git a/src/game/AccountMgr.cpp b/src/game/AccountMgr.cpp index f2168cbc090..74bc4cd2dcc 100644 --- a/src/game/AccountMgr.cpp +++ b/src/game/AccountMgr.cpp @@ -26,7 +26,7 @@ #include "Player.h" #include "Util.h" -extern DatabaseType LoginDatabase; +extern DatabaseType loginDatabase; INSTANTIATE_SINGLETON_1(AccountMgr); @@ -44,26 +44,26 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass normalizeString(username); normalizeString(password); - LoginDatabase.escape_string(username); - LoginDatabase.escape_string(password); + loginDatabase.escape_string(username); + loginDatabase.escape_string(password); - QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE username = '%s'", username.c_str()); + 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 } - if(!LoginDatabase.PExecute("INSERT INTO account(username,sha_pass_hash,joindate) VALUES('%s',SHA1(CONCAT('%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',SHA1(CONCAT('%s',':','%s')),NOW())", username.c_str(), username.c_str(), 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"); + 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"); return AOR_OK; // everything's fine } AccountOpResult AccountMgr::DeleteAccount(uint32 accid) { - QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); if(!result) return AOR_NAME_NOT_EXIST; // account doesn't exist delete result; @@ -94,13 +94,13 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid) // table realm specific but common for all characters of account for realm CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid); - LoginDatabase.BeginTransaction(); + loginDatabase.BeginTransaction(); bool res = - LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) && - LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid); + loginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid) && + loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid); - LoginDatabase.CommitTransaction(); + loginDatabase.CommitTransaction(); if(!res) return AOR_DB_INTERNAL_ERROR; // unexpected error; @@ -110,7 +110,7 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid) AccountOpResult AccountMgr::ChangeUsername(uint32 accid, std::string new_uname, std::string new_passwd) { - QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); if(!result) return AOR_NAME_NOT_EXIST; // account doesn't exist delete result; @@ -124,9 +124,9 @@ 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(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid)) + loginDatabase.escape_string(new_uname); + loginDatabase.escape_string(new_passwd); + if(!loginDatabase.PExecute("UPDATE account SET username='%s',sha_pass_hash=SHA1(CONCAT('%s',':','%s')) WHERE id='%d'", new_uname.c_str(), new_uname.c_str(), new_passwd.c_str(), accid)) return AOR_DB_INTERNAL_ERROR; // unexpected error return AOR_OK; @@ -134,7 +134,7 @@ 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); + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d'", accid); if(!result) return AOR_NAME_NOT_EXIST; // account doesn't exist delete result; @@ -144,8 +144,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd) normalizeString(new_passwd); - LoginDatabase.escape_string(new_passwd); - if(!LoginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd.c_str(), accid)) + loginDatabase.escape_string(new_passwd); + if(!loginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1(CONCAT(username,':','%s')) WHERE id='%d'", new_passwd.c_str(), accid)) return AOR_DB_INTERNAL_ERROR; // unexpected error return AOR_OK; @@ -153,8 +153,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd) uint32 AccountMgr::GetId(std::string username) { - LoginDatabase.escape_string(username); - QueryResult *result = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str()); + loginDatabase.escape_string(username); + QueryResult *result = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", username.c_str()); if(!result) return 0; else @@ -167,7 +167,7 @@ uint32 AccountMgr::GetId(std::string username) uint32 AccountMgr::GetSecurity(uint32 acc_id) { - QueryResult *result = LoginDatabase.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id); + QueryResult *result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE id = '%u'", acc_id); if(result) { uint32 sec = (*result)[0].GetUInt32(); @@ -180,7 +180,7 @@ uint32 AccountMgr::GetSecurity(uint32 acc_id) bool AccountMgr::GetName(uint32 acc_id, std::string &name) { - QueryResult *result = LoginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id); + QueryResult *result = loginDatabase.PQuery("SELECT username FROM account WHERE id = '%u'", acc_id); if(result) { name = (*result)[0].GetCppString(); @@ -194,9 +194,9 @@ bool AccountMgr::GetName(uint32 acc_id, std::string &name) bool AccountMgr::CheckPassword(uint32 accid, std::string passwd) { normalizeString(passwd); - LoginDatabase.escape_string(passwd); + loginDatabase.escape_string(passwd); - QueryResult *result = LoginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str()); + QueryResult *result = loginDatabase.PQuery("SELECT 1 FROM account WHERE id='%d' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", accid, passwd.c_str()); if (result) { delete result; diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index fdaa5dd82a8..e9c493f088b 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -36,6 +36,8 @@ #include "SpellMgr.h" #include "MapManager.h" +#include "BattleGround.h" +#include "BattleGroundAB.h" INSTANTIATE_SINGLETON_1(AchievementGlobalMgr); @@ -81,6 +83,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) switch(criteria->requiredType) { + case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: @@ -233,6 +236,8 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE: + return true; // not check correctness node indexes default: sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) have data for not supported data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType); return false; @@ -301,6 +306,13 @@ bool AchievementCriteriaData::Meets(Player const* source, Unit const* target, ui return Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= drunk.state; case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY: return IsHolidayActive(HolidayIds(holiday.id)); + case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE: + { + BattleGround* bg = source->GetBattleGround(); + if(!bg) + return false; + return bg->IsTeamScoreInRange(source->GetTeam()==ALLIANCE ? HORDE : ALLIANCE,bg_loss_team_score.min_score,bg_loss_team_score.max_score); + } } return false; } @@ -720,6 +732,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // specialized cases + case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: + { + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if (!miscvalue1) + continue; + if (achievementCriteria->win_bg.bgMapID != GetPlayer()->GetMapId()) + continue; + + if (achievementCriteria->win_bg.additionalRequirement1_type) + { + // those requirements couldn't be found in the dbc + AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria); + if (!data || !data->Meets(GetPlayer(),unit)) + continue; + } + // some hardcoded requirements + else + { + BattleGround* bg = GetPlayer()->GetBattleGround(); + if (!bg) + continue; + + switch(achievementCriteria->referredAchievement) + { + case 161: // AB, Overcome a 500 resource disadvantage + { + if (bg->GetTypeID() != BATTLEGROUND_AB) + continue; + if(!((BattleGroundAB*)bg)->IsTeamScores500disadvantage(GetPlayer()->GetTeam())) + continue; + break; + } + case 156: // AB, win while controlling all 5 flags (all nodes) + case 784: // EY, win while holding 4 bases (all nodes) + { + if(!bg->IsAllNodesConrolledByTeam(GetPlayer()->GetTeam())) + continue; + break; + } + case 1762: // SA, win without losing any siege vehicles + case 2192: // SA, win without losing any siege vehicles + continue; // not implemented + } + } + + SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE); + break; + } case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: { // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case @@ -790,14 +850,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE); break; - case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: - // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case - if(!miscvalue1) - continue; - if(GetPlayer()->GetMapId() != achievementCriteria->win_bg.bgMapID) - continue; - SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE); - break; case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) @@ -1347,6 +1399,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve switch(achievementCriteria->requiredType) { + case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: + return progress->counter >= achievementCriteria->win_bg.winCount; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: return progress->counter >= achievementCriteria->kill_creature.creatureCount; case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: @@ -1438,8 +1492,6 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return progress->counter >= achievementCriteria->learn_skill_line.spellCount; case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL: return progress->counter >= achievementCriteria->honorable_kill.killCount; - case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: - return progress->counter >= achievementCriteria->win_bg.winCount; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: @@ -1853,6 +1905,10 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() switch(criteria->requiredType) { + case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: + if(!criteria->win_bg.additionalRequirement1_type) + continue; + break; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: break; // any cases case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index b790716b77a..6f30dbfa446 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -59,9 +59,10 @@ enum AchievementCriteriaDataType ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM = 14,// team HORDE(67), ALLIANCE(469) ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK = 15,// drunken_state 0 (enum DrunkenState) of player ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16,// holiday_id 0 event in holiday time + ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17,// min_score max_score player's team win bg and opposition team have team score in range }; -#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 17 // maximum value in AchievementCriteriaDataType enum +#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 18 // maximum value in AchievementCriteriaDataType enum class Player; class Unit; @@ -141,11 +142,17 @@ struct AchievementCriteriaData { uint32 state; } drunk; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY + // ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY = 16 struct { - uint16 id; + uint32 id; } holiday; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE= 17 + struct + { + uint32 min_score; + uint32 max_score; + } bg_loss_team_score; // ... struct { diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index add971a2ab6..22d121c38c1 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -33,24 +33,24 @@ void ArenaTeamMember::ModifyPersonalRating(Player* plr, int32 mod, uint32 slot) ArenaTeam::ArenaTeam() { - Id = 0; - Type = 0; - Name = ""; - CaptainGuid = 0; - BackgroundColor = 0; // background - EmblemStyle = 0; // icon - EmblemColor = 0; // icon color - BorderStyle = 0; // border - BorderColor = 0; // border color - stats.games_week = 0; - stats.games_season = 0; - stats.rank = 0; + m_TeamId = 0; + m_Type = 0; + m_Name = ""; + m_CaptainGuid = 0; + m_BackgroundColor = 0; // background + m_EmblemStyle = 0; // icon + m_EmblemColor = 0; // icon color + m_BorderStyle = 0; // border + m_BorderColor = 0; // border color + m_stats.games_week = 0; + m_stats.games_season = 0; + m_stats.rank = 0; if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6) - stats.rating = 0; + m_stats.rating = 0; else - stats.rating = 1500; - stats.wins_week = 0; - stats.wins_season = 0; + m_stats.rating = 1500; + m_stats.wins_week = 0; + m_stats.wins_season = 0; } ArenaTeam::~ArenaTeam() @@ -66,27 +66,27 @@ bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid)); - CaptainGuid = captainGuid; - Name = ArenaTeamName; - Type = type; + m_CaptainGuid = captainGuid; + m_Name = ArenaTeamName; + m_Type = type; - Id = objmgr.GenerateArenaTeamId(); + m_TeamId = objmgr.GenerateArenaTeamId(); // ArenaTeamName already assigned to ArenaTeam::name, use it to encode string for DB CharacterDatabase.escape_string(ArenaTeamName); CharacterDatabase.BeginTransaction(); - // CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", Id); - MAX(arenateam)+1 not exist - CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", Id); + // CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", m_TeamId); - MAX(arenateam)+1 not exist + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", m_TeamId); CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) " "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')", - Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor); + m_TeamId, ArenaTeamName.c_str(), GUID_LOPART(m_CaptainGuid), m_Type, m_BackgroundColor, m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor); CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES " - "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id, stats.rating, stats.games_week, stats.wins_week, stats.games_season, stats.wins_season, stats.rank); + "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", m_TeamId, m_stats.rating, m_stats.games_week, m_stats.wins_week, m_stats.games_season, m_stats.wins_season, m_stats.rank); CharacterDatabase.CommitTransaction(); - AddMember(CaptainGuid); + AddMember(m_CaptainGuid); sLog.outArena("New ArenaTeam created [Id: %u] [Type: %u] [Captain GUID: %u]", GetId(), GetType(), GetCaptain()); return true; } @@ -145,8 +145,8 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid) newmember.wins_week = 0; if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6) { - if (stats.rating < 1000) - newmember.personal_rating = stats.rating; + if (m_stats.rating < 1000) + newmember.personal_rating = m_stats.rating; else newmember.personal_rating = 1000; } @@ -154,18 +154,18 @@ bool ArenaTeam::AddMember(const uint64& PlayerGuid) { newmember.personal_rating = 1500; } - members.push_back(newmember); + m_members.push_back(newmember); - CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", Id, GUID_LOPART(newmember.guid), newmember.personal_rating ); + CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", m_TeamId, GUID_LOPART(newmember.guid), newmember.personal_rating ); if(pl) { - pl->SetInArenaTeam(Id, GetSlot()); + pl->SetInArenaTeam(m_TeamId, GetSlot()); pl->SetArenaTeamIdInvited(0); pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating ); // hide promote/remove buttons - if(CaptainGuid != PlayerGuid) + if(m_CaptainGuid != PlayerGuid) pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1); sLog.outArena("Player: %s [GUID: %u] joined arena team type: %u [Id: %u].", pl->GetName(), pl->GetGUIDLow(), GetType(), GetId()); } @@ -181,15 +181,15 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) Field *fields = result->Fetch(); - Id = fields[0].GetUInt32(); - Name = fields[1].GetCppString(); - CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER); - Type = fields[3].GetUInt32(); - BackgroundColor = fields[4].GetUInt32(); - EmblemStyle = fields[5].GetUInt32(); - EmblemColor = fields[6].GetUInt32(); - BorderStyle = fields[7].GetUInt32(); - BorderColor = fields[8].GetUInt32(); + m_TeamId = fields[0].GetUInt32(); + m_Name = fields[1].GetCppString(); + m_CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER); + m_Type = fields[3].GetUInt32(); + m_BackgroundColor = fields[4].GetUInt32(); + m_EmblemStyle = fields[5].GetUInt32(); + m_EmblemColor = fields[6].GetUInt32(); + m_BorderStyle = fields[7].GetUInt32(); + m_BorderColor = fields[8].GetUInt32(); delete result; @@ -221,12 +221,12 @@ void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId) Field *fields = result->Fetch(); - stats.rating = fields[0].GetUInt32(); - stats.games_week = fields[1].GetUInt32(); - stats.wins_week = fields[2].GetUInt32(); - stats.games_season = fields[3].GetUInt32(); - stats.wins_season = fields[4].GetUInt32(); - stats.rank = fields[5].GetUInt32(); + m_stats.rating = fields[0].GetUInt32(); + m_stats.games_week = fields[1].GetUInt32(); + m_stats.wins_week = fields[2].GetUInt32(); + m_stats.games_season = fields[3].GetUInt32(); + m_stats.wins_season = fields[4].GetUInt32(); + m_stats.rank = fields[5].GetUInt32(); delete result; } @@ -253,7 +253,7 @@ void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId) newmember.personal_rating = fields[5].GetUInt32(); newmember.name = fields[6].GetCppString(); newmember.Class = fields[7].GetUInt8(); - members.push_back(newmember); + m_members.push_back(newmember); }while( result->NextRow() ); delete result; } @@ -266,10 +266,10 @@ void ArenaTeam::SetCaptain(const uint64& guid) oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); // set new captain - CaptainGuid = guid; + m_CaptainGuid = guid; // update database - CharacterDatabase.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid), Id); + CharacterDatabase.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid), m_TeamId); // enable remove/promote buttons Player *newcaptain = objmgr.GetPlayer(guid); @@ -282,11 +282,11 @@ void ArenaTeam::SetCaptain(const uint64& guid) void ArenaTeam::DelMember(uint64 guid) { - for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { if (itr->guid == guid) { - members.erase(itr); + m_members.erase(itr); break; } } @@ -314,21 +314,21 @@ void ArenaTeam::Disband(WorldSession *session) session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), ""); BroadcastPacket(&data); - while (!members.empty()) + while (!m_members.empty()) { // Removing from members is done in DelMember. - DelMember(members.front().guid); + DelMember(m_members.front().guid); } if(Player *player = session->GetPlayer()) sLog.outArena("Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", player->GetName(), player->GetGUIDLow(), GetType(), GetId()); CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id); - CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member - CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id); + CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", m_TeamId); + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", m_TeamId); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member + CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", m_TeamId); CharacterDatabase.CommitTransaction(); - objmgr.RemoveArenaTeam(Id); + objmgr.RemoveArenaTeam(m_TeamId); } void ArenaTeam::Roster(WorldSession *session) @@ -338,12 +338,12 @@ void ArenaTeam::Roster(WorldSession *session) uint8 unk308 = 0; WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100); - data << uint32(GetId()); // arena team id + data << uint32(GetId()); // team id data << uint8(unk308); // 308 unknown value but affect packet structure data << uint32(GetMembersSize()); // members count data << uint32(GetType()); // arena team type? - for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { pl = objmgr.GetPlayer(itr->guid); @@ -375,11 +375,11 @@ void ArenaTeam::Query(WorldSession *session) data << uint32(GetId()); // team id data << GetName(); // team name data << uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5) - data << uint32(BackgroundColor); // background color - data << uint32(EmblemStyle); // emblem style - data << uint32(EmblemColor); // emblem color - data << uint32(BorderStyle); // border style - data << uint32(BorderColor); // border color + data << uint32(m_BackgroundColor); // background color + data << uint32(m_EmblemStyle); // emblem style + data << uint32(m_EmblemColor); // emblem color + data << uint32(m_BorderStyle); // border style + data << uint32(m_BorderColor); // border color session->SendPacket(&data); sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE"); } @@ -387,13 +387,13 @@ void ArenaTeam::Query(WorldSession *session) void ArenaTeam::Stats(WorldSession *session) { WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*7); - data << uint32(GetId()); // arena team id - data << uint32(stats.rating); // rating - data << uint32(stats.games_week); // games this week - data << uint32(stats.wins_week); // wins this week - data << uint32(stats.games_season); // played this season - data << uint32(stats.wins_season); // wins this season - data << uint32(stats.rank); // rank + data << uint32(GetId()); // team id + data << uint32(m_stats.rating); // rating + data << uint32(m_stats.games_week); // games this week + data << uint32(m_stats.wins_week); // wins this week + data << uint32(m_stats.games_season); // played this season + data << uint32(m_stats.wins_season); // wins this season + data << uint32(m_stats.rank); // rank session->SendPacket(&data); } @@ -401,7 +401,7 @@ void ArenaTeam::NotifyStatsChanged() { // this is called after a rated match ended // updates arena team stats for every member of the team (not only the ones who participated!) - for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + for(MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { Player * plr = objmgr.GetPlayer(itr->guid); if(plr) @@ -419,9 +419,9 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) data << uint64(guid); // player guid data << uint8(GetSlot()); // slot (0...2) data << uint32(GetId()); // arena team id - data << uint32(stats.rating); // rating - data << uint32(stats.games_season); // season played - data << uint32(stats.wins_season); // season wins + data << uint32(m_stats.rating); // rating + data << uint32(m_stats.games_season); // season played + data << uint32(m_stats.wins_season); // season wins data << uint32(member->games_season); // played (count of all games, that the inspected member participated...) data << uint32(member->personal_rating); // personal rating session->SendPacket(&data); @@ -429,13 +429,13 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) void ArenaTeam::SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor) { - BackgroundColor = backgroundColor; - EmblemStyle = emblemStyle; - EmblemColor = emblemColor; - BorderStyle = borderStyle; - BorderColor = borderColor; + m_BackgroundColor = backgroundColor; + m_EmblemStyle = emblemStyle; + m_EmblemColor = emblemColor; + m_BorderStyle = borderStyle; + m_BorderColor = borderColor; - CharacterDatabase.PExecute("UPDATE arena_team SET BackgroundColor='%u', EmblemStyle='%u', EmblemColor='%u', BorderStyle='%u', BorderColor='%u' WHERE arenateamid='%u'", BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor, Id); + CharacterDatabase.PExecute("UPDATE arena_team SET BackgroundColor='%u', EmblemStyle='%u', EmblemColor='%u', BorderStyle='%u', BorderColor='%u' WHERE arenateamid='%u'", m_BackgroundColor, m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_TeamId); } void ArenaTeam::SetStats(uint32 stat_type, uint32 value) @@ -443,27 +443,27 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value) switch(stat_type) { case STAT_TYPE_RATING: - stats.rating = value; + m_stats.rating = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value, GetId()); break; case STAT_TYPE_GAMES_WEEK: - stats.games_week = value; + m_stats.games_week = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value, GetId()); break; case STAT_TYPE_WINS_WEEK: - stats.wins_week = value; + m_stats.wins_week = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value, GetId()); break; case STAT_TYPE_GAMES_SEASON: - stats.games_season = value; + m_stats.games_season = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value, GetId()); break; case STAT_TYPE_WINS_SEASON: - stats.wins_season = value; + m_stats.wins_season = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value, GetId()); break; case STAT_TYPE_RANK: - stats.rank = value; + m_stats.rank = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'", value, GetId()); break; default: @@ -474,7 +474,7 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value) void ArenaTeam::BroadcastPacket(WorldPacket *packet) { - for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { Player *player = objmgr.GetPlayer(itr->guid); if(player) @@ -498,7 +498,7 @@ uint8 ArenaTeam::GetSlotByType( uint32 type ) bool ArenaTeam::HaveMember( const uint64& guid ) const { - for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) if(itr->guid == guid) return true; @@ -510,7 +510,7 @@ uint32 ArenaTeam::GetPoints(uint32 MemberRating) // returns how many points would be awarded with this team type with this rating float points; - uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating; + uint32 rating = MemberRating + 150 < m_stats.rating ? MemberRating : m_stats.rating; if(rating<=1500) // points = (float)1500 * 0.22f + 14.0f; @@ -519,9 +519,9 @@ uint32 ArenaTeam::GetPoints(uint32 MemberRating) points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating)); // type penalties for <5v5 teams - if(Type == ARENA_TEAM_2v2) + if(m_Type == ARENA_TEAM_2v2) points *= 0.76f; - else if(Type == ARENA_TEAM_3v3) + else if(m_Type == ARENA_TEAM_3v3) points *= 0.88f; return (uint32) points; @@ -535,26 +535,25 @@ float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating) if (sWorld.getConfig(CONFIG_ARENA_SEASON_ID) >= 6) if (enemy_rating < 1300) enemy_rating = 1300; - return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)enemy_rating - (float)own_rating)/400.0f)); } void ArenaTeam::FinishGame(int32 mod) { - if (int32(stats.rating) + mod < 0) - stats.rating = 0; + if (int32(m_stats.rating) + mod < 0) + m_stats.rating = 0; else - stats.rating += mod; + m_stats.rating += mod; - stats.games_week += 1; - stats.games_season += 1; + m_stats.games_week += 1; + m_stats.games_season += 1; // update team's rank - stats.rank = 1; + m_stats.rank = 1; ObjectMgr::ArenaTeamMap::const_iterator i = objmgr.GetArenaTeamMapBegin(); for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i) { - if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating) - ++stats.rank; + if (i->second->GetType() == m_Type && i->second->GetStats().rating > m_stats.rating) + ++m_stats.rank; } } @@ -562,13 +561,13 @@ int32 ArenaTeam::WonAgainst(uint32 againstRating) { // called when the team has won //'chance' calculation - to beat the opponent - float chance = GetChanceAgainst(stats.rating, againstRating); + float chance = GetChanceAgainst(m_stats.rating, againstRating); // calculate the rating modification (ELO system with k=32) int32 mod = (int32)floor(32.0f * (1.0f - chance)); // modify the team stats accordingly FinishGame(mod); - stats.wins_week += 1; - stats.wins_season += 1; + m_stats.wins_week += 1; + m_stats.wins_season += 1; // return the rating change, used to display it on the results screen return mod; @@ -578,7 +577,7 @@ int32 ArenaTeam::LostAgainst(uint32 againstRating) { // called when the team has lost //'chance' calculation - to loose to the opponent - float chance = GetChanceAgainst(stats.rating, againstRating); + float chance = GetChanceAgainst(m_stats.rating, againstRating); // calculate the rating modification (ELO system with k=32) int32 mod = (int32)ceil(32.0f * (0.0f - chance)); // modify the team stats accordingly @@ -591,7 +590,7 @@ int32 ArenaTeam::LostAgainst(uint32 againstRating) void ArenaTeam::MemberLost(Player * plr, uint32 againstRating) { // called for each participant of a match after losing - for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { if(itr->guid == plr->GetGUID()) { @@ -613,7 +612,7 @@ void ArenaTeam::MemberLost(Player * plr, uint32 againstRating) void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstRating) { // called for offline player after ending rated arena match! - for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { if(itr->guid == guid) { @@ -635,7 +634,7 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstRating) void ArenaTeam::MemberWon(Player * plr, uint32 againstRating) { // called for each participant after winning a match - for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { if(itr->guid == plr->GetGUID()) { @@ -661,17 +660,17 @@ void ArenaTeam::UpdateArenaPointsHelper(std::map<uint32, uint32>& PlayerPoints) // called after a match has ended and the stats are already modified // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons) // 10 played games per week is a minimum - if (stats.games_week < 10) + if (m_stats.games_week < 10) return; // to get points, a player has to participate in at least 30% of the matches - uint32 min_plays = (uint32) ceil(stats.games_week * 0.3); - for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + uint32 min_plays = (uint32) ceil(m_stats.games_week * 0.3); + for(MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { // the player participated in enough games, update his points uint32 points_to_add = 0; if (itr->games_week >= min_plays) points_to_add = GetPoints(itr->personal_rating); - // OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid); + // OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, m_TeamId, itr->guid); std::map<uint32, uint32>::iterator plr_itr = PlayerPoints.find(GUID_LOPART(itr->guid)); if (plr_itr != PlayerPoints.end()) @@ -690,19 +689,19 @@ void ArenaTeam::SaveToDB() // save team and member stats to db // called after a match has ended, or when calculating arena_points CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games_week, stats.games_season, stats.rank, stats.wins_week, stats.wins_season, GetId()); - for(MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", m_stats.rating, m_stats.games_week, m_stats.games_season, m_stats.rank, m_stats.wins_week, m_stats.wins_season, GetId()); + for(MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { - CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, Id, GUID_LOPART(itr->guid)); + CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, m_TeamId, GUID_LOPART(itr->guid)); } CharacterDatabase.CommitTransaction(); } void ArenaTeam::FinishWeek() { - stats.games_week = 0; // played this week - stats.wins_week = 0; // wins this week - for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + m_stats.games_week = 0; // played this week + m_stats.wins_week = 0; // wins this week + for(MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { itr->games_week = 0; itr->wins_week = 0; @@ -711,7 +710,7 @@ void ArenaTeam::FinishWeek() bool ArenaTeam::IsFighting() const { - for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { if (Player *p = objmgr.GetPlayer(itr->guid)) { diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h index 6db63c82ddc..dbeac2f09f0 100644 --- a/src/game/ArenaTeam.h +++ b/src/game/ArenaTeam.h @@ -117,26 +117,26 @@ class ArenaTeam ArenaTeam(); ~ArenaTeam(); - bool Create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName); + bool Create(uint64 captainGuid, uint32 type, std::string ArenaTeamName); void Disband(WorldSession *session); typedef std::list<ArenaTeamMember> MemberList; - uint32 GetId() const { return Id; } - uint32 GetType() const { return Type; } + uint32 GetId() const { return m_TeamId; } + uint32 GetType() const { return m_Type; } uint8 GetSlot() const { return GetSlotByType(GetType()); } static uint8 GetSlotByType(uint32 type); - const uint64& GetCaptain() const { return CaptainGuid; } - std::string GetName() const { return Name; } - const ArenaTeamStats& GetStats() const { return stats; } + const uint64& GetCaptain() const { return m_CaptainGuid; } + std::string GetName() const { return m_Name; } + const ArenaTeamStats& GetStats() const { return m_stats; } void SetStats(uint32 stat_type, uint32 value); - uint32 GetRating() const { return stats.rating; } + uint32 GetRating() const { return m_stats.rating; } - uint32 GetEmblemStyle() const { return EmblemStyle; } - uint32 GetEmblemColor() const { return EmblemColor; } - uint32 GetBorderStyle() const { return BorderStyle; } - uint32 GetBorderColor() const { return BorderColor; } - uint32 GetBackgroundColor() const { return BackgroundColor; } + uint32 GetEmblemStyle() const { return m_EmblemStyle; } + uint32 GetEmblemColor() const { return m_EmblemColor; } + uint32 GetBorderStyle() const { return m_BorderStyle; } + uint32 GetBorderColor() const { return m_BorderColor; } + uint32 GetBackgroundColor() const { return m_BackgroundColor; } void SetCaptain(const uint64& guid); bool AddMember(const uint64& PlayerGuid); @@ -147,15 +147,15 @@ class ArenaTeam void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor); - size_t GetMembersSize() const { return members.size(); } - bool Empty() const { return members.empty(); } - MemberList::iterator membersBegin() { return members.begin(); } - MemberList::iterator membersEnd() { return members.end(); } + size_t GetMembersSize() const { return m_members.size(); } + bool Empty() const { return m_members.empty(); } + MemberList::iterator m_membersBegin() { return m_members.begin(); } + MemberList::iterator m_membersEnd() { return m_members.end(); } bool HaveMember(const uint64& guid) const; ArenaTeamMember* GetMember(const uint64& guid) { - for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) if(itr->guid == guid) return &(*itr); @@ -164,7 +164,7 @@ class ArenaTeam ArenaTeamMember* GetMember(const std::string& name) { - for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + for (MemberList::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) if(itr->name == name) return &(*itr); @@ -203,19 +203,19 @@ class ArenaTeam protected: - uint32 Id; - uint32 Type; - std::string Name; - uint64 CaptainGuid; + uint32 m_TeamId; + uint32 m_Type; + std::string m_Name; + uint64 m_CaptainGuid; - uint32 BackgroundColor; // ARGB format - uint32 EmblemStyle; // icon id - uint32 EmblemColor; // ARGB format - uint32 BorderStyle; // border image id - uint32 BorderColor; // ARGB format + uint32 m_BackgroundColor; // ARGB format + uint32 m_EmblemStyle; // icon id + uint32 m_EmblemColor; // ARGB format + uint32 m_BorderStyle; // border image id + uint32 m_BorderColor; // ARGB format - MemberList members; - ArenaTeamStats stats; + MemberList m_members; + ArenaTeamStats m_stats; }; #endif diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index f1825fe805c..14778e9b471 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -182,6 +182,9 @@ BattleGround::BattleGround() m_PlayersCount[BG_TEAM_ALLIANCE] = 0; m_PlayersCount[BG_TEAM_HORDE] = 0; + m_TeamScores[BG_TEAM_ALLIANCE] = 0; + m_TeamScores[BG_TEAM_HORDE] = 0; + m_PrematureCountDown = false; m_PrematureCountDown = 0; @@ -473,7 +476,7 @@ void BattleGround::Update(uint32 diff) void BattleGround::SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O) { - uint8 idx = GetTeamIndexByTeamId(TeamID); + BattleGroundTeamId idx = GetTeamIndexByTeamId(TeamID); m_TeamStartLocX[idx] = X; m_TeamStartLocY[idx] = Y; m_TeamStartLocZ[idx] = Z; @@ -1875,3 +1878,9 @@ WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard( Player* player ) { return objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam() ); } + +bool BattleGround::IsTeamScoreInRange(uint32 team, uint32 minScore, uint32 maxScore) const +{ + BattleGroundTeamId team_idx = GetTeamIndexByTeamId(team); + return m_TeamScores[team_idx] >= minScore && m_TeamScores[team_idx] <= maxScore; +} diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 509ba6eb972..ab1a3d4b13c 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -298,6 +298,10 @@ class BattleGround virtual void StartingEventCloseDoors() {} virtual void StartingEventOpenDoors() {} + /* achievement req. */ + virtual bool IsAllNodesConrolledByTeam(uint32 /*team*/) const { return false; } + bool IsTeamScoreInRange(uint32 team, uint32 minScore, uint32 maxScore) const; + /* Battleground */ // Get methods: char const* GetName() const { return m_Name; } @@ -397,7 +401,7 @@ class BattleGround void SetTeamStartLoc(uint32 TeamID, float X, float Y, float Z, float O); void GetTeamStartLoc(uint32 TeamID, float &X, float &Y, float &Z, float &O) const { - uint8 idx = GetTeamIndexByTeamId(TeamID); + BattleGroundTeamId idx = GetTeamIndexByTeamId(TeamID); X = m_TeamStartLocX[idx]; Y = m_TeamStartLocY[idx]; Z = m_TeamStartLocZ[idx]; @@ -441,7 +445,7 @@ class BattleGround virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); - uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; } + static BattleGroundTeamId GetTeamIndexByTeamId(uint32 Team) { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; } uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; } uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases void UpdatePlayersCountByTeam(uint32 Team, bool remove) @@ -514,6 +518,9 @@ class BattleGround void SetDeleteThis() {m_SetDeleteThis = true;} + /* virtual score-array - get's used in bg-subclasses */ + int32 m_TeamScores[BG_TEAMS_COUNT]; + protected: //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround void EndNow(); diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index f5fba6f4186..0ed28112fe7 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -161,6 +161,18 @@ void BattleGroundAB::Update(uint32 diff) } } + // achievements flags + if (m_TeamScores[BG_TEAM_ALLIANCE] > m_TeamScores[BG_TEAM_HORDE]) + { + if (m_TeamScores[BG_TEAM_ALLIANCE] - m_TeamScores[BG_TEAM_HORDE] >= 500) + m_TeamScores500disadvantage[BG_TEAM_HORDE] = true; + } + else + { + if (m_TeamScores[BG_TEAM_HORDE] - m_TeamScores[BG_TEAM_ALLIANCE] >= 500) + m_TeamScores500disadvantage[BG_TEAM_ALLIANCE] = true; + } + // Test win condition if (m_TeamScores[BG_TEAM_ALLIANCE] >= BG_AB_MAX_TEAM_SCORE) EndBattleGround(ALLIANCE); @@ -428,7 +440,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ return; } - uint8 teamIndex = GetTeamIndexByTeamId(source->GetTeam()); + BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(source->GetTeam()); // Check if player really could use this banner, not cheated if (!(m_Nodes[node] == 0 || teamIndex == m_Nodes[node]%2)) @@ -474,7 +486,7 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; // FIXME: node names not localized - if (teamIndex == 0) + if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); @@ -491,15 +503,15 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ _CreateBanner(node, BG_AB_NODE_TYPE_OCCUPIED, teamIndex, true); _SendNodeUpdate(node); m_NodeTimers[node] = 0; - _NodeOccupied(node,(teamIndex == 0) ? ALLIANCE:HORDE); + _NodeOccupied(node,(teamIndex == BG_TEAM_ALLIANCE) ? ALLIANCE:HORDE); // FIXME: node names not localized - if (teamIndex == 0) + if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else SendMessage2ToAll(LANG_BG_AB_NODE_DEFENDED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); } - sound = (teamIndex == 0) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; + sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; } // If node is occupied, change to enemy-contested else @@ -516,19 +528,19 @@ void BattleGroundAB::EventPlayerClickedOnFlag(Player *source, GameObject* /*targ m_NodeTimers[node] = BG_AB_FLAG_CAPTURING_TIME; // FIXME: node names not localized - if (teamIndex == 0) + if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_ALLIANCE, source, _GetNodeNameId(node)); else SendMessage2ToAll(LANG_BG_AB_NODE_ASSAULTED,CHAT_MSG_BG_SYSTEM_HORDE, source, _GetNodeNameId(node)); - sound = (teamIndex == 0) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; + sound = (teamIndex == BG_TEAM_ALLIANCE) ? BG_AB_SOUND_NODE_ASSAULTED_ALLIANCE : BG_AB_SOUND_NODE_ASSAULTED_HORDE; } // If node is occupied again, send "X has taken the Y" msg. if (m_Nodes[node] >= BG_AB_NODE_TYPE_OCCUPIED) { // FIXME: team and node names not localized - if (teamIndex == 0) + if (teamIndex == BG_TEAM_ALLIANCE) SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_ALLIANCE, NULL, LANG_BG_AB_ALLY, _GetNodeNameId(node)); else SendMessage2ToAll(LANG_BG_AB_NODE_TAKEN,CHAT_MSG_BG_SYSTEM_HORDE, NULL, LANG_BG_AB_HORDE, _GetNodeNameId(node)); @@ -591,6 +603,8 @@ void BattleGroundAB::Reset() bool isBGWeekend = false; //TODO FIXME - call sBattleGroundMgr.IsBGWeekend(m_TypeID); - you must also implement that call! m_HonorTics = (isBGWeekend) ? BG_AB_ABBGWeekendHonorTicks : BG_AB_NotABBGWeekendHonorTicks; m_ReputationTics = (isBGWeekend) ? BG_AB_ABBGWeekendReputationTicks : BG_AB_NotABBGWeekendReputationTicks; + m_TeamScores500disadvantage[BG_TEAM_ALLIANCE] = false; + m_TeamScores500disadvantage[BG_TEAM_HORDE] = false; for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) { @@ -621,7 +635,7 @@ void BattleGroundAB::EndBattleGround(uint32 winner) WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) { - uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam()); + BattleGroundTeamId teamIndex = GetTeamIndexByTeamId(player->GetTeam()); // Is there any occupied node for this team? std::vector<uint8> nodes; @@ -679,3 +693,13 @@ void BattleGroundAB::UpdatePlayerScore(Player *Source, uint32 type, uint32 value } } +bool BattleGroundAB::IsAllNodesConrolledByTeam(uint32 team) const +{ + uint32 count = 0; + for(int i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) + if (team == ALLIANCE && m_Nodes[i] == BG_AB_NODE_STATUS_ALLY_OCCUPIED || + team == HORDE && m_Nodes[i] == BG_AB_NODE_STATUS_HORDE_OCCUPIED) + ++count; + + return count == BG_AB_DYNAMIC_NODES_COUNT; +} diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 1c4a6d3b738..1a940a041d4 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -262,6 +262,9 @@ class BattleGroundAB : public BattleGround /* Nodes occupying */ virtual void EventPlayerClickedOnFlag(Player *source, GameObject* target_obj); + /* achievement req. */ + bool IsAllNodesConrolledByTeam(uint32 team) const; // overwrited + bool IsTeamScores500disadvantage(uint32 team) const { return m_TeamScores500disadvantage[GetTeamIndexByTeamId(team)]; } private: /* Gameobject spawning/despawning */ void _CreateBanner(uint8 node, uint8 type, uint8 teamIndex, bool delay); @@ -285,15 +288,14 @@ class BattleGroundAB : public BattleGround uint8 m_prevNodes[BG_AB_DYNAMIC_NODES_COUNT]; BG_AB_BannerTimer m_BannerTimers[BG_AB_DYNAMIC_NODES_COUNT]; uint32 m_NodeTimers[BG_AB_DYNAMIC_NODES_COUNT]; - uint32 m_TeamScores[BG_TEAMS_COUNT]; uint32 m_lastTick[BG_TEAMS_COUNT]; uint32 m_HonorScoreTics[BG_TEAMS_COUNT]; uint32 m_ReputationScoreTics[BG_TEAMS_COUNT]; bool m_IsInformedNearVictory; uint32 m_HonorTics; uint32 m_ReputationTics; - - + // need for achievements + bool m_TeamScores500disadvantage[BG_TEAMS_COUNT]; }; #endif diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 9b54ecce643..39ef126d9e2 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -128,7 +128,7 @@ void BattleGroundEY::StartingEventOpenDoors() void BattleGroundEY::AddPoints(uint32 Team, uint32 Points) { - uint8 team_index = GetTeamIndexByTeamId(Team); + BattleGroundTeamId team_index = GetTeamIndexByTeamId(Team); m_TeamScores[team_index] += Points; m_HonorScoreTics[team_index] += Points; if (m_HonorScoreTics[team_index] >= m_HonorTics ) @@ -908,3 +908,12 @@ WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player) return nearestEntry; } +bool BattleGroundEY::IsAllNodesConrolledByTeam(uint32 team) const +{ + uint32 count = 0; + for(int i = 0; i < EY_POINTS_MAX; ++i) + if (m_PointOwnedByTeam[i] == team && m_PointState[i] == EY_POINT_UNDER_CONTROL) + ++count; + + return count == EY_POINTS_MAX; +} diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index a22d6ecc6db..3385a06bfb0 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -350,6 +350,8 @@ class BattleGroundEY : public BattleGround virtual void EventPlayerClickedOnFlag(Player *Source, GameObject* target_obj); virtual void EventPlayerDroppedFlag(Player *Source); + /* achievement req. */ + bool IsAllNodesConrolledByTeam(uint32 team) const; private: void EventPlayerCapturedFlag(Player *Source, uint32 BgObjectType); void EventTeamCapturedPoint(Player *Source, uint32 Point); @@ -369,7 +371,6 @@ class BattleGroundEY : public BattleGround void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } - uint32 m_TeamScores[2]; uint32 m_HonorScoreTics[2]; uint32 m_TeamPointsCount[2]; diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index 7395c3a5bb9..16631afecdc 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -200,12 +200,10 @@ class BattleGroundWS : public BattleGround void AddPoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] += Points; } void SetTeamPoint(uint32 TeamID, uint32 Points = 0) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] = Points; } void RemovePoint(uint32 TeamID, uint32 Points = 1) { m_TeamScores[GetTeamIndexByTeamId(TeamID)] -= Points; } - private: uint64 m_FlagKeepers[2]; // 0 - alliance, 1 - horde uint64 m_DroppedFlagGUID[2]; uint8 m_FlagState[2]; // for checking flag state - uint32 m_TeamScores[2]; int32 m_FlagsTimer[2]; int32 m_FlagsDropTimer[2]; diff --git a/src/game/ChannelHandler.cpp b/src/game/ChannelHandler.cpp index 9706e5657e7..e3c10afe81f 100644 --- a/src/game/ChannelHandler.cpp +++ b/src/game/ChannelHandler.cpp @@ -24,9 +24,6 @@ #include "ObjectMgr.h" // for normalizePlayerName #include "ChannelMgr.h" -INSTANTIATE_SINGLETON_1( AllianceChannelMgr ); -INSTANTIATE_SINGLETON_1( HordeChannelMgr ); - void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) { sLog.outDebug("Opcode %u", recvPacket.GetOpcode()); diff --git a/src/game/ChannelMgr.cpp b/src/game/ChannelMgr.cpp new file mode 100644 index 00000000000..09d172155cc --- /dev/null +++ b/src/game/ChannelMgr.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ChannelMgr.h" +#include "Policies/SingletonImp.h" +#include "World.h" + +INSTANTIATE_SINGLETON_1( AllianceChannelMgr ); +INSTANTIATE_SINGLETON_1( HordeChannelMgr ); + +ChannelMgr* channelMgr(uint32 team) +{ + if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) + return &MaNGOS::Singleton<AllianceChannelMgr>::Instance(); // cross-faction + + if(team == ALLIANCE) + return &MaNGOS::Singleton<AllianceChannelMgr>::Instance(); + if(team == HORDE) + return &MaNGOS::Singleton<HordeChannelMgr>::Instance(); + + return NULL; +} + +ChannelMgr::~ChannelMgr() +{ + for(ChannelMap::iterator itr = channels.begin();itr!=channels.end(); ++itr) + delete itr->second; + + channels.clear(); +} + +Channel *ChannelMgr::GetJoinChannel(std::string name, uint32 channel_id) +{ + if (channels.find(name) == channels.end()) + { + Channel *nchan = new Channel(name,channel_id, team); + channels[name] = nchan; + } + + return channels[name]; +} + +Channel *ChannelMgr::GetChannel(std::string name, Player *p, bool pkt) +{ + ChannelMap::const_iterator i = channels.find(name); + + if(i == channels.end()) + { + if(pkt) + { + WorldPacket data; + MakeNotOnPacket(&data,name); + p->GetSession()->SendPacket(&data); + } + + return NULL; + } + else + return i->second; +} + +void ChannelMgr::LeftChannel(std::string name) +{ + ChannelMap::const_iterator i = channels.find(name); + + if(i == channels.end()) + return; + + Channel* channel = i->second; + + if(channel->GetNumPlayers() == 0 && !channel->IsConstant()) + { + channels.erase(name); + delete channel; + } +} + +void ChannelMgr::MakeNotOnPacket(WorldPacket *data, std::string name) +{ + data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size + (*data) << (uint8)0x05 << name; +} diff --git a/src/game/ChannelMgr.h b/src/game/ChannelMgr.h index 956309e9873..f65a8520648 100644 --- a/src/game/ChannelMgr.h +++ b/src/game/ChannelMgr.h @@ -17,8 +17,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef TRINITYCORE_CHANNELMGR_H -#define TRINITYCORE_CHANNELMGR_H +#ifndef MANGOSSERVER_CHANNELMGR_H +#define MANGOSSERVER_CHANNELMGR_H + +#include "Common.h" +#include "Channel.h" +#include "Policies/Singleton.h" #include <map> #include <string> @@ -34,73 +38,20 @@ class ChannelMgr uint32 team; typedef std::map<std::string,Channel *> ChannelMap; ChannelMgr() {team = 0;} - ~ChannelMgr() - { - for(ChannelMap::const_iterator itr = channels.begin();itr!=channels.end(); ++itr) - delete itr->second; - channels.clear(); - } - Channel *GetJoinChannel(const std::string& name, uint32 channel_id) - { - if (channels.find(name) == channels.end()) - { - Channel *nchan = new Channel(name,channel_id, team); - channels[name] = nchan; - } - return channels[name]; - } - Channel *GetChannel(const std::string& name, Player *p) - { - ChannelMap::const_iterator i = channels.find(name); - - if(i == channels.end()) - { - WorldPacket data; - MakeNotOnPacket(&data,name); - p->GetSession()->SendPacket(&data); - return NULL; - } - else - return i->second; - } - void LeftChannel(const std::string& name) - { - ChannelMap::const_iterator i = channels.find(name); + ~ChannelMgr(); - if(i == channels.end()) - return; - - Channel* channel = i->second; - - if(channel->GetNumPlayers() == 0 && !channel->IsConstant()) - { - channels.erase(name); - delete channel; - } - } + Channel *GetJoinChannel(std::string name, uint32 channel_id); + Channel *GetChannel(std::string name, Player *p, bool pkt = true); + void LeftChannel(std::string name); private: ChannelMap channels; - void MakeNotOnPacket(WorldPacket *data, const std::string& name) - { - data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size - (*data) << (uint8)0x05 << name; - } + void MakeNotOnPacket(WorldPacket *data, std::string name); }; class AllianceChannelMgr : public ChannelMgr {}; class HordeChannelMgr : public ChannelMgr {}; -inline ChannelMgr* channelMgr(uint32 team) -{ - if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) - //For Test,No Seprate Faction - return &Trinity::Singleton<AllianceChannelMgr>::Instance(); +ChannelMgr* channelMgr(uint32 team); - if(team==ALLIANCE) - return &Trinity::Singleton<AllianceChannelMgr>::Instance(); - if(team==HORDE) - return &Trinity::Singleton<HordeChannelMgr>::Instance(); - return NULL; -} #endif diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index a5849b2aa98..a1a2122a050 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -123,7 +123,7 @@ 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()); + loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId()); WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size @@ -280,7 +280,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) return; } - QueryResult *resultacct = LoginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); + QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); if (resultacct) { Field *fields=resultacct->Fetch(); @@ -461,8 +461,8 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) pNewChar->SaveToDB(); charcount+=1; - LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); - LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); + loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); + loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); delete pNewChar; // created only to call SaveToDB() @@ -736,7 +736,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); - LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId()); + loginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId()); pCurrChar->SetInGameTime( getMSTime() ); // announce group about member online (must be after add to player list to receive announce to self) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 4dcc603afc4..72176a34f6a 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -1810,4 +1810,4 @@ LocaleConstant CliHandler::GetSessionDbcLocale() const int CliHandler::GetSessionDbLocaleIndex() const { return objmgr.GetDBCLocaleIndex(); -}
\ No newline at end of file +} diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index 45bff09eb03..901ec541455 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -39,7 +39,7 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts() objmgr.LoadTrinityStrings(WorldDatabase,"creature_ai_texts",MIN_CREATURE_AI_TEXT_STRING_ID,MAX_CREATURE_AI_TEXT_STRING_ID); // Gather Additional data from EventAI Texts - QueryResult *result = WorldDatabase.PQuery("SELECT entry, sound, type, language, emote FROM creature_ai_texts"); + QueryResult *result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM creature_ai_texts"); sLog.outString("Loading EventAI Texts additional data..."); if (result) @@ -117,8 +117,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Summons() //Drop Existing EventSummon Map m_CreatureEventAI_Summon_Map.clear(); - //Gather additional data for EventAI - QueryResult *result = WorldDatabase.PQuery("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons"); + // Gather additional data for EventAI + QueryResult *result = WorldDatabase.Query("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons"); if (result) { barGoLink bar(result->GetRowCount()); @@ -169,8 +169,8 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() //Drop Existing EventAI List m_CreatureEventAI_Event_Map.clear(); - //Gather event data - QueryResult *result = WorldDatabase.PQuery("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, " + // Gather event data + QueryResult *result = WorldDatabase.Query("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, " "event_param1, event_param2, event_param3, event_param4, " "action1_type, action1_param1, action1_param2, action1_param3, " "action2_type, action2_param1, action2_param2, action2_param3, " diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 910316881a4..a8b5d3ef177 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -84,11 +84,14 @@ struct AchievementCriteriaEntry } kill_creature; // ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1 - // TODO: there are further criterias instead just winning struct { uint32 bgMapID; // 3 uint32 winCount; // 4 + uint32 additionalRequirement1_type; // 5 additional requirement 1 type + uint32 additionalRequirement1_value; // 6 additional requirement 1 value + uint32 additionalRequirement2_type; // 7 additional requirement 2 type + uint32 additionalRequirement2_value; // 8 additional requirement 1 value } win_bg; // ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5 diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 59ec04fc649..b6ac3442c0d 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -949,7 +949,7 @@ void GameObject::Use(Unit* user) UseDoorOrButton(); // activate script - sWorld.ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this); + GetMap()->ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this); return; case GAMEOBJECT_TYPE_QUESTGIVER: //2 @@ -1045,7 +1045,7 @@ void GameObject::Use(Unit* user) player->CastedCreatureOrGO(info->id, GetGUID(), 0); if (info->goober.eventId) - sWorld.ScriptsStart(sEventScripts, info->goober.eventId, player, this); + GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this); } // cast this spell later if provided @@ -1068,7 +1068,7 @@ void GameObject::Use(Unit* user) player->SendCinematicStart(info->camera.cinematicId); if (info->camera.eventID) - sWorld.ScriptsStart(sEventScripts, info->camera.eventID, player, this); + GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this); return; } diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp index 4a33bf07b74..efc09494d1d 100644 --- a/src/game/Level0.cpp +++ b/src/game/Level0.cpp @@ -245,14 +245,14 @@ bool ChatHandler::HandleAccountLockCommand(const char* args) std::string argstr = (char*)args; if (argstr == "on") { - LoginDatabase.PExecute( "UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId()); + loginDatabase.PExecute( "UPDATE account SET locked = '1' WHERE id = '%d'",m_session->GetAccountId()); PSendSysMessage(LANG_COMMAND_ACCLOCKLOCKED); return true; } if (argstr == "off") { - LoginDatabase.PExecute( "UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId()); + loginDatabase.PExecute( "UPDATE account SET locked = '0' WHERE id = '%d'",m_session->GetAccountId()); PSendSysMessage(LANG_COMMAND_ACCLOCKUNLOCKED); return true; } diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 6c344b29903..275dd5b1e8c 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -499,7 +499,7 @@ bool ChatHandler::HandleGMTicketAssignToCommand(const char* args) } uint64 tarGUID = objmgr.GetPlayerGUIDByName(targm.c_str()); uint64 accid = objmgr.GetPlayerAccountIdByGUID(tarGUID); - QueryResult *result = LoginDatabase.PQuery("SELECT `gmlevel` FROM `account` WHERE `id` = '%u'", accid); + QueryResult *result = loginDatabase.PQuery("SELECT `gmlevel` FROM `account` WHERE `id` = '%u'", accid); if(!tarGUID|| !result || result->Fetch()->GetUInt32() < SEC_MODERATOR) { SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 7c506c7d212..e3f3bbce6e6 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -84,7 +84,7 @@ bool ChatHandler::HandleMuteCommand(const char* args) if (target) target->GetSession()->m_muteTime = mutetime; - LoginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id ); + loginDatabase.PExecute("UPDATE account SET mutetime = " UI64FMTD " WHERE id = '%u'",uint64(mutetime), account_id ); if(target) ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime, mutereasonstr.c_str()); @@ -130,7 +130,7 @@ bool ChatHandler::HandleUnmuteCommand(const char* args) target->GetSession()->m_muteTime = 0; } - LoginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id ); + loginDatabase.PExecute("UPDATE account SET mutetime = '0' WHERE id = '%u'", account_id ); if(target) ChatHandler(target).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); @@ -2189,7 +2189,7 @@ bool ChatHandler::HandlePInfoCommand(const char* args) uint32 security = 0; std::string last_login = GetTrinityString(LANG_ERROR); - QueryResult* result = LoginDatabase.PQuery("SELECT username,gmlevel,email,last_ip,last_login FROM account WHERE id = '%u'",accId); + QueryResult* result = loginDatabase.PQuery("SELECT username,gmlevel,email,last_ip,last_login FROM account WHERE id = '%u'",accId); if(result) { Field* fields = result->Fetch(); @@ -3933,9 +3933,9 @@ bool ChatHandler::HandleLookupPlayerIpCommand(const char* args) char* limit_str = strtok (NULL, " "); int32 limit = limit_str ? atoi (limit_str) : -1; - LoginDatabase.escape_string (ip); + loginDatabase.escape_string (ip); - QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ()); + QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE last_ip = '%s'", ip.c_str ()); return LookupPlayerSearchCommand (result,limit); } @@ -3952,9 +3952,9 @@ bool ChatHandler::HandleLookupPlayerAccountCommand(const char* args) if (!AccountMgr::normalizeString (account)) return false; - LoginDatabase.escape_string (account); + loginDatabase.escape_string (account); - QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ()); + QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE username = '%s'", account.c_str ()); return LookupPlayerSearchCommand (result,limit); } @@ -3969,9 +3969,9 @@ bool ChatHandler::HandleLookupPlayerEmailCommand(const char* args) char* limit_str = strtok (NULL, " "); int32 limit = limit_str ? atoi (limit_str) : -1; - LoginDatabase.escape_string (email); + loginDatabase.escape_string (email); - QueryResult* result = LoginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ()); + QueryResult* result = loginDatabase.PQuery ("SELECT id,username FROM account WHERE email = '%s'", email.c_str ()); return LookupPlayerSearchCommand (result,limit); } diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 5abc05260f1..33790d4d3fe 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1415,7 +1415,7 @@ bool ChatHandler::HandleAccountSetGmLevelCommand(const char* args) PSendSysMessage(LANG_YOURS_SECURITY_CHANGED, m_session->GetPlayer()->GetName(), gm); } - LoginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId); + loginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId); return true; }else { @@ -1456,7 +1456,7 @@ bool ChatHandler::HandleAccountSetGmLevelCommand(const char* args) } PSendSysMessage(LANG_YOU_CHANGE_SECURITY, targetAccountName.c_str(), gm); - LoginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId); + loginDatabase.PExecute("UPDATE account SET gmlevel = '%d' WHERE id = '%u'", gm, targetAccountId); return true; } } @@ -5909,7 +5909,7 @@ bool ChatHandler::HandleBanInfoCharacterCommand(const char* args) bool ChatHandler::HandleBanInfoHelper(uint32 accountid, char const* accountname) { - QueryResult *result = LoginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid); + QueryResult *result = loginDatabase.PQuery("SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate,banreason,bannedby FROM account_banned WHERE id = '%u' ORDER BY bandate ASC",accountid); if(!result) { PSendSysMessage(LANG_BANINFO_NOACCOUNTBAN, accountname); @@ -5949,8 +5949,8 @@ bool ChatHandler::HandleBanInfoIPCommand(const char* args) std::string IP = cIP; - LoginDatabase.escape_string(IP); - QueryResult *result = LoginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str()); + loginDatabase.escape_string(IP); + QueryResult *result = loginDatabase.PQuery("SELECT ip, FROM_UNIXTIME(bandate), FROM_UNIXTIME(unbandate), unbandate-UNIX_TIMESTAMP(), banreason,bannedby,unbandate-bandate FROM ip_banned WHERE ip = '%s'",IP.c_str()); if(!result) { PSendSysMessage(LANG_BANINFO_NOIP); @@ -5968,14 +5968,14 @@ bool ChatHandler::HandleBanInfoIPCommand(const char* args) bool ChatHandler::HandleBanListCharacterCommand(const char* args) { - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); char* cFilter = strtok ((char*)args, " "); if(!cFilter) return false; std::string filter = cFilter; - LoginDatabase.escape_string(filter); + loginDatabase.escape_string(filter); QueryResult* result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'"),filter.c_str()); if (!result) { @@ -5988,22 +5988,22 @@ bool ChatHandler::HandleBanListCharacterCommand(const char* args) bool ChatHandler::HandleBanListAccountCommand(const char* args) { - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); char* cFilter = strtok((char*)args, " "); std::string filter = cFilter ? cFilter : ""; - LoginDatabase.escape_string(filter); + loginDatabase.escape_string(filter); QueryResult* result; if(filter.empty()) { - result = LoginDatabase.Query("SELECT account.id, username FROM account, account_banned" + result = loginDatabase.Query("SELECT account.id, username FROM account, account_banned" " WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id"); } else { - result = LoginDatabase.PQuery("SELECT account.id, username FROM account, account_banned" + result = loginDatabase.PQuery("SELECT account.id, username FROM account, account_banned" " WHERE account.id = account_banned.id AND active = 1 AND username "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'")" GROUP BY account.id", filter.c_str()); } @@ -6029,7 +6029,7 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result) Field* fields = result->Fetch(); uint32 accountid = fields[0].GetUInt32(); - QueryResult* banresult = LoginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid); + QueryResult* banresult = loginDatabase.PQuery("SELECT account.username FROM account,account_banned WHERE account_banned.id='%u' AND account_banned.id=account.id",accountid); if(banresult) { Field* fields2 = banresult->Fetch(); @@ -6060,7 +6060,7 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result) accmgr.GetName (account_id,account_name); // No SQL injection. id is uint32. - QueryResult *banInfo = LoginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id); + QueryResult *banInfo = loginDatabase.PQuery("SELECT bandate,unbandate,bannedby,banreason FROM account_banned WHERE id = %u ORDER BY unbandate", account_id); if (banInfo) { Field *fields2 = banInfo->Fetch(); @@ -6097,23 +6097,23 @@ bool ChatHandler::HandleBanListHelper(QueryResult* result) bool ChatHandler::HandleBanListIPCommand(const char* args) { - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); char* cFilter = strtok((char*)args, " "); std::string filter = cFilter ? cFilter : ""; - LoginDatabase.escape_string(filter); + loginDatabase.escape_string(filter); QueryResult* result; if(filter.empty()) { - result = LoginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" + result = loginDatabase.Query ("SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP())" " ORDER BY unbandate" ); } else { - result = LoginDatabase.PQuery( "SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" + result = loginDatabase.PQuery( "SELECT ip,bandate,unbandate,bannedby,banreason FROM ip_banned" " WHERE (bandate=unbandate OR unbandate>UNIX_TIMESTAMP()) AND ip "_LIKE_" "_CONCAT3_("'%%'","'%s'","'%%'") " ORDER BY unbandate",filter.c_str() ); } @@ -6882,7 +6882,7 @@ bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/) bool ChatHandler::HandleGMListFullCommand(const char* /*args*/) { ///- Get the accounts with GM Level >0 - QueryResult *result = LoginDatabase.Query( "SELECT username,gmlevel FROM account WHERE gmlevel > 0" ); + QueryResult *result = loginDatabase.Query( "SELECT username,gmlevel FROM account WHERE gmlevel > 0" ); if(result) { SendSysMessage(LANG_GMLIST); @@ -6991,7 +6991,7 @@ bool ChatHandler::HandleAccountSetAddonCommand(const char* args) return false; // No SQL injection - LoginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",lev,account_id); + loginDatabase.PExecute("UPDATE account SET expansion = '%d' WHERE id = '%u'",lev,account_id); PSendSysMessage(LANG_ACCOUNT_SETADDON,account_name.c_str(),account_id,lev); return true; } diff --git a/src/game/Makefile.am b/src/game/Makefile.am index ed918234265..bc5dace3985 100644 --- a/src/game/Makefile.am +++ b/src/game/Makefile.am @@ -624,6 +624,7 @@ libmangosgame_a_SOURCES = \ Channel.cpp \ Channel.h \ ChannelHandler.cpp \ + ChannelMgr.cpp \ ChannelMgr.h \ CharacterHandler.cpp \ Chat.cpp \ @@ -840,11 +841,8 @@ libmangosgame_a_SOURCES = \ GroupRefManager.h >>>>>>> 5a6594330caefc0dc00a5fe792dcb0e344b457cb:src/game/Makefile.am -## Link against shared library -libmangosgame_a_LIBADD = ../shared/libmangosshared.a ../shared/Auth/libmangosauth.a ../shared/Config/libmangosconfig.a ../shared/Database/libmangosdatabase.a ../shared/vmap/libmangosvmaps.a - ## Additional files to include when running 'make dist' # Precompiled Headers for WIN EXTRA_DIST = \ pchdef.cpp \ - pchdef.h
\ No newline at end of file + pchdef.h diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 93fd3e21e1b..c01944b14c7 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -20,6 +20,7 @@ #include "MapManager.h" #include "Player.h" +#include "Vehicle.h" #include "GridNotifiers.h" #include "Log.h" #include "GridStates.h" @@ -36,6 +37,7 @@ #include "Group.h" #include "MapRefManager.h" #include "Vehicle.h" +#include "WaypointManager.h" #include "MapInstanced.h" #include "InstanceSaveMgr.h" @@ -46,9 +48,20 @@ GridState* si_GridStates[MAX_GRID_STATE]; +struct ScriptAction +{ + uint64 sourceGUID; + uint64 targetGUID; + uint64 ownerGUID; // owner of source if source is item + ScriptInfo const* script; // pointer to static script data +}; + Map::~Map() { UnloadAll(); + + if(!m_scriptSchedule.empty()) + sWorld.DecreaseScheduledScriptCount(m_scriptSchedule.size()); } bool Map::ExistMap(uint32 mapid,int gx,int gy) @@ -780,17 +793,21 @@ void Map::Update(const uint32 &t_diff) // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended - if (IsBattleGroundOrArena()) - return; - - for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); ) + if (!IsBattleGroundOrArena()) { - NGridType *grid = i->getSource(); - GridInfo *info = i->getSource()->getGridInfoRef(); - ++i; // The update might delete the map and we need the next map before the iterator gets invalid - assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE); - si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff); + for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); ) + { + NGridType *grid = i->getSource(); + GridInfo *info = i->getSource()->getGridInfoRef(); + ++i; // The update might delete the map and we need the next map before the iterator gets invalid + assert(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE); + si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff); + } } + + ///- Process necessary scripts + if (!m_scriptSchedule.empty()) + ScriptsProcess(); } void Map::Remove(Player *player, bool remove) @@ -1312,11 +1329,11 @@ bool GridMap::loadHeihgtData(FILE *in, uint32 offset, uint32 size) map_heightHeader header; fseek(in, offset, SEEK_SET); fread(&header, sizeof(header), 1, in); - if (header.fourcc != uint32(MAP_HEIGTH_MAGIC)) + if (header.fourcc != uint32(MAP_HEIGHT_MAGIC)) return false; m_gridHeight = header.gridHeight; - if (!(header.flags & MAP_HEIGHT_NO_HIGHT)) + if (!(header.flags & MAP_HEIGHT_NO_HEIGHT)) { if ((header.flags & MAP_HEIGHT_AS_INT16)) { @@ -1365,12 +1382,12 @@ bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 size) m_liquid_height= header.height; m_liquidLevel = header.liquidLevel; - if (!(header.flags&MAP_LIQUID_NO_TYPE)) + if (!(header.flags & MAP_LIQUID_NO_TYPE)) { m_liquid_type = new uint8 [16*16]; fread(m_liquid_type, sizeof(uint8), 16*16, in); } - if (!(header.flags&MAP_LIQUID_NO_HIGHT)) + if (!(header.flags & MAP_LIQUID_NO_HEIGHT)) { m_liquid_map = new float [m_liquid_width*m_liquid_height]; fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in); @@ -2745,6 +2762,836 @@ void BattleGroundMap::UnloadAll() Map::UnloadAll(); } +/// Put scripts in the execution queue +void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target) +{ + ///- Find the script map + ScriptMapMap::const_iterator s = scripts.find(id); + if (s == scripts.end()) + return; + + // prepare static data + uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source + uint64 targetGUID = target ? target->GetGUID() : (uint64)0; + uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; + + ///- Schedule script execution for all scripts in the script map + ScriptMap const *s2 = &(s->second); + bool immedScript = false; + for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter) + { + ScriptAction sa; + sa.sourceGUID = sourceGUID; + sa.targetGUID = targetGUID; + sa.ownerGUID = ownerGUID; + + sa.script = &iter->second; + m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + iter->first), sa)); + if (iter->first == 0) + immedScript = true; + + sWorld.IncreaseScheduledScriptsCount(); + } + ///- If one of the effects should be immediate, launch the script execution + if (/*start &&*/ immedScript) + ScriptsProcess(); +} + +void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target) +{ + // NOTE: script record _must_ exist until command executed + + // prepare static data + uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; + uint64 targetGUID = target ? target->GetGUID() : (uint64)0; + uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; + + ScriptAction sa; + sa.sourceGUID = sourceGUID; + sa.targetGUID = targetGUID; + sa.ownerGUID = ownerGUID; + + sa.script = &script; + m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(time_t(sWorld.GetGameTime() + delay), sa)); + + sWorld.IncreaseScheduledScriptsCount(); + + ///- If effects should be immediate, launch the script execution + if(delay == 0) + ScriptsProcess(); +} + +/// Process queued scripts +void Map::ScriptsProcess() +{ + if (m_scriptSchedule.empty()) + return; + + ///- Process overdue queued scripts + std::multimap<time_t, ScriptAction>::iterator iter = m_scriptSchedule.begin(); + // ok as multimap is a *sorted* associative container + while (!m_scriptSchedule.empty() && (iter->first <= sWorld.GetGameTime())) + { + ScriptAction const& step = iter->second; + + Object* source = NULL; + + if(step.sourceGUID) + { + switch(GUID_HIPART(step.sourceGUID)) + { + case HIGHGUID_ITEM: + // case HIGHGUID_CONTAINER: ==HIGHGUID_ITEM + { + Player* player = HashMapHolder<Player>::Find(step.ownerGUID); + if(player) + source = player->GetItemByGuid(step.sourceGUID); + break; + } + case HIGHGUID_UNIT: + source = HashMapHolder<Creature>::Find(step.sourceGUID); + break; + case HIGHGUID_PET: + source = HashMapHolder<Pet>::Find(step.sourceGUID); + break; + case HIGHGUID_VEHICLE: + source = HashMapHolder<Vehicle>::Find(step.sourceGUID); + break; + case HIGHGUID_PLAYER: + source = HashMapHolder<Player>::Find(step.sourceGUID); + break; + case HIGHGUID_GAMEOBJECT: + source = HashMapHolder<GameObject>::Find(step.sourceGUID); + break; + case HIGHGUID_CORPSE: + source = HashMapHolder<Corpse>::Find(step.sourceGUID); + break; + case HIGHGUID_MO_TRANSPORT: + for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) + { + if((*iter)->GetGUID() == step.sourceGUID) + { + source = reinterpret_cast<Object*>(*iter); + break; + } + } + break; + default: + sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID)); + break; + } + } + + //if(source && !source->IsInWorld()) source = NULL; + + Object* target = NULL; + + if(step.targetGUID) + { + switch(GUID_HIPART(step.targetGUID)) + { + case HIGHGUID_UNIT: + target = HashMapHolder<Creature>::Find(step.targetGUID); + break; + case HIGHGUID_PET: + target = HashMapHolder<Pet>::Find(step.targetGUID); + break; + case HIGHGUID_VEHICLE: + target = HashMapHolder<Vehicle>::Find(step.targetGUID); + break; + case HIGHGUID_PLAYER: // empty GUID case also + target = HashMapHolder<Player>::Find(step.targetGUID); + break; + case HIGHGUID_GAMEOBJECT: + target = HashMapHolder<GameObject>::Find(step.targetGUID); + break; + case HIGHGUID_CORPSE: + target = HashMapHolder<Corpse>::Find(step.targetGUID); + break; + default: + sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID)); + break; + } + } + + //if(target && !target->IsInWorld()) target = NULL; + + switch (step.script->command) + { + case SCRIPT_COMMAND_TALK: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_TALK call for NULL creature."); + break; + } + + if(source->GetTypeId()!=TYPEID_UNIT) + { + sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + if(step.script->datalong > 3) + { + sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong); + break; + } + + uint64 unit_target = target ? target->GetGUID() : 0; + + //datalong 0=normal say, 1=whisper, 2=yell, 3=emote text + switch(step.script->datalong) + { + case 0: // Say + ((Creature *)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target); + break; + case 1: // Whisper + if(!unit_target) + { + sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong); + break; + } + ((Creature *)source)->Whisper(step.script->dataint,unit_target); + break; + case 2: // Yell + ((Creature *)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target); + break; + case 3: // Emote text + ((Creature *)source)->TextEmote(step.script->dataint, unit_target); + break; + default: + break; // must be already checked at load + } + break; + } + + case SCRIPT_COMMAND_EMOTE: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature."); + break; + } + + if(source->GetTypeId()!=TYPEID_UNIT) + { + sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + ((Creature *)source)->HandleEmoteCommand(step.script->datalong); + break; + case SCRIPT_COMMAND_FIELD_SET: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_FIELD_SET call for NULL object."); + break; + } + if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FIELD_SET call for wrong field %u (max count: %u) in object (TypeId: %u).", + step.script->datalong,source->GetValuesCount(),source->GetTypeId()); + break; + } + + source->SetUInt32Value(step.script->datalong, step.script->datalong2); + break; + case SCRIPT_COMMAND_MOVE_TO: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature."); + break; + } + + if(source->GetTypeId()!=TYPEID_UNIT) + { + sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + ((Creature*)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2 ); + ((Creature*)source)->GetMap()->CreatureRelocation(((Creature*)source), step.script->x, step.script->y, step.script->z, 0); + break; + case SCRIPT_COMMAND_FLAG_SET: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_FLAG_SET call for NULL object."); + break; + } + if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FLAG_SET call for wrong field %u (max count: %u) in object (TypeId: %u).", + step.script->datalong,source->GetValuesCount(),source->GetTypeId()); + break; + } + + source->SetFlag(step.script->datalong, step.script->datalong2); + break; + case SCRIPT_COMMAND_FLAG_REMOVE: + if(!source) + { + sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for NULL object."); + break; + } + if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) + { + sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for wrong field %u (max count: %u) in object (TypeId: %u).", + step.script->datalong,source->GetValuesCount(),source->GetTypeId()); + break; + } + + source->RemoveFlag(step.script->datalong, step.script->datalong2); + break; + + case SCRIPT_COMMAND_TELEPORT_TO: + { + // accept player in any one from target/source arg + if (!target && !source) + { + sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for NULL object."); + break; + } + + // must be only Player + if((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER)) + { + sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); + break; + } + + Player* pSource = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source; + + pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o); + break; + } + + case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: + { + if(!step.script->datalong) // creature not specified + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL creature."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL world object."); + break; + } + + WorldObject* summoner = dynamic_cast<WorldObject*>(source); + + if(!summoner) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + float x = step.script->x; + float y = step.script->y; + float z = step.script->z; + float o = step.script->o; + + Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2); + if (!pCreature) + { + sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON failed for creature (entry: %u).",step.script->datalong); + break; + } + + break; + } + + case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: + { + if(!step.script->datalong) // gameobject not specified + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL gameobject."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL world object."); + break; + } + + WorldObject* summoner = dynamic_cast<WorldObject*>(source); + + if(!summoner) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + GameObject *go = NULL; + int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2; + + CellPair p(MaNGOS::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check); + + TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); + CellLock<GridReadGuard> cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *summoner->GetMap()); + + if ( !go ) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT failed for gameobject(guid: %u).", step.script->datalong); + break; + } + + if( go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE || + go->GetGoType()==GAMEOBJECT_TYPE_DOOR || + go->GetGoType()==GAMEOBJECT_TYPE_BUTTON || + go->GetGoType()==GAMEOBJECT_TYPE_TRAP ) + { + sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT can not be used with gameobject of type %u (guid: %u).", uint32(go->GetGoType()), step.script->datalong); + break; + } + + if( go->isSpawned() ) + break; //gameobject already spawned + + go->SetLootState(GO_READY); + go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds + + go->GetMap()->Add(go); + break; + } + case SCRIPT_COMMAND_OPEN_DOOR: + { + if(!step.script->datalong) // door not specified + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL door."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL unit."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + Unit* caster = (Unit*)source; + + GameObject *door = NULL; + int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; + + CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check); + + TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); + CellLock<GridReadGuard> cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *caster->GetMap()); + + if (!door) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong); + break; + } + if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR) + { + sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType()); + break; + } + + if (door->GetGoState() != GO_STATE_READY) + break; //door already open + + door->UseDoorOrButton(time_to_close); + + if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON) + ((GameObject*)target)->UseDoorOrButton(time_to_close); + break; + } + case SCRIPT_COMMAND_CLOSE_DOOR: + { + if(!step.script->datalong) // guid for door not specified + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL door."); + break; + } + + if(!source) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL unit."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + Unit* caster = (Unit*)source; + + GameObject *door = NULL; + int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; + + CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check); + + TypeContainerVisitor<MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); + CellLock<GridReadGuard> cell_lock(cell, p); + cell_lock->Visit(cell_lock, object_checker, *caster->GetMap()); + + if ( !door ) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for gameobject(guid: %u).", step.script->datalong); + break; + } + if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR ) + { + sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for non-door(GoType: %u).", door->GetGoType()); + break; + } + + if( door->GetGoState() == GO_STATE_READY ) + break; //door already closed + + door->UseDoorOrButton(time_to_open); + + if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON) + ((GameObject*)target)->UseDoorOrButton(time_to_open); + + break; + } + case SCRIPT_COMMAND_QUEST_EXPLORED: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL source."); + break; + } + + if(!target) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL target."); + break; + } + + // when script called for item spell casting then target == (unit or GO) and source is player + WorldObject* worldObject; + Player* player; + + if(target->GetTypeId()==TYPEID_PLAYER) + { + if(source->GetTypeId()!=TYPEID_UNIT && source->GetTypeId()!=TYPEID_GAMEOBJECT) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + worldObject = (WorldObject*)source; + player = (Player*)target; + } + else + { + if(target->GetTypeId()!=TYPEID_UNIT && target->GetTypeId()!=TYPEID_GAMEOBJECT) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",target->GetTypeId()); + break; + } + + if(source->GetTypeId()!=TYPEID_PLAYER) + { + sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-player(TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + worldObject = (WorldObject*)target; + player = (Player*)source; + } + + // quest id and flags checked at script loading + if( (worldObject->GetTypeId()!=TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) && + (step.script->datalong2==0 || worldObject->IsWithinDistInMap(player,float(step.script->datalong2))) ) + player->AreaExploredOrEventHappens(step.script->datalong); + else + player->FailQuest(step.script->datalong); + + break; + } + + case SCRIPT_COMMAND_ACTIVATE_OBJECT: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT must have source caster."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + if(!target) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for NULL gameobject."); + break; + } + + if(target->GetTypeId()!=TYPEID_GAMEOBJECT) + { + sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for non-gameobject (TypeId: %u), skipping.",target->GetTypeId()); + break; + } + + Unit* caster = (Unit*)source; + + GameObject *go = (GameObject*)target; + + go->Use(caster); + break; + } + + case SCRIPT_COMMAND_REMOVE_AURA: + { + Object* cmdTarget = step.script->datalong2 ? source : target; + + if(!cmdTarget) + { + sLog.outError("SCRIPT_COMMAND_REMOVE_AURA call for NULL %s.",step.script->datalong2 ? "source" : "target"); + break; + } + + if(!cmdTarget->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_REMOVE_AURA %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId()); + break; + } + + ((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong); + break; + } + + case SCRIPT_COMMAND_CAST_SPELL: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL must have source caster."); + break; + } + + Object* cmdTarget = step.script->datalong2 & 0x01 ? source : target; + + if(!cmdTarget) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x01 ? "source" : "target"); + break; + } + + if(!cmdTarget->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x01 ? "source" : "target",cmdTarget->GetTypeId()); + break; + } + + Unit* spellTarget = (Unit*)cmdTarget; + + Object* cmdSource = step.script->datalong2 & 0x02 ? target : source; + + if(!cmdSource) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x02 ? "target" : "source"); + break; + } + + if(!cmdSource->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x02 ? "target" : "source", cmdSource->GetTypeId()); + break; + } + + Unit* spellSource = (Unit*)cmdSource; + + //TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast + spellSource->CastSpell(spellTarget,step.script->datalong,false); + + break; + } + + case SCRIPT_COMMAND_LOAD_PATH: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_START_MOVE is tried to apply to NON-existing unit."); + break; + } + + if(!source->isType(TYPEMASK_UNIT)) + { + sLog.outError("SCRIPT_COMMAND_START_MOVE source mover isn't unit (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + if(!WaypointMgr.GetPath(step.script->datalong)) + { + sLog.outError("SCRIPT_COMMAND_START_MOVE source mover has an invallid path, skipping.", step.script->datalong2); + break; + } + + dynamic_cast<Unit*>(source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2); + break; + } + + case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT: + { + if(!step.script->datalong || !step.script->datalong2) + { + sLog.outError("SCRIPT_COMMAND_CALLSCRIPT calls invallid db_script_id or lowguid not present: skipping."); + break; + } + //our target + Creature* target = NULL; + + if(source) //using grid searcher + { + CellPair p(Trinity::ComputeCellPair(((Unit*)source)->GetPositionX(), ((Unit*)source)->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + //sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong); + Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong); + Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check); + + TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker); + CellLock<GridReadGuard> cell_lock(cell, p); + cell_lock->Visit(cell_lock, unit_checker, *(((Unit*)source)->GetMap())); + } + else //check hashmap holders + { + if(CreatureData const* data = objmgr.GetCreatureData(step.script->datalong)) + target = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), target); + } + //sLog.outDebug("attempting to pass target..."); + if(!target) + break; + //sLog.outDebug("target passed"); + //Lets choose our ScriptMap map + ScriptMapMap *datamap = NULL; + switch(step.script->dataint) + { + case 1://QUEST END SCRIPTMAP + datamap = &sQuestEndScripts; + break; + case 2://QUEST START SCRIPTMAP + datamap = &sQuestStartScripts; + break; + case 3://SPELLS SCRIPTMAP + datamap = &sSpellScripts; + break; + case 4://GAMEOBJECTS SCRIPTMAP + datamap = &sGameObjectScripts; + break; + case 5://EVENTS SCRIPTMAP + datamap = &sEventScripts; + break; + case 6://WAYPOINTS SCRIPTMAP + datamap = &sWaypointScripts; + break; + default: + sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring"); + break; + } + //if no scriptmap present... + if(!datamap) + break; + + uint32 script_id = step.script->datalong2; + //insert script into schedule but do not start it + ScriptsStart(*datamap, script_id, target, NULL/*, false*/); + break; + } + + case SCRIPT_COMMAND_KILL: + { + if(!source || ((Creature*)source)->isDead()) + break; + + ((Creature*)source)->DealDamage(((Creature*)source), ((Creature*)source)->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + switch(step.script->dataint) + { + case 0: break; //return false not remove corpse + case 1: ((Creature*)source)->RemoveCorpse(); break; + } + break; + } + + case SCRIPT_COMMAND_PLAY_SOUND: + { + if(!source) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for NULL creature."); + break; + } + + WorldObject* pSource = dynamic_cast<WorldObject*>(source); + if(!pSource) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for non-world object (TypeId: %u), skipping.",source->GetTypeId()); + break; + } + + // bitmask: 0/1=anyone/target, 0/2=with distance dependent + Player* pTarget = NULL; + if(step.script->datalong2 & 1) + { + if(!target) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for NULL target."); + break; + } + + if(target->GetTypeId()!=TYPEID_PLAYER) + { + sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for non-player (TypeId: %u), skipping.",target->GetTypeId()); + break; + } + + pTarget = (Player*)target; + } + + // bitmask: 0/1=anyone/target, 0/2=with distance dependent + if(step.script->datalong2 & 2) + pSource->PlayDistanceSound(step.script->datalong,pTarget); + else + pSource->PlayDirectSound(step.script->datalong,pTarget); + break; + } + default: + sLog.outError("Unknown script command %u called.",step.script->command); + break; + } + + m_scriptSchedule.erase(iter); + sWorld.DecreaseScheduledScriptCount(); + + iter = m_scriptSchedule.begin(); + } + return; +} + Creature* Map::GetCreature(uint64 guid) { diff --git a/src/game/Map.h b/src/game/Map.h index ed918125328..bbb861e8aeb 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -43,9 +43,12 @@ class WorldPacket; class InstanceData; class Group; class InstanceSave; +class Object; class WorldObject; class TempSummon; class CreatureGroup; +struct ScriptInfo; +struct ScriptAction; typedef ACE_RW_Thread_Mutex GridRWLock; @@ -74,10 +77,11 @@ typedef MaNGOS::SingleThreaded<GridRWLock>::Lock NullGuard; #define MAP_MAGIC 'SPAM' #define MAP_VERSION_MAGIC '0.1w' #define MAP_AREA_MAGIC 'AERA' -#define MAP_HEIGTH_MAGIC 'TGHM' +#define MAP_HEIGHT_MAGIC 'TGHM' #define MAP_LIQUID_MAGIC 'QILM' -struct map_fileheader{ +struct map_fileheader +{ uint32 mapMagic; uint32 versionMagic; uint32 areaMapOffset; @@ -89,17 +93,20 @@ struct map_fileheader{ }; #define MAP_AREA_NO_AREA 0x0001 -struct map_areaHeader{ + +struct map_areaHeader +{ uint32 fourcc; uint16 flags; uint16 gridArea; }; -#define MAP_HEIGHT_NO_HIGHT 0x0001 +#define MAP_HEIGHT_NO_HEIGHT 0x0001 #define MAP_HEIGHT_AS_INT16 0x0002 #define MAP_HEIGHT_AS_INT8 0x0004 -struct map_heightHeader{ +struct map_heightHeader +{ uint32 fourcc; uint32 flags; float gridHeight; @@ -107,8 +114,10 @@ struct map_heightHeader{ }; #define MAP_LIQUID_NO_TYPE 0x0001 -#define MAP_LIQUID_NO_HIGHT 0x0002 -struct map_liquidHeader{ +#define MAP_LIQUID_NO_HEIGHT 0x0002 + +struct map_liquidHeader +{ uint32 fourcc; uint16 flags; uint16 liquidType; @@ -119,7 +128,8 @@ struct map_liquidHeader{ float liquidLevel; }; -enum ZLiquidStatus{ +enum ZLiquidStatus +{ LIQUID_MAP_NO_WATER = 0x00000000, LIQUID_MAP_ABOVE_WATER = 0x00000001, LIQUID_MAP_WATER_WALK = 0x00000002, @@ -138,7 +148,8 @@ enum ZLiquidStatus{ #define MAP_LIQUID_TYPE_DARK_WATER 0x10 #define MAP_LIQUID_TYPE_WMO_WATER 0x20 -struct LiquidData{ +struct LiquidData +{ uint32 type; float level; float depth_level; @@ -398,6 +409,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj typedef MapRefManager PlayerList; PlayerList const& GetPlayers() const { return m_mapRefManager; } + //per-map script storage + void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target); + void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); + // must called with AddToWorld template<class T> void AddToActive(T* obj) { AddToActiveHelper(obj); } @@ -467,6 +482,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); } void setNGrid(NGridType* grid, uint32 x, uint32 y); + void ScriptsProcess(); void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff); protected: @@ -508,6 +524,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj std::vector<Unit*> i_unitsToNotify; std::set<WorldObject *> i_objectsToRemove; std::map<WorldObject*, bool> i_objectsToSwitch; + std::multimap<time_t, ScriptAction> m_scriptSchedule; // Type specific code for add/remove to/from grid template<class T> diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index c2a93c36e0c..48fdda872e9 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1216,15 +1216,17 @@ void WorldSession::HandleWardenDataOpcode(WorldPacket& /*recv_data*/) */ } -void WorldSession::HandlePlayedTime(WorldPacket& /*recv_data*/) +void WorldSession::HandlePlayedTime(WorldPacket& recv_data) { - uint32 TotalTimePlayed = GetPlayer()->GetTotalPlayedTime(); - uint32 LevelPlayedTime = GetPlayer()->GetLevelPlayedTime(); + CHECK_PACKET_SIZE(recv_data, 1); - WorldPacket data(SMSG_PLAYED_TIME, 9); - data << TotalTimePlayed; - data << LevelPlayedTime; - data << uint8(0); + uint8 unk1; + recv_data >> unk1; // 0 or 1 expected + + WorldPacket data(SMSG_PLAYED_TIME, 4 + 4 + 1); + data << uint32(_player->GetTotalPlayedTime()); + data << uint32(_player->GetLevelPlayedTime()); + data << uint8(unk1); // 0 - will not show in chat frame SendPacket(&data); } @@ -1356,7 +1358,7 @@ void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) uint32 accid = plr->GetSession()->GetAccountId(); - QueryResult *result = LoginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid); + QueryResult *result = loginDatabase.PQuery("SELECT username,email,last_ip FROM account WHERE id=%u", accid); if(!result) { SendNotification(LANG_ACCOUNT_FOR_PLAYER_NOT_FOUND, charname.c_str()); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d610031da00..f96eff21012 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -4110,7 +4110,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE guid = '%u'",guid); CharacterDatabase.CommitTransaction(); - //LoginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID); + //loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID); if(updateRealmChars) sWorld.UpdateRealmCharCount(accountId); } @@ -12882,7 +12882,7 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) //starting initial quest script if(questGiver && pQuest->GetQuestStartScript()!=0) - sWorld.ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this); + GetMap()->ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this); // Some spells applied at quest activation SpellAreaForQuestMapBounds saBounds = spellmgr.GetSpellAreaForQuestMapBounds(quest_id,true); @@ -14142,7 +14142,7 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive GetSession()->SendPacket( &data ); if (pQuest->GetQuestCompleteScript() != 0) - sWorld.ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this); + GetMap()->ScriptsStart(sQuestEndScripts, pQuest->GetQuestCompleteScript(), questGiver, this); } void Player::SendQuestFailed( uint32 quest_id ) diff --git a/src/game/PointMovementGenerator.cpp b/src/game/PointMovementGenerator.cpp index 24baa4939b4..ffd036e9c21 100644 --- a/src/game/PointMovementGenerator.cpp +++ b/src/game/PointMovementGenerator.cpp @@ -30,7 +30,6 @@ template<class T> void PointMovementGenerator<T>::Initialize(T &unit) { unit.StopMoving(); - unit.clearUnitState(UNIT_STAT_MOVING); Traveller<T> traveller(unit); // knockback effect has UNIT_STAT_JUMPING set,so if here we disable sentmonstermove there will be creature position sync problem between client and server i_destinationHolder.SetDestination(traveller,i_x,i_y,i_z, true /* !unit.hasUnitState(UNIT_STAT_JUMPING)*/); diff --git a/src/game/ReputationMgr.cpp b/src/game/ReputationMgr.cpp index 7536fb54f03..e4ed5b0db2e 100644 --- a/src/game/ReputationMgr.cpp +++ b/src/game/ReputationMgr.cpp @@ -475,4 +475,4 @@ void ReputationMgr::UpdateRankCounters( ReputationRank old_rank, ReputationRank ++m_reveredFactionCount; if(new_rank >= REP_HONORED) ++m_honoredFactionCount; -}
\ No newline at end of file +} diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 957ef4449a6..441234eed73 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -703,190 +703,194 @@ enum SpellEffects enum SpellCastResult { - SPELL_FAILED_AFFECTING_COMBAT = 0, - SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 1, - SPELL_FAILED_ALREADY_AT_FULL_MANA = 2, - SPELL_FAILED_ALREADY_AT_FULL_POWER = 3, - SPELL_FAILED_ALREADY_BEING_TAMED = 4, - SPELL_FAILED_ALREADY_HAVE_CHARM = 5, - SPELL_FAILED_ALREADY_HAVE_SUMMON = 6, - SPELL_FAILED_ALREADY_OPEN = 7, - SPELL_FAILED_AURA_BOUNCED = 8, - SPELL_FAILED_AUTOTRACK_INTERRUPTED = 9, - SPELL_FAILED_BAD_IMPLICIT_TARGETS = 10, - SPELL_FAILED_BAD_TARGETS = 11, - SPELL_FAILED_CANT_BE_CHARMED = 12, - SPELL_FAILED_CANT_BE_DISENCHANTED = 13, - SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 14, - SPELL_FAILED_CANT_BE_MILLED = 15, - SPELL_FAILED_CANT_BE_PROSPECTED = 16, - SPELL_FAILED_CANT_CAST_ON_TAPPED = 17, - SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 18, - SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 19, - SPELL_FAILED_CANT_STEALTH = 20, - SPELL_FAILED_CASTER_AURASTATE = 21, - SPELL_FAILED_CASTER_DEAD = 22, - SPELL_FAILED_CHARMED = 23, - SPELL_FAILED_CHEST_IN_USE = 24, - SPELL_FAILED_CONFUSED = 25, - SPELL_FAILED_DONT_REPORT = 26, - SPELL_FAILED_EQUIPPED_ITEM = 27, - SPELL_FAILED_EQUIPPED_ITEM_CLASS = 28, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 29, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 30, - SPELL_FAILED_ERROR = 31, - SPELL_FAILED_FIZZLE = 32, - SPELL_FAILED_FLEEING = 33, - SPELL_FAILED_FOOD_LOWLEVEL = 34, - SPELL_FAILED_HIGHLEVEL = 35, - SPELL_FAILED_HUNGER_SATIATED = 36, - SPELL_FAILED_IMMUNE = 37, - SPELL_FAILED_INCORRECT_AREA = 38, - SPELL_FAILED_INTERRUPTED = 39, - SPELL_FAILED_INTERRUPTED_COMBAT = 40, - SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 41, - SPELL_FAILED_ITEM_GONE = 42, - SPELL_FAILED_ITEM_NOT_FOUND = 43, - SPELL_FAILED_ITEM_NOT_READY = 44, - SPELL_FAILED_LEVEL_REQUIREMENT = 45, - SPELL_FAILED_LINE_OF_SIGHT = 46, - SPELL_FAILED_LOWLEVEL = 47, - SPELL_FAILED_LOW_CASTLEVEL = 48, - SPELL_FAILED_MAINHAND_EMPTY = 49, - SPELL_FAILED_MOVING = 50, - SPELL_FAILED_NEED_AMMO = 51, - SPELL_FAILED_NEED_AMMO_POUCH = 52, - SPELL_FAILED_NEED_EXOTIC_AMMO = 53, - SPELL_FAILED_NEED_MORE_ITEMS = 54, - SPELL_FAILED_NOPATH = 55, - SPELL_FAILED_NOT_BEHIND = 56, - SPELL_FAILED_NOT_FISHABLE = 57, - SPELL_FAILED_NOT_FLYING = 58, - SPELL_FAILED_NOT_HERE = 59, - SPELL_FAILED_NOT_INFRONT = 60, - SPELL_FAILED_NOT_IN_CONTROL = 61, - SPELL_FAILED_NOT_KNOWN = 62, - SPELL_FAILED_NOT_MOUNTED = 63, - SPELL_FAILED_NOT_ON_TAXI = 64, - SPELL_FAILED_NOT_ON_TRANSPORT = 65, - SPELL_FAILED_NOT_READY = 66, - SPELL_FAILED_NOT_SHAPESHIFT = 67, - SPELL_FAILED_NOT_STANDING = 68, - SPELL_FAILED_NOT_TRADEABLE = 69, - SPELL_FAILED_NOT_TRADING = 70, - SPELL_FAILED_NOT_UNSHEATHED = 71, - SPELL_FAILED_NOT_WHILE_GHOST = 72, - SPELL_FAILED_NOT_WHILE_LOOTING = 73, - SPELL_FAILED_NO_AMMO = 74, - SPELL_FAILED_NO_CHARGES_REMAIN = 75, - SPELL_FAILED_NO_CHAMPION = 76, - SPELL_FAILED_NO_COMBO_POINTS = 77, - SPELL_FAILED_NO_DUELING = 78, - SPELL_FAILED_NO_ENDURANCE = 79, - SPELL_FAILED_NO_FISH = 80, - SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 81, - SPELL_FAILED_NO_MOUNTS_ALLOWED = 82, - SPELL_FAILED_NO_PET = 83, - SPELL_FAILED_NO_POWER = 84, - SPELL_FAILED_NOTHING_TO_DISPEL = 85, - SPELL_FAILED_NOTHING_TO_STEAL = 86, - SPELL_FAILED_ONLY_ABOVEWATER = 87, - SPELL_FAILED_ONLY_DAYTIME = 88, - SPELL_FAILED_ONLY_INDOORS = 89, - SPELL_FAILED_ONLY_MOUNTED = 90, - SPELL_FAILED_ONLY_NIGHTTIME = 91, - SPELL_FAILED_ONLY_OUTDOORS = 92, - SPELL_FAILED_ONLY_SHAPESHIFT = 93, - SPELL_FAILED_ONLY_STEALTHED = 94, - SPELL_FAILED_ONLY_UNDERWATER = 95, - SPELL_FAILED_OUT_OF_RANGE = 96, - SPELL_FAILED_PACIFIED = 97, - SPELL_FAILED_POSSESSED = 98, - SPELL_FAILED_REAGENTS = 99, - SPELL_FAILED_REQUIRES_AREA = 100, - SPELL_FAILED_REQUIRES_SPELL_FOCUS = 101, - SPELL_FAILED_ROOTED = 102, - SPELL_FAILED_SILENCED = 103, - SPELL_FAILED_SPELL_IN_PROGRESS = 104, - SPELL_FAILED_SPELL_LEARNED = 105, - SPELL_FAILED_SPELL_UNAVAILABLE = 106, - SPELL_FAILED_STUNNED = 107, - SPELL_FAILED_TARGETS_DEAD = 108, - SPELL_FAILED_TARGET_AFFECTING_COMBAT = 109, - SPELL_FAILED_TARGET_AURASTATE = 110, - SPELL_FAILED_TARGET_DUELING = 111, - SPELL_FAILED_TARGET_ENEMY = 112, - SPELL_FAILED_TARGET_ENRAGED = 113, - SPELL_FAILED_TARGET_FRIENDLY = 114, - SPELL_FAILED_TARGET_IN_COMBAT = 115, - SPELL_FAILED_TARGET_IS_PLAYER = 116, - SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 117, - SPELL_FAILED_TARGET_NOT_DEAD = 118, - SPELL_FAILED_TARGET_NOT_IN_PARTY = 119, - SPELL_FAILED_TARGET_NOT_LOOTED = 120, - SPELL_FAILED_TARGET_NOT_PLAYER = 121, - SPELL_FAILED_TARGET_NO_POCKETS = 122, - SPELL_FAILED_TARGET_NO_WEAPONS = 123, - SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 124, - SPELL_FAILED_TARGET_UNSKINNABLE = 125, - SPELL_FAILED_THIRST_SATIATED = 126, - SPELL_FAILED_TOO_CLOSE = 127, - SPELL_FAILED_TOO_MANY_OF_ITEM = 128, - SPELL_FAILED_TOTEM_CATEGORY = 129, - SPELL_FAILED_TOTEMS = 130, - SPELL_FAILED_TRY_AGAIN = 131, - SPELL_FAILED_UNIT_NOT_BEHIND = 132, - SPELL_FAILED_UNIT_NOT_INFRONT = 133, - SPELL_FAILED_WRONG_PET_FOOD = 134, - SPELL_FAILED_NOT_WHILE_FATIGUED = 135, - SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 136, - SPELL_FAILED_NOT_WHILE_TRADING = 137, - SPELL_FAILED_TARGET_NOT_IN_RAID = 138, - SPELL_FAILED_TARGET_FREEFORALL = 139, - SPELL_FAILED_NO_EDIBLE_CORPSES = 140, - SPELL_FAILED_ONLY_BATTLEGROUNDS = 141, - SPELL_FAILED_TARGET_NOT_GHOST = 142, - SPELL_FAILED_TRANSFORM_UNUSABLE = 143, - SPELL_FAILED_WRONG_WEATHER = 144, - SPELL_FAILED_DAMAGE_IMMUNE = 145, - SPELL_FAILED_PREVENTED_BY_MECHANIC = 146, - SPELL_FAILED_PLAY_TIME = 147, - SPELL_FAILED_REPUTATION = 148, - SPELL_FAILED_MIN_SKILL = 149, - SPELL_FAILED_NOT_IN_ARENA = 150, - SPELL_FAILED_NOT_ON_SHAPESHIFT = 151, - SPELL_FAILED_NOT_ON_STEALTHED = 152, - SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 153, - SPELL_FAILED_NOT_ON_MOUNTED = 154, - SPELL_FAILED_TOO_SHALLOW = 155, - SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 156, - SPELL_FAILED_TARGET_IS_TRIVIAL = 157, - SPELL_FAILED_BM_OR_INVISGOD = 158, - SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 159, - SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 160, - SPELL_FAILED_NOT_IDLE = 161, - SPELL_FAILED_NOT_INACTIVE = 162, - SPELL_FAILED_PARTIAL_PLAYTIME = 163, - SPELL_FAILED_NO_PLAYTIME = 164, - SPELL_FAILED_NOT_IN_BATTLEGROUND = 165, - SPELL_FAILED_NOT_IN_RAID_INSTANCE = 166, - SPELL_FAILED_ONLY_IN_ARENA = 167, - SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 168, - SPELL_FAILED_ON_USE_ENCHANT = 169, - SPELL_FAILED_NOT_ON_GROUND = 170, - SPELL_FAILED_CUSTOM_ERROR = 171, - SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 172, - SPELL_FAILED_TOO_MANY_SOCKETS = 173, - SPELL_FAILED_INVALID_GLYPH = 174, - SPELL_FAILED_UNIQUE_GLYPH = 175, - SPELL_FAILED_GLYPH_SOCKET_LOCKED = 176, - SPELL_FAILED_NO_VALID_TARGETS = 177, - SPELL_FAILED_ITEM_AT_MAX_CHARGES = 178, - SPELL_FAILED_NOT_IN_BARBERSHOP = 179, - SPELL_FAILED_FISHING_TOO_LOW = 180, - SPELL_FAILED_UNKNOWN = 181, - - SPELL_CAST_OK = 255 //custom value, don't must be send to client + SPELL_FAILED_AFFECTING_COMBAT = 0x00, + SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01, + SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02, + SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03, + SPELL_FAILED_ALREADY_BEING_TAMED = 0x04, + SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05, + SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06, + SPELL_FAILED_ALREADY_OPEN = 0x07, + SPELL_FAILED_AURA_BOUNCED = 0x08, + SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09, + SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A, + SPELL_FAILED_BAD_TARGETS = 0x0B, + SPELL_FAILED_CANT_BE_CHARMED = 0x0C, + SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D, + SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E, + SPELL_FAILED_CANT_BE_MILLED = 0x0F, + SPELL_FAILED_CANT_BE_PROSPECTED = 0x10, + SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x11, + SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x12, + SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x13, + SPELL_FAILED_CANT_STEALTH = 0x14, + SPELL_FAILED_CASTER_AURASTATE = 0x15, + SPELL_FAILED_CASTER_DEAD = 0x16, + SPELL_FAILED_CHARMED = 0x17, + SPELL_FAILED_CHEST_IN_USE = 0x18, + SPELL_FAILED_CONFUSED = 0x19, + SPELL_FAILED_DONT_REPORT = 0x1A, + SPELL_FAILED_EQUIPPED_ITEM = 0x1B, + SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1C, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1D, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1E, + SPELL_FAILED_ERROR = 0x1F, + SPELL_FAILED_FIZZLE = 0x20, + SPELL_FAILED_FLEEING = 0x21, + SPELL_FAILED_FOOD_LOWLEVEL = 0x22, + SPELL_FAILED_HIGHLEVEL = 0x23, + SPELL_FAILED_HUNGER_SATIATED = 0x24, + SPELL_FAILED_IMMUNE = 0x25, + SPELL_FAILED_INCORRECT_AREA = 0x26, + SPELL_FAILED_INTERRUPTED = 0x27, + SPELL_FAILED_INTERRUPTED_COMBAT = 0x28, + SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x29, + SPELL_FAILED_ITEM_GONE = 0x2A, + SPELL_FAILED_ITEM_NOT_FOUND = 0x2B, + SPELL_FAILED_ITEM_NOT_READY = 0x2C, + SPELL_FAILED_LEVEL_REQUIREMENT = 0x2D, + SPELL_FAILED_LINE_OF_SIGHT = 0x2E, + SPELL_FAILED_LOWLEVEL = 0x2F, + SPELL_FAILED_LOW_CASTLEVEL = 0x30, + SPELL_FAILED_MAINHAND_EMPTY = 0x31, + SPELL_FAILED_MOVING = 0x32, + SPELL_FAILED_NEED_AMMO = 0x33, + SPELL_FAILED_NEED_AMMO_POUCH = 0x34, + SPELL_FAILED_NEED_EXOTIC_AMMO = 0x35, + SPELL_FAILED_NEED_MORE_ITEMS = 0x36, + SPELL_FAILED_NOPATH = 0x37, + SPELL_FAILED_NOT_BEHIND = 0x38, + SPELL_FAILED_NOT_FISHABLE = 0x39, + SPELL_FAILED_NOT_FLYING = 0x3A, + SPELL_FAILED_NOT_HERE = 0x3B, + SPELL_FAILED_NOT_INFRONT = 0x3C, + SPELL_FAILED_NOT_IN_CONTROL = 0x3D, + SPELL_FAILED_NOT_KNOWN = 0x3E, + SPELL_FAILED_NOT_MOUNTED = 0x3F, + SPELL_FAILED_NOT_ON_TAXI = 0x40, + SPELL_FAILED_NOT_ON_TRANSPORT = 0x41, + SPELL_FAILED_NOT_READY = 0x42, + SPELL_FAILED_NOT_SHAPESHIFT = 0x43, + SPELL_FAILED_NOT_STANDING = 0x44, + SPELL_FAILED_NOT_TRADEABLE = 0x45, + SPELL_FAILED_NOT_TRADING = 0x46, + SPELL_FAILED_NOT_UNSHEATHED = 0x47, + SPELL_FAILED_NOT_WHILE_GHOST = 0x48, + SPELL_FAILED_NOT_WHILE_LOOTING = 0x49, + SPELL_FAILED_NO_AMMO = 0x4A, + SPELL_FAILED_NO_CHARGES_REMAIN = 0x4B, + SPELL_FAILED_NO_CHAMPION = 0x4C, + SPELL_FAILED_NO_COMBO_POINTS = 0x4D, + SPELL_FAILED_NO_DUELING = 0x4E, + SPELL_FAILED_NO_ENDURANCE = 0x4F, + SPELL_FAILED_NO_FISH = 0x50, + SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x51, + SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x52, + SPELL_FAILED_NO_PET = 0x53, + SPELL_FAILED_NO_POWER = 0x54, + SPELL_FAILED_NOTHING_TO_DISPEL = 0x55, + SPELL_FAILED_NOTHING_TO_STEAL = 0x56, + SPELL_FAILED_ONLY_ABOVEWATER = 0x57, + SPELL_FAILED_ONLY_DAYTIME = 0x58, + SPELL_FAILED_ONLY_INDOORS = 0x59, + SPELL_FAILED_ONLY_MOUNTED = 0x5A, + SPELL_FAILED_ONLY_NIGHTTIME = 0x5B, + SPELL_FAILED_ONLY_OUTDOORS = 0x5C, + SPELL_FAILED_ONLY_SHAPESHIFT = 0x5D, + SPELL_FAILED_ONLY_STEALTHED = 0x5E, + SPELL_FAILED_ONLY_UNDERWATER = 0x5F, + SPELL_FAILED_OUT_OF_RANGE = 0x60, + SPELL_FAILED_PACIFIED = 0x61, + SPELL_FAILED_POSSESSED = 0x62, + SPELL_FAILED_REAGENTS = 0x63, + SPELL_FAILED_REQUIRES_AREA = 0x64, + SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x65, + SPELL_FAILED_ROOTED = 0x66, + SPELL_FAILED_SILENCED = 0x67, + SPELL_FAILED_SPELL_IN_PROGRESS = 0x68, + SPELL_FAILED_SPELL_LEARNED = 0x69, + SPELL_FAILED_SPELL_UNAVAILABLE = 0x6A, + SPELL_FAILED_STUNNED = 0x6B, + SPELL_FAILED_TARGETS_DEAD = 0x6C, + SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x6D, + SPELL_FAILED_TARGET_AURASTATE = 0x6E, + SPELL_FAILED_TARGET_DUELING = 0x6F, + SPELL_FAILED_TARGET_ENEMY = 0x70, + SPELL_FAILED_TARGET_ENRAGED = 0x71, + SPELL_FAILED_TARGET_FRIENDLY = 0x72, + SPELL_FAILED_TARGET_IN_COMBAT = 0x73, + SPELL_FAILED_TARGET_IS_PLAYER = 0x74, + SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x75, + SPELL_FAILED_TARGET_NOT_DEAD = 0x76, + SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x77, + SPELL_FAILED_TARGET_NOT_LOOTED = 0x78, + SPELL_FAILED_TARGET_NOT_PLAYER = 0x79, + SPELL_FAILED_TARGET_NO_POCKETS = 0x7A, + SPELL_FAILED_TARGET_NO_WEAPONS = 0x7B, + SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 0x7C, + SPELL_FAILED_TARGET_UNSKINNABLE = 0x7D, + SPELL_FAILED_THIRST_SATIATED = 0x7E, + SPELL_FAILED_TOO_CLOSE = 0x7F, + SPELL_FAILED_TOO_MANY_OF_ITEM = 0x80, + SPELL_FAILED_TOTEM_CATEGORY = 0x81, + SPELL_FAILED_TOTEMS = 0x82, + SPELL_FAILED_TRY_AGAIN = 0x83, + SPELL_FAILED_UNIT_NOT_BEHIND = 0x84, + SPELL_FAILED_UNIT_NOT_INFRONT = 0x85, + SPELL_FAILED_WRONG_PET_FOOD = 0x86, + SPELL_FAILED_NOT_WHILE_FATIGUED = 0x87, + SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x88, + SPELL_FAILED_NOT_WHILE_TRADING = 0x89, + SPELL_FAILED_TARGET_NOT_IN_RAID = 0x8A, + SPELL_FAILED_TARGET_FREEFORALL = 0x8B, + SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8C, + SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8D, + SPELL_FAILED_TARGET_NOT_GHOST = 0x8E, + SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F, + SPELL_FAILED_WRONG_WEATHER = 0x90, + SPELL_FAILED_DAMAGE_IMMUNE = 0x91, + SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92, + SPELL_FAILED_PLAY_TIME = 0x93, + SPELL_FAILED_REPUTATION = 0x94, + SPELL_FAILED_MIN_SKILL = 0x95, + SPELL_FAILED_NOT_IN_ARENA = 0x96, + SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97, + SPELL_FAILED_NOT_ON_STEALTHED = 0x98, + SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99, + SPELL_FAILED_NOT_ON_MOUNTED = 0x9A, + SPELL_FAILED_TOO_SHALLOW = 0x9B, + SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C, + SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D, + SPELL_FAILED_BM_OR_INVISGOD = 0x9E, + SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F, + SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0, + SPELL_FAILED_NOT_IDLE = 0xA1, + SPELL_FAILED_NOT_INACTIVE = 0xA2, + SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3, + SPELL_FAILED_NO_PLAYTIME = 0xA4, + SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5, + SPELL_FAILED_NOT_IN_RAID_INSTANCE = 0xA6, + SPELL_FAILED_ONLY_IN_ARENA = 0xA7, + SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA8, + SPELL_FAILED_ON_USE_ENCHANT = 0xA9, + SPELL_FAILED_NOT_ON_GROUND = 0xAA, + SPELL_FAILED_CUSTOM_ERROR = 0xAB, + SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 0xAC, + SPELL_FAILED_TOO_MANY_SOCKETS = 0xAD, + SPELL_FAILED_INVALID_GLYPH = 0xAE, + SPELL_FAILED_UNIQUE_GLYPH = 0xAF, + SPELL_FAILED_GLYPH_SOCKET_LOCKED = 0xB0, + SPELL_FAILED_NO_VALID_TARGETS = 0xB1, + SPELL_FAILED_ITEM_AT_MAX_CHARGES = 0xB2, + SPELL_FAILED_NOT_IN_BARBERSHOP = 0xB3, + SPELL_FAILED_FISHING_TOO_LOW = 0xB4, + SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 0xB5, + SPELL_FAILED_SUMMON_PENDING = 0xB6, + SPELL_FAILED_MAX_SOCKETS = 0xB7, + SPELL_FAILED_PET_CAN_RENAME = 0xB8, + SPELL_FAILED_UNKNOWN = 0xB9, + + SPELL_CAST_OK = 0xFF // custom value, don't must be send to client }; // Spell aura states @@ -970,7 +974,13 @@ enum Mechanics (1<<MECHANIC_SHACKLE )|(1<<MECHANIC_TURN )|(1<<MECHANIC_HORROR)| \ (1<<MECHANIC_DAZE )|(1<<MECHANIC_SAPPED ) ) -// Spell dispel type +// Daze and all croud control spells except polymorph are not removed +#define MECHANIC_NOT_REMOVED_BY_SHAPESHIFT ( \ + (1<<MECHANIC_CHARM )|(1<<MECHANIC_DISORIENTED)|(1<<MECHANIC_FEAR )|(1<<MECHANIC_PACIFY )| \ + (1<<MECHANIC_STUN )|(1<<MECHANIC_FREEZE )|(1<<MECHANIC_BANISH)|(1<<MECHANIC_SHACKLE)| \ + (1<<MECHANIC_HORROR)|(1<<MECHANIC_TURN )|(1<<MECHANIC_DAZE )|(1<<MECHANIC_SAPPED ) ) + +// Spell dispell type enum DispelType { DISPEL_NONE = 0, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 54e796a8231..af5cda5bec3 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2222,6 +2222,7 @@ void Spell::SetTargetMap(uint32 i, uint32 cur) case TARGET_UNIT_AREA_ENEMY_DST: case TARGET_UNIT_CONE_ENEMY: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + case TARGET_UNIT_AREA_PATH: radius = GetSpellRadius(m_spellInfo, i, false); targetType = SPELL_TARGETS_ENEMY; break; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 6ac842128b7..eef918ae5e8 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3235,13 +3235,37 @@ void AuraEffect::HandleAuraModShapeshift(bool apply, bool Real, bool changeAmoun case FORM_FLIGHT_EPIC: case FORM_FLIGHT: case FORM_MOONKIN: + { // remove movement affects m_target->RemoveMovementImpairingAuras(); +/* + m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + Unit::AuraList const& slowingAuras = m_target->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); + for (Unit::AuraList::const_iterator iter = slowingAuras.begin(); iter != slowingAuras.end();) + { + SpellEntry const* aurSpellInfo = (*iter)->GetSpellProto(); + + // If spell that caused this aura has Croud Control or Daze effect + if((GetAllSpellMechanicMask(aurSpellInfo) & MECHANIC_NOT_REMOVED_BY_SHAPESHIFT) || + // some Daze spells have these parameters instead of MECHANIC_DAZE + (aurSpellInfo->SpellIconID == 15 && aurSpellInfo->Dispel == 0)) + { + ++iter; + continue; + } + + // All OK, remove aura now + m_target->RemoveAurasDueToSpellByCancel(aurSpellInfo->Id); + iter = slowingAuras.begin(); + } +*/ // and polymorphic affects if(m_target->IsPolymorphed()) m_target->RemoveAurasDueToSpell(m_target->getTransForm()); + break; + } default: break; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 2e683e05122..2dca13cd08a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2483,7 +2483,7 @@ void Spell::EffectSendEvent(uint32 EffectIndex) we do not handle a flag dropping or clicking on flag in battleground by sendevent system */ sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id); - sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject); + m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject); } void Spell::EffectPowerBurn(uint32 i) @@ -2880,31 +2880,31 @@ void Spell::EffectEnergize(uint32 i) Powers power = Powers(m_spellInfo->EffectMiscValue[i]); // Some level depends spells - int multiplier = 0; + int level_multiplier = 0; int level_diff = 0; switch (m_spellInfo->Id) { - // Restore Energy - case 9512: + case 9512: // Restore Energy level_diff = m_caster->getLevel() - 40; - multiplier = 2; + level_multiplier = 2; break; - // Blood Fury - case 24571: + case 24571: // Blood Fury level_diff = m_caster->getLevel() - 60; - multiplier = 10; + level_multiplier = 10; break; - // Burst of Energy - case 24532: + case 24532: // Burst of Energy level_diff = m_caster->getLevel() - 60; - multiplier = 4; + level_multiplier = 4; break; + case 31930: // Judgements of the Wise + case 63375: // Improved Stormstrike + damage = damage * unitTarget->GetCreateMana() / 100; default: break; } if (level_diff > 0) - damage -= multiplier * level_diff; + damage -= level_multiplier * level_diff; if(damage < 0) return; @@ -2999,7 +2999,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype) case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: gameObjTarget->UseDoorOrButton(); - sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget); + player->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget); return; case GAMEOBJECT_TYPE_QUESTGIVER: @@ -3019,7 +3019,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype) if (gameObjTarget->GetGOInfo()->goober.eventId) { sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow()); - sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget); + player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget); gameObjTarget->EventInform(gameObjTarget->GetGOInfo()->goober.eventId); } @@ -3030,7 +3030,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype) return; Script->GOHello(player, gameObjTarget); - sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget); + gameObjTarget->GetMap()->ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget); gameObjTarget->AddUniqueUse(player); gameObjTarget->SetLootState(GO_JUST_DEACTIVATED); @@ -3052,7 +3052,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype) if (gameObjTarget->GetGOInfo()->chest.eventId) { sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow()); - sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget); + player->GetMap()->ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget); } // triggering linked GO @@ -5501,7 +5501,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) // normal DB scripted effect sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id); - sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); + m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); } void Spell::EffectSanctuary(uint32 /*i*/) @@ -5703,7 +5703,7 @@ void Spell::EffectActivateObject(uint32 effect_idx) int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx]; - sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); + gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); } void Spell::EffectApplyGlyph(uint32 i) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index f1f43d57821..234a7e3aaa1 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -147,6 +147,7 @@ SpellMgr::SpellMgr() case TARGET_UNIT_CONE_ALLY: case TARGET_UNIT_CONE_ENTRY: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + case TARGET_UNIT_AREA_PATH: SpellTargetType[i] = TARGET_TYPE_AREA_CONE; break; case TARGET_DST_CASTER: @@ -226,6 +227,7 @@ SpellMgr::SpellMgr() case TARGET_UNIT_CONE_ENEMY: case TARGET_UNIT_CONE_ALLY: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: + case TARGET_UNIT_AREA_PATH: case TARGET_UNIT_RAID_CASTER: IsAreaEffectTarget[i] = true; break; @@ -3846,6 +3848,7 @@ void SpellMgr::LoadSpellCustomAttr() case 40810: case 43267: case 43268: // Saber Lash case 42384: // Brutal Swipe case 45150: // Meteor Slash + case 64422: case 64688: // Sonic Screech mSpellCustomAttr[i] |= SPELL_ATTR_CU_SHARE_DAMAGE; break; case 59725: // Improved Spell Reflection - aoe aura diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index b0a588509f4..b2a89805ea9 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -487,7 +487,7 @@ void Transport::CheckForEvent(uint32 entry, uint32 wp_id) { uint32 key = entry*100+wp_id; if(objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end()) - sWorld.ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL); + GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL); } void Transport::Update(uint32 /*p_time*/) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index c72187df8f3..692185910db 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6202,8 +6202,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger // Judgements of the Wise if (dummySpell->SpellIconID == 3017) { - // hardcoded amount - basepoints0 = 25 * GetCreatePowers(POWER_MANA)/100; target = this; triggered_spell_id = 31930; // replenishment @@ -7052,6 +7050,7 @@ bool Unit::HandleObsModEnergyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id); + // Try handle unknown trigger spells if(!triggerEntry) { sLog.outError("Unit::HandleObsModEnergyAuraProc: Spell %u have not existed triggered spell %u",dummySpell->Id,triggered_spell_id); @@ -7872,9 +7871,15 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig ((Player*)this)->RemoveSpellCategoryCooldown(1209, true); break; } - case 63375: // Improved Stormstrike + // Maelstrom Weapon + case 53817: { - basepoints0 = GetCreateMana() * 0.20f; + // have rank dependent proc chance, ignore too often cases + // PPM = 2.5 * (rank of talent), + uint32 rank = spellmgr.GetSpellRank(auraSpellInfo->Id); + // 5 rank -> 100% 4 rank -> 80% and etc from full rate + if(!roll_chance_i(20*rank)) + return false; break; } // Brain Freeze diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index 34be9d3179b..92fd9bca2d7 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -198,7 +198,7 @@ WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff) //note: disable "start" for mtmap if(node->event_id && rand()%100 < node->event_chance) - sWorld.ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL, false); + unit.GetMap()->ScriptsStart(sWaypointScripts, node->event_id, &unit, NULL/*, false*/); MovementInform(unit); unit.UpdateWaypointID(i_currentNode); diff --git a/src/game/World.cpp b/src/game/World.cpp index db59f101389..47f18362ce3 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -63,7 +63,6 @@ #include "GridNotifiersImpl.h" #include "CellImpl.h" #include "InstanceSaveMgr.h" -#include "WaypointManager.h" #include "Util.h" #include "Language.h" #include "CreatureGroups.h" @@ -83,14 +82,6 @@ float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE; float World::m_VisibleUnitGreyDistance = 0; float World::m_VisibleObjectGreyDistance = 0; -struct ScriptAction -{ - uint64 sourceGUID; - uint64 targetGUID; - uint64 ownerGUID; // owner of source if source is item - ScriptInfo const* script; // pointer to static script data -}; - /// World constructor World::World() { @@ -106,6 +97,7 @@ World::World() m_MaxPlayerCount = 0; m_resultQueue = NULL; m_NextDailyQuestReset = 0; + m_scheduledScripts = 0; m_defaultDbcLocale = LOCALE_enUS; m_availableDbcLocaleMask = 0; @@ -268,7 +260,7 @@ World::AddSession_ (WorldSession* s) float popu = GetActiveSessionCount (); //updated number of users on the server popu /= pLimit; popu *= 2; - LoginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); + loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); sLog.outDetail ("Server Population (%f).", popu); } } @@ -1180,7 +1172,7 @@ void World::SetInitialWorldSettings() // not send custom type REALM_FFA_PVP to realm list uint32 server_type = IsFFAPvPRealm() ? REALM_TYPE_PVP : getConfig(CONFIG_GAME_TYPE); uint32 realm_zone = getConfig(CONFIG_REALM_ZONE); - LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); + loginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID); ///- Remove the bones after a restart CharacterDatabase.PExecute("DELETE FROM corpse WHERE corpse_type = '0'"); @@ -1535,7 +1527,7 @@ void World::SetInitialWorldSettings() sprintf( isoDate, "%04d-%02d-%02d %02d:%02d:%02d", local.tm_year+1900, local.tm_mon+1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec); - LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)", + loginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)", realmID, uint64(m_startTime), isoDate); m_timers[WUPDATE_OBJECTS].SetInterval(IN_MILISECONDS/2); @@ -1586,7 +1578,7 @@ void World::SetInitialWorldSettings() objmgr.LoadTransportEvents(); sLog.outString("Deleting expired bans..." ); - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); sLog.outString("Calculate next daily quest reset time..." ); InitDailyQuestResetTime(); @@ -1769,7 +1761,7 @@ void World::Update(uint32 diff) uint32 maxClientsNum = GetMaxActiveSessionCount(); m_timers[WUPDATE_UPTIME].Reset(); - LoginDatabase.PExecute("UPDATE uptime SET uptime = %u, maxplayers = %u WHERE realmid = %u AND starttime = " UI64FMTD, tmpDiff, maxClientsNum, realmID, uint64(m_startTime)); + loginDatabase.PExecute("UPDATE uptime SET uptime = %u, maxplayers = %u WHERE realmid = %u AND starttime = " UI64FMTD, tmpDiff, maxClientsNum, realmID, uint64(m_startTime)); } /// <li> Clean logs table @@ -1781,7 +1773,7 @@ void World::Update(uint32 diff) uint32 maxClientsNum = sWorld.GetMaxActiveSessionCount(); m_timers[WUPDATE_CLEANDB].Reset(); - LoginDatabase.PExecute("DELETE FROM logs WHERE (time + %u) < "UI64FMTD";", + loginDatabase.PExecute("DELETE FROM logs WHERE (time + %u) < "UI64FMTD";", sWorld.getConfig(CONFIG_LOGDB_CLEARTIME), uint64(time(0))); } } @@ -1796,14 +1788,6 @@ void World::Update(uint32 diff) MapManager::Instance().DoDelayedMovesAndRemoves(); }*/ - ///- Process necessary scripts - if (!m_scriptSchedule.empty()) - { - RecordTimeDiff(NULL); - ScriptsProcess(); - RecordTimeDiff("UpdateScriptsProcess"); - } - sBattleGroundMgr.Update(diff); RecordTimeDiff("UpdateBattleGroundMgr"); @@ -1848,831 +1832,6 @@ void World::ForceGameEventUpdate() m_timers[WUPDATE_EVENTS].Reset(); } -/// Put scripts in the execution queue -void World::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, Object* target, bool start) -{ - ///- Find the script map - ScriptMapMap::const_iterator s = scripts.find(id); - if (s == scripts.end()) - return; - - // prepare static data - uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; //some script commands doesn't have source - uint64 targetGUID = target ? target->GetGUID() : (uint64)0; - uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; - - ///- Schedule script execution for all scripts in the script map - ScriptMap const *s2 = &(s->second); - bool immedScript = false; - for (ScriptMap::const_iterator iter = s2->begin(); iter != s2->end(); ++iter) - { - ScriptAction sa; - sa.sourceGUID = sourceGUID; - sa.targetGUID = targetGUID; - sa.ownerGUID = ownerGUID; - - sa.script = &iter->second; - m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(m_gameTime + iter->first, sa)); - if (iter->first == 0) - immedScript = true; - } - ///- If one of the effects should be immediate, launch the script execution - if (start && immedScript) - ScriptsProcess(); -} - -void World::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target) -{ - // NOTE: script record _must_ exist until command executed - - // prepare static data - uint64 sourceGUID = source ? source->GetGUID() : (uint64)0; - uint64 targetGUID = target ? target->GetGUID() : (uint64)0; - uint64 ownerGUID = (source->GetTypeId()==TYPEID_ITEM) ? ((Item*)source)->GetOwnerGUID() : (uint64)0; - - ScriptAction sa; - sa.sourceGUID = sourceGUID; - sa.targetGUID = targetGUID; - sa.ownerGUID = ownerGUID; - - sa.script = &script; - m_scriptSchedule.insert(std::pair<time_t, ScriptAction>(m_gameTime + delay, sa)); - - ///- If effects should be immediate, launch the script execution - if(delay == 0) - ScriptsProcess(); -} - -/// Process queued scripts -void World::ScriptsProcess() -{ - if (m_scriptSchedule.empty()) - return; - - ///- Process overdue queued scripts - std::multimap<time_t, ScriptAction>::iterator iter = m_scriptSchedule.begin(); - // ok as multimap is a *sorted* associative container - while (!m_scriptSchedule.empty() && (iter->first <= m_gameTime)) - { - ScriptAction const& step = iter->second; - - Object* source = NULL; - - if(step.sourceGUID) - { - switch(GUID_HIPART(step.sourceGUID)) - { - case HIGHGUID_ITEM: - // case HIGHGUID_CONTAINER: ==HIGHGUID_ITEM - { - Player* player = HashMapHolder<Player>::Find(step.ownerGUID); - if(player) - source = player->GetItemByGuid(step.sourceGUID); - break; - } - case HIGHGUID_UNIT: - source = HashMapHolder<Creature>::Find(step.sourceGUID); - break; - case HIGHGUID_PET: - source = HashMapHolder<Pet>::Find(step.sourceGUID); - break; - case HIGHGUID_VEHICLE: - source = HashMapHolder<Vehicle>::Find(step.sourceGUID); - break; - case HIGHGUID_PLAYER: - source = HashMapHolder<Player>::Find(step.sourceGUID); - break; - case HIGHGUID_GAMEOBJECT: - source = HashMapHolder<GameObject>::Find(step.sourceGUID); - break; - case HIGHGUID_CORPSE: - source = HashMapHolder<Corpse>::Find(step.sourceGUID); - break; - case HIGHGUID_MO_TRANSPORT: - for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) - { - if((*iter)->GetGUID() == step.sourceGUID) - { - source = reinterpret_cast<Object*>(*iter); - break; - } - } - break; - default: - sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.sourceGUID)); - break; - } - } - - //if(source && !source->IsInWorld()) source = NULL; - - Object* target = NULL; - - if(step.targetGUID) - { - switch(GUID_HIPART(step.targetGUID)) - { - case HIGHGUID_UNIT: - target = HashMapHolder<Creature>::Find(step.targetGUID); - break; - case HIGHGUID_PET: - target = HashMapHolder<Pet>::Find(step.targetGUID); - break; - case HIGHGUID_VEHICLE: - target = HashMapHolder<Vehicle>::Find(step.targetGUID); - break; - case HIGHGUID_PLAYER: // empty GUID case also - target = HashMapHolder<Player>::Find(step.targetGUID); - break; - case HIGHGUID_GAMEOBJECT: - target = HashMapHolder<GameObject>::Find(step.targetGUID); - break; - case HIGHGUID_CORPSE: - target = HashMapHolder<Corpse>::Find(step.targetGUID); - break; - default: - sLog.outError("*_script source with unsupported high guid value %u",GUID_HIPART(step.targetGUID)); - break; - } - } - - //if(target && !target->IsInWorld()) target = NULL; - - switch (step.script->command) - { - case SCRIPT_COMMAND_TALK: - { - if(!source) - { - sLog.outError("SCRIPT_COMMAND_TALK call for NULL creature."); - break; - } - - if(source->GetTypeId()!=TYPEID_UNIT) - { - sLog.outError("SCRIPT_COMMAND_TALK call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - if(step.script->datalong > 3) - { - sLog.outError("SCRIPT_COMMAND_TALK invalid chat type (%u), skipping.",step.script->datalong); - break; - } - - uint64 unit_target = target ? target->GetGUID() : 0; - - //datalong 0=normal say, 1=whisper, 2=yell, 3=emote text - switch(step.script->datalong) - { - case 0: // Say - ((Creature *)source)->Say(step.script->dataint, LANG_UNIVERSAL, unit_target); - break; - case 1: // Whisper - if(!unit_target) - { - sLog.outError("SCRIPT_COMMAND_TALK attempt to whisper (%u) NULL, skipping.",step.script->datalong); - break; - } - ((Creature *)source)->Whisper(step.script->dataint,unit_target); - break; - case 2: // Yell - ((Creature *)source)->Yell(step.script->dataint, LANG_UNIVERSAL, unit_target); - break; - case 3: // Emote text - ((Creature *)source)->TextEmote(step.script->dataint, unit_target); - break; - default: - break; // must be already checked at load - } - break; - } - - case SCRIPT_COMMAND_EMOTE: - if(!source) - { - sLog.outError("SCRIPT_COMMAND_EMOTE call for NULL creature."); - break; - } - - if(source->GetTypeId()!=TYPEID_UNIT) - { - sLog.outError("SCRIPT_COMMAND_EMOTE call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - ((Creature *)source)->HandleEmoteCommand(step.script->datalong); - break; - case SCRIPT_COMMAND_FIELD_SET: - if(!source) - { - sLog.outError("SCRIPT_COMMAND_FIELD_SET call for NULL object."); - break; - } - if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) - { - sLog.outError("SCRIPT_COMMAND_FIELD_SET call for wrong field %u (max count: %u) in object (TypeId: %u).", - step.script->datalong,source->GetValuesCount(),source->GetTypeId()); - break; - } - - source->SetUInt32Value(step.script->datalong, step.script->datalong2); - break; - case SCRIPT_COMMAND_MOVE_TO: - if(!source) - { - sLog.outError("SCRIPT_COMMAND_MOVE_TO call for NULL creature."); - break; - } - - if(source->GetTypeId()!=TYPEID_UNIT) - { - sLog.outError("SCRIPT_COMMAND_MOVE_TO call for non-creature (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - ((Creature*)source)->SendMonsterMoveWithSpeed(step.script->x, step.script->y, step.script->z, step.script->datalong2 ); - ((Creature*)source)->GetMap()->CreatureRelocation(((Creature*)source), step.script->x, step.script->y, step.script->z, 0); - break; - case SCRIPT_COMMAND_FLAG_SET: - if(!source) - { - sLog.outError("SCRIPT_COMMAND_FLAG_SET call for NULL object."); - break; - } - if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) - { - sLog.outError("SCRIPT_COMMAND_FLAG_SET call for wrong field %u (max count: %u) in object (TypeId: %u).", - step.script->datalong,source->GetValuesCount(),source->GetTypeId()); - break; - } - - source->SetFlag(step.script->datalong, step.script->datalong2); - break; - case SCRIPT_COMMAND_FLAG_REMOVE: - if(!source) - { - sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for NULL object."); - break; - } - if(step.script->datalong <= OBJECT_FIELD_ENTRY || step.script->datalong >= source->GetValuesCount()) - { - sLog.outError("SCRIPT_COMMAND_FLAG_REMOVE call for wrong field %u (max count: %u) in object (TypeId: %u).", - step.script->datalong,source->GetValuesCount(),source->GetTypeId()); - break; - } - - source->RemoveFlag(step.script->datalong, step.script->datalong2); - break; - - case SCRIPT_COMMAND_TELEPORT_TO: - { - // accept player in any one from target/source arg - if (!target && !source) - { - sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for NULL object."); - break; - } - - // must be only Player - if((!target || target->GetTypeId() != TYPEID_PLAYER) && (!source || source->GetTypeId() != TYPEID_PLAYER)) - { - sLog.outError("SCRIPT_COMMAND_TELEPORT_TO call for non-player (TypeIdSource: %u)(TypeIdTarget: %u), skipping.", source ? source->GetTypeId() : 0, target ? target->GetTypeId() : 0); - break; - } - - Player* pSource = target && target->GetTypeId() == TYPEID_PLAYER ? (Player*)target : (Player*)source; - - pSource->TeleportTo(step.script->datalong, step.script->x, step.script->y, step.script->z, step.script->o); - break; - } - - case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE: - { - if(!step.script->datalong) // creature not specified - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL creature."); - break; - } - - if(!source) - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for NULL world object."); - break; - } - - WorldObject* summoner = dynamic_cast<WorldObject*>(source); - - if(!summoner) - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON_CREATURE call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - float x = step.script->x; - float y = step.script->y; - float z = step.script->z; - float o = step.script->o; - - Creature* pCreature = summoner->SummonCreature(step.script->datalong, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,step.script->datalong2); - if (!pCreature) - { - sLog.outError("SCRIPT_COMMAND_TEMP_SUMMON failed for creature (entry: %u).",step.script->datalong); - break; - } - - break; - } - - case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT: - { - if(!step.script->datalong) // gameobject not specified - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL gameobject."); - break; - } - - if(!source) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for NULL world object."); - break; - } - - WorldObject* summoner = dynamic_cast<WorldObject*>(source); - - if(!summoner) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT call for non-WorldObject (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - GameObject *go = NULL; - int32 time_to_despawn = step.script->datalong2<5 ? 5 : (int32)step.script->datalong2; - - CellPair p(Trinity::ComputeCellPair(summoner->GetPositionX(), summoner->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong); - MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check); - - TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, object_checker, *summoner->GetMap()); - - if ( !go ) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT failed for gameobject(guid: %u).", step.script->datalong); - break; - } - - if( go->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE || - go->GetGoType()==GAMEOBJECT_TYPE_DOOR || - go->GetGoType()==GAMEOBJECT_TYPE_BUTTON || - go->GetGoType()==GAMEOBJECT_TYPE_TRAP ) - { - sLog.outError("SCRIPT_COMMAND_RESPAWN_GAMEOBJECT can not be used with gameobject of type %u (guid: %u).", uint32(go->GetGoType()), step.script->datalong); - break; - } - - if( go->isSpawned() ) - break; //gameobject already spawned - - go->SetLootState(GO_READY); - go->SetRespawnTime(time_to_despawn); //despawn object in ? seconds - - go->GetMap()->Add(go); - break; - } - case SCRIPT_COMMAND_OPEN_DOOR: - { - if(!step.script->datalong) // door not specified - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL door."); - break; - } - - if(!source) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for NULL unit."); - break; - } - - if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - Unit* caster = (Unit*)source; - - GameObject *door = NULL; - int32 time_to_close = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; - - CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); - MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check); - - TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, object_checker, *caster->GetMap()); - - if (!door) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong); - break; - } - if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR) - { - sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType()); - break; - } - - if (door->GetGoState() != GO_STATE_READY) - break; //door already open - - door->UseDoorOrButton(time_to_close); - - if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON) - ((GameObject*)target)->UseDoorOrButton(time_to_close); - break; - } - case SCRIPT_COMMAND_CLOSE_DOOR: - { - if(!step.script->datalong) // guid for door not specified - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL door."); - break; - } - - if(!source) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for NULL unit."); - break; - } - - if(!source->isType(TYPEMASK_UNIT)) // must be any Unit (creature or player) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR call for non-unit (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - Unit* caster = (Unit*)source; - - GameObject *door = NULL; - int32 time_to_open = step.script->datalong2 < 15 ? 15 : (int32)step.script->datalong2; - - CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); - MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check); - - TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, object_checker, *caster->GetMap()); - - if ( !door ) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for gameobject(guid: %u).", step.script->datalong); - break; - } - if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR ) - { - sLog.outError("SCRIPT_COMMAND_CLOSE_DOOR failed for non-door(GoType: %u).", door->GetGoType()); - break; - } - - if( door->GetGoState() == GO_STATE_READY ) - break; //door already closed - - door->UseDoorOrButton(time_to_open); - - if(target && target->isType(TYPEMASK_GAMEOBJECT) && ((GameObject*)target)->GetGoType()==GAMEOBJECT_TYPE_BUTTON) - ((GameObject*)target)->UseDoorOrButton(time_to_open); - - break; - } - case SCRIPT_COMMAND_QUEST_EXPLORED: - { - if(!source) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL source."); - break; - } - - if(!target) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for NULL target."); - break; - } - - // when script called for item spell casting then target == (unit or GO) and source is player - WorldObject* worldObject; - Player* player; - - if(target->GetTypeId()==TYPEID_PLAYER) - { - if(source->GetTypeId()!=TYPEID_UNIT && source->GetTypeId()!=TYPEID_GAMEOBJECT) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - worldObject = (WorldObject*)source; - player = (Player*)target; - } - else - { - if(target->GetTypeId()!=TYPEID_UNIT && target->GetTypeId()!=TYPEID_GAMEOBJECT) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-creature and non-gameobject (TypeId: %u), skipping.",target->GetTypeId()); - break; - } - - if(source->GetTypeId()!=TYPEID_PLAYER) - { - sLog.outError("SCRIPT_COMMAND_QUEST_EXPLORED call for non-player(TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - worldObject = (WorldObject*)target; - player = (Player*)source; - } - - // quest id and flags checked at script loading - if( (worldObject->GetTypeId()!=TYPEID_UNIT || ((Unit*)worldObject)->isAlive()) && - (step.script->datalong2==0 || worldObject->IsWithinDistInMap(player,float(step.script->datalong2))) ) - player->AreaExploredOrEventHappens(step.script->datalong); - else - player->FailQuest(step.script->datalong); - - break; - } - - case SCRIPT_COMMAND_ACTIVATE_OBJECT: - { - if(!source) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT must have source caster."); - break; - } - - if(!source->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT source caster isn't unit (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - if(!target) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for NULL gameobject."); - break; - } - - if(target->GetTypeId()!=TYPEID_GAMEOBJECT) - { - sLog.outError("SCRIPT_COMMAND_ACTIVATE_OBJECT call for non-gameobject (TypeId: %u), skipping.",target->GetTypeId()); - break; - } - - Unit* caster = (Unit*)source; - - GameObject *go = (GameObject*)target; - - go->Use(caster); - break; - } - - case SCRIPT_COMMAND_REMOVE_AURA: - { - Object* cmdTarget = step.script->datalong2 ? source : target; - - if(!cmdTarget) - { - sLog.outError("SCRIPT_COMMAND_REMOVE_AURA call for NULL %s.",step.script->datalong2 ? "source" : "target"); - break; - } - - if(!cmdTarget->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_REMOVE_AURA %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 ? "source" : "target",cmdTarget->GetTypeId()); - break; - } - - ((Unit*)cmdTarget)->RemoveAurasDueToSpell(step.script->datalong); - break; - } - - case SCRIPT_COMMAND_CAST_SPELL: - { - if(!source) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL must have source caster."); - break; - } - - Object* cmdTarget = step.script->datalong2 & 0x01 ? source : target; - - if(!cmdTarget) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x01 ? "source" : "target"); - break; - } - - if(!cmdTarget->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x01 ? "source" : "target",cmdTarget->GetTypeId()); - break; - } - - Unit* spellTarget = (Unit*)cmdTarget; - - Object* cmdSource = step.script->datalong2 & 0x02 ? target : source; - - if(!cmdSource) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL call for NULL %s.",step.script->datalong2 & 0x02 ? "target" : "source"); - break; - } - - if(!cmdSource->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_CAST_SPELL %s isn't unit (TypeId: %u), skipping.",step.script->datalong2 & 0x02 ? "target" : "source", cmdSource->GetTypeId()); - break; - } - - Unit* spellSource = (Unit*)cmdSource; - - //TODO: when GO cast implemented, code below must be updated accordingly to also allow GO spell cast - spellSource->CastSpell(spellTarget,step.script->datalong,false); - - break; - } - - case SCRIPT_COMMAND_LOAD_PATH: - { - if(!source) - { - sLog.outError("SCRIPT_COMMAND_START_MOVE is tried to apply to NON-existing unit."); - break; - } - - if(!source->isType(TYPEMASK_UNIT)) - { - sLog.outError("SCRIPT_COMMAND_START_MOVE source mover isn't unit (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - if(!WaypointMgr.GetPath(step.script->datalong)) - { - sLog.outError("SCRIPT_COMMAND_START_MOVE source mover has an invallid path, skipping.", step.script->datalong2); - break; - } - - dynamic_cast<Unit*>(source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2); - break; - } - - case SCRIPT_COMMAND_CALLSCRIPT_TO_UNIT: - { - if(!step.script->datalong || !step.script->datalong2) - { - sLog.outError("SCRIPT_COMMAND_CALLSCRIPT calls invallid db_script_id or lowguid not present: skipping."); - break; - } - //our target - Creature* target = NULL; - - if(source) //using grid searcher - { - CellPair p(Trinity::ComputeCellPair(((Unit*)source)->GetPositionX(), ((Unit*)source)->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - //sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong); - Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong); - Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check); - - TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker); - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, unit_checker, *(((Unit*)source)->GetMap())); - } - else //check hashmap holders - { - if(CreatureData const* data = objmgr.GetCreatureData(step.script->datalong)) - target = ObjectAccessor::GetObjectInWorld<Creature>(data->mapid, data->posX, data->posY, MAKE_NEW_GUID(step.script->datalong, data->id, HIGHGUID_UNIT), target); - } - //sLog.outDebug("attempting to pass target..."); - if(!target) - break; - //sLog.outDebug("target passed"); - //Lets choose our ScriptMap map - ScriptMapMap *datamap = NULL; - switch(step.script->dataint) - { - case 1://QUEST END SCRIPTMAP - datamap = &sQuestEndScripts; - break; - case 2://QUEST START SCRIPTMAP - datamap = &sQuestStartScripts; - break; - case 3://SPELLS SCRIPTMAP - datamap = &sSpellScripts; - break; - case 4://GAMEOBJECTS SCRIPTMAP - datamap = &sGameObjectScripts; - break; - case 5://EVENTS SCRIPTMAP - datamap = &sEventScripts; - break; - case 6://WAYPOINTS SCRIPTMAP - datamap = &sWaypointScripts; - break; - default: - sLog.outError("SCRIPT_COMMAND_CALLSCRIPT ERROR: no scriptmap present... ignoring"); - break; - } - //if no scriptmap present... - if(!datamap) - break; - - uint32 script_id = step.script->datalong2; - //insert script into schedule but do not start it - ScriptsStart(*datamap, script_id, target, NULL, false); - break; - } - - case SCRIPT_COMMAND_KILL: - { - if(!source || ((Creature*)source)->isDead()) - break; - - ((Creature*)source)->DealDamage(((Creature*)source), ((Creature*)source)->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - - switch(step.script->dataint) - { - case 0: break; //return false not remove corpse - case 1: ((Creature*)source)->RemoveCorpse(); break; - } - break; - } - - case SCRIPT_COMMAND_PLAY_SOUND: - { - if(!source) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for NULL creature."); - break; - } - - WorldObject* pSource = dynamic_cast<WorldObject*>(source); - if(!pSource) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND call for non-world object (TypeId: %u), skipping.",source->GetTypeId()); - break; - } - - // bitmask: 0/1=anyone/target, 0/2=with distance dependent - Player* pTarget = NULL; - if(step.script->datalong2 & 1) - { - if(!target) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for NULL target."); - break; - } - - if(target->GetTypeId()!=TYPEID_PLAYER) - { - sLog.outError("SCRIPT_COMMAND_PLAY_SOUND in targeted mode call for non-player (TypeId: %u), skipping.",target->GetTypeId()); - break; - } - - pTarget = (Player*)target; - } - - // bitmask: 0/1=anyone/target, 0/2=with distance dependent - if(step.script->datalong2 & 2) - pSource->PlayDistanceSound(step.script->datalong,pTarget); - else - pSource->PlayDirectSound(step.script->datalong,pTarget); - break; - } - default: - sLog.outError("Unknown script command %u called.",step.script->command); - break; - } - - m_scriptSchedule.erase(iter); - - iter = m_scriptSchedule.begin(); - } - return; -} - /// Send a packet to all players (except self if mentioned) void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team) { @@ -2872,10 +2031,10 @@ void World::KickAllLess(AccountTypes sec) /// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author) { - LoginDatabase.escape_string(nameOrIP); - LoginDatabase.escape_string(reason); + loginDatabase.escape_string(nameOrIP); + loginDatabase.escape_string(reason); std::string safe_author=author; - LoginDatabase.escape_string(safe_author); + loginDatabase.escape_string(safe_author); uint32 duration_secs = TimeStringToSecs(duration); QueryResult *resultAccounts = NULL; //used for kicking @@ -2885,12 +2044,12 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura { case BAN_IP: //No SQL injection as strings are escaped - resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str()); - LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str()); + resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str()); + loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str()); break; case BAN_ACCOUNT: //No SQL injection as string is escaped - resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); + resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); break; case BAN_CHARACTER: //No SQL injection as string is escaped @@ -2917,7 +2076,7 @@ BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string dura if(mode!=BAN_IP) { //No SQL injection as strings are escaped - LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')", + loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')", account,duration_secs,safe_author.c_str(),reason.c_str()); } @@ -2936,8 +2095,8 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP) { if (mode == BAN_IP) { - LoginDatabase.escape_string(nameOrIP); - LoginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str()); + loginDatabase.escape_string(nameOrIP); + loginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str()); } else { @@ -2951,7 +2110,7 @@ bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP) return false; //NO SQL injection as account is uint32 - LoginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account); + loginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account); } return true; } @@ -3149,8 +2308,8 @@ void World::_UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId Field *fields = resultCharCount->Fetch(); uint32 charCount = fields[0].GetUInt32(); delete resultCharCount; - LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID); - LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID); + loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID); + loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID); } } @@ -3213,7 +2372,7 @@ void World::SetPlayerLimit( int32 limit, bool needUpdate ) m_playerLimit = limit; if(db_update_need) - LoginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID); + loginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID); } void World::UpdateMaxSessionCounters() diff --git a/src/game/World.h b/src/game/World.h index 4864977b029..78d4c181b4a 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -29,6 +29,7 @@ #include "Timer.h" #include "Policies/Singleton.h" #include "SharedDefines.h" +#include "ace/Atomic_Op.h" #include <map> #include <set> @@ -553,9 +554,10 @@ class World BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author); bool RemoveBanAccount(BanMode mode, std::string nameOrIP); - void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo> > const& scripts, uint32 id, Object* source, Object* target, bool start = true); - void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); - bool IsScriptScheduled() const { return !m_scriptSchedule.empty(); } + uint32 IncreaseScheduledScriptsCount() { return (uint32)++m_scheduledScripts; } + uint32 DecreaseScheduledScriptCount() { return (uint32)--m_scheduledScripts; } + uint32 DecreaseScheduledScriptCount(size_t count) { return (uint32)(m_scheduledScripts -= count); } + bool IsScriptScheduled() const { return m_scheduledScripts > 0; } bool IsAllowedMap(uint32 mapid) { return m_forbiddenMapIds.count(mapid) == 0 ;} @@ -592,7 +594,6 @@ class World void RecordTimeDiff(const char * text, ...); protected: void _UpdateGameTime(); - void ScriptsProcess(); // callback for UpdateRealmCharacters void _UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId); @@ -606,6 +607,9 @@ class World bool m_isClosed; + //atomic op counter for active scripts amount + ACE_Atomic_Op<ACE_Thread_Mutex, long> m_scheduledScripts; + time_t m_startTime; time_t m_gameTime; IntervalTimer m_timers[WUPDATE_COUNT]; @@ -626,8 +630,6 @@ class World uint32 m_PlayerCount; uint32 m_MaxPlayerCount; - std::multimap<time_t, ScriptAction> m_scriptSchedule; - std::string m_newCharString; float rate_values[MAX_RATES]; diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 1390fd6a830..3b32eefcda7 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -53,7 +53,7 @@ m_latency(0), m_TutorialsChanged(false) { m_Address = sock->GetRemoteAddress (); sock->AddReference (); - LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); + loginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); } } @@ -78,7 +78,7 @@ WorldSession::~WorldSession() WorldPacket *packet = _recvQueue.next (); delete packet; } - LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); + loginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = %u;", GetAccountId()); } diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 440eeb31790..0efb0cd3d4e 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -678,7 +678,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) BigNumber K; - if (recvPacket.size () < (4 + 4 + 1 + 4 + 20)) + if (recvPacket.size () < (4 + 4 + 1 + 4 + 4 + 20)) { sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size"); return -1; @@ -700,7 +700,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) recvPacket >> account; recvPacket >> unk3; - if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20)) + if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 4 + 20)) { sLog.outError ("WorldSocket::HandleAuthSession: wrong packet size second check"); return -1; @@ -709,19 +709,20 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) recvPacket >> clientSeed; recvPacket.read (digest, 20); - DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, clientseed %u", + DEBUG_LOG ("WorldSocket::HandleAuthSession: client %u, unk2 %u, account %s, unk3 %u, clientseed %u", BuiltNumberClient, unk2, account.c_str (), + unk3, clientSeed); // Get the account information from the realmd database std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below - LoginDatabase.escape_string (safe_account); + loginDatabase.escape_string (safe_account); // No SQL injection, username escaped. QueryResult *result = - LoginDatabase.PQuery ("SELECT " + loginDatabase.PQuery ("SELECT " "id, " //0 "gmlevel, " //1 "sessionkey, " //2 @@ -786,7 +787,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) vold, vStr); - LoginDatabase.PExecute ("UPDATE account " + loginDatabase.PExecute ("UPDATE account " "SET " "v = '0', " "s = '0' " @@ -843,7 +844,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) // Re-check account ban (same check as in realmd) QueryResult *banresult = - LoginDatabase.PQuery ("SELECT " + loginDatabase.PQuery ("SELECT " "bandate, " "unbandate " "FROM account_banned " @@ -909,9 +910,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) // Update the last_ip in the database // No SQL injection, username escaped. - LoginDatabase.escape_string (address); + loginDatabase.escape_string (address); - LoginDatabase.PExecute ("UPDATE account " + loginDatabase.PExecute ("UPDATE account " "SET last_ip = '%s' " "WHERE username = '%s'", address.c_str (), diff --git a/src/shared/Database/DatabaseEnv.h b/src/shared/Database/DatabaseEnv.h index 1d3d735881c..d5d6867e82f 100644 --- a/src/shared/Database/DatabaseEnv.h +++ b/src/shared/Database/DatabaseEnv.h @@ -50,7 +50,7 @@ typedef DatabaseMysql DatabaseType; extern DatabaseType WorldDatabase; extern DatabaseType CharacterDatabase; -extern DatabaseType LoginDatabase; +extern DatabaseType loginDatabase; #endif diff --git a/src/shared/Log.cpp b/src/shared/Log.cpp index 8cc2dff504d..8dc23066245 100644 --- a/src/shared/Log.cpp +++ b/src/shared/Log.cpp @@ -359,9 +359,9 @@ void Log::outDB( LogTypes type, const char * str ) std::string new_str(str); if (new_str.empty()) return; - LoginDatabase.escape_string(new_str); + loginDatabase.escape_string(new_str); - LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) " + loginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) " "VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, type, new_str.c_str()); } diff --git a/src/shared/vmap/VMapManager.cpp b/src/shared/vmap/VMapManager.cpp index f5c2640be70..342da0eb9e2 100644 --- a/src/shared/vmap/VMapManager.cpp +++ b/src/shared/vmap/VMapManager.cpp @@ -446,7 +446,7 @@ namespace VMAP //========================================================= /** - get height or INVALID_HEIGHT if to hight was calculated + get height or INVALID_HEIGHT if to height was calculated */ //int gGetHeightCounter = 0; diff --git a/src/tools/genrevision/Makefile.am b/src/tools/genrevision/Makefile.am index 3f60ac14ab2..fc66e8181b3 100644 --- a/src/tools/genrevision/Makefile.am +++ b/src/tools/genrevision/Makefile.am @@ -19,12 +19,12 @@ ## CPP flags for includes, defines, etc. AM_CPPFLAGS = -I$(srcdir) -## Build world list daemon as standalone program +## Build as standalone program bin_PROGRAMS = genrevision genrevision_SOURCES = \ genrevision.cpp -## Link world daemon against the shared library +## Link against the shared library genrevision_LDADD = genrevision_LDFLAGS = -L$(libdir) diff --git a/src/trinitycore/CliRunnable.cpp b/src/trinitycore/CliRunnable.cpp index 15dd45edfff..d950adc22f8 100644 --- a/src/trinitycore/CliRunnable.cpp +++ b/src/trinitycore/CliRunnable.cpp @@ -239,7 +239,7 @@ bool ChatHandler::HandleAccountOnlineListCommand(const char* /*args*/) ///- Get the username, last IP and GM level of each account // No SQL injection. account is uint32. // 0 1 2 3 - QueryResult *resultLogin = LoginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account); + QueryResult *resultLogin = loginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account); if(resultLogin) { diff --git a/src/trinitycore/Main.cpp b/src/trinitycore/Main.cpp index eb51c770896..faa88c994d5 100644 --- a/src/trinitycore/Main.cpp +++ b/src/trinitycore/Main.cpp @@ -59,7 +59,7 @@ int m_ServiceStatus = -1; DatabaseType WorldDatabase; ///< Accessor to the world database DatabaseType CharacterDatabase; ///< Accessor to the character database -DatabaseType LoginDatabase; ///< Accessor to the realm/login database +DatabaseType loginDatabase; ///< Accessor to the realm/login database uint32 realmID; ///< Id of the realm diff --git a/src/trinitycore/Master.cpp b/src/trinitycore/Master.cpp index b7159225f42..8a5fba940f1 100644 --- a/src/trinitycore/Master.cpp +++ b/src/trinitycore/Master.cpp @@ -136,7 +136,7 @@ public: loopCounter = 0; sLog.outDetail ("Ping MySQL to keep connection alive"); delete WorldDatabase.Query ("SELECT 1 FROM command LIMIT 1"); - delete LoginDatabase.Query ("SELECT 1 FROM realmlist LIMIT 1"); + delete loginDatabase.Query ("SELECT 1 FROM realmlist LIMIT 1"); delete CharacterDatabase.Query ("SELECT 1 FROM bugreport LIMIT 1"); } } @@ -242,7 +242,7 @@ int Master::Run() t.setPriority ((ACE_Based::Priority )2); // set server online - LoginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID); + loginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID); #ifdef WIN32 if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/) @@ -333,7 +333,7 @@ int Master::Run() sWorldSocketMgr->Wait (); // set server offline - LoginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID); + loginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID); ///- Remove signal handling before leaving _UnhookSignals(); @@ -349,7 +349,7 @@ int Master::Run() ///- Wait for delay threads to end CharacterDatabase.HaltDelayThread(); WorldDatabase.HaltDelayThread(); - LoginDatabase.HaltDelayThread(); + loginDatabase.HaltDelayThread(); sLog.outString( "Halting process..." ); @@ -438,7 +438,7 @@ bool Master::_StartDB() } ///- Get login database info from configuration file - dbstring = sConfig.GetStringDefault("LoginDatabaseInfo", ""); + dbstring = sConfig.GetStringDefault("loginDatabaseInfo", ""); if(dbstring.empty()) { sLog.outError("Login database not specified in configuration file"); @@ -446,7 +446,7 @@ bool Master::_StartDB() } ///- Initialise the login database - if(!LoginDatabase.Initialize(dbstring.c_str())) + if(!loginDatabase.Initialize(dbstring.c_str())) { sLog.outError("Cannot connect to login database %s",dbstring.c_str()); return false; @@ -494,7 +494,7 @@ void Master::clearOnlineAccounts() { // Cleanup online status for characters hosted at current realm /// \todo Only accounts with characters logged on *this* realm should have online status reset. Move the online column from 'account' to 'realmcharacters'? - LoginDatabase.PExecute( + loginDatabase.PExecute( "UPDATE account SET online = 0 WHERE online > 0 " "AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = '%d')",realmID); diff --git a/src/trinitycore/RASocket.cpp b/src/trinitycore/RASocket.cpp index b15f4e447d6..d0ee5cc8053 100644 --- a/src/trinitycore/RASocket.cpp +++ b/src/trinitycore/RASocket.cpp @@ -152,9 +152,9 @@ void RASocket::OnRead() AccountMgr::normalizeString(login); ///- Escape the Login to allow quotes in names - LoginDatabase.escape_string(login); + loginDatabase.escape_string(login); - QueryResult* result = LoginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str()); + QueryResult* result = loginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str()); ///- If the user is not found, deny access if(!result) @@ -193,10 +193,10 @@ void RASocket::OnRead() AccountMgr::normalizeString(login); AccountMgr::normalizeString(pw); - LoginDatabase.escape_string(login); - LoginDatabase.escape_string(pw); + loginDatabase.escape_string(login); + loginDatabase.escape_string(pw); - QueryResult *check = LoginDatabase.PQuery( + QueryResult *check = loginDatabase.PQuery( "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT('%s',':','%s'))", login.c_str(), login.c_str(), pw.c_str()); diff --git a/src/trinitycore/WorldRunnable.cpp b/src/trinitycore/WorldRunnable.cpp index ad0243a36ae..06c0e69fa16 100644 --- a/src/trinitycore/WorldRunnable.cpp +++ b/src/trinitycore/WorldRunnable.cpp @@ -50,7 +50,7 @@ void WorldRunnable::run() ///- Init new SQL thread for the world database WorldDatabase.ThreadStart(); // let thread do safe mySQL requests (one connection call enough) CharacterDatabase.ThreadStart(); - LoginDatabase.ThreadStart(); + loginDatabase.ThreadStart(); sWorld.InitResultQueue(); uint32 realCurrTime = 0; @@ -100,5 +100,5 @@ void WorldRunnable::run() ///- End the database thread WorldDatabase.ThreadEnd(); // free mySQL thread resources CharacterDatabase.ThreadStart(); - LoginDatabase.ThreadEnd(); + loginDatabase.ThreadEnd(); } diff --git a/src/trinityrealm/AuthCodes.h b/src/trinityrealm/AuthCodes.h index 4ef5e4e8699..2a215968c3b 100644 --- a/src/trinityrealm/AuthCodes.h +++ b/src/trinityrealm/AuthCodes.h @@ -70,6 +70,6 @@ enum LoginResult // others will not and opposite // will only support WoW, WoW:TBC and WoW:WotLK 3.1.3 client build 9947... -#define EXPECTED_TRINITY_CLIENT_BUILD {9947, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9947, 0} #endif diff --git a/src/trinityrealm/AuthSocket.cpp b/src/trinityrealm/AuthSocket.cpp index 80e8184605b..6a6cde45895 100644 --- a/src/trinityrealm/AuthSocket.cpp +++ b/src/trinityrealm/AuthSocket.cpp @@ -36,7 +36,7 @@ extern RealmList m_realmList; -extern DatabaseType LoginDatabase; +extern DatabaseType loginDatabase; #define ChunkSize 2048 @@ -112,7 +112,7 @@ typedef struct AUTH_LOGON_PROOF_C uint8 M1[20]; uint8 crc_hash[20]; uint8 number_of_keys; - uint8 unk; // Added in 1.12.x client branch + uint8 securityFlags; // 0x00-0x04 } sAuthLogonProof_C; /* typedef struct @@ -264,17 +264,11 @@ void AuthSocket::OnRead() ///- Get the command out of it ibuf.SoftRead((char *)&_cmd, 1); // UQ1: No longer exists in new net code ??? - //ibuf.Read((char *)&_cmd, 1); - /*char *command = (char *)malloc(1); - ibuf.Read(command, 1); - - _cmd = (uint8)command;*/ - // assert(0); size_t i; ///- Circle through known commands and call the correct command handler - for (i=0;i<AUTH_TOTAL_COMMANDS; i++) + for (i = 0; i < AUTH_TOTAL_COMMANDS; ++i) { if ((uint8)table[i].cmd == _cmd && (table[i].status == STATUS_CONNECTED || @@ -292,7 +286,7 @@ void AuthSocket::OnRead() } ///- Report unknown commands in the debug log - if (i==AUTH_TOTAL_COMMANDS) + if (i == AUTH_TOTAL_COMMANDS) { DEBUG_LOG("[Auth] got unknown packet %u", (uint32)_cmd); return; @@ -306,13 +300,13 @@ void AuthSocket::_SetVSFields(const std::string& rI) BigNumber I; I.SetHexStr(rI.c_str()); - //In case of leading zeroes in the rI hash, restore them + // In case of leading zeros in the rI hash, restore them uint8 mDigest[SHA_DIGEST_LENGTH]; - memset(mDigest,0,SHA_DIGEST_LENGTH); + memset(mDigest, 0, SHA_DIGEST_LENGTH); if (I.GetNumBytes() <= SHA_DIGEST_LENGTH) - memcpy(mDigest,I.AsByteArray(),I.GetNumBytes()); + memcpy(mDigest, I.AsByteArray(), I.GetNumBytes()); - std::reverse(mDigest,mDigest+SHA_DIGEST_LENGTH); + std::reverse(mDigest, mDigest + SHA_DIGEST_LENGTH); Sha1Hash sha; sha.UpdateData(s.AsByteArray(), s.GetNumBytes()); @@ -325,7 +319,7 @@ void AuthSocket::_SetVSFields(const std::string& rI) const char *v_hex, *s_hex; v_hex = v.AsHexStr(); s_hex = s.AsHexStr(); - LoginDatabase.PExecute("UPDATE account SET v = '%s', s = '%s' WHERE username = '%s'",v_hex,s_hex, _safelogin.c_str() ); + loginDatabase.PExecute("UPDATE account SET v = '%s', s = '%s' WHERE username = '%s'", v_hex, s_hex, _safelogin.c_str() ); OPENSSL_free((void*)v_hex); OPENSSL_free((void*)s_hex); } @@ -380,19 +374,19 @@ bool AuthSocket::_HandleLogonChallenge() //Escape the user login to avoid further SQL injection //Memory will be freed on AuthSocket object destruction - _safelogin=_login; - LoginDatabase.escape_string(_safelogin); + _safelogin = _login; + loginDatabase.escape_string(_safelogin); pkt << (uint8) AUTH_LOGON_CHALLENGE; pkt << (uint8) 0x00; ///- Verify that this IP is not in the ip_banned table // No SQL injection possible (paste the IP address as passed by the socket) - LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); std::string address = GetRemoteAddress(); - LoginDatabase.escape_string(address); - QueryResult *result = LoginDatabase.PQuery( "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); + loginDatabase.escape_string(address); + QueryResult *result = loginDatabase.PQuery( "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); if(result) { pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; @@ -404,7 +398,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 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 @@ -432,9 +426,9 @@ bool AuthSocket::_HandleLogonChallenge() if (!locked) { //set expired bans to inactive - LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + loginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); ///- If the account is banned, reject the logon attempt - QueryResult *banresult = LoginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); + QueryResult *banresult = loginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); if(banresult) { if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) @@ -457,35 +451,56 @@ bool AuthSocket::_HandleLogonChallenge() _SetVSFields(rI); b.SetRand(19 * 8); - BigNumber gmod=g.ModExp(b, N); + BigNumber gmod = g.ModExp(b, N); B = ((v * 3) + gmod) % N; ASSERT(gmod.GetNumBytes() <= 32); BigNumber unk3; - unk3.SetRand(16*8); + unk3.SetRand(16 * 8); ///- Fill the response packet with the result - pkt << (uint8)REALM_AUTH_SUCCESS; + pkt << uint8(REALM_AUTH_SUCCESS); - // B may be calculated < 32B so we force minnimal length to 32B - pkt.append(B.AsByteArray(32), 32); // 32 bytes - pkt << (uint8)1; + // B may be calculated < 32B so we force minimal length to 32B + pkt.append(B.AsByteArray(32), 32); // 32 bytes + pkt << uint8(1); pkt.append(g.AsByteArray(), 1); - pkt << (uint8)32; + pkt << uint8(32); pkt.append(N.AsByteArray(), 32); pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes pkt.append(unk3.AsByteArray(), 16); - pkt << (uint8)0; // Added in 1.12.x client branch + uint8 securityFlags = 0; + pkt << uint8(securityFlags); // security flags (0x0...0x04) + + if(securityFlags & 0x01) // PIN input + { + pkt << uint32(0); + pkt << uint64(0) << uint64(0); // 16 bytes hash? + } + + if(securityFlags & 0x02) // Matrix input + { + pkt << uint8(0); + pkt << uint8(0); + pkt << uint8(0); + pkt << uint8(0); + pkt << uint64(0); + } + + if(securityFlags & 0x04) // Security token input + { + pkt << uint8(1); + } uint8 secLevel = (*result)[4].GetUInt8(); _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; _localizationName.resize(4); - for(int i = 0; i <4; ++i) + for(int i = 0; i < 4; ++i) _localizationName[i] = ch->country[4-i-1]; - sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3],ch->country[2],ch->country[1],ch->country[0], GetLocaleByName(_localizationName)); + sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName)); } } delete result; @@ -510,13 +525,13 @@ bool AuthSocket::_HandleLogonProof() ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C)); ///- Check if the client has one of the expected version numbers - bool valid_version=false; - int accepted_versions[]=EXPECTED_TRINITY_CLIENT_BUILD; - for(int i=0;accepted_versions[i];i++) + bool valid_version = false; + int accepted_versions[] = EXPECTED_MANGOS_CLIENT_BUILD; + for(int i = 0; accepted_versions[i]; ++i) { - if(_build==accepted_versions[i]) + if(_build == accepted_versions[i]) { - valid_version=true; + valid_version = true; break; } } @@ -529,9 +544,9 @@ bool AuthSocket::_HandleLogonProof() // 24 = len("./patches/65535enGB.mpq")+1 char tmp[24]; // No buffer overflow (fixed length of arguments) - sprintf(tmp,"./patches/%d%s.mpq",_build, _localizationName.c_str()); - // This will be closed at the destruction of the AuthSocket (client deconnection) - FILE *pFile=fopen(tmp,"rb"); + sprintf(tmp, "./patches/%d%s.mpq", _build, _localizationName.c_str()); + // This will be closed at the destruction of the AuthSocket (client disconnection) + FILE *pFile = fopen(tmp, "rb"); if(!pFile) { @@ -540,37 +555,37 @@ bool AuthSocket::_HandleLogonProof() pkt << (uint8) 0x00; pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER; DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build); - DEBUG_LOG("[AuthChallenge] Patch %s not found",tmp); + DEBUG_LOG("[AuthChallenge] Patch %s not found", tmp); SendBuf((char const*)pkt.contents(), pkt.size()); return true; } else // have patch { - pPatch=pFile; + pPatch = pFile; XFER_INIT xferh; ///- Get the MD5 hash of the patch file (get it from preloaded Patcher cache or calculate it) - if(PatchesCache.GetHash(tmp,(uint8*)&xferh.md5)) + if(PatchesCache.GetHash(tmp, (uint8*)&xferh.md5)) { - DEBUG_LOG("\n[AuthChallenge] Found precached patch info for patch %s",tmp); + DEBUG_LOG("\n[AuthChallenge] Found precached patch info for patch %s", tmp); } else - { //calculate patch md5 - printf("\n[AuthChallenge] Patch info for %s was not cached.",tmp); + { // calculate patch md5 + printf("\n[AuthChallenge] Patch info for %s was not cached.", tmp); PatchesCache.LoadPatchMD5(tmp); - PatchesCache.GetHash(tmp,(uint8*)&xferh.md5); + PatchesCache.GetHash(tmp, (uint8*)&xferh.md5); } ///- Send a packet to the client with the file length and MD5 hash - uint8 data[2]={AUTH_LOGON_PROOF,REALM_AUTH_UPDATE_CLIENT}; - SendBuf((const char*)data,sizeof(data)); + uint8 data[2] = { AUTH_LOGON_PROOF, REALM_AUTH_UPDATE_CLIENT }; + SendBuf((const char*)data, sizeof(data)); - memcpy(&xferh,"0\x05Patch",7); - xferh.cmd=XFER_INITIATE; - fseek(pPatch,0,SEEK_END); - xferh.file_size=ftell(pPatch); + memcpy(&xferh, "0\x05Patch", 7); + xferh.cmd = XFER_INITIATE; + fseek(pPatch, 0, SEEK_END); + xferh.file_size = ftell(pPatch); - SendBuf((const char*)&xferh,sizeof(xferh)); + SendBuf((const char*)&xferh, sizeof(xferh)); return true; } } @@ -591,27 +606,27 @@ bool AuthSocket::_HandleLogonProof() uint8 t1[16]; uint8 vK[40]; memcpy(t, S.AsByteArray(), 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]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); - for (int i = 0; i < 20; i++) + for (int i = 0; i < 20; ++i) { - vK[i*2] = sha.GetDigest()[i]; + vK[i * 2] = sha.GetDigest()[i]; } - for (int i = 0; i < 16; i++) + for (int i = 0; i < 16; ++i) { - t1[i] = t[i*2+1]; + t1[i] = t[i * 2 + 1]; } sha.Initialize(); sha.UpdateData(t1, 16); sha.Finalize(); - for (int i = 0; i < 20; i++) + for (int i = 0; i < 20; ++i) { - vK[i*2+1] = sha.GetDigest()[i]; + vK[i * 2 + 1] = sha.GetDigest()[i]; } K.SetBinary(vK, 40); @@ -624,7 +639,7 @@ bool AuthSocket::_HandleLogonProof() sha.Initialize(); sha.UpdateBigNumbers(&g, NULL); sha.Finalize(); - for (int i = 0; i < 20; i++) + for (int i = 0; i < 20; ++i) { hash[i] ^= sha.GetDigest()[i]; } @@ -653,7 +668,7 @@ bool AuthSocket::_HandleLogonProof() ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account // No SQL injection (escaped user name) and IP address as received by socket const char* K_hex = K.AsHexStr(); - LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() ); + loginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() ); OPENSSL_free((void*)K_hex); ///- Finish SRP6 and send the final result to the client @@ -676,17 +691,17 @@ bool AuthSocket::_HandleLogonProof() } else { - char data[4]={AUTH_LOGON_PROOF,REALM_AUTH_NO_MATCH,3,0}; - SendBuf(data,sizeof(data)); + char data[4]= { AUTH_LOGON_PROOF, REALM_AUTH_NO_MATCH, 3, 0}; + SendBuf(data, sizeof(data)); sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ()); uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0); if(MaxWrongPassCount > 0) { //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP - LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str()); + loginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str()); - if(QueryResult *loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str())) + if(QueryResult *loginfail = loginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str())) { Field* fields = loginfail->Fetch(); uint32 failed_logins = fields[1].GetUInt32(); @@ -699,7 +714,7 @@ bool AuthSocket::_HandleLogonProof() if(WrongPassBanType) { uint32 acc_id = fields[0].GetUInt32(); - LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)", + loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)", acc_id, WrongPassBanTime); sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", _login.c_str(), WrongPassBanTime, failed_logins); @@ -707,8 +722,8 @@ bool AuthSocket::_HandleLogonProof() else { std::string current_ip = GetRemoteAddress(); - LoginDatabase.escape_string(current_ip); - LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')", + loginDatabase.escape_string(current_ip); + loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')", current_ip.c_str(), WrongPassBanTime); sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins); @@ -754,7 +769,7 @@ bool AuthSocket::_HandleReconnectChallenge() _login = (const char*)ch->I; _safelogin = _login; - QueryResult *result = LoginDatabase.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ()); + QueryResult *result = loginDatabase.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ()); // Stop if the account is not found if (!result) @@ -772,7 +787,7 @@ bool AuthSocket::_HandleReconnectChallenge() ByteBuffer pkt; pkt << (uint8) AUTH_RECONNECT_CHALLENGE; pkt << (uint8) 0x00; - _reconnectProof.SetRand(16*8); + _reconnectProof.SetRand(16 * 8); pkt.append(_reconnectProof.AsByteBuffer()); // 16 bytes random pkt << (uint64) 0x00 << (uint64) 0x00; // 16 bytes zeros SendBuf((char const*)pkt.contents(), pkt.size()); @@ -834,7 +849,7 @@ bool AuthSocket::_HandleRealmList() ///- Get the user id (else close the connection) // No SQL injection (escaped user name) - QueryResult *result = LoginDatabase.PQuery("SELECT id,sha_pass_hash FROM account WHERE username = '%s'",_safelogin.c_str()); + QueryResult *result = loginDatabase.PQuery("SELECT id,sha_pass_hash FROM account WHERE username = '%s'",_safelogin.c_str()); if(!result) { sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str()); @@ -854,12 +869,12 @@ bool AuthSocket::_HandleRealmList() pkt << (uint32) 0; pkt << (uint16) m_realmList.size(); RealmList::RealmMap::const_iterator i; - for( i = m_realmList.begin(); i != m_realmList.end(); i++ ) + for( i = m_realmList.begin(); i != m_realmList.end(); ++i ) { uint8 AmountOfCharacters; // No SQL injection. id of realm is controlled by the database. - result = LoginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); + result = loginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); if( result ) { Field *fields = result->Fetch(); @@ -901,7 +916,7 @@ bool AuthSocket::_HandleXferResume() { DEBUG_LOG("Entering _HandleXferResume"); ///- Check packet length and patch existence - if (ibuf.GetLength()<9 || !pPatch) + if (ibuf.GetLength() < 9 || !pPatch) { sLog.outError("Error while resuming patch transfer (wrong packet)"); return false; @@ -911,7 +926,7 @@ bool AuthSocket::_HandleXferResume() uint64 start; ibuf.Remove(1); ibuf.Read((char*)&start,sizeof(start)); - fseek(pPatch,start,0); + fseek(pPatch, start, 0); ACE_Based::Thread u(*new PatcherRunnable(this)); return true; @@ -942,9 +957,9 @@ bool AuthSocket::_HandleXferAccept() return false; } - ///- Launch a PatcherRunnable thread, starting at the begining of the patch file - ibuf.Remove(1); //clear input buffer - fseek(pPatch,0,0); + ///- Launch a PatcherRunnable thread, starting at the beginning of the patch file + ibuf.Remove(1); // clear input buffer + fseek(pPatch, 0, 0); ACE_Based::Thread u(*new PatcherRunnable(this)); return true; @@ -953,12 +968,12 @@ bool AuthSocket::_HandleXferAccept() /// Check if there is lag on the connection to the client bool AuthSocket::IsLag() { - return (TCP_BUFSIZE_READ-GetOutputLength()< 2*ChunkSize); + return (TCP_BUFSIZE_READ-GetOutputLength() < 2 * ChunkSize); } PatcherRunnable::PatcherRunnable(class AuthSocket * as) { - mySocket=as; + mySocket = as; } /// Send content of patch file to the client @@ -977,8 +992,8 @@ void PatcherRunnable::run() ACE_Based::Thread::Sleep(1); } ///- And send content of the patch file to the client - xfdata.data_size=fread(&xfdata.data,1,ChunkSize,mySocket->pPatch); - mySocket->SendBuf((const char*)&xfdata,xfdata.data_size +(sizeof(XFER_DATA_STRUCT)-ChunkSize)); + xfdata.data_size = fread(&xfdata.data, 1, ChunkSize, mySocket->pPatch); + mySocket->SendBuf((const char*)&xfdata, xfdata.data_size + (sizeof(XFER_DATA_STRUCT) - ChunkSize)); } } @@ -999,8 +1014,9 @@ void Patcher::LoadPatchesInfo() errno = 0; if ((dp = readdir(dirp)) != NULL) { - int l=strlen(dp->d_name); - if(l<8)continue; + int l = strlen(dp->d_name); + if(l < 8) + continue; if(!memcmp(&dp->d_name[l-4],".mpq",4)) LoadPatchMD5(dp->d_name); } @@ -1023,15 +1039,15 @@ void Patcher::LoadPatchesInfo() void Patcher::LoadPatchesInfo() { WIN32_FIND_DATA fil; - HANDLE hFil=FindFirstFile("./patches/*.mpq",&fil); - if(hFil==INVALID_HANDLE_VALUE) - return; //no patches were found + HANDLE hFil=FindFirstFile("./patches/*.mpq", &fil); + if(hFil == INVALID_HANDLE_VALUE) + return; // no patches were found do { LoadPatchMD5(fil.cFileName); } - while(FindNextFile(hFil,&fil)); + while(FindNextFile(hFil, &fil)); } #endif @@ -1041,11 +1057,11 @@ void Patcher::LoadPatchMD5(char * szFileName) ///- Try to open the patch file std::string path = "./patches/"; path += szFileName; - FILE * pPatch=fopen(path.c_str(),"rb"); - sLog.outDebug("Loading patch info from %s\n",path.c_str()); + FILE *pPatch = fopen(path.c_str(), "rb"); + sLog.outDebug("Loading patch info from %s\n", path.c_str()); if(!pPatch) { - sLog.outError("Error loading patch %s\n",path.c_str()); + sLog.outError("Error loading patch %s\n", path.c_str()); return; } @@ -1064,16 +1080,16 @@ void Patcher::LoadPatchMD5(char * szFileName) ///- Store the result in the internal patch hash map _patches[path] = new PATCH_INFO; - MD5_Final((uint8 *)&_patches[path]->md5 , &ctx); + MD5_Final((uint8 *)&_patches[path]->md5, &ctx); } /// Get cached MD5 hash for a given patch file -bool Patcher::GetHash(char * pat,uint8 mymd5[16]) +bool Patcher::GetHash(char * pat, uint8 mymd5[16]) { - for( Patches::iterator i = _patches.begin(); i != _patches.end(); i++ ) - if(!stricmp(pat,i->first.c_str () )) + for( Patches::iterator i = _patches.begin(); i != _patches.end(); ++i ) + if(!stricmp(pat, i->first.c_str())) { - memcpy(mymd5,i->second->md5,16); + memcpy(mymd5, i->second->md5, 16); return true; } @@ -1089,6 +1105,6 @@ Patcher::Patcher() /// Empty and delete the patch map on termination Patcher::~Patcher() { - for(Patches::iterator i = _patches.begin(); i != _patches.end(); i++ ) + for(Patches::iterator i = _patches.begin(); i != _patches.end(); ++i ) delete i->second; } diff --git a/src/trinityrealm/Main.cpp b/src/trinityrealm/Main.cpp index 3d934f4ba85..1985009ea93 100644 --- a/src/trinityrealm/Main.cpp +++ b/src/trinityrealm/Main.cpp @@ -66,7 +66,7 @@ void HookSignals(); bool stopEvent = false; ///< Setting it to true stops the server RealmList m_realmList; ///< Holds the list of realms for this server -DatabaseType LoginDatabase; ///< Accessor to the realm server database +DatabaseType loginDatabase; ///< Accessor to the realm server database /// Print out the usage string for this program on the console. void usage(const char *prog) @@ -304,7 +304,7 @@ extern int main(int argc, char **argv) { loopCounter = 0; sLog.outDetail("Ping MySQL to keep connection alive"); - delete LoginDatabase.Query("SELECT 1 FROM realmlist LIMIT 1"); + delete loginDatabase.Query("SELECT 1 FROM realmlist LIMIT 1"); } #ifdef WIN32 if (m_ServiceStatus == 0) stopEvent = true; @@ -313,8 +313,8 @@ extern int main(int argc, char **argv) } ///- Wait for the delay thread to exit - LoginDatabase.ThreadEnd(); - LoginDatabase.HaltDelayThread(); + loginDatabase.ThreadEnd(); + loginDatabase.HaltDelayThread(); ///- Remove signal handling before leaving UnhookSignals(); @@ -346,19 +346,19 @@ void OnSignal(int s) /// Initialize connection to the database bool StartDB() { - std::string dbstring = sConfig.GetStringDefault("LoginDatabaseInfo", ""); + std::string dbstring = sConfig.GetStringDefault("loginDatabaseInfo", ""); if(dbstring.empty()) { sLog.outError("Database not specified"); return false; } - if(!LoginDatabase.Initialize(dbstring.c_str())) + if(!loginDatabase.Initialize(dbstring.c_str())) { sLog.outError("Cannot connect to database"); return false; } - LoginDatabase.ThreadStart(); + loginDatabase.ThreadStart(); return true; } diff --git a/src/trinityrealm/RealmList.cpp b/src/trinityrealm/RealmList.cpp index 6a3d6b47e0f..4de3a796179 100644 --- a/src/trinityrealm/RealmList.cpp +++ b/src/trinityrealm/RealmList.cpp @@ -29,7 +29,7 @@ INSTANTIATE_SINGLETON_1( RealmList ); -extern DatabaseType LoginDatabase; +extern DatabaseType loginDatabase; RealmList::RealmList( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) { @@ -82,7 +82,7 @@ void RealmList::UpdateRealms(bool init) { sLog.outDetail("Updating Realm List..."); - QueryResult *result = LoginDatabase.Query( "SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population FROM realmlist WHERE color <> 3 ORDER BY name" ); + QueryResult *result = loginDatabase.Query( "SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population FROM realmlist WHERE color <> 3 ORDER BY name" ); ///- Circle through results and add them to the realm map if(result) |