2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "WorldPacket.h"
20 #include "ObjectMgr.h"
21 #include "ObjectDefines.h"
22 #include "ArenaTeam.h"
25 ArenaTeam::ArenaTeam()
31 m_BackgroundColor
= 0; // background
32 m_EmblemStyle
= 0; // icon
33 m_EmblemColor
= 0; // icon color
34 m_BorderStyle
= 0; // border
35 m_BorderColor
= 0; // border color
36 m_stats
.games_week
= 0;
37 m_stats
.games_season
= 0;
39 if (sWorld
.getConfig(CONFIG_ARENA_SEASON_ID
) >= 6)
42 m_stats
.rating
= 1500;
43 m_stats
.wins_week
= 0;
44 m_stats
.wins_season
= 0;
47 ArenaTeam::~ArenaTeam()
52 bool ArenaTeam::Create(uint64 captainGuid
, uint32 type
, std::string ArenaTeamName
)
54 if(!sObjectMgr
.GetPlayer(captainGuid
)) // player not exist
56 if(sObjectMgr
.GetArenaTeamByName(ArenaTeamName
)) // arena team with this name already exist
59 sLog
.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName
.c_str(), GUID_LOPART(captainGuid
));
61 m_CaptainGuid
= captainGuid
;
62 m_Name
= ArenaTeamName
;
65 m_TeamId
= sObjectMgr
.GenerateArenaTeamId();
67 // ArenaTeamName already assigned to ArenaTeam::name, use it to encode string for DB
68 CharacterDatabase
.escape_string(ArenaTeamName
);
70 CharacterDatabase
.BeginTransaction();
71 // CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", m_TeamId); - MAX(arenateam)+1 not exist
72 CharacterDatabase
.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", m_TeamId
);
73 CharacterDatabase
.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) "
74 "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')",
75 m_TeamId
, ArenaTeamName
.c_str(), GUID_LOPART(m_CaptainGuid
), m_Type
, m_BackgroundColor
, m_EmblemStyle
, m_EmblemColor
, m_BorderStyle
, m_BorderColor
);
76 CharacterDatabase
.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES "
77 "('%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
);
79 CharacterDatabase
.CommitTransaction();
81 AddMember(m_CaptainGuid
);
85 bool ArenaTeam::AddMember(const uint64
& PlayerGuid
)
90 // arena team is full (can't have more than type * 2 players!)
91 if(GetMembersSize() >= GetType() * 2)
94 Player
*pl
= sObjectMgr
.GetPlayer(PlayerGuid
);
97 if(pl
->GetArenaTeamId(GetSlot()))
99 sLog
.outError("Arena::AddMember() : player already in this sized team");
103 plClass
= pl
->getClass();
104 plName
= pl
->GetName();
109 QueryResult
*result
= CharacterDatabase
.PQuery("SELECT name, class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid
));
113 plName
= (*result
)[0].GetCppString();
114 plClass
= (*result
)[1].GetUInt8();
117 // check if player already in arenateam of that size
118 if(Player::GetArenaTeamIdFromDB(PlayerGuid
, GetType()) != 0)
120 sLog
.outError("Arena::AddMember() : player already in this sized team");
125 // remove all player signs from another petitions
126 // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity
127 Player::RemovePetitionsAndSigns(PlayerGuid
, GetType());
129 ArenaTeamMember newmember
;
130 newmember
.name
= plName
;
131 newmember
.guid
= PlayerGuid
;
132 newmember
.Class
= plClass
;
133 newmember
.games_season
= 0;
134 newmember
.games_week
= 0;
135 newmember
.wins_season
= 0;
136 newmember
.wins_week
= 0;
137 if (sWorld
.getConfig(CONFIG_ARENA_SEASON_ID
) >= 6)
139 if (m_stats
.rating
< 1000)
140 newmember
.personal_rating
= 0;
142 newmember
.personal_rating
= 1000;
146 newmember
.personal_rating
= 1500;
148 m_members
.push_back(newmember
);
150 CharacterDatabase
.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", m_TeamId
, GUID_LOPART(newmember
.guid
), newmember
.personal_rating
);
154 pl
->SetInArenaTeam(m_TeamId
, GetSlot(), GetType());
155 pl
->SetArenaTeamIdInvited(0);
156 pl
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_PERSONAL_RATING
, newmember
.personal_rating
);
158 // hide promote/remove buttons
159 if(m_CaptainGuid
!= PlayerGuid
)
160 pl
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_MEMBER
, 1);
165 bool ArenaTeam::LoadArenaTeamFromDB(QueryResult
*arenaTeamDataResult
)
167 if(!arenaTeamDataResult
)
170 Field
*fields
= arenaTeamDataResult
->Fetch();
172 m_TeamId
= fields
[0].GetUInt32();
173 m_Name
= fields
[1].GetCppString();
174 m_CaptainGuid
= MAKE_NEW_GUID(fields
[2].GetUInt32(), 0, HIGHGUID_PLAYER
);
175 m_Type
= fields
[3].GetUInt32();
176 m_BackgroundColor
= fields
[4].GetUInt32();
177 m_EmblemStyle
= fields
[5].GetUInt32();
178 m_EmblemColor
= fields
[6].GetUInt32();
179 m_BorderStyle
= fields
[7].GetUInt32();
180 m_BorderColor
= fields
[8].GetUInt32();
182 m_stats
.rating
= fields
[9].GetUInt32();
183 m_stats
.games_week
= fields
[10].GetUInt32();
184 m_stats
.wins_week
= fields
[11].GetUInt32();
185 m_stats
.games_season
= fields
[12].GetUInt32();
186 m_stats
.wins_season
= fields
[13].GetUInt32();
187 m_stats
.rank
= fields
[14].GetUInt32();
192 bool ArenaTeam::LoadMembersFromDB(QueryResult
*arenaTeamMembersResult
)
194 if(!arenaTeamMembersResult
)
197 bool captainPresentInTeam
= false;
201 Field
*fields
= arenaTeamMembersResult
->Fetch();
202 //prevent crash if db records are broken, when all members in result are already processed and current team hasn't got any members
205 uint32 arenaTeamId
= fields
[0].GetUInt32();
206 if (arenaTeamId
< m_TeamId
)
208 //there is in table arena_team_member record which doesn't have arenateamid in arena_team table, report error
209 sLog
.outErrorDb("ArenaTeam %u does not exist but it has record in arena_team_member table, deleting it!", arenaTeamId
);
210 CharacterDatabase
.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", arenaTeamId
);
214 if (arenaTeamId
> m_TeamId
)
215 //we loaded all members for this arena_team already, break cycle
218 ArenaTeamMember newmember
;
219 newmember
.guid
= MAKE_NEW_GUID(fields
[1].GetUInt32(), 0, HIGHGUID_PLAYER
);
220 newmember
.games_week
= fields
[2].GetUInt32();
221 newmember
.wins_week
= fields
[3].GetUInt32();
222 newmember
.games_season
= fields
[4].GetUInt32();
223 newmember
.wins_season
= fields
[5].GetUInt32();
224 newmember
.personal_rating
= fields
[6].GetUInt32();
225 newmember
.name
= fields
[7].GetCppString();
226 newmember
.Class
= fields
[8].GetUInt8();
228 //check if member exists in characters table
229 if (newmember
.name
.empty())
231 sLog
.outErrorDb("ArenaTeam %u has member with empty name - probably player %u doesn't exist, deleting him from memberlist!", arenaTeamId
, GUID_LOPART(newmember
.guid
));
232 this->DelMember(newmember
.guid
);
235 if (newmember
.guid
== GetCaptain())
236 captainPresentInTeam
= true;
238 m_members
.push_back(newmember
);
239 }while (arenaTeamMembersResult
->NextRow());
241 if(Empty() || !captainPresentInTeam
)
243 // arena team is empty or captain is not in team, delete from db
244 sLog
.outErrorDb("ArenaTeam %u does not have any members or its captain is not in team, disbanding it...", m_TeamId
);
251 void ArenaTeam::SetCaptain(const uint64
& guid
)
253 // disable remove/promote buttons
254 Player
*oldcaptain
= sObjectMgr
.GetPlayer(GetCaptain());
256 oldcaptain
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_MEMBER
, 1);
259 m_CaptainGuid
= guid
;
262 CharacterDatabase
.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid
), m_TeamId
);
264 // enable remove/promote buttons
265 Player
*newcaptain
= sObjectMgr
.GetPlayer(guid
);
267 newcaptain
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_MEMBER
, 0);
270 void ArenaTeam::DelMember(uint64 guid
)
272 for (MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
274 if (itr
->guid
== guid
)
276 m_members
.erase(itr
);
281 if(Player
*player
= sObjectMgr
.GetPlayer(guid
))
283 player
->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S
, GetName(), "", 0);
284 // delete all info regarding this team
285 for(int i
= 0; i
< ARENA_TEAM_END
; ++i
)
286 player
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + i
, 0);
289 CharacterDatabase
.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid
));
292 void ArenaTeam::Disband(WorldSession
*session
)
298 session
->BuildArenaTeamEventPacket(&data
, ERR_ARENA_TEAM_DISBANDED_S
, 2, session
->GetPlayerName(), GetName(), "");
299 BroadcastPacket(&data
);
302 while (!m_members
.empty())
304 // Removing from members is done in DelMember.
305 DelMember(m_members
.front().guid
);
308 CharacterDatabase
.BeginTransaction();
309 CharacterDatabase
.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", m_TeamId
);
310 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
311 CharacterDatabase
.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", m_TeamId
);
312 CharacterDatabase
.CommitTransaction();
313 sObjectMgr
.RemoveArenaTeam(m_TeamId
);
316 void ArenaTeam::Roster(WorldSession
*session
)
322 WorldPacket
data(SMSG_ARENA_TEAM_ROSTER
, 100);
323 data
<< uint32(GetId()); // team id
324 data
<< uint8(unk308
); // 308 unknown value but affect packet structure
325 data
<< uint32(GetMembersSize()); // members count
326 data
<< uint32(GetType()); // arena team type?
328 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
330 pl
= sObjectMgr
.GetPlayer(itr
->guid
);
332 data
<< uint64(itr
->guid
); // guid
333 data
<< uint8((pl
? 1 : 0)); // online flag
334 data
<< itr
->name
; // member name
335 data
<< uint32((itr
->guid
== GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
336 data
<< uint8((pl
? pl
->getLevel() : 0)); // unknown, level?
337 data
<< uint8(itr
->Class
); // class
338 data
<< uint32(itr
->games_week
); // played this week
339 data
<< uint32(itr
->wins_week
); // wins this week
340 data
<< uint32(itr
->games_season
); // played this season
341 data
<< uint32(itr
->wins_season
); // wins this season
342 data
<< uint32(itr
->personal_rating
); // personal rating
345 data
<< float(0.0); // 308 unk
346 data
<< float(0.0); // 308 unk
350 session
->SendPacket(&data
);
351 sLog
.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
354 void ArenaTeam::Query(WorldSession
*session
)
356 WorldPacket
data(SMSG_ARENA_TEAM_QUERY_RESPONSE
, 4*7+GetName().size()+1);
357 data
<< uint32(GetId()); // team id
358 data
<< GetName(); // team name
359 data
<< uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5)
360 data
<< uint32(m_BackgroundColor
); // background color
361 data
<< uint32(m_EmblemStyle
); // emblem style
362 data
<< uint32(m_EmblemColor
); // emblem color
363 data
<< uint32(m_BorderStyle
); // border style
364 data
<< uint32(m_BorderColor
); // border color
365 session
->SendPacket(&data
);
366 sLog
.outDebug("WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE");
369 void ArenaTeam::Stats(WorldSession
*session
)
371 WorldPacket
data(SMSG_ARENA_TEAM_STATS
, 4*7);
372 data
<< uint32(GetId()); // team id
373 data
<< uint32(m_stats
.rating
); // rating
374 data
<< uint32(m_stats
.games_week
); // games this week
375 data
<< uint32(m_stats
.wins_week
); // wins this week
376 data
<< uint32(m_stats
.games_season
); // played this season
377 data
<< uint32(m_stats
.wins_season
); // wins this season
378 data
<< uint32(m_stats
.rank
); // rank
379 session
->SendPacket(&data
);
382 void ArenaTeam::NotifyStatsChanged()
384 // this is called after a rated match ended
385 // updates arena team stats for every member of the team (not only the ones who participated!)
386 for(MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
388 Player
* plr
= sObjectMgr
.GetPlayer(itr
->guid
);
390 Stats(plr
->GetSession());
394 void ArenaTeam::InspectStats(WorldSession
*session
, uint64 guid
)
396 ArenaTeamMember
* member
= GetMember(guid
);
400 WorldPacket
data(MSG_INSPECT_ARENA_TEAMS
, 8+1+4*6);
401 data
<< uint64(guid
); // player guid
402 data
<< uint8(GetSlot()); // slot (0...2)
403 data
<< uint32(GetId()); // arena team id
404 data
<< uint32(m_stats
.rating
); // rating
405 data
<< uint32(m_stats
.games_season
); // season played
406 data
<< uint32(m_stats
.wins_season
); // season wins
407 data
<< uint32(member
->games_season
); // played (count of all games, that the inspected member participated...)
408 data
<< uint32(member
->personal_rating
); // personal rating
409 session
->SendPacket(&data
);
412 void ArenaTeam::SetEmblem(uint32 backgroundColor
, uint32 emblemStyle
, uint32 emblemColor
, uint32 borderStyle
, uint32 borderColor
)
414 m_BackgroundColor
= backgroundColor
;
415 m_EmblemStyle
= emblemStyle
;
416 m_EmblemColor
= emblemColor
;
417 m_BorderStyle
= borderStyle
;
418 m_BorderColor
= borderColor
;
420 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
);
423 void ArenaTeam::SetStats(uint32 stat_type
, uint32 value
)
427 case STAT_TYPE_RATING
:
428 m_stats
.rating
= value
;
429 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value
, GetId());
431 case STAT_TYPE_GAMES_WEEK
:
432 m_stats
.games_week
= value
;
433 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value
, GetId());
435 case STAT_TYPE_WINS_WEEK
:
436 m_stats
.wins_week
= value
;
437 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value
, GetId());
439 case STAT_TYPE_GAMES_SEASON
:
440 m_stats
.games_season
= value
;
441 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value
, GetId());
443 case STAT_TYPE_WINS_SEASON
:
444 m_stats
.wins_season
= value
;
445 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value
, GetId());
448 m_stats
.rank
= value
;
449 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'", value
, GetId());
452 sLog
.outDebug("unknown stat type in ArenaTeam::SetStats() %u", stat_type
);
457 void ArenaTeam::BroadcastPacket(WorldPacket
*packet
)
459 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
461 Player
*player
= sObjectMgr
.GetPlayer(itr
->guid
);
463 player
->GetSession()->SendPacket(packet
);
467 uint8
ArenaTeam::GetSlotByType( uint32 type
)
471 case ARENA_TEAM_2v2
: return 0;
472 case ARENA_TEAM_3v3
: return 1;
473 case ARENA_TEAM_5v5
: return 2;
477 sLog
.outError("FATAL: Unknown arena team type %u for some arena team", type
);
481 bool ArenaTeam::HaveMember( const uint64
& guid
) const
483 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
484 if(itr
->guid
== guid
)
490 uint32
ArenaTeam::GetPoints(uint32 MemberRating
)
492 // returns how many points would be awarded with this team type with this rating
495 uint32 rating
= MemberRating
+ 150 < m_stats
.rating
? MemberRating
: m_stats
.rating
;
498 points
= (float)rating
* 0.22f
+ 14.0f
;
500 points
= 1511.26f
/ (1.0f
+ 1639.28f
* exp(-0.00412f
* (float)rating
));
502 // type penalties for <5v5 teams
503 if(m_Type
== ARENA_TEAM_2v2
)
505 else if(m_Type
== ARENA_TEAM_3v3
)
508 return (uint32
) points
;
511 float ArenaTeam::GetChanceAgainst(uint32 own_rating
, uint32 enemy_rating
)
513 // returns the chance to win against a team with the given rating, used in the rating adjustment calculation
516 if (sWorld
.getConfig(CONFIG_ARENA_SEASON_ID
) >= 6)
517 if (enemy_rating
< 1000)
519 return 1.0f
/(1.0f
+exp(log(10.0f
)*(float)((float)enemy_rating
- (float)own_rating
)/400.0f
));
522 void ArenaTeam::FinishGame(int32 mod
)
524 if (int32(m_stats
.rating
) + mod
< 0)
527 m_stats
.rating
+= mod
;
529 m_stats
.games_week
+= 1;
530 m_stats
.games_season
+= 1;
531 // update team's rank
533 ObjectMgr::ArenaTeamMap::const_iterator i
= sObjectMgr
.GetArenaTeamMapBegin();
534 for ( ; i
!= sObjectMgr
.GetArenaTeamMapEnd(); ++i
)
536 if (i
->second
->GetType() == this->m_Type
&& i
->second
->GetStats().rating
> m_stats
.rating
)
541 int32
ArenaTeam::WonAgainst(uint32 againstRating
)
543 // called when the team has won
544 // 'chance' calculation - to beat the opponent
545 float chance
= GetChanceAgainst(m_stats
.rating
, againstRating
);
546 float K
= (m_stats
.rating
< 1000) ? 48.0f
: 32.0f
;
547 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
548 int32 mod
= (int32
)floor(K
* (1.0f
- chance
));
549 // modify the team stats accordingly
551 m_stats
.wins_week
+= 1;
552 m_stats
.wins_season
+= 1;
554 // return the rating change, used to display it on the results screen
558 int32
ArenaTeam::LostAgainst(uint32 againstRating
)
560 // called when the team has lost
561 //'chance' calculation - to loose to the opponent
562 float chance
= GetChanceAgainst(m_stats
.rating
, againstRating
);
563 float K
= (m_stats
.rating
< 1000) ? 48.0f
: 32.0f
;
564 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
565 int32 mod
= (int32
)ceil(K
* (0.0f
- chance
));
566 // modify the team stats accordingly
569 // return the rating change, used to display it on the results screen
573 void ArenaTeam::MemberLost(Player
* plr
, uint32 againstRating
)
575 // called for each participant of a match after losing
576 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
578 if(itr
->guid
== plr
->GetGUID())
580 // update personal rating
581 float chance
= GetChanceAgainst(itr
->personal_rating
, againstRating
);
582 float K
= (itr
->personal_rating
< 1000) ? 48.0f
: 32.0f
;
583 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
584 int32 mod
= (int32
)ceil(K
* (0.0f
- chance
));
585 itr
->ModifyPersonalRating(plr
, mod
, GetSlot());
586 // update personal played stats
587 itr
->games_week
+= 1;
588 itr
->games_season
+= 1;
589 // update the unit fields
590 plr
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_GAMES_WEEK
, itr
->games_week
);
591 plr
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_GAMES_SEASON
, itr
->games_season
);
597 void ArenaTeam::OfflineMemberLost(uint64 guid
, uint32 againstRating
)
599 // called for offline player after ending rated arena match!
600 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
602 if(itr
->guid
== guid
)
604 // update personal rating
605 float chance
= GetChanceAgainst(itr
->personal_rating
, againstRating
);
606 float K
= (itr
->personal_rating
< 1000) ? 48.0f
: 32.0f
;
607 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
608 int32 mod
= (int32
)ceil(K
* (0.0f
- chance
));
609 if (int32(itr
->personal_rating
) + mod
< 0)
610 itr
->personal_rating
= 0;
612 itr
->personal_rating
+= mod
;
613 // update personal played stats
614 itr
->games_week
+= 1;
615 itr
->games_season
+= 1;
621 void ArenaTeam::MemberWon(Player
* plr
, uint32 againstRating
)
623 // called for each participant after winning a match
624 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
626 if(itr
->guid
== plr
->GetGUID())
628 // update personal rating
629 float chance
= GetChanceAgainst(itr
->personal_rating
, againstRating
);
630 float K
= (itr
->personal_rating
< 1000) ? 48.0f
: 32.0f
;
631 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
632 int32 mod
= (int32
)floor(K
* (1.0f
- chance
));
633 itr
->ModifyPersonalRating(plr
, mod
, GetSlot());
634 // update personal stats
635 itr
->games_week
+= 1;
636 itr
->games_season
+= 1;
637 itr
->wins_season
+= 1;
639 // update unit fields
640 plr
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_GAMES_WEEK
, itr
->games_week
);
641 plr
->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1
+ (GetSlot() * ARENA_TEAM_END
) + ARENA_TEAM_GAMES_SEASON
, itr
->games_season
);
647 void ArenaTeam::UpdateArenaPointsHelper(std::map
<uint32
, uint32
>& PlayerPoints
)
649 // called after a match has ended and the stats are already modified
650 // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
651 // 10 played games per week is a minimum
652 if (m_stats
.games_week
< 10)
654 // to get points, a player has to participate in at least 30% of the matches
655 uint32 min_plays
= (uint32
) ceil(m_stats
.games_week
* 0.3);
656 for(MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
658 // the player participated in enough games, update his points
659 uint32 points_to_add
= 0;
660 if (itr
->games_week
>= min_plays
)
661 points_to_add
= GetPoints(itr
->personal_rating
);
662 // 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);
664 std::map
<uint32
, uint32
>::iterator plr_itr
= PlayerPoints
.find(GUID_LOPART(itr
->guid
));
665 if (plr_itr
!= PlayerPoints
.end())
667 //check if there is already more points
668 if (plr_itr
->second
< points_to_add
)
669 PlayerPoints
[GUID_LOPART(itr
->guid
)] = points_to_add
;
672 PlayerPoints
[GUID_LOPART(itr
->guid
)] = points_to_add
;
676 void ArenaTeam::SaveToDB()
678 // save team and member stats to db
679 // called after a match has ended, or when calculating arena_points
680 CharacterDatabase
.BeginTransaction();
681 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());
682 for(MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
684 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
));
686 CharacterDatabase
.CommitTransaction();
689 void ArenaTeam::FinishWeek()
691 m_stats
.games_week
= 0; // played this week
692 m_stats
.wins_week
= 0; // wins this week
693 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
700 bool ArenaTeam::IsFighting() const
702 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
704 if (Player
*p
= sObjectMgr
.GetPlayer(itr
->guid
))
706 if (p
->GetMap()->IsBattleArena())