|
@@ -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]
|
|
|
|