summaryrefslogtreecommitdiff
path: root/src/map/status.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/status.c')
-rw-r--r--src/map/status.c134
1 files changed, 125 insertions, 9 deletions
diff --git a/src/map/status.c b/src/map/status.c
index 37efe1f93..46df84473 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -719,6 +719,24 @@ void initChangeTables(void)
status->set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE );
status->set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT );
+ /**
+ * Summoner
+ */
+ status->set_sc(SU_HIDE, SC_SUHIDE, SI_SUHIDE, SCB_SPEED);
+ add_sc(SU_SCRATCH, SC_BLOODING);
+ status->set_sc(SU_STOOP, SC_SU_STOOP, SI_SU_STOOP, SCB_NONE);
+ status->set_sc(SU_FRESHSHRIMP, SC_FRESHSHRIMP, SI_FRESHSHRIMP, SCB_NONE);
+ add_sc(SU_SV_STEMSPEAR, SC_BLOODING);
+ status->set_sc(SU_CN_POWDERING, SC_CATNIPPOWDER, SI_CATNIPPOWDER, SCB_WATK | SCB_SPEED | SCB_REGEN);
+ add_sc(SU_CN_METEOR, SC_CURSE);
+ set_sc_with_vfx(SU_SV_ROOTTWIST, SC_SV_ROOTTWIST, SI_SV_ROOTTWIST, SCB_NONE);
+ add_sc(SU_SCAROFTAROU, SC_STUN );
+ status->set_sc(SU_SCAROFTAROU, SC_BITESCAR, SI_BITESCAR, SCB_NONE);
+ status->set_sc(SU_ARCLOUSEDASH, SC_ARCLOUSEDASH, SI_ARCLOUSEDASH, SCB_AGI | SCB_SPEED);
+ add_sc(SU_LUNATICCARROTBEAT, SC_STUN);
+ status->set_sc(SU_TUNAPARTY, SC_TUNAPARTY, SI_TUNAPARTY, SCB_NONE);
+ status->set_sc(SU_BUNCHOFSHRIMP, SC_SHRIMP, SI_SHRIMP, SCB_BATK | SCB_MATK);
+
// Elemental Spirit summoner's 'side' status changes.
status->set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE );
status->set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL );
@@ -997,6 +1015,9 @@ void initChangeTables(void)
status->dbs->IconChangeTable[SC_MAGICAL_FEATHER] = SI_MAGICAL_FEATHER;
status->dbs->IconChangeTable[SC_BLOSSOM_FLUTTERING] = SI_BLOSSOM_FLUTTERING;
+ // Summoner
+ status->dbs->IconChangeTable[SC_SPRITEMABLE] = SI_SPRITEMABLE;
+
// Other SC which are not necessarily associated to skills.
status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] |= SCB_ASPD;
status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION2] |= SCB_ASPD;
@@ -1347,6 +1368,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
status_change_end(target, SC_CLOAKING, INVALID_TIMER);
status_change_end(target, SC_CHASEWALK, INVALID_TIMER);
status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER);
+ status_change_end(target, SC_SUHIDE, INVALID_TIMER);
if ((sce=sc->data[SC_ENDURE]) && !sce->val4 && !sc->data[SC_LKCONCENTRATION]) {
//Endure count is only reduced by non-players on non-gvg maps.
//val4 signals infinite endure. [Skotlex]
@@ -1802,6 +1824,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
(sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD)
|| (sc->data[SC_AUTOCOUNTER] && !flag && skill_id)
|| (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_id != PA_GOSPEL)
+ || (sc->data[SC_SUHIDE] && skill_id != SU_HIDE)
)
return 0;
@@ -2381,7 +2404,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
//Give them all modes except these (useful for clones)
bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
- bstatus->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM;
+ bstatus->size = (sd->class_&JOBL_BABY || (sd->class_&MAPID_BASEMASK) == MAPID_SUMMONER)?SZ_SMALL:SZ_MEDIUM;
if (battle_config.character_size && (pc_isridingpeco(sd) || pc_isridingdragon(sd))) { //[Lupus]
if (sd->class_&JOBL_BABY) {
if (battle_config.character_size&SZ_BIG)
@@ -2393,7 +2416,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
}
bstatus->aspd_rate = 1000;
bstatus->ele_lv = 1;
- bstatus->race = RC_PLAYER;
+ bstatus->race = ((sd->class_&MAPID_BASEMASK) == MAPID_SUMMONER)?RC_BRUTE:RC_PLAYER;
// Autobonus
pc->delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true);
@@ -2696,6 +2719,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
bstatus->dex += skill_lv;
if((skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP))>0)
bstatus->int_ += skill_lv;
+ if ((pc->checkskill(sd,SU_POWEROFLAND)) > 0)
+ bstatus->int_ += 20;
// Bonuses from cards and equipment as well as base stat, remember to avoid overflows.
i = bstatus->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0];
@@ -2733,9 +2758,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
bstatus->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX);
// Absolute modifiers from passive skills
- if((skill_lv=pc->checkskill(sd,CR_TRUST))>0)
+ if ((skill_lv=pc->checkskill(sd,CR_TRUST)) > 0)
bstatus->max_hp += skill_lv*200;
+ if ((pc->checkskill(sd,SU_SPRITEMABLE)) > 0)
+ bstatus->max_hp += 1000;
+
// Apply relative modifiers from equipment
if(sd->hprate < 0)
sd->hprate = 0;
@@ -2768,6 +2796,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
bstatus->max_sp += 200 + 20 * skill_lv;
if( (skill_lv = pc->checkskill(sd,WM_LESSON)) > 0 )
bstatus->max_sp += 30 * skill_lv;
+ if ((pc->checkskill(sd,SU_SPRITEMABLE)) > 0)
+ bstatus->max_sp += 100;
// Apply relative modifiers from equipment
if(sd->sprate < 0)
@@ -2840,6 +2870,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
sd->critical_rate = 0;
if(sd->critical_rate != 100)
bstatus->cri = bstatus->cri * sd->critical_rate/100;
+ if (pc->checkskill(sd, SU_POWEROFLIFE) > 0)
+ bstatus->cri += 20;
if(sd->flee2_rate < 0)
sd->flee2_rate = 0;
@@ -2872,6 +2904,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
bstatus->hit += 3*skill_lv;
if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
bstatus->hit += 2*skill_lv;
+ if (pc->checkskill(sd, SU_POWEROFLIFE) > 0)
+ bstatus->hit += 20;
// ----- FLEE CALCULATION -----
@@ -2880,6 +2914,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
bstatus->flee += skill_lv*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3);
if((skill_lv=pc->checkskill(sd,MO_DODGE))>0)
bstatus->flee += (skill_lv*3)>>1;
+ if (pc->checkskill(sd, SU_POWEROFLIFE) > 0)
+ bstatus->flee += 20;
// ----- EQUIPMENT-DEF CALCULATION -----
// Apply relative modifiers from equipment
@@ -3175,6 +3211,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
clif->updatestatus(sd,SP_CARTINFO);
}
+ // Spirit Marble status activates automatically for a infinite
+ // amount of time when the skill is learned. Felt this was the
+ // best place to put this. [Rytech]
+ if (pc->checkskill(sd, SU_SPRITEMABLE))
+ sc_start(&sd->bl, &sd->bl, SC_SPRITEMABLE, 100, 1, INFINITE_DURATION);
+
calculating = 0;
return 0;
@@ -3584,6 +3626,10 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
regen->rate.hp += regen->rate.hp * sc->data[SC_BUCHEDENOEL]->val1 / 100;
regen->rate.sp += regen->rate.sp * sc->data[SC_BUCHEDENOEL]->val2 / 100;
}
+ if (sc->data[SC_CATNIPPOWDER]) {
+ regen->rate.hp *= 2;
+ regen->rate.sp *= 2;
+ }
}
#define status_get_homstr(st, hd) ((st)->str + (hd)->homunculus.str_value)
@@ -4581,9 +4627,12 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
if (sc->data[SC_2011RWC])
agi += sc->data[SC_2011RWC]->val1;
- if(sc->data[SC_MARSHOFABYSS])
+ if (sc->data[SC_MARSHOFABYSS])
agi -= agi * sc->data[SC_MARSHOFABYSS]->val2 / 100;
+ if (sc->data[SC_ARCLOUSEDASH])
+ agi += sc->data[SC_ARCLOUSEDASH]->val2;
+
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
@@ -4916,6 +4965,9 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc,
if (sc->data[SC_STEAMPACK])
batk += sc->data[SC_STEAMPACK]->val1;
+ if (sc->data[SC_SHRIMP])
+ batk += batk * sc->data[SC_SHRIMP]->val2 / 100;
+
return (unsigned short)cap_value(batk,0,USHRT_MAX);
}
@@ -5008,6 +5060,8 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100;
if( sc->data[SC_FLASHCOMBO] )
watk += sc->data[SC_FLASHCOMBO]->val2;
+ if (sc->data[SC_CATNIPPOWDER])
+ watk -= watk * sc->data[SC_CATNIPPOWDER]->val2 / 100;
return (unsigned short)cap_value(watk,0,USHRT_MAX);
}
@@ -5035,6 +5089,8 @@ unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc
matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2
if(sc->data[SC_IZAYOI])
matk += 25 * sc->data[SC_IZAYOI]->val1;
+ if (sc->data[SC_SHRIMP])
+ matk += matk * sc->data[SC_SHRIMP]->val2 / 100;
return (unsigned short)cap_value(matk,0,USHRT_MAX);
#else
return 0;
@@ -5721,6 +5777,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if (sc->data[SC_DEC_AGI] || sc->data[SC_QUAGMIRE] || sc->data[SC_DONTFORGETME])
return 0;
}
+ if (sc->data[SC_CATNIPPOWDER])
+ val = max(val, sc->data[SC_CATNIPPOWDER]->val3);
if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup
val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate );
@@ -5771,6 +5829,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
val = max(val, sc->data[SC_MOVHASTE_HORSE]->val1);
if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate < 0 ) // permanent item-based speedup
val = max( val, -(sd->bonus.speed_rate + sd->bonus.speed_add_rate) );
+ if (sc->data[SC_ARCLOUSEDASH])
+ val = max(val, sc->data[SC_ARCLOUSEDASH]->val3);
speed_rate -= val;
}
@@ -7507,6 +7567,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
break;
case SC_KYRIE:
+ case SC_TUNAPARTY:
if (bl->type == BL_MOB)
return 0;
break;
@@ -7770,12 +7831,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_OBLIVIONCURSE:
case SC_LEECHESEND:
- // Ranger Effects
+ // Ranger Effects
case SC_WUGBITE:
case SC_ELECTRICSHOCKER:
case SC_MAGNETICFIELD:
- // Masquerades
+ // Masquerades
case SC__ENERVATION:
case SC__GROOMY:
case SC__LAZINESS:
@@ -7786,7 +7847,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
// Other Effects
case SC_VACUUM_EXTREME:
case SC_NETHERWORLD:
-
+ case SC_FRESHSHRIMP:
+ case SC_SV_ROOTTWIST:
+ case SC_BITESCAR:
return 0;
}
}
@@ -9744,6 +9807,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (!mob->db_checkid(val1))
val1 = MOBID_PORING;
break;
+ case SC_SPRITEMABLE:
case SC_ALL_RIDING:
tick = INFINITE_DURATION;
break;
@@ -9754,6 +9818,36 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
**/
val2 = 20+(20*val1);
break;
+ /**
+ * Summoner
+ */
+ case SC_FRESHSHRIMP:
+ val4 = tick / (10000 - ((val1 - 1) * 1000));
+ tick_time = 10000 - ((val1 - 1) * 1000);
+ if (val4 <= 0) // Prevents a negeative value from happening
+ val4 = 0;
+ break;
+ case SC_ARCLOUSEDASH:
+ val2 = 15 + 5 * val1; // AGI
+ val3 = 25; // Move speed increase
+ if (sd && (sd->class_&MAPID_BASEMASK) == MAPID_SUMMONER)
+ val4 = 10; // Ranged ATK increase
+ break;
+ case SC_TUNAPARTY:
+ val2 = (st->max_hp * (val1 * 10) / 100); // %Max HP to absorb
+ break;
+ case SC_BITESCAR:
+ val2 = 2 * val1; // MHP% damage
+ val4 = tick / 1000;
+ tick_time = 1000;
+ break;
+ case SC_SHRIMP:
+ val2 = 10; // BATK%, MATK%
+ break;
+ case SC_CATNIPPOWDER:
+ val2 = 50; // WATK%, MATK%
+ val3 = 25 * val1; // Move speed reduction
+ break;
default:
if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) {
//Status change with no calc, no icon, and no skill associated...?
@@ -9966,6 +10060,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_NEEDLE_OF_PARALYZE:
case SC_DEATHBOUND:
case SC_NETHERWORLD:
+ case SC_SV_ROOTTWIST:
unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
break;
case SC_ANKLESNARE:
@@ -9980,6 +10075,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_CAMOUFLAGE:
case SC_SIREN:
case SC_ALL_RIDING:
+ case SC_SUHIDE:
unit->stop_attack(bl);
break;
case SC_SILENCE:
@@ -10823,10 +10919,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
break;
case SC_NEUTRALBARRIER_MASTER:
case SC_STEALTHFIELD_MASTER:
- if( sce->val2 ) {
+ case SC_SV_ROOTTWIST:
+ if (sce->val2) {
struct skill_unit_group* group = skill->id2group(sce->val2);
sce->val2 = 0;
- if( group ) /* might have been cleared before status ended, e.g. land protector */
+ if (group) /* might have been cleared before status ended, e.g. land protector */
skill->del_unitgroup(group,ALC_MARK);
}
break;
@@ -12018,6 +12115,19 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data)
return 0;
}
break;
+ case SC_FRESHSHRIMP:
+ if (--(sce->val4) >= 0) {
+ status_heal(bl, st->max_hp / 100, 0, 2);
+ sc_timer_next((10000 - ((sce->val1 - 1) * 1000)) + tick, status->change_timer, bl->id, data);
+ }
+ break;
+ case SC_BITESCAR:
+ if (--(sce->val4) >= 0) {
+ status_percent_damage(bl, bl, -(sce->val2), 0, 0);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
+ return 0;
+ }
+ break;
}
// default for all non-handled control paths is to end the status
@@ -12204,6 +12314,10 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
// Any +MATK you get from skills and cards, including cards in weapon, is added here.
if ( sd && sd->bonus.ematk > 0 && flag != 3 )
*matk_min += sd->bonus.ematk;
+ if (sd && pc->checkskill(sd, SU_POWEROFLAND) > 0) {
+ if (pc->checkskill(sd, SU_SV_STEMSPEAR) == 5 && pc->checkskill(sd, SU_CN_POWDERING) == 5 && pc->checkskill(sd, SU_CN_METEOR) == 5 && pc->checkskill(sd, SU_SV_ROOTTWIST) == 5)
+ *matk_min += *matk_min * 20 / 100;
+ }
if ( flag != 3 )
*matk_min = status->calc_ematk(bl, sc, *matk_min);
@@ -12215,6 +12329,8 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
if ( (st->rhw.matk + st->lhw.matk) > 0 ) {
int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks
int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level
+ if (sc != NULL && sc->data[SC_CATNIPPOWDER])
+ wMatk -= wMatk * sc->data[SC_CATNIPPOWDER]->val2 / 100;
*matk_min += wMatk - variance;
*matk_max += wMatk + variance;
}