Exemple #1
0
/**
 * Player requesting to change map-serv
 * @param fd: wich fd to parse from
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_reqchangemapserv(int fd){
	if (RFIFOREST(fd) < 39)
		return 0;
	{
		int map_id, map_fd = -1;
		struct mmo_charstatus* char_data;
		struct mmo_charstatus char_dat;
		DBMap* char_db_ = char_get_chardb();

		map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
		if (map_id >= 0)
			map_fd = map_server[map_id].fd;
		//Char should just had been saved before this packet, so this should be safe. [Skotlex]
		char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
		if (char_data == NULL) {	//Really shouldn't happen.
			char_mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
			char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
		}

		if( runflag == CHARSERVER_ST_RUNNING &&
			session_isActive(map_fd) &&
			char_data )
		{	//Send the map server the auth of this player.
			struct online_char_data* data;
			struct auth_node* node;
			DBMap*  auth_db = char_get_authdb();
			DBMap* online_char_db = char_get_onlinedb();

			int aid = RFIFOL(fd,2);

			//Update the "last map" as this is where the player must be spawned on the new map server.
			char_data->last_point.map = RFIFOW(fd,18);
			char_data->last_point.x = RFIFOW(fd,20);
			char_data->last_point.y = RFIFOW(fd,22);
			char_data->sex = RFIFOB(fd,30);

			// create temporary auth entry
			CREATE(node, struct auth_node, 1);
			node->account_id = aid;
			node->char_id = RFIFOL(fd,14);
			node->login_id1 = RFIFOL(fd,6);
			node->login_id2 = RFIFOL(fd,10);
			node->sex = RFIFOB(fd,30);
			node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing)
			node->ip = ntohl(RFIFOL(fd,31));
			node->group_id = RFIFOL(fd,35);
			node->changing_mapservers = 1;
			idb_put(auth_db, aid, node);

			data = idb_ensure(online_char_db, aid, char_create_online_data);
			data->char_id = char_data->char_id;
			data->server = map_id; //Update server where char is.

			//Reply with an ack.
			chmapif_changemapserv_ack(fd,0);
		} else { //Reply with nak
			chmapif_changemapserv_ack(fd,1);
		}
		RFIFOSKIP(fd,39);
	}
Exemple #2
0
/** [Cydh]
* Find item(s) that will be obtained by player based on Item Group
* @param group_id: The group ID that will be gained by player
* @param nameid: The item that trigger this item group
* @return val: 0:success, 1:no sd, 2:invalid item group
*/
char itemdb_pc_get_itemgroup(uint16 group_id, struct map_session_data *sd) {
	uint16 i = 0;
	struct s_item_group_db *group;

	nullpo_retr(1,sd);
	
	if (!(group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id))) {
		ShowError("itemdb_pc_get_itemgroup: Invalid group id '%d' specified.\n",group_id);
		return 2;
	}
	
	// Get the 'must' item(s)
	if (group->must_qty) {
		for (i = 0; i < group->must_qty; i++)
			if (&group->must[i])
				itemdb_pc_get_itemgroup_sub(sd,&group->must[i]);
	}

	// Get the 'random' item each random group
	for (i = 0; i < MAX_ITEMGROUP_RANDGROUP; i++) {
		uint16 rand;
		if (!(&group->random[i]) || !group->random[i].data_qty) //Skip empty random group
			continue;
		rand = rnd()%group->random[i].data_qty;
		if (!(&group->random[i].data[rand]) || !group->random[i].data[rand].nameid)
			continue;
		itemdb_pc_get_itemgroup_sub(sd,&group->random[i].data[rand]);
	}

	return 0;
}
Exemple #3
0
/**
* Return a random group entry from Item Group
* @param group_id
* @param sub_group: 0 is 'must' item group, random groups start from 1 to MAX_ITEMGROUP_RANDGROUP+1
* @return Item group entry or NULL on fail
*/
struct s_item_group_entry *itemdb_get_randgroupitem(uint16 group_id, uint8 sub_group) {
	struct s_item_group_db *group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id);
	struct s_item_group_entry *list = NULL;
	uint16 qty = 0;

	if (!group) {
		ShowError("itemdb_get_randgroupitem: Invalid group id %d\n", group_id);
		return NULL;
	}
	if (sub_group > MAX_ITEMGROUP_RANDGROUP+1) {
		ShowError("itemdb_get_randgroupitem: Invalid sub_group %d\n", sub_group);
		return NULL;
	}
	if (sub_group == 0) {
		list = group->must;
		qty = group->must_qty;
	}
	else {
		list = group->random[sub_group-1].data;
		qty = group->random[sub_group-1].data_qty;
	}
	if (!qty) {
		ShowError("itemdb_get_randgroupitem: No item entries for group id %d and sub group %d\n", group_id, sub_group);
		return NULL;
	}
	return &list[rnd()%qty];
}
Exemple #4
0
/*==========================================
 * Searches for an instance name in the database
 *------------------------------------------*/
