Adjusts NPC_EARTHQUAKE behavior (#5017)
* Fixes #1679 and fixes #3176. * Converts the skill to a unit-based skill. * Damage is now properly calculated based on the caster's ATK. * Damage is considered magic with the element forced to Neutral. * Now ignores target's DEF and Land Protector. * Kaupe and Tumbling now can avoid the first attack only. * Removed old bits of the skill. Thanks to @poporing, @mrjnumber1, @Daegaladh, @malufett, and @exneval!
This commit is contained in:
parent
36b9b942c9
commit
53e7f59f48
@ -15307,10 +15307,12 @@ Body:
|
|||||||
DamageFlags:
|
DamageFlags:
|
||||||
Splash: true
|
Splash: true
|
||||||
SplashSplit: true
|
SplashSplit: true
|
||||||
|
IgnoreDefense: true
|
||||||
Flags:
|
Flags:
|
||||||
IsNpc: true
|
IsNpc: true
|
||||||
TargetTrap: true
|
TargetTrap: true
|
||||||
ShowScale: true
|
ShowScale: true
|
||||||
|
IgnoreLandProtector: true
|
||||||
Hit: Multi_Hit
|
Hit: Multi_Hit
|
||||||
HitCount: 1
|
HitCount: 1
|
||||||
SplashArea:
|
SplashArea:
|
||||||
@ -15334,6 +15336,34 @@ Body:
|
|||||||
Area: 11
|
Area: 11
|
||||||
- Level: 10
|
- Level: 10
|
||||||
Area: 13
|
Area: 13
|
||||||
|
Duration1: 910
|
||||||
|
Unit:
|
||||||
|
Id: Earthquake
|
||||||
|
Range:
|
||||||
|
- Level: 1
|
||||||
|
Size: 5
|
||||||
|
- Level: 2
|
||||||
|
Size: 7
|
||||||
|
- Level: 3
|
||||||
|
Size: 9
|
||||||
|
- Level: 4
|
||||||
|
Size: 11
|
||||||
|
- Level: 5
|
||||||
|
Size: 13
|
||||||
|
- Level: 6
|
||||||
|
Size: 5
|
||||||
|
- Level: 7
|
||||||
|
Size: 7
|
||||||
|
- Level: 8
|
||||||
|
Size: 9
|
||||||
|
- Level: 9
|
||||||
|
Size: 11
|
||||||
|
- Level: 10
|
||||||
|
Size: 13
|
||||||
|
Interval: 300
|
||||||
|
Target: Enemy
|
||||||
|
Flag:
|
||||||
|
PathCheck: true
|
||||||
- Id: 654
|
- Id: 654
|
||||||
Name: NPC_FIREBREATH
|
Name: NPC_FIREBREATH
|
||||||
Description: Fire Breath
|
Description: Fire Breath
|
||||||
|
@ -15705,10 +15705,12 @@ Body:
|
|||||||
DamageFlags:
|
DamageFlags:
|
||||||
Splash: true
|
Splash: true
|
||||||
SplashSplit: true
|
SplashSplit: true
|
||||||
|
IgnoreDefense: true
|
||||||
Flags:
|
Flags:
|
||||||
IsNpc: true
|
IsNpc: true
|
||||||
TargetTrap: true
|
TargetTrap: true
|
||||||
ShowScale: true
|
ShowScale: true
|
||||||
|
IgnoreLandProtector: true
|
||||||
Hit: Multi_Hit
|
Hit: Multi_Hit
|
||||||
HitCount: 1
|
HitCount: 1
|
||||||
SplashArea:
|
SplashArea:
|
||||||
@ -15732,6 +15734,35 @@ Body:
|
|||||||
Area: 11
|
Area: 11
|
||||||
- Level: 10
|
- Level: 10
|
||||||
Area: 13
|
Area: 13
|
||||||
|
Duration1: 910
|
||||||
|
FixedCastTime: -1
|
||||||
|
Unit:
|
||||||
|
Id: Earthquake
|
||||||
|
Range:
|
||||||
|
- Level: 1
|
||||||
|
Size: 5
|
||||||
|
- Level: 2
|
||||||
|
Size: 7
|
||||||
|
- Level: 3
|
||||||
|
Size: 9
|
||||||
|
- Level: 4
|
||||||
|
Size: 11
|
||||||
|
- Level: 5
|
||||||
|
Size: 13
|
||||||
|
- Level: 6
|
||||||
|
Size: 5
|
||||||
|
- Level: 7
|
||||||
|
Size: 7
|
||||||
|
- Level: 8
|
||||||
|
Size: 9
|
||||||
|
- Level: 9
|
||||||
|
Size: 11
|
||||||
|
- Level: 10
|
||||||
|
Size: 13
|
||||||
|
Interval: 300
|
||||||
|
Target: Enemy
|
||||||
|
Flag:
|
||||||
|
PathCheck: true
|
||||||
- Id: 654
|
- Id: 654
|
||||||
Name: NPC_FIREBREATH
|
Name: NPC_FIREBREATH
|
||||||
Description: Fire Breath
|
Description: Fire Breath
|
||||||
|
@ -1283,7 +1283,7 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sc->data[SC_DODGE] && (flag&BF_LONG || sc->data[SC_SPURT]) && rnd() % 100 < 20) {
|
if (sc->data[SC_DODGE] && (flag&BF_LONG || sc->data[SC_SPURT]) && (skill_id != NPC_EARTHQUAKE || (skill_id == NPC_EARTHQUAKE && flag & NPC_EARTHQUAKE_FLAG)) && rnd() % 100 < 20) {
|
||||||
map_session_data *sd = map_id2sd(target->id);
|
map_session_data *sd = map_id2sd(target->id);
|
||||||
|
|
||||||
if (sd && pc_issit(sd))
|
if (sd && pc_issit(sd))
|
||||||
@ -1293,7 +1293,7 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sce = sc->data[SC_KAUPE]) && rnd() % 100 < sce->val2) { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries.
|
if ((sce = sc->data[SC_KAUPE]) && (skill_id != NPC_EARTHQUAKE || (skill_id == NPC_EARTHQUAKE && flag & NPC_EARTHQUAKE_FLAG)) && rnd() % 100 < sce->val2) { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries.
|
||||||
clif_specialeffect(target, EF_STORMKICK4, AREA);
|
clif_specialeffect(target, EF_STORMKICK4, AREA);
|
||||||
//Shouldn't end until Breaker's non-weapon part connects.
|
//Shouldn't end until Breaker's non-weapon part connects.
|
||||||
#ifndef RENEWAL
|
#ifndef RENEWAL
|
||||||
@ -2782,6 +2782,7 @@ static bool is_attack_hitting(struct Damage* wd, struct block_list *src, struct
|
|||||||
case NPC_DARKNESSATTACK:
|
case NPC_DARKNESSATTACK:
|
||||||
case NPC_UNDEADATTACK:
|
case NPC_UNDEADATTACK:
|
||||||
case NPC_TELEKINESISATTACK:
|
case NPC_TELEKINESISATTACK:
|
||||||
|
case NPC_EARTHQUAKE:
|
||||||
case NPC_BLEEDING:
|
case NPC_BLEEDING:
|
||||||
hitrate += hitrate * 20 / 100;
|
hitrate += hitrate * 20 / 100;
|
||||||
break;
|
break;
|
||||||
@ -6103,6 +6104,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
|||||||
s_ele = rnd()%ELE_ALL;
|
s_ele = rnd()%ELE_ALL;
|
||||||
|
|
||||||
switch(skill_id) {
|
switch(skill_id) {
|
||||||
|
case NPC_EARTHQUAKE:
|
||||||
|
s_ele = ELE_NEUTRAL;
|
||||||
|
break;
|
||||||
case LG_SHIELDSPELL:
|
case LG_SHIELDSPELL:
|
||||||
if (skill_lv == 2)
|
if (skill_lv == 2)
|
||||||
s_ele = ELE_HOLY;
|
s_ele = ELE_HOLY;
|
||||||
@ -6215,6 +6219,22 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
|||||||
case AB_RENOVATIO:
|
case AB_RENOVATIO:
|
||||||
ad.damage = status_get_lv(src) * 10 + sstatus->int_;
|
ad.damage = status_get_lv(src) * 10 + sstatus->int_;
|
||||||
break;
|
break;
|
||||||
|
case NPC_EARTHQUAKE:
|
||||||
|
if (mflag & NPC_EARTHQUAKE_FLAG) {
|
||||||
|
ad.flag |= NPC_EARTHQUAKE_FLAG; // Pass flag to battle_calc_damage
|
||||||
|
mflag &= ~NPC_EARTHQUAKE_FLAG; // Remove before NK_SPLASHSPLIT check
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src->type == BL_PC)
|
||||||
|
ad.damage = sstatus->str * 2 + battle_calc_weapon_attack(src, target, skill_id, skill_lv, mflag).damage;
|
||||||
|
else
|
||||||
|
ad.damage = battle_calc_base_damage(src, sstatus, &sstatus->rhw, sc, tstatus->size, 0);
|
||||||
|
|
||||||
|
MATK_RATE(200 + 100 * skill_lv + 100 * (skill_lv / 2) + ((skill_lv > 4) ? 100 : 0));
|
||||||
|
|
||||||
|
if (nk[NK_SPLASHSPLIT] && mflag > 1)
|
||||||
|
ad.damage /= mflag;
|
||||||
|
break;
|
||||||
case NPC_ICEMINE:
|
case NPC_ICEMINE:
|
||||||
case NPC_FLAMECROSS:
|
case NPC_FLAMECROSS:
|
||||||
ad.damage = sstatus->rhw.atk * 20 * skill_lv;
|
ad.damage = sstatus->rhw.atk * 20 * skill_lv;
|
||||||
@ -6381,9 +6401,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
|||||||
case NPC_ENERGYDRAIN:
|
case NPC_ENERGYDRAIN:
|
||||||
skillratio += 100 * skill_lv;
|
skillratio += 100 * skill_lv;
|
||||||
break;
|
break;
|
||||||
case NPC_EARTHQUAKE:
|
|
||||||
skillratio += 100 + 100 * skill_lv + 100 * (skill_lv / 2) + ((skill_lv > 4) ? 100 : 0);
|
|
||||||
break;
|
|
||||||
#ifdef RENEWAL
|
#ifdef RENEWAL
|
||||||
case WZ_HEAVENDRIVE:
|
case WZ_HEAVENDRIVE:
|
||||||
skillratio += 25;
|
skillratio += 25;
|
||||||
@ -6748,16 +6765,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
|||||||
ad.damage = ad.damage * (100-mdef)/100 - mdef2;
|
ad.damage = ad.damage * (100-mdef)/100 - mdef2;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if 0 // Doesn't seem to be official
|
|
||||||
if (skill_id == NPC_EARTHQUAKE) {
|
|
||||||
//Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex]
|
|
||||||
//Also divide the extra bonuses from atk2 based on the number in range [Kevin]
|
|
||||||
if(mflag>0)
|
|
||||||
ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag;
|
|
||||||
else
|
|
||||||
ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(ad.damage<1)
|
if(ad.damage<1)
|
||||||
ad.damage=1;
|
ad.damage=1;
|
||||||
else if(sc) { //only applies when hit
|
else if(sc) { //only applies when hit
|
||||||
|
@ -7832,6 +7832,7 @@
|
|||||||
export_constant(UNT_GROUNDDRIFT_POISON);
|
export_constant(UNT_GROUNDDRIFT_POISON);
|
||||||
export_constant(UNT_GROUNDDRIFT_WATER);
|
export_constant(UNT_GROUNDDRIFT_WATER);
|
||||||
export_constant(UNT_GROUNDDRIFT_FIRE);
|
export_constant(UNT_GROUNDDRIFT_FIRE);
|
||||||
|
export_constant(UNT_EARTHQUAKE);
|
||||||
export_constant(UNT_EVILLAND);
|
export_constant(UNT_EVILLAND);
|
||||||
export_constant(UNT_EPICLESIS);
|
export_constant(UNT_EPICLESIS);
|
||||||
export_constant(UNT_EARTHSTRAIN);
|
export_constant(UNT_EARTHSTRAIN);
|
||||||
|
@ -3579,6 +3579,9 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
|||||||
case LG_OVERBRAND_PLUSATK:
|
case LG_OVERBRAND_PLUSATK:
|
||||||
dmg.dmotion = clif_skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,DMG_SPLASH);
|
dmg.dmotion = clif_skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,DMG_SPLASH);
|
||||||
break;
|
break;
|
||||||
|
case NPC_EARTHQUAKE:
|
||||||
|
dmg.dmotion = clif_skill_damage(src, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, DMG_ENDURE);
|
||||||
|
break;
|
||||||
case NPC_DARKPIERCING:
|
case NPC_DARKPIERCING:
|
||||||
case EL_FIRE_BOMB:
|
case EL_FIRE_BOMB:
|
||||||
case EL_FIRE_BOMB_ATK:
|
case EL_FIRE_BOMB_ATK:
|
||||||
@ -4261,14 +4264,6 @@ static TIMER_FUNC(skill_timerskill){
|
|||||||
case BS_HAMMERFALL:
|
case BS_HAMMERFALL:
|
||||||
sc_start(src, target, status_skill2sc(skl->skill_id), skl->type, skl->skill_lv, skill_get_time2(skl->skill_id, skl->skill_lv));
|
sc_start(src, target, status_skill2sc(skl->skill_id), skl->type, skl->skill_lv, skill_get_time2(skl->skill_id, skl->skill_lv));
|
||||||
break;
|
break;
|
||||||
case NPC_EARTHQUAKE:
|
|
||||||
if( skl->type > 1 )
|
|
||||||
skill_addtimerskill(src,tick+250,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag);
|
|
||||||
skill_area_temp[0] = map_foreachinallrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, BCT_ENEMY, skill_area_sub_count);
|
|
||||||
skill_area_temp[1] = src->id;
|
|
||||||
skill_area_temp[2] = 0;
|
|
||||||
map_foreachinallrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), splash_target(src), src, skl->skill_id, skl->skill_lv, tick, skl->flag, skill_castend_damage_id);
|
|
||||||
break;
|
|
||||||
case WZ_WATERBALL:
|
case WZ_WATERBALL:
|
||||||
{
|
{
|
||||||
//Get the next waterball cell to consume
|
//Get the next waterball cell to consume
|
||||||
@ -5110,7 +5105,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|||||||
case NJ_HUUMA:
|
case NJ_HUUMA:
|
||||||
case ASC_METEORASSAULT:
|
case ASC_METEORASSAULT:
|
||||||
case GS_SPREADATTACK:
|
case GS_SPREADATTACK:
|
||||||
case NPC_EARTHQUAKE:
|
|
||||||
case NPC_PULSESTRIKE:
|
case NPC_PULSESTRIKE:
|
||||||
case NPC_HELLJUDGEMENT:
|
case NPC_HELLJUDGEMENT:
|
||||||
case NPC_VAMPIRE_GIFT:
|
case NPC_VAMPIRE_GIFT:
|
||||||
@ -5225,9 +5219,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|||||||
case MH_XENO_SLASHER:
|
case MH_XENO_SLASHER:
|
||||||
clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, DMG_SINGLE);
|
clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, DMG_SINGLE);
|
||||||
break;
|
break;
|
||||||
case NPC_EARTHQUAKE: //FIXME: Isn't EarthQuake a ground skill after all?
|
|
||||||
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 NPC_REVERBERATION_ATK:
|
||||||
case NC_ARMSCANNON:
|
case NC_ARMSCANNON:
|
||||||
skill_area_temp[1] = 0;
|
skill_area_temp[1] = 0;
|
||||||
@ -7584,7 +7575,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|||||||
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
||||||
case SR_EARTHSHAKER:
|
case SR_EARTHSHAKER:
|
||||||
case NC_INFRAREDSCAN:
|
case NC_INFRAREDSCAN:
|
||||||
case NPC_EARTHQUAKE:
|
|
||||||
case NPC_VAMPIRE_GIFT:
|
case NPC_VAMPIRE_GIFT:
|
||||||
case NPC_HELLJUDGEMENT:
|
case NPC_HELLJUDGEMENT:
|
||||||
case NPC_PULSESTRIKE:
|
case NPC_PULSESTRIKE:
|
||||||
@ -12445,6 +12435,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|||||||
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
||||||
flag|=1;
|
flag|=1;
|
||||||
break;
|
break;
|
||||||
|
case NPC_EARTHQUAKE:
|
||||||
|
clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, DMG_SINGLE);
|
||||||
|
skill_unitsetting(src, skill_id, skill_lv, x, y, 0);
|
||||||
|
break;
|
||||||
#ifndef RENEWAL
|
#ifndef RENEWAL
|
||||||
case HP_BASILICA:
|
case HP_BASILICA:
|
||||||
if( sc->data[SC_BASILICA] ) {
|
if( sc->data[SC_BASILICA] ) {
|
||||||
@ -14445,6 +14439,11 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UNT_EARTHQUAKE:
|
||||||
|
sg->val1++; // Hit count
|
||||||
|
skill_attack(skill_get_type(sg->skill_id), ss, &unit->bl, bl, sg->skill_id, sg->skill_lv, tick, map_foreachinallrange(skill_area_sub, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), BL_CHAR, &unit->bl, sg->skill_id, sg->skill_lv, tick, BCT_ENEMY, skill_area_sub_count) | (sg->val1 == 1 ? NPC_EARTHQUAKE_FLAG : 0));
|
||||||
|
break;
|
||||||
|
|
||||||
case UNT_ELECTRICSHOCKER:
|
case UNT_ELECTRICSHOCKER:
|
||||||
if( bl->id != ss->id ) {
|
if( bl->id != ss->id ) {
|
||||||
if( status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id, sg->skill_lv), SCSTART_NORATEDEF) ) {
|
if( status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id, sg->skill_lv), SCSTART_NORATEDEF) ) {
|
||||||
|
@ -37,6 +37,9 @@ struct status_change_entry;
|
|||||||
#define SKILL_NAME_LENGTH 31 /// Max Skill Name length
|
#define SKILL_NAME_LENGTH 31 /// Max Skill Name length
|
||||||
#define SKILL_DESC_LENGTH 31 /// Max Skill Desc length
|
#define SKILL_DESC_LENGTH 31 /// Max Skill Desc length
|
||||||
|
|
||||||
|
/// Used with tracking the hitcount of Earthquake for skills that can avoid the first attack
|
||||||
|
#define NPC_EARTHQUAKE_FLAG 0x800
|
||||||
|
|
||||||
/// Constants to identify a skill's nk value (damage properties)
|
/// Constants to identify a skill's nk value (damage properties)
|
||||||
/// The NK value applies only to non INF_GROUND_SKILL skills
|
/// The NK value applies only to non INF_GROUND_SKILL skills
|
||||||
/// when determining skill castend function to invoke.
|
/// when determining skill castend function to invoke.
|
||||||
@ -2167,7 +2170,7 @@ enum e_skill_unit_id : uint16 {
|
|||||||
UNT_DEATHWAVE, //TODO
|
UNT_DEATHWAVE, //TODO
|
||||||
UNT_WATERATTACK, //TODO
|
UNT_WATERATTACK, //TODO
|
||||||
UNT_WINDATTACK, //TODO
|
UNT_WINDATTACK, //TODO
|
||||||
UNT_EARTHQUAKE, //TODO
|
UNT_EARTHQUAKE,
|
||||||
UNT_EVILLAND,
|
UNT_EVILLAND,
|
||||||
UNT_DARK_RUNNER, //TODO
|
UNT_DARK_RUNNER, //TODO
|
||||||
UNT_DARK_TRANSFER, //TODO
|
UNT_DARK_TRANSFER, //TODO
|
||||||
|
Loading…
x
Reference in New Issue
Block a user