diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map/battle.c | 9 | ||||
-rw-r--r-- | src/map/mob.c | 7 | ||||
-rw-r--r-- | src/map/pc.c | 1 | ||||
-rw-r--r-- | src/map/skill.c | 181 | ||||
-rw-r--r-- | src/map/skill.h | 2 | ||||
-rw-r--r-- | src/map/status.c | 34 | ||||
-rw-r--r-- | src/map/status.h | 3 |
7 files changed, 177 insertions, 60 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index f06ab2292..046e64eb0 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1456,9 +1456,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if( sd && !skill_num ) { //Check for double attack. if( ( ( skill_lv = pc_checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER ) - || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) ) //Will fail bare-handed + || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) //Will fail bare-handed + || ( sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST )) // Need confirmation { //Success chance is not added, the higher one is used [Skotlex] - if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sd->bonus.double_rate ) ) + if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) { wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1); wd.type = 0x08; @@ -4441,6 +4442,10 @@ int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int if (rdamage < 1) rdamage = 1; } } + + if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability + rdamage = 0; + return rdamage; } diff --git a/src/map/mob.c b/src/map/mob.c index 1e9b3caf9..4ed1f3848 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -959,6 +959,8 @@ int mob_spawn (struct mob_data *md) md->attacked_id = 0; md->target_id = 0; md->move_fail_count = 0; + md->ud.state.attack_continue = 0; + md->ud.target_to = 0; if( md->spawn_timer != INVALID_TIMER ) { delete_timer(md->spawn_timer, mob_delayspawn); @@ -2132,10 +2134,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if(src && src->type == BL_MOB) mob_unlocktarget((struct mob_data *)src,tick); - - /* clear previous target otherwise we'll respawn aiming at the same dude */ - md->attacked_id = 0; - + if( sd ) { if( sd->mission_mobid == md->class_) { //TK_MISSION [Skotlex] if( ++sd->mission_count >= 100 && (temp = mob_get_random_id(0, 0xE, sd->status.base_level)) ) diff --git a/src/map/pc.c b/src/map/pc.c index d7cfe66e1..e3c7840ef 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4120,6 +4120,7 @@ int pc_useitem(struct map_session_data *sd,int n) sd->sc.data[SC_TRICKDEAD] || sd->sc.data[SC_HIDING] || sd->sc.data[SC__SHADOWFORM] || + sd->sc.data[SC_KAGEHUMI] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) )) return 0; diff --git a/src/map/skill.c b/src/map/skill.c index 966910c33..79ff1a490 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -112,7 +112,7 @@ int firewall_unit_pos; int icewall_unit_pos; int earthstrain_unit_pos; //early declaration -int skill_stasis_check(struct block_list *bl, int src_id, int skillid); +int skill_block_check(struct block_list *bl, enum sc_type type, int skillid); static int skill_check_unit_range (struct block_list *bl, int x, int y, int skillid, int skilllv); static int skill_check_unit_range2 (struct block_list *bl, int x, int y, int skillid, int skilllv); static int skill_destroy_trap( struct block_list *bl, va_list ap ); @@ -2053,6 +2053,9 @@ static int skill_magic_reflect(struct block_list* src, struct block_list* bl, in struct status_change *sc = status_get_sc(bl); struct map_session_data* sd = BL_CAST(BL_PC, bl); + if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability + return 0; + // item-based reflection if( sd && sd->bonus.magic_damage_return && type && rnd()%100 < sd->bonus.magic_damage_return ) return 1; @@ -2208,6 +2211,15 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds || (sc && sc->data[SC_REFLECTDAMAGE])) ) rdamage = battle_calc_return_damage(bl,src, &damage, dmg.flag, skillid); + if( damage && sc && sc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){ + struct block_list *nbl = NULL; + nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id); + if( nbl ){ // Only one target is chosen. + damage = damage / 2; // Deflect half of the damage to a target nearby + clif_skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); + } + } + //Skill hit type type=(skillid==0)?5:skill_get_hit(skillid); @@ -4701,8 +4713,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (tsc->data[SC_BERSERK]) heal = 0; //Needed so that it actually displays 0 when healing. } - heal_get_jobexp = status_heal(bl,heal,0,0); clif_skill_nodamage (src, bl, skillid, heal, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && heal && skillid != HLIF_HEAL ) + heal = ~heal + 1; + heal_get_jobexp = status_heal(bl,heal,0,0); if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){ heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100; @@ -6162,7 +6176,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case AM_CP_ARMOR: case AM_CP_HELM: { + unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; enum sc_type scid = (sc_type)(SC_STRIPWEAPON + (skillid - AM_CP_WEAPON)); + + if( sd && ( bl->type != BL_PC || ( dstsd && pc_checkequip(dstsd,equip[skillid - AM_CP_WEAPON]) < 0 ) ) ){ + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); // Don't consume item requirements + return 0; + } + status_change_end(bl, scid, INVALID_TIMER); clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); @@ -7511,8 +7533,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl) || (tsc && tsc->data[SC_BERSERK])) i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] - status_heal(bl, i, 0, 1); clif_skill_nodamage(bl, bl, skillid, i, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && i ) + i = ~i + 1; + status_heal(bl, i, 0, 1); } } else if( sd ) @@ -7648,7 +7672,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in **/ case WL_STASIS: if( flag&1 ) - sc_start2(bl,type,100,skilllv,src->id,skill_get_time(skillid,skilllv)); + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); else { map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid, skilllv),BL_CHAR,src,skillid,skilllv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill_castend_nodamage_id); @@ -8739,12 +8763,46 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in } break; + case OB_AKAITSUKI: + case OB_OBOROGENSOU: + if( sd && ( (skillid == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters. + || is_boss(bl) ) ){ // Does not work on Boss monsters. + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } case KO_IZAYOI: + case OB_ZANGETSU: + case KG_KYOMU: + case KG_KAGEMUSYA: clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); break; + case KG_KAGEHUMI: + if( flag&1 ){ + if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) || + tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || + tsc->data[SC_MARIONETTE] || tsc->data[SC_HARMONIZE])){ + sc_start(src, type, 100, skilllv, skill_get_time(skillid, skilllv)); + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + } + if( skill_area_temp[2] > 0){ + clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + sc_start(src, SC_STOP, 100, skilllv, skill_get_time(skillid, skilllv)); + } + }else{ + skill_area_temp[2] = 0; + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_nodamage_id); + } + break; default: if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) { if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd ) @@ -9982,7 +10040,8 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char sd->sc.data[SC_BASILICA] || sd->sc.data[SC_MARIONETTE] || sd->sc.data[SC_WHITEIMPRISON] || - (sd->sc.data[SC_STASIS] && skill_stasis_check(&sd->bl, sd->sc.data[SC_STASIS]->val2, skill_num)) || + (sd->sc.data[SC_STASIS] && skill_block_check(&sd->bl, SC_STASIS, skill_num)) || + (sd->sc.data[SC_KAGEHUMI] && skill_block_check(&sd->bl, SC_KAGEHUMI, skill_num)) || sd->sc.data[SC_OBLIVIONCURSE] || sd->sc.data[SC__MANHOLE] )) { @@ -10982,6 +11041,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( status_isimmune(bl) ) heal = 0; clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && heal ) + heal = ~heal + 1; status_heal(bl, heal, 0, 0); if( diff >= 500 ) sg->val1--; @@ -11196,6 +11257,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_BARDDANCER) ) break; // affects self only when soullinked heal = skill_calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); + if( tsc->data[SC_AKAITSUKI] && heal ) + heal = ~heal + 1; clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); status_heal(bl, heal, 0, 0); break; @@ -11477,9 +11540,11 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns struct status_change *ssc = status_get_sc(ss); if( ssc && ssc->data[SC_HEATER_OPTION] ) hp += hp * ssc->data[SC_HEATER_OPTION]->val3 / 100; - status_heal(bl, hp, 0, 0); if( tstatus->hp != tstatus->max_hp ) clif_skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0); + if( tsc && tsc->data[SC_AKAITSUKI] && hp ) + hp = ~hp + 1; + status_heal(bl, hp, 0, 0); sc_start(bl, SC_WARMER, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); } break; @@ -12589,6 +12654,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh return 0; } break; + case LG_REFLECTDAMAGE: + case CR_REFLECTSHIELD: + if( sc && sc->data[SC_KYOMU] && rand()%100 < 30){ + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; case KO_KAHU_ENTEN: case KO_HYOUHU_HUBUKI: case KO_KAZEHU_SEIRAN: @@ -16755,54 +16827,65 @@ void skill_init_unit_layout (void) } } -// Stasis skill usage check. [LimitLine/3CeAM] -int skill_stasis_check(struct block_list *bl, int src_id, int skillid) { + +int skill_block_check(struct block_list *bl, sc_type type , int skillid) { int inf = 0; - if( !bl || skillid < 1 ) - return 0; // Can do it - inf = skill_get_inf2(skillid); - if( inf == INF2_SONG_DANCE || /*skill_get_inf2(skillid) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL ) - return 1; // Can't do it. + struct status_change *sc = status_get_sc(bl); - switch( skillid ) - { - case NV_FIRSTAID: case TF_HIDING: case AS_CLOAKING: case WZ_SIGHTRASHER: - case RG_STRIPWEAPON: case RG_STRIPSHIELD: case RG_STRIPARMOR: case WZ_METEOR: - case RG_STRIPHELM: case SC_STRIPACCESSARY: case ST_FULLSTRIP: case WZ_SIGHTBLASTER: - case ST_CHASEWALK: case SC_ENERVATION: case SC_GROOMY: case WZ_ICEWALL: - case SC_IGNORANCE: case SC_LAZINESS: case SC_UNLUCKY: case WZ_STORMGUST: - case SC_WEAKNESS: case AL_RUWACH: case AL_PNEUMA: case WZ_JUPITEL: - case AL_HEAL: case AL_BLESSING: case AL_INCAGI: case WZ_VERMILION: - case AL_TELEPORT: case AL_WARP: case AL_HOLYWATER: case WZ_EARTHSPIKE: - case AL_HOLYLIGHT: case PR_IMPOSITIO: case PR_ASPERSIO: case WZ_HEAVENDRIVE: - case PR_SANCTUARY: case PR_STRECOVERY: case PR_MAGNIFICAT: case WZ_QUAGMIRE: - case ALL_RESURRECTION: case PR_LEXDIVINA: case PR_LEXAETERNA: case HW_GRAVITATION: - case PR_MAGNUS: case PR_TURNUNDEAD: case MG_SRECOVERY: case HW_MAGICPOWER: - case MG_SIGHT: case MG_NAPALMBEAT: case MG_SAFETYWALL: case HW_GANBANTEIN: - case MG_SOULSTRIKE: case MG_COLDBOLT: case MG_FROSTDIVER: case WL_DRAINLIFE: - case MG_STONECURSE: case MG_FIREBALL: case MG_FIREWALL: case WL_SOULEXPANSION: - case MG_FIREBOLT: case MG_LIGHTNINGBOLT: case MG_THUNDERSTORM: case MG_ENERGYCOAT: - case WL_WHITEIMPRISON: case WL_SUMMONFB: case WL_SUMMONBL: case WL_SUMMONWB: - case WL_SUMMONSTONE: case WL_SIENNAEXECRATE: case WL_RELEASE: case WL_EARTHSTRAIN: - case WL_RECOGNIZEDSPELL: case WL_READING_SB: case SA_MAGICROD: case SA_SPELLBREAKER: - case SA_DISPELL: case SA_FLAMELAUNCHER: case SA_FROSTWEAPON: case SA_LIGHTNINGLOADER: - case SA_SEISMICWEAPON: case SA_VOLCANO: case SA_DELUGE: case SA_VIOLENTGALE: - case SA_LANDPROTECTOR: case PF_HPCONVERSION: case PF_SOULCHANGE: case PF_SPIDERWEB: - case PF_FOGWALL: case TK_RUN: case TK_HIGHJUMP: case TK_SEVENWIND: - case SL_KAAHI: case SL_KAUPE: case SL_KAITE: - - // Skills that need to be confirmed. - case SO_FIREWALK: case SO_ELECTRICWALK: case SO_SPELLFIST: case SO_EARTHGRAVE: - case SO_DIAMONDDUST: case SO_POISON_BUSTER: case SO_PSYCHIC_WAVE: case SO_CLOUD_KILL: - case SO_STRIKING: case SO_WARMER: case SO_VACUUM_EXTREME: case SO_VARETYR_SPEAR: - case SO_ARRULLO: - return 1; // Can't do it. + if( !sc || !bl || skillid < 1 ) + return 0; // Can do it - default: - return 0; // Can do it. + switch(type){ + case SC_STASIS: + inf = skill_get_inf2(skillid); + if( inf == INF2_SONG_DANCE || /*skill_get_inf2(skillid) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL ) + return 1; // Can't do it. + switch( skillid ) + { + case NV_FIRSTAID: case TF_HIDING: case AS_CLOAKING: case WZ_SIGHTRASHER: + case RG_STRIPWEAPON: case RG_STRIPSHIELD: case RG_STRIPARMOR: case WZ_METEOR: + case RG_STRIPHELM: case SC_STRIPACCESSARY: case ST_FULLSTRIP: case WZ_SIGHTBLASTER: + case ST_CHASEWALK: case SC_ENERVATION: case SC_GROOMY: case WZ_ICEWALL: + case SC_IGNORANCE: case SC_LAZINESS: case SC_UNLUCKY: case WZ_STORMGUST: + case SC_WEAKNESS: case AL_RUWACH: case AL_PNEUMA: case WZ_JUPITEL: + case AL_HEAL: case AL_BLESSING: case AL_INCAGI: case WZ_VERMILION: + case AL_TELEPORT: case AL_WARP: case AL_HOLYWATER: case WZ_EARTHSPIKE: + case AL_HOLYLIGHT: case PR_IMPOSITIO: case PR_ASPERSIO: case WZ_HEAVENDRIVE: + case PR_SANCTUARY: case PR_STRECOVERY: case PR_MAGNIFICAT: case WZ_QUAGMIRE: + case ALL_RESURRECTION: case PR_LEXDIVINA: case PR_LEXAETERNA: case HW_GRAVITATION: + case PR_MAGNUS: case PR_TURNUNDEAD: case MG_SRECOVERY: case HW_MAGICPOWER: + case MG_SIGHT: case MG_NAPALMBEAT: case MG_SAFETYWALL: case HW_GANBANTEIN: + case MG_SOULSTRIKE: case MG_COLDBOLT: case MG_FROSTDIVER: case WL_DRAINLIFE: + case MG_STONECURSE: case MG_FIREBALL: case MG_FIREWALL: case WL_SOULEXPANSION: + case MG_FIREBOLT: case MG_LIGHTNINGBOLT: case MG_THUNDERSTORM: case MG_ENERGYCOAT: + case WL_WHITEIMPRISON: case WL_SUMMONFB: case WL_SUMMONBL: case WL_SUMMONWB: + case WL_SUMMONSTONE: case WL_SIENNAEXECRATE: case WL_RELEASE: case WL_EARTHSTRAIN: + case WL_RECOGNIZEDSPELL: case WL_READING_SB: case SA_MAGICROD: case SA_SPELLBREAKER: + case SA_DISPELL: case SA_FLAMELAUNCHER: case SA_FROSTWEAPON: case SA_LIGHTNINGLOADER: + case SA_SEISMICWEAPON: case SA_VOLCANO: case SA_DELUGE: case SA_VIOLENTGALE: + case SA_LANDPROTECTOR: case PF_HPCONVERSION: case PF_SOULCHANGE: case PF_SPIDERWEB: + case PF_FOGWALL: case TK_RUN: case TK_HIGHJUMP: case TK_SEVENWIND: + case SL_KAAHI: case SL_KAUPE: case SL_KAITE: + + // Skills that need to be confirmed. + case SO_FIREWALK: case SO_ELECTRICWALK: case SO_SPELLFIST: case SO_EARTHGRAVE: + case SO_DIAMONDDUST: case SO_POISON_BUSTER: case SO_PSYCHIC_WAVE: case SO_CLOUD_KILL: + case SO_STRIKING: case SO_WARMER: case SO_VACUUM_EXTREME: case SO_VARETYR_SPEAR: + case SO_ARRULLO: + return 1; // Can't do it. + } + break; + case SC_KAGEHUMI: + switch(skillid){ + case TF_HIDING: case AS_CLOAKING: case GC_CLOAKINGEXCEED: case SC_SHADOWFORM: + case MI_HARMONIZE: case CG_MARIONETTE: case AL_TELEPORT: case TF_BACKSLIDING: + case RA_CAMOUFLAGE: case ST_CHASEWALK: case GD_EMERGENCYCALL: + return 1; // needs more info + } + break; } - return 0; // Can Cast anything else like Weapon Skills + return 0; } int skill_get_elemental_type( int skill_id , int skill_lv ) { diff --git a/src/map/skill.h b/src/map/skill.h index f9f5607e4..f3b254b61 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -1788,7 +1788,7 @@ enum wl_spheres { WLS_STONE, }; int skill_spellbook (struct map_session_data *sd, int nameid); -int skill_stasis_check(struct block_list *bl, int src_id, int skillid); +int skill_block_check(struct block_list *bl, enum sc_type type, int skillid); /** * Guilottine Cross **/ diff --git a/src/map/status.c b/src/map/status.c index a89253a2d..c4a0e5583 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -718,6 +718,12 @@ void initChangeTables(void) { add_sc( KO_JYUSATSU , SC_CURSE ); set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE ); set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK ); + set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE ); + set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE ); + set_sc( KG_KAGEHUMI , SC_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE ); + set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK ); + 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 ); @@ -996,6 +1002,7 @@ void initChangeTables(void) { StatusChangeStateTable[SC_NETHERWORLD] |= SCS_NOMOVE; StatusChangeStateTable[SC_CAMOUFLAGE] |= SCS_NOMOVE|SCS_NOMOVECOND; StatusChangeStateTable[SC_MEIKYOUSISUI] |= SCS_NOMOVE; + StatusChangeStateTable[SC_KAGEHUMI] |= SCS_NOMOVE; /* StatusChangeState (SCS_) NOPICKUPITEMS */ StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM; @@ -1186,6 +1193,8 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_change_end(target, SC_DANCING, INVALID_TIMER); if(sc->data[SC_CLOAKINGEXCEED] && --(sc->data[SC_CLOAKINGEXCEED]->val2) <= 0) status_change_end(target, SC_CLOAKINGEXCEED, INVALID_TIMER); + if(sc->data[SC_KAGEMUSYA] && --(sc->data[SC_KAGEMUSYA]->val3) <= 0) + status_change_end(target, SC_KAGEMUSYA, INVALID_TIMER); } unit_skillcastcancel(target, 2); } @@ -1611,7 +1620,8 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int sc->cant.cast || (sc->data[SC_MARIONETTE] && skill_num != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it (sc->data[SC_MARIONETTE2] && skill_num == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another - (sc->data[SC_STASIS] && skill_stasis_check(src, sc->data[SC_STASIS]->val2, skill_num)) + (sc->data[SC_STASIS] && skill_block_check(src, SC_STASIS, skill_num)) || + (sc->data[SC_KAGEHUMI] && skill_block_check(src, SC_KAGEHUMI, skill_num)) )) return 0; @@ -4381,7 +4391,9 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan // renewal EDP increases your base atk by atk x skill level if( sc->data[SC_EDP] ) batk = batk * sc->data[SC_EDP]->val1; -#endif +#endif + if( sc->data[SC_ZANGETSU] ) + batk += batk * sc->data[SC_ZANGETSU]->val2 / 100; return (unsigned short)cap_value(batk,0,USHRT_MAX); } @@ -4506,6 +4518,8 @@ static unsigned short status_calc_matk(struct block_list *bl, struct status_chan matk += 70; if(sc->data[SC_IZAYOI]) matk += 50 * sc->data[SC_IZAYOI]->val1; + if( sc->data[SC_ZANGETSU] ) + matk += matk * sc->data[SC_ZANGETSU]->val2 / 100; return (unsigned short)cap_value(matk,0,USHRT_MAX); } @@ -8268,10 +8282,21 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 2*val1 + rand()%val1; clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); // Temporarily shows Poring need official [malufett] break; + case SC_KAGEMUSYA: + val3 = val1 * 2; case SC_IZAYOI: val2 = tick/1000; tick_time = 1000; break; + case SC_ZANGETSU: + val2 = status_get_lv(bl) / 2 + 50; + break; + case SC_GENSOU: + if( rand()%100 < 50) // needs more info + status_zap(bl, 500, 500); + else + status_heal(bl, 500, 500, 0); + break; default: if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) { //Status change with no calc, no icon, and no skill associated...? @@ -9880,7 +9905,10 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_RENOVATIO: if( --(sce->val4) >= 0 ) { - status_heal(bl, status->max_hp * 3 / 100, 0, 2); + int heal = status->max_hp * 3 / 100; + if( sc && sc->data[SC_AKAITSUKI] && heal ) + heal = ~heal + 1; + status_heal(bl, heal, 0, 2); sc_timer_next(5000 + tick, status_change_timer, bl->id, data); return 0; } diff --git a/src/map/status.h b/src/map/status.h index 0c684bcf9..5537064ae 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -633,7 +633,8 @@ typedef enum sc_type { SC_KYOMU, SC_KAGEMUSYA, SC_ZANGETSU, - SC_OBOROGENSOU, + SC_GENSOU, + SC_AKAITSUKI, SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; |