* Introducing Item Reuse Limit Group

* By expanding current item_delay.txt's function to implement official item reuse limit.
  * There's the 3rd optional column, put SC ID value to add reuse limit. The reuse delay will be acknowledged as status change. Ignoring this column will use 'normal' item delay.
  * Added some items to their reuse limit group.
* Item DB Updates
  * Added effect for ASPD_Potion (12684).
  * Added effect and delay for Para_Team_Mark_ (22508).

Signed-off-by: Cydh Ramdh <cydh@pservero.com>
This commit is contained in:
Cydh Ramdh 2015-08-03 20:47:50 +07:00
parent 356d0a4bad
commit 64cb02e5f1
14 changed files with 359 additions and 98 deletions

View File

@ -1796,7 +1796,22 @@ SC_MTF_MSP 604
SC_MTF_PUMPKIN 605
SC_MTF_HITFLEE 606
SC_CRIFOOD 607
SC_EXTREMITYFIST2 608
SC_HASTEATTACK_CASH 608
SC_REUSE_LIMIT_A 609
SC_REUSE_LIMIT_B 610
SC_REUSE_LIMIT_C 611
SC_REUSE_LIMIT_D 612
SC_REUSE_LIMIT_E 613
SC_REUSE_LIMIT_F 614
SC_REUSE_LIMIT_G 615
SC_REUSE_LIMIT_H 616
SC_REUSE_LIMIT_MTF 617
SC_REUSE_LIMIT_ASPD_POTION 618
SC_REUSE_MILLENNIUMSHIELD 619
SC_REUSE_CRUSHSTRIKE 620
SC_REUSE_STORMBLAST 621
SC_ALL_RIDING_REUSE_LIMIT 622
SC_EXTREMITYFIST2 623
//Status Icon
SI_BLANK -1

View File

@ -1,31 +1,56 @@
// Item Delay Database
//
// Structure of Database:
// Item ID,Delay in Milliseconds
// <ItemID>,<Delay>{,<SC_GroupID>}
//
// NOTE:
// There is a max concurrent number of entries set in src/map/itemdb.h as MAX_ITEMDELAYS.
// <ItemID>
// ID of item that will has reuse delay.
// <Delay>
// Re-use delay in milliseconds.
// <SC_GroupID>
// SC (status change) group for the item.
// Example for SC_REUSE_LIMIT_MTF
// 12658,10000,620 // Transformation Scroll(Deviruchi)
// 12659,10000,620 // Transformation Scroll(Raydric)
// -> 12658 has reuse delay for 10 seconds, and also,
// 12659 cannot be used when this delay is active.
// Since this is optional, default is -1 will ignores the
// delay group and the delay will be stored in character's
// data that has limit set in src/map/itemdb.h as MAX_ITEMDELAYS.
// SC_REUSE_LIMIT_A 609
14538,300000,608 //Glass_Of_Illusion
// SC_REUSE_LIMIT_B 610
14586,180000,609 //Spark_Candy
// SC_REUSE_LIMIT_C 611
12208,60000,610 //Battle_Manual
// SC_REUSE_LIMIT_D 612
12210,60000,611 //Bubble_Gum
// SC_REUSE_LIMIT_E 613
11522,1000,612 //Red_Raffle_Sap
11523,2000,612 //Yellow_Raffle_Sap
11524,3000,612 //White_Raffle_Sap
// SC_REUSE_LIMIT_F 614
607,5000,613 //Yggdrasil_Berry
// SC_REUSE_LIMIT_G 615
608,3000,614 //Yggdrasil_Seed
// SC_REUSE_LIMIT_H 616
11525,5000,615 //Mora_Hip_Tea
// Misc
//12202,60000 //Str_Dish10_
//12203,60000 //Agi_Dish10_
//12204,60000 //Int_Dish10_
//12205,60000 //Dex_Dish10_
//12206,60000 //Luk_Dish10_
//12207,60000 //Vit_Dish10_
12208,60000 //Battle_Manual
12210,60000 //Bubble_Gum
14538,300000 //Glass_Of_Illusion
14586,180000 //Spark_Candy
607,5000 //Yggdrasil_Berry
608,3000 //Yggdrasil_Seed
// Bifrost Items
11522,1000 //Red_Raffle_Sap
11523,2000 //Yellow_Raffle_Sap
11524,3000 //White_Raffle_Sap
11525,5000 //Mora_Hip_Tea
// FIX ME! Delays need confirmation.
12968,300000 //Emergency_Scroll1
12969,300000 //Emergency_Scroll2
12970,300000 //Emergency_Scroll3
12968,300000 //Emergency_Scroll1 //! CHECKME: Need confirmation!
12969,300000 //Emergency_Scroll2 //! CHECKME: Need confirmation!
12970,300000 //Emergency_Scroll3 //! CHECKME: Need confirmation!

