diff --git a/sql/mangos.sql b/sql/mangos.sql index fa1273f60..7c5817f30 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_2008_11_27_01_mangos_playercreateinfo_item` bit(1) default NULL + `required_2008_11_29_02_mangos_spell_elixir` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -13741,6 +13741,7 @@ INSERT INTO `spell_elixir` VALUES (41610,0xB), (41611,0xB), (42735,0x3), +(45373,0x1), (46837,0xB), (46839,0xB); /*!40000 ALTER TABLE `spell_elixir` ENABLE KEYS */; @@ -14731,7 +14732,7 @@ INSERT INTO `spell_proc_event` VALUES (34950,0,0,0,0,0x0000000000000000,0x00400000,0,0), (34954,0,0,0,0,0x0000000000000000,0x00400000,0,0), (35077,0,0,0,0,0x0000000000000000,0x00008000,0,60), -(35080,0,0,0,0,0x0000000000000000,0x00000001,0,60), +(35080,0,0,0,0,0x0000000000000000,0x00080001,0,60), (35083,0,0,0,0,0x0000000000000000,0x00020000,0,60), (35086,0,0,0,0,0x0000000000000000,0x08020000,0,60), (35100,0,0,0,0,0x0000000000000000,0x00080000,0,0), diff --git a/sql/updates/2008_11_29_01_mangos_spell_proc_event.sql b/sql/updates/2008_11_29_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..339ae216d --- /dev/null +++ b/sql/updates/2008_11_29_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_11_27_01_mangos_playercreateinfo_item required_2008_11_29_01_mangos_spell_proc_event bit; + +DELETE FROM spell_proc_event where entry = 35080; +INSERT INTO spell_proc_event (entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown) VALUES +(35080,0,0,0,0,0x0000000000000000,0x00080001,0,60); diff --git a/sql/updates/2008_11_29_02_mangos_spell_elixir.sql b/sql/updates/2008_11_29_02_mangos_spell_elixir.sql new file mode 100644 index 000000000..7d6d353a2 --- /dev/null +++ b/sql/updates/2008_11_29_02_mangos_spell_elixir.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_11_29_01_mangos_spell_proc_event required_2008_11_29_02_mangos_spell_elixir bit; + +DELETE FROM `spell_elixir` WHERE `entry` = 45373; +INSERT INTO `spell_elixir` VALUES +(45373,0x1); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index d363373f1..17c5d931a 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -138,6 +138,8 @@ pkgdata_DATA = \ 2008_11_18_01_mangos_creature_movement.sql \ 2008_11_18_02_mangos_mangos_string.sql \ 2008_11_27_01_mangos_playercreateinfo_item.sql \ + 2008_11_29_01_mangos_spell_proc_event.sql \ + 2008_11_29_02_mangos_spell_elixir.sql \ README ## Additional files to include when running 'make dist' @@ -257,4 +259,6 @@ EXTRA_DIST = \ 2008_11_18_01_mangos_creature_movement.sql \ 2008_11_18_02_mangos_mangos_string.sql \ 2008_11_27_01_mangos_playercreateinfo_item.sql \ + 2008_11_29_01_mangos_spell_proc_event.sql \ + 2008_11_29_02_mangos_spell_elixir.sql \ README diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index 88ed21ebf..0b9808c3b 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -22,21 +22,21 @@ 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 = 0; - stats.played = 0; - stats.rank = 0; - stats.rating = 1500; - stats.wins = 0; - stats.wins2 = 0; + 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; + stats.rating = 1500; + stats.wins_week = 0; + stats.wins_season = 0; } ArenaTeam::~ArenaTeam() @@ -51,7 +51,7 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam if(objmgr.GetArenaTeamByName(ArenaTeamName)) // arena team with this name already exist return false; - sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid)); + sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid)); CaptainGuid = captainGuid; Name = ArenaTeamName; @@ -69,7 +69,7 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')", Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor); CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES " - "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id,stats.rating,stats.games,stats.wins,stats.played,stats.wins2,stats.rank); + "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id,stats.rating,stats.games_week,stats.wins_week,stats.games_season,stats.wins_season,stats.rank); CharacterDatabase.CommitTransaction(); @@ -122,13 +122,14 @@ bool ArenaTeam::AddMember(uint64 PlayerGuid) Player::RemovePetitionsAndSigns(PlayerGuid, GetType()); ArenaTeamMember newmember; - newmember.name = plName; - newmember.guid = PlayerGuid; - newmember.Class = plClass; - newmember.played_season = 0; - newmember.played_week = 0; - newmember.wons_season = 0; - newmember.wons_week = 0; + newmember.name = plName; + newmember.guid = PlayerGuid; + newmember.Class = plClass; + newmember.games_season = 0; + newmember.games_week = 0; + newmember.wins_season = 0; + newmember.wins_week = 0; + newmember.personal_rating = 1500; members.push_back(newmember); CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid,guid) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid)); @@ -192,12 +193,12 @@ void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId) Field *fields = result->Fetch(); - stats.rating = fields[0].GetUInt32(); - stats.games = fields[1].GetUInt32(); - stats.wins = fields[2].GetUInt32(); - stats.played = fields[3].GetUInt32(); - stats.wins2 = fields[4].GetUInt32(); - stats.rank = fields[5].GetUInt32(); + 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(); delete result; } @@ -206,7 +207,7 @@ void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId) { Field *fields; - QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); + QueryResult *result = CharacterDatabase.PQuery("SELECT guid,games_week,wins_week,games_season,wins_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); if(!result) return; @@ -216,10 +217,10 @@ void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId) ArenaTeamMember newmember; newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); LoadPlayerStats(&newmember); - newmember.played_week = fields[1].GetUInt32(); - newmember.wons_week = fields[2].GetUInt32(); - newmember.played_season = fields[3].GetUInt32(); - newmember.wons_season = fields[4].GetUInt32(); + newmember.games_week = fields[1].GetUInt32(); + newmember.wins_week = fields[2].GetUInt32(); + newmember.games_season = fields[3].GetUInt32(); + newmember.wins_season = fields[4].GetUInt32(); members.push_back(newmember); }while( result->NextRow() ); delete result; @@ -337,11 +338,11 @@ void ArenaTeam::Roster(WorldSession *session) data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown data << uint8(pl->getLevel()); // unknown, probably level data << uint8(pl->getClass()); // class - data << uint32(itr->played_week); // played this week - data << uint32(itr->wons_week); // wins this week - data << uint32(itr->played_season); // played this season - data << uint32(itr->wons_season); // wins this season - data << uint32(0); // personal rating? + data << uint32(itr->games_week); // played this week + data << uint32(itr->wins_week); // wins this week + data << uint32(itr->games_season); // played this season + data << uint32(itr->wins_season); // wins this season + data << uint32(itr->personal_rating); // personal rating } else { @@ -351,11 +352,11 @@ void ArenaTeam::Roster(WorldSession *session) data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown data << uint8(0); // unknown, level? data << uint8(itr->Class); // class - data << uint32(itr->played_week); // played this week - data << uint32(itr->wons_week); // wins this week - data << uint32(itr->played_season); // played this season - data << uint32(itr->wons_season); // wins this season - data << uint32(0); // personal rating? + data << uint32(itr->games_week); // played this week + data << uint32(itr->wins_week); // wins this week + data << uint32(itr->games_season); // played this season + data << uint32(itr->wins_season); // wins this season + data << uint32(itr->personal_rating); // personal rating } } session->SendPacket(&data); @@ -382,25 +383,29 @@ 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); // games - data << uint32(stats.wins); // wins - data << uint32(stats.played); // played - data << uint32(stats.wins2); // wins(again o_O) + 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 session->SendPacket(&data); } void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) { + ArenaTeamMember* member = GetMember(guid); + if(!member) + return; + WorldPacket data(MSG_INSPECT_ARENA_TEAMS, 8+1+4*6); 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); // games - data << uint32(stats.wins); // wins - data << uint32(stats.played); // played (count of all games, that played...) - data << uint32(0); // 2.3.3 personal rating? + data << uint32(stats.games_season); // season played + data << uint32(stats.wins_season); // season wins + data << member->games_season; // played (count of all games, that the inspected member participated...) + data << member->personal_rating; // personal rating session->SendPacket(&data); } @@ -423,20 +428,20 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value) stats.rating = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value, GetId()); break; - case STAT_TYPE_GAMES: - stats.games = value; + case STAT_TYPE_GAMES_WEEK: + stats.games_week = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value, GetId()); break; - case STAT_TYPE_WINS: - stats.wins = value; + case STAT_TYPE_WINS_WEEK: + stats.wins_week = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value, GetId()); break; - case STAT_TYPE_PLAYED: - stats.played = value; + case STAT_TYPE_GAMES_SEASON: + stats.games_season = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value, GetId()); break; - case STAT_TYPE_WINS2: - stats.wins2 = value; + case STAT_TYPE_WINS_SEASON: + stats.wins_season = value; CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value, GetId()); break; case STAT_TYPE_RANK: @@ -493,24 +498,35 @@ bool ArenaTeam::HaveMember( uint64 guid ) const return false; } +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) + { + itr->games_week = 0; + itr->wins_week = 0; + } +} + /* arenateam fields (id from 2.3.3 client): 1414 - arena team id 2v2 1415 - 0=captain, 1=member -1416 - played this season -1417 - played this week +1416 - played this week +1417 - played this season 1418 - unk -1419 - unk +1419 - personal arena rating 1420 - arena team id 3v3 1421 - 0=captain, 1=member -1422 - played this season -1423 - played this week +1422 - played this week +1423 - played this season 1424 - unk -1425 - unk +1425 - personal arena rating 1426 - arena team id 5v5 1427 - 0=captain, 1=member -1428 - played this season -1429 - played this week +1428 - played this week +1429 - played this season 1430 - unk -1431 - unk +1431 - personal arena rating */ diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h index 0d26b00cf..b12b759a8 100644 --- a/src/game/ArenaTeam.h +++ b/src/game/ArenaTeam.h @@ -66,12 +66,12 @@ ERR_ARENA_TEAM_LEVEL_TOO_LOW_I enum ArenaTeamStatTypes { - STAT_TYPE_RATING = 0, - STAT_TYPE_GAMES = 1, - STAT_TYPE_WINS = 2, - STAT_TYPE_PLAYED = 3, - STAT_TYPE_WINS2 = 4, - STAT_TYPE_RANK = 5 + STAT_TYPE_RATING = 0, + STAT_TYPE_GAMES_WEEK = 1, + STAT_TYPE_WINS_WEEK = 2, + STAT_TYPE_GAMES_SEASON = 3, + STAT_TYPE_WINS_SEASON = 4, + STAT_TYPE_RANK = 5 }; enum ArenaTeamTypes @@ -88,19 +88,20 @@ struct ArenaTeamMember //uint32 unk2; //uint8 unk1; uint8 Class; - uint32 played_week; - uint32 wons_week; - uint32 played_season; - uint32 wons_season; + uint32 games_week; + uint32 wins_week; + uint32 games_season; + uint32 wins_season; + uint32 personal_rating; }; struct ArenaTeamStats { uint32 rating; - uint32 games; - uint32 wins; - uint32 played; - uint32 wins2; + uint32 games_week; + uint32 wins_week; + uint32 games_season; + uint32 wins_season; uint32 rank; }; @@ -123,7 +124,7 @@ class ArenaTeam static uint8 GetSlotByType(uint32 type); const uint64& GetCaptain() const { return CaptainGuid; } std::string GetName() const { return Name; } - ArenaTeamStats GetStats() const { return stats; } + const ArenaTeamStats& GetStats() const { return stats; } void SetStats(uint32 stat_type, uint32 value); uint32 GetRating() const { return stats.rating; } @@ -143,6 +144,14 @@ class ArenaTeam MemberList::iterator membersbegin(){ return members.begin(); } MemberList::iterator membersEnd(){ return members.end(); } bool HaveMember(uint64 guid) const; + ArenaTeamMember* GetMember(uint64 guid) + { + for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + if(itr->guid==guid) + return &(*itr); + + return NULL; + } bool LoadArenaTeamFromDB(uint32 ArenaTeamId); void LoadMembersFromDB(uint32 ArenaTeamId); @@ -156,6 +165,8 @@ class ArenaTeam void Stats(WorldSession *session); void InspectStats(WorldSession *session, uint64 guid); + void FinishWeek(); + protected: uint32 Id; diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 4438aec1f..c51c4e9e3 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -710,14 +710,21 @@ void BattleGround::AddPlayer(Player *plr) plr->RemoveArenaSpellCooldowns(); //plr->RemoveArenaAuras(); plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT); - if(team == ALLIANCE && plr->GetTeam() == ALLIANCE) - plr->CastSpell(plr,SPELL_ALLIANCE_GOLD_FLAG,true); - else if(team == HORDE && plr->GetTeam() == ALLIANCE) - plr->CastSpell(plr,SPELL_ALLIANCE_GREEN_FLAG,true); - else if(team == ALLIANCE && plr->GetTeam() == HORDE) - plr->CastSpell(plr,SPELL_HORDE_GOLD_FLAG,true); + if(team == ALLIANCE) // gold + { + if(plr->GetTeam() == HORDE) + plr->CastSpell(plr, SPELL_HORDE_GOLD_FLAG,true); + else + plr->CastSpell(plr, SPELL_ALLIANCE_GOLD_FLAG,true); + } else - plr->CastSpell(plr,SPELL_HORDE_GREEN_FLAG,true); + { + if(plr->GetTeam() == HORDE) // green + plr->CastSpell(plr, SPELL_HORDE_GREEN_FLAG,true); + else + plr->CastSpell(plr, SPELL_ALLIANCE_GREEN_FLAG,true); + } + plr->DestroyConjuredItems(true); if(GetStatus() == STATUS_WAIT_JOIN) // not started yet diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 2163e05c5..4f4f2db94 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -765,6 +765,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); + if(sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) + pCurrChar->SetTaxiCheater(true); + if(pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); diff --git a/src/game/MapRefManager.h b/src/game/MapRefManager.h index 05d93903c..bfd0ca12e 100644 --- a/src/game/MapRefManager.h +++ b/src/game/MapRefManager.h @@ -39,6 +39,6 @@ class MapRefManager : public RefManager iterator rbegin() { return iterator(getLast()); } iterator rend() { return iterator(NULL); } const_iterator begin() const { return const_iterator(getFirst()); } - const_iterator end() const { return const_iterator(getLast()); } + const_iterator end() const { return const_iterator(NULL); } }; #endif diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 65a9060db..abfcfa2a1 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -275,13 +275,6 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ ) if (uint64 lguid = GetPlayer()->GetLootGUID()) DoLootRelease(lguid); - //instant logout for admins, gm's, mod's - if( GetSecurity() > SEC_PLAYER ) - { - LogoutPlayer(true); - return; - } - //Can not logout if... if( GetPlayer()->isInCombat() || //...is in combat GetPlayer()->duel || //...is in Duel @@ -297,8 +290,9 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ ) return; } - //instant logout in taverns/cities or on taxi - if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight()) + //instant logout in taverns/cities or on taxi or for admins, gm's, mod's if its enabled in mangosd.conf + if (GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) || GetPlayer()->isInFlight() || + GetSecurity() >= sWorld.getConfig(CONFIG_INSTANT_LOGOUT)) { LogoutPlayer(true); return; @@ -664,6 +658,10 @@ void WorldSession::HandleCorpseReclaimOpcode(WorldPacket &recv_data) if (GetPlayer()->isAlive()) return; + // do not allow corpse reclaim in arena + if (GetPlayer()->InArena()) + return; + // body not released yet if(!GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) return; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 5eae50158..95f0cda1f 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -7336,7 +7336,7 @@ void ObjectMgr::CheckScripts(ScriptMapMap const& scripts,std::set& ids) if(itrM->second.dataint) { if(!GetMangosStringLocale (itrM->second.dataint)) - sLog.outErrorDb( "Table `db_script_string` has not existed string id %u", *itrM); + sLog.outErrorDb( "Table `db_script_string` has not existed string id %u", itrM->first); if(ids.count(itrM->second.dataint)) ids.erase(itrM->second.dataint); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index c4fbbe1b8..5fd97a769 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -596,13 +596,22 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, } // set starting level - if(getClass() == CLASS_DEATH_KNIGHT) - SetUInt32Value(UNIT_FIELD_LEVEL, 55); + if (GetSession()->GetSecurity() >= SEC_MODERATOR) + SetUInt32Value(UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_GM_LEVEL)); else - SetUInt32Value( UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) ); + { + if(getClass() == CLASS_DEATH_KNIGHT) + SetUInt32Value(UNIT_FIELD_LEVEL, 55); + else + SetUInt32Value(UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_PLAYER_LEVEL)); + } InitRunes(); + SetUInt32Value (PLAYER_FIELD_COINAGE, sWorld.getConfig(CONFIG_START_PLAYER_MONEY)); + SetUInt32Value (PLAYER_FIELD_HONOR_CURRENCY, sWorld.getConfig(CONFIG_START_HONOR_POINTS)); + SetUInt32Value (PLAYER_FIELD_ARENA_CURRENCY, sWorld.getConfig(CONFIG_START_ARENA_POINTS)); + // Played time m_Last_tick = time(NULL); m_Played_time[0] = 0; @@ -838,8 +847,8 @@ void Player::HandleDrowning() if(!m_isunderwater) return; - //if have water breath , then remove bar - if(waterbreath || isGameMaster() || !isAlive()) + //if player is GM, have waterbreath, is dead or if breathing is disabled then return + if(waterbreath || isGameMaster() || !isAlive() || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) { StopMirrorTimer(BREATH_TIMER); m_isunderwater = 0; @@ -2197,7 +2206,7 @@ void Player::GiveLevel(uint32 level) if(getLevel()!= level) m_Played_time[1] = 0; // Level Played Time reset SetLevel(level); - UpdateMaxSkills(); + UpdateSkillsForLevel (); // save base values (bonuses already included in stored stats for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) @@ -2272,7 +2281,7 @@ void Player::InitStatsForLevel(bool reapplyMods) SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ); SetUInt32Value(PLAYER_NEXT_LEVEL_XP, MaNGOS::XP::xp_to_level(getLevel())); - UpdateMaxSkills (); + UpdateSkillsForLevel (); // set default cast time multiplier SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); @@ -3783,7 +3792,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) // some items limited to specific map DestroyZoneLimitedItem( true, GetZoneId()); - if(!applySickness || getLevel() <= 10) + if(!applySickness) return; //Characters from level 1-10 are not affected by resurrection sickness. @@ -4906,9 +4915,12 @@ void Player::ModifySkillBonus(uint32 skillid,int32 val, bool talent) } } -void Player::UpdateMaxSkills() +void Player::UpdateSkillsForLevel() { uint16 maxconfskill = sWorld.GetConfigMaxSkillValue(); + uint32 maxSkill = GetMaxSkillValueForLevel(); + + bool alwaysMaxSkill = sWorld.getConfig(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL); for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) @@ -4926,11 +4938,15 @@ void Player::UpdateMaxSkills() uint32 max = SKILL_MAX(data); uint32 val = SKILL_VALUE(data); - // update only level dependent max skill values - if(max!=1 && max != maxconfskill) + /// update only level dependent max skill values + if(max!=1) { - uint32 max_Skill = GetMaxSkillValueForLevel(); - SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(val,max_Skill)); + /// miximize skill always + if(alwaysMaxSkill) + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(maxSkill,maxSkill)); + /// update max skill value if current max skill not maximized + else if(max != maxconfskill) + SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(val,maxSkill)); } } } @@ -5963,6 +5979,18 @@ void Player::UpdateHonorFields() ///An exact honor value can also be given (overriding the calcs) bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor) { + // do not reward honor in arenas, but enable onkill spellproc + if(InArena()) + { + if(!uVictim || uVictim == this || uVictim->GetTypeId() != TYPEID_PLAYER) + return false; + + if( GetBGTeam() == ((Player*)uVictim)->GetBGTeam() ) + return false; + + return true; + } + // 'Inactive' this aura prevents the player from gaining honor points and battleground tokens if(GetDummyAura(SPELL_AURA_PLAYER_INACTIVE)) return false; diff --git a/src/game/Player.h b/src/game/Player.h index 88e576ac1..7f1844e96 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1771,7 +1771,7 @@ class MANGOS_DLL_SPEC Player : public Unit void SetFactionVisible(FactionState* faction); void SetFactionVisibleForFactionTemplateId(uint32 FactionTemplateId); void SetFactionVisibleForFactionId(uint32 FactionId); - void UpdateMaxSkills(); + void UpdateSkillsForLevel(); void UpdateSkillsToMaxSkillsForLevel(); // for .levelup void ModifySkillBonus(uint32 skillid,int32 val, bool talent); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 7420e985d..4ee734d57 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2594,13 +2594,23 @@ void Spell::SendCastResult(uint8 result) break; case SPELL_FAILED_REQUIRES_AREA: // hardcode areas limitation case - if( m_spellInfo->Id==41618 || m_spellInfo->Id==41620 ) - data << uint32(3842); - else if( m_spellInfo->Id==41617 || m_spellInfo->Id==41619 ) - data << uint32(3905); - // normal case - else - data << uint32(m_spellInfo->AreaId); + switch(m_spellInfo->Id) + { + case 41617: // Cenarion Mana Salve + case 41619: // Cenarion Healing Salve + data << uint32(3905); + break; + case 41618: // Bottled Nethergon Energy + case 41620: // Bottled Nethergon Vapor + data << uint32(3842); + break; + case 45373: // Bloodberry Elixir + data << uint32(4075); + break; + default: // default case + data << uint32(m_spellInfo->AreaId); + break; + } break; case SPELL_FAILED_TOTEMS: if(m_spellInfo->Totem[0]) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7bfbff618..b93aad5fc 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2233,6 +2233,11 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z { if(uint32 mask = spellmgr.GetSpellElixirMask(spellInfo->Id)) { + if(mask & ELIXIR_BATTLE_MASK) + { + if(spellInfo->Id==45373) // Bloodberry Elixir + return zone_id==4075; + } if(mask & ELIXIR_UNSTABLE_MASK) { // in the Blade's Edge Mountains Plateaus and Gruul's Lair. @@ -2240,9 +2245,8 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z } if(mask & ELIXIR_SHATTRATH_MASK) { - // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple - // TODO: and the Sunwell Plateau - if(zone_id ==3607 || map_id==534 || map_id==564) + // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau + if(zone_id ==3607 || map_id==534 || map_id==564 || zone_id==4075) return true; MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); @@ -2260,8 +2264,8 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z // special cases zone check (maps checked by multimap common id) switch(spellInfo->Id) { - case 41618: - case 41620: + case 41618: // Bottled Nethergon Energy + case 41620: // Bottled Nethergon Vapor { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); if(!mapEntry) @@ -2269,9 +2273,8 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z return mapEntry->multimap_id==206; } - - case 41617: - case 41619: + case 41617: // Cenarion Mana Salve + case 41619: // Cenarion Healing Salve { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); if(!mapEntry) @@ -2279,14 +2282,9 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z return mapEntry->multimap_id==207; } - // Dragonmaw Illusion - case 40216: - case 42016: - { - if ( area_id != 3759 && area_id != 3966 && area_id != 3939 ) - return false; - break; - } + case 40216: // Dragonmaw Illusion + case 42016: // Dragonmaw Illusion + return area_id == 3759 || area_id == 3966 || area_id == 3939; } return true; diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index 6138d8478..64061487c 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -49,7 +49,8 @@ void WaypointMovementGenerator::LoadPath(Creature &c) i_path = WaypointMgr.GetPath(c.GetDBTableGUIDLow()); if(!i_path) { - sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s(%d) doesn't have waypoint path", c.GetName(), c.GetDBTableGUIDLow()); + sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %d) doesn't have waypoint path", + c.GetName(), c.GetEntry(), c.GetDBTableGUIDLow()); return; } diff --git a/src/game/World.cpp b/src/game/World.cpp index 912b182f0..ea6cdd9c6 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -112,10 +112,12 @@ World::World() World::~World() { ///- Empty the kicked session set - for (std::set::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr) - delete *itr; - - m_kicked_sessions.clear(); + while (!m_sessions.empty()) + { + // not remove from queue, prevent loading new sessions + delete m_sessions.begin()->second; + m_sessions.erase(m_sessions.begin()); + } ///- Empty the WeatherMap for (WeatherMap::iterator itr = m_weathers.begin(); itr != m_weathers.end(); ++itr) @@ -195,17 +197,26 @@ World::AddSession_ (WorldSession* s) if (!RemoveSession (s->GetAccountId ())) { s->KickPlayer (); - m_kicked_sessions.insert (s); + delete s; // session not added yet in session list, so not listed in queue return; } + // decrease session counts only at not reconnection case + bool decrease_session = true; + // if session already exist, prepare to it deleting at next world update // NOTE - KickPlayer() should be called on "old" in RemoveSession() { - SessionMap::const_iterator old = m_sessions.find(s->GetAccountId ()); + SessionMap::const_iterator old = m_sessions.find(s->GetAccountId ()); - if(old != m_sessions.end()) - m_kicked_sessions.insert (old->second); + if(old != m_sessions.end()) + { + // prevent decrease sessions count if session queued + if(RemoveQueuedPlayer(old->second)) + decrease_session = false; + // not remove replaced session form queue if listed + delete old->second; + } } m_sessions[s->GetAccountId ()] = s; @@ -213,9 +224,11 @@ World::AddSession_ (WorldSession* s) uint32 Sessions = GetActiveAndQueuedSessionCount (); uint32 pLimit = GetPlayerAmountLimit (); uint32 QueueSize = GetQueueSize (); //number of players in the queue + //so we don't count the user trying to //login as a session and queue the socket that we are using - --Sessions; + if(decrease_session) + --Sessions; if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER ) { @@ -259,6 +272,7 @@ int32 World::GetQueuePos(WorldSession* sess) void World::AddQueuedPlayer(WorldSession* sess) { + sess->SetInQueue(true); m_QueuedPlayer.push_back (sess); // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. @@ -274,7 +288,7 @@ void World::AddQueuedPlayer(WorldSession* sess) //sess->SendAuthWaitQue (GetQueuePos (sess)); } -void World::RemoveQueuedPlayer(WorldSession* sess) +bool World::RemoveQueuedPlayer(WorldSession* sess) { // sessions count including queued to remove (if removed_session set) uint32 sessions = GetActiveSessionCount(); @@ -282,16 +296,16 @@ void World::RemoveQueuedPlayer(WorldSession* sess) uint32 position = 1; Queue::iterator iter = m_QueuedPlayer.begin(); - // if session not queued then we need decrease sessions count (Remove socked callet before session removing from session list) - bool decrease_session = true; - // search to remove and count skipped positions + bool found = false; + for(;iter != m_QueuedPlayer.end(); ++iter, ++position) { if(*iter==sess) { + sess->SetInQueue(false); iter = m_QueuedPlayer.erase(iter); - decrease_session = false; // removing queued session + found = true; // removing queued session break; } } @@ -299,15 +313,16 @@ void World::RemoveQueuedPlayer(WorldSession* sess) // iter point to next socked after removed or end() // position store position of removed socket and then new position next socket after removed - // decrease for case session queued for removing - if(decrease_session && sessions) + // if session not queued then we need decrease sessions count + if(!found && sessions) --sessions; // accept first in queue if( (!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty() ) { - WorldSession * socket = m_QueuedPlayer.front(); - socket->SendAuthWaitQue(0); + WorldSession* pop_sess = m_QueuedPlayer.front(); + pop_sess->SetInQueue(false); + pop_sess->SendAuthWaitQue(0); m_QueuedPlayer.pop_front(); // update iter to point first queued socket or end() if queue is empty now @@ -319,6 +334,8 @@ void World::RemoveQueuedPlayer(WorldSession* sess) // iter point to first not updated socket, position store new position for(; iter != m_QueuedPlayer.end(); ++iter, ++position) (*iter)->SendAuthWaitQue(position); + + return found; } /// Find a Weather object by the given zoneid @@ -654,8 +671,63 @@ void World::LoadConfigSettings(bool reload) sLog.outError("StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.",m_configs[CONFIG_START_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]); m_configs[CONFIG_START_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL]; } + + m_configs[CONFIG_START_PLAYER_MONEY] = sConfig.GetIntDefault("StartPlayerMoney", 0); + if(m_configs[CONFIG_START_PLAYER_MONEY] < 0) + { + sLog.outError("StartPlayerMoney (%i) must be in range 0..%u. Set to %u.",m_configs[CONFIG_START_PLAYER_MONEY],MAX_MONEY_AMOUNT,0); + m_configs[CONFIG_START_PLAYER_MONEY] = 0; + } + else if(m_configs[CONFIG_START_PLAYER_MONEY] > MAX_MONEY_AMOUNT) + { + sLog.outError("StartPlayerMoney (%i) must be in range 0..%u. Set to %u.", + m_configs[CONFIG_START_PLAYER_MONEY],MAX_MONEY_AMOUNT,MAX_MONEY_AMOUNT); + m_configs[CONFIG_START_PLAYER_MONEY] = MAX_MONEY_AMOUNT; + } + m_configs[CONFIG_MAX_HONOR_POINTS] = sConfig.GetIntDefault("MaxHonorPoints", 75000); + if(m_configs[CONFIG_MAX_HONOR_POINTS] < 0) + { + sLog.outError("MaxHonorPoints (%i) can't be negative. Set to 0.",m_configs[CONFIG_MAX_HONOR_POINTS]); + m_configs[CONFIG_MAX_HONOR_POINTS] = 0; + } + + m_configs[CONFIG_START_HONOR_POINTS] = sConfig.GetIntDefault("StartHonorPoints", 0); + if(m_configs[CONFIG_START_HONOR_POINTS] < 0) + { + sLog.outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.", + m_configs[CONFIG_START_HONOR_POINTS],m_configs[CONFIG_MAX_HONOR_POINTS],0); + m_configs[CONFIG_MAX_HONOR_POINTS] = 0; + } + else if(m_configs[CONFIG_START_HONOR_POINTS] > m_configs[CONFIG_MAX_HONOR_POINTS]) + { + sLog.outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.", + m_configs[CONFIG_START_HONOR_POINTS],m_configs[CONFIG_MAX_HONOR_POINTS],m_configs[CONFIG_MAX_HONOR_POINTS]); + m_configs[CONFIG_START_HONOR_POINTS] = m_configs[CONFIG_MAX_HONOR_POINTS]; + } + m_configs[CONFIG_MAX_ARENA_POINTS] = sConfig.GetIntDefault("MaxArenaPoints", 5000); + if(m_configs[CONFIG_MAX_ARENA_POINTS] < 0) + { + sLog.outError("MaxArenaPoints (%i) can't be negative. Set to 0.",m_configs[CONFIG_MAX_ARENA_POINTS]); + m_configs[CONFIG_MAX_ARENA_POINTS] = 0; + } + + m_configs[CONFIG_START_ARENA_POINTS] = sConfig.GetIntDefault("StartArenaPoints", 0); + if(m_configs[CONFIG_START_ARENA_POINTS] < 0) + { + sLog.outError("StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.", + m_configs[CONFIG_START_ARENA_POINTS],m_configs[CONFIG_MAX_ARENA_POINTS],0); + m_configs[CONFIG_MAX_ARENA_POINTS] = 0; + } + else if(m_configs[CONFIG_START_ARENA_POINTS] > m_configs[CONFIG_MAX_ARENA_POINTS]) + { + sLog.outError("StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.", + m_configs[CONFIG_START_ARENA_POINTS],m_configs[CONFIG_MAX_ARENA_POINTS],m_configs[CONFIG_MAX_ARENA_POINTS]); + m_configs[CONFIG_START_ARENA_POINTS] = m_configs[CONFIG_MAX_ARENA_POINTS]; + } + + m_configs[CONFIG_ALL_TAXI_PATHS] = sConfig.GetBoolDefault("AllFlightPaths", false); m_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfig.GetBoolDefault("Instance.IgnoreLevel", false); m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false); @@ -685,6 +757,19 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false); m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false); + m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1); + if(m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL]) + { + sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..255. Set to %u.", + m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL]); + m_configs[CONFIG_START_GM_LEVEL] = m_configs[CONFIG_START_PLAYER_LEVEL]; + } + else if(m_configs[CONFIG_START_GM_LEVEL] > 255) + { + sLog.outError("GM.StartLevel (%i) must be in range 1..255. Set to %u.",m_configs[CONFIG_START_GM_LEVEL],255); + m_configs[CONFIG_START_GM_LEVEL] = 255; + } + m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); m_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfig.GetIntDefault("MailDeliveryDelay",HOUR); @@ -750,6 +835,10 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY] = sConfig.GetBoolDefault("SaveRespawnTimeImmediately",true); m_configs[CONFIG_WEATHER] = sConfig.GetBoolDefault("ActivateWeather",true); + m_configs[CONFIG_DISABLE_BREATHING] = sConfig.GetIntDefault("DisableWaterBreath", SEC_CONSOLE); + + m_configs[CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL] = sConfig.GetBoolDefault("AlwaysMaxSkillForLevel", false); + if(reload) { uint32 val = sConfig.GetIntDefault("Expansion",1); @@ -806,6 +895,8 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25); m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300); + m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR); + m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); if(m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE) { @@ -2193,6 +2284,8 @@ void World::SendZoneText(uint32 zone, const char* text, WorldSession *self, uint /// Kick (and save) all players void World::KickAll() { + m_QueuedPlayer.clear(); // prevent send queue update packet and login queued sessions + // session not removed at kick and will removed in next update tick for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) itr->second->KickPlayer(); @@ -2207,18 +2300,6 @@ void World::KickAllLess(AccountTypes sec) itr->second->KickPlayer(); } -/// Kick all queued players -void World::KickAllQueued() -{ - // session not removed at kick and will removed in next update tick - //TODO here -// for (Queue::iterator itr = m_QueuedPlayer.begin(); itr != m_QueuedPlayer.end(); ++itr) -// if(WorldSession* session = (*itr)->GetSession()) -// session->KickPlayer(); - - m_QueuedPlayer.empty(); -} - /// Kick (and save) the designated player bool World::KickPlayer(std::string playerName) { @@ -2449,20 +2530,13 @@ void World::SendServerMessage(uint32 type, const char *text, Player* player) void World::UpdateSessions( time_t diff ) { + ///- Add new sessions while(!addSessQueue.empty()) { - WorldSession* sess = addSessQueue.next (); - AddSession_ (sess); + WorldSession* sess = addSessQueue.next (); + AddSession_ (sess); } - ///- Delete kicked sessions at add new session - for (std::set::iterator itr = m_kicked_sessions.begin(); itr != m_kicked_sessions.end(); ++itr) - { - RemoveQueuedPlayer (*itr); - delete *itr; - } - m_kicked_sessions.clear(); - ///- Then send an update signal to remaining ones for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next) { diff --git a/src/game/World.h b/src/game/World.h index 3821be4fe..d8800e2c3 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -103,8 +103,11 @@ enum WorldConfigs CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, CONFIG_START_PLAYER_LEVEL, + CONFIG_START_PLAYER_MONEY, CONFIG_MAX_HONOR_POINTS, + CONFIG_START_HONOR_POINTS, CONFIG_MAX_ARENA_POINTS, + CONFIG_START_ARENA_POINTS, CONFIG_INSTANCE_IGNORE_LEVEL, CONFIG_INSTANCE_IGNORE_RAID, CONFIG_BATTLEGROUND_CAST_DESERTER, @@ -122,6 +125,7 @@ enum WorldConfigs CONFIG_GM_IN_GM_LIST, CONFIG_GM_IN_WHO_LIST, CONFIG_GM_LOG_TRADE, + CONFIG_START_GM_LEVEL, CONFIG_GROUP_VISIBILITY, CONFIG_MAIL_DELIVERY_DELAY, CONFIG_UPTIME_UPDATE, @@ -138,6 +142,7 @@ enum WorldConfigs CONFIG_SKILL_GAIN_WEAPON, CONFIG_MAX_OVERSPEED_PINGS, CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY, + CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL, CONFIG_WEATHER, CONFIG_EXPANSION, CONFIG_CHATFLOOD_MESSAGE_COUNT, @@ -164,6 +169,9 @@ enum WorldConfigs CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP, CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE, CONFIG_THREAT_RADIUS, + CONFIG_INSTANT_LOGOUT, + CONFIG_DISABLE_BREATHING, + CONFIG_ALL_TAXI_PATHS, CONFIG_DECLINED_NAMES_USED, CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, @@ -352,7 +360,7 @@ class World //player Queue typedef std::list Queue; void AddQueuedPlayer(WorldSession*); - void RemoveQueuedPlayer(WorldSession*); + bool RemoveQueuedPlayer(WorldSession* session); int32 GetQueuePos(WorldSession*); uint32 GetQueueSize() const { return m_QueuedPlayer.size(); } @@ -435,7 +443,6 @@ class World bool KickPlayer(std::string playerName); void KickAll(); void KickAllLess(AccountTypes sec); - void KickAllQueued(); BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author); bool RemoveBanAccount(BanMode mode, std::string nameOrIP); @@ -493,7 +500,6 @@ class World WeatherMap m_weathers; typedef UNORDERED_MAP SessionMap; SessionMap m_sessions; - std::set m_kicked_sessions; uint32 m_maxActiveSessionCount; uint32 m_maxQueuedSessionCount; diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 8a54cc802..08d4df368 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -45,7 +45,7 @@ WorldSession::WorldSession(uint32 id, WorldSocket *sock, uint32 sec, uint8 expan LookingForGroup_auto_join(false), LookingForGroup_auto_add(false), m_muteTime(mute_time), _player(NULL), m_Socket(sock),_security(sec), _accountId(id), m_expansion(expansion), m_sessionDbcLocale(sWorld.GetAvailableDbcLocale(locale)), m_sessionDbLocaleIndex(objmgr.GetIndexForLocale(locale)), -_logoutTime(0), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0) +_logoutTime(0), m_inQueue(false), m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_latency(0) { if (sock) { @@ -205,6 +205,13 @@ bool WorldSession::Update(uint32 /*diff*/) (this->*opHandle.handler)(*packet); break; case STATUS_AUTHED: + // prevent cheating with skip queue wait + if(m_inQueue) + { + logUnexpectedOpcode(packet, "the player not pass queue yet"); + break; + } + m_playerRecentlyLogout = false; (this->*opHandle.handler)(*packet); break; diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index f855f1597..383bb8964 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -108,6 +108,9 @@ class MANGOS_DLL_SPEC WorldSession void SetPlayer(Player *plr) { _player = plr; } uint8 Expansion() const { return m_expansion; } + /// Session in auth.queue currently + void SetInQueue(bool state) { m_inQueue = state; } + /// Is the user engaged in a log out process? bool isLogingOut() const { return _logoutTime || m_playerLogout; } @@ -678,6 +681,7 @@ class MANGOS_DLL_SPEC WorldSession uint8 m_expansion; time_t _logoutTime; + bool m_inQueue; // session wait in auth.queue bool m_playerLoading; // code processed in LoginPlayer bool m_playerLogout; // code processed in LogoutPlayer bool m_playerRecentlyLogout; diff --git a/src/mangosd/WorldRunnable.cpp b/src/mangosd/WorldRunnable.cpp index 7ebe95fc7..87d7e78a9 100644 --- a/src/mangosd/WorldRunnable.cpp +++ b/src/mangosd/WorldRunnable.cpp @@ -72,7 +72,6 @@ void WorldRunnable::run() prevSleepTime = 0; } - sWorld.KickAllQueued(); // kick all queued players (and prevent its login at kick in game players) sWorld.KickAll(); // save and kick all players sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 554e3cfaf..59da7deff 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -419,17 +419,48 @@ LogColors = "" # Change not recommended # Default: 70 # +# StartPlayerLevel +# Staring level that have character at creating (in range 1 to MaxPlayerLevel) +# Default: 1 +# +# StartPlayerMoney +# Amount of money that new players will start with. +# If you want to start with silver, use for example 100 (100 copper = 1 silver) +# Default: 0 +# # MaxHonorPoints # Max honor points that player can have. # Default: 75000 # +# StartHonorPoints +# Amount of honor that new players will start with +# Default: 0 +# # MaxArenaPoints # Max arena points that player can have. # Default: 5000 # -# StartPlayerLevel -# Staring level that have character at creating (in range 1 to MaxPlayerLevel) -# Default: 1 +# StartArenaPoints +# Amount of arena points that new players will start with +# Default: 0 +# +# InstantLogout +# Enable or disable instant logout for security level (0..4) or high (NOT in combat/while dueling/while falling) +# Default: 1 (Mods/GMs/Admins) +# +# DisableWaterBreath +# Disable/enable waterbreathing for security level (0..4) or high +# Default: 4 (None) +# +# AllFlightPaths +# Players will start with all flight paths (Note: ALL flight paths, not only player's team) +# Default: 0 (true) +# 1 (false) +# +# AlwaysMaxSkillForLevel +# Players will automatically gain max level dependent (weapon/defense) skill when logging in, leveling up etc. +# Default: 0 (true) +# 1 (false) # # ActivateWeather # Activate weather system @@ -541,9 +572,16 @@ CharactersPerAccount = 50 CharactersPerRealm = 10 SkipCinematics = 0 MaxPlayerLevel = 80 -MaxHonorPoints = 75000 -MaxArenaPoints = 5000 StartPlayerLevel = 1 +StartPlayerMoney = 0 +MaxHonorPoints = 75000 +StartHonorPoints = 0 +MaxArenaPoints = 5000 +StartArenaPoints = 0 +InstantLogout = 1 +DisableWaterBreath = 4 +AllFlightPaths = 0 +AlwaysMaxSkillForLevel = 0 ActivateWeather = 1 Battleground.CastDeserter = 1 Battleground.QueueAnnouncer.Enable = 1 @@ -804,15 +842,20 @@ Channel.SilentlyGMJoin = 0 # Default: 1 (include) # 0 (not include) # +# GM.StartLevel +# GM starting level (1-255) +# Default: 1 +# ################################################################################################################### GM.LoginState = 2 GM.AcceptTickets = 2 GM.Chat = 2 GM.WhisperingTo = 2 -GM.InGMList = 0 -GM.InWhoList = 0 -GM.LogTrade = 1 +GM.InGMList = 0 +GM.InWhoList = 0 +GM.LogTrade = 1 +GM.StartLevel = 1 ################################################################################################################### # VISIBILITY AND RADIUSES diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0fc59aede..dd5528e2c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6856" + #define REVISION_NR "6863" #endif // __REVISION_NR_H__ diff --git a/win/VC80/framework.vcproj b/win/VC80/framework.vcproj index 9b41a6692..b9cda2773 100644 --- a/win/VC80/framework.vcproj +++ b/win/VC80/framework.vcproj @@ -422,7 +422,7 @@ >