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 <lemongrass@kstp.at>
This commit is contained in:
Aleos 2020-08-08 12:23:29 -04:00 committed by GitHub
parent 2d9ef842e4
commit 36195d157d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 397 additions and 488 deletions

View File

@ -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; },{},{}

View File

@ -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

View File

@ -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

View File

@ -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#

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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
**/

View File

@ -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);

View File

@ -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

View File

@ -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<sc_type>(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<sc_type>(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<std::vector<uint16>> 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++;
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;
// 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 (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);
if(j == 5) { // If 5 spheres, remove last one and only do 4 actions (Official behavior)
status_change_end(src, static_cast<sc_type>(spheres[4]), INVALID_TIMER);
j = 4;
}
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<sc_type>(i)] == nullptr)
continue;
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;
uint16 subskill = 0;
switch (sc->data[static_cast<sc_type>(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<sc_type>(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<sc_type>(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;
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<sc_type>(i), INVALID_TIMER);
}else //something went wrong :(
break;
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,47 +5815,20 @@ 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<sc_type>(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<sc_type>(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<sc_type>(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<sc_type>(i)]->val2, BF_MAGIC, flag | SD_LEVEL);
status_change_end(src, static_cast<sc_type>(i), INVALID_TIMER); // Eliminate ball
}
clif_skill_nodamage(src, bl, skill_id, 0, 1);
}
@ -5874,14 +5836,20 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
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:
if (flag & 1) {
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);
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 (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<sc_type>(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;
}
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_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<sc_type>(i), INVALID_TIMER); // Removes previous type
sc_start2(src, src, static_cast<sc_type>(i), 100, element, skill_lv, skill_get_time(skill_id, skill_lv));
}
}
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);
}
break;
case WL_READING_SB:
case WL_READING_SB_READING:
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);
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,8 +15963,9 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
case WL_SUMMONBL:
case WL_SUMMONWB:
case WL_SUMMONSTONE:
if( sc ) {
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;
@ -16002,23 +15973,25 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
}
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,32 +20582,27 @@ 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( !sc->data[i] )
break;
}
if( i > SC_MAXSPELLBOOK ) {
if (i == SC_MAXSPELLBOOK) {
clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0);
return;
}
}
std::shared_ptr<s_skill_spellbook_db> 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);

View File

@ -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,

View File

@ -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
#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

View File

@ -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