View File

@ -6556,7 +6556,7 @@
12681,Nestea_Lemon,Nestea Lemon,2,0,,50,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}
12682,Nestea_Blacktea,Nestea Black Tea,2,0,,30,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}
12683,Sg_Vi_Potion_Box200,Siege Violet Potion Box (200),2,20,,200,,,,,0xFFFFFFFF,63,2,,,,,,{ getitem 11547,200; },{},{}
12684,ASPD_Potion,ASPD Potion,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}
12684,ASPD_Potion,ASPD Potion,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_HASTEATTACK_CASH,900000,3; },{},{}
12685,Gryphon_Egg_Scroll,Gryphon Egg Scroll,2,20,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}
12686,Str_Dish20,Str Dish20,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}
12687,Int_Dish20,Int Dish20,2,0,,10,,,,,0xFFFFFFFF,63,2,,,,,,{},{},{}
@ -9883,7 +9883,7 @@
22064,Thorny_Shoes,Thorny Shoes,4,0,,1000,,25,,1,0xFFFFFFFF,63,2,64,,,1,,{ bonus bShortWeaponDamageReturn,getrefine()/2; },{},{}
22067,Shoe_of_Witch,Shoe of Witch,4,10,,400,,10,,0,0xFFFFFFFE,63,2,64,,1,1,,{ skill "ALL_CATCRY",1,1; },{},{}
//
22508,Para_Team_Mark_,Eden Group Mark,11,0,,0,,,,,,,,,,,,,{},{},{}
22508,Para_Team_Mark_,Eden Group Mark,11,0,,0,,,,0,0xFFFFFFFF,63,2,,,,,,{ /*itemskill "AL_TELEPORT",3;*/ unitskilluseid getcharid(3),"AL_TELEPORT",3; },{},{}
22507,Worn-Out-Scroll,Worn-Out-Scroll,3,10,,10,,,,0,,,,,,,,,{},{},{}
22510,King_Wolf_Scroll,King Wolf Scroll,2,10,,10,,,,0,0xFFFFFFFF,63,2,,,,,,{ /*TODO, confirm the rates*/ getitem callfunc("F_Rand",6635,19598,5658,6238,6239),1; },{},{}
22513,King_of_Gift_Box,King of Gift Box,2,10,,100,,,,0,0xFFFFFFFF,63,2,,,,,,{ /*TODO, confirm the rates*/ getitem callfunc("F_Rand",12817,4403,14512),1; },{},{}

View File

