Skill_colldown
Move skillcooldown from ram saving to sql saving. This will fix multimap skillcooldown and avoind increasing ram by offline users.
This commit is contained in:
parent
9a5a6b9e6e
commit
69b28292cf
@ -1,3 +1,17 @@
|
||||
|
||||
--
|
||||
-- Table structure for table `skillcooldown`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `skillcooldown` (
|
||||
`account_id` int(11) unsigned NOT NULL,
|
||||
`char_id` int(11) unsigned NOT NULL,
|
||||
`skill` smallint(11) unsigned NOT NULL DEFAULT '0',
|
||||
`tick` int(11) NOT NULL,
|
||||
KEY `account_id` (`account_id`),
|
||||
KEY `char_id` (`char_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
--
|
||||
-- Table structure for table `auction`
|
||||
--
|
||||
|
8
sql-files/upgrades/upgrade_svn17541.sql
Normal file
8
sql-files/upgrades/upgrade_svn17541.sql
Normal file
@ -0,0 +1,8 @@
|
||||
CREATE TABLE IF NOT EXISTS `skillcooldown` (
|
||||
`account_id` int(11) unsigned NOT NULL,
|
||||
`char_id` int(11) unsigned NOT NULL,
|
||||
`skill` smallint(11) unsigned NOT NULL DEFAULT '0',
|
||||
`tick` int(11) NOT NULL,
|
||||
KEY `account_id` (`account_id`),
|
||||
KEY `char_id` (`char_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
@ -39,6 +39,7 @@ static char* msg_table[CHAR_MAX_MSG]; // Login Server messages_conf
|
||||
|
||||
char char_db[256] = "char";
|
||||
char scdata_db[256] = "sc_data";
|
||||
char skillcooldown_db[256] = "skillcooldown";
|
||||
char cart_db[256] = "cart_inventory";
|
||||
char inventory_db[256] = "inventory";
|
||||
char charlog_db[256] = "charlog";
|
||||
@ -2923,6 +2924,51 @@ int parse_frommap(int fd)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2b0a: //Request skillcooldown data
|
||||
if (RFIFOREST(fd) < 10)
|
||||
return 0;
|
||||
{
|
||||
int aid, cid;
|
||||
aid = RFIFOL(fd,2);
|
||||
cid = RFIFOL(fd,6);
|
||||
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT skill, tick FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
|
||||
skillcooldown_db, aid, cid) )
|
||||
{
|
||||
Sql_ShowDebug(sql_handle);
|
||||
break;
|
||||
}
|
||||
if( Sql_NumRows(sql_handle) > 0 )
|
||||
{
|
||||
int count;
|
||||
char* data;
|
||||
struct skill_cooldown_data scd;
|
||||
|
||||
WFIFOHEAD(fd,14 + MAX_SKILLCOOLDOWN * sizeof(struct skill_cooldown_data));
|
||||
WFIFOW(fd,0) = 0x2b0b;
|
||||
WFIFOL(fd,4) = aid;
|
||||
WFIFOL(fd,8) = cid;
|
||||
for( count = 0; count < MAX_SKILLCOOLDOWN && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count )
|
||||
{
|
||||
Sql_GetData(sql_handle, 0, &data, NULL); scd.skill_id = atoi(data);
|
||||
Sql_GetData(sql_handle, 1, &data, NULL); scd.tick = atoi(data);
|
||||
memcpy(WFIFOP(fd,14+count*sizeof(struct skill_cooldown_data)), &scd, sizeof(struct skill_cooldown_data));
|
||||
}
|
||||
if( count >= MAX_SKILLCOOLDOWN )
|
||||
ShowWarning("Too many skillcooldowns for %d:%d, some of them were not loaded.\n", aid, cid);
|
||||
if( count > 0 )
|
||||
{
|
||||
WFIFOW(fd,2) = 14 + count * sizeof(struct skill_cooldown_data);
|
||||
WFIFOW(fd,12) = count;
|
||||
WFIFOSET(fd,WFIFOW(fd,2));
|
||||
//Clear the data once loaded.
|
||||
if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", skillcooldown_db, aid, cid) )
|
||||
Sql_ShowDebug(sql_handle);
|
||||
}
|
||||
}
|
||||
Sql_FreeResult(sql_handle);
|
||||
RFIFOSKIP(fd, 10);
|
||||
}
|
||||
break;
|
||||
case 0x2afe: //set MAP user count
|
||||
if (RFIFOREST(fd) < 4)
|
||||
return 0;
|
||||
@ -3398,6 +3444,37 @@ int parse_frommap(int fd)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2b15: //Request to save skill cooldown data
|
||||
if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
|
||||
return 0;
|
||||
{
|
||||
int count, aid, cid;
|
||||
aid = RFIFOL(fd,4);
|
||||
cid = RFIFOL(fd,8);
|
||||
count = RFIFOW(fd,12);
|
||||
if( count > 0 )
|
||||
{
|
||||
struct skill_cooldown_data data;
|
||||
StringBuf buf;
|
||||
int i;
|
||||
|
||||
StringBuf_Init(&buf);
|
||||
StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `skill`, `tick`) VALUES ", skillcooldown_db);
|
||||
for( i = 0; i < count; ++i )
|
||||
{
|
||||
memcpy(&data,RFIFOP(fd,14+i*sizeof(struct skill_cooldown_data)),sizeof(struct skill_cooldown_data));
|
||||
if( i > 0 )
|
||||
StringBuf_AppendStr(&buf, ", ");
|
||||
StringBuf_Printf(&buf, "('%d','%d','%d','%d')", aid, cid, data.skill_id, data.tick);
|
||||
}
|
||||
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
|
||||
Sql_ShowDebug(sql_handle);
|
||||
StringBuf_Destroy(&buf);
|
||||
}
|
||||
RFIFOSKIP(fd, RFIFOW(fd, 2));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2b23: // map-server alive packet
|
||||
WFIFOHEAD(fd,2);
|
||||
WFIFOW(fd,0) = 0x2b24;
|
||||
|
@ -128,6 +128,7 @@
|
||||
|
||||
#define MAX_FRIENDS 40
|
||||
#define MAX_MEMOPOINTS 3
|
||||
#define MAX_SKILLCOOLDOWN 20
|
||||
|
||||
//Size of the fame list arrays.
|
||||
#define MAX_FAME_LIST 10
|
||||
@ -248,6 +249,11 @@ struct status_change_data {
|
||||
long val1, val2, val3, val4, tick; //Remaining duration.
|
||||
};
|
||||
|
||||
struct skill_cooldown_data {
|
||||
unsigned short skill_id;
|
||||
long tick;
|
||||
};
|
||||
|
||||
struct storage_data {
|
||||
int storage_amount;
|
||||
struct item items[MAX_STORAGE];
|
||||
|
@ -2021,9 +2021,10 @@ static int is_attack_piercing(struct Damage wd, struct block_list *src, struct b
|
||||
sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
|
||||
sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))) )
|
||||
{ //Pass effect onto right hand if configured so. [Skotlex]
|
||||
if (battle_config.left_cardfix_to_right && is_attack_right_handed(src, skill_id))
|
||||
if (battle_config.left_cardfix_to_right && is_attack_right_handed(src, skill_id)){
|
||||
if (weapon_position == EQI_HAND_R)
|
||||
return 1;
|
||||
}
|
||||
else if (weapon_position == EQI_HAND_L)
|
||||
return 1;
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ static DBMap* auth_db; // int id -> struct auth_node*
|
||||
static const int packet_len_table[0x3d] = { // U - used, F - free
|
||||
60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
|
||||
6,-1,18, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
|
||||
6,30, 0, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
|
||||
11,10,10, 0,11, 0,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17
|
||||
6,30, 10, -1,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
|
||||
11,10,10, 0,11, -1,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, U->2b15, U->2b16, U->2b17
|
||||
2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
|
||||
-1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
|
||||
};
|
||||
@ -275,8 +275,10 @@ int chrif_save(struct map_session_data *sd, int flag) {
|
||||
|
||||
if (flag && sd->state.active) { //Store player data which is quitting
|
||||
//FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex]
|
||||
if ( chrif_isconnected() )
|
||||
chrif_save_scdata(sd);
|
||||
if (chrif_isconnected()) {
|
||||
chrif_save_scdata(sd);
|
||||
chrif_skillcooldown_save(sd);
|
||||
}
|
||||
if ( !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) )
|
||||
ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id);
|
||||
}
|
||||
@ -575,8 +577,20 @@ int chrif_scdata_request(int account_id, int char_id) {
|
||||
WFIFOL(char_fd,6) = char_id;
|
||||
WFIFOSET(char_fd,10);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/*==========================================
|
||||
* Request skillcooldown from charserver
|
||||
*------------------------------------------*/
|
||||
int chrif_skillcooldown_request(int account_id, int char_id) {
|
||||
chrif_check(-1);
|
||||
WFIFOHEAD(char_fd, 10);
|
||||
WFIFOW(char_fd, 0) = 0x2b0a;
|
||||
WFIFOL(char_fd, 2) = account_id;
|
||||
WFIFOL(char_fd, 6) = char_id;
|
||||
WFIFOSET(char_fd, 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
@ -1214,6 +1228,44 @@ int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the
|
||||
WFIFOW(char_fd,2) = 14 +count*sizeof(struct status_change_data); //Total packet size
|
||||
WFIFOSET(char_fd,WFIFOW(char_fd,2));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chrif_skillcooldown_save(struct map_session_data *sd) {
|
||||
int i, count = 0;
|
||||
struct skill_cooldown_data data;
|
||||
unsigned int tick;
|
||||
const struct TimerData *timer;
|
||||
|
||||
chrif_check(-1);
|
||||
tick = gettick();
|
||||
|
||||
WFIFOHEAD(char_fd, 14 + MAX_SKILLCOOLDOWN * sizeof (struct skill_cooldown_data));
|
||||
WFIFOW(char_fd, 0) = 0x2b15;
|
||||
WFIFOL(char_fd, 4) = sd->status.account_id;
|
||||
WFIFOL(char_fd, 8) = sd->status.char_id;
|
||||
for (i = 0; i < MAX_SKILLCOOLDOWN; i++) {
|
||||
if (!sd->scd[i])
|
||||
continue;
|
||||
|
||||
if (!battle_config.guild_skill_relog_delay && (sd->scd[i]->skill_id >= GD_BATTLEORDER && sd->scd[i]->skill_id <= GD_EMERGENCYCALL))
|
||||
continue;
|
||||
|
||||
timer = get_timer(sd->scd[i]->timer);
|
||||
if (timer == NULL || timer->func != skill_blockpc_end || DIFF_TICK(timer->tick, tick) < 0)
|
||||
continue;
|
||||
|
||||
data.tick = DIFF_TICK(timer->tick, tick);
|
||||
data.skill_id = sd->scd[i]->skill_id;
|
||||
memcpy(WFIFOP(char_fd, 14 + count * sizeof (struct skill_cooldown_data)), &data, sizeof (struct skill_cooldown_data));
|
||||
count++;
|
||||
}
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
WFIFOW(char_fd, 12) = count;
|
||||
WFIFOW(char_fd, 2) = 14 + count * sizeof (struct skill_cooldown_data);
|
||||
WFIFOSET(char_fd, WFIFOW(char_fd, 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1248,8 +1300,35 @@ int chrif_load_scdata(int fd) {
|
||||
status_change_start(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 1|2|4|8);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
//Retrieve and load skillcooldown for a player
|
||||
|
||||
int chrif_skillcooldown_load(int fd) {
|
||||
struct map_session_data *sd;
|
||||
struct skill_cooldown_data *data;
|
||||
int aid, cid, i, count;
|
||||
|
||||
aid = RFIFOL(fd, 4);
|
||||
cid = RFIFOL(fd, 8);
|
||||
|
||||
|
||||
sd = map_id2sd(aid);
|
||||
if (!sd) {
|
||||
ShowError("chrif_skillcooldown_load: Player of AID %d not found!\n", aid);
|
||||
return -1;
|
||||
}
|
||||
if (sd->status.char_id != cid) {
|
||||
ShowError("chrif_skillcooldown_load: Receiving data for account %d, char id does not matches (%d != %d)!\n", aid, sd->status.char_id, cid);
|
||||
return -1;
|
||||
}
|
||||
count = RFIFOW(fd, 12); //sc_count
|
||||
for (i = 0; i < count; i++) {
|
||||
data = (struct skill_cooldown_data*) RFIFOP(fd, 14 + i * sizeof (struct skill_cooldown_data));
|
||||
skill_blockpc_start(sd, data->skill_id, data->tick);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
@ -1443,6 +1522,7 @@ int chrif_parse(int fd) {
|
||||
case 0x2b04: chrif_recvmap(fd); break;
|
||||
case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
|
||||
case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
|
||||
case 0x2b0b: chrif_skillcooldown_load(fd); break;
|
||||
case 0x2b0d: chrif_changedsex(fd); break;
|
||||
case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break;
|
||||
case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break;
|
||||
|
@ -38,6 +38,9 @@ bool chrif_auth_finished(struct map_session_data* sd);
|
||||
void chrif_authreq(struct map_session_data* sd);
|
||||
void chrif_authok(int fd);
|
||||
int chrif_scdata_request(int account_id, int char_id);
|
||||
int chrif_skillcooldown_request(int account_id, int char_id);
|
||||
int chrif_skillcooldown_save(struct map_session_data *sd);
|
||||
int chrif_skillcooldown_load(int fd);
|
||||
int chrif_save(struct map_session_data* sd, int flag);
|
||||
int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip);
|
||||
int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port);
|
||||
|
@ -856,15 +856,16 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
|
||||
if( i == -1 )
|
||||
return 0; // not a member (inconsistency!)
|
||||
|
||||
online_member_sd = guild_getavailablesd(g);
|
||||
if(online_member_sd == NULL)
|
||||
return 0; // noone online to inform
|
||||
|
||||
#ifdef BOUND_ITEMS
|
||||
//Guild bound item check
|
||||
guild_retrieveitembound(char_id,account_id,guild_id);
|
||||
#endif
|
||||
|
||||
online_member_sd = guild_getavailablesd(g);
|
||||
if(online_member_sd == NULL)
|
||||
return 0; // noone online to inform
|
||||
|
||||
|
||||
if(!flag)
|
||||
clif_guild_leave(online_member_sd, name, mes);
|
||||
else
|
||||
@ -912,15 +913,15 @@ void guild_retrieveitembound(int char_id,int aid,int guild_id)
|
||||
}
|
||||
else { //Character is offline, ask char server to do the job
|
||||
struct guild_storage* stor = guild2storage2(guild_id);
|
||||
struct guild *g = guild_search(guild_id);
|
||||
int i;
|
||||
nullpo_retv(g);
|
||||
if(stor && stor->storage_status == 1) { //Someone is in guild storage, close them
|
||||
struct s_mapiterator* iter = mapit_getallusers();
|
||||
for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) {
|
||||
if(sd->status.guild_id == guild_id && sd->state.storage_flag == 2) {
|
||||
for(i=0; i<g->max_member; i++){
|
||||
TBL_PC *pl_sd = g->member[i].sd;
|
||||
if(pl_sd && pl_sd->state.storage_flag == 2)
|
||||
storage_guild_storageclose(sd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mapit_free(iter);
|
||||
}
|
||||
intif_itembound_req(char_id,aid,guild_id);
|
||||
}
|
||||
@ -1398,7 +1399,7 @@ void guild_block_skill(struct map_session_data *sd, int time)
|
||||
uint16 skill_id[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL };
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
skill_blockpc_start_(sd, skill_id[i], time , true);
|
||||
skill_blockpc_start(sd, skill_id[i], time);
|
||||
}
|
||||
|
||||
/*====================================================
|
||||
|
@ -2182,16 +2182,13 @@ void intif_itembound_req(int char_id,int aid,int guild_id) {
|
||||
WFIFOL(inter_fd,6) = aid;
|
||||
WFIFOW(inter_fd,10) = guild_id;
|
||||
WFIFOSET(inter_fd,12);
|
||||
if(gstor)
|
||||
gstor->lock = 1; //Lock for retrieval process
|
||||
if(gstor) gstor->lock = 1; //Lock for retrieval process
|
||||
}
|
||||
|
||||
//3856
|
||||
void intif_parse_itembound_ack(int fd) {
|
||||
struct guild_storage *gstor;
|
||||
int guild_id = RFIFOW(char_fd,6);
|
||||
|
||||
gstor = guild2storage2(guild_id);
|
||||
int guild_id = RFIFOW(fd,6);
|
||||
struct guild_storage *gstor = guild2storage2(guild_id);
|
||||
if(gstor) gstor->lock = 0; //Unlock now that operation is completed
|
||||
}
|
||||
#endif
|
||||
|
@ -963,7 +963,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
|
||||
}
|
||||
switch(map[m].npc[i]->subtype) {
|
||||
case WARP:
|
||||
if (pc_ishiding(sd) || sd->sc.count && sd->sc.data[SC_CAMOUFLAGE] || pc_isdead(sd))
|
||||
if (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]) || pc_isdead(sd))
|
||||
break; // hidden or dead chars cannot use warps
|
||||
pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,CLR_OUTSIGHT);
|
||||
break;
|
||||
@ -2725,7 +2725,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
|
||||
|
||||
if(!imap)
|
||||
imap = map_mapname2mapid(map[dm].name);
|
||||
|
||||
|
||||
if( imap == -1 ) {
|
||||
ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map[dm].name, snd->exname);
|
||||
return 1;
|
||||
|
@ -1147,11 +1147,6 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
|
||||
clif_changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if player have any cool downs on
|
||||
**/
|
||||
skill_cooldown_load(sd);
|
||||
|
||||
/**
|
||||
* Check if player have any item cooldowns on
|
||||
**/
|
||||
@ -1296,7 +1291,7 @@ int pc_reg_received(struct map_session_data *sd)
|
||||
|
||||
status_calc_pc(sd,1);
|
||||
chrif_scdata_request(sd->status.account_id, sd->status.char_id);
|
||||
|
||||
chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id);
|
||||
intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
|
||||
intif_request_questlog(sd);
|
||||
|
||||
|
11
src/map/pc.h
11
src/map/pc.h
@ -115,6 +115,11 @@ struct s_autobonus {
|
||||
unsigned short pos;
|
||||
};
|
||||
|
||||
struct skill_cooldown_entry {
|
||||
unsigned short skill_id;
|
||||
int timer;
|
||||
};
|
||||
|
||||
enum npc_timeout_type {
|
||||
NPCT_INPUT = 0,
|
||||
NPCT_MENU = 1,
|
||||
@ -244,7 +249,7 @@ struct map_session_data {
|
||||
uint16 skill_id_old,skill_lv_old;
|
||||
uint16 skill_id_dance,skill_lv_dance;
|
||||
short cook_mastery; // range: [0,1999] [Inkfish]
|
||||
unsigned char blockskill[MAX_SKILL];
|
||||
struct skill_cooldown_entry * scd[MAX_SKILLCOOLDOWN]; // Skill Cooldown
|
||||
int cloneskill_id, reproduceskill_id;
|
||||
int menuskill_id, menuskill_val, menuskill_val2;
|
||||
|
||||
@ -321,6 +326,10 @@ struct map_session_data {
|
||||
short flag, rate;
|
||||
unsigned char ele;
|
||||
} subele2[MAX_PC_BONUS];
|
||||
struct {
|
||||
int id;
|
||||
int val;
|
||||
} cooldown[MAX_PC_BONUS];
|
||||
struct {
|
||||
short value;
|
||||
int rate, tick;
|
||||
|
196
src/map/skill.c
196
src/map/skill.c
@ -63,20 +63,6 @@ static DBMap* bowling_db = NULL; // int mob_id -> struct mob_data*
|
||||
|
||||
DBMap* skillunit_db = NULL; // int id -> struct skill_unit*
|
||||
|
||||
/**
|
||||
* Skill Cool Down Delay Saving
|
||||
* Struct skill_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* skillcd_db = NULL; // char_id -> struct skill_cd
|
||||
struct skill_cd {
|
||||
int duration[MAX_SKILL_TREE];//milliseconds
|
||||
short skidx[MAX_SKILL_TREE];//the skill index entries belong to
|
||||
short nameid[MAX_SKILL_TREE];//skill id
|
||||
unsigned char cursor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Skill Unit Persistency during endack routes (mostly for songs see bugreport:4574)
|
||||
**/
|
||||
@ -257,6 +243,27 @@ int skill_tree_get_max(uint16 skill_id, int b_class)
|
||||
return skill_get_max(skill_id);
|
||||
}
|
||||
|
||||
int skill_get_cooldown_(struct map_session_data *sd, int id, int lv) {
|
||||
int i, cooldown;
|
||||
int idx = skill_get_index (id);
|
||||
if (!idx) return 0;
|
||||
|
||||
cooldown = 0;
|
||||
if (skill_db[idx].cooldown[lv - 1])
|
||||
cooldown = skill_db[idx].cooldown[lv - 1];
|
||||
|
||||
for (i = 0; i < ARRAYLENGTH(sd->cooldown) && sd->cooldown[i].id; i++) {
|
||||
if (sd->cooldown[i].id == id) {
|
||||
cooldown += sd->cooldown[i].val;
|
||||
if (cooldown < 0)
|
||||
cooldown = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cooldown;
|
||||
}
|
||||
|
||||
int skill_frostjoke_scream(struct block_list *bl,va_list ap);
|
||||
int skill_attack_area(struct block_list *bl,va_list ap);
|
||||
struct skill_unit_group *skill_locate_element_field(struct block_list *bl); // [Skotlex]
|
||||
@ -446,7 +453,7 @@ static short skill_isCopyable (struct map_session_data *sd, uint16 skill_id, str
|
||||
// Only copy skill that player doesn't have or the skill is old clone
|
||||
if (sd->status.skill[skill_id].id != 0 && sd->status.skill[skill_id].flag != SKILL_FLAG_PLAGIARIZED)
|
||||
return 0;
|
||||
|
||||
|
||||
// Never copy NPC/Wedding Skills
|
||||
if (skill_get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL))
|
||||
return 0;
|
||||
@ -510,7 +517,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sd->blockskill[idx] > 0) {
|
||||
if (skill_blockpc_get(sd, skill_id) != -1){
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_SKILLINTERVAL,0);
|
||||
return true;
|
||||
}
|
||||
@ -711,7 +718,7 @@ bool skill_isNotOk_npcRange(struct block_list *src, struct block_list *target, u
|
||||
|
||||
if (src->type == BL_PC && pc_has_permission(BL_CAST(BL_PC,src),PC_PERM_SKILL_UNCONDITIONAL))
|
||||
return false;
|
||||
|
||||
|
||||
inf = skill_get_inf(skill_id);
|
||||
//if self skill
|
||||
if (inf&INF_SELF_SKILL) {
|
||||
@ -9650,15 +9657,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
|
||||
if( !sd || sd->skillitem != ud->skill_id || skill_get_delay(ud->skill_id,ud->skill_lv) )
|
||||
ud->canact_tick = tick + skill_delayfix(src, ud->skill_id, ud->skill_lv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish]
|
||||
if (sd) { //Cooldown application
|
||||
int i, cooldown = skill_get_cooldown(ud->skill_id, ud->skill_lv);
|
||||
for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses.
|
||||
if (sd->skillcooldown[i].id == ud->skill_id){
|
||||
cooldown += sd->skillcooldown[i].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(cooldown)
|
||||
skill_blockpc_start(sd, ud->skill_id, cooldown);
|
||||
int cooldown = skill_get_cooldown_(sd,ud->skill_id, ud->skill_lv); // Increases/Decreases cooldown of a skill by item/card bonuses.
|
||||
if(cooldown) skill_blockpc_start(sd, ud->skill_id, cooldown);
|
||||
}
|
||||
if( battle_config.display_status_timers && sd )
|
||||
clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
|
||||
@ -17337,86 +17337,81 @@ static int skill_destroy_trap( struct block_list *bl, va_list ap ) {
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
*
|
||||
*------------------------------------------*/
|
||||
*
|
||||
*------------------------------------------*/
|
||||
int skill_blockpc_get(struct map_session_data *sd, int skillid) {
|
||||
int i;
|
||||
nullpo_retr(-1, sd);
|
||||
|
||||
ARR_FIND(0, MAX_SKILLCOOLDOWN, i, sd->scd[i] && sd->scd[i]->skill_id == skillid);
|
||||
return (i >= MAX_SKILLCOOLDOWN) ? -1 : i;
|
||||
}
|
||||
|
||||
int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
struct map_session_data *sd = map_id2sd(id);
|
||||
struct skill_cd * cd = NULL;
|
||||
int i = (int) data;
|
||||
|
||||
if (data <= 0 || data >= MAX_SKILL)
|
||||
if (!sd || data < 0 || data >= MAX_SKILLCOOLDOWN)
|
||||
return 0;
|
||||
if (!sd) return 0;
|
||||
if (sd->blockskill[data] != (0x1|(tid&0xFE))) return 0;
|
||||
|
||||
if( ( cd = idb_get(skillcd_db,sd->status.char_id) ) ) {
|
||||
int i,cursor;
|
||||
ARR_FIND( 0, cd->cursor+1, cursor, cd->skidx[cursor] == data );
|
||||
cd->duration[cursor] = 0;
|
||||
cd->skidx[cursor] = 0;
|
||||
cd->nameid[cursor] = 0;
|
||||
// compact the cool down list
|
||||
for( i = 0, cursor = 0; i < cd->cursor; i++ ) {
|
||||
if( cd->duration[i] == 0 )
|
||||
continue;
|
||||
if( cursor != i ) {
|
||||
cd->duration[cursor] = cd->duration[i];
|
||||
cd->skidx[cursor] = cd->skidx[i];
|
||||
cd->nameid[cursor] = cd->nameid[i];
|
||||
}
|
||||
cursor++;
|
||||
}
|
||||
if( cursor == 0 )
|
||||
idb_remove(skillcd_db,sd->status.char_id);
|
||||
else
|
||||
cd->cursor = cursor;
|
||||
if (!sd->scd[i] || sd->scd[i]->timer != tid) {
|
||||
ShowWarning("skill_blockpc_end: Invalid Timer or not Skill Cooldown.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sd->blockskill[data] = 0;
|
||||
return 1;
|
||||
aFree(sd->scd[i]);
|
||||
sd->scd[i] = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* flags a singular skill as being blocked from persistent usage.
|
||||
* @param sd the player the skill delay affects
|
||||
* @param skill_id the skill which should be delayed
|
||||
* @param tick the length of time the delay should last
|
||||
* @param load whether this assignment is being loaded upon player login
|
||||
* @return 0 if successful, -1 otherwise
|
||||
*/
|
||||
int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, bool load)
|
||||
{
|
||||
int oskill_id = skill_id;
|
||||
struct skill_cd* cd = NULL;
|
||||
uint16 idx = skill_get_index(skill_id);
|
||||
|
||||
nullpo_retr (-1, sd);
|
||||
|
||||
if (idx == 0)
|
||||
* flags a singular skill as being blocked from persistent usage.
|
||||
* @param sd the player the skill delay affects
|
||||
* @param skill_id the skill which should be delayed
|
||||
* @param tick the length of time the delay should last
|
||||
* @param load whether this assignment is being loaded upon player login
|
||||
* @return 0 if successful, -1 otherwise
|
||||
*/
|
||||
int skill_blockpc_start(struct map_session_data *sd, int skillid, int tick) {
|
||||
int i;
|
||||
nullpo_retr(-1, sd);
|
||||
if (skillid == 0 || tick < 1)
|
||||
return -1;
|
||||
|
||||
if (tick < 1) {
|
||||
sd->blockskill[idx] = 0;
|
||||
return -1;
|
||||
ARR_FIND(0, MAX_SKILLCOOLDOWN, i, sd->scd[i] && sd->scd[i]->skill_id == skillid);
|
||||
if (i < MAX_SKILLCOOLDOWN) { // Skill already with cooldown
|
||||
delete_timer(sd->scd[i]->timer, skill_blockpc_end);
|
||||
aFree(sd->scd[i]);
|
||||
sd->scd[i] = NULL;
|
||||
}
|
||||
|
||||
if( battle_config.display_status_timers )
|
||||
clif_skill_cooldown(sd, idx, tick);
|
||||
ARR_FIND(0, MAX_SKILLCOOLDOWN, i, !sd->scd[i]);
|
||||
if (i < MAX_SKILLCOOLDOWN) { // Free Slot found
|
||||
CREATE(sd->scd[i], struct skill_cooldown_entry, 1);
|
||||
sd->scd[i]->skill_id = skillid;
|
||||
sd->scd[i]->timer = add_timer(gettick() + tick, skill_blockpc_end, sd->bl.id, i);
|
||||
|
||||
if( !load ) {// not being loaded initially so ensure the skill delay is recorded
|
||||
if( !(cd = idb_get(skillcd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage
|
||||
CREATE( cd, struct skill_cd, 1 );
|
||||
idb_put( skillcd_db, sd->status.char_id, cd );
|
||||
}
|
||||
if (battle_config.display_status_timers && tick > 0)
|
||||
clif_skill_cooldown(sd, skillid, tick);
|
||||
|
||||
// record the skill duration in the database map
|
||||
cd->duration[cd->cursor] = tick;
|
||||
cd->skidx[cd->cursor] = idx;
|
||||
cd->nameid[cd->cursor] = oskill_id;
|
||||
cd->cursor++;
|
||||
return 1;
|
||||
} else {
|
||||
ShowWarning("skill_blockpc_start: Too many skillcooldowns, increase MAX_SKILLCOOLDOWN.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sd->blockskill[idx] = 0x1|(0xFE&add_timer(gettick()+tick,skill_blockpc_end,sd->bl.id,idx));
|
||||
return 0;
|
||||
int skill_blockpc_clear(struct map_session_data *sd) {
|
||||
int i;
|
||||
nullpo_ret(sd);
|
||||
for (i = 0; i < MAX_SKILLCOOLDOWN; i++) {
|
||||
if (!sd->scd[i])
|
||||
continue;
|
||||
delete_timer(sd->scd[i]->timer, skill_blockpc_end);
|
||||
aFree(sd->scd[i]);
|
||||
sd->scd[i] = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[orn]
|
||||
@ -17938,29 +17933,6 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* reload stored skill cooldowns when a player logs in.
|
||||
* @param sd the affected player structure
|
||||
*/
|
||||
void skill_cooldown_load(struct map_session_data * sd)
|
||||
{
|
||||
int i;
|
||||
struct skill_cd* cd = NULL;
|
||||
|
||||
// always check to make sure the session properly exists
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( !(cd = idb_get(skillcd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character
|
||||
return;
|
||||
}
|
||||
|
||||
// process each individual cooldown associated with the character
|
||||
for( i = 0; i < cd->cursor; i++ ) {
|
||||
// block the skill from usage but ensure it is not recorded (load = true)
|
||||
skill_blockpc_start_( sd, cd->nameid[i], cd->duration[i], true );
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* sub-function of DB reading.
|
||||
* skill_db.txt
|
||||
@ -18492,7 +18464,6 @@ int do_init_skill (void)
|
||||
|
||||
group_db = idb_alloc(DB_OPT_BASE);
|
||||
skillunit_db = idb_alloc(DB_OPT_BASE);
|
||||
skillcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
bowling_db = idb_alloc(DB_OPT_BASE);
|
||||
skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_NONE);
|
||||
@ -18514,7 +18485,6 @@ int do_final_skill(void)
|
||||
db_destroy(skilldb_name2id);
|
||||
db_destroy(group_db);
|
||||
db_destroy(skillunit_db);
|
||||
db_destroy(skillcd_db);
|
||||
db_destroy(skillusave_db);
|
||||
db_destroy(bowling_db);
|
||||
ers_destroy(skill_unit_ers);
|
||||
|
@ -429,11 +429,13 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,uin
|
||||
int skill_castend_damage_id( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag );
|
||||
int skill_castend_pos2( struct block_list *src, int x,int y,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag);
|
||||
|
||||
int skill_blockpc_start_(struct map_session_data*, uint16 skill_id, int, bool);
|
||||
int skill_blockpc_start(struct map_session_data*, int, int);
|
||||
int skill_blockpc_get(struct map_session_data *sd, int skillid);
|
||||
int skill_blockpc_clear(struct map_session_data *sd);
|
||||
int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data);
|
||||
int skill_blockhomun_start (struct homun_data*,uint16 skill_id,int);
|
||||
int skill_blockmerc_start (struct mercenary_data*,uint16 skill_id,int);
|
||||
|
||||
#define skill_blockpc_start(sd, skill_id, tick) skill_blockpc_start_( sd, skill_id, tick, false )
|
||||
|
||||
// (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names)
|
||||
#define skill_ischangesex(id) ( \
|
||||
|
@ -2370,6 +2370,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
duel_reject(sd->duel_invite, sd);
|
||||
|
||||
channel_pcquit(sd,0xF); //leave all chan
|
||||
skill_blockpc_clear(sd); //clear all skill cooldown related
|
||||
|
||||
// Notify friends that this char logged out. [Skotlex]
|
||||
map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user