diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 3846c0543c..5145c5918e 100644 --- a/src/map/atcommand.c +++ b/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) diff --git a/src/map/battle.c b/src/map/battle.c index e47e51cb26..bd2eef4e67 100644 --- a/src/map/battle.c +++ b/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; diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index a48d4cbd88..6b8b1ae52f 100644 --- a/src/map/buyingstore.c +++ b/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; +} diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h index ee4673d8c3..c5d0d3a02e 100644 --- a/src/map/buyingstore.h +++ b/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 ); diff --git a/src/map/clif.c b/src/map/clif.c index c0184ca322..99315b2be0 100644 --- a/src/map/clif.c +++ b/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; } } diff --git a/src/map/map.c b/src/map/map.c index af61cd6847..0e470ab1c6 100644 --- a/src/map/map.c +++ b/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) diff --git a/src/map/map.h b/src/map/map.h index 9a1f31ac5b..12194dec49 100644 --- a/src/map/map.h +++ b/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]; diff --git a/src/map/mob.c b/src/map/mob.c index a461f4a203..4093fd76e6 100644 --- a/src/map/mob.c +++ b/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]); diff --git a/src/map/pc.c b/src/map/pc.c index 96bec5844e..3e5fc43045 100755 --- a/src/map/pc.c +++ b/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 diff --git a/src/map/pc.h b/src/map/pc.h index 8346608d77..0e7ef54bd4 100644 --- a/src/map/pc.h +++ b/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)) diff --git a/src/map/script.c b/src/map/script.c index 86ab5d4b0f..3ee4409015 100644 --- a/src/map/script.c +++ b/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; jequip_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; kinventory_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; jequip_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); } diff --git a/src/map/searchstore.c b/src/map/searchstore.c index 35d6927315..64f4aecf2d 100644 --- a/src/map/searchstore.c +++ b/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 diff --git a/src/map/skill.c b/src/map/skill.c index 80102b673b..0bf737eef1 100755 --- a/src/map/skill.c +++ b/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 ) diff --git a/src/map/status.c b/src/map/status.c index 52bb8366eb..e2db69e24e 100644 --- a/src/map/status.c +++ b/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); } diff --git a/src/map/status.h b/src/map/status.h index f7de0841aa..440a31e1b5 100644 --- a/src/map/status.h +++ b/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, diff --git a/src/map/unit.c b/src/map/unit.c index 68eb283db1..322a71f81b 100644 --- a/src/map/unit.c +++ b/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] diff --git a/src/map/vending.c b/src/map/vending.c index 3a184ee4d8..c43937994a 100755 --- a/src/map/vending.c +++ b/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); } }