Battleground Queue fixes (#4648)

* Fixes #4644.
* Initialize all battleground queues at startup to reduce overhead of creation/deletion during live server.
* Removes lots of duplicate code between team checks.
* Adds missing checks for script commands bg_leave and bg_desert to only warp players out using the Battleground Queue System.
* Adds documentation for script commands bg_leave and bg_desert to state players will be warped out after when using the Battleground Queue System.
* Optimizes join logic to add new players to the end of the queue rather than the front.
* Cleans up the client messages so certain responses are cleared when they need to be.
Thanks to @Balferian and @Lemongrass3110!
This commit is contained in:
Aleos 2020-02-20 22:25:14 -05:00 committed by GitHub
parent 55645b8d3d
commit 1fc4b8de20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 187 additions and 386 deletions

View File

@ -9390,6 +9390,9 @@ Note: 'bg_reserve' and 'bg_unbook' prevent the Battlegrounds queue from joining
Same as 'bg_leave' but slaps the player with a deserter status so they can't enter another queue for the time Same as 'bg_leave' but slaps the player with a deserter status so they can't enter another queue for the time
defined in battleground_db (10 minutes by default). defined in battleground_db (10 minutes by default).
With the Battleground Queue System, it will also warp the player to their previous position when they joined or
to their save point if the map had MF_NOSAVE.
--------------------------------------- ---------------------------------------
*bg_warp <Battle Group>,"<map name>",<x>,<y>; *bg_warp <Battle Group>,"<map name>",<x>,<y>;
@ -9451,6 +9454,9 @@ OnTimer1000:
Removes attached player from their Battle Group. Removes attached player from their Battle Group.
With the Battleground Queue System, it will also warp the player to their previous position when they joined or
to their save point if the map had MF_NOSAVE.
--------------------------------------- ---------------------------------------
*bg_destroy <Batte Group>; *bg_destroy <Batte Group>;

View File

@ -538,6 +538,7 @@ bat_b01,10,294,3 script Vintenar#bat_b01_aover 419,{
close; close;
} }
bg_leave; bg_leave;
if (!getbattleflag("feature.bgqueue"))
warp "bat_room",154,150; warp "bat_room",154,150;
end; end;
@ -562,6 +563,7 @@ bat_b01,389,14,3 script Vintenar#bat_b01_bover 415,{
close; close;
} }
bg_leave; bg_leave;
if (!getbattleflag("feature.bgqueue"))
warp "bat_room",154,150; warp "bat_room",154,150;
end; end;

View File

@ -539,6 +539,7 @@ bat_b02,10,294,3 script Vintenar#bat_b02_aover 419,{
close; close;
} }
bg_leave; bg_leave;
if (!getbattleflag("feature.bgqueue"))
warp "bat_room",154,150; warp "bat_room",154,150;
end; end;
@ -563,6 +564,7 @@ bat_b02,389,14,3 script Vintenar#bat_b02_bover 415,{
close; close;
} }
bg_leave; bg_leave;
if (!getbattleflag("feature.bgqueue"))
warp "bat_room",154,150; warp "bat_room",154,150;
end; end;

View File

@ -375,8 +375,8 @@ bat_c02,51,130,5 script KVM Officer#KVM02A 419,{
set Bat_Team,0; set Bat_Team,0;
if (!getbattleflag("feature.bgqueue")) if (!getbattleflag("feature.bgqueue"))
warp "bat_room",154,150; warp "bat_room",154,150;
end;
} }
end;
} }
bat_c02,148,53,1 duplicate(KVM Officer#KVM02A) KVM Officer#KVM02B 415 bat_c02,148,53,1 duplicate(KVM Officer#KVM02A) KVM Officer#KVM02B 415

View File

@ -723,7 +723,7 @@ bat_a02,45,19,3 script Croix Vintenar#a02_b 415,{
callfunc "F_BG_Badge",1,"Croix","Tierra"; callfunc "F_BG_Badge",1,"Croix","Tierra";
} }
bg_leave; bg_leave;
if (getbattleflag("feature.bgqueue")) if (!getbattleflag("feature.bgqueue"))
warp "bat_room",154,150; warp "bat_room",154,150;
end; end;