static struct instance_db *instance_searchname_db(const char *instance_name)
{
	uint16 id = instance_name2id(instance_name);

	if(!id)
		return NULL;
	return (struct instance_db *)uidb_get(InstanceDB, id);
}
Exemple #5
0
/*==========================================
 * Loads an item from the db. If not found, it will return the dummy item.
 * @param nameid
 * @return *item_data or *dummy_item if item not found
 *------------------------------------------*/
struct item_data* itemdb_search(unsigned short nameid) {
	struct item_data* id = NULL;
	if (nameid == dummy_item->nameid)
		id = dummy_item;
	else if (!(id = (struct item_data*)uidb_get(itemdb, nameid))) {
		ShowWarning("itemdb_search: Item ID %hu does not exists in the item_db. Using dummy data.\n", nameid);
		id = dummy_item;
	}
	return id;
}
Exemple #6
0
int classdb_path(int id) {
	struct class_data *db=NULL;
	
	db = uidb_get(class_db, id);
	
	if (db) {
		return db->path;
	} else {
		return 0;
	}
}
Exemple #7
0
int setInvalidCount(unsigned int ip) {
	int c=uidb_get(bf_lockout,ip);
	
	if(!c) {
		timer_insert(10*60*1000,10*60*1000,login_clear_lockout,ip,0);
	}

	uidb_put(bf_lockout,ip,c+1);
	
	return c+1;
}
Exemple #8
0
unsigned int classdb_level(int path,int lvl) {
	struct class_data *db=NULL;
	
	db=uidb_get(class_db,path);
	
	if (db) {
		return db->level[lvl];
	 } else {
		return 0;
	}
}
Exemple #9
0
//character selected, insert into auth db
void chrif_authok(int fd)
{
	struct auth_node *auth_data;
	TBL_PC* sd;
	//Check if we don't already have player data in our server
	//(prevents data that is to be saved from being overwritten by
	//this received status data if this auth is later successful) [Skotlex]
	if ((sd = map_id2sd(RFIFOL(fd, 4))) != NULL)
	{
		struct mmo_charstatus *status = (struct mmo_charstatus *)RFIFOP(fd, 20);
		//Auth check is because this could be the very same sd that is waiting char-server authorization.
		if (sd->state.auth && sd->status.char_id == status->char_id)
			return;
	}
	
	if ((auth_data =uidb_get(auth_db, RFIFOL(fd, 4))) != NULL)
	{	//Is the character already awaiting authorization?
		if (auth_data->sd)
		{
			//First, check to see if the session data still exists (avoid dangling pointers)
			if(session[auth_data->fd] && session[auth_data->fd]->session_data == auth_data->sd)
			{	
				if (auth_data->char_dat == NULL &&
					auth_data->account_id == RFIFOL(fd, 4) &&
					auth_data->login_id1 == RFIFOL(fd, 8))
				{ //Auth Ok
					pc_authok(auth_data->sd, RFIFOL(fd, 16), RFIFOL(fd, 12), (struct mmo_charstatus*)RFIFOP(fd, 20));
				} else { //Auth Failed
					pc_authfail(auth_data->sd);
					chrif_char_offline(auth_data->sd); //Set him offline, the char server likely has it set as online already.
				}
			} //else: Character no longer exists, just go through.
		}
		//Delete the data of this node...
		if (auth_data->char_dat)
			aFree (auth_data->char_dat);
		uidb_remove(auth_db, RFIFOL(fd, 4));
		return;
	}
	// Awaiting for client to connect.
	auth_data = (struct auth_node *)aCalloc(1,sizeof(struct auth_node));
	auth_data->char_dat = (struct mmo_charstatus *) aCalloc(1,sizeof(struct mmo_charstatus));

	auth_data->account_id=RFIFOL(fd, 4);
	auth_data->login_id1=RFIFOL(fd, 8);
	auth_data->connect_until_time=RFIFOL(fd, 12);
	auth_data->login_id2=RFIFOL(fd, 16);
	memcpy(auth_data->char_dat,RFIFOP(fd, 20),sizeof(struct mmo_charstatus));
	auth_data->node_created=gettick();
	uidb_put(auth_db, RFIFOL(fd, 4), auth_data);
}
Exemple #10
0
struct creation_data* createdb_search(int id) {
	static struct creation_data *db=NULL;
	if (db && db->id == id)
		return db;

	db = uidb_get(create_db, id);
	if (db)
		return db;

	CALLOC(db, struct creation_data, 1);
	uidb_put(create_db, id, db);
	db->id = id;
	//strcpy(db->name, "??");

	return db;
}
Exemple #11
0
struct class_data* classdb_search(int id) {
	static struct class_data *db=NULL;
	if (db && db->id == id)
		return db;

	db = uidb_get(class_db, id);
	if (db)
		return db;
	
	CALLOC(db, struct class_data, 1);
	uidb_put(class_db, id, db);
	db->id = id;
	db->chat=0;
	strcpy(db->rank0,"??");
	//strcpy(db->rank_name[0], "??");

	return db;
}
Exemple #12
0
/**
* Return a random item id from group. (takes into account % chance giving/tot group)
* NOTE: Sub group 0 will be set to default 1, since 0 isn't random group
* @param group_id
* @param sub_group: Default is 1
* @return nameid
*/
unsigned short itemdb_searchrandomid(uint16 group_id, uint8 sub_group)
{
	struct s_item_group_db *group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id);
	if (sub_group)
		sub_group -= 1;
	if (!group) {
		ShowError("itemdb_searchrandomid: Invalid group id %d\n", group_id);
		return UNKNOWN_ITEM_ID;
	}
	if (sub_group > MAX_ITEMGROUP_RANDGROUP) {
		ShowError("itemdb_searchrandomid: Invalid sub_group %d\n", sub_group+1);
		return UNKNOWN_ITEM_ID;
	}
	if (&group->random[sub_group] && group->random[sub_group].data_qty)
		return group->random[sub_group].data[rand()%group->random[sub_group].data_qty].nameid;

	ShowError("itemdb_searchrandomid: No item entries for group id %d and sub group %d\n", group_id, sub_group+1);
	return UNKNOWN_ITEM_ID;
}
Exemple #13
0
char *classdb_name(int id,int a) {
	struct class_data *db=NULL;
	
	db = uidb_get(class_db, id);
	
	switch(a) {
	case 0:
	  return db->rank0;
	case 1:
	  return db->rank1;
	case 2:
	  return db->rank2;
	case 3:
	  return db->rank3;
	case 4:
	  return db->rank4;
	case 5:
	  return db->rank5;
	case 6:
	  return db->rank6;
	case 7:
	  return db->rank7;
	case 8:
	  return db->rank8;
	case 9:
	  return db->rank9;
	case 10:
	  return db->rank10;
	case 11:
	  return db->rank11;
	case 12:
	  return db->rank12;
	case 13:
	  return db->rank13;
	case 14:
	  return db->rank14;
	case 15:
	  return db->rank15;
	default:
	  return db->rank0;
	}
}
Exemple #14
0
/** [Cydh]
* Return a number of item's amount that will be obtained for 'getrandgroupitem id,1;'
* NOTE: Sub group 0 will be set to default 1, since 0 isn't random group
* @param group_id
* @param sub_group
* @param nameid: The target item will be found
* @return amount
*/
uint16 itemdb_get_randgroupitem_count(uint16 group_id, uint8 sub_group, unsigned short nameid) {
	uint16 i, amt = 1;
	struct s_item_group_db *group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id);
	
	if (sub_group)
		sub_group -= 1;
	if (!group) {
		ShowError("itemdb_get_randgroupitem_count: Invalid group id %d\n", group_id);
		return amt;
	}
	if (sub_group > MAX_ITEMGROUP_RANDGROUP) {
		ShowError("itemdb_get_randgroupitem_count: Invalid sub_group id %d\n", group_id+1);
		return amt;
	}
	if (!(&group->random[sub_group]) || !group->random[sub_group].data_qty)
		return amt;
	for (i = 0; i < group->random[sub_group].data_qty; i++) {
		if (group->random[sub_group].data[i].nameid == nameid)
			return group->random[sub_group].data[i].amount;
	}
	return amt;
}
Exemple #15
0
/*==========================================
 * Read the instance_db.txt file
 *------------------------------------------*/
