2008-10-02 16:23:55 -05:00
/*
2009-02-04 12:04:12 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-02 16:23:55 -05:00
*
* 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
2008-11-14 14:19:23 -06:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-02 16:23:55 -05:00
* 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
2008-11-14 14:19:23 -06:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-02 16:23:55 -05:00
*/
#include "ObjectMgr.h"
2009-06-04 21:41:07 +02:00
#include "WorldPacket.h"
2008-10-02 16:23:55 -05:00
#include "ArenaTeam.h"
2009-06-18 11:33:32 -05:00
void ArenaTeamMember :: ModifyPersonalRating ( Player * plr , int32 mod , uint32 slot )
{
2009-06-18 16:51:32 -05:00
int32 memberRating = int32 ( personal_rating ) + mod ;
personal_rating = memberRating > 0 ? memberRating : 0 ;
2009-06-18 11:33:32 -05:00
if ( plr )
plr -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + ( slot * 6 ) + 5 , personal_rating );
2009-06-18 16:51:32 -05:00
//sLog.outArena("Modify personal rating for player %s: personal rating %u, mod %d, rating %d", plr->GetName(), personal_rating, mod, rating);
2009-06-18 11:33:32 -05:00
}
2008-10-02 16:23:55 -05:00
ArenaTeam :: ArenaTeam ()
{
2008-11-30 12:47:26 -06:00
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 ;
2009-06-17 18:19:08 -05:00
stats . rating = ARENA_NEW_TEAM_RATING ;
2008-11-30 12:47:26 -06:00
stats . wins_week = 0 ;
stats . wins_season = 0 ;
2008-10-02 16:23:55 -05:00
}
ArenaTeam ::~ ArenaTeam ()
{
}
2008-12-19 16:05:13 -06:00
bool ArenaTeam :: Create ( uint64 captainGuid , uint32 type , std :: string ArenaTeamName )
2008-10-02 16:23:55 -05:00
{
if ( ! objmgr . GetPlayer ( captainGuid )) // player not exist
return false ;
if ( objmgr . GetArenaTeamByName ( ArenaTeamName )) // arena team with this name already exist
return false ;
2008-10-05 08:48:32 -05:00
sLog . outDebug ( "GUILD: creating arena team %s to leader: %u" , ArenaTeamName . c_str (), GUID_LOPART ( captainGuid ));
2008-10-02 16:23:55 -05:00
CaptainGuid = captainGuid ;
Name = ArenaTeamName ;
Type = type ;
2008-12-19 16:05:13 -06:00
Id = objmgr . GenerateArenaTeamId ();
2008-10-02 16:23:55 -05:00
// 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 ( "INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) "
"VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')" ,
2008-12-19 16:05:13 -06:00
Id , ArenaTeamName . c_str (), GUID_LOPART ( CaptainGuid ), Type , BackgroundColor , EmblemStyle , EmblemColor , BorderStyle , BorderColor );
2008-10-02 16:23:55 -05:00
CharacterDatabase . PExecute ( "INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES "
2008-12-19 16:05:13 -06:00
"('%u', '%u', '%u', '%u', '%u', '%u', '%u')" , Id , stats . rating , stats . games_week , stats . wins_week , stats . games_season , stats . wins_season , stats . rank );
2008-10-02 16:23:55 -05:00
CharacterDatabase . CommitTransaction ();
AddMember ( CaptainGuid );
2009-06-01 20:44:23 +02:00
sLog . outArena ( "New ArenaTeam created [Id: %u] [Type: %u] [Captain GUID: %u]" , GetId (), GetType (), GetCaptain ());
2008-10-02 16:23:55 -05:00
return true ;
}
2008-12-19 16:05:13 -06:00
bool ArenaTeam :: AddMember ( const uint64 & PlayerGuid )
2008-10-02 16:23:55 -05:00
{
std :: string plName ;
uint8 plClass ;
2008-11-10 09:04:23 -06:00
// arena team is full (can't have more than type * 2 players!)
2008-10-02 16:23:55 -05:00
if ( GetMembersSize () >= GetType () * 2 )
return false ;
Player * pl = objmgr . GetPlayer ( PlayerGuid );
if ( pl )
{
2008-11-16 18:44:17 +01:00
if ( pl -> GetArenaTeamId ( GetSlot ()))
2008-11-10 09:04:23 -06:00
{
sLog . outError ( "Arena::AddMember() : player already in this sized team" );
return false ;
}
2008-10-02 16:23:55 -05:00
plClass = ( uint8 ) pl -> getClass ();
2008-11-10 09:04:23 -06:00
plName = pl -> GetName ();
2008-10-02 16:23:55 -05:00
}
else
{
2008-11-10 09:04:23 -06:00
// 0 1
QueryResult * result = CharacterDatabase . PQuery ( "SELECT name, class FROM characters WHERE guid='%u'" , GUID_LOPART ( PlayerGuid ));
2008-10-02 16:23:55 -05:00
if ( ! result )
return false ;
2008-11-10 09:04:23 -06:00
plName = ( * result )[ 0 ]. GetCppString ();
plClass = ( * result )[ 1 ]. GetUInt8 ();
2008-10-02 16:23:55 -05:00
delete result ;
2008-11-10 09:04:23 -06:00
// check if player already in arenateam of that size
if ( Player :: GetArenaTeamIdFromDB ( PlayerGuid , GetType ()) != 0 )
{
sLog . outError ( "Arena::AddMember() : player already in this sized team" );
return false ;
}
2008-10-02 16:23:55 -05:00
}
2008-11-10 09:04:23 -06:00
// remove all player signs from another petitions
// this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity
Player :: RemovePetitionsAndSigns ( PlayerGuid , GetType ());
2008-10-02 16:23:55 -05:00
ArenaTeamMember newmember ;
2008-11-30 12:47:26 -06:00
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 ;
2009-06-17 18:19:08 -05:00
newmember . personal_rating = AREAN_NEW_PERSONAL_RATING ;
2008-10-02 16:23:55 -05:00
members . push_back ( newmember );
2008-12-19 16:05:13 -06:00
CharacterDatabase . PExecute ( "INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')" , Id , GUID_LOPART ( newmember . guid ), newmember . personal_rating );
2008-10-02 16:23:55 -05:00
if ( pl )
{
pl -> SetInArenaTeam ( Id , GetSlot ());
pl -> SetArenaTeamIdInvited ( 0 );
2008-12-19 16:05:13 -06:00
pl -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + ( GetSlot () * 6 ) + 5 , newmember . personal_rating );
2008-10-02 16:23:55 -05:00
2008-11-30 12:47:26 -06:00
// hide promote/remove buttons
if ( CaptainGuid != PlayerGuid )
2008-12-19 16:05:13 -06:00
pl -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + ( GetSlot () * 6 ) + 1 , 1 );
2009-06-07 10:23:50 -05:00
sLog . outArena ( "Player: %s [GUID: %u] joined arena team type: %u [Id: %u]." , pl -> GetName (), pl -> GetGUIDLow (), GetType (), GetId ());
2008-11-30 12:47:26 -06:00
}
2008-10-02 16:23:55 -05:00
return true ;
}
bool ArenaTeam :: LoadArenaTeamFromDB ( uint32 ArenaTeamId )
{
QueryResult * result = CharacterDatabase . PQuery ( "SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'" , ArenaTeamId );
if ( ! result )
return false ;
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 ();
delete result ;
2008-10-05 08:48:32 -05:00
// only load here, so additional checks can be made
LoadStatsFromDB ( ArenaTeamId );
LoadMembersFromDB ( ArenaTeamId );
2008-12-19 16:05:13 -06:00
if ( Empty ())
2008-10-05 08:48:32 -05:00
{
// arena team is empty, delete from db
CharacterDatabase . BeginTransaction ();
CharacterDatabase . PExecute ( "DELETE FROM arena_team WHERE arenateamid = '%u'" , ArenaTeamId );
CharacterDatabase . PExecute ( "DELETE FROM arena_team_member WHERE arenateamid = '%u'" , ArenaTeamId );
CharacterDatabase . PExecute ( "DELETE FROM arena_team_stats WHERE arenateamid = '%u'" , ArenaTeamId );
CharacterDatabase . CommitTransaction ();
return false ;
}
2008-10-02 16:23:55 -05:00
return true ;
}
void ArenaTeam :: LoadStatsFromDB ( uint32 ArenaTeamId )
{
// 0 1 2 3 4 5
QueryResult * result = CharacterDatabase . PQuery ( "SELECT rating,games,wins,played,wins2,rank FROM arena_team_stats WHERE arenateamid = '%u'" , ArenaTeamId );
if ( ! result )
return ;
Field * fields = result -> Fetch ();
2008-11-30 12:47:26 -06:00
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 ();
2008-10-02 16:23:55 -05:00
delete result ;
}
void ArenaTeam :: LoadMembersFromDB ( uint32 ArenaTeamId )
{
2008-12-19 16:05:13 -06:00
// 0 1 2 3 4 5 6 7
QueryResult * result = CharacterDatabase . PQuery ( "SELECT member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class "
"FROM arena_team_member member "
"INNER JOIN characters chars on member.guid = chars.guid "
"WHERE member.arenateamid = '%u'" , ArenaTeamId );
2008-10-02 16:23:55 -05:00
if ( ! result )
return ;
do
{
2008-12-19 16:05:13 -06:00
Field * fields = result -> Fetch ();
2008-10-02 16:23:55 -05:00
ArenaTeamMember newmember ;
newmember . guid = MAKE_NEW_GUID ( fields [ 0 ]. GetUInt32 (), 0 , HIGHGUID_PLAYER );
2008-11-30 12:47:26 -06:00
newmember . games_week = fields [ 1 ]. GetUInt32 ();
newmember . wins_week = fields [ 2 ]. GetUInt32 ();
newmember . games_season = fields [ 3 ]. GetUInt32 ();
newmember . wins_season = fields [ 4 ]. GetUInt32 ();
2008-12-19 16:05:13 -06:00
newmember . personal_rating = fields [ 5 ]. GetUInt32 ();
newmember . name = fields [ 6 ]. GetCppString ();
newmember . Class = fields [ 7 ]. GetUInt8 ();
2008-10-02 16:23:55 -05:00
members . push_back ( newmember );
} while ( result -> NextRow () );
delete result ;
}
2008-12-19 16:05:13 -06:00
void ArenaTeam :: SetCaptain ( const uint64 & guid )
2008-10-02 16:23:55 -05:00
{
// disable remove/promote buttons
Player * oldcaptain = objmgr . GetPlayer ( GetCaptain ());
if ( oldcaptain )
oldcaptain -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + ( GetSlot () * 6 ), 1 );
// set new captain
CaptainGuid = guid ;
// update database
CharacterDatabase . PExecute ( "UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'" , GUID_LOPART ( guid ), Id );
// enable remove/promote buttons
Player * newcaptain = objmgr . GetPlayer ( guid );
if ( newcaptain )
2009-06-01 20:44:23 +02:00
{
2008-10-02 16:23:55 -05:00
newcaptain -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + ( GetSlot () * 6 ), 0 );
2009-06-07 10:23:50 -05:00
sLog . outArena ( "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u]." , oldcaptain -> GetName (), oldcaptain -> GetGUIDLow (), newcaptain -> GetName (), newcaptain -> GetGUID (), GetId (), GetType ());
2009-06-01 20:44:23 +02:00
}
2008-10-02 16:23:55 -05:00
}
void ArenaTeam :: DelMember ( uint64 guid )
{
2008-12-19 16:05:13 -06:00
for ( MemberList :: iterator itr = members . begin (); itr != members . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
if ( itr -> guid == guid )
{
members . erase ( itr );
break ;
}
}
Player * player = objmgr . GetPlayer ( guid );
2008-12-19 16:05:13 -06:00
2008-10-02 16:23:55 -05:00
if ( player )
{
player -> SetInArenaTeam ( 0 , GetSlot ());
player -> GetSession () -> SendArenaTeamCommandResult ( ERR_ARENA_TEAM_QUIT_S , GetName (), "" , 0 );
2008-10-05 08:48:32 -05:00
// delete all info regarding this team
2009-06-18 17:21:25 +02:00
for ( uint8 i = 0 ; i < 6 ; ++ i )
2008-10-05 08:48:32 -05:00
{
player -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + ( GetSlot () * 6 ) + i , 0 );
}
2009-06-07 10:23:50 -05:00
sLog . outArena ( "Player: %s [GUID: %u] left arena team type: %u [Id: %u]." , player -> GetName (), player -> GetGUIDLow (), GetType (), GetId ());
2008-10-02 16:23:55 -05:00
}
2008-10-05 08:48:32 -05:00
CharacterDatabase . PExecute ( "DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'" , GetId (), GUID_LOPART ( guid ));
2008-10-02 16:23:55 -05:00
}
void ArenaTeam :: Disband ( WorldSession * session )
{
// event
WorldPacket data ;
session -> BuildArenaTeamEventPacket ( & data , ERR_ARENA_TEAM_DISBANDED_S , 2 , session -> GetPlayerName (), GetName (), "" );
BroadcastPacket ( & data );
2008-12-19 16:05:13 -06:00
while ( ! members . empty ())
2008-10-02 16:23:55 -05:00
{
2008-12-19 16:05:13 -06:00
// Removing from members is done in DelMember.
DelMember ( members . front (). guid );
2008-10-02 16:23:55 -05:00
}
2009-06-01 20:44:23 +02:00
if ( Player * player = session -> GetPlayer ())
2009-06-07 10:23:50 -05:00
sLog . outArena ( "Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u]." , player -> GetName (), player -> GetGUIDLow (), GetType (), GetId ());
2009-06-01 20:44:23 +02:00
2008-10-02 16:23:55 -05:00
CharacterDatabase . BeginTransaction ();
CharacterDatabase . PExecute ( "DELETE FROM arena_team WHERE arenateamid = '%u'" , Id );
2008-12-19 16:05:13 -06:00
CharacterDatabase . PExecute ( "DELETE FROM arena_team_member WHERE arenateamid = '%u'" , Id ); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member
2008-10-02 16:23:55 -05:00
CharacterDatabase . PExecute ( "DELETE FROM arena_team_stats WHERE arenateamid = '%u'" , Id );
CharacterDatabase . CommitTransaction ();
2009-02-15 12:14:14 -06:00
objmgr . RemoveArenaTeam ( Id );
2008-10-02 16:23:55 -05:00
}
void ArenaTeam :: Roster ( WorldSession * session )
{
Player * pl = NULL ;
2009-01-30 19:22:49 -06:00
uint8 unk308 = 0 ;
2008-10-02 16:23:55 -05:00
WorldPacket data ( SMSG_ARENA_TEAM_ROSTER , 100 );
data << uint32 ( GetId ()); // arena team id
2009-01-30 19:22:49 -06:00
data << uint8 ( unk308 ); // 308 unknown value but affect packet structure
2008-10-02 16:23:55 -05:00
data << uint32 ( GetMembersSize ()); // members count
data << uint32 ( GetType ()); // arena team type?
2009-02-15 12:14:14 -06:00
for ( MemberList :: const_iterator itr = members . begin (); itr != members . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
pl = objmgr . GetPlayer ( itr -> guid );
2008-12-19 16:05:13 -06:00
2009-01-30 19:22:49 -06:00
data << uint64 ( itr -> guid ); // guid
data << uint8 (( pl ? 1 : 0 )); // online flag
data << itr -> name ; // member name
2008-12-19 16:05:13 -06:00
data << uint32 (( itr -> guid == GetCaptain () ? 0 : 1 )); // captain flag 0 captain 1 member
2009-01-30 19:22:49 -06:00
data << uint8 (( pl ? pl -> getLevel () : 0 )); // unknown, level?
data << uint8 ( itr -> Class ); // class
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
if ( unk308 )
{
data << float ( 0.0 ); // 308 unk
data << float ( 0.0 ); // 308 unk
}
2008-10-02 16:23:55 -05:00
}
2009-01-30 19:22:49 -06:00
2008-10-02 16:23:55 -05:00
session -> SendPacket ( & data );
sLog . outDebug ( "WORLD: Sent SMSG_ARENA_TEAM_ROSTER" );
}
void ArenaTeam :: Query ( WorldSession * session )
{
WorldPacket data ( SMSG_ARENA_TEAM_QUERY_RESPONSE , 4 * 7 + GetName (). size () + 1 );
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
session -> SendPacket ( & data );
sLog . outDebug ( "WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE" );
}
void ArenaTeam :: Stats ( WorldSession * session )
{
WorldPacket data ( SMSG_ARENA_TEAM_STATS , 4 * 7 );
data << uint32 ( GetId ()); // arena team id
data << uint32 ( stats . rating ); // rating
2008-11-30 12:47:26 -06:00
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
2008-10-02 16:23:55 -05:00
data << uint32 ( stats . rank ); // rank
session -> SendPacket ( & data );
}
2008-10-05 08:48:32 -05:00
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!)
2009-02-15 12:14:14 -06:00
for ( MemberList :: const_iterator itr = members . begin (); itr != members . end (); ++ itr )
2008-10-05 08:48:32 -05:00
{
2008-12-19 16:05:13 -06:00
Player * plr = objmgr . GetPlayer ( itr -> guid );
2008-10-05 08:48:32 -05:00
if ( plr )
Stats ( plr -> GetSession ());
}
}
2008-10-02 16:23:55 -05:00
void ArenaTeam :: InspectStats ( WorldSession * session , uint64 guid )
{
2008-11-30 12:47:26 -06:00
ArenaTeamMember * member = GetMember ( guid );
if ( ! member )
return ;
2008-10-02 16:23:55 -05:00
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
2008-11-30 12:47:26 -06:00
data << uint32 ( stats . games_season ); // season played
data << uint32 ( stats . wins_season ); // season wins
2008-12-19 16:05:13 -06:00
data << uint32 ( member -> games_season ); // played (count of all games, that the inspected member participated...)
data << uint32 ( member -> personal_rating ); // personal rating
2008-10-02 16:23:55 -05:00
session -> SendPacket ( & data );
}
void ArenaTeam :: SetEmblem ( uint32 backgroundColor , uint32 emblemStyle , uint32 emblemColor , uint32 borderStyle , uint32 borderColor )
{
BackgroundColor = backgroundColor ;
EmblemStyle = emblemStyle ;
EmblemColor = emblemColor ;
BorderStyle = borderStyle ;
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 );
}
void ArenaTeam :: SetStats ( uint32 stat_type , uint32 value )
{
switch ( stat_type )
{
case STAT_TYPE_RATING :
stats . rating = value ;
CharacterDatabase . PExecute ( "UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'" , value , GetId ());
break ;
2008-11-30 12:47:26 -06:00
case STAT_TYPE_GAMES_WEEK :
stats . games_week = value ;
2008-10-02 16:23:55 -05:00
CharacterDatabase . PExecute ( "UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'" , value , GetId ());
break ;
2008-11-30 12:47:26 -06:00
case STAT_TYPE_WINS_WEEK :
stats . wins_week = value ;
2008-10-02 16:23:55 -05:00
CharacterDatabase . PExecute ( "UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'" , value , GetId ());
break ;
2008-11-30 12:47:26 -06:00
case STAT_TYPE_GAMES_SEASON :
stats . games_season = value ;
2008-10-02 16:23:55 -05:00
CharacterDatabase . PExecute ( "UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'" , value , GetId ());
break ;
2008-11-30 12:47:26 -06:00
case STAT_TYPE_WINS_SEASON :
stats . wins_season = value ;
2008-10-02 16:23:55 -05:00
CharacterDatabase . PExecute ( "UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'" , value , GetId ());
break ;
case STAT_TYPE_RANK :
stats . rank = value ;
CharacterDatabase . PExecute ( "UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'" , value , GetId ());
break ;
default :
sLog . outDebug ( "unknown stat type in ArenaTeam::SetStats() %u" , stat_type );
break ;
}
}
void ArenaTeam :: BroadcastPacket ( WorldPacket * packet )
{
2009-02-15 12:14:14 -06:00
for ( MemberList :: const_iterator itr = members . begin (); itr != members . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
Player * player = objmgr . GetPlayer ( itr -> guid );
if ( player )
player -> GetSession () -> SendPacket ( packet );
}
}
uint8 ArenaTeam :: GetSlotByType ( uint32 type )
{
switch ( type )
{
case ARENA_TEAM_2v2 : return 0 ;
case ARENA_TEAM_3v3 : return 1 ;
case ARENA_TEAM_5v5 : return 2 ;
default :
break ;
}
2008-12-19 16:05:13 -06:00
sLog . outError ( "FATAL: Unknown arena team type %u for some arena team" , type );
2008-10-02 16:23:55 -05:00
return 0xFF ;
}
2008-12-19 16:05:13 -06:00
bool ArenaTeam :: HaveMember ( const uint64 & guid ) const
2008-10-02 16:23:55 -05:00
{
for ( MemberList :: const_iterator itr = members . begin (); itr != members . end (); ++ itr )
2008-12-19 16:05:13 -06:00
if ( itr -> guid == guid )
2008-10-02 16:23:55 -05:00
return true ;
return false ;
}
2008-10-05 08:48:32 -05:00
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 ;
if ( rating <= 1500 )
2009-07-14 00:04:15 +02:00
// points = (float)1500 * 0.22f + 14.0f;
points = 344f ; // 3.1 change - teams with rating below 1500 get arena points for 1500 rating
2008-10-05 08:48:32 -05:00
else
points = 1511.26f / ( 1.0f + 1639.28f * exp ( - 0.00412f * ( float ) rating ));
// type penalties for <5v5 teams
if ( Type == ARENA_TEAM_2v2 )
points *= 0.76f ;
else if ( Type == ARENA_TEAM_3v3 )
points *= 0.88f ;
return ( uint32 ) points ;
}
2008-12-19 16:05:13 -06:00
float ArenaTeam :: GetChanceAgainst ( uint32 own_rating , uint32 enemy_rating )
2008-10-05 08:48:32 -05:00
{
// returns the chance to win against a team with the given rating, used in the rating adjustment calculation
// ELO system
2008-12-19 16:05:13 -06:00
return 1.0f / ( 1.0f + exp ( log ( 10.0f ) * ( float )(( float ) enemy_rating - ( float ) own_rating ) / 400.0f ));
2008-10-05 08:48:32 -05:00
}
2008-12-19 16:05:13 -06:00
int32 ArenaTeam :: WonAgainst ( uint32 againstRating )
2008-10-05 08:48:32 -05:00
{
2008-12-19 16:05:13 -06:00
// called when the team has won
//'chance' calculation - to beat the opponent
float chance = GetChanceAgainst ( stats . rating , againstRating );
2008-10-05 08:48:32 -05:00
// calculate the rating modification (ELO system with k=32)
int32 mod = ( int32 ) floor ( 32.0f * ( 1.0f - chance ));
// modify the team stats accordingly
2009-06-18 16:51:32 -05:00
int32 newTeamRating = ( int32 ) stats . rating + mod ;
stats . rating = newTeamRating > 0 ? newTeamRating : 0 ;
2008-11-30 12:47:26 -06:00
stats . games_week += 1 ;
stats . wins_week += 1 ;
stats . games_season += 1 ;
stats . wins_season += 1 ;
2008-12-19 16:05:13 -06:00
//update team's rank
stats . rank = 1 ;
2009-04-29 00:26:07 -05:00
ObjectMgr :: ArenaTeamMap :: const_iterator i = objmgr . GetArenaTeamMapBegin ();
2008-12-19 16:05:13 -06:00
for ( ; i != objmgr . GetArenaTeamMapEnd (); ++ i )
2008-10-05 08:48:32 -05:00
{
2008-12-19 16:05:13 -06:00
if ( i -> second -> GetType () == this -> Type && i -> second -> GetStats (). rating > stats . rating )
++ stats . rank ;
2008-10-05 08:48:32 -05:00
}
2008-12-19 16:05:13 -06:00
2008-10-05 08:48:32 -05:00
// return the rating change, used to display it on the results screen
return mod ;
}
2008-12-19 16:05:13 -06:00
int32 ArenaTeam :: LostAgainst ( uint32 againstRating )
2008-10-05 08:48:32 -05:00
{
2008-12-19 16:05:13 -06:00
// called when the team has lost
//'chance' calculation - to loose to the opponent
float chance = GetChanceAgainst ( stats . rating , againstRating );
2008-10-05 08:48:32 -05:00
// calculate the rating modification (ELO system with k=32)
int32 mod = ( int32 ) ceil ( 32.0f * ( 0.0f - chance ));
// modify the team stats accordingly
2009-06-18 16:51:32 -05:00
int32 newTeamRating = ( int32 ) stats . rating + mod ;
stats . rating = newTeamRating > 0 ? newTeamRating : 0 ;
2008-11-30 12:47:26 -06:00
stats . games_week += 1 ;
stats . games_season += 1 ;
2008-12-19 16:05:13 -06:00
//update team's rank
stats . rank = 1 ;
2009-04-29 00:26:07 -05:00
ObjectMgr :: ArenaTeamMap :: const_iterator i = objmgr . GetArenaTeamMapBegin ();
2008-12-19 16:05:13 -06:00
for ( ; i != objmgr . GetArenaTeamMapEnd (); ++ i )
2008-10-05 08:48:32 -05:00
{
2008-12-19 16:05:13 -06:00
if ( i -> second -> GetType () == this -> Type && i -> second -> GetStats (). rating > stats . rating )
++ stats . rank ;
2008-10-05 08:48:32 -05:00
}
2008-12-19 16:05:13 -06:00
// return the rating change, used to display it on the results screen
2008-10-05 08:48:32 -05:00
return mod ;
}
2008-12-19 16:05:13 -06:00
void ArenaTeam :: MemberLost ( Player * plr , uint32 againstRating )
2008-10-05 08:48:32 -05:00
{
// called for each participant of a match after losing
for ( MemberList :: iterator itr = members . begin (); itr != members . end (); ++ itr )
{
if ( itr -> guid == plr -> GetGUID ())
{
// update personal rating
2008-12-19 16:05:13 -06:00
float chance = GetChanceAgainst ( itr -> personal_rating , againstRating );
2008-10-05 08:48:32 -05:00
int32 mod = ( int32 ) ceil ( 32.0f * ( 0.0f - chance ));
2008-12-19 16:05:13 -06:00
itr -> ModifyPersonalRating ( plr , mod , GetSlot ());
2008-10-05 08:48:32 -05:00
// update personal played stats
2008-11-30 12:47:26 -06:00
itr -> games_week += 1 ;
itr -> games_season += 1 ;
2008-10-05 08:48:32 -05:00
// update the unit fields
2008-11-30 12:47:26 -06:00
plr -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot () + 2 , itr -> games_week );
plr -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot () + 3 , itr -> games_season );
2008-10-05 08:48:32 -05:00
return ;
}
}
}
2009-03-09 17:07:40 -06:00
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 )
{
if ( itr -> guid == guid )
{
// update personal rating
float chance = GetChanceAgainst ( itr -> personal_rating , againstRating );
int32 mod = ( int32 ) ceil ( 32.0f * ( 0.0f - chance ));
if ( int32 ( itr -> personal_rating ) + mod < 0 )
itr -> personal_rating = 0 ;
else
itr -> personal_rating += mod ;
// update personal played stats
itr -> games_week += 1 ;
itr -> games_season += 1 ;
return ;
}
}
}
2008-12-19 16:05:13 -06:00
void ArenaTeam :: MemberWon ( Player * plr , uint32 againstRating )
2008-10-05 08:48:32 -05:00
{
// called for each participant after winning a match
for ( MemberList :: iterator itr = members . begin (); itr != members . end (); ++ itr )
{
if ( itr -> guid == plr -> GetGUID ())
{
// update personal rating
2008-12-19 16:05:13 -06:00
float chance = GetChanceAgainst ( itr -> personal_rating , againstRating );
2008-10-05 08:48:32 -05:00
int32 mod = ( int32 ) floor ( 32.0f * ( 1.0f - chance ));
2008-12-19 16:05:13 -06:00
itr -> ModifyPersonalRating ( plr , mod , GetSlot ());
2008-10-05 08:48:32 -05:00
// update personal stats
2008-11-30 12:47:26 -06:00
itr -> games_week += 1 ;
itr -> games_season += 1 ;
itr -> wins_season += 1 ;
itr -> wins_week += 1 ;
2008-10-05 08:48:32 -05:00
// update unit fields
2008-11-30 12:47:26 -06:00
plr -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot () + 2 , itr -> games_week );
plr -> SetUInt32Value ( PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot () + 3 , itr -> games_season );
2008-10-05 08:48:32 -05:00
return ;
}
}
}
2008-12-19 16:05:13 -06:00
void ArenaTeam :: UpdateArenaPointsHelper ( std :: map < uint32 , uint32 >& PlayerPoints )
2008-10-05 08:48:32 -05:00
{
// 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
2008-12-19 16:05:13 -06:00
if ( stats . games_week < 10 )
2008-10-05 08:48:32 -05:00
return ;
// to get points, a player has to participate in at least 30% of the matches
2008-12-19 16:05:13 -06:00
uint32 min_plays = ( uint32 ) ceil ( stats . games_week * 0.3 );
2009-04-29 00:26:07 -05:00
for ( MemberList :: const_iterator itr = members . begin (); itr != members . end (); ++ itr )
2008-10-05 08:48:32 -05:00
{
// the player participated in enough games, update his points
2008-12-19 16:05:13 -06:00
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);
std :: map < uint32 , uint32 >:: iterator plr_itr = PlayerPoints . find ( GUID_LOPART ( itr -> guid ));
if ( plr_itr != PlayerPoints . end ())
2008-10-05 08:48:32 -05:00
{
2008-12-19 16:05:13 -06:00
//check if there is already more points
if ( plr_itr -> second < points_to_add )
PlayerPoints [ GUID_LOPART ( itr -> guid )] = points_to_add ;
2008-10-05 08:48:32 -05:00
}
else
2008-12-19 16:05:13 -06:00
PlayerPoints [ GUID_LOPART ( itr -> guid )] = points_to_add ;
2008-10-05 08:48:32 -05:00
}
}
void ArenaTeam :: SaveToDB ()
{
// save team and member stats to db
2008-12-19 16:05:13 -06:00
// called after a match has ended, or when calculating arena_points
2009-02-24 11:14:28 -06:00
CharacterDatabase . BeginTransaction ();
2008-11-30 12:47:26 -06:00
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 ());
2009-04-29 00:26:07 -05:00
for ( MemberList :: const_iterator itr = members . begin (); itr != members . end (); ++ itr )
2008-10-05 08:48:32 -05:00
{
2009-02-24 11:14:28 -06:00
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 ));
2008-10-05 08:48:32 -05:00
}
2009-02-24 11:14:28 -06:00
CharacterDatabase . CommitTransaction ();
2008-10-05 08:48:32 -05:00
}
void ArenaTeam :: FinishWeek ()
{
2008-11-30 12:47:26 -06:00
stats . games_week = 0 ; // played this week
stats . wins_week = 0 ; // wins this week
2008-10-05 08:48:32 -05:00
for ( MemberList :: iterator itr = members . begin (); itr != members . end (); ++ itr )
{
2008-11-30 12:47:26 -06:00
itr -> games_week = 0 ;
itr -> wins_week = 0 ;
2008-10-05 08:48:32 -05:00
}
}
2009-02-09 22:08:06 -06:00
bool ArenaTeam :: IsFighting () const
{
for ( MemberList :: const_iterator itr = members . begin (); itr != members . end (); ++ itr )
{
if ( Player * p = objmgr . GetPlayer ( itr -> guid ))
{
if ( p -> GetMap () -> IsBattleArena ())
return true ;
}
}
return false ;
}
2008-10-02 16:23:55 -05:00
/*
arenateam fields (id from 2.3.3 client):
1414 - arena team id 2v2
1415 - 0=captain, 1=member
2008-10-05 08:48:32 -05:00
1416 - played this week
1417 - played this season
2008-12-19 16:05:13 -06:00
1418 - unk - rank?
2008-10-05 08:48:32 -05:00
1419 - personal arena rating
2008-10-02 16:23:55 -05:00
1420 - arena team id 3v3
1421 - 0=captain, 1=member
2008-10-05 08:48:32 -05:00
1422 - played this week
1423 - played this season
2008-12-19 16:05:13 -06:00
1424 - unk - rank?
2008-10-05 08:48:32 -05:00
1425 - personal arena rating
2008-10-02 16:23:55 -05:00
1426 - arena team id 5v5
1427 - 0=captain, 1=member
2008-10-05 08:48:32 -05:00
1428 - played this week
1429 - played this season
2008-12-19 16:05:13 -06:00
1430 - unk - rank?
2008-10-05 08:48:32 -05:00
1431 - personal arena rating
2008-10-02 16:23:55 -05:00
*/
2009-02-17 20:07:49 -06:00