瀏覽代碼

Bug fixes & misc:
- Follow up 7fd6776, correcting how to make player sit by autotrade persistance.
- Follow up 7fd6776, pc_setstand() does a check if player can stand or not.
- bugreport:9174, buyingstore_close() doesn't clear buyingstores data on table.
- Fixed "missing" buyingstore search (purchase type search) in searchstore, by adding DBMap *buyingstore_db.
- Added nullpo checks on some buyingstore.c functions.
- Added do_init_buyingstore() and do_final_buyingstore().
- Failing autotrader from pc_setpos(). (Since autotrade doesn't have 'fd'? FIXME later)

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh 10 年之前
父節點
當前提交
8a819403c1
共有 17 個文件被更改,包括 181 次插入114 次删除
  1. 4 4
      src/map/atcommand.c
  2. 6 3
      src/map/battle.c
  3. 62 21
      src/map/buyingstore.c
  4. 3 0
      src/map/buyingstore.h
  5. 5 11
      src/map/clif.c
  6. 7 2
      src/map/map.c
  7. 1 1
      src/map/map.h
  8. 5 5
      src/map/mob.c
  9. 28 12
      src/map/pc.c
  10. 3 3
      src/map/pc.h
  11. 13 13
      src/map/script.c
  12. 2 1
      src/map/searchstore.c
  13. 9 11
      src/map/skill.c
  14. 20 18
      src/map/status.c
  15. 3 3
      src/map/status.h
  16. 1 3
      src/map/unit.c
  17. 9 3
      src/map/vending.c

+ 4 - 4
src/map/atcommand.c

@@ -3545,7 +3545,7 @@ ACMD_FUNC(recallall)
 				count++;
 			else {
 				if (pc_isdead(pl_sd)) { //Wake them up
-					pc_setstand(pl_sd);
+					pc_setstand(pl_sd, true);
 					pc_setrestartvalue(pl_sd,1);
 				}
 				pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN);
@@ -5766,7 +5766,7 @@ ACMD_FUNC(autotrade) {
 			Sql_ShowDebug( mmysql_handle );
 		}
 	}else if( sd->state.buyingstore ){
-		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;", buyingstore_db, sd->buyer_id ) != SQL_SUCCESS ){
+		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;", buyingstores_db, sd->buyer_id ) != SQL_SUCCESS ){
 			Sql_ShowDebug( mmysql_handle );
 		}
 	}
@@ -5778,7 +5778,7 @@ ACMD_FUNC(autotrade) {
 
 	channel_pcquit(sd,0xF); //leave all chan
 	clif_authfail_fd(sd->fd, 15);
-	
+
 	chrif_save(sd,3);
 
 	return 0;
@@ -9532,7 +9532,7 @@ ACMD_FUNC(cloneequip) {
 	else {
 		int8 i;
 		for (i = 0; i < EQI_MAX; i++) {
-			int8 idx;
+			short idx;
 			char flag = 0;
 			struct item tmp_item;
 			if ((idx = pl_sd->equip_index[i]) < 0)

+ 6 - 3
src/map/battle.c

@@ -889,7 +889,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 			(flag&BF_LONG || sc->data[SC_SPURT])
 			&& rnd()%100 < 20)
 		{
-			if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge.
+			if (sd && pc_issit(sd)) pc_setstand(sd, true); //Stand it to dodge.
 			clif_skill_nodamage(bl,bl,TK_DODGE,1,1);
 			if (!sc->data[SC_COMBO])
 				sc_start4(src,bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000);
@@ -3556,7 +3556,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 			break;
 		case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] %
 			if (sd && skill_lv == 1) {
-				int index = sd->equip_index[EQI_HAND_L];
+				short index = sd->equip_index[EQI_HAND_L];
 
 				if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR)
 					skillratio += sd->inventory_data[index]->def * 10;
@@ -6379,6 +6379,9 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
 	struct weapon_data *wd;
 	int64 *damage;
 	int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp=0, sp=0, i;
+	if (!CHK_RACE(race) && !CHK_CLASS(class_))
+		return;
+
 	for (i = 0; i < 4; i++) {
 		//First two iterations: Right hand
 		if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
@@ -6538,7 +6541,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
 		if (sd->state.arrow_atk)
 		{
-			int index = sd->equip_index[EQI_AMMO];
+			short index = sd->equip_index[EQI_AMMO];
 			if (index < 0) {
 				clif_arrow_fail(sd,0);
 				return ATK_NONE;

+ 62 - 21
src/map/buyingstore.c

@@ -1,6 +1,7 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
+#include "../common/nullpo.h"
 #include "../common/cbasetypes.h"
 #include "../common/db.h"  // ARR_FIND
 #include "../common/malloc.h" // aMalloc, aFree
@@ -48,6 +49,11 @@ static void do_final_buyingstore_autotrade(void);
 #define BUYINGSTORE_MAX_PRICE 99990000
 #define BUYINGSTORE_MAX_AMOUNT 9999
 
+static DBMap *buyingstore_db;
+
+DBMap *buyingstore_getdb(void) {
+	return buyingstore_db;
+}
 
 /// failure constants for clif functions
 enum e_buyingstore_failure
@@ -80,6 +86,8 @@ static unsigned int buyingstore_getuid(void)
 * @return 0 If success, 1 - Cannot open, 2 - Manner penalty, 3 - Mapflag restiction, 4 - Cell restriction
 */
 char buyingstore_setup(struct map_session_data* sd, unsigned char slots){
+	nullpo_retr(1, sd);
+
 	if (!battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0) {
 		return 1;
 	}
@@ -128,6 +136,8 @@ char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 	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;
@@ -239,7 +249,7 @@ char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 
 	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' );",
-		buyingstore_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 ){
+		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);
 	}
 
@@ -251,30 +261,30 @@ char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 
 	clif_buyingstore_myitemlist(sd);
 	clif_buyingstore_entry(sd);
+	idb_put(buyingstore_db, sd->status.char_id, sd);
 
 	return 0;
 }
 
 /**
-* Close buying store
+* Close buying store and clear buying store data from tables
 * @param sd
 */
-void buyingstore_close(struct map_session_data* sd)
-{
-	if( sd->state.buyingstore )
-	{
-		if( !sd->state.autotrade ){
-			if( 
-				Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE buyingstore_id = %d;", buyingstore_items_db, sd->buyer_id ) != SQL_SUCCESS ||
-				Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `id` = %d;", buyingstore_db, sd->buyer_id ) != SQL_SUCCESS
-			){
-				Sql_ShowDebug(mmysql_handle);
-			}
+void buyingstore_close(struct map_session_data* sd) {
+	nullpo_retv(sd);
+
+	if( sd->state.buyingstore ) {
+		if( 
+			Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE buyingstore_id = %d;", buyingstore_items_db, sd->buyer_id ) != SQL_SUCCESS ||
+			Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `id` = %d;", buyingstores_db, sd->buyer_id ) != SQL_SUCCESS
+		) {
+			Sql_ShowDebug(mmysql_handle);
 		}
 
-		// invalidate data
 		sd->state.buyingstore = false;
+		sd->buyer_id = 0;
 		memset(&sd->buyingstore, 0, sizeof(sd->buyingstore));
+		idb_remove(buyingstore_db, sd->status.char_id);
 
 		// notify other players
 		clif_buyingstore_disappear_entry(sd);
@@ -290,6 +300,8 @@ void buyingstore_open(struct map_session_data* sd, int account_id)
 {
 	struct map_session_data* pl_sd;
 
+	nullpo_retv(sd);
+
 	if( !battle_config.feature_buying_store || pc_istrading(sd) )
 	{// not allowed to sell
 		return;
@@ -328,6 +340,8 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
 	unsigned int i, weight, listidx, k;
 	struct map_session_data* pl_sd;
 
+	nullpo_retv(sd);
+
 	if( count == 0 )
 	{// nothing to do
 		return;
@@ -490,7 +504,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
 	}
 	else
 	{// continue buying
-		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `limit` = %d WHERE `id` = %d;", buyingstore_db, pl_sd->buyingstore.zenylimit, pl_sd->buyer_id ) != SQL_SUCCESS ){
+		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `limit` = %d WHERE `id` = %d;", buyingstores_db, pl_sd->buyingstore.zenylimit, pl_sd->buyer_id ) != SQL_SUCCESS ){
 			Sql_ShowDebug( mmysql_handle );
 		}
 
@@ -513,6 +527,8 @@ bool buyingstore_search(struct map_session_data* sd, unsigned short nameid)
 {
 	unsigned int i;
 
+	nullpo_ret(sd);
+
 	if( !sd->state.buyingstore )
 	{// not buying
 		return false;
@@ -535,6 +551,8 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
 	unsigned int i, idx;
 	struct s_buyingstore_item* it;
 
+	nullpo_ret(sd);
+
 	if( !sd->state.buyingstore )
 	{// not buying
 		return true;
@@ -578,8 +596,10 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
 * @param sd Player as autotrader
 */
 void buyingstore_reopen( struct map_session_data* sd ){
+	nullpo_retv(sd);
+
 	// Ready to open buyingstore for this char
-	if ( sd && autotrader_count > 0 && autotraders){
+	if ( autotrader_count > 0 && autotraders){
 		uint16 i;
 		uint8 *data, *p, fail = 0;
 		uint16 j, count;
@@ -619,7 +639,7 @@ void buyingstore_reopen( struct map_session_data* sd ){
 			// Set him to autotrade
 			if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1, `body_direction` = '%d', `head_direction` = '%d', `sit` = '%d' "
 				"WHERE `id` = %d;",
-				buyingstore_db, autotraders[i]->dir, autotraders[i]->head_dir, autotraders[i]->sit, sd->buyer_id ) != SQL_SUCCESS )
+				buyingstores_db, autotraders[i]->dir, autotraders[i]->head_dir, autotraders[i]->sit, sd->buyer_id ) != SQL_SUCCESS )
 			{
 				Sql_ShowDebug( mmysql_handle );
 			}
@@ -627,8 +647,11 @@ void buyingstore_reopen( struct map_session_data* sd ){
 			// Make buyer look perfect
 			pc_setdir(sd, autotraders[i]->dir, autotraders[i]->head_dir);
 			clif_changed_dir(&sd->bl, AREA_WOS);
-			if( autotraders[i]->sit )
+			if( autotraders[i]->sit ) {
 				pc_setsit(sd);
+				skill_sit(sd, 1);
+				clif_sitting(&sd->bl);
+			}
 
 			// Immediate save
 			chrif_save(sd, 3);
@@ -662,7 +685,7 @@ void do_init_buyingstore_autotrade( void ) {
 			"FROM `%s` "
 			"WHERE `autotrade` = 1 AND `limit` > 0 AND (SELECT COUNT(`buyingstore_id`) FROM `%s` WHERE `buyingstore_id` = `id`) > 0 "
 			"ORDER BY `id`;",
-			buyingstore_db, buyingstore_items_db ) != SQL_SUCCESS )
+			buyingstores_db, buyingstore_items_db ) != SQL_SUCCESS )
 		{
 			Sql_ShowDebug(mmysql_handle);
 			return;
@@ -758,12 +781,12 @@ void do_init_buyingstore_autotrade( void ) {
 				Sql_FreeResult(mmysql_handle);
 			}
 
-			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
+			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' buyingstore autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
 		}
 	}
 
 	// Everything is loaded fine, their entries will be reinserted once they are loaded
-	if (Sql_Query( mmysql_handle, "DELETE FROM `%s`;", buyingstore_db ) != SQL_SUCCESS ||
+	if (Sql_Query( mmysql_handle, "DELETE FROM `%s`;", buyingstores_db ) != SQL_SUCCESS ||
 		Sql_Query( mmysql_handle, "DELETE FROM `%s`;", buyingstore_items_db ) != SQL_SUCCESS)
 	{
 		Sql_ShowDebug(mmysql_handle);
@@ -798,3 +821,21 @@ void do_final_buyingstore_autotrade(void) {
 		autotrader_count = 0;
 	}
 }
+
+/**
+ * Initialise the buyingstore module
+ * called in map::do_init
+ */
+void do_final_buyingstore(void) {
+	db_destroy(buyingstore_db);
+	do_final_buyingstore_autotrade();
+}
+
+/**
+ * Destory the buyingstore module
+ * called in map::do_final
+ */
+void do_init_buyingstore(void) {
+	buyingstore_db = idb_alloc(DB_OPT_BASE);
+	buyingstore_nextid = 0;
+}

+ 3 - 0
src/map/buyingstore.h

@@ -29,6 +29,9 @@ void buyingstore_open(struct map_session_data* sd, int account_id);
 void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count);
 bool buyingstore_search(struct map_session_data* sd, unsigned short nameid);
 bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s);
+DBMap *buyingstore_getdb(void);
+void do_final_buyingstore(void);
+void do_init_buyingstore(void);
 
 void do_init_buyingstore_autotrade( void );
 void buyingstore_reopen( struct map_session_data* sd );

+ 5 - 11
src/map/clif.c

@@ -10372,18 +10372,12 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 			return;
 		}
 
-		// Cannot stand yet
-		// TODO: Move to SCS_NOSTAND [Cydh]
-		if (&sd->sc && (sd->sc.data[SC_SITDOWN_FORCE] || sd->sc.data[SC_BANANA_BOMB_SITDOWN])) {
-			return;
+		if (pc_setstand(sd, false)) {
+			if (battle_config.idletime_option&IDLE_SIT)
+				sd->idletime = last_tick;
+			skill_sit(sd, 0);
+			clif_standing(&sd->bl);
 		}
-
-		if (battle_config.idletime_option&IDLE_SIT)
-			sd->idletime = last_tick;
-
-		pc_setstand(sd);
-		skill_sit(sd, 0);
-		clif_standing(&sd->bl);
 	break;
 	}
 }

+ 7 - 2
src/map/map.c

@@ -70,7 +70,7 @@ char map_server_db[32] = "ragnarok";
 Sql* mmysql_handle;
 
 int db_use_sqldbs = 0;
-char buyingstore_db[32] = "buyingstores";
+char buyingstores_db[32] = "buyingstores";
 char buyingstore_items_db[32] = "buyingstore_items";
 char item_db_db[32] = "item_db";
 char item_db2_db[32] = "item_db2";
@@ -1768,6 +1768,9 @@ int map_quit(struct map_session_data *sd) {
 	if (sd->state.vending)
 		idb_remove(vending_getdb(), sd->status.char_id);
 
+	if (sd->state.buyingstore)
+		idb_remove(buyingstore_getdb(), sd->status.char_id);
+
 	pc_damage_log_clear(sd,0);
 	party_booking_delete(sd); // Party Booking [Spiria]
 	pc_makesavestatus(sd);
@@ -3587,7 +3590,7 @@ int inter_config_read(char *cfgName)
 			continue;
 
 		if( strcmpi( w1, "buyingstore_db" ) == 0 )
-			strcpy( buyingstore_db, w2 );
+			strcpy( buyingstores_db, w2 );
 		else if( strcmpi( w1, "buyingstore_items_db" ) == 0 )
 			strcpy( buyingstore_items_db, w2 );
 		else if(strcmpi(w1,"item_db_db")==0)
@@ -3881,6 +3884,7 @@ void do_final(void)
 	do_final_cashshop();
 	do_final_channel(); //should be called after final guild
 	do_final_vending();
+	do_final_buyingstore();
 
 	map_db->destroy(map_db, map_db_final);
 
@@ -4191,6 +4195,7 @@ int do_init(int argc, char *argv[])
 	do_init_battleground();
 	do_init_duel();
 	do_init_vending();
+	do_init_buyingstore();
 
 	npc_event_do_oninit();	// Init npcs (OnInit)
 

+ 1 - 1
src/map/map.h

@@ -936,7 +936,7 @@ extern int db_use_sqldbs;
 extern Sql* mmysql_handle;
 extern Sql* logmysql_handle;
 
-extern char buyingstore_db[32];
+extern char buyingstores_db[32];
 extern char buyingstore_items_db[32];
 extern char item_db_db[32];
 extern char item_db2_db[32];

+ 5 - 5
src/map/mob.c

@@ -4019,9 +4019,9 @@ static int mob_read_sqldb(void)
  *------------------------------------------*/
 static bool mob_readdb_mobavail(char* str[], int columns, int current)
 {
-	int mob_id, k;
+	int mob_id, sprite_id;
 
-	mob_id=atoi(str[0]);
+	mob_id = atoi(str[0]);
 
 	if(mob_db(mob_id) == mob_dummy)	// invalid class (probably undefined in db)
 	{
@@ -4029,13 +4029,13 @@ static bool mob_readdb_mobavail(char* str[], int columns, int current)
 		return false;
 	}
 
-	k=atoi(str[1]);
+	sprite_id = atoi(str[1]);
 
 	memset(&mob_db_data[mob_id]->vd, 0, sizeof(struct view_data));
-	mob_db_data[mob_id]->vd.class_=k;
+	mob_db_data[mob_id]->vd.class_ = sprite_id;
 
 	//Player sprites
-	if(pcdb_checkid(k) && columns==12) {
+	if(pcdb_checkid(sprite_id) && columns==12) {
 		mob_db_data[mob_id]->vd.sex=atoi(str[2]);
 		mob_db_data[mob_id]->vd.hair_style=atoi(str[3]);
 		mob_db_data[mob_id]->vd.hair_color=atoi(str[4]);

+ 28 - 12
src/map/pc.c

@@ -849,7 +849,7 @@ bool pc_isequipped(struct map_session_data *sd, unsigned short nameid)
 
 	for( i = 0; i < EQI_MAX; i++ )
 	{
-		int8 index = sd->equip_index[i], j;
+		short index = sd->equip_index[i], j;
 		if( index < 0 )
 			continue;
 		if( pc_is_same_equip_index((enum equip_index)i, sd->equip_index, index) )
@@ -5152,8 +5152,11 @@ char pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int
 		return 1;
 	}
 
+	if ( sd->state.autotrade && (sd->vender_id || sd->buyer_id) ) // Player with autotrade just causes clif glitch! @ FIXME
+		return 1;
+
 	if( battle_config.revive_onwarp && pc_isdead(sd) ) { //Revive dead people before warping them
-		pc_setstand(sd);
+		pc_setstand(sd, true);
 		pc_setrestartvalue(sd,1);
 	}
 
@@ -7059,7 +7062,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
 	if( sd->bg_id && bg_member_respawn(sd) )
 		return; // member revived by battleground
 
-	pc_setstand(sd);
+	pc_setstand(sd, true);
 	pc_setrestartvalue(sd,3);
 	if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) )
 		clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
@@ -7090,7 +7093,7 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h
 		return;
 
 	if( pc_issit(sd) ) {
-		pc_setstand(sd);
+		pc_setstand(sd, true);
 		skill_sit(sd,0);
 	}
 
@@ -7471,7 +7474,7 @@ void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
 	if(hp) clif_updatestatus(sd,SP_HP);
 	if(sp) clif_updatestatus(sd,SP_SP);
 
-	pc_setstand(sd);
+	pc_setstand(sd, true);
 	if(battle_config.pc_invincible_time > 0)
 		pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
 
@@ -8076,6 +8079,8 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper)
 		elemental_delete(sd->ed, 0);
 	if (sd->state.vending)
 		vending_closevending(sd);
+	if (sd->state.buyingstore)
+		buyingstore_close(sd);
 
 	map_foreachinmap(jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id);
 
@@ -8910,8 +8915,7 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) {
 			bool found = false;
 			
 			for( k = 0; k < EQI_MAX; k++ ) {
-				int8 index;
-				index = sd->equip_index[k];
+				short index = sd->equip_index[k];
 				if( index < 0 )
 					continue;
 				if( pc_is_same_equip_index((enum equip_index)k, sd->equip_index, index) )
@@ -9051,8 +9055,8 @@ int pc_load_combo(struct map_session_data *sd) {
 	int i, ret = 0;
 	for( i = 0; i < EQI_MAX; i++ ) {
 		struct item_data *id = NULL;
-		int idx = sd->equip_index[i];
-		if( sd->equip_index[i] < 0 || !(id = sd->inventory_data[idx] ) )
+		short idx = sd->equip_index[i];
+		if( idx < 0 || !(id = sd->inventory_data[idx] ) )
 			continue;
 		if( id->combos_count )
 			ret += pc_checkcombo(sd,id);
@@ -9889,8 +9893,19 @@ int map_night_timer(int tid, unsigned int tick, int id, intptr_t data)
 	return 0;
 }
 
-void pc_setstand(struct map_session_data *sd){
-	nullpo_retv(sd);
+/**
+* Attempt to stand up a player
+* @param sd
+* @param force Ignore the check, ask player to stand up. Used in some cases like pc_damage(), pc_revive(), etc
+* @return True if success, Fals if failed
+*/
+bool pc_setstand(struct map_session_data *sd, bool force){
+	nullpo_ret(sd);
+
+	// Cannot stand yet
+	// TODO: Move to SCS_NOSTAND [Cydh]
+	if (!force && &sd->sc && (sd->sc.data[SC_SITDOWN_FORCE] || sd->sc.data[SC_BANANA_BOMB_SITDOWN]))
+		return false;
 
 	status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
 	clif_status_load(&sd->bl,SI_SIT,0);
@@ -9898,6 +9913,7 @@ void pc_setstand(struct map_session_data *sd){
 	//Reset sitting tick.
 	sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0;
 	sd->state.dead_sit = sd->vd.dead_sit = 0;
+	return true;
 }
 
 /**
@@ -11144,7 +11160,7 @@ short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id)
 * @param index Known index item in inventory from sd->equip_index[] to compare with specified EQI in *equip_index
 * @return True if item in same inventory index, False if doesn't
 */
-bool pc_is_same_equip_index(enum equip_index eqi, int *equip_index, int8 index) {
+bool pc_is_same_equip_index(enum equip_index eqi, short *equip_index, short index) {
 	if (index < 0 || index >= MAX_INVENTORY)
 		return true;
 	// Dual weapon checks

+ 3 - 3
src/map/pc.h

@@ -252,7 +252,7 @@ struct map_session_data {
 	struct registry save_reg;
 
 	struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
-	int equip_index[EQI_MAX];
+	short equip_index[EQI_MAX];
 	unsigned int weight,max_weight;
 	int cart_weight,cart_num,cart_weight_max;
 	int fd;
@@ -1010,7 +1010,7 @@ struct map_session_data *pc_get_child(struct map_session_data *sd);
 void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick);
 void pc_regen (struct map_session_data *sd, unsigned int diff_tick);
 
-void pc_setstand(struct map_session_data *sd);
+bool pc_setstand(struct map_session_data *sd, bool force);
 bool pc_candrop(struct map_session_data *sd,struct item *item);
 bool pc_can_attack(struct map_session_data *sd, int target_id);
 
@@ -1122,7 +1122,7 @@ void pc_itemgrouphealrate_clear(struct map_session_data *sd);
 short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid);
 short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id);
 
-bool pc_is_same_equip_index(enum equip_index eqi, int *equip_index, int8 index);
+bool pc_is_same_equip_index(enum equip_index eqi, short *equip_index, short index);
 /// Check if player is Taekwon Ranker and the level is >= 90 (battle_config.taekwon_ranker_min_lv)
 #define pc_is_taekwon_ranker(sd) (((sd)->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && (sd)->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank((sd)->status.char_id,MAPID_TAEKWON))
 

+ 13 - 13
src/map/script.c

@@ -308,7 +308,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag);
 const char* parse_syntax(const char* p);
 static int parse_syntax_for_flag = 0;
 
-extern int current_equip_item_index; //for New CARDS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus]
+extern short current_equip_item_index; //for New CARDS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus]
 int potion_flag=0; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
 int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0;
 int potion_target=0;
@@ -13145,8 +13145,7 @@ BUILDIN_FUNC(skilleffect)
 
 	/* Ensure we're standing because the following packet causes the client to virtually set the char to stand,
 	 * which leaves the server thinking it still is sitting. */
-	if( pc_issit(sd) ) {
-		pc_setstand(sd);
+	if( pc_issit(sd) && pc_setstand(sd, false) ) {
 		skill_sit(sd, 0);
 		clif_standing(&sd->bl);
 	}
@@ -14014,7 +14013,7 @@ BUILDIN_FUNC(isday)
 BUILDIN_FUNC(isequippedcnt)
 {
 	TBL_PC *sd;
-	int i, j, k, id = 1;
+	int i, id = 1;
 	int ret = 0;
 
 	sd = script_rid2sd(st);
@@ -14024,13 +14023,13 @@ BUILDIN_FUNC(isequippedcnt)
 	}
 
 	for (i=0; id!=0; i++) {
+		short j;
 		FETCH (i+2, id) else id = 0;
 		if (id <= 0)
 			continue;
 
 		for (j=0; j<EQI_MAX; j++) {
-			int index;
-			index = sd->equip_index[j];
+			short index = sd->equip_index[j];
 			if(index < 0)
 				continue;
 			if (pc_is_same_equip_index((enum equip_index)j, sd->equip_index, index))
@@ -14043,6 +14042,7 @@ BUILDIN_FUNC(isequippedcnt)
 				if (sd->inventory_data[index]->nameid == id)
 					ret+= sd->status.inventory[index].amount;
 			} else { //Count cards.
+				short k;
 				if (itemdb_isspecial(sd->status.inventory[index].card[0]))
 					continue; //No cards
 				for(k=0; k<sd->inventory_data[index]->slot; k++) {
@@ -14066,8 +14066,7 @@ BUILDIN_FUNC(isequippedcnt)
 BUILDIN_FUNC(isequipped)
 {
 	TBL_PC *sd;
-	int i, j, k, id = 1;
-	int index, flag;
+	int i, id = 1;
 	int ret = -1;
 	//Original hash to reverse it when full check fails.
 	unsigned int setitem_hash = 0, setitem_hash2 = 0;
@@ -14076,18 +14075,19 @@ BUILDIN_FUNC(isequipped)
 
 	if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing...
 		script_pushint(st,0);
-		return 0;
+		return SCRIPT_CMD_SUCCESS;
 	}
 
 	setitem_hash = sd->bonus.setitem_hash;
 	setitem_hash2 = sd->bonus.setitem_hash2;
 	for (i=0; id!=0; i++) {
+		int flag = 0;
+		short j;
 		FETCH (i+2, id) else id = 0;
 		if (id <= 0)
 			continue;
-		flag = 0;
 		for (j=0; j<EQI_MAX; j++) {
-			index = sd->equip_index[j];
+			short index = sd->equip_index[j];
 			if(index < 0)
 				continue;
 			if (pc_is_same_equip_index((enum equip_index)i, sd->equip_index, index))
@@ -14102,6 +14102,7 @@ BUILDIN_FUNC(isequipped)
 				flag = 1;
 				break;
 			} else { //Cards
+				short k;
 				if (sd->inventory_data[index]->slot == 0 ||
 					itemdb_isspecial(sd->status.inventory[index].card[0]))
 					continue;
@@ -18296,8 +18297,7 @@ BUILDIN_FUNC(stand)
 	if( sd == NULL)
 		return SCRIPT_CMD_FAILURE;
 
-	if( pc_issit(sd) ) {
-		pc_setstand(sd);
+	if( pc_issit(sd) && pc_setstand(sd, false)) {
 		skill_sit(sd, 0);
 		clif_standing(&sd->bl);
 	}

+ 2 - 1
src/map/searchstore.c

@@ -115,6 +115,7 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
 	searchstore_searchall_t store_searchall;
 	time_t querytime;
 	DBMap *vending_db = vending_getdb();
+	DBMap *buyingstore_db = buyingstore_getdb();
 
 	if( !battle_config.feature_search_stores ) {
 		return;
@@ -179,7 +180,7 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
 	s.card_count = card_count;
 	s.min_price  = min_price;
 	s.max_price  = max_price;
-	iter         = db_iterator(vending_db);
+	iter         = db_iterator((type == SEARCHTYPE_VENDING) ?  vending_db : buyingstore_db);
 
 	for( pl_sd = dbi_first(iter); dbi_exists(iter);  pl_sd = dbi_next(iter) ) {
 		if( sd == pl_sd ) {// skip own shop, if any

+ 9 - 11
src/map/skill.c

@@ -2081,7 +2081,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 	 	!(skill_get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) &&
 		(rate=pc_checkskill(sd,HW_SOULDRAIN))>0
 	){	//Soul Drain should only work on targetted spells [Skotlex]
-		if (pc_issit(sd)) pc_setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex]
+		if (pc_issit(sd)) pc_setstand(sd, true); //Character stuck in attacking animation while 'sitting' fix. [Skotlex]
 		clif_skill_nodamage(src,bl,HW_SOULDRAIN,rate,1);
 		status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2);
 	}
@@ -2277,7 +2277,7 @@ int skill_break_equip (struct block_list *src,struct block_list *bl, unsigned sh
 		return 0;
 	if (sd) {
 		for (i = 0; i < EQI_MAX; i++) {
-			int j = sd->equip_index[i];
+			short j = sd->equip_index[i];
 			if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j])
 				continue;
 
@@ -8117,8 +8117,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 						continue;
 					if(map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH))
 						dx[j] = dy[j] = 0;
-					pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN);
-					called++;
+					if (!pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN))
+						called++;
 				}
 			}
 			if (sd)
@@ -9141,11 +9141,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		else if( sd ) {
 			int opt = rnd()%3 + 1;
 			int val = 0, splash = 0;
-			int index = sd->equip_index[EQI_HAND_L];
+			short index = sd->equip_index[EQI_HAND_L];
 			struct item_data *shield_data = NULL;
-			if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
-				shield_data = sd->inventory_data[index];
-			if( !shield_data || shield_data->type != IT_ARMOR ) {	// No shield?
+			if( index < 0 || !(shield_data = sd->inventory_data[index]) || shield_data->type == IT_ARMOR ) {	// No shield?
 				clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
 				break;
 			}
@@ -9215,8 +9213,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 
 				case 3: // refine based
 					{
-						struct item *shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]];
-						if( !shield || !shield->refine ) {
+						struct item *shield = NULL;
+						if( sd->equip_index[EQI_HAND_L] < 0 || !(shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]) || !shield->refine ) {
 							clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 							break;
 						}
@@ -9753,7 +9751,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		if( sd ) {
 			short ammo_id;
 			i = sd->equip_index[EQI_AMMO];
-			if( i <= 0 )
+			if( i < 0 )
 				break; // No ammo.
 			ammo_id = sd->inventory_data[i]->nameid;
 			if( ammo_id <= 0 )

+ 20 - 18
src/map/status.c

@@ -60,7 +60,7 @@ static int atkmods[3][MAX_WEAPON_TYPE];	/// ATK weapon modification for size (si
 static struct eri *sc_data_ers; /// For sc_data entries
 static struct status_data dummy_status;
 
-int current_equip_item_index; /// Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
+short current_equip_item_index; /// Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
 int current_equip_card_id; /// To prevent card-stacking (from jA) [Skotlex]
 // We need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only to avoid cards exploits
 
@@ -2755,7 +2755,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 	const struct status_change *sc = &sd->sc;
 	struct s_skill b_skill[MAX_SKILL]; ///< Previous skill tree
 	int b_weight, b_max_weight, b_cart_weight_max, ///< Previous weight
-	i, index, skill,refinedef=0;
+	i, skill,refinedef=0;
+	short index = -1;
 
 	if (++calculating > 10) // Too many recursive calls!
 		return -1;
@@ -5183,7 +5184,7 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
 		#ifndef RENEWAL
 		else {
 			TBL_PC *sd = (TBL_PC*)bl;
-			int index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R];
+			short index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R];
 
 			if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
 				watk += sc->data[SC_NIBELUNGEN]->val2;
@@ -6499,7 +6500,7 @@ const char* status_get_name(struct block_list *bl)
 }
 
 /**
-* Gets the class of the given bl
+* Gets the class/sprite id of the given bl
 * @param bl: Object whose class to get [PC|MOB|PET|HOM|MER|NPC|ELEM]
 * @return class or 0 if any other bl->type than noted above
 **/
@@ -7664,7 +7665,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	// Strip skills, need to divest something or it fails.
 	case SC_STRIPWEAPON:
 		if (sd && !(flag&4)) { // Apply sc anyway if loading saved sc_data
-			int i;
+			short i;
 			opt_flag = 0; // Reuse to check success condition.
 			if(sd->bonus.unstripable_equip&EQP_WEAPON)
 				return 0;
@@ -7687,7 +7688,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		if( val2 == 1 ) val2 = 0; // GX effect. Do not take shield off..
 		else
 		if (sd && !(flag&4)) {
-			int i;
+			short i;
 			if(sd->bonus.unstripable_equip&EQP_SHIELD)
 				return 0;
 			i = sd->equip_index[EQI_HAND_L];
@@ -7699,7 +7700,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	break;
 	case SC_STRIPARMOR:
 		if (sd && !(flag&4)) {
-			int i;
+			short i;
 			if(sd->bonus.unstripable_equip&EQP_ARMOR)
 				return 0;
 			i = sd->equip_index[EQI_ARMOR];
@@ -7711,7 +7712,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	break;
 	case SC_STRIPHELM:
 		if (sd && !(flag&4)) {
-			int i;
+			short i;
 			if(sd->bonus.unstripable_equip&EQP_HELM)
 				return 0;
 			i = sd->equip_index[EQI_HEAD_TOP];
@@ -7783,7 +7784,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	break;
 	case SC__STRIPACCESSORY:
 		if( sd ) {
-			int i = -1;
+			short i = -1;
 			if( !(sd->bonus.unstripable_equip&EQP_ACC_L) ) {
 				i = sd->equip_index[EQI_ACC_L];
 				if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
@@ -9435,10 +9436,13 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			tick_time = 10000; // [GodLesZ] tick time
 			break;
 		case SC_EXEEDBREAK:
-			val1 *= 100; // 100 * skill_lv
-			if( sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]] ) {
-				val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status_get_lv(bl) / 100);
-				val1 += 10 * sd->status.job_level;
+			{
+				short idx = -1;
+				val1 *= 100; // 100 * skill_lv
+				if( sd && (idx = sd->equip_index[EQI_HAND_R]) >= 0 && sd->inventory_data[idx] ) {
+					val1 += (sd->inventory_data[idx]->weight/10 * sd->inventory_data[idx]->wlv * status_get_lv(bl) / 100);
+					val1 += 10 * sd->status.job_level;
+				}
 			}
 			break;
 		case SC_PRESTIGE:
@@ -9919,7 +9923,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_STONE:
 		case SC_DEEPSLEEP:
 			if (sd && pc_issit(sd)) // Avoid sprite sync problems.
-				pc_setstand(sd);
+				pc_setstand(sd, true);
 		case SC_TRICKDEAD:
 			status_change_end(bl, SC_DANCING, INVALID_TIMER);
 			// Cancel cast when get status [LuzZza]
@@ -10803,8 +10807,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 			sc_start(bl, bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1));
 			break;
 		case SC_SITDOWN_FORCE:
-			if( sd && pc_issit(sd) ) {
-				pc_setstand(sd);
+			if( sd && pc_issit(sd) && pc_setstand(sd, false) ) {
 				clif_standing(bl);
 			}
 			break;
@@ -10863,8 +10866,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 			status_change_end(bl,SC_TEARGAS_SOB,INVALID_TIMER);
 			break;
 		case SC_BANANA_BOMB_SITDOWN:
-			if( sd && pc_issit(sd) ) {
-				pc_setstand(sd);
+			if( sd && pc_issit(sd) && pc_setstand(sd, false) ) {
 				skill_sit(sd,0);
 				clif_standing(bl);
 			}

+ 3 - 3
src/map/status.h

@@ -1535,7 +1535,7 @@ enum e_joint_break
 	BREAK_FLAGS	= BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK,
 };
 
-extern int current_equip_item_index;
+extern short current_equip_item_index;
 extern int current_equip_card_id;
 
 //Mode definitions to clear up code reading. [Skotlex]
@@ -1556,9 +1556,9 @@ enum e_mode {
 	MD_CHANGETARGET_CHASE	= 0x002000,
 	MD_TARGETWEAK			= 0x004000,
 	MD_RANDOMTARGET			= 0x008000,
-	MD_IGNOREMELEE			= 0x010000,
+	MD_IGNOREMELEE			= 0x010000, //! TODO: Unused yet
 	MD_IGNOREMAGIC			= 0x020000,
-	MD_IGNORERANGED			= 0x040000,
+	MD_IGNORERANGED			= 0x040000, //! TODO: Unused yet
 	MD_MVP					= 0x080000,
 	MD_IGNOREMISC			= 0x100000,
 	MD_KNOCKBACK_IMMUNE		= 0x200000,

+ 1 - 3
src/map/unit.c

@@ -2413,7 +2413,6 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 				chat_leavechat(sd,0);
 			if(sd->trade_partner)
 				trade_tradecancel(sd);
-			buyingstore_close(sd);
 			searchstore_close(sd);
 			if (sd->menuskill_id != AL_TELEPORT) { //bugreport:8027
 				if (sd->state.storage_flag == 1)
@@ -2451,8 +2450,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 			if(sd->duel_group > 0)
 				duel_leave(sd->duel_group, sd);
 
-			if(pc_issit(sd)) {
-				pc_setstand(sd);
+			if(pc_issit(sd) && pc_setstand(sd, false)) {
 				skill_sit(sd,0);
 			}
 			party_send_dot_remove(sd);// minimap dot fix [Kevin]

+ 9 - 3
src/map/vending.c

@@ -85,6 +85,7 @@ void vending_closevending(struct map_session_data* sd)
 		}
 		
 		sd->state.vending = false;
+		sd->vender_id = 0;
 		clif_closevendingboard(&sd->bl, 0);
 		idb_remove(vending_db, sd->status.char_id);
 	}
@@ -483,8 +484,10 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
 * @param sd Player as autotrader
 */
 void vending_reopen( struct map_session_data* sd ){
+	nullpo_retv(sd);
+
 	// Ready to open vending for this char
-	if ( sd && autotrader_count > 0 && autotraders){
+	if ( autotrader_count > 0 && autotraders){
 		uint16 i;
 		uint8 *data, *p, fail = 0;
 		uint16 j, count;
@@ -538,8 +541,11 @@ void vending_reopen( struct map_session_data* sd ){
 			// Make vendor look perfect
 			pc_setdir(sd, autotraders[i]->dir, autotraders[i]->head_dir);
 			clif_changed_dir(&sd->bl, AREA_WOS);
-			if( autotraders[i]->sit )
+			if( autotraders[i]->sit ) {
 				pc_setsit(sd);
+				skill_sit(sd, 1);
+				clif_sitting(&sd->bl);
+			}
 
 			// Immediate save
 			chrif_save(sd, 3);
@@ -671,7 +677,7 @@ void do_init_vending_autotrade( void ) {
 				Sql_FreeResult(mmysql_handle);
 			}
 
-			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
+			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' vending autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
 		}
 	}