diff options
-rw-r--r-- | src/map/status.c | 352 | ||||
-rw-r--r-- | src/map/status.h | 1 |
2 files changed, 189 insertions, 164 deletions
diff --git a/src/map/status.c b/src/map/status.c index 7ffd48978..1b85e164a 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -9675,8 +9675,191 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t status->change_start_stop_action(bl, type); // Set option as needed. - opt_flag = 1; - switch(type) { + opt_flag = status->change_start_set_option(bl, sc, type, val1, val2, val3, val4); + + + //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. + if(opt_flag) { + clif->changeoption(bl); + if( sd && opt_flag&0x4 ) { + if (vd) + clif->changelook(bl, LOOK_BASE, vd->class); + clif->changelook(bl,LOOK_WEAPON,0); + clif->changelook(bl,LOOK_SHIELD,0); + if (vd) + clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + } + } + if (calc_flag&SCB_DYE) { + //Reset DYE color + if (vd && vd->cloth_color) { + val4 = vd->cloth_color; + clif->changelook(bl,LOOK_CLOTHES_COLOR,0); + } + calc_flag&=~SCB_DYE; + } + +#if 0 //Currently No SC's use this + if (calc_flag&SCB_BODY) { + //Reset Body Style + if (vd && vd->body_style) { + val4 = vd->body_style; + clif->changelook(bl,LOOK_BODY2,0); + } + calc_flag&=~SCB_BODY; + } +#endif + + if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) + clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); + + /** + * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. + **/ + if( tick_time ) + tick = tick_time; + + //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. + if((sce=sc->data[type])) {// reuse old sc + if( sce->timer != INVALID_TIMER ) + timer->delete(sce->timer, status->change_timer); + } else {// new sc + ++(sc->count); + sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); + } + + sce->val1 = val1; + sce->val2 = val2; + sce->val3 = val3; + sce->val4 = val4; + + if (tick >= 0) { + sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); + sce->infinite_duration = false; + } else { + sce->timer = INVALID_TIMER; //Infinite duration + sce->infinite_duration = true; + if( sd ) + chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); + } + + if (calc_flag) + status_calc_bl(bl,calc_flag); + + if(sd && sd->pd) + pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing + + switch (type) { + case SC_BERSERK: + if (!(sce->val2)) { //don't heal if already set + status->heal(bl, st->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 + } + sce->val2 = 5 * st->max_hp / 100; + break; + case SC_HLIF_CHANGE: + status_percent_heal(bl, 100, 100); + break; + case SC_RUN: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->run(bl, NULL, SC_RUN); + } + break; + case SC_CASH_BOSS_ALARM: + if( sd ) + clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message + break; + case SC_MER_HP: + status_percent_heal(bl, 100, 0); // Recover Full HP + break; + case SC_MER_SP: + status_percent_heal(bl, 0, 100); // Recover Full SP + break; + case SC_PROMOTE_HEALTH_RESERCH: + status_percent_heal(bl, sce->val4, 0); + break; + case SC_ENERGY_DRINK_RESERCH: + status_percent_heal(bl, 0, sce->val4); + break; + /** + * Ranger + **/ + case SC_WUGDASH: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->run(bl, sd, SC_WUGDASH); + } + break; + case SC_COMBOATTACK: + switch (sce->val1) { + case TK_STORMKICK: + clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); + break; + case TK_DOWNKICK: + clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); + break; + case TK_TURNKICK: + clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); + break; + case TK_COUNTER: + clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); + break; + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + if (sd) + clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); + break; + case TK_JUMPKICK: + if (sd) + clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); + break; + case MO_TRIPLEATTACK: + if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) + clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); + break; + case SR_FALLENEMPIRE: + if (sd){ + clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); + clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); + } + break; + } + break; + case SC_RAISINGDRAGON: + sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] + break; + } + + if( opt_flag&2 && sd && sd->touching_id ) + npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range + + return 1; +} + +/** + * Set new status values. + * + * @param bl Status change target bl. + * @param sc Current statuses. + * @param type Status change type. + * @param val1 Additional value (meaning depends on type). + * @param val2 Additional value (meaning depends on type). + * @param val3 Additional value (meaning depends on type). + * @param val4 Additional value (meaning depends on type). + * + * @retval option flag. + */ +int status_change_start_set_option(struct block_list *bl, struct status_change* sc, enum sc_type type, int val1, int val2, int val3, int val4) +{ + int opt_flag = 1; + + nullpo_retr(true, bl); + nullpo_retr(true, sc); + switch (type) { //OPT1 case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; @@ -9754,7 +9937,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; #endif // 0 case SC_DANCING: - if ((val1&0xFFFF) == CG_MOONLIT) + if ((val1 & 0xFFFF) == CG_MOONLIT) sc->opt3 |= OPT3_MOONLIT; opt_flag = 0; break; @@ -9851,167 +10034,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t default: opt_flag = 0; } - - //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. - if(opt_flag) { - clif->changeoption(bl); - if( sd && opt_flag&0x4 ) { - if (vd) - clif->changelook(bl, LOOK_BASE, vd->class); - clif->changelook(bl,LOOK_WEAPON,0); - clif->changelook(bl,LOOK_SHIELD,0); - if (vd) - clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - } - } - if (calc_flag&SCB_DYE) { - //Reset DYE color - if (vd && vd->cloth_color) { - val4 = vd->cloth_color; - clif->changelook(bl,LOOK_CLOTHES_COLOR,0); - } - calc_flag&=~SCB_DYE; - } - -#if 0 //Currently No SC's use this - if (calc_flag&SCB_BODY) { - //Reset Body Style - if (vd && vd->body_style) { - val4 = vd->body_style; - clif->changelook(bl,LOOK_BODY2,0); - } - calc_flag&=~SCB_BODY; - } -#endif - - if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) - clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); - - /** - * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. - **/ - if( tick_time ) - tick = tick_time; - - //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. - if((sce=sc->data[type])) {// reuse old sc - if( sce->timer != INVALID_TIMER ) - timer->delete(sce->timer, status->change_timer); - } else {// new sc - ++(sc->count); - sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); - } - - sce->val1 = val1; - sce->val2 = val2; - sce->val3 = val3; - sce->val4 = val4; - - if (tick >= 0) { - sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); - sce->infinite_duration = false; - } else { - sce->timer = INVALID_TIMER; //Infinite duration - sce->infinite_duration = true; - if( sd ) - chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); - } - - if (calc_flag) - status_calc_bl(bl,calc_flag); - - if(sd && sd->pd) - pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing - - switch (type) { - case SC_BERSERK: - if (!(sce->val2)) { //don't heal if already set - status->heal(bl, st->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 - } - sce->val2 = 5 * st->max_hp / 100; - break; - case SC_HLIF_CHANGE: - status_percent_heal(bl, 100, 100); - break; - case SC_RUN: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->run(bl, NULL, SC_RUN); - } - break; - case SC_CASH_BOSS_ALARM: - if( sd ) - clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message - break; - case SC_MER_HP: - status_percent_heal(bl, 100, 0); // Recover Full HP - break; - case SC_MER_SP: - status_percent_heal(bl, 0, 100); // Recover Full SP - break; - case SC_PROMOTE_HEALTH_RESERCH: - status_percent_heal(bl, sce->val4, 0); - break; - case SC_ENERGY_DRINK_RESERCH: - status_percent_heal(bl, 0, sce->val4); - break; - /** - * Ranger - **/ - case SC_WUGDASH: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->run(bl, sd, SC_WUGDASH); - } - break; - case SC_COMBOATTACK: - switch (sce->val1) { - case TK_STORMKICK: - clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); - break; - case TK_DOWNKICK: - clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); - break; - case TK_TURNKICK: - clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); - break; - case TK_COUNTER: - clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); - break; - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - if (sd) - clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); - break; - case TK_JUMPKICK: - if (sd) - clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); - break; - case MO_TRIPLEATTACK: - if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) - clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); - break; - case SR_FALLENEMPIRE: - if (sd){ - clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); - clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); - } - break; - } - break; - case SC_RAISINGDRAGON: - sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] - break; - } - - if( opt_flag&2 && sd && sd->touching_id ) - npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range - - return 1; + return opt_flag; } /** @@ -13556,6 +13579,7 @@ void status_defaults(void) status->is_boss_resist_sc = status_is_boss_resist_sc; status->end_sc_before_start = status_end_sc_before_start; status->change_start_stop_action = status_change_start_stop_action; + status->change_start_set_option = status_change_start_set_option; status->calc_bl_ = status_calc_bl_; status->calc_mob_ = status_calc_mob_; status->calc_pet_ = status_calc_pet_; diff --git a/src/map/status.h b/src/map/status.h index 4260747b6..161f66f43 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -2335,6 +2335,7 @@ struct status_interface { bool (*is_boss_resist_sc) (enum sc_type type); bool (*end_sc_before_start) (struct block_list *bl, struct status_data *st, struct status_change* sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4); void (*change_start_stop_action) (struct block_list *bl, enum sc_type type); + int (*change_start_set_option) (struct block_list *bl, struct status_change* sc, enum sc_type type, int val1, int val2, int val3, int val4); int (*kaahi_heal_timer) (int tid, int64 tick, int id, intptr_t data); int (*change_timer) (int tid, int64 tick, int id, intptr_t data); int (*change_timer_sub) (struct block_list* bl, va_list ap); |