From 36195d157d6eef99056926190468bf2e25f4dbed Mon Sep 17 00:00:00 2001 From: Aleos Date: Sat, 8 Aug 2020 12:23:29 -0400 Subject: [PATCH] Job Improvement Project - Warlock (#4897) * Fixes #4706. * kRO Changelog: http://ro.gnjoy.com/news/update/View.asp?seq=239&curpage=1 Thanks to @LordWhiplash, @Badarosk0, Sigma, @Balferian, @tumemmac, @teededung, @attackjom, @Felleonel and @mrjnumber1! Co-authored-by: Lemongrass3110 --- db/re/item_db.txt | 54 ++-- db/re/item_flag.txt | 10 + db/re/skill_db.yml | 221 ++++++-------- db/re/skill_tree.txt | 24 +- db/re/spellbook_db.yml | 45 +-- sql-files/upgrades/upgrade_20200505.sql | 11 + src/map/battle.cpp | 68 ++--- src/map/clif.cpp | 39 --- src/map/clif.hpp | 2 - src/map/itemdb.hpp | 1 + src/map/skill.cpp | 380 +++++++++++------------- src/map/skill.hpp | 3 +- src/map/status.cpp | 19 +- src/map/status.hpp | 8 +- 14 files changed, 397 insertions(+), 488 deletions(-) create mode 100644 sql-files/upgrades/upgrade_20200505.sql diff --git a/db/re/item_db.txt b/db/re/item_db.txt index 26d7b7b633..a61bab81a1 100644 --- a/db/re/item_db.txt +++ b/db/re/item_db.txt @@ -4289,23 +4289,23 @@ 6186,Monkey_Wrench,Monkey Wrench,3,500,,10,,,,,,,,,,,,,{},{},{} 6187,Blank_Card,Blank Card,3,20,,10,,,,,,,,,,,,,{},{},{} 6188,Slot_Coupon,Slotting Advertisement,3,20,,10,,,,,,,,,,,,,{},{},{} -6189,Magic_Book_FB,Spell Book (Fire Bolt),3,0,,0,,,,,,,,,,,,,{},{},{} -6190,Magic_Book_CB,Spell Book (Cold Bolt),3,0,,0,,,,,,,,,,,,,{},{},{} -6191,Magic_Book_LB,Spell Book (Lightening Bolt),3,0,,0,,,,,,,,,,,,,{},{},{} -6192,Magic_Book_SG,Spell Book (Storm Gust),3,0,,0,,,,,,,,,,,,,{},{},{} -6193,Magic_Book_LOV,Spell Book (Lord Of Vermilion),3,0,,0,,,,,,,,,,,,,{},{},{} -6194,Magic_Book_MS,Spell Book (Meteor Storm),3,0,,0,,,,,,,,,,,,,{},{},{} -6195,Magic_Book_CM,Spell Book (Comet),3,0,,0,,,,,,,,,,,,,{},{},{} -6196,Magic_Book_TV,Spell Book (Tetra Vortex),3,0,,0,,,,,,,,,,,,,{},{},{} -6197,Magic_Book_TS,Spell Book (Thunder Storm),3,0,,0,,,,,,,,,,,,,{},{},{} -6198,Magic_Book_JT,Spell Book (Jupitel Thunder),3,0,,0,,,,,,,,,,,,,{},{},{} -6199,Magic_Book_WB,Spell Book (Water Ball),3,0,,0,,,,,,,,,,,,,{},{},{} -6200,Magic_Book_HD,Spell Book (Heaven's Drive),3,0,,0,,,,,,,,,,,,,{},{},{} -6201,Magic_Book_ES,Spell Book (Earth Spike),3,0,,0,,,,,,,,,,,,,{},{},{} -6202,Magic_Book_ES_,Spell Book (Earth Strain),3,0,,0,,,,,,,,,,,,,{},{},{} -6203,Magic_Book_CL,Spell Book (Chain Lightning),3,0,,0,,,,,,,,,,,,,{},{},{} -6204,Magic_Book_CR,Spell Book (Crimson Rock),3,0,,0,,,,,,,,,,,,,{},{},{} -6205,Magic_Book_DL,Spell Book (Drain Life),3,0,,0,,,,,,,,,,,,,{},{},{} +6189,Magic_Book_FB,Old Spell Book (Fire Bolt),3,0,,0,,,,,,,,,,,,,{},{},{} +6190,Magic_Book_CB,Old Spell Book (Cold Bolt),3,0,,0,,,,,,,,,,,,,{},{},{} +6191,Magic_Book_LB,Old Spell Book (Lightening Bolt),3,0,,0,,,,,,,,,,,,,{},{},{} +6192,Magic_Book_SG,Old Spell Book (Storm Gust),3,0,,0,,,,,,,,,,,,,{},{},{} +6193,Magic_Book_LOV,Old Spell Book (Lord Of Vermilion),3,0,,0,,,,,,,,,,,,,{},{},{} +6194,Magic_Book_MS,Old Spell Book (Meteor Storm),3,0,,0,,,,,,,,,,,,,{},{},{} +6195,Magic_Book_CM,Old Spell Book (Comet),3,0,,0,,,,,,,,,,,,,{},{},{} +6196,Magic_Book_TV,Old Spell Book (Tetra Vortex),3,0,,0,,,,,,,,,,,,,{},{},{} +6197,Magic_Book_TS,Old Spell Book (Thunder Storm),3,0,,0,,,,,,,,,,,,,{},{},{} +6198,Magic_Book_JT,Old Spell Book (Jupitel Thunder),3,0,,0,,,,,,,,,,,,,{},{},{} +6199,Magic_Book_WB,Old Spell Book (Water Ball),3,0,,0,,,,,,,,,,,,,{},{},{} +6200,Magic_Book_HD,Old Spell Book (Heaven's Drive),3,0,,0,,,,,,,,,,,,,{},{},{} +6201,Magic_Book_ES,Old Spell Book (Earth Spike),3,0,,0,,,,,,,,,,,,,{},{},{} +6202,Magic_Book_ES_,Old Spell Book (Earth Strain),3,0,,0,,,,,,,,,,,,,{},{},{} +6203,Magic_Book_CL,Old Spell Book (Chain Lightning),3,0,,0,,,,,,,,,,,,,{},{},{} +6204,Magic_Book_CR,Old Spell Book (Crimson Rock),3,0,,0,,,,,,,,,,,,,{},{},{} +6205,Magic_Book_DL,Old Spell Book (Drain Life),3,0,,0,,,,,,,,,,,,,{},{},{} 6206,I_Love_You,I Love You,3,0,,0,,,,,,,,,,,,,{},{},{} 6207,Thank_You,Thank You,3,0,,0,,,,,,,,,,,,,{},{},{} 6208,I_Respect_You,I Respect You,3,0,,0,,,,,,,,,,,,,{},{},{} @@ -13668,15 +13668,33 @@ 32351,Estal,Estal,5,20,,700,195,,1,2,0x00040000,56,2,2,4,170,1,2,{ .@r = getrefine(); bonus2 bSkillCooldown,"GN_SPORE_EXPLOSION",-1000; bonus bBaseAtk,4*.@r; if (.@r>=11) .@val = 50; else if (.@r>=9) .@val = 30; bonus2 bSkillAtk,"GN_SPORE_EXPLOSION",.@val; },{},{} //100052,Enchant_Stone_Box19,Costume Enchantment Stone Box 19,2,10,,10,,,,0,0xFFFFFFFF,63,2,,,1,,,{ getgroupitem(IG_Enchant_Stone_Box19); },{},{} + +//=================================================================== +// New Warlock Spell Books +//=================================================================== +100065,WL_MB_SG,Spell Book (Storm Gust),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",1; },{},{} +100066,WL_MB_LOV,Spell Book (Lord of Vermilion),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",2; },{},{} +100067,WL_MB_MS,Spell Book (Meteor Storm),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",3; },{},{} +100068,WL_MB_DL,Spell Book (Drain Life),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",4; },{},{} +100069,WL_MB_JF,Spell Book (Jack Frost),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",5; },{},{} +100070,WL_MB_ES,Spell Book (Earth Strain),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",6; },{},{} +100071,WL_MB_CR,Spell Book (Crimson Rock),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",7; },{},{} +100072,WL_MB_CL,Spell Book (Chain Lightning),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",8; },{},{} +100073,WL_MB_CM,Spell Book (Comet),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",9; },{},{} +100074,WL_MB_TV,Spell Book (Tetra Vortex),11,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_READING_SB_READING",10; },{},{} + //100202,Enchant_Stone_Box20,Costume Enchantment Stone Box 20,2,10,,10,,,,0,0xFFFFFFFF,63,2,,,1,,,{ getgroupitem(IG_Enchant_Stone_Box20); },{},{} + //100231,Ref_T_Potion,Golden X,0,10,,30,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_REF_T_POTION,30000,0; },{},{} //100232,Add_Atk_Potion,Red Herb Activator,0,10,,30,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_ADD_ATK_DAMAGE,500000,15; },{},{} //100233,Add_Matk_Potion,Blue Herb Activator,0,10,,30,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_ADD_MATK_DAMAGE,500000,15; },{},{} + //100314,Enchant_Stone_Box21,Costume Enchantment Stone Box 21,2,10,,10,,,,0,0xFFFFFFFF,63,2,,,1,,,{ getgroupitem(IG_Enchant_Stone_Box21); },{},{} // Costumes +//400020,C_BeachBall,Costume Beachball,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,0,1918,{},{},{} //440000,C_SharkHead,Costume Shark Hat,4,0,,0,,,,0,0xFFFFFFFF,63,2,5120,,1,0,1919,{},{},{} //440002,C_Happy_Cat_TW,Costume Happy Cat,4,0,,0,,,,0,0xFFFFFFFF,63,2,7168,,1,0,1980,{},{},{} -//400020,C_BeachBall,Costume Beachball,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,0,1918,{},{},{} + //1100003,Concentrated_R_P,Concentrated Red Potion,0,10,,2,,,,,0xFFFFFFFF,63,2,,,120,,,{ itemheal rand(655,675),0; },{},{} //1100004,Concentrated_B_P,Concentrated Blue Potion,0,10,,2,,,,,0xFFFFFFFF,63,2,,,120,,,{ itemheal 0,rand(340,360); },{},{} //1100005,Concentrated_G_P,Concentrated Gold Potion,0,10,,2,,,,,0xFFFFFFFF,63,2,,,180,,,{ itemheal rand(2730,2750),0; },{},{} diff --git a/db/re/item_flag.txt b/db/re/item_flag.txt index 2f46a1517c..a90bf07c9f 100644 --- a/db/re/item_flag.txt +++ b/db/re/item_flag.txt @@ -1785,3 +1785,13 @@ 12622,32 //Boarding_Halter 12887,32 //C_Wing_Of_Fly 22508,32 //Para_Team_Mark_ +//100065,32 //WL_MB_SG +//100066,32 //WL_MB_LOV +//100067,32 //WL_MB_MS +//100068,32 //WL_MB_DL +//100069,32 //WL_MB_JF +//100070,32 //WL_MB_ES +//100071,32 //WL_MB_CR +//100072,32 //WL_MB_CL +//100073,32 //WL_MB_CM +//100074,32 //WL_MB_TV diff --git a/db/re/skill_db.yml b/db/re/skill_db.yml index 4a97bf3989..6b70357373 100644 --- a/db/re/skill_db.yml +++ b/db/re/skill_db.yml @@ -9959,25 +9959,25 @@ Body: Requires: SpCost: - Level: 1 - Amount: 14 + Amount: 35 - Level: 2 - Amount: 18 + Amount: 40 - Level: 3 - Amount: 22 + Amount: 45 - Level: 4 - Amount: 26 - - Level: 5 - Amount: 30 - - Level: 6 - Amount: 34 - - Level: 7 - Amount: 38 - - Level: 8 - Amount: 42 - - Level: 9 - Amount: 46 - - Level: 10 Amount: 50 + - Level: 5 + Amount: 55 + - Level: 6 + Amount: 60 + - Level: 7 + Amount: 65 + - Level: 8 + Amount: 70 + - Level: 9 + Amount: 75 + - Level: 10 + Amount: 80 - Id: 367 Name: PA_PRESSURE Description: Gloria Domini @@ -18089,25 +18089,36 @@ Body: Description: Frosty Misty MaxLevel: 5 Type: Magic - TargetType: Self + TargetType: Ground DamageFlags: Splash: true Flags: AlterRangeRadius: true + Range: 11 Hit: Multi_Hit HitCount: - Level: 1 - Count: -3 + Count: 1 - Level: 2 - Count: -4 + Count: 2 - Level: 3 - Count: -5 + Count: 3 - Level: 4 - Count: -6 + Count: 4 - Level: 5 - Count: -7 + Count: 5 Element: Water - SplashArea: 9 + SplashArea: + - Level: 1 + Area: 3 + - Level: 2 + Area: 3 + - Level: 3 + Area: 4 + - Level: 4 + Area: 4 + - Level: 5 + Area: 5 CopyFlags: Skill: Reproduce: true @@ -18125,6 +18136,7 @@ Body: Time: 4000 AfterCastActDelay: 1000 Duration1: 40000 + Duration2: 10000 Cooldown: 4000 FixedCastTime: 500 Requires: @@ -18144,23 +18156,24 @@ Body: Description: Jack Frost MaxLevel: 5 Type: Magic - TargetType: Self + TargetType: Attack DamageFlags: Splash: true + Range: 11 Hit: Multi_Hit HitCount: -5 Element: Water SplashArea: - Level: 1 - Area: 5 + Area: 3 - Level: 2 - Area: 6 + Area: 3 - Level: 3 - Area: 7 + Area: 4 - Level: 4 - Area: 8 + Area: 4 - Level: 5 - Area: 9 + Area: 5 CopyFlags: Skill: Reproduce: true @@ -18188,6 +18201,7 @@ Body: Time: 27500 - Level: 5 Time: 32500 + Cooldown: 4000 FixedCastTime: 1000 Requires: SpCost: @@ -18450,7 +18464,7 @@ Body: Reproduce: true CastCancel: true CastTime: 5000 - AfterCastActDelay: 2000 + AfterCastActDelay: 500 Duration1: 5000 Cooldown: 5000 FixedCastTime: 1000 @@ -18472,32 +18486,46 @@ Body: MaxLevel: 5 Type: Magic TargetType: Attack + DamageFlags: + Splash: true Flags: AlterRangeRadius: true Range: 11 Hit: Single HitCount: 1 Element: Fire + SplashArea: + - Level: 1 + Area: 1 + - Level: 2 + Area: 1 + - Level: 3 + Area: 1 + - Level: 4 + Area: 2 + - Level: 5 + Area: 2 CopyFlags: Skill: Reproduce: true CastCancel: true CastTime: 3000 - AfterCastActDelay: 1000 + AfterCastActDelay: 500 Duration1: 15000 + Cooldown: 3000 FixedCastTime: 1000 Requires: SpCost: - Level: 1 - Amount: 35 + Amount: 64 - Level: 2 - Amount: 40 + Amount: 70 - Level: 3 - Amount: 45 + Amount: 76 - Level: 4 - Amount: 50 + Amount: 82 - Level: 5 - Amount: 55 + Amount: 88 - Id: 2213 Name: WL_COMET Description: Comet @@ -18510,8 +18538,8 @@ Body: AlterRangeRadius: true Range: 11 Hit: Multi_Hit - HitCount: -20 - SplashArea: 9 + HitCount: -10 + SplashArea: 6 Knockback: 2 CopyFlags: Skill: @@ -18519,45 +18547,32 @@ Body: CastCancel: true CastTime: - Level: 1 - Time: 10000 + Time: 6000 - Level: 2 - Time: 11000 + Time: 7000 - Level: 3 - Time: 12000 + Time: 8000 - Level: 4 - Time: 13000 + Time: 9000 - Level: 5 - Time: 14000 - AfterCastActDelay: 2000 + Time: 10000 + AfterCastActDelay: 1500 Duration1: 100 Duration2: 42000 - Cooldown: 60000 - FixedCastTime: - - Level: 1 - Time: 1000 - - Level: 2 - Time: 1500 - - Level: 3 - Time: 2000 - - Level: 4 - Time: 2500 - - Level: 5 - Time: 3000 + Cooldown: 20000 + FixedCastTime: 2000 Requires: SpCost: - Level: 1 - Amount: 480 + Amount: 70 - Level: 2 - Amount: 560 + Amount: 90 - Level: 3 - Amount: 640 + Amount: 110 - Level: 4 - Amount: 720 + Amount: 130 - Level: 5 - Amount: 800 - ItemCost: - - Item: Red_Gemstone - Amount: 2 + Amount: 150 Unit: Id: Dummyskill Range: 9 @@ -18661,7 +18676,7 @@ Body: Time: 5000 - Level: 5 Time: 6000 - AfterCastActDelay: 1000 + AfterCastActDelay: 500 Duration1: 100 Duration2: - Level: 1 @@ -18674,7 +18689,7 @@ Body: Time: 120000 - Level: 5 Time: 135000 - Cooldown: 10000 + Cooldown: 7000 FixedCastTime: 2000 Requires: SpCost: @@ -18842,7 +18857,7 @@ Body: - Id: 2222 Name: WL_SUMMONFB Description: Summon Fire Ball - MaxLevel: 5 + MaxLevel: 2 Type: Magic TargetType: Self DamageFlags: @@ -18855,17 +18870,7 @@ Body: Reproduce: true CastCancel: true CastTime: 2000 - Duration1: - - Level: 1 - Time: 120000 - - Level: 2 - Time: 160000 - - Level: 3 - Time: 200000 - - Level: 4 - Time: 240000 - - Level: 5 - Time: 280000 + Duration1: 280000 FixedCastTime: -1 Requires: SpCost: @@ -18882,7 +18887,7 @@ Body: - Id: 2223 Name: WL_SUMMONBL Description: Summon Lightning Ball - MaxLevel: 5 + MaxLevel: 2 Type: Magic TargetType: Self DamageFlags: @@ -18895,17 +18900,7 @@ Body: Reproduce: true CastCancel: true CastTime: 2000 - Duration1: - - Level: 1 - Time: 120000 - - Level: 2 - Time: 160000 - - Level: 3 - Time: 200000 - - Level: 4 - Time: 240000 - - Level: 5 - Time: 280000 + Duration1: 280000 FixedCastTime: -1 Requires: SpCost: @@ -18922,7 +18917,7 @@ Body: - Id: 2224 Name: WL_SUMMONWB Description: Summon Water Ball - MaxLevel: 5 + MaxLevel: 2 Type: Magic TargetType: Self DamageFlags: @@ -18935,17 +18930,7 @@ Body: Reproduce: true CastCancel: true CastTime: 2000 - Duration1: - - Level: 1 - Time: 120000 - - Level: 2 - Time: 160000 - - Level: 3 - Time: 200000 - - Level: 4 - Time: 240000 - - Level: 5 - Time: 280000 + Duration1: 280000 FixedCastTime: -1 Requires: SpCost: @@ -19026,7 +19011,7 @@ Body: - Id: 2229 Name: WL_SUMMONSTONE Description: Summon Stone - MaxLevel: 5 + MaxLevel: 2 Type: Magic TargetType: Self DamageFlags: @@ -19039,17 +19024,7 @@ Body: Reproduce: true CastCancel: true CastTime: 2000 - Duration1: - - Level: 1 - Time: 120000 - - Level: 2 - Time: 160000 - - Level: 3 - Time: 200000 - - Level: 4 - Time: 240000 - - Level: 5 - Time: 280000 + Duration1: 280000 FixedCastTime: -1 Requires: SpCost: @@ -19085,19 +19060,7 @@ Body: Name: WL_READING_SB Description: Reading Spellbook MaxLevel: 1 - Type: Magic - TargetType: Self - DamageFlags: - NoDamage: true - Hit: Single - HitCount: 1 - CastCancel: true - CastTime: 5000 - AfterCastActDelay: 500 Duration1: 30000 - FixedCastTime: 1000 - Requires: - SpCost: 40 - Id: 2232 Name: WL_FREEZE_SP Description: Freeze Spell @@ -33511,6 +33474,14 @@ Body: Name: NV_TRANSCENDENCE Description: Transcendence MaxLevel: 5 + - Id: 5078 + Name: WL_READING_SB_READING + Description: Reading Spellbook + MaxLevel: 10 + TargetType: Self + CastTime: 5000 + AfterCastActDelay: 500 + FixedCastTime: 1000 - Id: 8001 Name: HLIF_HEAL Description: Healing Touch diff --git a/db/re/skill_tree.txt b/db/re/skill_tree.txt index 0b1c054d44..d9fc3ac0f4 100644 --- a/db/re/skill_tree.txt +++ b/db/re/skill_tree.txt @@ -2492,10 +2492,10 @@ 4055,2214,5,2223,1,0,0,0,0,0,0,0,0 //WL_CHAINLIGHTNING#Chain Lightning# 4055,2216,5,2207,2,0,0,0,0,0,0,0,0 //WL_EARTHSTRAIN#Earth Strain# 4055,2217,10,2204,5,2212,5,2214,5,2216,5,0,0 //WL_TETRAVORTEX#Tetra Vortex# -4055,2222,5,83,1,0,0,0,0,0,0,0,0 //WL_SUMMONFB#Summon Fire Ball# -4055,2223,5,85,1,0,0,0,0,0,0,0,0 //WL_SUMMONBL#Summon Lightning Ball# -4055,2224,5,89,1,0,0,0,0,0,0,0,0 //WL_SUMMONWB#Summon Water Ball# -4055,2229,5,91,1,0,0,0,0,0,0,0,0 //WL_SUMMONSTONE#Summon Stone# +4055,2222,2,83,1,0,0,0,0,0,0,0,0 //WL_SUMMONFB#Summon Fire Ball# +4055,2223,2,85,1,0,0,0,0,0,0,0,0 //WL_SUMMONBL#Summon Lightning Ball# +4055,2224,2,89,1,0,0,0,0,0,0,0,0 //WL_SUMMONWB#Summon Water Ball# +4055,2229,2,91,1,0,0,0,0,0,0,0,0 //WL_SUMMONSTONE#Summon Stone# 4055,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4055,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4055,2232,10,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# @@ -2833,10 +2833,10 @@ 4061,2214,5,2223,1,0,0,0,0,0,0,0,0 //WL_CHAINLIGHTNING#Chain Lightning# 4061,2216,5,2207,2,0,0,0,0,0,0,0,0 //WL_EARTHSTRAIN#Earth Strain# 4061,2217,10,2204,5,2212,5,2214,5,2216,5,0,0 //WL_TETRAVORTEX#Tetra Vortex# -4061,2222,5,83,1,0,0,0,0,0,0,0,0 //WL_SUMMONFB#Summon Fire Ball# -4061,2223,5,85,1,0,0,0,0,0,0,0,0 //WL_SUMMONBL#Summon Lightning Ball# -4061,2224,5,89,1,0,0,0,0,0,0,0,0 //WL_SUMMONWB#Summon Water Ball# -4061,2229,5,91,1,0,0,0,0,0,0,0,0 //WL_SUMMONSTONE#Summon Stone# +4061,2222,2,83,1,0,0,0,0,0,0,0,0 //WL_SUMMONFB#Summon Fire Ball# +4061,2223,2,85,1,0,0,0,0,0,0,0,0 //WL_SUMMONBL#Summon Lightning Ball# +4061,2224,2,89,1,0,0,0,0,0,0,0,0 //WL_SUMMONWB#Summon Water Ball# +4061,2229,2,91,1,0,0,0,0,0,0,0,0 //WL_SUMMONSTONE#Summon Stone# 4061,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4061,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4061,2232,10,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# @@ -4500,10 +4500,10 @@ 4097,2214,5,2223,1,0,0,0,0,0,0,0,0 //WL_CHAINLIGHTNING#Chain Lightning# 4097,2216,5,2207,2,0,0,0,0,0,0,0,0 //WL_EARTHSTRAIN#Earth Strain# 4097,2217,10,2204,5,2212,5,2214,5,2216,5,0,0 //WL_TETRAVORTEX#Tetra Vortex# -4097,2222,5,83,1,0,0,0,0,0,0,0,0 //WL_SUMMONFB#Summon Fire Ball# -4097,2223,5,85,1,0,0,0,0,0,0,0,0 //WL_SUMMONBL#Summon Lightning Ball# -4097,2224,5,89,1,0,0,0,0,0,0,0,0 //WL_SUMMONWB#Summon Water Ball# -4097,2229,5,91,1,0,0,0,0,0,0,0,0 //WL_SUMMONSTONE#Summon Stone# +4097,2222,2,83,1,0,0,0,0,0,0,0,0 //WL_SUMMONFB#Summon Fire Ball# +4097,2223,2,85,1,0,0,0,0,0,0,0,0 //WL_SUMMONBL#Summon Lightning Ball# +4097,2224,2,89,1,0,0,0,0,0,0,0,0 //WL_SUMMONWB#Summon Water Ball# +4097,2229,2,91,1,0,0,0,0,0,0,0,0 //WL_SUMMONSTONE#Summon Stone# 4097,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4097,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4097,2232,10,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# diff --git a/db/re/spellbook_db.yml b/db/re/spellbook_db.yml index a366226a26..3c3456eea2 100644 --- a/db/re/spellbook_db.yml +++ b/db/re/spellbook_db.yml @@ -32,54 +32,33 @@ Header: Version: 1 Body: - - Skill: MG_COLDBOLT - Book: Magic_Book_CB - PreservePoints: 7 - - Skill: MG_FIREBOLT - Book: Magic_Book_FB - PreservePoints: 7 - - Skill: MG_LIGHTNINGBOLT - Book: Magic_Book_LB - PreservePoints: 7 - - Skill: MG_THUNDERSTORM - Book: Magic_Book_TS - PreservePoints: 9 - Skill: WZ_METEOR - Book: Magic_Book_MS + Book: WL_MB_MS PreservePoints: 10 - - Skill: WZ_JUPITEL - Book: Magic_Book_JT - PreservePoints: 9 - Skill: WZ_VERMILION - Book: Magic_Book_LOV + Book: WL_MB_LOV PreservePoints: 10 - - Skill: WZ_WATERBALL - Book: Magic_Book_WB - PreservePoints: 9 - Skill: WZ_STORMGUST - Book: Magic_Book_SG + Book: WL_MB_SG + PreservePoints: 10 + - Skill: WL_JACKFROST + Book: WL_MB_JF PreservePoints: 10 - - Skill: WZ_EARTHSPIKE - Book: Magic_Book_ES - PreservePoints: 8 - - Skill: WZ_HEAVENDRIVE - Book: Magic_Book_HD - PreservePoints: 9 - Skill: WL_DRAINLIFE - Book: Magic_Book_DL + Book: WL_MB_DL PreservePoints: 8 - Skill: WL_CRIMSONROCK - Book: Magic_Book_CR + Book: WL_MB_CR PreservePoints: 12 - Skill: WL_COMET - Book: Magic_Book_CM + Book: WL_MB_CM PreservePoints: 22 - Skill: WL_CHAINLIGHTNING - Book: Magic_Book_CL + Book: WL_MB_CL PreservePoints: 12 - Skill: WL_EARTHSTRAIN - Book: Magic_Book_ES_ + Book: WL_MB_ES PreservePoints: 12 - Skill: WL_TETRAVORTEX - Book: Magic_Book_TV + Book: WL_MB_TV PreservePoints: 22 diff --git a/sql-files/upgrades/upgrade_20200505.sql b/sql-files/upgrades/upgrade_20200505.sql new file mode 100644 index 0000000000..a3875f1d30 --- /dev/null +++ b/sql-files/upgrades/upgrade_20200505.sql @@ -0,0 +1,11 @@ +-- WL_SUMMONFB +UPDATE `char` c, `skill` s SET `c`.skill_point = `c`.skill_point + (`s`.lv - 2), `s`.lv = 2 WHERE `s`.id = 2222 AND `s`.lv > 2 AND `c`.char_id = `s`.char_id; + +-- WL_SUMMONBL +UPDATE `char` c, `skill` s SET `c`.skill_point = `c`.skill_point + (`s`.lv - 2), `s`.lv = 2 WHERE `s`.id = 2223 AND `s`.lv > 2 AND `c`.char_id = `s`.char_id; + +-- WL_SUMMONWB +UPDATE `char` c, `skill` s SET `c`.skill_point = `c`.skill_point + (`s`.lv - 2), `s`.lv = 2 WHERE `s`.id = 2224 AND `s`.lv > 2 AND `c`.char_id = `s`.char_id; + +-- WL_SUMMONSTONE +UPDATE `char` c, `skill` s SET `c`.skill_point = `c`.skill_point + (`s`.lv - 2), `s`.lv = 2 WHERE `s`.id = 2229 AND `s`.lv > 2 AND `c`.char_id = `s`.char_id; diff --git a/src/map/battle.cpp b/src/map/battle.cpp index d2abd9564a..79250d6cb3 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -601,6 +601,13 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d } break; } + + if (tsc->data[SC_MAGIC_POISON]) +#ifdef RENEWAL + ratio += 50; +#else + damage += (int64)(damage * 50 / 100); +#endif } if (battle_config.attr_recover == 0 && ratio < 0) @@ -6112,8 +6119,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list s_ele = ELE_HOLY; break; case WL_HELLINFERNO: - if (mflag&ELE_DARK) + if (mflag == ELE_DARK) { s_ele = ELE_DARK; + ad.div_ = 3; + } break; case WM_REVERBERATION: if (sd) @@ -6448,14 +6457,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list skillratio += 300 + 40 * skill_lv; break; case WL_SOULEXPANSION: - skillratio += -100 + (skill_lv + 4) * 100 + status_get_int(src); + skillratio += -100 + 750 + skill_lv * 150 + sstatus->int_; RE_LVL_DMOD(100); break; case WL_FROSTMISTY: - skillratio += 100 + 100 * skill_lv; + skillratio += -100 + 200 + 100 * skill_lv; RE_LVL_DMOD(100); break; - case WL_JACKFROST: case NPC_JACKFROST: if (tsc && tsc->data[SC_FREEZING]) { skillratio += 900 + 300 * skill_lv; @@ -6465,50 +6473,30 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list RE_LVL_DMOD(150); } break; + case WL_JACKFROST: + if (tsc && tsc->data[SC_MISTY_FROST]) + skillratio += -100 + 1200 + 600 * skill_lv; + else + skillratio += -100 + 1000 + 300 * skill_lv; + RE_LVL_DMOD(100); + break; case WL_DRAINLIFE: - skillratio += -100 + 200 * skill_lv + status_get_int(src); + skillratio += -100 + 200 * skill_lv + sstatus->int_; RE_LVL_DMOD(100); break; case WL_CRIMSONROCK: - skillratio += 1200 + 300 * skill_lv; + skillratio += -100 + 700 + 600 * skill_lv; RE_LVL_DMOD(100); break; case WL_HELLINFERNO: - skillratio += -100 + 300 * skill_lv; + skillratio += -100 + 400 * skill_lv; + if (mflag == ELE_DARK) + skillratio += 200; RE_LVL_DMOD(100); - // Shadow: MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) x 4/5 }] % - // Fire : MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) /5 }] % - if (mflag&ELE_DARK) - skillratio *= 4; - skillratio /= 5; break; case WL_COMET: - i = (sc ? distance_xy(target->x, target->y, sc->comet_x, sc->comet_y) : 8); - if (i <= 3) - skillratio += 2400 + 500 * skill_lv; // 7 x 7 cell - else if (i <= 5) - skillratio += 1900 + 500 * skill_lv; // 11 x 11 cell - else if (i <= 7) - skillratio += 1400 + 500 * skill_lv; // 15 x 15 cell - else - skillratio += 900 + 500 * skill_lv; // 19 x 19 cell - - if (sd && sd->status.party_id) { - struct map_session_data* psd; - int p_sd[MAX_PARTY], c; - - c = 0; - memset(p_sd, 0, sizeof(p_sd)); - party_foreachsamemap(skill_check_condition_char_sub, sd, 3, &sd->bl, &c, &p_sd, skill_id); - c = (c > 1 ? rnd()%c : 0); - - if( (psd = map_id2sd(p_sd[c])) && pc_checkskill(psd,WL_COMET) > 0 ){ - skillratio = skill_lv * 400; //MATK [{( Skill Level x 400 ) x ( Caster's Base Level / 120 )} + 2500 ] % - RE_LVL_DMOD(120); - skillratio += 2500; - status_zap(&psd->bl, 0, skill_get_sp(skill_id, skill_lv) / 2); - } - } + skillratio += -100 + 2500 + 500 * skill_lv; + RE_LVL_DMOD(100); break; case WL_CHAINLIGHTNING_ATK: skillratio += 400 + 100 * skill_lv; @@ -6517,7 +6505,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list skillratio += 100 * mflag; break; case WL_EARTHSTRAIN: - skillratio += 1900 + 100 * skill_lv; + skillratio += -100 + 1000 + 600 * skill_lv; RE_LVL_DMOD(100); break; case WL_TETRAVORTEX_FIRE: @@ -6534,7 +6522,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case WL_SUMMON_ATK_WIND: case WL_SUMMON_ATK_GROUND: skillratio += -100 + (1 + skill_lv) / 2 * (status_get_lv(src) + (sd ? sd->status.job_level : 0)); - RE_LVL_DMOD(100); + RE_LVL_DMOD(100); // ! TODO: Confirm new formula break; case LG_RAYOFGENESIS: skillratio += -100 + 200 * skill_lv; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 3cca47c160..f4f460a7da 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -13056,9 +13056,6 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd) { case SA_CREATECON: skill_produce_mix(sd,SA_CREATECON,p->itemId,0,0,0,1,-1); break; - case WL_READING_SB: - skill_spellbook(sd,p->itemId); - break; case GC_POISONINGWEAPON: skill_poisoningweapon(sd,p->itemId); break; @@ -18957,43 +18954,7 @@ void clif_millenniumshield(struct block_list *bl, short shields) { clif_send(buf,packet_len(0x440),bl,AREA); #endif } -/** - * Warlock - **/ -/*========================================== - * Spellbook list [LimitLine/3CeAM] - *------------------------------------------*/ -void clif_spellbook_list( struct map_session_data *sd ){ - nullpo_retv( sd ); - int fd = sd->fd; - - if( !session_isActive( fd ) ){ - return; - } - - WFIFOHEAD( fd, sizeof( struct PACKET_ZC_MAKINGARROW_LIST ) + MAX_INVENTORY * sizeof( struct PACKET_ZC_MAKINGARROW_LIST_sub ) ); - struct PACKET_ZC_MAKINGARROW_LIST *p = (struct PACKET_ZC_MAKINGARROW_LIST *)WFIFOP( fd, 0 ); - p->packetType = HEADER_ZC_MAKINGARROW_LIST; - - int count = 0; - for( int i = 0; i < MAX_INVENTORY; i++ ){ - if( reading_spellbook_db.findBook( sd->inventory.u.items_inventory[i].nameid ) ){ - p->items[count].itemId = client_nameid( sd->inventory.u.items_inventory[i].nameid ); - count++; - } - } - - if( count > 0 ){ - p->packetLength = sizeof( struct PACKET_ZC_MAKINGARROW_LIST ) + count * sizeof( struct PACKET_ZC_MAKINGARROW_LIST_sub ); - WFIFOSET( fd, p->packetLength ); - sd->menuskill_id = WL_READING_SB; - sd->menuskill_val = count; - }else{ - status_change_end( &sd->bl, SC_STOP, INVALID_TIMER ); - clif_skill_fail( sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK, 0 ); - } -} /** * Mechanic **/ diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 39a12db261..a925e1c24e 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -1050,8 +1050,6 @@ void clif_elementalconverter_list(struct map_session_data *sd); void clif_millenniumshield(struct block_list *bl, short shields); -void clif_spellbook_list(struct map_session_data *sd); - void clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x, short y); void clif_poison_list(struct map_session_data *sd, uint16 skill_lv); diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp index 00cb4748ee..02dc489ed4 100644 --- a/src/map/itemdb.hpp +++ b/src/map/itemdb.hpp @@ -113,6 +113,7 @@ enum item_itemid : t_itemid ITEMID_WOB_RACHEL = 14584, ITEMID_WOB_LOCAL = 14585, ITEMID_SIEGE_TELEPORT_SCROLL = 14591, + ITEMID_WL_MB_SG = 100065, }; ///Rune Knight diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 8b026a33ef..c3ebf3b1bf 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -1704,20 +1704,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case AB_ADORAMUS: sc_start(src,bl, SC_ADORAMUS, skill_lv * 4 + (sd ? sd->status.job_level : 50) / 2, skill_lv, skill_get_time2(skill_id, skill_lv)); break; - case WL_CRIMSONROCK: - sc_start(src,bl, SC_STUN, 40, skill_lv, skill_get_time(skill_id, skill_lv)); - break; case WL_COMET: + sc_start(src, bl, status_skill2sc(skill_id), 100, skill_lv, 20000); + break; case NPC_COMET: sc_start4(src,bl,SC_BURNING,100,skill_lv,1000,src->id,0,skill_get_time(skill_id,skill_lv)); break; - case WL_EARTHSTRAIN: - if (dmg_lv != ATK_DEF) // Only strip if we make a successful hit. - break; - - skill_strip_equip(src, bl, skill_id, skill_lv); - break; - case WL_JACKFROST: case NPC_JACKFROST: sc_start(src,bl,SC_FREEZE,200,skill_lv,skill_get_time(skill_id,skill_lv)); break; @@ -2801,13 +2793,6 @@ bool skill_strip_equip(struct block_list *src, struct block_list *target, uint16 case SC_STRIPACCESSARY: location = EQP_ACC; break; - case WL_EARTHSTRAIN: - location = EQP_SHIELD|EQP_ARMOR|EQP_HELM; - if (skill_lv >= 4) - location |= EQP_WEAPON; - if (skill_lv >= 5) - location |= EQP_ACC; - break; } for (uint8 i = 0; i < ARRAYLENGTH(pos); i++) { @@ -3479,10 +3464,6 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * dmg_type = (skill_id == 0) ? DMG_SPLASH : skill_get_hit(skill_id); switch( skill_id ) { - case WL_HELLINFERNO: - if (dmg.dmg_lv == ATK_DEF && !(flag&ELE_DARK)) // Burning only starts if the fire attack successfully lands - sc_start4(src, bl, SC_BURNING, 55 + 5 * skill_lv, skill_lv, 1000, src->id, 0, skill_get_time(skill_id, skill_lv)); - break; case SC_TRIANGLESHOT: if( rnd()%100 > (1 + skill_lv) ) dmg.blewcount = 0; @@ -3551,7 +3532,6 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * else // the central target doesn't display an animation dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, DMG_SPLASH); // needs -2(!) as skill level break; - case WL_HELLINFERNO: case SR_EARTHSHAKER: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,DMG_SINGLE); break; @@ -4337,11 +4317,7 @@ static TIMER_FUNC(skill_timerskill){ } if (j) { i = applyeffects[rnd()%j]; - status_change_start(src, target, static_cast(i), 10000, skl->skill_lv, - (i == SC_BURNING ? 1000 : (i == SC_BLEEDING ? src->id : 0)), - (i == SC_BURNING ? src->id : 0), 0, - (i == SC_BURNING ? 15000 : (i == SC_FREEZING ? 40000 : - (i == SC_BLEEDING ? 120000 : 5000))), SCSTART_NONE); + sc_start(src, target, static_cast(i), 100, skl->skill_lv, (i == SC_BURNING ? 18000 : (i == SC_FREEZING ? 27000 : (i == SC_BLEEDING ? 108000 : 4500)))); } } } @@ -5724,86 +5700,99 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case WL_TETRAVORTEX: - if( sc ) { // No SC? No spheres - int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }, - i, j = 0, k, subskill = 0; + if (sd == nullptr) { // Monster usage + uint8 i = 0; + const static std::vector> tetra_skills = { { WL_TETRAVORTEX_FIRE, 1 }, + { WL_TETRAVORTEX_WIND, 4 }, + { WL_TETRAVORTEX_WATER, 2 }, + { WL_TETRAVORTEX_GROUND, 8 } }; - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - if( sc->data[i] ) { - spheres[j] = i; - positions[j] = sc->data[i]->val2; - j++; - } - - // Sphere Sort, this time from new to old - for( i = 0; i <= j - 2; i++ ) - for( k = i + 1; k <= j - 1; k++ ) - if( positions[i] < positions[k] ) { - SWAP(positions[i],positions[k]); - SWAP(spheres[i],spheres[k]); - } - - if(j == 5) { // If 5 spheres, remove last one and only do 4 actions (Official behavior) - status_change_end(src, static_cast(spheres[4]), INVALID_TIMER); - j = 4; + for (const auto &skill : tetra_skills) { + if (skill_lv > 5) { + skill_area_temp[0] = i; + skill_area_temp[1] = skill[1]; + map_foreachinallrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill[0], skill_lv, tick, flag | BCT_ENEMY, skill_castend_damage_id); + } else + skill_addtimerskill(src, tick + i * 200, bl->id, skill[1], 0, skill[0], skill_lv, i, flag); + i++; } + } else if (sc) { // No SC? No spheres + int i, k = 0; - k = 0; - for( i = 0; i < j; i++ ) { // Loop should always be 4 for regular players, but unconditional_skill could be less - switch( sc->data[spheres[i]]->val1 ) { - case WLS_FIRE: subskill = WL_TETRAVORTEX_FIRE; k |= 1; break; - case WLS_WIND: subskill = WL_TETRAVORTEX_WIND; k |= 4; break; - case WLS_WATER: subskill = WL_TETRAVORTEX_WATER; k |= 2; break; - case WLS_STONE: subskill = WL_TETRAVORTEX_GROUND; k |= 8; break; + if (sc->data[SC_SPHERE_5]) // If 5 spheres, remove last one (based on reverse order) and only do 4 actions (Official behavior) + status_change_end(src, SC_SPHERE_1, INVALID_TIMER); + + for (i = SC_SPHERE_5; i >= SC_SPHERE_1; i--) { // Loop should always be 4 for regular players, but unconditional_skill could be less + if (sc->data[static_cast(i)] == nullptr) + continue; + + uint16 subskill = 0; + + switch (sc->data[static_cast(i)]->val1) { + case WLS_FIRE: + subskill = WL_TETRAVORTEX_FIRE; + k |= 1; + break; + case WLS_WIND: + subskill = WL_TETRAVORTEX_WIND; + k |= 4; + break; + case WLS_WATER: + subskill = WL_TETRAVORTEX_WATER; + k |= 2; + break; + case WLS_STONE: + subskill = WL_TETRAVORTEX_GROUND; + k |= 8; + break; } if (skill_lv > 5) { - skill_area_temp[0] = i; + skill_area_temp[0] = abs(i - SC_SPHERE_5); skill_area_temp[1] = k; map_foreachinallrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, subskill, skill_lv, tick, flag | BCT_ENEMY, skill_castend_damage_id); } else - skill_addtimerskill(src, tick + i * 200, bl->id, k, 0, subskill, skill_lv, i, flag); - status_change_end(src, static_cast(spheres[i]), INVALID_TIMER); + skill_addtimerskill(src, tick + abs(i - SC_SPHERE_5) * 200, bl->id, k, 0, subskill, skill_lv, abs(i - SC_SPHERE_5), flag); + status_change_end(src, static_cast(i), INVALID_TIMER); } } break; case WL_RELEASE: - if( sd ) - { + if (sc == nullptr) + break; + if (sd) { int i; skill_toggle_magicpower(src, skill_id); // No hit will be amplified - // Priority is to release SpellBook - if( sc && sc->data[SC_FREEZE_SP] ) - { // SpellBook - uint16 pres_skill_id, pres_skill_lv, point, s = 0; - int spell[SC_MAXSPELLBOOK-SC_SPELLBOOK1 + 1]; - int cooldown; - - for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) // List all available spell to be released - if( sc->data[i] ) spell[s++] = i; - - if ( s == 0 ) + if (skill_lv == 1) { // SpellBook + if (sc->data[SC_FREEZE_SP] == nullptr) break; - i = spell[s==1?0:rnd()%s];// Random select of spell to be released. - if(sc->data[i] ){// Now extract the data from the preserved spell - pres_skill_id = sc->data[i]->val1; - pres_skill_lv = sc->data[i]->val2; - point = sc->data[i]->val3; - status_change_end(src, static_cast(i), INVALID_TIMER); - }else //something went wrong :( + bool found_spell = false; + + for (i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) { // List all available spell to be released + if (sc->data[i] != nullptr) { + found_spell = true; + break; + } + } + + if (!found_spell) break; + // Now extract the data from the preserved spell + uint16 pres_skill_id = sc->data[i]->val1; + uint16 pres_skill_lv = sc->data[i]->val2; + uint16 point = sc->data[i]->val3; + + status_change_end(src, static_cast(i), INVALID_TIMER); + if( sc->data[SC_FREEZE_SP]->val2 > point ) sc->data[SC_FREEZE_SP]->val2 -= point; else // Last spell to be released status_change_end(src, SC_FREEZE_SP, INVALID_TIMER); - if( bl->type != BL_SKILL ) /* skill types will crash the client */ - clif_skill_nodamage(src, bl, pres_skill_id, pres_skill_lv, 1); if( !skill_check_condition_castbegin(sd, pres_skill_id, pres_skill_lv) ) break; @@ -5826,62 +5815,41 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint sd->ud.canact_tick = i64max(tick + skill_delayfix(src, pres_skill_id, pres_skill_lv), sd->ud.canact_tick); clif_status_change(src, EFST_POSTDELAY, 1, skill_delayfix(src, pres_skill_id, pres_skill_lv), 0, 0, 0); - cooldown = pc_get_skillcooldown(sd,pres_skill_id, pres_skill_lv); - if( cooldown ) + int cooldown = pc_get_skillcooldown(sd,pres_skill_id, pres_skill_lv); + + if( cooldown > 0 ) skill_blockpc_start(sd, pres_skill_id, cooldown); - } - else - { // Summon Balls - int j = 0, k; - int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }; + } else { // Summoned Balls + for (i = SC_SPHERE_5; i >= SC_SPHERE_1; i--) { + if (sc->data[static_cast(i)] == nullptr) + continue; - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - if( sc && sc->data[i] ) - { - spheres[j] = i; - positions[j] = sc->data[i]->val2; - sc->data[i]->val2--; // Prepares for next position - j++; - } + int skele = WL_RELEASE - 5 + sc->data[static_cast(i)]->val1 - WLS_FIRE; // Convert Ball Element into Skill ATK for balls - if( j == 0 ) - { // No Spheres - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0); - break; - } - - // Sphere Sort - for( i = 0; i <= j - 2; i++ ) - for( k = i + 1; k <= j - 1; k++ ) - if( positions[i] > positions[k] ) - { - SWAP(positions[i],positions[k]); - SWAP(spheres[i],spheres[k]); - } - - if( skill_lv == 1 ) j = 1; // Limit only to one ball - for( i = 0; i < j; i++ ) - { - int skele = WL_RELEASE - 5 + sc->data[spheres[i]]->val1 - WLS_FIRE; // Convert Ball Element into Skill ATK for balls // WL_SUMMON_ATK_FIRE, WL_SUMMON_ATK_WIND, WL_SUMMON_ATK_WATER, WL_SUMMON_ATK_GROUND - skill_addtimerskill(src,tick+(t_tick)status_get_adelay(src)*i,bl->id,0,0,skele,sc->data[spheres[i]]->val3,BF_MAGIC,flag|SD_LEVEL); - status_change_end(src, static_cast(spheres[i]), INVALID_TIMER); // Eliminate ball + skill_addtimerskill(src, tick + (t_tick)status_get_adelay(src) * abs(i - SC_SPHERE_1), bl->id, 0, 0, skele, sc->data[static_cast(i)]->val2, BF_MAGIC, flag | SD_LEVEL); + status_change_end(src, static_cast(i), INVALID_TIMER); // Eliminate ball } - clif_skill_nodamage(src,bl,skill_id,0,1); + clif_skill_nodamage(src, bl, skill_id, 0, 1); } } break; case WL_FROSTMISTY: // Causes Freezing status through walls. - sc_start(src,bl,status_skill2sc(skill_id),20+12*skill_lv+(sd ? sd->status.job_level : 50)/5,skill_lv,skill_get_time(skill_id,skill_lv)); + sc_start(src, bl, status_skill2sc(skill_id), 25 + 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv)); + sc_start(src, bl, SC_MISTY_FROST, 100, skill_lv, skill_get_time2(skill_id, skill_lv)); // Doesn't deal damage through non-shootable walls. if( !battle_config.skill_wall_check || (battle_config.skill_wall_check && path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL)) ) skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); break; case WL_HELLINFERNO: - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - skill_addtimerskill(src,tick + 200,bl->id,0,0,skill_id,skill_lv,BF_MAGIC,flag|ELE_DARK); + if (flag & 1) { + skill_attack(BF_MAGIC, src, src, bl, skill_id, skill_lv, tick, flag); + skill_addtimerskill(src, tick + 300, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag | ELE_DARK); + } 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; case RA_WUGSTRIKE: if( sd && pc_isridingwug(sd) ){ @@ -10060,12 +10028,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif_skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); break; - case WL_FROSTMISTY: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinallrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill_castend_damage_id); - break; - - case WL_JACKFROST: case NPC_JACKFROST: 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|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); @@ -10111,53 +10073,65 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case WL_SUMMONWB: case WL_SUMMONSTONE: { - short element = 0, sctype = 0, pos = -1; - struct status_change *sc = status_get_sc(src); + status_change *sc = status_get_sc(src); - if( !sc ) + if (sc == nullptr) break; - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) { - if( !sctype && !sc->data[i] ) - sctype = i; // Take the free SC - if( sc->data[i] ) - pos = max(sc->data[i]->val2,pos); + e_wl_spheres element; + + switch (skill_id) { // Set val2. The SC element for this ball + case WL_SUMMONFB: + element = WLS_FIRE; + break; + case WL_SUMMONBL: + element = WLS_WIND; + break; + case WL_SUMMONWB: + element = WLS_WATER; + break; + case WL_SUMMONSTONE: + element = WLS_STONE; + break; } - if( !sctype ) { - if( sd ) // No free slots to put SC - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); - break; + if (skill_lv == 1) { + sc_type sphere = SC_NONE; + + for (i = SC_SPHERE_1; i <= SC_SPHERE_5; i++) { + if (sc->data[i] == nullptr) { + sphere = static_cast(i); // Take the free SC + break; + } + } + + if (sphere == SC_NONE) { + if (sd) // No free slots to put SC + clif_skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0); + break; + } + + sc_start2(src, src, sphere, 100, element, skill_lv, skill_get_time(skill_id, skill_lv)); + } else { + for (i = SC_SPHERE_1; i <= SC_SPHERE_5; i++) { + status_change_end(src, static_cast(i), INVALID_TIMER); // Removes previous type + sc_start2(src, src, static_cast(i), 100, element, skill_lv, skill_get_time(skill_id, skill_lv)); + } } - pos++; // Used in val2 for SC. Indicates the order of this ball - switch( skill_id ) { // Set val1. The SC element for this ball - case WL_SUMMONFB: element = WLS_FIRE; break; - case WL_SUMMONBL: element = WLS_WIND; break; - case WL_SUMMONWB: element = WLS_WATER; break; - case WL_SUMMONSTONE: element = WLS_STONE; break; - } - - sc_start4(src,src,(enum sc_type)sctype,100,element,pos,skill_lv,0,skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage(src,bl,skill_id,0,0); + clif_skill_nodamage(src, bl, skill_id, 0, 0); } break; - case WL_READING_SB: - if( sd ) { - struct status_change *sc = status_get_sc(bl); - - for( i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) - if( sc && !sc->data[i] ) - break; - if( i == SC_MAXSPELLBOOK ) { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); + case WL_READING_SB_READING: + if (sd) { + if (pc_checkskill(sd, WL_READING_SB) == 0 || skill_lv < 1 || skill_lv > 10) { + clif_skill_fail(sd, skill_id, USESKILL_FAIL_SPELLBOOK_READING, 0); break; } - sc_start(src,bl, SC_STOP, 100, skill_lv, INFINITE_TICK); //Can't move while selecting a spellbook. - clif_spellbook_list(sd); clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); + skill_spellbook(sd, ITEMID_WL_MB_SG + skill_lv - 1); } break; @@ -11858,6 +11832,7 @@ TIMER_FUNC(skill_castend_id){ } case GN_WALLOFTHORN: case SC_ESCAPE: + case WL_FROSTMISTY: case SU_CN_POWDERING: ud->skillx = target->x; ud->skilly = target->y; @@ -12729,6 +12704,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case NC_COLDSLOWER: case RK_DRAGONBREATH: case RK_DRAGONBREATH_WATER: + case WL_FROSTMISTY: case RL_HAMMER_OF_GOD: // Cast center might be relevant later (e.g. for knockback direction) skill_area_temp[4] = x; @@ -15237,8 +15213,8 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) if (*c >= 2) // Check for two companions for Benedictio. [Skotlex] return 0; } - else if (is_chorus || skill_id == WL_COMET) { - if (*c == MAX_PARTY) // Check for partners for Chorus or Comet; Cap if the entire party is accounted for. + else if (is_chorus) { + if (*c == MAX_PARTY) // Check for partners for Chorus; Cap if the entire party is accounted for. return 0; } else if (*c >= 1) // Check for one companion for all other cases. @@ -15275,11 +15251,6 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) if( (tsd->class_&MAPID_UPPERMASK) == MAPID_PRIEST ) p_sd[(*c)++] = tsd->bl.id; return 1; - case WL_COMET: - // Comet does not consume Red Gemstones when there is at least 1 Warlock class next to the caster - if( ( sd->class_&MAPID_THIRDMASK ) == MAPID_WARLOCK ) - p_sd[(*c)++] = tsd->bl.id; - return 1; default: //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex] { uint16 skill_lv; @@ -15367,7 +15338,7 @@ int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, uint16 memset (p_sd, 0, sizeof(p_sd)); i = map_foreachinallrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id); - if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET && skill_id != WM_GREAT_ECHO ) //Apply the average lv to encore skills. + if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WM_GREAT_ECHO ) //Apply the average lv to encore skills. *skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners. return c; } @@ -15980,8 +15951,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i } } break; - case AB_ADORAMUS: // bugreport:7647 mistress card DOES remove requirements for gemstones from Adoramus and Comet -helvetica - case WL_COMET: + case AB_ADORAMUS: // bugreport:7647 mistress card DOES remove requirements for gemstones from Adoramus -helvetica if( skill_check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0 && require.itemid[0] && sd->special_state.no_gemstone == 0 && ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->inventory.u.items_inventory[i].amount < require.amount[0]) ) { @@ -15993,32 +15963,35 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i case WL_SUMMONBL: case WL_SUMMONWB: case WL_SUMMONSTONE: - if( sc ) { - ARR_FIND(SC_SPHERE_1,SC_SPHERE_5+1,i,!sc->data[i]); - if( i == SC_SPHERE_5+1 ) { // No more free slots - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); + if (skill_lv == 1 && sc) { // Failure only happens on level 1 + ARR_FIND(SC_SPHERE_1, SC_SPHERE_5 + 1, i, !sc->data[i]); + + if (i == SC_SPHERE_5 + 1) { // No more free slots + clif_skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0); return false; } } break; case WL_TETRAVORTEX: // bugreport:7598 moved sphere check to precast to avoid triggering cooldown per official behavior -helvetica - if( sc ) { - int j = 0; + case WL_RELEASE: { + int active_spheres = 0, req_spheres = 0; - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - if( sc->data[i] ) { - j++; - } + for (i = SC_SPHERE_1; i <= SC_SPHERE_5; i++) { + if (sc && sc->data[i]) + active_spheres++; + } - if( j < 4 ) { // Need 4 spheres minimum - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + // Cast requirement + if (skill_id == WL_TETRAVORTEX) + req_spheres = 4; + else if (skill_id == WL_RELEASE && skill_lv == 2) // Only level 2 uses Spheres + req_spheres = 1; + + if (active_spheres < req_spheres) { // Need minimum amount of spheres + clif_skill_fail(sd, skill_id, (skill_id == WL_RELEASE) ? USESKILL_FAIL_SUMMON_NONE : USESKILL_FAIL_LEVEL, 0); return false; } } - else { // no status at all? no spheres present - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return false; - } break; case GC_HALLUCINATIONWALK: if( sc && (sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY]) ) { @@ -16976,10 +16949,6 @@ struct s_skill_condition skill_get_requirement(struct map_session_data* sd, uint if( itemdb_group_item_exists(IG_GEMSTONE, skill->require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2)) ) continue; break; - case WL_COMET: - if( itemdb_group_item_exists(IG_GEMSTONE, skill->require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0)) ) - continue; - break; } req.itemid[i] = skill->require.itemid[i]; @@ -20613,31 +20582,26 @@ int skill_magicdecoy(struct map_session_data *sd, t_itemid nameid) { return 0; } -// Warlock Spellbooks. [LimitLine/3CeAM] +/** + * Process Warlock Spellbooks + * @param sd: Player data + * @param nameid: Spellbook item used + */ void skill_spellbook(struct map_session_data *sd, t_itemid nameid) { nullpo_retv(sd); if (reading_spellbook_db.empty()) return; - int i; struct status_change *sc = status_get_sc(&sd->bl); - status_change_end(&sd->bl, SC_STOP, INVALID_TIMER); - - for (i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) { - // No further checks needed - if( !sc ){ + for (int i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) { + if (sc == nullptr || sc->data[i] == nullptr) break; + if (i == SC_MAXSPELLBOOK) { + clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); + return; } - - if( !sc->data[i] ) - break; - } - - if( i > SC_MAXSPELLBOOK ) { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); - return; } std::shared_ptr spell = reading_spellbook_db.findBook(nameid); @@ -20647,7 +20611,7 @@ void skill_spellbook(struct map_session_data *sd, t_itemid nameid) { uint16 skill_id = spell->skill_id, skill_lv = pc_checkskill(sd, skill_id); - if (!skill_lv) { // Caster hasn't learned the skill + if (skill_lv == 0) { // Caster hasn't learned the skill sc_start(&sd->bl,&sd->bl, SC_SLEEP, 100, 1, skill_get_time(WL_READING_SB, pc_checkskill(sd, WL_READING_SB))); clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); return; @@ -20660,7 +20624,7 @@ void skill_spellbook(struct map_session_data *sd, t_itemid nameid) { clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0); return; } - for (i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) { // This is how official saves spellbook. [malufett] + for (int i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) { // This is how official saves spellbook. [malufett] if (!sc->data[i]) { sc->data[SC_FREEZE_SP]->val2 += points; // increase points sc_start4(&sd->bl,&sd->bl, (sc_type)i, 100, skill_id, skill_lv, points, 0, INFINITE_TICK); diff --git a/src/map/skill.hpp b/src/map/skill.hpp index b41708cc1d..f91d3a6f1a 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -1965,6 +1965,7 @@ enum e_skill { NV_BREAKTHROUGH, NV_HELPANGEL, NV_TRANSCENDENCE, + WL_READING_SB_READING, HLIF_HEAL = 8001, HLIF_AVOID, @@ -2261,7 +2262,7 @@ void skill_usave_trigger(struct map_session_data *sd); /** * Warlock **/ -enum wl_spheres { +enum e_wl_spheres { WLS_FIRE = 0x44, WLS_WIND, WLS_WATER, diff --git a/src/map/status.cpp b/src/map/status.cpp index 5c2f9a5a12..8e110cf94c 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -847,14 +847,11 @@ void initChangeTables(void) /* Warlock */ add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON ); set_sc_with_vfx( WL_FROSTMISTY , SC_FREEZING , EFST_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF ); - add_sc( WL_JACKFROST , SC_FREEZE ); set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , EFST_MARSHOFABYSS , SCB_AGI|SCB_DEX|SCB_SPEED ); set_sc( WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , EFST_RECOGNIZEDSPELL , SCB_MATK); add_sc( WL_SIENNAEXECRATE , SC_STONE ); set_sc( WL_STASIS , SC_STASIS , EFST_STASIS , SCB_NONE ); - add_sc( WL_CRIMSONROCK , SC_STUN ); - set_sc( WL_HELLINFERNO , SC_BURNING , EFST_BURNT , SCB_MDEF ); - set_sc( WL_COMET , SC_BURNING , EFST_BURNT , SCB_MDEF ); + set_sc_with_vfx( WL_COMET , SC_MAGIC_POISON , EFST_MAGIC_POISON , SCB_NONE ); set_sc( WL_TELEKINESIS_INTENSE , SC_TELEKINESIS_INTENSE, EFST_TELEKINESIS_INTENSE, SCB_MATK ); /* Ranger */ @@ -1385,6 +1382,7 @@ void initChangeTables(void) StatusIconChangeTable[SC_ADD_ATK_DAMAGE] = EFST_ADD_ATK_DAMAGE; StatusIconChangeTable[SC_ADD_MATK_DAMAGE] = EFST_ADD_MATK_DAMAGE; StatusIconChangeTable[SC_ENSEMBLEFATIGUE] = EFST_ENSEMBLEFATIGUE; + StatusIconChangeTable[SC_MISTY_FROST] = EFST_MISTY_FROST; // Battleground Queue StatusIconChangeTable[SC_ENTRY_QUEUE_APPLY_DELAY] = EFST_ENTRY_QUEUE_APPLY_DELAY; @@ -1569,6 +1567,7 @@ void initChangeTables(void) StatusChangeFlagTable[SC_ANCILLA] |= SCB_REGEN; StatusChangeFlagTable[SC_ENSEMBLEFATIGUE] |= SCB_SPEED|SCB_ASPD; + StatusChangeFlagTable[SC_MISTY_FROST] |= SCB_NONE; #ifdef RENEWAL // renewal EDP increases your weapon atk @@ -1615,6 +1614,8 @@ void initChangeTables(void) StatusDisplayType[SC_SPRITEMABLE] = BL_PC; StatusDisplayType[SC_SV_ROOTTWIST] = BL_PC; StatusDisplayType[SC_HELLS_PLANT] = BL_PC; + StatusDisplayType[SC_MISTY_FROST] = BL_PC; + StatusDisplayType[SC_MAGIC_POISON] = BL_PC; // Costumes StatusDisplayType[SC_MOONSTAR] = BL_PC; @@ -10325,7 +10326,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty case SC_MAGICPOWER: // val1: Skill lv val2 = 1; // Lasts 1 invocation - val3 = 5*val1; // Matk% increase +#ifdef RENEWAL + val3 = 10 * val1; // Matk% increase +#else + val3 = 5 * val1; // Matk% increase +#endif val4 = 0; // 0 = ready to be used, 1 = activated and running break; case SC_SACRIFICE: @@ -11915,6 +11920,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty val2 = 10 + val1 * 5; // Def/Mdef tick = INFINITE_TICK; break; + case SC_MAGIC_POISON: + val2 = 50; // Attribute Reduction + break; /* Rebellion */ case SC_B_TRAP: @@ -12248,6 +12256,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty case SC_CROSSBOWCLAN: case SC_JUMPINGCLAN: case SC_DRESSUP: + case SC_MISTY_FROST: val_flag |= 1; break; // Start |1|2 val_flag setting diff --git a/src/map/status.hpp b/src/map/status.hpp index 42e8414b08..9aa8b16aa8 100644 --- a/src/map/status.hpp +++ b/src/map/status.hpp @@ -652,11 +652,7 @@ enum sc_type : int16 { SC_SPELLBOOK4, SC_SPELLBOOK5, SC_SPELLBOOK6, -/** - * In official server there are only 7 maximum number of spell books that can be memorized - * To increase the maximum value just add another status type before SC_MAXSPELLBOOK (ex. SC_SPELLBOOK7, SC_SPELLBOOK8 and so on) - **/ - SC_MAXSPELLBOOK, + SC_MAXSPELLBOOK, // SC_SPELLBOOK7 /* Max HP & SP */ SC_INCMHP, SC_INCMSP, @@ -933,6 +929,8 @@ enum sc_type : int16 { SC_LUXANIMA, SC_REUSE_LIMIT_LUXANIMA, SC_ENSEMBLEFATIGUE, + SC_MISTY_FROST, + SC_MAGIC_POISON, #ifdef RENEWAL SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled