Exemple #1
0
//--------------------------------------------------------
// Save registry to sql
int inter_accreg_tosql(uint32 account_id, uint32 char_id, struct accreg* reg, int type)
{
	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'", schema_config.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'", schema_config.reg_db, account_id) )
				Sql_ShowDebug(sql_handle);
			char_id = 0;
			break;
		case 1: //Account2 Reg
			ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
			return 0;
		default:
			ShowError("inter_accreg_tosql: Invalid type %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 ", schema_config.reg_db);

	for( i = 0; i < reg->reg_num; ++i ) {
		struct global_reg* r = &reg->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;
}
Exemple #2
0
/**
 * Handles save reg data from map server and distributes accordingly.
 *
 * @param val either str or int, depending on type
 * @param type false when int, true otherwise
 **/
void inter_savereg(uint32 account_id, uint32 char_id, const char *key, unsigned int index, intptr_t val, bool is_string)
{
	char esc_val[254*2+1];
	char esc_key[32*2+1];

	Sql_EscapeString(sql_handle, esc_key, key);
	if( is_string && val ) {
		Sql_EscapeString(sql_handle, esc_val, (char*)val);
	}
	if( key[0] == '#' && key[1] == '#' ) { // global account reg
		if( session_isValid(login_fd) )
			chlogif_send_global_accreg(key,index,val,is_string);
		else {
			ShowError("Login server unavailable, can't perform update on '%s' variable for AID:%d CID:%d\n",key,account_id,char_id);
		}
	} else if ( key[0] == '#' ) { // local account reg
		if( is_string ) {
			if( val ) {
				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", schema_config.acc_reg_str_table, account_id, esc_key, index, esc_val) )
					Sql_ShowDebug(sql_handle);
			} else {
				if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.acc_reg_str_table, account_id, esc_key, index) )
					Sql_ShowDebug(sql_handle);
			}
		} else {
			if( val ) {
				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", schema_config.acc_reg_num_table, account_id, esc_key, index, (int)val) )
					Sql_ShowDebug(sql_handle);
			} else {
				if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.acc_reg_num_table, account_id, esc_key, index) )
					Sql_ShowDebug(sql_handle);
			}
		}
	} else { /* char reg */
		if( is_string ) {
			if( val ) {
				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", schema_config.char_reg_str_table, char_id, esc_key, index, esc_val) )
					Sql_ShowDebug(sql_handle);
			} else {
				if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.char_reg_str_table, char_id, esc_key, index) )
					Sql_ShowDebug(sql_handle);
			}
		} else {
			if( val ) {
				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", schema_config.char_reg_num_table, char_id, esc_key, index, (int)val) )
					Sql_ShowDebug(sql_handle);
			} else {
				if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", schema_config.char_reg_num_table, char_id, esc_key, index) )
					Sql_ShowDebug(sql_handle);
			}
		}
	}
}
Exemple #3
0
/**
 * Retrieve data from db and store it in the provided data structure.
 *  Doesn't actually retrieve data yet: escapes and checks userid, then transforms it to accid for fetching.
 *  Filled data structure is done by delegation to account_db_sql_load_num.
 * @param self: pointer to db
 * @param acc: pointer of mmo_account to fill
 * @param userid: name of user account
 * @return true if successful, false if something has failed
 */
