From 72b3d1bf0ea90fdab7c65df38047da437a655932 Mon Sep 17 00:00:00 2001 From: Lemongrass3110 Date: Wed, 17 Jan 2024 21:20:20 +0100 Subject: [PATCH] Initial implementation of Hyper Novice (#8101) Taken from #7024 Co-authored-by: munkrej Co-authored-by: Aleos --- db/re/skill_db.yml | 780 +++++++++++++++++++++++++++++++++++ db/re/skill_tree.yml | 86 ++++ db/re/status.yml | 28 ++ src/map/battle.cpp | 133 ++++++ src/map/script_constants.hpp | 19 +- src/map/skill.cpp | 119 +++++- src/map/skill.hpp | 3 + src/map/status.cpp | 8 + src/map/status.hpp | 9 + 9 files changed, 1181 insertions(+), 4 deletions(-) diff --git a/db/re/skill_db.yml b/db/re/skill_db.yml index 3774fdea78..c0b0afdaa4 100644 --- a/db/re/skill_db.yml +++ b/db/re/skill_db.yml @@ -41385,6 +41385,786 @@ Body: SplashArea: 6 Requires: SpCost: 1 + - Id: 5449 + Name: HN_SELFSTUDY_TATICS + Description: Self Study Tactics + MaxLevel: 10 + - Id: 5450 + Name: HN_SELFSTUDY_SOCERY + Description: Self Study Sorcery + MaxLevel: 10 + - Id: 5451 + Name: HN_DOUBLEBOWLINGBASH + Description: Double Bowling Bash + MaxLevel: 10 + Type: Weapon + TargetType: Attack + Range: 2 + Hit: Multi_Hit + HitCount: 3 + Element: Weapon + DamageFlags: + Splash: true + SplashArea: 4 + Knockback: 2 + CastCancel: true + CastTime: 300 + AfterCastActDelay: 1000 + GiveAp: 3 + Cooldown: 1000 + FixedCastTime: 200 + Duration2: 1000 + Requires: + SpCost: + - Level: 1 + Amount: 38 + - Level: 2 + Amount: 41 + - Level: 3 + Amount: 44 + - Level: 4 + Amount: 47 + - Level: 5 + Amount: 50 + - Level: 6 + Amount: 53 + - Level: 7 + Amount: 56 + - Level: 8 + Amount: 59 + - Level: 9 + Amount: 62 + - Level: 10 + Amount: 65 + Status: Hnnoweapon + - Id: 5452 + Name: HN_MEGA_SONIC_BLOW + Description: Mega Sonic Blow + MaxLevel: 10 + Type: Weapon + TargetType: Attack + DamageFlags: + Critical: true + Range: 2 + Hit: Multi_Hit + HitCount: -8 + GiveAp: 2 + Element: Weapon + AfterCastActDelay: 500 + Cooldown: 300 + Duration2: 5000 + Requires: + SpCost: + - Level: 1 + Amount: 42 + - Level: 2 + Amount: 44 + - Level: 3 + Amount: 46 + - Level: 4 + Amount: 48 + - Level: 5 + Amount: 50 + - Level: 6 + Amount: 52 + - Level: 7 + Amount: 54 + - Level: 8 + Amount: 56 + - Level: 9 + Amount: 58 + - Level: 10 + Amount: 60 + - Id: 5453 + Name: HN_SHIELD_CHAIN_RUSH + Description: Shield Chain Rush + MaxLevel: 10 + Type: Weapon + TargetType: Attack + Range: 7 + Hit: Multi_Hit + HitCount: -5 + DamageFlags: + Splash: true + SplashArea: 4 + GiveAp: 2 + Element: Weapon + CastCancel: true + CastTime: 1200 + AfterCastActDelay: 500 + Cooldown: 300 + FixedCastTime: 300 + Duration1: 5000 + Duration2: 1200 + Requires: + SpCost: + - Level: 1 + Amount: 35 + - Level: 2 + Amount: 38 + - Level: 3 + Amount: 41 + - Level: 4 + Amount: 44 + - Level: 5 + Amount: 47 + - Level: 6 + Amount: 50 + - Level: 7 + Amount: 53 + - Level: 8 + Amount: 56 + - Level: 9 + Amount: 59 + - Level: 10 + Amount: 62 + State: Shield + Status: Shieldchainrush + - Id: 5454 + Name: HN_SPIRAL_PIERCE_MAX + Description: Spiral Pierce Max + MaxLevel: 10 + Type: Weapon + TargetType: Attack + Range: 7 + Hit: Multi_Hit + HitCount: -5 + Element: Weapon + GiveAp: 2 + CastCancel: true + CastTime: 1000 + AfterCastActDelay: 500 + Cooldown: 300 + FixedCastTime: 300 + Duration2: 2000 + Requires: + SpCost: + - Level: 1 + Amount: 37 + - Level: 2 + Amount: 39 + - Level: 3 + Amount: 41 + - Level: 4 + Amount: 43 + - Level: 5 + Amount: 45 + - Level: 6 + Amount: 47 + - Level: 7 + Amount: 49 + - Level: 8 + Amount: 51 + - Level: 9 + Amount: 53 + - Level: 10 + Amount: 55 + - Id: 5455 + Name: HN_METEOR_STORM_BUSTER + Description: Meteor Storm Buster + MaxLevel: 10 + Type: Magic + TargetType: Ground + Range: -9 + Hit: Multi_Hit + HitCount: 1 + Element: Fire + GiveAp: 3 + DamageFlags: + Splash: true + SplashArea: 2 + CastCancel: true + CastTime: 4000 + Cooldown: + - Level: 1 + Time: 2100 + - Level: 2 + Time: 2200 + - Level: 3 + Time: 2300 + - Level: 4 + Time: 2400 + - Level: 5 + Time: 2500 + - Level: 6 + Time: 2600 + - Level: 7 + Time: 2700 + - Level: 8 + Time: 2800 + - Level: 9 + Time: 2900 + - Level: 10 + Time: 3000 + FixedCastTime: 1500 + Duration1: + - Level: 1 + Time: 1000 + - Level: 2 + Time: 1000 + - Level: 3 + Time: 1500 + - Level: 4 + Time: 1500 + - Level: 5 + Time: 2000 + - Level: 6 + Time: 2000 + - Level: 7 + Time: 2000 + - Level: 8 + Time: 2500 + - Level: 9 + Time: 2500 + - Level: 10 + Time: 2500 + Duration2: 500 + Requires: + SpCost: + - Level: 1 + Amount: 74 + - Level: 2 + Amount: 78 + - Level: 3 + Amount: 82 + - Level: 4 + Amount: 86 + - Level: 5 + Amount: 90 + - Level: 6 + Amount: 94 + - Level: 7 + Amount: 98 + - Level: 8 + Amount: 102 + - Level: 9 + Amount: 106 + - Level: 10 + Amount: 110 + Unit: + Id: Dummyskill + Range: + - Level: 1 + Size: 3 + - Level: 2 + Size: 3 + - Level: 3 + Size: 3 + - Level: 4 + Size: 3 + - Level: 5 + Size: 3 + - Level: 6 + Size: 3 + - Level: 7 + Size: 3 + - Level: 8 + Size: 4 + - Level: 9 + Size: 4 + - Level: 10 + Size: 4 + Interval: 1500 + Target: Enemy + Flag: + PathCheck: true + - Id: 5456 + Name: HN_JUPITEL_THUNDER_STORM + Description: Jupitel Thunderstorm + MaxLevel: 10 + Type: Magic + TargetType: Attack + Range: 11 + Hit: Multi_Hit + HitCount: -10 + Element: Wind + GiveAp: 2 + DamageFlags: + Splash: true + SplashArea: + - Level: 1 + Area: 2 + - Level: 2 + Area: 2 + - Level: 3 + Area: 2 + - Level: 4 + Area: 2 + - Level: 5 + Area: 3 + - Level: 6 + Area: 3 + - Level: 7 + Area: 3 + - Level: 8 + Area: 3 + - Level: 9 + Area: 4 + - Level: 10 + Area: 4 + CastCancel: true + CastTime: + - Level: 1 + Time: 1100 + - Level: 2 + Time: 1200 + - Level: 3 + Time: 1300 + - Level: 4 + Time: 1400 + - Level: 5 + Time: 1500 + - Level: 6 + Time: 1600 + - Level: 7 + Time: 1700 + - Level: 8 + Time: 1800 + - Level: 9 + Time: 1900 + - Level: 10 + Time: 2000 + AfterCastActDelay: 500 + Cooldown: 1800 + FixedCastTime: 1000 + Requires: + SpCost: + - Level: 1 + Amount: 75 + - Level: 2 + Amount: 80 + - Level: 3 + Amount: 85 + - Level: 4 + Amount: 90 + - Level: 5 + Amount: 95 + - Level: 6 + Amount: 100 + - Level: 7 + Amount: 105 + - Level: 8 + Amount: 110 + - Level: 9 + Amount: 115 + - Level: 10 + Amount: 120 + - Id: 5457 + Name: HN_JACK_FROST_NOVA + Description: Jack Frost Nova + MaxLevel: 10 + Type: Magic + TargetType: Ground + Range: -9 + Hit: Multi_Hit + HitCount: -2 + Element: Water + GiveAp: 3 + DamageFlags: + Splash: true + SplashArea: + - Level: 1 + Area: 3 + - Level: 2 + Area: 3 + - Level: 3 + Area: 3 + - Level: 4 + Area: 3 + - Level: 5 + Area: 3 + - Level: 6 + Area: 4 + - Level: 7 + Area: 4 + - Level: 8 + Area: 4 + - Level: 9 + Area: 4 + - Level: 10 + Area: 4 + CastCancel: true + CastTime: + - Level: 1 + Time: 1600 + - Level: 2 + Time: 1700 + - Level: 3 + Time: 1800 + - Level: 4 + Time: 1900 + - Level: 5 + Time: 2000 + - Level: 6 + Time: 2100 + - Level: 7 + Time: 2200 + - Level: 8 + Time: 2300 + - Level: 9 + Time: 2400 + - Level: 10 + Time: 2500 + AfterCastActDelay: 300 + Cooldown: 3000 + FixedCastTime: 1500 + Duration1: + - Level: 1 + Time: 900 + - Level: 2 + Time: 1200 + - Level: 3 + Time: 1500 + - Level: 4 + Time: 1800 + - Level: 5 + Time: 2100 + - Level: 6 + Time: 2400 + - Level: 7 + Time: 2700 + - Level: 8 + Time: 3000 + - Level: 9 + Time: 3300 + - Level: 10 + Time: 3600 + Duration2: 5000 + Requires: + SpCost: + - Level: 1 + Amount: 68 + - Level: 2 + Amount: 71 + - Level: 3 + Amount: 74 + - Level: 4 + Amount: 77 + - Level: 5 + Amount: 80 + - Level: 6 + Amount: 83 + - Level: 7 + Amount: 86 + - Level: 8 + Amount: 89 + - Level: 9 + Amount: 92 + - Level: 10 + Amount: 95 + Unit: + Id: JACK_FROST_NOVA + Range: + - Level: 1 + Size: 3 + - Level: 2 + Size: 3 + - Level: 3 + Size: 3 + - Level: 4 + Size: 3 + - Level: 5 + Size: 3 + - Level: 6 + Size: 4 + - Level: 7 + Size: 4 + - Level: 8 + Size: 4 + - Level: 9 + Size: 4 + - Level: 10 + Size: 4 + Interval: 300 + Target: Enemy + Flag: + PathCheck: true + Status: Mistyfrost + - Id: 5458 + Name: HN_HELLS_DRIVE + Description: Hell's Drive + MaxLevel: 10 + Type: Magic + TargetType: Self + Range: 1 + Hit: Multi_Hit + HitCount: -3 + Element: Earth + GiveAp: 2 + DamageFlags: + Splash: true + SplashArea: + - Level: 1 + Area: 1 + - Level: 2 + Area: 1 + - Level: 3 + Area: 1 + - Level: 4 + Area: 2 + - Level: 5 + Area: 2 + - Level: 6 + Area: 2 + - Level: 7 + Area: 3 + - Level: 8 + Area: 3 + - Level: 9 + Area: 3 + - Level: 10 + Area: 4 + CastCancel: true + CastTime: 1200 + AfterCastActDelay: 1000 + Cooldown: + - Level: 1 + Time: 2500 + - Level: 2 + Time: 2300 + - Level: 3 + Time: 2100 + - Level: 4 + Time: 1900 + - Level: 5 + Time: 1700 + - Level: 6 + Time: 1500 + - Level: 7 + Time: 1300 + - Level: 8 + Time: 1100 + - Level: 9 + Time: 900 + - Level: 10 + Time: 700 + FixedCastTime: 1000 + Requires: + SpCost: + - Level: 1 + Amount: 71 + - Level: 2 + Amount: 74 + - Level: 3 + Amount: 77 + - Level: 4 + Amount: 80 + - Level: 5 + Amount: 83 + - Level: 6 + Amount: 86 + - Level: 7 + Amount: 89 + - Level: 8 + Amount: 92 + - Level: 9 + Amount: 95 + - Level: 10 + Amount: 98 + - Id: 5459 + Name: HN_GROUND_GRAVITATION + Description: Ground Gravitation + MaxLevel: 10 + Type: Magic + TargetType: Self + Range: -9 + Hit: Multi_Hit + HitCount: 1 + Element: Neutral + GiveAp: 5 + DamageFlags: + Splash: true + SplashArea: + - Level: 1 + Area: 2 + - Level: 2 + Area: 2 + - Level: 3 + Area: 2 + - Level: 4 + Area: 2 + - Level: 5 + Area: 3 + - Level: 6 + Area: 3 + - Level: 7 + Area: 3 + - Level: 8 + Area: 3 + - Level: 9 + Area: 4 + - Level: 10 + Area: 4 + CastCancel: true + CastTime: + - Level: 1 + Time: 3000 + - Level: 2 + Time: 3000 + - Level: 3 + Time: 3000 + - Level: 4 + Time: 3200 + - Level: 5 + Time: 3500 + - Level: 6 + Time: 3800 + - Level: 7 + Time: 4100 + - Level: 8 + Time: 4400 + - Level: 9 + Time: 4700 + - Level: 10 + Time: 5000 + AfterCastActDelay: + - Level: 1 + Time: 2000 + - Level: 2 + Time: 2000 + - Level: 3 + Time: 2000 + - Level: 4 + Time: 1800 + - Level: 5 + Time: 1800 + - Level: 6 + Time: 1800 + - Level: 7 + Time: 1600 + - Level: 8 + Time: 1400 + - Level: 9 + Time: 1200 + - Level: 10 + Time: 1000 + Cooldown: 5000 + FixedCastTime: 1500 + Duration1: 5000 + Duration2: 5000 + Requires: + SpCost: + - Level: 1 + Amount: 55 + - Level: 2 + Amount: 60 + - Level: 3 + Amount: 65 + - Level: 4 + Amount: 70 + - Level: 5 + Amount: 75 + - Level: 6 + Amount: 80 + - Level: 7 + Amount: 85 + - Level: 8 + Amount: 90 + - Level: 9 + Amount: 95 + - Level: 10 + Amount: 100 + Unit: + Id: GROUND_GRAVITATION + Range: + - Level: 1 + Size: 2 + - Level: 2 + Size: 2 + - Level: 3 + Size: 2 + - Level: 4 + Size: 2 + - Level: 5 + Size: 3 + - Level: 6 + Size: 3 + - Level: 7 + Size: 3 + - Level: 8 + Size: 3 + - Level: 9 + Size: 4 + - Level: 10 + Size: 4 + Interval: 500 + Target: Enemy + Flag: + PathCheck: true + Status: Groundgravity + - Id: 5460 + Name: HN_NAPALM_VULCAN_STRIKE + Description: Napalm Vulcan Strike + MaxLevel: 10 + Type: Magic + TargetType: Attack + Range: 11 + Hit: Multi_Hit + HitCount: -7 + Element: Ghost + GiveAp: 2 + DamageFlags: + Splash: true + SplashArea: 3 + CastCancel: true + CastTime: 500 + Cooldown: 300 + AfterCastActDelay: 500 + FixedCastTime: 1000 + Requires: + SpCost: + - Level: 1 + Amount: 48 + - Level: 2 + Amount: 51 + - Level: 3 + Amount: 54 + - Level: 4 + Amount: 57 + - Level: 5 + Amount: 60 + - Level: 6 + Amount: 63 + - Level: 7 + Amount: 66 + - Level: 8 + Amount: 69 + - Level: 9 + Amount: 72 + - Level: 10 + Amount: 75 + - Id: 5461 + Name: HN_BREAKINGLIMIT + Description: Breaking Limit + MaxLevel: 1 + Type: Magic + TargetType: Self + DamageFlags: + NoDamage: true + Duration1: 300000 + Cooldown: 60000 + CastCancel: true + FixedCastTime: 1000 + Requires: + SpCost: 150 + ApCost: 150 + Status: Breakinglimit + - Id: 5462 + Name: HN_RULEBREAK + Description: Rule Break + MaxLevel: 1 + Type: Magic + TargetType: Self + DamageFlags: + NoDamage: true + Duration1: 300000 + Cooldown: 60000 + CastCancel: true + FixedCastTime: 1000 + Requires: + SpCost: 150 + ApCost: 150 + Status: Rulebreak - Id: 6001 Name: DK_DRAGONIC_BREATH Description: Dragonic Breath diff --git a/db/re/skill_tree.yml b/db/re/skill_tree.yml index 02d5d441cd..9788a49f67 100644 --- a/db/re/skill_tree.yml +++ b/db/re/skill_tree.yml @@ -7864,3 +7864,89 @@ Body: Royal_Guard: true Royal_Guard_T: true Imperial_Guard: true + - Job: Hyper_Novice + Inherit: + Novice: true + Supernovice: true + Super_Novice_E: true + Tree: + - Name: HN_SELFSTUDY_TATICS + MaxLevel: 10 + - Name: HN_SELFSTUDY_SOCERY + MaxLevel: 10 + - Name: HN_DOUBLEBOWLINGBASH + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_TATICS + Level: 5 + - Name: HN_SHIELD_CHAIN_RUSH + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_TATICS + Level: 5 + - Name: HN_METEOR_STORM_BUSTER + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_SOCERY + Level: 5 + - Name: HN_JUPITEL_THUNDER_STORM + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_SOCERY + Level: 5 + - Name: HN_JACK_FROST_NOVA + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_SOCERY + Level: 5 + - Name: HN_HELLS_DRIVE + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_SOCERY + Level: 5 + - Name: HN_MEGA_SONIC_BLOW + MaxLevel: 10 + Requires: + - Name: HN_DOUBLEBOWLINGBASH + Level: 7 + - Name: HN_SPIRAL_PIERCE_MAX + MaxLevel: 10 + Requires: + - Name: HN_SHIELD_CHAIN_RUSH + Level: 7 + - Name: HN_GROUND_GRAVITATION + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_SOCERY + Level: 5 + - Name: HN_NAPALM_VULCAN_STRIKE + MaxLevel: 10 + Requires: + - Name: HN_SELFSTUDY_SOCERY + Level: 5 + - Name: HN_BREAKINGLIMIT + MaxLevel: 1 + Requires: + - Name: HN_DOUBLEBOWLINGBASH + Level: 7 + - Name: HN_MEGA_SONIC_BLOW + Level: 7 + - Name: HN_SHIELD_CHAIN_RUSH + Level: 7 + - Name: HN_SPIRAL_PIERCE_MAX + Level: 7 + - Name: HN_RULEBREAK + MaxLevel: 1 + Requires: + - Name: HN_METEOR_STORM_BUSTER + Level: 5 + - Name: HN_JUPITEL_THUNDER_STORM + Level: 5 + - Name: HN_JACK_FROST_NOVA + Level: 5 + - Name: HN_HELLS_DRIVE + Level: 5 + - Name: HN_GROUND_GRAVITATION + Level: 5 + - Name: HN_NAPALM_VULCAN_STRIKE + Level: 5 diff --git a/db/re/status.yml b/db/re/status.yml index fc9c373dd3..5bc04d39c3 100644 --- a/db/re/status.yml +++ b/db/re/status.yml @@ -8753,3 +8753,31 @@ Body: NoDispell: true NoBanishingBuster: true NoClearance: true + - Status: Hnnoweapon + Icon: EFST_NOEQUIPWEAPON + DurationLookup: HN_DOUBLEBOWLINGBASH + - Status: Shieldchainrush + Icon: EFST_SHIELDCHAINRUSH + DurationLookup: HN_SHIELD_CHAIN_RUSH + CalcFlags: + Speed: true + Flags: + BossResist: true + - Status: Mistyfrost + Icon: EFST_MISTYFROST + DurationLookup: HN_JACK_FROST_NOVA + Flags: + BossResist: true + - Status: Groundgravity + Icon: EFST_GROUNDGRAVITY + DurationLookup: HN_GROUND_GRAVITATION + CalcFlags: + Speed: true + Flags: + BossResist: true + - Status: Breakinglimit + Icon: EFST_BREAKINGLIMIT + DurationLookup: HN_BREAKINGLIMIT + - Status: Rulebreak + Icon: EFST_RULEBREAK + DurationLookup: HN_RULEBREAK diff --git a/src/map/battle.cpp b/src/map/battle.cpp index 03e74746dd..1ae1415488 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -580,6 +580,12 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d ratio += 50; #else damage += (int64)(damage * 50 / 100); +#endif + if (tsc->getSCE(SC_MISTYFROST)) +#ifdef RENEWAL + ratio += 15; +#else + damage += (int64)(damage * 15 / 100); #endif break; case ELE_EARTH: @@ -1569,6 +1575,11 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam damage *= 4; #endif + if (tsc->getSCE(SC_GROUNDGRAVITY) && flag&(BF_MAGIC|BF_WEAPON)) + damage += damage * 15 / 100; + if (tsc->getSCE(SC_SHIELDCHAINRUSH)) + damage += damage / 10; + if (tsc->getSCE(SC_AETERNA) && skill_id != PF_SOULBURN) { if (src->type != BL_MER || !skill_id) damage *= 2; // Lex Aeterna only doubles damage of regular attacks from mercenaries @@ -1831,6 +1842,36 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam status_change* sc = status_get_sc(src); if (sc && sc->count) { + if (sc->getSCE(SC_BREAKINGLIMIT)) { + switch (skill_id) { + case HN_SHIELD_CHAIN_RUSH: + case HN_DOUBLEBOWLINGBASH: + damage += damage / 2; + break; + case HN_MEGA_SONIC_BLOW: + case HN_SPIRAL_PIERCE_MAX: + damage += damage * 70 / 100; + break; + } + } + + if (sc->getSCE(SC_RULEBREAK)) { + switch (skill_id) { + case HN_METEOR_STORM_BUSTER: + case HN_GROUND_GRAVITATION: + damage += damage / 2; + break; + case HN_JUPITEL_THUNDER_STORM: + case HN_JACK_FROST_NOVA: + case HN_HELLS_DRIVE: + damage += damage * 70 / 100; + break; + case HN_NAPALM_VULCAN_STRIKE: + damage += damage * 40 / 100; + break; + } + } + if( sc->getSCE(SC_INVINCIBLE) && !sc->getSCE(SC_INVINCIBLEOFF) ) damage += damage * 75 / 100; @@ -5775,6 +5816,43 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list * case ABR_INFINITY_BUSTER:// Need official formula. skillratio += -100 + 50000; break; + case HN_SPIRAL_PIERCE_MAX: + skillratio += -100 + 550 + 350 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_TATICS) * 3 * skill_lv; + skillratio += 5 * sstatus->pow; + switch (status_get_size(target)){ + case SZ_SMALL: + skillratio = skillratio * 150 / 100; + break; + case SZ_MEDIUM: + skillratio = skillratio * 130 / 100; + break; + case SZ_BIG: + skillratio = skillratio * 120 / 100; + break; + } + RE_LVL_DMOD(100); + break; + case HN_SHIELD_CHAIN_RUSH: + skillratio += -100 + 600 + 450 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_TATICS) * 3 * skill_lv; + skillratio += 5 * sstatus->pow; + RE_LVL_DMOD(100); + break; + case HN_MEGA_SONIC_BLOW: + skillratio += -100 + 900 + 450 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_TATICS) * 5 * skill_lv; + skillratio += 5 * sstatus->pow; + if (status_get_hp(target) < status_get_max_hp(target) / 2) + skillratio *= 2; + RE_LVL_DMOD(100); + break; + case HN_DOUBLEBOWLINGBASH: + skillratio += -100 + 150 + 250 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_TATICS) * 3 * skill_lv; + skillratio += 5 * sstatus->pow; + RE_LVL_DMOD(100); + break; } return skillratio; } @@ -6742,6 +6820,10 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block if (sc && sc->getSCE(SC_RESEARCHREPORT)) wd.div_ = 4; break; + case HN_DOUBLEBOWLINGBASH: + if (wd.miscflag > 1) + wd.div_ += min(4, wd.miscflag); + break; } } else { bool is_long = false; @@ -8177,6 +8259,57 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case NPC_RAINOFMETEOR: skillratio += 350; // unknown ratio break; + case HN_NAPALM_VULCAN_STRIKE: + skillratio += -100 + 350 + 650 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_SOCERY) * 4 * skill_lv; + skillratio += 5 * sstatus->spl; + RE_LVL_DMOD(100); + break; + case HN_JUPITEL_THUNDER_STORM: + skillratio += -100 + 1800 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_SOCERY) * 3 * skill_lv; + skillratio += 5 * sstatus->spl; + RE_LVL_DMOD(100); + break; + case HN_HELLS_DRIVE: + skillratio += -100 + 1500 + 700 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_SOCERY) * 4 * skill_lv; + skillratio += 5 * sstatus->spl; + RE_LVL_DMOD(100); + break; + case HN_GROUND_GRAVITATION: + if (mflag & SKILL_ALTDMG_FLAG) { + skillratio += -100 + 3000 + 1500 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_SOCERY) * 4 * skill_lv; + ad.div_ = -2; + } else { + skillratio += -100 + 800 + 700 * skill_lv; + skillratio += pc_checkskill(sd, HN_SELFSTUDY_SOCERY) * 2 * skill_lv; + } + skillratio += 5 * sstatus->spl; + RE_LVL_DMOD(100); + break; + case HN_JACK_FROST_NOVA: + if (mflag & SKILL_ALTDMG_FLAG) { + skillratio += -100 + 200 * skill_lv; + } else { + skillratio += -100 + 400 + 500 * skill_lv; + } + skillratio += pc_checkskill(sd, HN_SELFSTUDY_SOCERY) * 3 * skill_lv; + skillratio += 5 * sstatus->spl; + RE_LVL_DMOD(100); + break; + case HN_METEOR_STORM_BUSTER: + if (mflag & SKILL_ALTDMG_FLAG) { + skillratio += -100 + 300 + 160 * skill_lv * 2; + ad.div_ = -3; + } else { + skillratio += -100 + 450 + 160 * skill_lv; + } + skillratio += pc_checkskill(sd, HN_SELFSTUDY_SOCERY) * 5 * skill_lv; + skillratio += 5 * sstatus->spl; + RE_LVL_DMOD(100); + break; } if (sc) {// Insignia's increases the damage of offensive magic by a fixed percentage depending on the element. diff --git a/src/map/script_constants.hpp b/src/map/script_constants.hpp index 513e710f05..8ffda6775d 100644 --- a/src/map/script_constants.hpp +++ b/src/map/script_constants.hpp @@ -1894,6 +1894,12 @@ export_constant(SC_RUSH_QUAKE1); export_constant(SC_RUSH_QUAKE2); export_constant(SC_G_LIFEPOTION); + export_constant(SC_HNNOWEAPON); + export_constant(SC_SHIELDCHAINRUSH); + export_constant(SC_MISTYFROST); + export_constant(SC_GROUNDGRAVITY); + export_constant(SC_BREAKINGLIMIT); + export_constant(SC_RULEBREAK); #ifdef RENEWAL export_constant(SC_EXTREMITYFIST2); @@ -10065,12 +10071,21 @@ export_constant(UNT_LIGHTNING_LAND); export_constant(UNT_VENOM_SWAMP); export_constant(UNT_CONFLAGRATION); - export_constant(UNT_DEEPBLINDTRAP); export_constant(UNT_SOLIDTRAP); export_constant(UNT_SWIFTTRAP); export_constant(UNT_FLAMETRAP); - + export_constant(UNT_TWINKLING_GALAXY); + export_constant(UNT_STAR_CANNON); + export_constant(UNT_GRENADES_DROPPING); + export_constant(UNT_FUUMASHOUAKU); + export_constant(UNT_MISSION_BOMBARD); + export_constant(UNT_TOTEM_OF_TUTELARY); + export_constant(UNT_HYUN_ROKS_BREEZE); + export_constant(UNT_SHINKIROU); + export_constant(UNT_JACK_FROST_NOVA); + export_constant(UNT_GROUND_GRAVITATION); + export_constant(UNT_KUNAIWAIKYOKU); export_constant(UNT_GD_LEADERSHIP); export_constant(UNT_GD_GLORYWOUNDS); export_constant(UNT_GD_SOULCOLD); diff --git a/src/map/skill.cpp b/src/map/skill.cpp index a2615adc88..60c051e4d8 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -1434,6 +1434,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint break; case AS_SONICBLOW: + case HN_MEGA_SONIC_BLOW: sc_start(src,bl,SC_STUN,(2*skill_lv+10),skill_lv,skill_get_time2(skill_id,skill_lv)); break; @@ -1480,6 +1481,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint break; case WZ_METEOR: + case HN_METEOR_STORM_BUSTER: sc_start(src,bl,SC_STUN,3*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); break; @@ -1696,6 +1698,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint case LK_SPIRALPIERCE: case ML_SPIRALPIERCE: + case HN_SPIRAL_PIERCE_MAX: if( dstsd || ( dstmd && !status_bl_has_mode(bl,MD_STATUSIMMUNE) ) ) //Does not work on status immune sc_start(src,bl,SC_STOP,100,0,skill_get_time2(skill_id,skill_lv)); break; @@ -1729,6 +1732,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint break; case HW_NAPALMVULCAN: + case HN_NAPALM_VULCAN_STRIKE: sc_start(src,bl,SC_CURSE,5*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); break; @@ -2203,6 +2207,11 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint case MT_RUSH_QUAKE: sc_start( src, bl, SC_RUSH_QUAKE1, 100, skill_lv, skill_get_time( skill_id, skill_lv ) ); break; + case HN_SHIELD_CHAIN_RUSH: + case HN_JACK_FROST_NOVA: + case HN_GROUND_GRAVITATION: + sc_start(src, bl, skill_get_sc(skill_id), 100, 0, skill_get_time2(skill_id, skill_lv)); + break; } //end switch skill_id if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai && md->special_state.ai != AI_ABR && md->special_state.ai != AI_BIONIC) @@ -4769,6 +4778,22 @@ static TIMER_FUNC(skill_timerskill){ case NC_MAGMA_ERUPTION: skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,0); break; + case HN_METEOR_STORM_BUSTER: { + int16 area = 4; + int16 tmpx = rnd_value( skl->x - area, skl->x + area ); + int16 tmpy = rnd_value( skl->y - area, skl->y + area ); + + if( map_getcell(src->m, tmpx, tmpy, CELL_CHKLANDPROTECTOR) ) { + return 0; + } + + int splash = skill_get_splash(skl->skill_id, skl->skill_lv); + + clif_skill_poseffect(src, skl->skill_id, skl->skill_lv, tmpx, tmpy, tick); + map_foreachinarea(skill_area_sub, src->m, tmpx - splash, tmpy - splash, tmpx + splash, tmpy + splash, BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, skl->flag | BCT_ENEMY | SD_SPLASH | SKILL_ALTDMG_FLAG | 1, skill_castend_damage_id); + skill_unitsetting(src, skl->skill_id, skl->skill_lv, tmpx, tmpy, skill_get_unit_interval(skl->skill_id)); + } + break; } } } while (0); @@ -5220,6 +5245,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case WH_HAWKBOOMERANG: case TR_ROSEBLOSSOM: case TR_RHYTHMSHOOTING: + case HN_MEGA_SONIC_BLOW: + case HN_SPIRAL_PIERCE_MAX: clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); if (skill_id == DK_DRAGONIC_AURA) @@ -5669,6 +5696,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case IG_SHIELD_SHOOTING: case TR_METALIC_FURY: case IG_GRAND_JUDGEMENT: + case HN_JUPITEL_THUNDER_STORM: if( flag&1 ) {//Recursive invocation int sflag = skill_area_temp[0] & 0xFFF; int heal = 0; @@ -5739,6 +5767,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case DK_DRAGONIC_BREATH: case DK_HACKANDSLASHER: case MT_SPARK_BLASTER: + case HN_JUPITEL_THUNDER_STORM: clif_skill_nodamage(src,bl,skill_id,skill_lv,1); break; #ifdef RENEWAL @@ -6087,6 +6116,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case AG_ASTRAL_STRIKE_ATK: case AG_DESTRUCTIVE_HURRICANE_CLIMAX: case CD_ARBITRIUM: + case HN_METEOR_STORM_BUSTER: skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); break; @@ -7011,6 +7041,44 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint sc_start(src, bl, SC_VENOMIMPRESS, 100, skill_lv, skill_get_time(skill_id,skill_lv)); break; + case HN_DOUBLEBOWLINGBASH: + if (flag & 1) { + skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, skill_area_temp[0] & 0xFFF); + } else { + int splash = skill_get_splash(skill_id, skill_lv); + clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); + skill_area_temp[0] = map_foreachinallrange(skill_area_sub, bl, splash, BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill_area_sub_count); + map_foreachinrange(skill_area_sub, bl, splash, BL_CHAR, src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); + sc_start(src, src, SC_HNNOWEAPON, 100, skill_lv, skill_get_time2(skill_id, skill_lv)); + } + break; + + case HN_SHIELD_CHAIN_RUSH: + if (flag & 1) { + 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_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); + sc_start(src, src, SC_HNNOWEAPON, 100, skill_lv, skill_get_time2(skill_id, skill_lv)); + } + break; + + case HN_JACK_FROST_NOVA: + case HN_HELLS_DRIVE: + case HN_GROUND_GRAVITATION: + if (flag & 1) + skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); + break; + + case HN_NAPALM_VULCAN_STRIKE: + if (flag & 1) { + 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_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); + } + break; + default: ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skill_id); clif_skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion, @@ -7900,6 +7968,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case NPC_DAMAGE_HEAL: case NPC_RELIEVE_ON: case NPC_RELIEVE_OFF: + case HN_BREAKINGLIMIT: + case HN_RULEBREAK: 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; @@ -12792,6 +12862,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui } break; + case HN_HELLS_DRIVE: + clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); + map_foreachinrange(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_damage_id); + break; + default: { std::shared_ptr skill = skill_db.find(skill_id); ShowWarning("skill_castend_nodamage_id: missing code case for skill %s(%d)\n", skill ? skill->name : "UNKNOWN", skill_id); @@ -13529,6 +13604,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case SC_ESCAPE: case SU_CN_METEOR: case NPC_RAINOFMETEOR: + case HN_METEOR_STORM_BUSTER: break; //Effect is displayed on respective switch case. default: if(skill_get_inf(skill_id)&INF_SELF_SKILL) @@ -14436,6 +14512,41 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui } break; + case HN_JACK_FROST_NOVA: + case HN_GROUND_GRAVITATION: { + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) { + clif_skill_fail(sd,skill_id,USESKILL_FAIL,0); + return 0; + } + + int splash = skill_get_splash(skill_id, skill_lv); + + map_foreachinarea(skill_area_sub, src->m, x - splash, y - splash, x + splash, y + splash, BL_CHAR, src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | SKILL_ALTDMG_FLAG | 1, skill_castend_damage_id); + skill_unitsetting(src, skill_id, skill_lv, x, y, flag); + + for (i = 1; i <= (skill_get_time(skill_id, skill_lv) / skill_get_unit_interval(skill_id)); i++) { + skill_addtimerskill(src, tick + (t_tick)i*skill_get_unit_interval(skill_id), 0, x, y, skill_id, skill_lv, 0, flag); + } + } + break; + + case HN_METEOR_STORM_BUSTER: { + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) { + clif_skill_fail(sd,skill_id,USESKILL_FAIL,0); + return 0; + } + + int splash = skill_get_splash(skill_id, skill_lv); + + map_foreachinarea(skill_area_sub, src->m, x - splash, y - splash, x + splash, y + splash, BL_CHAR, src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | SKILL_ALTDMG_FLAG | 1, skill_castend_damage_id); + skill_unitsetting(src, skill_id, skill_lv, x, y, skill_get_unit_interval(skill_id)); + + for (i = 1; i <= (skill_get_time(skill_id, skill_lv) / skill_get_time2(skill_id, skill_lv)); i++) { + skill_addtimerskill(src, tick + (t_tick)i*skill_get_time2(skill_id, skill_lv), 0, x, y, skill_id, skill_lv, 0, flag); + } + } + break; + default: ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skill_id); return 1; @@ -14775,6 +14886,7 @@ std::shared_ptr skill_unitsetting(struct block_list *src, ui case SU_CN_METEOR: case SU_CN_METEOR2: case NPC_RAINOFMETEOR: + case HN_METEOR_STORM_BUSTER: limit = flag; flag = 0; // Flag should not influence anything else for these skills break; @@ -21108,7 +21220,8 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) default: if (group->val2 == 1 && (group->skill_id == WZ_METEOR || group->skill_id == SU_CN_METEOR || group->skill_id == SU_CN_METEOR2 || - group->skill_id == AG_VIOLENT_QUAKE_ATK || group->skill_id == AG_ALL_BLOOM_ATK || group->skill_id == AG_ALL_BLOOM_ATK2 || group->skill_id == NPC_RAINOFMETEOR)) { + group->skill_id == AG_VIOLENT_QUAKE_ATK || group->skill_id == AG_ALL_BLOOM_ATK || group->skill_id == AG_ALL_BLOOM_ATK2 || group->skill_id == NPC_RAINOFMETEOR || + group->skill_id == HN_METEOR_STORM_BUSTER)) { // Deal damage before expiration break; } @@ -21164,7 +21277,8 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) break; default: if (group->skill_id == WZ_METEOR || group->skill_id == SU_CN_METEOR || group->skill_id == SU_CN_METEOR2 || - group->skill_id == AG_VIOLENT_QUAKE_ATK || group->skill_id == AG_ALL_BLOOM_ATK || group->skill_id == AG_ALL_BLOOM_ATK2 || group->skill_id == NPC_RAINOFMETEOR) { + group->skill_id == AG_VIOLENT_QUAKE_ATK || group->skill_id == AG_ALL_BLOOM_ATK || group->skill_id == AG_ALL_BLOOM_ATK2 || group->skill_id == NPC_RAINOFMETEOR || + group->skill_id == HN_METEOR_STORM_BUSTER) { if (group->val2 == 0 && (DIFF_TICK(tick, group->tick) >= group->limit - group->interval || DIFF_TICK(tick, group->tick) >= unit->limit - group->interval)) { // Unit will expire the next interval, start dropping Meteor block_list *src = map_id2bl(group->src_id); @@ -21206,6 +21320,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) } else if (group->skill_id == WZ_METEOR || group->skill_id == SU_CN_METEOR || group->skill_id == SU_CN_METEOR2 || group->skill_id == AG_VIOLENT_QUAKE_ATK || group->skill_id == AG_ALL_BLOOM_ATK || group->skill_id == AG_ALL_BLOOM_ATK2 || group->skill_id == NPC_RAINOFMETEOR || + group->skill_id == HN_METEOR_STORM_BUSTER || ((group->skill_id == CR_GRANDCROSS || group->skill_id == NPC_GRANDDARKNESS) && unit->val1 <= 0)) { skill_delunit(unit); return 0; diff --git a/src/map/skill.hpp b/src/map/skill.hpp index 077fe8c959..c1ac243df3 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -39,6 +39,9 @@ class status_change; /// Used with tracking the hitcount of Earthquake for skills that can avoid the first attack #define NPC_EARTHQUAKE_FLAG 0x800 +/// To control alternative skill scalings +#define SKILL_ALTDMG_FLAG 0x10 + /// 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. diff --git a/src/map/status.cpp b/src/map/status.cpp index fd5f3445e7..f3dafd248f 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -4379,6 +4379,10 @@ int status_calc_pc_sub(map_session_data* sd, uint8 opt) base_status->patk += skill * 3; base_status->smatk += skill * 3; } + if ((skill = pc_checkskill(sd, HN_SELFSTUDY_TATICS)) > 0) + base_status->patk += skill; + if ((skill = pc_checkskill(sd, HN_SELFSTUDY_SOCERY)) > 0) + base_status->smatk += skill; // 2-Handed Staff Mastery if( sd->status.weapon == W_2HSTAFF && ( skill = pc_checkskill( sd, AG_TWOHANDSTAFF ) ) > 0 ){ @@ -8012,6 +8016,10 @@ static unsigned short status_calc_speed(struct block_list *bl, status_change *sc val = max(val, sc->getSCE(SC_SP_SHA)->val2); if (sc->getSCE(SC_CREATINGSTAR)) val = max(val, 90); + if (sc->getSCE(SC_SHIELDCHAINRUSH)) + val = max(val, 20); + if (sc->getSCE(SC_GROUNDGRAVITY)) + val = max(val, 20); if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // Permanent item-based speedup val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate ); diff --git a/src/map/status.hpp b/src/map/status.hpp index 386b4bf381..fb1a3a95aa 100644 --- a/src/map/status.hpp +++ b/src/map/status.hpp @@ -1284,6 +1284,15 @@ enum sc_type : int16 { SC_RUSH_QUAKE2, SC_G_LIFEPOTION, + + // Hyper Novice + SC_HNNOWEAPON, + SC_SHIELDCHAINRUSH, + SC_MISTYFROST, + SC_GROUNDGRAVITY, + SC_BREAKINGLIMIT, + SC_RULEBREAK, + #ifdef RENEWAL SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled #endif