예제 #1
0
파일: itemdb.c 프로젝트: icxbb-xx/trunk
/** [Cydh]
 * Gives item(s) to the player based on item group
 * @param sd: Player that obtains item from item group
 * @param group_id: The group ID of item that obtained by player
 * @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx]
*/
static void itemdb_pc_get_itemgroup_sub(struct map_session_data *sd, uint16 group_id, struct s_item_group *group) {
	uint16 i;
	struct item tmp;

	nullpo_retv(group);

	memset(&tmp, 0, sizeof(tmp));

	tmp.nameid = group->nameid;
	tmp.amount = (itemdb_isstackable(group->nameid)) ? group->amount : 1;
	tmp.bound = group->bound;
	tmp.identify = 1;
	tmp.expire_time = (group->duration) ? (unsigned int)(time(NULL) + group->duration * 60) : 0;
	if (group->isNamed) {
		tmp.card[0] = itemdb_isequip(group->nameid) ? CARD0_FORGE : CARD0_CREATE;
		tmp.card[1] = 0;
		tmp.card[2] = GetWord(sd->status.char_id, 0);
		tmp.card[3] = GetWord(sd->status.char_id, 1);
	}
	//Do loop for non-stackable item
	for (i = 0; i < group->amount; i++) {
		int flag;

		if ((flag = pc_additem(sd,&tmp,tmp.amount,LOG_TYPE_SCRIPT)))
			clif_additem(sd,0,0,flag);
		else if (!flag && group->isAnnounced) {
			char output[CHAT_SIZE_MAX];

			sprintf(output, msg_txt(717), sd->status.name, itemdb_jname(group->nameid), itemdb_jname(sd->itemid));
			clif_broadcast(&sd->bl, output,strlen(output), 0, ALL_CLIENT);
		}
		if (itemdb_isstackable(group->nameid))
			break;
	}
}
예제 #2
0
/*==========================================
 * Request a shop's item list
 *------------------------------------------*/
void vending_vendinglistreq(struct map_session_data* sd, int id)
{
	struct map_session_data* vsd;
	nullpo_retv(sd);

	if( (vsd = map_id2sd(id)) == NULL )
		return;
	if( !vsd->state.vending )
		return; // not vending

	if ( !pc_can_give_items(pc_isGM(sd)) || !pc_can_give_items(pc_isGM(vsd)) ) //check if both GMs are allowed to trade
	{	// GM is not allowed to trade
		clif_displaymessage(sd->fd, msg_txt(246));
		return;
	} 

	sd->vended_id = vsd->vender_id;  // register vending uid
	if( battle_config.vending_zeny_id && vsd->vend_coin )
	{ // Extended Vending System
		char output[256];
		sprintf(output,msg_txt(914),itemdb_jname(vsd->vend_coin));
		clif_displaymessage(sd->fd,output);
	}

	clif_vendinglist(sd, id, vsd->vending);
}
예제 #3
0
/** [Cydh]
* Gives item(s) to the player based on item group
* @param sd: Player that obtains item from item group
* @param group_id: The group ID of item that obtained by player
* @param *group: struct s_item_group from itemgroup_db[group_id].random[idx] or itemgroup_db[group_id].must[sub_group][idx]
*/
static void itemdb_pc_get_itemgroup_sub(struct map_session_data *sd, struct s_item_group_entry *data) {
	uint16 i;
	struct item tmp;

	nullpo_retv(data);

	memset(&tmp, 0, sizeof(tmp));

	tmp.nameid = data->nameid;
	tmp.amount = (itemdb_isstackable(data->nameid)) ? data->amount : 1;
	tmp.bound = data->bound;
	tmp.identify = 1;
	tmp.expire_time = (data->duration) ? (unsigned int)(time(NULL) + data->duration*60) : 0;
	if (data->isNamed) {
		tmp.card[0] = itemdb_isequip(data->nameid) ? CARD0_FORGE : CARD0_CREATE;
		tmp.card[1] = 0;
		tmp.card[2] = GetWord(sd->status.char_id, 0);
		tmp.card[3] = GetWord(sd->status.char_id, 1);
	}
	// Do loop for non-stackable item
	for (i = 0; i < data->amount; i++) {
		char flag = 0;
#ifdef ENABLE_ITEM_GUID
		tmp.unique_id = data->GUID ? pc_generate_unique_id(sd) : 0; // Generate UID
#endif
		if ((flag = pc_additem(sd, &tmp, tmp.amount, LOG_TYPE_SCRIPT)))
			clif_additem(sd, 0, 0, flag);
		else if (!flag && data->isAnnounced) {
			char output[CHAT_SIZE_MAX];
			sprintf(output, msg_txt(NULL, 717), sd->status.name, itemdb_jname(data->nameid), itemdb_jname(sd->itemid));

			//! TODO: Move this broadcast to proper packet
			intif_broadcast(output, strlen(output) + 1, BC_DEFAULT);
			//clif_broadcast_obtain_special_item();
		}
		if (itemdb_isstackable(data->nameid))
			break;
	}
}
예제 #4
0
파일: itemdb.c 프로젝트: Lilystar/Auriga
/*==========================================
 * アイテムの名前テーブルを読み込む
 *------------------------------------------
 */
