Skip to content

Commit

Permalink
NPC_INVINCIBLE and Spell Breaker (#8255)
Browse files Browse the repository at this point in the history
- NPC_INVINCIBLE now grants SC_INVINCIBLE for 300s instead of unlimited
- NPC_INVINCIBLEOFF and MER_INVINCIBLEOFF2 now just end SC_INVINCIBLE instead of having their own status change
- SC_INVINCIBLE now works like plant mode instead of just setting incoming damage to 1
- SC_INVINCIBLE now increases ATKpercent by 100 instead of increasing all damage by 75%
- SC_INVINCIBLE no longer blocks skills
- SC_INVINCIBLE now increases movement speed by 50% instead of 75%
- SC_INVINCIBLE now increases ASPD strongly
- Quagmire can no longer prevent ASPD increase (it still ends various status changes and prevents them)
- If you counter Spell Breaker with Magic Rod you now receive 20% of the caster's MaxSP
- Spell Breaker will now only deal HP damage on level 5
- Spell Breaker now can deal damage to bosses to 10% in pre-re (cannot be reduced by SC_INVINCIBLE unless you enable the "invincible_nodamage" setting)
- Spell Breaker will no longer deal damage if it would be lethal
- Added missing animation of Spell Breaker's damage
- Fixes #8228
  • Loading branch information
Playtester committed Apr 17, 2024
1 parent 5df7de2 commit 25b98c8
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 134 deletions.
4 changes: 1 addition & 3 deletions db/pre-re/skill_db.yml
Expand Up @@ -16336,7 +16336,7 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: -1
Duration1: 300000
Status: Invincible
- Id: 686
Name: NPC_INVINCIBLEOFF
Expand All @@ -16348,8 +16348,6 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: 60000
Status: InvincibleOff
- Id: 687
Name: NPC_ALLHEAL
Description: Full Heal
Expand Down
13 changes: 1 addition & 12 deletions db/pre-re/status.yml
Expand Up @@ -2824,23 +2824,12 @@ Body:
Icon: EFST_INVINCIBLE
DurationLookup: NPC_INVINCIBLE
CalcFlags:
Aspd: true
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincibleoff: true
- Status: Invincibleoff
DurationLookup: NPC_INVINCIBLEOFF
CalcFlags:
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincible: true
- Status: Manu_Atk
Icon: EFST_MANU_ATK
Flags:
Expand Down
6 changes: 1 addition & 5 deletions db/re/skill_db.yml
Expand Up @@ -16709,7 +16709,7 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: -1
Duration1: 300000
Status: Invincible
- Id: 686
Name: NPC_INVINCIBLEOFF
Expand All @@ -16721,8 +16721,6 @@ Body:
Flags:
IsNpc: true
HitCount: 1
Duration1: 60000
Status: InvincibleOff
- Id: 687
Name: NPC_ALLHEAL
Description: Full Heal
Expand Down Expand Up @@ -46959,9 +46957,7 @@ Body:
Range: 2
Hit: Single
HitCount: 1
Duration1: 10000
Cooldown: 30000
Status: InvincibleOff
- Id: 8401
Name: EL_CIRCLE_OF_FIRE
Description: Circle of Fire
Expand Down
13 changes: 1 addition & 12 deletions db/re/status.yml
Expand Up @@ -2928,23 +2928,12 @@ Body:
Icon: EFST_INVINCIBLE
DurationLookup: NPC_INVINCIBLE
CalcFlags:
Aspd: true
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincibleoff: true
- Status: Invincibleoff
DurationLookup: NPC_INVINCIBLEOFF
CalcFlags:
Speed: true
Flags:
NoDispell: true
NoBanishingBuster: true
NoClearance: true
EndOnStart:
Invincible: true
- Status: Manu_Atk
Icon: EFST_MANU_ATK
Flags:
Expand Down
17 changes: 8 additions & 9 deletions src/map/battle.cpp
Expand Up @@ -1548,11 +1548,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return 0;
}

status_change* tsc = status_get_sc(bl); //check target status

if( tsc && tsc->getSCE(SC_INVINCIBLE) && !tsc->getSCE(SC_INVINCIBLEOFF) )
return 1;

switch (skill_id) {
#ifndef RENEWAL
case PA_PRESSURE:
Expand All @@ -1566,6 +1561,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return damage; //These skills bypass everything else.
}

status_change* tsc = status_get_sc(bl); //check target status

// Nothing can reduce the damage, but Safety Wall and Millennium Shield can block it completely.
// So can defense sphere's but what the heck is that??? [Rytech]
if (skill_id == SJ_NOVAEXPLOSING && !(tsc && (tsc->getSCE(SC_SAFETYWALL) || tsc->getSCE(SC_MILLENNIUMSHIELD)))) {
Expand Down Expand Up @@ -1880,9 +1877,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
}
}

if( sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) )
damage += damage * 75 / 100;

if ((sce = sc->getSCE(SC_BLOODLUST)) && flag&BF_WEAPON && damage > 0 && rnd()%100 < sce->val3)
status_heal(src, damage * sce->val4 / 100, 0, 3);

Expand Down Expand Up @@ -2845,6 +2839,10 @@ bool is_infinite_defense(struct block_list *target, int flag)
if(status_has_mode(tstatus,MD_IGNOREMISC) && flag&(BF_MISC) )
return true;

