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:
Aleos 2020-08-06 15:21:20 -04:00 committed by GitHub
parent 36b9b942c9
commit 53e7f59f48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 29 deletions

View File

@ -15307,10 +15307,12 @@ Body:
DamageFlags:
Splash: true
SplashSplit: true
IgnoreDefense: true
Flags:
IsNpc: true
TargetTrap: true
ShowScale: true
IgnoreLandProtector: true
Hit: Multi_Hit
HitCount: 1
SplashArea:
@ -15334,6 +15336,34 @@ Body:
Area: 11
- Level: 10
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
Name: NPC_FIREBREATH
Description: Fire Breath

View File

@ -15705,10 +15705,12 @@ Body:
DamageFlags:
Splash: true
SplashSplit: true
IgnoreDefense: true
Flags:
IsNpc: true
TargetTrap: true
ShowScale: true
IgnoreLandProtector: true
Hit: Multi_Hit
HitCount: 1
SplashArea:
@ -15732,6 +15734,35 @@ Body:
Area: 11
- Level: 10
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
Name: NPC_FIREBREATH
Description: Fire Breath

View File

@ -1283,7 +1283,7 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe
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);
if (sd && pc_issit(sd))
@ -1293,7 +1293,7 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe
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);
//Shouldn't end until Breaker's non-weapon part connects.
#ifndef RENEWAL
@ -2782,6 +2782,7 @@ static bool is_attack_hitting(struct Damage* wd, struct block_list *src, struct
case NPC_DARKNESSATTACK:
case NPC_UNDEADATTACK:
case NPC_TELEKINESISATTACK:
case NPC_EARTHQUAKE:
case NPC_BLEEDING:
hitrate += hitrate * 20 / 100;
break;
@ -6103,6 +6104,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
s_ele = rnd()%ELE_ALL;
switch(skill_id) {
case NPC_EARTHQUAKE:
s_ele = ELE_NEUTRAL;
break;
case LG_SHIELDSPELL:
if (skill_lv == 2)
s_ele = ELE_HOLY;
@ -6215,6 +6219,22 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
case AB_RENOVATIO:
ad.damage = status_get_lv(src) * 10 + sstatus->int_;
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_FLAMECROSS:
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:
skillratio += 100 * skill_lv;
break;
case NPC_EARTHQUAKE:
skillratio += 100 + 100 * skill_lv + 100 * (skill_lv / 2) + ((skill_lv > 4) ? 100 : 0);
break;
#ifdef RENEWAL
case WZ_HEAVENDRIVE:
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;
#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)
ad.damage=1;
else if(sc) { //only applies when hit

View File

@ -7832,6 +7832,7 @@
export_constant(UNT_GROUNDDRIFT_POISON);
export_constant(UNT_GROUNDDRIFT_WATER);
export_constant(UNT_GROUNDDRIFT_FIRE);
export_constant(UNT_EARTHQUAKE);
export_constant(UNT_EVILLAND);
export_constant(UNT_EPICLESIS);
export_constant(UNT_EARTHSTRAIN);

View File

@ -3579,6 +3579,9 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
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);
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 EL_FIRE_BOMB:
case EL_FIRE_BOMB_ATK:
@ -4261,14 +4264,6 @@ static TIMER_FUNC(skill_timerskill){
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));
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:
{
//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 ASC_METEORASSAULT:
case GS_SPREADATTACK:
case NPC_EARTHQUAKE:
case NPC_PULSESTRIKE:
case NPC_HELLJUDGEMENT:
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:
clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, DMG_SINGLE);
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 NC_ARMSCANNON:
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);
case SR_EARTHSHAKER:
case NC_INFRAREDSCAN:
case NPC_EARTHQUAKE:
case NPC_VAMPIRE_GIFT:
case NPC_HELLJUDGEMENT:
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);
flag|=1;
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
case HP_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;
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:
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) ) {

View File

@ -37,6 +37,9 @@ struct status_change_entry;
#define SKILL_NAME_LENGTH 31 /// Max Skill Name 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)
/// The NK value applies only to non INF_GROUND_SKILL skills
/// when determining skill castend function to invoke.
@ -2167,7 +2170,7 @@ enum e_skill_unit_id : uint16 {
UNT_DEATHWAVE, //TODO
UNT_WATERATTACK, //TODO
UNT_WINDATTACK, //TODO
UNT_EARTHQUAKE, //TODO
UNT_EARTHQUAKE,
UNT_EVILLAND,
UNT_DARK_RUNNER, //TODO
UNT_DARK_TRANSFER, //TODO