duel.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "duel.hpp"
  4. #include <cstdio>
  5. #include <cstring>
  6. #include <unordered_map>
  7. #include <common/cbasetypes.hpp>
  8. #include <common/timer.hpp>
  9. #include "atcommand.hpp" // msg_txt
  10. #include "battle.hpp"
  11. #include "clif.hpp"
  12. #include "pc.hpp"
  13. //std::recursive_mutex> duel_list_mutex; //preparation for multithread
  14. std::unordered_map<size_t,struct duel> duel_list;
  15. std::unordered_map<size_t,struct duel> duel_get_list() { return duel_list; } //this could be exposed but not really necessarly, (hiden impl)
  16. bool duel_exist( size_t did ) { return duel_list.find( did ) != duel_list.end(); }
  17. duel& duel_get_duelid(size_t did) { return duel_list.at(did); }
  18. /**
  19. * Number of duels created
  20. * @return duel_list size
  21. */
  22. size_t duel_counttotal() {
  23. return duel_list.size();
  24. }
  25. /**
  26. * Number of active duels (player has accepted the duel)
  27. * @return active duels
  28. */
  29. size_t duel_countactives()
  30. {
  31. size_t count = 0;
  32. for ( const auto& lcur : duel_list )
  33. if ( lcur.second.members_count > 1 ) ++count;
  34. return count;
  35. }
  36. static void duel_set(const size_t did, map_session_data* sd);
  37. /*
  38. * Save the current time of the duel in PC_LAST_DUEL_TIME
  39. */
  40. void duel_savetime(map_session_data* sd)
  41. {
  42. time_t timer;
  43. struct tm *t;
  44. time(&timer);
  45. t = localtime(&timer);
  46. pc_setglobalreg(sd, add_str("PC_LAST_DUEL_TIME"), t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min);
  47. }
  48. /*
  49. * Check if the time elapsed between last duel is enough to launch another.
  50. */
  51. bool duel_checktime(map_session_data* sd)
  52. {
  53. int64 diff;
  54. time_t timer;
  55. struct tm *t;
  56. time(&timer);
  57. t = localtime(&timer);
  58. diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, add_str("PC_LAST_DUEL_TIME"));
  59. return !(diff >= 0 && diff < battle_config.duel_time_interval);
  60. }
  61. /*
  62. * Check if duel respect the member limit
  63. */
  64. bool duel_check_player_limit(struct duel& pDuel)
  65. {
  66. if(pDuel.max_players_limit > 0 &&
  67. pDuel.members_count >= pDuel.max_players_limit) {
  68. return false;
  69. }
  70. return true;
  71. }
  72. /*
  73. * Display opponents name of sd
  74. */
  75. static int duel_showinfo_sub(map_session_data* sd, va_list va)
  76. {
  77. map_session_data *ssd = va_arg(va, map_session_data*);
  78. int *p = va_arg(va, int*);
  79. if (sd->duel_group != ssd->duel_group)
  80. return 0;
  81. char output[256];
  82. sprintf(output, " %d. %s", ++(*p), sd->status.name);
  83. clif_messagecolor(&ssd->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF);
  84. return 1;
  85. }
  86. /*
  87. * Display duel infos,
  88. * Number of duely...
  89. */
  90. void duel_showinfo(const size_t did, map_session_data* sd)
  91. {
  92. //std::lock_guard<std::recursive_mutex> _(duel_list_mutex); //or shared_ptr
  93. if ( !duel_exist( did ) )
  94. return;
  95. int p=0;
  96. char output[256];
  97. if(duel_list[did].max_players_limit > 0)
  98. sprintf(output, msg_txt(sd,370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --"
  99. did, duel_counttotal(),
  100. duel_list[did].members_count,
  101. duel_list[did].members_count + duel_list[did].invites_count,
  102. duel_list[did].max_players_limit);
  103. else
  104. sprintf(output, msg_txt(sd,371), //" -- Duels: %d/%d, Members: %d/%d --"
  105. did, duel_counttotal(),
  106. duel_list[did].members_count,
  107. duel_list[did].members_count + duel_list[did].invites_count);
  108. clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF);
  109. map_foreachpc(duel_showinfo_sub, sd, &p);
  110. }
  111. /*
  112. * Moves sd to duel
  113. */
  114. static void duel_set(const size_t did, map_session_data* sd) {
  115. sd->state.changemap = 1;
  116. sd->state.warping = 1;
  117. // As you move to a different plane, ground effects need to be cleared
  118. skill_clear_unitgroup(&sd->bl);
  119. skill_unit_move(&sd->bl, gettick(), 2);
  120. skill_cleartimerskill(&sd->bl);
  121. sd->duel_group = did;
  122. skill_unit_move(&sd->bl, gettick(), 3);
  123. sd->state.changemap = 0;
  124. sd->state.warping = 0;
  125. }
  126. /*
  127. * Create a new duel for sd
  128. * return new duel_id or 0 when fail
  129. */
  130. size_t duel_create(map_session_data* sd, const uint32 maxpl)
  131. {
  132. static size_t lastID=0;
  133. lastID++;
  134. { //mutex scope
  135. //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
  136. duel_list[lastID].members_count++;
  137. duel_list[lastID].invites_count = 0;
  138. duel_list[lastID].max_players_limit = maxpl;
  139. }
  140. duel_set(lastID, sd);
  141. char output[256];
  142. strcpy(output, msg_txt(sd,372)); // " -- Duel has been created (@invite/@leave) --"
  143. clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF);
  144. clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
  145. //clif_misceffect2(&sd->bl, 159);
  146. return lastID;
  147. }
  148. /*
  149. * Invite opponent into the duel.
  150. * @did = duel id
  151. * @sd = inviting player
  152. * @target_sd = invited player
  153. */
  154. bool duel_invite(const size_t did, map_session_data* sd, map_session_data* target_sd)
  155. {
  156. //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
  157. if ( !duel_exist( did ) )
  158. return false;
  159. target_sd->duel_invite = did;
  160. duel_list[did].invites_count++;
  161. char output[256];
  162. // " -- Player %s invites %s to duel --"
  163. sprintf(output, msg_txt(sd,373), sd->status.name, target_sd->status.name);
  164. clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
  165. // "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
  166. sprintf(output, msg_txt(sd,374), sd->status.name);
  167. clif_broadcast((struct block_list *)target_sd, output, strlen(output)+1, BC_BLUE, SELF);
  168. return true;
  169. }
  170. /*
  171. * Sub function to loop trough all duely to remove invite for sd
  172. * @sd = leaving player
  173. * @va = list(only contain duel_id atm)
  174. */
  175. static int duel_leave_sub(map_session_data* sd, va_list va)
  176. {
  177. size_t did = va_arg(va, size_t);
  178. if (sd->duel_invite == did)
  179. sd->duel_invite = 0;
  180. return 0;
  181. }
  182. /*
  183. * Make a player leave a duel
  184. * @did = duel id
  185. * @sd = leaving player
  186. */
  187. bool duel_leave(const size_t did, map_session_data* sd)
  188. {
  189. //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
  190. if ( !duel_exist( did ) )
  191. return false;
  192. duel_list[did].members_count--;
  193. if(duel_list[did].members_count == 0) {
  194. map_foreachpc(duel_leave_sub, did);
  195. duel_list.erase( did );
  196. }
  197. duel_set(0, sd);
  198. duel_savetime(sd);
  199. char output[256];
  200. // " <- Player %s has left duel --"
  201. sprintf(output, msg_txt(sd,375), sd->status.name);
  202. clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
  203. clif_map_property(&sd->bl, MAPPROPERTY_NOTHING, SELF);
  204. return true;
  205. }
  206. /*
  207. * Make a player accept a duel
  208. * @did = duel id
  209. * @sd = player accepting duel
  210. */
  211. bool duel_accept(const size_t did, map_session_data* sd)
  212. {
  213. { //mutex scope
  214. //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
  215. if ( !duel_exist( did ) )
  216. return false;
  217. duel_list[did].members_count++;
  218. duel_list[did].invites_count--;
  219. }
  220. duel_set( sd->duel_invite, sd );
  221. sd->duel_invite = 0;
  222. char output[256];
  223. // " -> Player %s has accepted duel --"
  224. sprintf(output, msg_txt(sd,376), sd->status.name);
  225. clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
  226. clif_map_property(&sd->bl, MAPPROPERTY_FREEPVPZONE, SELF);
  227. //clif_misceffect2(&sd->bl, 159);
  228. return true;
  229. }
  230. /*
  231. * Make a player decline a duel
  232. * @did = duel id
  233. * @sd = player refusing duel
  234. */
  235. bool duel_reject(const size_t did, map_session_data* sd)
  236. {
  237. {
  238. //std::lock_guard<std::recursive_mutex> _(duel_list_mutex);
  239. if ( !duel_exist( did ) )
  240. return false;
  241. duel_list[did].invites_count--;
  242. sd->duel_invite = 0;
  243. }
  244. char output[256];
  245. // " -- Player %s has rejected duel --"
  246. sprintf(output, msg_txt(sd,377), sd->status.name);
  247. clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
  248. return true;
  249. }
  250. /*
  251. * Destructor of duel module
  252. * Put cleanup code here before server end
  253. */
  254. void do_final_duel(void)
  255. {
  256. duel_list.clear();
  257. }
  258. /*
  259. * Initialisator of duel module
  260. */
  261. void do_init_duel(void) {
  262. duel_list.clear();
  263. }