// Copyright (c) Hemagx, licensed under GNU GPL. // See the LICENSE file // Portions Copyright (c) Athena Dev Teams // Support is not provided upon share/re-sell #define HERCULES_CORE #include "ebg.h" #include #include #include #include "map.h" #include "clif.h" #include "pc.h" #include "itemdb.h" #include "homunculus.h" #include "mercenary.h" #include "pet.h" #include "battleground.h" #include "npc.h" #include "../common/conf.h" #include "../common/showmsg.h" #include "../common/mapindex.h" #include "../common/malloc.h" #include "../common/random.h" #include "../common/timer.h" #include "../common/strlib.h" #include "../common/utils.h" #include "../common/mapindex.h" #include "../common/sql.h" enum item_types ebg_get_item_type(const char *name) { if(!strcmpi(name,"IT_HEALING")) return IT_HEALING; else if(!strcmpi(name,"IT_UNKNOWN")) return IT_UNKNOWN; else if(!strcmpi(name,"IT_USABLE")) return IT_USABLE; else if(!strcmpi(name,"IT_ETC")) return IT_ETC; else if(!strcmpi(name,"IT_WEAPON")) return IT_WEAPON; else if(!strcmpi(name,"IT_ARMOR")) return IT_ARMOR; else if(!strcmpi(name,"IT_CARD")) return IT_CARD; else if(!strcmpi(name,"IT_PETEGG")) return IT_PETEGG; else if(!strcmpi(name,"IT_PETARMOR")) return IT_PETARMOR; else if(!strcmpi(name,"IT_UNKNOWN2")) return IT_UNKNOWN2; else if(!strcmpi(name,"IT_AMMO")) return IT_AMMO; else if(!strcmpi(name,"IT_DELAYCONSUME")) return IT_DELAYCONSUME; else if(!strcmpi(name,"IT_CASH")) return IT_CASH; else return IT_MAX; } void ebg_mapflags(void) { config_t ebg_mapflags; config_setting_t *maps = NULL; const char *config_filename = "ebg/maps_flags.conf"; if (libconfig->read_file(&ebg_mapflags, config_filename)) return; maps = libconfig->lookup(&ebg_mapflags, "maps"); if (maps != NULL) { config_setting_t *maps_e; config_setting_t *black_list_items; config_setting_t *white_list_items; config_setting_t *black_list_item_type; const char *name; const char *mapname; int i,h,v; int maps_count = 0, black_list_items_count = 0, white_list_items_count = 0, black_list_item_type_count = 0, map_id = 0, map_index = 0,hp_modifer = 0, walkspeed_modifer = 0, block_type = 0; maps_count = libconfig->setting_length(maps); for (i = 0; i < maps_count; i++) { maps_e = libconfig->setting_get_elem(maps, i); if (!libconfig->setting_lookup_string(maps_e, "name", &name)) { ShowError("map_flag_db: missing map_name name, skipping... (%s:%d)\n", config_setting_source_file(maps_e), config_setting_source_line(maps_e)); libconfig->setting_remove_elem(maps,i); --maps_count; --i; continue; } if ( ( map_index = mapindex->name2id(name) ) == 0) { ShowError("map_flag_db: unknow map %s, Skipping... \n", name); continue; } map_id = map->mapindex2mapid(map_index); mapname = name; if (libconfig->setting_lookup_int(maps_e, "hp_modifer", &hp_modifer)) map->list[map_id].hp_modifer = hp_modifer; if (libconfig->setting_lookup_int(maps_e, "walkspeed_modifer", &walkspeed_modifer)) map->list[map_id].walkspeed_modifer = walkspeed_modifer; if (libconfig->setting_lookup_int(maps_e, "block_type", &block_type)) { map->list[map_id].noitem = block_type; if( (black_list_items = libconfig->setting_get_member(maps_e, "black_list_items")) != NULL ) { black_list_items_count = libconfig->setting_length(black_list_items); for(h = 0; h < libconfig->setting_length(black_list_items); h++) { config_setting_t *item = libconfig->setting_get_elem(black_list_items, h); name = config_setting_name(item); if( !map->zone_str2itemid(name) ) { ShowError("map_flag_db: unknown item (%s) in black_list_items for map '%s', skipping item...\n",name,mapname); libconfig->setting_remove_elem(black_list_items,h); --black_list_items_count; --h; continue; } if( !libconfig->setting_get_bool(item) ) --black_list_items_count; } CREATE( map->list[map_id].itemblacklist, int, black_list_items_count ); for(h = 0, v = 0; h < libconfig->setting_length(black_list_items); h++) { config_setting_t *item = libconfig->setting_get_elem(black_list_items, h); if ( libconfig->setting_get_bool(item) ) { name = config_setting_name(item); map->list[map_id].itemblacklist[v++] = map->zone_str2itemid(name); map->list[map_id].itemblacklist_count = v; } } } if( (white_list_items = libconfig->setting_get_member(maps_e, "white_list_items")) != NULL ) { white_list_items_count = libconfig->setting_length(white_list_items); for(h = 0; h < libconfig->setting_length(white_list_items); h++) { config_setting_t *item = libconfig->setting_get_elem(white_list_items, h); name = config_setting_name(item); if( !map->zone_str2itemid(name) ) { ShowError("map_flag_db: unknown item (%s) in white_list_items for map '%s', skipping item...\n",name,mapname); libconfig->setting_remove_elem(white_list_items,h); --white_list_items_count; --h; continue; } if( !libconfig->setting_get_bool(item) ) --white_list_items_count; } CREATE( map->list[map_id].itemwhitelist, int, white_list_items_count ); for(h = 0, v = 0; h < libconfig->setting_length(white_list_items); h++) { config_setting_t *item = libconfig->setting_get_elem(white_list_items, h); if ( libconfig->setting_get_bool(item) ) { name = config_setting_name(item); map->list[map_id].itemwhitelist[v++] = map->zone_str2itemid(name); map->list[map_id].itemwhitelist_count = v; } } } if( (black_list_item_type = libconfig->setting_get_member(maps_e, "black_list_item_type")) != NULL ) { black_list_item_type_count = libconfig->setting_length(black_list_item_type); for(h = 0; h < libconfig->setting_length(black_list_item_type); h++) { config_setting_t *item = libconfig->setting_get_elem(black_list_item_type, h); name = config_setting_name(item); if( ebg_get_item_type(name) == IT_MAX ) { ShowError("map_flag_db: unknown item type (%s) in black_list_item_type for map '%s', skipping item...\n",name,mapname); libconfig->setting_remove_elem(black_list_item_type,h); --black_list_item_type_count; --h; continue; } if( !libconfig->setting_get_bool(item) ) --black_list_item_type_count; CREATE( map->list[map_id].item_block_type, int, black_list_item_type_count ); for(h = 0, v = 0; h < libconfig->setting_length(black_list_item_type); h++) { config_setting_t *item2 = libconfig->setting_get_elem(black_list_item_type, h); if ( libconfig->setting_get_bool(item2) ) { name = config_setting_name(item2); map->list[map_id].item_block_type[v++] = ebg_get_item_type(name); map->list[map_id].item_block_type_count = v; } } } } } } } } int ebg_chose_captain (int bg_id) { struct battleground_data *bgd; int random, members[MAX_BG_MEMBERS] = {0}, count = 0, i = 0, current = 0; if ( ( bgd = bg->team_search(bg_id) ) == NULL ) return 0; for( i = 0; i < MAX_BG_MEMBERS; i++) { if ( bgd->members[i].sd ) { members[count] = i; count++; } } random = rnd_value(0,count - 1); current = members[random]; ShowDebug(">> %d %p\n", current, current >= 0 ? bgd->members[current].sd : NULL); ShowDebug("%d\n", bgd->members[current].sd->bl.id); bgd->members[current].sd->state.size = 2; clif->specialeffect(&bgd->members[current].sd->bl,422,AREA); pc->setpos(bgd->members[current].sd, bgd->members[current].sd->mapindex, bgd->members[current].sd->bl.x, bgd->members[current].sd->bl.y, CLR_TELEPORT); bgd->members[current].sd->ebg.is_captian = 1; return bgd->members[current].sd->bl.id; } int ebg_end_captian (int bg_id) { struct battleground_data *bgd; int i; if ( ( bgd = bg->team_search(bg_id) ) == NULL ) return 0; for( i = 0; i < MAX_BG_MEMBERS; i++) { if ( !bgd->members[i].sd ) continue; if ( bgd->members[i].sd->ebg.is_captian ) { bgd->members[i].sd->ebg.is_captian = 0; bgd->members[i].sd->state.size = 0; clif->specialeffect(&bgd->members[i].sd->bl,420,AREA); pc->setpos(bgd->members[i].sd, bgd->members[i].sd->mapindex, bgd->members[i].sd->bl.x, bgd->members[i].sd->bl.y, CLR_TELEPORT); } } return 1; } int ebg_end_bg_spectat (int bg_id ) { struct battleground_data *bgd; int i; if ( ( bgd = bg->team_search(bg_id) ) == NULL ) return 0; for( i = 0; i < MAX_BG_MEMBERS; i++) { if ( !bgd->members[i].sd ) continue; if ( bgd->members[i].sd->state.spectat ) { bgd->members[i].sd->sc.option &= ~OPTION_INVISIBLE; if (bgd->members[i].sd->disguise != -1 ) status->set_viewdata(&bgd->members[i].sd->bl, bgd->members[i].sd->disguise); else status->set_viewdata(&bgd->members[i].sd->bl, bgd->members[i].sd->status.class_); map->list[bgd->members[i].sd->bl.m].users_pvp++; if( map->list[bgd->members[i].sd->bl.m].flag.pvp && !map->list[bgd->members[i].sd->bl.m].flag.pvp_nocalcrank ) { bgd->members[i].sd->pvp_timer = timer->add( timer->gettick() + 200, pc->calc_pvprank_timer, bgd->members[i].sd->bl.id, 0 ); } map->foreachinmovearea(clif->insight, &bgd->members[i].sd->bl, AREA_SIZE, bgd->members[i].sd->bl.x, bgd->members[i].sd->bl.y, BL_ALL, &bgd->members[i].sd->bl); bgd->members[i].sd->state.spectat = false; clif->changeoption(&bgd->members[i].sd->bl); } } return 1; } void ebg_bg_update_score (struct map_session_data *target, struct block_list *src) { target->ebg.death++; if (src) { switch(src->type) { case BL_MOB: return; break; case BL_PET: src = &((TBL_PET*)src)->msd->bl; break; case BL_MER: src = &((TBL_MER*)src)->master->bl; break; case BL_HOM: src = &((TBL_HOM*)src)->master->bl; break; } } if (src && src->type == BL_PC) { struct map_session_data *sd = (struct map_session_data *)src; if (target->ebg.is_captian) { sd->ebg.captian_kill++; target->ebg.captain_death++; } else sd->ebg.kill++; } } int ebg_return_alive_members (struct battleground_data *bgd) { int count = 0,i; for( i = 0; i < MAX_BG_MEMBERS; i++) { if( !bgd->members[i].sd ) continue; if ( !bgd->members[i].sd->state.spectat && !pc_isdead(bgd->members[i].sd)) count++; } return count; } int ebg_get_captian_rid ( struct battleground_data *bgd ) { int i; for (i = 0; i < MAX_BG_MEMBERS; i++) { if (bgd->members[i].sd) { if ( bgd->members[i].sd->ebg.is_captian ) return bgd->members[i].sd->bl.id; } } return 0; } int ebg_set_freeforall ( int id, const char *joinevent, const char *dieevent, const char *quitevent, const char *map_name, int x, int y ) { int map_index; if ( !ebg_ffa_isvaildid(id) ) return 0; safestrncpy(bg_freeforall[id].join_event, joinevent, sizeof(bg_freeforall[id].join_event)); safestrncpy(bg_freeforall[id].die_event, dieevent, sizeof(bg_freeforall[id].die_event)); safestrncpy(bg_freeforall[id].quit_event, quitevent, sizeof(bg_freeforall[id].quit_event)); if( strcmp(map_name,"-") != 0 ) { map_index = mapindex->name2id(map_name); if( map_index == 0 ) return 0; bg_freeforall[id].mapindex = map_index; bg_freeforall[id].x = x; bg_freeforall[id].y = y; } return 1; } int ebg_join_freeforall ( int id, struct map_session_data *sd ) { int i; if ( !ebg_ffa_isvaildid(id) ) return 0; //Do we have free slot ? if ( bg_freeforall[id].count == MAX_FREEFORALLMEMBERS ) return -1; for ( i = 0; i < MAX_FREEFORALLMEMBERS; i++ ) { if ( bg_freeforall[id].members[i].sd ) continue; bg_freeforall[id].members[i].sd = sd; bg_freeforall[id].count++; sd->ebg.pvp_id = id; } npc->event(sd,bg_freeforall[id].join_event,0); return 1; } int ebg_die_freeforall ( struct map_session_data *sd ) { npc->event(sd,bg_freeforall[sd->ebg.pvp_id].die_event,0); return 1; } int ebg_quit_freeforall ( struct map_session_data *sd ) { int i; struct map_session_data *dsd; for ( i = 0; i < MAX_FREEFORALLMEMBERS; i++ ) { if ( !bg_freeforall[sd->ebg.pvp_id].members[i].sd ) continue; dsd = bg_freeforall[sd->ebg.pvp_id].members[i].sd; if ( dsd->bl.id == sd->bl.id ) { bg_freeforall[sd->ebg.pvp_id].count--; sd->ebg.pvp_id = 0; sd->ebg.death = 0; sd->ebg.kill = 0; memset(&bg_freeforall[sd->ebg.pvp_id].members[i], 0, sizeof(bg_freeforall[sd->ebg.pvp_id].members[0])); break; } } npc->event(sd,bg_freeforall[sd->ebg.pvp_id].quit_event,0); return 1; } int ebg_destory_freeforall ( int id ) { int i; struct map_session_data *sd; if ( !ebg_ffa_isvaildid(id) ) return 0; for ( i = 0; i < MAX_FREEFORALLMEMBERS; i++ ) { if ( (sd = bg_freeforall[id].members[i].sd) != NULL ) { sd->ebg.pvp_id = 0; sd->ebg.death = 0; sd->ebg.kill = 0; } memset(&bg_freeforall[id].members[i], 0, sizeof(bg_freeforall[id].members[0])); } bg_freeforall[id].count = 0; return 1; } int ebg_giveprizeffa( int id ) { int i, points; struct map_session_data *sd; if ( !ebg_ffa_isvaildid(id) ) return 0; for ( i = 0; i < MAX_FREEFORALLMEMBERS; i++ ) { sd = bg_freeforall[id].members[i].sd; if (sd) { points = 0; if ( sd->ebg.kill < 1 ) continue; if ( sd->ebg.death > 0 ) points = (int)0.5 * ( sd->ebg.kill / sd->ebg.death ); else points = (int)0.5 * sd->ebg.kill; points = cap_value(points,1,10); points += pc_readglobalreg(sd,script->add_str("ebg_points")); pc_setglobalreg(sd,script->add_str("ebg_points"),points); } } return 1; } void ebg_init_ranking_user ( struct map_session_data *sd ) { char *data = NULL; char esc_name[2*NAME_LENGTH+1]; if ( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT * FROM lts_ranking WHERE char_id = %d", sd->status.char_id) ) { Sql_ShowDebug(map->mysql_handle); return; } if( !(SQL_SUCCESS == SQL->NextRow(map->mysql_handle) && SQL_SUCCESS == SQL->GetData(map->mysql_handle, 0, &data, NULL) && data != NULL) ) { SQL->EscapeString(map->mysql_handle,esc_name,sd->status.name); if ( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO lts_ranking VALUES ( NULL, %d,0,0,0,'%s')", sd->status.char_id, esc_name)) { Sql_ShowDebug(map->mysql_handle); return; } } if ( SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT score FROM captian_ranking WHERE char_id = %d", sd->status.char_id) ) { Sql_ShowDebug(map->mysql_handle); return; } if( !(SQL_SUCCESS == SQL->NextRow(map->mysql_handle) && SQL_SUCCESS == SQL->GetData(map->mysql_handle, 0, &data, NULL) && data != NULL) ) { SQL->EscapeString(map->mysql_handle,esc_name,sd->status.name); if ( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO captian_ranking VALUES ( NULL, %d,0,'%s')", sd->status.char_id, esc_name)) { Sql_ShowDebug(map->mysql_handle); return; } } else { sd->ebg.captain_score = atoi(data); } } int ebg_save_ranking ( int flag, int id1, int id2 ) { if(flag == EBG_LTS) { struct battleground_data *bgd1 = bg->team_search(id1); struct battleground_data *bgd2 = bg->team_search(id2); struct map_session_data *sd; int i; if ( !bgd1 || !bgd2 ) return 0; // Go through first team for ( i = 0; i < MAX_BG_MEMBERS; i++ ) { if ( !bgd1->members[i].sd ) continue; sd = bgd1->members[i].sd; if ( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE lts_ranking SET `kill` = `kill` + %d, death = death + %d, kdr = (`kill` / death) WHERE char_id = %d",sd->ebg.kill, sd->ebg.death, sd->status.char_id) ) { Sql_ShowDebug(map->mysql_handle); continue; } } for ( i = 0; i < MAX_BG_MEMBERS; i++ ) { if ( !bgd2->members[i].sd ) continue; sd = bgd2->members[i].sd; if ( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE lts_ranking SET `kill` = `kill` + %d, death = death + %d, kdr = (`kill` / death) WHERE char_id = %d",sd->ebg.kill, sd->ebg.death, sd->status.char_id) ) { Sql_ShowDebug(map->mysql_handle); continue; } } }else if ( flag == EBG_CAPTAIN ) { struct battleground_data *bgd1 = bg->team_search(id1); struct battleground_data *bgd2 = bg->team_search(id2); struct map_session_data *sd; int i, score; if ( !bgd1 || !bgd2 ) return 0; for ( i = 0; i < MAX_BG_MEMBERS; i++ ) { if ( !bgd1->members[i].sd ) continue; sd = bgd1->members[i].sd; score = sd->ebg.captain_score - sd->ebg.captain_death; sd->ebg.captain_death = 0; score = cap_value(score,0,INT_MAX); if ( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE captian_ranking SET `score` =%d WHERE char_id = %d", score, sd->status.char_id) ) { Sql_ShowDebug(map->mysql_handle); continue; } } for ( i = 0; i < MAX_BG_MEMBERS; i++ ) { if ( !bgd2->members[i].sd ) continue; sd = bgd2->members[i].sd; score = sd->ebg.captain_score - sd->ebg.captain_death; sd->ebg.captain_death = 0; score = cap_value(score,0,INT_MAX); if ( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE captian_ranking SET `score` =%d WHERE char_id = %d", score, sd->status.char_id) ) { Sql_ShowDebug(map->mysql_handle); continue; } } } return 1; } void ebg_init (void) { ebg_mapflags(); }