@ -1,41 +1,91 @@
// Item Delay Database
//
// Structure of Database:
// Item ID,Delay in Milliseconds
// <ItemID>,<Delay>{,<SC_GroupID>}
//
// NOTE:
// There is a max concurrent number of entries set in src/map/itemdb.h as MAX_ITEMDELAYS.
// <ItemID>
// ID of item that will has reuse delay.
// <Delay>
// Re-use delay in milliseconds.
// <SC_GroupID>
// SC (status change) group for the item.
// Example for SC_REUSE_LIMIT_MTF
// 12658,10000,620 // Transformation Scroll(Deviruchi)
// 12659,10000,620 // Transformation Scroll(Raydric)
// -> 12658 has reuse delay for 10 seconds, and also,
// 12659 cannot be used when this delay is active.
// Since this is optional, default is -1 will ignores the
// delay group and the delay will be stored in character's
// data that has limit set in src/map/itemdb.h as MAX_ITEMDELAYS.
// SC_REUSE_REFRESH 317
12725,120000,317 //Runstone_Nosiege
// SC_REUSE_LIMIT_A 609
14538,300000,608 //Glass_Of_Illusion
// SC_REUSE_LIMIT_B 610
12596,180000,609 //Magic_Candy
14586,180000,609 //Spark_Candy
// SC_REUSE_LIMIT_C 611
12208,60000,610 //Battle_Manual
// SC_REUSE_LIMIT_D 612
12210,60000,611 //Bubble_Gum
// SC_REUSE_LIMIT_E 613
11522,1000,612 //Red_Raffle_Sap
11523,2000,612 //Yellow_Raffle_Sap
11524,3000,612 //White_Raffle_Sap
// SC_REUSE_LIMIT_F 614
607,5000,613 //Yggdrasil_Berry
// SC_REUSE_LIMIT_G 615
608,3000,614 //Yggdrasil_Seed
22559,3000,614 //Mock_Strawberry
// SC_REUSE_LIMIT_H 616
11525,5000,615 //Mora_Hip_Tea
// SC_REUSE_LIMIT_ASPD_POTION 617
//12684,0,616 //ASPD_Potion //! CHECKME: Need confirmation!
// SC_REUSE_LIMIT_MTF 618
12658,10000,620 //Transformation Scroll(Deviruchi)
12659,10000,620 //Transformation Scroll(Raydric)
12660,10000,620 //Transformation Scroll(Mavka)
12661,10000,620 //Transformation Scroll(Marduk)
12662,10000,620 //Transformation Scroll(Banshee)
12663,10000,620 //Transformation Scroll(Poring)
12664,10000,620 //Transformation Scroll(Golem)
// SC_ALL_RIDING_REUSE_LIMIT 619
12622,3000,621 //Boarding_Halter
// SC_SEARCH_STORE_INFO 620
12580,0,624 //Vending_Search_Scroll
12581,0,624 //Vending_Search_Scroll2
12591,0,624 //Uni_Catalog_Bz
// SC_REUSE_MILLENNIUMSHIELD 621
12727,60000,625 //Runstone_Verkana
// SC_REUSE_CRUSHSTRIKE 622
12726,30000,626 //Runstone_Rhydo
// SC_REUSE_STORMBLAST 623
12732,1000,627 //Runstone_Pertz
// Misc
//12202,60000 //Str_Dish10_
//12203,60000 //Agi_Dish10_
//12204,60000 //Int_Dish10_
//12205,60000 //Dex_Dish10_
//12206,60000 //Luk_Dish10_
//12207,60000 //Vit_Dish10_
12208,60000 //Battle_Manual
12210,60000 //Bubble_Gum
14538,300000 //Glass_Of_Illusion
607,5000 //Yggdrasil_Berry
608,3000 //Yggdrasil_Seed
// Bifrost Items
11522,1000 //Red_Raffle_Sap
11523,2000 //Yellow_Raffle_Sap
11524,3000 //White_Raffle_Sap
11525,5000 //Mora_Hip_Tea
12658,10000 //Transformation Scroll(Deviruchi)
12659,10000 //Transformation Scroll(Raydric)
12660,10000 //Transformation Scroll(Mavka)
12661,10000 //Transformation Scroll(Marduk)
12662,10000 //Transformation Scroll(Banshee)
12663,10000 //Transformation Scroll(Poring)
12664,10000 //Transformation Scroll(Golem)
// FIX ME! Delays need confirmation.
12968,300000 //Emergency_Scroll1
12969,300000 //Emergency_Scroll2
12970,300000 //Emergency_Scroll3
12596,300000 //Magic_Candy
14586,300000 //Spark_Candy
12968,300000 //Emergency_Scroll1 //! CHECKME: Need confirmation!
12969,300000 //Emergency_Scroll2 //! CHECKME: Need confirmation!
12970,300000 //Emergency_Scroll3 //! CHECKME: Need confirmation!
22508,7200000 //Para_Team_Mark_

View File