View File

@ -420,22 +420,26 @@ int bg_team_leave(struct map_session_data *sd, bool quit, bool deserter)
sd->bg_id = 0; sd->bg_id = 0;
if (bgteam) { if (bgteam) {
char output[CHAT_SIZE_MAX]; // Warping members out only applies to the Battleground Queue System
int i; if (battle_config.feature_bgqueue) {
auto member = bgteam->members.begin();
ARR_FIND(0, bgteam->members.size(), i, bgteam->members[i].sd == sd); while (member != bgteam->members.end()) {
if (i < bgteam->members.size()) { // Removes member from BG if (member->sd == sd && member->entry_point.map != 0) {
if (bgteam->members[i].entry_point.map != 0) { if (!map_getmapflag(map_mapindex2mapid(member->entry_point.map), MF_NOSAVE))
int16 map_id = map_mapindex2mapid(bgteam->members[i].entry_point.map); pc_setpos(sd, member->entry_point.map, member->entry_point.x, member->entry_point.y, CLR_TELEPORT);
if (!map_getmapflag(map_id, MF_NOSAVE))
pc_setpos(sd, bgteam->members[i].entry_point.map, bgteam->members[i].entry_point.x, bgteam->members[i].entry_point.y, CLR_TELEPORT);
else else
pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); // Warp to save point if the entry map has no save flag. pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); // Warp to save point if the entry map has no save flag.
bgteam->members.erase(member);
break;
} else
member++;
} }
util::erase_at(bgteam->members, i);
} }
char output[CHAT_SIZE_MAX];
if (quit) if (quit)
sprintf(output, "Server: %s has quit the game...", sd->status.name); sprintf(output, "Server: %s has quit the game...", sd->status.name);
else else
@ -681,7 +685,9 @@ static TIMER_FUNC(bg_on_ready_start)
nullpo_retr(1, queue); nullpo_retr(1, queue);
bg_queue_start_battleground(std::shared_ptr<s_battleground_queue>(queue)); queue->tid_start = INVALID_TIMER;
bg_queue_start_battleground(queue);
return 0; return 0;
} }
@ -794,154 +800,25 @@ bool bg_queue_reservation(const char *name, bool state)
return false; return false;
} }
/**
* Initialize a Battleground queue
* @param bg_id: Battleground ID
* @param req_players: Required amount of players
* @return s_battleground_queue*
*/
std::shared_ptr<s_battleground_queue> bg_queue_create(int bg_id, int req_players)
{
auto queue = std::make_shared<s_battleground_queue>();
queue->id = bg_id;
queue->required_players = req_players;
queue->accepted_players = 0;
queue->tid_expire = INVALID_TIMER;
queue->tid_start = INVALID_TIMER;
queue->tid_requeue = INVALID_TIMER;
queue->in_ready_state = false;
return queue;
}
/**
* Allow a player to join a Battleground queue
* @param name: Battleground name
* @param sd: Player data
* @return @see e_bg_queue_apply_ack
*/
e_bg_queue_apply_ack bg_queue_join(const char *name, struct map_session_data *sd)
{
if (!sd) {
ShowError("bg_queue_join: Tried to join non-existent player.\n.");
return BG_APPLY_NONE;
}
if (!bg_queue_check_status(sd, name))
return BG_APPLY_NONE;
if (bg_player_is_in_bg_map(sd)) {
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You may not join a battleground queue when you're in a battleground map.
return BG_APPLY_NONE;
}
std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
if (!bg) {
ShowWarning("bq_queue_join: Could not find battleground \"%s\" requested by %s (AID: %d / CID: %d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
return BG_APPLY_INVALID_NAME;
}
if (bg->min_lvl && sd->status.base_level < bg->min_lvl)
return BG_APPLY_PLAYER_LEVEL; // Level too low
if (bg->max_lvl && sd->status.base_level > bg->max_lvl)
return BG_APPLY_PLAYER_LEVEL; // Level too high
std::shared_ptr<s_battleground_queue> queue;
bool r;
if (bg_queues.empty()) {
r = rnd() % 2 != 0;
queue = bg_queue_create(bg->id, bg->required_players);
if (!r)
queue->teama_members.push_back(sd);
else
queue->teamb_members.push_back(sd);
sd->bg_queue = queue;
bg_queues.insert(bg_queues.begin(), queue);
return BG_APPLY_ACCEPT;
} else {
r = rnd() % 2 != 0;
for (const auto &it : bg_queues) {
try {
queue = it;
} catch (std::out_of_range &) {
continue;
}
if (queue->in_ready_state)
continue;
if (!r) {
if (queue->teama_members.size() != queue->required_players) {
sd->bg_queue = queue;
queue->teama_members.push_back(sd);
if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
bg_queue_on_ready(name, queue);
return BG_APPLY_ACCEPT;
} else if (queue->teamb_members.size() != queue->required_players) {
sd->bg_queue = queue;
queue->teamb_members.push_back(sd);
if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
bg_queue_on_ready(name, queue);
return BG_APPLY_ACCEPT;
}
} else {
if (queue->teamb_members.size() != queue->required_players) {
sd->bg_queue = queue;
queue->teamb_members.push_back(sd);
if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
bg_queue_on_ready(name, queue);
return BG_APPLY_ACCEPT;
} else if (queue->teama_members.size() != queue->required_players) {
sd->bg_queue = queue;
queue->teama_members.push_back(sd);
if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
bg_queue_on_ready(name, queue);
return BG_APPLY_ACCEPT;
}
}
}
}
queue = bg_queue_create(bg->id, bg->required_players);
r = rnd() % 2 != 0;
if (!r)
queue->teama_members.push_back(sd);
else
queue->teamb_members.push_back(sd);
sd->bg_queue = queue;
bg_queues.insert(bg_queues.begin(), queue);
return BG_APPLY_ACCEPT;
}
/** /**
* Join a party onto the same side of a Battleground * Join a party onto the same side of a Battleground
* @param name: Battleground name * @param name: Battleground name
* @param sd: Player who requested to join the battlegrounds * @param sd: Player who requested to join the battlegrounds
* @return @see e_bg_queue_apply_ack
*/ */
e_bg_queue_apply_ack bg_queue_join_party(const char *name, struct map_session_data *sd) void bg_queue_join_party(const char *name, struct map_session_data *sd)
{ {
struct party_data *p = party_search(sd->status.party_id); struct party_data *p = party_search(sd->status.party_id);
if (!p) if (!p) {
return BG_APPLY_INVALID_APP; // Someone has bypassed the client check for being in a party clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd);
return; // Someone has bypassed the client check for being in a party
}
for (const auto &it : p->party.member) { for (const auto &it : p->party.member) {
if (it.leader && sd->status.char_id != it.char_id) if (it.leader && sd->status.char_id != it.char_id) {
return BG_APPLY_PARTYGUILD_LEADER; // Not the party leader clif_bg_queue_apply_result(BG_APPLY_PARTYGUILD_LEADER, name, sd);
return; // Not the party leader
}
} }
std::shared_ptr<s_battleground_type> bg = bg_search_name(name); std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
@ -954,8 +831,10 @@ e_bg_queue_apply_ack bg_queue_join_party(const char *name, struct map_session_da
p_online++; p_online++;
} }
if (p_online > bg->max_players) if (p_online > bg->max_players) {
return BG_APPLY_PLAYER_COUNT; // Too many party members online clif_bg_queue_apply_result(BG_APPLY_PLAYER_COUNT, name, sd);
return; // Too many party members online
}
std::vector<struct map_session_data *> list; std::vector<struct map_session_data *> list;
@ -971,10 +850,11 @@ e_bg_queue_apply_ack bg_queue_join_party(const char *name, struct map_session_da
} }
} }
return bg_queue_join_multi(name, sd, list); // Join as party, all on the same side of the BG bg_queue_join_multi(name, sd, list); // Join as party, all on the same side of the BG
} else { } else {
ShowWarning("clif_parse_bg_queue_apply_request: Could not find Battleground: \"%s\" requested by player: %s (AID:%d CID:%d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id); ShowWarning("clif_parse_bg_queue_apply_request: Could not find Battleground: \"%s\" requested by player: %s (AID:%d CID:%d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
return BG_APPLY_INVALID_NAME; // Invalid BG name clif_bg_queue_apply_result(BG_APPLY_INVALID_NAME, name, sd);
return; // Invalid BG name
} }
} }
@ -982,30 +862,29 @@ e_bg_queue_apply_ack bg_queue_join_party(const char *name, struct map_session_da
* Join a guild onto the same side of a Battleground * Join a guild onto the same side of a Battleground
* @param name: Battleground name * @param name: Battleground name
* @param sd: Player who requested to join the battlegrounds * @param sd: Player who requested to join the battlegrounds
* @return @see e_bg_queue_apply_ack
*/ */
e_bg_queue_apply_ack bg_queue_join_guild(const char *name, struct map_session_data *sd) void bg_queue_join_guild(const char *name, struct map_session_data *sd)
{ {
if (!sd->guild) if (!sd->guild) {
return BG_APPLY_INVALID_APP; // Someone has bypassed the client check for being in a guild clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd);
return; // Someone has bypassed the client check for being in a guild
}
if (strcmp(sd->status.name, sd->guild->master) != 0) if (strcmp(sd->status.name, sd->guild->master) != 0) {
return BG_APPLY_PARTYGUILD_LEADER; // Not the guild leader clif_bg_queue_apply_result(BG_APPLY_PARTYGUILD_LEADER, name, sd);
return; // Not the guild leader
}
std::shared_ptr<s_battleground_type> bg = bg_search_name(name); std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
if (bg) { if (bg) {
struct guild *g = guild_search(sd->status.guild_id); struct guild* g = sd->guild;
int g_online = 0;
for (const auto &it : g->member) { if (g->connect_member > bg->max_players) {
if (it.online) clif_bg_queue_apply_result(BG_APPLY_PLAYER_COUNT, name, sd);
g_online++; return; // Too many guild members online
} }
if (g_online > bg->max_players)
return BG_APPLY_PLAYER_COUNT; // Too many guild members online
std::vector<struct map_session_data *> list; std::vector<struct map_session_data *> list;
for (const auto &it : g->member) { for (const auto &it : g->member) {
@ -1020,10 +899,11 @@ e_bg_queue_apply_ack bg_queue_join_guild(const char *name, struct map_session_da
} }
} }
return bg_queue_join_multi(name, sd, list); // Join as guild, all on the same side of the BG bg_queue_join_multi(name, sd, list); // Join as guild, all on the same side of the BG
} else { } else {
ShowWarning("clif_parse_bg_queue_apply_request: Could not find Battleground: \"%s\" requested by player: %s (AID:%d CID:%d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id); ShowWarning("clif_parse_bg_queue_apply_request: Could not find Battleground: \"%s\" requested by player: %s (AID:%d CID:%d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
return BG_APPLY_INVALID_NAME; // Invalid BG name clif_bg_queue_apply_result(BG_APPLY_INVALID_NAME, name, sd);
return; // Invalid BG name
} }
} }
@ -1032,96 +912,45 @@ e_bg_queue_apply_ack bg_queue_join_guild(const char *name, struct map_session_da
* @param name: Battleground name * @param name: Battleground name
* @param sd: Player who requested to join the battlegrounds * @param sd: Player who requested to join the battlegrounds
* @param list: Contains all players including the player who requested to join * @param list: Contains all players including the player who requested to join
* @return @see e_bg_queue_apply_ack
*/ */
e_bg_queue_apply_ack bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vector <map_session_data *> list) void bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vector <map_session_data *> list)
{ {
if (!sd) { if (!sd) {
ShowError("bg_queue_join_multi: Tried to join non-existent player\n."); ShowError("bg_queue_join_multi: Tried to join non-existent player\n.");
return BG_APPLY_NONE; return;
}
if (!bg_queue_check_status(sd, name))
return BG_APPLY_NONE;
if (bg_player_is_in_bg_map(sd)) {
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You may not join a battleground queue when you're in a battleground map.
return BG_APPLY_NONE;
} }
std::shared_ptr<s_battleground_type> bg = bg_search_name(name); std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
if (!bg) { if (!bg) {
ShowWarning("bq_queue_join_multi: Could not find battleground \"%s\" requested by %s (AID: %d / CID: %d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id); ShowWarning("bq_queue_join_multi: Could not find battleground \"%s\" requested by %s (AID: %d / CID: %d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
return BG_APPLY_INVALID_NAME; return;
} }
if (bg->min_lvl && sd->status.base_level < bg->min_lvl) if (!bg_queue_check_joinable(bg, sd, name)){
return BG_APPLY_PLAYER_LEVEL; // Level too low return;
if (bg->max_lvl && sd->status.base_level > bg->max_lvl)
return BG_APPLY_PLAYER_LEVEL; // Level too high
if (bg_queues.empty()) {
std::shared_ptr<s_battleground_queue> queue = bg_queue_create(bg->id, bg->required_players);
bool r = rnd() % 2 != 0;
if (!r) {
while (!list.empty() && queue->teama_members.size() < bg->required_players) {
struct map_session_data *sd2 = list.back();
list.pop_back();
if (!sd2 || sd2->bg_queue)
continue;
if (!bg_queue_check_joinable(bg, sd2, name))
continue;
sd2->bg_queue = queue;
clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
clif_bg_queue_apply_notify(name, sd2);
queue->teama_members.insert(queue->teama_members.begin(), sd2);
}
} else {
while (!list.empty() && queue->teamb_members.size() < bg->required_players) {
struct map_session_data *sd2 = list.back();
list.pop_back();
if (!sd2 || sd2->bg_queue)
continue;
if (!bg_queue_check_joinable(bg, sd2, name))
continue;
sd2->bg_queue = queue;
clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
clif_bg_queue_apply_notify(name, sd2);
queue->teamb_members.insert(queue->teamb_members.begin(), sd2);
}
} }
bg_queues.insert(bg_queues.begin(), queue); for (const auto &queue : bg_queues) {
if (queue->id != bg->id)
return BG_APPLY_ACCEPT;
} else {
std::shared_ptr<s_battleground_queue> queue;
bool r = rnd() % 2 != 0;
for (const auto &it : bg_queues) {
try {
queue = it;
} catch (std::out_of_range &) {
continue; continue;
}
if (queue->in_ready_state) if (queue->in_ready_state)
continue; continue;
if (queue->teama_members.size() + list.size() <= bg->required_players || queue->teamb_members.size() + list.size() <= bg->required_players) { // Make sure there's enough space on one side to join as a party/guild in this queue // Make sure there's enough space on one side to join as a party/guild in this queue
if (!r && queue->teama_members.size() + list.size() <= bg->required_players) { if (queue->teama_members.size() + list.size() > bg->required_players && queue->teamb_members.size() + list.size() > bg->required_players) {
while (!list.empty() && queue->teama_members.size() < bg->required_players) { break;
}
bool r = rnd() % 2 != 0;
std::vector<map_session_data *>* team = r ? &queue->teamb_members : &queue->teama_members;
// If the designated team is full, put the player into the other team
if (team->size() + list.size() > bg->required_players) {
team = r ? &queue->teama_members : &queue->teamb_members;
}
while (!list.empty() && team->size() < bg->required_players) {
struct map_session_data *sd2 = list.back(); struct map_session_data *sd2 = list.back();
list.pop_back(); list.pop_back();
@ -1133,85 +962,52 @@ e_bg_queue_apply_ack bg_queue_join_multi(const char *name, struct map_session_da
continue; continue;
sd2->bg_queue = queue; sd2->bg_queue = queue;
team->push_back(sd2);
clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2); clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
clif_bg_queue_apply_notify(name, sd2); clif_bg_queue_apply_notify(name, sd2);
queue->teama_members.insert(queue->teama_members.begin(), sd2);
} }
if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined // Enough players have joined
if (queue->teamb_members.size() == bg->required_players && queue->teama_members.size() == bg->required_players)
bg_queue_on_ready(name, queue); bg_queue_on_ready(name, queue);
return BG_APPLY_ACCEPT; return;
} else {
while (!list.empty() && queue->teamb_members.size() < bg->required_players) {
struct map_session_data *sd2 = list.back();
list.pop_back();
if (!sd2)
continue;
if (!bg_queue_check_joinable(bg, sd2, name))
continue;
sd2->bg_queue = queue;
clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
clif_bg_queue_apply_notify(name, sd2);
queue->teamb_members.insert(queue->teamb_members.begin(), sd2);
}
} }
return BG_APPLY_ACCEPT; // Something went wrong, sends reconnect and then reapply message to client.
} clif_bg_queue_apply_result(BG_APPLY_RECONNECT, name, sd);
} }
// Create a new queue if none of the existing ones are joinable for this party/guild /**
queue = nullptr; * Clear Battleground queue for next one
queue = bg_queue_create(bg->id, bg->required_players); * @param queue: Queue to clean up
r = rnd() % 2 != 0; */
static void bg_queue_clear(s_battleground_queue *queue)
{
if (!queue)
return;
if (!r) { if (queue->tid_requeue != INVALID_TIMER) {
while (!list.empty() && queue->teama_members.size() < bg->required_players) { delete_timer(queue->tid_requeue, bg_on_ready_loopback);
struct map_session_data *sd2 = list.back(); queue->tid_requeue = INVALID_TIMER;
list.pop_back();
if (!sd2 || sd2->bg_queue)
continue;
if (!bg_queue_check_joinable(bg, sd2, name))
continue;
sd2->bg_queue = queue;
clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
clif_bg_queue_apply_notify(name, sd2);
queue->teama_members.insert(queue->teama_members.begin(), sd2);
}
} else {
while (!list.empty() && queue->teamb_members.size() < bg->required_players) {
struct map_session_data *sd2 = list.back();
list.pop_back();
if (!sd2 || sd2->bg_queue)
continue;
if (!bg_queue_check_joinable(bg, sd2, name))
continue;
sd2->bg_queue = queue;
clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
clif_bg_queue_apply_notify(name, sd2);
queue->teamb_members.insert(queue->teamb_members.begin(), sd2);
}
} }
bg_queues.insert(bg_queues.begin(), queue); if (queue->tid_expire != INVALID_TIMER) {
delete_timer(queue->tid_expire, bg_on_ready_expire);
return BG_APPLY_ACCEPT; queue->tid_expire = INVALID_TIMER;
} }
return BG_APPLY_RECONNECT; // Something went wrong, sends reconnect and then reapply message to client. if (queue->tid_start != INVALID_TIMER) {
delete_timer(queue->tid_start, bg_on_ready_start);
queue->tid_start = INVALID_TIMER;
}
if (queue->map != nullptr) {
queue->map->isReserved = false; // Remove reservation to free up for future queue
queue->map = nullptr;
}
queue->in_ready_state = false;
queue->accepted_players = 0; // Reset the queue count
} }
/** /**
@ -1238,22 +1034,12 @@ static bool bg_queue_leave_sub(struct map_session_data *sd, std::vector<map_sess
sd->bg_queue_accept_state = false; sd->bg_queue_accept_state = false;
} }
list_it = lista.erase(list_it); lista.erase(list_it);
if (lista.empty() && listb.empty()) { // If there are no players left in the queue, discard it if (lista.empty() && listb.empty()) { // If there are no players left in the queue, discard it
auto queue_it = bg_queues.begin(); for (auto &queue : bg_queues) {
if (sd->bg_queue == queue)
while (queue_it != bg_queues.end()) { bg_queue_clear(queue.get());
std::shared_ptr<s_battleground_queue> q = *queue_it;
if (sd->bg_queue == q) {
if (q->tid_requeue != INVALID_TIMER && get_timer(q->tid_requeue)) {
delete_timer(q->tid_requeue, bg_on_ready_loopback);
q->tid_requeue = INVALID_TIMER;
}
queue_it = bg_queues.erase(queue_it);
}
} }
} }
@ -1349,7 +1135,7 @@ void bg_queue_on_accept_invite(std::shared_ptr<s_battleground_queue> queue, stru
if (queue->accepted_players == queue->required_players * 2) { if (queue->accepted_players == queue->required_players * 2) {
queue->tid_start = add_timer(gettick() + battleground_db.find(queue->id)->start_delay * 1000, bg_on_ready_start, 0, (intptr_t)queue.get()); queue->tid_start = add_timer(gettick() + battleground_db.find(queue->id)->start_delay * 1000, bg_on_ready_start, 0, (intptr_t)queue.get());
if (queue->tid_expire != INVALID_TIMER && get_timer(queue->tid_expire)) { if (queue->tid_expire != INVALID_TIMER) {
delete_timer(queue->tid_expire, bg_on_ready_expire); delete_timer(queue->tid_expire, bg_on_ready_expire);
queue->tid_expire = INVALID_TIMER; queue->tid_expire = INVALID_TIMER;
} }
@ -1360,13 +1146,8 @@ void bg_queue_on_accept_invite(std::shared_ptr<s_battleground_queue> queue, stru
* Begin the Battleground from the given queue * Begin the Battleground from the given queue
* @param queue: Battleground queue * @param queue: Battleground queue
*/ */
void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue) void bg_queue_start_battleground(s_battleground_queue *queue)
{ {
if (queue->tid_start != INVALID_TIMER && get_timer(queue->tid_start)) {
delete_timer(queue->tid_start, bg_on_ready_start);
queue->tid_start = INVALID_TIMER;
}
std::shared_ptr<s_battleground_type> bg = battleground_db.find(queue->id); std::shared_ptr<s_battleground_type> bg = battleground_db.find(queue->id);
if (!bg) { if (!bg) {
@ -1401,15 +1182,28 @@ void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue)
queue->teamb_members.clear(); queue->teamb_members.clear();
queue->teama_members.shrink_to_fit(); queue->teama_members.shrink_to_fit();
queue->teamb_members.shrink_to_fit(); queue->teamb_members.shrink_to_fit();
bg_queue_clear(queue);
auto queue_it = bg_queues.begin();
while (queue_it != bg_queues.end()) {
if (*queue_it == queue)
queue_it = bg_queues.erase(queue_it);
} }
return; /**
* Initialize a Battleground queue
* @param bg_id: Battleground ID
* @param req_players: Required amount of players
* @return s_battleground_queue*
*/
static void bg_queue_create(int bg_id, int req_players)
{
auto queue = std::make_shared<s_battleground_queue>();
queue->id = bg_id;
queue->required_players = req_players;
queue->accepted_players = 0;
queue->tid_expire = INVALID_TIMER;
queue->tid_start = INVALID_TIMER;
queue->tid_requeue = INVALID_TIMER;
queue->in_ready_state = false;
bg_queues.push_back(queue);
} }
/** /**
@ -1417,9 +1211,13 @@ void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue)
*/ */
void do_init_battleground(void) void do_init_battleground(void)
{ {
if (battle_config.feature_bgqueue) if (battle_config.feature_bgqueue) {
battleground_db.load(); battleground_db.load();
for (const auto &bg : battleground_db)
bg_queue_create(bg.first, bg.second->required_players);
}
add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer"); add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer");
add_timer_func_list(bg_on_ready_loopback, "bg_on_ready_loopback"); add_timer_func_list(bg_on_ready_loopback, "bg_on_ready_loopback");
add_timer_func_list(bg_on_ready_expire, "bg_on_ready_expire"); add_timer_func_list(bg_on_ready_expire, "bg_on_ready_expire");

View File

@ -126,15 +126,13 @@ int bg_team_leave(struct map_session_data *sd, bool quit, bool deserter);
bool bg_team_warp(int bg_id, unsigned short mapindex, short x, short y); bool bg_team_warp(int bg_id, unsigned short mapindex, short x, short y);
bool bg_player_is_in_bg_map(struct map_session_data *sd); bool bg_player_is_in_bg_map(struct map_session_data *sd);
bool bg_queue_check_joinable(std::shared_ptr<s_battleground_type> bg, struct map_session_data *sd, const char *name); bool bg_queue_check_joinable(std::shared_ptr<s_battleground_type> bg, struct map_session_data *sd, const char *name);
std::shared_ptr<s_battleground_queue> bg_queue_create(int bg_id, int req_players); void bg_queue_join_party(const char *name, struct map_session_data *sd);
e_bg_queue_apply_ack bg_queue_join(const char *name, struct map_session_data *sd); void bg_queue_join_guild(const char *name, struct map_session_data *sd);
e_bg_queue_apply_ack bg_queue_join_party(const char *name, struct map_session_data *sd); void bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vector<map_session_data *> list);
e_bg_queue_apply_ack bg_queue_join_guild(const char *name, struct map_session_data *sd);
e_bg_queue_apply_ack bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vector<map_session_data *> list);
bool bg_queue_leave(struct map_session_data *sd); bool bg_queue_leave(struct map_session_data *sd);
bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> queue); bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> queue);
void bg_queue_on_accept_invite(std::shared_ptr<s_battleground_queue> queue, struct map_session_data *sd); void bg_queue_on_accept_invite(std::shared_ptr<s_battleground_queue> queue, struct map_session_data *sd);
void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue); void bg_queue_start_battleground(s_battleground_queue *queue);
bool bg_member_respawn(struct map_session_data *sd); bool bg_member_respawn(struct map_session_data *sd);
void bg_send_message(struct map_session_data *sd, const char *mes, int len); void bg_send_message(struct map_session_data *sd, const char *mes, int len);

