diff --git a/src/map/atcommand.c b/src/map/atcommand.c index c5a74bf922..18a78357a5 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -8066,6 +8066,8 @@ ACMD_FUNC(cash) } else clif_displaymessage(fd, msg_txt(sd,149)); // Unable to decrease the number/value. } else { + if (-value > sd->cashPoints) //By command, if cash < value, force it to remove all + value = -sd->cashPoints; if( (ret=pc_paycash(sd, -value, 0, LOG_TYPE_COMMAND)) >= 0){ // If this option is set, the message is already sent by pc function if( !battle_config.cashshop_show_points ){ diff --git a/src/map/cashshop.c b/src/map/cashshop.c index c7458f5d58..b9d0402433 100644 --- a/src/map/cashshop.c +++ b/src/map/cashshop.c @@ -190,22 +190,26 @@ static void cashshop_read_db( void ){ } } -/* - * Attempts to purchase a cashshop item from the list. +/** Attempts to purchase a cashshop item from the list. * Checks if the transaction is valid and if the user has enough inventory space to receive the item. - * If yes, take cashpoints and give items; - * else return clif_error. + * If yes, take cashpoints and give items; else return clif_error. + * @param sd Player that request to buy item(s) + * @param kafrapoints + * @param n Count of item list + * @param item_list Array of item ID + * @return true: success, false: fail */ -void cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, uint16* item_list ){ +bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, uint16* item_list ){ uint32 totalcash = 0; uint32 totalweight = 0; int i,new_; if( sd == NULL || item_list == NULL ){ - return; + clif_cashshop_result( sd, 0, CASHSHOP_RESULT_ERROR_UNKNOWN ); + return false; }else if( sd->state.trading ){ clif_cashshop_result( sd, 0, CASHSHOP_RESULT_ERROR_PC_STATE ); - return; + return false; } new_ = 0; @@ -218,14 +222,14 @@ void cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u if( tab > CASHSHOP_TAB_SEARCH ){ clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_UNKNOWN ); - return; + return false; } ARR_FIND( 0, cash_shop_items[tab].count, j, nameid == cash_shop_items[tab].item[j]->nameid ); if( j == cash_shop_items[tab].count || !itemdb_exists( nameid ) ){ - clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_UNKNOWN ); - return; + clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_UNKONWN_ITEM ); + return false; }else if( !itemdb_isstackable( nameid ) && quantity > 1 ){ uint32* quantity_ptr = (uint32*)item_list + i * 5 + 2; ShowWarning( "Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable cash item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, quantity, nameid ); @@ -242,7 +246,7 @@ void cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u case CHKADDITEM_OVERAMOUNT: clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_OVER_PRODUCT_TOTAL_CNT ); - return; + return false; } totalcash += cash_shop_items[tab].item[j]->price * quantity; @@ -251,15 +255,15 @@ void cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u if( ( totalweight + sd->weight ) > sd->max_weight ){ clif_cashshop_result( sd, 0, CASHSHOP_RESULT_ERROR_INVENTORY_WEIGHT ); - return; + return false; }else if( pc_inventoryblank( sd ) < new_ ){ clif_cashshop_result( sd, 0, CASHSHOP_RESULT_ERROR_INVENTORY_ITEMCNT ); - return; + return false; } if(pc_paycash( sd, totalcash, kafrapoints, LOG_TYPE_CASH ) < 0){ clif_cashshop_result( sd, 0, CASHSHOP_RESULT_ERROR_SHORTTAGE_CASH ); - return; + return false; } for( i = 0; i < n; ++i ){ @@ -278,21 +282,22 @@ void cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u switch( pc_additem( sd, &item_tmp, quantity, LOG_TYPE_CASH ) ){ case ADDITEM_OVERWEIGHT: clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_INVENTORY_WEIGHT ); - return; + return false; case ADDITEM_OVERITEM: clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_INVENTORY_ITEMCNT ); - return; + return false; case ADDITEM_OVERAMOUNT: clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_OVER_PRODUCT_TOTAL_CNT ); - return; + return false; case ADDITEM_STACKLIMIT: clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_RUNE_OVERCOUNT ); - return; + return false; } } } - clif_cashshop_result( sd, 0, CASHSHOP_RESULT_SUCCESS ); + clif_cashshop_result( sd, 0, CASHSHOP_RESULT_SUCCESS ); //Doesn't show any message? + return true; } /* diff --git a/src/map/cashshop.h b/src/map/cashshop.h index c2314f2fa9..daf1833788 100644 --- a/src/map/cashshop.h +++ b/src/map/cashshop.h @@ -10,7 +10,7 @@ int do_init_cashshop( void ); int do_final_cashshop( void ); void cashshop_reloaddb( void ); -void cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, uint16* item_list ); +bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, uint16* item_list ); // Taken from AEGIS enum CASH_SHOP_TAB_CODE{ diff --git a/src/map/clif.c b/src/map/clif.c index be4fc347d3..322668effe 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -14965,8 +14965,6 @@ void clif_cashshop_result( struct map_session_data *sd, uint16 item_id, uint16 r /// 0288 .W .L .W { .W .W }.4B*count (PACKETVER >= 20100803) /// 0848 .W .W .W .L .W { .W .W .W }.6B*count (PACKETVER >= 20130000) void clif_parse_cashshop_buy(int fd, struct map_session_data *sd){ - - int fail = 0; struct s_packet_db* info; int cmd = RFIFOW(fd,0); @@ -14974,16 +14972,17 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd){ info = &packet_db[sd->packet_ver][cmd]; - if( sd->state.trading || !sd->npc_shopid ) - fail = 1; + if( sd->state.trading || !sd->npc_shopid ) { + clif_cashshop_ack(sd,1); + return; + } else { #if PACKETVER < 20101116 short nameid = RFIFOW(fd,info->pos[0]); short amount = RFIFOW(fd,info->pos[1]); int points = RFIFOL(fd,info->pos[2]); - fail = npc_cashshop_buy(sd, nameid, amount, points); - clif_cashshop_ack(sd,fail); + clif_cashshop_ack(sd,npc_cashshop_buy(sd, nameid, amount, points)); #else int s_itl = (cmd==0x848)?10:4; //item _list size (depend on cmd even for 2013+) int len = RFIFOW(fd,info->pos[0]); @@ -14996,13 +14995,15 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd){ return; } if(cmd==0x848){ - cashshop_buylist( sd, points, count, item_list); + if (cashshop_buylist( sd, points, count, item_list)) + clif_cashshop_ack(sd,0); + return; } else { - fail = npc_cashshop_buylist(sd,points,count,item_list); + clif_cashshop_ack(sd,npc_cashshop_buylist(sd,points,count,item_list)); + return; } #endif } - clif_cashshop_ack(sd,fail); } /// Adoption System diff --git a/src/map/itemdb.h b/src/map/itemdb.h index 1011d39c06..a7ff9307cc 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -8,33 +8,30 @@ #include "../common/mmo.h" // ITEM_NAME_LENGTH #include "map.h" -// 32k array entries in array (the rest goes to the db) +/// 32k array entries in array (the rest goes to the db) #define MAX_ITEMDB 0x8000 - -//Use apple for unknown items. +///Use apple for unknown items. #define UNKNOWN_ITEM_ID 512 - -// The maximum number of item delays +/// The maximum number of item delays #define MAX_ITEMDELAYS 10 - -#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display. - -/* maximum amount of items a combo may require */ +///Designed for search functions, species max number of matches to display. +#define MAX_SEARCH 5 +///Maximum amount of items a combo may require #define MAX_ITEMS_PER_COMBO 6 //The only item group required by the code to be known. See const.txt for the full list. #define IG_FINDINGORE 6 #define IG_POTION 37 -#define MAX_ITEMGROUP 390 ///The max. item group count (increase this when needed). TODO: Remove this limit and use dynamic allocaton +#define MAX_ITEMGROUP 390 ///The max. item group count (increase this when needed). TODO: Remove this limit and use dynamic allocaton if needed -#define MAX_ITEMGROUP_RANDGROUP 4 ///Max group for random item (increase this when needed). +#define MAX_ITEMGROUP_RANDGROUP 4 ///Max group for random item (increase this when needed). TODO: Remove this limit and use dynamic allocaton if needed #define CARD0_FORGE 0x00FF #define CARD0_CREATE 0x00FE #define CARD0_PET ((short)0xFF00) -//Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex] +///Marks if the card0 given is "special" (non-item id used to mark pets/created items. [Skotlex] #define itemdb_isspecial(i) (i == CARD0_FORGE || i == CARD0_CREATE || i == CARD0_PET) ///Enum of item id (for hardcoded purpose) @@ -120,9 +117,7 @@ enum item_itemid { ITEMID_JOB_MANUAL50 = 14592, }; -/** - * Mercenary Scrolls - */ +///Mercenary Scrolls enum mercenary_scroll_item_list { ITEMID_BOW_MERCENARY_SCROLL1 = 12153, ITEMID_BOW_MERCENARY_SCROLL2, @@ -156,9 +151,7 @@ enum mercenary_scroll_item_list { ITEMID_SPEARMERCENARY_SCROLL10, }; -/** - * Rune Knight - */ +///Rune Knight enum rune_item_list { ITEMID_NAUTHIZ = 12725, ITEMID_RAIDO, @@ -172,9 +165,7 @@ enum rune_item_list { ITEMID_LUX_ANIMA = 22540, }; -/** - * Mechanic - */ +///Mechanic enum mechanic_item_list { ITEMID_ACCELERATOR = 2800, ITEMID_HOVERING_BOOSTER, @@ -193,9 +184,7 @@ enum mechanic_item_list { ITEMID_LIME_GREEN_PTS, }; -/** - * Genetic - */ +///Genetic enum genetic_item_list { ITEMID_SEED_OF_HORNY_PLANT = 6210, ITEMID_BLOODSUCK_PLANT_SEED = 6211, @@ -250,9 +239,7 @@ enum genetic_item_list { ITEMID_BLACK_THING_TO_THROW, }; -/** - * Guillotine Cross - */ +///Guillotine Cross enum poison_item_list { ITEMID_PARALYSE = 12717, ITEMID_LEECHESEND, @@ -264,9 +251,7 @@ enum poison_item_list { ITEMID_VENOMBLEED, }; -/** - * Spell Books - */ +///Spell Books enum spell_book_item_list { ITEMID_MAGIC_BOOK_FB = 6189, ITEMID_MAGIC_BOOK_CB, @@ -287,9 +272,7 @@ enum spell_book_item_list { ITEMID_MAGIC_BOOK_DL, }; -/** - * Cash Food - */ +///Cash Food enum cash_food_item_list { ITEMID_STR_DISH10_ = 12202, ITEMID_AGI_DISH10_, @@ -299,10 +282,12 @@ enum cash_food_item_list { ITEMID_VIT_DISH10_, }; +///Item No Use List enum item_nouse_list { NOUSE_SITTING = 0x01, }; +///Item job enum e_item_job { ITEMJ_NORMAL = 0x01, ITEMJ_UPPER = 0x02, @@ -312,6 +297,7 @@ enum e_item_job { ITEMJ_THIRD_BABY = 0x20, }; +///Item combo struct struct item_combo { struct script_code *script; unsigned short *nameid;/* nameid array */ @@ -320,6 +306,7 @@ struct item_combo { bool isRef;/* whether this struct is a reference or the master */ }; +///Main item data struct struct item_data { uint16 nameid; char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; @@ -386,7 +373,7 @@ struct item_data { /* Struct of item group entry */ struct s_item_group { uint16 nameid, ///item id - duration; ///duration if item as rental item + duration; ///duration if item as rental item (in minute) uint16 amount; ///amount of item will be obtained bool isAnnounced, ///broadcast if player get this item isNamed; ///named the item (if possible) @@ -403,7 +390,7 @@ struct s_item_group_random { struct s_item_group_db { struct s_item_group *must; uint16 must_qty; - struct s_item_group_random random[MAX_ITEMGROUP_RANDGROUP]; //! TODO: Move this fixed array to dynamic allocation! + struct s_item_group_random random[MAX_ITEMGROUP_RANDGROUP]; //! TODO: Move this fixed array to dynamic allocation if needed. }; struct item_data* itemdb_searchname(const char *name); diff --git a/src/map/pc.c b/src/map/pc.c index 6a1fe7ce57..eb2cdfcfba 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -3854,10 +3854,14 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, return 0; } -/*========================================== - * Cash Shop - *------------------------------------------*/ +/** Makes player pays by using cash points + * @param sd Player who pays + * @param price How many point player has to pay + * @param points + * @param type e_log_pick_type + * @return -2: Paying negative points, -1: Not enough points, otherwise is succes (cash+points) + */ int pc_paycash(struct map_session_data *sd, int price, int points, e_log_pick_type type ){ int cash; nullpo_retr(-1,sd); diff --git a/src/map/skill.c b/src/map/skill.c index c6c2b706cb..bcc4b90c44 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -507,6 +507,9 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) if (skill_id == AL_TELEPORT && sd->skillitem == skill_id && sd->skillitemlv > 2) return false; // Teleport lv 3 bypasses this check.[Inkfish] + if (map[m].flag.noskill) + return true; + // Epoque: // This code will compare the player's attack motion value which is influenced by ASPD before // allowing a skill to be cast. This is to prevent no-delay ACT files from spamming skills such as @@ -643,7 +646,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) break; } - return (map[m].flag.noskill); + return false; } /** Check if the homunculus skill is ok to be processed @@ -9789,32 +9792,24 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui } break; - case MH_SILENT_BREEZE: { - struct status_change *ssc = status_get_sc(src); - struct block_list *m_bl = battle_get_master(src); - int heal; - if(tsc){ - const enum sc_type scs[] = { - SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION - }; - for (i = 0; i < ARRAYLENGTH(scs); i++) { - if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); - } - if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target - status_change_start(src,bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8); - } - heal = status_get_sp(src) + status_get_lv(src); //cur_sp+blvl @TODO need real value - status_heal(bl, heal, 0, 7); + case MH_SILENT_BREEZE: + { + //Silences the homunculus and target + status_change_start(src,src,SC_SILENCE,10000,skill_lv,0,0,0,skill_get_time(skill_id,skill_lv),0); + status_change_start(src,bl,SC_SILENCE,10000,skill_lv,0,0,0,skill_get_time(skill_id,skill_lv),0); - //now inflict silence on everyone - if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun - status_change_start(src, src, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8); - if(m_bl) { - struct status_change *msc = status_get_sc(m_bl); - if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master - status_change_start(src, m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8); - } - if (hd) + //Recover the target's HP + status_heal(bl,status_get_lv(src)+status_get_sp(src),0,3); //(custom) + + //Removes these SC from target + if (tsc) { + const enum sc_type scs[] = { + SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION + }; + for (i = 0; i < ARRAYLENGTH(scs); i++) + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } + if (hd) skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv)); } break; @@ -11864,7 +11859,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill int alive = 1; // are the coordinates out of range? - if( ux <= 0 || uy <= 0 || ux >= map[sd->bl.m].xs || uy >= map[sd->bl.m].ys ){ + if( ux <= 0 || uy <= 0 || ux >= map[src->m].xs || uy >= map[src->m].ys ){ continue; } diff --git a/src/map/status.c b/src/map/status.c index fc2b9d2b79..eb0cdb0db5 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -7221,7 +7221,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ * @param src: Source of the status change [PC|MOB|HOM|MER|ELEM|NPC] * @param bl: Target of the status change (See: enum sc_type) * @param type: Status change (SC_*) -* @param rate: Initial percentage rate of affecting bl +* @param rate: Initial percentage rate of affecting bl (0~10000) * @param val1~4: Depends on type of status change * @param tick: Initial duration that the status change affects bl * @param flag: Value which determines what parts to calculate