diff options
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 134 |
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; } |