diff options
author | skotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2007-11-22 23:52:58 +0000 |
---|---|---|
committer | skotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2007-11-22 23:52:58 +0000 |
commit | 2b2dbf43f11aecf778ff118dd1da1af9726f36e6 (patch) | |
tree | 890231641c122da8ef8664471be4a008041c6349 /src/map/skill.c | |
parent | 78dcaf513236ab7736a84deff5820b71cf6a76fb (diff) | |
download | hercules-2b2dbf43f11aecf778ff118dd1da1af9726f36e6.tar.gz hercules-2b2dbf43f11aecf778ff118dd1da1af9726f36e6.tar.bz2 hercules-2b2dbf43f11aecf778ff118dd1da1af9726f36e6.tar.xz hercules-2b2dbf43f11aecf778ff118dd1da1af9726f36e6.zip |
- 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
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 692 |
1 files changed, 342 insertions, 350 deletions
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;i<SC_MAX;i++){ - if (tsc->data[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; /* 黄金蟲カード(ヒール量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); } } |