From ae57ff81700dbe6714ef107b34510457e9c9c5b6 Mon Sep 17 00:00:00 2001 From: glighta Date: Mon, 12 Nov 2012 00:06:25 +0000 Subject: -Add Homon-S skills, 1st implementation (all done except Eleanors) --Upd Skill conf to set land-limit for homonculus by default (ground skill limit) --Mv MH_HEILIGE_STANGE and MH_ANGRIFFS_MODUS skill from Eleanor to Bayeri -Enforce all zeny transaction to use pc_payzeny and pc_getzeny handlers, (auto log and clif) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16914 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/status.c | 216 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 171 insertions(+), 45 deletions(-) (limited to 'src/map/status.c') diff --git a/src/map/status.c b/src/map/status.c index 3b641cf92..282e2313b 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -491,6 +491,26 @@ void initChangeTables(void) { set_sc( HAMI_DEFENCE , SC_DEFENCE , SI_BLANK , SCB_DEF ); set_sc( HAMI_BLOODLUST , SC_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK ); + // Homunculus S + add_sc(MH_STAHL_HORN, SC_STUN); + set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP); + set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP); + add_sc( MH_STEINWAND, SC_SAFETYWALL ); + add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER); + set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD); + add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE); + set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); + set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE); + set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE); + set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE); + add_sc(MH_LAVA_SLIDE, SC_BURNING); + set_sc(MH_NEEDLE_OF_PARALYZE, SC_PARALYSIS, SI_NEEDLE_OF_PARALYZE, SCB_DEF2); + add_sc(MH_POISON_MIST, SC_BLIND); + set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD); + + add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE); + + add_sc( MER_CRASH , SC_STUN ); set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); add_sc( MS_MAGNUM , SC_WATK_ELEMENT ); @@ -728,13 +748,6 @@ void initChangeTables(void) { set_sc_with_vfx( OB_AKAITSUKI , SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE ); set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE ); - add_sc( MH_STAHL_HORN , SC_STUN ); - set_sc( MH_ANGRIFFS_MODUS , SC_ANGRIFFS_MODUS , SI_ANGRIFFS_MODUS , SCB_BATK|SCB_WATK|SCB_DEF|SCB_FLEE ); - set_sc( MH_GOLDENE_FERSE , SC_GOLDENE_FERSE , SI_GOLDENE_FERSE , SCB_SPEED|SCB_FLEE|SCB_ATK_ELE ); - add_sc( MH_LAVA_SLIDE , SC_BURNING ); - add_sc( MH_POISON_MIST , SC_BLIND ); - set_sc( MH_ERASER_CUTTER , SC_ERASER_CUTTER , SI_BLANK , SCB_NONE ); - // Storing the target job rather than simply SC_SPIRIT simplifies code later on. SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK, @@ -1034,6 +1047,9 @@ void initChangeTables(void) { StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOCAST; StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; + //Homon S + StatusChangeStateTable[SC_PARALYSIS] |= SCS_NOMOVE; + } static void initDummyData(void) @@ -1294,9 +1310,17 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s return hp+sp; } - - if( target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*)target)->state.rebirth ) - {// Ensure the monster has not already rebirthed before doing so. + if(target->type == BL_PC){ + TBL_PC *sd = BL_CAST(BL_PC,target); + TBL_HOM *hd = sd->hd; + if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){ + clif_skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill_get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage + clif_skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0)); + status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); + return hp + sp; + } + } + if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {// Ensure the monster has not already rebirthed before doing so. status_revive(target, sc->data[SC_REBIRTH]->val2, 0); status_change_clear(target,0); ((TBL_MOB*)target)->state.rebirth = 1; @@ -3254,6 +3278,7 @@ static unsigned short status_calc_dmotion(struct block_list *bl, struct status_c #ifdef RENEWAL_ASPD static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag); #endif +static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int); static unsigned int status_calc_maxhp(struct block_list *,struct status_change *,unsigned int); static unsigned int status_calc_maxsp(struct block_list *,struct status_change *,unsigned int); static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element); @@ -3809,10 +3834,10 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if(status->aspd_rate != 1000) // absolute percentage modifier amotion = ( 200 - (200-amotion/10) * status->aspd_rate / 1000 ) * 10; #endif - //fixed value added + //@TODO move FIGHTINGSPIRIT in fix_aspd if( sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) amotion -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) / 10 * 40; - + amotion = status_calc_fix_aspd(bl, sc, amotion); status->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); status->adelay = 2*status->amotion; @@ -3826,6 +3851,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if(status->aspd_rate != 1000) amotion = amotion*status->aspd_rate/1000; + amotion = status_calc_fix_aspd(bl, sc, amotion); status->amotion = cap_value(amotion,battle_config.max_aspd,2000); status->adelay = status->amotion; @@ -3838,6 +3864,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if(status->aspd_rate != 1000) amotion = amotion*status->aspd_rate/1000; + amotion = status_calc_fix_aspd(bl, sc, amotion); status->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000); temp = b_status->adelay*status->aspd_rate/1000; @@ -4407,10 +4434,17 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += sc->data[SC_FULL_SWING_K]->val1; if(sc->data[SC_ODINS_POWER]) batk += 70; - if(sc->data[SC_ANGRIFFS_MODUS]) - batk += batk * sc->data[SC_ANGRIFFS_MODUS]->val2/100; if( sc->data[SC_ZANGETSU] ) batk += batk * sc->data[SC_ZANGETSU]->val2 / 100; + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(status_get_element(bl) == ELE_WATER) //water type + batk /= 2; + } + if(sc->data[SC_PYROCLASTIC]) + batk += sc->data[SC_PYROCLASTIC]->val2; + if (sc->data[SC_ANGRIFFS_MODUS]) + batk += sc->data[SC_ANGRIFFS_MODUS]->val2; + return (unsigned short)cap_value(batk,0,USHRT_MAX); } @@ -4597,6 +4631,8 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change hit -= hit * 20 / 100; if(sc->data[SC_INSPIRATION]) hit += 5 * sc->data[SC_INSPIRATION]->val1; + if (sc->data[SC_ASH]) + hit /= 2; return (short)cap_value(hit,1,SHRT_MAX); } @@ -4668,14 +4704,18 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change flee += flee * sc->data[SC_ZEPHYR]->val2 / 100; if( sc->data[SC_MARSHOFABYSS] ) flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1); - if( sc->data[SC_ANGRIFFS_MODUS] ) - flee -= flee * sc->data[SC_ANGRIFFS_MODUS]->val3 / 100; - if( sc->data[SC_GOLDENE_FERSE ] ) - flee -= flee * sc->data[SC_GOLDENE_FERSE ]->val2 / 100; #ifdef RENEWAL if( sc->data[SC_SPEARQUICKEN] ) flee += 2 * sc->data[SC_SPEARQUICKEN]->val1; #endif + if (sc->data[SC_ANGRIFFS_MODUS]) + flee -= sc->data[SC_ANGRIFFS_MODUS]->val3; + if (sc->data[SC_OVERED_BOOST]) + flee = max(flee,sc->data[SC_OVERED_BOOST]->val2); + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ //mob + if(status_get_element(bl) == ELE_WATER) //water type + flee /= 2; + } return (short)cap_value(flee,1,SHRT_MAX); } @@ -4765,7 +4805,11 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, if(sc->data[SC_ODINS_POWER]) def -= 20; if( sc->data[SC_ANGRIFFS_MODUS] ) - def -= def * sc->data[SC_ANGRIFFS_MODUS]->val4 / 100; + def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(status_get_race(bl)==RC_PLANT) + def /= 2; + } return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);; } @@ -4823,6 +4867,12 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); if( sc->data[SC_GT_REVITALIZE] && sc->data[SC_GT_REVITALIZE]->val4) def2 += def2 * sc->data[SC_GT_REVITALIZE]->val4 / 100; + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(status_get_race(bl)==RC_PLANT) + def2 /= 2; + } + if (sc->data[SC_PARALYSIS]) + def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100; #ifdef RENEWAL return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); @@ -5212,6 +5262,28 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s } #endif +static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) { + if (!sc || !sc->count) + return cap_value(aspd, 0, 2000); + + if (!sc->data[SC_QUAGMIRE]) { + if (sc->data[SC_FIGHTINGSPIRIT]) + aspd += sc->data[SC_FIGHTINGSPIRIT]->val3; + if ((sc->data[SC_GUST_OPTION] + || sc->data[SC_BLAST_OPTION] + || sc->data[SC_WILD_STORM_OPTION]) + ) + aspd -= 50; // ventus passive = +5 ASPD + if (sc->data[SC_OVERED_BOOST]){ + aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10; + } +// if(sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) +// aspd -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) * 4; + } + + return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway +} + /// Calculates an object's ASPD modifier (alters the base amotion value). /// Note that the scale of aspd_rate is 1000 = 100%. static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate) @@ -5258,9 +5330,6 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * max < sc->data[SC_FLEET]->val2) max = sc->data[SC_FLEET]->val2; - if( sc->data[SC_GOLDENE_FERSE] && max < sc->data[SC_GOLDENE_FERSE]->val3 ) - max = sc->data[SC_GOLDENE_FERSE]->val3; - if(sc->data[SC_ASSNCROS] && max < sc->data[SC_ASSNCROS]->val2) { @@ -5346,6 +5415,10 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * aspd_rate -= sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1 * 10; if( sc->data[SC_INCASPDRATE] ) aspd_rate -= sc->data[SC_INCASPDRATE]->val1 * 10; + if( sc->data[SC_PAIN_KILLER]) + aspd_rate += sc->data[SC_PAIN_KILLER]->val2 * 10; + if( sc->data[SC_GOLDENE_FERSE]) + aspd_rate -= sc->data[SC_GOLDENE_FERSE]->val3 * 10; return (short)cap_value(aspd_rate,0,SHRT_MAX); } @@ -5416,6 +5489,10 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100; if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) maxhp += 500; + if (sc->data[SC_ANGRIFFS_MODUS]) + maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100; + if (sc->data[SC_GOLDENE_FERSE]) + maxhp += (maxhp * sc->data[SC_GOLDENE_FERSE]->val2) / 100; return cap_value(maxhp,1,UINT_MAX); } @@ -5516,8 +5593,8 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch return ELE_GHOST; if(sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON] ) return ELE_WATER; - if(sc->data[SC_GOLDENE_FERSE] && rand()%100 < sc->data[SC_GOLDENE_FERSE]->val4) - return ELE_HOLY; + if(sc->data[SC_PYROCLASTIC]) + return ELE_FIRE; return (unsigned char)cap_value(element,0,UCHAR_MAX); } @@ -6118,6 +6195,9 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti case SC_KYOUGAKU: tick -= 30*status->int_; break; + case SC_PARALYSIS: + tick -= 50 * (status->vit + status->luk); //(1000/20); + break; default: //Effect that cannot be reduced? Likely a buff. if (!(rnd()%10000 < rate)) @@ -6306,6 +6386,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val undead_flag = battle_check_undead(status->race,status->def_ele); //Check for inmunities / sc fails switch (type) { + case SC_ANGRIFFS_MODUS: + case SC_GOLDENE_FERSE: + if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS]) + || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE]) + ) + return 0; case SC_STONE: if(sc->data[SC_POWER_OF_GAIA]) return 0; @@ -6609,6 +6695,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_BURNING: // Place here until we have info about its behavior on Boss-monsters. [pakpil] case SC_MARSHOFABYSS: case SC_ADORAMUS: + case SC_PARALYSIS: // Exploit prevention - kRO Fix case SC_PYREXIA: @@ -7654,16 +7741,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = 3*val1; //Leech chance val4 = 20; //Leech percent break; - case SC_ANGRIFFS_MODUS: - val2 = 70 + 30*val1; //atk - val3 = 50 + 20*val1; //flee - val4 = 60 + 20*val1; //def - break; - case SC_GOLDENE_FERSE: - val2 = 20 + 10*val1; //flee - val3 = 10 + 4*val1; //aspd - val4 = 2 + 2*val1; //chance to issue holy-ele attack - break; case SC_FLEET: val2 = 30*val1; //Aspd change val3 = 5+5*val1; //bAtk/wAtk rate change @@ -8318,7 +8395,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_KYOUGAKU: val2 = 2*val1 + rand()%val1; - clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); + clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); break; case SC_KAGEMUSYA: val3 = val1 * 2; @@ -8351,6 +8428,41 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100); } break; + case SC_ANGRIFFS_MODUS: + val2 = 50 + 20 * val1; //atk bonus + val3 = 40 + 20 * val1; // Flee reduction. + val4 = tick/1000; // hp/sp reduction timer + tick_time = 1000; + break; + case SC_GOLDENE_FERSE: + val2 = 10 + 10*val1; //max hp bonus + val3 = 6 + 4 * val1; // Aspd Bonus + val4 = 2 + 2 * val1; // Chance of holy attack + break; + case SC_OVERED_BOOST: + val2 = 300 + 40*val1; //flee bonus + val3 = 179 + 2*val1; //aspd bonus + break; + case SC_GRANITIC_ARMOR: + val2 = 2*val1; //dmg reduction + val3 = 6*val1; //dmg on status end + break; + case SC_MAGMA_FLOW: + val2 = 3*val1; //activation chance + break; + case SC_PYROCLASTIC: + val2 += 10*val1; //atk bonus + break; + case SC_PARALYSIS: //[Lighta] need real info + val2 = 2*val1; //def reduction + val3 = 500*val1; //varcast augmentation + break; + case SC_PAIN_KILLER: //[Lighta] need real info + val2 = 2*val1; //aspd reduction % + val3 = 2*val1; //dmg reduction % + if(sc->data[SC_PARALYSIS]) + sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration + break; default: if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) { //Status change with no calc, no icon, and no skill associated...? @@ -8407,6 +8519,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_NETHERWORLD: case SC_MEIKYOUSISUI: case SC_KYOUGAKU: + case SC_PARALYSIS: unit_stop_walking(bl,1); break; case SC_HIDING: @@ -8877,6 +8990,17 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const vd = status_get_viewdata(bl); calc_flag = StatusChangeFlagTable[type]; switch(type){ + case SC_GRANITIC_ARMOR:{ + int dammage = status->max_hp*sce->val3/100; + if(status->hp < dammage) //to not kill him + dammage = status->hp-1; + status_damage(NULL, bl, dammage,0,0,1); + break; + } + case SC_PYROCLASTIC: + if(bl->type == BL_PC) + skill_break_equip(bl,EQP_WEAPON,10000,BCT_SELF); + break; case SC_WEDDING: case SC_XMAS: case SC_SUMMER: @@ -10274,8 +10398,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_WIND_STEP: case SC_STONE_SHIELD: case SC_SOLID_SKIN: - if( !status_charge(bl,0,sce->val2) ) - { + if( !status_charge(bl,0,sce->val2) ){ struct block_list *s_bl = battle_get_master(bl); if( s_bl ) status_change_end(s_bl,type+1,INVALID_TIMER); @@ -10286,8 +10409,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) return 0; case SC_STOMACHACHE: - if( --(sce->val4) > 0 ) - { + if( --(sce->val4) > 0 ){ status_charge(bl,0,sce->val2); // Reduce 8 every 10 seconds. if( sd && !pc_issit(sd) ) // Force to sit every 10 seconds. { @@ -10308,8 +10430,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) sc_timer_next(600000 + tick, status_change_timer, bl->id, data); return 0; case SC_MEIKYOUSISUI: - if( --(sce->val4) > 0 ) - { + if( --(sce->val4) > 0 ){ status_heal(bl, status->max_hp * (sce->val1+1) / 100, status->max_sp * sce->val1 / 100, 0); sc_timer_next(1000 + tick, status_change_timer, bl->id, data); return 0; @@ -10317,12 +10438,17 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_IZAYOI: case SC_KAGEMUSYA: - if( --(sce->val2) > 0 ) - { - if(!status_charge(bl, 0, 1)) - break; + if( --(sce->val2) > 0 ){ + if(!status_charge(bl, 0, 1)) break; sc_timer_next(1000+tick, status_change_timer, bl->id, data); return 0; + } + break; + case SC_ANGRIFFS_MODUS: + if(--(sce->val4) >= 0) { //drain hp/sp + if( !status_charge(bl,100,20) ) break; + sc_timer_next(1000+tick,status_change_timer,bl->id, data); + return 0; } break; } -- cgit v1.2.3-60-g2f50