status_change* tsc = status_get_sc(target);
if (tsc && tsc->getSCE(SC_INVINCIBLE))
return true;

return false;
}

Expand Down Expand Up @@ -4459,10 +4457,11 @@ static unsigned short battle_get_atkpercent(struct block_list& bl, uint16 skill_
atkpercent += sc.getSCE(SC_BLOODLUST)->val2;
if (sc.getSCE(SC_FLEET))
atkpercent += sc.getSCE(SC_FLEET)->val3;
if (sc.getSCE(SC_INVINCIBLE))
atkpercent += sc.getSCE(SC_INVINCIBLE)->val2;

/* Only few selected skills should use this function, DO NOT ADD any that are not caused by the skills listed below
* TODO:
* NPC_INVINCIBLE (+100)
* GD_GUARDUP (2*skLevel+8)
* EL_WATERBARRIER (-3)
* SC_ENERVATION (-30/-40/-50)
Expand Down
2 changes: 1 addition & 1 deletion src/map/script_constants.hpp
Expand Up @@ -1258,7 +1258,7 @@
//export_constant(SC_IGNOREDEF);
export_constant(SC_HELLPOWER);
export_constant(SC_INVINCIBLE);
export_constant(SC_INVINCIBLEOFF);
//export_constant(SC_INVINCIBLEOFF);
export_constant(SC_MANU_ATK);
export_constant(SC_MANU_DEF);
export_constant(SC_SPL_ATK);
Expand Down
68 changes: 36 additions & 32 deletions src/map/skill.cpp
Expand Up @@ -7976,8 +7976,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_WEAPONBRAKER:
case NPC_BARRIER:
case NPC_INVINCIBLE:
case NPC_INVINCIBLEOFF:
case MER_INVINCIBLEOFF2:
case RK_DEATHBOUND:
case AB_EXPIATIO:
case AB_DUPLELIGHT:
Expand Down Expand Up @@ -9767,43 +9765,43 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SA_SPELLBREAKER:
{
int sp;
if(tsc && tsc->getSCE(SC_MAGICROD)) {
sp = skill_get_sp(skill_id,skill_lv);
sp = sp * tsc->getSCE(SC_MAGICROD)->val2 / 100;
if(sp < 1) sp = 1;
status_heal(bl,0,sp,2);
status_percent_damage(bl, src, 0, -20, false); //20% max SP damage.
} else {
struct unit_data *ud = unit_bl2ud(bl);
int bl_skill_id=0,bl_skill_lv=0,hp = 0;
if (dstsd && tsc && tsc->getSCE(SC_MAGICROD)) {
// If target enemy player has Magic Rod, then 20% of your SP is transferred to that player
sp = status_percent_damage(bl, src, 0, -20, false);
status_heal(bl, 0, sp, 2);
}
else {
struct unit_data* ud = unit_bl2ud(bl);
if (!ud || ud->skilltimer == INVALID_TIMER)
break; //Nothing to cancel.
bl_skill_id = ud->skill_id;
bl_skill_lv = ud->skill_lv;
if (status_has_mode(tstatus,MD_STATUSIMMUNE)) { //Only 10% success chance against status immune. [Skotlex]
if (rnd()%100 < 90)
int hp = 0;
if (status_has_mode(tstatus, MD_STATUSIMMUNE)) { //Only 10% success chance against status immune. [Skotlex]
if (rnd_chance(90, 100))
{
if (sd) clif_skill_fail( *sd, skill_id );
break;
}
} else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players.
hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex]

clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
unit_skillcastcancel(bl,0);
sp = skill_get_sp(bl_skill_id,bl_skill_lv);
status_zap(bl, hp, sp);

if (hp && skill_lv >= 5)
hp /= 2; //Recover half damaged HP at level 5 [Skotlex]
else
hp = 0;

if (sp) //Recover some of the SP used
sp = sp*(25*(skill_lv-1))/100;
}
#ifdef RENEWAL
else // HP damage does not work on bosses in renewal
#endif
if (skill_lv >= 5 && (!dstsd || map_flag_vs(bl->m))) //HP damage only on pvp-maps when against players.
hp = tstatus->max_hp / 50; //Siphon 2% HP at level 5

if(hp || sp)
status_heal(src, hp, sp, 2);
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
unit_skillcastcancel(bl, 0);
sp = skill_get_sp(ud->skill_id, ud->skill_lv);
status_zap(bl, 0, sp);
// Recover some of the SP used
status_heal(src, 0, sp * (25 * (skill_lv - 1)) / 100, 2);

// If damage would be lethal, it does not deal damage
if (hp && hp < tstatus->hp) {
clif_damage(src, bl, tick, 0, 0, hp, 0, DMG_NORMAL, 0, false);
status_zap(bl, hp, 0);
// Recover 50% of damage dealt
status_heal(src, hp / 2, 0, 2);
}
}
}
break;
Expand Down Expand Up @@ -10027,6 +10025,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
break;

case NPC_INVINCIBLEOFF:
case MER_INVINCIBLEOFF2:
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
status_change_end(bl, SC_INVINCIBLE);
break;

case WE_MALE: {
uint8 hp_rate = abs(skill_get_hp_rate(skill_id, skill_lv));

Expand Down

0 comments on commit 25b98c8

Please sign in to comment.