Browse Source

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://svn.code.sf.net/p/rathena/svn/trunk@15762 54d463be-8e91-2dee-dedb-b68131a5f0ec

shennetsind 13 years ago
parent
commit
f8ddb21f74
4 changed files with 92 additions and 18 deletions
  1. 1 1
      src/map/itemdb.c
  2. 3 0
      src/map/map.c
  3. 83 16
      src/map/pc.c
  4. 5 1
      src/map/pc.h

+ 1 - 1
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);
 }
 

+ 3 - 0
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, 

+ 83 - 16
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]
 

+ 5 - 1
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_ */