|
@@ -89,8 +89,6 @@ static unsigned short skill_arrow_count;
|
|
|
|
|
|
AbraDatabase abra_db;
|
|
|
|
|
|
-ImprovisedSongDatabase improvised_song_db;
|
|
|
-
|
|
|
ReadingSpellbookDatabase reading_spellbook_db;
|
|
|
|
|
|
#define MAX_SKILL_CHANGEMATERIAL_DB 75
|
|
@@ -932,6 +930,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
|
|
|
case WM_SIRCLEOFNATURE:
|
|
|
case WM_SOUND_OF_DESTRUCTION:
|
|
|
case WM_LULLABY_DEEPSLEEP:
|
|
|
+ case WM_GLOOMYDAY:
|
|
|
case WM_SATURDAY_NIGHT_FEVER:
|
|
|
if( !mapdata_flag_vs(mapdata) ) {
|
|
|
clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails.
|
|
@@ -1832,47 +1831,6 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
|
|
case SR_HOWLINGOFLION:
|
|
|
sc_start(src,bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv));
|
|
|
break;
|
|
|
- case WM_SOUND_OF_DESTRUCTION:
|
|
|
- if( tsc && ( tsc->data[SC_SWINGDANCE] || tsc->data[SC_SYMPHONYOFLOVER] || tsc->data[SC_MOONLITSERENADE] ||
|
|
|
- tsc->data[SC_RUSHWINDMILL] || tsc->data[SC_ECHOSONG] || tsc->data[SC_HARMONIZE] ||
|
|
|
- tsc->data[SC_VOICEOFSIREN] || tsc->data[SC_DEEPSLEEP] || tsc->data[SC_SIRCLEOFNATURE] ||
|
|
|
- tsc->data[SC_GLOOMYDAY] || tsc->data[SC_GLOOMYDAY_SK] || tsc->data[SC_SONGOFMANA] ||
|
|
|
- tsc->data[SC_DANCEWITHWUG] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC_LERADSDEW] ||
|
|
|
- tsc->data[SC_MELODYOFSINK] || tsc->data[SC_BEYONDOFWARCRY] || tsc->data[SC_UNLIMITEDHUMMINGVOICE] ) &&
|
|
|
- rnd()%100 < 4 * skill_lv + 2 * ((sd) ? pc_checkskill(sd, WM_LESSON) : skill_get_max(WM_LESSON)) + 10 * battle_calc_chorusbonus(sd)) {
|
|
|
- status_change_start(src, bl, SC_STUN, 10000, skill_lv, 0, 0, 0, skill_get_time(skill_id,skill_lv), SCSTART_NOTICKDEF);
|
|
|
- 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);
|
|
|
-#ifndef RENEWAL
|
|
|
- status_change_end(bl, SC_LONGING, INVALID_TIMER);
|
|
|
-#endif
|
|
|
- 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;
|
|
|
case SO_EARTHGRAVE:
|
|
|
sc_start2(src,bl, SC_BLEEDING, 5 * skill_lv, skill_lv, src->id, skill_get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine]
|
|
|
break;
|
|
@@ -3681,6 +3639,8 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
|
|
type = DMG_SPLASH;
|
|
|
if (!(flag&SD_ANIMATION))
|
|
|
clif_skill_nodamage(dsrc, bl, skill_id, skill_lv, 1);
|
|
|
+ // Fall through
|
|
|
+ case WM_REVERBERATION_MAGIC:
|
|
|
dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, dmg_type);
|
|
|
break;
|
|
|
case SJ_FALLINGSTAR_ATK:
|
|
@@ -3962,7 +3922,6 @@ static int skill_check_unit_range_sub(struct block_list *bl, va_list ap)
|
|
|
case SC_DIMENSIONDOOR:
|
|
|
case SC_BLOODYLUST:
|
|
|
case NPC_REVERBERATION:
|
|
|
- case WM_REVERBERATION:
|
|
|
case GN_THORNS_TRAP:
|
|
|
case RL_B_TRAP:
|
|
|
case SC_ESCAPE:
|
|
@@ -4382,8 +4341,6 @@ static TIMER_FUNC(skill_timerskill){
|
|
|
}
|
|
|
break;
|
|
|
case NPC_REVERBERATION_ATK:
|
|
|
- case WM_REVERBERATION_MELEE:
|
|
|
- case WM_REVERBERATION_MAGIC:
|
|
|
skill_castend_damage_id(src,target,skl->skill_id,skl->skill_lv,tick,skl->flag|SD_LEVEL|SD_ANIMATION);
|
|
|
break;
|
|
|
case LG_MOONSLASHER:
|
|
@@ -4550,7 +4507,7 @@ static int skill_active_reverberation(struct block_list *bl, va_list ap) {
|
|
|
|
|
|
if (bl->type != BL_SKILL)
|
|
|
return 0;
|
|
|
- if (su->alive && (sg = su->group) && (sg->skill_id == WM_REVERBERATION || sg->skill_id == NPC_REVERBERATION)) {
|
|
|
+ if (su->alive && (sg = su->group) && sg->skill_id == NPC_REVERBERATION) {
|
|
|
map_foreachinallrange(skill_trap_splash, bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, gettick());
|
|
|
su->limit = DIFF_TICK(gettick(), sg->tick);
|
|
|
sg->unit_id = UNT_USED_TRAPS;
|
|
@@ -5173,8 +5130,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
|
case SR_SKYNETBLOW:
|
|
|
case SR_WINDMILL:
|
|
|
case SR_RIDEINLIGHTNING:
|
|
|
- case WM_REVERBERATION_MELEE:
|
|
|
- case WM_REVERBERATION_MAGIC:
|
|
|
case SO_VARETYR_SPEAR:
|
|
|
case GN_CART_TORNADO:
|
|
|
case GN_CARTCANNON:
|
|
@@ -5261,8 +5216,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
|
skill_addtimerskill(src,tick+250,src->id,0,0,skill_id,skill_lv,2,flag|BCT_ENEMY|SD_SPLASH|1);
|
|
|
break;
|
|
|
case NPC_REVERBERATION_ATK:
|
|
|
- case WM_REVERBERATION_MELEE:
|
|
|
- case WM_REVERBERATION_MAGIC:
|
|
|
case NC_ARMSCANNON:
|
|
|
skill_area_temp[1] = 0;
|
|
|
starget = splash_target(src);
|
|
@@ -5688,7 +5641,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
|
break;
|
|
|
case RK_STORMBLAST:
|
|
|
if( flag&1 )
|
|
|
- skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
|
|
|
+ skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag);
|
|
|
else {
|
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
|
map_foreachinallrange(skill_area_sub, bl,skill_get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,skill_castend_nodamage_id);
|
|
@@ -6075,6 +6028,16 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case WM_REVERBERATION:
|
|
|
+ if (flag & 1)
|
|
|
+ skill_attack(skill_get_type(WM_REVERBERATION_MAGIC), src, src, bl, WM_REVERBERATION_MAGIC, skill_lv, tick, flag);
|
|
|
+ else {
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
+ map_foreachinallrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR|BL_SKILL, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
|
|
|
+ battle_consume_ammo(sd, skill_id, skill_lv); // Consume here since Magic/Misc attacks reset arrow_atk
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
case SO_POISON_BUSTER:
|
|
|
if( tsc && tsc->data[SC_POISON] ) {
|
|
|
skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
|
|
@@ -10713,25 +10676,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
if( !status_isdead(bl) )
|
|
|
break;
|
|
|
|
|
|
- if( rnd()%100 < 88 + 2 * skill_lv ) {
|
|
|
- int heal = tstatus->sp;
|
|
|
- if( heal <= 0 )
|
|
|
- heal = 1;
|
|
|
- tstatus->hp = heal;
|
|
|
- tstatus->sp -= tstatus->sp * ( 60 - 10 * skill_lv ) / 100;
|
|
|
- clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
|
- pc_revive((TBL_PC*)bl,heal,0);
|
|
|
- clif_resurrection(bl,1);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
+ int heal = tstatus->sp;
|
|
|
|
|
|
- case WM_SIRCLEOFNATURE:
|
|
|
- if( flag&1 )
|
|
|
- sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
|
- else {
|
|
|
- map_foreachinallrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|BCT_ALL|1,skill_castend_nodamage_id);
|
|
|
+ if( heal <= 0 )
|
|
|
+ heal = 1;
|
|
|
+ tstatus->hp = heal;
|
|
|
+ tstatus->sp -= tstatus->sp * ( 60 - 10 * skill_lv ) / 100;
|
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
|
+ pc_revive((TBL_PC*)bl,heal,0);
|
|
|
+ clif_resurrection(bl,1);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -10752,7 +10705,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
if( dstsd && ( 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) ) )
|
|
|
- {
|
|
|
+ { // !TODO: Which skills aren't boosted anymore?
|
|
|
sc_start(src,bl,SC_GLOOMYDAY_SK,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
|
break;
|
|
|
}
|
|
@@ -10760,31 +10713,17 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
break;
|
|
|
|
|
|
case WM_SATURDAY_NIGHT_FEVER:
|
|
|
- if( flag&1 ) { // Affect to all targets arround the caster and caster too.
|
|
|
- if (tsc && ((tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK)) || tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_STEALTHFIELD] || tsc->data[SC__SHADOWFORM]))
|
|
|
- break;
|
|
|
- sc_start(src,bl, type, 100, skill_lv,skill_get_time(skill_id, skill_lv));
|
|
|
- } 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,DMG_NORMAL,0,false),skill_id);
|
|
|
- } else if( sd ) {
|
|
|
- short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4;
|
|
|
- if( !sd->status.party_id || (rnd()%100 > chance)) {
|
|
|
- clif_skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0);
|
|
|
- break;
|
|
|
+ if( flag&1 ) {
|
|
|
+ sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
|
+ } else if (sd) {
|
|
|
+ if( rnd()%100 < sstatus->int_ / 6 + sd->status.job_level / 5 + skill_lv * 4 + pc_checkskill(sd, WM_LESSON) ) { // !TODO: What's the Lesson bonus?
|
|
|
+ map_foreachinallrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
|
|
+ clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
|
}
|
|
|
- if( map_foreachinallrange(skill_area_sub, bl, skill_get_splash(skill_id,skill_lv),
|
|
|
- BL_PC, src, skill_id, skill_lv, tick, BCT_ENEMY, skill_area_sub_count) > 7 )
|
|
|
- flag |= 2;
|
|
|
- else
|
|
|
- flag |= 1;
|
|
|
- map_foreachinallrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF, skill_castend_nodamage_id);
|
|
|
- clif_skill_nodamage(src, bl, skill_id, skill_lv,
|
|
|
- sc_start(src,src,SC_STOP,100,skill_lv,skill_get_time2(skill_id,skill_lv)));
|
|
|
- if( flag&2 ) // Dealed here to prevent conflicts
|
|
|
- status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,DMG_NORMAL,0,false),skill_id);
|
|
|
}
|
|
|
break;
|
|
|
+
|
|
|
+ case WM_SIRCLEOFNATURE:
|
|
|
case WM_SONG_OF_MANA:
|
|
|
case WM_DANCE_WITH_WUG:
|
|
|
case WM_LERADS_DEW:
|
|
@@ -10792,87 +10731,58 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
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(src,bl,type,100,skill_lv,battle_calc_chorusbonus(sd),skill_get_time(skill_id,skill_lv));
|
|
|
+ sc_start2(src,bl,type,100,skill_lv,pc_checkskill(sd, WM_LESSON),skill_get_time(skill_id,skill_lv));
|
|
|
}
|
|
|
} else if( sd ) {
|
|
|
- if( sc_start2(src,bl,type,100,skill_lv,battle_calc_chorusbonus(sd),skill_get_time(skill_id,skill_lv)) )
|
|
|
+ if( sc_start2(src,bl,type,100,skill_lv,pc_checkskill(sd, WM_LESSON),skill_get_time(skill_id,skill_lv)) )
|
|
|
party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id);
|
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case WM_MELODYOFSINK:
|
|
|
- case WM_BEYOND_OF_WARCRY:
|
|
|
if( flag&1 ) {
|
|
|
- sc_start2(src,bl,type,100,skill_lv,battle_calc_chorusbonus(sd),skill_get_time(skill_id,skill_lv));
|
|
|
- } else { // These affect to all targets arround the caster.
|
|
|
- if( rnd()%100 < 15 + 5 * skill_lv * 5 * battle_calc_chorusbonus(sd) ) {
|
|
|
+ sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
|
+ } else { // These affect to all targets around the caster.
|
|
|
+ if( rnd()%100 < 5 + 5 * skill_lv + pc_checkskill(sd, WM_LESSON) ) { // !TODO: What's the Lesson bonus?
|
|
|
map_foreachinallrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
|
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
- case WM_RANDOMIZESPELL:
|
|
|
- if (improvised_song_db.empty()) {
|
|
|
- clif_skill_nodamage (src, bl, skill_id, skill_lv, 1);
|
|
|
- break;
|
|
|
+ case WM_BEYOND_OF_WARCRY:
|
|
|
+ if( flag&1 ) {
|
|
|
+ sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
|
+ } else { // These affect to all targets around the caster.
|
|
|
+ if( rnd()%100 < 12 + 3 * skill_lv + (sd ? pc_checkskill(sd, WM_LESSON) : 0) ) { // !TODO: What's the Lesson bonus?
|
|
|
+ map_foreachinallrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
|
|
+ clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
|
|
+ }
|
|
|
}
|
|
|
- else {
|
|
|
- int improv_skill_id = 0, improv_skill_lv, checked = 0, checked_max = improvised_song_db.size() * 3;
|
|
|
-
|
|
|
- do {
|
|
|
- auto improvise_spell = improvised_song_db.random();
|
|
|
-
|
|
|
- improv_skill_id = improvise_spell->skill_id;
|
|
|
-
|
|
|
- if( rnd() % 10000 >= improvise_spell->per ){
|
|
|
- break;
|
|
|
- }
|
|
|
- } while (checked++ < checked_max);
|
|
|
+ break;
|
|
|
|
|
|
- if (!skill_get_index(improv_skill_id)) {
|
|
|
- if (sd)
|
|
|
- clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
|
|
|
- break;
|
|
|
- }
|
|
|
+ case WM_SOUND_OF_DESTRUCTION:
|
|
|
+ if (flag&1) {
|
|
|
+ sc_start(src, bl, type, 100, skill_lv, (sd ? pc_checkskill(sd, WM_LESSON) * 500 : 0) + skill_get_time(skill_id, skill_lv)); // !TODO: Confirm Lesson increase
|
|
|
+ } else {
|
|
|
+ map_foreachinallrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
+ }
|
|
|
+ break;
|
|
|
|
|
|
- improv_skill_lv = min(4 + skill_lv, skill_get_max(improv_skill_id));
|
|
|
- clif_skill_nodamage (src, bl, skill_id, skill_lv, 1);
|
|
|
+ case WM_RANDOMIZESPELL:
|
|
|
+ if (rnd() % 100 < 30 + (10 * skill_lv)) {
|
|
|
+ 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_SATURDAYNIGHTFEVER, INVALID_TIMER);
|
|
|
+ status_change_end(bl, SC_BEYONDOFWARCRY, 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);
|
|
|
|
|
|
- if( sd ) {
|
|
|
- sd->state.abra_flag = 2;
|
|
|
- sd->skillitem = improv_skill_id;
|
|
|
- sd->skillitemlv = improv_skill_lv;
|
|
|
- sd->skillitem_keep_requirement = false;
|
|
|
- clif_item_skill(sd, improv_skill_id, improv_skill_lv);
|
|
|
- } else {
|
|
|
- struct unit_data *ud = unit_bl2ud(src);
|
|
|
- int inf = skill_get_inf(improv_skill_id);
|
|
|
- if (!ud) break;
|
|
|
- if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
|
|
|
- if (src->type == BL_PET)
|
|
|
- bl = (struct block_list*)((TBL_PET*)src)->master;
|
|
|
- if (!bl) bl = src;
|
|
|
- unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv);
|
|
|
- } else {
|
|
|
- int target_id = 0;
|
|
|
- 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_skill_id) == CAST_GROUND) {
|
|
|
- bl = map_id2bl(target_id);
|
|
|
- if (!bl) bl = src;
|
|
|
- unit_skilluse_pos(src, bl->x, bl->y, improv_skill_id, improv_skill_lv);
|
|
|
- } else
|
|
|
- unit_skilluse_id(src, target_id, improv_skill_id, improv_skill_lv);
|
|
|
- }
|
|
|
- }
|
|
|
+ clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -10976,7 +10886,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
sc_start(src, bl, type, rate, skill_lv, duration);
|
|
|
} else {
|
|
|
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
|
|
- map_foreachinallrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ALL|BCT_WOS|1, skill_castend_nodamage_id);
|
|
|
+ map_foreachinallrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -12099,7 +12009,7 @@ TIMER_FUNC(skill_castend_id){
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
- if (sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL) // they just set the data so leave it as it is.[Inkfish]
|
|
|
+ if (sd && ud->skill_id != SA_ABRACADABRA) // they just set the data so leave it as it is.[Inkfish]
|
|
|
sd->skillitem = sd->skillitemlv = sd->skillitem_keep_requirement = 0;
|
|
|
|
|
|
if (ud->skilltimer == INVALID_TIMER) {
|
|
@@ -12487,7 +12397,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
case SC_CHAOSPANIC:
|
|
|
case SC_MAELSTROM:
|
|
|
case SC_BLOODYLUST:
|
|
|
- case WM_REVERBERATION:
|
|
|
case WM_POEMOFNETHERWORLD:
|
|
|
case SO_PSYCHIC_WAVE:
|
|
|
case SO_VACUUM_EXTREME:
|
|
@@ -12964,7 +12873,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
break;
|
|
|
|
|
|
case WM_GREAT_ECHO:
|
|
|
- case WM_SOUND_OF_DESTRUCTION:
|
|
|
i = skill_get_splash(skill_id,skill_lv);
|
|
|
map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
|
|
|
break;
|
|
@@ -13863,7 +13771,6 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
unit_val2 = 0;
|
|
|
break;
|
|
|
case NPC_REVERBERATION:
|
|
|
- case WM_REVERBERATION:
|
|
|
unit_val1 = 1 + skill_lv;
|
|
|
break;
|
|
|
case WM_POEMOFNETHERWORLD:
|
|
@@ -15424,9 +15331,10 @@ int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, uint16
|
|
|
struct map_session_data* tsd;
|
|
|
switch (skill_id) {
|
|
|
case PR_BENEDICTIO:
|
|
|
+ case WM_GREAT_ECHO:
|
|
|
for (i = 0; i < c; i++) {
|
|
|
if ((tsd = map_id2sd(p_sd[i])) != NULL)
|
|
|
- status_charge(&tsd->bl, 0, 10);
|
|
|
+ status_charge(&tsd->bl, 0, (skill_id == PR_BENEDICTIO) ? 10 : skill_get_sp(skill_id, *skill_lv) / 2);
|
|
|
}
|
|
|
return c;
|
|
|
case AB_ADORAMUS:
|
|
@@ -15456,7 +15364,7 @@ int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, uint16
|
|
|
memset (p_sd, 0, sizeof(p_sd));
|
|
|
i = map_foreachinallrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id);
|
|
|
|
|
|
- if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET ) //Apply the average lv to encore skills.
|
|
|
+ if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET && skill_id != WM_GREAT_ECHO ) //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;
|
|
|
}
|
|
@@ -15680,7 +15588,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
|
|
|
sd->state.arrow_atk = require.ammo?1:0;
|
|
|
|
|
|
// perform skill-group checks
|
|
|
- if(inf2[INF2_ISCHORUS]) {
|
|
|
+ if(skill_id != WM_GREAT_ECHO && inf2[INF2_ISCHORUS]) {
|
|
|
if (skill_check_pc_partner(sd, skill_id, &skill_lv, AREA_SIZE, 0) < 1) {
|
|
|
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
|
|
return false;
|
|
@@ -16247,13 +16155,10 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
|
|
|
}
|
|
|
break;
|
|
|
case WM_GREAT_ECHO: {
|
|
|
- int count;
|
|
|
- count = skill_check_pc_partner(sd, skill_id, &skill_lv, AREA_SIZE, 0);
|
|
|
- if( count < 1 ) {
|
|
|
- clif_skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0);
|
|
|
- return false;
|
|
|
- } else
|
|
|
- require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party.
|
|
|
+ int count = skill_check_pc_partner(sd, skill_id, &skill_lv, AREA_SIZE, 1);
|
|
|
+
|
|
|
+ if (count > 0)
|
|
|
+ require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party.
|
|
|
}
|
|
|
break;
|
|
|
case SO_FIREWALK:
|
|
@@ -16981,8 +16886,6 @@ struct s_skill_condition skill_get_requirement(struct map_session_data* sd, uint
|
|
|
if( sc ) {
|
|
|
if( sc->data[SC__LAZINESS] )
|
|
|
req.sp += req.sp + sc->data[SC__LAZINESS]->val1 * 10;
|
|
|
- if (sc->data[SC_UNLIMITEDHUMMINGVOICE])
|
|
|
- req.sp += req.sp * sc->data[SC_UNLIMITEDHUMMINGVOICE]->val3 / 100;
|
|
|
if( sc->data[SC_RECOGNIZEDSPELL] )
|
|
|
req.sp += req.sp / 4;
|
|
|
if( sc->data[SC_OFFERTORIUM])
|
|
@@ -16995,6 +16898,8 @@ struct s_skill_condition skill_get_requirement(struct map_session_data* sd, uint
|
|
|
if (sc->data[SC_NIBELUNGEN] && sc->data[SC_NIBELUNGEN]->val2 == RINGNBL_SPCONSUM)
|
|
|
req.sp -= req.sp * 30 / 100;
|
|
|
#endif
|
|
|
+ if (sc->data[SC_GLOOMYDAY])
|
|
|
+ req.sp += req.sp * (skill_lv * 10) / 100;
|
|
|
}
|
|
|
|
|
|
req.zeny = skill->require.zeny[skill_lv-1];
|
|
@@ -17472,6 +17377,8 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
|
|
|
fixcast_r = max(fixcast_r, sc->data[SC_HEAT_BARREL]->val2);
|
|
|
if (sc->data[SC_FREEZING])
|
|
|
fixcast_r -= 50;
|
|
|
+ if (sc->data[SC_SWINGDANCE])
|
|
|
+ fixcast_r = max(fixcast_r, skill_lv * 6);
|
|
|
// Additive Fixed CastTime values
|
|
|
if (sc->data[SC_MANDRAGORA])
|
|
|
fixed += sc->data[SC_MANDRAGORA]->val1 * 500;
|
|
@@ -17479,6 +17386,8 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
|
|
|
fixed -= 1000;
|
|
|
if (sc->data[SC_IZAYOI])
|
|
|
fixed = 0;
|
|
|
+ if (sc->data[SC_GLOOMYDAY])
|
|
|
+ fixed += skill_lv * 500;
|
|
|
}
|
|
|
if (sc && sc->data[SC_SECRAMENT] && skill_id == HW_MAGICPOWER && (flag&2)) // Sacrament lowers Mystical Amplification cast time
|
|
|
fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2);
|
|
@@ -17510,7 +17419,7 @@ int skill_delayfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv)
|
|
|
nullpo_ret(bl);
|
|
|
sd = BL_CAST(BL_PC, bl);
|
|
|
|
|
|
- if (skill_id == SA_ABRACADABRA || skill_id == WM_RANDOMIZESPELL)
|
|
|
+ if (skill_id == SA_ABRACADABRA)
|
|
|
return 0; //Will use picked skill's delay.
|
|
|
|
|
|
if (bl->type&battle_config.no_skill_delay)
|
|
@@ -18460,12 +18369,7 @@ static int skill_trap_splash(struct block_list *bl, va_list ap)
|
|
|
}
|
|
|
break;
|
|
|
case UNT_REVERBERATION: // For proper skill delay animation when used with Dominion Impulse
|
|
|
- if (ss->type != BL_PC)
|
|
|
- skill_addtimerskill(ss, tick + 50, bl->id, 0, 0, NPC_REVERBERATION_ATK, sg->skill_lv, BF_WEAPON, 0);
|
|
|
- else {
|
|
|
- skill_addtimerskill(ss, tick + status_get_amotion(ss), bl->id, 0, 0, WM_REVERBERATION_MELEE, sg->skill_lv, BF_WEAPON, 0);
|
|
|
- skill_addtimerskill(ss, tick + status_get_amotion(ss) * 2, bl->id, 0, 0, WM_REVERBERATION_MAGIC, sg->skill_lv, BF_MAGIC, 0);
|
|
|
- }
|
|
|
+ skill_addtimerskill(ss, tick + 50, bl->id, 0, 0, NPC_REVERBERATION_ATK, sg->skill_lv, BF_WEAPON, 0);
|
|
|
break;
|
|
|
case UNT_FIRINGTRAP:
|
|
|
case UNT_ICEBOUNDTRAP:
|
|
@@ -22804,60 +22708,6 @@ std::shared_ptr<s_skill_spellbook_db> ReadingSpellbookDatabase::findBook(int32 n
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-const std::string ImprovisedSongDatabase::getDefaultLocation() {
|
|
|
- return std::string(db_path) + "/improvise_db.yml";
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
-* Reads and parses an entry from the improvise_db.
|
|
|
-* @param node: YAML node containing the entry.
|
|
|
-* @return count of successfully parsed rows
|
|
|
-*/
|
|
|
-uint64 ImprovisedSongDatabase::parseBodyNode(const YAML::Node &node) {
|
|
|
- std::string skill_name;
|
|
|
-
|
|
|
- if (!this->asString(node, "Skill", skill_name))
|
|
|
- return 0;
|
|
|
-
|
|
|
- uint16 skill_id = skill_name2id(skill_name.c_str());
|
|
|
-
|
|
|
- if (!skill_id) {
|
|
|
- this->invalidWarning(node["Skill"], "Invalid Improvised Song skill name \"%s\", skipping.\n", skill_name.c_str());
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (!skill_get_inf(skill_id)) {
|
|
|
- this->invalidWarning(node["Skill"], "Passive skill %s cannot be casted by Improvised Song.\n", skill_name.c_str());
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- std::shared_ptr<s_skill_improvise_db> improvise = this->find(skill_id);
|
|
|
- bool exists = improvise != nullptr;
|
|
|
-
|
|
|
- if (!exists) {
|
|
|
- if (!this->nodesExist(node, { "Probability" }))
|
|
|
- return 0;
|
|
|
-
|
|
|
- improvise = std::make_shared<s_skill_improvise_db>();
|
|
|
- improvise->skill_id = skill_id;
|
|
|
- }
|
|
|
-
|
|
|
- if (this->nodeExists(node, "Probability")) {
|
|
|
- uint16 probability;
|
|
|
-
|
|
|
- if (!this->asUInt16Rate(node, "Probability", probability))
|
|
|
- return 0;
|
|
|
-
|
|
|
- improvise->per = probability;
|
|
|
- }
|
|
|
-
|
|
|
- if (!exists)
|
|
|
- this->put(skill_id, improvise);
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
const std::string MagicMushroomDatabase::getDefaultLocation() {
|
|
|
return std::string(db_path) + "/magicmushroom_db.yml";
|
|
|
}
|
|
@@ -23247,7 +23097,6 @@ static void skill_readdb(void)
|
|
|
}
|
|
|
|
|
|
abra_db.load();
|
|
|
- improvised_song_db.load();
|
|
|
magic_mushroom_db.load();
|
|
|
reading_spellbook_db.load();
|
|
|
|