From 067c21b6475ae7fc0fcb368f5d1a5e06a0e0c706 Mon Sep 17 00:00:00 2001 From: eppc0330 <47050704+eppc0330@users.noreply.github.com> Date: Thu, 16 Mar 2023 05:36:47 +0900 Subject: [PATCH] Implement NPC_DAMAGE_HEAL and NPC_IMMUNE_PROPERTY (#7638) Co-authored-by: Lemongrass3110 --- db/re/skill_db.yml | 22 ++++ db/re/status.yml | 165 ++++++++++++++++++++++++ src/map/battle.cpp | 235 ++++++++++++++++++++++++++--------- src/map/script_constants.hpp | 11 ++ src/map/skill.cpp | 17 +++ src/map/status.cpp | 14 +++ src/map/status.hpp | 11 ++ 7 files changed, 416 insertions(+), 59 deletions(-) diff --git a/db/re/skill_db.yml b/db/re/skill_db.yml index bfb95080ff..f1fd26dec4 100644 --- a/db/re/skill_db.yml +++ b/db/re/skill_db.yml @@ -17977,6 +17977,28 @@ Body: Range: 9 Duration1: 3000 Status: GRADUAL_GRAVITY + - Id: 753 + Name: NPC_DAMAGE_HEAL + Description: Damage Heal + MaxLevel: 3 + TargetType: Self + DamageFlags: + NoDamage: true + Flags: + IsNpc: true + Duration1: 30000 + Status: DAMAGE_HEAL + - Id: 754 + Name: NPC_IMMUNE_PROPERTY + Description: Property Immune + MaxLevel: 10 + TargetType: Support + DamageFlags: + NoDamage: true + Flags: + IsNpc: true + Range: 14 #TODO: confirm + Duration1: 30000 - Id: 755 Name: NPC_MOVE_COORDINATE Description: Change Location diff --git a/db/re/status.yml b/db/re/status.yml index a987628103..2f09ba628f 100644 --- a/db/re/status.yml +++ b/db/re/status.yml @@ -8578,3 +8578,168 @@ Body: NoDispell: true NoBanishingBuster: true NoClearance: true + - Status: DAMAGE_HEAL + Icon: EFST_DAMAGE_HEAL + DurationLookup: NPC_DAMAGE_HEAL + Flags: + NoDispell: true + - Status: IMMUNE_PROPERTY_NOTHING + Icon: EFST_IMMUNE_PROPERTY_NOTHING + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_WATER + Icon: EFST_IMMUNE_PROPERTY_WATER + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_GROUND + Icon: EFST_IMMUNE_PROPERTY_GROUND + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_FIRE + Icon: EFST_IMMUNE_PROPERTY_FIRE + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_WIND + Icon: EFST_IMMUNE_PROPERTY_WIND + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_POISON + Icon: EFST_IMMUNE_PROPERTY_POISON + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_SAINT + Icon: EFST_IMMUNE_PROPERTY_SAINT + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_DARKNESS + Icon: EFST_IMMUNE_PROPERTY_DARKNESS + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_TELEKINESIS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_TELEKINESIS + Icon: EFST_IMMUNE_PROPERTY_TELEKINESIS + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_UNDEAD: true + - Status: IMMUNE_PROPERTY_UNDEAD + Icon: EFST_IMMUNE_PROPERTY_UNDEAD + DurationLookup: NPC_IMMUNE_PROPERTY + Flags: + BlEffect: true + DisplayPc: true + EndOnStart: + IMMUNE_PROPERTY_NOTHING: true + IMMUNE_PROPERTY_WATER: true + IMMUNE_PROPERTY_GROUND: true + IMMUNE_PROPERTY_FIRE: true + IMMUNE_PROPERTY_WIND: true + IMMUNE_PROPERTY_POISON: true + IMMUNE_PROPERTY_SAINT: true + IMMUNE_PROPERTY_DARKNESS: true + IMMUNE_PROPERTY_TELEKINESIS: true diff --git a/src/map/battle.cpp b/src/map/battle.cpp index df3267f3d9..1cd5db296d 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -39,6 +39,8 @@ static struct eri *delay_damage_ers; //For battle delay damage structures. // Early declaration int battle_get_weapon_element(struct Damage *wd, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, short weapon_position, bool calc_for_damage_only); +int battle_get_magic_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag); +int battle_get_misc_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag); /** * Returns the current/list skill used by the bl @@ -1126,6 +1128,81 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe status_change_end(target, SC_KYRIE); } + int element; + if (flag & BF_WEAPON) { + struct status_data *sstatus = status_get_status_data(src); + if(sstatus->rhw.ele == ELE_NEUTRAL && sstatus->lhw.ele > sstatus->rhw.ele) + element = battle_get_weapon_element(d, src, target, skill_id, skill_lv, EQI_HAND_L, false); + else + element = battle_get_weapon_element(d, src, target, skill_id, skill_lv, EQI_HAND_R, false); + } else if(flag & BF_MAGIC) + element = battle_get_magic_element(src, target, skill_id, skill_lv, d->miscflag); + else + element = battle_get_misc_element(src, target, skill_id, skill_lv, d->miscflag); + + switch( element ){ + case ELE_NEUTRAL: + if( sc->getSCE( SC_IMMUNE_PROPERTY_NOTHING ) ){ + damage = 0; + return false; + } + break; + case ELE_WATER: + if( sc->getSCE( SC_IMMUNE_PROPERTY_WATER ) ){ + damage = 0; + return false; + } + break; + case ELE_EARTH: + if( sc->getSCE( SC_IMMUNE_PROPERTY_GROUND ) ){ + damage = 0; + return false; + } + break; + case ELE_FIRE: + if( sc->getSCE( SC_IMMUNE_PROPERTY_FIRE ) ){ + damage = 0; + return false; + } + break; + case ELE_WIND: + if( sc->getSCE( SC_IMMUNE_PROPERTY_WIND ) ){ + damage = 0; + return false; + } + break; + case ELE_DARK: + if( sc->getSCE( SC_IMMUNE_PROPERTY_DARKNESS ) ){ + damage = 0; + return false; + } + break; + case ELE_HOLY: + if( sc->getSCE( SC_IMMUNE_PROPERTY_SAINT ) ){ + damage = 0; + return false; + } + break; + case ELE_POISON: + if( sc->getSCE( SC_IMMUNE_PROPERTY_POISON ) ){ + damage = 0; + return false; + } + break; + case ELE_GHOST: + if( sc->getSCE( SC_IMMUNE_PROPERTY_TELEKINESIS ) ){ + damage = 0; + return false; + } + break; + case ELE_UNDEAD: + if( sc->getSCE( SC_IMMUNE_PROPERTY_UNDEAD ) ){ + damage = 0; + return false; + } + break; + } + if ((sce = sc->getSCE(SC_P_ALTER)) && damage > 0) { clif_specialeffect(target, EF_GUARD, AREA); sce->val3 -= static_cast(cap_value(damage, INT_MIN, INT_MAX)); @@ -1395,6 +1472,21 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe status_change_end(target, SC_BUNSINJYUTSU); return false; } + + if ((sce = sc->getSCE(SC_DAMAGE_HEAL))) { + if (damage > 0 && (flag & sce->val2)) { + int32 heal = static_cast( i64min( damage, INT32_MAX ) ); + if(flag & BF_WEAPON) { + clif_specialeffect_value(target, EF_HEAL, heal, AREA); + } else { + clif_specialeffect_value(target, 1143, heal, AREA); + } + clif_specialeffect_value(target, EF_GREEN_NUMBER, heal, AREA); + status_heal(target, damage, 0, 0); + damage = 0; + return false; + } + } return true; } @@ -3279,6 +3371,86 @@ int battle_get_weapon_element(struct Damage* wd, struct block_list *src, struct return element; } +int battle_get_magic_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag) { + int element = skill_get_ele(skill_id, skill_lv); + map_session_data *sd = BL_CAST(BL_PC, src); + status_change *sc = status_get_sc(src); + struct status_data *sstatus = status_get_status_data(src); + + if (element == ELE_WEAPON) { // pl=-1 : the skill takes the weapon's element + element = sstatus->rhw.ele; + if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm >= MAX_SPIRITCHARM) + element = sd->spiritcharm_type; // Summoning 10 spiritcharm will endow your weapon + } else if (element == ELE_ENDOWED) //Use status element + element = status_get_attack_sc_element(src,status_get_sc(src)); + else if (element == ELE_RANDOM) //Use random element + element = rnd()%ELE_ALL; + + switch(skill_id) { + case NPC_EARTHQUAKE: + element = ELE_NEUTRAL; + break; + case WL_HELLINFERNO: + if (mflag & 2) { // ELE_DARK + element = ELE_DARK; + } + break; + case NPC_PSYCHIC_WAVE: + case SO_PSYCHIC_WAVE: + if( sc && sc->count ) { + static const std::vector types = { + SC_HEATER_OPTION, + SC_COOLER_OPTION, + SC_BLAST_OPTION, + SC_CURSED_SOIL_OPTION, + SC_FLAMETECHNIC_OPTION, + SC_COLD_FORCE_OPTION, + SC_GRACE_BREEZE_OPTION, + SC_EARTH_CARE_OPTION, + SC_DEEP_POISONING_OPTION + }; + for( sc_type type : types ){ + if( sc->getSCE( type ) ){ + element = sc->getSCE( type )->val3; + break; + } + } + } + break; + case KO_KAIHOU: + if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0) + element = sd->spiritcharm_type; + break; + case AB_ADORAMUS: + if (sc && sc->getSCE(SC_ANCILLA)) + element = ELE_NEUTRAL; + break; + case LG_RAYOFGENESIS: + if (sc && sc->getSCE(SC_INSPIRATION)) + element = ELE_NEUTRAL; + break; + case WM_REVERBERATION: + case TR_METALIC_FURY: + case TR_SOUNDBLEND: + if (sd) + element = sd->bonus.arrow_ele; + break; + } + + return element; +} + +int battle_get_misc_element(struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv, int mflag) { + int element = skill_get_ele(skill_id, skill_lv); + + if (element == ELE_WEAPON || element == ELE_ENDOWED) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] + element = ELE_NEUTRAL; + else if (element == ELE_RANDOM) //Use random element + element = rnd()%ELE_ALL; + + return element; +} + /*======================================== * Do element damage modifier calculation *---------------------------------------- @@ -6851,6 +7023,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list ad.dmotion = tstatus->dmotion; ad.blewcount = skill_get_blewcount(skill_id, skill_lv); ad.flag = BF_MAGIC|BF_SKILL; + ad.miscflag = mflag; ad.dmg_lv = ATK_DEF; std::shared_ptr skill = skill_db.find(skill_id); @@ -6868,67 +7041,18 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list tsc = status_get_sc(target); //Initialize variables that will be used afterwards - s_ele = skill_get_ele(skill_id, skill_lv); - - if (s_ele == ELE_WEAPON) { // pl=-1 : the skill takes the weapon's element - s_ele = sstatus->rhw.ele; - if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm >= MAX_SPIRITCHARM) - s_ele = sd->spiritcharm_type; // Summoning 10 spiritcharm will endow your weapon - } else if (s_ele == ELE_ENDOWED) //Use status element - s_ele = status_get_attack_sc_element(src,status_get_sc(src)); - else if (s_ele == ELE_RANDOM) //Use random element - s_ele = rnd()%ELE_ALL; + s_ele = battle_get_magic_element(src, target, skill_id, skill_lv, mflag); switch(skill_id) { - case NPC_EARTHQUAKE: - s_ele = ELE_NEUTRAL; - break; case WL_HELLINFERNO: if (mflag & 2) { // ELE_DARK - s_ele = ELE_DARK; ad.div_ = 3; } break; - case WM_REVERBERATION: - if (sd) - s_ele = sd->bonus.arrow_ele; - break; case NPC_PSYCHIC_WAVE: case SO_PSYCHIC_WAVE: if (sd && (sd->weapontype1 == W_STAFF || sd->weapontype1 == W_2HSTAFF || sd->weapontype1 == W_BOOK)) ad.div_ = 2; - if( sc && sc->count ) { - if( sc->getSCE(SC_HEATER_OPTION) ) - s_ele = sc->getSCE(SC_HEATER_OPTION)->val3; - else if( sc->getSCE(SC_COOLER_OPTION) ) - s_ele = sc->getSCE(SC_COOLER_OPTION)->val3; - else if( sc->getSCE(SC_BLAST_OPTION) ) - s_ele = sc->getSCE(SC_BLAST_OPTION)->val3; - else if( sc->getSCE(SC_CURSED_SOIL_OPTION) ) - s_ele = sc->getSCE(SC_CURSED_SOIL_OPTION)->val3; - else if( sc->getSCE(SC_FLAMETECHNIC_OPTION) ) - s_ele = sc->getSCE(SC_FLAMETECHNIC_OPTION)->val3; - else if( sc->getSCE(SC_COLD_FORCE_OPTION) ) - s_ele = sc->getSCE(SC_COLD_FORCE_OPTION)->val3; - else if( sc->getSCE(SC_GRACE_BREEZE_OPTION) ) - s_ele = sc->getSCE(SC_GRACE_BREEZE_OPTION)->val3; - else if( sc->getSCE(SC_EARTH_CARE_OPTION) ) - s_ele = sc->getSCE(SC_EARTH_CARE_OPTION)->val3; - else if( sc->getSCE(SC_DEEP_POISONING_OPTION) ) - s_ele = sc->getSCE(SC_DEEP_POISONING_OPTION)->val3; - } - break; - case KO_KAIHOU: - if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0) - s_ele = sd->spiritcharm_type; - break; - case AB_ADORAMUS: - if (sc && sc->getSCE(SC_ANCILLA)) - s_ele = ELE_NEUTRAL; - break; - case LG_RAYOFGENESIS: - if (sc && sc->getSCE(SC_INSPIRATION)) - s_ele = ELE_NEUTRAL; break; case AG_DESTRUCTIVE_HURRICANE: if (sc && sc->getSCE(SC_CLIMAX) && sc->getSCE(SC_CLIMAX)->val1 == 2) @@ -6944,10 +7068,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list break; case TR_METALIC_FURY:// Deals up to 5 additional hits. But what affects the number of hits? [Rytech] ad.div_ = min(ad.div_ + mflag, 5); // Number of hits doesn't go above 5. - // Fall through and check arrow element - case TR_SOUNDBLEND: - if (sd) - s_ele = sd->bonus.arrow_ele; break; } @@ -7990,6 +8110,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.blewcount = skill_get_blewcount(skill_id,skill_lv); md.dmg_lv = ATK_DEF; md.flag = BF_MISC|BF_SKILL; + md.miscflag = mflag; std::shared_ptr skill = skill_db.find(skill_id); std::bitset nk; @@ -8005,11 +8126,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.blewcount += battle_blewcount_bonus(sd, skill_id); } - s_ele = skill_get_ele(skill_id, skill_lv); - if (s_ele == ELE_WEAPON || s_ele == ELE_ENDOWED) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] - s_ele = ELE_NEUTRAL; - else if (s_ele == ELE_RANDOM) //Use random element - s_ele = rnd()%ELE_ALL; + s_ele = battle_get_misc_element(src, target, skill_id, skill_lv, mflag); //Skill Range Criteria md.flag |= battle_range_type(src, target, skill_id, skill_lv); diff --git a/src/map/script_constants.hpp b/src/map/script_constants.hpp index c770fd7c3c..5c33c2513c 100644 --- a/src/map/script_constants.hpp +++ b/src/map/script_constants.hpp @@ -1875,6 +1875,17 @@ export_constant(SC_GRADUAL_GRAVITY); export_constant(SC_ALL_STAT_DOWN); export_constant(SC_KILLING_AURA); + export_constant(SC_DAMAGE_HEAL); + export_constant(SC_IMMUNE_PROPERTY_NOTHING); + export_constant(SC_IMMUNE_PROPERTY_WATER); + export_constant(SC_IMMUNE_PROPERTY_GROUND); + export_constant(SC_IMMUNE_PROPERTY_FIRE); + export_constant(SC_IMMUNE_PROPERTY_WIND); + export_constant(SC_IMMUNE_PROPERTY_POISON); + export_constant(SC_IMMUNE_PROPERTY_SAINT); + export_constant(SC_IMMUNE_PROPERTY_DARKNESS); + export_constant(SC_IMMUNE_PROPERTY_TELEKINESIS); + export_constant(SC_IMMUNE_PROPERTY_UNDEAD); #ifdef RENEWAL export_constant(SC_EXTREMITYFIST2); diff --git a/src/map/skill.cpp b/src/map/skill.cpp index ed01d3d356..9caf67696c 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -7653,6 +7653,22 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui } break; + case NPC_IMMUNE_PROPERTY: + switch (skill_lv) { + case 1: type = SC_IMMUNE_PROPERTY_NOTHING; break; + case 2: type = SC_IMMUNE_PROPERTY_WATER; break; + case 3: type = SC_IMMUNE_PROPERTY_GROUND; break; + case 4: type = SC_IMMUNE_PROPERTY_FIRE; break; + case 5: type = SC_IMMUNE_PROPERTY_WIND; break; + case 6: type = SC_IMMUNE_PROPERTY_DARKNESS; break; + case 7: type = SC_IMMUNE_PROPERTY_SAINT; break; + case 8: type = SC_IMMUNE_PROPERTY_POISON; break; + case 9: type = SC_IMMUNE_PROPERTY_TELEKINESIS; break; + case 10: type = SC_IMMUNE_PROPERTY_UNDEAD; break; + } + clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); + break; + case PR_KYRIE: case MER_KYRIE: case SU_TUNAPARTY: @@ -7837,6 +7853,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case TR_MYSTIC_SYMPHONY: case TR_KVASIR_SONATA: case EM_SPELL_ENCHANTING: + case NPC_DAMAGE_HEAL: clif_skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); break; diff --git a/src/map/status.cpp b/src/map/status.cpp index f19c37e71a..62da4f3333 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -10921,6 +10921,20 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty val2 -= 10; } break; + case SC_DAMAGE_HEAL: + switch( val1 ){ + case 1: + val2 = BF_WEAPON; + break; + case 2: + val2 = BF_MAGIC; + break; + case 3: + //TODO: Absorb MISC damage? Both WEAPON & MAGIC damage? Which is correct on level 3? + val2 = BF_MISC; + break; + } + break; case SC_BOSSMAPINFO: if( sd != NULL ) { struct mob_data *boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map diff --git a/src/map/status.hpp b/src/map/status.hpp index 2080f82f9d..8562513592 100644 --- a/src/map/status.hpp +++ b/src/map/status.hpp @@ -1266,6 +1266,17 @@ enum sc_type : int16 { SC_GRADUAL_GRAVITY, SC_ALL_STAT_DOWN, SC_KILLING_AURA, + SC_DAMAGE_HEAL, + SC_IMMUNE_PROPERTY_NOTHING, + SC_IMMUNE_PROPERTY_WATER, + SC_IMMUNE_PROPERTY_GROUND, + SC_IMMUNE_PROPERTY_FIRE, + SC_IMMUNE_PROPERTY_WIND, + SC_IMMUNE_PROPERTY_POISON, + SC_IMMUNE_PROPERTY_SAINT, + SC_IMMUNE_PROPERTY_DARKNESS, + SC_IMMUNE_PROPERTY_TELEKINESIS, + SC_IMMUNE_PROPERTY_UNDEAD, #ifdef RENEWAL SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled