Skip to content
Permalink
Browse files
Minor bug fix
If a player did not meet the requirements to reopen the buyingstore/vending for whatever reason the character is now set offline.

A possible examples I have tested with is to change the area where the player's shop was to novending, which will not allow him to open the shop in this area.
  • Loading branch information
Lemongrass3110 committed Feb 6, 2014
1 parent b3506fb commit ff9b6253c281d5f0eb5e73d17c7da924f14f7540
Showing with 85 additions and 74 deletions.
  1. +46 −40 src/map/buyingstore.c
  2. +1 −1 src/map/buyingstore.h
  3. +37 −32 src/map/vending.c
  4. +1 −1 src/map/vending.h
@@ -107,46 +107,46 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots){
}


void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
bool 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];

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

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;
return false;
}

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;
return false;
}

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

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;
return false;
}

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;
return false;
}

weight = sd->weight;
@@ -202,14 +202,14 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
{// invalid item/amount/price
sd->buyingstore.slots = 0;
clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
return;
return false;
}

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;
return false;
}

// success
@@ -233,6 +233,8 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha

clif_buyingstore_myitemlist(sd);
clif_buyingstore_entry(sd);

return true;
}


@@ -538,13 +540,12 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
return true;
}

/** Open vending for Autotrader
/** Open buyingstore for Autotrader
* @param sd Player as autotrader
*/
void buyingstore_reopen( struct map_session_data* sd ){
if (!sd || !autotrader_count || !autotraders)
return;
else { // Ready to open vending for this char
// Ready to open buyingstore for this char
if ( sd && autotrader_count > 0 && autotraders){
uint16 i;
uint8 *data, *p;
uint16 j, count;
@@ -554,7 +555,7 @@ void buyingstore_reopen( struct map_session_data* sd ){
return;
}

// Init vending data for autotrader
// Init buyingstore data for autotrader
CREATE(data, uint8, autotraders[i]->count * 8);

for (j = 0, p = data, count = autotraders[i]->count; j < autotraders[i]->count; j++) {
@@ -570,26 +571,33 @@ void buyingstore_reopen( struct map_session_data* sd ){
p += 8;
}

// Open the shop again
buyingstore_setup( sd, (unsigned char)autotraders[i]->count );
buyingstore_create( sd, autotraders[i]->limit, 1, autotraders[i]->title, data, autotraders[i]->count );
aFree(data);
// Open the buyingstore again
if( buyingstore_setup( sd, (unsigned char)autotraders[i]->count ) &&
buyingstore_create( sd, autotraders[i]->limit, 1, autotraders[i]->title, data, autotraders[i]->count ) )
{
ShowInfo("Loaded autotrade buyingstore data 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);

ShowInfo("Loaded autotrade buyingstore data 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);
// Set him to autotrade
if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;",
buyingstore_db, sd->buyer_id ) != SQL_SUCCESS )
{
Sql_ShowDebug( mmysql_handle );
}

// Set him to autotrade
if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;",
buyingstore_db, sd->buyer_id ) != SQL_SUCCESS )
{
Sql_ShowDebug( mmysql_handle );
}
// Make him look perfect
unit_setdir(&sd->bl,battle_config.feature_autotrade_direction);

// Make him look perfect
unit_setdir(&sd->bl,battle_config.feature_autotrade_direction);
if( battle_config.feature_autotrade_sit )
pc_setsit(sd);
}else{
// Failed to open the buyingstore, set him offline
ShowWarning("Failed to load autotrade buyingstore data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items\n", sd->status.name, count );

if( battle_config.feature_autotrade_sit )
pc_setsit(sd);
map_quit( sd );
}

aFree(data);

//If the last autotrade is loaded, clear autotraders [Cydh]
if (i+1 >= autotrader_count)
@@ -606,7 +614,7 @@ void do_init_buyingstore_autotrade( void ) {
autotrader_count = 0;

// Get autotrader from table. `map`, `x`, and `y`, aren't used here
// Just read player that has data at vending_items [Cydh]
// Just read player that has data at buyingstore_items [Cydh]
if (Sql_Query(mmysql_handle,
"SELECT `id`, `account_id`, `char_id`, `sex`, `title`, `limit` "
"FROM `%s` "
@@ -623,6 +631,12 @@ void do_init_buyingstore_autotrade( void ) {
// Init autotraders
CREATE(autotraders, struct s_autotrade *, autotrader_count);

if (autotraders == NULL) { //This is shouldn't happen [Cydh]
ShowError("Failed to initialize buyingstore autotraders!\n");
Sql_FreeResult(mmysql_handle);
return;
}

// Init each autotrader data
i = 0;
while (SQL_SUCCESS == Sql_NextRow(mmysql_handle) && i < autotrader_count) {
@@ -650,12 +664,6 @@ void do_init_buyingstore_autotrade( void ) {
}
Sql_FreeResult(mmysql_handle);

if (autotraders == NULL) { //This is shouldn't happen [Cydh]
ShowError("Failed to initialize autotraders!\n");
do_final_buyingstore_autotrade();
return;
}

//Init items on vending list each autotrader
for (i = 0; i < autotrader_count; i++){
struct s_autotrade *at = NULL;
@@ -714,9 +722,7 @@ void do_init_buyingstore_autotrade( void ) {
* @author [Cydh]
*/
void do_final_buyingstore_autotrade(void) {
if (!autotrader_count || !autotraders)
return;
else {
if (autotrader_count && autotraders){
uint16 i = 0;
while (i < autotrader_count) { //Free the autotrader
if (autotraders[i] == NULL)
@@ -23,7 +23,7 @@ struct s_buyingstore
};

bool buyingstore_setup(struct map_session_data* sd, unsigned char slots);
void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
bool buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
void buyingstore_close(struct map_session_data* sd);
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);
@@ -297,29 +297,29 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
* data := {<index>.w <amount>.w <value>.l}[count]
* @param count : number of different items
*/
void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
bool 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_retv(sd);

if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd))
return; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once
return false; // 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;
return false;
}

// 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;
return false;
}

// filter out invalid items
@@ -353,7 +353,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const

if( i == 0 ) { // no valid item found
clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
return;
return false;
}
sd->state.prevend = 0;
sd->state.vending = true;
@@ -377,6 +377,8 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
clif_showvendingboard(&sd->bl,message,0);

idb_put(vending_db, sd->status.char_id, sd);

return true;
}

/**
@@ -463,9 +465,8 @@ 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 ){
if (!sd || !autotrader_count || !autotraders)
return;
else { // Ready to open vending for this char
// Ready to open vending for this char
if ( sd && autotrader_count > 0 && autotraders){
uint16 i;
uint8 *data, *p;
uint16 j, count;
@@ -502,25 +503,31 @@ void vending_reopen( struct map_session_data* sd ){
// Set him into a hacked prevend state
sd->state.prevend = 1;

// Open the shop again
vending_openvending(sd, autotraders[i]->title, data, count);
aFree(data);
// Open the vending again
if( vending_openvending(sd, autotraders[i]->title, data, count) ){
// Set him to autotrade
if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;",
vendings_db, sd->vender_id ) != SQL_SUCCESS )
{
Sql_ShowDebug( mmysql_handle );
}

ShowInfo("Loaded autotrade vending data 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);
// Make him look perfect
unit_setdir(&sd->bl,battle_config.feature_autotrade_direction);

// Set him to autotrade
if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;",
vendings_db, sd->vender_id ) != SQL_SUCCESS )
{
Sql_ShowDebug( mmysql_handle );
}
if( battle_config.feature_autotrade_sit )
pc_setsit(sd);

// Make him look perfect
unit_setdir(&sd->bl,battle_config.feature_autotrade_direction);
ShowInfo("Loaded autotrade vending data 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);
}else{
// Failed to open the vending, set him offline
ShowWarning("Failed to load autotrade vending data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items\n", sd->status.name, count );

map_quit( sd );
}

if( battle_config.feature_autotrade_sit )
pc_setsit(sd);
aFree(data);

//If the last autotrade is loaded, clear autotraders [Cydh]
if (i+1 >= autotrader_count)
@@ -554,6 +561,12 @@ void do_init_vending_autotrade( void ) {
// Init autotraders
CREATE(autotraders, struct s_autotrade *, autotrader_count);

if (autotraders == NULL) { //This is shouldn't happen [Cydh]
ShowError("Failed to initialize vending autotraders!\n");
Sql_FreeResult(mmysql_handle);
return;
}

// Init each autotrader data
i = 0;
while (SQL_SUCCESS == Sql_NextRow(mmysql_handle) && i < autotrader_count) {
@@ -580,12 +593,6 @@ void do_init_vending_autotrade( void ) {
}
Sql_FreeResult(mmysql_handle);

if (autotraders == NULL) { //This is shouldn't happen [Cydh]
ShowError("Failed to initialize autotraders!\n");
do_final_vending_autotrade();
return;
}

//Init items on vending list each autotrader
for (i = 0; i < autotrader_count; i++){
struct s_autotrade *at = NULL;
@@ -644,9 +651,7 @@ void do_init_vending_autotrade( void ) {
* @author [Cydh]
*/
void do_final_vending_autotrade(void) {
if (!autotrader_count || !autotraders)
return;
else {
if (autotrader_count && autotraders){
uint16 i = 0;
while (i < autotrader_count) { //Free the autotrader
if (autotraders[i] == NULL)
@@ -22,7 +22,7 @@ void do_init_vending_autotrade( void );

void vending_reopen( struct map_session_data* sd );
void vending_closevending(struct map_session_data* sd);
void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count);
bool vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count);
void vending_vendinglistreq(struct map_session_data* sd, int id);
void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count);
bool vending_search(struct map_session_data* sd, unsigned short nameid);

0 comments on commit ff9b625

Please sign in to comment.