From da898e993549046daa47d7ad423ac8d4c2db46a0 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sun, 19 Feb 2012 17:49:23 +0000 Subject: Initial support for Wanderer and Minstrel, and a few adjustments here and there for other classes. - credits to 3ceam for the base. - should you step by any bugs let us know, http://rathena.org/board/tracker git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@15616 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 22 ++- src/map/skill.c | 464 ++++++++++++++++++++++++++++++++++++++++++++++++------- src/map/skill.h | 6 +- src/map/status.c | 312 +++++++++++++++++++++++++++++-------- src/map/status.h | 24 +-- 5 files changed, 689 insertions(+), 139 deletions(-) (limited to 'src/map') diff --git a/src/map/battle.c b/src/map/battle.c index 1853b9cf1..d15c45b63 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -2165,6 +2165,22 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo case SR_RIDEINLIGHTNING: skillratio += 200 * skill_lv -100; break; + case WM_REVERBERATION_MELEE: + skillratio += 200 + 100 * pc_checkskill(sd, WM_REVERBERATION); + break; + case WM_SEVERE_RAINSTORM_MELEE: + skillratio = 50 + 50 * skill_lv; + break; + case WM_GREAT_ECHO: + skillratio += 800 + 100 * skill_lv; + if( sd ) { // Still need official value [pakpil] + short lv = (short)skill_lv; + skillratio += 100 * skill_check_pc_partner(sd,skill_num,&lv,skill_get_splash(skill_num,skill_lv),0); + } + break; + case WM_SOUND_OF_DESTRUCTION: + skillratio += 400; + break; } ATK_RATE(skillratio); @@ -4265,14 +4281,16 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f case MS_MAGNUM: case RA_DETONATOR: case RA_SENSITIVEKEEN: + case GN_CRAZYWEED: state |= BCT_ENEMY; strip_enemy = 0; break; default: return 0; } - } else if (su->group->skill_id==WZ_ICEWALL) - { + } else if (su->group->skill_id==WZ_ICEWALL || + su->group->skill_id == GN_WALLOFTHORN || + su->group->skill_id == WM_REVERBERATION) { state |= BCT_ENEMY; strip_enemy = 0; } else //Excepting traps and icewall, you should not be able to target skills. diff --git a/src/map/skill.c b/src/map/skill.c index cac203aba..1bd44b612 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -75,7 +75,11 @@ struct s_skill_db skill_db[MAX_SKILL_DB]; struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB]; - +struct s_skill_improvise_db { + int skillid; + short per;//1-10000 +}; +struct s_skill_improvise_db skill_improvise_db[MAX_SKILL_IMPROVISE_DB]; bool skill_reproduce_db[MAX_SKILL_DB]; //Warlock @@ -554,6 +558,14 @@ int skillnotok (int skillid, struct map_session_data *sd) return 1; } break; + case WM_LULLABY_DEEPSLEEP: + case WM_SIRCLEOFNATURE: + if( !map_flag_vs(m) ) { + clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. + return 1; + } + break; + } return (map[m].flag.noskill); } @@ -1235,6 +1247,38 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int case SR_HOWLINGOFLION: sc_start(bl, SC_FEAR, 5 + 5 * skilllv, skilllv, skill_get_time(skillid, skilllv)); break; + case WM_SOUND_OF_DESTRUCTION: + if( rand()%100 < 5 + 5 * skilllv ) { // Temporarly Check Until We Get the Official Formula + status_change_end(bl, SC_DANCING, INVALID_TIMER); + status_change_end(bl, SC_RICHMANKIM, INVALID_TIMER); + status_change_end(bl, SC_ETERNALCHAOS, INVALID_TIMER); + status_change_end(bl, SC_DRUMBATTLE, INVALID_TIMER); + status_change_end(bl, SC_NIBELUNGEN, INVALID_TIMER); + status_change_end(bl, SC_INTOABYSS, INVALID_TIMER); + status_change_end(bl, SC_SIEGFRIED, INVALID_TIMER); + status_change_end(bl, SC_WHISTLE, INVALID_TIMER); + status_change_end(bl, SC_ASSNCROS, INVALID_TIMER); + status_change_end(bl, SC_POEMBRAGI, INVALID_TIMER); + status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER); + status_change_end(bl, SC_HUMMING, INVALID_TIMER); + status_change_end(bl, SC_FORTUNE, INVALID_TIMER); + status_change_end(bl, SC_SERVICE4U, INVALID_TIMER); + status_change_end(bl, SC_LONGING, INVALID_TIMER); + status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); + status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + status_change_end(bl, SC_WINKCHARM, INVALID_TIMER); + status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); + status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); + status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + } + break; } if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) @@ -1901,8 +1945,9 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in break; case BL_SKILL: su = (struct skill_unit *)target; - if( su->group->unit_id == UNT_ANKLESNARE ) - return 0; // ankle snare cannot be knocked back + if( su && su->group && (su->group->unit_id == UNT_ANKLESNARE || su->group->unit_id == UNT_ELECTRICSHOCKER + || su->group->unit_id == UNT_CLUSTERBOMB || su->group->unit_id == UNT_REVERBERATION) ) + return 0; // ankle snare, electricshocker, clusterbomb, reverberation cannot be knocked back break; } @@ -2236,9 +2281,13 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case LG_OVERBRAND_PLUSATK: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,5); break; - /** - * Arch Bishop - **/ + case WM_SEVERE_RAINSTORM_MELEE: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skilllv,5); + break; + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6); + break; case AB_DUPLELIGHT_MELEE: case AB_DUPLELIGHT_MAGIC: dmg.amotion = 300; @@ -2268,6 +2317,13 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case WL_CHAINLIGHTNING_ATK: copy_skill = WL_CHAINLIGHTNING; break; + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + copy_skill = WM_REVERBERATION; + break; + case WM_SEVERE_RAINSTORM_MELEE: + copy_skill = WM_SEVERE_RAINSTORM; + break; case LG_OVERBRAND_BRANDISH: case LG_OVERBRAND_PLUSATK: copy_skill = LG_OVERBRAND; @@ -2462,16 +2518,25 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds } } if( damage > 0 ) { - if( skillid == RK_CRUSHSTRIKE ) // Your weapon will not be broken if you miss. - skill_break_equip(src,EQP_WEAPON,10000,BCT_SELF); - - if( skillid == GC_VENOMPRESSURE ) { - struct status_change *ssc = status_get_sc(src); - if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skilllv ) { - sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON,ssc->data[SC_POISONINGWEAPON]->val1)); - status_change_end(src,SC_POISONINGWEAPON,-1); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } + /** + * Post-damage effects + **/ + switch( skillid ) { + case RK_CRUSHSTRIKE: + skill_break_equip(src,EQP_WEAPON,10000,BCT_SELF); + break; + case GC_VENOMPRESSURE: { + struct status_change *ssc = status_get_sc(src); + if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skilllv ) { + sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON,ssc->data[SC_POISONINGWEAPON]->val1)); + status_change_end(src,SC_POISONINGWEAPON,-1); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + } + break; + case WM_METALICSOUND: + status_zap(bl, 0, damage*100/(100*(110-pc_checkskill(sd,WM_LESSON)*10))); + break; } } @@ -2933,6 +2998,10 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) } } break; + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + skill_attack(skill_get_type(skl->skill_id),src, src, target, skl->skill_id, skl->skill_lv, 0, SD_LEVEL); + break; case SC_FATALMENACE: if( src == target ) // Casters Part unit_warp(src, -1, skl->x, skl->y, 3); @@ -3044,6 +3113,18 @@ int skill_cleartimerskill (struct block_list *src) } return 1; } +static int skill_ative_reverberation( struct block_list *bl, va_list ap) { + struct skill_unit *su = (TBL_SKILL*)bl; + struct skill_unit_group *sg; + if( bl->type != BL_SKILL ) + return 0; + if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION ) { + clif_changetraplook(bl, UNT_USED_TRAPS); + su->limit=DIFF_TICK(gettick(),sg->tick)+1500; + sg->unit_id = UNT_USED_TRAPS; + } + return 0; +} static int skill_reveal_trap (struct block_list *bl, va_list ap) { @@ -3210,6 +3291,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case SR_CRESCENTELBOW_AUTOSPELL: case SR_GATEOFHELL: case SR_GENTLETOUCH_QUIET: + case WM_SEVERE_RAINSTORM_MELEE: + case WM_GREAT_ECHO: skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; @@ -3431,6 +3514,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case SR_RAMPAGEBLASTER: case SR_WINDMILL: case SR_RIDEINLIGHTNING: + case WM_REVERBERATION: + case WM_SOUND_OF_DESTRUCTION: if( flag&1 ) { //Recursive invocation // skill_area_temp[0] holds number of targets in area @@ -3578,18 +3663,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case NJ_KOUENKA: case NJ_HYOUSENSOU: case NJ_HUUJIN: - - /** - * Arch Bishop - **/ case AB_ADORAMUS: case AB_RENOVATIO: case AB_HIGHNESSHEAL: case AB_DUPLELIGHT_MAGIC: - /** - * Warlock - **/ case WL_HELLINFERNO: + case WM_METALICSOUND: skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); break; @@ -4136,12 +4215,15 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); } else skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); - } - else + } else 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_damage_id); clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); break; + case WM_LULLABY_DEEPSLEEP: + if( rand()%100 < 88 + 2 * skilllv ) + sc_start(bl,status_skill2sc(skillid),100,skilllv,skill_get_time(skillid,skilllv)); + break; case 0: if(sd) { @@ -4224,8 +4306,20 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if(status_isdead(src)) return 1; - if( src != bl && status_isdead(bl) && skillid != ALL_RESURRECTION && skillid != PR_REDEMPTIO && skillid != NPC_WIDESOULDRAIN ) - return 1; + if( src != bl && status_isdead(bl) ) { + /** + * Skills that may be cast on dead targets + **/ + switch( skillid ) { + case NPC_WIDESOULDRAIN: + case PR_REDEMPTIO: + case ALL_RESURRECTION: + case WM_DEADHILLHERE: + break; + default: + return 1; + } + } tstatus = status_get_status_data(bl); sstatus = status_get_status_data(src); @@ -7752,6 +7846,173 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in } clif_skill_nodamage(src,bl,skillid,skilllv,1); break; + case WA_SWING_DANCE: + case WA_MOONLIT_SERENADE: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + else if( sd ) { // Only shows effects on caster. + clif_skill_nodamage(src,bl,skillid,skilllv,1); + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + } + break; + + case WA_SYMPHONY_OF_LOVER: + case MI_RUSH_WINDMILL: + case MI_ECHOSONG: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start4(bl,type,100,skilllv,6*skilllv,(sd?pc_checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill_get_time(skillid,skilllv)); + else if( sd ) { // Only shows effects on caster. + clif_skill_nodamage(src,bl,skillid,skilllv,1); + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + } + break; + + case MI_HARMONIZE: + clif_skill_nodamage(src, bl, skillid, skilllv,sc_start(bl, type, 100, skilllv, skill_get_time(skillid,skilllv))); + break; + + case WM_DEADHILLHERE: + if( bl->type == BL_PC ) { + if( !status_isdead(bl) ) + break; + + if( rand()%100 < 88 + 2 * skilllv ) { + int heal = tstatus->sp; + if( heal <= 0 ) + heal = 1; + tstatus->hp = heal; + tstatus->sp -= tstatus->sp * ( 120 - 20 * skilllv ) / 100; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + pc_revive((TBL_PC*)bl,heal,0); + clif_resurrection(bl,1); + } + } + break; + + case WM_SIRCLEOFNATURE: + flag |= BCT_PARTY|BCT_SELF; + case WM_VOICEOFSIREN: + if( flag&1 ) { + sc_start2(bl,type,(skillid==WM_VOICEOFSIREN)?20+10*skilllv:100,skilllv,(skillid==WM_VOICEOFSIREN)?src->id:0,skill_get_time(skillid,skilllv)); + } else { + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),(skillid==WM_VOICEOFSIREN)?BL_CHAR:BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case WM_GLOOMYDAY: + if( dstsd ) { + if( pc_checkskill(dstsd,KN_BRANDISHSPEAR) || pc_checkskill(dstsd,LK_SPIRALPIERCE) || + pc_checkskill(dstsd,CR_SHIELDCHARGE) || pc_checkskill(dstsd,CR_SHIELDBOOMERANG) || + pc_checkskill(dstsd,PA_SHIELDCHAIN) || pc_checkskill(dstsd,LG_SHIELDPRESS) ) + { + sc_start(bl,SC_GLOOMYDAY_SK,100,skilllv,skill_get_time(skillid,skilllv)); + } else + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } else + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + break; + + case WM_SATURDAY_NIGHT_FEVER: + if( flag&1 ) { // Affect to all targets arround the caster and caster too. + if( !(tsc && tsc->data[type]) ) + sc_start(bl, type, 100, skilllv,skill_get_time(skillid, skilllv)); + } else if( flag&2 ) { + if( src->id != bl->id && battle_check_target(src,bl,BCT_ENEMY) > 0 ) + status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); + } else if( sd ) { + if( !sd->status.party_id ) { + clif_skill_fail(sd,skillid,0x11,0); + break; + } + if( map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid,skilllv), + BL_PC, src, skillid, skilllv, tick, BCT_ENEMY, skill_area_sub_count) > 7 ) + flag |= 2; + else + flag |= 1; + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|BCT_SELF, skill_castend_nodamage_id); + clif_skill_nodamage(src, bl, skillid, skilllv, + sc_start(src,SC_STOP,100,skilllv,skill_get_time2(skillid,skilllv))); + if( flag&2 ) // Dealed here to prevent conflicts + status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); + } + break; + + case WM_SONG_OF_MANA: + case WM_DANCE_WITH_WUG: + case WM_LERADS_DEW: + if( flag&1 ) { // These affect to to all party members near the caster. + struct status_change *sc = status_get_sc(src); + if( sc && sc->data[type] ) { + sc_start2(bl,type,100,skilllv,sc->data[type]->val2,skill_get_time(skillid,skilllv)); + } + } else if( sd ) { + short lv = (short)skilllv; + int count = skill_check_pc_partner(sd,skillid,&lv,skill_get_splash(skillid,skilllv),1); + if( sc_start2(bl,type,100,skilllv,count,skill_get_time(skillid,skilllv)) ) + party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skillid,skilllv),src,skillid,skilllv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + + } + break; + + case WM_MELODYOFSINK: + case WM_BEYOND_OF_WARCRY: + case WM_UNLIMITED_HUMMING_VOICE: + if( flag&1 ) { + sc_start2(bl,type,100,skilllv,skill_area_temp[0],skill_get_time(skillid,skilllv)); + } else { // These affect to all targets arround the caster. + short lv = (short)skilllv; + skill_area_temp[0] = (sd) ? skill_check_pc_partner(sd,skillid,&lv,skill_get_splash(skillid,skilllv),1) : 50; // 50% chance in non BL_PC (clones). + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case WM_RANDOMIZESPELL: { + int improv_skillid = 0, improv_skilllv; + do { + i = rand() % MAX_SKILL_IMPROVISE_DB; + improv_skillid = skill_improvise_db[i].skillid; + } while( improv_skillid == 0 || rand()%10000 >= skill_improvise_db[i].per ); + improv_skilllv = 4 + skilllv; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + + if( sd ) { + sd->skillitem = improv_skillid; + sd->skillitemlv = improv_skilllv; + clif_item_skill(sd, improv_skillid, improv_skilllv); + } else { + struct unit_data *ud = unit_bl2ud(src); + int inf = skill_get_inf(improv_skillid); + int target_id = 0; + if (!ud) break; + if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { + if (src->type == BL_PET) + bl = (struct block_list*)((TBL_PET*)src)->msd; + if (!bl) bl = src; + unit_skilluse_id(src, bl->id, improv_skillid, improv_skilllv); + } else { + if (ud->target) + target_id = ud->target; + else switch (src->type) { + case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; + case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + } + if (!target_id) + break; + if (skill_get_casttype(improv_skillid) == CAST_GROUND) { + bl = map_id2bl(target_id); + if (!bl) bl = src; + unit_skilluse_pos(src, bl->x, bl->y, improv_skillid, improv_skilllv); + } else + unit_skilluse_id(src, target_id, improv_skillid, improv_skilllv); + } + } + } + break; + case RETURN_TO_ELDICASTES: case ALL_GUARDIAN_RECALL: @@ -8053,7 +8314,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) skill_blockpc_start(sd,BD_ADAPTATION,3000); } - if( sd && ud->skillid != SA_ABRACADABRA ) // Hocus-Pocus has just set the data so leave it as it is.[Inkfish] + if( sd && ud->skillid != SA_ABRACADABRA && ud->skillid != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] sd->skillitem = sd->skillitemlv = 0; if (ud->skilltimer == INVALID_TIMER) { @@ -8433,6 +8694,9 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk case SC_CHAOSPANIC: case SC_BLOODYLUST: case SC_MAELSTROM: + case WM_REVERBERATION: + case WM_SEVERE_RAINSTORM: + case WM_POEMOFNETHERWORLD: flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). case GS_GROUNDDRIFT: //Ammo should be deleted right away. skill_unitsetting(src,skillid,skilllv,x,y,0); @@ -8680,16 +8944,12 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk } } break; - /** - * Mechanic - **/ + case NC_COLDSLOWER: case NC_ARMSCANNON: - /** - * Rune Knight - **/ case RK_DRAGONBREATH: case RK_WINDCUTTER: + case WM_LULLABY_DEEPSLEEP: i = skill_get_splash(skillid,skilllv); map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,BL_CHAR, src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); @@ -8829,6 +9089,19 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk } else if( sd ) clif_skill_fail(sd,skillid,USESKILL_FAIL,0); break; + + case WM_DOMINION_IMPULSE: + i = skill_get_splash(skillid, skilllv); + map_foreachinarea( skill_ative_reverberation, + src->m, x-i, y-i, x+i,y+i,BL_SKILL); + break; + + case WM_GREAT_ECHO: + flag|=1; // Should counsume 1 item per skill usage. + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_castend_damage_id); + break; + + default: ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid); return 1; @@ -8879,7 +9152,7 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char sd->sc.data[SC_ROKISWEIL] || sd->sc.data[SC_AUTOCOUNTER] || sd->sc.data[SC_STEELBODY] || - sd->sc.data[SC_DANCING] || + (sd->sc.data[SC_DANCING] && skill_num < RK_ENCHANTBLADE && !pc_checkskill(sd, WM_LESSON)) || sd->sc.data[SC_BERSERK] || sd->sc.data[SC_BASILICA] || sd->sc.data[SC_MARIONETTE] || @@ -9341,9 +9614,6 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli break; } - /** - * Guilotine Cross - **/ case GC_POISONSMOKE: if( !(sc && sc->data[SC_POISONINGWEAPON]) ) return NULL; @@ -9351,12 +9621,16 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison limit = 4000 + 2000 * skilllv; break; - /** - * Royal Guard - **/ case LG_BANDING: limit = -1; break; + case WM_REVERBERATION: + interval = limit; + val2 = 1; + case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + return NULL; + break; } nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)+subunt, limit, interval)); @@ -9456,6 +9730,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli if (val1 < 1) val1 = 1; val2 = 0; break; + case WM_REVERBERATION: + val1 = 1; + break; default: if (group->state.song_dance&0x1) val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance @@ -10188,6 +10465,13 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( battle_check_target(&src->bl, bl, BCT_ENEMY) ) skill_attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0); break; + case UNT_NETHERWORLD: + if( !(status_get_mode(bl)&MD_BOSS) ) { + if( !(tsc && tsc->data[type]) ) + sc_start(bl, type, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); + } + break; + } if (sg->state.magic_power && sc && !sc->data[SC_MAGICPOWER]) @@ -10415,6 +10699,7 @@ int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int dam case UNT_TALKIEBOX: case UNT_ANKLESNARE: case UNT_ICEWALL: + case UNT_REVERBERATION: src->val1-=damage; break; case UNT_BLASTMINE: @@ -10517,32 +10802,36 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short* static int c=0; static int p_sd[2] = { 0, 0 }; int i; + bool is_chorus = ( skill_get_inf2(skill_id)&INF2_CHORUS_SKILL ); if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) - return 99; //As if there were infinite partners. + return is_chorus ? MAX_PARTY : 99; //As if there were infinite partners. - if (cast_flag) - { //Execute the skill on the partners. + if (cast_flag) { //Execute the skill on the partners. struct map_session_data* tsd; - switch (skill_id) - { + switch (skill_id) { case PR_BENEDICTIO: - for (i = 0; i < c; i++) - { + for (i = 0; i < c; i++) { if ((tsd = map_id2sd(p_sd[i])) != NULL) status_charge(&tsd->bl, 0, 10); } return c; case AB_ADORAMUS: - if( c > 0 && (tsd = map_id2sd(p_sd[0])) != NULL ) - { + if( c > 0 && (tsd = map_id2sd(p_sd[0])) != NULL ) { i = 2 * (*skill_lv); status_charge(&tsd->bl, 0, i); } break; + case WM_GREAT_ECHO: + for( i = 0; i < c; i++ ) { + if( (tsd = map_id2sd(p_sd[i])) != NULL ) + status_zap(&tsd->bl,0,skill_get_sp(skill_id,*skill_lv)/c); + } + break; default: //Warning: Assuming Ensemble skills here (for speed) - if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map_id2sd(p_sd[0])) != NULL) - { + if( is_chorus ) + break;//Chorus skills are not to be parsed as ensambles + if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map_id2sd(p_sd[0])) != NULL) { sd->sc.data[SC_DANCING]->val4 = tsd->bl.id; sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill_get_time(skill_id,*skill_lv)+1000); clif_skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1); @@ -10556,9 +10845,12 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short* //Else: new search for partners. c = 0; memset (p_sd, 0, sizeof(p_sd)); - i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id); + if( is_chorus ) + i = party_foreachsamemap(skill_check_condition_char_sub,sd,AREA_SIZE,&sd->bl, &c, &p_sd, skill_id, *skill_lv); + else + i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id); - if (skill_id != PR_BENEDICTIO) //Apply the average lv to encore skills. + if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET ) //Apply the average lv to encore skills. *skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners. return c; } @@ -11150,6 +11442,16 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh return 0; } break; + case WM_GREAT_ECHO: { + int count; + count = skill_check_pc_partner(sd, skill, &lv, skill_get_splash(skill,lv), 0); + if( count < 1 ) { + clif_skill_fail(sd,skill,0x11,0); + return 0; + } else + require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party. + } + break; } switch(require.state) { @@ -11811,7 +12113,7 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv) nullpo_ret(bl); sd = BL_CAST(BL_PC, bl); - if (skill_id == SA_ABRACADABRA) + if (skill_id == SA_ABRACADABRA || skill_id == WM_RANDOMIZESPELL) return 0; //Will use picked skill's delay. if (bl->type&battle_config.no_skill_delay) @@ -12734,6 +13036,13 @@ static int skill_trap_splash (struct block_list *bl, va_list ap) if(skill_attack(BF_MISC,ss,bl,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) clif_skill_damage(bl,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5); break; + case UNT_REVERBERATION: + skill_attack(BF_WEAPON,ss,src,bl,WM_REVERBERATION_MELEE,sg->skill_lv,tick,0); + skill_addtimerskill(ss,tick+200,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,SD_LEVEL); + break; + case UNT_SEVERE_RAINSTORM: + skill_attack(BF_WEAPON,ss,ss,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0); + break; default: skill_attack(skill_get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0); break; @@ -13356,6 +13665,18 @@ static int skill_unit_timer_sub (DBKey key, void* data, va_list ap) } break; + case UNT_REVERBERATION: + if( unit->val1 <= 0 ) { // If it was deactivated. + skill_delunit(unit); + break; + } + clif_changetraplook(bl,UNT_USED_TRAPS); + map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); + group->limit = DIFF_TICK(tick,group->tick) + 1500; + unit->limit = DIFF_TICK(tick,group->tick) + 1500; + group->unit_id = UNT_USED_TRAPS; + break; + case UNT_FEINTBOMB: { struct block_list *src = map_id2bl(group->src_id); if( src ) @@ -13387,9 +13708,6 @@ static int skill_unit_timer_sub (DBKey key, void* data, va_list ap) case UNT_FREEZINGTRAP: case UNT_TALKIEBOX: case UNT_ANKLESNARE: - /** - * Ranger - **/ case UNT_ELECTRICSHOCKER: case UNT_CLUSTERBOMB: if( unit->val1 <= 0 ) { @@ -13401,6 +13719,10 @@ static int skill_unit_timer_sub (DBKey key, void* data, va_list ap) } } break; + case UNT_REVERBERATION: + if( unit->val1 <= 0 ) + unit->limit = DIFF_TICK(tick + 700,group->tick); + break; } } @@ -15211,6 +15533,31 @@ static bool skill_parse_row_spellbookdb(char* split[], int columns, int current) return false; } +static bool skill_parse_row_improvisedb(char* split[], int columns, int current) +{// SkillID + int i = atoi(split[0]); + short j = atoi(split[1]); + + if( !skill_get_index(i) || !skill_get_max(i) ) { + ShowError("skill_improvise_db: Invalid skill ID %d\n", i); + return false; + } + if ( !skill_get_inf(i) ) { + ShowError("skill_improvise_db: Passive skills cannot be casted (%d/%s)\n", i, skill_get_name(i)); + return false; + } + if( j < 1 ) { + ShowError("skill_improvise_db: Chances have to be 1 or above! (%d/%s)\n", i, skill_get_name(i)); + return false; + } + if( current >= MAX_SKILL_IMPROVISE_DB ) { + ShowError("skill_improvise_db: Maximum amount of entries reached (%d), increase MAX_SKILL_IMPROVISE_DB\n",MAX_SKILL_IMPROVISE_DB); + } + skill_improvise_db[current].skillid = i; + skill_improvise_db[current].per = j; // Still need confirm it. + + return true; +} static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) { int i = atoi(split[0]); @@ -15305,6 +15652,7 @@ static void skill_readdb(void) //Guillotine Cross sv_readdb(db_path, "magicmushroom_db.txt" , ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill_parse_row_magicmushroomdb); sv_readdb(db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill_parse_row_reproducedb); + sv_readdb(db_path, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb); } diff --git a/src/map/skill.h b/src/map/skill.h index 7c325adde..cc6ba6898 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -18,6 +18,7 @@ struct status_change_entry; #define MAX_SKILL_ARROW_DB 150 #define MAX_ARROW_RESOURCE 5 #define MAX_SKILL_ABRA_DB 350 +#define MAX_SKILL_IMPROVISE_DB 50 #define MAX_SKILL_LEVEL 100 @@ -64,7 +65,8 @@ enum e_skill_inf2 INF2_PARTY_ONLY = 0x0400, INF2_GUILD_ONLY = 0x0800, INF2_NO_ENEMY = 0x1000, - INF2_NOLP = 0x2000, // Spells that can ignore Land Protector + INF2_NOLP = 0x2000, // Spells that can ignore Land Protector + INF2_CHORUS_SKILL = 0x4000, // Chorus skill }; //Walk intervals at which chase-skills are attempted to be triggered. @@ -1534,7 +1536,7 @@ enum { UNT_SEVERE_RAINSTORM, //TODO UNT_FIREWALK, //TODO UNT_ELECTRICWALK, //TODO - UNT_POEMOFNETHERWORLD, //TODO + UNT_NETHERWORLD, //TODO UNT_PSYCHIC_WAVE, //TODO UNT_CLOUD_KILL, //TODO UNT_POISONSMOKE, //TODO diff --git a/src/map/status.c b/src/map/status.c index 3c3c8248f..564307285 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -536,9 +536,9 @@ void initChangeTables(void) set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD ); set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK); - ///** - // * Shadow Chaser - // **/ + /** + * Shadow Chaser + **/ set_sc( SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE ); set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE ); set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE ); @@ -567,27 +567,27 @@ void initChangeTables(void) set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GT_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE ); set_sc( SR_GENTLETOUCH_CHANGE , SC_GT_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_BATK|SCB_ASPD|SCB_DEF|SCB_MDEF ); set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GT_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_DEF2|SCB_REGEN|SCB_ASPD|SCB_SPEED ); - ///** - // * Wanderer / Mistrel - // **/ - //set_sc( WA_SWING_DANCE , SC_SWINGDANCE , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD ); - //set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONYOFLOVER , SI_SYMPHONYOFLOVERS , SCB_MDEF ); - //set_sc( WA_MOONLIT_SERENADE , SC_MOONLITSERENADE , SI_MOONLITSERENADE , SCB_MATK ); - //set_sc( MI_RUSH_WINDMILL , SC_RUSHWINDMILL , SI_RUSHWINDMILL , SCB_BATK ); - //set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 ); - //set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); - //set_sc( WM_POEMOFNETHERWORLD , SC_STOP , SI_NETHERWORLD , SCB_NONE ); - //set_sc( WM_VOICEOFSIREN , SC_VOICEOFSIREN , SI_VOICEOFSIREN , SCB_NONE ); - //set_sc( WM_LULLABY_DEEPSLEEP , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE ); - //set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE ); - //set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD ); - //set_sc( WM_SONG_OF_MANA , SC_SONGOFMANA , SI_SONGOFMANA , SCB_NONE ); - //set_sc( WM_DANCE_WITH_WUG , SC_DANCEWITHWUG , SI_DANCEWITHWUG , SCB_ASPD ); - //set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAYNIGHTFEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); - //set_sc( WM_LERADS_DEW , SC_LERADSDEW , SI_LERADSDEW , SCB_MAXHP ); - //set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK ); - //set_sc( WM_BEYOND_OF_WARCRY , SC_BEYONDOFWARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK ); - //set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITEDHUMMINGVOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE ); + /** + * Wanderer / Minstrel + **/ + set_sc( WA_SWING_DANCE , SC_SWINGDANCE , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD ); + set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONYOFLOVER , SI_SYMPHONYOFLOVERS , SCB_MDEF ); + set_sc( WA_MOONLIT_SERENADE , SC_MOONLITSERENADE , SI_MOONLITSERENADE , SCB_MATK ); + set_sc( MI_RUSH_WINDMILL , SC_RUSHWINDMILL , SI_RUSHWINDMILL , SCB_BATK ); + set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 ); + set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc( WM_POEMOFNETHERWORLD , SC_STOP , SI_NETHERWORLD , SCB_NONE ); + set_sc( WM_VOICEOFSIREN , SC_VOICEOFSIREN , SI_VOICEOFSIREN , SCB_NONE ); + set_sc( WM_LULLABY_DEEPSLEEP , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE ); + set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE ); + set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD ); + set_sc( WM_SONG_OF_MANA , SC_SONGOFMANA , SI_SONGOFMANA , SCB_NONE ); + set_sc( WM_DANCE_WITH_WUG , SC_DANCEWITHWUG , SI_DANCEWITHWUG , SCB_ASPD ); + set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAYNIGHTFEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); + set_sc( WM_LERADS_DEW , SC_LERADSDEW , SI_LERADSDEW , SCB_MAXHP ); + set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK ); + set_sc( WM_BEYOND_OF_WARCRY , SC_BEYONDOFWARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK ); + set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITEDHUMMINGVOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE ); ///** // * Sorcerer // **/ @@ -1015,6 +1015,8 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_change_end(target, SC_BERSERK, INVALID_TIMER); if( sc->data[SC_RAISINGDRAGON] && status->hp <= 1000 ) status_change_end(target, SC_RAISINGDRAGON, -1); + if (sc->data[SC_SATURDAYNIGHTFEVER] && status->hp <= 100) + status_change_end(target, SC_SATURDAYNIGHTFEVER, -1); } switch (target->type) @@ -1344,7 +1346,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int if(sc && sc->count) { - if(sc->opt1 >0 && sc->opt1 != OPT1_BURNING) + if(sc->opt1 >0 && sc->opt1 != OPT1_BURNING && skill_num != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc if (flag != 1) //Can't cast, casted stuff can't damage. return 0; @@ -1378,8 +1380,12 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int } } - if (sc->data[SC_DANCING] && flag!=2) - { + if (sc->data[SC_DANCING] && flag!=2) { + if( src->type == BL_PC && skill_num >= WA_SWING_DANCE && skill_num <= WM_UNLIMITED_HUMMING_VOICE ) + { // Lvl 5 Lesson or higher allow you use 3rd job skills while dancing.v + if( pc_checkskill((TBL_PC*)src,WM_LESSON) < 5 ) + return 0; + } if(sc->data[SC_LONGING]) { //Allow everything except dancing/re-dancing. [Skotlex] if (skill_num == BD_ENCORE || @@ -1413,7 +1419,10 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int sc->data[SC_WHITEIMPRISON] || (sc->data[SC_STASIS] && skill_stasis_check(src, sc->data[SC_STASIS]->val2, skill_num)) || sc->data[SC__INVISIBILITY] || - sc->data[SC__IGNORANCE] || + sc->data[SC_CRYSTALIZE] || + sc->data[SC__IGNORANCE] || // Target afflicted with this debuff cannot use skills or magic. + sc->data[SC_DEEPSLEEP] || + sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC_CURSEDCIRCLE_TARGET] )) return 0; @@ -1544,6 +1553,9 @@ int status_check_visibility(struct block_list *src, struct block_list *target) if (src->m != target->m || !check_distance_bl(src, target, view_range)) return 0; + if( tsc && tsc->data[SC_STEALTHFIELD] ) + return 0; + switch (target->type) { //Check for chase-walk/hiding/cloaking opponents. case BL_PC: @@ -3100,6 +3112,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str || sc->data[SC_BLEEDING] || sc->data[SC_MAGICMUSHROOM] || sc->data[SC_RAISINGDRAGON] + || sc->data[SC_SATURDAYNIGHTFEVER] ) //No regen regen->flag = 0; @@ -3677,13 +3690,16 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang str += ((sc->data[SC_MARIONETTE2]->val3)>>16)&0xFF; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && str < 50) str = 50; - /** - * RK Rune Skill - **/ if(sc->data[SC_GIANTGROWTH]) str += 30; + if(sc->data[SC_HARMONIZE]) + str += sc->data[SC_HARMONIZE]->val2; + if(sc->data[SC_SAVAGE_STEAK]) + str += sc->data[SC_SAVAGE_STEAK]->val1; if(sc->data[SC_INSPIRATION]) str += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + str -= sc->data[SC_STOMACHACHE]->val1; return (unsigned short)cap_value(str,0,USHRT_MAX); } @@ -3723,13 +3739,17 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang agi += ((sc->data[SC_MARIONETTE2]->val3)>>8)&0xFF; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && agi < 50) agi = 50; - /** - * Arch Bishop - **/ if(sc->data[SC_ADORAMUS]) agi -= sc->data[SC_ADORAMUS]->val2; + if(sc->data[SC_HARMONIZE]) + agi += sc->data[SC_HARMONIZE]->val2; + if(sc->data[SC_DROCERA_HERB_STEAMED]) + agi += sc->data[SC_DROCERA_HERB_STEAMED]->val1; if(sc->data[SC_INSPIRATION]) agi += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + agi -= sc->data[SC_STOMACHACHE]->val1; + return (unsigned short)cap_value(agi,0,USHRT_MAX); } @@ -3759,10 +3779,19 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang vit -= sc->data[SC_MARIONETTE]->val3&0xFF; if(sc->data[SC_MARIONETTE2]) vit += sc->data[SC_MARIONETTE2]->val3&0xFF; - if(sc->data[SC_INSPIRATION]) - vit += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50) vit = 50; + if(sc->data[SC_LAUDAAGNUS]) + vit += 4 + sc->data[SC_LAUDAAGNUS]->val1; + if(sc->data[SC_HARMONIZE]) + vit += sc->data[SC_HARMONIZE]->val2; + if(sc->data[SC_MINOR_BBQ]) + vit += sc->data[SC_MINOR_BBQ]->val1; + if(sc->data[SC_INSPIRATION]) + vit += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + vit -= sc->data[SC_STOMACHACHE]->val1; + return (unsigned short)cap_value(vit,0,USHRT_MAX); } @@ -3800,12 +3829,20 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; if(sc->data[SC_MARIONETTE2]) int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; - if(sc->data[SC_INSPIRATION]) - int_ += sc->data[SC_INSPIRATION]->val3; - if(sc->data[SC__STRIPACCESSORY]) - int_ -= int_ * sc->data[SC__STRIPACCESSORY]->val2 / 100; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && int_ < 50) int_ = 50; + if(sc->data[SC_MANDRAGORA]) + int_ -= 5 + 5 * sc->data[SC_MANDRAGORA]->val1; + if(sc->data[SC__STRIPACCESSORY]) + int_ -= int_ * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_HARMONIZE]) + int_ += sc->data[SC_HARMONIZE]->val2; + if(sc->data[SC_COCKTAIL_WARG_BLOOD]) + int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1; + if(sc->data[SC_INSPIRATION]) + int_ += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + int_ -= sc->data[SC_STOMACHACHE]->val1; return (unsigned short)cap_value(int_,0,USHRT_MAX); } @@ -3846,12 +3883,18 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; if(sc->data[SC_MARIONETTE2]) dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF; - if(sc->data[SC_INSPIRATION]) - dex += sc->data[SC_INSPIRATION]->val3; - if(sc->data[SC__STRIPACCESSORY]) - dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && dex < 50) dex = 50; + if(sc->data[SC__STRIPACCESSORY]) + dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_HARMONIZE]) + dex += sc->data[SC_HARMONIZE]->val2; + if(sc->data[SC_SIROMA_ICE_TEA]) + dex += sc->data[SC_SIROMA_ICE_TEA]->val1; + if(sc->data[SC_INSPIRATION]) + dex += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + dex -= sc->data[SC_STOMACHACHE]->val1; return (unsigned short)cap_value(dex,0,USHRT_MAX); } @@ -3879,12 +3922,23 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang luk -= sc->data[SC_MARIONETTE]->val4&0xFF; if(sc->data[SC_MARIONETTE2]) luk += sc->data[SC_MARIONETTE2]->val4&0xFF; - if(sc->data[SC_INSPIRATION]) - luk += sc->data[SC_INSPIRATION]->val3; - if(sc->data[SC__STRIPACCESSORY]) - luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100; if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50) luk = 50; + if(sc->data[SC_LAUDARAMUS]) + luk += 4 + sc->data[SC_LAUDARAMUS]->val1; + if(sc->data[SC__STRIPACCESSORY]) + luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_HARMONIZE]) + luk += sc->data[SC_HARMONIZE]->val2; + if(sc->data[SC_PUTTI_TAILS_NOODLES]) + luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1; + if(sc->data[SC_INSPIRATION]) + luk += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + luk -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_BANANA_BOMB]) + luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100; + return (unsigned short)cap_value(luk,0,USHRT_MAX); } @@ -3925,8 +3979,18 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC__BLOODYLUST]) batk += batk * 32 / 100; + if(sc->data[SC_RUSHWINDMILL]) + batk += batk * sc->data[SC_RUSHWINDMILL]->val2/100; + if(sc->data[SC_SATURDAYNIGHTFEVER]) + batk += 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1; + if(sc->data[SC_MELODYOFSINK]) + batk -= batk * sc->data[SC_MELODYOFSINK]->val3/100; + if(sc->data[SC_BEYONDOFWARCRY]) + batk += batk * sc->data[SC_BEYONDOFWARCRY]->val3/100; if(sc->data[SC_GT_CHANGE]) batk += batk * sc->data[SC_GT_CHANGE]->val3 / 100; + if(sc->data[SC_FULL_SWING_K]) + batk += sc->data[SC_FULL_SWING_K]->val1; #if RE_EDP /** * in RE EDP increases your base atk by atk x Skill Level. @@ -3980,12 +4044,30 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100; if(sc->data[SC_MERC_ATKUP]) watk += sc->data[SC_MERC_ATKUP]->val2; + if(sc->data[SC_FIGHTINGSPIRIT]) + watk += sc->data[SC_FIGHTINGSPIRIT]->val1; + if(sc->data[SC__ENERVATION]) + watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; + if(sc->data[SC__BLOODYLUST]) + watk += watk * 32 / 100; + if(sc->data[SC_STRIKING]) + watk += sc->data[SC_STRIKING]->val2; if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) watk += sc->data[SC_SHIELDSPELL_DEF]->val2; if(sc->data[SC_INSPIRATION]) watk += sc->data[SC_INSPIRATION]->val2; if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 ) watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); + if( sc->data[SC_TROPIC_OPTION] ) + watk += sc->data[SC_TROPIC_OPTION]->val2; + if( sc->data[SC_HEATER_OPTION] ) + watk += sc->data[SC_HEATER_OPTION]->val2; + if( sc->data[SC_WATER_BARRIER] ) + watk -= sc->data[SC_WATER_BARRIER]->val3; + if( sc->data[SC_PYROTECHNIC_OPTION] ) + watk += sc->data[SC_PYROTECHNIC_OPTION]->val2; + if( sc && sc->data[SC_TIDAL_WEAPON] ) + watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100; #if RE_EDP /** @@ -4013,6 +4095,20 @@ static unsigned short status_calc_matk(struct block_list *bl, struct status_chan matk += matk * sc->data[SC_MINDBREAKER]->val2/100; if(sc->data[SC_INCMATKRATE]) matk += matk * sc->data[SC_INCMATKRATE]->val1/100; + if(sc->data[SC_MOONLITSERENADE]) + matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100; + if(sc->data[SC_MELODYOFSINK]) + matk += matk * sc->data[SC_MELODYOFSINK]->val3/100; + if(sc->data[SC_BEYONDOFWARCRY]) + matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100; + if(sc->data[SC_MANA_PLUS]) + matk += sc->data[SC_MANA_PLUS]->val1; + if(sc->data[SC_AQUAPLAY_OPTION]) + matk += sc->data[SC_AQUAPLAY_OPTION]->val2; + if(sc->data[SC_CHILLY_AIR_OPTION]) + matk += sc->data[SC_CHILLY_AIR_OPTION]->val2; + if(sc->data[SC_WATER_BARRIER]) + matk -= sc->data[SC_WATER_BARRIER]->val3; return (unsigned short)cap_value(matk,0,USHRT_MAX); } @@ -4032,6 +4128,8 @@ static signed short status_calc_critical(struct block_list *bl, struct status_ch critical += sc->data[SC_TRUESIGHT]->val2; if(sc->data[SC_CLOAKING]) critical += critical; + if(sc->data[SC_STRIKING]) + critical += sc->data[SC_STRIKING]->val1; if(sc->data[SC__INVISIBILITY]) critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100; if(sc->data[SC_CAMOUFLAGE]) @@ -4214,8 +4312,10 @@ static signed short status_calc_flee2(struct block_list *bl, struct status_chang def -= def * sc->data[SC_STRIPSHIELD]->val2/100; if (sc->data[SC_FLING]) def -= def * (sc->data[SC_FLING]->val2)/100; + if(sc->data[SC_STONEHARDSKIN])// Final DEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + def += sc->data[SC_STONEHARDSKIN]->val1; if( sc->data[SC_FREEZING] ) - def -= def * 3 / 10; + def -= def * 10 / 100; if( sc->data[SC_MARSHOFABYSS] ) def -= def * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; if( sc->data[SC_ANALYZE] ) @@ -4321,6 +4421,8 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1; if(sc->data[SC_CONCENTRATION]) mdef += 1; //Skill info says it adds a fixed 1 Mdef point. + if(sc->data[SC_STONEHARDSKIN])// Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + mdef += sc->data[SC_STONEHARDSKIN]->val1; if( sc->data[SC_MARSHOFABYSS] ) mdef -= mdef * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; if(sc->data[SC_ANALYZE]) @@ -4332,6 +4434,7 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change if(sc->data[SC_WATER_BARRIER]) mdef += sc->data[SC_WATER_BARRIER]->val2; + #if REMODE return (short)cap_value(mdef,SHRT_MIN,SHRT_MAX); #else @@ -4494,6 +4597,13 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, sc->data[SC_CLOAKINGEXCEED]->val3); if( sc->data[SC_GT_REVITALIZE] ) val = max( val, sc->data[SC_GT_REVITALIZE]->val2 ); + if( sc->data[SC_SWINGDANCE] ) + val = max( val, sc->data[SC_SWINGDANCE]->val2 ); + if( sc->data[SC_GT_REVITALIZE] ) + val = max( val, sc->data[SC_GT_REVITALIZE]->val2 ); + if( sc->data[SC_WIND_STEP_OPTION] ) + val = max( val, sc->data[SC_WIND_STEP_OPTION]->val2 ); + //FIXME: official items use a single bonus for this [ultramage] if( sc->data[SC_SPEEDUP0] ) // temporary item-based speedup val = max( val, 25 ); @@ -4717,17 +4827,26 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang maxhp -= maxhp * 15 / 100; if(sc->data[SC__WEAKNESS]) maxhp -= maxhp * sc->data[SC__WEAKNESS]->val2 / 100; + if(sc->data[SC_LERADSDEW]) + maxhp += maxhp * sc->data[SC_LERADSDEW]->val3 / 100; if(sc->data[SC_FORCEOFVANGUARD]) maxhp += maxhp * 3 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; + if(sc->data[SC_INSPIRATION]) //Custom value. + maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100; if(sc->data[SC_RAISINGDRAGON]) maxhp += maxhp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; if(sc->data[SC_GT_CHANGE]) maxhp -= maxhp * (2 * sc->data[SC_GT_CHANGE]->val1) / 100; if(sc->data[SC_GT_REVITALIZE]) maxhp += maxhp * (3 * sc->data[SC_GT_REVITALIZE]->val1) / 100; - if(sc->data[SC_INSPIRATION]) //Custom value. - maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100; - + if(sc->data[SC_MUSTLE_M]) + maxhp += maxhp * sc->data[SC_MUSTLE_M]->val1/100; + if(sc->data[SC_SOLID_SKIN_OPTION]) + maxhp += 2000;// Fix amount. + if(sc->data[SC_POWER_OF_GAIA]) + maxhp += 3000; + if(sc->data[SC_MYSTERIOUS_POWDER]) + maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100; return cap_value(maxhp,1,UINT_MAX); } @@ -4745,6 +4864,8 @@ static unsigned int status_calc_maxsp(struct block_list *bl, struct status_chang maxsp += maxsp * sc->data[SC_MERC_SPUP]->val2/100; if(sc->data[SC_RAISINGDRAGON]) maxsp += maxsp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; + if(sc->data[SC_LIFE_FORCE_F]) + maxsp += maxsp * sc->data[SC_LIFE_FORCE_F]->val1/100; return cap_value(maxsp,1,UINT_MAX); } @@ -4816,6 +4937,8 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch return ELE_DARK; if(sc->data[SC_GHOSTWEAPON] || sc->data[SC__INVISIBILITY]) return ELE_GHOST; + if(sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON] ) + return ELE_WATER; return (unsigned char)cap_value(element,0,UCHAR_MAX); } @@ -5299,6 +5422,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti case SC_STONE: case SC_QUAGMIRE: case SC_SUITON: + case SC_SWINGDANCE: case SC__ENERVATION: case SC__GROOMY: case SC__IGNORANCE: @@ -5326,6 +5450,10 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti case SC_SLEEP: sc_def = 3 +status->int_; break; + case SC_DEEPSLEEP: + tick_def = status->int_ / 10 + status_get_lv(bl) * 65 / 1000; // Seems to be -1 sec every 10 int and -5% chance every 10 int. + sc_def = 5 * status->int_ /10; + break; case SC_DECREASEAGI: case SC_ADORAMUS://Arch Bishop if (sd) tick>>=1; //Half duration for players. @@ -5359,9 +5487,6 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti if (sd) //Duration greatly reduced for players. tick /= 15; //No defense against it (buff). - /** - * 3rd stuff - **/ case SC_WHITEIMPRISON: rate -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; // Lineal Reduction of Rate //tick_def = (int)floor(log10(status_get_lv(bl)) * 10.); @@ -5379,8 +5504,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti sc_def = status->int_*4/5; //FIXME: info said this is the formula of status chance. Check again pls. [Jobbie] break; case SC_ELECTRICSHOCKER: - case SC_BITE: - { + case SC_BITE: { if( bl->type == BL_MOB ) tick -= 1000 * (status->agi/10); if( sd && type != SC_ELECTRICSHOCKER ) @@ -5577,8 +5701,7 @@ 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) - { + switch (type) { case SC_STONE: if(sc->data[SC_POWER_OF_GAIA]) return 0; @@ -5870,8 +5993,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } //Before overlapping fail, one must check for status cured. - switch (type) - { + switch (type) { case SC_BLESSING: //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] @@ -5930,8 +6052,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); break; case SC_BERSERK: - if(battle_config.berserk_cancels_buffs) - { + if(battle_config.berserk_cancels_buffs) { status_change_end(bl, SC_ONEHAND, INVALID_TIMER); status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); @@ -6004,6 +6125,45 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_FOOD_LUK_CASH: status_change_end(bl, SC_LUKFOOD, INVALID_TIMER); break; + case SC_FIGHTINGSPIRIT: + status_change_end(bl, type, INVALID_TIMER); // Remove previous one. + break; + case SC_SWINGDANCE: + case SC_SYMPHONYOFLOVER: + case SC_MOONLITSERENADE: + case SC_RUSHWINDMILL: + case SC_ECHOSONG: + case SC_HARMONIZE: + case SC_VOICEOFSIREN: + case SC_DEEPSLEEP: + case SC_SIRCLEOFNATURE: + if( sc->data[type] ) // Don't remove same sc. + break; + status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); + status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + status_change_end(bl, SC_VOICEOFSIREN, INVALID_TIMER); + status_change_end(bl, SC_DEEPSLEEP, INVALID_TIMER); + status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); + break; + case SC_SONGOFMANA: + case SC_DANCEWITHWUG: + case SC_LERADSDEW: + case SC_MELODYOFSINK: + case SC_BEYONDOFWARCRY: + case SC_UNLIMITEDHUMMINGVOICE: + if( sc->data[type] ) // Don't remove same sc. + break; + status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); + status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); + status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + break; case SC_REFLECTSHIELD: status_change_end(bl, SC_REFLECTDAMAGE, INVALID_TIMER); break; @@ -6119,6 +6279,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = sce->val3; val4 = sce->val4; break; + case SC_LERADSDEW: + if( sc && sc->data[SC_BERSERK] ) + return 0; + case SC_SHAPESHIFT: + case SC_PROPERTYWALK: + break; case SC_JOINTBEAT: val2 |= sce->val2; // stackable ailments default: @@ -7465,12 +7631,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } //Those that make you stop attacking/walking.... - switch (type) - { + switch (type) { case SC_FREEZE: case SC_STUN: case SC_SLEEP: case SC_STONE: + case SC_DEEPSLEEP: if (sd && pc_issit(sd)) //Avoid sprite sync problems. pc_setstand(sd); case SC_TRICKDEAD: @@ -7487,10 +7653,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_SPIDERWEB: case SC_ELECTRICSHOCKER: case SC_BITE: + case SC_THORNSTRAP: case SC__MANHOLE: case SC_CHAOS: + case SC_CRYSTALIZE: + case SC_WHITEIMPRISON: + case SC_VACUUM_EXTREME: case SC_CURSEDCIRCLE_ATKER: case SC_CURSEDCIRCLE_TARGET: + case SC_FEAR: unit_stop_walking(bl,1); break; case SC_HIDING: @@ -7499,6 +7670,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CHASEWALK: case SC_WEIGHT90: case SC_CAMOUFLAGE: + case SC_VOICEOFSIREN: unit_stop_attack(bl); break; case SC_SILENCE: @@ -8157,6 +8329,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const break; case SC_BERSERK: + case SC_SATURDAYNIGHTFEVER: //If val2 is removed, no HP penalty (dispelled?) [Skotlex] if(status->hp > 100 && sce->val2) status_set_hp(bl, 100, 0); @@ -8166,6 +8339,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const status_change_end(bl, SC_ENDURE, INVALID_TIMER); } sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1)); + if( type == SC_SATURDAYNIGHTFEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds. + sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); break; case SC_GOSPEL: if (sce->val3) { //Clear the group. @@ -9471,11 +9646,18 @@ int status_change_clear_buffs (struct block_list* bl, int type) case SC_STRIPSHIELD: case SC_STRIPARMOR: case SC_STRIPHELM: + case SC_BITE: + case SC_ADORAMUS: + case SC_VACUUM_EXTREME: + case SC_BURNING: + case SC_FEAR: + case SC_MAGNETICFIELD: if (!(type&2)) continue; break; //The rest are buffs that can be removed. case SC_BERSERK: + case SC_SATURDAYNIGHTFEVER: if (!(type&1)) continue; sc->data[i]->val2 = 0; diff --git a/src/map/status.h b/src/map/status.h index ad2bded4e..a71a4ef49 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1008,32 +1008,32 @@ enum si_type { SI_GENTLETOUCH_CHANGE = 426, SI_GENTLETOUCH_REVITALIZE = 427, SI_BLOODYLUST = 428, - SI_SWING = 429, - SI_SYMPHONY_LOVE = 430, + SI_SWINGDANCE = 429, + SI_SYMPHONYOFLOVERS = 430, SI_PROPERTYWALK = 431, SI_SPELLFIST = 432, SI_NETHERWORLD = 433, - SI_SIREN = 434, - SI_DEEP_SLEEP = 435, + SI_VOICEOFSIREN = 434, + SI_DEEPSLEEP = 435, SI_SIRCLEOFNATURE = 436, SI_COLD = 437, SI_GLOOMYDAY = 438, - SI_SONG_OF_MANA = 439, + SI_SONGOFMANA = 439, SI_CLOUD_KILL = 440, - SI_DANCE_WITH_WUG = 441, - SI_RUSH_WINDMILL = 442, + SI_DANCEWITHWUG = 441, + SI_RUSHWINDMILL = 442, SI_ECHOSONG = 443, SI_HARMONIZE = 444, SI_STRIKING = 445, SI_WARMER = 446, - SI_MOONLIT_SERENADE = 447, - SI_SATURDAY_NIGHT_FEVER = 448, + SI_MOONLITSERENADE = 447, + SI_SATURDAYNIGHTFEVER = 448, SI_SITDOWN_FORCE = 449, SI_ANALYZE = 450, - SI_LERADS_DEW = 451, + SI_LERADSDEW = 451, SI_MELODYOFSINK = 452, - SI_BEYOND_OF_WARCRY = 453, - SI_UNLIMITED_HUMMING_VOICE = 454, + SI_WARCRYOFBEYOND = 453, + SI_UNLIMITEDHUMMINGVOICE = 454, SI_SPELLBOOK1 = 455, SI_SPELLBOOK2 = 456, SI_SPELLBOOK3 = 457, -- cgit v1.2.3-60-g2f50