View File

@ -17482,7 +17482,6 @@ void clif_parse_bg_queue_apply_request(int fd, struct map_session_data *sd)
short type = RFIFOW(fd,2); short type = RFIFOW(fd,2);
char name[NAME_LENGTH]; char name[NAME_LENGTH];
e_bg_queue_apply_ack result;
safestrncpy(name, RFIFOCP(fd, 4), NAME_LENGTH); safestrncpy(name, RFIFOCP(fd, 4), NAME_LENGTH);
@ -17491,20 +17490,16 @@ void clif_parse_bg_queue_apply_request(int fd, struct map_session_data *sd)
clif_bg_queue_apply_result(BG_APPLY_DUPLICATE, name, sd); // Duplicate application warning clif_bg_queue_apply_result(BG_APPLY_DUPLICATE, name, sd); // Duplicate application warning
return; return;
} else if (type == 1) // Solo } else if (type == 1) // Solo
result = bg_queue_join(name, sd); bg_queue_join_multi(name, sd, { sd });
else if (type == 2) // Party else if (type == 2) // Party
result = bg_queue_join_party(name, sd); bg_queue_join_party(name, sd);
else if (type == 4) // Guild else if (type == 4) // Guild
result = bg_queue_join_guild(name, sd); bg_queue_join_guild(name, sd);
else { else {
ShowWarning("clif_parse_bg_queue_apply_request: Received invalid queue type: %d from player %s (AID:%d CID:%d).\n", type, sd->status.name, sd->status.account_id, sd->status.char_id); ShowWarning("clif_parse_bg_queue_apply_request: Received invalid queue type: %d from player %s (AID:%d CID:%d).\n", type, sd->status.name, sd->status.account_id, sd->status.char_id);
clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd); // Someone sent an invalid queue type packet clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd); // Someone sent an invalid queue type packet
return; return;
} }
clif_bg_queue_apply_result(result, name, sd);
if (result == BG_APPLY_ACCEPT)
clif_bg_queue_apply_notify(name, sd);
} }
/// Outgoing battlegrounds queue apply result. /// Outgoing battlegrounds queue apply result.