summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/itemdb.c2
-rw-r--r--src/map/map.c3
-rw-r--r--src/map/pc.c99
-rw-r--r--src/map/pc.h6
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_ */