From 4cc9d5f91cf6276e28cc02bb75fc4158d28d553b Mon Sep 17 00:00:00 2001 From: shennetsind Date: Tue, 18 Mar 2014 14:59:53 -0300 Subject: BG Queue Fixes & +++ Fixed issue where players would be able to join a ongoing game when queueing by meeting the criteria. Fixed/Implemented the maximum_afk_seconds setting. Fixed issue with the maxPlayers arena setting that'd cause the maximum to be less than specified. Added a new battlegrounds.conf setting "allowedTypes" for arenas in order for further customisation. Expect a few more soon. Special Thanks to AnnieRuru Signed-off-by: shennetsind --- src/map/battleground.c | 103 ++++++++++++++++++++++++++++++++++++++++++------- src/map/battleground.h | 16 ++++++-- src/map/map.c | 2 +- src/map/script.c | 2 +- 4 files changed, 104 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/map/battleground.c b/src/map/battleground.c index 65f475124..3640b8344 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -113,7 +113,7 @@ bool bg_team_join(int bg_id, struct map_session_data *sd) { } /// Single Player leaves team -int bg_team_leave(struct map_session_data *sd, int flag) { +int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag) { int i, bg_id; struct battleground_data *bgd; char output[128]; @@ -137,10 +137,18 @@ int bg_team_leave(struct map_session_data *sd, int flag) { } if( --bgd->count != 0 ) { - if( flag ) - sprintf(output, "Server : %s has quit the game...", sd->status.name); - else - sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name); + switch( flag ) { + default: + case BGTL_QUIT: + sprintf(output, "Server : %s has quit the game...", sd->status.name); + break; + case BGTL_LEFT: + sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name); + break; + case BGTL_AFK: + sprintf(output, "Server : %s has been afk-kicked from the battlefield...", sd->status.name); + break; + } clif->bg_message(bgd, 0, "Server", output, strlen(output) + 1); } @@ -252,6 +260,34 @@ int bg_send_xy_timer(int tid, int64 tick, int id, intptr_t data) { bg->team_db->foreach(bg->team_db, bg->send_xy_timer_sub, tick); return 0; } + +enum bg_queue_types bg_str2teamtype (const char *str) { + char temp[200], *parse; + enum bg_queue_types type = BGQT_INVALID; + + safestrncpy(temp, str, 200); + + parse = strtok(temp,"|"); + + while (parse != NULL) { + normalize_name(parse," "); + if( strcmpi(parse,"all") == 0 ) + type |= BGQT_INDIVIDUAL|BGQT_PARTY|BGQT_GUILD; + else if( strcmpi(parse,"party") == 0 ) + type |= BGQT_PARTY; + else if( strcmpi(parse,"guild") == 0 ) + type |= BGQT_GUILD; + else if( strcmpi(parse,"solo") == 0 ) + type |= BGQT_INDIVIDUAL; + else { + ShowError("bg_str2teamtype: '%s' unknown type, skipping...\n",parse); + } + parse = strtok(NULL,"|"); + } + + return type; +} + void bg_config_read(void) { config_t bg_conf; config_setting_t *data = NULL; @@ -274,7 +310,7 @@ void bg_config_read(void) { safestrncpy(bg->gdelay_var, delay_var, BG_DELAY_VAR_LENGTH); libconfig->setting_lookup_int(settings, "maximum_afk_seconds", &bg->mafksec); - + libconfig->setting_lookup_bool(settings, "feature_off", &offline); if( offline == 0 ) @@ -286,12 +322,13 @@ void bg_config_read(void) { for(i = 0; i < arena_count; i++) { config_setting_t *arena = libconfig->setting_get_elem(arenas, i); config_setting_t *reward; - const char *aName, *aEvent, *aDelayVar; + const char *aName, *aEvent, *aDelayVar, *aTeamTypes; int minLevel = 0, maxLevel = 0; int prizeWin, prizeLoss, prizeDraw; int minPlayers, maxPlayers, minTeamPlayers; int maxDuration; int fillup_duration = 0, pregame_duration = 0; + enum bg_queue_types allowedTypes; bg->arena[i] = NULL; @@ -361,6 +398,12 @@ void bg_config_read(void) { continue; } + + if( !libconfig->setting_lookup_string(arena, "allowedTypes", &aTeamTypes) ) { + ShowError("bg_config_read: failed to find 'allowedTypes' for arena '%s'/#%d\n",aName,i); + continue; + } + libconfig->setting_lookup_int(arena, "maxDuration", &maxDuration); if( maxDuration < 0 ) { @@ -381,6 +424,7 @@ void bg_config_read(void) { pregame_duration = 20; } + allowedTypes = bg->str2teamtype(aTeamTypes); CREATE( bg->arena[i], struct bg_arena, 1 ); @@ -403,6 +447,7 @@ void bg_config_read(void) { bg->arena[i]->pregame_duration = pregame_duration; bg->arena[i]->fillup_duration = fillup_duration; bg->arena[i]->ongoing = false; + bg->arena[i]->allowed_types = allowedTypes; } bg->arenas = arena_count; @@ -452,7 +497,7 @@ void bg_queue_ready_ack (struct bg_arena *arena, struct map_session_data *sd, bo count++; } } - /* check if all are ready then cancell timer, and start game */ + /* check if all are ready then cancel timer, and start game */ if( count == queue->items ) { timer->delete(arena->begin_timer,bg->begin_timer); arena->begin_timer = INVALID_TIMER; @@ -527,6 +572,10 @@ void bg_begin(struct bg_arena *arena) { bg->match_over(arena,true); } else { arena->ongoing = true; + + if( bg->afk_timer_id == INVALID_TIMER && bg->mafksec > 0 ) + bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0); + /* TODO: make this a arena-independant var? or just .@? */ mapreg->setreg(script->add_str("$@bg_queue_id"),arena->queue_id); mapreg->setregstr(script->add_str("$@bg_delay_var$"),bg->gdelay_var); @@ -557,10 +606,6 @@ void bg_begin(struct bg_arena *arena) { mapreg->setreg(script->add_str("$@bg_member_size"),count); npc->event_do(arena->npc_event); - /* we split evenly? */ - /* but if a party of say 10 joins, it cant be split evenly unless by luck there are 10 soloers in the queue besides them */ - /* not sure how to split T_T needs more info */ - /* currently running only on solo mode so we do it evenly */ } } int bg_begin_timer(int tid, int64 tick, int id, intptr_t data) { @@ -569,6 +614,28 @@ int bg_begin_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } +int bg_afk_timer(int tid, int64 tick, int id, intptr_t data) { + struct s_mapiterator* iter; + struct map_session_data* sd; + int count = 0; + + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { + if( !sd->bg_queue.arena || !sd->bg_id ) + continue; + if( DIFF_TICK(sockt->last_tick, sd->idletime) < bg->mafksec ) + bg->team_leave(sd,BGTL_AFK); + count++; + } + mapit->free(iter); + + if( count ) + bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0); + else + bg->afk_timer_id = INVALID_TIMER; + return 0; +} + void bg_queue_pregame(struct bg_arena *arena) { struct hQueue *queue = &script->hq[arena->queue_id]; int i; @@ -605,7 +672,7 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q struct hQueue *queue; int i, count = 0; - if( arena->begin_timer != INVALID_TIMER ) { + if( arena->begin_timer != INVALID_TIMER || arena->ongoing ) { clif->bgqueue_ack(sd,BGQA_FAIL_QUEUING_FINISHED,arena->id); return; } @@ -636,7 +703,7 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q break; } - if( !(queue = script->queue(arena->queue_id)) || (queue->items+count) >= arena->max_players ) { + if( !(queue = script->queue(arena->queue_id)) || (queue->items+count) > arena->max_players ) { clif->bgqueue_ack(sd,BGQA_FAIL_PPL_OVERAMOUNT,arena->id); return; } @@ -684,6 +751,10 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) { int tick; unsigned int tsec; + + if( !(arena->allowed_types & type) ) + return BGQA_FAIL_TYPE_INVALID; + if ( sd->status.base_level > arena->max_level || sd->status.base_level < arena->min_level ) return BGQA_FAIL_LEVEL_INCORRECT; @@ -810,6 +881,7 @@ void battleground_defaults(void) { bg->queue_on = false; bg->mafksec = 0; + bg->afk_timer_id = INVALID_TIMER; bg->arena = NULL; bg->arenas = 0; /* */ @@ -844,6 +916,9 @@ void battleground_defaults(void) { bg->send_message = bg_send_message; bg->send_xy_timer_sub = bg_send_xy_timer_sub; bg->send_xy_timer = bg_send_xy_timer; + bg->afk_timer = bg_afk_timer; + /* */ + bg->str2teamtype = bg_str2teamtype; /* */ bg->config_read = bg_config_read; } diff --git a/src/map/battleground.h b/src/map/battleground.h index ed7347566..05c4eb060 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -26,6 +26,12 @@ enum bg_queue_types { BGQT_GUILD = 0x4, }; +enum bg_team_leave_type { + BGTL_LEFT = 0x0, + BGTL_QUIT = 0x1, + BGTL_AFK = 0x2, +}; + struct battleground_member_data { unsigned short x, y; struct map_session_data *sd; @@ -62,12 +68,13 @@ struct bg_arena { unsigned short fillup_duration; unsigned short pregame_duration; bool ongoing; + enum bg_queue_types allowed_types; }; struct battleground_interface { bool queue_on; /* */ - int mafksec; + int mafksec, afk_timer_id; char gdelay_var[BG_DELAY_VAR_LENGTH]; /* */ struct bg_arena **arena; @@ -97,13 +104,16 @@ struct battleground_interface { bool (*team_warp) (int bg_id, unsigned short map_index, short x, short y); void (*send_dot_remove) (struct map_session_data *sd); bool (*team_join) (int bg_id, struct map_session_data *sd); - int (*team_leave) (struct map_session_data *sd, int flag); + int (*team_leave) (struct map_session_data *sd, enum bg_team_leave_type flag); bool (*member_respawn) (struct map_session_data *sd); int (*create) (unsigned short map_index, short rx, short ry, const char *ev, const char *dev); int (*team_get_id) (struct block_list *bl); bool (*send_message) (struct map_session_data *sd, const char *mes, int len); int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap); - int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); + int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data); + int (*afk_timer) (int tid, int64 tick, int id, intptr_t data); + /* */ + enum bg_queue_types (*str2teamtype) (const char *str); /* */ void (*config_read) (void); }; diff --git a/src/map/map.c b/src/map/map.c index a7e83cae3..51b717a16 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1685,7 +1685,7 @@ int map_quit(struct map_session_data *sd) { npc->event_dequeue(sd); if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */ - bg->team_leave(sd,1); + bg->team_leave(sd,BGTL_QUIT); if( sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !hChSys.closing ) pc->autotrade_update(sd,PAUC_REMOVE); diff --git a/src/map/script.c b/src/map/script.c index 17eba6b21..01a7e6410 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -16350,7 +16350,7 @@ BUILDIN(bg_leave) if( sd == NULL || !sd->bg_id ) return true; - bg->team_leave(sd,0); + bg->team_leave(sd,BGTL_LEFT); return true; } -- cgit v1.2.3-60-g2f50