2 * Copyright (C) 2005-2010 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_UINT32_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_UINT32_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
->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_PERSONAL_RATING
, newmember
.personal_rating
);
158 // hide promote/remove buttons
159 if(m_CaptainGuid
!= PlayerGuid
)
160 pl
->SetArenaTeamInfoField(GetSlot(), 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
->SetArenaTeamInfoField(GetSlot(), 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
->SetArenaTeamInfoField(GetSlot(), 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
->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(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
)
297 // probably only 1 string required...
298 BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S
, 0, 2, session
->GetPlayerName(), GetName(), "");
301 while (!m_members
.empty())
303 // Removing from members is done in DelMember.
304 DelMember(m_members
.front().guid
);
307 CharacterDatabase
.BeginTransaction();
308 CharacterDatabase
.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", m_TeamId
);
309 CharacterDatabase
.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", m_TeamId
); //< this should be already done by calling DelMember(memberGuids[j]); for each member
310 CharacterDatabase
.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", m_TeamId
);
311 CharacterDatabase
.CommitTransaction();
312 sObjectMgr
.RemoveArenaTeam(m_TeamId
);
315 void ArenaTeam::Roster(WorldSession
*session
)
321 WorldPacket
data(SMSG_ARENA_TEAM_ROSTER
, 100);
322 data
<< uint32(GetId()); // team id
323 data
<< uint8(unk308
); // 308 unknown value but affect packet structure
324 data
<< uint32(GetMembersSize()); // members count
325 data
<< uint32(GetType()); // arena team type?
327 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
329 pl
= sObjectMgr
.GetPlayer(itr
->guid
);
331 data
<< uint64(itr
->guid
); // guid
332 data
<< uint8((pl
? 1 : 0)); // online flag
333 data
<< itr
->name
; // member name
334 data
<< uint32((itr
->guid
== GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member
335 data
<< uint8((pl
? pl
->getLevel() : 0)); // unknown, level?
336 data
<< uint8(itr
->Class
); // class
337 data
<< uint32(itr
->games_week
); // played this week
338 data
<< uint32(itr
->wins_week
); // wins this week
339 data
<< uint32(itr
->games_season
); // played this season
340 data
<< uint32(itr
->wins_season
); // wins this season
341 data
<< uint32(itr
->personal_rating
); // personal rating
344 data
<< float(0.0); // 308 unk
345 data
<< float(0.0); // 308 unk
349 session
->SendPacket(&data
);
350 sLog
.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
353 void ArenaTeam::Query(WorldSession
*session
)
355 WorldPacket
data(SMSG_ARENA_TEAM_QUERY_RESPONSE
, 4*7+GetName().size()+1);
356 data
<< uint32(GetId()); // team id
357 data
<< GetName(); // team name
358 data
<< uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5)
359 data
<< uint32(m_BackgroundColor
); // background color
360 data
<< uint32(m_EmblemStyle
); // emblem style
361 data
<< uint32(m_EmblemColor
); // emblem color
362 data
<< uint32(m_BorderStyle
); // border style
363 data
<< uint32(m_BorderColor
); // border color
364 session
->SendPacket(&data
);
365 sLog
.outDebug("WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE");
368 void ArenaTeam::Stats(WorldSession
*session
)
370 WorldPacket
data(SMSG_ARENA_TEAM_STATS
, 4*7);
371 data
<< uint32(GetId()); // team id
372 data
<< uint32(m_stats
.rating
); // rating
373 data
<< uint32(m_stats
.games_week
); // games this week
374 data
<< uint32(m_stats
.wins_week
); // wins this week
375 data
<< uint32(m_stats
.games_season
); // played this season
376 data
<< uint32(m_stats
.wins_season
); // wins this season
377 data
<< uint32(m_stats
.rank
); // rank
378 session
->SendPacket(&data
);
381 void ArenaTeam::NotifyStatsChanged()
383 // this is called after a rated match ended
384 // updates arena team stats for every member of the team (not only the ones who participated!)
385 for(MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
387 Player
* plr
= sObjectMgr
.GetPlayer(itr
->guid
);
389 Stats(plr
->GetSession());
393 void ArenaTeam::InspectStats(WorldSession
*session
, uint64 guid
)
395 ArenaTeamMember
* member
= GetMember(guid
);
399 WorldPacket
data(MSG_INSPECT_ARENA_TEAMS
, 8+1+4*6);
400 data
<< uint64(guid
); // player guid
401 data
<< uint8(GetSlot()); // slot (0...2)
402 data
<< uint32(GetId()); // arena team id
403 data
<< uint32(m_stats
.rating
); // rating
404 data
<< uint32(m_stats
.games_season
); // season played
405 data
<< uint32(m_stats
.wins_season
); // season wins
406 data
<< uint32(member
->games_season
); // played (count of all games, that the inspected member participated...)
407 data
<< uint32(member
->personal_rating
); // personal rating
408 session
->SendPacket(&data
);
411 void ArenaTeam::SetEmblem(uint32 backgroundColor
, uint32 emblemStyle
, uint32 emblemColor
, uint32 borderStyle
, uint32 borderColor
)
413 m_BackgroundColor
= backgroundColor
;
414 m_EmblemStyle
= emblemStyle
;
415 m_EmblemColor
= emblemColor
;
416 m_BorderStyle
= borderStyle
;
417 m_BorderColor
= borderColor
;
419 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
);
422 void ArenaTeam::SetStats(uint32 stat_type
, uint32 value
)
426 case STAT_TYPE_RATING
:
427 m_stats
.rating
= value
;
428 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value
, GetId());
430 case STAT_TYPE_GAMES_WEEK
:
431 m_stats
.games_week
= value
;
432 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value
, GetId());
434 case STAT_TYPE_WINS_WEEK
:
435 m_stats
.wins_week
= value
;
436 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value
, GetId());
438 case STAT_TYPE_GAMES_SEASON
:
439 m_stats
.games_season
= value
;
440 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value
, GetId());
442 case STAT_TYPE_WINS_SEASON
:
443 m_stats
.wins_season
= value
;
444 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value
, GetId());
447 m_stats
.rank
= value
;
448 CharacterDatabase
.PExecute("UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'", value
, GetId());
451 sLog
.outDebug("unknown stat type in ArenaTeam::SetStats() %u", stat_type
);
456 void ArenaTeam::BroadcastPacket(WorldPacket
*packet
)
458 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
460 Player
*player
= sObjectMgr
.GetPlayer(itr
->guid
);
462 player
->GetSession()->SendPacket(packet
);
466 void ArenaTeam::BroadcastEvent(ArenaTeamEvents event
, uint64 guid
, uint8 strCount
, std::string str1
, std::string str2
, std::string str3
)
468 WorldPacket
data(SMSG_ARENA_TEAM_EVENT
, 1+1+1);
469 data
<< uint8(event
);
470 data
<< uint8(strCount
);
479 data
<< str1
<< str2
;
482 data
<< str1
<< str2
<< str3
;
485 sLog
.outError("Unhandled strCount %u in ArenaTeam::BroadcastEvent", strCount
);
490 data
<< uint64(guid
);
492 BroadcastPacket(&data
);
494 sLog
.outDebug("WORLD: Sent SMSG_ARENA_TEAM_EVENT");
497 uint8
ArenaTeam::GetSlotByType( uint32 type
)
501 case ARENA_TEAM_2v2
: return 0;
502 case ARENA_TEAM_3v3
: return 1;
503 case ARENA_TEAM_5v5
: return 2;
507 sLog
.outError("FATAL: Unknown arena team type %u for some arena team", type
);
511 bool ArenaTeam::HaveMember( const uint64
& guid
) const
513 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
514 if(itr
->guid
== guid
)
520 uint32
ArenaTeam::GetPoints(uint32 MemberRating
)
522 // returns how many points would be awarded with this team type with this rating
525 uint32 rating
= MemberRating
+ 150 < m_stats
.rating
? MemberRating
: m_stats
.rating
;
528 points
= (float)rating
* 0.22f
+ 14.0f
;
530 points
= 1511.26f
/ (1.0f
+ 1639.28f
* exp(-0.00412f
* (float)rating
));
532 // type penalties for <5v5 teams
533 if(m_Type
== ARENA_TEAM_2v2
)
535 else if(m_Type
== ARENA_TEAM_3v3
)
538 return (uint32
) points
;
541 float ArenaTeam::GetChanceAgainst(uint32 own_rating
, uint32 enemy_rating
)
543 // returns the chance to win against a team with the given rating, used in the rating adjustment calculation
546 if (sWorld
.getConfig(CONFIG_UINT32_ARENA_SEASON_ID
) >= 6)
547 if (enemy_rating
< 1000)
549 return 1.0f
/(1.0f
+exp(log(10.0f
)*(float)((float)enemy_rating
- (float)own_rating
)/400.0f
));
552 void ArenaTeam::FinishGame(int32 mod
)
554 if (int32(m_stats
.rating
) + mod
< 0)
557 m_stats
.rating
+= mod
;
559 m_stats
.games_week
+= 1;
560 m_stats
.games_season
+= 1;
561 // update team's rank
563 ObjectMgr::ArenaTeamMap::const_iterator i
= sObjectMgr
.GetArenaTeamMapBegin();
564 for ( ; i
!= sObjectMgr
.GetArenaTeamMapEnd(); ++i
)
566 if (i
->second
->GetType() == this->m_Type
&& i
->second
->GetStats().rating
> m_stats
.rating
)
571 int32
ArenaTeam::WonAgainst(uint32 againstRating
)
573 // called when the team has won
574 // 'chance' calculation - to beat the opponent
575 float chance
= GetChanceAgainst(m_stats
.rating
, againstRating
);
576 float K
= (m_stats
.rating
< 1000) ? 48.0f
: 32.0f
;
577 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
578 int32 mod
= (int32
)floor(K
* (1.0f
- chance
));
579 // modify the team stats accordingly
581 m_stats
.wins_week
+= 1;
582 m_stats
.wins_season
+= 1;
584 // return the rating change, used to display it on the results screen
588 int32
ArenaTeam::LostAgainst(uint32 againstRating
)
590 // called when the team has lost
591 //'chance' calculation - to loose to the opponent
592 float chance
= GetChanceAgainst(m_stats
.rating
, againstRating
);
593 float K
= (m_stats
.rating
< 1000) ? 48.0f
: 32.0f
;
594 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
595 int32 mod
= (int32
)ceil(K
* (0.0f
- chance
));
596 // modify the team stats accordingly
599 // return the rating change, used to display it on the results screen
603 void ArenaTeam::MemberLost(Player
* plr
, uint32 againstRating
)
605 // called for each participant of a match after losing
606 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
608 if(itr
->guid
== plr
->GetGUID())
610 // update personal rating
611 float chance
= GetChanceAgainst(itr
->personal_rating
, againstRating
);
612 float K
= (itr
->personal_rating
< 1000) ? 48.0f
: 32.0f
;
613 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
614 int32 mod
= (int32
)ceil(K
* (0.0f
- chance
));
615 itr
->ModifyPersonalRating(plr
, mod
, GetSlot());
616 // update personal played stats
617 itr
->games_week
+= 1;
618 itr
->games_season
+= 1;
619 // update the unit fields
620 plr
->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK
, itr
->games_week
);
621 plr
->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON
, itr
->games_season
);
627 void ArenaTeam::OfflineMemberLost(uint64 guid
, uint32 againstRating
)
629 // called for offline player after ending rated arena match!
630 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
632 if(itr
->guid
== guid
)
634 // update personal rating
635 float chance
= GetChanceAgainst(itr
->personal_rating
, againstRating
);
636 float K
= (itr
->personal_rating
< 1000) ? 48.0f
: 32.0f
;
637 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
638 int32 mod
= (int32
)ceil(K
* (0.0f
- chance
));
639 if (int32(itr
->personal_rating
) + mod
< 0)
640 itr
->personal_rating
= 0;
642 itr
->personal_rating
+= mod
;
643 // update personal played stats
644 itr
->games_week
+= 1;
645 itr
->games_season
+= 1;
651 void ArenaTeam::MemberWon(Player
* plr
, uint32 againstRating
)
653 // called for each participant after winning a match
654 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
656 if(itr
->guid
== plr
->GetGUID())
658 // update personal rating
659 float chance
= GetChanceAgainst(itr
->personal_rating
, againstRating
);
660 float K
= (itr
->personal_rating
< 1000) ? 48.0f
: 32.0f
;
661 // calculate the rating modification (ELO system with k=32 or k=48 if rating<1000)
662 int32 mod
= (int32
)floor(K
* (1.0f
- chance
));
663 itr
->ModifyPersonalRating(plr
, mod
, GetSlot());
664 // update personal stats
665 itr
->games_week
+= 1;
666 itr
->games_season
+= 1;
667 itr
->wins_season
+= 1;
669 // update unit fields
670 plr
->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_WEEK
, itr
->games_week
);
671 plr
->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_GAMES_SEASON
, itr
->games_season
);
677 void ArenaTeam::UpdateArenaPointsHelper(std::map
<uint32
, uint32
>& PlayerPoints
)
679 // called after a match has ended and the stats are already modified
680 // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons)
681 // 10 played games per week is a minimum
682 if (m_stats
.games_week
< 10)
684 // to get points, a player has to participate in at least 30% of the matches
685 uint32 min_plays
= (uint32
) ceil(m_stats
.games_week
* 0.3);
686 for(MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
688 // the player participated in enough games, update his points
689 uint32 points_to_add
= 0;
690 if (itr
->games_week
>= min_plays
)
691 points_to_add
= GetPoints(itr
->personal_rating
);
692 // 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);
694 std::map
<uint32
, uint32
>::iterator plr_itr
= PlayerPoints
.find(GUID_LOPART(itr
->guid
));
695 if (plr_itr
!= PlayerPoints
.end())
697 //check if there is already more points
698 if (plr_itr
->second
< points_to_add
)
699 PlayerPoints
[GUID_LOPART(itr
->guid
)] = points_to_add
;
702 PlayerPoints
[GUID_LOPART(itr
->guid
)] = points_to_add
;
706 void ArenaTeam::SaveToDB()
708 // save team and member stats to db
709 // called after a match has ended, or when calculating arena_points
710 CharacterDatabase
.BeginTransaction();
711 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());
712 for(MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
714 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
));
716 CharacterDatabase
.CommitTransaction();
719 void ArenaTeam::FinishWeek()
721 m_stats
.games_week
= 0; // played this week
722 m_stats
.wins_week
= 0; // wins this week
723 for(MemberList::iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
730 bool ArenaTeam::IsFighting() const
732 for (MemberList::const_iterator itr
= m_members
.begin(); itr
!= m_members
.end(); ++itr
)
734 if (Player
*p
= sObjectMgr
.GetPlayer(itr
->guid
))
736 if (p
->GetMap()->IsBattleArena())