diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 9a3f317809..c82ad51415 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -5394,7 +5394,7 @@ ACMD_FUNC(skilloff) *------------------------------------------*/ ACMD_FUNC(npcmove) { - short x = 0, y = 0, m; + short x = 0, y = 0; struct npc_data *nd = 0; char npc_name[NPC_NAME_LENGTH]; @@ -5412,18 +5412,12 @@ ACMD_FUNC(npcmove) return -1; } - if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) - { + if ( npc_movenpc( nd, x, y ) ) + { //actually failed to move clif_displaymessage(fd, msg_txt(sd,1154)); // NPC is not on this map. return -1; //Not on a map. - } - - x = cap_value(x, 0, map[m].xs-1); - y = cap_value(y, 0, map[m].ys-1); - map_foreachinallrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); - map_moveblock(&nd->bl, x, y, gettick()); - map_foreachinallrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); - clif_displaymessage(fd, msg_txt(sd,1155)); // NPC moved. + } else + clif_displaymessage(fd, msg_txt(sd,1155)); // NPC moved return 0; } @@ -8307,14 +8301,12 @@ ACMD_FUNC(invite) return -1; } - if(did == 0) { + if(did == 0 || !duel_exist(did) ) { clif_displaymessage(fd, msg_txt(sd,350)); // "Duel: @invite without @duel." return 0; } - if(duel_list[did].max_players_limit > 0 && - duel_list[did].members_count >= duel_list[did].max_players_limit) { - + if( !duel_check_player_limit( duel_get_duelid(did) ) ){ clif_displaymessage(fd, msg_txt(sd,351)); // "Duel: Limit of players is reached." return 0; } @@ -8426,12 +8418,12 @@ ACMD_FUNC(accept) return 0; } - if(sd->duel_invite <= 0) { + if(sd->duel_invite <= 0 || !duel_exist(sd->duel_invite) ) { clif_displaymessage(fd, msg_txt(sd,360)); // "Duel: @accept without invititation." return 0; } - if( duel_list[sd->duel_invite].max_players_limit > 0 && duel_list[sd->duel_invite].members_count >= duel_list[sd->duel_invite].max_players_limit ) + if( duel_check_player_limit( duel_get_duelid( sd->duel_invite ) ) ) { clif_displaymessage(fd, msg_txt(sd,351)); // "Duel: Limit of players is reached." return 0; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 444670ec6e..ce45bdbcc0 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -6177,19 +6177,16 @@ void clif_displaymessage(const int fd, const char* mes) void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target) { int lp = (type&BC_COLOR_MASK) ? 4 : 0; - unsigned char *buf = (unsigned char*)aMalloc((4 + lp + len)*sizeof(unsigned char)); + std::unique_ptr buf(new unsigned char[4+lp+len]); - WBUFW(buf,0) = 0x9a; - WBUFW(buf,2) = 4 + lp + len; + WBUFW(buf.get(),0) = 0x9a; + WBUFW(buf.get(),2) = 4 + lp + len; if (type&BC_BLUE) - WBUFL(buf,4) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. + WBUFL(buf.get(),4) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. else if (type&BC_WOE) - WBUFL(buf,4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. - memcpy(WBUFP(buf, 4 + lp), mes, len); - clif_send(buf, WBUFW(buf,2), bl, target); - - if (buf) - aFree(buf); + WBUFL(buf.get(),4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. + memcpy(WBUFP(buf.get(), 4 + lp), mes, len); + clif_send(buf.get(), WBUFW(buf.get(),2), bl, target); } /*========================================== @@ -6197,8 +6194,7 @@ void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, e * 008d .W .L .?B (ZC_NOTIFY_CHAT) *------------------------------------------*/ void clif_GlobalMessage(struct block_list* bl, const char* message, enum send_target target) { - char buf[8+CHAT_SIZE_MAX]; - int len; + size_t len; nullpo_retv(bl); if(!message) @@ -6206,16 +6202,19 @@ void clif_GlobalMessage(struct block_list* bl, const char* message, enum send_ta len = strlen(message)+1; - if( len > sizeof(buf)-8 ) { + static_assert(CHAT_SIZE_MAX > 8, "CHAT_SIZE_MAX too small for packet"); + if( len > CHAT_SIZE_MAX ) { ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len); - len = sizeof(buf)-8; + len = CHAT_SIZE_MAX; } + std::unique_ptr buf(new char[8+len]); - WBUFW(buf,0)=0x8d; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=bl->id; - safestrncpy(WBUFCP(buf,8),message,len); - clif_send((unsigned char *) buf,WBUFW(buf,2),bl,target); + WBUFW(buf.get(),0)=0x8d; + WBUFW(buf.get(),2)=static_cast(len+8); + WBUFL(buf.get(),4)=bl->id; + safestrncpy(WBUFCP(buf.get(),8),message,len); + + clif_send((unsigned char *)buf.get(),WBUFW(buf.get(),2),bl,target); } @@ -6223,20 +6222,17 @@ void clif_GlobalMessage(struct block_list* bl, const char* message, enum send_ta /// 01c3 .W .L .W .W .W .W .?B void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target) { - unsigned char *buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char)); + std::unique_ptr buf(new unsigned char[16+len]); - WBUFW(buf,0) = 0x1c3; - WBUFW(buf,2) = len + 16; - WBUFL(buf,4) = fontColor; - WBUFW(buf,8) = fontType; - WBUFW(buf,10) = fontSize; - WBUFW(buf,12) = fontAlign; - WBUFW(buf,14) = fontY; - memcpy(WBUFP(buf,16), mes, len); - clif_send(buf, WBUFW(buf,2), bl, target); - - if (buf) - aFree(buf); + WBUFW(buf.get(),0) = 0x1c3; + WBUFW(buf.get(),2) = len + 16; + WBUFL(buf.get(),4) = fontColor; + WBUFW(buf.get(),8) = fontType; + WBUFW(buf.get(),10) = fontSize; + WBUFW(buf.get(),12) = fontAlign; + WBUFW(buf.get(),14) = fontY; + memcpy(WBUFP(buf.get(),16), mes, len); + clif_send(buf.get(), WBUFW(buf.get(),2), bl, target); } /* diff --git a/src/map/duel.cpp b/src/map/duel.cpp index 1cda9a0430..09e1f72057 100644 --- a/src/map/duel.cpp +++ b/src/map/duel.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -15,11 +16,34 @@ #include "pc.hpp" #include "battle.hpp" -//global var (extern) -struct duel duel_list[MAX_DUEL]; //list of current duel -int duel_count = 0; //number of duel active +//std::recursive_mutex> duel_list_mutex; //preparation for multithread +std::unordered_map duel_list; -static void duel_set(const unsigned int did, struct map_session_data* sd); +std::unordered_map 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, struct map_session_data* sd); /* * Save the current time of the duel in PC_LAST_DUEL_TIME @@ -38,7 +62,7 @@ void duel_savetime(struct map_session_data* sd) /* * Check if the time elapsed between last duel is enough to launch another. */ -int duel_checktime(struct map_session_data* sd) +bool duel_checktime(struct map_session_data* sd) { int diff; time_t timer; @@ -52,6 +76,18 @@ int duel_checktime(struct map_session_data* sd) 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 */ @@ -59,10 +95,11 @@ static int duel_showinfo_sub(struct map_session_data* sd, va_list va) { struct map_session_data *ssd = va_arg(va, struct map_session_data*); int *p = va_arg(va, int*); + + if (sd->duel_group != ssd->duel_group) + return 0; + char output[256]; - - if (sd->duel_group != ssd->duel_group) return 0; - sprintf(output, " %d. %s", ++(*p), sd->status.name); clif_messagecolor(&ssd->bl, color_table[COLOR_LIGHT_GREEN], output, false, SELF); return 1; @@ -72,20 +109,24 @@ static int duel_showinfo_sub(struct map_session_data* sd, va_list va) * Display duel infos, * Number of duely... */ -void duel_showinfo(const unsigned int did, struct map_session_data* sd) +void duel_showinfo(const size_t did, struct map_session_data* sd) { + //std::lock_guard _(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_count, + 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_count, + did, duel_counttotal(), duel_list[did].members_count, duel_list[did].members_count + duel_list[did].invites_count); @@ -96,7 +137,7 @@ void duel_showinfo(const unsigned int did, struct map_session_data* sd) /* * Moves sd to duel */ -static void duel_set(const unsigned int did, struct map_session_data* sd) { +static void duel_set(const size_t did, struct map_session_data* sd) { sd->state.changemap = 1; sd->state.warping = 1; @@ -115,28 +156,27 @@ static void duel_set(const unsigned int did, struct map_session_data* sd) { /* * Create a new duel for sd - * return duel_id or 0 when fail + * return new duel_id or 0 when fail */ -int duel_create(struct map_session_data* sd, const unsigned int maxpl) +size_t duel_create(struct map_session_data* sd, const unsigned int maxpl) { - int i=1; + static size_t lastID=0; + lastID++; + + { //mutex scope + //std::lock_guard _(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]; - - while(duel_list[i].members_count > 0 && i < MAX_DUEL) i++; - if(i == MAX_DUEL) return 0; - - duel_count++; - duel_set(i, sd); - duel_list[i].members_count++; - duel_list[i].invites_count = 0; - duel_list[i].max_players_limit = maxpl; - 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 i; + return lastID; } /* @@ -145,20 +185,23 @@ int duel_create(struct map_session_data* sd, const unsigned int maxpl) * @sd = inviting player * @target_sd = invited player */ -void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd) +bool duel_invite(const size_t did, struct map_session_data* sd, struct map_session_data* target_sd) { - 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); + //std::lock_guard _(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; } /* @@ -168,7 +211,7 @@ void duel_invite(const unsigned int did, struct map_session_data* sd, struct map */ static int duel_leave_sub(struct map_session_data* sd, va_list va) { - int did = va_arg(va, int); + size_t did = va_arg(va, size_t); if (sd->duel_invite == did) sd->duel_invite = 0; return 0; @@ -179,24 +222,27 @@ static int duel_leave_sub(struct map_session_data* sd, va_list va) * @did = duel id * @sd = leaving player */ -void duel_leave(const unsigned int did, struct map_session_data* sd) +bool duel_leave(const size_t did, struct map_session_data* 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); + //std::lock_guard _(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_count--; + 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; } /* @@ -204,21 +250,26 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) * @did = duel id * @sd = player accepting duel */ -void duel_accept(const unsigned int did, struct map_session_data* sd) +bool duel_accept(const size_t did, struct map_session_data* sd) { - char output[256]; + { //mutex scope + //std::lock_guard _(duel_list_mutex); + if ( !duel_exist( did ) ) + return false; - duel_list[did].members_count++; - duel_set(sd->duel_invite, sd); - duel_list[did].invites_count--; + 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; } /* @@ -226,16 +277,22 @@ void duel_accept(const unsigned int did, struct map_session_data* sd) * @did = duel id * @sd = player refusing duel */ -void duel_reject(const unsigned int did, struct map_session_data* sd) +bool duel_reject(const size_t did, struct map_session_data* sd) { - char output[256]; + { + //std::lock_guard _(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); - - duel_list[did].invites_count--; - sd->duel_invite = 0; + return true; } /* @@ -244,11 +301,12 @@ void duel_reject(const unsigned int did, struct map_session_data* sd) */ void do_final_duel(void) { + duel_list.clear(); } /* * Initialisator of duel module */ void do_init_duel(void) { - memset(&duel_list[0], 0, sizeof(duel_list)); + duel_list.clear(); } diff --git a/src/map/duel.hpp b/src/map/duel.hpp index b479fec5b1..03ac699dfb 100644 --- a/src/map/duel.hpp +++ b/src/map/duel.hpp @@ -1,6 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder - +#pragma once #ifndef _DUEL_HPP_ #define _DUEL_HPP_ @@ -12,18 +12,20 @@ struct duel { int max_players_limit; }; -#define MAX_DUEL 1024 //max number of duels on server -extern struct duel duel_list[MAX_DUEL]; //list of current duel -extern int duel_count; //current number of duel on server +duel& duel_get_duelid( size_t did ); +bool duel_exist( size_t did ); +size_t duel_counttotal(); +size_t duel_countactives(); //Duel functions // [LuzZza] -int duel_create(struct map_session_data* sd, const unsigned int maxpl); -void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd); -void duel_accept(const unsigned int did, struct map_session_data* sd); -void duel_reject(const unsigned int did, struct map_session_data* sd); -void duel_leave(const unsigned int did, struct map_session_data* sd); -void duel_showinfo(const unsigned int did, struct map_session_data* sd); -int duel_checktime(struct map_session_data* sd); +size_t duel_create(struct map_session_data* sd, const unsigned int maxpl); +bool duel_invite(const size_t did, struct map_session_data* sd, struct map_session_data* target_sd); +bool duel_accept(const size_t did, struct map_session_data* sd); +bool duel_reject(const size_t did, struct map_session_data* sd); +bool duel_leave(const size_t did, struct map_session_data* sd); +void duel_showinfo(const size_t did, struct map_session_data* sd); +bool duel_checktime(struct map_session_data* sd); +bool duel_check_player_limit( struct duel& pDuel ); void do_init_duel(void); void do_final_duel(void); diff --git a/src/map/map.cpp b/src/map/map.cpp index 6b923687d3..805f09570e 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -2720,7 +2720,7 @@ int map_addmobtolist(unsigned short m, struct spawn_data *spawn) if( i < MAX_MOB_LIST_PER_MAP ) { map[m].moblist[i] = spawn; - return i; + return static_cast(i); } return -1; } diff --git a/src/map/npc.cpp b/src/map/npc.cpp index 7cdc07ae59..281510dec9 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -3595,10 +3595,11 @@ void npc_unsetcells(struct npc_data* nd) map_foreachinallarea( npc_unsetcells_sub, m, x0, y0, x1, y1, BL_NPC, nd->bl.id ); } -void npc_movenpc(struct npc_data* nd, int16 x, int16 y) +bool npc_movenpc(struct npc_data* nd, int16 x, int16 y) { const int16 m = nd->bl.m; - if (m < 0 || nd->bl.prev == NULL) return; //Not on a map. + if (m < 0 || nd->bl.prev == NULL) + return false; //Not on a map. x = cap_value(x, 0, map[m].xs-1); y = cap_value(y, 0, map[m].ys-1); @@ -3606,6 +3607,7 @@ void npc_movenpc(struct npc_data* nd, int16 x, int16 y) map_foreachinallrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); map_moveblock(&nd->bl, x, y, gettick()); map_foreachinallrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + return true; } /// Changes the display name of the npc. diff --git a/src/map/npc.hpp b/src/map/npc.hpp index a57653a025..a3a198a969 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -1138,7 +1138,7 @@ const char *npc_get_script_event_name(int npce_index); void npc_setcells(struct npc_data* nd); void npc_unsetcells(struct npc_data* nd); -void npc_movenpc(struct npc_data* nd, int16 x, int16 y); +bool npc_movenpc(struct npc_data* nd, int16 x, int16 y); int npc_enable(const char* name, int flag); void npc_setdisplayname(struct npc_data* nd, const char* newname); void npc_setclass(struct npc_data* nd, short class_); diff --git a/src/map/pc.hpp b/src/map/pc.hpp index d379841050..54b6fa275e 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -572,8 +572,8 @@ struct map_session_data { char fakename[NAME_LENGTH]; // fake names [Valaris] - int duel_group; // duel vars [LuzZza] - int duel_invite; + size_t duel_group; // duel vars [LuzZza] + size_t duel_invite; int killerrid, killedrid; diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 499dfd85da..72fbb8ecf7 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -21520,8 +21520,8 @@ static void skill_readdb(void) skill_changematerial_count = skill_spellbook_count = skill_magicmushroom_count = 0; for(i=0; i