/** * Player setup a new shop * @param sd : player opening the shop * @param message : shop title * @param data : itemlist data * data := {<index>.w <amount>.w <value>.l}[count] * @param count : number of different items * @param at Autotrader info, or NULL if requetsed not from autotrade persistance * @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - Cart data isn't saved yet, 5 - No valid item found */ int8 vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count, struct s_autotrader *at) { int i, j; int vending_skill_lvl; char message_sql[MESSAGE_SIZE*2]; StringBuf buf; nullpo_retr(false,sd); if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) { return 1; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once } vending_skill_lvl = pc_checkskill(sd, MC_VENDING); // skill level and cart check if( !vending_skill_lvl || !pc_iscarton(sd) ) { clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return 2; } // check number of items in shop if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { // invalid item count clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return 3; } if (save_settings&CHARSAVE_VENDING) // Avoid invalid data from saving chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART); // filter out invalid items i = 0; for( j = 0; j < count; j++ ) { short index = *(uint16*)(data + 8*j + 0); short amount = *(uint16*)(data + 8*j + 2); unsigned int value = *(uint32*)(data + 8*j + 4); index -= 2; // offset adjustment (client says that the first cart position is 2) if( index < 0 || index >= MAX_CART // invalid position || pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity //NOTE: official server does not do any of the following checks! || !sd->cart.u.items_cart[index].identify // unidentified item || sd->cart.u.items_cart[index].attribute == 1 // broken item || sd->cart.u.items_cart[index].expire_time // It should not be in the cart but just in case || (sd->cart.u.items_cart[index].bound && !pc_can_give_bounded_items(sd)) // can't trade account bound items and has no permission || !itemdb_cantrade(&sd->cart.u.items_cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item continue; sd->vending[i].index = index; sd->vending[i].amount = amount; sd->vending[i].value = min(value, (unsigned int)battle_config.vending_max_value); i++; // item successfully added } if( i != j ) clif_displaymessage (sd->fd, msg_txt(sd,266)); //"Some of your items cannot be vended and were removed from the shop." if( i == 0 ) { // no valid item found clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet return 5; } sd->state.prevend = 0; sd->state.vending = true; sd->state.workinprogress = WIP_DISABLE_NONE; sd->vender_id = vending_getuid(); sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); 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`, `autotrade`, `body_direction`, `head_direction`, `sit`) " "VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );", vendings_table, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == SEX_FEMALE ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ) { Sql_ShowDebug(mmysql_handle); } StringBuf_Init(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES", vending_items_table); for (j = 0; j < i; j++) { StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, j, sd->cart.u.items_cart[sd->vending[j].index].id, sd->vending[j].amount, sd->vending[j].value); if (j < i-1) StringBuf_AppendStr(&buf, ","); } if (SQL_ERROR == Sql_QueryStr(mmysql_handle, StringBuf_Value(&buf))) Sql_ShowDebug(mmysql_handle); StringBuf_Destroy(&buf); clif_openvending(sd,sd->bl.id,sd->vending); clif_showvendingboard(&sd->bl,message,0); idb_put(vending_db, sd->status.char_id, sd); return 0; }
CCurrencyPacket1::CCurrencyPacket1(CCharEntity* PChar) { this->type = 0x13; this->size = 0x6F; const char* query = "SELECT sandoria_cp, bastok_cp, windurst_cp, beastman_seal, kindred_seal, kindred_crest, \ high_kindred_crest, sacred_kindred_crest, ancient_beastcoin, valor_point, scyld, \ guild_fishing, guild_woodworking, guild_smithing, guild_goldsmithing, guild_weaving, \ guild_leathercraft, guild_bonecraft, guild_alchemy, guild_cooking, cinder, fire_fewell, \ ice_fewell, wind_fewell, earth_fewell, lightning_fewell, water_fewell, light_fewell, \ dark_fewell, ballista_point, fellow_point, chocobuck_sandoria, chocobuck_bastok, chocobuck_windurst, \ research_mark, tunnel_worm, morion_worm, phantom_worm, moblin_marble, infamy, prestige, \ legion_point, spark_of_eminence, shining_star, imperial_standing, leujaoam_assault_point, \ mamool_assault_point, lebros_assault_point, periqia_assault_point, ilrusi_assault_point, \ nyzul_isle_assault_point, zeni_point, jetton, therion_ichor, allied_notes, cruor, resistance_credit, \ dominion_note, fifth_echelon_trophy, fourth_echelon_trophy, third_echelon_trophy, second_echelon_trophy, \ first_echelon_trophy, cave_points, id_tags, op_credits, traverser_stones, voidstones, kupofried_corundums, \ pheromone_sacks FROM char_points WHERE charid = %d"; int ret = Sql_Query(SqlHandle, query, PChar->id); if (ret != SQL_ERROR && Sql_NextRow(SqlHandle) == SQL_SUCCESS) { WBUFL(data, (0x04)-4) = Sql_GetIntData(SqlHandle, 0); WBUFL(data, (0x08)-4) = Sql_GetIntData(SqlHandle, 1); WBUFL(data, (0x0C)-4) = Sql_GetIntData(SqlHandle, 2); WBUFW(data, (0x10)-4) = Sql_GetUIntData(SqlHandle, 3); WBUFW(data, (0x12)-4) = Sql_GetUIntData(SqlHandle, 4); WBUFW(data, (0x14)-4) = Sql_GetUIntData(SqlHandle, 5); WBUFW(data, (0x16)-4) = Sql_GetUIntData(SqlHandle, 6); WBUFW(data, (0x18)-4) = Sql_GetUIntData(SqlHandle, 7); WBUFW(data, (0x1A)-4) = Sql_GetUIntData(SqlHandle, 8); WBUFW(data, (0x1C)-4) = Sql_GetUIntData(SqlHandle, 9); WBUFW(data, (0x1E)-4) = Sql_GetUIntData(SqlHandle, 10); WBUFL(data, (0x20)-4) = Sql_GetIntData(SqlHandle, 11); WBUFL(data, (0x24)-4) = Sql_GetIntData(SqlHandle, 12); WBUFL(data, (0x28)-4) = Sql_GetIntData(SqlHandle, 13); WBUFL(data, (0x2C)-4) = Sql_GetIntData(SqlHandle, 14); WBUFL(data, (0x30)-4) = Sql_GetIntData(SqlHandle, 15); WBUFL(data, (0x34)-4) = Sql_GetIntData(SqlHandle, 16); WBUFL(data, (0x38)-4) = Sql_GetIntData(SqlHandle, 17); WBUFL(data, (0x3C)-4) = Sql_GetIntData(SqlHandle, 18); WBUFL(data, (0x40)-4) = Sql_GetIntData(SqlHandle, 19); WBUFL(data, (0x44)-4) = Sql_GetIntData(SqlHandle, 20); WBUFB(data, (0x48)-4) = Sql_GetUIntData(SqlHandle, 21); WBUFB(data, (0x49)-4) = Sql_GetUIntData(SqlHandle, 22); WBUFB(data, (0x4A)-4) = Sql_GetUIntData(SqlHandle, 23); WBUFB(data, (0x4B)-4) = Sql_GetUIntData(SqlHandle, 24); WBUFB(data, (0x4C)-4) = Sql_GetUIntData(SqlHandle, 25); WBUFB(data, (0x4D)-4) = Sql_GetUIntData(SqlHandle, 26); WBUFB(data, (0x4E)-4) = Sql_GetUIntData(SqlHandle, 27); WBUFB(data, (0x4F)-4) = Sql_GetUIntData(SqlHandle, 28); WBUFL(data, (0x50)-4) = Sql_GetIntData(SqlHandle, 29); WBUFL(data, (0x54)-4) = Sql_GetIntData(SqlHandle, 30); WBUFW(data, (0x58)-4) = Sql_GetUIntData(SqlHandle, 31); WBUFW(data, (0x5A)-4) = Sql_GetUIntData(SqlHandle, 32); WBUFW(data, (0x5C)-4) = Sql_GetUIntData(SqlHandle, 33); // daily tally (2 byte) WBUFL(data, (0x60)-4) = Sql_GetIntData(SqlHandle, 34); WBUFB(data, (0x64)-4) = Sql_GetUIntData(SqlHandle, 35); WBUFB(data, (0x65)-4) = Sql_GetUIntData(SqlHandle, 36); WBUFB(data, (0x66)-4) = Sql_GetUIntData(SqlHandle, 37); WBUFL(data, (0x68)-4) = Sql_GetIntData(SqlHandle, 38); WBUFW(data, (0x6C)-4) = Sql_GetUIntData(SqlHandle, 39); WBUFW(data, (0x6E)-4) = Sql_GetUIntData(SqlHandle, 40); WBUFL(data, (0x70)-4) = Sql_GetIntData(SqlHandle, 41); WBUFL(data, (0x74)-4) = Sql_GetIntData(SqlHandle, 42); WBUFL(data, (0x78)-4) = Sql_GetIntData(SqlHandle, 43); WBUFL(data, (0x7C)-4) = Sql_GetIntData(SqlHandle, 44); WBUFL(data, (0x80)-4) = Sql_GetIntData(SqlHandle, 45); WBUFL(data, (0x84)-4) = Sql_GetIntData(SqlHandle, 46); WBUFL(data, (0x88)-4) = Sql_GetIntData(SqlHandle, 47); WBUFL(data, (0x8C)-4) = Sql_GetIntData(SqlHandle, 48); WBUFL(data, (0x90)-4) = Sql_GetIntData(SqlHandle, 49); WBUFL(data, (0x94)-4) = Sql_GetIntData(SqlHandle, 50); WBUFL(data, (0x98)-4) = Sql_GetIntData(SqlHandle, 51); WBUFL(data, (0x9C)-4) = Sql_GetIntData(SqlHandle, 52); WBUFL(data, (0xA0)-4) = Sql_GetIntData(SqlHandle, 53); WBUFL(data, (0xA4)-4) = Sql_GetIntData(SqlHandle, 54); // AMAN vouchers // unity accolades WBUFL(data, (0xAC)-4) = Sql_GetIntData(SqlHandle, 55); WBUFL(data, (0xB0)-4) = Sql_GetIntData(SqlHandle, 56); WBUFL(data, (0xB4)-4) = Sql_GetIntData(SqlHandle, 57); WBUFB(data, (0xB8)-4) = Sql_GetUIntData(SqlHandle, 58); WBUFB(data, (0xB9)-4) = Sql_GetUIntData(SqlHandle, 59); WBUFB(data, (0xBA)-4) = Sql_GetUIntData(SqlHandle, 60); WBUFB(data, (0xBB)-4) = Sql_GetUIntData(SqlHandle, 61); WBUFB(data, (0xBC)-4) = Sql_GetUIntData(SqlHandle, 62); WBUFB(data, (0xBD)-4) = Sql_GetUIntData(SqlHandle, 63); WBUFB(data, (0xBE)-4) = Sql_GetUIntData(SqlHandle, 64); WBUFB(data, (0xBF)-4) = Sql_GetUIntData(SqlHandle, 65); WBUFL(data, (0xC0)-4) = Sql_GetIntData(SqlHandle, 66); WBUFL(data, (0xC4)-4) = Sql_GetIntData(SqlHandle, 67); WBUFL(data, (0xC8)-4) = Sql_GetIntData(SqlHandle, 68); WBUFB(data, (0xCC)-4) = Sql_GetUIntData(SqlHandle, 69); } }
/* [Dekamaster/Nightroad] */ void mapif_parse_accinfo(int fd) { int u_fd = RFIFOL(fd,2), aid = RFIFOL(fd,6), castergroup = RFIFOL(fd,10); char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1]; int account_id; char *data; safestrncpy(query, (char*) RFIFOP(fd,14), NAME_LENGTH); Sql_EscapeString(sql_handle, query_esq, query); account_id = atoi(query); if (account_id < START_ACCOUNT_NUM) { // is string if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `char` WHERE `name` LIKE '%s' LIMIT 10", query_esq) || Sql_NumRows(sql_handle) == 0 ) { if( Sql_NumRows(sql_handle) == 0 ) { inter_to_fd(fd, u_fd, aid, "Não foram encontrados resultados para seu critério, '%s'",query); } else { Sql_ShowDebug(sql_handle); inter_to_fd(fd, u_fd, aid, "Um erro ocorreu, incomode seu administrador sobre isso."); } Sql_FreeResult(sql_handle); return; } else { if( Sql_NumRows(sql_handle) == 1 ) {//we found a perfect match Sql_NextRow(sql_handle); Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); Sql_FreeResult(sql_handle); } else {// more than one, listing... [Dekamaster/Nightroad] inter_to_fd(fd, u_fd, aid, "Sua requisição retornou %d resultados, seja mais específico...",(int)Sql_NumRows(sql_handle)); while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { int class_; short base_level, job_level, online; char name[NAME_LENGTH]; Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); Sql_GetData(sql_handle, 2, &data, NULL); class_ = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); base_level = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); job_level = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); online = atoi(data); inter_to_fd(fd, u_fd, aid, "[AID: %d] %s | %s | Nível: %d/%d | %s", account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline"); } Sql_FreeResult(sql_handle); return; } } } /* it will only get here if we have a single match */ if( account_id ) { char userid[NAME_LENGTH], user_pass[NAME_LENGTH], email[40], last_ip[20], lastlogin[30]; short level = -1; int logincount = 0,state = 0; if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `userid`, `user_pass`, `email`, `last_ip`, `group_id`, `lastlogin`, `logincount`, `state` FROM `login` WHERE `account_id` = '%d' LIMIT 1", account_id) || Sql_NumRows(sql_handle) == 0 ) { if( Sql_NumRows(sql_handle) == 0 ) { inter_to_fd(fd, u_fd, aid, "Nenhuma conta de ID '%d' foi encontrada.", account_id ); } else { inter_to_fd(fd, u_fd, aid, "Um erro ocorreu, incomode seu administrador sobre isso."); Sql_ShowDebug(sql_handle); } } else { Sql_NextRow(sql_handle); Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(userid, data, sizeof(userid)); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(user_pass, data, sizeof(user_pass)); Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(email, data, sizeof(email)); Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(last_ip, data, sizeof(last_ip)); Sql_GetData(sql_handle, 4, &data, NULL); level = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(lastlogin, data, sizeof(lastlogin)); Sql_GetData(sql_handle, 6, &data, NULL); logincount = atoi(data); Sql_GetData(sql_handle, 7, &data, NULL); state = atoi(data); } Sql_FreeResult(sql_handle); if (level == -1) return; inter_to_fd(fd, u_fd, aid, "-- Conta %d --", account_id ); inter_to_fd(fd, u_fd, aid, "Usuário: %s | Grupo de GM: %d | Estado: %d", userid, level, state ); if (level < castergroup) /* only show pass if your gm level is greater than the one you're searching for */ inter_to_fd(fd, u_fd, aid, "Senha: %s", user_pass ); inter_to_fd(fd, u_fd, aid, "Conta de email: %s", email); inter_to_fd(fd, u_fd, aid, "Último IP: %s (%s)", last_ip, geoip_getcountry(str2ip(last_ip)) ); inter_to_fd(fd, u_fd, aid, "Este usuário logou %d vezes, a última vez foi em %s", logincount, lastlogin ); inter_to_fd(fd, u_fd, aid, "-- Detalhes do personagem --" ); if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `char` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", account_id, MAX_CHARS) || Sql_NumRows(sql_handle) == 0 ) { if( Sql_NumRows(sql_handle) == 0 ) inter_to_fd(fd, u_fd, aid,"Esta conta não tem personagens."); else { inter_to_fd(fd, u_fd, aid,"Um erro ocorreu, fale com seu administrador sobre isso."); Sql_ShowDebug(sql_handle); } } else { while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { int char_id, class_; short char_num, base_level, job_level, online; char name[NAME_LENGTH]; Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); Sql_GetData(sql_handle, 2, &data, NULL); char_num = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); class_ = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); job_level = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); online = atoi(data); inter_to_fd(fd, u_fd, aid, "[Slot/CID: %d/%d] %s | %s | Nível: %d/%d | %s", char_num, char_id, name, job_name(class_), base_level, job_level, online?"On":"Off"); } } Sql_FreeResult(sql_handle); } return; }
void CParty::ReloadParty() { //check if partyflags have changed int ret = Sql_Query(SqlHandle, "SELECT charid, partyflag FROM accounts_parties WHERE partyid = %d;", m_PartyID); if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) > 0) { uint8 j = 0; while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) { uint32 charid = Sql_GetUIntData(SqlHandle, 0); uint16 memberflags = Sql_GetUIntData(SqlHandle, 1); if (memberflags & PARTY_LEADER) { bool found = false; for (auto member : members) { if (member->id == charid) { m_PLeader = member; found = true; } } if (!found) { m_PLeader = NULL; } } if (memberflags & PARTY_QM) { bool found = false; for (auto member : members) { if (member->id == charid) { m_PQuaterMaster = member; found = true; } } if (!found) { m_PQuaterMaster = NULL; } } } } //alliance if (this->m_PAlliance != NULL) { for (uint8 a = 0; a < m_PAlliance->partyList.size(); ++a) { for (uint8 i = 0; i < m_PAlliance->partyList.at(a)->members.size(); ++i) { CCharEntity* PChar = (CCharEntity*)m_PAlliance->partyList.at(a)->members.at(i); PChar->ReloadPartyDec(); uint16 alliance = 0; PChar->pushPacket(new CPartyDefinePacket(m_PAlliance->partyList.at(a))); int ret = Sql_Query(SqlHandle, "SELECT chars.charid, chars.charname, partyflag, pos_zone, partyid FROM accounts_parties \ LEFT JOIN chars ON accounts_parties.charid = chars.charid WHERE \ allianceid = %d ORDER BY partyflag & %u, timestamp;", m_PAlliance->m_AllianceID, PARTY_SECOND | PARTY_THIRD); if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) > 0) { uint8 j = 0; while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) { if (Sql_GetUIntData(SqlHandle, 2) & (PARTY_SECOND | PARTY_THIRD) != alliance) { alliance = Sql_GetUIntData(SqlHandle, 2) & (PARTY_SECOND | PARTY_THIRD); j = 0; } CCharEntity* PPartyMember = zoneutils::GetChar(Sql_GetUIntData(SqlHandle, 0)); if (PPartyMember) { PChar->pushPacket(new CPartyMemberUpdatePacket(PPartyMember, j, PChar->getZone())); } else { PChar->pushPacket(new CPartyMemberUpdatePacket( Sql_GetUIntData(SqlHandle, 0), Sql_GetData(SqlHandle, 1), Sql_GetUIntData(SqlHandle, 2), Sql_GetUIntData(SqlHandle, 3))); } j++; } } } } } else //regular party for (uint8 i = 0; i < members.size(); ++i)
// 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(read_message("Source.char.inter_parsewisrequest_s1")); return 0; } else if(RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows... ShowError(read_message("Source.char.inter_parsewisrequest_s2")); 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 = gettick(); idb_put(wis_db, wd->id, wd); mapif_wis_message(wd); } } Sql_FreeResult(sql_handle); return 0; }
/// Retrieves a single message from the database. /// Returns true if the operation succeeds (or false if it fails). bool mail_loadmessage(int mail_id, struct mail_message* msg) { int i, j; StringBuf buf; char* data; if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`,`zeny`,`type` FROM `%s` WHERE `id` = '%d'", schema_config.mail_db, mail_id ) || SQL_SUCCESS != Sql_NextRow(sql_handle) ){ Sql_ShowDebug(sql_handle); Sql_FreeResult(sql_handle); return false; }else{ Sql_GetData(sql_handle, 0, &data, NULL); msg->id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH); Sql_GetData(sql_handle, 2, &data, NULL); msg->send_id = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH); Sql_GetData(sql_handle, 4, &data, NULL); msg->dest_id = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); Sql_GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); Sql_GetData(sql_handle, 8, &data, NULL); msg->status = (mail_status)atoi(data); Sql_GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); Sql_GetData(sql_handle,10, &data, NULL); msg->type = (mail_inbox_type)atoi(data); if( msg->type == MAIL_INBOX_NORMAL && charserv_config.mail_return_days > 0 ){ msg->scheduled_deletion = msg->timestamp + charserv_config.mail_return_days * 24 * 60 * 60; }else if( msg->type == MAIL_INBOX_RETURNED && charserv_config.mail_delete_days > 0 ){ msg->scheduled_deletion = msg->timestamp + charserv_config.mail_delete_days * 24 * 60 * 60; }else{ msg->scheduled_deletion = 0; } Sql_FreeResult(sql_handle); } StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `amount`,`nameid`,`refine`,`attribute`,`identify`,`unique_id`,`bound`"); for (j = 0; j < MAX_SLOTS; j++) StringBuf_Printf(&buf, ",`card%d`", j); for (j = 0; j < MAX_ITEM_RDM_OPT; ++j) { StringBuf_Printf(&buf, ", `option_id%d`", j); StringBuf_Printf(&buf, ", `option_val%d`", j); StringBuf_Printf(&buf, ", `option_parm%d`", j); } StringBuf_Printf(&buf, " FROM `%s`", schema_config.mail_attachment_db); StringBuf_Printf(&buf, " WHERE `id` = '%d'", mail_id); StringBuf_AppendStr(&buf, " ORDER BY `index` ASC"); StringBuf_Printf(&buf, " LIMIT %d", MAIL_MAX_ITEM); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ){ Sql_ShowDebug(sql_handle); Sql_FreeResult(sql_handle); StringBuf_Destroy(&buf); return false; } memset(msg->item, 0, sizeof(struct item) * MAIL_MAX_ITEM); for( i = 0; i < MAIL_MAX_ITEM && SQL_SUCCESS == Sql_NextRow(sql_handle); i++ ){ Sql_GetData(sql_handle,0, &data, NULL); msg->item[i].amount = (short)atoi(data); Sql_GetData(sql_handle,1, &data, NULL); msg->item[i].nameid = atoi(data); Sql_GetData(sql_handle,2, &data, NULL); msg->item[i].refine = atoi(data); Sql_GetData(sql_handle,3, &data, NULL); msg->item[i].attribute = atoi(data); Sql_GetData(sql_handle,4, &data, NULL); msg->item[i].identify = atoi(data); Sql_GetData(sql_handle,5, &data, NULL); msg->item[i].unique_id = strtoull(data, NULL, 10); Sql_GetData(sql_handle,6, &data, NULL); msg->item[i].bound = atoi(data); msg->item[i].expire_time = 0; for( j = 0; j < MAX_SLOTS; j++ ){ Sql_GetData(sql_handle,7 + j, &data, NULL); msg->item[i].card[j] = atoi(data); } for( j = 0; j < MAX_ITEM_RDM_OPT; j++ ){ Sql_GetData(sql_handle, 7 + MAX_SLOTS + j * 3, &data, NULL); msg->item[i].option[j].id = atoi(data); Sql_GetData(sql_handle, 8 + MAX_SLOTS + j * 3, &data, NULL); msg->item[i].option[j].value = atoi(data); Sql_GetData(sql_handle, 9 + MAX_SLOTS + j * 3, &data, NULL); msg->item[i].option[j].param = atoi(data); } } StringBuf_Destroy(&buf); Sql_FreeResult(sql_handle); return true; }
void mapif_Mail_getattach(int fd, uint32 char_id, int mail_id, int type) { struct mail_message msg; if( ( type&MAIL_ATT_ALL ) == 0 ){ return; } if( !mail_loadmessage(mail_id, &msg) ) return; if( msg.dest_id != char_id ) return; if( msg.status != MAIL_READ ) return; if( type & MAIL_ATT_ZENY ){ if( msg.zeny > 0 ){ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `zeny` = 0 WHERE `id` = '%d'", schema_config.mail_db, mail_id ) ){ Sql_ShowDebug(sql_handle); return; } }else{ type &= ~MAIL_ATT_ZENY; } } if( type & MAIL_ATT_ITEM ){ int i; ARR_FIND(0, MAIL_MAX_ITEM, i, msg.item[i].nameid > 0 && msg.item[i].amount > 0); // No item was found if( i == MAIL_MAX_ITEM ){ type &= ~MAIL_ATT_ITEM; }else{ if( !mail_DeleteAttach(mail_id) ){ return; } } } if( type == MAIL_ATT_NONE ) return; // No Attachment WFIFOHEAD(fd, sizeof(struct item)*MAIL_MAX_ITEM + 16); WFIFOW(fd,0) = 0x384a; WFIFOW(fd,2) = sizeof(struct item)*MAIL_MAX_ITEM + 16; WFIFOL(fd,4) = char_id; WFIFOL(fd,8) = mail_id; if( type & MAIL_ATT_ZENY ){ WFIFOL(fd,12) = msg.zeny; }else{ WFIFOL(fd, 12) = 0; } if( type & MAIL_ATT_ITEM ){ memcpy(WFIFOP(fd, 16), &msg.item, sizeof(struct item)*MAIL_MAX_ITEM); }else{ memset(WFIFOP(fd, 16), 0, sizeof(struct item)*MAIL_MAX_ITEM); } WFIFOSET(fd,WFIFOW(fd,2)); }
static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new) { Sql* sql_handle = db->accounts; SqlStmt* stmt = SqlStmt_Malloc(sql_handle); bool result = false; int i; // try do { if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION") ) { Sql_ShowDebug(sql_handle); break; } if( is_new ) {// insert into account table if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", db->account_db) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_STRING, (void*)&acc->email, strlen(acc->email)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_INT, (void*)&acc->group_id, sizeof(acc->group_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 8, SQLDT_INT, (void*)&acc->expiration_time, sizeof(acc->expiration_time)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_UINT, (void*)&acc->logincount, sizeof(acc->logincount)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); break; } } else {// update account table if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, (void*)acc->email, strlen(acc->email)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_INT, (void*)&acc->group_id, sizeof(acc->group_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->expiration_time, sizeof(acc->expiration_time)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 8, SQLDT_UINT, (void*)&acc->logincount, sizeof(acc->logincount)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); break; } } // remove old account regs if( SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) ) { Sql_ShowDebug(sql_handle); break; } // insert new account regs if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ? );", db->accreg_db, acc->account_id) ) { SqlStmt_ShowDebug(stmt); break; } for( i = 0; i < acc->account_reg2_num; ++i ) { if( SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->account_reg2[i].str, strlen(acc->account_reg2[i].str)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->account_reg2[i].value, strlen(acc->account_reg2[i].value)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); break; } } if( i < acc->account_reg2_num ) { result = false; break; } // if we got this far, everything was successful result = true; } while(0); // finally result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") ); SqlStmt_Free(stmt); return result; }
// Load an homunculus bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) { int i; char* data; size_t len; memset(hd, 0, sizeof(*hd)); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `homunculus` WHERE `homun_id`='%u'", homun_id) ) { Sql_ShowDebug(sql_handle); return false; } if( !Sql_NumRows(sql_handle) ) { //No homunculus found. Sql_FreeResult(sql_handle); return false; } if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); Sql_FreeResult(sql_handle); return false; } hd->hom_id = homun_id; Sql_GetData(sql_handle, 1, &data, NULL); hd->char_id = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); hd->class_ = atoi(data); Sql_GetData(sql_handle, 3, &data, &len); safestrncpy(hd->name, data, sizeof(hd->name)); Sql_GetData(sql_handle, 4, &data, NULL); hd->level = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); hd->exp = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); hd->intimacy = (unsigned int)strtoul(data, NULL, 10); Sql_GetData(sql_handle, 7, &data, NULL); hd->hunger = atoi(data); Sql_GetData(sql_handle, 8, &data, NULL); hd->str = atoi(data); Sql_GetData(sql_handle, 9, &data, NULL); hd->agi = atoi(data); Sql_GetData(sql_handle, 10, &data, NULL); hd->vit = atoi(data); Sql_GetData(sql_handle, 11, &data, NULL); hd->int_ = atoi(data); Sql_GetData(sql_handle, 12, &data, NULL); hd->dex = atoi(data); Sql_GetData(sql_handle, 13, &data, NULL); hd->luk = atoi(data); Sql_GetData(sql_handle, 14, &data, NULL); hd->hp = atoi(data); Sql_GetData(sql_handle, 15, &data, NULL); hd->max_hp = atoi(data); Sql_GetData(sql_handle, 16, &data, NULL); hd->sp = atoi(data); Sql_GetData(sql_handle, 17, &data, NULL); hd->max_sp = atoi(data); Sql_GetData(sql_handle, 18, &data, NULL); hd->skillpts = atoi(data); Sql_GetData(sql_handle, 19, &data, NULL); hd->rename_flag = atoi(data); Sql_GetData(sql_handle, 20, &data, NULL); hd->vaporize = atoi(data); Sql_FreeResult(sql_handle); hd->intimacy = cap_value(hd->intimacy, 0, 100000); hd->hunger = cap_value(hd->hunger, 0, 100); // Load Homunculus Skill if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `skill_homunculus` WHERE `homun_id`=%d", homun_id) ) { Sql_ShowDebug(sql_handle); return false; } while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { // id Sql_GetData(sql_handle, 0, &data, NULL); i = atoi(data); if( i < HM_SKILLBASE || i >= HM_SKILLBASE + MAX_HOMUNSKILL ) continue;// invalid skill id i = i - HM_SKILLBASE; hd->hskill[i].id = (unsigned short)atoi(data); // lv Sql_GetData(sql_handle, 1, &data, NULL); hd->hskill[i].lv = (unsigned char)atoi(data); } Sql_FreeResult(sql_handle); if( save_log ) ShowInfo("Homunculus loaded (%d - %s).\n", hd->hom_id, hd->name); return true; }
/** * Start transaction * @param sd Player/Seller * @param account_id Buyer account ID * @param *itemlist List of sold items { <index>.W, <nameid>.W, <amount>.W }* * @param count Number of item on the itemlist */ void buyingstore_trade(struct map_session_data* sd, uint32 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; nullpo_retv(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_displaymessage(sd->fd, msg_txt(sd,246)); clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( ( pl_sd = map_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->inventory.u.items_inventory) || sd->inventory_data[index] == NULL || sd->inventory.u.items_inventory[index].nameid != nameid || sd->inventory.u.items_inventory[index].amount < amount ) {// invalid input clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( sd->inventory.u.items_inventory[index].expire_time || (sd->inventory.u.items_inventory[index].bound && !pc_can_give_bounded_items(sd)) || !itemdb_cantrade(&sd->inventory.u.items_inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->inventory.u.items_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) == CHKADDITEM_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->inventory.u.items_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; if( pl_sd->buyingstore.items[listidx].amount > 0 ){ if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `amount` = %d WHERE `buyingstore_id` = %d AND `index` = %d;", buyingstore_items_table, pl_sd->buyingstore.items[listidx].amount, pl_sd->buyer_id, listidx ) != SQL_SUCCESS ){ Sql_ShowDebug( mmysql_handle ); } }else{ if( Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `buyingstore_id` = %d AND `index` = %d;", buyingstore_items_table, pl_sd->buyer_id, listidx ) != SQL_SUCCESS ){ Sql_ShowDebug( mmysql_handle ); } } // 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, sd->status.char_id, zeny); } if( save_settings&CHARSAVE_BANK ) { chrif_save(sd, CSAVE_NORMAL); chrif_save(pl_sd, CSAVE_NORMAL); } // 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 if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `limit` = %d WHERE `id` = %d;", buyingstores_table, pl_sd->buyingstore.zenylimit, pl_sd->buyer_id ) != SQL_SUCCESS ){ Sql_ShowDebug( mmysql_handle ); } return; } // cannot continue buying buyingstore_close(pl_sd); // remove auto-trader if( pl_sd->state.autotrade ) { map_quit(pl_sd); } }
static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id) { Sql* sql_handle = db->accounts; char* data; int i = 0; // retrieve login entry for the specified account if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate` FROM `%s` WHERE `account_id` = %d", db->account_db, account_id ) ) { Sql_ShowDebug(sql_handle); return false; } if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) {// no such entry Sql_FreeResult(sql_handle); return false; } Sql_GetData(sql_handle, 0, &data, NULL); acc->account_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->userid, data, sizeof(acc->userid)); Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass)); Sql_GetData(sql_handle, 3, &data, NULL); acc->sex = data[0]; Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email)); Sql_GetData(sql_handle, 5, &data, NULL); acc->group_id = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); acc->state = strtoul(data, NULL, 10); Sql_GetData(sql_handle, 7, &data, NULL); acc->unban_time = atol(data); Sql_GetData(sql_handle, 8, &data, NULL); acc->expiration_time = atol(data); Sql_GetData(sql_handle, 9, &data, NULL); acc->logincount = strtoul(data, NULL, 10); Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin)); Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip)); Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate)); Sql_FreeResult(sql_handle); // retrieve account regs for the specified user if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) ) { Sql_ShowDebug(sql_handle); return false; } acc->account_reg2_num = (int)Sql_NumRows(sql_handle); while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { char* data; Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str)); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value)); ++i; } Sql_FreeResult(sql_handle); if( i != acc->account_reg2_num ) return false; return true; }
/** * 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 * @param at Autotrader info, or NULL if requetsed not from autotrade persistance * @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 */ int8 buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count, struct s_autotrader *at) { unsigned int i, weight, listidx; char message_sql[MESSAGE_SIZE*2]; StringBuf buf; 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->inventory.u.items_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_table, 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, at ? at->dir : sd->ud.dir, at ? at->head_dir : sd->head_dir, at ? at->sit : pc_issit(sd) ) != SQL_SUCCESS ){ Sql_ShowDebug(mmysql_handle); } StringBuf_Init(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s`(`buyingstore_id`,`index`,`item_id`,`amount`,`price`) VALUES", buyingstore_items_table); for (i = 0; i < sd->buyingstore.slots; i++){ StringBuf_Printf(&buf, "(%d,%d,%hu,%d,%d)", sd->buyer_id, i, sd->buyingstore.items[i].nameid, sd->buyingstore.items[i].amount, sd->buyingstore.items[i].price); if (i < sd->buyingstore.slots-1) StringBuf_AppendStr(&buf, ","); } if (SQL_ERROR == Sql_QueryStr(mmysql_handle, StringBuf_Value(&buf))) Sql_ShowDebug(mmysql_handle); StringBuf_Destroy(&buf); clif_buyingstore_myitemlist(sd); clif_buyingstore_entry(sd); idb_put(buyingstore_db, sd->status.char_id, sd); return 0; }
/* Loads up custom mob mods from mob_pool_mods and mob_family_mods table. This will allow you to customize a mobs regen rate, magic defense, triple attack rate from a table instead of hardcoding it. Usage: Evil weapons have a magic defense boost. So pop that into mob_family_mods table. Goblin Diggers have a vermin killer trait, so find its poolid and put it in mod_pool_mods table. */ void LoadCustomMods() { // load family mods const int8 QueryFamilyMods[] = "SELECT familyid, modid, value, type FROM mob_family_mods;"; int32 ret = Sql_Query(SqlHandle, QueryFamilyMods); if(ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { while(Sql_NextRow(SqlHandle) == SQL_SUCCESS) { ModsList_t* familyMods = GetMobFamilyMods(Sql_GetUIntData(SqlHandle,0), true); CModifier* mod = new CModifier(Sql_GetUIntData(SqlHandle,1)); mod->setModAmount(Sql_GetIntData(SqlHandle,2)); uint16 type = Sql_GetUIntData(SqlHandle,3); if(type == 1) { familyMods->mobMods.push_back(mod); } else { familyMods->mods.push_back(mod); } } } // load pool mods const int8 QueryPoolMods[] = "SELECT poolid, modid, value, type FROM mob_pool_mods;"; ret = Sql_Query(SqlHandle, QueryPoolMods); if(ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { while(Sql_NextRow(SqlHandle) == SQL_SUCCESS) { uint16 pool = Sql_GetUIntData(SqlHandle,0); ModsList_t* poolMods = GetMobPoolMods(pool, true); uint16 id = Sql_GetUIntData(SqlHandle,1); CModifier* mod = new CModifier(id); mod->setModAmount(Sql_GetUIntData(SqlHandle,2)); uint16 type = Sql_GetUIntData(SqlHandle,3); if(type == 1) { poolMods->mobMods.push_back(mod); } else { poolMods->mods.push_back(mod); } } } // load spawn mods const int8 QuerySpawnMods[] = "SELECT mobid, modid, value, type FROM mob_spawn_mods;"; ret = Sql_Query(SqlHandle, QuerySpawnMods); if(ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { while(Sql_NextRow(SqlHandle) == SQL_SUCCESS) { ModsList_t* spawnMods = GetMobSpawnMods(Sql_GetUIntData(SqlHandle,0), true); CModifier* mod = new CModifier(Sql_GetUIntData(SqlHandle,1)); mod->setModAmount(Sql_GetUIntData(SqlHandle,2)); uint16 type = Sql_GetUIntData(SqlHandle,3); if(type == 1) { spawnMods->mobMods.push_back(mod); } else { spawnMods->mods.push_back(mod); } } } }
/*************************************************************** Spawns monsters for the given BCNMID/Battlefield number by looking at bcnm_battlefield table for mob ids then spawning them and adding them to the monster list for the given battlefield. ****************************************************************/ bool spawnMonstersForBcnm(CBattlefield* battlefield){ DSP_DEBUG_BREAK_IF(battlefield==nullptr); //get ids from DB const int8* fmtQuery = "SELECT monsterId, conditions \ FROM bcnm_battlefield \ WHERE bcnmId = %u AND battlefieldNumber = %u"; int32 ret = Sql_Query(SqlHandle, fmtQuery, battlefield->getID(), battlefield->getBattlefieldNumber()); if (ret == SQL_ERROR || Sql_NumRows(SqlHandle) == 0) { ShowError("spawnMonstersForBcnm : SQL error - Cannot find any monster IDs for BCNMID %i Battlefield %i \n", battlefield->getID(), battlefield->getBattlefieldNumber()); } else{ while(Sql_NextRow(SqlHandle) == SQL_SUCCESS){ uint32 mobid = Sql_GetUIntData(SqlHandle,0); uint8 condition = Sql_GetUIntData(SqlHandle,1); CMobEntity* PMob = (CMobEntity*)zoneutils::GetEntity(mobid, TYPE_MOB); if (PMob != nullptr) { PMob->m_battlefieldID = battlefield->getBattlefieldNumber(); PMob->m_bcnmID = battlefield->getID(); if (condition & CONDITION_SPAWNED_AT_START) { // This condition is needed for some mob at dynamis, else he don't pop if(PMob->PBattleAI->GetCurrentAction() == ACTION_FADE_OUT){ PMob->PBattleAI->SetLastActionTime(0); PMob->PBattleAI->SetCurrentAction(ACTION_NONE); } if (PMob->PBattleAI->GetCurrentAction() == ACTION_NONE || PMob->PBattleAI->GetCurrentAction() == ACTION_SPAWN) { PMob->PBattleAI->SetLastActionTime(0); PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN); if(strcmp(PMob->GetName(),"Maat")==0){ mobutils::SetupMaat(PMob, (JOBTYPE)battlefield->getPlayerMainJob()); PMob->m_DropID = 4485; //Give Maat his stealable Warp Scroll // disable players subjob battlefield->disableSubJob(); // disallow subjob, this will enable for later battlefield->m_RuleMask &= ~(1 << RULES_ALLOW_SUBJOBS); } //ShowDebug("Spawned %s (%u) id %i inst %i \n",PMob->GetName(),PMob->id,battlefield->getID(),battlefield->getBattlefieldNumber()); battlefield->addEnemy(PMob, condition); } else { ShowDebug(CL_CYAN"SpawnMobForBcnm: <%s> (%u) is already spawned\n" CL_RESET, PMob->GetName(), PMob->id); } } else { battlefield->addEnemy(PMob, condition); } } else { ShowDebug("SpawnMobForBcnm: mob %u not found\n", mobid); } } return true; } return false; }
// Save party to mysql int inter_party_tosql(struct party *p, int flag, int index) { // 'party' ('party_id','name','exp','item','leader_id','leader_char') char esc_name[NAME_LENGTH*2+1];// escaped party name int party_id; if( p == NULL || p->party_id == 0 ) return 0; party_id = p->party_id; #ifdef NOISY ShowInfo("Save party request ("CL_BOLD"%d"CL_RESET" - %s).\n", party_id, p->name); #endif Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); #ifndef TXT_SQL_CONVERT if( flag & PS_BREAK ) {// Break the party // we'll skip name-checking and just reset everyone with the same party id [celest] if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) Sql_ShowDebug(sql_handle); if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) Sql_ShowDebug(sql_handle); //Remove from memory idb_remove(party_db_, party_id); return 1; } #endif //TXT_SQL_CONVERT if( flag & PS_CREATE ) {// Create party #ifndef TXT_SQL_CONVERT if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`name`, `exp`, `item`, `leader_id`, `leader_char`) " "VALUES ('%s', '%d', '%d', '%d', '%d')", party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) { Sql_ShowDebug(sql_handle); return 0; } party_id = p->party_id = (int)Sql_LastInsertId(sql_handle); #else //During conversion, you want to specify the id, and allow overwriting //(in case someone is re-running the process. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` " "(`party_id`, `name`, `exp`, `item`, `leader_id`, `leader_char`) " "VALUES ('%d', '%s', '%d', '%d', '%d', '%d')", party_db, p->party_id, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) { Sql_ShowDebug(sql_handle); return 0; } #endif } #ifndef TXT_SQL_CONVERT if( flag & PS_BASIC ) {// Update party info. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'", party_db, esc_name, p->exp, p->item, party_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_LEADER ) {// Update leader if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'", party_db, p->member[index].account_id, p->member[index].char_id, party_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_ADDMEMBER ) {// Add one party member. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_DELMEMBER ) {// Remove one party member. if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'", char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) Sql_ShowDebug(sql_handle); } #endif //TXT_SQL_CONVERT if( save_log ) ShowInfo("Party Saved (%d - %s)\n", party_id, p->name); return 1; }
bool mapif_homunculus_save(struct s_homunculus* hd) { bool flag = true; char esc_name[NAME_LENGTH*2+1]; Sql_EscapeStringLen(sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH)); if( hd->hom_id == 0 ) {// new homunculus if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `homunculus` " "(`char_id`, `class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) " "VALUES ('%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", hd->char_id, hd->class_, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize) ) { Sql_ShowDebug(sql_handle); flag = false; } else { hd->hom_id = (int)Sql_LastInsertId(sql_handle); } } else { if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `homunculus` SET `char_id`='%d', `class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'", hd->char_id, hd->class_, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) ) { Sql_ShowDebug(sql_handle); flag = false; } else { SqlStmt* stmt; int i; stmt = SqlStmt_Malloc(sql_handle); if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `skill_homunculus` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", hd->hom_id) ) SqlStmt_ShowDebug(stmt); for( i = 0; i < MAX_HOMUNSKILL; ++i ) { if( hd->hskill[i].id > 0 && hd->hskill[i].lv != 0 ) { SqlStmt_BindParam(stmt, 0, SQLDT_USHORT, &hd->hskill[i].id, 0); SqlStmt_BindParam(stmt, 1, SQLDT_USHORT, &hd->hskill[i].lv, 0); if( SQL_ERROR == SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); flag = false; break; } } } SqlStmt_Free(stmt); } } return flag; }
// Read party from mysql struct party_data *inter_party_fromsql(int party_id) { int leader_id = 0; int leader_char = 0; struct party_data* p; struct party_member* m; char* data; size_t len; int i; #ifdef NOISY ShowInfo("Load party request ("CL_BOLD"%d"CL_RESET")\n", party_id); #endif if( party_id <= 0 ) return NULL; //Load from memory p = (struct party_data*)idb_get(party_db_, party_id); if( p != NULL ) return p; p = party_pt; memset(p, 0, sizeof(struct party_data)); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) { Sql_ShowDebug(sql_handle); return NULL; } if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) return NULL; p->party.party_id = party_id; Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH)); Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0); Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data); Sql_FreeResult(sql_handle); // Load members if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) ) { Sql_ShowDebug(sql_handle); return NULL; } for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { m = &p->party.member[i]; Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data); Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0); Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data); m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0); } Sql_FreeResult(sql_handle); if( save_log ) ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name); //Add party to memory. CREATE(p, struct party_data, 1); memcpy(p, party_pt, sizeof(struct party_data)); //init state int_party_calc_state(p); idb_put(party_db_, party_id, p); return p; }
respawntime, spawntype, dropid, mob_groups.HP, mob_groups.MP, minLevel, maxLevel, \ modelid, mJob, sJob, cmbSkill, cmbDmgMult, cmbDelay, behavior, links, mobType, immunity, \ systemid, mobsize, speed, \ STR, DEX, VIT, AGI, `INT`, MND, CHR, EVA, DEF, \ Slash, Pierce, H2H, Impact, \ Fire, Ice, Wind, Earth, Lightning, Water, Light, Dark, Element, \ mob_pools.familyid, name_prefix, flags, animationsub, \ (mob_family_system.HP / 100), (mob_family_system.MP / 100), hasSpellScript, spellList, ATT, ACC, mob_groups.poolid, \ allegiance, namevis, aggro \ FROM instance_entities INNER JOIN mob_spawn_points ON instance_entities.id = mob_spawn_points.mobid \ INNER JOIN mob_groups ON mob_groups.groupid = mob_spawn_points.groupid \ INNER JOIN mob_pools ON mob_groups.poolid = mob_pools.poolid \ INNER JOIN mob_family_system ON mob_pools.familyid = mob_family_system.familyid \ WHERE instanceid = %u AND NOT (pos_x = 0 AND pos_y = 0 AND pos_z = 0);"; int32 ret = Sql_Query(SqlInstanceHandle, Query, instance->GetID()); if (!instance->Failed() && ret != SQL_ERROR && Sql_NumRows(SqlInstanceHandle) != 0) { while (Sql_NextRow(SqlInstanceHandle) == SQL_SUCCESS) { CMobEntity* PMob = new CMobEntity; PMob->name.insert(0, Sql_GetData(SqlInstanceHandle, 0)); PMob->id = (uint32)Sql_GetUIntData(SqlInstanceHandle, 1); PMob->targid = (uint16)PMob->id & 0x0FFF; PMob->m_SpawnPoint.rotation = (uint8)Sql_GetIntData(SqlInstanceHandle, 2); PMob->m_SpawnPoint.x = Sql_GetFloatData(SqlInstanceHandle, 3); PMob->m_SpawnPoint.y = Sql_GetFloatData(SqlInstanceHandle, 4); PMob->m_SpawnPoint.z = Sql_GetFloatData(SqlInstanceHandle, 5);
/*========================================== * Mark mail as 'Read' *------------------------------------------*/ void mapif_parse_Mail_read(int fd) { int mail_id = RFIFOL(fd,2); if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", schema_config.mail_db, MAIL_READ, mail_id) ) Sql_ShowDebug(sql_handle); }
int32 do_init(int32 argc, char** argv) { int32 i; LOGIN_CONF_FILENAME = "conf/login_darkstar.conf"; VERSION_INFO_FILENAME = "version.info"; const char *lan_cfgName = LAN_CONFIG_NAME; //srand(gettick()); for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--h") == 0 || strcmp(argv[i], "--?") == 0 || strcmp(argv[i], "/?") == 0) login_helpscreen(1); else if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "--v") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "/v") == 0) login_versionscreen(1); else if (strcmp(argv[i], "--login_config") == 0 || strcmp(argv[i], "--login-config") == 0) LOGIN_CONF_FILENAME = argv[i + 1]; else if (strcmp(argv[i], "--lan_config") == 0 || strcmp(argv[i], "--lan-config") == 0) lan_cfgName = argv[i + 1]; else if (strcmp(argv[i], "--run_once") == 0) // close the map-server as soon as its done.. for testing [Celest] runflag = 0; } //lan_config_default(&lan_config); //lan_config_read(lan_cfgName,&lan_config); login_config_default(); login_config_read(LOGIN_CONF_FILENAME); version_info_default(); version_info_read(VERSION_INFO_FILENAME); login_fd = makeListenBind_tcp(login_config.login_auth_ip, login_config.login_auth_port, connect_client_login); ShowStatus("The login-server-auth is " CL_GREEN"ready" CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_auth_port); login_lobbydata_fd = makeListenBind_tcp(login_config.login_data_ip, login_config.login_data_port, connect_client_lobbydata); ShowStatus("The login-server-lobbydata is " CL_GREEN"ready" CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_data_port); login_lobbyview_fd = makeListenBind_tcp(login_config.login_view_ip, login_config.login_view_port, connect_client_lobbyview); ShowStatus("The login-server-lobbyview is " CL_GREEN"ready" CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_view_port); SqlHandle = Sql_Malloc(); if (Sql_Connect(SqlHandle, login_config.mysql_login, login_config.mysql_password, login_config.mysql_host, login_config.mysql_port, login_config.mysql_database) == SQL_ERROR) { exit(EXIT_FAILURE); } Sql_Keepalive(SqlHandle); const char *fmtQuery = "OPTIMIZE TABLE `accounts`,`accounts_banned`, `accounts_sessions`, `chars`,`char_equip`, \ `char_inventory`, `char_jobs`,`char_look`,`char_stats`, `char_vars`, `char_bazaar_msg`, \ `char_skills`, `char_titles`, `char_effects`, `char_exp`;"; if (Sql_Query(SqlHandle, fmtQuery) == SQL_ERROR) { ShowError("do_init: Impossible to optimise tables\n"); } messageThread = std::thread(message_server_init); ShowStatus("The login-server is " CL_GREEN"ready" CL_RESET" to work...\n"); return 0; }
void CParty::RemoveMember(CBattleEntity* PEntity) { DSP_DEBUG_BREAK_IF(PEntity == NULL); DSP_DEBUG_BREAK_IF(PEntity->PParty != this); if (m_PLeader == PEntity) { RemovePartyLeader(PEntity); } else { for (uint32 i = 0; i < members.size(); ++i) { if (PEntity == members.at(i)) { members.erase(members.begin()+i); if (m_PartyType == PARTY_PCS) { CCharEntity* PChar = (CCharEntity*)PEntity; if (m_PQuaterMaster == PChar) { SetQuaterMaster(NULL); } if (m_PSyncTarget == PChar) { SetSyncTarget(NULL, 553); CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553)); sync->SetStartTime(gettick()); sync->SetDuration(30000); } DisableSync(); } if (m_PSyncTarget != NULL && m_PSyncTarget != PChar) { if (PChar->status != STATUS_DISAPPEAR && PChar->getZone() == m_PSyncTarget->getZone() ) { CStatusEffect* sync = PChar->StatusEffectContainer->GetStatusEffect(EFFECT_LEVEL_SYNC); if (sync && sync->GetDuration() == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 30, 553)); sync->SetStartTime(gettick()); sync->SetDuration(30000); } } } PChar->PLatentEffectContainer->CheckLatentsPartyMembers(members.size()); PChar->pushPacket(new CPartyDefinePacket(NULL)); PChar->pushPacket(new CPartyMemberUpdatePacket(PChar, 0, PChar->getZone())); PChar->pushPacket(new CCharUpdatePacket(PChar)); PChar->PParty = NULL; Sql_Query(SqlHandle, "DELETE FROM accounts_parties WHERE charid = %u;", PChar->id); uint8 data[4]; WBUFL(data, 0) = m_PartyID; message::send(MSG_PT_RELOAD, data, sizeof data, NULL); if (PChar->PTreasurePool != NULL && PChar->PTreasurePool->GetPoolType() != TREASUREPOOL_ZONE) { PChar->PTreasurePool->DelMember(PChar); PChar->PTreasurePool = new CTreasurePool(TREASUREPOOL_SOLO); PChar->PTreasurePool->AddMember(PChar); PChar->PTreasurePool->UpdatePool(PChar); } } break; } } } }
/** * Player setup a new shop * @param sd : player opening the shop * @param message : shop title * @param data : itemlist data * data := {<index>.w <amount>.w <value>.l}[count] * @param count : number of different items * @param at Autotrader info, or NULL if requetsed not from autotrade persistance * @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - No valid item found */ int8 vending_openvending(struct map_session_data *sd, const char *message, const uint8 *data, int count, struct s_autotrader *at) { int i, j; int vending_skill_lvl; char message_sql[MESSAGE_SIZE * 2]; StringBuf buf; nullpo_retr(1, sd); if( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd) ) return 1; //Can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once vending_skill_lvl = pc_checkskill(sd, MC_VENDING); //Skill level and cart check if( !vending_skill_lvl || !pc_iscarton(sd) ) { clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0); return 2; } //Check number of items in shop if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { //Invalid item count clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0); return 3; } if( save_settings&2 ) // Avoid invalid data from saving chrif_save(sd, 0); //Filter out invalid items i = 0; for( j = 0; j < count; j++ ) { short index = *(uint16 *)(data + 8 * j + 0); short amount = *(uint16 *)(data + 8 * j + 2); unsigned int value = *(uint32 *)(data + 8 * j + 4); index -= 2; //Offset adjustment (client says that the first cart position is 2) if( index < 0 || index >= MAX_CART || //Invalid position pc_cartitem_amount(sd, index, amount) < 0 || //Invalid item or insufficient quantity //NOTE: Official server does not do any of the following checks! !sd->status.cart[index].identify || //Unidentified item sd->status.cart[index].attribute == 1 || //Broken item sd->status.cart[index].expire_time || //It should not be in the cart but just in case (sd->status.cart[index].bound && !pc_can_give_bounded_items(sd)) || //Can't trade account bound items and has no permission !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) //Untradeable item continue; sd->vending[i].index = index; sd->vending[i].amount = amount; sd->vending[i].value = min(value, (unsigned int)battle_config.vending_max_value); //Player just moved item to cart and we don't have the correct cart ID yet if( battle_config.feature_autotrade && sd->status.cart[sd->vending[i].index].id == 0 ) { struct item_data *idb = itemdb_search(sd->status.cart[index].nameid); char msg[256]; sprintf(msg, msg_txt(725), idb->jname); // Item '%s' has not yet saved well to the cart. Please re-log your character. clif_displaymessage(sd->fd, msg); clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0); return 4; } i++; //Item successfully added } if( i != j ) clif_displaymessage(sd->fd, msg_txt(266)); // "Some of your items cannot be vended and were removed from the shop." if( i == 0 ) { //No valid item found clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0, 0); //Custom reply packet return 4; } sd->state.prevend = 0; sd->state.vending = 1; sd->vender_id = vending_getuid(); sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); 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`,`autotrade`,`body_direction`,`head_direction`,`sit`) VALUES(%d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d');", vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, (!sd->status.sex ? 'F' : 'M'), map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, (at ? at->dir : sd->ud.dir), (at ? at->head_dir : sd->head_dir), (at ? at->sit : pc_issit(sd))) != SQL_SUCCESS ) Sql_ShowDebug(mmysql_handle); StringBuf_Init(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES", vending_items_db); for( i = 0; i < count; i++ ) { StringBuf_Printf(&buf, "(%d,%d,%d,%d,%d)", sd->vender_id, i, sd->status.cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value); if( i < count - 1 ) StringBuf_AppendStr(&buf, ","); } if( SQL_ERROR == Sql_QueryStr(mmysql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(mmysql_handle); StringBuf_Destroy(&buf); clif_openvending(sd, sd->bl.id, sd->vending); clif_showvendingboard(&sd->bl, message, 0); idb_put(vending_db, sd->status.char_id, sd); return 0; }
/// logs item transactions void log_pick(struct block_list* bl, e_log_pick_type type, int nameid, int amount, struct item* itm) { const char* mapname; int id = 0, account_id = 0; char esc_name[NAME_LENGTH*2+1] = ""; if( ( log_config.enable_logs&type ) == 0 ) {// disabled return; } if( !should_log_item(nameid, amount, itm ? itm->refine : 0) ) return; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] //either PLAYER or MOB (here we get map name and objects ID) if( bl == NULL ) { ShowError("log_pick: bl == NULL\n"); } else switch( bl->type ) { case BL_PC: id = ((TBL_PC*)bl)->status.char_id; account_id = ((TBL_PC*)bl)->status.account_id; Sql_EscapeStringLen(logmysql_handle, esc_name, ((TBL_PC*)bl)->status.name, NAME_LENGTH); break; case BL_MOB: id = ((TBL_MOB*)bl)->class_; account_id = 0; Sql_EscapeStringLen(logmysql_handle, esc_name, ((TBL_MOB*)bl)->name, NAME_LENGTH); break; default: ShowDebug("log_pick: Unhandled bl type %d.\n", bl->type); } mapname = map[bl->m].name; #ifndef TXT_ONLY if( log_config.sql_logs ) { if( itm == NULL ) {//We log common item if( SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `account_id`, `char_id`, `name`, `type`, `nameid`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%c', '%d', '%d', '%s')", log_config.log_pick, account_id, id, esc_name, log_picktype2char(type), nameid, amount, mapname) ) { Sql_ShowDebug(logmysql_handle); return; } } else {//We log Extended item if( SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `account_id`, `char_id`, `name`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `serial`) VALUES (NOW(), '%d', '%d', '%s', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%u')", log_config.log_pick, account_id, id, esc_name, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname, itm->serial) ) { Sql_ShowDebug(logmysql_handle); return; } } } else #endif { char timestring[255]; time_t curtime; FILE* logfp; if( ( logfp = fopen(log_config.log_pick, "a") ) == NULL ) return; time(&curtime); strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); if( itm == NULL ) {//We log common item fprintf(logfp,"%s - %d\t%c\t%d,%d,%s\n", timestring, id, log_picktype2char(type), nameid, amount, mapname); } else {//We log Extended item fprintf(logfp,"%s - %d\t%c\t%d,%d,%d,%d,%d,%d,%d,%s\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); } fclose(logfp); } }
/** * Initializing autotraders from table */ void do_init_vending_autotrade(void) { if( battle_config.feature_autotrade ) { if( Sql_Query(mmysql_handle, "SELECT `id`, `account_id`, `char_id`, `sex`, `title`, `body_direction`, `head_direction`, `sit` " "FROM `%s` " "WHERE `autotrade` = 1 AND (SELECT COUNT(`vending_id`) FROM `%s` WHERE `vending_id` = `id`) > 0 " "ORDER BY `id`;", vendings_db, vending_items_db) != SQL_SUCCESS ) { Sql_ShowDebug(mmysql_handle); return; } if( Sql_NumRows(mmysql_handle) > 0 ) { uint16 items = 0; DBIterator *iter = NULL; struct s_autotrader *at = NULL; //Init each autotrader data while (SQL_SUCCESS == Sql_NextRow(mmysql_handle)) { size_t len; char *data; at = NULL; CREATE(at, struct s_autotrader, 1); Sql_GetData(mmysql_handle, 0, &data, NULL); at->id = atoi(data); Sql_GetData(mmysql_handle, 1, &data, NULL); at->account_id = atoi(data); Sql_GetData(mmysql_handle, 2, &data, NULL); at->char_id = atoi(data); Sql_GetData(mmysql_handle, 3, &data, NULL); at->sex = (data[0] == 'F') ? SEX_FEMALE : SEX_MALE; Sql_GetData(mmysql_handle, 4, &data, &len); safestrncpy(at->title, data, min(len + 1, MESSAGE_SIZE)); Sql_GetData(mmysql_handle, 5, &data, NULL); at->dir = atoi(data); Sql_GetData(mmysql_handle, 6, &data, NULL); at->head_dir = atoi(data); Sql_GetData(mmysql_handle, 7, &data, NULL); at->sit = atoi(data); at->count = 0; if( battle_config.feature_autotrade_direction >= 0 ) at->dir = battle_config.feature_autotrade_direction; if( battle_config.feature_autotrade_head_direction >= 0 ) at->head_dir = battle_config.feature_autotrade_head_direction; if( battle_config.feature_autotrade_sit >= 0 ) at->sit = battle_config.feature_autotrade_sit; //Initialize player CREATE(at->sd, struct map_session_data, 1); pc_setnewpc(at->sd, at->account_id, at->char_id, 0, gettick(), at->sex, 0); at->sd->state.autotrade = 1|2; at->sd->state.monster_ignore = (battle_config.autotrade_monsterignore); chrif_authreq(at->sd, true); uidb_put(vending_autotrader_db, at->char_id, at); } Sql_FreeResult(mmysql_handle); //Init items for each autotraders iter = db_iterator(vending_autotrader_db); for( at = dbi_first(iter); dbi_exists(iter); at = dbi_next(iter) ) { uint16 j = 0; if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT `cartinventory_id`, `amount`, `price` " "FROM `%s` " "WHERE `vending_id` = %d " "ORDER BY `index` ASC;", vending_items_db, at->id) ) { Sql_ShowDebug(mmysql_handle); continue; } if( !(at->count = (uint16)Sql_NumRows(mmysql_handle)) ) { map_quit(at->sd); vending_autotrader_remove(at, true); continue; } //Init the list CREATE(at->entries, struct s_autotrade_entry *, at->count); //Add the item into list j = 0; while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) && j < at->count ) { char *data; CREATE(at->entries[j], struct s_autotrade_entry, 1); Sql_GetData(mmysql_handle, 0, &data, NULL); at->entries[j]->cartinventory_id = atoi(data); Sql_GetData(mmysql_handle, 1, &data, NULL); at->entries[j]->amount = atoi(data); Sql_GetData(mmysql_handle, 2, &data, NULL); at->entries[j]->price = atoi(data); j++; } items += j; Sql_FreeResult(mmysql_handle); } dbi_destroy(iter); ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' vending autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", db_size(vending_autotrader_db), items); } }
// Load account_reg from sql (type=2) int inter_accreg_fromsql(int account_id,int char_id, int fd, int type) { char* data; size_t len; unsigned int plen = 0; switch(type) { case 3: //Char Reg if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", char_reg_str_db, char_id) ) Sql_ShowDebug(sql_handle); break; case 2: //account reg if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", acc_reg_str_db, account_id) ) Sql_ShowDebug(sql_handle); break; case 1: //Account2 Reg ShowError(read_message("Source.char.inter_accreg_tosql_s1")); return 0; default: ShowError(read_message("Source.char.inter_accreg_tosql_s2"), type); return 0; } WFIFOHEAD(fd, 60000 + 300); WFIFOW(fd, 0) = 0x3804; /* 0x2 = length, set prior to being sent */ WFIFOL(fd, 4) = account_id; WFIFOL(fd, 8) = char_id; WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ WFIFOB(fd, 13) = 1;/* is string type */ WFIFOW(fd, 14) = 0;/* count */ plen = 16; /** * Vessel! * * str type * { keyLength(B), key(<keyLength>), index(L), valLength(B), val(<valLength>) } **/ while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { Sql_GetData(sql_handle, 0, &data, NULL); len = strlen(data)+1; WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */ plen += 1; safestrncpy((char*)WFIFOP(fd,plen), data, len); plen += len; Sql_GetData(sql_handle, 1, &data, NULL); WFIFOL(fd, plen) = (unsigned int)atol(data); plen += 4; Sql_GetData(sql_handle, 2, &data, NULL); len = strlen(data)+1; WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */ plen += 1; safestrncpy((char*)WFIFOP(fd,plen), data, len); plen += len; WFIFOW(fd, 14) += 1; if( plen > 60000 ) { WFIFOW(fd, 2) = plen; WFIFOSET(fd, plen); /* prepare follow up */ WFIFOHEAD(fd, 60000 + 300); WFIFOW(fd, 0) = 0x3804; /* 0x2 = length, set prior to being sent */ WFIFOL(fd, 4) = account_id; WFIFOL(fd, 8) = char_id; WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ WFIFOB(fd, 13) = 1;/* is string type */ WFIFOW(fd, 14) = 0;/* count */ plen = 16; } } /* mark & go. */ WFIFOW(fd, 2) = plen; WFIFOSET(fd, plen); Sql_FreeResult(sql_handle); switch( type ) { case 3: //char reg if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", char_reg_num_db, char_id) ) Sql_ShowDebug(sql_handle); break; case 2: //account reg if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", acc_reg_num_db, account_id) ) Sql_ShowDebug(sql_handle); break; case 1: //account2 reg ShowError(read_message("Source.char.inter_accreg_fromsql_s1")); return 0; } WFIFOHEAD(fd, 60000 + 300); WFIFOW(fd, 0) = 0x3804; /* 0x2 = length, set prior to being sent */ WFIFOL(fd, 4) = account_id; WFIFOL(fd, 8) = char_id; WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ WFIFOB(fd, 13) = 0;/* is int type */ WFIFOW(fd, 14) = 0;/* count */ plen = 16; /** * Vessel! * * int type * { keyLength(B), key(<keyLength>), index(L), value(L) } **/ while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { Sql_GetData(sql_handle, 0, &data, NULL); len = strlen(data)+1; WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */ plen += 1; safestrncpy((char*)WFIFOP(fd,plen), data, len); plen += len; Sql_GetData(sql_handle, 1, &data, NULL); WFIFOL(fd, plen) = (unsigned int)atol(data); plen += 4; Sql_GetData(sql_handle, 2, &data, NULL); WFIFOL(fd, plen) = atoi(data); plen += 4; WFIFOW(fd, 14) += 1; if( plen > 60000 ) { WFIFOW(fd, 2) = plen; WFIFOSET(fd, plen); /* prepare follow up */ WFIFOHEAD(fd, 60000 + 300); WFIFOW(fd, 0) = 0x3804; /* 0x2 = length, set prior to being sent */ WFIFOL(fd, 4) = account_id; WFIFOL(fd, 8) = char_id; WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ WFIFOB(fd, 13) = 0;/* is int type */ WFIFOW(fd, 14) = 0;/* count */ plen = 16; } } /* mark as complete & go. */ WFIFOB(fd, 12) = type; WFIFOW(fd, 2) = plen; WFIFOSET(fd, plen); Sql_FreeResult(sql_handle); return 1; }
/** * Purchase item(s) from a shop * @param sd : buyer player session * @param aid : account id of vender * @param uid : shop unique id * @param data : items data who would like to purchase * data := {<index>.w <amount>.w }[count] * @param count : number of different items he's trying to buy */ void vending_purchasereq(struct map_session_data *sd, int aid, int uid, const uint8 *data, int count) { int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING]; double z; struct s_vending vending[MAX_VENDING]; //Against duplicate packets struct map_session_data *vsd = map_id2sd(aid); nullpo_retv(sd); if( vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id ) return; //Invalid shop if( vsd->vender_id != uid ) { //Shop has changed clif_buyvending(sd, 0, 0, 6); //Store information was incorrect return; } if( !searchstore_queryremote(sd, aid) && ( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) ) ) return; //Shop too far away searchstore_clearremote(sd); if( count < 1 || count > MAX_VENDING || count > vsd->vend_num ) return; //Invalid amount of purchased items blank = pc_inventoryblank(sd); //Number of free cells in the buyer's inventory //Duplicate item in vending to check hacker with multiple packets memcpy(&vending, &vsd->vending, sizeof(vsd->vending)); //Copy vending list //Some checks z = 0.; //Zeny counter w = 0; //Weight counter for( i = 0; i < count; i++ ) { short amount = *(uint16 *)(data + 4 * i + 0); short idx = *(uint16 *)(data + 4 * i + 2); idx -= 2; if( amount <= 0 ) return; //Check of item index in the cart if( idx < 0 || idx >= MAX_CART ) return; ARR_FIND(0, vsd->vend_num, j, vsd->vending[j].index == idx); if( j == vsd->vend_num ) return; //Picked non-existing item else vend_list[i] = j; z += ((double)vsd->vending[j].value * (double)amount); if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) { clif_buyvending(sd, idx, amount, 1); //You don't have enough zeny return; } if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max ) { clif_buyvending(sd, idx, vsd->vending[j].amount, 4); //Too much zeny = overflow return; } w += itemdb_weight(vsd->status.cart[idx].nameid) * amount; if( w + sd->weight > sd->max_weight ) { clif_buyvending(sd, idx, amount, 2); //You can not buy, because overweight return; } //Check to see if cart/vend info is in sync. if( vending[j].amount > vsd->status.cart[idx].amount ) vending[j].amount = vsd->status.cart[idx].amount; //If they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples). //Here, we check cumulative amounts if( vending[j].amount < amount ) { //Send more quantity is not a hack (an other player can have buy items just before) clif_buyvending(sd, idx, vsd->vending[j].amount, 4); //Not enough quantity return; } vending[j].amount -= amount; switch( pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) { case CHKADDITEM_EXIST: break; //We'd add this item to the existing one (in buyers inventory) case CHKADDITEM_NEW: new_++; if (new_ > blank) return; //Buyer has no space in his inventory break; case CHKADDITEM_OVERAMOUNT: return; //too many items } } pc_payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd); if( battle_config.vending_tax ) z -= z * (battle_config.vending_tax / 10000.); pc_getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd); for( i = 0; i < count; i++ ) { short amount = *(uint16 *)(data + 4 * i + 0); short idx = *(uint16 *)(data + 4 * i + 2); idx -= 2; z = 0.; //Zeny counter //Vending item pc_additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING); vsd->vending[vend_list[i]].amount -= amount; z += ((double)vsd->vending[i].value * (double)amount); if( vsd->vending[vend_list[i]].amount ) { if( Sql_Query(mmysql_handle, "UPDATE `%s` SET `amount` = %d WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vending[vend_list[i]].amount, vsd->vender_id, vsd->status.cart[idx].id) != SQL_SUCCESS ) Sql_ShowDebug(mmysql_handle); } else { if( Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `vending_id` = %d and `cartinventory_id` = %d", vending_items_db, vsd->vender_id, vsd->status.cart[idx].id) != SQL_SUCCESS ) Sql_ShowDebug(mmysql_handle); } pc_cart_delitem(vsd, idx, amount, 0, LOG_TYPE_VENDING); if( battle_config.vending_tax ) z -= z * (battle_config.vending_tax / 10000.); clif_vendingreport(vsd, idx, amount, sd->status.char_id, (int)z); //Print buyer's name if( battle_config.buyer_name ) { char temp[256]; sprintf(temp, msg_txt(265), sd->status.name); clif_disp_onlyself(vsd,temp,strlen(temp)); } } //Compact the vending list for( i = 0, cursor = 0; i < vsd->vend_num; i++ ) { if( vsd->vending[i].amount == 0 ) continue; if( cursor != i ) { //Speedup vsd->vending[cursor].index = vsd->vending[i].index; vsd->vending[cursor].amount = vsd->vending[i].amount; vsd->vending[cursor].value = vsd->vending[i].value; } cursor++; } vsd->vend_num = cursor; //Always save BOTH: customer (buyer) and vender if( save_settings&2 ) { chrif_save(sd,0); chrif_save(vsd,0); } //Check for @AUTOTRADE users [durf] if( vsd->state.autotrade ) { //See if there is anything left in the shop ARR_FIND(0, vsd->vend_num, i, vsd->vending[i].amount > 0); if( i == vsd->vend_num ) { //Close Vending (this was automatically done by the client, we have to do it manually for autovenders) [Skotlex] vending_closevending(vsd); map_quit(vsd); //They have no reason to stay around anymore, do they? } } }
void inter_auctions_fromsql(void) { int i; struct auction_data *auction; struct item *item; char *data; StringBuf buf; unsigned int tick = gettick(), endtick; time_t now = time(NULL); StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `auction_id`,`seller_id`,`seller_name`,`buyer_id`,`buyer_name`," "`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`"); for( i = 0; i < MAX_SLOTS; i++ ) StringBuf_Printf(&buf, ",`card%d`", i); StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); StringBuf_Destroy(&buf); while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { CREATE(auction, struct auction_data, 1); Sql_GetData(sql_handle, 0, &data, NULL); auction->auction_id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); auction->seller_id = atoi(data); Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(auction->seller_name, data, NAME_LENGTH); Sql_GetData(sql_handle, 3, &data, NULL); auction->buyer_id = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(auction->buyer_name, data, NAME_LENGTH); Sql_GetData(sql_handle, 5, &data, NULL); auction->price = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); auction->buynow = atoi(data); Sql_GetData(sql_handle, 7, &data, NULL); auction->hours = atoi(data); Sql_GetData(sql_handle, 8, &data, NULL); auction->timestamp = atoi(data); item = &auction->item; Sql_GetData(sql_handle, 9, &data, NULL); item->nameid = atoi(data); Sql_GetData(sql_handle,10, &data, NULL); safestrncpy(auction->item_name, data, ITEM_NAME_LENGTH); Sql_GetData(sql_handle,11, &data, NULL); auction->type = atoi(data); Sql_GetData(sql_handle,12, &data, NULL); item->refine = atoi(data); Sql_GetData(sql_handle,13, &data, NULL); item->attribute = atoi(data); Sql_GetData(sql_handle,14, &data, NULL); item->unique_id = strtoull(data, NULL, 10); item->identify = 1; item->amount = 1; item->expire_time = 0; for( i = 0; i < MAX_SLOTS; i++ ) { Sql_GetData(sql_handle, 15 + i, &data, NULL); item->card[i] = atoi(data); } if( auction->timestamp > now ) endtick = ((unsigned int)(auction->timestamp - now) * 1000) + tick; else endtick = tick + 10000; // 10 Second's to process ended auctions auction->auction_end_timer = add_timer(endtick, auction_end_timer, auction->auction_id, 0); idb_put(auction_db_, auction->auction_id, auction); } Sql_FreeResult(sql_handle); }
static int mail_fromsql(int char_id, struct mail_data* md) { int i, j; struct mail_message *msg; struct item *item; char *data; StringBuf buf; memset(md, 0, sizeof(struct mail_data)); md->amount = 0; md->full = false; StringBuf_Init(&buf); StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`," "`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`"); for (i = 0; i < MAX_SLOTS; i++) StringBuf_Printf(&buf, ",`card%d`", i); // I keep the `status` < 3 just in case someone forget to apply the sqlfix StringBuf_Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' AND `status` < 3 ORDER BY `id` LIMIT %d", mail_db, char_id, MAIL_MAX_INBOX + 1); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); StringBuf_Destroy(&buf); for (i = 0; i < MAIL_MAX_INBOX && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { msg = &md->msg[i]; Sql_GetData(sql_handle, 0, &data, NULL); msg->id = atoi(data); Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH); Sql_GetData(sql_handle, 2, &data, NULL); msg->send_id = atoi(data); Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH); Sql_GetData(sql_handle, 4, &data, NULL); msg->dest_id = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); Sql_GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); Sql_GetData(sql_handle, 8, &data, NULL); msg->status = atoi(data); Sql_GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); item = &msg->item; Sql_GetData(sql_handle,10, &data, NULL); item->amount = (short)atoi(data); Sql_GetData(sql_handle,11, &data, NULL); item->nameid = atoi(data); Sql_GetData(sql_handle,12, &data, NULL); item->refine = atoi(data); Sql_GetData(sql_handle,13, &data, NULL); item->attribute = atoi(data); Sql_GetData(sql_handle,14, &data, NULL); item->identify = atoi(data); for (j = 0; j < MAX_SLOTS; j++) { Sql_GetData(sql_handle, 15 + j, &data, NULL); item->card[j] = atoi(data); } } md->full = ( Sql_NumRows(sql_handle) > MAIL_MAX_INBOX ); md->amount = i; md->changed = false; Sql_FreeResult(sql_handle); md->unchecked = 0; md->unread = 0; for (i = 0; i < md->amount; i++) { msg = &md->msg[i]; if( msg->status == MAIL_NEW ) { if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_UNREAD, msg->id) ) Sql_ShowDebug(sql_handle); msg->status = MAIL_UNREAD; md->unchecked++; } else if ( msg->status == MAIL_UNREAD ) md->unread++; } ShowInfo("mail load complete from DB - id: %d (total: %d)\n", char_id, md->amount); return 1; }
//-------------------------------------------------------- // Save registry to sql int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type) { struct global_reg* r; StringBuf buf; int i; if( account_id <= 0 ) return 0; reg->account_id = account_id; reg->char_id = char_id; //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) switch( type ) { case 3: //Char Reg if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) Sql_ShowDebug(sql_handle); account_id = 0; break; case 2: //Account Reg if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) Sql_ShowDebug(sql_handle); char_id = 0; break; case 1: //Account2 Reg ShowError("inter_accreg_tosql: char-server não deveria manusear registros de valor tipo 1 (##). Isto é trabalho do login-server!\n"); return 0; default: ShowError("inter_accreg_tosql: Tipo inválido: %d\n", type); return 0; } if( reg->reg_num <= 0 ) return 0; StringBuf_Init(&buf); StringBuf_Printf(&buf, "INSERT INTO `%s` (`type`,`account_id`,`char_id`,`str`,`value`) VALUES ", reg_db); for( i = 0; i < reg->reg_num; ++i ) { r = ®->reg[i]; if( r->str[0] != '\0' && r->value[0] != '\0' ) { char str[32]; char val[256]; if( i > 0 ) StringBuf_AppendStr(&buf, ","); Sql_EscapeString(sql_handle, str, r->str); Sql_EscapeString(sql_handle, val, r->value); StringBuf_Printf(&buf, "('%d','%d','%d','%s','%s')", type, account_id, char_id, str, val); } } if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { Sql_ShowDebug(sql_handle); } StringBuf_Destroy(&buf); return 1; }
std::list<SearchEntity*> CDataLoader::GetPlayersList(search_req sr, int* count) { std::list<SearchEntity*> PlayersList; std::string filterQry = ""; if (sr.jobid > 0 && sr.jobid < 21){ filterQry.append(" AND "); filterQry.append(" mjob = "); filterQry.append(std::to_string(static_cast<unsigned long long>(sr.jobid))); } if (sr.zoneid[0] > 0) { string_t zoneList; int i = 1; zoneList.append(std::to_string(static_cast<unsigned long long>(sr.zoneid[0]))); while (i < 10 && sr.zoneid[i] != 0) { zoneList.append(", "); zoneList.append(std::to_string(static_cast<unsigned long long>(sr.zoneid[i]))); i++; } filterQry.append(" AND "); filterQry.append("(pos_zone IN ("); filterQry.append(zoneList); filterQry.append(") OR (pos_zone = 0 AND pos_prevzone IN ("); filterQry.append(zoneList); filterQry.append("))) "); } std::string fmtQuery = "SELECT charid, partyid, charname, pos_zone, pos_prevzone, nation, rank_sandoria, rank_bastok, rank_windurst, race, nameflags, mjob, sjob, mlvl, slvl " "FROM accounts_sessions " "LEFT JOIN accounts_parties USING (charid) " "LEFT JOIN chars USING (charid) " "LEFT JOIN char_look USING (charid) " "LEFT JOIN char_stats USING (charid) " "LEFT JOIN char_profile USING(charid) " "WHERE charname IS NOT NULL "; fmtQuery.append(filterQry); fmtQuery.append(" ORDER BY charname ASC"); int32 ret = Sql_Query(SqlHandle, fmtQuery.c_str()); if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { int totalResults = 0; //gives ALL matching criteria (total) int visibleResults = 0; //capped at first 20 while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) { SearchEntity* PPlayer = new SearchEntity; memset(PPlayer, 0, sizeof(SearchEntity)); memcpy(PPlayer->name, Sql_GetData(SqlHandle, 2), 15); PPlayer->id = (uint32)Sql_GetUIntData(SqlHandle, 0); PPlayer->zone = (uint16)Sql_GetIntData(SqlHandle, 3); PPlayer->prevzone = (uint16)Sql_GetIntData(SqlHandle, 4); PPlayer->nation = (uint8)Sql_GetIntData(SqlHandle, 5); PPlayer->mjob = (uint8)Sql_GetIntData(SqlHandle, 11); PPlayer->sjob = (uint8)Sql_GetIntData(SqlHandle, 12); PPlayer->mlvl = (uint8)Sql_GetIntData(SqlHandle, 13); PPlayer->slvl = (uint8)Sql_GetIntData(SqlHandle, 14); PPlayer->race = (uint8)Sql_GetIntData(SqlHandle, 9); PPlayer->rank = (uint8)Sql_GetIntData(SqlHandle, 6 + PPlayer->nation); PPlayer->zone = (PPlayer->zone == 0 ? PPlayer->prevzone : PPlayer->zone); uint32 partyid = (uint32)Sql_GetUIntData(SqlHandle, 1); uint32 nameflag = (uint32)Sql_GetUIntData(SqlHandle, 10); if (partyid == PPlayer->id) PPlayer->flags1 |= 0x0008; if (nameflag & FLAG_AWAY) PPlayer->flags1 |= 0x0100; if (nameflag & FLAG_DC) PPlayer->flags1 |= 0x0800; if (partyid != 0) PPlayer->flags1 |= 0x2000; if (nameflag & FLAG_ANON) PPlayer->flags1 |= 0x4000; if (nameflag & FLAG_INVITE) PPlayer->flags1 |= 0x8000; PPlayer->flags2 = PPlayer->flags1; // TODO: search comments // filter by job if (sr.jobid > 0 && sr.jobid != PPlayer->mjob) continue; // filter by nation if (sr.nation != 255 && sr.nation != PPlayer->nation) continue; // filter by race if (sr.race != 255) { // hume (male/female) if (sr.race == 0 && (PPlayer->race != 1 && PPlayer->race != 2)) continue; // elvaan (male/female) else if (sr.race == 1 && (PPlayer->race != 3 && PPlayer->race != 4)) continue; // tarutaru (male/female) else if (sr.race == 2 && (PPlayer->race != 5 && PPlayer->race != 6)) continue; // mithra (female only) else if (sr.race == 3 && PPlayer->race != 7) continue; // galka (male only) else if (sr.race == 4 && PPlayer->race != 8) continue; } // filter by rank if (sr.minRank > 0 && sr.maxRank >= sr.minRank) { if (PPlayer->rank < sr.minRank || PPlayer->rank > sr.maxRank) continue; } // filter by flag (away, seek party etc.) if (sr.flags != 0 && !(PPlayer->flags2 & sr.flags)) continue; // filter by level if (sr.minlvl > 0 && sr.maxlvl >= sr.minlvl){ if (PPlayer->mlvl < sr.minlvl || PPlayer->mlvl > sr.maxlvl) continue; } // filter by name if (sr.nameLen > 0){ string_t dbname; dbname.insert(0, (char*)PPlayer->name); //can't be this name, too long if (sr.nameLen > dbname.length()){ continue; } bool validName = true; for (int i = 0; i < sr.nameLen; i++){ //convert to lowercase for both if (tolower(sr.name[i]) != tolower(PPlayer->name[i])){ validName = false; break; } } if (!validName){ continue; } } // dont show hidden gm if (nameflag & FLAG_ANON && nameflag & FLAG_GM) { continue; } if (visibleResults < 20){ PlayersList.push_back(PPlayer); visibleResults++; } totalResults++; } if (totalResults > 0){ *count = totalResults; } ShowMessage("Found %i results, displaying %i. \n", totalResults, visibleResults); } return PlayersList; }