int32 map_config_read(const int8* cfgName) { int8 line[1024], w1[1024], w2[1024]; FILE* fp; fp = fopen(cfgName, "r"); if (fp == nullptr) { ShowError("Map configuration file not found at: %s\n", cfgName); return 1; } while (fgets(line, sizeof(line), fp)) { int8* ptr; if (line[0] == '#') { continue; } if (sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2) { continue; } //Strip trailing spaces ptr = w2 + strlen(w2); while (--ptr >= w2 && *ptr == ' '); ptr++; *ptr = '\0'; if (strcmpi(w1, "timestamp_format") == 0) { strncpy(timestamp_format, w2, 20); } else if (strcmpi(w1, "stdout_with_ansisequence") == 0) { stdout_with_ansisequence = config_switch(w2); } else if (strcmpi(w1, "console_silent") == 0) { ShowInfo("Console Silent Setting: %d", atoi(w2)); msg_silent = atoi(w2); } else if (strcmpi(w1, "map_port") == 0) { map_config.usMapPort = (atoi(w2)); } else if (strcmp(w1, "buff_maxsize") == 0) { map_config.buffer_size = atoi(w2); } else if (strcmp(w1, "max_time_lastupdate") == 0) { map_config.max_time_lastupdate = atoi(w2); } else if (strcmp(w1, "vanadiel_time_offset") == 0) { map_config.vanadiel_time_offset = atoi(w2); } else if (strcmp(w1, "lightluggage_block") == 0) { map_config.lightluggage_block = atoi(w2); } else if (strcmp(w1, "exp_rate") == 0) { map_config.exp_rate = atof(w2); } else if (strcmp(w1, "exp_loss_rate") == 0) { map_config.exp_loss_rate = atof(w2); } else if (strcmp(w1, "exp_party_gap_penalties") == 0) { map_config.exp_party_gap_penalties = atof(w2); } else if (strcmp(w1, "fov_party_gap_penalties") == 0) { map_config.fov_party_gap_penalties = atof(w2); } else if (strcmp(w1, "fov_allow_alliance") == 0) { map_config.fov_allow_alliance = atof(w2); } else if (strcmp(w1, "mob_tp_multiplier") == 0) { map_config.mob_tp_multiplier = atof(w2); } else if (strcmp(w1, "player_tp_multiplier") == 0) { map_config.player_tp_multiplier = atof(w2); } else if (strcmp(w1, "nm_hp_multiplier") == 0) { map_config.nm_hp_multiplier = atof(w2); } else if (strcmp(w1, "mob_hp_multiplier") == 0) { map_config.mob_hp_multiplier = atof(w2); } else if (strcmp(w1, "player_hp_multiplier") == 0) { map_config.player_hp_multiplier = atof(w2); } else if (strcmp(w1, "nm_mp_multiplier") == 0) { map_config.nm_mp_multiplier = atof(w2); } else if (strcmp(w1, "mob_mp_multiplier") == 0) { map_config.mob_mp_multiplier = atof(w2); } else if (strcmp(w1, "player_mp_multiplier") == 0) { map_config.player_mp_multiplier = atof(w2); } else if (strcmp(w1, "sj_mp_divisor") == 0) { map_config.sj_mp_divisor = atof(w2); } else if (strcmp(w1, "nm_stat_multiplier") == 0) { map_config.nm_stat_multiplier = atof(w2); } else if (strcmp(w1, "mob_stat_multiplier") == 0) { map_config.mob_stat_multiplier = atof(w2); } else if (strcmp(w1, "player_stat_multiplier") == 0) { map_config.player_stat_multiplier = atof(w2); } else if (strcmp(w1, "drop_rate_multiplier") == 0) { map_config.drop_rate_multiplier = atof(w2); } else if (strcmp(w1, "all_mobs_gil_bonus") == 0) { map_config.all_mobs_gil_bonus = atoi(w2); } else if (strcmp(w1, "max_gil_bonus") == 0) { map_config.max_gil_bonus = atoi(w2); } else if (strcmp(w1, "exp_retain") == 0) { map_config.exp_retain = dsp_cap(atof(w2), 0.0f, 1.0f); } else if (strcmp(w1, "exp_loss_level") == 0) { map_config.exp_loss_level = atoi(w2); } else if (strcmp(w1, "level_sync_enable") == 0) { map_config.level_sync_enable = atoi(w2); } else if (strcmp(w1, "all_jobs_widescan") == 0) { map_config.all_jobs_widescan = atoi(w2); } else if (strcmp(w1, "speed_mod") == 0) { map_config.speed_mod = atoi(w2); } else if (strcmp(w1, "mob_speed_mod") == 0) { map_config.mob_speed_mod = atoi(w2); } else if (strcmp(w1, "skillup_chance_multiplier") == 0) { map_config.skillup_chance_multiplier = atof(w2); } else if (strcmp(w1, "craft_chance_multiplier") == 0) { map_config.craft_chance_multiplier = atof(w2); } else if (strcmp(w1, "skillup_amount_multiplier") == 0) { map_config.skillup_amount_multiplier = atof(w2); } else if (strcmp(w1, "craft_amount_multiplier") == 0) { map_config.craft_amount_multiplier = atof(w2); } else if (strcmp(w1, "craft_day_matters") == 0) { map_config.craft_day_matters = atof(w2); } else if (strcmp(w1, "craft_moonphase_matters") == 0) { map_config.craft_moonphase_matters = atof(w2); } else if (strcmp(w1, "craft_direction_matters") == 0) { map_config.craft_direction_matters = atof(w2); } else if (strcmp(w1, "mysql_host") == 0) { map_config.mysql_host = aStrdup(w2); } else if (strcmp(w1, "mysql_login") == 0) { map_config.mysql_login = aStrdup(w2); } else if (strcmp(w1, "mysql_password") == 0) { map_config.mysql_password = aStrdup(w2); } else if (strcmp(w1, "mysql_port") == 0) { map_config.mysql_port = atoi(w2); } else if (strcmp(w1, "mysql_database") == 0) { map_config.mysql_database = aStrdup(w2); } else if (strcmpi(w1, "import") == 0) { map_config_read(w2); } else if (strcmpi(w1, "newstyle_skillups") == 0) { map_config.newstyle_skillups = atoi(w2); } else if (strcmp(w1, "Battle_cap_tweak") == 0) { map_config.Battle_cap_tweak = atoi(w2); } else if (strcmp(w1, "CoP_Battle_cap") == 0) { map_config.CoP_Battle_cap = atoi(w2); } else if (strcmp(w1, "max_merit_points") == 0) { map_config.max_merit_points = atoi(w2); } else if (strcmp(w1, "yell_cooldown") == 0) { map_config.yell_cooldown = atoi(w2); } else if (strcmp(w1, "audit_chat") == 0) { map_config.audit_chat = atoi(w2); } else if (strcmp(w1, "audit_say") == 0) { map_config.audit_say = atoi(w2); } else if (strcmp(w1, "audit_shout") == 0) { map_config.audit_shout = atoi(w2); } else if (strcmp(w1, "audit_tell") == 0) { map_config.audit_tell = atoi(w2); } else if (strcmp(w1, "audit_yell") == 0) { map_config.audit_yell = atoi(w2); } else if (strcmp(w1, "audit_linkshell") == 0) { map_config.audit_linkshell = atoi(w2); } else if (strcmp(w1, "audit_party") == 0) { map_config.audit_party = atoi(w2); } else if (strcmp(w1, "msg_server_port") == 0) { map_config.msg_server_port = atoi(w2); } else if (strcmp(w1, "msg_server_ip") == 0) { map_config.msg_server_ip = aStrdup(w2); } else { ShowWarning(CL_YELLOW"Unknown setting '%s' in file %s\n" CL_RESET, w1, cfgName); } } fclose(fp); // Load the English server message.. fp = fopen("./conf/server_message.conf", "rb"); if (fp == nullptr) { ShowError("Could not read English server message from: ./conf/server_message.conf\n"); return 1; } while (fgets(line, sizeof(line), fp)) { string_t sline(line); map_config.server_message += sline; } fclose(fp); // Load the French server message.. fp = fopen("./conf/server_message_fr.conf", "rb"); if (fp == nullptr) { ShowError("Could not read English server message from: ./conf/server_message_fr.conf\n"); return 1; } while (fgets(line, sizeof(line), fp)) { string_t sline(line); map_config.server_message_fr += sline; } fclose(fp); // Ensure both messages have nullptr terminates.. if (map_config.server_message.at(map_config.server_message.length() - 1) != 0x00) { map_config.server_message += (char)0x00; } if (map_config.server_message_fr.at(map_config.server_message_fr.length() - 1) != 0x00) { map_config.server_message_fr += (char)0x00; } return 0; }
void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count) { int zeny = 0; unsigned int i, weight, listidx, k; struct map_session_data* pl_sd; if( count == 0 ) {// nothing to do return; } if( !battle_config.feature_buying_store || pc_istrading(sd) ) {// not allowed to sell clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( !pc->can_give_items(sd) ) {// custom: GM is not allowed to sell clif->message(sd->fd, msg_txt(246)); clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( ( pl_sd = iMap->id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id ) {// not online, not buying or not same store clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( !searchstore->queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) {// out of view range clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } searchstore->clearremote(sd); if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit ) {// buyer lost zeny in the mean time? fix the limit pl_sd->buyingstore.zenylimit = pl_sd->status.zeny; } weight = pl_sd->weight; // check item list for( i = 0; i < count; i++ ) {// itemlist: <index>.W <name id>.W <amount>.W unsigned short nameid, amount; int index; index = RBUFW(itemlist,i*6+0)-2; nameid = RBUFW(itemlist,i*6+2); amount = RBUFW(itemlist,i*6+4); if( i ) {// duplicate check. as the client does this too, only malicious intent should be caught here ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index ); if( k != i ) {// duplicate ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id); clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } } if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount ) {// invalid input clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc->get_group_level(sd), pc->get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) {// non-tradable item clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 ) {// there is no such item or the buyer has already bought all of them clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( pl_sd->buyingstore.items[listidx].amount < amount ) {// buyer does not need that much of the item clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid); return; } if( pc->checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT ) {// buyer does not have enough space for this item clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight ) {// normally this is not supposed to happen, as the total weight is // checked upon creation, but the buyer could have gained items clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } weight+= amount*sd->inventory_data[index]->weight; if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny ) {// buyer does not have enough zeny clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid); return; } zeny+= amount*pl_sd->buyingstore.items[listidx].price; } // process item list for( i = 0; i < count; i++ ) {// itemlist: <index>.W <name id>.W <amount>.W unsigned short nameid, amount; int index; index = RBUFW(itemlist,i*6+0)-2; nameid = RBUFW(itemlist,i*6+2); amount = RBUFW(itemlist,i*6+4); ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); zeny = amount*pl_sd->buyingstore.items[listidx].price; // move item pc->additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE); pc->delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE); pl_sd->buyingstore.items[listidx].amount-= amount; // pay up pc->payzeny(pl_sd, zeny, LOG_TYPE_BUYING_STORE, sd); pc->getzeny(sd, zeny, LOG_TYPE_BUYING_STORE, pl_sd); pl_sd->buyingstore.zenylimit-= zeny; // notify clients clif->buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price); clif->buyingstore_update_item(pl_sd, nameid, amount); } if( iMap->save_settings&128 ) { chrif_save(sd, 0); chrif_save(pl_sd, 0); } // check whether or not there is still something to buy ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 ); if( i == pl_sd->buyingstore.slots ) {// everything was bought clif->buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS); } else if( pl_sd->buyingstore.zenylimit == 0 ) {// zeny limit reached clif->buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY); } else {// continue buying return; } // cannot continue buying buyingstore_close(pl_sd); // remove auto-trader if( pl_sd->state.autotrade ) { iMap->quit(pl_sd); } }
void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count) { unsigned int i; struct map_session_data* pl_sd; struct DBIterator *iter; struct s_search_store_search s; searchstore_searchall_t store_searchall; time_t querytime; if( !battle_config.feature_search_stores ) { return; } if( !sd->searchstore.open ) { return; } if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) { ShowError("searchstore_query: Tipo de procura desconhecida %u (account_id=%d).\n", (unsigned int)type, sd->bl.id); return; } time(&querytime); if( sd->searchstore.nextquerytime > querytime ) { clif->search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME); return; } if( !sd->searchstore.uses ) { clif->search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT); return; } // validate lists for( i = 0; i < item_count; i++ ) { if( !itemdb->exists(itemlist[i]) ) { ShowWarning("searchstore_query: Item do Client determinado %hu nao se sabe.\n", itemlist[i]); clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); return; } } for( i = 0; i < card_count; i++ ) { if( !itemdb->exists(cardlist[i]) ) { ShowWarning("searchstore_query: Carta do Client determinado %hu nao se sabe.\n", cardlist[i]); clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); return; } } if( max_price < min_price ) { swap(min_price, max_price); } sd->searchstore.uses--; sd->searchstore.type = type; sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay; // drop previous results searchstore->clear(sd); // allocate max. amount of results sd->searchstore.items = (struct s_search_store_info_item*)aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults); // search s.search_sd = sd; s.itemlist = itemlist; s.cardlist = cardlist; s.item_count = item_count; s.card_count = card_count; s.min_price = min_price; s.max_price = max_price; iter = db_iterator(vending->db); for( pl_sd = dbi_first(iter); dbi_exists(iter); pl_sd = dbi_next(iter) ) { if( sd == pl_sd ) {// skip own shop, if any continue; } if( !store_searchall(pl_sd, &s) ) {// exceeded result size clif->search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT); break; } } dbi_destroy(iter); if( sd->searchstore.count ) { // reclaim unused memory sd->searchstore.items = (struct s_search_store_info_item*)aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count); // present results clif->search_store_info_ack(sd); // one page displayed sd->searchstore.pages++; } else { // cleanup searchstore->clear(sd); // update uses clif->search_store_info_ack(sd); // notify of failure clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); } }
/*========================================== * processes one itemdb entry *------------------------------------------*/ static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) { /* +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script | +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ */ int nameid; struct item_data* id; nameid = atoi(str[0]); if( nameid <= 0 ) { ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source); return false; } //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View id = itemdb_load(nameid); safestrncpy(id->name, str[1], sizeof(id->name)); safestrncpy(id->jname, str[2], sizeof(id->jname)); id->type = atoi(str[3]); if( id->type < 0 || id->type == IT_UNKNOWN || id->type == IT_UNKNOWN2 || ( id->type > IT_DELAYCONSUME && id->type < IT_THROWWEAPON ) || id->type >= IT_MAX ) {// catch invalid item types ShowWarning("itemdb_parse_dbrow: Invalid item type %d for item %d. IT_ETC will be used.\n", id->type, nameid); id->type = IT_ETC; } if (id->type == IT_DELAYCONSUME) { //Items that are consumed only after target confirmation id->type = IT_USABLE; id->flag.delay_consume = 1; } else //In case of an itemdb reload and the item type changed. id->flag.delay_consume = 0; //When a particular price is not given, we should base it off the other one //(it is important to make a distinction between 'no price' and 0z) if ( str[4][0] ) id->value_buy = atoi(str[4]); else id->value_buy = atoi(str[5]) * 2; if ( str[5][0] ) id->value_sell = atoi(str[5]); else id->value_sell = id->value_buy / 2; /* if ( !str[4][0] && !str[5][0]) { ShowWarning("itemdb_parse_dbrow: No buying/selling price defined for item %d (%s), using 20/10z\n", nameid, id->jname); id->value_buy = 20; id->value_sell = 10; } else */ if (id->value_buy/124. < id->value_sell/75.) ShowWarning("itemdb_parse_dbrow: Buying/Selling [%d/%d] price of item %d (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n", id->value_buy, id->value_sell, nameid, id->jname); id->weight = atoi(str[6]); #if REMODE itemdb_re_split_atoi(str[7],&id->atk,&id->matk); #else id->atk = atoi(str[7]); #endif id->def = atoi(str[8]); id->range = atoi(str[9]); id->slot = atoi(str[10]); if (id->slot > MAX_SLOTS) { ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", nameid, id->jname, id->slot, MAX_SLOTS, MAX_SLOTS); id->slot = MAX_SLOTS; } itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0)); id->class_upper = atoi(str[12]); id->sex = atoi(str[13]); id->equip = atoi(str[14]); if (!id->equip && itemdb_isequip2(id)) { ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); id->type = IT_ETC; } id->wlv = atoi(str[15]); id->elv = atoi(str[16]); id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this id->look = atoi(str[18]); id->flag.available = 1; id->view_id = 0; id->sex = itemdb_gendercheck(id); //Apply gender filtering. if (id->script) { script_free_code(id->script); id->script = NULL; } if (id->equip_script) { script_free_code(id->equip_script); id->equip_script = NULL; } if (id->unequip_script) { script_free_code(id->unequip_script); id->unequip_script = NULL; } if (*str[19]) id->script = parse_script(str[19], source, line, scriptopt); if (*str[20]) id->equip_script = parse_script(str[20], source, line, scriptopt); if (*str[21]) id->unequip_script = parse_script(str[21], source, line, scriptopt); return true; }
void netbuffer_init() { char localsection[32]; raconf conf; sysint i; // Initialize Statistic counters: l_nEmergencyAllocations = 0; // Set localsection name according to running serverype. switch(SERVER_TYPE) { case SERVER_TYPE_LOGIN: strcpy(localsection, "login-netbuffer"); break; case SERVER_TYPE_CHAR: strcpy(localsection, "char-netbuffer"); break; //case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break; case SERVER_TYPE_MAP: strcpy(localsection, "map-netbuffer"); break; default: strcpy(localsection, "unsupported_type"); break; } conf = raconf_parse("conf/network.conf"); if(conf == NULL) { ShowFatalError(read_message("Source.common.net_buffer_init")); exit(EXIT_FAILURE); } // Get Values from config file l_nPools = (sysint)raconf_getintEx(conf, localsection, "netbuffer", "num", 0); if(l_nPools == 0) { ShowFatalError(read_message("Source.common.net_buffer_init2")); exit(EXIT_FAILURE); } // Allocate arrays. l_poolElemSize = (sysint *)aCalloc(l_nPools, sizeof(sysint)); l_pool = (mempool *)aCalloc(l_nPools, sizeof(mempool)); for(i = 0; i < l_nPools; i++) { int64 num_prealloc, num_realloc; char key[32]; sprintf(key, "pool_%u_size", (uint32)i+1); l_poolElemSize[i] = (sysint)raconf_getintEx(conf, localsection, "netbuffer", key, 4096); if(l_poolElemSize[i] < 32) { ShowWarning(read_message("Source.common.net_buffer_init3")); l_poolElemSize[i] = 32; } sprintf(key, "pool_%u_prealloc", (uint32)i+1); num_prealloc = raconf_getintEx(conf, localsection, "netbuffer", key, 150); sprintf(key, "pool_%u_realloc_step", (uint32)i+1); num_realloc = raconf_getintEx(conf, localsection, "netbuffer", key, 100); // Create Pool! sprintf(key, "Netbuffer %u", (uint32)l_poolElemSize[i]); // name. // Info ShowInfo(read_message("Source.net_buffer_init4"), l_poolElemSize[i], num_prealloc, num_realloc, (float)((sizeof(struct netbuf) + l_poolElemSize[i] - 32)* num_prealloc)/1024.0f/1024.0f); // // Size Calculation: // struct netbuf + requested buffer size - 32 (because the struct already contains 32 byte buffer space at the end of struct) l_pool[i] = mempool_create(key, (sizeof(struct netbuf) + l_poolElemSize[i] - 32), num_prealloc, num_realloc, NULL, NULL); if(l_pool[i] == NULL) { ShowFatalError(read_message("Source.net_buffer_init5"), l_poolElemSize[i]); // @leak: clean everything :D exit(EXIT_FAILURE); } }// raconf_destroy(conf); }//end: netbuffer_init()
Plugin* plugin_open(const char* filename) { Plugin* plugin; Plugin_Info* info; Plugin_Event_Table* events; void** procs; int init_flag = 1; //ShowDebug("plugin_open(%s)\n", filename); // Check if the plugin has been loaded before plugin = plugin_head; while (plugin) { // returns handle to the already loaded plugin if( plugin->state && strcmpi(plugin->filename, filename) == 0 ){ ShowWarning("plugin_open: not loaded (duplicate) : '"CL_WHITE"%s"CL_RESET"'\n", filename); return plugin; } plugin = plugin->next; } CREATE(plugin, Plugin, 1); plugin->state = -1; // not loaded plugin->dll = DLL_OPEN(filename); if( !plugin->dll ){ ShowWarning("plugin_open: not loaded (invalid file) : '"CL_WHITE"%s"CL_RESET"'\n", filename); plugin_unload(plugin); return NULL; } // Retrieve plugin information plugin->state = 0; // initialising info = (Plugin_Info*)DLL_SYM(plugin->dll, "plugin_info"); // For high priority plugins (those that are explicitly loaded from the conf file) // we'll ignore them even (could be a 3rd party dll file) if( !info ) {// foreign plugin //ShowDebug("plugin_open: plugin_info not found\n"); if( load_priority == 0 ) {// not requested //ShowDebug("plugin_open: not loaded (not requested) : '"CL_WHITE"%s"CL_RESET"'\n", filename); plugin_unload(plugin); return NULL; } } else if( !plugin_iscompatible(info->req_version) ) {// incompatible version ShowWarning("plugin_open: not loaded (incompatible version '%s' -> '%s') : '"CL_WHITE"%s"CL_RESET"'\n", info->req_version, PLUGIN_VERSION, filename); plugin_unload(plugin); return NULL; } else if( (info->type != PLUGIN_ALL && info->type != PLUGIN_CORE && info->type != SERVER_TYPE) || (info->type == PLUGIN_CORE && SERVER_TYPE != PLUGIN_LOGIN && SERVER_TYPE != PLUGIN_CHAR && SERVER_TYPE != PLUGIN_MAP) ) {// not for this server //ShowDebug("plugin_open: not loaded (incompatible) : '"CL_WHITE"%s"CL_RESET"'\n", filename); plugin_unload(plugin); return NULL; } plugin->info = ( info != NULL ? info : &default_info ); plugin->filename = aStrdup(filename); // Initialise plugin call table (For exporting procedures) procs = (void**)DLL_SYM(plugin->dll, "plugin_call_table"); if( procs ) *procs = plugin_call_table; //else ShowDebug("plugin_open: plugin_call_table not found\n"); // Register plugin events events = (Plugin_Event_Table*)DLL_SYM(plugin->dll, "plugin_event_table"); if( events ){ int i = 0; //ShowDebug("plugin_open: parsing plugin_event_table\n"); while( events[i].func_name ){ if( strcmpi(events[i].event_name, EVENT_PLUGIN_TEST) == 0 ){ Plugin_Test_Func* test_func; test_func = (Plugin_Test_Func*)DLL_SYM(plugin->dll, events[i].func_name); //ShowDebug("plugin_open: invoking "EVENT_PLUGIN_TEST" with %s()\n", events[i].func_name); if( test_func && test_func() == 0 ){ // plugin has failed test, disabling //ShowDebug("plugin_open: disabled (failed test) : %s\n", filename); init_flag = 0; } } else { Plugin_Event_Func* func; func = (Plugin_Event_Func*)DLL_SYM(plugin->dll, events[i].func_name); if (func) register_plugin_event(func, events[i].event_name); } i++; } } //else ShowDebug("plugin_open: plugin_event_table not found\n"); plugin->next = plugin_head; plugin_head = plugin; plugin->state = init_flag; // fully loaded ShowStatus("Done loading plugin '"CL_WHITE"%s"CL_RESET"'\n", (info) ? plugin->info->name : filename); return plugin; }
/// opens accounts file, loads it, and starts a periodic saving timer static bool account_db_txt_init(AccountDB* self) { AccountDB_TXT* db = (AccountDB_TXT*)self; DBMap* accounts; FILE* fp; char line[2048]; unsigned int version = 0; // create accounts database db->accounts = idb_alloc(DB_OPT_RELEASE_DATA); accounts = db->accounts; // open data file fp = fopen(db->account_db, "r"); if( fp == NULL ) { // no account file -> no account -> no login, including char-server (ERROR) ShowError(CL_RED"account_db_txt_init: Accounts file [%s] not found."CL_RESET"\n", db->account_db); return false; } // load data file while( fgets(line, sizeof(line), fp) != NULL ) { int account_id, n; unsigned int v; struct mmo_account acc; struct mmo_account* tmp; struct DBIterator* iter; int (*compare)(const char* str1, const char* str2) = ( db->case_sensitive ) ? strcmp : stricmp; if( line[0] == '/' && line[1] == '/' ) continue; n = 0; if( sscanf(line, "%d%n", &v, &n) == 1 && (line[n] == '\n' || line[n] == '\r') ) {// format version definition version = v; continue; } n = 0; if( sscanf(line, "%d\t%%newid%%%n", &account_id, &n) == 1 && (line[n] == '\n' || line[n] == '\r') ) {// auto-increment if( account_id > db->next_account_id ) db->next_account_id = account_id; continue; } if( !mmo_auth_fromstr(&acc, line, version) ) { ShowError("account_db_txt_init: skipping invalid data: %s", line); continue; } // apply constraints & checks here if( acc.sex != 'S' && (acc.account_id < START_ACCOUNT_NUM || acc.account_id > END_ACCOUNT_NUM) ) ShowWarning("account_db_txt_init: account %d:'%s' has ID outside of the defined range for accounts (min:%d max:%d)!\n", acc.account_id, acc.userid, START_ACCOUNT_NUM, END_ACCOUNT_NUM); iter = accounts->iterator(accounts); for( tmp = (struct mmo_account*)iter->first(iter,NULL); iter->exists(iter); tmp = (struct mmo_account*)iter->next(iter,NULL) ) if( compare(acc.userid, tmp->userid) == 0 ) break; iter->destroy(iter); if( tmp != NULL ) {// entry with identical username ShowWarning("account_db_txt_init: account %d:'%s' has same username as account %d. The account will be inaccessible!\n", acc.account_id, acc.userid, tmp->account_id); } if( idb_get(accounts, acc.account_id) != NULL ) {// account id already occupied ShowError("account_db_txt_init: ID collision for account id %d! Discarding data for account '%s'...\n", acc.account_id, acc.userid); continue; } // record entry in db tmp = (struct mmo_account*)aMalloc(sizeof(struct mmo_account)); memcpy(tmp, &acc, sizeof(struct mmo_account)); idb_put(accounts, acc.account_id, tmp); if( acc.account_id >= db->next_account_id ) db->next_account_id = acc.account_id + 1; } // close data file fclose(fp); // initialize data saving timer add_timer_func_list(mmo_auth_sync_timer, "mmo_auth_sync_timer"); db->save_timer = add_timer_interval(gettick() + AUTH_SAVING_INTERVAL, mmo_auth_sync_timer, 0, (intptr)db, AUTH_SAVING_INTERVAL); return true; }
/*========================================== * *------------------------------------------*/ int chrif_parse(int fd) { int packet_len, cmd; // only process data from the char-server if ( fd != char_fd ) { ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); do_close(fd); return 0; } if ( session[fd]->flag.eof ) { do_close(fd); char_fd = -1; chrif_on_disconnect(); return 0; } else if ( session[fd]->flag.ping ) {/* we've reached stall time */ if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */ set_eof(fd); return 0; } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */ chrif_keepalive(fd); session[fd]->flag.ping = 2; } } while ( RFIFOREST(fd) >= 2 ) { cmd = RFIFOW(fd,0); if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { int r = intif_parse(fd); // Passed on to the intif if (r == 1) continue; // Treated in intif if (r == 2) return 0; // Didn't have enough data (len==-1) ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); set_eof(fd); return 0; } if ( ( packet_len = packet_len_table[cmd-0x2af8] ) == -1) { // dynamic-length packet, second WORD holds the length if (RFIFOREST(fd) < 4) return 0; packet_len = RFIFOW(fd,2); } if ((int)RFIFOREST(fd) < packet_len) return 0; //ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd); switch(cmd) { case 0x2af9: chrif_connectack(fd); break; case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: chrif_authok(fd); break; case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; case 0x2b03: clif->charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; case 0x2b0a: socket_datasync(fd, false); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b14: chrif_accountban(fd); break; case 0x2b1b: chrif_recvfamelist(fd); break; case 0x2b1d: chrif_load_scdata(fd); break; case 0x2b1e: chrif_update_ip(fd); break; case 0x2b1f: chrif_disconnectplayer(fd); break; case 0x2b20: chrif_removemap(fd); break; case 0x2b21: chrif_save_ack(fd); break; case 0x2b22: chrif_updatefamelist_ack(fd); break; case 0x2b24: chrif_keepalive_ack(fd); break; case 0x2b25: chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; case 0x2b27: chrif_authfail(fd); break; default: ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); set_eof(fd); return 0; } if ( fd == char_fd ) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] RFIFOSKIP(fd, packet_len); } return 0; }
// Wisp/page request to send int mapif_parse_WisRequest(int fd) { struct WisData* wd; static int wisid = 0; char name[NAME_LENGTH], t_name[NAME_LENGTH*2]; //Needs space to allocate names with escaped chars [Skotlex] if ( fd <= 0 ) {return 0;} // check if we have a valid fd if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) { ShowWarning("inter: Wis message size too long.\n"); return 0; } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows... ShowError("inter: Wis message doesn't exist.\n"); return 0; } memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] name[NAME_LENGTH-1]= '\0'; sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, jstrescapecpy(t_name, name)); if(mysql_query(&mysql_handle, tmp_sql) ) { ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); } sql_res = mysql_store_result(&mysql_handle); // search if character exists before to ask all map-servers if (!(sql_row = mysql_fetch_row(sql_res))) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); // Character exists. So, ask all map-servers } else { // to be sure of the correct name, rewrite it memset(name, 0, NAME_LENGTH); strncpy(name, sql_row[0], NAME_LENGTH); // if source is destination, don't ask other servers. if (strcmp((char*)RFIFOP(fd,4),name) == 0) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); } else { CREATE(wd, struct WisData, 1); // Whether the failure of previous wisp/page transmission (timeout) check_ttl_wisdata(); wd->id = ++wisid; wd->fd = fd; wd->len= RFIFOW(fd,2)-52; memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH); memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH); memcpy(wd->msg, RFIFOP(fd,52), wd->len); wd->tick = gettick(); numdb_insert(wis_db, wd->id, wd); mapif_wis_message(wd); } } //Freeing ... O.o if(sql_res){ mysql_free_result(sql_res); } return 0; }
/** * Read each line of Mercenary's database **/ static bool mercenary_readdb_sub(char* str[], int columns, int current) { int ele; uint16 i, class_ = atoi(str[0]); struct s_mercenary_db *db; struct status_data *status; //Find the ID, already exist or not in mercenary_db ARR_FIND(0,mercenary_count,i,mercenary_db[i].class_ == class_); if (i >= mercenary_count) db = &mercenary_db[mercenary_count]; else db = &mercenary_db[i]; db->class_ = class_; safestrncpy(db->sprite, str[1], NAME_LENGTH); safestrncpy(db->name, str[2], NAME_LENGTH); db->lv = atoi(str[3]); status = &db->status; db->vd.class_ = db->class_; status->max_hp = atoi(str[4]); status->max_sp = atoi(str[5]); status->rhw.range = atoi(str[6]); status->rhw.atk = atoi(str[7]); status->rhw.atk2 = status->rhw.atk + atoi(str[8]); status->def = atoi(str[9]); status->mdef = atoi(str[10]); status->str = atoi(str[11]); status->agi = atoi(str[12]); status->vit = atoi(str[13]); status->int_ = atoi(str[14]); status->dex = atoi(str[15]); status->luk = atoi(str[16]); db->range2 = atoi(str[17]); db->range3 = atoi(str[18]); status->size = atoi(str[19]); status->race = atoi(str[20]); ele = atoi(str[21]); status->def_ele = ele%20; status->ele_lv = (unsigned char)floor(ele/20.); if( !CHK_ELEMENT(status->def_ele) ) { ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_ALL - 1); status->def_ele = ELE_NEUTRAL; } if( !CHK_ELEMENT_LEVEL(status->ele_lv) ) { ShowWarning("Mercenary %d has invalid element level %d (max is %d)\n", db->class_, status->ele_lv, MAX_ELE_LEVEL); status->ele_lv = 1; } status->aspd_rate = 1000; status->speed = atoi(str[22]); status->adelay = atoi(str[23]); status->amotion = atoi(str[24]); status->dmotion = atoi(str[25]); if (i >= mercenary_count) mercenary_count++; return true; }
void yaml_invalid_warning(const char* fmt, YAML::Node &node, std::string &file) { YAML::Emitter out; out << node; ShowWarning(fmt, file.c_str()); ShowMessage("%s\n", out.c_str()); }
void CZone::DecreaseZoneCounter(CCharEntity* PChar) { DSP_DEBUG_BREAK_IF(PChar == NULL); DSP_DEBUG_BREAK_IF(PChar->loc.zone != this); //remove pets if(PChar->PPet != NULL) { charutils::BuildingCharPetAbilityTable(PChar,(CPetEntity*)PChar->PPet,0);//blank the pet commands if(PChar->PPet->isCharmed) { petutils::DespawnPet(PChar); } else { PChar->PPet->status = STATUS_DISAPPEAR; if( ((CPetEntity*)(PChar->PPet))->getPetType() == PETTYPE_AVATAR ) PChar->setModifier(MOD_AVATAR_PERPETUATION, 0); } // It may have been nulled by DespawnPet if(PChar->PPet != NULL) { PChar->PPet->PBattleAI->SetCurrentAction(ACTION_NONE); DeletePET(PChar->PPet);//remove the TID for this pet for (EntityList_t::const_iterator it = m_charList.begin() ; it != m_charList.end() ; ++it) { //inform other players of the pets removal CCharEntity* PCurrentChar = (CCharEntity*)it->second; SpawnIDList_t::iterator PET = PCurrentChar->SpawnPETList.find(PChar->PPet->id); if( PET != PCurrentChar->SpawnPETList.end() ) { PCurrentChar->SpawnPETList.erase(PET); PCurrentChar->pushPacket(new CEntityUpdatePacket(PChar->PPet, ENTITY_DESPAWN)); } } PChar->PPet = NULL; } } //remove bcnm status if(m_InstanceHandler != NULL && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_BATTLEFIELD)) { if(m_InstanceHandler->disconnectFromBcnm(PChar)){ ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n",PChar->GetName()); } if(PChar->loc.destination==0){ //this player is disconnecting/logged out, so move them to the entrance //move depending on zone int pos[4] = {0,0,0,0}; instanceutils::getStartPosition(m_zoneID,pos); if(pos!=NULL){ PChar->loc.p.x = pos[0]; PChar->loc.p.y = pos[1]; PChar->loc.p.z = pos[2]; PChar->loc.p.rotation = pos[3]; charutils::SaveCharPosition(PChar); } else{ ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n",PChar->GetName()); } } } else if(m_InstanceHandler != NULL && PChar->StatusEffectContainer->HasStatusEffect(EFFECT_DYNAMIS, 0)) { if(m_InstanceHandler->disconnectFromDynamis(PChar)){ ShowDebug("Removed %s from the BCNM they were in as they have left the zone.\n",PChar->GetName()); } if(PChar->loc.destination==0){ //this player is disconnecting/logged out, so move them to the entrance //move depending on zone int pos[4] = {0,0,0,0}; instanceutils::getStartPosition(m_zoneID,pos); if(pos!=NULL){ PChar->loc.p.x = pos[0]; PChar->loc.p.y = pos[1]; PChar->loc.p.z = pos[2]; PChar->loc.p.rotation = pos[3]; charutils::SaveCharPosition(PChar); } else{ ShowWarning("%s has disconnected from the BCNM but cannot move them to the lobby as the lobby position is unknown!\n",PChar->GetName()); } } } for (EntityList_t::const_iterator it = m_mobList.begin() ; it != m_mobList.end() ; ++it) { CMobEntity* PCurrentMob = (CMobEntity*)it->second; PCurrentMob->PEnmityContainer->Clear(PChar->id); if(PCurrentMob->m_OwnerID.id == PChar->id){ PCurrentMob->m_OwnerID.clean(); } } // TODO: могут возникать проблемы с переходом между одной и той же зоной (zone == prevzone) m_charList.erase(PChar->targid); ShowDebug(CL_CYAN"CZone:: %s DecreaseZoneCounter <%u> %s\n" CL_RESET, GetName(), m_charList.size(),PChar->GetName()); if (ZoneTimer && m_charList.empty()) { ZoneTimer->m_type = CTaskMgr::TASK_REMOVE; ZoneTimer = NULL; HealAllMobs(); } else { for (EntityList_t::const_iterator it = m_charList.begin() ; it != m_charList.end() ; ++it) { CCharEntity* PCurrentChar = (CCharEntity*)it->second; SpawnIDList_t::iterator PC = PCurrentChar->SpawnPCList.find(PChar->id); if( PC != PCurrentChar->SpawnPCList.end() ) { PCurrentChar->SpawnPCList.erase(PC); PCurrentChar->pushPacket(new CCharPacket(PChar,ENTITY_DESPAWN)); } } } if (PChar->m_LevelRestriction != 0) { if (PChar->PParty) { if (PChar->PParty->GetSyncTarget() == PChar || PChar->PParty->GetLeader() == PChar) { PChar->PParty->SetSyncTarget(NULL, 551); } if (PChar->PParty->GetSyncTarget() != NULL) { uint8 count = 0; for (uint32 i = 0; i < PChar->PParty->members.size(); ++i) { if (PChar->PParty->members.at(i) != PChar && PChar->PParty->members.at(i)->getZone() == PChar->PParty->GetSyncTarget()->getZone()) { count++; } } if (count < 2) //3, because one is zoning out - thus at least 2 will be left { PChar->PParty->SetSyncTarget(NULL, 552); } } } PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_LEVEL_SYNC); PChar->StatusEffectContainer->DelStatusEffectSilent(EFFECT_LEVEL_RESTRICTION); } if (PChar->PTreasurePool != NULL) // TODO: условие для устранения проблем с MobHouse, надо блин решить ее раз и навсегда { PChar->PTreasurePool->DelMember(PChar); } for (regionList_t::const_iterator region = m_regionList.begin(); region != m_regionList.end(); ++region) { if ((*region)->GetRegionID() == PChar->m_InsideRegionID) { luautils::OnRegionLeave(PChar, *region); break; } } PChar->loc.zone = NULL; PChar->loc.prevzone = m_zoneID; PChar->SpawnPCList.clear(); PChar->SpawnNPCList.clear(); PChar->SpawnMOBList.clear(); PChar->SpawnPETList.clear(); }
int read_elemental_skilldb(void) { FILE *fp; char line[1024], *p; char *str[4]; struct s_elemental_db *db; int i, j = 0, k = 0, class_; int skillid, skilllv, skillmode; sprintf(line, "%s/%s", db_path, "elemental_skill_db.txt"); fp = fopen(line, "r"); if( !fp ) { ShowError("read_elemental_skilldb : can't read elemental_skill_db.txt\n"); return -1; } while( fgets(line, sizeof(line), fp) ) { k++; if( line[0] == '/' && line[1] == '/' ) continue; i = 0; p = strtok(line, ","); while( p != NULL && i < 4 ) { str[i++] = p; p = strtok(NULL, ","); } if( i < 4 ) { ShowError("read_elemental_skilldb : Incorrect number of columns at elemental_skill_db.txt line %d.\n", k); continue; } class_ = atoi(str[0]); ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental_db[i].class_); if( i == MAX_ELEMENTAL_CLASS ) { ShowError("read_elemental_skilldb : Class not found in elemental_db for skill entry, line %d.\n", k); continue; } skillid = atoi(str[1]); if( skillid < EL_SKILLBASE || skillid >= EL_SKILLBASE + MAX_ELEMENTALSKILL ) { ShowError("read_elemental_skilldb : Skill out of range, line %d.\n", k); continue; } db = &elemental_db[i]; skilllv = atoi(str[2]); skillmode = atoi(str[3]); if( skillmode < EL_SKILLMODE_PASIVE || skillmode > EL_SKILLMODE_AGGRESSIVE ) { ShowError("read_elemental_skilldb : Skillmode out of range, line %d.\n",k); skillmode = EL_SKILLMODE_PASIVE; continue; } ARR_FIND( 0, MAX_ELESKILLTREE, i, db->skill[i].id == 0 || db->skill[i].id == skillid ); if( i == MAX_ELESKILLTREE ) { ShowWarning("Unable to load skill %d into Elemental %d's tree. Maximum number of skills per elemental has been reached.\n", skillid, class_); continue; } db->skill[i].id = skillid; db->skill[i].lv = skilllv; db->skill[i].mode = skillmode; j++; } fclose(fp); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/elemental_skill_db.txt"CL_RESET"'.\n",j); return 0; }
int read_elementaldb(void) { FILE *fp; char line[1024], *p; char *str[26]; int i, j = 0, k = 0, ele; struct s_elemental_db *db; struct status_data *status; sprintf(line, "%s/%s", db_path, "elemental_db.txt"); memset(elemental_db,0,sizeof(elemental_db)); fp = fopen(line, "r"); if( !fp ) { ShowError("read_elementaldb : can't read elemental_db.txt\n"); return -1; } while( fgets(line, sizeof(line), fp) && j < MAX_ELEMENTAL_CLASS ) { k++; if( line[0] == '/' && line[1] == '/' ) continue; i = 0; p = strtok(line, ","); while( p != NULL && i < 26 ) { str[i++] = p; p = strtok(NULL, ","); } if( i < 26 ) { ShowError("read_elementaldb : Incorrect number of columns at elemental_db.txt line %d.\n", k); continue; } db = &elemental_db[j]; db->class_ = atoi(str[0]); strncpy(db->sprite, str[1], NAME_LENGTH); strncpy(db->name, str[2], NAME_LENGTH); db->lv = atoi(str[3]); status = &db->status; db->vd.class_ = db->class_; status->max_hp = atoi(str[4]); status->max_sp = atoi(str[5]); status->rhw.range = atoi(str[6]); status->rhw.atk = atoi(str[7]); status->rhw.atk2 = status->rhw.atk + atoi(str[8]); status->def = atoi(str[9]); status->mdef = atoi(str[10]); status->str = atoi(str[11]); status->agi = atoi(str[12]); status->vit = atoi(str[13]); status->int_ = atoi(str[14]); status->dex = atoi(str[15]); status->luk = atoi(str[16]); db->range2 = atoi(str[17]); db->range3 = atoi(str[18]); status->size = atoi(str[19]); status->race = atoi(str[20]); ele = atoi(str[21]); status->def_ele = ele%10; status->ele_lv = ele/20; if( status->def_ele >= ELE_MAX ) { ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); status->def_ele = ELE_NEUTRAL; } if( status->ele_lv < 1 || status->ele_lv > 4 ) { ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); status->ele_lv = 1; } status->aspd_rate = 1000; status->speed = atoi(str[22]); status->adelay = atoi(str[23]); status->amotion = atoi(str[24]); status->dmotion = atoi(str[25]); j++; } fclose(fp); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' elementals in '"CL_WHITE"db/elemental_db.txt"CL_RESET"'.\n",j); return 0; }
/** * Attempt to create new buying store * @param sd * @param zenylimit * @param result * @param storename * @param *itemlist { <nameid>.W, <amount>.W, <price>.L }* * @param count Number of item on the itemlist * @return 0 If success, 1 - Cannot open, 2 - Manner penalty, 3 - Mapflag restiction, 4 - Cell restriction, 5 - Invalid count/result, 6 - Cannot give item, 7 - Will be overweight */ char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count) { unsigned int i, weight, listidx; char message_sql[MESSAGE_SIZE*2]; nullpo_retr(1, sd); if( !result || count == 0 ) {// canceled, or no items return 5; } if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] ) {// disabled or invalid input sd->buyingstore.slots = 0; clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return 1; } if( !pc_can_give_items(sd) ) {// custom: GM is not allowed to buy (give zeny) sd->buyingstore.slots = 0; clif_displaymessage(sd->fd, msg_txt(sd,246)); clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return 6; } if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) ) {// custom: mute limitation return 2; } if( map[sd->bl.m].flag.novending ) {// custom: no vending maps clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map" return 3; } if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) {// custom: no vending cells clif_displaymessage(sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell." return 4; } weight = sd->weight; // check item list for( i = 0; i < count; i++ ) {// itemlist: <name id>.W <amount>.W <price>.L unsigned short nameid, amount; int price, idx; struct item_data* id; nameid = RBUFW(itemlist,i*8+0); amount = RBUFW(itemlist,i*8+2); price = RBUFL(itemlist,i*8+4); if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 ) {// invalid input break; } if( price <= 0 || price > BUYINGSTORE_MAX_PRICE ) {// invalid price: unlike vending, items cannot be bought at 0 Zeny break; } if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_get_group_level(sd), pc_get_group_level(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 ) {// restrictions: allowed, no character-bound items and at least one must be owned break; } if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT ) {// too many items of same kind break; } if( i ) {// duplicate check. as the client does this too, only malicious intent should be caught here ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid ); if( listidx != i ) {// duplicate ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id); break; } } weight+= id->weight*amount; sd->buyingstore.items[i].nameid = nameid; sd->buyingstore.items[i].amount = amount; sd->buyingstore.items[i].price = price; } if( i != count ) {// invalid item/amount/price sd->buyingstore.slots = 0; clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return 5; } if( (sd->max_weight*90)/100 < weight ) {// not able to carry all wanted items without getting overweight (90%) sd->buyingstore.slots = 0; clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight); return 7; } // success sd->state.buyingstore = true; sd->buyer_id = buyingstore_getuid(); sd->buyingstore.zenylimit = zenylimit; sd->buyingstore.slots = i; // store actual amount of items safestrncpy(sd->message, storename, sizeof(sd->message)); Sql_EscapeString( mmysql_handle, message_sql, sd->message ); if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`limit`,`autotrade`, `body_direction`, `head_direction`, `sit`) " "VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, %d, '%d', '%d', '%d' );", buyingstores_db, sd->buyer_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->buyingstore.zenylimit, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){ Sql_ShowDebug(mmysql_handle); } for( i = 0; i < sd->buyingstore.slots; i++ ){ if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`buyingstore_id`,`index`,`item_id`,`amount`,`price`) VALUES( %d, %d, %hu, %d, %d );", buyingstore_items_db, sd->buyer_id, i, sd->buyingstore.items[i].nameid, sd->buyingstore.items[i].amount, sd->buyingstore.items[i].price ) != SQL_SUCCESS ){ Sql_ShowDebug(mmysql_handle); } } clif_buyingstore_myitemlist(sd); clif_buyingstore_entry(sd); idb_put(buyingstore_db, sd->status.char_id, sd); return 0; }
int log_config_read(const char* cfgName) { static int count = 0; char line[1024], w1[1024], w2[1024]; FILE *fp; if( count++ == 0 ) log_set_defaults(); if( ( fp = fopen(cfgName, "r") ) == NULL ) { ShowError("Log configuration file not found at: %s\n", cfgName); return 1; } while( fgets(line, sizeof(line), fp) ) { if( line[0] == '/' && line[1] == '/' ) continue; if( sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 ) { if( strcmpi(w1, "enable_logs") == 0 ) log_config.enable_logs = (e_log_pick_type)config_switch(w2); else if( strcmpi(w1, "sql_logs") == 0 ) log_config.sql_logs = (bool)config_switch(w2); //start of common filter settings else if( strcmpi(w1, "rare_items_log") == 0 ) log_config.rare_items_log = atoi(w2); else if( strcmpi(w1, "refine_items_log") == 0 ) log_config.refine_items_log = atoi(w2); else if( strcmpi(w1, "price_items_log") == 0 ) log_config.price_items_log = atoi(w2); else if( strcmpi(w1, "amount_items_log") == 0 ) log_config.amount_items_log = atoi(w2); //end of common filter settings else if( strcmpi(w1, "log_branch") == 0 ) log_config.branch = config_switch(w2); else if( strcmpi(w1, "log_filter") == 0 ) log_config.filter = config_switch(w2); else if( strcmpi(w1, "log_zeny") == 0 ) log_config.zeny = config_switch(w2); else if( strcmpi( w1, "log_cash" ) == 0 ) log_config.cash = config_switch( w2 ); else if( strcmpi(w1, "log_commands") == 0 ) log_config.commands = config_switch(w2); else if( strcmpi(w1, "log_npc") == 0 ) log_config.npc = config_switch(w2); else if( strcmpi(w1, "log_chat") == 0 ) log_config.chat = config_switch(w2); else if( strcmpi(w1, "log_mvpdrop") == 0 ) log_config.mvpdrop = config_switch(w2); else if( strcmpi(w1, "log_chat_woe_disable") == 0 ) log_config.log_chat_woe_disable = (bool)config_switch(w2); else if( strcmpi(w1, "log_branch_db") == 0 ) safestrncpy(log_config.log_branch, w2, sizeof(log_config.log_branch)); else if( strcmpi(w1, "log_pick_db") == 0 ) safestrncpy(log_config.log_pick, w2, sizeof(log_config.log_pick)); else if( strcmpi(w1, "log_zeny_db") == 0 ) safestrncpy(log_config.log_zeny, w2, sizeof(log_config.log_zeny)); else if( strcmpi(w1, "log_mvpdrop_db") == 0 ) safestrncpy(log_config.log_mvpdrop, w2, sizeof(log_config.log_mvpdrop)); else if( strcmpi(w1, "log_gm_db") == 0 ) safestrncpy(log_config.log_gm, w2, sizeof(log_config.log_gm)); else if( strcmpi(w1, "log_npc_db") == 0 ) safestrncpy(log_config.log_npc, w2, sizeof(log_config.log_npc)); else if( strcmpi(w1, "log_chat_db") == 0 ) safestrncpy(log_config.log_chat, w2, sizeof(log_config.log_chat)); else if( strcmpi( w1, "log_cash_db" ) == 0 ) safestrncpy( log_config.log_cash, w2, sizeof( log_config.log_cash ) ); //support the import command, just like any other config else if( strcmpi(w1,"import") == 0 ) log_config_read(w2); else ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); } } fclose(fp); if( --count == 0 ) {// report final logging state const char* target = log_config.sql_logs ? "table" : "file"; if( log_config.enable_logs && log_config.filter ) { ShowInfo("Logging item transactions to %s '%s'.\n", target, log_config.log_pick); } if( log_config.branch ) { ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, log_config.log_pick); } if( log_config.chat ) { ShowInfo("Logging chat to %s '%s'.\n", target, log_config.log_chat); } if( log_config.commands ) { ShowInfo("Logging commands to %s '%s'.\n", target, log_config.log_gm); } if( log_config.mvpdrop ) { ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, log_config.log_mvpdrop); } if( log_config.npc ) { ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, log_config.log_npc); } if( log_config.zeny ) { ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, log_config.log_zeny); } if( log_config.cash ){ ShowInfo( "Logging Cash transactions to %s '%s'.\n", target, log_config.log_cash ); } } return 0; }
static void cevents_init() { if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE) ShowWarning ("Unable to install the console handler!\n"); }
bool CStatusEffectContainer::AddStatusEffect(CStatusEffect* PStatusEffect, bool silent) { if(PStatusEffect == nullptr){ ShowWarning("status_effect_container::AddStatusEffect Status effect given was nullptr!\n"); return false; } uint16 statusId = PStatusEffect->GetStatusID(); if(statusId >= MAX_EFFECTID){ ShowWarning("status_effect_container::AddStatusEffect statusId given is OVER limit %d\n", statusId); return false; } if(CanGainStatusEffect((EFFECT)statusId, PStatusEffect->GetPower())) { // check for minimum duration if(PStatusEffect->GetDuration() < effects::EffectsParams[statusId].MinDuration){ PStatusEffect->SetDuration(effects::EffectsParams[statusId].MinDuration); } // remove clean up other effects OverwriteStatusEffect(PStatusEffect); PStatusEffect->SetOwner(m_POwner); SetEffectParams(PStatusEffect); // remove effects with same type DelStatusEffectsByType(PStatusEffect->GetType()); PStatusEffect->SetStartTime(gettick()); m_StatusEffectList.push_back(PStatusEffect); luautils::OnEffectGain(m_POwner, PStatusEffect); m_POwner->addModifiers(&PStatusEffect->modList); if (PStatusEffect->GetStatusID() >= EFFECT_FIRE_MANEUVER && PStatusEffect->GetStatusID() <= EFFECT_DARK_MANEUVER && m_POwner->objtype == TYPE_PC) { puppetutils::CheckAttachmentsForManeuver((CCharEntity*)m_POwner, PStatusEffect->GetStatusID(), true); } if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in { m_POwner->UpdateHealth(); } if (m_POwner->objtype == TYPE_PC) { CCharEntity* PChar = (CCharEntity*)m_POwner; if (PStatusEffect->GetIcon() != 0) { UpdateStatusIcons(); } if( m_POwner->health.maxhp != 0) //make sure we're not in the middle of logging in { //check for latents PChar->PLatentEffectContainer->CheckLatentsFoodEffect(); PChar->PLatentEffectContainer->CheckLatentsStatusEffect(); PChar->PLatentEffectContainer->CheckLatentsRollSong(PStatusEffect->GetFlag() & (EFFECTFLAG_SONG | EFFECTFLAG_ROLL)); PChar->UpdateHealth(); PChar->pushPacket(new CCharHealthPacket(PChar)); } PChar->pushPacket(new CCharSyncPacket(PChar)); } m_POwner->updatemask |= UPDATE_HP; return true; } return false; }
static BOOL PrepareToConfig() { BOOL bMustExit = FALSE; // Use a local copy of the config info to decide what should be configured // or unconfigured. We do this so that if the user cancels for some reason, // the real config state will still be what the user expects (what was // previously read from the system plus the user's changes). CONFIG_STATE configFS = g_CfgData.configFS; // File server CONFIG_STATE configDB = g_CfgData.configDB; // Database server CONFIG_STATE configBak = g_CfgData.configBak; // Backup server CONFIG_STATE configSCS = g_CfgData.configSCS; // System Control server CONFIG_STATE configSCC = g_CfgData.configSCC; // System Control client BOOL bWorkToDo = FALSE; bWorkToDo |= PrepareToConfig(configFS, bFsRunning, bFsOn, IDC_FS_SERVICE); bWorkToDo |= PrepareToConfig(configDB, bDbRunning, bDbOn, IDC_DB_SERVICE); bWorkToDo |= PrepareToConfig(configBak, bBakRunning, bBakOn, IDC_BK_SERVICE); bWorkToDo |= PrepareToConfig(configSCS, bScsRunning, bScsOn, IDC_SCS); bWorkToDo |= PrepareToConfig(configSCC, bSccRunning, bSccOn, IDC_SCC); // If there is nothing to do, then just return TRUE. if (!bWorkToDo) return TRUE; // If we are unconfiguring the last DB server: // 1) Warn user and ask for confirmation // 2) Unconfigure all other servers that are running on this machine // 3) Tell them (after unconfiguring) that they must run the Wizard if they // wish to reconfigure the machine, then exit the program. if (configDB == CS_UNCONFIGURE) { if (g_CfgData.bLastDBServer) { int nChoice = MsgBox(hDlg, IDS_LAST_DB_SERVER, GetAppTitleID(), MB_YESNO | MB_ICONEXCLAMATION); if (nChoice == IDNO) return FALSE; // Make sure these all get unconfigured as well. If they are not configured, then // nothing bad will happen because the config calls are idempotent. configFS = CS_UNCONFIGURE; configBak = CS_UNCONFIGURE; configSCS = CS_UNCONFIGURE; configSCC = CS_UNCONFIGURE; } } // Get additional needed information from the user GET_ADMIN_INFO_OPTIONS eOptions; BOOL bDB = (ShouldConfig(configDB) || ShouldUnconfig(configDB)); // Use this as our default eOptions = GAIO_LOGIN_ONLY; // If we already have a sys control machine, then we don't need to ask for it if (ShouldConfig(configSCC)) { if (szScMachine[0] == 0) { ShowWarning(hDlg, IDS_MUST_ENTER_SCS_NAME); return FALSE; } lstrcpy(g_CfgData.szSysControlMachine, szScMachine); } else if (bDB && !g_CfgData.bLastDBServer) { // We need to know the name of the SCM machine. Are we the SCM machine? if (bScsRunning) lstrcpy(g_CfgData.szSysControlMachine, g_CfgData.szHostname); else eOptions = GAIO_GET_SCS; } // If doing a login only and the admin info is reusable if ((eOptions != GAIO_LOGIN_ONLY) || !g_CfgData.bReuseAdminInfo) { if (!GetAdminInfo(hDlg, eOptions)) return FALSE; // Use the admin info to get new handles if (!GetHandles(hDlg)) return FALSE; } // Now that we are ready to configure, copy our local config info // into the structure that the config engine uses. g_CfgData.configFS = configFS; g_CfgData.configDB = configDB; g_CfgData.configBak = configBak; g_CfgData.configSCS = configSCS; g_CfgData.configSCC = configSCC; // Configure the server BOOL bConfigSucceeded = Configure(hDlg, bMustExit); if (bConfigSucceeded) { if (bMustExit) { PostQuitMessage(0); return TRUE; } g_CfgData.bReuseAdminInfo = TRUE; } else g_CfgData.szAdminPW[0] = 0; // Get current config status BOOL bCanceled = FALSE; DWORD dwStatus = GetCurrentConfig(hDlg, bCanceled); if (dwStatus || bCanceled) { if (!bCanceled) ErrorDialog(dwStatus, IDS_CONFIG_CHECK_FAILED); } // Show the initial services config ShowInitialConfig(); ShowServiceStates(); return TRUE; }
static void cevents_init() { if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE) ShowWarning ("Não foi possível instalar o manipulador do console!\n"); }
// ギルドメンバデータ変更要求 int mapif_parse_GuildMemberInfoChange(int fd, int guild_id, int account_id, int char_id, int type, const char *data, int len) { int i; struct guild *g; g = idb_get(guild_db, guild_id); if(g == NULL) return 0; for(i = 0; i < g->max_member; i++) if (g->member[i].account_id == account_id && g->member[i].char_id == char_id) break; if (i == g->max_member) { ShowWarning("int_guild: GuildMemberChange: Not found %d,%d in %d[%s]\n", account_id, char_id, guild_id, g->name); return 0; } switch(type) { case GMI_POSITION: // 役職 g->member[i].position = *((int *)data); break; case GMI_EXP: // EXP { unsigned int exp, old_exp=g->member[i].exp; g->member[i].exp=*((unsigned int *)data); if (g->member[i].exp > old_exp) { exp = g->member[i].exp - old_exp; if (guild_exp_rate != 100) exp = exp*guild_exp_rate/100; if (exp > UINT_MAX - g->exp) g->exp = UINT_MAX; else g->exp+=exp; guild_calcinfo(g); mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,4); } break; } case GMI_HAIR: { g->member[i].hair=*((int *)data); mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); break; } case GMI_HAIR_COLOR: { g->member[i].hair_color=*((int *)data); mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); break; } case GMI_GENDER: { g->member[i].gender=*((int *)data); mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); break; } case GMI_CLASS: { g->member[i].class_=*((int *)data); mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); break; } case GMI_LEVEL: { g->member[i].lv=*((int *)data); mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len); break; } default: ShowError("int_guild: GuildMemberInfoChange: Unknown type %d\n", type); break; } mapif_guild_memberinfochanged(guild_id, account_id, char_id, type, data, len); return 0; }
int32 login_config_read(const char *cfgName) { char line[1024], w1[1024], w2[1024]; FILE *fp; fp = fopen(cfgName, "r"); if (fp == nullptr) { ShowError("login configuration file not found at: %s\n", cfgName); return 1; } while (fgets(line, sizeof(line), fp)) { char* ptr; if (line[0] == '#') continue; if (sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2) continue; //Strip trailing spaces ptr = w2 + strlen(w2); while (--ptr >= w2 && *ptr == ' '); ptr++; *ptr = '\0'; if (strcmpi(w1, "timestamp_format") == 0) { strncpy(timestamp_format, w2, 19); } else if (strcmpi(w1, "stdout_with_ansisequence") == 0) { stdout_with_ansisequence = config_switch(w2); } else if (strcmpi(w1, "console_silent") == 0) { ShowInfo("Console Silent Setting: %d\n", atoi(w2)); msg_silent = atoi(w2); } else if (strcmp(w1, "mysql_host") == 0) { login_config.mysql_host = aStrdup(w2); } else if (strcmp(w1, "mysql_login") == 0) { login_config.mysql_login = aStrdup(w2); } else if (strcmp(w1, "mysql_password") == 0) { login_config.mysql_password = aStrdup(w2); } else if (strcmp(w1, "mysql_port") == 0) { login_config.mysql_port = atoi(w2); } else if (strcmp(w1, "mysql_database") == 0) { login_config.mysql_database = aStrdup(w2); } else if (strcmp(w1, "search_server_port") == 0) { login_config.search_server_port = atoi(w2); } else if (strcmp(w1, "expansions") == 0) { login_config.expansions = atoi(w2); } else if (strcmp(w1, "servername") == 0) { login_config.servername = aStrdup(w2); } else if (strcmpi(w1, "import") == 0) { login_config_read(w2); } else if (strcmp(w1, "msg_server_port") == 0) { login_config.msg_server_port = atoi(w2); } else if (strcmp(w1, "msg_server_ip") == 0) { login_config.msg_server_ip = aStrdup(w2); } else { ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); } } fclose(fp); return 0; }
/*========================================== * アイテムデータベースの読み込み *------------------------------------------*/ static int itemdb_readdb(void) { const char* filename[] = { #if REMODE "re/item_db.txt", #else "pre-re/item_db.txt", #endif "item_db2.txt" }; int fi; for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { uint32 lines = 0, count = 0; char line[1024]; char path[256]; FILE* fp; sprintf(path, "%s/%s", db_path, filename[fi]); fp = fopen(path, "r"); if( fp == NULL ) { ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path); continue; } // process rows one by one while(fgets(line, sizeof(line), fp)) { char *str[32], *p; int i; lines++; if(line[0] == '/' && line[1] == '/') continue; memset(str, 0, sizeof(str)); p = line; while( ISSPACE(*p) ) ++p; if( *p == '\0' ) continue;// empty line for( i = 0; i < 19; ++i ) { str[i] = p; p = strchr(p,','); if( p == NULL ) break;// comma not found *p = '\0'; ++p; } if( p == NULL ) { ShowError("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } // Script if( *p != '{' ) { ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } str[19] = p; p = strstr(p+1,"},"); if( p == NULL ) { ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } p[1] = '\0'; p += 2; // OnEquip_Script if( *p != '{' ) { ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } str[20] = p; p = strstr(p+1,"},"); if( p == NULL ) { ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } p[1] = '\0'; p += 2; // OnUnequip_Script (last column) if( *p != '{' ) { ShowError("itemdb_readdb: Invalid format (OnUnequip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); continue; } str[21] = p; if (!itemdb_parse_dbrow(str, path, lines, 0)) continue; count++; } fclose(fp); ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]); } return 0; }
/*========================================== * *------------------------------------------*/ int chrif_parse(int fd) { int packet_len, cmd; // only process data from the char-server if (fd != char_fd) { ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); do_close(fd); return 0; } if (session[fd]->flag.eof) { if (chrif_connected == 1) chrif_disconnect(fd); do_close(fd); return 0; } while (RFIFOREST(fd) >= 2) { cmd = RFIFOW(fd,0); if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { int r = intif_parse(fd); // intifに渡す if (r == 1) continue; // intifで処理した if (r == 2) return 0; // intifで処理したが、データが足りない ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); set_eof(fd); return 0; } packet_len = packet_len_table[cmd-0x2af8]; if (packet_len == -1) { // dynamic-length packet, second WORD holds the length if (RFIFOREST(fd) < 4) return 0; packet_len = RFIFOW(fd,2); } if ((int)RFIFOREST(fd) < packet_len) return 0; //ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd); switch(cmd) { case 0x2af9: chrif_connectack(fd); break; case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: chrif_authok(fd); break; case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b07: clif_updatemaxid(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; case 0x2b0b: chrif_changedgm(fd); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; case 0x2b12: chrif_divorce(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b13: chrif_accountdeletion(fd); break; case 0x2b14: chrif_accountban(fd); break; case 0x2b15: chrif_recvgmaccounts(fd); break; case 0x2b1b: chrif_recvfamelist(fd); break; case 0x2b1d: chrif_load_scdata(fd); break; case 0x2b1e: chrif_update_ip(fd); break; case 0x2b1f: chrif_disconnectplayer(fd); break; case 0x2b20: chrif_removemap(fd); break; case 0x2b21: chrif_save_ack(fd); break; case 0x2b22: chrif_updatefamelist_ack(fd); break; case 0x2b24: chrif_keepalive_ack(fd); break; default: ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); set_eof(fd); return 0; } if (fd == char_fd) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] RFIFOSKIP(fd, packet_len); } return 0; }
/** * Loads group configuration from config file into memory. * @private */ static void read_config(void) { config_setting_t *groups = NULL; const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name int group_count = 0; if (conf_read_file(&pc_group_config, config_filename)) return; groups = config_lookup(&pc_group_config, "groups"); if (groups != NULL) { GroupSettings *group_settings = NULL; DBIterator *iter = NULL; int i, loop = 0; group_count = config_setting_length(groups); for (i = 0; i < group_count; ++i) { int id = 0, level = 0; const char *groupname = NULL; int log_commands = 0; config_setting_t *group = config_setting_get_elem(groups, i); if (!config_setting_lookup_int(group, "id", &id)) { ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i); config_setting_remove_elem(groups, i); --i; --group_count; continue; } if (id2group(id) != NULL) { ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i); config_setting_remove_elem(groups, i); --i; --group_count; continue; } config_setting_lookup_int(group, "level", &level); config_setting_lookup_bool(group, "log_commands", &log_commands); if (!config_setting_lookup_string(group, "name", &groupname)) { char temp[20]; config_setting_t *name = NULL; snprintf(temp, sizeof(temp), "Group %d", id); if ((name = config_setting_add(group, "name", CONFIG_TYPE_STRING)) == NULL || !config_setting_set_string(name, temp)) { ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n", id, config_setting_source_file(group), config_setting_source_line(group)); continue; } config_setting_lookup_string(group, "name", &groupname); // Retrieve the pointer } if (name2group(groupname) != NULL) { ShowConfigWarning(group, "pc_groups:read_config: duplicate group name %s, removing...", groupname); config_setting_remove_elem(groups, i); --i; --group_count; continue; } CREATE(group_settings, GroupSettings, 1); group_settings->id = id; group_settings->level = level; group_settings->name = groupname; group_settings->log_commands = (bool)log_commands; group_settings->inherit = config_setting_get_member(group, "inherit"); group_settings->commands = config_setting_get_member(group, "commands"); group_settings->permissions = config_setting_get_member(group, "permissions"); group_settings->inheritance_done = false; group_settings->root = group; group_settings->group_pos = i; strdb_put(pc_groupname_db, groupname, group_settings); idb_put(pc_group_db, id, group_settings); } group_count = config_setting_length(groups); // Save number of groups // Check if all commands and permissions exist iter = db_iterator(pc_group_db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; int count = 0, j; // Make sure there is "commands" group if (commands == NULL) commands = group_settings->commands = config_setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP); count = config_setting_length(commands); for (j = 0; j < count; ++j) { config_setting_t *command = config_setting_get_elem(commands, j); const char *name = config_setting_name(command); if (!atcommand_exists(name)) { ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name); config_setting_remove(commands, name); --j; --count; } } // Make sure there is "permissions" group if (permissions == NULL) permissions = group_settings->permissions = config_setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP); count = config_setting_length(permissions); for(j = 0; j < count; ++j) { config_setting_t *permission = config_setting_get_elem(permissions, j); const char *name = config_setting_name(permission); int p; ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), p, strcmp(pc_g_permission_name[p].name, name) == 0); if (p == ARRAYLENGTH(pc_g_permission_name)) { ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name); config_setting_remove(permissions, name); --p; --count; } } } dbi_destroy(iter); // Apply inheritance i = 0; // counter for processed groups while (i < group_count) { iter = db_iterator(pc_group_db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *inherit = NULL, *commands = group_settings->commands, *permissions = group_settings->permissions; int j, inherit_count = 0, done = 0; if (group_settings->inheritance_done) // group already processed continue; if ((inherit = group_settings->inherit) == NULL || (inherit_count = config_setting_length(inherit)) <= 0) { // this group does not inherit from others ++i; group_settings->inheritance_done = true; continue; } for (j = 0; j < inherit_count; ++j) { GroupSettings *inherited_group = NULL; const char *groupname = config_setting_get_string_elem(inherit, j); if (groupname == NULL) { ShowConfigWarning(inherit, "pc_groups:read_config: \"inherit\" array member #%d is not a name, removing...", j); config_setting_remove_elem(inherit,j); continue; } if ((inherited_group = name2group(groupname)) == NULL) { ShowConfigWarning(inherit, "pc_groups:read_config: non-existent group name \"%s\", removing...", groupname); config_setting_remove_elem(inherit,j); continue; } if (!inherited_group->inheritance_done) continue; // we need to do that group first // Copy settings (commands/permissions) that are not defined yet if (inherited_group->commands != NULL) { int l = 0, commands_count = config_setting_length(inherited_group->commands); for (l = 0; l < commands_count; ++l) config_setting_copy(commands, config_setting_get_elem(inherited_group->commands, l)); } if (inherited_group->permissions != NULL) { int l = 0, permissions_count = config_setting_length(inherited_group->permissions); for (l = 0; l < permissions_count; ++l) config_setting_copy(permissions, config_setting_get_elem(inherited_group->permissions, l)); } ++done; // copied commands and permissions from one of inherited groups } if (done == inherit_count) { // copied commands from all of inherited groups ++i; group_settings->inheritance_done = true; // we're done with this group } } dbi_destroy(iter); if (++loop > group_count) { ShowWarning("pc_groups:read_config: Could not process inheritance rules, check your config '%s' for cycles...\n", config_filename); break; } } // while(i < group_count) // Pack permissions into GroupSettings.e_permissions for faster checking iter = db_iterator(pc_group_db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { config_setting_t *permissions = group_settings->permissions; int c, count = config_setting_length(permissions); for (c = 0; c < count; ++c) { config_setting_t *perm = config_setting_get_elem(permissions, c); const char *name = config_setting_name(perm); int val = config_setting_get_bool(perm); int j; if (val == 0) // does not have this permission continue; ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); group_settings->e_permissions |= pc_g_permission_name[j].permission; } } dbi_destroy(iter); } ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename); if( ( pc_group_max = group_count ) ) { DBIterator *iter = db_iterator(pc_group_db); GroupSettings *group_settings = NULL; int* group_ids = aMalloc( pc_group_max * sizeof(int) ); int i = 0; for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { group_ids[i++] = group_settings->id; } atcommand_db_load_groups(group_ids); aFree(group_ids); dbi_destroy(iter); } }
int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) { // cleaned up [LuzZza] int i,alv,c,idx=-1,om=0,oldonline=-1; struct guild *g = guild_search(guild_id); if(g == NULL) return 0; for(i=0,alv=0,c=0,om=0;i<g->max_member;i++){ struct guild_member *m=&g->member[i]; if(!m->account_id) continue; if(m->account_id==account_id && m->char_id==char_id ){ oldonline=m->online; m->online=online; m->lv=lv; m->class_=class_; idx=i; } alv+=m->lv; c++; if(m->online) om++; } if(idx == -1 || c == 0) { // ギルドのメンバー外なので追放扱いする struct map_session_data *sd = map_id2sd(account_id); if(sd && sd->status.char_id == char_id) { sd->status.guild_id=0; sd->guild_emblem_id=0; } ShowWarning("guild: not found member %d,%d on %d[%s]\n", account_id,char_id,guild_id,g->name); return 0; } g->average_lv=alv/c; g->connect_member=om; //Ensure validity of pointer (ie: player logs in/out, changes map-server) g->member[idx].sd = guild_sd_check(guild_id, account_id, char_id); if(oldonline!=online) clif_guild_memberlogin_notice(g, idx, online); if(!g->member[idx].sd) return 0; //Send XY dot updates. [Skotlex] //Moved from guild_send_memberinfoshort [LuzZza] for(i=0; i < g->max_member; i++) { if(!g->member[i].sd || i == idx || g->member[i].sd->bl.m != g->member[idx].sd->bl.m) continue; clif_guild_xy_single(g->member[idx].sd->fd, g->member[i].sd); clif_guild_xy_single(g->member[i].sd->fd, g->member[idx].sd); } return 0; }
void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count) { unsigned int i, weight, listidx; struct item_data* id; if( !result || count == 0 ) {// canceled, or no items return; } if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] ) {// disabled or invalid input sd->buyingstore.slots = 0; clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return; } if( !pc->can_give_items(sd) ) {// custom: GM is not allowed to buy (give zeny) sd->buyingstore.slots = 0; clif->message(sd->fd, msg_txt(246)); clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return; } if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) ) {// custom: mute limitation return; } if( map[sd->bl.m].flag.novending ) {// custom: no vending maps clif->message(sd->fd, msg_txt(276)); // "You can't open a shop on this map" return; } if( iMap->getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) {// custom: no vending cells clif->message(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." return; } weight = sd->weight; // check item list for( i = 0; i < count; i++ ) {// itemlist: <name id>.W <amount>.W <price>.L unsigned short nameid, amount; int price, idx; nameid = RBUFW(itemlist,i*8+0); amount = RBUFW(itemlist,i*8+2); price = RBUFL(itemlist,i*8+4); if( ( id = itemdb->exists(nameid) ) == NULL || amount == 0 ) {// invalid input break; } if( price <= 0 || price > BUYINGSTORE_MAX_PRICE ) {// invalid price: unlike vending, items cannot be bought at 0 Zeny break; } if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc->get_group_level(sd), pc->get_group_level(sd)) || ( idx = pc->search_inventory(sd, nameid) ) == -1 ) {// restrictions: allowed, no character-bound items and at least one must be owned break; } if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT ) {// too many items of same kind break; } if( i ) {// duplicate check. as the client does this too, only malicious intent should be caught here ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid ); if( listidx != i ) {// duplicate ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id); break; } } weight+= id->weight*amount; sd->buyingstore.items[i].nameid = nameid; sd->buyingstore.items[i].amount = amount; sd->buyingstore.items[i].price = price; } if( i != count ) {// invalid item/amount/price sd->buyingstore.slots = 0; clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return; } if( (sd->max_weight*90)/100 < weight ) {// not able to carry all wanted items without getting overweight (90%) sd->buyingstore.slots = 0; clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight); return; } // success sd->state.buyingstore = true; sd->buyer_id = buyingstore_getuid(); sd->buyingstore.zenylimit = zenylimit; sd->buyingstore.slots = i; // store actual amount of items safestrncpy(sd->message, storename, sizeof(sd->message)); clif->buyingstore_myitemlist(sd); clif->buyingstore_entry(sd); }
// Wisp/page request to send int mapif_parse_WisRequest(int fd) { struct WisData* wd; static int wisid = 0; char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1];// escaped name char* data; size_t len; if ( fd <= 0 ) {return 0;} // check if we have a valid fd if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) { ShowWarning("inter: Wis message size too long.\n"); return 0; } else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows... ShowError("inter: Wis message doesn't exist.\n"); return 0; } safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] SQL->EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) ) Sql_ShowDebug(sql_handle); // search if character exists before to ask all map-servers if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); } else {// Character exists. So, ask all map-servers // to be sure of the correct name, rewrite it SQL->GetData(sql_handle, 0, &data, &len); memset(name, 0, NAME_LENGTH); memcpy(name, data, min(len, NAME_LENGTH)); // if source is destination, don't ask other servers. if( strncmp((const char*)RFIFOP(fd,4), name, NAME_LENGTH) == 0 ) { uint8 buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); } else { CREATE(wd, struct WisData, 1); // Whether the failure of previous wisp/page transmission (timeout) check_ttl_wisdata(); wd->id = ++wisid; wd->fd = fd; wd->len= RFIFOW(fd,2)-52; memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH); memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH); memcpy(wd->msg, RFIFOP(fd,52), wd->len); wd->tick = timer->gettick(); idb_put(wis_db, wd->id, wd); mapif_wis_message(wd); } } SQL->FreeResult(sql_handle); return 0; }
void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid) { unsigned int i; struct map_session_data* pl_sd; searchstore_search_t store_search; if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count ) { return; } searchstore->clearremote(sd); ARR_FIND( 0, sd->searchstore.count, i, sd->searchstore.items[i].store_id == store_id && sd->searchstore.items[i].account_id == account_id && sd->searchstore.items[i].nameid == nameid ); if( i == sd->searchstore.count ) {// no such result, crafted ShowWarning("searchstore_click: Pedido recebido do item %hu da conta %d, que nao faz parte do conjunto de resultados atual (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id); clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } if( ( pl_sd = map->id2sd(account_id) ) == NULL ) {// no longer online clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } if( !searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id ) { // no longer vending/buying or not same shop clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } store_search = searchstore_getsearchfunc(sd->searchstore.type); if( !store_search(pl_sd, nameid) ) {// item no longer being sold/bought clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } switch( sd->searchstore.effect ) { case EFFECTTYPE_NORMAL: // display coords if( sd->bl.m != pl_sd->bl.m ) {// not on same map, wipe previous marker clif->search_store_info_click_ack(sd, -1, -1); } else { clif->search_store_info_click_ack(sd, pl_sd->bl.x, pl_sd->bl.y); } break; case EFFECTTYPE_CASH: // open remotely // to bypass range checks sd->searchstore.remote_id = account_id; switch( sd->searchstore.type ) { case SEARCHTYPE_VENDING: vending->list(sd, account_id); break; case SEARCHTYPE_BUYING_STORE: buyingstore->open(sd, account_id); break; } break; default: // unknown ShowError("searchstore_click: Efeito de procura de loja desconhecido %u (account_id=%d).\n", (unsigned int)sd->searchstore.effect, sd->bl.id); } }
int32 map_cleanup(uint32 tick, CTaskMgr::CTask* PTask) { map_session_list_t::iterator it = map_session_list.begin(); while (it != map_session_list.end()) { map_session_data_t* map_session_data = it->second; CCharEntity* PChar = map_session_data->PChar; if ((time(nullptr) - map_session_data->last_update) > 5) { if (PChar != nullptr && !(PChar->nameflags.flags & FLAG_DC)) { PChar->nameflags.flags |= FLAG_DC; PChar->updatemask |= UPDATE_HP; if (PChar->status == STATUS_NORMAL) { PChar->loc.zone->SpawnPCs(PChar); } } if ((time(nullptr) - map_session_data->last_update) > map_config.max_time_lastupdate) { if (PChar != nullptr) { if (map_session_data->shuttingDown == 0) { //[Alliance] fix to stop server crashing: //if a party within an alliance only has 1 char (that char will be party leader) //if char then disconnects we need to tell the server about the alliance change if (PChar->PParty != nullptr && PChar->PParty->m_PAlliance != nullptr && PChar->PParty->GetLeader() == PChar) { if (PChar->PParty->members.size() == 1) { if (PChar->PParty->m_PAlliance->partyList.size() == 1) { PChar->PParty->m_PAlliance->dissolveAlliance(); } else { PChar->PParty->m_PAlliance->removeParty(PChar->PParty); } } } // uncharm pet if player d/c if (PChar->PPet != nullptr && PChar->PPet->objtype == TYPE_MOB) { petutils::DespawnPet(PChar); } PChar->StatusEffectContainer->SaveStatusEffects(true); ShowDebug(CL_CYAN"map_cleanup: %s timed out, closing session\n" CL_RESET, PChar->GetName()); PChar->status = STATUS_SHUTDOWN; PacketParser[0x00D](map_session_data, PChar, 0); } else { map_session_data->PChar->StatusEffectContainer->SaveStatusEffects(true); Sql_Query(SqlHandle, "DELETE FROM accounts_sessions WHERE charid = %u;", map_session_data->PChar->id); aFree(map_session_data->server_packet_data); delete map_session_data->PChar; delete map_session_data; map_session_data = nullptr; map_session_list.erase(it++); continue; } } else if (map_session_data->shuttingDown == 0) { ShowWarning(CL_YELLOW"map_cleanup: WHITHOUT CHAR timed out, session closed\n" CL_RESET); const int8* Query = "DELETE FROM accounts_sessions WHERE client_addr = %u AND client_port = %u"; Sql_Query(SqlHandle, Query, map_session_data->client_addr, map_session_data->client_port); aFree(map_session_data->server_packet_data); map_session_list.erase(it++); delete map_session_data; continue; } } } else if (PChar != nullptr && (PChar->nameflags.flags & FLAG_DC)) { PChar->nameflags.flags &= ~FLAG_DC; PChar->updatemask |= UPDATE_HP; PChar->pushPacket(new CCharUpdatePacket(PChar)); if (PChar->status == STATUS_NORMAL) { PChar->loc.zone->SpawnPCs(PChar); } charutils::SaveCharStats(PChar); } ++it; } return 0; }