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
This commit is contained in:
shennetsind 2012-03-22 07:37:23 +00:00
parent b3b6616733
commit f8ddb21f74
4 changed files with 92 additions and 18 deletions

View File

@ -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);
}

View File

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

View File

@ -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<EFBFBD>Šú»
*------------------------------------------*/
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]

View File

@ -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_ */