static int itemdb_read_itemnametable(void)
{
	char *buf,*p;
	int s;

	buf = (char *)grfio_reads("data\\idnum2itemdisplaynametable.txt",&s);

	if(buf == NULL)
		return -1;

	buf[s] = 0;
	for(p=buf; p-buf<s; ) {
		int nameid;
		char buf2[64];

		if(sscanf(p,"%d#%63[^#]#",&nameid,buf2) == 2) {
			char *jname = itemdb_jname(nameid);
			buf2[47] = '\0';	// force \0 terminal

#ifdef ITEMDB_OVERRIDE_NAME_VERBOSE
			if(itemdb_exists(nameid) && strcmp(jname, buf2) != 0) {
				printf("[override] %d %s => %s\n", nameid, jname, buf2);
			}
#endif
			memcpy(jname,buf2,48);
		}

		p=strchr(p,'\n');
		if(!p) break;
		p++;
	}
	aFree(buf);
	printf("read data\\idnum2itemdisplaynametable.txt done.\n");

	return 0;
}
예제 #5
0
//Does party loot. first_charid holds the charid of the player who has time priority to take the item.
int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid)
{
	TBL_PC* target = NULL;
	int i;
	if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1)))
	{
		//item distribution to party members.
		if (battle_config.party_share_type&2)
		{	//Round Robin
			TBL_PC* psd;
			i = p->itemc;
			do {
				i++;
				if (i >= MAX_PARTY)
					i = 0;	// reset counter to 1st person in party so it'll stop when it reaches "itemc"

				if( (psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd)) )
					continue;
				
				if (pc_additem(psd,item_data,item_data->amount))
					continue; //Chosen char can't pick up loot.

				//Successful pick.
				p->itemc = i;
				target = psd;
				break;
			} while (i != p->itemc);
		}
		else
		{	//Random pick
			TBL_PC* psd[MAX_PARTY];
			int count = 0;
			//Collect pick candidates
			for (i = 0; i < MAX_PARTY; i++) {
				if( (psd[count] = p->data[i].sd) == NULL || psd[count]->bl.m != sd->bl.m || pc_isdead(psd[count]) || (battle_config.idle_no_share && pc_isidle(psd[count])) )
					continue;

				count++;
			}
			while (count > 0) { //Pick a random member.
				i = rand()%count;
				if (pc_additem(psd[i],item_data,item_data->amount))
				{	//Discard this receiver.
					psd[i] = psd[count-1];
					count--;
				} else { //Successful pick.
					target = psd[i];
					break;
				}
			}
		}
	}

	if (!target) { 
		target = sd; //Give it to the char that picked it up
		if ((i=pc_additem(sd,item_data,item_data->amount)))
			return i;
	}

	if(log_config.enable_logs&0x8) //Logs items, taken by (P)layers [Lupus]
		log_pick_pc(target, "P", item_data->nameid, item_data->amount, item_data);
	
	if(battle_config.party_show_share_picker && target != sd) {
		char output[80];
		sprintf(output, "%s acquired %s.",target->status.name, itemdb_jname(item_data->nameid));
		clif_disp_onlyself(sd,output,strlen(output));
	}
	return 0;
}
예제 #6
0
/*==========================================
 * Purchase item(s) from a shop
 *------------------------------------------*/
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);
	char output[256];

	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( !vsd->vend_coin || vsd->vend_coin == battle_config.vending_zeny_id )
		{ // Normal Vending - Zeny Option
			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;
			}
 		}
		else if( battle_config.vending_cash_id && vsd->vend_coin == battle_config.vending_cash_id )
		{ // Cash Shop
			if( z > (double)sd->cashPoints || z < 0. || z > (double)MAX_ZENY )
			{
				sprintf(output,msg_txt(915),itemdb_jname(vsd->vend_coin));
				clif_displaymessage(sd->fd,output);
				return;
			}
			if( z + (double)vsd->cashPoints > (double)MAX_ZENY && !battle_config.vending_over_max )
			{
				sprintf(output,msg_txt(916),itemdb_jname(vsd->vend_coin));
				clif_displaymessage(sd->fd,output);
				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 ADDITEM_EXIST:
			break;	//We'd add this item to the existing one (in buyers inventory)
		case ADDITEM_NEW:
			new_++;
			if (new_ > blank)
				return; //Buyer has no space in his inventory
			break;
		case ADDITEM_OVERAMOUNT:
			return; //too many items
		}
	}

	// Payments
	if( !vsd->vend_coin || vsd->vend_coin == battle_config.vending_zeny_id )
	{
		if( log_config.zeny > 0 )
			log_zeny(vsd, "V", sd, (int)z); //Logs (V)ending Zeny [Lupus]

		pc_payzeny(sd, (int)z);

		if( battle_config.vending_tax || (vsd->state.autotrade && battle_config.at_tax && !pc_isPremium(vsd)) )
			z -= z * ((battle_config.vending_tax + ((vsd->state.autotrade && !pc_isPremium(vsd)) ? battle_config.at_tax : 0)) / 10000.);

		pc_getzeny(vsd, (int)z);
	}
	else if( battle_config.vending_cash_id && vsd->vend_coin == battle_config.vending_cash_id )
	{
		pc_paycash(sd,(int)z,0);
		pc_getcash(vsd,(int)z,0);
	}
	else
	{
		if( z < 0. || (i = pc_search_inventory(sd,vsd->vend_coin)) < 0 || z > (double)sd->status.inventory[i].amount )
		{
			sprintf(output,msg_txt(915),itemdb_jname(vsd->vend_coin));
			clif_displaymessage(sd->fd,output);
			return;
		}

		switch( pc_checkadditem(vsd,vsd->vend_coin,(int)z) )
		{
		case ADDITEM_NEW:
			if( pc_inventoryblank(vsd) > 0 )
				break;
		case ADDITEM_OVERAMOUNT:
			sprintf(output,msg_txt(916),itemdb_jname(vsd->vend_coin));
			clif_displaymessage(sd->fd,output);
			return;
		}

		pc_additem(vsd,&sd->status.inventory[i],(int)z);
		pc_delitem(sd,i,(int)z,0,6);
	}
	for( i = 0; i < count; i++ )
	{
		short amount = *(uint16*)(data + 4*i + 0);
		short idx    = *(uint16*)(data + 4*i + 2);
		idx -= 2;

		//Logs sold (V)ending items [Lupus]
		if(log_config.enable_logs&0x4) {
			log_pick_pc(vsd, "V", vsd->status.cart[idx].nameid, -amount, &vsd->status.cart[idx], vsd->status.cart[idx].serial );
			log_pick_pc( sd, "V", vsd->status.cart[idx].nameid,  amount, &vsd->status.cart[idx], vsd->status.cart[idx].serial );
		}

		// vending item
		pc_additem(sd, &vsd->status.cart[idx], amount);
		vsd->vending[vend_list[i]].amount -= amount;
		pc_cart_delitem(vsd, idx, amount, 0);
		clif_vendingreport(vsd, idx, amount);

		//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: buyer and customer
	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?
		}
	}
}