From 5fb385aef1e83cef546ea69b1b06feb00b8e5a73 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 22 Mar 2012 07:37:23 +0000 Subject: Rehashed Item_delay.txt (bugreport:5487) - Before you could only have MAX_ITEMDELAYS (10) items with delays. Now: you can have up to MAX_ITEMDELAYS (10) concurrent delays. and of course you can always increase MAX_ITEMDELAYS in src/map/itemdb.h as much as you may need. - Item delays are no longer lost on logout, they're persistent until server restarts. - When a item use is denied due to delay still up a message now tells the user why he can't use the item (before would leave the user wondering wtf was going on. it had no response) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@15762 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/itemdb.c | 2 +- src/map/map.c | 3 ++ src/map/pc.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++--------- src/map/pc.h | 6 +++- 4 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 03de87081..3523ea7ef 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1038,7 +1038,7 @@ static void itemdb_read(void) sv_readdb(db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail); sv_readdb(db_path, "item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip); sv_readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade); - sv_readdb(db_path, "item_delay.txt", ',', 2, 2, MAX_ITEMDELAYS, &itemdb_read_itemdelay); + sv_readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay); sv_readdb(db_path, "item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore); } diff --git a/src/map/map.c b/src/map/map.c index 30e766402..d7be8e5a7 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1671,6 +1671,9 @@ int map_quit(struct map_session_data *sd) if( sd->bg_id ) bg_team_leave(sd,1); + + pc_itemcd_do(sd,false); + npc_script_event(sd, NPCE_LOGOUT); //Unit_free handles clearing the player related data, diff --git a/src/map/pc.c b/src/map/pc.c index 67c49b9fe..a81300b9e 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -73,6 +73,19 @@ const struct sg_data sg_info[MAX_PC_FEELHATE] = { { SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star } }; +/** + * Item Cool Down Delay Saving + * Struct item_cd is not a member of struct map_session_data + * to keep cooldowns in memory between player log-ins. + * All cooldowns are reset when server is restarted. + **/ +DBMap* itemcd_db = NULL; // char_id -> struct skill_cd +struct item_cd { + unsigned int tick[MAX_ITEMDELAYS];//tick + short nameid[MAX_ITEMDELAYS];//skill id +}; + + //Converts a class to its array index for CLASS_COUNT defined arrays. //Note that it does not do a validity check for speed purposes, where parsing //player input make sure to use a pcdb_checkid first! @@ -1072,6 +1085,11 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim **/ skill_cooldown_load(sd); + /** + * Check if player have any item cooldowns on + **/ + pc_itemcd_do(sd,true); + // Request all registries (auth is considered completed whence they arrive) intif_request_registry(sd,7); return true; @@ -3995,23 +4013,36 @@ int pc_useitem(struct map_session_data *sd,int n) if( sd->inventory_data[n]->delay > 0 ) { // Check if there is a delay on this item [Paradox924X] ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid || !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 ) + 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[100]; + if( e_tick > 99 ) + sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %.1f minutes.", + itemdb_jname(sd->status.inventory[n].nameid), + (double)e_tick / 60); + else + sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %d seconds.", + itemdb_jname(sd->status.inventory[n].nameid), + e_tick); + clif_colormes(sd,COLOR_RED,e_msg); return 0; // Delay has not expired yet - } - else - {// not yet used item (all slots are initially empty) + } + } else {// not yet used item (all slots are initially empty) sd->item_delay[i].nameid = nameid; } sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay; - } - else - {// should not happen + } else {// should not happen ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, 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; + } + } } sd->itemid = sd->status.inventory[n].nameid; @@ -8700,18 +8731,54 @@ 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 + return; + } + for(i = 0; i < MAX_ITEMDELAYS; i++) { + if( cd->nameid[i] && DIFF_TICK(gettick(),cd->tick[i]) < 0 ) { + sd->item_delay[cursor].tick = cd->tick[i]; + sd->item_delay[cursor].nameid = cd->nameid[i]; + cursor++; + } + } + idb_remove(itemcd_db,sd->status.char_id); + } else { + if( !(cd = idb_get(itemcd_db,sd->status.char_id)) ) { + // create a new skill cooldown object for map storage + CREATE( cd, struct item_cd, 1 ); + idb_put( itemcd_db, sd->status.char_id, cd ); + } + for(i = 0; i < MAX_ITEMDELAYS; i++) { + if( sd->item_delay[i].nameid && DIFF_TICK(gettick(),sd->item_delay[i].tick) < 0 ) { + cd->tick[cursor] = sd->item_delay[i].tick; + cd->nameid[cursor] = sd->item_delay[i].nameid; + cursor++; + } + } + } + return; +} /*========================================== * pc? W *------------------------------------------*/ -void do_final_pc(void) -{ +void do_final_pc(void) { + + db_destroy(itemcd_db); + do_final_pc_groups(); return; } -int do_init_pc(void) -{ +int do_init_pc(void) { + + itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA); + pc_readdb(); pc_read_motd(); // Read MOTD [Valaris] diff --git a/src/map/pc.h b/src/map/pc.h index a035092b5..8d8e9e7e0 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -218,7 +218,7 @@ struct map_session_data { unsigned int ks_floodprotect_tick; // [Kill Steal Protection] struct { - int nameid; + short nameid; unsigned int tick; } item_delay[MAX_ITEMDELAYS]; // [Paradox924X] @@ -897,4 +897,8 @@ void pc_overheat(struct map_session_data *sd, int val); * Royal Guard **/ int pc_banding(struct map_session_data *sd, short skill_lv); +/** + * Item Cooldown persistency + **/ +void pc_itemcd_do(struct map_session_data *sd, bool load); #endif /* _PC_H_ */ -- cgit v1.2.3-70-g09d2