123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
- // For more information, see LICENCE in the main folder
- #include "duel.hpp"
- #include <cstdio>
- #include <cstring>
- #include <unordered_map>
- #include <common/cbasetypes.hpp>
- #include <common/timer.hpp>
- #include "atcommand.hpp" // msg_txt
- #include "battle.hpp"
- #include "clif.hpp"
- #include "pc.hpp"
- //std::recursive_mutex> duel_list_mutex; //preparation for multithread
- std::unordered_map<size_t,struct duel> duel_list;
- std::unordered_map<size_t,struct duel> duel_get_list() { return duel_list; } //this could be exposed but not really necessarly, (hiden impl)
- bool duel_exist( size_t did ) { return duel_list.find( did ) != duel_list.end(); }
- duel& duel_get_duelid(size_t did) { return duel_list.at(did); }
- /**
- * Number of duels created
- * @return duel_list size
- */
- size_t duel_counttotal() {
- return duel_list.size();
- }
- /**
- * Number of active duels (player has accepted the duel)
- * @return active duels
- */
- size_t duel_countactives()
- {
- size_t count = 0;
- for ( const auto& lcur : duel_list )
- if ( lcur.second.members_count > 1 ) ++count;
- return count;
- }
- static void duel_set(const size_t did, map_session_data* sd);
- /*
- * Save the current time of the duel in PC_LAST_DUEL_TIME
- */
- void duel_savetime(map_session_data* sd)
- {
- time_t timer;
- struct tm *t;
- time(&timer);
- t = localtime(&timer);
- pc_setglobalreg(sd, add_str("PC_LAST_DUEL_TIME"), t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min);
- }
- /*
- * Check if the time elapsed between last duel is enough to launch another.
- */
- bool duel_checktime(map_session_data* sd)
- {
- int64 diff;
- time_t timer;
- struct tm *t;
- time(&timer);
- t = localtime(&timer);
- diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, add_str("PC_LAST_DUEL_TIME"));
- return !(diff >= 0 && diff < battle_config.duel_time_interval);
- }
- /*
- * Check if duel respect the member limit
- */
- bool duel_check_player_limit(struct duel& pDuel)
- {
- if(pDuel.max_players_limit > 0 &&
- pDuel.members_count >= pDuel.max_players_limit) {
- return false;
- }
- return true;
- }
- /*
- * Display opponents name of sd
- */
- static int duel_showinfo_sub(map_session_data* sd, va_list va)
- {
- map_session_data *ssd = va_arg(va, map_session_data*);
- int *p = va_arg(va, int*);
- if (sd->duel_group != ssd->duel_group)
- return 0;
- char output[256];
- sprintf(output, " %d. %s", ++(*p), sd->status.name);
- clif_messagecolor(&ssd->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF);
- return 1;
- }
- /*
- * Display duel infos,
- * Number of duely...
- */
- void duel_showinfo(const size_t did, map_session_data* sd)
- {
- //std::lock_guard<std::recursive_mutex> _(duel_list_mutex); //or shared_ptr
- if ( !duel_exist( did ) )
- return;
- int p=0;
- char output[256];
- if(duel_list[did].max_players_limit > 0)
- sprintf(output, msg_txt(sd,370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --"
- did, duel_counttotal(),
- duel_list[did].members_count,
- duel_list[did].members_count + duel_list[did].invites_count,
- duel_list[did].max_players_limit);
- else
- sprintf(output, msg_txt(sd,371), //" -- Duels: %d/%d, Members: %d/%d --"
- did, duel_counttotal(),
- duel_list[did].members_count,
- duel_list[did].members_count + duel_list[did].invites_count);
- clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF);
- map_foreachpc(duel_showinfo_sub, sd, &p);
- }
- /*
- * Moves sd to duel
- */
- static void duel_set(const size_t did, map_session_data* sd) {
- sd->state.changemap = 1;
- sd->state.warping = 1;
- // As you move to a different plane, ground effects need to be cleared
- skill_clear_unitgroup(&sd->bl);
- skill_unit_move(&sd->bl, gettick(), 2);
- skill_cleartimerskill(&sd->bl);
- sd->duel_group = did;
- skill_unit_move(&sd->bl, gettick(), 3);
- sd->state.changemap = 0;
- sd->state.warping = 0;
- }
- /*
- * Create a new duel for sd
- * return new duel_id or 0 when fail
- */
- size_t duel_create(map_session_data* sd, const uint32 maxpl)
- {
- static size_t lastID=0;
- lastID++;
- { //mutex scope
- //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
- duel_list[lastID].members_count++;
- duel_list[lastID].invites_count = 0;
- duel_list[lastID].max_players_limit = maxpl;
- }
- duel_set(lastID, sd);
- char output[256];
- strcpy(output, msg_txt(sd,372)); // " -- Duel has been created (@invite/@leave) --"
- clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF);
- clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
- //clif_misceffect2(&sd->bl, 159);
- return lastID;
- }
- /*
- * Invite opponent into the duel.
- * @did = duel id
- * @sd = inviting player
- * @target_sd = invited player
- */
- bool duel_invite(const size_t did, map_session_data* sd, map_session_data* target_sd)
- {
- //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
- if ( !duel_exist( did ) )
- return false;
- target_sd->duel_invite = did;
- duel_list[did].invites_count++;
- char output[256];
- // " -- Player %s invites %s to duel --"
- sprintf(output, msg_txt(sd,373), sd->status.name, target_sd->status.name);
- clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
- // "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
- sprintf(output, msg_txt(sd,374), sd->status.name);
- clif_broadcast((struct block_list *)target_sd, output, strlen(output)+1, BC_BLUE, SELF);
- return true;
- }
- /*
- * Sub function to loop trough all duely to remove invite for sd
- * @sd = leaving player
- * @va = list(only contain duel_id atm)
- */
- static int duel_leave_sub(map_session_data* sd, va_list va)
- {
- size_t did = va_arg(va, size_t);
- if (sd->duel_invite == did)
- sd->duel_invite = 0;
- return 0;
- }
- /*
- * Make a player leave a duel
- * @did = duel id
- * @sd = leaving player
- */
- bool duel_leave(const size_t did, map_session_data* sd)
- {
- //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
- if ( !duel_exist( did ) )
- return false;
- duel_list[did].members_count--;
- if(duel_list[did].members_count == 0) {
- map_foreachpc(duel_leave_sub, did);
- duel_list.erase( did );
- }
- duel_set(0, sd);
- duel_savetime(sd);
- char output[256];
- // " <- Player %s has left duel --"
- sprintf(output, msg_txt(sd,375), sd->status.name);
- clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
- clif_map_property(&sd->bl, MAPPROPERTY_NOTHING, SELF);
- return true;
- }
- /*
- * Make a player accept a duel
- * @did = duel id
- * @sd = player accepting duel
- */
- bool duel_accept(const size_t did, map_session_data* sd)
- {
- { //mutex scope
- //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
- if ( !duel_exist( did ) )
- return false;
- duel_list[did].members_count++;
- duel_list[did].invites_count--;
- }
- duel_set( sd->duel_invite, sd );
- sd->duel_invite = 0;
- char output[256];
- // " -> Player %s has accepted duel --"
- sprintf(output, msg_txt(sd,376), sd->status.name);
- clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
- clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
- //clif_misceffect2(&sd->bl, 159);
- return true;
- }
- /*
- * Make a player decline a duel
- * @did = duel id
- * @sd = player refusing duel
- */
- bool duel_reject(const size_t did, map_session_data* sd)
- {
- {
- //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
- if ( !duel_exist( did ) )
- return false;
- duel_list[did].invites_count--;
- sd->duel_invite = 0;
- }
- char output[256];
- // " -- Player %s has rejected duel --"
- sprintf(output, msg_txt(sd,377), sd->status.name);
- clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
- return true;
- }
- /*
- * Destructor of duel module
- * Put cleanup code here before server end
- */
- void do_final_duel(void)
- {
- duel_list.clear();
- }
- /*
- * Initialisator of duel module
- */
- void do_init_duel(void) {
- duel_list.clear();
- }
|