static bool instance_readdb_sub(char *str[], int columns, int current)
{
	uint8 i;
	int id = atoi(str[0]);
	struct instance_db *db;
	bool isNew = false, defined = false;

	if(!id || id >  USHRT_MAX) {
		ShowError("instance_readdb_sub: Cannot add instance with ID '%d'. Valid ID is 1 ~ %d.\n", id, USHRT_MAX);
		return false;
	}

	if(mapindex_name2id(str[3]) == 0) {
		ShowError("instance_readdb_sub: Invalid map '%s' as entrance map.\n", str[3]);
		return false;
	}

	if(!(db = (struct instance_db *)uidb_get(InstanceDB, id))) {
		CREATE(db, struct instance_db, 1);
		db->id = id;
		db->name = StringBuf_Malloc();
		db->enter.mapname = StringBuf_Malloc();
		isNew = true;
	} else {
Exemple #16
0
/*==========================================
 * Searches for an instance ID in the database
 *------------------------------------------*/
static struct instance_db *instance_searchtype_db(unsigned short instance_id)
{
	return (struct instance_db *)uidb_get(InstanceDB, instance_id);
}
Exemple #17
0
int getInvalidCount(unsigned int ip) {
	int c=uidb_get(bf_lockout,ip);
	return c;
}
Exemple #18
0
struct creation_data* createdb_searchexist(int id) {
	struct creation_data *db=NULL;
	db = uidb_get(create_db, id);
	return db;
}
Exemple #19
0
/** Read item group data
* Structure: GroupID,ItemID,Rate{,Amount,isMust,isAnnounced,Duration,GUID,isBound,isNamed}
*/
static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
{
	FILE *fp;
	int ln = 0, entries = 0;
	char line[1024];

	if ((fp=fopen(filename,"r")) == NULL) {
		if(silent == 0) ShowError("Can't read %s\n", filename);
		return;
	}
	
	while (fgets(line,sizeof(line),fp)) {
		DBData data;
		int group_id = -1;
		unsigned int j, prob = 1;
		uint8 rand_group = 1;
		char *str[10], *p;
		struct s_item_group_random *random = NULL;
		struct s_item_group_db *group = NULL;
		struct s_item_group_entry entry;
		bool found = false;

		ln++;
		if (line[0] == '/' && line[1] == '/')
			continue;
		if (strstr(line,"import")) {
			char w1[16], w2[64];

			if (sscanf(line,"%15[^:]: %63[^\r\n]",w1,w2) == 2 &&
				strcmpi(w1,"import") == 0)
			{
				itemdb_read_itemgroup_sub(w2, 0);
				continue;
			}
		}
		memset(str,0,sizeof(str));
		for (j = 0, p = line; j < 9 && p;j++) {
			str[j] = p;
			p = strchr(p,',');
			if (p) *p++=0;
		}
		if (str[0] == NULL) //Empty Group ID
			continue;
		if (j < 3) {
			if (j > 1) // Or else it barks on blank lines...
				ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln);
			continue;
		}

		memset(&entry, 0, sizeof(entry));
		entry.amount = 1;
		entry.bound = BOUND_NONE;

		// Checking group_id
		trim(str[0]);
		if (ISDIGIT(str[0][0]))
			group_id = atoi(str[0]);
		else // Try reads group id by const
			script_get_constant(trim(str[0]), &group_id);

		if (group_id < 0) {
			ShowWarning("itemdb_read_itemgroup: Invalid Group ID '%s' (%s:%d)\n", str[0], filename, ln);
			continue;
		}

		// Remove from DB
		if (strcmpi(str[1], "clear") == 0 && itemdb_group->remove(itemdb_group, db_ui2key(group_id), &data)) {
			itemdb_group_free(db_ui2key(group_id), &data, 0);
			ShowNotice("Item Group '%s' has been cleared.\n", str[0]);
			continue;
		}

		// Checking sub group
		prob = atoi(str[2]);
		if (str[4] != NULL)
			rand_group = atoi(str[4]);
		if (rand_group < 0 || rand_group > MAX_ITEMGROUP_RANDGROUP) {
			ShowWarning("itemdb_read_itemgroup: Invalid sub group '%d' for group '%s' in %s:%d\n", rand_group, str[0], filename, ln);
			continue;
		}

		if (rand_group != 0 && prob < 1) {
			ShowWarning("itemdb_read_itemgroup: Random item must has probability. Group '%s' in %s:%d\n", str[0], filename, ln);
			continue;
		}

		// Checking item
		trim(str[1]);
		if (ISDIGIT(str[1][0]) && ISDIGIT(str[1][1]) && itemdb_exists((entry.nameid = atoi(str[1]))))
			found = true;
		else {
			struct item_data *id = itemdb_searchname(str[1]);
			if (id) {
				entry.nameid = id->nameid;
				found = true;
			}
		}

		if (!found) {
			ShowWarning("itemdb_read_itemgroup: Non-existant item '%s' in %s:%d\n", str[1], filename, ln);
			continue;
		}

		if (str[3] != NULL) entry.amount = cap_value(atoi(str[3]),1,MAX_AMOUNT);
		if (str[5] != NULL) entry.isAnnounced= atoi(str[5]);
		if (str[6] != NULL) entry.duration = cap_value(atoi(str[6]),0,UINT16_MAX);
#ifdef ENABLE_ITEM_GUID
		if (str[7] != NULL) entry.GUID = atoi(str[7]);
#endif
		if (str[8] != NULL) entry.bound = cap_value(atoi(str[8]),BOUND_NONE,BOUND_MAX-1);
		if (str[9] != NULL) entry.isNamed = atoi(str[9]);

		if (!(group = (struct s_item_group_db *) uidb_get(itemdb_group, group_id))) {
			CREATE(group, struct s_item_group_db, 1);
			group->id = group_id;
			uidb_put(itemdb_group, group->id, group);
		}

		// Must item (rand_group == 0), place it here
		if (!rand_group) {
			RECREATE(group->must, struct s_item_group_entry, group->must_qty+1);
			group->must[group->must_qty++] = entry;

			// If 'must' item isn't set as random item, skip the next process
			if (!prob) {
				entries++;
				continue;
			}
			rand_group = 0;
		}
Exemple #20
0
struct class_data* classdb_searchexist(int id) {
	struct class_data *db=NULL;
	
	db = uidb_get(class_db, id);
	return db;
}
Exemple #21
0
/**
* Open vending for Autotrader
* @param sd Player as autotrader
*/
void vending_reopen( struct map_session_data* sd )
{
	struct s_autotrader *at = NULL;
	int8 fail = -1;

	nullpo_retv(sd);

	// Open vending for this autotrader
	if ((at = uidb_get(vending_autotrader_db, sd->status.char_id)) && at->count && at->entries) {
		uint8 *data, *p;
		uint16 j, count;

		// Init vending data for autotrader
		CREATE(data, uint8, at->count * 8);

		for (j = 0, p = data, count = at->count; j < at->count; j++) {
			struct s_autotrade_entry *entry = at->entries[j];
			uint16 *index = (uint16*)(p + 0);
			uint16 *amount = (uint16*)(p + 2);
			uint32 *value = (uint32*)(p + 4);

			// Find item position in cart
			ARR_FIND(0, MAX_CART, entry->index, sd->status.cart[entry->index].id == entry->cartinventory_id);

			if (entry->index == MAX_CART) {
				count--;
				continue;
			}

			*index = entry->index + 2;
			*amount = itemdb_isstackable(sd->status.cart[entry->index].nameid) ? entry->amount : 1;
			*value = entry->price;

			p += 8;
		}

		sd->state.prevend = 1; // Set him into a hacked prevend state
		sd->state.autotrade = 1;

		// Make sure abort all NPCs
		npc_event_dequeue(sd);
		pc_cleareventtimer(sd);

		// Open the vending again
		if( (fail = vending_openvending(sd, at->title, data, count, at)) == 0 ) {
			// Make vendor look perfect
			pc_setdir(sd, at->dir, at->head_dir);
			clif_changed_dir(&sd->bl, AREA_WOS);
			if( at->sit ) {
				pc_setsit(sd);
				skill_sit(sd, 1);
				clif_sitting(&sd->bl);
			}

			// Immediate save
			chrif_save(sd, 3);

			ShowInfo("Vending loaded for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items at "CL_WHITE"%s (%d,%d)"CL_RESET"\n",
				sd->status.name, count, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y);
		}
		aFree(data);
	}

	if (at) {
		vending_autotrader_remove(at, true);
		if (db_size(vending_autotrader_db) == 0)
			vending_autotrader_db->clear(vending_autotrader_db, vending_autotrader_free);
	}

	if (fail != 0) {
		ShowError("vending_reopen: (Error:%d) Load failed for autotrader '"CL_WHITE"%s"CL_RESET"' (CID=%/AID=%d)\n", fail, sd->status.name, sd->status.char_id, sd->status.account_id);
		map_quit(sd);
	}
}
Exemple #22
0
/** Searches for the item_data. Use this to check if item exists or not.
* @param nameid
* @return *item_data if item is exist, or NULL if not
*/
struct item_data* itemdb_exists(unsigned short nameid) {
	return ((struct item_data*)uidb_get(itemdb,nameid));
}
Exemple #23
0
/**
* Check if item group exists
* @param group_id
* @return NULL if not exist, or s_item_group_db *
*/
struct s_item_group_db *itemdb_group_exists(unsigned short group_id) {
	return (struct s_item_group_db *)uidb_get(itemdb_group, group_id);
}
Exemple #24
0
/**
* Open buyingstore for Autotrader
* @param sd Player as autotrader
*/
void buyingstore_reopen( struct map_session_data* sd ){
	struct s_autotrader *at = NULL;
	int8 fail = -1;

	nullpo_retv(sd);

	// Ready to open buyingstore for this char
	if ((at = (struct s_autotrader *)uidb_get(buyingstore_autotrader_db, sd->status.char_id)) && at->count && at->entries) {
		uint8 *data, *p;
		uint16 j, count;

		// Init buyingstore data for autotrader
		CREATE(data, uint8, at->count * 8);

		for (j = 0, p = data, count = at->count; j < at->count; j++) {
			struct s_autotrade_entry *entry = at->entries[j];
			unsigned short *item_id = (uint16*)(p + 0);
			uint16 *amount = (uint16*)(p + 2);
			uint32 *price = (uint32*)(p + 4);

			*item_id = entry->item_id;
			*amount = entry->amount;
			*price = entry->price;

			p += 8;
		}

		sd->state.autotrade = 1;

		// Make sure abort all NPCs
		npc_event_dequeue(sd);
		pc_cleareventtimer(sd);

		// Open the buyingstore again
		if( (fail = buyingstore_setup( sd, (unsigned char)at->count )) == 0 &&
			(fail = buyingstore_create( sd, at->limit, 1, at->title, data, at->count, at )) == 0 )
		{
			// Make buyer look perfect
			pc_setdir(sd, at->dir, at->head_dir);
			clif_changed_dir(&sd->bl, AREA_WOS);
			if( at->sit ) {
				pc_setsit(sd);
				skill_sit(sd, 1);
				clif_sitting(&sd->bl);
			}

			// Immediate save
			chrif_save(sd, CSAVE_AUTOTRADE);

			ShowInfo("Buyingstore loaded for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items at "CL_WHITE"%s (%d,%d)"CL_RESET"\n",
				sd->status.name, count, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y);
		}
		aFree(data);
	}

	if (at) {
		buyingstore_autotrader_remove(at, true);
		if (db_size(buyingstore_autotrader_db) == 0)
			buyingstore_autotrader_db->clear(buyingstore_autotrader_db, buyingstore_autotrader_free);
	}

	if (fail != 0) {
		ShowError("buyingstore_reopen: (Error:%d) Load failed for autotrader '"CL_WHITE"%s"CL_RESET"' (CID=%/AID=%d)\n", fail, sd->status.name, sd->status.char_id, sd->status.account_id);
		map_quit(sd);
	}
}
Exemple #25
0
/**
* Check if combo exists
* @param combo_id
* @return NULL if not exist, or struct item_combo*
*/
struct item_combo *itemdb_combo_exists(unsigned short combo_id) {
	return (struct item_combo *)uidb_get(itemdb_combo, combo_id);
}