static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid) {
	AccountDB_SQL* db = (AccountDB_SQL*)self;
	Sql* sql_handle = db->accounts;
	char esc_userid[2*NAME_LENGTH+1];
	uint32 account_id;
	char* data;

	Sql_EscapeString(sql_handle, esc_userid, userid);

	// get the list of account IDs for this user ID
	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `userid`= %s '%s'",
		db->account_db, (db->case_sensitive ? "BINARY" : ""), esc_userid) )
	{
		Sql_ShowDebug(sql_handle);
		return false;
	}

	if( Sql_NumRows(sql_handle) > 1 )
	{// serious problem - duplicit account
		ShowError("account_db_sql_load_str: multiple accounts found when retrieving data for account '%s'!\n", userid);
		Sql_FreeResult(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);
	account_id = atoi(data);

	return account_db_sql_load_num(self, acc, account_id);
}
Exemple #4
0
/* [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 `%s` WHERE `name` LIKE '%s' LIMIT 10", char_db, query_esq)
			|| Sql_NumRows(sql_handle) == 0) {
			if(Sql_NumRows(sql_handle) == 0) {
				inter_msg_to_fd(fd, u_fd, aid, read_message("Source.char.inter_parse_accinfo_s1"), query);
			} else {
				Sql_ShowDebug(sql_handle);
				inter_msg_to_fd(fd, u_fd, aid, read_message("Source.char.inter_parse_accinfo_s2"));
			}
			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_msg_to_fd(fd, u_fd, aid, read_message("Source.char.inter_parse_accinfo_s3"), (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_msg_to_fd(fd, u_fd, aid, read_message("Source.char.inter_parse_accinfo_s4"), 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 */
	/* and we will send packet with account id to login server asking for account info */
	if(account_id) {
		mapif_on_parse_accinfo(account_id, u_fd, aid, castergroup, fd);
	}

	return;
}
Exemple #5
0
/**
 * Receive a account_info request from map-serv
 * @author : [Dekamaster/Nightroad]
 * @param fd : map-serv link
 */
void mapif_parse_accinfo(int fd) {
	int u_fd = RFIFOL(fd,2), u_aid = RFIFOL(fd,6), u_group = RFIFOL(fd,10);
	char type= RFIFOB(fd,14);
	char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1];
	uint32 account_id = 0;
	char *data;

	safestrncpy(query, RFIFOCP(fd,15), 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 `%s` WHERE `name` LIKE '%s' LIMIT 10", schema_config.char_db, query_esq)
				|| Sql_NumRows(sql_handle) == 0 ) {
			if( Sql_NumRows(sql_handle) == 0 ) {
				inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(212) ,query);
			} else {
				Sql_ShowDebug(sql_handle);
				inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
			}
			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, u_aid, (char *)msg_txt(214),(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, u_aid, (char *)msg_txt(215), 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 then ask login-server to fetch the `login` record */
	if (!account_id || chlogif_req_accinfo(fd, u_fd, u_aid, u_group, account_id, type) != 1) {
		inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
	}
	return;
}
Exemple #6
0
/**
 * Player setup a new shop
 * @param sd : player opening the shop
 * @param message : shop title
 * @param data : itemlist data \n
 *	data := {<index>.w <amount>.w <value>.l}[count]
 * @param count : number of different items
 * @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
 */
char vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
	int i, j;
	int vending_skill_lvl;
	char message_sql[MESSAGE_SIZE*2];
	
	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&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 (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(sd, 733), idb->jname);
			clif_displaymessage(sd->fd, msg);
			clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
			return 4;
		}

		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->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 == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){
		Sql_ShowDebug(mmysql_handle);
	}

	for( i = 0; i < count; i++ ) {
		if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`vending_id`,`index`,`cartinventory_id`,`amount`,`price`) VALUES( %d, %d, %d, %d, %d );", vending_items_db, sd->vender_id, i, sd->status.cart[sd->vending[i].index].id, sd->vending[i].amount, sd->vending[i].value ) != SQL_SUCCESS ){
			Sql_ShowDebug(mmysql_handle);
		}
	}

	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;
}
Exemple #7
0
/**
* Attempt to create new buying store
* @param sd
* @param zenylimit
* @param result
* @param storename
* @param *itemlist { <nameid>.W, <amount>.W, <price>.L }*
* @param count Number of item on the itemlist
* @return 0 If success, 1 - Cannot open, 2 - Manner penalty, 3 - Mapflag restiction, 4 - Cell restriction, 5 - Invalid count/result, 6 - Cannot give item, 7 - Will be overweight
*/
char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
{
	unsigned int i, weight, listidx;
	char message_sql[MESSAGE_SIZE*2];

	nullpo_retr(1, sd);

	if( !result || count == 0 )
	{// canceled, or no items
		return 5;
	}

	if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
	{// disabled or invalid input
		sd->buyingstore.slots = 0;
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
		return 1;
	}

	if( !pc_can_give_items(sd) )
	{// custom: GM is not allowed to buy (give zeny)
		sd->buyingstore.slots = 0;
		clif_displaymessage(sd->fd, msg_txt(sd,246));
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
		return 6;
	}

	if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
	{// custom: mute limitation
		return 2;
	}

	if( map[sd->bl.m].flag.novending )
	{// custom: no vending maps
		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
		return 3;
	}

	if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
	{// custom: no vending cells
		clif_displaymessage(sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
		return 4;
	}

	weight = sd->weight;

	// check item list
	for( i = 0; i < count; i++ )
	{// itemlist: <name id>.W <amount>.W <price>.L
		unsigned short nameid, amount;
		int price, idx;
		struct item_data* id;

		nameid = RBUFW(itemlist,i*8+0);
		amount = RBUFW(itemlist,i*8+2);
		price  = RBUFL(itemlist,i*8+4);

		if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 )
		{// invalid input
			break;
		}

		if( price <= 0 || price > BUYINGSTORE_MAX_PRICE )
		{// invalid price: unlike vending, items cannot be bought at 0 Zeny
			break;
		}

		if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_get_group_level(sd), pc_get_group_level(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 )
		{// restrictions: allowed, no character-bound items and at least one must be owned
			break;
		}

		if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT )
		{// too many items of same kind
			break;
		}

		if( i )
		{// duplicate check. as the client does this too, only malicious intent should be caught here
			ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid );
			if( listidx != i )
			{// duplicate
				ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id);
				break;
			}
		}

		weight+= id->weight*amount;
		sd->buyingstore.items[i].nameid = nameid;
		sd->buyingstore.items[i].amount = amount;
		sd->buyingstore.items[i].price  = price;
	}

	if( i != count )
	{// invalid item/amount/price
		sd->buyingstore.slots = 0;
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
		return 5;
	}

	if( (sd->max_weight*90)/100 < weight )
	{// not able to carry all wanted items without getting overweight (90%)
		sd->buyingstore.slots = 0;
		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight);
		return 7;
	}

	// success
	sd->state.buyingstore = true;
	sd->buyer_id = buyingstore_getuid();
	sd->buyingstore.zenylimit = zenylimit;
	sd->buyingstore.slots = i;  // store actual amount of items
	safestrncpy(sd->message, storename, sizeof(sd->message));

	Sql_EscapeString( mmysql_handle, message_sql, sd->message );

	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`limit`,`autotrade`, `body_direction`, `head_direction`, `sit`) "
		"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, %d, '%d', '%d', '%d' );",
		buyingstores_db, sd->buyer_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->buyingstore.zenylimit, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){
		Sql_ShowDebug(mmysql_handle);
	}

	for( i = 0; i < sd->buyingstore.slots; i++ ){
		if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`buyingstore_id`,`index`,`item_id`,`amount`,`price`) VALUES( %d, %d, %hu, %d, %d );", buyingstore_items_db, sd->buyer_id, i, sd->buyingstore.items[i].nameid, sd->buyingstore.items[i].amount, sd->buyingstore.items[i].price ) != SQL_SUCCESS ){
			Sql_ShowDebug(mmysql_handle);
		}
	}

	clif_buyingstore_myitemlist(sd);
	clif_buyingstore_entry(sd);
	idb_put(buyingstore_db, sd->status.char_id, sd);

	return 0;
}
Exemple #8
0
/* [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, "No matches were found for your criteria, '%s'",query);
			} else {
				Sql_ShowDebug(sql_handle);
				inter_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it.");
			}
			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, "Your query returned the following %d results, please be more specific...",(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 | Level: %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,  "No account with ID '%d' was found.", account_id );
			} else {
				inter_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it.");
				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, "-- Account %d --", account_id );
		inter_to_fd(fd, u_fd, aid, "User: %s | GM Group: %d | State: %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, "Password: %s", user_pass );
		
		inter_to_fd(fd, u_fd, aid, "Account e-mail: %s", email);
		inter_to_fd(fd, u_fd, aid, "Last IP: %s (%s)", last_ip, geoip_getcountry(str2ip(last_ip)) );
		inter_to_fd(fd, u_fd, aid, "This user has logged %d times, the last time were at %s", logincount, lastlogin );
		inter_to_fd(fd, u_fd, aid, "-- Character Details --" );
		
		
		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,"This account doesn't have characters.");
				else {
					inter_to_fd(fd, u_fd, aid,"An error occured, bother your admin about it.");
					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 | Level: %d/%d | %s", char_num, char_id, name, job_name(class_), base_level, job_level, online?"On":"Off");
			}
		}
		Sql_FreeResult(sql_handle);
	}
	
	return;
}
Exemple #9
0
/**
 * 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, k, n;
	int vending_skill_lvl;
	char message_sql[MESSAGE_SIZE*2];
	int item_bad_price[MAX_VENDING];
	StringBuf buf;
	struct item_data *item;
	
	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, 0);

	// filter out invalid items
	i = k = 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;

		item = itemdb_search(sd->status.cart[index].nameid);

		if (item->value_buy_min > 0 && value > item->value_buy_min)
		{
			if (battle_config.vending_price_min_overflow  > 0 )
			{
				if (value > item->value_buy_min + (item->value_buy_min * (battle_config.vending_price_min_overflow / 10000.)))
				{
					item_bad_price[k++] = sd->status.cart[index].nameid;
					continue;
				}
			}
			else
			{
				item_bad_price[k++] = sd->status.cart[index].nameid;
				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 (sd->status.cart[sd->vending[i].index].id == 0) {
			char msg[256];

			snprintf(msg, 256, "äÍà·çÁ %s ÂѧäÁèä´éºÑ¹·Ö¡. ¡ÃسÒÍÍ¡à¢éÒãËÁè à¾×èÍãËéäÍà·çÁ·Ó¡ÒÃ૿ŧÃéÒ¹¤éÒ", item->jname);
			clif_displaymessage(sd->fd, msg);
			clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
			return 4;
		}

		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."

	for (n = 0; n < k; n++)
	{
		char msg[512];

		item = itemdb_search(item_bad_price[n]);
		
		if (battle_config.vending_price_min_overflow > 0)
			sprintf(msg, "%s µÑé§ÃÒ¤Ò¢ÒÂÊÙ§¡ÇèÒ·Õè NPC ÁÕ¢ÒÂÍÂÙèà¡Ô¹ %d%% ¨Ð¶Ù¡µÑ´ÍÍ¡¨Ò¡ÃÒ¡ÒÃà¾×èÍ»éͧ¡Ñ¹¡ÒÃâ¡è§ÃÒ¤Ò", item->jname, battle_config.vending_price_min_overflow/100);
		else
			sprintf(msg, "%s µÑé§ÃÒ¤Ò¢ÒÂÊÙ§¡ÇèÒ·Õè NPC ÁÕ¢ÒÂÍÂÙè ¨Ð¶Ù¡µÑ´ÍÍ¡¨Ò¡ÃÒ¡ÒÃà¾×èÍ»éͧ¡Ñ¹¡ÒÃâ¡è§ÃÒ¤Ò", item->jname);
		clif_displaymessage(sd->fd, msg);
	}

	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->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 == 0 ? '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;
}
Exemple #10
0
//--------------------------------------------------------
// 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->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;
}
Exemple #11
0
/* [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;
}
Exemple #12
0
/**
 * 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&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 || //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 = umin(value, (unsigned int)battle_config.vending_max_value);
		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( 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;
}