@ -6587,7 +6587,7 @@ REPLACE INTO `item_db_re` VALUES (12680,'Sg_Blue_Potion_Box','Siege Blue Potion
REPLACE INTO `item_db_re` VALUES (12681,'Nestea_Lemon','Nestea Lemon',2,0,NULL,50,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (12682,'Nestea_Blacktea','Nestea Black Tea',2,0,NULL,30,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (12683,'Sg_Vi_Potion_Box200','Siege Violet Potion Box (200)',2,20,NULL,200,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'getitem 11547,200;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (12684,'ASPD_Potion','ASPD Potion',2,0,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (12684,'ASPD_Potion','ASPD Potion',2,0,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_HASTEATTACK_CASH,900000,3;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (12685,'Gryphon_Egg_Scroll','Gryphon Egg Scroll',2,20,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (12686,'Str_Dish20','Str Dish20',2,0,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (12687,'Int_Dish20','Int Dish20',2,0,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
@ -9914,7 +9914,7 @@ REPLACE INTO `item_db_re` VALUES (22059,'Aegir_Shoes','Aegir Shoes',4,10,NULL,30
REPLACE INTO `item_db_re` VALUES (22064,'Thorny_Shoes','Thorny Shoes',4,0,NULL,1000,NULL,25,NULL,1,0xFFFFFFFF,63,2,64,NULL,NULL,1,NULL,'bonus bShortWeaponDamageReturn,getrefine()/2;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22067,'Shoe_of_Witch','Shoe of Witch',4,10,NULL,400,NULL,10,NULL,0,0xFFFFFFFE,63,2,64,NULL,'1',1,NULL,'skill "ALL_CATCRY",1,1;',NULL,NULL);
#
REPLACE INTO `item_db_re` VALUES (22508,'Para_Team_Mark_','Eden Group Mark',11,0,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22508,'Para_Team_Mark_','Eden Group Mark',11,0,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'/*itemskill "AL_TELEPORT",3;*/ unitskilluseid getcharid(3),"AL_TELEPORT",3;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22507,'Worn-Out-Scroll','Worn-Out-Scroll',3,10,NULL,10,NULL,NULL,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22510,'King_Wolf_Scroll','King Wolf Scroll',2,10,NULL,10,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'/*TODO, confirm the rates*/ getitem callfunc("F_Rand",6635,19598,5658,6238,6239),1;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (22513,'King_of_Gift_Box','King of Gift Box',2,10,NULL,100,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'/*TODO, confirm the rates*/ getitem callfunc("F_Rand",12817,4403,14512),1;',NULL,NULL);

View File

@ -428,6 +428,7 @@ enum clif_messages {
ITEM_PRODUCE_SUCCESS = 0x627,
ITEM_PRODUCE_FAIL = 0x628,
ITEM_UNIDENTIFIED = 0x62d,
ITEM_REUSE_LIMIT = 0x746,
USAGE_FAIL = 0x783,
NEED_REINS_OF_MOUNT = 0x78c,
};

View File

@ -786,6 +786,11 @@ static bool itemdb_read_itemdelay(char* str[], int columns, int current) {
id->delay = delay;
if (columns == 2)
id->delay_sc = SC_NONE;
else
id->delay_sc = (sc_type)atoi(str[2]);
return true;
}
@ -1602,7 +1607,7 @@ static void itemdb_read(void) {
itemdb_read_combos(dbsubpath2,i); //TODO change this to sv_read ? id#script ?
sv_readdb(dbsubpath2, "item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip, i);
sv_readdb(dbsubpath2, "item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade, i);
sv_readdb(dbsubpath2, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay, i);
sv_readdb(dbsubpath2, "item_delay.txt", ',', 2, 3, -1, &itemdb_read_itemdelay, i);
sv_readdb(dbsubpath2, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore, i);
sv_readdb(dbsubpath2, "item_flag.txt", ',', 2, 2, -1, &itemdb_read_flag, i);
aFree(dbsubpath1);

View File

@ -450,6 +450,7 @@ struct item_data
/* bugreport:309 */
struct item_combo **combos;
unsigned char combos_count;
enum sc_type delay_sc; ///< Use delay group if any instead using player's item_delay data [Cydh]
};
struct item_data* itemdb_searchname(const char *name);

View File

@ -4768,41 +4768,8 @@ int pc_useitem(struct map_session_data *sd,int n)
if( id->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status_check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
return 0;
if( id->delay > 0 && !pc_has_permission(sd,PC_PERM_ITEM_UNCONDITIONAL) ) {
int i;
ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid );
if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */
ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid );
if( i < MAX_ITEMDELAYS ) {
if( sd->item_delay[i].nameid ) {// found
if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) {
int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000;
char e_msg[CHAT_SIZE_MAX];
if( e_tick > 99 )
sprintf(e_msg,msg_txt(sd,379), // Item Failed. [%s] is cooling down. Wait %.1f minutes.
itemdb_jname(sd->item_delay[i].nameid), (double)e_tick / 60);
else
sprintf(e_msg,msg_txt(sd,380), // Item Failed. [%s] is cooling down. Wait %d seconds.
itemdb_jname(sd->item_delay[i].nameid), e_tick+1);
clif_colormes(sd->fd,color_table[COLOR_YELLOW],e_msg);
return 0; // Delay has not expired yet
}
} else {// not yet used item (all slots are initially empty)
sd->item_delay[i].nameid = nameid;
}
if( !(nameid == ITEMID_REINS_OF_MOUNT && sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR)) )
sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay;
} else {// should not happen
ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%hu, char_id=%d)\n", nameid, sd->status.char_id);
}
//clean up used delays so we can give room for more
for(i = 0; i < MAX_ITEMDELAYS; i++) {
if( DIFF_TICK(sd->item_delay[i].tick, tick) <= 0 ) {
sd->item_delay[i].tick = 0;
sd->item_delay[i].nameid = 0;
}
}
}
if( id->delay > 0 && !pc_has_permission(sd,PC_PERM_ITEM_UNCONDITIONAL) && pc_itemcd_check(sd, id, tick, n))
return 0;
/* on restricted maps the item is consumed but the effect is not used */
if (!pc_has_permission(sd,PC_PERM_ITEM_UNCONDITIONAL) && itemdb_isNoEquip(id,sd->bl.m)) {
@ -10967,13 +10934,14 @@ int pc_read_motd(void)
return 0;
}
void pc_itemcd_do(struct map_session_data *sd, bool load) {
int i,cursor = 0;
struct item_cd* cd = NULL;
if( load ) {
if( !(cd = idb_get(itemcd_db, sd->status.char_id)) ) {
// no skill cooldown is associated with this character
// no item cooldown is associated with this character
return;
}
for(i = 0; i < MAX_ITEMDELAYS; i++) {
@ -11001,6 +10969,82 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
return;
}
/**
* Add item delay to player's item delay data
* @param sd Player
* @param id Item data
* @param tick Current tick
* @param n Item index in inventory
* @return 0: No delay, can consume item.
* 1: Has delay, cancel consumption.
**/
uint8 pc_itemcd_add(struct map_session_data *sd, struct item_data *id, unsigned int tick, unsigned short n) {
int i;
ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == id->nameid );
if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */
ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid );
if( i < MAX_ITEMDELAYS ) {
if( sd->item_delay[i].nameid ) {// found
if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) {
int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000;
char e_msg[CHAT_SIZE_MAX];
if( e_tick > 99 )
sprintf(e_msg,msg_txt(sd,379), // Item Failed. [%s] is cooling down. Wait %.1f minutes.
itemdb_jname(sd->item_delay[i].nameid), (double)e_tick / 60);
else
sprintf(e_msg,msg_txt(sd,380), // Item Failed. [%s] is cooling down. Wait %d seconds.
itemdb_jname(sd->item_delay[i].nameid), e_tick+1);
clif_colormes(sd->fd,color_table[COLOR_YELLOW],e_msg);
return 1; // Delay has not expired yet
}
} else {// not yet used item (all slots are initially empty)
sd->item_delay[i].nameid = id->nameid;
}
if( !(id->nameid == ITEMID_REINS_OF_MOUNT && sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR)) )
sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay;
} else {// should not happen
ShowError("pc_itemcd_add: Exceeded item delay array capacity! (nameid=%hu, char_id=%d)\n", id->nameid, sd->status.char_id);
}
//clean up used delays so we can give room for more
for(i = 0; i < MAX_ITEMDELAYS; i++) {
if( DIFF_TICK(sd->item_delay[i].tick, tick) <= 0 ) {
sd->item_delay[i].tick = 0;
sd->item_delay[i].nameid = 0;
}
}
return 0;
}
/**
* Check if player has delay to reuse item
* @param sd Player
* @param id Item data
* @param tick Current tick
* @param n Item index in inventory
* @return 0: No delay, can consume item.
* 1: Has delay, cancel consumption.
**/
uint8 pc_itemcd_check(struct map_session_data *sd, struct item_data *id, unsigned int tick, unsigned short n) {
struct status_change *sc = NULL;
nullpo_retr(0, sd);
nullpo_retr(0, id);
// Do normal delay assignment
if (id->delay_sc <= SC_NONE || id->delay_sc >= SC_MAX || !(sc = &sd->sc))
return pc_itemcd_add(sd, id, tick, n);
// Send reply of delay remains
if (sc->data[id->delay_sc]) {
const struct TimerData *timer = get_timer(sc->data[id->delay_sc]->timer);
clif_msg_value(sd, ITEM_REUSE_LIMIT, timer ? DIFF_TICK(timer->tick, tick) / 1000 : 99);
return 1;
}
sc_start(&sd->bl, &sd->bl, id->delay_sc, 100, id->nameid, id->delay);
return 0;
}
/**
* Clear the dmglog data from player
* @param sd

View File

@ -1153,6 +1153,8 @@ void pc_overheat(struct map_session_data *sd, int val);
int pc_banding(struct map_session_data *sd, uint16 skill_lv);
void pc_itemcd_do(struct map_session_data *sd, bool load);
uint8 pc_itemcd_add(struct map_session_data *sd, struct item_data *id, unsigned int tick, unsigned short n);
uint8 pc_itemcd_check(struct map_session_data *sd, struct item_data *id, unsigned int tick, unsigned short n);
int pc_load_combo(struct map_session_data *sd);

View File

@ -10575,6 +10575,12 @@ BUILDIN_FUNC(sc_end)
case SC_MTF_MSP:
case SC_MTF_PUMPKIN:
case SC_MTF_HITFLEE:
case SC_ATTHASTE_CASH:
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT: case SC_REUSE_REFRESH:
return 0;
default:
break;

View File

@ -1700,6 +1700,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case SC_MTF_ASPD2: case SC_MTF_RANGEATK2: case SC_MTF_MATK2:
case SC_2011RWC_SCROLL: case SC_JP_EVENT04: case SC_MTF_MHP:
case SC_MTF_MSP: case SC_MTF_PUMPKIN: case SC_MTF_HITFLEE:
case SC_ATTHASTE_CASH: case SC_REUSE_REFRESH:
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
continue;
case SC_WHISTLE: case SC_ASSNCROS: case SC_POEMBRAGI:
case SC_APPLEIDUN: case SC_HUMMING: case SC_DONTFORGETME:
@ -7440,6 +7446,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SC_MTF_ASPD2: case SC_MTF_RANGEATK2: case SC_MTF_MATK2:
case SC_2011RWC_SCROLL: case SC_JP_EVENT04: case SC_MTF_MHP:
case SC_MTF_MSP: case SC_MTF_PUMPKIN: case SC_MTF_HITFLEE:
case SC_ATTHASTE_CASH: case SC_REUSE_REFRESH:
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
continue;
//bugreport:4888 these songs may only be dispelled if you're not in their song area anymore
case SC_WHISTLE:
@ -8922,6 +8934,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SC_MTF_ASPD2: case SC_MTF_RANGEATK2: case SC_MTF_MATK2:
case SC_2011RWC_SCROLL: case SC_JP_EVENT04: case SC_MTF_MHP:
case SC_MTF_MSP: case SC_MTF_PUMPKIN: case SC_MTF_HITFLEE:
case SC_ATTHASTE_CASH: case SC_REUSE_REFRESH:
case SC_REUSE_LIMIT_A: case SC_REUSE_LIMIT_B: case SC_REUSE_LIMIT_C:
case SC_REUSE_LIMIT_D: case SC_REUSE_LIMIT_E: case SC_REUSE_LIMIT_F:
case SC_REUSE_LIMIT_G: case SC_REUSE_LIMIT_H: case SC_REUSE_LIMIT_MTF:
case SC_REUSE_LIMIT_ASPD_POTION: case SC_REUSE_MILLENNIUMSHIELD: case SC_REUSE_CRUSHSTRIKE:
case SC_REUSE_STORMBLAST: case SC_ALL_RIDING_REUSE_LIMIT:
continue;
case SC_ASSUMPTIO:
if( bl->type == BL_MOB )

View File

@ -886,6 +886,7 @@ void initChangeTables(void)
StatusIconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION;
StatusIconChangeTable[SC_SPCOST_RATE] = SI_ATKER_BLOOD;
StatusIconChangeTable[SC_COMMONSC_RESIST] = SI_TARGET_BLOOD;
StatusIconChangeTable[SC_ATTHASTE_CASH] = SI_ATTHASTE_CASH;
/* Mercenary Bonus Effects */
StatusIconChangeTable[SC_MERC_FLEEUP] = SI_MERC_FLEEUP;
@ -1007,6 +1008,23 @@ void initChangeTables(void)
StatusIconChangeTable[SC_MTF_MSP] = SI_MTF_MSP;
StatusIconChangeTable[SC_MTF_PUMPKIN] = SI_MTF_PUMPKIN;
// Item Reuse Limits
StatusIconChangeTable[SC_REUSE_REFRESH] = SI_REUSE_REFRESH;
StatusIconChangeTable[SC_REUSE_LIMIT_A] = SI_REUSE_LIMIT_A;
StatusIconChangeTable[SC_REUSE_LIMIT_B] = SI_REUSE_LIMIT_B;
StatusIconChangeTable[SC_REUSE_LIMIT_C] = SI_REUSE_LIMIT_C;
StatusIconChangeTable[SC_REUSE_LIMIT_D] = SI_REUSE_LIMIT_D;
StatusIconChangeTable[SC_REUSE_LIMIT_E] = SI_REUSE_LIMIT_E;
StatusIconChangeTable[SC_REUSE_LIMIT_F] = SI_REUSE_LIMIT_F;
StatusIconChangeTable[SC_REUSE_LIMIT_G] = SI_REUSE_LIMIT_G;
StatusIconChangeTable[SC_REUSE_LIMIT_H] = SI_REUSE_LIMIT_H;
StatusIconChangeTable[SC_REUSE_LIMIT_MTF] = SI_REUSE_LIMIT_MTF;
StatusIconChangeTable[SC_REUSE_LIMIT_ASPD_POTION] = SI_REUSE_LIMIT_ASPD_POTION;
StatusIconChangeTable[SC_REUSE_MILLENNIUMSHIELD] = SI_REUSE_MILLENNIUMSHIELD;
StatusIconChangeTable[SC_REUSE_CRUSHSTRIKE] = SI_REUSE_CRUSHSTRIKE;
StatusIconChangeTable[SC_REUSE_STORMBLAST] = SI_REUSE_STORMBLAST;
StatusIconChangeTable[SC_ALL_RIDING_REUSE_LIMIT] = SI_ALL_RIDING_REUSE_LIMIT;
/* Other SC which are not necessarily associated to skills */
StatusChangeFlagTable[SC_ASPDPOTION0] |= SCB_ASPD;
StatusChangeFlagTable[SC_ASPDPOTION1] |= SCB_ASPD;
@ -1064,6 +1082,7 @@ void initChangeTables(void)
StatusChangeFlagTable[SC_FOOD_DEX_CASH] |= SCB_DEX;
StatusChangeFlagTable[SC_FOOD_INT_CASH] |= SCB_INT;
StatusChangeFlagTable[SC_FOOD_LUK_CASH] |= SCB_LUK;
StatusChangeFlagTable[SC_ATTHASTE_CASH] |= SCB_ASPD;
/* Mercenary Bonus Effects */
StatusChangeFlagTable[SC_MERC_FLEEUP] |= SCB_FLEE;
@ -6255,6 +6274,9 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
sc->data[i=SC_ASPDPOTION0])
pots += sc->data[i]->val1;
if (sc->data[SC_ATTHASTE_CASH])
pots += sc->data[SC_ATTHASTE_CASH]->val1;
if( !sc->data[SC_QUAGMIRE] ) {
if(sc->data[SC_TWOHANDQUICKEN] && skills1 < 7)
skills1 = 7;
@ -6478,6 +6500,9 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
sc->data[i=SC_ASPDPOTION0] )
aspd_rate -= sc->data[i]->val2;
if (sc->data[SC_ATTHASTE_CASH])
aspd_rate -= sc->data[SC_ATTHASTE_CASH]->val2;
if(sc->data[SC_DONTFORGETME])
aspd_rate += sc->data[SC_DONTFORGETME]->val2;
if(sc->data[SC_LONGING])
@ -8539,6 +8564,21 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC__WEAKNESS:
case SC__UNLUCKY:
//case SC__CHAOS:
case SC_REUSE_REFRESH:
case SC_REUSE_LIMIT_A:
case SC_REUSE_LIMIT_B:
case SC_REUSE_LIMIT_C:
case SC_REUSE_LIMIT_D:
case SC_REUSE_LIMIT_E:
case SC_REUSE_LIMIT_F:
case SC_REUSE_LIMIT_G:
case SC_REUSE_LIMIT_H:
case SC_REUSE_LIMIT_MTF:
case SC_REUSE_LIMIT_ASPD_POTION:
case SC_REUSE_MILLENNIUMSHIELD:
case SC_REUSE_CRUSHSTRIKE:
case SC_REUSE_STORMBLAST:
case SC_ALL_RIDING_REUSE_LIMIT:
return 0;
case SC_COMBO:
case SC_DANCING:
@ -8552,6 +8592,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
case SC_ENCHANTARMS:
case SC_ARMOR_ELEMENT:
case SC_ARMOR_RESIST:
case SC_ATTHASTE_CASH:
break;
case SC_GOSPEL:
// Must not override a casting gospel char.
@ -8841,6 +8882,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
val2 = 50*(2+type-SC_ASPDPOTION0);
break;
case SC_ATTHASTE_CASH:
val2 = 50*val1; // Just custom for pre-re
break;
case SC_NOCHAT:
// A hardcoded interval of 60 seconds is expected, as the time that SC_NOCHAT uses is defined by
// mmocharstatus.manner, each negative point results in 1 minute with this status activated.
@ -10771,6 +10816,22 @@ int status_change_clear(struct block_list* bl, int type)
case SC_QUEST_BUFF3:
case SC_2011RWC_SCROLL:
case SC_JP_EVENT04:
case SC_ATTHASTE_CASH:
case SC_REUSE_REFRESH:
case SC_REUSE_LIMIT_A:
case SC_REUSE_LIMIT_B:
case SC_REUSE_LIMIT_C:
case SC_REUSE_LIMIT_D:
case SC_REUSE_LIMIT_E:
case SC_REUSE_LIMIT_F:
case SC_REUSE_LIMIT_G:
case SC_REUSE_LIMIT_H:
case SC_REUSE_LIMIT_MTF:
case SC_REUSE_LIMIT_ASPD_POTION:
case SC_REUSE_MILLENNIUMSHIELD:
case SC_REUSE_CRUSHSTRIKE:
case SC_REUSE_STORMBLAST:
case SC_ALL_RIDING_REUSE_LIMIT:
continue;
}
}
@ -12652,6 +12713,22 @@ void status_change_clear_buffs (struct block_list* bl, int type)
case SC_MTF_MSP:
case SC_MTF_PUMPKIN:
case SC_MTF_HITFLEE:
case SC_ATTHASTE_CASH:
case SC_REUSE_REFRESH:
case SC_REUSE_LIMIT_A:
case SC_REUSE_LIMIT_B:
case SC_REUSE_LIMIT_C:
case SC_REUSE_LIMIT_D:
case SC_REUSE_LIMIT_E:
case SC_REUSE_LIMIT_F:
case SC_REUSE_LIMIT_G:
case SC_REUSE_LIMIT_H:
case SC_REUSE_LIMIT_MTF:
case SC_REUSE_LIMIT_ASPD_POTION:
case SC_REUSE_MILLENNIUMSHIELD:
case SC_REUSE_CRUSHSTRIKE:
case SC_REUSE_STORMBLAST:
case SC_ALL_RIDING_REUSE_LIMIT:
continue;
// Debuffs that can be removed.

