* Updated Silent Breeze effect, only gives chance to give silence status to target and the caster (Eira), bugreport:8529, http://rathena.org/board/tracker/issue-8529-homunculus-s-eira-silent-breeze/
* Follow up 80f7984, and some minors Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
This commit is contained in:
parent
5a1f3f95c4
commit
a0760f171b
@ -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 ){
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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{
|
||||
|
@ -14965,8 +14965,6 @@ void clif_cashshop_result( struct map_session_data *sd, uint16 item_id, uint16 r
|
||||
/// 0288 <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W }.4B*count (PACKETVER >= 20100803)
|
||||
/// 0848 <packet len>.W <count>.W <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W <tab>.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
|
||||
|
@ -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);
|
||||
|
10
src/map/pc.c
10
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user