summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/battle.c22
-rw-r--r--src/map/skill.c464
-rw-r--r--src/map/skill.h6
-rw-r--r--src/map/status.c312
-rw-r--r--src/map/status.h24
5 files changed, 689 insertions, 139 deletions
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,