View File

@ -716,6 +716,23 @@ typedef enum sc_type {
SC_MTF_HITFLEE,
SC_CRIFOOD,
SC_ATTHASTE_CASH,
// Item Reuse Limits
SC_REUSE_LIMIT_A,
SC_REUSE_LIMIT_B,
SC_REUSE_LIMIT_C,
SC_REUSE_LIMIT_D,
SC_REUSE_LIMIT_E,
SC_REUSE_LIMIT_F,
SC_REUSE_LIMIT_G,
SC_REUSE_LIMIT_H,
SC_REUSE_LIMIT_MTF,
SC_REUSE_LIMIT_ASPD_POTION,
SC_REUSE_MILLENNIUMSHIELD,
SC_REUSE_CRUSHSTRIKE,
SC_REUSE_STORMBLAST,
SC_ALL_RIDING_REUSE_LIMIT,
#ifdef RENEWAL
SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled
@ -1029,14 +1046,14 @@ enum si_type {
SI_ATKER_BLOOD = 300,
SI_TARGET_BLOOD = 301,
SI_ARMOR_PROPERTY = 302,
// SI_REUSE_LIMIT_A = 303,
SI_REUSE_LIMIT_A = 303,
SI_HELLPOWER = 304,
SI_STEAMPACK = 305,
// SI_REUSE_LIMIT_B = 306,
// SI_REUSE_LIMIT_C = 307,
// SI_REUSE_LIMIT_D = 308,
// SI_REUSE_LIMIT_E = 309,
// SI_REUSE_LIMIT_F = 310,
SI_REUSE_LIMIT_B = 306,
SI_REUSE_LIMIT_C = 307,
SI_REUSE_LIMIT_D = 308,
SI_REUSE_LIMIT_E = 309,
SI_REUSE_LIMIT_F = 310,
SI_INVINCIBLE = 311,
SI_CASH_PLUSONLYJOBEXP = 312,
SI_PARTYFLEE = 313,