Character re-customization fix
[getmangos.git] / src / game / ArenaTeam.cpp
blob72ed8d6796eb3eb2828271bf61264e7f571f5a17
1 /*
2 * Copyright (C) 2005-2008 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 "ArenaTeam.h"
23 ArenaTeam::ArenaTeam()
25 Id = 0;
26 Type = 0;
27 Name = "";
28 CaptainGuid = 0;
29 BackgroundColor = 0; // background
30 EmblemStyle = 0; // icon
31 EmblemColor = 0; // icon color
32 BorderStyle = 0; // border
33 BorderColor = 0; // border color
34 stats.games_week = 0;
35 stats.games_season = 0;
36 stats.rank = 0;
37 stats.rating = 1500;
38 stats.wins_week = 0;
39 stats.wins_season = 0;
42 ArenaTeam::~ArenaTeam()
47 bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamName)
49 if(!objmgr.GetPlayer(captainGuid)) // player not exist
50 return false;
51 if(objmgr.GetArenaTeamByName(ArenaTeamName)) // arena team with this name already exist
52 return false;
54 sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid));
56 CaptainGuid = captainGuid;
57 Name = ArenaTeamName;
58 Type = type;
60 Id = objmgr.GenerateArenaTeamId();
62 // ArenaTeamName already assigned to ArenaTeam::name, use it to encode string for DB
63 CharacterDatabase.escape_string(ArenaTeamName);
65 CharacterDatabase.BeginTransaction();
66 // CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", Id); - MAX(arenateam)+1 not exist
67 CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", Id);
68 CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) "
69 "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')",
70 Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor);
71 CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES "
72 "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id,stats.rating,stats.games_week,stats.wins_week,stats.games_season,stats.wins_season,stats.rank);
74 CharacterDatabase.CommitTransaction();
76 AddMember(CaptainGuid);
77 return true;
80 bool ArenaTeam::AddMember(uint64 PlayerGuid)
82 std::string plName;
83 uint8 plClass;
85 // arena team is full (can't have more than type * 2 players!)
86 if(GetMembersSize() >= GetType() * 2)
87 return false;
89 Player *pl = objmgr.GetPlayer(PlayerGuid);
90 if(pl)
92 if(pl->GetArenaTeamId(GetSlot()))
94 sLog.outError("Arena::AddMember() : player already in this sized team");
95 return false;
98 plClass = (uint8)pl->getClass();
99 plName = pl->GetName();
101 else
103 // 0 1
104 QueryResult *result = CharacterDatabase.PQuery("SELECT name, class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid));
105 if(!result)
106 return false;
108 plName = (*result)[0].GetCppString();
109 plClass = (*result)[1].GetUInt8();
110 delete result;
112 // check if player already in arenateam of that size
113 if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0)
115 sLog.outError("Arena::AddMember() : player already in this sized team");
116 return false;
120 // remove all player signs from another petitions
121 // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity
122 Player::RemovePetitionsAndSigns(PlayerGuid, GetType());
124 ArenaTeamMember newmember;
125 newmember.name = plName;
126 newmember.guid = PlayerGuid;
127 newmember.Class = plClass;
128 newmember.games_season = 0;
129 newmember.games_week = 0;
130 newmember.wins_season = 0;
131 newmember.wins_week = 0;
132 newmember.personal_rating = 1500;
133 members.push_back(newmember);
135 CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid,guid) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid));
137 if(pl)
139 pl->SetInArenaTeam(Id, GetSlot());
140 pl->SetArenaTeamIdInvited(0);
142 // hide promote/remove buttons
143 if(CaptainGuid != PlayerGuid)
144 pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
146 else
148 Tokens tokens;
149 if(Player::LoadValuesArrayFromDB(tokens,PlayerGuid))
151 Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id);
152 // hide promote/remove buttons
153 if(CaptainGuid != PlayerGuid)
154 Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
156 Player::SaveValuesArrayInDB(tokens,PlayerGuid);
159 return true;
162 bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId)
164 LoadStatsFromDB(ArenaTeamId);
165 LoadMembersFromDB(ArenaTeamId);
167 // 0 1 2 3 4 5 6 7 8
168 QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId);
170 if(!result)
171 return false;
173 Field *fields = result->Fetch();
175 Id = fields[0].GetUInt32();
176 Name = fields[1].GetCppString();
177 CaptainGuid = MAKE_NEW_GUID(fields[2].GetUInt32(), 0, HIGHGUID_PLAYER);
178 Type = fields[3].GetUInt32();
179 BackgroundColor = fields[4].GetUInt32();
180 EmblemStyle = fields[5].GetUInt32();
181 EmblemColor = fields[6].GetUInt32();
182 BorderStyle = fields[7].GetUInt32();
183 BorderColor = fields[8].GetUInt32();
185 delete result;
187 return true;
190 void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId)
192 // 0 1 2 3 4 5
193 QueryResult *result = CharacterDatabase.PQuery("SELECT rating,games,wins,played,wins2,rank FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId);
195 if(!result)
196 return;
198 Field *fields = result->Fetch();
200 stats.rating = fields[0].GetUInt32();
201 stats.games_week = fields[1].GetUInt32();
202 stats.wins_week = fields[2].GetUInt32();
203 stats.games_season = fields[3].GetUInt32();
204 stats.wins_season = fields[4].GetUInt32();
205 stats.rank = fields[5].GetUInt32();
207 delete result;
210 void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId)
212 Field *fields;
214 QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId);
215 if(!result)
216 return;
220 fields = result->Fetch();
221 ArenaTeamMember newmember;
222 newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
223 LoadPlayerStats(&newmember);
224 newmember.games_week = fields[1].GetUInt32();
225 newmember.wins_week = fields[2].GetUInt32();
226 newmember.games_season = fields[3].GetUInt32();
227 newmember.wins_season = fields[4].GetUInt32();
228 members.push_back(newmember);
229 }while( result->NextRow() );
230 delete result;
233 void ArenaTeam::LoadPlayerStats(ArenaTeamMember *member)
235 Field *fields;
237 QueryResult *result = CharacterDatabase.PQuery("SELECT name,class FROM characters WHERE guid = '%u'", GUID_LOPART(member->guid));
238 if(!result)
239 return;
240 fields = result->Fetch();
241 member->name = fields[0].GetCppString();
242 member->Class = fields[1].GetUInt8();
244 delete result;
247 void ArenaTeam::SetCaptain(uint64 guid)
249 // disable remove/promote buttons
250 Player *oldcaptain = objmgr.GetPlayer(GetCaptain());
251 if(oldcaptain)
252 oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1);
253 else
254 Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, GetCaptain());
256 // set new captain
257 CaptainGuid = guid;
259 // update database
260 CharacterDatabase.PExecute("UPDATE arena_team SET captainguid = '%u' WHERE arenateamid = '%u'", GUID_LOPART(guid), Id);
262 // enable remove/promote buttons
263 Player *newcaptain = objmgr.GetPlayer(guid);
264 if(newcaptain)
265 newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0);
266 else
267 Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0, guid);
270 void ArenaTeam::DelMember(uint64 guid)
272 MemberList::iterator itr;
273 for (itr = members.begin(); itr != members.end(); itr++)
275 if (itr->guid == guid)
277 members.erase(itr);
278 break;
282 Player *player = objmgr.GetPlayer(guid);
283 if(player)
285 player->SetInArenaTeam(0, GetSlot());
286 player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0);
288 else
290 Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid);
293 CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid));
296 void ArenaTeam::Disband(WorldSession *session)
298 // event
299 WorldPacket data;
300 session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), "");
301 BroadcastPacket(&data);
303 uint32 count = members.size();
304 uint64 *memberGuids = new uint64[count];
306 MemberList::iterator itr;
307 uint32 i=0;
308 for(itr = members.begin(); itr != members.end(); itr++)
310 memberGuids[i] = itr->guid;
311 ++i;
314 for(uint32 j = 0; j < count; j++)
315 DelMember(memberGuids[j]);
316 delete[] memberGuids;
318 CharacterDatabase.BeginTransaction();
319 CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id);
320 CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id);
321 CharacterDatabase.CommitTransaction();
322 objmgr.RemoveArenaTeam(this);
325 void ArenaTeam::Roster(WorldSession *session)
327 Player *pl = NULL;
329 WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100);
330 data << uint32(GetId()); // arena team id
331 data << uint32(GetMembersSize()); // members count
332 data << uint32(GetType()); // arena team type?
334 for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
336 pl = objmgr.GetPlayer(itr->guid);
337 if(pl)
339 data << uint64(pl->GetGUID()); // guid
340 data << uint8(1); // online flag
341 data << pl->GetName(); // member name
342 data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown
343 data << uint8(pl->getLevel()); // unknown, probably level
344 data << uint8(pl->getClass()); // class
345 data << uint32(itr->games_week); // played this week
346 data << uint32(itr->wins_week); // wins this week
347 data << uint32(itr->games_season); // played this season
348 data << uint32(itr->wins_season); // wins this season
349 data << uint32(itr->personal_rating); // personal rating
351 else
353 data << uint64(itr->guid); // guid
354 data << uint8(0); // online flag
355 data << itr->name; // member name
356 data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown
357 data << uint8(0); // unknown, level?
358 data << uint8(itr->Class); // class
359 data << uint32(itr->games_week); // played this week
360 data << uint32(itr->wins_week); // wins this week
361 data << uint32(itr->games_season); // played this season
362 data << uint32(itr->wins_season); // wins this season
363 data << uint32(itr->personal_rating); // personal rating
366 session->SendPacket(&data);
367 sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER");
370 void ArenaTeam::Query(WorldSession *session)
372 WorldPacket data(SMSG_ARENA_TEAM_QUERY_RESPONSE, 4*7+GetName().size()+1);
373 data << uint32(GetId()); // team id
374 data << GetName(); // team name
375 data << uint32(GetType()); // arena team type (2=2x2, 3=3x3 or 5=5x5)
376 data << uint32(BackgroundColor); // background color
377 data << uint32(EmblemStyle); // emblem style
378 data << uint32(EmblemColor); // emblem color
379 data << uint32(BorderStyle); // border style
380 data << uint32(BorderColor); // border color
381 session->SendPacket(&data);
382 sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_QUERY_RESPONSE");
385 void ArenaTeam::Stats(WorldSession *session)
387 WorldPacket data(SMSG_ARENA_TEAM_STATS, 4*7);
388 data << uint32(GetId()); // arena team id
389 data << uint32(stats.rating); // rating
390 data << uint32(stats.games_week); // games this week
391 data << uint32(stats.wins_week); // wins this week
392 data << uint32(stats.games_season); // played this season
393 data << uint32(stats.wins_season); // wins this season
394 data << uint32(stats.rank); // rank
395 session->SendPacket(&data);
398 void ArenaTeam::InspectStats(WorldSession *session, uint64 guid)
400 ArenaTeamMember* member = GetMember(guid);
401 if(!member)
402 return;
404 WorldPacket data(MSG_INSPECT_ARENA_TEAMS, 8+1+4*6);
405 data << uint64(guid); // player guid
406 data << uint8(GetSlot()); // slot (0...2)
407 data << uint32(GetId()); // arena team id
408 data << uint32(stats.rating); // rating
409 data << uint32(stats.games_season); // season played
410 data << uint32(stats.wins_season); // season wins
411 data << member->games_season; // played (count of all games, that the inspected member participated...)
412 data << member->personal_rating; // personal rating
413 session->SendPacket(&data);
416 void ArenaTeam::SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor)
418 BackgroundColor = backgroundColor;
419 EmblemStyle = emblemStyle;
420 EmblemColor = emblemColor;
421 BorderStyle = borderStyle;
422 BorderColor = borderColor;
424 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);
427 void ArenaTeam::SetStats(uint32 stat_type, uint32 value)
429 switch(stat_type)
431 case STAT_TYPE_RATING:
432 stats.rating = value;
433 CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u' WHERE arenateamid = '%u'", value, GetId());
434 break;
435 case STAT_TYPE_GAMES_WEEK:
436 stats.games_week = value;
437 CharacterDatabase.PExecute("UPDATE arena_team_stats SET games = '%u' WHERE arenateamid = '%u'", value, GetId());
438 break;
439 case STAT_TYPE_WINS_WEEK:
440 stats.wins_week = value;
441 CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins = '%u' WHERE arenateamid = '%u'", value, GetId());
442 break;
443 case STAT_TYPE_GAMES_SEASON:
444 stats.games_season = value;
445 CharacterDatabase.PExecute("UPDATE arena_team_stats SET played = '%u' WHERE arenateamid = '%u'", value, GetId());
446 break;
447 case STAT_TYPE_WINS_SEASON:
448 stats.wins_season = value;
449 CharacterDatabase.PExecute("UPDATE arena_team_stats SET wins2 = '%u' WHERE arenateamid = '%u'", value, GetId());
450 break;
451 case STAT_TYPE_RANK:
452 stats.rank = value;
453 CharacterDatabase.PExecute("UPDATE arena_team_stats SET rank = '%u' WHERE arenateamid = '%u'", value, GetId());
454 break;
455 default:
456 sLog.outDebug("unknown stat type in ArenaTeam::SetStats() %u", stat_type);
457 break;
461 uint8 ArenaTeam::GetSlot() const
463 uint8 slot = GetSlotByType(GetType());
464 if(slot >= MAX_ARENA_SLOT)
466 sLog.outError("Unknown arena team type %u for arena team %u", uint32(GetType()), GetId());
467 return 0; // better return existed slot to prevent untelated data curruption
470 return slot;
473 void ArenaTeam::BroadcastPacket(WorldPacket *packet)
475 for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
477 Player *player = objmgr.GetPlayer(itr->guid);
478 if(player)
479 player->GetSession()->SendPacket(packet);
483 uint8 ArenaTeam::GetSlotByType( uint32 type )
485 switch(type)
487 case ARENA_TEAM_2v2: return 0;
488 case ARENA_TEAM_3v3: return 1;
489 case ARENA_TEAM_5v5: return 2;
490 default:
491 break;
493 return 0xFF;
496 bool ArenaTeam::HaveMember( uint64 guid ) const
498 for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr)
499 if(itr->guid==guid)
500 return true;
502 return false;
505 void ArenaTeam::FinishWeek()
507 stats.games_week = 0; // played this week
508 stats.wins_week = 0; // wins this week
509 for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr)
511 itr->games_week = 0;
512 itr->wins_week = 0;
517 arenateam fields (id from 2.3.3 client):
518 1414 - arena team id 2v2
519 1415 - 0=captain, 1=member
520 1416 - played this week
521 1417 - played this season
522 1418 - unk
523 1419 - personal arena rating
524 1420 - arena team id 3v3
525 1421 - 0=captain, 1=member
526 1422 - played this week
527 1423 - played this season
528 1424 - unk
529 1425 - personal arena rating
530 1426 - arena team id 5v5
531 1427 - 0=captain, 1=member
532 1428 - played this week
533 1429 - played this season
534 1430 - unk
535 1431 - personal arena rating