From 2b2dbf43f11aecf778ff118dd1da1af9726f36e6 Mon Sep 17 00:00:00 2001 From: skotlex Date: Thu, 22 Nov 2007 23:52:58 +0000 Subject: - Changed the status_change structure to use dynamic rather than static memory to hold the individual status changes, this should have a noticeable impact on the server's memory consumption. - Had to add a few 'ugly' flags to status_change since now you can't track SC related information while said SC is not active (happens only for Storm Gust, Joint Beat and Magic Power). - Since I am unable to fully test, watch out for any bugs~ git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11786 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 6 + src/common/mmo.h | 2 +- src/map/atcommand.c | 42 +- src/map/battle.c | 262 ++++---- src/map/charcommand.c | 8 +- src/map/chrif.c | 28 +- src/map/clif.c | 69 +- src/map/map.c | 25 +- src/map/map.h | 13 +- src/map/mob.c | 35 +- src/map/party.c | 2 +- src/map/pc.c | 97 +-- src/map/pet.c | 2 +- src/map/skill.c | 692 ++++++++++--------- src/map/skill.h | 2 +- src/map/status.c | 1785 +++++++++++++++++++++++++------------------------ src/map/status.h | 9 +- src/map/unit.c | 148 ++-- 18 files changed, 1618 insertions(+), 1609 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 750659746..2ecab7ca6 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,12 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +2007/11/23 + * Changed the status_change structure to use dynamic rather than static + memory to hold the individual status changes, this should have a noticeable + impact on the server's memory consumption. However, since this is a pretty + large update (and I am unable to fully test all possible situations + relating to status changes), watch out for any bugs. [Skotlex] 2007/11/22 * Moved the reset of references to after the empty script checks in parse_script. (fixes bugreport:222 and bugreport:449) diff --git a/src/common/mmo.h b/src/common/mmo.h index 1db623982..56e4eb9ce 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -436,7 +436,7 @@ enum { GD_SKILLBASE=10000, GD_APPROVAL=10000, GD_KAFRACONTRACT=10001, - GD_GUARDIANRESEARCH=10002, + GD_GUARDRESEARCH=10002, GD_GUARDUP=10003, GD_EXTENSION=10004, GD_GLORYGUILD=10005, diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 3cbe1f885..81761a453 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -4950,7 +4950,7 @@ int atcommand_jail(const int fd, struct map_session_data* sd, const char* comman return -1; } - if (pl_sd->sc.data[SC_JAILED].timer != -1) + if (pl_sd->sc.data[SC_JAILED]) { clif_displaymessage(fd, msg_txt(118)); // Player warped in jails. return -1; @@ -5002,7 +5002,7 @@ int atcommand_unjail(const int fd, struct map_session_data* sd, const char* comm return -1; } - if (pl_sd->sc.data[SC_JAILED].timer == -1) + if (!pl_sd->sc.data[SC_JAILED]) { clif_displaymessage(fd, msg_txt(119)); // This player is not in jails. return -1; @@ -5086,10 +5086,10 @@ int atcommand_jailfor(const int fd, struct map_session_data* sd, const char* com } //Added by Coltaro - if (pl_sd->sc.count && pl_sd->sc.data[SC_JAILED].timer != -1 && - pl_sd->sc.data[SC_JAILED].val1 != INT_MAX) + if(pl_sd->sc.data[SC_JAILED] && + pl_sd->sc.data[SC_JAILED]->val1 != INT_MAX) { //Update the player's jail time - jailtime += pl_sd->sc.data[SC_JAILED].val1; + jailtime += pl_sd->sc.data[SC_JAILED]->val1; if (jailtime <= 0) { jailtime = 0; clif_displaymessage(pl_sd->fd, msg_txt(120)); // GM has discharge you. @@ -5131,23 +5131,23 @@ int atcommand_jailtime(const int fd, struct map_session_data* sd, const char* co nullpo_retr(-1, sd); - if (!sd->sc.count || sd->sc.data[SC_JAILED].timer == -1) { + if (!sd->sc.data[SC_JAILED]) { clif_displaymessage(fd, "You are not in jail."); // You are not in jail. return -1; } - if (sd->sc.data[SC_JAILED].val1 == INT_MAX) { + if (sd->sc.data[SC_JAILED]->val1 == INT_MAX) { clif_displaymessage(fd, "You have been jailed indefinitely."); return 0; } - if (sd->sc.data[SC_JAILED].val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?) + if (sd->sc.data[SC_JAILED]->val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?) clif_displaymessage(fd, "You have been jailed for an unknown amount of time."); return -1; } //Get remaining jail time - get_jail_time(sd->sc.data[SC_JAILED].val1,&year,&month,&day,&hour,&minute); + get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute); sprintf(atcmd_output,msg_txt(402),"You will remain",year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes clif_displaymessage(fd, atcmd_output); @@ -6366,8 +6366,8 @@ int atcommand_npctalk(const int fd, struct map_session_data* sd, const char* com struct npc_data *nd; if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK].timer!=-1 || - (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))) + (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; if (!message || !*message || sscanf(message, "%23[^,], %99[^\n]", name, mes) < 2) { @@ -6407,8 +6407,8 @@ int atcommand_pettalk(const int fd, struct map_session_data* sd, const char* com } if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK].timer!=-1 || - (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))) + (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { @@ -6670,7 +6670,7 @@ int atcommand_unmute(const int fd, struct map_session_data* sd, const char* comm return -1; } - if(pl_sd->sc.data[SC_NOCHAT].timer == -1) { + if(!pl_sd->sc.data[SC_NOCHAT]) { clif_displaymessage(sd->fd,"Player is not muted"); return -1; } @@ -7175,8 +7175,8 @@ int atcommand_homtalk(const int fd, struct map_session_data* sd, const char* com nullpo_retr(-1, sd); if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK].timer!=-1 || - (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))) + (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; if ( !merc_is_hom_active(sd->hd) ) { @@ -7564,7 +7564,7 @@ static int atcommand_mutearea_sub(struct block_list *bl,va_list ap) pl_sd->status.manner -= time; if (pl_sd->status.manner < 0) sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); - else if (pl_sd->sc.count && pl_sd->sc.data[SC_NOCHAT].timer != -1) + else if (pl_sd->sc.data[SC_NOCHAT]) status_change_end(&pl_sd->bl, SC_NOCHAT, -1); } return 0; @@ -7617,8 +7617,8 @@ int atcommand_me(const int fd, struct map_session_data* sd, const char* command, memset(atcmd_output, '\0', sizeof(atcmd_output)); if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK].timer!=-1 || - (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))) + (sd->sc.data[SC_BERSERK] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return -1; if (!message || !*message || sscanf(message, "%199[^\n]", tempmes) < 0) { @@ -8025,7 +8025,7 @@ int atcommand_main(const int fd, struct map_session_data* sd, const char* comman sd->state.mainchat = 1; clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated. } - if (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT) { + if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) { clif_displaymessage(fd, msg_txt(387)); return -1; } @@ -8474,7 +8474,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message if( !message || !*message ) return false; // shouldn't happen - if( sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCOMMAND ) + if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCOMMAND ) return true; // so that it won't display as normal message if( battle_config.atc_gmonly != 0 && gmlvl == 0 ) diff --git a/src/map/battle.c b/src/map/battle.c index f686410f4..13740edb7 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -223,24 +223,24 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag ratio = attr_fix_table[def_lv-1][atk_elem][def_type]; if (sc && sc->count) { - if(sc->data[SC_VOLCANO].timer!=-1 && atk_elem == ELE_FIRE) - ratio += enchant_eff[sc->data[SC_VOLCANO].val1-1]; - if(sc->data[SC_VIOLENTGALE].timer!=-1 && atk_elem == ELE_WIND) - ratio += enchant_eff[sc->data[SC_VIOLENTGALE].val1-1]; - if(sc->data[SC_DELUGE].timer!=-1 && atk_elem == ELE_WATER) - ratio += enchant_eff[sc->data[SC_DELUGE].val1-1]; + if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE) + ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1]; + if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND) + ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1]; + if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER) + ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1]; } if (tsc && tsc->count) { - if(tsc->data[SC_ARMOR_ELEMENT].timer!=-1) + if(tsc->data[SC_ARMOR_ELEMENT]) { - if (tsc->data[SC_ARMOR_ELEMENT].val1 == atk_elem) - ratio -= tsc->data[SC_ARMOR_ELEMENT].val2; + if (tsc->data[SC_ARMOR_ELEMENT]->val1 == atk_elem) + ratio -= tsc->data[SC_ARMOR_ELEMENT]->val2; else - if (tsc->data[SC_ARMOR_ELEMENT].val3 == atk_elem) - ratio -= tsc->data[SC_ARMOR_ELEMENT].val4; + if (tsc->data[SC_ARMOR_ELEMENT]->val3 == atk_elem) + ratio -= tsc->data[SC_ARMOR_ELEMENT]->val4; } - if(tsc->data[SC_SPIDERWEB].timer!=-1 && atk_elem == ELE_FIRE) + if(tsc->data[SC_SPIDERWEB] && atk_elem == ELE_FIRE) { // [Celest] damage <<= 1; status_change_end(target, SC_SPIDERWEB, -1); @@ -256,7 +256,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i { struct map_session_data *sd = NULL; struct status_change *sc; - struct status_change_entry *sci; + struct status_change_entry *sce; nullpo_retr(0, bl); @@ -290,9 +290,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i if (sc && sc->count) { //First, sc_*'s that reduce damage to 0. - if (sc->data[SC_SAFETYWALL].timer!=-1 && flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK + if (sc->data[SC_SAFETYWALL] && flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK ) { - struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL].val3; + struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL]->val3; if (group) { if (--group->val2<=0) skill_delunitgroup(NULL,group); @@ -301,82 +301,80 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i status_change_end(bl,SC_SAFETYWALL,-1); } - if(sc->data[SC_AUTOGUARD].timer != -1 && flag&BF_WEAPON && + if((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) && - rand()%100 < sc->data[SC_AUTOGUARD].val2) + rand()%100 < sce->val2) { int delay; - clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sc->data[SC_AUTOGUARD].val1,1); + clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); // different delay depending on skill level [celest] - if (sc->data[SC_AUTOGUARD].val1 <= 5) + if (sce->val1 <= 5) delay = 300; - else if (sc->data[SC_AUTOGUARD].val1 > 5 && sc->data[SC_AUTOGUARD].val1 <= 9) + else if (sce->val1 > 5 && sce->val1 <= 9) delay = 200; else delay = 100; unit_set_walkdelay(bl, gettick(), delay, 1); - if(sc->data[SC_SHRINK].timer != -1 && rand()%100<5*sc->data[SC_AUTOGUARD].val1) + if(sc->data[SC_SHRINK] && rand()%100<5*sce->val1) skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0); return 0; } // -- moonsoul (chance to block attacks with new Lord Knight skill parrying) // - if(sc->data[SC_PARRYING].timer != -1 && flag&BF_WEAPON && - rand()%100 < sc->data[SC_PARRYING].val2) { - clif_skill_nodamage(bl,bl,LK_PARRYING,sc->data[SC_PARRYING].val1,1); + if((sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && + rand()%100 < sce->val2) { + clif_skill_nodamage(bl,bl,LK_PARRYING,sce->val1,1); return 0; } - if(sc->data[SC_DODGE].timer != -1 && !sc->opt1 && - (flag&BF_LONG || sc->data[SC_SPURT].timer != -1) + if(sc->data[SC_DODGE] && !sc->opt1 && + (flag&BF_LONG || sc->data[SC_SPURT]) && rand()%100 < 20) { if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge. clif_skill_nodamage(bl,bl,TK_DODGE,1,1); - if (sc->data[SC_COMBO].timer == -1) + if (!sc->data[SC_COMBO]) sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000); return 0; } - if(sc->data[SC_HERMODE].timer != -1 && flag&BF_MAGIC) + if(sc->data[SC_HERMODE] && flag&BF_MAGIC) return 0; - if(sc->data[SC_TATAMIGAESHI].timer != -1 && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) + if(sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) return 0; - if(sc->data[SC_KAUPE].timer != -1 && - rand()%100 < sc->data[SC_KAUPE].val2 && + if((sce=sc->data[SC_KAUPE]) && + rand()%100 < sce->val2 && (src->type == BL_PC || !skill_num)) { //Kaupe only blocks all skills of players. clif_specialeffect(bl, 462, AREA); //Shouldn't end until Breaker's non-weapon part connects. if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON)) - if (--sc->data[SC_KAUPE].val3 <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. + if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. status_change_end(bl, SC_KAUPE, -1); return 0; } - if ((sc->data[SC_UTSUSEMI].timer != -1 || sc->data[SC_BUNSINJYUTSU].timer != -1) + if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK)) { - if (sc->data[SC_UTSUSEMI].timer != -1) { + if (sce) { clif_specialeffect(bl, 462, AREA); - skill_blown(src,bl,sc->data[SC_UTSUSEMI].val3,-1,0); + skill_blown(src,bl,sce->val3,-1,0); } //Both need to be consumed if they are active. - if (sc->data[SC_UTSUSEMI].timer != -1 && - --sc->data[SC_UTSUSEMI].val2 <= 0) + if (sce && --(sce->val2) <= 0) status_change_end(bl, SC_UTSUSEMI, -1); - if (sc->data[SC_BUNSINJYUTSU].timer != -1 && - --sc->data[SC_BUNSINJYUTSU].val2 <= 0) + if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0) status_change_end(bl, SC_BUNSINJYUTSU, -1); return 0; } //Now damage increasing effects - if(sc->data[SC_AETERNA].timer!=-1 && skill_num != PF_SOULBURN){ + if(sc->data[SC_AETERNA] && skill_num != PF_SOULBURN){ damage<<=1; //Shouldn't end until Breaker's non-weapon part connects. if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON)) @@ -384,35 +382,33 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i } //Finally damage reductions.... - if(sc->data[SC_ASSUMPTIO].timer != -1){ + if(sc->data[SC_ASSUMPTIO]){ if(map_flag_vs(bl->m)) damage=damage*2/3; //Receive 66% damage else damage>>=1; //Receive 50% damage } - if(sc->data[SC_DEFENDER].timer != -1 && + if(sc->data[SC_DEFENDER] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - damage=damage*(100-sc->data[SC_DEFENDER].val2)/100; + damage=damage*(100-sc->data[SC_DEFENDER]->val2)/100; - if(sc->data[SC_ADJUSTMENT].timer != -1 && + if(sc->data[SC_ADJUSTMENT] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) damage -= 20*damage/100; - if(sc->data[SC_FOGWALL].timer != -1) { + if(sc->data[SC_FOGWALL]) { if(flag&BF_SKILL) //25% reduction damage -= 25*damage/100; else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) damage >>= 2; //75% reduction } - if(sc->data[SC_ARMOR].timer != -1 && - sc->data[SC_ARMOR].val3&flag && - sc->data[SC_ARMOR].val4&flag) - //NPC_DEFENDER - damage -= damage*sc->data[SC_ARMOR].val2/100; + if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER + sce->val3&flag && sce->val4&flag) + damage -= damage*sc->data[SC_ARMOR]->val2/100; - if(sc->data[SC_ENERGYCOAT].timer!=-1 && flag&BF_WEAPON){ + if(sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON){ struct status_data *status = status_get_status_data(bl); int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval per /=20; //Uses 20% SP intervals. @@ -423,34 +419,32 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i damage -= damage * 6 * (1+per) / 100; } - if(sc->data[SC_REJECTSWORD].timer!=-1 && flag&BF_WEAPON && + if((sce=sc->data[SC_REJECTSWORD]) && flag&BF_WEAPON && // Fixed the condition check [Aalye] (src->type!=BL_PC || ( ((TBL_PC *)src)->status.weapon == W_DAGGER || ((TBL_PC *)src)->status.weapon == W_1HSWORD || ((TBL_PC *)src)->status.weapon == W_2HSWORD - )) + )) && + rand()%100 < sce->val2 ){ - if(rand()%100 < sc->data[SC_REJECTSWORD].val2){ - damage = damage*50/100; - status_fix_damage(bl,src,damage,clif_damage(bl,src,gettick(),0,0,damage,0,0,0)); - clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sc->data[SC_REJECTSWORD].val1,1); - if((--sc->data[SC_REJECTSWORD].val3)<=0) - status_change_end(bl, SC_REJECTSWORD, -1); - } + damage = damage*50/100; + status_fix_damage(bl,src,damage,clif_damage(bl,src,gettick(),0,0,damage,0,0,0)); + clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sce->val1,1); + if(--(sce->val3)<=0) + status_change_end(bl, SC_REJECTSWORD, -1); } //Finally Kyrie because it may, or not, reduce damage to 0. - if(sc->data[SC_KYRIE].timer!=-1 && damage > 0){ - sci=&sc->data[SC_KYRIE]; - sci->val2-=damage; + if((sce = sc->data[SC_KYRIE]) && damage > 0){ + sce->val2-=damage; if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){ - if(sci->val2>=0) + if(sce->val2>=0) damage=0; else - damage=-sci->val2; + damage=-sce->val2; } - if((--sci->val3)<=0 || (sci->val2<=0) || skill_num == AL_HOLYLIGHT) + if((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT) status_change_end(bl, SC_KYRIE, -1); } @@ -458,9 +452,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i //Probably not the most correct place, but it'll do here //(since battle_drain is strictly for players currently) - if (sc->data[SC_BLOODLUST].timer != -1 && flag&BF_WEAPON && damage > 0 && - rand()%100 < sc->data[SC_BLOODLUST].val3) - status_heal(src, damage*sc->data[SC_BLOODLUST].val4/100, 0, 3); + if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 && + rand()%100 < sce->val3) + status_heal(src, damage*sce->val4/100, 0, 3); } //SC effects from caster side. Currently none. @@ -611,7 +605,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) { damage += (skill * 4); - if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_HUNTER) + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER) damage += sd->status.str; } @@ -729,7 +723,7 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk } } - if (sc && sc->data[SC_MAXIMIZEPOWER].timer!=-1) + if (sc && sc->data[SC_MAXIMIZEPOWER]) atkmin = atkmax; //Weapon Damage calculation @@ -1009,7 +1003,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if(tsc) { - if (tsc->data[SC_SLEEP].timer!=-1 ) + if (tsc->data[SC_SLEEP]) cri <<=1; } switch (skill_num) @@ -1040,7 +1034,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } else { //Check for Perfect Hit if(sd && sd->perfect_hit > 0 && rand()%100 < sd->perfect_hit) flag.hit = 1; - if (sc && sc->data[SC_FUSION].timer != -1) { + if (sc && sc->data[SC_FUSION]) { flag.hit = 1; //SG_FUSION always hit [Komurka] flag.idef = flag.idef2 = 1; //def ignore [Komurka] } @@ -1053,7 +1047,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo flag.hit = 1; break; case CR_SHIELDBOOMERANG: - if (sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_CRUSADER) + if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) flag.hit = 1; break; case 0: @@ -1090,7 +1084,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo hitrate+= sstatus->hit - flee; if(wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks. - tsc && tsc->data[SC_FOGWALL].timer!=-1) + tsc && tsc->data[SC_FOGWALL]) hitrate -= 50; if(sd && flag.arrow) @@ -1166,9 +1160,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo status_zap(src, wd.damage, 0);//Damage to self is always 9% wd.damage2 = 0; - if (sc && sc->data[SC_SACRIFICE].timer != -1) + if (sc && sc->data[SC_SACRIFICE]) { - if (--sc->data[SC_SACRIFICE].val2 <= 0) + if (--sc->data[SC_SACRIFICE]->val2 <= 0) status_change_end(src, SC_SACRIFICE,-1); } break; @@ -1221,9 +1215,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo i = (flag.cri?1:0)| (flag.arrow?2:0)| (skill_num == HW_MAGICCRASHER?4:0)| - (!skill_num && sc && sc->data[SC_CHANGE].timer!=-1?4:0)| + (!skill_num && sc && sc->data[SC_CHANGE]?4:0)| (skill_num == MO_EXTREMITYFIST?8:0)| - (sc && sc->data[SC_WEAPONPERFECTION].timer!=-1?8:0); + (sc && sc->data[SC_WEAPONPERFECTION]?8:0); if (flag.arrow && sd) switch(sd->status.weapon) { case W_BOW: @@ -1267,11 +1261,11 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo //Skill damage modifiers that stack linearly if(sc && skill_num != PA_SACRIFICE) { - if(sc->data[SC_OVERTHRUST].timer != -1) - skillratio += 5*sc->data[SC_OVERTHRUST].val1; - if(sc->data[SC_MAXOVERTHRUST].timer != -1) - skillratio += 20*sc->data[SC_MAXOVERTHRUST].val1; - if(sc->data[SC_BERSERK].timer != -1) + if(sc->data[SC_OVERTHRUST]) + skillratio += sc->data[SC_OVERTHRUST]->val2; + if(sc->data[SC_MAXOVERTHRUST]) + skillratio += sc->data[SC_MAXOVERTHRUST]->val2; + if(sc->data[SC_BERSERK]) skillratio += 100; } if (!skill_num) @@ -1498,7 +1492,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo break; case TK_JUMPKICK: skillratio += -70 + 10*skill_lv; - if (sc && sc->data[SC_COMBO].timer != -1 && sc->data[SC_COMBO].val1 == skill_num) + if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num) skillratio += 10*status_get_lv(src)/3; break; case GS_TRIPLEACTION: @@ -1597,29 +1591,29 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo //The following are applied on top of current damage and are stackable. if (sc) { - if(sc->data[SC_TRUESIGHT].timer != -1) - ATK_ADDRATE(2*sc->data[SC_TRUESIGHT].val1); + if(sc->data[SC_TRUESIGHT]) + ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1); - if(sc->data[SC_EDP].timer != -1 && + if(sc->data[SC_EDP] && skill_num != ASC_BREAKER && skill_num != ASC_METEORASSAULT && skill_num != AS_SPLASHER && skill_num != AS_VENOMKNIFE) - ATK_ADDRATE(sc->data[SC_EDP].val3); + ATK_ADDRATE(sc->data[SC_EDP]->val3); } switch (skill_num) { case AS_SONICBLOW: - if (sc && sc->data[SC_SPIRIT].timer != -1 && - sc->data[SC_SPIRIT].val2 == SL_ASSASIN) + if (sc && sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe if(sd && pc_checkskill(sd,AS_SONICACCEL)>0) ATK_ADDRATE(10); break; case CR_SHIELDBOOMERANG: - if(sc && sc->data[SC_SPIRIT].timer != -1 && - sc->data[SC_SPIRIT].val2 == SL_CRUSADER) + if(sc && sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) ATK_ADDRATE(100); break; } @@ -1732,8 +1726,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo //Post skill/vit reduction damage increases if (sc && skill_num != LK_SPIRALPIERCE) { //SC skill damages - if(sc->data[SC_AURABLADE].timer!=-1) - ATK_ADD(20*sc->data[SC_AURABLADE].val1); + if(sc->data[SC_AURABLADE]) + ATK_ADD(20*sc->data[SC_AURABLADE]->val1); } //Refine bonus @@ -1767,7 +1761,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo wd.damage2 = battle_addmastery(sd,target,wd.damage2,1); if((skill=pc_checkskill(sd,SG_STAR_ANGER)) >0 && (t_class == sd->hate_mob[2] || - (sc && sc->data[SC_MIRACLE].timer!=-1))) + (sc && sc->data[SC_MIRACLE]))) { skillratio = sd->status.base_level + sstatus->str + sstatus->dex + sstatus->luk; if (skill<4) @@ -1814,11 +1808,11 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } if (flag.lh && wd.damage2 > 0) wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); - if(sc && sc->data[SC_WATK_ELEMENT].timer != -1) + if(sc && sc->data[SC_WATK_ELEMENT]) { //Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] int damage= battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)); - damage = damage*sc->data[SC_WATK_ELEMENT].val2/100; - damage = battle_attr_fix(src,target,damage,sc->data[SC_WATK_ELEMENT].val1,tstatus->def_ele, tstatus->ele_lv); + damage = damage*sc->data[SC_WATK_ELEMENT]->val2/100; + damage = battle_attr_fix(src,target,damage,sc->data[SC_WATK_ELEMENT]->val1,tstatus->def_ele, tstatus->ele_lv); ATK_ADD(damage); } } @@ -2047,9 +2041,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo { // Self weapon breaking int breakrate = battle_config.equip_natural_break_rate; if (sc) { - if(sc->data[SC_OVERTHRUST].timer!=-1) + if(sc->data[SC_OVERTHRUST]) breakrate += 10; - if(sc->data[SC_MAXOVERTHRUST].timer!=-1) + if(sc->data[SC_MAXOVERTHRUST]) breakrate += 10; } if (breakrate) @@ -2064,9 +2058,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo breakrate[1] += sd->break_armor_rate; } if (sc) { - if (sc->data[SC_MELTDOWN].timer!=-1) { - breakrate[0] += sc->data[SC_MELTDOWN].val2; - breakrate[1] += sc->data[SC_MELTDOWN].val3; + if (sc->data[SC_MELTDOWN]) { + breakrate[0] += sc->data[SC_MELTDOWN]->val2; + breakrate[1] += sc->data[SC_MELTDOWN]->val3; } } if (breakrate[0]) @@ -2077,7 +2071,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } //SG_FUSION hp penalty [Komurka] - if (sc && sc->data[SC_FUSION].timer!=-1) + if (sc && sc->data[SC_FUSION]) { int hp= sstatus->max_hp; if (sd && tsd) { @@ -2243,7 +2237,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list break; case AL_HOLYLIGHT: skillratio += 25; - if (sd && sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_PRIEST) + if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST) skillratio *= 5; //Does 5x damage include bonuses from other skills? break; case AL_RUWACH: @@ -2678,27 +2672,25 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl int battle_calc_return_damage(struct block_list* bl, int damage, int flag) { struct map_session_data* sd = NULL; - struct status_change* sc; int rdamage = 0; BL_CAST(BL_PC, bl, sd); - sc = status_get_sc(bl); - if(sc && !sc->count) - sc = NULL; //Bounces back part of the damage. if (flag & BF_SHORT) { + struct status_change* sc; if (sd && sd->short_weapon_damage_return) { rdamage += damage * sd->short_weapon_damage_return / 100; if(rdamage < 1) rdamage = 1; } - if (sc && sc->data[SC_REFLECTSHIELD].timer != -1) + sc = status_get_sc(bl); + if (sc && sc->data[SC_REFLECTSHIELD]) { - rdamage += damage * sc->data[SC_REFLECTSHIELD].val2 / 100; + rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; if (rdamage < 1) rdamage = 1; } - } else if (flag & BF_LONG) { + } else { if (sd && sd->long_weapon_damage_return) { rdamage += damage * sd->long_weapon_damage_return / 100; @@ -2823,14 +2815,13 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } } - if (sc && sc->data[SC_CLOAKING].timer != -1 && !(sc->data[SC_CLOAKING].val4&2)) + if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&2)) status_change_end(src,SC_CLOAKING,-1); //Check for counter attacks that block your attack. [Skotlex] if(tsc) { - if(tsc->data[SC_AUTOCOUNTER].timer != -1 && - (!sc || sc->data[SC_AUTOCOUNTER].timer == -1) && + if(tsc->data[SC_AUTOCOUNTER] && status_check_skilluse(target, src, KN_AUTOCOUNTER, 1) ) { int dir = map_calc_dir(target,src->x,src->y); @@ -2838,7 +2829,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t int dist = distance_bl(src, target); if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { - int skilllv = tsc->data[SC_AUTOCOUNTER].val1; + int skilllv = tsc->data[SC_AUTOCOUNTER]->val1; clif_skillcastcancel(target); //Remove the casting bar. [Skotlex] clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. status_change_end(target,SC_AUTOCOUNTER,-1); @@ -2846,8 +2837,8 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return 0; } } - if (tsc->data[SC_BLADESTOP_WAIT].timer != -1 && !is_boss(src)) { - int skilllv = tsc->data[SC_BLADESTOP_WAIT].val1; + if (tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src)) { + int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1; int duration = skill_get_time2(MO_BLADESTOP,skilllv); status_change_end(target, SC_BLADESTOP_WAIT, -1); if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, (int)target, duration)) @@ -2863,9 +2854,9 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0) { int triple_rate= 30 - skillv; //Base Rate - if (sc && sc->data[SC_SKILLRATE_UP].timer!=-1 && sc->data[SC_SKILLRATE_UP].val1 == MO_TRIPLEATTACK) + if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK) { - triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP].val2)/100; + triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100; status_change_end(src,SC_SKILLRATE_UP,-1); } if (rand()%100 < triple_rate) @@ -2874,10 +2865,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if (sc) { - if (sc->data[SC_SACRIFICE].timer != -1) - return skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE].val1,tick,0); - if (sc->data[SC_MAGICALATTACK].timer != -1) - return skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK].val1,tick,0); + if (sc->data[SC_SACRIFICE]) + return skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE]->val1,tick,0); + if (sc->data[SC_MAGICALATTACK]) + return skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0); } wd = battle_calc_weapon_attack(src, target, 0, 0, flag); @@ -2908,12 +2899,12 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t battle_delay_damage(tick+wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion); - if (sc && sc->data[SC_AUTOSPELL].timer != -1 && rand()%100 < sc->data[SC_AUTOSPELL].val4) { + if (sc && sc->data[SC_AUTOSPELL] && rand()%100 < sc->data[SC_AUTOSPELL]->val4) { int sp = 0; - int skillid = sc->data[SC_AUTOSPELL].val2; - int skilllv = sc->data[SC_AUTOSPELL].val3; + int skillid = sc->data[SC_AUTOSPELL]->val2; + int skilllv = sc->data[SC_AUTOSPELL]->val3; int i = rand()%100; - if (sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_SAGE) + if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE) i = 0; //Max chance, no skilllv reduction. [Skotlex] if (i >= 50) skilllv -= 2; else if (i >= 15) skilllv--; @@ -2949,20 +2940,21 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } if (tsc) { - if (tsc->data[SC_POISONREACT].timer != -1 && - (rand()%100 < tsc->data[SC_POISONREACT].val3 + if (tsc->data[SC_POISONREACT] && + (rand()%100 < tsc->data[SC_POISONREACT]->val3 || sstatus->def_ele == ELE_POISON) && // check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O; status_check_skilluse(target, src, TF_POISON, 0) ) { //Poison React + struct status_change_entry *sce = tsc->data[SC_POISONREACT]; if (sstatus->def_ele == ELE_POISON) { - tsc->data[SC_POISONREACT].val2 = 0; - skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,tsc->data[SC_POISONREACT].val1,tick,0); + sce->val2 = 0; + skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0); } else { skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0); - --tsc->data[SC_POISONREACT].val2; + --sce->val2; } - if (tsc->data[SC_POISONREACT].val2 <= 0) + if (sce->val2 <= 0) status_change_end(target, SC_POISONREACT, -1); } } diff --git a/src/map/charcommand.c b/src/map/charcommand.c index 08aa5ead2..e44954a4c 100644 --- a/src/map/charcommand.c +++ b/src/map/charcommand.c @@ -2830,17 +2830,17 @@ int charcommand_jailtime(const int fd, struct map_session_data* sd, const char* return -1; } - if (pl_sd->sc.data[SC_JAILED].val1 == INT_MAX) { + if (pl_sd->sc.data[SC_JAILED]->val1 == INT_MAX) { clif_displaymessage(fd, "You have been jailed indefinitely."); return 0; } - if (pl_sd->sc.data[SC_JAILED].val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?) + if (pl_sd->sc.data[SC_JAILED]->val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?) clif_displaymessage(fd, "This player has been jailed for an unknown amount of time."); return -1; } //Get remaining jail time - get_jail_time(pl_sd->sc.data[SC_JAILED].val1,&year,&month,&day,&hour,&minute); + get_jail_time(pl_sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute); sprintf(output,msg_txt(402),"This player will remain",year,month,day,hour,minute); clif_displaymessage(fd, output); @@ -3861,7 +3861,7 @@ bool is_charcommand(const int fd, struct map_session_data* sd, const char* messa if( !message || !*message ) return false; - if( sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCOMMAND ) + if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCOMMAND ) return true; // so that it won't display as normal message if( battle_config.atc_gmonly != 0 && gmlvl == 0 ) diff --git a/src/map/chrif.c b/src/map/chrif.c index 0f4df2544..03bed41b1 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1022,6 +1022,7 @@ int chrif_save_scdata(struct map_session_data *sd) int i, count=0; unsigned int tick; struct status_change_data data; + struct status_change *sc = &sd->sc; const struct TimerData *timer; if (sd->state.finalsave) //Character was already saved? @@ -1036,17 +1037,21 @@ int chrif_save_scdata(struct map_session_data *sd) WFIFOL(char_fd,8) = sd->status.char_id; for (i = 0; i < SC_MAX; i++) { - if (sd->sc.data[i].timer == -1) + if (!sc->data[i]) continue; - timer = get_timer(sd->sc.data[i].timer); - if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) - continue; - data.tick = DIFF_TICK(timer->tick,tick); //Duration that is left before ending. + if (sc->data[i]->timer != -1) + { + timer = get_timer(sc->data[i]->timer); + if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) + continue; + data.tick = DIFF_TICK(timer->tick,tick); //Duration that is left before ending. + } else + data.tick = -1; //Infinite duration data.type = i; - data.val1 = sd->sc.data[i].val1; - data.val2 = sd->sc.data[i].val2; - data.val3 = sd->sc.data[i].val3; - data.val4 = sd->sc.data[i].val4; + data.val1 = sc->data[i]->val1; + data.val2 = sc->data[i]->val2; + data.val3 = sc->data[i]->val3; + data.val4 = sc->data[i]->val4; memcpy(WFIFOP(char_fd,14 +count*sizeof(struct status_change_data)), &data, sizeof(struct status_change_data)); count++; @@ -1086,11 +1091,6 @@ int chrif_load_scdata(int fd) for (i = 0; i < count; i++) { data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data)); - if (data->tick < 1) - { //Protection against invalid tick values. [Skotlex] - ShowWarning("chrif_load_scdata: Received invalid duration (%d ms) for status change %d (character %s)\n", data->tick, data->type, sd->status.name); - continue; - } status_change_start(&sd->bl, data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15); } #endif diff --git a/src/map/clif.c b/src/map/clif.c index 0e1d11e35..ff78a8f3f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -3675,11 +3675,11 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic sc = status_get_sc(dst); if(sc && sc->count) { - if(type != 4 && dst->type == BL_PC && sc->data[SC_ENDURE].timer != -1 && !map_flag_gvg(dst->m)) + if(type != 4 && dst->type == BL_PC && sc->data[SC_ENDURE] && !map_flag_gvg(dst->m)) type = 9; - if(sc->data[SC_HALLUCINATION].timer != -1) { - if(damage > 0) damage = damage*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100; - if(damage2 > 0) damage2 = damage2*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100; + if(sc->data[SC_HALLUCINATION]) { + if(damage) damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rand()%100; + if(damage2) damage2 = damage2*(sc->data[SC_HALLUCINATION]->val2) + rand()%100; } } @@ -4246,10 +4246,10 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int sc = status_get_sc(dst); if(sc && sc->count) { - if(type != 4 && dst->type == BL_PC && sc->data[SC_ENDURE].timer != -1 && !map_flag_gvg(dst->m)) + if(type != 4 && dst->type == BL_PC && sc->data[SC_ENDURE] && !map_flag_gvg(dst->m)) type = 9; - if(sc->data[SC_HALLUCINATION].timer != -1 && damage > 0) - damage = damage*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100; + if(sc->data[SC_HALLUCINATION] && damage) + damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rand()%100; } #if PACKETVER < 3 @@ -4337,8 +4337,8 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in sc = status_get_sc(dst); if(sc && sc->count) { - if(sc->data[SC_HALLUCINATION].timer != -1 && damage > 0) - damage = damage*(5+sc->data[SC_HALLUCINATION].val1) + rand()%100; + if(sc->data[SC_HALLUCINATION] && damage) + damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rand()%100; } WBUFW(buf,0)=0x115; @@ -8084,7 +8084,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) else if (pc_cant_act(sd)) return; - if(sd->sc.count && sd->sc.data[SC_RUN].timer != -1) + if(sd->sc.data[SC_RUN]) return; pc_delinvincibletimer(sd); @@ -8109,7 +8109,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) WFIFOW(fd,0) = 0x18b; /* Rovert's prevent logout option fixed [Valaris] */ - if (sd->sc.data[SC_CLOAKING].timer==-1 && sd->sc.data[SC_HIDING].timer==-1 && + if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) { clif_setwaitclose(fd); @@ -8176,7 +8176,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) if( is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) ) return; - if( sd->sc.data[SC_BERSERK].timer != -1 || (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -8355,9 +8355,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, } if (sd->sc.count && - (sd->sc.data[SC_TRICKDEAD].timer != -1 || - sd->sc.data[SC_AUTOCOUNTER].timer != -1 || - sd->sc.data[SC_BLADESTOP].timer != -1)) + (sd->sc.data[SC_TRICKDEAD] || + sd->sc.data[SC_AUTOCOUNTER] || + sd->sc.data[SC_BLADESTOP])) return; pc_stop_walking(sd, 1); @@ -8404,8 +8404,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, break; if (sd->sc.count && ( - sd->sc.data[SC_DANCING].timer != -1 || - (sd->sc.data[SC_GRAVITATION].timer != -1 && sd->sc.data[SC_GRAVITATION].val3 == BCT_SELF) + sd->sc.data[SC_DANCING] || + (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) )) //No sitting during these states either. break; @@ -8487,7 +8487,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if (is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) ) return; - if (sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT)) + if (sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) return; if (battle_config.min_chat_delay) @@ -8665,9 +8665,9 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) break; if(sd->sc.count && ( - sd->sc.data[SC_TRICKDEAD].timer != -1 || - sd->sc.data[SC_BLADESTOP].timer != -1 || - (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOITEM)) + sd->sc.data[SC_TRICKDEAD] || + sd->sc.data[SC_BLADESTOP] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)) ) break; @@ -8696,9 +8696,9 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) return; if (sd->sc.count && ( - sd->sc.data[SC_AUTOCOUNTER].timer != -1 || - sd->sc.data[SC_BLADESTOP].timer != -1 || - (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOITEM) + sd->sc.data[SC_AUTOCOUNTER] || + sd->sc.data[SC_BLADESTOP] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) )) return; @@ -8768,7 +8768,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) else if (pc_cant_act(sd)) return; - if(sd->sc.data[SC_BLADESTOP].timer!=-1 || sd->sc.data[SC_BERSERK].timer!=-1 ) + if(sd->sc.data[SC_BLADESTOP] || sd->sc.data[SC_BERSERK]) return; if(!sd->status.inventory[index].identify) { @@ -8916,7 +8916,7 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) char s_title[CHATROOM_TITLE_SIZE]; char s_password[CHATROOM_PASS_SIZE]; - if (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOROOM) + if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) return; if(battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 4) { clif_skill_fail(sd,1,0,3); @@ -9241,10 +9241,10 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) sd->skillitem = sd->skillitemlv = 0; if (skillnum == MO_EXTREMITYFIST) { - if ((sd->sc.data[SC_COMBO].timer == -1 || - (sd->sc.data[SC_COMBO].val1 != MO_COMBOFINISH && - sd->sc.data[SC_COMBO].val1 != CH_TIGERFIST && - sd->sc.data[SC_COMBO].val1 != CH_CHAINCRUSH))) { + if ((!sd->sc.data[SC_COMBO] || + (sd->sc.data[SC_COMBO]->val1 != MO_COMBOFINISH && + sd->sc.data[SC_COMBO]->val1 != CH_TIGERFIST && + sd->sc.data[SC_COMBO]->val1 != CH_CHAINCRUSH))) { if (!sd->state.skill_flag ) { sd->state.skill_flag = 1; clif_skillinfo(sd, MO_EXTREMITYFIST, INF_ATTACK_SKILL, -1); @@ -9256,8 +9256,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) } } if (skillnum == TK_JUMPKICK) { - if (sd->sc.data[SC_COMBO].timer == -1 || - sd->sc.data[SC_COMBO].val1 != TK_JUMPKICK) { + if (!sd->sc.data[SC_COMBO] || sd->sc.data[SC_COMBO]->val1 != TK_JUMPKICK) { if (!sd->state.skill_flag ) { sd->state.skill_flag = 1; clif_skillinfo(sd, TK_JUMPKICK, INF_ATTACK_SKILL, -1); @@ -9893,7 +9892,7 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) if( is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) ) return; - if( sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -9950,7 +9949,7 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) bool flag = (bool)RFIFOB(fd,84); const uint8* data = (uint8*)RFIFOP(fd,85); - if( sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOROOM ) + if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM ) return; if( map[sd->bl.m].flag.novending || map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) ) { clif_displaymessage (sd->fd, msg_txt(276)); // "You can't open shop on this map" @@ -10165,7 +10164,7 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) if( is_atcommand(fd, sd, message) || is_charcommand(fd, sd, message) ) return; - if( sd->sc.data[SC_BERSERK].timer!=-1 || (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) diff --git a/src/map/map.c b/src/map/map.c index 5cff144b9..d113e8a6d 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -454,17 +454,17 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) skill_unit_move(bl,tick,2); sc = status_get_sc(bl); if (sc && sc->count) { - if (sc->data[SC_CLOSECONFINE].timer != -1) + if (sc->data[SC_CLOSECONFINE]) status_change_end(bl, SC_CLOSECONFINE, -1); - if (sc->data[SC_CLOSECONFINE2].timer != -1) + if (sc->data[SC_CLOSECONFINE2]) status_change_end(bl, SC_CLOSECONFINE2, -1); -// if (sc->data[SC_BLADESTOP].timer != -1) //Won't stop when you are knocked away, go figure... +// if (sc->data[SC_BLADESTOP]) //Won't stop when you are knocked away, go figure... // status_change_end(bl, SC_BLADESTOP, -1); - if (sc->data[SC_BASILICA].timer != -1) + if (sc->data[SC_BASILICA]) status_change_end(bl, SC_BASILICA, -1); - if (sc->data[SC_TATAMIGAESHI].timer != -1) + if (sc->data[SC_TATAMIGAESHI]) status_change_end(bl, SC_TATAMIGAESHI, -1); - if (sc->data[SC_MAGICROD].timer != -1) + if (sc->data[SC_MAGICROD]) status_change_end(bl, SC_MAGICROD, -1); } } else @@ -484,12 +484,12 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) skill_unit_move(bl,tick,3); if (sc) { if (sc->count) { - if (sc->data[SC_CLOAKING].timer != -1) - skill_check_cloaking(bl, sc); - if (sc->data[SC_DANCING].timer != -1) - skill_unit_move_unit_group((struct skill_unit_group *)sc->data[SC_DANCING].val2, bl->m, x1-x0, y1-y0); - if (sc->data[SC_WARM].timer != -1) - skill_unit_move_unit_group((struct skill_unit_group *)sc->data[SC_WARM].val4, bl->m, x1-x0, y1-y0); + if (sc->data[SC_CLOAKING]) + skill_check_cloaking(bl, sc->data[SC_CLOAKING]); + if (sc->data[SC_DANCING]) + skill_unit_move_unit_group((struct skill_unit_group *)sc->data[SC_DANCING]->val2, bl->m, x1-x0, y1-y0); + if (sc->data[SC_WARM]) + skill_unit_move_unit_group((struct skill_unit_group *)sc->data[SC_WARM]->val4, bl->m, x1-x0, y1-y0); } } } else @@ -3073,6 +3073,7 @@ void do_final(void) do_final_guild(); do_final_party(); do_final_pc(); + do_final_status(); do_final_pet(); do_final_mob(); do_final_msg(); diff --git a/src/map/map.h b/src/map/map.h index 6f3b27c2b..dcc2412d1 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -374,12 +374,17 @@ struct status_change_entry { }; struct status_change { - struct status_change_entry data[SC_MAX]; - short count; + unsigned int option;// effect state + unsigned int opt3;// skill state unsigned short opt1;// body state unsigned short opt2;// health state - unsigned int opt3; - unsigned int option;// effect state + unsigned char count; + //TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive. + unsigned char jb_flag; //Joint Beat type flag + unsigned short mp_matk_min, mp_matk_max; //Previous matk min/max for ground spells (Amplify magic power) + int sg_id; //ID of the previous Storm gust that hit you + unsigned char sg_counter; //Storm gust counter (previous hits from storm gust) + struct status_change_entry *data[SC_MAX]; }; struct s_vending { diff --git a/src/map/mob.c b/src/map/mob.c index 00ef6f794..d38e4b098 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1141,13 +1141,13 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) return 0; // Abnormalities - if((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->sc.data[SC_BLADESTOP].timer != -1) + if((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->sc.data[SC_BLADESTOP]) { //Should reset targets. md->target_id = md->attacked_id = 0; return 0; } - if (md->sc.count && md->sc.data[SC_BLIND].timer != -1) + if (md->sc.count && md->sc.data[SC_BLIND]) view_range = 3; else view_range = md->db->range2; @@ -1181,7 +1181,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) if (!battle_check_range(&md->bl, tbl, md->status.rhw.range) && ( //Can't attack back and can't reach back. (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && - (battle_config.mob_ai&0x2 || md->sc.data[SC_SPIDERWEB].timer != -1)) || + (battle_config.mob_ai&0x2 || md->sc.data[SC_SPIDERWEB])) || (!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH)) ) && md->state.attacked_count++ >= RUDE_ATTACKED_COUNT && @@ -1200,7 +1200,7 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) (!battle_check_range(&md->bl, abl, md->status.rhw.range) && ( //Reach check (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && - (battle_config.mob_ai&0x2 || md->sc.data[SC_SPIDERWEB].timer != -1)) || + (battle_config.mob_ai&0x2 || md->sc.data[SC_SPIDERWEB])) || !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH) ) ) @@ -1787,9 +1787,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) md->state.skillstate = MSS_DEAD; mobskill_use(md,tick,-1); //On Dead skill. - if (md->sc.data[SC_KAIZEL].timer != -1) + if (md->sc.data[SC_KAIZEL]) { //Revive in a bit. - add_timer(gettick()+3000, mob_respawn, md->bl.id, 10*md->sc.data[SC_KAIZEL].val1); //% of life to rebirth with + add_timer(gettick()+3000, mob_respawn, md->bl.id, md->sc.data[SC_KAIZEL]->val2); //% of life to rebirth with map_delblock(&md->bl); return 1; //Return 1 to only clear the object. } @@ -1900,8 +1900,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) bonus = 100; - if (md->sc.data[SC_RICHMANKIM].timer != -1) - bonus += md->sc.data[SC_RICHMANKIM].val2; + if (md->sc.data[SC_RICHMANKIM]) + bonus += md->sc.data[SC_RICHMANKIM]->val2; if(battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris] bonus += (md->level-md->db->lv)*battle_config.mobs_level_up_exp_rate; @@ -2017,13 +2017,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) // attempt to drop the item if (rand() % 10000 >= drop_rate) - { - if (sd && sd->sc.data[SC_ITEMBOOST].timer != -1) - { - if (rand() % 10000 >= drop_rate) - continue; // Double try by Bubble Gum - } - else + { // Double try by Bubble Gum + if (!(sd && sd->sc.data[SC_ITEMBOOST] && rand() % 10000 < drop_rate)) continue; } @@ -2667,11 +2662,11 @@ int mob_getfriendstatus_sub(struct block_list *bl,va_list ap) if( cond2==-1 ){ int j; for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){ - if ((flag=(md->sc.data[j].timer!=-1))) //Once an effect was found, break out. [Skotlex] + if ((flag=(md->sc.data[j] != NULL))) //Once an effect was found, break out. [Skotlex] break; } }else - flag=( md->sc.data[cond2].timer!=-1 ); + flag=( md->sc.data[cond2] != NULL ); if( flag^( cond1==MSC_FRIENDSTATUSOFF ) ) (*fr)=md; @@ -2755,10 +2750,10 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) flag = 0; } else if (ms[i].cond2 == -1) { for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++) - if ((flag = (md->sc.data[j].timer != -1)) != 0) + if ((flag = (md->sc.data[j]!=NULL)) != 0) break; } else { - flag = (md->sc.data[ms[i].cond2].timer != -1); + flag = (md->sc.data[ms[i].cond2]!=NULL); } flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break; case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp% @@ -3236,7 +3231,7 @@ static bool mob_parse_dbrow(char** str) } if (mob_db_data[class_] == NULL) - mob_db_data[class_] = aCalloc(1, sizeof (struct mob_data)); + mob_db_data[class_] = aCalloc(1, sizeof (struct mob_db)); db = mob_db_data[class_]; status = &db->status; diff --git a/src/map/party.c b/src/map/party.c index 70fdafe97..772fd9ab6 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -663,7 +663,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, int skillid, in break; case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR - && sd->sc.data[SC_READYCOUNTER].timer != -1 + && sd->sc.data[SC_READYCOUNTER] && pc_checkskill(p_sd,SG_FRIEND)) { sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, 50+50*pc_checkskill(p_sd,SG_FRIEND), //+100/150/200% rate diff --git a/src/map/pc.c b/src/map/pc.c index 913f108d0..1dcf97fda 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -339,7 +339,7 @@ int pc_makesavestatus(struct map_session_data *sd) //status change load/saving. [Skotlex] sd->status.option = sd->sc.option&(OPTION_CART|OPTION_FALCON|OPTION_RIDING); - if (sd->sc.count && sd->sc.data[SC_JAILED].timer != -1) + if (sd->sc.data[SC_JAILED]) { //When Jailed, do not move last point. if(pc_isdead(sd)){ pc_setrestartvalue(sd,0); @@ -563,16 +563,16 @@ int pc_isequip(struct map_session_data *sd,int n) return 0; if (sd->sc.count) { - if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_STRIPWEAPON].timer != -1) // Also works with left-hand weapons [DracoRPG] + if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_STRIPWEAPON]) // Also works with left-hand weapons [DracoRPG] return 0; - if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_STRIPSHIELD].timer != -1) + if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_STRIPSHIELD]) return 0; - if(item->equip & EQP_ARMOR && sd->sc.data[SC_STRIPARMOR].timer != -1) + if(item->equip & EQP_ARMOR && sd->sc.data[SC_STRIPARMOR]) return 0; - if(item->equip & EQP_HELM && sd->sc.data[SC_STRIPHELM].timer != -1) + if(item->equip & EQP_HELM && sd->sc.data[SC_STRIPHELM]) return 0; - if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_SUPERNOVICE) { + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) { //Spirit of Super Novice equip bonuses. [Skotlex] if (sd->status.base_level > 90 && item->equip & EQP_HELM) return 1; //Can equip all helms @@ -964,7 +964,7 @@ int pc_calc_skilltree(struct map_session_data *sd) sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; sd->status.skill[i].flag=0; } - if(sd->sc.count && sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU) + if(sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU) { //Enable Bard/Dancer spirit linked skills. if (sd->status.sex) { //Link dancer skills to bard. sd->status.skill[i].id=i; @@ -1024,7 +1024,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if(!sd->status.skill[id].lv && ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || inf2&INF2_WEDDING_SKILL || - (inf2&INF2_SPIRIT_SKILL && !(sd->sc.count && sd->sc.data[SC_SPIRIT].timer != -1)) + (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) )) continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills. @@ -1106,7 +1106,7 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill) if(!sd->status.skill[id].lv && ( (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || j&INF2_WEDDING_SKILL || - (j&INF2_SPIRIT_SKILL && !(sd->sc.count && sd->sc.data[SC_SPIRIT].timer != -1)) + (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) )) continue; //Cannot be learned via normal means. @@ -1177,7 +1177,7 @@ int pc_updateweightstatus(struct map_session_data *sd) nullpo_retr(1, sd); - old_overweight = (sd->sc.data[SC_WEIGHT90].timer != -1) ? 2 : (sd->sc.data[SC_WEIGHT50].timer != -1) ? 1 : 0; + old_overweight = (sd->sc.data[SC_WEIGHT90]) ? 2 : (sd->sc.data[SC_WEIGHT50]) ? 1 : 0; new_overweight = (pc_is90overweight(sd)) ? 2 : (pc_is50overweight(sd)) ? 1 : 0; if( old_overweight == new_overweight ) @@ -3092,12 +3092,12 @@ int pc_useitem(struct map_session_data *sd,int n) return 0; if (sd->sc.count && ( - sd->sc.data[SC_BERSERK].timer!=-1 || - sd->sc.data[SC_MARIONETTE].timer!=-1 || - (sd->sc.data[SC_GRAVITATION].timer!=-1 && sd->sc.data[SC_GRAVITATION].val3 == BCT_SELF) || - sd->sc.data[SC_TRICKDEAD].timer != -1 || - sd->sc.data[SC_BLADESTOP].timer != -1 || - (sd->sc.data[SC_NOCHAT].timer!=-1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOITEM) + sd->sc.data[SC_BERSERK] || + sd->sc.data[SC_MARIONETTE] || + (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) || + sd->sc.data[SC_TRICKDEAD] || + sd->sc.data[SC_BLADESTOP] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) )) return 0; @@ -3123,7 +3123,7 @@ int pc_useitem(struct map_session_data *sd,int n) pc_famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST)) { potion_flag = 2; // Famous player's potions have 50% more efficiency - if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_ROGUE) + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ROGUE) potion_flag = 3; //Even more effective potions. } @@ -3399,7 +3399,7 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target) return 0; md = (TBL_MOB*)target; - if(md->state.steal_coin_flag || md->sc.data[SC_STONE].timer != -1 || md->sc.data[SC_FREEZE].timer != -1) + if(md->state.steal_coin_flag || md->sc.data[SC_STONE] || md->sc.data[SC_FREEZE]) return 0; if (md->class_>=1324 && md->class_<1364) @@ -3439,19 +3439,21 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y { //Misc map-changing settings if (sd->sc.count) { //Cancel some map related stuff. - if (sd->sc.data[SC_JAILED].timer != -1) + if (sd->sc.data[SC_JAILED]) return 1; //You may not get out! - if (sd->sc.data[SC_WARM].timer != -1) + if (sd->sc.data[SC_WARM]) status_change_end(&sd->bl,SC_WARM,-1); - if (sd->sc.data[SC_SUN_COMFORT].timer != -1) + if (sd->sc.data[SC_SUN_COMFORT]) status_change_end(&sd->bl,SC_SUN_COMFORT,-1); - if (sd->sc.data[SC_MOON_COMFORT].timer != -1) + if (sd->sc.data[SC_MOON_COMFORT]) status_change_end(&sd->bl,SC_MOON_COMFORT,-1); - if (sd->sc.data[SC_STAR_COMFORT].timer != -1) + if (sd->sc.data[SC_STAR_COMFORT]) status_change_end(&sd->bl,SC_STAR_COMFORT,-1); - if (sd->sc.data[SC_KNOWLEDGE].timer != -1) { - delete_timer(sd->sc.data[SC_KNOWLEDGE].timer, status_change_timer); - sd->sc.data[SC_KNOWLEDGE].timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sd->sc.data[SC_KNOWLEDGE].val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE); + if (sd->sc.data[SC_KNOWLEDGE]) { + struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE]; + if (sce->timer != -1) + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE); } } if (battle_config.clear_unit_onwarp&BL_PC) @@ -3677,18 +3679,18 @@ int pc_checkallowskill(struct map_session_data *sd) for (i = 0; i < ARRAYLENGTH(scw_list); i++) { // Skills requiring specific weapon types - if(sd->sc.data[scw_list[i]].timer!=-1 && + if(sd->sc.data[scw_list[i]] && !pc_check_weapontype(sd,skill_get_weapontype(StatusSkillChangeTable[scw_list[i]]))) status_change_end(&sd->bl,scw_list[i],-1); } - if(sd->sc.data[SC_SPURT].timer!=-1 && sd->status.weapon) + if(sd->sc.data[SC_SPURT] && sd->status.weapon) // Spurt requires bare hands (feet, in fact xD) status_change_end(&sd->bl,SC_SPURT,-1); if(sd->status.shield <= 0) { // Skills requiring a shield for (i = 0; i < ARRAYLENGTH(scs_list); i++) - if(sd->sc.data[scs_list[i]].timer!=-1) + if(sd->sc.data[scs_list[i]]) status_change_end(&sd->bl,scs_list[i],-1); } return 0; @@ -4199,7 +4201,7 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi //SG additional exp from Blessings [Komurka] - probably can be optimalized ^^;; temp = status_get_class(src); if(temp == sd->hate_mob[2] && - (battle_config.allow_skill_without_day || is_day_of_star() || sd->sc.data[SC_MIRACLE].timer!=-1)) + (battle_config.allow_skill_without_day || is_day_of_star() || sd->sc.data[SC_MIRACLE])) bonus += 20*pc_checkskill(sd,SG_STAR_BLESS); else if(temp == sd->hate_mob[1] && @@ -4214,8 +4216,8 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi (int)(status_get_lv(src) - sd->status.base_level) >= 20) bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris] - if (sd->sc.data[SC_EXPBOOST].timer != -1) - bonus += sd->sc.data[SC_EXPBOOST].val1; + if (sd->sc.data[SC_EXPBOOST]) + bonus += sd->sc.data[SC_EXPBOOST]->val1; if (!bonus) return; @@ -5104,7 +5106,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if(battle_config.death_penalty_type && sd->state.snovice_dead_flag != 1 && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty && !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg(sd->bl.m) - && sd->sc.data[SC_BABY].timer == -1 && sd->sc.data[SC_LIFEINSURANCE].timer == -1) + && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE]) { unsigned int base_penalty =0; if (battle_config.death_penalty_base > 0) { @@ -5228,16 +5230,17 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) return 1; } - if (sd->sc.count && sd->sc.data[SC_KAIZEL].timer != -1) + if (sd->sc.data[SC_KAIZEL]) { - j = sd->sc.data[SC_KAIZEL].val1; //Kaizel Lv. + j = sd->sc.data[SC_KAIZEL]->val1; //Kaizel Lv. + i = sd->sc.data[SC_KAIZEL]->val2; //Revive % pc_setstand(sd); status_change_clear(&sd->bl,0); clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,1,1); if(sd->special_state.restart_full_recover) status_percent_heal(&sd->bl, 100, 100); else - status_percent_heal(&sd->bl, 10*j, 0); + status_percent_heal(&sd->bl, i, 0); clif_resurrection(&sd->bl, 1); if(battle_config.pc_invincible_time) pc_setinvincibletimer(sd, battle_config.pc_invincible_time); @@ -5489,8 +5492,8 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp) hp = hp * bonus / 100; // Recovery Potion - if( sd->sc.count && sd->sc.data[SC_INCHEALRATE].timer!=-1 ) - hp += (int)(hp * sd->sc.data[SC_INCHEALRATE].val1/100.); + if( sd->sc.data[SC_INCHEALRATE] ) + hp += (int)(hp * sd->sc.data[SC_INCHEALRATE]->val1/100.); } if(sp) { bonus = 100 + (sd->battle_status.int_<<1) @@ -5502,10 +5505,10 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp) sp = sp * bonus / 100; } - if (sd->sc.count && sd->sc.data[SC_CRITICALWOUND].timer!=-1) + if (sd->sc.data[SC_CRITICALWOUND]) { - hp -= hp * sd->sc.data[SC_CRITICALWOUND].val2 / 100; - sp -= sp * sd->sc.data[SC_CRITICALWOUND].val2 / 100; + hp -= hp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100; } return status_heal(&sd->bl, hp, sp, 1); @@ -5606,7 +5609,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) for(i = 0; i < MAX_SKILL_TREE && (id = skill_tree[class_][i].id) > 0; i++) { //Remove status specific to your current tree skills. id = SkillStatusChangeTable(id); - if (id > SC_COMMON_MAX && sd->sc.data[id].timer != -1) + if (id > SC_COMMON_MAX && sd->sc.data[id]) status_change_end(&sd->bl, id, -1); } } @@ -6372,7 +6375,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) // -- moonsoul (if player is berserk then cannot equip) // - if(sd->sc.count && sd->sc.data[SC_BERSERK].timer!=-1){ + if(sd->sc.data[SC_BERSERK]){ clif_equipitemack(sd,n,0,0); // fail return 0; } @@ -6513,7 +6516,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) // -- moonsoul (if player is berserk then cannot unequip) // - if(!(flag&2) && sd->sc.count && (sd->sc.data[SC_BLADESTOP].timer!=-1 || sd->sc.data[SC_BERSERK].timer!=-1)){ + if(!(flag&2) && sd->sc.count && (sd->sc.data[SC_BLADESTOP] || sd->sc.data[SC_BERSERK])){ clif_unequipitemack(sd,n,0,0); return 0; } @@ -6535,7 +6538,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) sd->status.weapon = sd->weapontype2; pc_calcweapontype(sd); clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - if(sd->sc.data[SC_DANCING].timer!=-1) //When unequipping, stop dancing. [Skotlex] + if(sd->sc.data[SC_DANCING]) //When unequipping, stop dancing. [Skotlex] skill_stop_dancing(&sd->bl); } if(sd->status.inventory[n].equip & EQP_HAND_L) { @@ -6571,7 +6574,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) status_calc_pc(sd,0); } - if(sd->sc.count && sd->sc.data[SC_SIGNUMCRUCIS].timer != -1 && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele)) + if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele)) status_change_end(&sd->bl,SC_SIGNUMCRUCIS,-1); //OnUnEquip script [Skotlex] @@ -7091,7 +7094,7 @@ int map_night_timer(int tid, unsigned int tick, int id, int data) void pc_setstand(struct map_session_data *sd){ nullpo_retv(sd); - if(sd->sc.count && sd->sc.data[SC_TENSIONRELAX].timer!=-1) + if(sd->sc.data[SC_TENSIONRELAX]) status_change_end(&sd->bl,SC_TENSIONRELAX,-1); //Reset sitting tick. diff --git a/src/map/pet.c b/src/map/pet.c index fc4dd3875..e52753085 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -1127,7 +1127,7 @@ int pet_recovery_timer(int tid,unsigned int tick,int id,int data) return 0; } - if(sd->sc.count && sd->sc.data[pd->recovery->type].timer != -1) + if(sd->sc.data[pd->recovery->type]) { //Display a heal animation? //Detoxify is chosen for now. clif_skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1); diff --git a/src/map/skill.c b/src/map/skill.c index 46913de66..4bc847560 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -256,10 +256,10 @@ int skill_calc_heal (struct block_list *src, struct block_list *target, int skil sc = status_get_sc(target); if (sc && sc->count) { - if( sc->data[SC_CRITICALWOUND].timer!=-1 ) - heal -= heal * sc->data[SC_CRITICALWOUND].val2/100; - if( sc->data[SC_INCHEALRATE].timer!=-1 ) - heal += heal * sc->data[SC_INCHEALRATE].val1/100; + if( sc->data[SC_CRITICALWOUND] ) + heal -= heal * sc->data[SC_CRITICALWOUND]->val2/100; + if( sc->data[SC_INCHEALRATE] ) + heal += heal * sc->data[SC_INCHEALRATE]->val1/100; } return heal; } @@ -451,24 +451,24 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int clif_skill_fail(sd,RG_SNATCHER,0,0); } // Chance to trigger Taekwon kicks [Dralnu] - if(sc && sc->data[SC_COMBO].timer == -1) { - if(sc->data[SC_READYSTORM].timer != -1 && + if(sc && !sc->data[SC_COMBO]) { + if(sc->data[SC_READYSTORM] && sc_start(src,SC_COMBO, 15, TK_STORMKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered - else if(sc->data[SC_READYDOWN].timer != -1 && + else if(sc->data[SC_READYDOWN] && sc_start(src,SC_COMBO, 15, TK_DOWNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered - else if(sc->data[SC_READYTURN].timer != -1 && + else if(sc->data[SC_READYTURN] && sc_start(src,SC_COMBO, 15, TK_TURNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered - else if(sc->data[SC_READYCOUNTER].timer != -1) + else if(sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka] rate = 20; - if (sc->data[SC_SKILLRATE_UP].timer != -1 && sc->data[SC_SKILLRATE_UP].val1 == TK_COUNTER) { - rate += rate*sc->data[SC_SKILLRATE_UP].val2/100; + if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) { + rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; status_change_end(src,SC_SKILLRATE_UP,-1); } sc_start4(src,SC_COMBO, rate, TK_COUNTER, bl->id,0,0, @@ -486,15 +486,15 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int } if (sc) { - // Enchant Poison gives a chance to poison attacked enemies - if(sc->data[SC_ENCPOISON].timer != -1) //Don't use sc_start since chance comes in 1/10000 rate. - status_change_start(bl,SC_POISON,sc->data[SC_ENCPOISON].val2, - sc->data[SC_ENCPOISON].val1,0,0,0, - skill_get_time2(AS_ENCHANTPOISON,sc->data[SC_ENCPOISON].val1),0); + struct status_change_entry *sce; + // Enchant Poison gives a chance to poison attacked enemies + if((sce=sc->data[SC_ENCPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. + status_change_start(bl,SC_POISON,sce->val2, sce->val1,0,0,0, + skill_get_time2(AS_ENCHANTPOISON,sce->val1),0); // Enchant Deadly Poison gives a chance to deadly poison attacked enemies - if(sc->data[SC_EDP].timer != -1) - sc_start4(bl,SC_DPOISON,sc->data[SC_EDP].val2, - sc->data[SC_EDP].val1,0,0,0,skill_get_time2(ASC_EDP,sc->data[SC_EDP].val1)); + if((sce=sc->data[SC_EDP])) + sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,0,0,0, + skill_get_time2(ASC_EDP,sce->val1)); } } break; @@ -524,7 +524,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int case AS_GRIMTOOTH: skill = dstsd?SC_SLOWDOWN:SC_STOP; - if (tsc->data[skill].timer == -1) + if (!tsc->data[skill]) sc_start(bl,skill,100,skilllv,skill_get_time2(skillid, skilllv)); break; case MG_FROSTDIVER: @@ -533,9 +533,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int break; case WZ_STORMGUST: - //Use two since the counter is increased AFTER the attack. - if(tsc->data[SC_FREEZE].val3 >= 2) //Tharis pointed out that this is normal freeze chance with a base of 300% - sc_start(bl,SC_FREEZE,300,skilllv,skill_get_time2(skillid,skilllv)); + //Tharis pointed out that this is normal freeze chance with a base of 300% + if(tsc->sg_counter >= 3 && + sc_start(bl,SC_FREEZE,300,skilllv,skill_get_time2(skillid,skilllv))) + tsc->sg_counter = 0; break; case WZ_METEOR: @@ -689,7 +690,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int break; case PF_FOGWALL: - if (src != bl && tsc->data[SC_DELUGE].timer == -1) + if (src != bl && !tsc->data[SC_DELUGE]) status_change_start(bl,SC_BLIND,10000,skilllv,0,0,0,skill_get_time2(skillid,skilllv),8); break; @@ -700,9 +701,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int case LK_JOINTBEAT: skill = SkillStatusChangeTable(skillid); - if (tsc->data[skill].val4) { - sc_start2(bl,skill,(5*skilllv+5),skilllv,tsc->data[skill].val4&BREAK_FLAGS,skill_get_time2(skillid,skilllv)); - tsc->data[skill].val4 = 0; + if (tsc->jb_flag) { + sc_start2(bl,skill,(5*skilllv+5),skilllv,tsc->jb_flag&BREAK_FLAGS,skill_get_time2(skillid,skilllv)); + tsc->jb_flag = 0; } break; case ASC_METEORASSAULT: @@ -739,23 +740,23 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int //Cancel out Soul Linker status of the target. [Skotlex] if (tsc->count) { //Remove NORMAL potions effect. - if (tsc->data[SC_ASPDPOTION0].timer != -1 && !tsc->data[SC_ASPDPOTION0].val4) + if (tsc->data[SC_ASPDPOTION0] && !tsc->data[SC_ASPDPOTION0]->val4) status_change_end(bl, SC_ASPDPOTION0, -1); - if (tsc->data[SC_ASPDPOTION1].timer != -1 && !tsc->data[SC_ASPDPOTION1].val4) + if (tsc->data[SC_ASPDPOTION1] && !tsc->data[SC_ASPDPOTION1]->val4) status_change_end(bl, SC_ASPDPOTION1, -1); - if (tsc->data[SC_ASPDPOTION2].timer != -1 && !tsc->data[SC_ASPDPOTION2].val4) + if (tsc->data[SC_ASPDPOTION2] && !tsc->data[SC_ASPDPOTION2]->val4) status_change_end(bl, SC_ASPDPOTION2, -1); - if (tsc->data[SC_ASPDPOTION3].timer != -1 && !tsc->data[SC_ASPDPOTION3].val4) + if (tsc->data[SC_ASPDPOTION3] && !tsc->data[SC_ASPDPOTION3]->val4) status_change_end(bl, SC_ASPDPOTION3, -1); - if (tsc->data[SC_SPEEDUP0].timer != -1 && !tsc->data[SC_SPEEDUP0].val4) + if (tsc->data[SC_SPEEDUP0] && !tsc->data[SC_SPEEDUP0]->val4) status_change_end(bl, SC_SPEEDUP0, -1); - if (tsc->data[SC_SPEEDUP1].timer != -1 && !tsc->data[SC_SPEEDUP1].val4) + if (tsc->data[SC_SPEEDUP1] && !tsc->data[SC_SPEEDUP1]->val4) status_change_end(bl, SC_SPEEDUP1, -1); - if (tsc->data[SC_SPIRIT].timer != -1) + if (tsc->data[SC_SPIRIT]) status_change_end(bl, SC_SPIRIT, -1); - if (tsc->data[SC_ONEHAND].timer != -1) + if (tsc->data[SC_ONEHAND]) status_change_end(bl, SC_ONEHAND, -1); - if (tsc->data[SC_ADRENALINE2].timer != -1) + if (tsc->data[SC_ADRENALINE2]) status_change_end(bl, SC_ADRENALINE2, -1); } break; @@ -954,9 +955,9 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * switch(skillid){ case 0: //Normal Attack - if(tsc && tsc->data[SC_KAAHI].timer != -1 && tsc->data[SC_KAAHI].val4 == -1) - tsc->data[SC_KAAHI].val4 = add_timer( - tick+skill_get_time2(SL_KAAHI,tsc->data[SC_KAAHI].val1), + if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == -1) + tsc->data[SC_KAAHI]->val4 = add_timer( + tick+skill_get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, bl->id, SC_KAAHI); //Activate heal. break; case MO_EXTREMITYFIST: @@ -1135,7 +1136,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in for (i = 0; i < 4; i++) { if (where&where_list[i]) { - if (sc && sc->count && sc->data[scdef[i]].timer != -1) + if (sc && sc->count && sc->data[scdef[i]]) where&=~where_list[i]; else if (rand()%10000 >= rate) where&=~where_list[i]; @@ -1194,7 +1195,7 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int return 0; for (i = 0; i < ARRAYLENGTH(pos); i++) { - if (where&pos[i] && sc->data[sc_def[i]].timer != -1) + if (where&pos[i] && sc->data[sc_def[i]]) where&=~pos[i]; } if (!where) return 0; @@ -1297,13 +1298,13 @@ static int skill_magic_reflect(struct block_list *bl, int type) if(sc && sc->count) { - if(sc->data[SC_MAGICMIRROR].timer != -1 && rand()%100 < sc->data[SC_MAGICMIRROR].val2) + if(sc->data[SC_MAGICMIRROR] && rand()%100 < sc->data[SC_MAGICMIRROR]->val2) return 1; - if(sc->data[SC_KAITE].timer != -1 && (sd || status_get_lv(bl) <= 80)) + if(sc->data[SC_KAITE] && (sd || status_get_lv(bl) <= 80)) { //Works on players or mobs with level under 80. clif_specialeffect(bl, 438, AREA); - if (--sc->data[SC_KAITE].val2 <= 0) + if (--sc->data[SC_KAITE]->val2 <= 0) status_change_end(bl, SC_KAITE, -1); return 1; } @@ -1362,7 +1363,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if(skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) return 0; //Trick Dead protects you from damage, but not from buffs and the like, hence it's placed here. - if (sc && sc->data[SC_TRICKDEAD].timer != -1 && !(sstatus->mode&MD_BOSS)) + if (sc && sc->data[SC_TRICKDEAD] && !(sstatus->mode&MD_BOSS)) return 0; dmg=battle_calc_attack(attack_type,src,bl,skillid,skilllv,flag&0xFFF); @@ -1399,16 +1400,16 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if (sc && !sc->count) sc = NULL; //Don't need it. //Spirit of Wizard blocks bounced back spells. - if (sc && sc->data[SC_SPIRIT].timer != -1 && - sc->data[SC_SPIRIT].val2 == SL_WIZARD) + if (sc && sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_WIZARD) { //It should only consume once per skill casted. Val3 is the skill //id and val4 is the ID of the damage src, this should account for //ground spells (and single target spells will be completed on //castend_id) [Skotlex] if (tsd && !( - sc->data[SC_SPIRIT].val3 == skillid && - sc->data[SC_SPIRIT].val4 == dsrc->id) + sc->data[SC_SPIRIT]->val3 == skillid && + sc->data[SC_SPIRIT]->val4 == dsrc->id) ) { //Check if you have stone to consume. type = pc_search_inventory (tsd, 7321); if (type >= 0) @@ -1418,21 +1419,21 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if (type >= 0) { dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_FLEE; - sc->data[SC_SPIRIT].val3 = skillid; - sc->data[SC_SPIRIT].val4 = dsrc->id; + sc->data[SC_SPIRIT]->val3 = skillid; + sc->data[SC_SPIRIT]->val4 = dsrc->id; } } } - if(sc && sc->data[SC_MAGICROD].timer != -1 && src == dsrc) { + if(sc && sc->data[SC_MAGICROD] && src == dsrc) { int sp = skill_get_sp(skillid,skilllv); dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_FLEE; //This will prevent skill additional effect from taking effect. [Skotlex] - sp = sp * sc->data[SC_MAGICROD].val2 / 100; + sp = sp * sc->data[SC_MAGICROD]->val2 / 100; if(skillid == WZ_WATERBALL && skilllv > 1) sp = sp/((skilllv|1)*(skilllv|1)); //Estimate SP cost of a single water-ball status_heal(bl, 0, sp, 2); - clif_skill_nodamage(bl,bl,SA_MAGICROD,sc->data[SC_MAGICROD].val1,1); + clif_skill_nodamage(bl,bl,SA_MAGICROD,sc->data[SC_MAGICROD]->val1,1); } } @@ -1462,7 +1463,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if(sd) { int flag = 0; //Used to signal if this skill can be combo'ed later on. - if (sd->sc.data[SC_COMBO].timer!=-1) + if (sd->sc.data[SC_COMBO]) { //End combo state after skill is invoked. [Skotlex] switch (skillid) { case TK_TURNKICK: @@ -1473,10 +1474,10 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds { //Extend combo time. sd->skillid_old = skillid; //Set as previous so you can't repeat sd->skilllv_old = skilllv; - sd->sc.data[SC_COMBO].val1 = skillid; //Update combo-skill - delete_timer(sd->sc.data[SC_COMBO].timer, status_change_timer); - sd->sc.data[SC_COMBO].timer = add_timer( - tick+sd->sc.data[SC_COMBO].val4, + sd->sc.data[SC_COMBO]->val1 = skillid; //Update combo-skill + delete_timer(sd->sc.data[SC_COMBO]->timer, status_change_timer); + sd->sc.data[SC_COMBO]->timer = add_timer( + tick+sd->sc.data[SC_COMBO]->val4, status_change_timer, src->id, SC_COMBO); break; } @@ -1503,7 +1504,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if (!flag && pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1) flag=1; case CH_CHAINCRUSH: - if (!flag && pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball > 0 && sd->sc.data[SC_EXPLOSIONSPIRITS].timer != -1) + if (!flag && pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball > 0 && sd->sc.data[SC_EXPLOSIONSPIRITS]) flag=1; break; case AC_DOUBLE: @@ -1524,7 +1525,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds break; case SL_STIN: case SL_STUN: - if (skilllv >= 7 && sd->sc.data[SC_SMA].timer == -1) + if (skilllv >= 7 && !sd->sc.data[SC_SMA]) sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA, skilllv)); break; case GS_FULLBUSTER: @@ -1583,7 +1584,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if(damage > 0 && dmg.flag&BF_SKILL && tsd && pc_checkskill(tsd,RG_PLAGIARISM) - && (!sc || sc->data[SC_PRESERVE].timer == -1) + && (!sc || !sc->data[SC_PRESERVE]) && damage < tsd->status.hp) { //Updated to not be able to copy skills if the blow will kill you. [Skotlex] if ((!tsd->status.skill[skillid].id || tsd->status.skill[skillid].flag >= 13) && @@ -1677,8 +1678,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds skillid == MG_COLDBOLT || skillid == MG_FIREBOLT || skillid == MG_LIGHTNINGBOLT ) && (sc = status_get_sc(src)) && - sc->count && sc->data[SC_DOUBLECAST].timer != -1 && - rand() % 100 < 40+10*sc->data[SC_DOUBLECAST].val1) + sc->data[SC_DOUBLECAST] && + rand() % 100 < sc->data[SC_DOUBLECAST]->val2) { // skill_addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skillid, skilllv, BF_MAGIC, flag|2); skill_addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skillid, skilllv, BF_MAGIC, flag|2); @@ -1853,11 +1854,11 @@ int skill_guildaura_sub (struct block_list *bl, va_list ap) strvit = va_arg(ap,int); agidex = va_arg(ap,int); - if (sd->sc.count && sd->sc.data[SC_GUILDAURA].timer != -1) { - if (sd->sc.data[SC_GUILDAURA].val3 != strvit || - sd->sc.data[SC_GUILDAURA].val4 != agidex) { - sd->sc.data[SC_GUILDAURA].val3 = strvit; - sd->sc.data[SC_GUILDAURA].val4 = agidex; + if (sd->sc.data[SC_GUILDAURA]) { + struct status_change_entry *sce = sd->sc.data[SC_GUILDAURA]; + if (sce->val3 != strvit || sce->val4 != agidex) { + sce->val3 = strvit; + sce->val4 = agidex; status_calc_bl(&sd->bl, StatusChangeFlagTable[SC_GUILDAURA]); } return 0; @@ -1876,7 +1877,6 @@ int skill_guildaura_sub (struct block_list *bl, va_list ap) static int skill_check_condition_hom (struct homun_data *hd, int skill, int lv, int type) { struct status_data *status; - struct status_change *sc; TBL_PC * sd; int i,j,hp,sp,hp_rate,sp_rate,state,mhp ; int itemid[10],amount[10]; @@ -1888,10 +1888,7 @@ static int skill_check_condition_hom (struct homun_data *hd, int skill, int lv, if (lv <= 0) return 0; status = &hd->battle_status; - sc = &hd->sc; - if (!sc->count) - sc = NULL; - + //Code speedup, rather than using skill_get_* over and over again. j = skill_get_index(skill); if( j == 0 ) @@ -2081,12 +2078,12 @@ static int skill_timerskill (int tid, unsigned int tick, int id, int data) } else { struct status_change *sc = status_get_sc(src); if(sc) { - if(sc->data[SC_MAGICPOWER].timer != -1) + if(sc->data[SC_MAGICPOWER]) status_change_end(src,SC_MAGICPOWER,-1); - if(sc->data[SC_SPIRIT].timer != -1 && - sc->data[SC_SPIRIT].val2 == SL_WIZARD && - sc->data[SC_SPIRIT].val3 == skl->skill_id) - sc->data[SC_SPIRIT].val3 = 0; //Clear bounced spell check. + if(sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_WIZARD && + sc->data[SC_SPIRIT]->val3 == skl->skill_id) + sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. } } break; @@ -2311,15 +2308,14 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case 4: flag |= BREAK_WAIST; break; case 5: flag |= BREAK_NECK; break; } - //Seems a little ugly, but we have done this or worse with other skills like Storm Gust. [Skotlex] - //val3 holds the status that it should start when it connects. + //TODO: is there really no cleaner way to do this? sc = status_get_sc(bl); - if (sc) sc->data[SkillStatusChangeTable(skillid)].val4 = flag; + if (sc) sc->jb_flag = flag; skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; case MO_COMBOFINISH: - if (!(flag&1) && sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_MONK) + if (!(flag&1) && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) { //Becomes a splash attack when Soul Linked. map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv),splash_target(src), @@ -2389,7 +2385,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case MO_INVESTIGATE: skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if (sc && sc->data[SC_BLADESTOP].timer != -1) + if (sc && sc->data[SC_BLADESTOP]) status_change_end(src,SC_BLADESTOP,-1); break; @@ -2397,7 +2393,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int { int dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl); if ((!check_distance_bl(src, bl, 0) && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) { - if (sc && sc->data[SC_HIDING].timer != -1) + if (sc && sc->data[SC_HIDING]) status_change_end(src, SC_HIDING, -1); skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] @@ -2415,29 +2411,29 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int for (i = 1; i < sd->spiritball_old; i++) skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag); } - if (sc && sc->data[SC_BLADESTOP].timer != -1) + if (sc && sc->data[SC_BLADESTOP]) status_change_end(src,SC_BLADESTOP,-1); break; case MO_CHAINCOMBO: skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if (sc && sc->data[SC_BLADESTOP].timer != -1) + if (sc && sc->data[SC_BLADESTOP]) status_change_end(src,SC_BLADESTOP,-1); break; case NJ_ISSEN: if (sc) { - if (sc->data[SC_NEN].timer != -1) + if (sc->data[SC_NEN]) status_change_end(src,SC_NEN,-1); - if (sc->data[SC_HIDING].timer != -1) + if (sc->data[SC_HIDING]) status_change_end(src,SC_HIDING,-1); } case MO_EXTREMITYFIST: if (sc && skillid == MO_EXTREMITYFIST) { - if (sc->data[SC_EXPLOSIONSPIRITS].timer != -1) + if (sc->data[SC_EXPLOSIONSPIRITS]) status_change_end(src, SC_EXPLOSIONSPIRITS, -1); - if (sc->data[SC_BLADESTOP].timer != -1) + if (sc->data[SC_BLADESTOP]) status_change_end(src,SC_BLADESTOP,-1); } //Client expects you to move to target regardless of distance @@ -2690,7 +2686,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int break; case SL_SMA: - if (sc && sc->data[SC_SMA].timer != -1) + if (sc && sc->data[SC_SMA]) status_change_end(src,SC_SMA,-1); case SL_STIN: case SL_STUN: @@ -2764,7 +2760,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int if (unit_movepos(src, x, y, 0, 0)) clif_slide(src,src->x,src->y); } - if (sc && sc->data[SC_HIDING].timer != -1) + if (sc && sc->data[SC_HIDING]) status_change_end(src, SC_HIDING, -1); skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; @@ -2810,6 +2806,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in struct map_session_data *dstsd; struct status_data *sstatus, *tstatus; struct status_change *tsc; + struct status_change_entry *tsce; struct mob_data *md; struct mob_data *dstmd; int i,type; @@ -2870,6 +2867,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in type = SkillStatusChangeTable(skillid); tsc = status_get_sc(bl); + tsce = (tsc && type != -1)?tsc->data[type]:NULL; if (src!=bl && type > -1 && (i = skill_get_ele(skillid, skilllv)) > ELE_NEUTRAL && @@ -2898,9 +2896,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (tsc && tsc->count) { - if (tsc->data[SC_KAITE].timer != -1 && !(sstatus->mode&MD_BOSS) + if (tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) ) { //Bounce back heal - if (--tsc->data[SC_KAITE].val2 <= 0) + if (--tsc->data[SC_KAITE]->val2 <= 0) status_change_end(bl, SC_KAITE, -1); if (src == bl) heal=0; //When you try to heal yourself under Kaite, the heal is voided. @@ -2909,7 +2907,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in dstsd = sd; } } else - if (tsc->data[SC_BERSERK].timer != -1) + if (tsc->data[SC_BERSERK]) heal = 0; //Needed so that it actually displays 0 when healing. } heal_get_jobexp = status_heal(bl,heal,0,0); @@ -3016,7 +3014,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case PR_LEXDIVINA: - if (tsc && tsc->count && tsc->data[type].timer != -1) { + if (tsce) { status_change_end(bl,type, -1); clif_skill_nodamage (src, bl, skillid, skilllv, 1); } else @@ -3160,14 +3158,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in int type2 = SC_MARIONETTE2; if(sc && tsc){ - if (sc->data[type].timer == -1 && tsc->data[type2].timer == -1) { + if (!sc->data[type] && !tsc->data[type2]) { sc_start(src,type,100,bl->id,skill_get_time(skillid,skilllv)); sc_start(bl,type2,100,src->id,skill_get_time(skillid,skilllv)); clif_marionette(src, bl); clif_skill_nodamage(src,bl,skillid,skilllv,1); } - else if (sc->data[type].timer != -1 && tsc->data[type2].timer != -1 && - sc->data[type].val1 == bl->id && tsc->data[type2].val1 == src->id) { + else if (sc->data[type] && tsc->data[type2] && + sc->data[type]->val1 == bl->id && tsc->data[type2]->val1 == src->id) { status_change_end(src, type, -1); status_change_end(bl, type2, -1); } @@ -3190,15 +3188,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SA_SEISMICWEAPON: if (dstsd) { if(dstsd->status.weapon == W_FIST || - (dstsd->sc.count && dstsd->sc.data[type].timer == -1 && + (dstsd->sc.count && !dstsd->sc.data[type] && ( //Allow re-enchanting to lenghten time. [Skotlex] - dstsd->sc.data[SC_FIREWEAPON].timer != -1 || - dstsd->sc.data[SC_WATERWEAPON].timer != -1 || - dstsd->sc.data[SC_WINDWEAPON].timer != -1 || - dstsd->sc.data[SC_EARTHWEAPON].timer != -1 || - dstsd->sc.data[SC_SHADOWWEAPON].timer != -1 || - dstsd->sc.data[SC_GHOSTWEAPON].timer != -1 || - dstsd->sc.data[SC_ENCPOISON].timer != -1 + dstsd->sc.data[SC_FIREWEAPON] || + dstsd->sc.data[SC_WATERWEAPON] || + dstsd->sc.data[SC_WINDWEAPON] || + dstsd->sc.data[SC_EARTHWEAPON] || + dstsd->sc.data[SC_SHADOWWEAPON] || + dstsd->sc.data[SC_GHOSTWEAPON] || + dstsd->sc.data[SC_ENCPOISON] )) ) { if (sd) clif_skill_fail(sd,skillid,0,0); @@ -3334,7 +3332,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case NJ_BUNSINJYUTSU: clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - if (tsc && tsc->data[SC_NEN].timer != -1) + if (tsc && tsc->data[SC_NEN]) status_change_end(bl,SC_NEN,-1); break; /* Was modified to only affect targetted char. [Skotlex] @@ -3360,13 +3358,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case AS_ENCHANTPOISON: // Prevent spamming [Valaris] if (sd && dstsd && dstsd->sc.count) { - if (dstsd->sc.data[SC_FIREWEAPON].timer != -1 || - dstsd->sc.data[SC_WATERWEAPON].timer != -1 || - dstsd->sc.data[SC_WINDWEAPON].timer != -1 || - dstsd->sc.data[SC_EARTHWEAPON].timer != -1 || - dstsd->sc.data[SC_SHADOWWEAPON].timer != -1 || - dstsd->sc.data[SC_GHOSTWEAPON].timer != -1 - // dstsd->sc.data[SC_ENCPOISON].timer != -1 //People say you should be able to recast to lengthen the timer. [Skotlex] + if (dstsd->sc.data[SC_FIREWEAPON] || + dstsd->sc.data[SC_WATERWEAPON] || + dstsd->sc.data[SC_WINDWEAPON] || + dstsd->sc.data[SC_EARTHWEAPON] || + dstsd->sc.data[SC_SHADOWWEAPON] || + dstsd->sc.data[SC_GHOSTWEAPON] + // dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex] ) { clif_skill_nodamage(src,bl,skillid,skilllv,0); clif_skill_fail(sd,skillid,0,0); @@ -3414,7 +3412,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); map_foreachinrange( status_change_timer_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR, - src,status_get_sc(src),type,tick); + src,NULL,type,tick); } break; @@ -3438,11 +3436,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in unit_skillcastcancel(bl, 2); if(tsc && tsc->count){ - if(tsc->data[SC_FREEZE].timer!=-1) + if(tsc->data[SC_FREEZE]) status_change_end(bl,SC_FREEZE,-1); - if(tsc->data[SC_STONE].timer!=-1 && tsc->data[SC_STONE].val2==0) + if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) status_change_end(bl,SC_STONE,-1); - if(tsc->data[SC_SLEEP].timer!=-1) + if(tsc->data[SC_SLEEP]) status_change_end(bl,SC_SLEEP,-1); } @@ -3458,7 +3456,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in int lv = sd->status.base_level - dstsd->status.base_level; if (lv < 0) lv = -lv; if (lv > battle_config.devotion_level_difference || - (dstsd->sc.data[type].timer != -1 && dstsd->sc.data[type].val1 != src->id) || //Avoid overriding [Skotlex] + (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || //Avoid overriding [Skotlex] (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) { clif_skill_fail(sd,skillid,0,0); map_freeblock_unlock(); @@ -3697,7 +3695,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case ST_PRESERVE: case SG_FUSION: case GS_GATLINGFEVER: - if (tsc && tsc->data[type].timer != -1) + if (tsce) i = status_change_end(bl, type, -1); else i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); @@ -3709,7 +3707,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SL_KAUPE: if (sd) { if (!dstsd || !( - (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_SOULLINKER) || + (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SOULLINKER) || (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER || dstsd->status.char_id == sd->status.char_id || dstsd->status.char_id == sd->status.partner_id || @@ -3724,7 +3722,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv))); break; case SM_AUTOBERSERK: // Celest - if (tsc && tsc->data[type].timer != -1) + if (tsce) i = status_change_end(bl, type, -1); else i = sc_start(bl,type,100,skilllv,60000); @@ -3732,14 +3730,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case TF_HIDING: case ST_CHASEWALK: - if (tsc && tsc->data[type].timer != -1) + if (tsce) i = status_change_end(bl, type, -1); else i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); clif_skill_nodamage(src,bl,skillid,-1,i); //Hide skill-scream animation. break; case TK_RUN: - if (tsc && tsc->data[type].timer != -1) + if (tsce) clif_skill_nodamage(src,bl,skillid,skilllv, status_change_end(bl, type, -1)); else { @@ -3752,7 +3750,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in } break; case AS_CLOAKING: - if(tsc && tsc->data[type].timer!=-1 ) + if(tsce) i = status_change_end(bl, type, -1); else i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); @@ -3762,7 +3760,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case BD_ADAPTATION: - if(tsc && tsc->data[SC_DANCING].timer!=-1){ + if(tsc && tsc->data[SC_DANCING]){ clif_skill_nodamage(src,bl,skillid,skilllv,1); skill_stop_dancing(bl); } @@ -3833,7 +3831,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (dstmd) mob_target(dstmd,src,skill_get_range2(src,skillid,skilllv)); - if (tsc->data[SC_STONE].timer != -1) { + if (tsc->data[SC_STONE]) { status_change_end(bl,SC_STONE,-1); if (sd) clif_skill_fail(sd,skillid,0,0); break; @@ -3848,7 +3846,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (skilllv > 5) break; } if (sd) { - if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_WIZARD) + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_WIZARD) break; //Do not delete the gemstone. if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) >= 0 ) pc_delitem(sd, i, skill_db[skillid].amount[0], 0); @@ -4073,7 +4071,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); pc_delitem(sd,i,skill_db[skillid].amount[x],0); potion_flag = potion_target = 0; - if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_ALCHEMIST) + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST) bonus += sd->status.base_level; if(potion_per_hp > 0 || potion_per_sp > 0) { hp = tstatus->max_hp * potion_per_hp / 100; @@ -4109,10 +4107,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if(dstsd) hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; } - if (tsc && tsc->count && tsc->data[SC_CRITICALWOUND].timer!=-1) + if (tsc && tsc->data[SC_CRITICALWOUND]) { - hp -= hp * tsc->data[SC_CRITICALWOUND].val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND].val2 / 100; + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; } clif_skill_nodamage(src,bl,skillid,skilllv,1); if(hp > 0 || (skillid == AM_POTIONPITCHER && sp <= 0)) @@ -4128,7 +4126,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case AM_CP_HELM: { int scid = SC_STRIPWEAPON + (skillid - AM_CP_WEAPON); - if(tsc && tsc->data[scid].timer != -1) + if(tsc && tsc->data[scid]) status_change_end(bl, scid, -1 ); clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); @@ -4173,7 +4171,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in i = tstatus->mdef; if (i >= 100 || (dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || - tsc == NULL || (tsc->data[SC_SPIRIT].timer != -1 && tsc->data[SC_SPIRIT].val2 == SL_ROGUE) || //Rogue's spirit defends againt dispel. + tsc == NULL || (tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_ROGUE) || //Rogue's spirit defends againt dispel. //Fixed & changed to use a proportionnal reduction (no info, but seems far more logical) [DracoRPG] rand()%100 >= (100-i)*(50+10*skilllv)/100) { @@ -4184,7 +4182,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if(status_isimmune(bl) || !tsc->count) break; for(i=0;idata[i].timer == -1) + if (!tsc->data[i]) continue; switch (i) { case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: @@ -4203,7 +4201,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SC_BOSSMAPINFO: continue; } - if(i==SC_BERSERK) tsc->data[i].val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + if(i==SC_BERSERK) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. status_change_end(bl,i,-1); } break; @@ -4255,12 +4253,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SA_SPELLBREAKER: { int sp; - if(tsc && tsc->data[SC_MAGICROD].timer != -1) { + if(tsc && tsc->data[SC_MAGICROD]) { sp = skill_get_sp(skillid,skilllv); - sp = sp * tsc->data[SC_MAGICROD].val2 / 100; + sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; if(sp < 1) sp = 1; status_heal(bl,0,sp,2); - clif_skill_nodamage(bl,bl,SA_MAGICROD,tsc->data[SC_MAGICROD].val1,1); + clif_skill_nodamage(bl,bl,SA_MAGICROD,tsc->data[SC_MAGICROD]->val1,1); status_percent_damage(bl, src, 0, -20); //20% max SP damage. } else { struct unit_data *ud = unit_bl2ud(bl); @@ -4309,7 +4307,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT }; if(skilllv >= 10) { spellid = MG_FROSTDIVER; -// if (tsc && tsc->data[SC_SPIRIT].timer != -1 && tsc->data[SC_SPIRIT].val2 == SA_SAGE) +// if (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SA_SAGE) // maxlv = 10; // else maxlv = skilllv - 9; @@ -4481,7 +4479,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if(md && md->skillidx >= 0 && tsc) { clif_emotion(bl, md->db->skill[md->skillidx].val[0]); - if(md->db->skill[md->skillidx].val[4] && tsc->data[type].timer != -1) + if(md->db->skill[md->skillidx].val[4] && tsce) status_change_end(bl, type, -1); if(md->db->skill[md->skillidx].val[1] || md->db->skill[md->skillidx].val[2]) @@ -4661,7 +4659,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in return 1; } - if (tsc && tsc->data[type].timer != -1) + if (tsce) { //HelloKitty2 (?) explained that this silently fails when target is //already inflicted. [Skotlex] map_freeblock_unlock(); @@ -4680,11 +4678,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in unit_skillcastcancel(bl,0); if(tsc && tsc->count){ - if(tsc->data[SC_FREEZE].timer!=-1) + if(tsc->data[SC_FREEZE]) status_change_end(bl,SC_FREEZE,-1); - if(tsc->data[SC_STONE].timer!=-1 && tsc->data[SC_STONE].val2==0) + if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) status_change_end(bl,SC_STONE,-1); - if(tsc->data[SC_SLEEP].timer!=-1) + if(tsc->data[SC_SLEEP]) status_change_end(bl,SC_SLEEP,-1); } @@ -4728,10 +4726,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (sp) sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10)/100; } - if (tsc && tsc->count && tsc->data[SC_CRITICALWOUND].timer!=-1) + if (tsc && tsc->data[SC_CRITICALWOUND]->timer!=-1) { - hp -= hp * tsc->data[SC_CRITICALWOUND].val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND].val2 / 100; + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; } if(hp > 0) clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); @@ -4750,7 +4748,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; } for (i=0; i<4; i++) { - if(tsc->data[SC_STRIPWEAPON + i].timer != -1) + if(tsc->data[SC_STRIPWEAPON + i]) status_change_end(bl, SC_STRIPWEAPON + i, -1 ); sc_start(bl,SC_CP_WEAPON + i,100,skilllv,skilltime); } @@ -4764,8 +4762,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case CG_LONGINGFREEDOM: { - if (tsc && tsc->data[SC_LONGING].timer == -1 && tsc->data[SC_DANCING].timer != -1 && tsc->data[SC_DANCING].val4 - && (tsc->data[SC_DANCING].val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] + if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 + && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] { clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); @@ -4900,7 +4898,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case SL_SWOO: - if (tsc && tsc->data[type].timer != -1) { + if (tsce) { sc_start(src,SC_STUN,100,skilllv,10000); break; } @@ -5234,7 +5232,7 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) { sc = status_get_sc(target); if (battle_check_target(src,target, BCT_ENEMY)<=0 && - (!sc || sc->data[SC_SILENCE].timer == -1)) + (!sc || !sc->data[SC_SILENCE])) { //If it's not an enemy, and not silenced, you can't use the skill on them. [Skotlex] clif_skill_nodamage (src, target, ud->skillid, ud->skilllv, 0); break; @@ -5265,7 +5263,7 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) break; if(inf&BCT_ENEMY && (sc = status_get_sc(target)) && - sc->count && sc->data[SC_FOGWALL].timer != -1 && + sc->data[SC_FOGWALL] && rand()%100 < 75) { //Fogwall makes all offensive-type targetted skills fail at 75% if (sd) clif_skill_fail(sd,ud->skillid,0,0); @@ -5320,14 +5318,14 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) sc = status_get_sc(src); if(sc && sc->count) { - if(sc->data[SC_MAGICPOWER].timer != -1 && + if(sc->data[SC_MAGICPOWER] && ud->skillid != HW_MAGICPOWER && ud->skillid != WZ_WATERBALL) status_change_end(src,SC_MAGICPOWER,-1); - if(sc->data[SC_SPIRIT].timer != -1 && - sc->data[SC_SPIRIT].val2 == SL_WIZARD && - sc->data[SC_SPIRIT].val3 == ud->skillid && + if(sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_WIZARD && + sc->data[SC_SPIRIT]->val3 == ud->skillid && ud->skillid != WZ_WATERBALL) - sc->data[SC_SPIRIT].val3 = 0; //Clear bounced spell check. + sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. } if (ud->skilltimer == -1) { @@ -5340,7 +5338,7 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) } while(0); //Skill failed. - if (ud->skillid == MO_EXTREMITYFIST && sd && !(sc && sc->count && sc->data[SC_FOGWALL].timer != -1)) + if (ud->skillid == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) { //When Asura fails... (except when it fails from Fog of Wall) //Consume SP/spheres skill_check_condition(sd,ud->skillid, ud->skilllv,1); @@ -5348,9 +5346,9 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) sc = &sd->sc; if (sc->count) { //End states - if (sc->data[SC_EXPLOSIONSPIRITS].timer != -1) + if (sc->data[SC_EXPLOSIONSPIRITS]) status_change_end(src, SC_EXPLOSIONSPIRITS, -1); - if (sc->data[SC_BLADESTOP].timer != -1) + if (sc->data[SC_BLADESTOP]) status_change_end(src,SC_BLADESTOP,-1); } if (target && target->m == src->m) @@ -5504,6 +5502,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk { struct map_session_data* sd; struct status_change* sc; + struct status_change_entry *sce; struct skill_unit_group* sg; int i,type; @@ -5519,6 +5518,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk sc = status_get_sc(src); type = SkillStatusChangeTable(skillid); + sce = (sc && type != -1)?sc->data[type]:NULL; switch (skillid) { //Skill effect. case WZ_METEOR: @@ -5560,7 +5560,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk i = skill_get_splash(skillid, skilllv); map_foreachinarea( status_change_timer_sub, src->m, x-i, y-i, x+i,y+i,BL_CHAR, - src,status_get_sc(src),SC_SIGHT,tick); + src,NULL,SC_SIGHT,tick); if(battle_config.traps_setting&1) map_foreachinarea( skill_reveal_trap, src->m, x-i, y-i, x+i,y+i,BL_SKILL); @@ -5660,7 +5660,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk { int flag=0, area = skill_get_splash(skillid, skilllv); short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0; - if (sc && sc->data[SC_MAGICPOWER].timer != -1) + if (sc && sc->data[SC_MAGICPOWER]) flag = flag|2; //Store the magic power flag for future use. [Skotlex] for(i=0;i<2+(skilllv>>1);i++) { tmpx = x; @@ -5705,7 +5705,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk unit_movepos(src, x, y, 1, 0); clif_slide(src,x,y); } - if (sc && sc->data[SC_HIDING].timer != -1) + if (sc && sc->data[SC_HIDING]) status_change_end(src, SC_HIDING, -1); } break; @@ -5831,13 +5831,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk break; case PA_GOSPEL: - if (sc && sc->data[type].timer != -1 && sc->data[type].val4 == BCT_SELF) + if (sce && sce->val4 == BCT_SELF) status_change_end(src,SC_GOSPEL,-1); else { sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); if (!sg) break; - if (sc && sc->data[type].timer != -1) + if (sce) status_change_end(src,type,-1); //Was under someone else's Gospel. [Skotlex] sc_start4(src,type,100,skilllv,0,(int)sg,BCT_SELF,skill_get_time(skillid,skilllv)); clif_skill_poseffect(src, skillid, skilllv, 0, 0, tick); // PA_GOSPEL music packet @@ -5864,7 +5864,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk return 1; } - if (sc && sc->data[SC_MAGICPOWER].timer != -1) + if (sc && sc->data[SC_MAGICPOWER]) status_change_end(src,SC_MAGICPOWER,-1); if (sd && !(flag&1) && sd->state.arrow_atk) //Consume arrow if a ground skill was not invoked. [Skotlex] @@ -5895,13 +5895,13 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char return 0; } if(sd->sc.count && ( - sd->sc.data[SC_SILENCE].timer!=-1 || - sd->sc.data[SC_ROKISWEIL].timer!=-1 || - sd->sc.data[SC_AUTOCOUNTER].timer != -1 || - sd->sc.data[SC_STEELBODY].timer != -1 || - sd->sc.data[SC_DANCING].timer!=-1 || - sd->sc.data[SC_BERSERK].timer != -1 || - sd->sc.data[SC_MARIONETTE].timer != -1 + sd->sc.data[SC_SILENCE] || + sd->sc.data[SC_ROKISWEIL] || + sd->sc.data[SC_AUTOCOUNTER] || + sd->sc.data[SC_STEELBODY] || + sd->sc.data[SC_DANCING] || + sd->sc.data[SC_BERSERK] || + sd->sc.data[SC_MARIONETTE] )) { skill_failed(sd); return 0; @@ -6135,7 +6135,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli val2=skilllv+1; break; case MG_FIREWALL: - if(sc && sc->data[SC_VIOLENTGALE].timer!=-1) + if(sc && sc->data[SC_VIOLENTGALE]) limit = limit*3/2; val2=4+skilllv; break; @@ -6347,7 +6347,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli group->val3=val3; group->target_flag=target; group->bl_flag= skill_get_unit_bl_target(skillid); - group->state.magic_power = (flag&2 || (sc && sc->data[SC_MAGICPOWER].timer != -1)); //Store the magic power flag. [Skotlex] + group->state.magic_power = (flag&2 || (sc && sc->data[SC_MAGICPOWER])); //Store the magic power flag. [Skotlex] group->state.ammo_consume = (sd && sd->state.arrow_atk && skillid != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo. group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet @@ -6475,6 +6475,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned struct skill_unit_group *sg; struct block_list *ss; struct status_change *sc; + struct status_change_entry *sce; int type,skillid; nullpo_retr(0, src); @@ -6495,11 +6496,12 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned return 0; //Hidden characters are immune to AoE skills except Heaven's Drive. [Skotlex] type = SkillStatusChangeTable(sg->skill_id); + sce = (sc && type != -1)?sc->data[type]:NULL; skillid = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still. switch (sg->unit_id) { case UNT_SAFETYWALL: //TODO: Find a more reliable way to handle the link to sg, this could cause dangling pointers. [Skotlex] - if (sc && sc->data[type].timer == -1) + if (!sce) sc_start4(bl,type,100,sg->skill_lv,sg->group_id,(int)sg,0,sg->limit); break; @@ -6523,19 +6525,19 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned break; case UNT_QUAGMIRE: - if(sc && sc->data[type].timer==-1) + if(!sce) sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); break; case UNT_VOLCANO: case UNT_DELUGE: case UNT_VIOLENTGALE: - if(sc && sc->data[type].timer==-1) + if(!sce) sc_start(bl,type,100,sg->skill_lv,sg->limit); break; case UNT_SUITON: - if(sc && sc->data[type].timer==-1) + if(!sce) sc_start4(bl,type,100,sg->skill_lv, map_flag_vs(bl->m) || battle_check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. 0,0,sg->limit); @@ -6550,9 +6552,9 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned case UNT_SIEGFRIED: case UNT_HERMODE: //Needed to check when a dancer/bard leaves their ensemble area. - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_BARDDANCER)) + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) return skillid; - if (sc && sc->data[type].timer==-1) + if (!sce) sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); break; case UNT_WHISTLE: @@ -6563,21 +6565,21 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned case UNT_DONTFORGETME: case UNT_FORTUNEKISS: case UNT_SERVICEFORYOU: - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_BARDDANCER)) + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) return 0; if (!sc) return 0; - if (sc->data[type].timer==-1) + if (!sce) sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - else if (sc->data[type].val4 == 1) { + else if (sce->val4 == 1) { //Readjust timers since the effect will not last long. - sc->data[type].val4 = 0; - delete_timer(sc->data[type].timer, status_change_timer); - sc->data[type].timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); + sce->val4 = 0; + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); } break; case UNT_FOGWALL: - if (sc && sc->data[type].timer==-1) + if (!sce) { sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) @@ -6586,7 +6588,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned break; case UNT_GRAVITATION: - if (sc && sc->data[type].timer==-1) + if (!sce) sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); break; @@ -6599,7 +6601,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned case UNT_MOONLIT: //Knockback out of area if affected char isn't in Moonlit effect - if (sc && sc->data[SC_DANCING].timer != -1 && (sc->data[SC_DANCING].val1&0xFFFF) == CG_MOONLIT) + if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT) break; if (ss == bl) //Also needed to prevent infinite loop crash. break; @@ -6621,7 +6623,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns struct status_data *tstatus, *sstatus; struct status_change *tsc, *sc; struct skill_unit_group_tickset *ts; - int matk_min = 0, matk_max = 0; //For Magic power... int type, skillid; int diff=0; @@ -6671,13 +6672,11 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1); } //Temporarily set magic power to have it take effect. [Skotlex] - if (sg->state.magic_power && sc && sc->data[SC_MAGICPOWER].timer == -1) + if (sg->state.magic_power && sc && !sc->data[SC_MAGICPOWER]) { //Store previous values. - matk_min = sstatus->matk_min; - matk_max = sstatus->matk_max; + swap(sstatus->matk_min, sc->mp_matk_min); + swap(sstatus->matk_max, sc->mp_matk_max); //Note to NOT return from the function until this is unset! - sstatus->matk_min = sc->data[SC_MAGICPOWER].val3; - sstatus->matk_max = sc->data[SC_MAGICPOWER].val4; } switch (sg->unit_id) @@ -6712,10 +6711,10 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns break; if (tsc) { - if( tsc->data[SC_INCHEALRATE].timer!=-1 ) - heal += heal * tsc->data[SC_INCHEALRATE].val1 / 100; - if( tsc->data[SC_CRITICALWOUND].timer!=-1 ) - heal -= heal * tsc->data[SC_CRITICALWOUND].val2 / 100; + if( tsc->data[SC_INCHEALRATE] ) + heal += heal * tsc->data[SC_INCHEALRATE]->val1 / 100; + if( tsc->data[SC_CRITICALWOUND] ) + heal -= heal * tsc->data[SC_CRITICALWOUND]->val2 / 100; } if (status_isimmune(bl)) heal = 0; /* 鮟驥題浚繧ォ繝シ繝会シ医ヲ繝シ繝ォ驥擾シ撰シ */ @@ -6737,8 +6736,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns int heal = sg->val2; if (tstatus->hp >= tstatus->max_hp) break; - if (tsc && tsc->count && tsc->data[SC_CRITICALWOUND].timer!=-1) - heal -= heal * tsc->data[SC_CRITICALWOUND].val2 / 100; + if (tsc && tsc->data[SC_CRITICALWOUND]) + heal -= heal * tsc->data[SC_CRITICALWOUND]->val2 / 100; if (status_isimmune(bl)) heal = 0; clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); @@ -6779,14 +6778,16 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns } break; case WZ_STORMGUST: - if (tsc && tsc->data[SC_FREEZE].val4 != sg->group_id) + if (tsc) { //Reset hit counter when under new storm gust. - tsc->data[SC_FREEZE].val4 = sg->group_id; - tsc->data[SC_FREEZE].val3 = 0; + if (tsc->sg_id != sg->group_id) { + tsc->sg_id = sg->group_id; + tsc->sg_counter = 0; + } + tsc->sg_counter++; //SG hit counter. } - if (skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) > 0 - && tsc) //Increase freeze counter if attack connects. - tsc->data[SC_FREEZE].val3++; //SG hit counter. + if (skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc) + tsc->sg_counter=0; //Attack absorbed. break; default: skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); @@ -6822,7 +6823,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns int sec = skill_get_time2(sg->skill_id,sg->skill_lv); if (status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8)) { - struct TimerData* td = get_timer(tsc->data[type].timer); + struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; if (td) sec = DIFF_TICK(td->tick, tick); map_moveblock(bl, src->bl.x, src->bl.y, tick); clif_fixpos(bl); @@ -6837,7 +6838,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns break; case UNT_VENOMDUST: - if(tsc && tsc->data[type].timer==-1 ) + if(tsc && !tsc->data[type]) status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),8); break; @@ -6887,8 +6888,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if (sg->src_id == bl->id) break; heal = sg->val2; - if(tsc && tsc->data[SC_CRITICALWOUND].timer!=-1) - heal -= heal * tsc->data[SC_CRITICALWOUND].val2 / 100; + if(tsc && tsc->data[SC_CRITICALWOUND]) + heal -= heal * tsc->data[SC_CRITICALWOUND]->val2 / 100; clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); status_heal(bl, heal, 0, 0); break; @@ -7022,10 +7023,10 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns break; } - if (sg->state.magic_power && sc && sc->data[SC_MAGICPOWER].timer == -1) + if (sg->state.magic_power && sc && !sc->data[SC_MAGICPOWER]) { //Unset magic power. - sstatus->matk_min = matk_min; - sstatus->matk_max = matk_max; + swap(sstatus->matk_min, sc->mp_matk_min); + swap(sstatus->matk_max, sc->mp_matk_max); } if (bl->type == BL_MOB && ss != bl) @@ -7040,6 +7041,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in { struct skill_unit_group *sg; struct status_change *sc; + struct status_change_entry *sce; int type; nullpo_retr(0, src); @@ -7047,6 +7049,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in nullpo_retr(0, sg=src->group); sc = status_get_sc(bl); type = SkillStatusChangeTable(sg->skill_id); + sce = (sc && type != -1)?sc->data[type]:NULL; if (bl->prev==NULL || !src->alive || //Need to delete the trap if the source died. (status_isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB)) @@ -7054,11 +7057,11 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in switch(sg->unit_id){ case UNT_SAFETYWALL: - if (sc && sc->data[type].timer!=-1) + if (sce) status_change_end(bl,type,-1); break; case UNT_HERMODE: //Clear Hermode if the owner moved. - if (sc && sc->data[type].timer!=-1 && sc->data[type].val3 == BCT_SELF && sc->data[type].val4 == sg->group_id) + if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id) status_change_end(bl,type,-1); break; @@ -7067,7 +7070,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in struct block_list *target = map_id2bl(sg->val2); if (target && target==bl) { - if (sc && sc->data[type].timer!=-1 && sc->data[type].val2 == sg->group_id) + if (sce && sce->val2 == sg->group_id) status_change_end(bl,type,-1); sg->limit = DIFF_TICK(tick,sg->tick)+1000; } @@ -7083,6 +7086,7 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int tick) { struct status_change *sc; + struct status_change_entry *sce; int type; sc = status_get_sc(bl); @@ -7090,13 +7094,14 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int sc = NULL; type = SkillStatusChangeTable(skill_id); + sce = (sc && type != -1)?sc->data[type]:NULL; switch (skill_id) { case WZ_QUAGMIRE: if (bl->type==BL_MOB) break; - if (sc && sc->data[type].timer != -1) + if (sce) status_change_end(bl, type, -1); break; @@ -7108,7 +7113,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int case BD_ROKISWEIL: case BD_INTOABYSS: case BD_SIEGFRIED: - if(sc && sc->data[SC_DANCING].timer != -1 && (sc->data[SC_DANCING].val1&0xFFFF) == skill_id) + if(sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == skill_id) { //Check if you just stepped out of your ensemble skill to cancel dancing. [Skotlex] //We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance. //FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner, @@ -7125,7 +7130,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int case CG_HERMODE: case HW_GRAVITATION: case NJ_SUITON: - if (sc && sc->data[type].timer != -1) + if (sce) status_change_end(bl, type, -1); break; @@ -7137,26 +7142,26 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int case DC_DONTFORGETME: case DC_FORTUNEKISS: case DC_SERVICEFORYOU: - if (sc && sc->data[type].timer != -1) + if (sce) { - delete_timer(sc->data[type].timer, status_change_timer); + delete_timer(sce->timer, status_change_timer); //NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas... //not possible on our current implementation. - sc->data[type].val4 = 1; //Store the fact that this is a "reduced" duration effect. - sc->data[type].timer = add_timer(tick+skill_get_time2(skill_id,1), status_change_timer, bl->id, type); + sce->val4 = 1; //Store the fact that this is a "reduced" duration effect. + sce->timer = add_timer(tick+skill_get_time2(skill_id,1), status_change_timer, bl->id, type); } break; case PF_FOGWALL: - if (sc && sc->data[type].timer != -1) + if (sce) { status_change_end(bl,type,-1); - if (sc->data[SC_BLIND].timer!=-1) + if ((sce=sc->data[SC_BLIND])) { if (bl->type == BL_PC) //Players get blind ended inmediately, others have it still for 30 secs. [Skotlex] status_change_end(bl, SC_BLIND, -1); else { - delete_timer(sc->data[SC_BLIND].timer, status_change_timer); - sc->data[SC_BLIND].timer = add_timer(30000+tick, status_change_timer, bl->id, SC_BLIND); + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(30000+tick, status_change_timer, bl->id, SC_BLIND); } } } @@ -7298,7 +7303,7 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) if(pc_isdead(tsd)) return 0; - if (tsd->sc.count && (tsd->sc.data[SC_SILENCE].timer != -1 || tsd->sc.opt1)) + if (tsd->sc.data[SC_SILENCE] || tsd->sc.opt1) return 0; switch(skillid) @@ -7323,7 +7328,7 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) (tsd->weapontype1==W_MUSICAL || tsd->weapontype1==W_WHIP) && sd->status.party_id && tsd->status.party_id && sd->status.party_id == tsd->status.party_id && - tsd->sc.data[SC_DANCING].timer == -1) + tsd->sc.data[SC_DANCING]) { p_sd[(*c)++]=tsd->bl.id; return skilllv; @@ -7333,7 +7338,7 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) } break; } - //return 0; + return 0; } /*========================================== @@ -7362,10 +7367,10 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short* } return c; default: //Warning: Assuming Ensemble skills here (for speed) - if (c > 0 && (tsd = map_id2sd(p_sd[0])) != NULL) + if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map_id2sd(p_sd[0])) != NULL) { - sd->sc.data[SC_DANCING].val4= tsd->bl.id; - sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING].val2,*skill_lv,sd->bl.id,skill_get_time(skill_id,*skill_lv)+1000); + sd->sc.data[SC_DANCING]->val4 = tsd->bl.id; + sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill_get_time(skill_id,*skill_lv)+1000); clif_skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1); tsd->skillid_dance = skill_id; tsd->skilllv_dance = *skill_lv; @@ -7503,7 +7508,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in //Consume sd->itemid = sd->itemindex = -1; if(skill == WZ_EARTHSPIKE && sc && - sc->data[SC_TKREST].timer != -1 && rand()%100 > sc->data[SC_TKREST].val2) // [marquis007] + sc->data[SC_TKREST] && rand()%100 > sc->data[SC_TKREST]->val2) // [marquis007] ; //Do not consume item. else pc_delitem(sd,i,1,0); @@ -7569,7 +7574,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in zeny -= zeny*10/100; break; case AL_HOLYLIGHT: - if(sc && sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_PRIEST) + if(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_PRIEST) sp *= 5; break; case SL_SMA: @@ -7593,7 +7598,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in case MO_COMBOFINISH: case CH_TIGERFIST: case CH_CHAINCRUSH: - if(sc && sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_MONK) + if(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) sp -= sp*25/100; //FIXME: Need real data. this is a custom value. break; } @@ -7619,7 +7624,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: - if(sc && sc->data[SkillStatusChangeTable(skill)].timer!=-1) + if(sc && sc->data[SkillStatusChangeTable(skill)]) return 1; //Allow turning off. break; @@ -7646,38 +7651,38 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in else sd->spiritball_old = spiritball; break; case MO_BODYRELOCATION: - if (sc && sc->data[SC_EXPLOSIONSPIRITS].timer!=-1) + if (sc && sc->data[SC_EXPLOSIONSPIRITS]) spiritball = 0; break; case MO_CHAINCOMBO: if(!sc) return 0; - if(sc->data[SC_BLADESTOP].timer!=-1) + if(sc->data[SC_BLADESTOP]) break; - if(sc->data[SC_COMBO].timer != -1 && sc->data[SC_COMBO].val1 == MO_TRIPLEATTACK) + if(sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_TRIPLEATTACK) break; return 0; - case MO_COMBOFINISH: //迪幃セ肴教 - if(!sc || sc->data[SC_COMBO].timer == -1 || sc->data[SC_COMBO].val1 != MO_CHAINCOMBO) + case MO_COMBOFINISH: + if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_CHAINCOMBO)) return 0; break; - case CH_TIGERFIST: //莨剰剋諡ウ - if(!sc || sc->data[SC_COMBO].timer == -1 || sc->data[SC_COMBO].val1 != MO_COMBOFINISH) + case CH_TIGERFIST: + if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_COMBOFINISH)) return 0; break; - case CH_CHAINCRUSH: //騾」譟ア蟠ゥ謦 - if(!sc || sc->data[SC_COMBO].timer == -1) + case CH_CHAINCRUSH: + if(!(sc && sc->data[SC_COMBO])) return 0; - if(sc->data[SC_COMBO].val1 != MO_COMBOFINISH && sc->data[SC_COMBO].val1 != CH_TIGERFIST) + if(sc->data[SC_COMBO]->val1 != MO_COMBOFINISH && sc->data[SC_COMBO]->val1 != CH_TIGERFIST) return 0; break; case MO_EXTREMITYFIST: -// if(sc && sc->data[SC_EXTREMITYFIST].timer != -1) //To disable Asura during the 5 min skill block uncomment this... +// if(sc && sc->data[SC_EXTREMITYFIST]) //To disable Asura during the 5 min skill block uncomment this... // return 0; - if(sc && sc->data[SC_BLADESTOP].timer!=-1) + if(sc && sc->data[SC_BLADESTOP]) spiritball--; - else if (sc && sc->data[SC_COMBO].timer != -1) { - switch(sc->data[SC_COMBO].val1) { + else if (sc && sc->data[SC_COMBO]) { + switch(sc->data[SC_COMBO]->val1) { case MO_COMBOFINISH: spiritball = 4; break; @@ -7708,7 +7713,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in case TK_READYDOWN: case TK_READYSTORM: case TK_READYTURN: - if(sc && sc->data[SkillStatusChangeTable(skill)].timer!=-1) + if(sc && sc->data[SkillStatusChangeTable(skill)]) return 1; //Enable disabling them regardless of who you are. case TK_JUMPKICK: if ((sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) { @@ -7724,7 +7729,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in case TK_COUNTER: if ((sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) return 0; //Anti-Soul Linker check in case you job-changed with Stances active. - if(!sc || sc->data[SC_COMBO].timer == -1) + if(!(sc && sc->data[SC_COMBO])) return 0; //Combo needs to be ready if (pc_famerank(sd->status.char_id,MAPID_TAEKWON)) { //Unlimited Combo @@ -7735,23 +7740,23 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in } break; } else - if(sc->data[SC_COMBO].val1 == skill) + if(sc->data[SC_COMBO]->val1 == skill) break; //Combo ready. //Cancel combo wait. unit_cancel_combo(&sd->bl); return 0; - case BD_ADAPTATION: /* 繧「繝峨Μ繝 */ + case BD_ADAPTATION: { int time; - if(!sc || sc->data[SC_DANCING].timer==-1) + if(!(sc && sc->data[SC_DANCING])) { clif_skill_fail(sd,skill,0,0); return 0; } - time = 1000*(sc->data[SC_DANCING].val3>>16); + time = 1000*(sc->data[SC_DANCING]->val3>>16); if (skill_get_time( - (sc->data[SC_DANCING].val1&0xFFFF), //Dance Skill ID - (sc->data[SC_DANCING].val1>>16)) //Dance Skill LV + (sc->data[SC_DANCING]->val1&0xFFFF), //Dance Skill ID + (sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV - time <= skill_get_time2(skill,lv)) { clif_skill_fail(sd,skill,0,0); @@ -7800,12 +7805,12 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in break; case SL_SMA: if(type) break; //Only do the combo check when the target is selected (type == 0) - if(!sc || sc->data[SC_SMA].timer == -1) + if(!(sc && sc->data[SC_SMA])) return 0; break; case HT_POWER: - if(!sc || sc->data[SC_COMBO].timer == -1 || sc->data[SC_COMBO].val1 != skill) + if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill)) return 0; break; case SA_DELUGE: @@ -7870,30 +7875,30 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in case SG_SUN_WARM: case SG_MOON_WARM: case SG_STAR_WARM: - if ((sd->bl.m == sd->feel_map[skill-SG_SUN_WARM].m) || (sc && sc->data[SC_MIRACLE].timer!=-1)) + if ((sd->bl.m == sd->feel_map[skill-SG_SUN_WARM].m) || (sc && sc->data[SC_MIRACLE])) break; clif_skill_fail(sd,skill,0,0); return 0; break; case SG_SUN_COMFORT: - if ((sd->bl.m == sd->feel_map[0].m && (battle_config.allow_skill_without_day || is_day_of_sun())) || (sc && sc->data[SC_MIRACLE].timer!=-1)) + if ((sd->bl.m == sd->feel_map[0].m && (battle_config.allow_skill_without_day || is_day_of_sun())) || (sc && sc->data[SC_MIRACLE])) break; clif_skill_fail(sd,skill,0,0); return 0; case SG_MOON_COMFORT: - if ((sd->bl.m == sd->feel_map[1].m && (battle_config.allow_skill_without_day || is_day_of_moon())) || (sc && sc->data[SC_MIRACLE].timer!=-1)) + if ((sd->bl.m == sd->feel_map[1].m && (battle_config.allow_skill_without_day || is_day_of_moon())) || (sc && sc->data[SC_MIRACLE])) break; clif_skill_fail(sd,skill,0,0); return 0; case SG_STAR_COMFORT: - if ((sd->bl.m == sd->feel_map[2].m && (battle_config.allow_skill_without_day || is_day_of_star())) || (sc && sc->data[SC_MIRACLE].timer!=-1)) + if ((sd->bl.m == sd->feel_map[2].m && (battle_config.allow_skill_without_day || is_day_of_star())) || (sc && sc->data[SC_MIRACLE])) break; clif_skill_fail(sd,skill,0,0); return 0; case SG_FUSION: - if (sc && sc->data[SC_FUSION].timer!=-1) + if (sc && sc->data[SC_FUSION]) return 1; - if (sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_STAR) + if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_STAR) break; //Auron insists we should implement SP consumption when you are not Soul Linked. [Skotlex] if(sp>0 && type&1) @@ -7930,7 +7935,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in return 0; } case NJ_BUNSINJYUTSU: - if (!sc || sc->data[SC_NEN].timer==-1) { + if (!(sc && sc->data[SC_NEN])) { clif_skill_fail(sd,skill,0,0); return 0; } @@ -8035,6 +8040,11 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in return 0; } break; + case ST_CARTBOOST: + if(!(sc && sc->data[SC_CARTBOOST])) { + clif_skill_fail(sd,skill,0,0); + return 0; + } case ST_CART: if(!pc_iscarton(sd)) { clif_skill_fail(sd,skill,0,0); @@ -8048,19 +8058,13 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in } break; case ST_SIGHT: - if(!sc || sc->data[SC_SIGHT].timer == -1) { + if(!(sc && sc->data[SC_SIGHT])) { clif_skill_fail(sd,skill,0,0); return 0; } break; case ST_EXPLOSIONSPIRITS: - if(!sc || sc->data[SC_EXPLOSIONSPIRITS].timer == -1) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case ST_CARTBOOST: - if(!pc_iscarton(sd) || !sc || sc->data[SC_CARTBOOST].timer == -1) { + if(!(sc && sc->data[SC_EXPLOSIONSPIRITS])) { clif_skill_fail(sd,skill,0,0); return 0; } @@ -8072,7 +8076,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in } break; case ST_MOVE_ENABLE: - if (sc && sc->data[SC_COMBO].timer != -1 && sc->data[SC_COMBO].val1 == skill) + if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill) sd->ud.canmove_tick = gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex] if (!unit_can_move(&sd->bl)) { @@ -8081,7 +8085,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in } break; case ST_WATER: - if (sc && (sc->data[SC_DELUGE].timer != -1 || sc->data[SC_SUITON].timer != -1)) + if (sc && (sc->data[SC_DELUGE] || sc->data[SC_SUITON])) break; if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER)) break; @@ -8109,7 +8113,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in if (--amount[i] < 1) continue; } - if(sc && sc->data[SC_INTOABYSS].timer != -1) + if(sc && sc->data[SC_INTOABYSS]) continue; } @@ -8129,7 +8133,7 @@ int skill_check_condition(struct map_session_data* sd, short skill, short lv, in return 0; } if( itemid_isgemstone(itemid[i]) && skill != HW_GANBANTEIN && - sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_WIZARD) + sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD) index[i] = -1; //Gemstones are checked, but not substracted from inventory. } @@ -8204,21 +8208,21 @@ int skill_castfix_sc (struct block_list *bl, int time) struct status_change *sc = status_get_sc(bl); if (sc && sc->count) { - if (sc->data[SC_SLOWCAST].timer != -1) - time += time * sc->data[SC_SLOWCAST].val2 / 100; - if (sc->data[SC_FASTCAST].timer != -1) - time -= time * sc->data[SC_FASTCAST].val1 / 100; - if (sc->data[SC_SUFFRAGIUM].timer != -1) { - time -= time * sc->data[SC_SUFFRAGIUM].val2 / 100; + if (sc->data[SC_SLOWCAST]) + time += time * sc->data[SC_SLOWCAST]->val2 / 100; + if (sc->data[SC_FASTCAST]) + time -= time * sc->data[SC_FASTCAST]->val1 / 100; + if (sc->data[SC_SUFFRAGIUM]) { + time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100; status_change_end(bl, SC_SUFFRAGIUM, -1); } - if (sc->data[SC_MEMORIZE].timer != -1) { + if (sc->data[SC_MEMORIZE]) { time>>=1; - if ((--sc->data[SC_MEMORIZE].val2) <= 0) + if ((--sc->data[SC_MEMORIZE]->val2) <= 0) status_change_end(bl, SC_MEMORIZE, -1); } - if (sc->data[SC_POEMBRAGI].timer != -1) - time -= time * sc->data[SC_POEMBRAGI].val2 / 100; + if (sc->data[SC_POEMBRAGI]) + time -= time * sc->data[SC_POEMBRAGI]->val2 / 100; } return (time > 0) ? time : 0; } @@ -8273,16 +8277,16 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv) struct status_change *sc; sc= status_get_sc(bl); if (sc && sc->count) { - if (sc->data[SC_POEMBRAGI].timer != -1) - time -= time * sc->data[SC_POEMBRAGI].val3 / 100; - if (sc->data[SC_SPIRIT].timer != -1) + if (sc->data[SC_POEMBRAGI]) + time -= time * sc->data[SC_POEMBRAGI]->val3 / 100; + if (sc->data[SC_SPIRIT]) switch (skill_id) { case CR_SHIELDBOOMERANG: - if (sc->data[SC_SPIRIT].val2 == SL_CRUSADER) + if (sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) time /=2; break; case AS_SONICBLOW: - if (!map_flag_gvg(bl->m) && sc->data[SC_SPIRIT].val2 == SL_ASSASIN) + if (!map_flag_gvg(bl->m) && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) time /= 2; break; } @@ -8584,7 +8588,7 @@ int skill_autospell (struct map_session_data *sd, int skillid) if(skillid==MG_NAPALMBEAT) maxlv=3; else if(skillid==MG_COLDBOLT || skillid==MG_FIREBOLT || skillid==MG_LIGHTNINGBOLT){ - if (sd->sc.data[SC_SPIRIT].timer != -1 && sd->sc.data[SC_SPIRIT].val2 == SL_SAGE) + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SAGE) maxlv =10; //Soul Linker bonus. [Skotlex] else if(skilllv==2) maxlv=1; else if(skilllv==3) maxlv=2; @@ -9098,34 +9102,21 @@ int skill_trap_splash (struct block_list *bl, va_list ap) int skill_enchant_elemental_end (struct block_list *bl, int type) { struct status_change *sc; - + const enum sc_type scs[] = { SC_ENCPOISON, SC_ASPERSIO, SC_FIREWEAPON, SC_WATERWEAPON, SC_WINDWEAPON, SC_EARTHWEAPON, SC_SHADOWWEAPON, SC_GHOSTWEAPON, SC_ENCHANTARMS }; + int i; nullpo_retr(0, bl); nullpo_retr(0, sc= status_get_sc(bl)); if (!sc->count) return 0; - - if (type != SC_ENCPOISON && sc->data[SC_ENCPOISON].timer != -1) - status_change_end(bl, SC_ENCPOISON, -1); - if (type != SC_ASPERSIO && sc->data[SC_ASPERSIO].timer != -1) - status_change_end(bl, SC_ASPERSIO, -1); - if (type != SC_FIREWEAPON && sc->data[SC_FIREWEAPON].timer != -1) - status_change_end(bl, SC_FIREWEAPON, -1); - if (type != SC_WATERWEAPON && sc->data[SC_WATERWEAPON].timer != -1) - status_change_end(bl, SC_WATERWEAPON, -1); - if (type != SC_WINDWEAPON && sc->data[SC_WINDWEAPON].timer != -1) - status_change_end(bl, SC_WINDWEAPON, -1); - if (type != SC_EARTHWEAPON && sc->data[SC_EARTHWEAPON].timer != -1) - status_change_end(bl, SC_EARTHWEAPON, -1); - if (type != SC_SHADOWWEAPON && sc->data[SC_SHADOWWEAPON].timer != -1) - status_change_end(bl, SC_SHADOWWEAPON, -1); - if (type != SC_GHOSTWEAPON && sc->data[SC_GHOSTWEAPON].timer != -1) - status_change_end(bl, SC_GHOSTWEAPON, -1); - if (type != SC_ENCHANTARMS && sc->data[SC_ENCHANTARMS].timer != -1) - status_change_end(bl, SC_ENCHANTARMS, -1); + + for (i = 0; i < ARRAYLENGTH(scs); i++) + if (type != scs[i] && sc->data[scs[i]]) + status_change_end(bl, scs[i], -1); + return 0; } -int skill_check_cloaking(struct block_list *bl, struct status_change *sc) +int skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce) { static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; //optimized by Lupus static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; @@ -9142,21 +9133,21 @@ int skill_check_cloaking(struct block_list *bl, struct status_change *sc) } } else end = 0; //No wall check. - + + if(!sce) return end; //Just report. + if(end){ - if (sc->data[SC_CLOAKING].timer != -1) { - if (sc->data[SC_CLOAKING].val1 < 3) //End cloaking. - status_change_end(bl, SC_CLOAKING, -1); - else if(sc->data[SC_CLOAKING].val4&1) - { //Remove wall bonus - sc->data[SC_CLOAKING].val4&=~1; - status_calc_bl(bl,SCB_SPEED); - } - } + if (sce->val1 < 3) //End cloaking. + status_change_end(bl, SC_CLOAKING, -1); + else if(sce->val4&1) + { //Remove wall bonus + sce->val4&=~1; + status_calc_bl(bl,SCB_SPEED); + } } - else if(sc->data[SC_CLOAKING].timer != -1 && !(sc->data[SC_CLOAKING].val4&1)) + else if(!(sce->val4&1)) { //Add wall speed bonus - sc->data[SC_CLOAKING].val4|=1; + sce->val4|=1; status_calc_bl(bl,SCB_SPEED); } @@ -9170,30 +9161,31 @@ int skill_check_cloaking(struct block_list *bl, struct status_change *sc) void skill_stop_dancing (struct block_list *src) { struct status_change* sc; + struct status_change_entry *sce; struct skill_unit_group* group; struct map_session_data* dsd = NULL; nullpo_retv(src); nullpo_retv(sc = status_get_sc(src)); - if(!sc->count || sc->data[SC_DANCING].timer == -1) + if(!sc->count || !(sce=sc->data[SC_DANCING])) return; - group = (struct skill_unit_group *)sc->data[SC_DANCING].val2; - sc->data[SC_DANCING].val2 = 0; + group = (struct skill_unit_group *)sce->val2; + sce->val2 = 0; - if (sc->data[SC_DANCING].val4) + if (sce->val4) { - if (sc->data[SC_DANCING].val4 != BCT_SELF) - dsd = map_id2sd(sc->data[SC_DANCING].val4); - sc->data[SC_DANCING].val4 = 0; + if (sce->val4 != BCT_SELF) + dsd = map_id2sd(sce->val4); + sce->val4 = 0; } status_change_end(src, SC_DANCING, -1); - if (dsd) + if (dsd && (sce=dsd->sc.data[SC_DANCING])) { - dsd->sc.data[SC_DANCING].val4 = dsd->sc.data[SC_DANCING].val2 = 0; + sce->val4 = sce->val2 = 0; status_change_end(&dsd->bl, SC_DANCING, -1); } @@ -9385,9 +9377,9 @@ int skill_delunitgroup (struct block_list *src, struct skill_unit_group *group) if (skill_get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) { struct status_change* sc = status_get_sc(src); - if (sc && sc->data[SC_DANCING].timer != -1) + if (sc && sc->data[SC_DANCING]) { - sc->data[SC_DANCING].val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex] + sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex] status_change_end(src,SC_DANCING,-1); } } @@ -9396,8 +9388,8 @@ int skill_delunitgroup (struct block_list *src, struct skill_unit_group *group) // (needs to be done when the group is deleted by other means than skill deactivation) if (group->unit_id == UNT_GOSPEL) { struct status_change *sc = status_get_sc(src); - if(sc && sc->data[SC_GOSPEL].timer != -1) { - sc->data[SC_GOSPEL].val3 = 0; //Remove reference to this group. [Skotlex] + if(sc && sc->data[SC_GOSPEL]) { + sc->data[SC_GOSPEL]->val3 = 0; //Remove reference to this group. [Skotlex] status_change_end(src,SC_GOSPEL,-1); } } @@ -9406,8 +9398,8 @@ int skill_delunitgroup (struct block_list *src, struct skill_unit_group *group) group->skill_id == SG_MOON_WARM || group->skill_id == SG_STAR_WARM) { struct status_change *sc = status_get_sc(src); - if(sc && sc->data[SC_WARM].timer != -1) { - sc->data[SC_WARM].val4 = 0; + if(sc && sc->data[SC_WARM]) { + sc->data[SC_WARM]->val4 = 0; status_change_end(src,SC_WARM,-1); } } diff --git a/src/map/skill.h b/src/map/skill.h index 5ddd5b27c..9bff96961 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -246,7 +246,7 @@ int skill_autospell(struct map_session_data *md,int skillid); int skill_calc_heal(struct block_list *src, struct block_list *target, int skill_lv); -int skill_check_cloaking(struct block_list *bl, struct status_change *sc); +int skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce); // ステ?タス異常 int skill_enchant_elemental_end(struct block_list *bl, int type); diff --git a/src/map/status.c b/src/map/status.c index b7221ea6e..a76c03a6c 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -7,6 +7,7 @@ #include "../common/showmsg.h" #include "../common/malloc.h" #include "../common/utils.h" +#include "../common/ers.h" #include "pc.h" #include "map.h" @@ -63,6 +64,8 @@ int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex] //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only //to avoid cards exploits +static struct eri *sc_data_ers; //For sc_data entries + static void add_sc(int skill, int sc) { int sk = skill; @@ -637,10 +640,11 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s if (hp && !(flag&1)) { if (sc) { - if (sc->data[SC_DEVOTION].val1 && src && battle_getcurrentskill(src) != PA_PRESSURE) + struct status_change_entry *sce; + if ((sce=sc->data[SC_DEVOTION]) && src && battle_getcurrentskill(src) != PA_PRESSURE) { //Devotion prevents any of the other ailments from ending. - struct map_session_data *sd2 = map_id2sd(sc->data[SC_DEVOTION].val1); - if (sd2 && sd2->devotion[sc->data[SC_DEVOTION].val2] == target->id) + struct map_session_data *sd2 = map_id2sd(sce->val1); + if (sd2 && sd2->devotion[sce->val2] == target->id) { clif_damage(&sd2->bl, &sd2->bl, gettick(), 0, 0, hp, 0, 0, 0); status_fix_damage(NULL, &sd2->bl, hp, 0); @@ -648,41 +652,41 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s } status_change_end(target, SC_DEVOTION, -1); } - if (sc->data[SC_FREEZE].timer != -1) + if (sc->data[SC_FREEZE]) status_change_end(target,SC_FREEZE,-1); - if (sc->data[SC_STONE].timer!=-1 && sc->opt1 == OPT1_STONE) + if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) status_change_end(target,SC_STONE,-1); - if (sc->data[SC_SLEEP].timer != -1) + if (sc->data[SC_SLEEP]) status_change_end(target,SC_SLEEP,-1); - if (sc->data[SC_WINKCHARM].timer != -1) + if (sc->data[SC_WINKCHARM]) status_change_end(target,SC_WINKCHARM,-1); - if (sc->data[SC_CONFUSION].timer != -1) + if (sc->data[SC_CONFUSION]) status_change_end(target, SC_CONFUSION, -1); - if (sc->data[SC_TRICKDEAD].timer != -1) + if (sc->data[SC_TRICKDEAD]) status_change_end(target, SC_TRICKDEAD, -1); - if (sc->data[SC_HIDING].timer != -1) + if (sc->data[SC_HIDING]) status_change_end(target, SC_HIDING, -1); - if (sc->data[SC_CLOAKING].timer != -1) + if (sc->data[SC_CLOAKING]) status_change_end(target, SC_CLOAKING, -1); - if (sc->data[SC_CHASEWALK].timer != -1) + if (sc->data[SC_CHASEWALK]) status_change_end(target, SC_CHASEWALK, -1); - if (sc->data[SC_ENDURE].timer != -1 && !sc->data[SC_ENDURE].val4) { + if ((sce=sc->data[SC_ENDURE]) && !sce->val4) { //Endure count is only reduced by non-players on non-gvg maps. //val4 signals infinite endure. [Skotlex] if (src && src->type != BL_PC && !map_flag_gvg(target->m) - && --(sc->data[SC_ENDURE].val2) < 0) + && --(sce->val2) < 0) status_change_end(target, SC_ENDURE, -1); } - if (sc->data[SC_GRAVITATION].timer != -1 && - sc->data[SC_GRAVITATION].val3 == BCT_SELF) { - struct skill_unit_group *sg = (struct skill_unit_group *)sc->data[SC_GRAVITATION].val4; + if ((sce=sc->data[SC_GRAVITATION]) && + sce->val3 == BCT_SELF) { + struct skill_unit_group *sg = (struct skill_unit_group *)sce->val4; if (sg) { skill_delunitgroup(target,sg); - sc->data[SC_GRAVITATION].val4 = 0; + sce->val4 = 0; status_change_end(target, SC_GRAVITATION, -1); } } - if(sc->data[SC_DANCING].timer != -1 && (unsigned int)hp > status->max_hp>>2) + if(sc->data[SC_DANCING] && (unsigned int)hp > status->max_hp>>2) skill_stop_dancing(target); } unit_skillcastcancel(target, 2); @@ -702,12 +706,11 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status->sp-= sp; if (sc && hp && status->hp) { - if (sc->data[SC_AUTOBERSERK].timer != -1 && - (sc->data[SC_PROVOKE].timer==-1 || !sc->data[SC_PROVOKE].val2) && + if (sc->data[SC_AUTOBERSERK] && + (!sc->data[SC_PROVOKE] || !sc->data[SC_PROVOKE]->val2) && status->hp < status->max_hp>>2) sc_start4(target,SC_PROVOKE,100,10,1,0,0,0); - if (sc->data[SC_BERSERK].timer != -1 && - status->hp <= 100) + if (sc->data[SC_BERSERK] && status->hp <= 100) status_change_end(target, SC_BERSERK, -1); } @@ -801,7 +804,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) } if(hp) { - if (!(flag&1) && sc && sc->data[SC_BERSERK].timer!=-1) + if (!(flag&1) && sc && sc->data[SC_BERSERK]) hp = 0; if((unsigned int)hp > status->max_hp - status->hp) @@ -824,9 +827,9 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) status->sp+= sp; if(hp && sc && - sc->data[SC_AUTOBERSERK].timer != -1 && - sc->data[SC_PROVOKE].timer!=-1 && - sc->data[SC_PROVOKE].val2==1 && + sc->data[SC_AUTOBERSERK] && + sc->data[SC_PROVOKE] && + sc->data[SC_PROVOKE]->val2==1 && status->hp>=status->max_hp>>2 ) //End auto berserk. status_change_end(bl,SC_PROVOKE,-1); @@ -1007,22 +1010,21 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int } if ( - (sc->data[SC_TRICKDEAD].timer != -1 && skill_num != NV_TRICKDEAD) - || (sc->data[SC_AUTOCOUNTER].timer != -1 && !flag) - || (sc->data[SC_GOSPEL].timer != -1 && sc->data[SC_GOSPEL].val4 == BCT_SELF && skill_num != PA_GOSPEL) - || (sc->data[SC_GRAVITATION].timer != -1 && sc->data[SC_GRAVITATION].val3 == BCT_SELF && flag != 2) -// || (sc->data[SC_CLOAKING].timer != -1 && sc->data[SC_CLOAKING].val1 < 3 && skill_num != AS_CLOAKING) //Official sites say it blocks attack/skill usage, ingame proof says it does not. + (sc->data[SC_TRICKDEAD] && skill_num != NV_TRICKDEAD) + || (sc->data[SC_AUTOCOUNTER] && !flag) + || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_num != PA_GOSPEL) + || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2) ) return 0; - if (sc->data[SC_WINKCHARM].timer != -1 && target && !flag) + if (sc->data[SC_WINKCHARM] && target && !flag) { //Prevents skill usage clif_emotion(src, 3); return 0; } - if (sc->data[SC_BLADESTOP].timer != -1) { - switch (sc->data[SC_BLADESTOP].val1) + if (sc->data[SC_BLADESTOP]) { + switch (sc->data[SC_BLADESTOP]->val1) { case 5: if (skill_num == MO_EXTREMITYFIST) break; case 4: if (skill_num == MO_CHAINCOMBO) break; @@ -1032,19 +1034,25 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int } } - if (sc->data[SC_DANCING].timer != -1 && flag!=2) + if (sc->data[SC_DANCING] && flag!=2) { - if(sc->data[SC_LONGING].timer != -1) + if(sc->data[SC_LONGING]) { //Allow everything except dancing/re-dancing. [Skotlex] if (skill_num == BD_ENCORE || skill_get_inf2(skill_num)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL) ) return 0; } else - if (skill_num != BD_ADAPTATION && skill_num != CG_LONGINGFREEDOM - && skill_num != BA_MUSICALSTRIKE && skill_num != DC_THROWARROW) + switch (skill_num) { + case BD_ADAPTATION: + case CG_LONGINGFREEDOM: + case BA_MUSICALSTRIKE: + case DC_THROWARROW: + break; + default: return 0; - if ((sc->data[SC_DANCING].val1&0xFFFF) == CG_HERMODE && skill_num == BD_ADAPTATION) + } + if ((sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE && skill_num == BD_ADAPTATION) return 0; //Can't amp out of Wand of Hermode :/ [Skotlex] } @@ -1052,20 +1060,20 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_num) ) { //Skills blocked through status changes... if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through - sc->data[SC_SILENCE].timer != -1 || - (sc->data[SC_MARIONETTE].timer != -1 && skill_num != CG_MARIONETTE) || - (sc->data[SC_MARIONETTE2].timer != -1 && skill_num == CG_MARIONETTE) || - sc->data[SC_STEELBODY].timer != -1 || - sc->data[SC_BERSERK].timer != -1 + sc->data[SC_SILENCE] || + (sc->data[SC_MARIONETTE] && skill_num != CG_MARIONETTE) || + (sc->data[SC_MARIONETTE2] && skill_num == CG_MARIONETTE) || + sc->data[SC_STEELBODY] || + sc->data[SC_BERSERK] )) return 0; //Skill blocking. if ( - (sc->data[SC_VOLCANO].timer != -1 && skill_num == WZ_ICEWALL) || - (sc->data[SC_ROKISWEIL].timer != -1 && skill_num != BD_ADAPTATION) || - (sc->data[SC_HERMODE].timer != -1 && skill_get_inf(skill_num) & INF_SUPPORT_SKILL) || - (sc->data[SC_NOCHAT].timer != -1 && sc->data[SC_NOCHAT].val1&MANNER_NOSKILL) + (sc->data[SC_VOLCANO] && skill_num == WZ_ICEWALL) || + (sc->data[SC_ROKISWEIL] && skill_num != BD_ADAPTATION) || + (sc->data[SC_HERMODE] && skill_get_inf(skill_num) & INF_SUPPORT_SKILL) || + (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOSKILL) ) return 0; @@ -1098,12 +1106,12 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int if(tsc && tsc->count) { - if(!skill_num && !(status->mode&MD_BOSS) && tsc->data[SC_TRICKDEAD].timer != -1) + if(!skill_num && !(status->mode&MD_BOSS) && tsc->data[SC_TRICKDEAD]) return 0; if((skill_num == WZ_STORMGUST || skill_num == NJ_HYOUSYOURAKU) - && tsc->data[SC_FREEZE].timer != -1) + && tsc->data[SC_FREEZE]) return 0; - if(skill_num == PR_LEXAETERNA && (tsc->data[SC_FREEZE].timer != -1 || (tsc->data[SC_STONE].timer != -1 && tsc->opt1 == OPT1_STONE))) + if(skill_num == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE))) return 0; } @@ -2246,8 +2254,8 @@ int status_calc_pc(struct map_session_data* sd,int first) sd->max_weight += 2000*skill; if(pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) sd->max_weight += 10000; - if(sd->sc.data[SC_KNOWLEDGE].timer != -1) - sd->max_weight += sd->max_weight*sd->sc.data[SC_KNOWLEDGE].val1/10; + if(sd->sc.data[SC_KNOWLEDGE]) + sd->max_weight += sd->max_weight*sd->sc.data[SC_KNOWLEDGE]->val1/10; if((skill=pc_checkskill(sd,ALL_INCCARRY))>0) sd->max_weight += 2000*skill; @@ -2261,8 +2269,8 @@ int status_calc_pc(struct map_session_data* sd,int first) sd->dsprate -= 4*skill; if(sd->sc.count){ - if(sd->sc.data[SC_SERVICE4U].timer!=-1) - sd->dsprate -= sd->sc.data[SC_SERVICE4U].val3; + if(sd->sc.data[SC_SERVICE4U]) + sd->dsprate -= sd->sc.data[SC_SERVICE4U]->val3; } //Underflow protections. @@ -2293,25 +2301,26 @@ int status_calc_pc(struct map_session_data* sd,int first) } if(sd->sc.count){ - if(sd->sc.data[SC_CONCENTRATE].timer!=-1) + if(sd->sc.data[SC_CONCENTRATE]) { //Update the card-bonus data - sd->sc.data[SC_CONCENTRATE].val3 = sd->param_bonus[1]; //Agi - sd->sc.data[SC_CONCENTRATE].val4 = sd->param_bonus[4]; //Dex + sd->sc.data[SC_CONCENTRATE]->val3 = sd->param_bonus[1]; //Agi + sd->sc.data[SC_CONCENTRATE]->val4 = sd->param_bonus[4]; //Dex } - if(sd->sc.data[SC_SIEGFRIED].timer!=-1){ - sd->subele[1] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[2] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[3] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[4] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[5] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[6] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[7] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[8] += sd->sc.data[SC_SIEGFRIED].val2; - sd->subele[9] += sd->sc.data[SC_SIEGFRIED].val2; + if(sd->sc.data[SC_SIEGFRIED]){ + i = sd->sc.data[SC_SIEGFRIED]->val2; + sd->subele[ELE_WATER] += i; + sd->subele[ELE_EARTH] += i; + sd->subele[ELE_FIRE] += i; + sd->subele[ELE_WIND] += i; + sd->subele[ELE_POISON] += i; + sd->subele[ELE_HOLY] += i; + sd->subele[ELE_DARK] += i; + sd->subele[ELE_GHOST] += i; + sd->subele[ELE_UNDEAD] += i; } - if(sd->sc.data[SC_PROVIDENCE].timer!=-1){ - sd->subele[6] += sd->sc.data[SC_PROVIDENCE].val2; - sd->subrace[RC_DEMON] += sd->sc.data[SC_PROVIDENCE].val2; + if(sd->sc.data[SC_PROVIDENCE]){ + sd->subele[ELE_HOLY] += sd->sc.data[SC_PROVIDENCE]->val2; + sd->subrace[RC_DEMON] += sd->sc.data[SC_PROVIDENCE]->val2; } } @@ -2616,42 +2625,43 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str return; if ( - (sc->data[SC_POISON].timer != -1 && sc->data[SC_SLOWPOISON].timer == -1) - || (sc->data[SC_DPOISON].timer != -1 && sc->data[SC_SLOWPOISON].timer == -1) - || sc->data[SC_BERSERK].timer != -1 - || sc->data[SC_TRICKDEAD].timer != -1 - || sc->data[SC_BLEEDING].timer != -1 + (sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON]) + || (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON]) + || sc->data[SC_BERSERK] + || sc->data[SC_TRICKDEAD] + || sc->data[SC_BLEEDING] ) //No regen regen->flag = 0; if ( - sc->data[SC_EXTREMITYFIST].timer != -1 - || sc->data[SC_DANCING].timer != -1 - || (sc->data[SC_EXPLOSIONSPIRITS].timer != -1 - && (sc->data[SC_SPIRIT].timer==-1 || sc->data[SC_SPIRIT].val2 != SL_MONK)) + sc->data[SC_EXTREMITYFIST] + || sc->data[SC_DANCING] + || (sc->data[SC_EXPLOSIONSPIRITS] + && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)) ) //No natural SP regen regen->flag &=~RGN_SP; if( - sc->data[SC_TENSIONRELAX].timer!=-1 + sc->data[SC_TENSIONRELAX] ) { regen->rate.hp += 2; if (regen->sregen) regen->sregen->rate.hp += 3; } - if (sc->data[SC_MAGNIFICAT].timer != -1) + if (sc->data[SC_MAGNIFICAT]) { regen->rate.hp += 1; regen->rate.sp += 1; } - if (sc->data[SC_REGENERATION].timer != -1) + if (sc->data[SC_REGENERATION]) { - if (!sc->data[SC_REGENERATION].val4) + const struct status_change_entry *sce = sc->data[SC_REGENERATION]; + if (!sce->val4) { - regen->rate.hp += sc->data[SC_REGENERATION].val2; - regen->rate.sp += sc->data[SC_REGENERATION].val3; + regen->rate.hp += sce->val2; + regen->rate.sp += sce->val3; } else - regen->flag&=~sc->data[SC_REGENERATION].val4; //Remove regen as specified by val4 + regen->flag&=~sce->val4; //Remove regen as specified by val4 } } @@ -2715,9 +2725,9 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) status->matk_min = status_calc_matk(&sd->bl, &sd->sc, status->matk_min); status->matk_max = status_calc_matk(&sd->bl, &sd->sc, status->matk_max); - if(sd->sc.data[SC_MAGICPOWER].timer!=-1) { //Store current matk values - sd->sc.data[SC_MAGICPOWER].val3 = status->matk_min; - sd->sc.data[SC_MAGICPOWER].val4 = status->matk_max; + if(sd->sc.data[SC_MAGICPOWER]) { //Store current matk values + sd->sc.mp_matk_min = status->matk_min; + sd->sc.mp_matk_max = status->matk_max; } } @@ -2834,7 +2844,6 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] { struct status_data *status = &hd->battle_status, *b_status = &hd->base_status; - struct status_change *sc = &hd->sc; int skill = 0; @@ -2862,23 +2871,23 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] if(flag&SCB_VIT) { //Since vit affects def, recalculate def. flag|=SCB_DEF; - status->def = status_calc_def(&hd->bl, sc, b_status->def); + status->def = status_calc_def(&hd->bl, &hd->sc, b_status->def); status->def+= (status->vit/5 - b_status->vit/5); } if(flag&SCB_INT) { flag|=SCB_MDEF; - status->mdef = status_calc_mdef(&hd->bl, sc, b_status->mdef); + status->mdef = status_calc_mdef(&hd->bl, &hd->sc, b_status->mdef); status->mdef+= (status->int_/5 - b_status->int_/5); } if(flag&SCB_DEX) { flag |=SCB_WATK; - status->rhw.atk = status_calc_watk(&hd->bl, sc, b_status->rhw.atk); + status->rhw.atk = status_calc_watk(&hd->bl, &hd->sc, b_status->rhw.atk); status->rhw.atk+= (status->dex - b_status->dex); } if(flag&SCB_STR) { flag |=SCB_WATK; - status->rhw.atk2 = status_calc_watk(&hd->bl, sc, b_status->rhw.atk2); + status->rhw.atk2 = status_calc_watk(&hd->bl, &hd->sc, b_status->rhw.atk2); status->rhw.atk2+= (status->str - b_status->str); } if(flag|SCB_WATK && status->rhw.atk2 < status->rhw.atk) @@ -2896,7 +2905,7 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] skill = (1000 -4*status->agi -status->dex) *hd->homunculusDB->baseASPD/1000; - status->aspd_rate = status_calc_aspd_rate(&hd->bl, sc , b_status->aspd_rate); + status->aspd_rate = status_calc_aspd_rate(&hd->bl, &hd->sc , b_status->aspd_rate); if(status->aspd_rate != 1000) skill = skill*status->aspd_rate/1000; @@ -2907,14 +2916,14 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] if(flag&(SCB_AGI|SCB_DSPD)) { skill = 800-status->agi*4; status->dmotion = cap_value(skill, 400, 800); - status->dmotion = status_calc_dmotion(&hd->bl, sc, b_status->dmotion); + status->dmotion = status_calc_dmotion(&hd->bl, &hd->sc, b_status->dmotion); } if(flag&(SCB_INT|SCB_MAXSP|SCB_VIT|SCB_MAXHP) && flag != SCB_ALL) status_calc_regen(&hd->bl, status, &hd->regen); if(flag&SCB_REGEN) - status_calc_regen_rate(&hd->bl, &hd->regen, sc); + status_calc_regen_rate(&hd->bl, &hd->regen, &hd->sc); if (flag == SCB_ALL) return; //Refresh is done on invoking function (status_calc_hom) @@ -3119,9 +3128,9 @@ void status_calc_bl(struct block_list *bl, unsigned long flag) status->matk_max = status_base_matk_max(status); status->matk_min = status_calc_matk(bl, sc, status->matk_min); status->matk_max = status_calc_matk(bl, sc, status->matk_max); - if(sc->data[SC_MAGICPOWER].timer!=-1) { //Store current matk values - sc->data[SC_MAGICPOWER].val3 = status->matk_min; - sc->data[SC_MAGICPOWER].val4 = status->matk_max; + if(sc->data[SC_MAGICPOWER]) { //Store current matk values + sc->mp_matk_min = status->matk_min; + sc->mp_matk_max = status->matk_max; } } @@ -3158,35 +3167,35 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(str,0,USHRT_MAX); - if(sc->data[SC_INCALLSTATUS].timer!=-1) - str += sc->data[SC_INCALLSTATUS].val1; - if(sc->data[SC_INCSTR].timer!=-1) - str += sc->data[SC_INCSTR].val1; - if(sc->data[SC_STRFOOD].timer!=-1) - str += sc->data[SC_STRFOOD].val1; - if(sc->data[SC_BATTLEORDERS].timer!=-1) + if(sc->data[SC_INCALLSTATUS]) + str += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCSTR]) + str += sc->data[SC_INCSTR]->val1; + if(sc->data[SC_STRFOOD]) + str += sc->data[SC_STRFOOD]->val1; + if(sc->data[SC_BATTLEORDERS]) str += 5; - if(sc->data[SC_GUILDAURA].timer != -1 && sc->data[SC_GUILDAURA].val3>>16) - str += sc->data[SC_GUILDAURA].val3>>16; - if(sc->data[SC_LOUD].timer!=-1) + if(sc->data[SC_GUILDAURA] && sc->data[SC_GUILDAURA]->val3>>16) + str += (sc->data[SC_GUILDAURA]->val3)>>16; + if(sc->data[SC_LOUD]) str += 4; - if(sc->data[SC_TRUESIGHT].timer!=-1) + if(sc->data[SC_TRUESIGHT]) str += 5; - if(sc->data[SC_SPURT].timer!=-1) + if(sc->data[SC_SPURT]) str += 10; - if(sc->data[SC_NEN].timer!=-1) - str += sc->data[SC_NEN].val1; - if(sc->data[SC_BLESSING].timer != -1){ - if(sc->data[SC_BLESSING].val2) - str += sc->data[SC_BLESSING].val2; + if(sc->data[SC_NEN]) + str += sc->data[SC_NEN]->val1; + if(sc->data[SC_BLESSING]){ + if(sc->data[SC_BLESSING]->val2) + str += sc->data[SC_BLESSING]->val2; else str >>= 1; } - if(sc->data[SC_MARIONETTE].timer!=-1) - str -= (sc->data[SC_MARIONETTE].val3>>16)&0xFF; - if(sc->data[SC_MARIONETTE2].timer!=-1) - str += (sc->data[SC_MARIONETTE2].val3>>16)&0xFF; - if(sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_HIGH && str < 50) + if(sc->data[SC_MARIONETTE]) + str -= ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF; + if(sc->data[SC_MARIONETTE2]) + str += ((sc->data[SC_MARIONETTE2]->val3)>>16)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && str < 50) str = 50; return (unsigned short)cap_value(str,0,USHRT_MAX); @@ -3197,33 +3206,33 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(agi,0,USHRT_MAX); - if(sc->data[SC_CONCENTRATE].timer!=-1 && sc->data[SC_QUAGMIRE].timer == -1) - agi += (agi-sc->data[SC_CONCENTRATE].val3)*sc->data[SC_CONCENTRATE].val2/100; - if(sc->data[SC_INCALLSTATUS].timer!=-1) - agi += sc->data[SC_INCALLSTATUS].val1; - if(sc->data[SC_INCAGI].timer!=-1) - agi += sc->data[SC_INCAGI].val1; - if(sc->data[SC_AGIFOOD].timer!=-1) - agi += sc->data[SC_AGIFOOD].val1; - if(sc->data[SC_GUILDAURA].timer != -1 && sc->data[SC_GUILDAURA].val4>>16) - agi += sc->data[SC_GUILDAURA].val4>>16; - if(sc->data[SC_TRUESIGHT].timer!=-1) + if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) + agi += (agi-sc->data[SC_CONCENTRATE]->val3)*sc->data[SC_CONCENTRATE]->val2/100; + if(sc->data[SC_INCALLSTATUS]) + agi += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCAGI]) + agi += sc->data[SC_INCAGI]->val1; + if(sc->data[SC_AGIFOOD]) + agi += sc->data[SC_AGIFOOD]->val1; + if(sc->data[SC_GUILDAURA] && (sc->data[SC_GUILDAURA]->val4)>>16) + agi += (sc->data[SC_GUILDAURA]->val4)>>16; + if(sc->data[SC_TRUESIGHT]) agi += 5; - if(sc->data[SC_INCREASEAGI].timer!=-1) - agi += sc->data[SC_INCREASEAGI].val2; - if(sc->data[SC_INCREASING].timer!=-1) + if(sc->data[SC_INCREASEAGI]) + agi += sc->data[SC_INCREASEAGI]->val2; + if(sc->data[SC_INCREASING]) agi += 4; // added based on skill updates [Reddozen] - if(sc->data[SC_DECREASEAGI].timer!=-1) - agi -= sc->data[SC_DECREASEAGI].val2; - if(sc->data[SC_QUAGMIRE].timer!=-1) - agi -= sc->data[SC_QUAGMIRE].val2; - if(sc->data[SC_SUITON].timer!=-1 && sc->data[SC_SUITON].val3) - agi -= sc->data[SC_SUITON].val2; - if(sc->data[SC_MARIONETTE].timer!=-1) - agi -= (sc->data[SC_MARIONETTE].val3>>8)&0xFF; - if(sc->data[SC_MARIONETTE2].timer!=-1) - agi += (sc->data[SC_MARIONETTE2].val3>>8)&0xFF; - if(sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_HIGH && agi < 50) + if(sc->data[SC_DECREASEAGI]) + agi -= sc->data[SC_DECREASEAGI]->val2; + if(sc->data[SC_QUAGMIRE]) + agi -= sc->data[SC_QUAGMIRE]->val2; + if(sc->data[SC_SUITON] && sc->data[SC_SUITON]->val3) + agi -= sc->data[SC_SUITON]->val2; + if(sc->data[SC_MARIONETTE]) + agi -= ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF; + if(sc->data[SC_MARIONETTE2]) + agi += ((sc->data[SC_MARIONETTE2]->val3)>>8)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && agi < 50) agi = 50; return (unsigned short)cap_value(agi,0,USHRT_MAX); @@ -3234,25 +3243,25 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(vit,0,USHRT_MAX); - if(sc->data[SC_INCALLSTATUS].timer!=-1) - vit += sc->data[SC_INCALLSTATUS].val1; - if(sc->data[SC_INCVIT].timer!=-1) - vit += sc->data[SC_INCVIT].val1; - if(sc->data[SC_VITFOOD].timer!=-1) - vit += sc->data[SC_VITFOOD].val1; - if(sc->data[SC_CHANGE].timer!=-1) - vit += sc->data[SC_CHANGE].val2; - if(sc->data[SC_GUILDAURA].timer != -1 && sc->data[SC_GUILDAURA].val3&0xFFFF) - vit += sc->data[SC_GUILDAURA].val3&0xFFFF; - if(sc->data[SC_TRUESIGHT].timer!=-1) + if(sc->data[SC_INCALLSTATUS]) + vit += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCVIT]) + vit += sc->data[SC_INCVIT]->val1; + if(sc->data[SC_VITFOOD]) + vit += sc->data[SC_VITFOOD]->val1; + if(sc->data[SC_CHANGE]) + vit += sc->data[SC_CHANGE]->val2; + if(sc->data[SC_GUILDAURA] && sc->data[SC_GUILDAURA]->val3&0xFFFF) + vit += sc->data[SC_GUILDAURA]->val3&0xFFFF; + if(sc->data[SC_TRUESIGHT]) vit += 5; - if(sc->data[SC_STRIPARMOR].timer!=-1) - vit -= vit * sc->data[SC_STRIPARMOR].val2/100; - if(sc->data[SC_MARIONETTE].timer!=-1) - vit -= sc->data[SC_MARIONETTE].val3&0xFF; - if(sc->data[SC_MARIONETTE2].timer!=-1) - vit += sc->data[SC_MARIONETTE2].val3&0xFF; - if(sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_HIGH && vit < 50) + if(sc->data[SC_STRIPARMOR]) + vit -= vit * sc->data[SC_STRIPARMOR]->val2/100; + if(sc->data[SC_MARIONETTE]) + vit -= sc->data[SC_MARIONETTE]->val3&0xFF; + if(sc->data[SC_MARIONETTE2]) + vit += sc->data[SC_MARIONETTE2]->val3&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50) vit = 50; return (unsigned short)cap_value(vit,0,USHRT_MAX); @@ -3263,33 +3272,33 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(int_,0,USHRT_MAX); - if(sc->data[SC_INCALLSTATUS].timer!=-1) - int_ += sc->data[SC_INCALLSTATUS].val1; - if(sc->data[SC_INCINT].timer!=-1) - int_ += sc->data[SC_INCINT].val1; - if(sc->data[SC_INTFOOD].timer!=-1) - int_ += sc->data[SC_INTFOOD].val1; - if(sc->data[SC_CHANGE].timer!=-1) - int_ += sc->data[SC_CHANGE].val3; - if(sc->data[SC_BATTLEORDERS].timer!=-1) + if(sc->data[SC_INCALLSTATUS]) + int_ += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCINT]) + int_ += sc->data[SC_INCINT]->val1; + if(sc->data[SC_INTFOOD]) + int_ += sc->data[SC_INTFOOD]->val1; + if(sc->data[SC_CHANGE]) + int_ += sc->data[SC_CHANGE]->val3; + if(sc->data[SC_BATTLEORDERS]) int_ += 5; - if(sc->data[SC_TRUESIGHT].timer!=-1) + if(sc->data[SC_TRUESIGHT]) int_ += 5; - if(sc->data[SC_BLESSING].timer != -1){ - if (sc->data[SC_BLESSING].val2) - int_ += sc->data[SC_BLESSING].val2; + if(sc->data[SC_BLESSING]){ + if (sc->data[SC_BLESSING]->val2) + int_ += sc->data[SC_BLESSING]->val2; else int_ >>= 1; } - if(sc->data[SC_STRIPHELM].timer!=-1) - int_ -= int_ * sc->data[SC_STRIPHELM].val2/100; - if(sc->data[SC_NEN].timer!=-1) - int_ += sc->data[SC_NEN].val1; - if(sc->data[SC_MARIONETTE].timer!=-1) - int_ -= (sc->data[SC_MARIONETTE].val4>>16)&0xFF; - if(sc->data[SC_MARIONETTE2].timer!=-1) - int_ += (sc->data[SC_MARIONETTE2].val4>>16)&0xFF; - if(sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_HIGH && int_ < 50) + if(sc->data[SC_STRIPHELM]) + int_ -= int_ * sc->data[SC_STRIPHELM]->val2/100; + if(sc->data[SC_NEN]) + int_ += sc->data[SC_NEN]->val1; + if(sc->data[SC_MARIONETTE]) + int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; + if(sc->data[SC_MARIONETTE2]) + int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && int_ < 50) int_ = 50; return (unsigned short)cap_value(int_,0,USHRT_MAX); @@ -3300,36 +3309,36 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(dex,0,USHRT_MAX); - if(sc->data[SC_CONCENTRATE].timer!=-1 && sc->data[SC_QUAGMIRE].timer == -1) - dex += (dex-sc->data[SC_CONCENTRATE].val4)*sc->data[SC_CONCENTRATE].val2/100; + if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) + dex += (dex-sc->data[SC_CONCENTRATE]->val4)*sc->data[SC_CONCENTRATE]->val2/100; - if(sc->data[SC_INCALLSTATUS].timer!=-1) - dex += sc->data[SC_INCALLSTATUS].val1; - if(sc->data[SC_INCDEX].timer!=-1) - dex += sc->data[SC_INCDEX].val1; - if(sc->data[SC_DEXFOOD].timer!=-1) - dex += sc->data[SC_DEXFOOD].val1; - if(sc->data[SC_BATTLEORDERS].timer!=-1) + if(sc->data[SC_INCALLSTATUS]) + dex += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCDEX]) + dex += sc->data[SC_INCDEX]->val1; + if(sc->data[SC_DEXFOOD]) + dex += sc->data[SC_DEXFOOD]->val1; + if(sc->data[SC_BATTLEORDERS]) dex += 5; - if(sc->data[SC_GUILDAURA].timer != -1 && sc->data[SC_GUILDAURA].val4&0xFFFF) - dex += sc->data[SC_GUILDAURA].val4&0xFFFF; - if(sc->data[SC_TRUESIGHT].timer!=-1) + if(sc->data[SC_GUILDAURA] && sc->data[SC_GUILDAURA]->val4&0xFFFF) + dex += sc->data[SC_GUILDAURA]->val4&0xFFFF; + if(sc->data[SC_TRUESIGHT]) dex += 5; - if(sc->data[SC_QUAGMIRE].timer!=-1) - dex -= sc->data[SC_QUAGMIRE].val2; - if(sc->data[SC_BLESSING].timer != -1){ - if (sc->data[SC_BLESSING].val2) - dex += sc->data[SC_BLESSING].val2; + if(sc->data[SC_QUAGMIRE]) + dex -= sc->data[SC_QUAGMIRE]->val2; + if(sc->data[SC_BLESSING]){ + if (sc->data[SC_BLESSING]->val2) + dex += sc->data[SC_BLESSING]->val2; else dex >>= 1; } - if(sc->data[SC_INCREASING].timer!=-1) + if(sc->data[SC_INCREASING]) dex += 4; // added based on skill updates [Reddozen] - if(sc->data[SC_MARIONETTE].timer!=-1) - dex -= (sc->data[SC_MARIONETTE].val4>>8)&0xFF; - if(sc->data[SC_MARIONETTE2].timer!=-1) - dex += (sc->data[SC_MARIONETTE2].val4>>8)&0xFF; - if(sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_HIGH && dex < 50) + if(sc->data[SC_MARIONETTE]) + dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; + if(sc->data[SC_MARIONETTE2]) + dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && dex < 50) dex = 50; return (unsigned short)cap_value(dex,0,USHRT_MAX); @@ -3340,23 +3349,23 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(luk,0,USHRT_MAX); - if(sc->data[SC_CURSE].timer!=-1) + if(sc->data[SC_CURSE]) return 0; - if(sc->data[SC_INCALLSTATUS].timer!=-1) - luk += sc->data[SC_INCALLSTATUS].val1; - if(sc->data[SC_INCLUK].timer!=-1) - luk += sc->data[SC_INCLUK].val1; - if(sc->data[SC_LUKFOOD].timer!=-1) - luk += sc->data[SC_LUKFOOD].val1; - if(sc->data[SC_TRUESIGHT].timer!=-1) + if(sc->data[SC_INCALLSTATUS]) + luk += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCLUK]) + luk += sc->data[SC_INCLUK]->val1; + if(sc->data[SC_LUKFOOD]) + luk += sc->data[SC_LUKFOOD]->val1; + if(sc->data[SC_TRUESIGHT]) luk += 5; - if(sc->data[SC_GLORIA].timer!=-1) + if(sc->data[SC_GLORIA]) luk += 30; - if(sc->data[SC_MARIONETTE].timer!=-1) - luk -= sc->data[SC_MARIONETTE].val4&0xFF; - if(sc->data[SC_MARIONETTE2].timer!=-1) - luk += sc->data[SC_MARIONETTE2].val4&0xFF; - if(sc->data[SC_SPIRIT].timer!=-1 && sc->data[SC_SPIRIT].val2 == SL_HIGH && luk < 50) + if(sc->data[SC_MARIONETTE]) + luk -= sc->data[SC_MARIONETTE]->val4&0xFF; + if(sc->data[SC_MARIONETTE2]) + luk += sc->data[SC_MARIONETTE2]->val4&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50) luk = 50; return (unsigned short)cap_value(luk,0,USHRT_MAX); @@ -3367,34 +3376,34 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan if(!sc || !sc->count) return cap_value(batk,0,USHRT_MAX); - if(sc->data[SC_INCBASEATK].timer!=-1) - batk += sc->data[SC_INCBASEATK].val1; - if(sc->data[SC_ATKPOTION].timer!=-1) - batk += sc->data[SC_ATKPOTION].val1; - if(sc->data[SC_BATKFOOD].timer!=-1) - batk += sc->data[SC_BATKFOOD].val1; - if(sc->data[SC_INCATKRATE].timer!=-1) - batk += batk * sc->data[SC_INCATKRATE].val1/100; - if(sc->data[SC_PROVOKE].timer!=-1) - batk += batk * sc->data[SC_PROVOKE].val3/100; - if(sc->data[SC_CONCENTRATION].timer!=-1) - batk += batk * sc->data[SC_CONCENTRATION].val2/100; - if(sc->data[SC_SKE].timer!=-1) + if(sc->data[SC_INCBASEATK]) + batk += sc->data[SC_INCBASEATK]->val1; + if(sc->data[SC_ATKPOTION]) + batk += sc->data[SC_ATKPOTION]->val1; + if(sc->data[SC_BATKFOOD]) + batk += sc->data[SC_BATKFOOD]->val1; + if(sc->data[SC_INCATKRATE]) + batk += batk * sc->data[SC_INCATKRATE]->val1/100; + if(sc->data[SC_PROVOKE]) + batk += batk * sc->data[SC_PROVOKE]->val3/100; + if(sc->data[SC_CONCENTRATION]) + batk += batk * sc->data[SC_CONCENTRATION]->val2/100; + if(sc->data[SC_SKE]) batk += batk * 3; - if(sc->data[SC_BLOODLUST].timer!=-1) - batk += batk * sc->data[SC_BLOODLUST].val2/100; - if(sc->data[SC_JOINTBEAT].timer!=-1 && sc->data[SC_JOINTBEAT].val2&BREAK_WAIST) + if(sc->data[SC_BLOODLUST]) + batk += batk * sc->data[SC_BLOODLUST]->val2/100; + if(sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST) batk -= batk * 25/100; - if(sc->data[SC_CURSE].timer!=-1) + if(sc->data[SC_CURSE]) batk -= batk * 25/100; //Curse shouldn't effect on this? <- Curse OR Bleeding?? -// if(sc->data[SC_BLEEDING].timer != -1) +// if(sc->data[SC_BLEEDING]->) // batk -= batk * 25/100; - if(sc->data[SC_FLEET].timer!=-1) - batk += batk * sc->data[SC_FLEET].val3/100; - if(sc->data[SC_GATLINGFEVER].timer!=-1) - batk += sc->data[SC_GATLINGFEVER].val3; - if(sc->data[SC_MADNESSCANCEL].timer!=-1) + if(sc->data[SC_FLEET]) + batk += batk * sc->data[SC_FLEET]->val3/100; + if(sc->data[SC_GATLINGFEVER]) + batk += sc->data[SC_GATLINGFEVER]->val3; + if(sc->data[SC_MADNESSCANCEL]) batk += 100; return (unsigned short)cap_value(batk,0,USHRT_MAX); } @@ -3404,40 +3413,40 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan if(!sc || !sc->count) return cap_value(watk,0,USHRT_MAX); - if(sc->data[SC_IMPOSITIO].timer!=-1) - watk += sc->data[SC_IMPOSITIO].val2; - if(sc->data[SC_WATKFOOD].timer!=-1) - watk += sc->data[SC_WATKFOOD].val1; - if(sc->data[SC_DRUMBATTLE].timer!=-1) - watk += sc->data[SC_DRUMBATTLE].val2; - if(sc->data[SC_VOLCANO].timer!=-1) - watk += sc->data[SC_VOLCANO].val2; - if(sc->data[SC_INCATKRATE].timer!=-1) - watk += watk * sc->data[SC_INCATKRATE].val1/100; - if(sc->data[SC_PROVOKE].timer!=-1) - watk += watk * sc->data[SC_PROVOKE].val3/100; - if(sc->data[SC_CONCENTRATION].timer!=-1) - watk += watk * sc->data[SC_CONCENTRATION].val2/100; - if(sc->data[SC_SKE].timer!=-1) + if(sc->data[SC_IMPOSITIO]) + watk += sc->data[SC_IMPOSITIO]->val2; + if(sc->data[SC_WATKFOOD]) + watk += sc->data[SC_WATKFOOD]->val1; + if(sc->data[SC_DRUMBATTLE]) + watk += sc->data[SC_DRUMBATTLE]->val2; + if(sc->data[SC_VOLCANO]) + watk += sc->data[SC_VOLCANO]->val2; + if(sc->data[SC_INCATKRATE]) + watk += watk * sc->data[SC_INCATKRATE]->val1/100; + if(sc->data[SC_PROVOKE]) + watk += watk * sc->data[SC_PROVOKE]->val3/100; + if(sc->data[SC_CONCENTRATION]) + watk += watk * sc->data[SC_CONCENTRATION]->val2/100; + if(sc->data[SC_SKE]) watk += watk * 3; - if(sc->data[SC_NIBELUNGEN].timer!=-1) { + if(sc->data[SC_NIBELUNGEN]) { if (bl->type != BL_PC) - watk += sc->data[SC_NIBELUNGEN].val2; + watk += sc->data[SC_NIBELUNGEN]->val2; else { TBL_PC *sd = (TBL_PC*)bl; - int index = sd->equip_index[sd->state.lr_flag?8:9]; + int index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R]; if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) - watk += sc->data[SC_NIBELUNGEN].val2; + watk += sc->data[SC_NIBELUNGEN]->val2; } } - if(sc->data[SC_BLOODLUST].timer!=-1) - watk += watk * sc->data[SC_BLOODLUST].val2/100; - if(sc->data[SC_FLEET].timer!=-1) - watk += watk * sc->data[SC_FLEET].val3/100; - if(sc->data[SC_CURSE].timer!=-1) + if(sc->data[SC_BLOODLUST]) + watk += watk * sc->data[SC_BLOODLUST]->val2/100; + if(sc->data[SC_FLEET]) + watk += watk * sc->data[SC_FLEET]->val3/100; + if(sc->data[SC_CURSE]) watk -= watk * 25/100; - if(sc->data[SC_STRIPWEAPON].timer!=-1) - watk -= watk * sc->data[SC_STRIPWEAPON].val2/100; + if(sc->data[SC_STRIPWEAPON]) + watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100; return (unsigned short)cap_value(watk,0,USHRT_MAX); } @@ -3447,16 +3456,16 @@ static unsigned short status_calc_matk(struct block_list *bl, struct status_chan if(!sc || !sc->count) return cap_value(matk,0,USHRT_MAX); - if(sc->data[SC_MATKPOTION].timer!=-1) - matk += sc->data[SC_MATKPOTION].val1; - if(sc->data[SC_MATKFOOD].timer!=-1) - matk += sc->data[SC_MATKFOOD].val1; - if(sc->data[SC_MAGICPOWER].timer!=-1) - matk += matk * 5*sc->data[SC_MAGICPOWER].val1/100; - if(sc->data[SC_MINDBREAKER].timer!=-1) - matk += matk * sc->data[SC_MINDBREAKER].val2/100; - if(sc->data[SC_INCMATKRATE].timer!=-1) - matk += matk * sc->data[SC_INCMATKRATE].val1/100; + if(sc->data[SC_MATKPOTION]) + matk += sc->data[SC_MATKPOTION]->val1; + if(sc->data[SC_MATKFOOD]) + matk += sc->data[SC_MATKFOOD]->val1; + if(sc->data[SC_MAGICPOWER]) + matk += matk * sc->data[SC_MAGICPOWER]->val3/100; + if(sc->data[SC_MINDBREAKER]) + matk += matk * sc->data[SC_MINDBREAKER]->val2/100; + if(sc->data[SC_INCMATKRATE]) + matk += matk * sc->data[SC_INCMATKRATE]->val1/100; return (unsigned short)cap_value(matk,0,USHRT_MAX); } @@ -3466,15 +3475,15 @@ static signed short status_calc_critical(struct block_list *bl, struct status_ch if(!sc || !sc->count) return cap_value(critical,10,SHRT_MAX); - if (sc->data[SC_INCCRI].timer!=-1) - critical += sc->data[SC_INCCRI].val2; - if (sc->data[SC_EXPLOSIONSPIRITS].timer!=-1) - critical += sc->data[SC_EXPLOSIONSPIRITS].val2; - if (sc->data[SC_FORTUNE].timer!=-1) - critical += sc->data[SC_FORTUNE].val2; - if (sc->data[SC_TRUESIGHT].timer!=-1) - critical += sc->data[SC_TRUESIGHT].val2; - if(sc->data[SC_CLOAKING].timer!=-1) + if (sc->data[SC_INCCRI]) + critical += sc->data[SC_INCCRI]->val2; + if (sc->data[SC_EXPLOSIONSPIRITS]) + critical += sc->data[SC_EXPLOSIONSPIRITS]->val2; + if (sc->data[SC_FORTUNE]) + critical += sc->data[SC_FORTUNE]->val2; + if (sc->data[SC_TRUESIGHT]) + critical += sc->data[SC_TRUESIGHT]->val2; + if(sc->data[SC_CLOAKING]) critical += critical; return (short)cap_value(critical,10,SHRT_MAX); @@ -3486,23 +3495,23 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change if(!sc || !sc->count) return cap_value(hit,1,SHRT_MAX); - if(sc->data[SC_INCHIT].timer != -1) - hit += sc->data[SC_INCHIT].val1; - if(sc->data[SC_HITFOOD].timer!=-1) - hit += sc->data[SC_HITFOOD].val1; - if(sc->data[SC_TRUESIGHT].timer != -1) - hit += sc->data[SC_TRUESIGHT].val3; - if(sc->data[SC_HUMMING].timer!=-1) - hit += sc->data[SC_HUMMING].val2; - if(sc->data[SC_CONCENTRATION].timer != -1) - hit += sc->data[SC_CONCENTRATION].val3; - if(sc->data[SC_INCHITRATE].timer != -1) - hit += hit * sc->data[SC_INCHITRATE].val1/100; - if(sc->data[SC_BLIND].timer != -1) + if(sc->data[SC_INCHIT]) + hit += sc->data[SC_INCHIT]->val1; + if(sc->data[SC_HITFOOD]) + hit += sc->data[SC_HITFOOD]->val1; + if(sc->data[SC_TRUESIGHT]) + hit += sc->data[SC_TRUESIGHT]->val3; + if(sc->data[SC_HUMMING]) + hit += sc->data[SC_HUMMING]->val2; + if(sc->data[SC_CONCENTRATION]) + hit += sc->data[SC_CONCENTRATION]->val3; + if(sc->data[SC_INCHITRATE]) + hit += hit * sc->data[SC_INCHITRATE]->val1/100; + if(sc->data[SC_BLIND]) hit -= hit * 25/100; - if(sc->data[SC_ADJUSTMENT].timer!=-1) + if(sc->data[SC_ADJUSTMENT]) hit -= 30; - if(sc->data[SC_INCREASING].timer!=-1) + if(sc->data[SC_INCREASING]) hit += 20; // RockmanEXE; changed based on updated [Reddozen] return (short)cap_value(hit,1,SHRT_MAX); @@ -3516,34 +3525,34 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change if(!sc || !sc->count) return cap_value(flee,1,SHRT_MAX); - if(sc->data[SC_INCFLEE].timer!=-1) - flee += sc->data[SC_INCFLEE].val1; - if(sc->data[SC_FLEEFOOD].timer!=-1) - flee += sc->data[SC_FLEEFOOD].val1; - if(sc->data[SC_WHISTLE].timer!=-1) - flee += sc->data[SC_WHISTLE].val2; - if(sc->data[SC_WINDWALK].timer!=-1) - flee += sc->data[SC_WINDWALK].val2; - if(sc->data[SC_INCFLEERATE].timer!=-1) - flee += flee * sc->data[SC_INCFLEERATE].val1/100; - if(sc->data[SC_VIOLENTGALE].timer!=-1) - flee += sc->data[SC_VIOLENTGALE].val2; - if(sc->data[SC_MOON_COMFORT].timer!=-1) //SG skill [Komurka] - flee += sc->data[SC_MOON_COMFORT].val2; - if(sc->data[SC_CLOSECONFINE].timer!=-1) + if(sc->data[SC_INCFLEE]) + flee += sc->data[SC_INCFLEE]->val1; + if(sc->data[SC_FLEEFOOD]) + flee += sc->data[SC_FLEEFOOD]->val1; + if(sc->data[SC_WHISTLE]) + flee += sc->data[SC_WHISTLE]->val2; + if(sc->data[SC_WINDWALK]) + flee += sc->data[SC_WINDWALK]->val2; + if(sc->data[SC_INCFLEERATE]) + flee += flee * sc->data[SC_INCFLEERATE]->val1/100; + if(sc->data[SC_VIOLENTGALE]) + flee += sc->data[SC_VIOLENTGALE]->val2; + if(sc->data[SC_MOON_COMFORT]) //SG skill [Komurka] + flee += sc->data[SC_MOON_COMFORT]->val2; + if(sc->data[SC_CLOSECONFINE]) flee += 10; - if(sc->data[SC_SPIDERWEB].timer!=-1) + if(sc->data[SC_SPIDERWEB]) flee -= flee * 50/100; - if(sc->data[SC_BERSERK].timer!=-1) + if(sc->data[SC_BERSERK]) flee -= flee * 50/100; - if(sc->data[SC_BLIND].timer!=-1) + if(sc->data[SC_BLIND]) flee -= flee * 25/100; - if(sc->data[SC_ADJUSTMENT].timer!=-1) + if(sc->data[SC_ADJUSTMENT]) flee += 30; - if(sc->data[SC_GATLINGFEVER].timer!=-1) - flee -= sc->data[SC_GATLINGFEVER].val4; - if(sc->data[SC_SPEED].timer!=-1) - flee += 10 + sc->data[SC_SPEED].val1 * 10 ; + if(sc->data[SC_GATLINGFEVER]) + flee -= sc->data[SC_GATLINGFEVER]->val4; + if(sc->data[SC_SPEED]) + flee += 10 + sc->data[SC_SPEED]->val1 * 10 ; return (short)cap_value(flee,1,SHRT_MAX); } @@ -3553,10 +3562,10 @@ static signed short status_calc_flee2(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(flee2,10,SHRT_MAX); - if(sc->data[SC_INCFLEE2].timer!=-1) - flee2 += sc->data[SC_INCFLEE2].val2; - if(sc->data[SC_WHISTLE].timer!=-1) - flee2 += sc->data[SC_WHISTLE].val3*10; + if(sc->data[SC_INCFLEE2]) + flee2 += sc->data[SC_INCFLEE2]->val2; + if(sc->data[SC_WHISTLE]) + flee2 += sc->data[SC_WHISTLE]->val3*10; return (short)cap_value(flee2,10,SHRT_MAX); } @@ -3566,42 +3575,42 @@ static signed char status_calc_def(struct block_list *bl, struct status_change * if(!sc || !sc->count) return cap_value(def,0,CHAR_MAX); - if(sc->data[SC_BERSERK].timer!=-1) + if(sc->data[SC_BERSERK]) return 0; - if(sc->data[SC_SKA].timer != -1) - return sc->data[SC_SKA].val3; - if(sc->data[SC_BARRIER].timer!=-1) + if(sc->data[SC_SKA]) + return sc->data[SC_SKA]->val3; + if(sc->data[SC_BARRIER]) return 100; - if(sc->data[SC_KEEPING].timer!=-1) + if(sc->data[SC_KEEPING]) return 90; - if(sc->data[SC_STEELBODY].timer!=-1) + if(sc->data[SC_STEELBODY]) return 90; - if(sc->data[SC_INCDEF].timer!=-1) - def += sc->data[SC_INCDEF].val1; - if(sc->data[SC_ARMORCHANGE].timer!=-1) - def += sc->data[SC_ARMORCHANGE].val2; - if(sc->data[SC_DRUMBATTLE].timer!=-1) - def += sc->data[SC_DRUMBATTLE].val3; - if(sc->data[SC_DEFENCE].timer != -1) //[orn] - def += sc->data[SC_DEFENCE].val2 ; - if(sc->data[SC_INCDEFRATE].timer!=-1) - def += def * sc->data[SC_INCDEFRATE].val1/100; - if(sc->data[SC_STONE].timer!=-1 && sc->opt1 == OPT1_STONE) + if(sc->data[SC_INCDEF]) + def += sc->data[SC_INCDEF]->val1; + if(sc->data[SC_ARMORCHANGE]) + def += sc->data[SC_ARMORCHANGE]->val2; + if(sc->data[SC_DRUMBATTLE]) + def += sc->data[SC_DRUMBATTLE]->val3; + if(sc->data[SC_DEFENCE]) //[orn] + def += sc->data[SC_DEFENCE]->val2 ; + if(sc->data[SC_INCDEFRATE]) + def += def * sc->data[SC_INCDEFRATE]->val1/100; + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) def >>=1; - if(sc->data[SC_FREEZE].timer!=-1) + if(sc->data[SC_FREEZE]) def >>=1; - if(sc->data[SC_SIGNUMCRUCIS].timer!=-1) - def -= def * sc->data[SC_SIGNUMCRUCIS].val2/100; - if(sc->data[SC_CONCENTRATION].timer!=-1) - def -= def * sc->data[SC_CONCENTRATION].val4/100; - if(sc->data[SC_SKE].timer!=-1) + if(sc->data[SC_SIGNUMCRUCIS]) + def -= def * sc->data[SC_SIGNUMCRUCIS]->val2/100; + if(sc->data[SC_CONCENTRATION]) + def -= def * sc->data[SC_CONCENTRATION]->val4/100; + if(sc->data[SC_SKE]) def >>=1; - if(sc->data[SC_PROVOKE].timer!=-1 && bl->type != BL_PC) // Provoke doesn't alter player defense. - def -= def * sc->data[SC_PROVOKE].val4/100; - if(sc->data[SC_STRIPSHIELD].timer!=-1) - def -= def * sc->data[SC_STRIPSHIELD].val2/100; - if (sc->data[SC_FLING].timer!=-1) - def -= def * (sc->data[SC_FLING].val2)/100; + if(sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense-> + def -= def * sc->data[SC_PROVOKE]->val4/100; + if(sc->data[SC_STRIPSHIELD]) + def -= def * sc->data[SC_STRIPSHIELD]->val2/100; + if (sc->data[SC_FLING]) + def -= def * (sc->data[SC_FLING]->val2)/100; return (char)cap_value(def,0,CHAR_MAX); } @@ -3611,31 +3620,31 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change if(!sc || !sc->count) return cap_value(def2,1,SHRT_MAX); - if(sc->data[SC_BERSERK].timer!=-1) + if(sc->data[SC_BERSERK]) return 0; - if(sc->data[SC_ETERNALCHAOS].timer!=-1) + if(sc->data[SC_ETERNALCHAOS]) return 0; - if(sc->data[SC_SUN_COMFORT].timer!=-1) - def2 += sc->data[SC_SUN_COMFORT].val2; - if(sc->data[SC_ANGELUS].timer!=-1) - def2 += def2 * sc->data[SC_ANGELUS].val2/100; - if(sc->data[SC_CONCENTRATION].timer!=-1) - def2 -= def2 * sc->data[SC_CONCENTRATION].val4/100; - if(sc->data[SC_POISON].timer!=-1) + if(sc->data[SC_SUN_COMFORT]) + def2 += sc->data[SC_SUN_COMFORT]->val2; + if(sc->data[SC_ANGELUS]) + def2 += def2 * sc->data[SC_ANGELUS]->val2/100; + if(sc->data[SC_CONCENTRATION]) + def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100; + if(sc->data[SC_POISON]) def2 -= def2 * 25/100; - if(sc->data[SC_DPOISON].timer!=-1) + if(sc->data[SC_DPOISON]) def2 -= def2 * 25/100; - if(sc->data[SC_SKE].timer!=-1) + if(sc->data[SC_SKE]) def2 -= def2 * 50/100; - if(sc->data[SC_PROVOKE].timer!=-1) - def2 -= def2 * sc->data[SC_PROVOKE].val4/100; - if(sc->data[SC_JOINTBEAT].timer!=-1){ + if(sc->data[SC_PROVOKE]) + def2 -= def2 * sc->data[SC_PROVOKE]->val4/100; + if(sc->data[SC_JOINTBEAT]){ def2 -= def2 * - ( ( sc->data[SC_JOINTBEAT].val2&BREAK_SHOULDER ? 50 : 0 ) - + ( sc->data[SC_JOINTBEAT].val2&BREAK_WAIST ? 25 : 0 ) ); + ( ( sc->data[SC_JOINTBEAT]->val2&BREAK_SHOULDER ? 50 : 0 ) + + ( sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST ? 25 : 0 ) ); } - if(sc->data[SC_FLING].timer!=-1) - def2 -= def2 * (sc->data[SC_FLING].val3)/100; + if(sc->data[SC_FLING]) + def2 -= def2 * (sc->data[SC_FLING]->val3)/100; return (short)cap_value(def2,1,SHRT_MAX); } @@ -3645,24 +3654,24 @@ static signed char status_calc_mdef(struct block_list *bl, struct status_change if(!sc || !sc->count) return cap_value(mdef,0,CHAR_MAX); - if(sc->data[SC_BERSERK].timer!=-1) + if(sc->data[SC_BERSERK]) return 0; - if(sc->data[SC_BARRIER].timer!=-1) + if(sc->data[SC_BARRIER]) return 100; - if(sc->data[SC_STEELBODY].timer!=-1) + if(sc->data[SC_STEELBODY]) return 90; - if(sc->data[SC_SKA].timer != -1) // [marquis007] + if(sc->data[SC_SKA]) return 90; - if(sc->data[SC_ARMORCHANGE].timer!=-1) - mdef += sc->data[SC_ARMORCHANGE].val3; - if(sc->data[SC_STONE].timer!=-1 && sc->opt1 == OPT1_STONE) + if(sc->data[SC_ARMORCHANGE]) + mdef += sc->data[SC_ARMORCHANGE]->val3; + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) mdef += 25*mdef/100; - if(sc->data[SC_FREEZE].timer!=-1) + if(sc->data[SC_FREEZE]) mdef += 25*mdef/100; - if(sc->data[SC_ENDURE].timer!=-1 && sc->data[SC_ENDURE].val4 == 0) - mdef += sc->data[SC_ENDURE].val1; - if(sc->data[SC_INCMDEFRATE].timer!=-1) - mdef += mdef * sc->data[SC_INCMDEFRATE].val1/100; + if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 0) + mdef += sc->data[SC_ENDURE]->val1; + if(sc->data[SC_INCMDEFRATE]) + mdef += mdef * sc->data[SC_INCMDEFRATE]->val1/100; return (char)cap_value(mdef,0,CHAR_MAX); } @@ -3672,10 +3681,10 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(mdef2,1,SHRT_MAX); - if(sc->data[SC_BERSERK].timer!=-1) + if(sc->data[SC_BERSERK]) return 0; - if(sc->data[SC_MINDBREAKER].timer!=-1) - mdef2 -= mdef2 * sc->data[SC_MINDBREAKER].val3/100; + if(sc->data[SC_MINDBREAKER]) + mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; return (short)cap_value(mdef2,1,SHRT_MAX); } @@ -3686,71 +3695,71 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha return cap_value(speed,10,USHRT_MAX); // Fixed reductions - if(sc->data[SC_CURSE].timer!=-1) + if(sc->data[SC_CURSE]) speed += 450; - if(sc->data[SC_SWOO].timer != -1) // [marquis007] + if(sc->data[SC_SWOO]) speed += 450; //Let's use Curse's slow down momentarily (exact value unknown) - if(sc->data[SC_WEDDING].timer!=-1) + if(sc->data[SC_WEDDING]) speed += 300; - if(sc->data[SC_GATLINGFEVER].timer==-1) + if(!sc->data[SC_GATLINGFEVER]) { //% increases (they don't stack, with a few exceptions) - if(sc->data[SC_SPEEDUP1].timer!=-1) + if(sc->data[SC_SPEEDUP1]) speed -= speed * 50/100; - else if(sc->data[SC_AVOID].timer!=-1) - speed -= speed * sc->data[SC_AVOID].val2/100; + else if(sc->data[SC_AVOID]) + speed -= speed * sc->data[SC_AVOID]->val2/100; - if(sc->data[SC_RUN].timer!=-1) + if(sc->data[SC_RUN]) speed -= speed * 50/100; - else if(sc->data[SC_SPEEDUP0].timer!=-1) + else if(sc->data[SC_SPEEDUP0]) speed -= speed * 25/100; - else if(sc->data[SC_INCREASEAGI].timer!=-1) + else if(sc->data[SC_INCREASEAGI]) speed -= speed * 25/100; - else if(sc->data[SC_FUSION].timer != -1) + else if(sc->data[SC_FUSION]) speed -= speed * 25/100; - else if(sc->data[SC_CARTBOOST].timer!=-1) + else if(sc->data[SC_CARTBOOST]) speed -= speed * 20/100; - else if(sc->data[SC_BERSERK].timer!=-1) + else if(sc->data[SC_BERSERK]) speed -= speed * 20/100; - else if(sc->data[SC_WINDWALK].timer!=-1) - speed -= speed * sc->data[SC_WINDWALK].val3/100; + else if(sc->data[SC_WINDWALK]) + speed -= speed * sc->data[SC_WINDWALK]->val3/100; } //% reductions (they stack) - if(sc->data[SC_DANCING].timer!=-1 && sc->data[SC_DANCING].val3&0xFFFF) - speed += speed*(sc->data[SC_DANCING].val3&0xFFFF)/100; - if(sc->data[SC_DECREASEAGI].timer!=-1) + if(sc->data[SC_DANCING] && sc->data[SC_DANCING]->val3&0xFFFF) + speed += speed*(sc->data[SC_DANCING]->val3&0xFFFF)/100; + if(sc->data[SC_DECREASEAGI]) speed = speed * 100/75; - if(sc->data[SC_STEELBODY].timer!=-1) + if(sc->data[SC_STEELBODY]) speed = speed * 100/75; - if(sc->data[SC_QUAGMIRE].timer!=-1) + if(sc->data[SC_QUAGMIRE]) speed = speed * 100/50; - if(sc->data[SC_SUITON].timer!=-1 && sc->data[SC_SUITON].val3) - speed = speed * 100/sc->data[SC_SUITON].val3; - if(sc->data[SC_DONTFORGETME].timer!=-1) - speed = speed * 100/sc->data[SC_DONTFORGETME].val3; - if(sc->data[SC_DEFENDER].timer!=-1) - speed = speed * 100/sc->data[SC_DEFENDER].val3; - if(sc->data[SC_GOSPEL].timer!=-1 && sc->data[SC_GOSPEL].val4 == BCT_ENEMY) + if(sc->data[SC_SUITON] && sc->data[SC_SUITON]->val3) + speed = speed * 100/sc->data[SC_SUITON]->val3; + if(sc->data[SC_DONTFORGETME]) + speed = speed * 100/sc->data[SC_DONTFORGETME]->val3; + if(sc->data[SC_DEFENDER]) + speed = speed * 100/sc->data[SC_DEFENDER]->val3; + if(sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) speed = speed * 100/75; - if(sc->data[SC_JOINTBEAT].timer!=-1 && sc->data[SC_JOINTBEAT].val2&(BREAK_ANKLE|BREAK_KNEE)) { + if(sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&(BREAK_ANKLE|BREAK_KNEE)) { speed = speed * 100/(100 - - ( sc->data[SC_JOINTBEAT].val2&BREAK_ANKLE ? 50 : 0 ) - - ( sc->data[SC_JOINTBEAT].val2&BREAK_KNEE ? 30 : 0 )); + - ( sc->data[SC_JOINTBEAT]->val2&BREAK_ANKLE ? 50 : 0 ) + - ( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ? 30 : 0 )); } - if(sc->data[SC_CLOAKING].timer!=-1) + if(sc->data[SC_CLOAKING]) speed = speed * 100 /( - (sc->data[SC_CLOAKING].val4&1?25:0) //Wall speed bonus - +sc->data[SC_CLOAKING].val3); //Normal adjustment bonus. + (sc->data[SC_CLOAKING]->val4&1?25:0) //Wall speed bonus + +sc->data[SC_CLOAKING]->val3); //Normal adjustment bonus-> - if(sc->data[SC_LONGING].timer!=-1) - speed = speed * 100/sc->data[SC_LONGING].val3; - if(sc->data[SC_HIDING].timer!=-1 && sc->data[SC_HIDING].val3) - speed = speed * 100/sc->data[SC_HIDING].val3; - if(sc->data[SC_CHASEWALK].timer!=-1) - speed = speed * 100/sc->data[SC_CHASEWALK].val3; - if(sc->data[SC_GATLINGFEVER].timer!=-1) + if(sc->data[SC_LONGING]) + speed = speed * 100/sc->data[SC_LONGING]->val3; + if(sc->data[SC_HIDING] && sc->data[SC_HIDING]->val3) + speed = speed * 100/sc->data[SC_HIDING]->val3; + if(sc->data[SC_CHASEWALK]) + speed = speed * 100/sc->data[SC_CHASEWALK]->val3; + if(sc->data[SC_GATLINGFEVER]) speed = speed * 100/75; - if(sc->data[SC_SLOWDOWN].timer!=-1) + if(sc->data[SC_SLOWDOWN]) speed = speed * 100/75; return (short)cap_value(speed,10,USHRT_MAX); @@ -3762,45 +3771,45 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * if(!sc || !sc->count) return cap_value(aspd_rate,0,SHRT_MAX); - if(sc->data[SC_QUAGMIRE].timer==-1 && sc->data[SC_DONTFORGETME].timer==-1) + if(!sc->data[SC_QUAGMIRE] && !sc->data[SC_DONTFORGETME]) { int max = 0; - if(sc->data[SC_STAR_COMFORT].timer!=-1) - max = sc->data[SC_STAR_COMFORT].val2; + if(sc->data[SC_STAR_COMFORT]) + max = sc->data[SC_STAR_COMFORT]->val2; - if(sc->data[SC_TWOHANDQUICKEN].timer!=-1 && - max < sc->data[SC_TWOHANDQUICKEN].val2) - max = sc->data[SC_TWOHANDQUICKEN].val2; + if(sc->data[SC_TWOHANDQUICKEN] && + max < sc->data[SC_TWOHANDQUICKEN]->val2) + max = sc->data[SC_TWOHANDQUICKEN]->val2; - if(sc->data[SC_ONEHAND].timer!=-1 && - max < sc->data[SC_ONEHAND].val2) - max = sc->data[SC_ONEHAND].val2; + if(sc->data[SC_ONEHAND] && + max < sc->data[SC_ONEHAND]->val2) + max = sc->data[SC_ONEHAND]->val2; - if(sc->data[SC_ADRENALINE2].timer!=-1 && - max < sc->data[SC_ADRENALINE2].val3) - max = sc->data[SC_ADRENALINE2].val3; + if(sc->data[SC_ADRENALINE2] && + max < sc->data[SC_ADRENALINE2]->val3) + max = sc->data[SC_ADRENALINE2]->val3; - if(sc->data[SC_ADRENALINE].timer!=-1 && - max < sc->data[SC_ADRENALINE].val3) - max = sc->data[SC_ADRENALINE].val3; + if(sc->data[SC_ADRENALINE] && + max < sc->data[SC_ADRENALINE]->val3) + max = sc->data[SC_ADRENALINE]->val3; - if(sc->data[SC_SPEARQUICKEN].timer!=-1 && - max < sc->data[SC_SPEARQUICKEN].val2) - max = sc->data[SC_SPEARQUICKEN].val2; + if(sc->data[SC_SPEARQUICKEN] && + max < sc->data[SC_SPEARQUICKEN]->val2) + max = sc->data[SC_SPEARQUICKEN]->val2; - if(sc->data[SC_GATLINGFEVER].timer!=-1 && - max < sc->data[SC_GATLINGFEVER].val2) - max = sc->data[SC_GATLINGFEVER].val2; + if(sc->data[SC_GATLINGFEVER] && + max < sc->data[SC_GATLINGFEVER]->val2) + max = sc->data[SC_GATLINGFEVER]->val2; - if(sc->data[SC_FLEET].timer!=-1 && - max < sc->data[SC_FLEET].val2) - max = sc->data[SC_FLEET].val2; + if(sc->data[SC_FLEET] && + max < sc->data[SC_FLEET]->val2) + max = sc->data[SC_FLEET]->val2; - if(sc->data[SC_ASSNCROS].timer!=-1 && - max < sc->data[SC_ASSNCROS].val2) + if(sc->data[SC_ASSNCROS] && + max < sc->data[SC_ASSNCROS]->val2) { if (bl->type!=BL_PC) - max = sc->data[SC_ASSNCROS].val2; + max = sc->data[SC_ASSNCROS]->val2; else switch(((TBL_PC*)bl)->status.weapon) { @@ -3812,46 +3821,43 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * case W_GRENADE: break; default: - max = sc->data[SC_ASSNCROS].val2; + max = sc->data[SC_ASSNCROS]->val2; } } aspd_rate -= max; - //These stack with the rest of bonuses. - if(sc->data[SC_BERSERK].timer!=-1) + //These stack with the rest of bonuses-> + if(sc->data[SC_BERSERK]) aspd_rate -= 300; - else if(sc->data[SC_MADNESSCANCEL].timer!=-1) + else if(sc->data[SC_MADNESSCANCEL]) aspd_rate -= 200; } - if(sc->data[SC_INCASPDRATE].timer!=-1) - aspd_rate -= sc->data[SC_INCASPDRATE].val2; - if(sc->data[i=SC_ASPDPOTION3].timer!=-1 || - sc->data[i=SC_ASPDPOTION2].timer!=-1 || - sc->data[i=SC_ASPDPOTION1].timer!=-1 || - sc->data[i=SC_ASPDPOTION0].timer!=-1) - aspd_rate -= sc->data[i].val2; - if(sc->data[SC_DONTFORGETME].timer!=-1) - aspd_rate += sc->data[SC_DONTFORGETME].val2; - if(sc->data[SC_LONGING].timer!=-1) - aspd_rate += sc->data[SC_LONGING].val2; - if(sc->data[SC_STEELBODY].timer!=-1) + if(sc->data[SC_INCASPDRATE]) + aspd_rate -= sc->data[SC_INCASPDRATE]->val2; + if(sc->data[i=SC_ASPDPOTION3] || + sc->data[i=SC_ASPDPOTION2] || + sc->data[i=SC_ASPDPOTION1] || + sc->data[i=SC_ASPDPOTION0]) + aspd_rate -= sc->data[i]->val2; + if(sc->data[SC_DONTFORGETME]) + aspd_rate += sc->data[SC_DONTFORGETME]->val2; + if(sc->data[SC_LONGING]) + aspd_rate += sc->data[SC_LONGING]->val2; + if(sc->data[SC_STEELBODY]) aspd_rate += 250; - if(sc->data[SC_SKA].timer!=-1) + if(sc->data[SC_SKA]) aspd_rate += 250; - if(sc->data[SC_DEFENDER].timer != -1) - aspd_rate += sc->data[SC_DEFENDER].val4; - if(sc->data[SC_GOSPEL].timer!=-1 && sc->data[SC_GOSPEL].val4 == BCT_ENEMY) + if(sc->data[SC_DEFENDER]) + aspd_rate += sc->data[SC_DEFENDER]->val4; + if(sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) aspd_rate += 250; - if(sc->data[SC_GRAVITATION].timer!=-1) - aspd_rate += sc->data[SC_GRAVITATION].val2; -//Curse shouldn't effect on this? -// if(sc->data[SC_BLEEDING].timer != -1) -// aspd_rate += 250; - if(sc->data[SC_JOINTBEAT].timer!=-1) { - if( sc->data[SC_JOINTBEAT].val2&BREAK_WRIST ) + if(sc->data[SC_GRAVITATION]) + aspd_rate += sc->data[SC_GRAVITATION]->val2; + if(sc->data[SC_JOINTBEAT]) { + if( sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST ) aspd_rate += 250; - if( sc->data[SC_JOINTBEAT].val2&BREAK_KNEE ) + if( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ) aspd_rate += 100; } @@ -3863,11 +3869,11 @@ static unsigned short status_calc_dmotion(struct block_list *bl, struct status_c if(!sc || !sc->count || map_flag_gvg(bl->m)) return cap_value(dmotion,0,USHRT_MAX); - if (sc->data[SC_ENDURE].timer!=-1) + if (sc->data[SC_ENDURE]) return 0; - if (sc->data[SC_CONCENTRATION].timer!=-1) + if (sc->data[SC_CONCENTRATION]) return 0; - if(sc->data[SC_RUN].timer!=-1) + if(sc->data[SC_RUN]) return 0; return (unsigned short)cap_value(dmotion,0,USHRT_MAX); @@ -3878,13 +3884,13 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(maxhp,1,UINT_MAX); - if(sc->data[SC_INCMHPRATE].timer!=-1) - maxhp += maxhp * sc->data[SC_INCMHPRATE].val1/100; - if(sc->data[SC_APPLEIDUN].timer!=-1) - maxhp += maxhp * sc->data[SC_APPLEIDUN].val2/100; - if(sc->data[SC_DELUGE].timer!=-1) - maxhp += maxhp * sc->data[SC_DELUGE].val2/100; - if(sc->data[SC_BERSERK].timer!=-1) + if(sc->data[SC_INCMHPRATE]) + maxhp += maxhp * sc->data[SC_INCMHPRATE]->val1/100; + if(sc->data[SC_APPLEIDUN]) + maxhp += maxhp * sc->data[SC_APPLEIDUN]->val2/100; + if(sc->data[SC_DELUGE]) + maxhp += maxhp * sc->data[SC_DELUGE]->val2/100; + if(sc->data[SC_BERSERK]) maxhp += maxhp * 2; return cap_value(maxhp,1,UINT_MAX); @@ -3895,10 +3901,10 @@ static unsigned int status_calc_maxsp(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(maxsp,1,UINT_MAX); - if(sc->data[SC_INCMSPRATE].timer!=-1) - maxsp += maxsp * sc->data[SC_INCMSPRATE].val1/100; - if(sc->data[SC_SERVICE4U].timer!=-1) - maxsp += maxsp * sc->data[SC_SERVICE4U].val2/100; + if(sc->data[SC_INCMSPRATE]) + maxsp += maxsp * sc->data[SC_INCMSPRATE]->val1/100; + if(sc->data[SC_SERVICE4U]) + maxsp += maxsp * sc->data[SC_SERVICE4U]->val2/100; return cap_value(maxsp,1,UINT_MAX); } @@ -3907,16 +3913,17 @@ static unsigned char status_calc_element(struct block_list *bl, struct status_ch { if(!sc || !sc->count) return element; - if( sc->data[SC_FREEZE].timer!=-1 ) + + if(sc->data[SC_FREEZE]) return ELE_WATER; - if( sc->data[SC_STONE].timer!=-1 && sc->opt1 == OPT1_STONE) + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) return ELE_EARTH; - if( sc->data[SC_BENEDICTIO].timer!=-1 ) + if(sc->data[SC_BENEDICTIO]) return ELE_HOLY; - if( sc->data[SC_CHANGEUNDEAD].timer!=-1) + if(sc->data[SC_CHANGEUNDEAD]) return ELE_UNDEAD; - if( sc->data[SC_ELEMENTALCHANGE].timer!=-1) - return sc->data[SC_ELEMENTALCHANGE].val2; + if(sc->data[SC_ELEMENTALCHANGE]) + return sc->data[SC_ELEMENTALCHANGE]->val2; return (unsigned char)cap_value(element,0,UCHAR_MAX); } @@ -3924,16 +3931,18 @@ static unsigned char status_calc_element_lv(struct block_list *bl, struct status { if(!sc || !sc->count) return lv; - if( sc->data[SC_FREEZE].timer!=-1 ) + + if(sc->data[SC_FREEZE]) return 1; - if( sc->data[SC_STONE].timer!=-1 && sc->opt1 == OPT1_STONE) + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) return 1; - if( sc->data[SC_BENEDICTIO].timer!=-1 ) + if(sc->data[SC_BENEDICTIO]) return 1; - if( sc->data[SC_CHANGEUNDEAD].timer!=-1) + if(sc->data[SC_CHANGEUNDEAD]) return 1; - if(sc->data[SC_ELEMENTALCHANGE].timer!=-1) - return sc->data[SC_ELEMENTALCHANGE].val1; + if(sc->data[SC_ELEMENTALCHANGE]) + return sc->data[SC_ELEMENTALCHANGE]->val1; + return (unsigned char)cap_value(lv,1,4); } @@ -3942,23 +3951,23 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch { if(!sc || !sc->count) return element; - if( sc->data[SC_ENCHANTARMS].timer!=-1) - return sc->data[SC_ENCHANTARMS].val2; - if( sc->data[SC_WATERWEAPON].timer!=-1) + if(sc->data[SC_ENCHANTARMS]) + return sc->data[SC_ENCHANTARMS]->val2; + if(sc->data[SC_WATERWEAPON]) return ELE_WATER; - if( sc->data[SC_EARTHWEAPON].timer!=-1) + if(sc->data[SC_EARTHWEAPON]) return ELE_EARTH; - if( sc->data[SC_FIREWEAPON].timer!=-1) + if(sc->data[SC_FIREWEAPON]) return ELE_FIRE; - if( sc->data[SC_WINDWEAPON].timer!=-1) + if(sc->data[SC_WINDWEAPON]) return ELE_WIND; - if( sc->data[SC_ENCPOISON].timer!=-1) + if(sc->data[SC_ENCPOISON]) return ELE_POISON; - if( sc->data[SC_ASPERSIO].timer!=-1) + if(sc->data[SC_ASPERSIO]) return ELE_HOLY; - if( sc->data[SC_SHADOWWEAPON].timer!=-1) + if(sc->data[SC_SHADOWWEAPON]) return ELE_DARK; - if( sc->data[SC_GHOSTWEAPON].timer!=-1) + if(sc->data[SC_GHOSTWEAPON]) return ELE_GHOST; return (unsigned char)cap_value(element,0,UCHAR_MAX); } @@ -3967,13 +3976,13 @@ static unsigned short status_calc_mode(struct block_list *bl, struct status_chan { if(!sc || !sc->count) return mode; - if(sc->data[SC_MODECHANGE].timer!=-1) { - if (sc->data[SC_MODECHANGE].val2) - mode = sc->data[SC_MODECHANGE].val2; //Set mode - if (sc->data[SC_MODECHANGE].val3) - mode|= sc->data[SC_MODECHANGE].val3; //Add mode - if (sc->data[SC_MODECHANGE].val4) - mode&=~sc->data[SC_MODECHANGE].val4; //Del mode + if(sc->data[SC_MODECHANGE]) { + if (sc->data[SC_MODECHANGE]->val2) + mode = sc->data[SC_MODECHANGE]->val2; //Set mode + if (sc->data[SC_MODECHANGE]->val3) + mode|= sc->data[SC_MODECHANGE]->val3; //Add mode + if (sc->data[SC_MODECHANGE]->val4) + mode&=~sc->data[SC_MODECHANGE]->val4; //Del mode } return cap_value(mode,0,USHRT_MAX); } @@ -4252,7 +4261,7 @@ int status_isdead(struct block_list *bl) int status_isimmune(struct block_list *bl) { struct status_change *sc =status_get_sc(bl); - if (sc && sc->count && sc->data[SC_HERMODE].timer != -1) + if (sc && sc->data[SC_HERMODE]) return 100; if (bl->type == BL_PC && @@ -4407,11 +4416,8 @@ struct status_change *status_get_sc(struct block_list *bl) void status_change_init(struct block_list *bl) { struct status_change *sc = status_get_sc(bl); - int i; nullpo_retv(sc); memset(sc, 0, sizeof (struct status_change)); - for (i=0; i< SC_MAX; i++) - sc->data[i].timer = -1; } //Applies SC defense to a given status change. @@ -4542,10 +4548,10 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti sc = status_get_sc(bl); if (sc && sc->count) { - if (sc->data[SC_SCRESIST].timer != -1) - sc_def += sc->data[SC_SCRESIST].val1; //Status resist - else if (sc->data[SC_SIEGFRIED].timer != -1) - sc_def += sc->data[SC_SIEGFRIED].val3; //Status resistance. + if (sc->data[SC_SCRESIST]) + sc_def += sc->data[SC_SCRESIST]->val1; //Status resist + else if (sc->data[SC_SIEGFRIED]) + sc_def += sc->data[SC_SIEGFRIED]->val3; //Status resistance. } //When no tick def, reduction is the same for both. @@ -4594,6 +4600,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val { struct map_session_data *sd = NULL; struct status_change* sc; + struct status_change_entry* sce; struct status_data *status; struct view_data *vd; int opt_flag, calc_flag, undead_flag; @@ -4630,7 +4637,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } undead_flag = battle_check_undead(status->race,status->def_ele); - //Check for inmunities / sc fails switch (type) { @@ -4650,7 +4656,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; break; case SC_AETERNA: - if (sc->data[SC_STONE].timer != -1 || sc->data[SC_FREEZE].timer != -1) + if (sc->data[SC_STONE] || sc->data[SC_FREEZE]) return 0; break; case SC_KYRIE: @@ -4658,30 +4664,30 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; break; case SC_OVERTHRUST: - if (sc->data[SC_MAXOVERTHRUST].timer != -1) + if (sc->data[SC_MAXOVERTHRUST]) return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex] break; case SC_ADRENALINE: if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE))) return 0; - if (sc->data[SC_QUAGMIRE].timer!=-1 || - sc->data[SC_DONTFORGETME].timer!=-1 || - sc->data[SC_DECREASEAGI].timer!=-1 + if (sc->data[SC_QUAGMIRE] || + sc->data[SC_DONTFORGETME] || + sc->data[SC_DECREASEAGI] ) return 0; break; case SC_ADRENALINE2: if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE2))) return 0; - if (sc->data[SC_QUAGMIRE].timer!=-1 || - sc->data[SC_DONTFORGETME].timer!=-1 || - sc->data[SC_DECREASEAGI].timer!=-1 + if (sc->data[SC_QUAGMIRE] || + sc->data[SC_DONTFORGETME] || + sc->data[SC_DECREASEAGI] ) return 0; break; case SC_ONEHAND: case SC_TWOHANDQUICKEN: - if(sc->data[SC_DECREASEAGI].timer!=-1) + if(sc->data[SC_DECREASEAGI]) return 0; case SC_CONCENTRATE: case SC_INCREASEAGI: @@ -4690,15 +4696,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_WINDWALK: case SC_CARTBOOST: case SC_ASSNCROS: - if (sc->data[SC_QUAGMIRE].timer!=-1 || sc->data[SC_DONTFORGETME].timer!=-1) + if (sc->data[SC_QUAGMIRE] || sc->data[SC_DONTFORGETME]) return 0; break; case SC_CLOAKING: //Avoid cloaking with no wall and low skill level. [Skotlex] //Due to the cloaking card, we have to check the wall versus to known //skill level rather than the used one. [Skotlex] - //if (sd && val1 < 3 && skill_check_cloaking(bl)) - if (sd && pc_checkskill(sd, AS_CLOAKING)< 3 && skill_check_cloaking(bl,sc)) + //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) + if (sd && pc_checkskill(sd, AS_CLOAKING)< 3 && skill_check_cloaking(bl,NULL)) return 0; break; case SC_MODECHANGE: @@ -4706,17 +4712,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val int mode; struct status_data *bstatus = status_get_base_status(bl); if (!bstatus) return 0; - if (sc->data[type].timer != -1) + if (sc->data[type]) { //Pile up with previous values. - if(!val2) val2 = sc->data[type].val2; - val3 |= sc->data[type].val3; - val4 |= sc->data[type].val4; + if(!val2) val2 = sc->data[type]->val2; + val3 |= sc->data[type]->val3; + val4 |= sc->data[type]->val4; } mode = val2?val2:bstatus->mode; //Base mode if (val4) mode&=~val4; //Del mode if (val3) mode|= val3; //Add mode if (mode == bstatus->mode) { //No change. - if (sc->data[type].timer != -1) //Abort previous status + if (sc->data[type]) //Abort previous status return status_change_end(bl, type, -1); return 0; } @@ -4816,126 +4822,125 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val { case SC_BLESSING: if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) { - if (sc->data[SC_CURSE].timer!=-1) + if (sc->data[SC_CURSE]) status_change_end(bl,SC_CURSE,-1); - if (sc->data[SC_STONE].timer!=-1 && sc->opt1 == OPT1_STONE) + if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) status_change_end(bl,SC_STONE,-1); } break; case SC_INCREASEAGI: - if(sc->data[SC_DECREASEAGI].timer!=-1 ) + if(sc->data[SC_DECREASEAGI]) status_change_end(bl,SC_DECREASEAGI,-1); break; case SC_QUAGMIRE: - if(sc->data[SC_CONCENTRATE].timer!=-1 ) + if(sc->data[SC_CONCENTRATE]) status_change_end(bl,SC_CONCENTRATE,-1); - if(sc->data[SC_TRUESIGHT].timer!=-1 ) + if(sc->data[SC_TRUESIGHT]) status_change_end(bl,SC_TRUESIGHT,-1); - if(sc->data[SC_WINDWALK].timer!=-1 ) + if(sc->data[SC_WINDWALK]) status_change_end(bl,SC_WINDWALK,-1); //Also blocks the ones below... case SC_DECREASEAGI: - if(sc->data[SC_CARTBOOST].timer!=-1 ) + if(sc->data[SC_CARTBOOST]) status_change_end(bl,SC_CARTBOOST,-1); //Also blocks the ones below... case SC_DONTFORGETME: - if(sc->data[SC_INCREASEAGI].timer!=-1 ) + if(sc->data[SC_INCREASEAGI]) status_change_end(bl,SC_INCREASEAGI,-1); - if(sc->data[SC_ADRENALINE].timer!=-1 ) + if(sc->data[SC_ADRENALINE]) status_change_end(bl,SC_ADRENALINE,-1); - if(sc->data[SC_ADRENALINE2].timer!=-1 ) + if(sc->data[SC_ADRENALINE2]) status_change_end(bl,SC_ADRENALINE2,-1); - if(sc->data[SC_SPEARQUICKEN].timer!=-1 ) + if(sc->data[SC_SPEARQUICKEN]) status_change_end(bl,SC_SPEARQUICKEN,-1); - if(sc->data[SC_TWOHANDQUICKEN].timer!=-1 ) + if(sc->data[SC_TWOHANDQUICKEN]) status_change_end(bl,SC_TWOHANDQUICKEN,-1); - if(sc->data[SC_ONEHAND].timer!=-1 ) + if(sc->data[SC_ONEHAND]) status_change_end(bl,SC_ONEHAND,-1); break; case SC_ONEHAND: //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] - if(sc->data[SC_ASPDPOTION0].timer!=-1) + if(sc->data[SC_ASPDPOTION0]) status_change_end(bl,SC_ASPDPOTION0,-1); - if(sc->data[SC_ASPDPOTION1].timer!=-1) + if(sc->data[SC_ASPDPOTION1]) status_change_end(bl,SC_ASPDPOTION1,-1); - if(sc->data[SC_ASPDPOTION2].timer!=-1) + if(sc->data[SC_ASPDPOTION2]) status_change_end(bl,SC_ASPDPOTION2,-1); - if(sc->data[SC_ASPDPOTION3].timer!=-1) + if(sc->data[SC_ASPDPOTION3]) status_change_end(bl,SC_ASPDPOTION3,-1); break; case SC_MAXOVERTHRUST: //Cancels Normal Overthrust. [Skotlex] - if (sc->data[SC_OVERTHRUST].timer != -1) + if (sc->data[SC_OVERTHRUST]) status_change_end(bl, SC_OVERTHRUST, -1); break; case SC_KYRIE: // -- moonsoul (added to undo assumptio status if target has it) - if(sc->data[SC_ASSUMPTIO].timer!=-1 ) + if(sc->data[SC_ASSUMPTIO]) status_change_end(bl,SC_ASSUMPTIO,-1); break; case SC_DELUGE: - if (sc->data[SC_FOGWALL].timer != -1 && sc->data[SC_BLIND].timer != -1) + if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) status_change_end(bl,SC_BLIND,-1); break; case SC_SILENCE: - if (sc->data[SC_GOSPEL].timer!=-1 && sc->data[SC_GOSPEL].val4 == BCT_SELF) + if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) status_change_end(bl,SC_GOSPEL,-1); break; case SC_HIDING: - if(sc->data[SC_CLOSECONFINE].timer != -1) + if(sc->data[SC_CLOSECONFINE]) status_change_end(bl, SC_CLOSECONFINE, -1); - if(sc->data[SC_CLOSECONFINE2].timer != -1) + if(sc->data[SC_CLOSECONFINE2]) status_change_end(bl, SC_CLOSECONFINE2, -1); break; case SC_BERSERK: if(battle_config.berserk_cancels_buffs) { - if (sc->data[SC_ONEHAND].timer != -1) + if (sc->data[SC_ONEHAND]) status_change_end(bl,SC_ONEHAND,-1); - if (sc->data[SC_TWOHANDQUICKEN].timer != -1) + if (sc->data[SC_TWOHANDQUICKEN]) status_change_end(bl,SC_TWOHANDQUICKEN,-1); - if (sc->data[SC_CONCENTRATION].timer != -1) + if (sc->data[SC_CONCENTRATION]) status_change_end(bl,SC_CONCENTRATION,-1); - if (sc->data[SC_PARRYING].timer != -1) + if (sc->data[SC_PARRYING]) status_change_end(bl,SC_PARRYING,-1); - if (sc->data[SC_AURABLADE].timer != -1) + if (sc->data[SC_AURABLADE]) status_change_end(bl,SC_AURABLADE,-1); } break; case SC_ASSUMPTIO: - if(sc->data[SC_KYRIE].timer!=-1) + if(sc->data[SC_KYRIE]) status_change_end(bl,SC_KYRIE,-1); - if(sc->data[SC_KAITE].timer!=-1) + if(sc->data[SC_KAITE]) status_change_end(bl,SC_KAITE,-1); break; case SC_KAITE: - if(sc->data[SC_ASSUMPTIO].timer!=-1 ) + if(sc->data[SC_ASSUMPTIO]) status_change_end(bl,SC_ASSUMPTIO,-1); break; - case SC_CARTBOOST: - if(sc->data[SC_DECREASEAGI].timer!=-1 ) + if(sc->data[SC_DECREASEAGI]) { //Cancel Decrease Agi, but take no further effect [Skotlex] status_change_end(bl,SC_DECREASEAGI,-1); return 0; } break; case SC_FUSION: - if(sc->data[SC_SPIRIT].timer!=-1 ) + if(sc->data[SC_SPIRIT]) status_change_end(bl,SC_SPIRIT,-1); break; case SC_ADJUSTMENT: - if(sc->data[SC_MADNESSCANCEL].timer != -1) + if(sc->data[SC_MADNESSCANCEL]) status_change_end(bl,SC_MADNESSCANCEL,-1); break; case SC_MADNESSCANCEL: - if(sc->data[SC_ADJUSTMENT].timer!=-1) + if(sc->data[SC_ADJUSTMENT]) status_change_end(bl,SC_ADJUSTMENT,-1); break; } //Check for overlapping fails - if(sc->data[type].timer != -1) + if((sce=sc->data[type])) { switch (type) { @@ -4943,7 +4948,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_ADRENALINE2: case SC_WEAPONPERFECTION: case SC_OVERTHRUST: - if (sc->data[type].val2 > val2) + if (sce->val2 > val2) return 0; break; case SC_HPREGEN: @@ -4976,44 +4981,50 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_GOSPEL: //Must not override a casting gospel char. - if(sc->data[type].val4 == BCT_SELF) + if(sce->val4 == BCT_SELF) return 0; - if(sc->data[type].val1 > val1) + if(sce->val1 > val1) return 1; break; case SC_ENDURE: - if(sc->data[type].val4 && !val4) + if(sce->val4 && !val4) return 1; //Don't let you override infinite endure. - if(sc->data[type].val1 > val1) + if(sce->val1 > val1) return 1; break; case SC_KAAHI: - if(sc->data[type].val1 > val1) + if(sce->val1 > val1) return 1; //Delete timer if it exists. - if (sc->data[type].val4 != -1) { - delete_timer(sc->data[type].val4,kaahi_heal_timer); - sc->data[type].val4=-1; + if (sce->val4 != -1) { + delete_timer(sce->val4,kaahi_heal_timer); + sce->val4=-1; } break; case SC_JAILED: //When a player is already jailed, do not edit the jail data. - val2 = sc->data[type].val2; - val3 = sc->data[type].val3; - val4 = sc->data[type].val4; + val2 = sce->val2; + val3 = sce->val3; + val4 = sce->val4; break; + case SC_JOINTBEAT: + val2 |= sce->val2; // stackable ailments default: - if(sc->data[type].val1 > val1) + if(sce->val1 > val1) return 1; //Return true to not mess up skill animations. [Skotlex } (sc->count)--; - delete_timer(sc->data[type].timer, status_change_timer); - sc->data[type].timer = -1; + if (sce->timer != -1) + delete_timer(sce->timer, status_change_timer); + sce->timer = -1; } + //NOTE: avoiding returning after this point, or if you must return a failure, use this to properly cleanup any existing data. +#define sc_start_abort(ret) { \ + if (sce) { ers_free(sc_data_ers, sce); sc->data[type] = NULL; } \ + return ret; } vd = status_get_viewdata(bl); calc_flag = StatusChangeFlagTable[type]; - if(!(flag&4)) //&4 - Do not parse val settings when loading SCs switch(type) { @@ -5034,15 +5045,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } } //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) + if(val4) + tick = -1; break; case SC_AUTOBERSERK: if (status->hp < status->max_hp>>2 && - (sc->data[SC_PROVOKE].timer==-1 || sc->data[SC_PROVOKE].val2==0)) + (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); + tick = -1; break; - case SC_SIGNUMCRUCIS: val2 = 10 + 4*val1; //Def reduction + tick = -1; clif_emotion(bl,4); break; case SC_MAXIMIZEPOWER: @@ -5066,11 +5080,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_MAGICPOWER: //val1: Skill lv val2 = 1; //Lasts 1 invocation - //val3 will store matk_min (needed in case you use ground-spells) - //val4 will store matk_max + val3 = 5*val1; //Matk% increase + tick = -1; break; case SC_SACRIFICE: val2 = 5; //Lasts 5 hits + tick = -1; break; case SC_ENCPOISON: val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate @@ -5180,7 +5195,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = 0; //Tick duration/Speed penalty. if (sd) { //Store walk speed change in lower part of val3 val3 = 500-40*pc_checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON)); - if (sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_BARDDANCER) + if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER) val3 -= 40; //TODO: Figure out real bonus rate. } val3|= ((tick/1000)<<16)&0xFFFF0000; //Store tick in upper part of val3 @@ -5203,7 +5218,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_WEDDING: case SC_XMAS: case SC_SUMMER: - if (!vd) return 0; + if (!vd) sc_start_abort(0); //Store previous values as they could be removed. val1 = vd->class_; val2 = vd->weapon; @@ -5279,7 +5294,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CHASEWALK: val2 = tick>0?tick:10000; //Interval at which SP is drained. val3 = 65+val1*5; //Speed adjustment. - if (sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_ROGUE) + if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE) val3 += 60; val4 = 10+val1*2; //SP cost. if (map_flag_gvg(bl->m)) val4 *= 5; @@ -5311,17 +5326,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; //Permanent effects. + case SC_AETERNA: case SC_MODECHANGE: case SC_WEIGHT50: case SC_WEIGHT90: case SC_BROKENWEAPON: case SC_BROKENARMOR: - case SC_READYSTORM: // Taekwon stances SCs [Dralnu] + case SC_READYSTORM: case SC_READYDOWN: case SC_READYCOUNTER: case SC_READYTURN: case SC_DODGE: - tick = 600*1000; + tick = -1; break; case SC_AUTOGUARD: @@ -5382,11 +5398,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_JOINTBEAT: if( val2&BREAK_NECK ) sc_start(bl,SC_BLEEDING,100,val1,skill_get_time2(StatusSkillChangeTable[type],val1)); - val2 |= sc->data[SC_JOINTBEAT].val2; // stackable ailments break; case SC_BERSERK: - if (sc->data[SC_ENDURE].timer == -1 || !sc->data[SC_ENDURE].val4) + if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); //HP healing is performing after the calc_status call. //Val2 holds HP penalty @@ -5434,7 +5449,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } else { struct status_data *b_status = status_get_base_status(bl); if (!b_status) - return 0; + sc_start_abort(0); val3 = 0; val2 = b_status->str>>1; @@ -5469,74 +5484,75 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val { struct block_list *pbl = map_id2bl(val1); struct status_change *psc = pbl?status_get_sc(pbl):NULL; + struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE]:NULL; int stat,max; - if (!psc || psc->data[SC_MARIONETTE].timer == -1) - return 0; + if (!psce) + sc_start_abort(0); val2 = tick /1000; val3 = val4 = 0; if (sd) { max = pc_maxparameter(sd); //Cap to max parameter. [Skotlex] //Str - stat = (psc->data[SC_MARIONETTE].val3>>16)&0xFF; + stat = (psce->val3>>16)&0xFF; if (sd->status.str+stat > max) stat =max-sd->status.str; val3 |= stat<<16; //Agi - stat = (psc->data[SC_MARIONETTE].val3>>8)&0xFF; + stat = (psce->val3>>8)&0xFF; if (sd->status.agi+stat > max) stat =max-sd->status.agi; val3 |= stat<<8; //Vit - stat = psc->data[SC_MARIONETTE].val3&0xFF; + stat = psce->val3&0xFF; if (sd->status.vit+stat > max) stat =max-sd->status.vit; val3 |= stat; //Int - stat = (psc->data[SC_MARIONETTE].val4>>16)&0xFF; + stat = (psce->val4>>16)&0xFF; if (sd->status.int_+stat > max) stat =max-sd->status.int_; val4 |= stat<<16; //Dex - stat = (psc->data[SC_MARIONETTE].val4>>8)&0xFF; + stat = (psce->val4>>8)&0xFF; if (sd->status.dex+stat > max) stat =max-sd->status.dex; val4 |= stat<<8; //Luk - stat = psc->data[SC_MARIONETTE].val4&0xFF; + stat = psce->val4&0xFF; if (sd->status.luk+stat > max) stat =max-sd->status.luk; val4 |= stat; } else { struct status_data *b_status = status_get_base_status(bl); - if (!b_status) return 0; + if (!b_status) sc_start_abort(0); max = 0xFF; //Assume a 256 max parameter //Str - stat = (psc->data[SC_MARIONETTE].val3>>16)&0xFF; + stat = (psce->val3>>16)&0xFF; if (b_status->str+stat > max) stat = max - b_status->str; val3 |= stat<<16; //Agi - stat = (psc->data[SC_MARIONETTE].val3>>8)&0xFF; + stat = (psce->val3>>8)&0xFF; if (b_status->agi+stat > max) stat = max - b_status->agi; val3 |= stat<<8; //Vit - stat = psc->data[SC_MARIONETTE].val3&0xFF; + stat = psce->val3&0xFF; if (b_status->vit+stat > max) stat = max - b_status->vit; val3 |= stat; //Int - stat = (psc->data[SC_MARIONETTE].val4>>16)&0xFF; + stat = (psce->val4>>16)&0xFF; if (b_status->int_+stat > max) stat = max - b_status->int_; val4 |= stat<<16; //Dex - stat = (psc->data[SC_MARIONETTE].val4>>8)&0xFF; + stat = (psce->val4>>8)&0xFF; if (b_status->dex+stat > max) stat = max - b_status->dex; val4 |= stat<<8; //Luk - stat = psc->data[SC_MARIONETTE].val4&0xFF; + stat = psce->val4&0xFF; if (b_status->luk+stat > max) stat = max - b_status->luk; val4 |= stat; @@ -5547,10 +5563,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_REJECTSWORD: val2 = 15*val1; //Reflect chance val3 = 3; //Reflections + tick = -1; break; case SC_MEMORIZE: val2 = 5; //Memorized casts. + tick = -1; break; case SC_GRAVITATION: @@ -5582,9 +5600,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val int i = map_flag_gvg(bl->m)?2:3; while (i >= 0) { type2 = types[i]; - if (src->sc.data[type2].timer != -1) - sc_start(bl,type2,100,src->sc.data[type2].val1, - skill_get_time(StatusSkillChangeTable[type2],src->sc.data[type2].val1)); + if (src->sc.data[type2]) + sc_start(bl,type2,100,src->sc.data[type2]->val1, + skill_get_time(StatusSkillChangeTable[type2],src->sc.data[type2]->val1)); i--; } } @@ -5593,22 +5611,23 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp status_zap(bl, status->hp-1, val2?0:status->sp); - return 1; - + sc_start_abort(1); + break; case SC_CLOSECONFINE2: { struct block_list *src = val2?map_id2bl(val2):NULL; struct status_change *sc2 = src?status_get_sc(src):NULL; + struct status_change_entry *sce2 = sc2?sc2->data[SC_CLOSECONFINE]:NULL; if (src && sc2) { - if (sc2->data[SC_CLOSECONFINE].timer == -1) //Start lock on caster. - sc_start4(src,SC_CLOSECONFINE,100,sc->data[type].val1,1,0,0,tick+1000); + if (!sce2) //Start lock on caster. + sc_start4(src,SC_CLOSECONFINE,100,val1,1,0,0,tick+1000); else { //Increase count of locked enemies and refresh time. - sc2->data[SC_CLOSECONFINE].val2++; - delete_timer(sc2->data[SC_CLOSECONFINE].timer, status_change_timer); - sc2->data[SC_CLOSECONFINE].timer = add_timer(gettick()+tick+1000, status_change_timer, src->id, SC_CLOSECONFINE); + (sce2->val2)++; + delete_timer(sce2->timer, status_change_timer); + sce2->timer = add_timer(gettick()+tick+1000, status_change_timer, src->id, SC_CLOSECONFINE); } } else //Status failed. - return 0; + sc_start_abort(0); } break; case SC_KAITE: @@ -5664,6 +5683,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_RUN: val4 = gettick(); //Store time at which you started running. + tick = -1; break; case SC_KAAHI: val2 = 200*val1; //HP heal @@ -5678,6 +5698,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_TRICKDEAD: if (vd) vd->dead_sit = 1; + tick = -1; break; case SC_CONCENTRATE: val2 = 2 + val1; @@ -5688,11 +5709,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = val4 = 0; } break; + case SC_MAXOVERTHRUST: + val2 = 20*val1; //Power increase + break; + case SC_OVERTHRUST: + val2 = 5*val1; //Power increase + if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; case SC_ADRENALINE2: case SC_ADRENALINE: val3 = (val2) ? 300 : 200; // aspd increase case SC_WEAPONPERFECTION: - case SC_OVERTHRUST: if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) tick += tick / 10; break; @@ -5859,20 +5887,29 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_SUFFRAGIUM: val2 = 15 * val1; //Speed cast decrease break; + case SC_INCHEALRATE: + if (val1 < 1) + val1 = 1; + break; + case SC_HALLUCINATION: + val2 = 5+val1; //Factor by which displayed damage is increased by + break; + case SC_DOUBLECAST: + val2 = 40+10*val1; //Trigger rate + break; + case SC_KAIZEL: + val2 = 10*val1; //% of life to be revived with + break; case SC_ARMOR_ELEMENT: case SC_FASTCAST: //Place here SCs that have no SCB_* data, no skill associated, no ICON //associated, and yet are not wrong/unknown. [Skotlex] break; - case SC_INCHEALRATE: - if (val1 < 1) - val1 = 1; - break; default: if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) { //Status change with no calc, no icon, and no skill associated...? ShowError("UnknownStatusChange [%d]\n", type); - return 0; + sc_start_abort(0); } } else //Special considerations when loading SC data. @@ -5896,8 +5933,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_HIDING: case SC_CHASEWALK: case SC_DEFENDER: - if (!val3) - return 0; + if (!val3) val3 = 100; break; } @@ -6078,12 +6114,16 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val (sc->count)++; - sc->data[type].val1 = val1; - sc->data[type].val2 = val2; - sc->data[type].val3 = val3; - sc->data[type].val4 = val4; - - sc->data[type].timer = add_timer(gettick() + tick, status_change_timer, bl->id, type); + if (!sce) //Not null when overwriting existing sc. + sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry); + sce->val1 = val1; + sce->val2 = val2; + sce->val3 = val3; + sce->val4 = val4; + if (tick >= 0) + sce->timer = add_timer(gettick() + tick, status_change_timer, bl->id, type); + else + sce->timer = -1; //Infinite duration if (calc_flag) status_calc_bl(bl,calc_flag); @@ -6092,19 +6132,19 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing if (type==SC_BERSERK) { - sc->data[type].val2 = 5*status->max_hp/100; + sce->val2 = 5*status->max_hp/100; status_heal(bl, status->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. status_set_sp(bl, 0, 0); //Damage all SP } else if (type==SC_CHANGE) //Heal all HP/SP status_percent_heal(bl, 100, 100); - if (type==SC_RUN) { struct unit_data *ud = unit_bl2ud(bl); if (ud) ud->state.running = unit_run(bl); } return 1; +#undef sc_start_abort } /*========================================== * ステータス異常全解除 @@ -6123,12 +6163,12 @@ int status_change_clear(struct block_list* bl, int type) if (!sc || !sc->count) return 0; - if(sc->data[SC_DANCING].timer != -1) + if(sc->data[SC_DANCING]) skill_stop_dancing(bl); for(i = 0; i < SC_MAX; i++) { - if(sc->data[i].timer == -1) + if(!sc->data[i]) continue; if(type == 0) @@ -6152,11 +6192,13 @@ int status_change_clear(struct block_list* bl, int type) status_change_end(bl, i, INVALID_TIMER); - if( type == 1 && sc->data[i].timer != INVALID_TIMER ) + if( type == 1 && sc->data[i] ) { //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex] (sc->count)--; - delete_timer(sc->data[i].timer, status_change_timer); - sc->data[i].timer = -1; + if (sc->data[i]->timer != INVALID_TIMER) + delete_timer(sc->data[i]->timer, status_change_timer); + ers_free(sc_data_ers, sc->data[i]); + sc->data[i] = NULL; } } @@ -6178,6 +6220,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) { struct map_session_data *sd; struct status_change *sc; + struct status_change_entry *sce; struct status_data *status; struct view_data *vd; int opt_flag=0, calc_flag; @@ -6189,39 +6232,42 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) nullpo_retr(0,sc); nullpo_retr(0,status); - if(type < 0 || type >= SC_MAX) + if(type < 0 || type >= SC_MAX || !(sce = sc->data[type])) return 0; BL_CAST(BL_PC,bl,sd); - if (sc->data[type].timer == -1 || - (sc->data[type].timer != tid && tid != -1)) + if (sce->timer != tid && tid != -1) return 0; - + if (tid == -1) { - delete_timer(sc->data[type].timer,status_change_timer); + if (type == SC_ENDURE && sce->val4) + //Do not end infinite endure. + return 0; + if (sce->timer != -1) //Could be a SC with infinite duration + delete_timer(sce->timer,status_change_timer); if (sc->opt1) switch (type) { //"Ugly workaround" [Skotlex] //delays status change ending so that a skill that sets opt1 fails to //trigger when it also removed one case SC_STONE: - sc->data[type].val3 = 0; //Petrify time counter. + sce->val3 = 0; //Petrify time counter. case SC_FREEZE: case SC_STUN: case SC_SLEEP: - if (sc->data[type].val1) { + if (sce->val1) { //Removing the 'level' shouldn't affect anything in the code //since these SC are not affected by it, and it lets us know //if we have already delayed this attack or not. - sc->data[type].val1 = 0; - sc->data[type].timer = add_timer(gettick()+10, status_change_timer, bl->id, type); + sce->val1 = 0; + sce->timer = add_timer(gettick()+10, status_change_timer, bl->id, type); return 1; } } } - sc->data[type].timer=-1; + sc->data[type] = NULL; (sc->count)--; vd = status_get_viewdata(bl); @@ -6230,7 +6276,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) case SC_WEDDING: case SC_XMAS: case SC_SUMMER: - if (!vd) return 0; + if (!vd) break; if (sd) { //Load data from sd->status.* as the stored values could have changed. //Must remove OPTION to prevent class being rechanged. @@ -6238,10 +6284,10 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) clif_changeoption(&sd->bl); status_set_viewdata(bl, sd->status.class_); } else { - vd->class_ = sc->data[type].val1; - vd->weapon = sc->data[type].val2; - vd->shield = sc->data[type].val3; - vd->cloth_color = sc->data[type].val4; + vd->class_ = sce->val1; + vd->weapon = sce->val2; + vd->shield = sce->val3; + vd->cloth_color = sce->val4; } clif_changelook(bl,LOOK_BASE,vd->class_); clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); @@ -6256,21 +6302,19 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) if (ud->walktimer != -1) unit_stop_walking(bl,1); } - if (sc->data[type].val1 >= 7 && - DIFF_TICK(gettick(), sc->data[type].val4) <= 1000 && + if (sce->val1 >= 7 && + DIFF_TICK(gettick(), sce->val4) <= 1000 && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) ) - sc_start(bl,SC_SPURT,100,sc->data[type].val1,skill_get_time2(StatusSkillChangeTable[type], sc->data[type].val1)); + sc_start(bl,SC_SPURT,100,sce->val1,skill_get_time2(StatusSkillChangeTable[type], sce->val1)); } break; case SC_AUTOBERSERK: - if (sc->data[SC_PROVOKE].timer != -1 && sc->data[SC_PROVOKE].val2 == 1) + if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->val2 == 1) status_change_end(bl,SC_PROVOKE,-1); break; case SC_ENDURE: - if (sc->data[SC_ENDURE].val4) - return 0; //Do not end infinite endure. case SC_DEFENDER: case SC_REFLECTSHIELD: case SC_AUTOGUARD: @@ -6279,40 +6323,40 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) int i; for (i = 0; i < 5; i++) { //Clear the status from the others too [Skotlex] - if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type].timer != -1) + if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type]) status_change_end(&tsd->bl,type,-1); } } break; case SC_DEVOTION: { - struct map_session_data *md = map_id2sd(sc->data[type].val1); + struct map_session_data *md = map_id2sd(sce->val1); //The status could have changed because the Crusader left the game. [Skotlex] if (md) { - md->devotion[sc->data[type].val2] = 0; + md->devotion[sce->val2] = 0; clif_devotion(md); } //Remove inherited status [Skotlex] - if (sc->data[SC_AUTOGUARD].timer != -1) + if (sc->data[SC_AUTOGUARD]) status_change_end(bl,SC_AUTOGUARD,-1); - if (sc->data[SC_DEFENDER].timer != -1) + if (sc->data[SC_DEFENDER]) status_change_end(bl,SC_DEFENDER,-1); - if (sc->data[SC_REFLECTSHIELD].timer != -1) + if (sc->data[SC_REFLECTSHIELD]) status_change_end(bl,SC_REFLECTSHIELD,-1); - if (sc->data[SC_ENDURE].timer != -1) + if (sc->data[SC_ENDURE]) status_change_end(bl,SC_ENDURE,-1); break; } case SC_BLADESTOP: - if(sc->data[type].val4) + if(sce->val4) { - struct block_list *tbl = (struct block_list *)sc->data[type].val4; + struct block_list *tbl = (struct block_list *)sce->val4; struct status_change *tsc = status_get_sc(tbl); - sc->data[type].val4 = 0; - if(tsc && tsc->data[SC_BLADESTOP].timer!=-1) + sce->val4 = 0; + if(tsc && tsc->data[SC_BLADESTOP]) { - tsc->data[SC_BLADESTOP].val4 = 0; + tsc->data[SC_BLADESTOP]->val4 = 0; status_change_end(tbl,SC_BLADESTOP,-1); } clif_bladestop(bl,tbl,0); @@ -6321,27 +6365,27 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) case SC_DANCING: { struct map_session_data *dsd; - struct status_change *dsc; + struct status_change_entry *dsc; struct skill_unit_group *group; - if(sc->data[type].val2) + if(sce->val2) { - group = (struct skill_unit_group *)sc->data[type].val2; - sc->data[type].val2 = 0; + group = (struct skill_unit_group *)sce->val2; + sce->val2 = 0; skill_delunitgroup(bl, group); } - if(sc->data[type].val4 && sc->data[type].val4 != BCT_SELF && (dsd=map_id2sd(sc->data[type].val4))){ - dsc = &dsd->sc; - if(dsc && dsc->data[type].timer!=-1) + if(sce->val4 && sce->val4 != BCT_SELF && (dsd=map_id2sd(sce->val4))){ + dsc = dsd->sc.data[type]; + if(dsc) { //This will prevent recursive loops. - dsc->data[type].val2 = dsc->data[type].val4 = 0; + dsc->val2 = dsc->val4 = 0; status_change_end(&dsd->bl, type, -1); } } } - if ((sc->data[type].val1&0xFFFF) == CG_MOONLIT) + if ((sce->val1&0xFFFF) == CG_MOONLIT) clif_status_change(bl,SI_MOONLIT,0); - if (sc->data[SC_LONGING].timer!=-1) + if (sc->data[SC_LONGING]) status_change_end(bl,SC_LONGING,-1); break; case SC_NOCHAT: @@ -6350,54 +6394,48 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) break; case SC_SPLASHER: { - struct block_list *src=map_id2bl(sc->data[type].val3); + struct block_list *src=map_id2bl(sce->val3); if(src && tid!=-1) - skill_castend_damage_id(src, bl, sc->data[type].val2, sc->data[type].val1, gettick(), SD_LEVEL ); + skill_castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL ); } break; case SC_CLOSECONFINE2: { - struct block_list *src = sc->data[type].val2?map_id2bl(sc->data[type].val2):NULL; + struct block_list *src = sce->val2?map_id2bl(sce->val2):NULL; struct status_change *sc2 = src?status_get_sc(src):NULL; - if (src && sc2 && sc2->count) { + if (src && sc2 && sc2->data[SC_CLOSECONFINE]) { //If status was already ended, do nothing. - if (sc2->data[SC_CLOSECONFINE].timer != -1) - { //Decrease count - if (--sc2->data[SC_CLOSECONFINE].val1 <= 0) //No more holds, free him up. - status_change_end(src, SC_CLOSECONFINE, -1); - } + //Decrease count + if (--(sc2->data[SC_CLOSECONFINE]->val1) <= 0) //No more holds, free him up. + status_change_end(src, SC_CLOSECONFINE, -1); } } case SC_CLOSECONFINE: - if (sc->data[type].val2 > 0) { + if (sce->val2 > 0) { //Caster has been unlocked... nearby chars need to be unlocked. int range = 1 - +skill_get_range2(bl, StatusSkillChangeTable[type], sc->data[type].val1) + +skill_get_range2(bl, StatusSkillChangeTable[type], sce->val1) +skill_get_range2(bl, TF_BACKSLIDING, 1); //Since most people use this to escape the hold.... map_foreachinarea(status_change_timer_sub, - bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sc,type,gettick()); + bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,gettick()); } break; case SC_COMBO: //Clear last used skill when it is part of a combo. - if (sd && sd->skillid_old == sc->data[type].val1) + if (sd && sd->skillid_old == sce->val1) sd->skillid_old = sd->skilllv_old = 0; break; - case SC_FREEZE: - sc->data[type].val3 = 0; //Clear Storm Gust hit count - break; - case SC_MARIONETTE: case SC_MARIONETTE2: /// Marionette target - if (sc->data[type].val1) + if (sce->val1) { // check for partner and end their marionette status as well int type2 = (type == SC_MARIONETTE) ? SC_MARIONETTE2 : SC_MARIONETTE; - struct block_list *pbl = map_id2bl(sc->data[type].val1); + struct block_list *pbl = map_id2bl(sce->val1); struct status_change* sc2 = pbl?status_get_sc(pbl):NULL; - if (sc2 && sc2->count && sc2->data[type2].timer != -1) + if (sc2 && sc2->data[type2]) { - sc2->data[type2].val1 = 0; + sc2->data[type2]->val1 = 0; status_change_end(pbl, type2, -1); } } @@ -6407,25 +6445,25 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) case SC_BERSERK: //If val2 is removed, no HP penalty (dispelled?) [Skotlex] - if(status->hp > 100 && sc->data[type].val2) + if(status->hp > 100 && sce->val2) status_set_hp(bl, 100, 0); - if(sc->data[SC_ENDURE].timer != -1 && sc->data[SC_ENDURE].val4 == 2) + if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) { - sc->data[SC_ENDURE].val4 = 0; + sc->data[SC_ENDURE]->val4 = 0; status_change_end(bl, SC_ENDURE, -1); } sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), - skill_get_time(LK_BERSERK, sc->data[type].val1)); + skill_get_time(LK_BERSERK, sce->val1)); break; case SC_GOSPEL: - if (sc->data[type].val3) { //Clear the group. - struct skill_unit_group *group = (struct skill_unit_group *)sc->data[type].val3; - sc->data[type].val3 = 0; + if (sce->val3) { //Clear the group. + struct skill_unit_group *group = (struct skill_unit_group *)sce->val3; + sce->val3 = 0; skill_delunitgroup(bl, group); } break; case SC_HERMODE: - if(sc->data[type].val3 == BCT_SELF) + if(sce->val3 == BCT_SELF) skill_clear_unitgroup(bl); break; case SC_BASILICA: //Clear the skill area. [Skotlex] @@ -6435,25 +6473,23 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) if (vd) vd->dead_sit = 0; break; case SC_WARM: - if (sc->data[type].val4) { //Clear the group. - struct skill_unit_group *group = (struct skill_unit_group *)sc->data[type].val4; - sc->data[type].val4 = 0; + if (sce->val4) { //Clear the group. + struct skill_unit_group *group = (struct skill_unit_group *)sce->val4; + sce->val4 = 0; skill_delunitgroup(bl, group); } break; case SC_KAAHI: //Delete timer if it exists. - if (sc->data[type].val4 != -1) { - delete_timer(sc->data[type].val4,kaahi_heal_timer); - sc->data[type].val4=-1; - } + if (sce->val4 != -1) + delete_timer(sce->val4,kaahi_heal_timer); break; case SC_JAILED: if(tid == -1) break; //natural expiration. - if(sd && sd->mapindex == sc->data[type].val2) - pc_setpos(sd,(unsigned short)sc->data[type].val3,sc->data[type].val4&0xFFFF, sc->data[type].val4>>16, 3); + if(sd && sd->mapindex == sce->val2) + pc_setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, 3); break; //guess hes not in jail :P case SC_CHANGE: if (tid == -1) @@ -6462,9 +6498,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) status_set_hp(bl, 10, 0); status_set_sp(bl, 10, 0); break; - case SC_JOINTBEAT: - sc->data[type].val2 = 0; // Clear stackable ailments - break; } opt_flag = 1; @@ -6584,8 +6617,8 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) if (calc_flag&SCB_DYE) { //Restore DYE color - if (vd && !vd->cloth_color && sc->data[type].val4) - clif_changelook(bl,LOOK_CLOTHES_COLOR,sc->data[type].val4); + if (vd && !vd->cloth_color && sce->val4) + clif_changelook(bl,LOOK_CLOTHES_COLOR,sce->val4); calc_flag&=~SCB_DYE; } @@ -6607,6 +6640,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) if(opt_flag&2 && sd && map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) npc_touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. + ers_free(sc_data_ers, sce); return 1; } @@ -6614,6 +6648,7 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, int data) { struct block_list *bl; struct status_change *sc; + struct status_change_entry *sce; struct status_data *status; int hp; @@ -6621,25 +6656,26 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, int data) sc=status_get_sc(bl); status=status_get_status_data(bl); - if (!sc || !status || data != SC_KAAHI || sc->data[data].timer==-1) + if (!(sc && status && data == SC_KAAHI && sc->data[data])) return 0; - if(sc->data[data].val4 != tid) { - ShowError("kaahi_heal_timer: Timer mismatch: %d != %d\n", tid, sc->data[data].val4); - sc->data[data].val4=-1; + sce = sc->data[data]; + if(sce->val4 != tid) { + ShowError("kaahi_heal_timer: Timer mismatch: %d != %d\n", tid, sce->val4); + sce->val4=-1; return 0; } - if(!status_charge(bl, 0, sc->data[data].val3)) { - sc->data[data].val4=-1; + if(!status_charge(bl, 0, sce->val3)) { + sce->val4=-1; return 0; } hp = status->max_hp - status->hp; - if (hp > sc->data[data].val2) - hp = sc->data[data].val2; + if (hp > sce->val2) + hp = sce->val2; if (hp) status_heal(bl, hp, 0, 2); - sc->data[data].val4=-1; + sce->val4=-1; return 1; } @@ -6653,20 +6689,21 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) struct map_session_data *sd; struct status_data *status; struct status_change *sc; + struct status_change_entry *sce; bl = map_id2bl(id); sc = status_get_sc(bl); status = status_get_status_data(bl); - if( !bl || !sc || !status ) + if(!(bl && sc && (sce = sc->data[type]))) { ShowDebug("status_change_timer: Null pointer id: %d data: %d bl-type: %d\n", id, data, bl?bl->type:-1); return 0; } - if( sc->data[type].timer != tid ) + if( sce->timer != tid ) { - ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sc->data[type].timer, bl->id); + ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id); return 0; } @@ -6678,37 +6715,37 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) case SC_CLOAKING: if(!status_charge(bl, 0, 1)) break; //Not enough SP to continue. - sc->data[type].timer = add_timer(sc->data[type].val2+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(sce->val2+tick, status_change_timer, bl->id, data); return 0; case SC_CHASEWALK: - if(!status_charge(bl, 0, sc->data[type].val4)) + if(!status_charge(bl, 0, sce->val4)) break; //Not enough SP to continue. - if (sc->data[SC_INCSTR].timer == -1) { - sc_start(bl, SC_INCSTR,100,1<<(sc->data[type].val1-1), - (sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration - *skill_get_time2(StatusSkillChangeTable[type],sc->data[type].val1)); + if (!sc->data[SC_INCSTR]) { + sc_start(bl, SC_INCSTR,100,1<<(sce->val1-1), + (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration + *skill_get_time2(StatusSkillChangeTable[type],sce->val1)); } - sc->data[type].timer = add_timer(sc->data[type].val2+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(sce->val2+tick, status_change_timer, bl->id, data); return 0; break; case SC_SKA: - if((--sc->data[type].val2)>0){ - sc->data[type].val3 = rand()%100; //Random defense. - sc->data[type].timer = add_timer(1000+tick, status_change_timer,bl->id, data); + if(--(sce->val2)>0){ + sce->val3 = rand()%100; //Random defense. + sce->timer = add_timer(1000+tick, status_change_timer,bl->id, data); return 0; } break; case SC_HIDING: - if((--sc->data[type].val2)>0){ + if(--(sce->val2)>0){ - if(sc->data[type].val2 % sc->data[type].val4 == 0 &&!status_charge(bl, 0, 1)) + if(sce->val2 % sce->val4 == 0 &&!status_charge(bl, 0, 1)) break; //Fail if it's time to substract SP and there isn't. - sc->data[type].timer = add_timer(1000+tick, status_change_timer,bl->id, data); + sce->timer = add_timer(1000+tick, status_change_timer,bl->id, data); return 0; } break; @@ -6716,42 +6753,35 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) case SC_SIGHT: case SC_RUWACH: case SC_SIGHTBLASTER: - map_foreachinrange( status_change_timer_sub, bl, sc->data[type].val3, BL_CHAR, bl,sc,type,tick); + map_foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick); - if( (--sc->data[type].val2)>0 ){ - sc->data[type].timer = add_timer(250+tick, status_change_timer, bl->id, data); + if( --(sce->val2)>0 ){ + sce->timer = add_timer(250+tick, status_change_timer, bl->id, data); return 0; } break; case SC_PROVOKE: - if(sc->data[type].val2) { //Auto-provoke (it is ended in status_heal) - sc->data[type].timer = add_timer(1000*60+tick,status_change_timer, bl->id, data ); - return 0; - } - break; - - case SC_ENDURE: - if(sc->data[type].val4) { //Infinite Endure. - sc->data[type].timer = add_timer(1000*60+tick,status_change_timer, bl->id, data); + if(sce->val2) { //Auto-provoke (it is ended in status_heal) + sce->timer = add_timer(1000*60+tick,status_change_timer, bl->id, data ); return 0; } break; case SC_STONE: - if(sc->opt1 == OPT1_STONEWAIT && sc->data[type].val3) { - sc->data[type].val4 = 0; + if(sc->opt1 == OPT1_STONEWAIT && sce->val3) { + sce->val4 = 0; unit_stop_walking(bl,1); sc->opt1 = OPT1_STONE; clif_changeoption(bl); - sc->data[type].timer = add_timer(1000+tick,status_change_timer, bl->id, data ); + sce->timer = add_timer(1000+tick,status_change_timer, bl->id, data ); status_calc_bl(bl, StatusChangeFlagTable[type]); return 0; } - if((--sc->data[type].val3) > 0) { - if((++sc->data[type].val4)%5 == 0 && status->hp > status->max_hp/4) - status_zap(bl, sc->data[type].val2, 0); - sc->data[type].timer = add_timer(1000+tick,status_change_timer, bl->id, data ); + if(--(sce->val3) > 0) { + if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4) + status_zap(bl, sce->val2, 0); + sce->timer = add_timer(1000+tick,status_change_timer, bl->id, data ); return 0; } break; @@ -6760,84 +6790,66 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) if(status->hp <= status->max_hp>>2) //Stop damaging after 25% HP left. break; case SC_DPOISON: - if ((--sc->data[type].val3) > 0) { - if (sc->data[SC_SLOWPOISON].timer == -1) { - status_zap(bl, sc->data[type].val4, 0); + if (--(sce->val3) > 0) { + if (!sc->data[SC_SLOWPOISON]) { + status_zap(bl, sce->val4, 0); if (status_isdead(bl)) break; } - sc->data[type].timer = add_timer(1000 + tick, status_change_timer, bl->id, data ); + sce->timer = add_timer(1000 + tick, status_change_timer, bl->id, data ); return 0; } break; case SC_TENSIONRELAX: - if(status->max_hp > status->hp && (--sc->data[type].val3) > 0){ - sc->data[type].timer = add_timer(sc->data[type].val4+tick, status_change_timer, bl->id, data); + if(status->max_hp > status->hp && --(sce->val3) > 0){ + sce->timer = add_timer(sce->val4+tick, status_change_timer, bl->id, data); return 0; } break; case SC_BLEEDING: - if ((--sc->data[type].val4) >= 0) { + if (--(sce->val4) >= 0) { status_fix_damage(NULL, bl, rand()%600 + 200, 0); if (status_isdead(bl)) break; - sc->data[type].timer = add_timer(10000 + tick, status_change_timer, bl->id, data ); + sce->timer = add_timer(10000 + tick, status_change_timer, bl->id, data ); return 0; } break; case SC_HPREGEN: - if( sd && (--sc->data[type].val4) >= 0 ) + if( sd && --(sce->val4) >= 0 ) { if( status->hp < status->max_hp ) { - int hp = (int)(sd->status.max_hp * sc->data[type].val1 / 100.); + int hp = (int)(sd->status.max_hp * sce->val1 / 100.); status_heal(bl, hp, 0, 2); } - sc->data[type].timer = add_timer((sc->data[type].val2 * 1000) + tick, status_change_timer, bl->id, data ); + sce->timer = add_timer((sce->val2 * 1000) + tick, status_change_timer, bl->id, data ); return 0; } break; case SC_KNOWLEDGE: - if (sd) { - if(bl->m != sd->feel_map[0].m && bl->m != sd->feel_map[1].m && bl->m != sd->feel_map[2].m) - break; //End it - } //Otherwise continue. - // Status changes that don't have a time limit - case SC_AETERNA: - case SC_TRICKDEAD: - case SC_MODECHANGE: - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_MAGICPOWER: - case SC_REJECTSWORD: - case SC_MEMORIZE: - case SC_BROKENWEAPON: - case SC_BROKENARMOR: - case SC_SACRIFICE: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYTURN: - case SC_READYCOUNTER: - case SC_RUN: - case SC_DODGE: - case SC_AUTOBERSERK: - case SC_SIGNUMCRUCIS: - sc->data[type].timer = add_timer( 1000*600+tick,status_change_timer, bl->id, data ); - return 0; - + if (!sd) break; + if(bl->m == sd->feel_map[0].m || + bl->m == sd->feel_map[1].m || + bl->m == sd->feel_map[2].m) + { //Timeout will be handled by pc_setpos + sce->timer = -1; + return 0; + } + break; case SC_DANCING: //ダンススキルの時間SP消費 { int s = 0; int sp = 1; - int counter = sc->data[type].val3>>16; + int counter = (sce->val3)>>16; if (--counter <= 0) break; - sc->data[type].val3&= 0xFFFF; //Remove counter - sc->data[type].val3|=(counter<<16);//Reset it. - switch(sc->data[type].val1&0xFFFF){ + sce->val3&= 0xFFFF; //Remove counter + sce->val3|=(counter<<16);//Reset it. + switch(sce->val1&0xFFFF){ case BD_RICHMANKIM: case BD_DRUMBATTLEFIELD: case BD_RINGNIBELUNGEN: @@ -6866,7 +6878,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) break; case CG_MOONLIT: //Moonlit's cost is 4sp*skill_lv [Skotlex] - sp= 4*(sc->data[type].val1>>16); + sp= 4*(sce->val1>>16); //Upkeep is also every 10 secs. case DC_DONTFORGETME: s=10; @@ -6874,12 +6886,12 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) } if (s && (counter%s == 0)) { - if (sc->data[SC_LONGING].timer != -1) + if (sc->data[SC_LONGING]) sp*= 3; if (!status_charge(bl, 0, sp)) break; } - sc->data[type].timer = add_timer(1000+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(1000+tick, status_change_timer, bl->id, data); return 0; } break; @@ -6887,10 +6899,10 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) case SC_DEVOTION: { //Check range and timeleft to preserve status [Skotlex] //This implementation won't work for mobs because of map_id2sd, but it's a small cost in exchange of the speed of map_id2sd over map_id2bl - struct map_session_data *md = map_id2sd(sc->data[type].val1); - if (md && check_distance_bl(bl, &md->bl, sc->data[type].val3) && (sc->data[type].val4-=1000)>0) + struct map_session_data *md = map_id2sd(sce->val1); + if (md && check_distance_bl(bl, &md->bl, sce->val3) && (sce->val4-=1000)>0) { - sc->data[type].timer = add_timer(1000+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(1000+tick, status_change_timer, bl->id, data); return 0; } } @@ -6898,9 +6910,9 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) case SC_BERSERK: // 5% every 10 seconds [DracoRPG] - if((--sc->data[type].val3)>0 && status_charge(bl, sc->data[type].val2, 0)) + if(--(sce->val3)>0 && status_charge(bl, sce->val2, 0)) { - sc->data[type].timer = add_timer(sc->data[type].val4+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(sce->val4+tick, status_change_timer, bl->id, data); return 0; } break; @@ -6911,7 +6923,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) clif_updatestatus(sd,SP_MANNER); if (sd->status.manner < 0) { //Every 60 seconds your manner goes up by 1 until it gets back to 0. - sc->data[type].timer = add_timer(60000+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(60000+tick, status_change_timer, bl->id, data); return 0; } } @@ -6919,13 +6931,13 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) case SC_SPLASHER: // custom Venom Splasher countdown timer - //if (sc->data[type].val4 % 1000 == 0) { + //if (sce->val4 % 1000 == 0) { // char timer[10]; - // snprintf (timer, 10, "%d", sc->data[type].val4/1000); + // snprintf (timer, 10, "%d", sce->val4/1000); // clif_message(bl, timer); //} - if((sc->data[type].val4 -= 500) > 0) { - sc->data[type].timer = add_timer(500 + tick, status_change_timer, bl->id, data); + if((sce->val4 -= 500) > 0) { + sce->timer = add_timer(500 + tick, status_change_timer, bl->id, data); return 0; } break; @@ -6933,51 +6945,51 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) case SC_MARIONETTE: case SC_MARIONETTE2: { - struct block_list *pbl = map_id2bl(sc->data[type].val1); - if (pbl && check_distance_bl(bl, pbl, 7) && (sc->data[type].val2--)>0) + struct block_list *pbl = map_id2bl(sce->val1); + if (pbl && check_distance_bl(bl, pbl, 7) && (sce->val2)-->0) { - sc->data[type].timer = add_timer(1000 + tick, status_change_timer, bl->id, data); + sce->timer = add_timer(1000 + tick, status_change_timer, bl->id, data); return 0; } } break; case SC_GOSPEL: - if(sc->data[type].val4 == BCT_SELF && (--sc->data[type].val2) > 0) + if(sce->val4 == BCT_SELF && --(sce->val2) > 0) { int hp, sp; - hp = (sc->data[type].val1 > 5) ? 45 : 30; - sp = (sc->data[type].val1 > 5) ? 35 : 20; + hp = (sce->val1 > 5) ? 45 : 30; + sp = (sce->val1 > 5) ? 35 : 20; if(!status_charge(bl, hp, sp)) break; - sc->data[type].timer = add_timer(10000+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(10000+tick, status_change_timer, bl->id, data); return 0; } break; case SC_GUILDAURA: { - struct block_list *tbl = map_id2bl(sc->data[type].val2); + struct block_list *tbl = map_id2bl(sce->val2); if (tbl && battle_check_range(bl, tbl, 2)){ - sc->data[type].timer = add_timer(1000 + tick, status_change_timer, bl->id, data); + sce->timer = add_timer(1000 + tick, status_change_timer, bl->id, data); return 0; } } break; case SC_JAILED: - if(sc->data[type].val1 == INT_MAX || --sc->data[type].val1 > 0) + if(sce->val1 == INT_MAX || --(sce->val1) > 0) { - sc->data[type].timer = add_timer(60000+tick, status_change_timer, bl->id,data); + sce->timer = add_timer(60000+tick, status_change_timer, bl->id,data); return 0; } break; case SC_BLIND: - if(sc->data[SC_FOGWALL].timer!= -1) + if(sc->data[SC_FOGWALL]) { //Blind lasts forever while you are standing on the fog. - sc->data[type].timer = add_timer(5000+tick, status_change_timer, bl->id, data); + sce->timer = add_timer(5000+tick, status_change_timer, bl->id, data); return 0; } break; @@ -6996,8 +7008,8 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) struct status_change* tsc; struct block_list* src = va_arg(ap,struct block_list*); - struct status_change* sc = va_arg(ap,struct status_change*); - enum sc_type type = va_arg(ap,enum sc_type); + struct status_change_entry* sce = va_arg(ap,struct status_change_entry*); + enum sc_type type = va_arg(ap,enum sc_type); unsigned int tick = va_arg(ap,unsigned int); if (status_isdead(bl)) @@ -7013,14 +7025,14 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) case SC_SIGHT: /* サイト */ case SC_CONCENTRATE: if (tsc) { - if (tsc->data[SC_HIDING].timer != -1) + if (tsc->data[SC_HIDING]) status_change_end( bl, SC_HIDING, -1); - if (tsc->data[SC_CLOAKING].timer != -1) + if (tsc->data[SC_CLOAKING]) status_change_end( bl, SC_CLOAKING, -1); } break; case SC_RUWACH: /* ルアフ */ - if (tsc && (tsc->data[SC_HIDING].timer != -1 || tsc->data[SC_CLOAKING].timer != -1)) { + if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING])) { status_change_end( bl, SC_HIDING, -1); status_change_end( bl, SC_CLOAKING, -1); if(battle_check_target( src, bl, BCT_ENEMY ) > 0) @@ -7032,13 +7044,13 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)) { skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0); - if (sc) sc->data[type].val2 = 0; //This signals it to end. + if (sce) sce->val2 = 0; //This signals it to end. } break; case SC_CLOSECONFINE: //Lock char has released the hold on everyone... - if (tsc && tsc->data[SC_CLOSECONFINE2].timer != -1 && tsc->data[SC_CLOSECONFINE2].val2 == src->id) { - tsc->data[SC_CLOSECONFINE2].val2 = 0; + if (tsc && tsc->data[SC_CLOSECONFINE2] && tsc->data[SC_CLOSECONFINE2]->val2 == src->id) { + tsc->data[SC_CLOSECONFINE2]->val2 = 0; status_change_end(bl, SC_CLOSECONFINE2, -1); } break; @@ -7061,13 +7073,13 @@ int status_change_clear_buffs (struct block_list* bl, int type) if (type&2) //Debuffs for( i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++ ) { - if(sc->data[i].timer != -1) + if(sc->data[i]) status_change_end(bl,i,-1); } for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ ) { - if(sc->data[i].timer == -1) + if(!sc->data[i]) continue; switch (i) { @@ -7121,7 +7133,7 @@ int status_change_clear_buffs (struct block_list* bl, int type) case SC_BERSERK: if (!(type&1)) continue; - sc->data[i].val2 = 0; + sc->data[i]->val2 = 0; break; default: if (!(type&1)) @@ -7490,6 +7502,11 @@ int do_init_status(void) status_readdb(); status_calc_sigma(); natural_heal_prev_tick = gettick(); + sc_data_ers = ers_new(sizeof(struct status_change_entry)); add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL); return 0; } +void do_final_status(void) +{ + ers_destroy(sc_data_ers); +} diff --git a/src/map/status.h b/src/map/status.h index 71f84e93d..f1932ae32 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -272,10 +272,10 @@ enum sc_type { SC_MAGICMIRROR, SC_SLOWCAST, SC_SUMMER, - SC_EXPBOOST, // Field Guide - SC_ITEMBOOST, // Bubble Gum - SC_BOSSMAPINFO, // Convex Mirror - SC_LIFEINSURANCE, // Life Insurance + SC_EXPBOOST, + SC_ITEMBOOST, + SC_BOSSMAPINFO, + SC_LIFEINSURANCE, //260 SC_INCCRI, SC_INCDEF, SC_INCBASEATK, @@ -692,5 +692,6 @@ int status_check_visibility(struct block_list *src, struct block_list *target); int status_readdb(void); int do_init_status(void); +void do_final_status(void); #endif /* _STATUS_H_ */ diff --git a/src/map/unit.c b/src/map/unit.c index 0dd464a67..0e01517dc 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -299,7 +299,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) ud->to_y = y; sc = status_get_sc(bl); - if (sc && sc->count && sc->data[SC_CONFUSION].timer != -1) //Randomize the target position + if (sc && sc->data[SC_CONFUSION]) //Randomize the target position map_random_dir(bl, &ud->to_x, &ud->to_y); if(ud->walktimer != -1) { @@ -367,7 +367,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int ud->state.attack_continue = flag&2?1:0; //Chase to attack. sc = status_get_sc(bl); - if (sc && sc->count && sc->data[SC_CONFUSION].timer != -1) //Randomize the target position + if (sc && sc->data[SC_CONFUSION]) //Randomize the target position map_random_dir(bl, &ud->to_x, &ud->to_y); if(ud->walktimer != -1) { @@ -404,19 +404,18 @@ int unit_run(struct block_list *bl) short to_x,to_y,dir_x,dir_y; int i; - if (!sc || !sc->count || sc->data[SC_RUN].timer == -1) + if (!(sc && sc->data[SC_RUN])) return 0; if (!unit_can_move(bl)) { - if(sc->data[SC_RUN].timer!=-1) - status_change_end(bl,SC_RUN,-1); + status_change_end(bl,SC_RUN,-1); return 0; } to_x = bl->x; to_y = bl->y; - dir_x = dirx[sc->data[SC_RUN].val2]; - dir_y = diry[sc->data[SC_RUN].val2]; + dir_x = dirx[sc->data[SC_RUN]->val2]; + dir_y = diry[sc->data[SC_RUN]->val2]; for(i=0;idata[SC_RUN].val1),unit_getdir(bl),0); + skill_blown(bl,bl,skill_get_blewcount(TK_RUN,sc->data[SC_RUN]->val1),unit_getdir(bl),0); clif_fixpos(bl); //Why is a clif_slide (skill_blown) AND a fixpos needed? Ask Aegis. clif_status_change(bl, SI_BUMP, 0); return 0; @@ -446,7 +445,7 @@ int unit_run(struct block_list *bl) // copy-paste from above clif_status_change(bl, SI_BUMP, 1); status_change_end(bl,SC_RUN,-1); - skill_blown(bl,bl,skill_get_blewcount(TK_RUN,sc->data[SC_RUN].val1),unit_getdir(bl),0); + skill_blown(bl,bl,skill_get_blewcount(TK_RUN,sc->data[SC_RUN]->val1),unit_getdir(bl),0); clif_fixpos(bl); clif_status_change(bl, SI_BUMP, 0); return 0; @@ -722,25 +721,25 @@ int unit_can_move(struct block_list *bl) return 0; if (sc->count && ( - sc->data[SC_ANKLE].timer != -1 - || sc->data[SC_AUTOCOUNTER].timer !=-1 - || sc->data[SC_TRICKDEAD].timer !=-1 - || sc->data[SC_BLADESTOP].timer !=-1 - || sc->data[SC_BLADESTOP_WAIT].timer !=-1 - || sc->data[SC_SPIDERWEB].timer !=-1 - || (sc->data[SC_DANCING].timer !=-1 && sc->data[SC_DANCING].val4 && ( - sc->data[SC_LONGING].timer == -1 || - (sc->data[SC_DANCING].val1&0xFFFF) == CG_MOONLIT || - (sc->data[SC_DANCING].val1&0xFFFF) == CG_HERMODE + sc->data[SC_ANKLE] + || sc->data[SC_AUTOCOUNTER] + || sc->data[SC_TRICKDEAD] + || sc->data[SC_BLADESTOP] + || sc->data[SC_BLADESTOP_WAIT] + || sc->data[SC_SPIDERWEB] + || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && ( + sc->data[SC_LONGING] || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE )) - || (sc->data[SC_GOSPEL].timer !=-1 && sc->data[SC_GOSPEL].val4 == BCT_SELF) // cannot move while gospel is in effect - || sc->data[SC_STOP].timer != -1 - || sc->data[SC_CLOSECONFINE].timer != -1 - || sc->data[SC_CLOSECONFINE2].timer != -1 - || (sc->data[SC_CLOAKING].timer != -1 && //Need wall at level 1-2 - sc->data[SC_CLOAKING].val1 < 3 && !(sc->data[SC_CLOAKING].val4&1)) - || sc->data[SC_MADNESSCANCEL].timer != -1 - || (sc->data[SC_GRAVITATION].timer != -1 && sc->data[SC_GRAVITATION].val3 == BCT_SELF) + || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect + || sc->data[SC_STOP] + || sc->data[SC_CLOSECONFINE] + || sc->data[SC_CLOSECONFINE2] + || (sc->data[SC_CLOAKING] && //Need wall at level 1-2 + sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) + || sc->data[SC_MADNESSCANCEL] + || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) )) return 0; } @@ -817,16 +816,16 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh switch(skill_num) { //Check for skills that auto-select target case MO_CHAINCOMBO: - if (sc && sc->data[SC_BLADESTOP].timer != -1){ - if ((target=(struct block_list *)sc->data[SC_BLADESTOP].val4) == NULL) + if (sc && sc->data[SC_BLADESTOP]){ + if ((target=(struct block_list *)sc->data[SC_BLADESTOP]->val4) == NULL) return 0; } break; case TK_JUMPKICK: case TK_COUNTER: case HT_POWER: - if (sc && sc->data[SC_COMBO].timer != -1 && sc->data[SC_COMBO].val1 == skill_num) - target_id = sc->data[SC_COMBO].val2; + if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num) + target_id = sc->data[SC_COMBO]->val2; break; case WE_MALE: case WE_FEMALE: @@ -958,10 +957,10 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh casttime += casttime * min(skill_lv, sd->spiritball); break; case MO_EXTREMITYFIST: - if (sc && sc->data[SC_COMBO].timer != -1 && - (sc->data[SC_COMBO].val1 == MO_COMBOFINISH || - sc->data[SC_COMBO].val1 == CH_TIGERFIST || - sc->data[SC_COMBO].val1 == CH_CHAINCRUSH)) + if (sc && sc->data[SC_COMBO] && + (sc->data[SC_COMBO]->val1 == MO_COMBOFINISH || + sc->data[SC_COMBO]->val1 == CH_TIGERFIST || + sc->data[SC_COMBO]->val1 == CH_CHAINCRUSH)) casttime = 0; temp = 1; break; @@ -969,11 +968,11 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh temp = 1; break; case ST_CHASEWALK: - if (sc && sc->data[SC_CHASEWALK].timer != -1) + if (sc && sc->data[SC_CHASEWALK]) casttime = 0; break; case TK_RUN: - if (sc && sc->data[SC_RUN].timer != -1) + if (sc && sc->data[SC_RUN]) casttime = 0; break; case KN_CHARGEATK: @@ -1033,8 +1032,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh ud->skillid = skill_num; ud->skilllv = skill_lv; - if(sc && sc->data[SC_CLOAKING].timer != -1 && - !(sc->data[SC_CLOAKING].val4&4) && skill_num != AS_CLOAKING) + if(sc && sc->data[SC_CLOAKING] && + !(sc->data[SC_CLOAKING]->val4&4) && skill_num != AS_CLOAKING) { status_change_end(src,SC_CLOAKING,-1); if (!src->prev) return 0; //Warped away! @@ -1137,8 +1136,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh ud->skilly = skill_y; ud->skilltarget = 0; - if (sc && sc->data[SC_CLOAKING].timer != -1 && - !(sc->data[SC_CLOAKING].val4&4)) + if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4)) { status_change_end(src,SC_CLOAKING,-1); if (!src->prev) return 0; //Warped away! @@ -1621,43 +1619,43 @@ int unit_remove_map(struct block_list *bl, int clrtype) ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick(); if(sc && sc->count ) { //map-change/warp dispells. - if(sc->data[SC_BLADESTOP].timer!=-1) + if(sc->data[SC_BLADESTOP]) status_change_end(bl,SC_BLADESTOP,-1); - if(sc->data[SC_BASILICA].timer!=-1) + if(sc->data[SC_BASILICA]) status_change_end(bl,SC_BASILICA,-1); - if(sc->data[SC_ANKLE].timer != -1) + if(sc->data[SC_ANKLE]) status_change_end(bl, SC_ANKLE, -1); - if (sc->data[SC_TRICKDEAD].timer != -1) + if (sc->data[SC_TRICKDEAD]) status_change_end(bl, SC_TRICKDEAD, -1); - if (sc->data[SC_BLADESTOP].timer!=-1) + if (sc->data[SC_BLADESTOP]) status_change_end(bl,SC_BLADESTOP,-1); - if (sc->data[SC_RUN].timer!=-1) + if (sc->data[SC_RUN]) status_change_end(bl,SC_RUN,-1); - if (sc->data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris] + if (sc->data[SC_DANCING]) // clear dance effect when warping [Valaris] skill_stop_dancing(bl); - if (sc->data[SC_WARM].timer!=-1) + if (sc->data[SC_WARM]) status_change_end(bl, SC_WARM, -1); - if (sc->data[SC_DEVOTION].timer!=-1) + if (sc->data[SC_DEVOTION]) status_change_end(bl,SC_DEVOTION,-1); - if (sc->data[SC_MARIONETTE].timer!=-1) + if (sc->data[SC_MARIONETTE]) status_change_end(bl,SC_MARIONETTE,-1); - if (sc->data[SC_MARIONETTE2].timer!=-1) + if (sc->data[SC_MARIONETTE2]) status_change_end(bl,SC_MARIONETTE2,-1); - if (sc->data[SC_CLOSECONFINE].timer!=-1) + if (sc->data[SC_CLOSECONFINE]) status_change_end(bl,SC_CLOSECONFINE,-1); - if (sc->data[SC_CLOSECONFINE2].timer!=-1) + if (sc->data[SC_CLOSECONFINE2]) status_change_end(bl,SC_CLOSECONFINE2,-1); - if (sc->data[SC_HIDING].timer!=-1) + if (sc->data[SC_HIDING]) status_change_end(bl, SC_HIDING, -1); - if (sc->data[SC_CLOAKING].timer!=-1) + if (sc->data[SC_CLOAKING]) status_change_end(bl, SC_CLOAKING, -1); - if (sc->data[SC_CHASEWALK].timer!=-1) + if (sc->data[SC_CHASEWALK]) status_change_end(bl, SC_CHASEWALK, -1); - if (sc->data[SC_GOSPEL].timer != -1 && sc->data[SC_GOSPEL].val4 == BCT_SELF) + if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) status_change_end(bl, SC_GOSPEL, -1); - if (sc->data[SC_CHANGE].timer!=-1) + if (sc->data[SC_CHANGE]) status_change_end(bl, SC_CHANGE, -1); - if (sc->data[SC_MIRACLE].timer!=-1) + if (sc->data[SC_MIRACLE]) status_change_end(bl, SC_MIRACLE, -1); } @@ -1764,39 +1762,39 @@ int unit_free(struct block_list *bl, int clrtype) //Status that are not saved... if(sd->sc.count) { - if(sd->sc.data[SC_SPURT].timer!=-1) + if(sd->sc.data[SC_SPURT]) status_change_end(bl,SC_SPURT,-1); - if(sd->sc.data[SC_BERSERK].timer!=-1) + if(sd->sc.data[SC_BERSERK]) status_change_end(bl,SC_BERSERK,-1); - if(sd->sc.data[SC_TRICKDEAD].timer!=-1) + if(sd->sc.data[SC_TRICKDEAD]) status_change_end(bl,SC_TRICKDEAD,-1); - if(sd->sc.data[SC_GUILDAURA].timer!=-1) + if(sd->sc.data[SC_GUILDAURA]) status_change_end(bl,SC_GUILDAURA,-1); if (battle_config.debuff_on_logout&1) { - if(sd->sc.data[SC_ORCISH].timer!=-1) + if(sd->sc.data[SC_ORCISH]) status_change_end(bl,SC_ORCISH,-1); - if(sd->sc.data[SC_STRIPWEAPON].timer!=-1) + if(sd->sc.data[SC_STRIPWEAPON]) status_change_end(bl,SC_STRIPWEAPON,-1); - if(sd->sc.data[SC_STRIPARMOR].timer!=-1) + if(sd->sc.data[SC_STRIPARMOR]) status_change_end(bl,SC_STRIPARMOR,-1); - if(sd->sc.data[SC_STRIPSHIELD].timer!=-1) + if(sd->sc.data[SC_STRIPSHIELD]) status_change_end(bl,SC_STRIPSHIELD,-1); - if(sd->sc.data[SC_STRIPHELM].timer!=-1) + if(sd->sc.data[SC_STRIPHELM]) status_change_end(bl,SC_STRIPHELM,-1); - if(sd->sc.data[SC_EXTREMITYFIST].timer!=-1) + if(sd->sc.data[SC_EXTREMITYFIST]) status_change_end(bl,SC_EXTREMITYFIST,-1); - if(sd->sc.data[SC_EXPLOSIONSPIRITS].timer!=-1) + if(sd->sc.data[SC_EXPLOSIONSPIRITS]) status_change_end(bl,SC_EXPLOSIONSPIRITS,-1); - if(sd->sc.data[SC_REGENERATION].timer!=-1 && sd->sc.data[SC_REGENERATION].val4) + if(sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4) status_change_end(bl,SC_REGENERATION,-1); } if (battle_config.debuff_on_logout&2) { - if(sd->sc.data[SC_MAXIMIZEPOWER].timer!=-1) + if(sd->sc.data[SC_MAXIMIZEPOWER]) status_change_end(bl,SC_MAXIMIZEPOWER,-1); - if(sd->sc.data[SC_MAXOVERTHRUST].timer!=-1) + if(sd->sc.data[SC_MAXOVERTHRUST]) status_change_end(bl,SC_MAXOVERTHRUST,-1); - if(sd->sc.data[SC_STEELBODY].timer!=-1) + if(sd->sc.data[SC_STEELBODY]) status_change_end(bl,SC_STEELBODY,-1); } } -- cgit v1.2.3-60-g2f50