Show
Ignore:
Timestamp:
11/19/08 13:22:41 (17 years ago)
Author:
yumileroy
Message:

[svn] -enabled instantiated battlegrounds
-enabled arena matches
-rewritten battleground queuing to support joining as group
-removed queue announcements

Original author: w12x
Date: 2008-10-05 08:48:32-05:00

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/game/ArenaTeam.cpp

    r2 r9  
    5252        return false; 
    5353 
    54     sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid)); 
     54    sLog.outDebug("GUILD: creating arena team %s to leader: %u", ArenaTeamName.c_str(), GUID_LOPART(captainGuid)); 
    5555 
    5656    CaptainGuid = captainGuid; 
     
    139139        pl->SetInArenaTeam(Id, GetSlot()); 
    140140        pl->SetArenaTeamIdInvited(0); 
    141     } 
    142     else 
    143     { 
    144         Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id, PlayerGuid); 
     141        // personal rating 
     142        pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 5, 1500); 
    145143    } 
    146144 
     
    150148        if(pl) 
    151149            pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); 
    152         else 
    153             Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, PlayerGuid); 
    154     } 
     150    } 
     151 
     152    // setuint32valueindb is asynch, can't be used here 
     153    Tokens tokens; 
     154    if(!Player::LoadValuesArrayFromDB(tokens,PlayerGuid)) 
     155        return false; 
     156 
     157    // arena team id 
     158    uint16 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6); 
     159    char buf[11]; 
     160    snprintf(buf,11,"%u",Id); 
     161    tokens[index] = buf; 
     162    // pers rating 
     163    index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 5; 
     164    buf[11]; 
     165    snprintf(buf,11,"%u",1500); 
     166    tokens[index] = buf; 
     167    // hide promote/remove buttons 
     168    if(CaptainGuid != PlayerGuid) 
     169    { 
     170        index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6); 
     171        buf[11]; 
     172        snprintf(buf,11,"%u",1); 
     173        tokens[index] = buf; 
     174    } 
     175 
     176    Player::SaveValuesArrayInDB(tokens,PlayerGuid); 
     177 
    155178    return true; 
    156179} 
     
    158181bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) 
    159182{ 
    160     LoadStatsFromDB(ArenaTeamId); 
    161     LoadMembersFromDB(ArenaTeamId); 
    162  
    163     //                                                      0          1    2           3    4               5           6           7           8 
    164183    QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); 
    165184 
     
    181200    delete result; 
    182201 
     202    // only load here, so additional checks can be made 
     203    LoadStatsFromDB(ArenaTeamId); 
     204    LoadMembersFromDB(ArenaTeamId); 
     205 
     206    if(!GetMembersSize()) 
     207    { 
     208        // arena team is empty, delete from db 
     209        CharacterDatabase.BeginTransaction(); 
     210        CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); 
     211        CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 
     212        CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); 
     213        CharacterDatabase.CommitTransaction(); 
     214        // return false 
     215        return false; 
     216    } 
     217 
    183218    return true; 
    184219} 
     
    208243    Field *fields; 
    209244 
    210     QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 
     245    QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season,points_to_add FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); 
    211246    if(!result) 
    212247        return; 
     
    217252        ArenaTeamMember newmember; 
    218253        newmember.guid          = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); 
     254        // check if this member is in this arenateam 
     255        // based on character data field 
     256        if(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6),newmember.guid) != ArenaTeamId) 
     257        { 
     258            // the player's registered arena team for this slot isn't this team, so delete member info from here 
     259            CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u' AND arenateamid = '%u'",fields[0].GetUInt32(), ArenaTeamId); 
     260            continue; 
     261        } 
    219262        LoadPlayerStats(&newmember); 
    220263        newmember.played_week   = fields[1].GetUInt32(); 
     
    277320 
    278321    Player *player = objmgr.GetPlayer(guid); 
     322    // this will be ugly. because of the asynchronous sql handling, we have to set all the fields of the player at once, and save them at once, or else the save will only modify the last field. 
     323    // rip off of setuint32valueindb 
    279324    if(player) 
    280325    { 
    281326        player->SetInArenaTeam(0, GetSlot()); 
    282327        player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0); 
    283     } 
    284     else 
    285     { 
    286         Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid); 
    287     } 
    288  
    289     CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid)); 
     328        // delete all info regarding this team 
     329        for(int i = 0; i < 6; ++i) 
     330        { 
     331            player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0); 
     332        } 
     333    } 
     334 
     335    // we have to do it this way, setuint32valueindb is asynch, unsafe to use multiple times in a row on the same player 
     336    Tokens tokens; 
     337    if(!Player::LoadValuesArrayFromDB(tokens,guid)) 
     338        return; 
     339 
     340    for(int i = 0; i < 6; ++i) 
     341    { 
     342        uint16 index = PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i; 
     343        char buf[11]; 
     344        snprintf(buf,11,"%u",0); 
     345        tokens[index] = buf; 
     346    } 
     347 
     348    Player::SaveValuesArrayInDB(tokens,guid); 
     349 
     350    // only delete from this arena team! 
     351    CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid)); 
    290352} 
    291353 
     
    314376    CharacterDatabase.BeginTransaction(); 
    315377    CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id); 
     378    CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); 
    316379    CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id); 
    317380    CharacterDatabase.CommitTransaction(); 
     
    343406            data << uint32(itr->played_season);             // played this season 
    344407            data << uint32(itr->wons_season);               // wins this season 
    345             data << uint32(0);                              // personal rating? 
     408            data << uint32(pl->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5));                              // personal rating? 
    346409        } 
    347410        else 
     
    357420            data << uint32(itr->played_season);             // played this season 
    358421            data << uint32(itr->wons_season);               // wins this season 
    359             data << uint32(0);                              // personal rating? 
     422            data << uint32(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5, itr->guid));                              // personal rating? 
    360423        } 
    361424    } 
     
    392455} 
    393456 
     457void ArenaTeam::NotifyStatsChanged() 
     458{ 
     459    // this is called after a rated match ended 
     460    // updates arena team stats for every member of the team (not only the ones who participated!) 
     461    for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) 
     462    { 
     463        Player * plr=objmgr.GetPlayer(itr->guid); 
     464        if(plr) 
     465            Stats(plr->GetSession()); 
     466    } 
     467} 
     468 
    394469void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) 
    395470{ 
     
    399474    data << uint32(GetId());                                // arena team id 
    400475    data << uint32(stats.rating);                           // rating 
    401     data << uint32(stats.games);                            // games 
    402     data << uint32(stats.wins);                             // wins 
    403     data << uint32(stats.played);                           // played (count of all games, that played...) 
    404     data << uint32(0);                                      // 2.3.3 personal rating? 
     476    data << uint32(stats.played);                           // season played 
     477    data << uint32(stats.wins2);                            // season wins 
     478    uint32 participated = 0; 
     479    for(MemberList::iterator itr = members.begin(); itr!= members.end(); ++itr) 
     480    { 
     481        if(itr->guid == guid) 
     482        { 
     483            participated = itr->played_season; 
     484            break; 
     485        } 
     486    } 
     487    data << uint32(participated);                            // played (count of all games, that the inspected member participated...) 
     488    data << uint32(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + GetSlot() * 6 + 5, guid));                                       // unk, 2.3.3 (personal rating?) 
     489 
    405490    session->SendPacket(&data); 
    406491} 
     
    495580} 
    496581 
     582uint32 ArenaTeam::GetPoints(uint32 MemberRating) 
     583{ 
     584    // returns how many points would be awarded with this team type with this rating 
     585    float points; 
     586 
     587    uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating; 
     588 
     589    if(rating<=1500) 
     590    { 
     591        points = (float)rating * 0.22f + 14.0f; 
     592    } 
     593    else 
     594    { 
     595        points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating)); 
     596    } 
     597 
     598    // type penalties for <5v5 teams 
     599    if(Type == ARENA_TEAM_2v2) 
     600        points *= 0.76f; 
     601    else if(Type == ARENA_TEAM_3v3) 
     602        points *= 0.88f; 
     603 
     604    return (uint32) points; 
     605} 
     606 
     607float ArenaTeam::GetChanceAgainst(uint32 rating) 
     608{ 
     609    // returns the chance to win against a team with the given rating, used in the rating adjustment calculation 
     610    // ELO system 
     611    return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)rating - (float)stats.rating)/400.0f)); 
     612} 
     613 
     614int32 ArenaTeam::WonAgainstChance(float chance) 
     615{ 
     616    // called when the team has won, and had 'chance' calculated chance to beat the opponent 
     617    // calculate the rating modification (ELO system with k=32) 
     618    int32 mod = (int32)floor(32.0f * (1.0f - chance)); 
     619    // modify the team stats accordingly 
     620    stats.rating += mod; 
     621    stats.games += 1; 
     622    stats.wins += 1; 
     623    stats.played += 1; 
     624    stats.wins2 += 1; 
     625/*  this should be done in .flusharenapoints; not a breaker though. 
     626    uint32 higher_rank = 0; 
     627    QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT(arenateamid) FROM arena_team_stats WHERE rating > '%u' AND arenateamid <> '%u'",stats.rating, Id); 
     628    if(result) 
     629    { 
     630        higher_rank = result->Fetch()->GetUInt32(); 
     631        delete result; 
     632    } 
     633    stats.rank = higher_rank + 1;*/ 
     634    // return the rating change, used to display it on the results screen 
     635    return mod; 
     636} 
     637 
     638int32 ArenaTeam::LostAgainstChance(float chance) 
     639{ 
     640    // called when the team has lost, and had 'chance' calculated chance to beat the opponent 
     641    // calculate the rating modification (ELO system with k=32) 
     642    int32 mod = (int32)ceil(32.0f * (0.0f - chance)); 
     643    // modify the team stats accordingly 
     644    stats.rating += mod; 
     645    stats.games += 1; 
     646    stats.played += 1; 
     647/*    uint32 higher_rank = 0; 
     648    QueryResult *result = CharacterDatabase.PQuery("SELECT DISTINCT COUNT (arenateamid) FROM arena_team_stats WHERE rating > '%u' AND arenateamid <> '%u'",stats.rating, Id); 
     649    if(result) 
     650    { 
     651        higher_rank = result->Fetch()->GetUInt32(); 
     652        delete result; 
     653    } 
     654    stats.rank = higher_rank + 1;*/ 
     655    // return the rating adjustment for display 
     656    return mod; 
     657} 
     658 
     659void ArenaTeam::MemberLost(Player * plr, uint32 againstrating) 
     660{ 
     661    // called for each participant of a match after losing 
     662    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     663    { 
     664        if(itr->guid == plr->GetGUID()) 
     665        { 
     666            // update personal rating 
     667            int32 personalrating = plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5); 
     668            float chance = 1.0f/(1.0f+exp(log(10.0f)*(float)((float)againstrating - (float)personalrating)/400.0f)); 
     669            int32 mod = (int32)ceil(32.0f * (0.0f - chance)); 
     670            personalrating += mod; 
     671            if(personalrating < 0) 
     672                personalrating = 0; 
     673            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, personalrating); 
     674            // update personal played stats 
     675            itr->played_week +=1; 
     676            itr->played_season +=1; 
     677            // update the unit fields 
     678            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->played_week); 
     679            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->played_season); 
     680            return; 
     681        } 
     682    } 
     683} 
     684 
     685void ArenaTeam::MemberWon(Player * plr, uint32 againstrating) 
     686{ 
     687    // called for each participant after winning a match 
     688    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     689    { 
     690        if(itr->guid == plr->GetGUID()) 
     691        { 
     692            // update personal rating 
     693            int32 personalrating = plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5); 
     694            float chance = 1.0f/(1.0f+exp(log(10.0f)*(float)((float)againstrating - (float)personalrating)/400.0f)); 
     695            int32 mod = (int32)floor(32.0f * (1.0f - chance)); 
     696            personalrating += mod; 
     697            if(personalrating < 0) 
     698                personalrating = 0; 
     699            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, personalrating); 
     700            // update personal stats 
     701            itr->played_week +=1; 
     702            itr->played_season +=1; 
     703            itr->wons_season += 1; 
     704            itr->wons_week += 1; 
     705            // update unit fields 
     706            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->played_week); 
     707            plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->played_season); 
     708            return; 
     709        } 
     710    } 
     711} 
     712 
     713void ArenaTeam::UpdateArenaPointsHelper() 
     714{ 
     715    // called after a match has ended and the stats are already modified 
     716    // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons) 
     717    // 10 played games per week is a minimum 
     718    if(stats.games < 10) 
     719        return; 
     720    // to get points, a player has to participate in at least 30% of the matches 
     721    uint32 min_plays = ceil(stats.games * 0.3); 
     722    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     723    { 
     724        // the player participated in enough games, update his points 
     725        if(itr->played_week >= min_plays) 
     726        { 
     727            // do it separately for online and offline players 
     728            // online players might have modified personal rating in MemberLost/MemberWon, that's not already saved to DB because of asynch queries 
     729            // offline player cant have a personal rating not matching the db 
     730            Player * plr = objmgr.GetPlayer(itr->guid); 
     731            uint32 points_to_add = 0; 
     732            if(plr) 
     733                points_to_add = GetPoints(plr->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5)); 
     734            else 
     735                points_to_add = GetPoints(Player::GetUInt32ValueFromDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5,itr->guid)); 
     736            // it's enough to set the points in memory, the saving is done in separate function 
     737            CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid); 
     738        } 
     739        // the player failed to participate in enough games, so no points for him 
     740        else 
     741        { 
     742            CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", 0, Id, itr->guid); 
     743        } 
     744    } 
     745} 
     746 
     747void ArenaTeam::SaveToDB() 
     748{ 
     749    // save team and member stats to db 
     750    // called after a match has ended 
     751    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, stats.played, stats.rank, stats.wins, stats.wins2, GetId()); 
     752    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     753    { 
     754        CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->played_week, itr->wons_week, itr->played_season, itr->wons_season, Id, itr->guid); 
     755    } 
     756} 
     757 
     758void ArenaTeam::FinishWeek() 
     759{ 
     760    stats.games = 0; // played this week 
     761    stats.wins = 0; // wins this week 
     762    for(MemberList::iterator itr = members.begin(); itr !=  members.end(); ++itr) 
     763    { 
     764        itr->played_week = 0; 
     765        itr->wons_week = 0; 
     766    } 
     767} 
     768 
    497769/* 
    498770arenateam fields (id from 2.3.3 client): 
    4997711414 - arena team id 2v2 
    5007721415 - 0=captain, 1=member 
    501 1416 - played this season 
    502 1417 - played this week 
     7731416 - played this week 
     7741417 - played this season 
    5037751418 - unk 
    504 1419 - unk 
     7761419 - personal arena rating 
    5057771420 - arena team id 3v3 
    5067781421 - 0=captain, 1=member 
    507 1422 - played this season 
    508 1423 - played this week 
     7791422 - played this week 
     7801423 - played this season 
    5097811424 - unk 
    510 1425 - unk 
     7821425 - personal arena rating 
    5117831426 - arena team id 5v5 
    5127841427 - 0=captain, 1=member 
    513 1428 - played this season 
    514 1429 - played this week 
     7851428 - played this week 
     7861429 - played this season 
    5157871430 - unk 
    516 1431 - unk 
     7881431 - personal arena rating 
    517789*/