summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/status.c352
-rw-r--r--src/map/status.h1
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);