Updated Summoner class (#1965)
* Fixes #1865. * Updated and added new Summoner class skills. * Information based on kRO patch notes. - http://ro.gnjoy.com/news/devnote/View.asp?category=1&seq=1987966&curpage=1 * Updated previously implemented skills to better mimic official behavior. Thanks to @RagnarokNova, Fyrus, and Jet for their hard work on gathering the information! Thanks to @Grimfiend, @Atemo, @feltenc, @Lemongrass3110, @Felleonel, and @sanny1128 for the rapid test and reports!
This commit is contained in:
parent
689a3ff9b3
commit
5f7a143d3e
@ -1379,6 +1379,24 @@
|
||||
5040,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_BUNCHOFSHRIMP,Bunch of Shrimp
|
||||
5041,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_FRESHSHRIMP,Fresh Shrimp
|
||||
|
||||
// Unknown Unconfirmed Summoner Skills - Animations Show On These
|
||||
//5042,0,0,0,0,0,0,5,0,yes,0,0,0,none,0,0x0, SU_CN_METEOR_SEC,
|
||||
//5043,0,0,0,0,0,0,5,0,yes,0,0,0,none,0,0x0, SU_LUNATICCARROTBEAT_SEC,
|
||||
|
||||
5044,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SOULATTACK,Soul Attack
|
||||
5045,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_POWEROFFLOCK,Power of Flock
|
||||
5046,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SVG_SPIRIT,Spirit of Savage
|
||||
5047,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_HISS,Hiss
|
||||
5048,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_NYANGGRASS,Nyang Grass
|
||||
5049,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_GROOMING,Grooming
|
||||
5050,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_PURRING,Purring
|
||||
5051,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SHRIMPARTY,Tasty Shrimp Party
|
||||
5052,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SPIRITOFLIFE,Spirit of Life
|
||||
5053,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_MEOWMEOW,Meow Meow
|
||||
5054,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SPIRITOFLAND,Spirit of Land
|
||||
5055,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_CHATTERING,Chattering
|
||||
5056,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SPIRITOFSEA,Spirit of Sea
|
||||
|
||||
//****
|
||||
// Homunculus S
|
||||
8001,9,6,4,0,0x1,0,5,1,no,0,0,0,magic,0,0x0, HLIF_HEAL,Healing Touch
|
||||
|
@ -1770,7 +1770,7 @@
|
||||
|
||||
//===== Summoner ===========================
|
||||
//-- SU_BITE
|
||||
5019,1000,1000,0,0,0,0,0
|
||||
5019,1000,1000,0,0,0,0,-1
|
||||
//-- SU_HIDE
|
||||
5020,0,1000,0,-1,0,15000,0
|
||||
//-- SU_SCRATCH
|
||||
@ -1778,35 +1778,53 @@
|
||||
//-- SU_STOOP
|
||||
5022,0,1000,0,6000,0,15000,0
|
||||
//-- SU_LOPE
|
||||
5023,500,1000,0,0,0,2000:4000:6000,0
|
||||
5023,500,1000,0,0,0,2000:4000:6000,-1
|
||||
//-- SU_SV_STEMSPEAR
|
||||
5026,2500,1000,0,0,120000,0,0
|
||||
5026,2000,1000,0,0,120000,0,-1
|
||||
//-- SU_CN_POWDERING
|
||||
5027,1500,1000,0,3000:4000:5000:6000:7000,0,0,0
|
||||
5027,2000,1000,0,3000:4000:5000:6000:7000,0,10000,-1
|
||||
//-- SU_CN_METEOR
|
||||
5028,7500,1000,0,1500:2000:2500:3000:3500,20000,5000,-1
|
||||
5028,3000,1000,0,1500:2000:2500:3000:3500,20000,5000,3000
|
||||
//-- SU_SV_ROOTTWIST
|
||||
5029,0,1000,0,7000:9000:11000:13000:15000,0,3000,0
|
||||
//-- SU_SV_ROOTTWIST_ATK
|
||||
5030,0,1000,0,0,0,0
|
||||
5029,0,1000,0,7000:9000:11000:13000:15000,0,3000:2500:2000:1500:1000,0
|
||||
//-- SU_SCAROFTAROU
|
||||
5032,500,1000,0,9000,1000,0,0
|
||||
5032,500,1000,0,9000,1000,10000,-1
|
||||
//-- SU_PICKYPECK
|
||||
5033,2500,1000,0,0,0,0,0
|
||||
5033,1000,1000,0,0,0,0,-1
|
||||
//-- SU_PICKYPECK_DOUBLE_ATK
|
||||
5034,0,1000,0,0,0,0,0
|
||||
//-- SU_ARCLOUSEDASH
|
||||
5035,2500,1000,0,60000:70000:80000:90000:100000,0,10000,0
|
||||
5035,1000,1000,0,60000:70000:80000:90000:100000,0,10000,0
|
||||
//-- SU_LUNATICCARROTBEAT
|
||||
5036,1500,1000,0,0,5000,6000,0
|
||||
5036,1000,1000,0,0,5000,6000,-1
|
||||
//-- SU_TUNABELLY
|
||||
5038,2000,1000,0,0,0,8000:10000:12000:14000:16000,0
|
||||
5038,1000,1000,0,5000,0,2000:5000:8000:11000:14000,-1
|
||||
//-- SU_TUNAPARTY
|
||||
5039,0,1000,0,30000,0,20000,0
|
||||
//-- SU_BUNCHOFSHRIMP
|
||||
5040,0,1000,0,60000:90000:120000:150000:180000,0,10000,0
|
||||
5040,0,1000,0,60000:90000:120000:150000:180000,120000,10000,0
|
||||
//-- SU_FRESHSHRIMP
|
||||
5041,0,1000,0,120000,0,7000,0
|
||||
5041,0,1000,0,120000,0,6000:5000:4000:3000:2000,0
|
||||
//-- SU_POWEROFFLOCK
|
||||
5045,5000:4000:3000:2000:1000,1000,0,15000,10000,100000,-1
|
||||
//-- SU_SVG_SPIRIT
|
||||
5046,3000:3000:2500:2000:0,1000,0,0,0,22000,-1
|
||||
//-- SU_HISS
|
||||
5047,1000,1000,0,3000,3000:3000:4000:4000:5000,60000,-1
|
||||
//-- SU_NYANGGRASS
|
||||
5048,3000:2500:2000:1500:1000,1000,0,6000:7000:8000:9000:10000,0,60000,-1
|
||||
//-- SU_GROOMING
|
||||
5049,1000,1000,0,3000:4000:5000:6000:7000,0,60000:50000:40000:30000:20000,0
|
||||
//-- SU_PURRING
|
||||
5050,1000,1000,0,3000:4000:5000:6000:7000,0,65000:60000:55000:50000:45000,-1
|
||||
//-- SU_SHRIMPARTY
|
||||
5051,3500:3000:2500:2000:1500,1000,0,12000:14000:16000:18000:20000,0,65000:60000:55000:50000:45000,-1
|
||||
//-- SU_MEOWMEOW
|
||||
5053,0,1000,0,8000:8000:10000:10000:12000,0,180000:160000:140000:120000:100000,0
|
||||
//-- SU_SPIRITOFLAND
|
||||
5054,0,0,0,3000,0,0,0
|
||||
//-- SU_CHATTERING
|
||||
5055,0,1000,0,5000,10000,140000:120000:100000:80000:60000,0
|
||||
//==========================================
|
||||
|
||||
//===== Homunculus Skills ==================
|
||||
|
@ -1365,11 +1365,11 @@
|
||||
5023,6:10:14,6,2,0,0x1,0,3,1,yes,0,0,0,none,0,0x0, SU_LOPE,Lope
|
||||
5024,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SPRITEMABLE,Spirit Marble
|
||||
5025,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_POWEROFLAND,Power of Land
|
||||
5026,9,6,1,2:3:1:4:8,0x0,0,5,1,yes,0,0,0,magic,0,0x0, SU_SV_STEMSPEAR,Silvervine Stem Spear
|
||||
5026,9,6,1,2:3:1:4:8,0,0,5,1,yes,0,0,0,magic,0,0x0, SU_SV_STEMSPEAR,Silvervine Stem Spear
|
||||
5027,9,6,1,0,0x3,0,5,1,yes,0,0,1,none,0,0x0, SU_CN_POWDERING,Catnip Powdering
|
||||
5028,9,8,2,0,0,1:1:2:2:3,5,-5,yes,0,0,0,magic,0,0x0, SU_CN_METEOR,Catnip Meteor
|
||||
5029,9,6,1,0,0x1,0,5,1,yes,0,0,1,none,0,0x0, SU_SV_ROOTTWIST,Silvervine Root Twist
|
||||
5030,0,6,1,5,0x30,0,5,1,no,0,0,1,magic,0,0x0, SU_SV_ROOTTWIST_ATK,Silver Vine Root Twist Attack
|
||||
5030,0,6,1,5,0x70,0,5,1,no,0,0,1,misc,0,0x0, SU_SV_ROOTTWIST_ATK,Silver Vine Root Twist Attack
|
||||
5031,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_POWEROFLIFE,Power of Life
|
||||
5032,9,6,1,-1,0,0,5,1,yes,0,0,0,weapon,0,0x0, SU_SCAROFTAROU,Scar of Tarou
|
||||
5033,9,8,1,-1,0,0,5,-5,yes,0,0,0,weapon,0,0x0, SU_PICKYPECK,Picky Peck
|
||||
@ -1386,6 +1386,20 @@
|
||||
//5042,0,0,0,0,0,0,5,0,yes,0,0,0,none,0,0x0, SU_CN_METEOR_SEC,
|
||||
//5043,0,0,0,0,0,0,5,0,yes,0,0,0,none,0,0x0, SU_LUNATICCARROTBEAT_SEC,
|
||||
|
||||
5044,14,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SOULATTACK,Soul Attack
|
||||
5045,0,6,4,0,0x3,3:4:5:6:-1,5,0,yes,0,0,0,magic,0,0x0, SU_POWEROFFLOCK,Power of Flock
|
||||
5046,9,8,1,-1,0,1,5,1,yes,0,0,14,weapon,0,0x0, SU_SVG_SPIRIT,Spirit of Savage
|
||||
5047,0,6,4,0,0x3,-1,5,1,yes,0,0,0,magic,0,0x0, SU_HISS,Hiss
|
||||
5048,9,6,2,0,0x1,0,5,1,yes,0,0,1,none,0,0x0, SU_NYANGGRASS,Nyang Grass
|
||||
5049,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0, SU_GROOMING,Grooming
|
||||
5050,0,6,4,0,0x3,-1,5,1,yes,0,0,0,magic,0,0x0, SU_PURRING,Purring
|
||||
5051,0,6,4,0,0x3,-1,5,1,yes,0,0,0,magic,0,0x0, SU_SHRIMPARTY,Tasty Shrimp Party
|
||||
5052,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SPIRITOFLIFE,Spirit of Life
|
||||
5053,0,6,4,0,0x3,-1,5,1,yes,0,0,0,magic,0,0x0, SU_MEOWMEOW,Meow Meow
|
||||
5054,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SPIRITOFLAND,Spirit of Land
|
||||
5055,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0, SU_CHATTERING,Chattering
|
||||
5056,0,0,0,0,0,0,1,0,no,0,0,0,none,0,0x0, SU_SPIRITOFSEA,Spirit of Sea
|
||||
|
||||
//****
|
||||
// Homunculus S
|
||||
8001,9,6,4,0,0x1,0,5,1,no,0,0,0,magic,0,0x0, HLIF_HEAL,Healing Touch
|
||||
|
@ -93,7 +93,6 @@
|
||||
691,8 //CASH_ASSUMPITO
|
||||
2284,8 //SC_FATALMENACE
|
||||
2300,8 //SC_DIMENSIONDOOR
|
||||
5023,8 //SU_LOPE
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Mixed
|
||||
@ -177,7 +176,6 @@
|
||||
//----------------------------------------------------------------------------
|
||||
426,256 //TK_HIGHJUMP
|
||||
290,256 //SA_ABRACADABRA
|
||||
5023,256 //SU_LOPE
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Zone 5 - Sealed Shrine
|
||||
|
@ -973,7 +973,7 @@
|
||||
|
||||
// Summoner
|
||||
5019,0,0,10,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_BITE
|
||||
5020,0,0,30,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_HIDE
|
||||
5020,0,0,10,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_HIDE
|
||||
5021,0,0,20:25:30,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_SCRATCH
|
||||
5022,0,0,10,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_STOOP
|
||||
5023,0,0,30,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_LOPE
|
||||
@ -996,6 +996,16 @@
|
||||
//5042,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //
|
||||
//5043,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //
|
||||
|
||||
5045,0,0,50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_POWEROFFLOCK
|
||||
5046,0,0,60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_SVG_SPIRIT
|
||||
5047,0,0,50:46:42:38:34,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_HISS
|
||||
5048,0,0,50:48:46:44:42,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_NYANGGRASS
|
||||
5049,0,0,15,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_GROOMING
|
||||
5050,0,0,70:65:60:55:50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_PURRING
|
||||
5051,0,0,100:90:80:70:60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_SHRIMPARTY
|
||||
5053,0,0,100:90:80:70:60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_MEOWMEOW
|
||||
5055,0,0,50:45:40:35:30,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SU_CHATTERING
|
||||
|
||||
8001,0,0,13:16:19:22:25,0,0,0,99,0,0,none,0,0,545,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_HEAL
|
||||
8002,0,0,20:25:30:35:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_AVOID
|
||||
8004,0,0,100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //HLIF_CHANGE
|
||||
|
@ -5691,6 +5691,19 @@
|
||||
4218,5039,5,5038,3,0,0,0,0,0,0,0,0 //SU_TUNAPARTY##
|
||||
4218,5040,5,5041,3,0,0,0,0,0,0,0,0 //SU_BUNCHOFSHRIMP##
|
||||
4218,5041,5,5024,1,0,0,0,0,0,0,0,0 //SU_FRESHSHRIMP##
|
||||
4218,5044,1,5024,1,0,0,0,0,0,0,0,0 //SU_SOULATTACK##
|
||||
4218,5045,5,100,0,5047,5,0,0,0,0,0,0,0,0 //SU_POWEROFFLOCK##
|
||||
4218,5046,5,100,0,5045,5,0,0,0,0,0,0,0,0 //SU_SVG_SPIRIT##
|
||||
4218,5047,5,100,0,5031,1,0,0,0,0,0,0,0,0 //SU_HISS##
|
||||
4218,5048,5,100,0,5053,5,0,0,0,0,0,0,0,0 //SU_NYANGGRASS##
|
||||
4218,5049,5,100,0,5037,1,0,0,0,0,0,0,0,0 //SU_GROOMING##
|
||||
4218,5050,5,100,0,5049,5,0,0,0,0,0,0,0,0 //SU_PURRING##
|
||||
4218,5051,5,100,0,5050,5,0,0,0,0,0,0,0,0 //SU_SHRIMPARTY##
|
||||
4218,5052,1,100,0,5046,5,0,0,0,0,0,0,0,0 //SU_SPIRITOFLIFE##
|
||||
4218,5053,5,100,0,5025,1,0,0,0,0,0,0,0,0 //SU_MEOWMEOW##
|
||||
4218,5054,1,100,0,5048,5,0,0,0,0,0,0,0,0 //SU_SPIRITOFLAND##
|
||||
4218,5055,5,100,0,5025,1,0,0,0,0,0,0,0,0 //SU_CHATTERING##
|
||||
4218,5056,1,100,0,5051,5,0,0,0,0,0,0,0,0 //SU_SPIRITOFSEA##
|
||||
4218,681,1,0,0,0,0,0,0,0,0,0,0 //ALL_INCCARRY#Enlarge Weight Limit R#
|
||||
|
||||
//Baby Summoner
|
||||
|
@ -179,7 +179,7 @@
|
||||
|
||||
5027,0x106, , 1:1:2:2:3, 0, -1,enemy, 0x2010 // SU_CN_POWDERING
|
||||
5028,0x86, , 0, 3, 500,enemy, 0x10 // SU_CN_METEOR
|
||||
5029,0x107, , 0, 0,1000,enemy, 0x10 // SU_SV_ROOTTWIST
|
||||
5048,0x107, , 2:2:3:3:4, 0, -1, enemy, 0x2010 // SU_NYANGGRASS
|
||||
|
||||
8020,0xf5, , 3, 0,2300:2100:1900:1700:1500,enemy, 0x018 //MH_POISON_MIST
|
||||
8033,0x7e, , 0, 0, -1,all, 0x003 //MH_STEINWAND
|
||||
|
@ -2530,6 +2530,94 @@ SC_CHASEWALK2 (SI_CHASEWALK2)
|
||||
desc: 2nd effect of Chasewalk
|
||||
val1: +STR
|
||||
|
||||
SC_SUHIDE (SI_SUHIDE)
|
||||
desc: Hide caster. Can be seen by insect, demon, and boss. Cannot move or pickup items.
|
||||
val1: Skill Lv
|
||||
|
||||
SC_SU_STOOP (SI_SU_STOOP)
|
||||
desc: Places a temporary buff on the user that decreases all damage taken by 90%.
|
||||
val1: Skill Lv
|
||||
|
||||
SC_SPRITEMABLE (SI_SPRITEMABLE)
|
||||
desc: Increase 1000 HP and 100 SP.
|
||||
val1:
|
||||
|
||||
SC_CATNIPPOWDER (SI_CATNIPPOWDER)
|
||||
desc: Reduces ATK and MATK by 50% to targets in a 3x3~7x7 area. HP and SP recovery rate increase.
|
||||
val1: Skill Lv
|
||||
val2: WATK% / MATK%
|
||||
val3: Movement speed reduction
|
||||
|
||||
SC_SV_ROOTTWIST (SI_SV_ROOTTWIST)
|
||||
desc: Prevents the target from moving and receives 100 Poison damage every second. Cannot be used on Boss monsters.
|
||||
val1: Skill Lv
|
||||
|
||||
SC_BITESCAR (SI_BITESCAR)
|
||||
desc: Drains a portion of the target's Max HP each second.
|
||||
val1: Skill Lv
|
||||
val2: Max HP% damage
|
||||
val4: Tick
|
||||
|
||||
SC_ARCLOUSEDASH (SI_ARCLOUSEDASH)
|
||||
desc: Increases Agi and movement speed.
|
||||
val1: AGI
|
||||
val2: Movement speed increase
|
||||
val4: Ranged ATK increase for Doram
|
||||
|
||||
SC_TUNAPARTY (SI_TUNAPARTY)
|
||||
desc: Protects from damage, the amount is based on Max HP.
|
||||
val1: Max HP% to absorb
|
||||
val2: Double the shield life with Spirit of Sea
|
||||
|
||||
SC_SHRIMP (SI_SHRIMP)
|
||||
desc: Gives all party members on screen +10% ATK and MATK.
|
||||
val1: BATK% / MATK%
|
||||
|
||||
SC_FRESHSHRIMP (SI_FRESHSHRIMP)
|
||||
desc: Recovers a small amount of HP. Each level reduces the time between each HP recovery tick.
|
||||
val1: Skill Lv
|
||||
val2: Heal amount
|
||||
val4: Tick
|
||||
|
||||
SC_HISS (SI_HISS)
|
||||
desc: Increases movement speed and perfect dodge of the user and his party.
|
||||
val1: Skill Lv
|
||||
val2: Perfect Dodge
|
||||
|
||||
SC_NYANGGRASS (SI_NYANGGRASS)
|
||||
desc: Reduces monster's DEF and MDEF by 50%. Reduces other player's equipment DEF and MDEF to 0.
|
||||
val1: Skill Lv
|
||||
|
||||
SC_GROOMING (SI_GROOMING)
|
||||
desc: FLEE + 100. Cures Poison, Frozen, Stun, Sleep, Bleeding, Silence, Crystallization, Deep Sleep, Fear, and Mandragora Howling.
|
||||
val1: Skill Lv
|
||||
val2: FLEE
|
||||
|
||||
SC_SHRIMPBLESSING (SI_PROTECTIONOFSHRIMP)
|
||||
desc: Increases caster's SP recovery by 150%.
|
||||
val1: Skill Lv
|
||||
|
||||
SC_CHATTERING (SI_CHATTERING)
|
||||
desc: Increases the player's ATK and MATK by 100. Increases the player's movespeed.
|
||||
val1: Skill Lv
|
||||
val2: ATK / MATK
|
||||
|
||||
SC_DORAM_WALKSPEED ()
|
||||
desc: Adjusts player's walk speed.
|
||||
val1: Movement speed adjustment
|
||||
|
||||
SC_DORAM_MATK ()
|
||||
desc: Statically increases MATK for Spirit of Land.
|
||||
val1: MATK
|
||||
|
||||
SC_DORAM_FLEE2 ()
|
||||
desc: Statically increase FLEE2 for Spirit of Land.
|
||||
val1: FLEE2
|
||||
|
||||
SC_DORAM_SVSP ()
|
||||
desc: Casts Silvervine Stem Spear when receiving Magic or Ranged damage after using Catnip Meteor for Spirit of Land.
|
||||
val1: Value to know it's active
|
||||
|
||||
SC_GVG_GIANT (SI_GVG_GIANT)
|
||||
desc: Instantly consumes HP/SP, increases Physical/Magic damage on player enemies by n%.
|
||||
val1: Amount of HP that are instantly consumed
|
||||
|
@ -1408,13 +1408,12 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
|
||||
}
|
||||
|
||||
if ((sce = sc->data[SC_TUNAPARTY]) && damage > 0) {
|
||||
clif_specialeffect(bl, 336, AREA);
|
||||
sce->val2 -= (int)cap_value(damage, INT_MIN, INT_MAX);
|
||||
if (sce->val2 >= 0)
|
||||
damage = 0;
|
||||
else
|
||||
damage = -sce->val2;
|
||||
if (/*(--sce->val3) <= 0 ||*/ (sce->val2 <= 0))
|
||||
if (sce->val2 <= 0)
|
||||
status_change_end(bl, SC_TUNAPARTY, INVALID_TIMER);
|
||||
}
|
||||
|
||||
@ -4276,15 +4275,26 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
|
||||
break;
|
||||
case SU_SCAROFTAROU:
|
||||
skillratio += -100 + 100 * skill_lv;
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLIFE))
|
||||
skillratio += skillratio * status_get_hp(src) / status_get_max_hp(src);
|
||||
break;
|
||||
case SU_PICKYPECK:
|
||||
case SU_PICKYPECK_DOUBLE_ATK:
|
||||
skillratio += 100 + 100 * skill_lv;
|
||||
if (status_get_max_hp(target) / 100 <= 50)
|
||||
if (status_get_hp(target) < status_get_max_hp(target) >> 1)
|
||||
skillratio *= 2;
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLIFE))
|
||||
skillratio += skillratio * status_get_hp(src) / status_get_max_hp(src);
|
||||
break;
|
||||
case SU_LUNATICCARROTBEAT:
|
||||
skillratio += 100 + 100 * skill_lv;
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLIFE))
|
||||
skillratio += skillratio * status_get_hp(src) / status_get_max_hp(src);
|
||||
break;
|
||||
case SU_SVG_SPIRIT:
|
||||
skillratio += 150 + 150 * skill_lv;
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLIFE))
|
||||
skillratio += skillratio * status_get_hp(src) / status_get_max_hp(src);
|
||||
break;
|
||||
}
|
||||
return skillratio;
|
||||
@ -4524,9 +4534,10 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s
|
||||
|
||||
if ((wd.flag&(BF_LONG|BF_MAGIC)) == BF_LONG) {
|
||||
if (sd && pc_checkskill(sd, SU_POWEROFLIFE) > 0) {
|
||||
if (pc_checkskill(sd, SU_SCAROFTAROU) == 5 && pc_checkskill(sd, SU_PICKYPECK) == 5 && pc_checkskill(sd, SU_ARCLOUSEDASH) == 5 && pc_checkskill(sd, SU_LUNATICCARROTBEAT) == 5) {
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, 20);
|
||||
RE_ALLATK_ADDRATE(wd, 20);
|
||||
if ((pc_checkskill(sd, SU_SCAROFTAROU) + pc_checkskill(sd, SU_PICKYPECK) + pc_checkskill(sd, SU_ARCLOUSEDASH) + pc_checkskill(sd, SU_LUNATICCARROTBEAT) +
|
||||
pc_checkskill(sd, SU_HISS) + pc_checkskill(sd, SU_POWEROFFLOCK) + pc_checkskill(sd, SU_SVG_SPIRIT)) > 19) {
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, 20);
|
||||
RE_ALLATK_ADDRATE(wd, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5730,9 +5741,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
ad.damage >>= 1;
|
||||
#endif
|
||||
break;
|
||||
case SU_SV_ROOTTWIST_ATK:
|
||||
ad.damage = 100;
|
||||
break;
|
||||
default: {
|
||||
if (sstatus->matk_max > sstatus->matk_min) {
|
||||
MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min));
|
||||
@ -6586,6 +6594,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
||||
else
|
||||
md.damage = 0;
|
||||
break;
|
||||
case SU_SV_ROOTTWIST_ATK:
|
||||
md.damage = 100;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nk&NK_SPLASHSPLIT) { // Divide ATK among targets
|
||||
|
@ -2000,6 +2000,7 @@ int map_quit(struct map_session_data *sd) {
|
||||
status_change_end(&sd->bl, SC_CBC, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EQC, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SV_ROOTTWIST, INVALID_TIMER);
|
||||
// Remove visuals effect from headgear
|
||||
status_change_end(&sd->bl, SC_MOONSTAR, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SUPER_STAR, INVALID_TIMER);
|
||||
|
@ -1038,7 +1038,7 @@ uint8 pc_isequip(struct map_session_data *sd,int n)
|
||||
return ITEM_EQUIP_ACK_FAIL;
|
||||
if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY])
|
||||
return ITEM_EQUIP_ACK_FAIL;
|
||||
if(item->equip && sd->sc.data[SC_KYOUGAKU])
|
||||
if(item->equip && (sd->sc.data[SC_KYOUGAKU] || sd->sc.data[SC_SUHIDE]))
|
||||
return ITEM_EQUIP_ACK_FAIL;
|
||||
|
||||
if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) {
|
||||
@ -5666,6 +5666,8 @@ int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 sk
|
||||
if (!idx) return 0;
|
||||
if (skill_db[idx]->cooldown[skill_lv - 1])
|
||||
cooldown = skill_db[idx]->cooldown[skill_lv - 1];
|
||||
if (skill_id == SU_TUNABELLY && pc_checkskill(sd, SU_SPIRITOFSEA))
|
||||
cooldown -= skill_get_time(SU_TUNABELLY, skill_lv);
|
||||
|
||||
ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == skill_id);
|
||||
if (i < cooldownlen) {
|
||||
@ -8257,8 +8259,8 @@ bool pc_setparam(struct map_session_data *sd,int type,int val)
|
||||
*------------------------------------------*/
|
||||
void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int type)
|
||||
{
|
||||
if (type) {
|
||||
if (hp)
|
||||
if (type&2) {
|
||||
if (hp || type&4)
|
||||
clif_heal(sd->fd,SP_HP,hp);
|
||||
if (sp)
|
||||
clif_heal(sd->fd,SP_SP,sp);
|
||||
|
@ -1469,6 +1469,15 @@
|
||||
export_constant(SC_DAILYSENDMAILCNT);
|
||||
export_constant(SC_DORAM_BUF_01);
|
||||
export_constant(SC_DORAM_BUF_02);
|
||||
export_constant(SC_HISS);
|
||||
export_constant(SC_NYANGGRASS);
|
||||
export_constant(SC_GROOMING);
|
||||
export_constant(SC_SHRIMPBLESSING);
|
||||
export_constant(SC_CHATTERING);
|
||||
export_constant(SC_DORAM_WALKSPEED);
|
||||
export_constant(SC_DORAM_MATK);
|
||||
export_constant(SC_DORAM_FLEE2);
|
||||
export_constant(SC_DORAM_SVSP);
|
||||
#ifdef RENEWAL
|
||||
export_constant(SC_EXTREMITYFIST2);
|
||||
#endif
|
||||
|
207
src/map/skill.c
207
src/map/skill.c
@ -421,6 +421,8 @@ unsigned short skill_dummy2skill_id(unsigned short skill_id) {
|
||||
return RL_R_TRIP;
|
||||
case NPC_MAXPAIN_ATK:
|
||||
return NPC_MAXPAIN;
|
||||
case SU_SV_ROOTTWIST_ATK:
|
||||
return SU_SV_ROOTTWIST;
|
||||
}
|
||||
return skill_id;
|
||||
}
|
||||
@ -483,7 +485,8 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
|
||||
hp *= 2;
|
||||
if (sd && ((skill = pc_checkskill(sd, SU_POWEROFSEA)) > 0)) {
|
||||
hp += hp * 10 / 100;
|
||||
if (pc_checkskill(sd, SU_TUNABELLY) == 5 && pc_checkskill(sd, SU_TUNAPARTY) == 5 && pc_checkskill(sd, SU_BUNCHOFSHRIMP) == 5 && pc_checkskill(sd, SU_FRESHSHRIMP) == 5)
|
||||
if ((pc_checkskill(sd, SU_TUNABELLY) + pc_checkskill(sd, SU_TUNAPARTY) + pc_checkskill(sd, SU_BUNCHOFSHRIMP) + pc_checkskill(sd, SU_FRESHSHRIMP) +
|
||||
pc_checkskill(sd, SU_GROOMING) + pc_checkskill(sd, SU_PURRING) + pc_checkskill(sd, SU_SHRIMPARTY)) > 19)
|
||||
hp += hp * 20 / 100;
|
||||
}
|
||||
break;
|
||||
@ -1930,7 +1933,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
status_change_end(bl, SC_C_MARKER, INVALID_TIMER);
|
||||
break;
|
||||
case SU_SCRATCH:
|
||||
sc_start2(src, bl, SC_BLEEDING, (skill_lv * 3), skill_lv, src->id, skill_get_time2(skill_id, skill_lv)); // TODO: What's the chance/time?
|
||||
sc_start2(src, bl, SC_BLEEDING, skill_lv * 10 + 70, skill_lv, src->id, skill_get_time(skill_id, skill_lv));
|
||||
break;
|
||||
case SU_SV_STEMSPEAR:
|
||||
sc_start2(src, bl, SC_BLEEDING, 10, skill_lv, src->id, skill_get_time2(skill_id, skill_lv));
|
||||
@ -1939,9 +1942,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
|
||||
if (skill_area_temp[3] == 1)
|
||||
sc_start(src, bl, SC_CURSE, 20, skill_lv, skill_get_time2(skill_id, skill_lv));
|
||||
break;
|
||||
//case SU_SCAROFTAROU:
|
||||
// sc_start(src, bl, SC_STUN, 10, skill_lv, skill_get_time2(skill_id, skill_lv)); // TODO: What's the chance/time?
|
||||
// break;
|
||||
case SU_SCAROFTAROU:
|
||||
sc_start(src, bl, SC_STUN, 10, skill_lv, skill_get_time2(skill_id, skill_lv)); //! TODO: What's the chance/time?
|
||||
break;
|
||||
case SU_LUNATICCARROTBEAT:
|
||||
if (skill_area_temp[3] == 1)
|
||||
sc_start(src, bl, SC_STUN, 20, skill_lv, skill_get_time2(skill_id, skill_lv));
|
||||
@ -2386,6 +2389,13 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
|
||||
}
|
||||
}
|
||||
|
||||
if (dstsd && !status_isdead(bl) && !(skill_id && skill_get_nk(skill_id)&NK_NO_DAMAGE)) {
|
||||
struct status_change *sc = status_get_sc(bl);
|
||||
|
||||
if (sc && sc->data[SC_DORAM_SVSP] && attack_type&(BF_MAGIC|BF_LONG))
|
||||
skill_castend_damage_id(bl, src, SU_SV_STEMSPEAR, (pc_checkskill(dstsd, SU_SV_STEMSPEAR) ? pc_checkskill(dstsd, SU_SV_STEMSPEAR) : 1), tick, 0);
|
||||
}
|
||||
|
||||
// Trigger counter-spells to retaliate against damage causing skills.
|
||||
if(dstsd && !status_isdead(bl) && dstsd->autospell2[0].id &&
|
||||
!(skill_id && skill_get_nk(skill_id)&NK_NO_DAMAGE))
|
||||
@ -2676,8 +2686,12 @@ short skill_blown(struct block_list* src, struct block_list* target, char count,
|
||||
dy = -diry[dir];
|
||||
}
|
||||
|
||||
if (tsc && tsc->data[SC_SU_STOOP]) // Any knockback will cancel it.
|
||||
status_change_end(target, SC_SU_STOOP, INVALID_TIMER);
|
||||
if (tsc) {
|
||||
if (tsc->data[SC_SU_STOOP]) // Any knockback will cancel it.
|
||||
status_change_end(target, SC_SU_STOOP, INVALID_TIMER);
|
||||
if (tsc->data[SC_SV_ROOTTWIST]) // Shouldn't move.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return unit_blown(target, dx, dy, count, flag); // Send over the proper flag
|
||||
}
|
||||
@ -3386,6 +3400,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
case KO_BAKURETSU:
|
||||
case GN_CRAZYWEED_ATK:
|
||||
case NC_MAGMA_ERUPTION:
|
||||
case SU_SV_ROOTTWIST_ATK:
|
||||
dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,DMG_SPLASH);
|
||||
break;
|
||||
case GN_FIRE_EXPANSION_ACID:
|
||||
@ -4179,6 +4194,16 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
|
||||
if (target->type == BL_PC)
|
||||
sc_start(src, target, SC_SITDOWN_FORCE, 100, skl->skill_lv, skill_get_time(skl->skill_id, skl->skill_lv));
|
||||
break;
|
||||
case SU_SV_ROOTTWIST_ATK: {
|
||||
struct status_change *tsc = status_get_sc(target);
|
||||
|
||||
if (tsc && tsc->data[SC_SV_ROOTTWIST]) {
|
||||
if (check_distance_bl(src, target, 32)) // Only damage if caster is within 32x32 area
|
||||
skill_attack(skl->type, src, target, target, skl->skill_id, skl->skill_lv, tick, skl->flag);
|
||||
skill_addtimerskill(src, tick + 1000, target->id, 0, 0, skl->skill_id, skl->skill_lv, skl->type, skl->flag);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
|
||||
break;
|
||||
@ -4857,9 +4882,15 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
case SU_BITE:
|
||||
skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
|
||||
if (status_get_lv(src) >= 30 && (rnd() % 100 < (int)(status_get_lv(src) / 30) + 10)) // TODO: Need activation chance.
|
||||
if (status_get_lv(src) > 29 && (rnd() % 100 < (int)((status_get_lv(src) / 30) * 10 + 10)))
|
||||
skill_addtimerskill(src, tick + skill_get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
|
||||
break;
|
||||
case SU_SVG_SPIRIT:
|
||||
skill_area_temp[1] = bl->id;
|
||||
map_foreachinpath(skill_attack_area, src->m, src->x, src->y, bl->x, bl->y,
|
||||
skill_get_splash(skill_id, skill_lv), skill_get_maxcount(skill_id, skill_lv), splash_target(src),
|
||||
skill_get_type(skill_id), src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
|
||||
break;
|
||||
|
||||
//Splash attack skills.
|
||||
case AS_GRIMTOOTH:
|
||||
@ -4941,7 +4972,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1);
|
||||
status_heal(src,heal,0,0);
|
||||
}
|
||||
if (skill_id == SU_SCRATCH && status_get_lv(src) >= 30 && (rnd() % 100 < (int)(status_get_lv(src) / 30) + 10)) // TODO: Need activation chance.
|
||||
if (skill_id == SU_SCRATCH && status_get_lv(src) > 29 && (rnd() % 100 < (int)((status_get_lv(src) / 30) * 10 + 10)))
|
||||
skill_addtimerskill(src, tick + skill_get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
|
||||
} else {
|
||||
int starget = BL_CHAR|BL_SKILL;
|
||||
@ -5971,11 +6002,16 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
break;
|
||||
|
||||
case SU_SCAROFTAROU:
|
||||
sc_start(src, bl, status_skill2sc(skill_id), 10, skill_lv, skill_get_time(skill_id, skill_lv)); // TODO: What's the activation chance for the Bite effect?
|
||||
case SU_SV_STEMSPEAR:
|
||||
if (skill_id == SU_SCAROFTAROU)
|
||||
sc_start(src, bl, status_skill2sc(skill_id), 10, skill_lv, skill_get_time(skill_id, skill_lv)); //! TODO: What's the activation chance for the Bite effect?
|
||||
else {
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLAND))
|
||||
sc_start(src, src, SC_DORAM_WALKSPEED, 100, 50, skill_get_time(SU_SPIRITOFLAND, 1));
|
||||
}
|
||||
skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
|
||||
if (status_get_lv(src) >= 30 && (rnd() % 100 < (int)(status_get_lv(src) / 30) + 10)) // TODO: Need activation chance.
|
||||
skill_addtimerskill(src, tick + skill_get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, (skill_id == SU_SV_STEMSPEAR) ? BF_MAGIC : BF_WEAPON, flag);
|
||||
if (status_get_lv(src) > 29 && (rnd() % 100 < (int)((status_get_lv(src) / 30) * 10 + 10)))
|
||||
skill_addtimerskill(src, tick + skill_get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, skill_get_type(skill_id), flag);
|
||||
break;
|
||||
|
||||
case 0:/* no skill - basic/normal attack */
|
||||
@ -6559,6 +6595,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
case PR_KYRIE:
|
||||
case MER_KYRIE:
|
||||
case SU_TUNAPARTY:
|
||||
case SU_GROOMING:
|
||||
case SU_CHATTERING:
|
||||
clif_skill_nodamage(bl,bl,skill_id,skill_lv,
|
||||
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
|
||||
break;
|
||||
@ -6682,11 +6720,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
sc_start(src, bl, type, skill_lv*20, skill_lv, skill_get_time2(skill_id, skill_lv)));
|
||||
break;
|
||||
|
||||
case SU_STOOP:
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
break;
|
||||
|
||||
case KN_AUTOCOUNTER:
|
||||
sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
||||
skill_addtimerskill(src,tick + 100,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,flag);
|
||||
@ -10806,26 +10839,70 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
break;
|
||||
|
||||
case SU_STOOP:
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
break;
|
||||
|
||||
case SU_SV_ROOTTWIST:
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
if (sd && status_get_class_(bl) == CLASS_BOSS) {
|
||||
clif_skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0);
|
||||
break;
|
||||
}
|
||||
if (tsc->count && tsc->data[type]) // Refresh the status only if it's already active.
|
||||
sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
else {
|
||||
sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLAND))
|
||||
sc_start(src, src, SC_DORAM_MATK, 100, sd->status.base_level, skill_get_time(SU_SPIRITOFLAND, 1));
|
||||
skill_addtimerskill(src, tick + 1000, bl->id, 0, 0, SU_SV_ROOTTWIST_ATK, skill_lv, skill_get_type(SU_SV_ROOTTWIST_ATK), flag);
|
||||
}
|
||||
break;
|
||||
|
||||
case SU_TUNABELLY:
|
||||
{
|
||||
unsigned int heal;
|
||||
unsigned int heal = 0;
|
||||
|
||||
if (dstmd && (dstmd->mob_id == MOBID_EMPERIUM || status_get_class_(bl) == CLASS_BATTLEFIELD))
|
||||
heal = 0;
|
||||
else {
|
||||
else if (status_get_hp(bl) != status_get_max_hp(bl))
|
||||
heal = ((2 * skill_lv - 1) * 10) * status_get_max_hp(bl) / 100;
|
||||
status_heal(bl, heal, 0, 0);
|
||||
}
|
||||
status_heal(bl, heal, 0, 1|2|4);
|
||||
|
||||
clif_skill_nodamage(src, bl, skill_id, heal, 1);
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case SU_BUNCHOFSHRIMP:
|
||||
if (sd == NULL || sd->status.party_id == 0 || flag&1)
|
||||
clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)));
|
||||
else if (sd)
|
||||
case SU_HISS:
|
||||
case SU_PURRING:
|
||||
case SU_SHRIMPARTY:
|
||||
case SU_MEOWMEOW:
|
||||
if (sd == NULL || sd->status.party_id == 0 || flag&1) {
|
||||
int duration = skill_get_time(skill_id, skill_lv);
|
||||
|
||||
if (skill_id == SU_BUNCHOFSHRIMP && pc_checkskill(sd, SU_SPIRITOFSEA))
|
||||
duration += skill_get_time2(SU_BUNCHOFSHRIMP, skill_lv);
|
||||
clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, duration));
|
||||
} else if (sd) {
|
||||
if (skill_id == SU_SHRIMPARTY)
|
||||
sc_start(src, bl, SC_SHRIMPBLESSING, 100, skill_lv, skill_get_time2(skill_id, skill_lv));
|
||||
party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
|
||||
}
|
||||
break;
|
||||
|
||||
case SU_POWEROFFLOCK:
|
||||
if (flag&1) {
|
||||
sc_start(src, bl, SC_FEAR, 100, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
sc_start(src, bl, SC_FREEZE, 100, skill_lv, skill_get_time2(skill_id, skill_lv)); //! TODO: What's the duration?
|
||||
} else {
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
if (battle_config.skill_wall_check)
|
||||
map_foreachinshootrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
||||
else
|
||||
map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -11091,7 +11168,6 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
|
||||
case GN_WALLOFTHORN:
|
||||
case SC_ESCAPE:
|
||||
case SU_CN_POWDERING:
|
||||
case SU_SV_ROOTTWIST:
|
||||
ud->skillx = target->x;
|
||||
ud->skilly = target->y;
|
||||
ud->skilltimer = tid;
|
||||
@ -11647,8 +11723,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
case MH_XENO_SLASHER:
|
||||
case LG_KINGS_GRACE:
|
||||
case RL_B_TRAP:
|
||||
case SU_CN_POWDERING:
|
||||
case SU_SV_ROOTTWIST:
|
||||
flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
|
||||
case GS_GROUNDDRIFT: //Ammo should be deleted right away.
|
||||
case GN_WALLOFTHORN:
|
||||
@ -11695,16 +11769,31 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
||||
break;
|
||||
|
||||
case SU_CN_POWDERING:
|
||||
case SU_NYANGGRASS:
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFLAND)) {
|
||||
if (skill_id == SU_CN_POWDERING)
|
||||
sc_start(src, src, SC_DORAM_FLEE2, 100, sd->status.base_level / 12, skill_get_time(SU_SPIRITOFLAND, 1));
|
||||
else
|
||||
sc_start(src, src, SC_DORAM_MATK, 100, sd->status.base_level, skill_get_time(SU_SPIRITOFLAND, 1));
|
||||
}
|
||||
flag |= 1;
|
||||
skill_unitsetting(src, skill_id, skill_lv, x, y, 0);
|
||||
break;
|
||||
|
||||
case WZ_METEOR:
|
||||
case SU_CN_METEOR: {
|
||||
int area = skill_get_splash(skill_id, skill_lv);
|
||||
short tmpx = 0, tmpy = 0;
|
||||
if (sd && skill_id == SU_CN_METEOR) {
|
||||
short item_idx = pc_search_inventory(sd, ITEMID_CATNIP_FRUIT);
|
||||
|
||||
if (item_idx >= 0) {
|
||||
pc_delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_CONSUME);
|
||||
flag |= 1;
|
||||
}
|
||||
if (pc_checkskill(sd, SU_SPIRITOFLAND))
|
||||
sc_start(src, src, SC_DORAM_SVSP, 100, 100, skill_get_time(SU_SPIRITOFLAND, 1));
|
||||
}
|
||||
for (i = 1; i <= skill_get_time(skill_id, skill_lv)/skill_get_unit_interval(skill_id); i++) {
|
||||
// Creates a random Cell in the Splash Area
|
||||
@ -12230,16 +12319,25 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
skill_addtimerskill(src,gettick()+500,0,x,y,skill_id,skill_lv,BF_MISC,flag);
|
||||
}
|
||||
break;
|
||||
|
||||
case SU_LOPE:
|
||||
if (map[src->m].flag.noteleport && !(map[src->m].flag.battleground || map_flag_gvg2(src->m))) {
|
||||
x = src->x;
|
||||
y = src->y;
|
||||
}
|
||||
clif_skill_nodamage(src, src, SU_LOPE, skill_lv, 1);
|
||||
if (!map_count_oncell(src->m, x, y, BL_PC|BL_NPC|BL_MOB, 0) && path_search(NULL, src->m, src->x, src->y, x, y, 1, CELL_CHKNOREACH)) {
|
||||
clif_slide(src, x, y);
|
||||
unit_movepos(src, x, y, 1, 0);
|
||||
{
|
||||
uint8 dir = map_calc_dir(src, x, y);
|
||||
|
||||
// Fails on noteleport maps, except for GvG and BG maps
|
||||
if (map[src->m].flag.noteleport && !(map[src->m].flag.battleground || map_flag_gvg2(src->m))) {
|
||||
x = src->x;
|
||||
y = src->y;
|
||||
} else if (dir%2) { // Diagonal
|
||||
x += dirx[dir] * (skill_lv * 4) / 3;
|
||||
y += diry[dir] * (skill_lv * 4) / 3;
|
||||
} else {
|
||||
x += dirx[dir] * skill_lv * 2;
|
||||
y += diry[dir] * skill_lv * 2;
|
||||
}
|
||||
|
||||
clif_skill_nodamage(src, src, skill_id, skill_lv, 1);
|
||||
if (!map_count_oncell(src->m, x, y, BL_PC|BL_NPC|BL_MOB, 0) && map_getcell(src->m, x, y, CELL_CHKREACH) && unit_movepos(src, x, y, 1, 0))
|
||||
clif_blown(src);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -13383,6 +13481,11 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, un
|
||||
sc_start(ss, bl, type, 100, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
|
||||
break;
|
||||
|
||||
case UNT_NYANGGRASS:
|
||||
if (!sce)
|
||||
sc_start(ss, bl, type, 100, sg->skill_lv, skill_get_time(sg->skill_id, sg->skill_lv));
|
||||
break;
|
||||
|
||||
case UNT_GD_LEADERSHIP:
|
||||
case UNT_GD_GLORYWOUNDS:
|
||||
case UNT_GD_SOULCOLD:
|
||||
@ -14124,28 +14227,6 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
|
||||
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,SD_ANIMATION|SD_SPLASH),
|
||||
1,sg->skill_id,sg->skill_lv,DMG_SKILL);
|
||||
break;
|
||||
|
||||
case UNT_SV_ROOTTWIST:
|
||||
if (status_bl_has_mode(bl,MD_STATUS_IMMUNE))
|
||||
break;
|
||||
if (tsc) {
|
||||
if (!sg->val2) {
|
||||
int sec = skill_get_time(sg->skill_id, sg->skill_lv);
|
||||
|
||||
if (sc_start2(ss, bl, type, 100, sg->skill_lv, sg->group_id, sec)) {
|
||||
const struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL;
|
||||
|
||||
if(td)
|
||||
sec = DIFF_TICK(td->tick, tick);
|
||||
clif_fixpos(bl);
|
||||
sg->val2 = bl->id;
|
||||
} else // Couldn't trap it?
|
||||
sec = 7000;
|
||||
sg->limit = DIFF_TICK(tick, sg->tick) + sec;
|
||||
} else if (tsc->data[type] && bl->id == sg->val2)
|
||||
skill_attack(skill_get_type(SU_SV_ROOTTWIST_ATK), ss, &unit->bl, bl, SU_SV_ROOTTWIST_ATK, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (bl->type == BL_MOB && ss != bl)
|
||||
@ -14293,6 +14374,7 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, unsigned int tick)
|
||||
case LG_KINGS_GRACE:
|
||||
case NC_STEALTHFIELD:
|
||||
case NC_NEUTRALBARRIER:
|
||||
case SU_NYANGGRASS:
|
||||
if (sce)
|
||||
status_change_end(bl, type, INVALID_TIMER);
|
||||
break;
|
||||
@ -20563,7 +20645,6 @@ int skill_disable_check(struct status_change *sc, uint16 skill_id)
|
||||
case KO_YAMIKUMO:
|
||||
case RA_WUGDASH:
|
||||
case RA_CAMOUFLAGE:
|
||||
case SU_HIDE:
|
||||
if( sc->data[status_skill2sc(skill_id)] )
|
||||
return 1;
|
||||
break;
|
||||
@ -20603,6 +20684,8 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) {
|
||||
* @return True:If unit can be moved, False:If check on flags are met or unit cannot be moved.
|
||||
**/
|
||||
static bool skill_check_unit_movepos(uint8 check_flag, struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath) {
|
||||
struct status_change *sc;
|
||||
|
||||
nullpo_retr(false, bl);
|
||||
|
||||
if (check_flag&1 && map[bl->m].flag.battleground)
|
||||
@ -20612,6 +20695,10 @@ static bool skill_check_unit_movepos(uint8 check_flag, struct block_list *bl, sh
|
||||
if (check_flag&4 && map_flag_gvg2(bl->m))
|
||||
return false;
|
||||
|
||||
sc = status_get_sc(bl);
|
||||
if (sc && sc->data[SC_SV_ROOTTWIST])
|
||||
return false;
|
||||
|
||||
return unit_movepos(bl, dst_x, dst_y, easy, checkpath);
|
||||
}
|
||||
|
||||
|
@ -1789,6 +1789,21 @@ enum e_skill {
|
||||
SU_TUNAPARTY,
|
||||
SU_BUNCHOFSHRIMP,
|
||||
SU_FRESHSHRIMP,
|
||||
SU_CN_METEOR2,
|
||||
SU_LUNATICCARROTBEAT2,
|
||||
SU_SOULATTACK,
|
||||
SU_POWEROFFLOCK,
|
||||
SU_SVG_SPIRIT,
|
||||
SU_HISS,
|
||||
SU_NYANGGRASS,
|
||||
SU_GROOMING,
|
||||
SU_PURRING,
|
||||
SU_SHRIMPARTY,
|
||||
SU_SPIRITOFLIFE,
|
||||
SU_MEOWMEOW,
|
||||
SU_SPIRITOFLAND,
|
||||
SU_CHATTERING,
|
||||
SU_SPIRITOFSEA,
|
||||
|
||||
HLIF_HEAL = 8001,
|
||||
HLIF_AVOID,
|
||||
@ -2061,7 +2076,7 @@ enum s_skill_unit_id {
|
||||
UNT_FIRE_RAIN,
|
||||
|
||||
UNT_CATNIPPOWDER,
|
||||
UNT_SV_ROOTTWIST,
|
||||
UNT_NYANGGRASS,
|
||||
|
||||
/**
|
||||
* Guild Auras
|
||||
|
187
src/map/status.c
187
src/map/status.c
@ -852,16 +852,22 @@ void initChangeTables(void)
|
||||
add_sc( SU_SCRATCH , SC_BLEEDING );
|
||||
set_sc( SU_STOOP , SC_SU_STOOP , SI_SU_STOOP , SCB_NONE );
|
||||
add_sc( SU_SV_STEMSPEAR , SC_BLEEDING );
|
||||
set_sc( SU_CN_POWDERING , SC_CATNIPPOWDER , SI_CATNIPPOWDER , SCB_WATK|SCB_SPEED|SCB_REGEN );
|
||||
set_sc( SU_CN_POWDERING , SC_CATNIPPOWDER , SI_CATNIPPOWDER , SCB_WATK|SCB_MATK|SCB_SPEED|SCB_REGEN );
|
||||
add_sc( SU_CN_METEOR , SC_CURSE );
|
||||
set_sc_with_vfx( SU_SV_ROOTTWIST , SC_SV_ROOTTWIST , SI_SV_ROOTTWIST , SCB_NONE );
|
||||
//add_sc( SU_SCAROFTAROU , SC_STUN );
|
||||
set_sc_with_vfx( SU_SV_ROOTTWIST, SC_SV_ROOTTWIST , SI_SV_ROOTTWIST , SCB_NONE );
|
||||
set_sc( SU_SCAROFTAROU , SC_BITESCAR , SI_BITESCAR , SCB_NONE );
|
||||
set_sc( SU_ARCLOUSEDASH , SC_ARCLOUSEDASH , SI_ARCLOUSEDASH , SCB_AGI|SCB_SPEED );
|
||||
add_sc( SU_LUNATICCARROTBEAT , SC_STUN );
|
||||
set_sc( SU_TUNAPARTY , SC_TUNAPARTY , SI_TUNAPARTY , SCB_NONE );
|
||||
set_sc( SU_BUNCHOFSHRIMP , SC_SHRIMP , SI_SHRIMP , SCB_BATK|SCB_MATK );
|
||||
set_sc( SU_FRESHSHRIMP , SC_FRESHSHRIMP , SI_FRESHSHRIMP , SCB_NONE );
|
||||
set_sc( SU_HISS , SC_HISS , SI_HISS , SCB_FLEE2 );
|
||||
set_sc( SU_NYANGGRASS , SC_NYANGGRASS , SI_NYANGGRASS , SCB_DEF|SCB_MDEF );
|
||||
set_sc( SU_GROOMING , SC_GROOMING , SI_GROOMING , SCB_FLEE );
|
||||
add_sc( SU_PURRING , SC_GROOMING );
|
||||
add_sc( SU_SHRIMPARTY , SC_FRESHSHRIMP );
|
||||
add_sc( SU_MEOWMEOW , SC_CHATTERING );
|
||||
set_sc( SU_CHATTERING , SC_CHATTERING , SI_CHATTERING , SCB_WATK|SCB_MATK );
|
||||
|
||||
/* Storing the target job rather than simply SC_SPIRIT simplifies code later on */
|
||||
SkillStatusChangeTable[skill_get_index(SL_ALCHEMIST)] = (sc_type)MAPID_ALCHEMIST,
|
||||
@ -1083,6 +1089,7 @@ void initChangeTables(void)
|
||||
|
||||
/* Summoners status icons */
|
||||
StatusIconChangeTable[SC_SPRITEMABLE] = SI_SPRITEMABLE;
|
||||
StatusIconChangeTable[SC_SHRIMPBLESSING] = SI_PROTECTIONOFSHRIMP;
|
||||
StatusIconChangeTable[SC_DORAM_BUF_01] = SI_DORAM_BUF_01;
|
||||
StatusIconChangeTable[SC_DORAM_BUF_02] = SI_DORAM_BUF_02;
|
||||
|
||||
@ -1268,7 +1275,11 @@ void initChangeTables(void)
|
||||
// RODEX
|
||||
StatusChangeFlagTable[SC_DAILYSENDMAILCNT] |= SCB_NONE;
|
||||
|
||||
// Doram Buffs
|
||||
// Summoner
|
||||
StatusChangeFlagTable[SC_SHRIMPBLESSING] |= SCB_REGEN;
|
||||
StatusChangeFlagTable[SC_DORAM_WALKSPEED] |= SCB_SPEED;
|
||||
StatusChangeFlagTable[SC_DORAM_MATK] |= SCB_MATK;
|
||||
StatusChangeFlagTable[SC_DORAM_FLEE2] |= SCB_FLEE2;
|
||||
StatusChangeFlagTable[SC_DORAM_BUF_01] |= SCB_REGEN;
|
||||
StatusChangeFlagTable[SC_DORAM_BUF_02] |= SCB_REGEN;
|
||||
|
||||
@ -1315,6 +1326,7 @@ void initChangeTables(void)
|
||||
StatusDisplayType[SC_C_MARKER] = BL_PC;
|
||||
StatusDisplayType[SC_ANTI_M_BLAST] = BL_PC;
|
||||
StatusDisplayType[SC_SPRITEMABLE] = BL_PC;
|
||||
StatusDisplayType[SC_SV_ROOTTWIST] = BL_PC;
|
||||
|
||||
// Costumes
|
||||
StatusDisplayType[SC_MOONSTAR] = BL_PC;
|
||||
@ -1817,7 +1829,8 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
||||
* @param bl: Object to heal [PC|MOB|HOM|MER|ELEM]
|
||||
* @param hhp: How much HP to heal
|
||||
* @param hsp: How much SP to heal
|
||||
* @param flag: Whether it's Forced(&1) or gives HP/SP(&2) heal effect \n
|
||||
* @param flag: Whether it's Forced(&1), gives HP/SP(&2) heal effect,
|
||||
* or gives HP(&4) heal effect with 0 heal
|
||||
* Forced healing overrides heal impedement statuses (Berserk)
|
||||
* @return hp+sp
|
||||
*/
|
||||
@ -1868,7 +1881,7 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag)
|
||||
sp = status->max_sp - status->sp;
|
||||
}
|
||||
|
||||
if(!sp && !hp)
|
||||
if(!sp && !hp && !(flag&4))
|
||||
return 0;
|
||||
|
||||
status->hp += hp;
|
||||
@ -1884,7 +1897,7 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag)
|
||||
|
||||
// Send HP update to client
|
||||
switch(bl->type) {
|
||||
case BL_PC: pc_heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break;
|
||||
case BL_PC: pc_heal((TBL_PC*)bl,hp,sp,flag); break;
|
||||
case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break;
|
||||
case BL_HOM: hom_heal((TBL_HOM*)bl); break;
|
||||
case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break;
|
||||
@ -2087,7 +2100,7 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
|
||||
if (flag == 1 && sc->data[SC_CURSEDCIRCLE_TARGET] && skill_id == MO_ABSORBSPIRITS) // Absorb Spirits fails to go through
|
||||
return false;
|
||||
|
||||
if (skill_id != RK_REFRESH && sc->opt1 && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { // Stuned/Frozen/etc
|
||||
if (skill_id != RK_REFRESH && skill_id != SU_GROOMING && sc->opt1 && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { // Stuned/Frozen/etc
|
||||
if (flag != 1) // Can't cast, casted stuff can't damage.
|
||||
return false;
|
||||
if (!(skill_get_inf(skill_id)&INF_GROUND_SKILL))
|
||||
@ -2291,7 +2304,7 @@ int status_check_visibility(struct block_list *src, struct block_list *target)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (((tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK)) || tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_STEALTHFIELD]) && !is_boss && !is_detector)
|
||||
if (((tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK)) || tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_STEALTHFIELD] || tsc->data[SC_SUHIDE]) && !is_boss && !is_detector)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -2420,7 +2433,7 @@ unsigned int status_weapon_atk(struct weapon_atk wa, struct map_session_data *sd
|
||||
float str = sd->base_status.str;
|
||||
int weapon_atk_bonus = 0;
|
||||
|
||||
if (wa.range > 3)
|
||||
if (wa.range > 3 && !pc_checkskill(sd, SU_SOULATTACK))
|
||||
str = sd->base_status.dex;
|
||||
if (sd->bonus.weapon_atk_rate)
|
||||
weapon_atk_bonus = wa.atk * sd->bonus.weapon_atk_rate / 100;
|
||||
@ -2911,8 +2924,9 @@ static int status_get_hpbonus(struct block_list *bl, enum e_status_bonus type) {
|
||||
bonus += 1000;
|
||||
if (pc_checkskill(sd, SU_POWEROFSEA) > 0) {
|
||||
bonus += 1000;
|
||||
if (pc_checkskill(sd, SU_TUNABELLY) == 5 && pc_checkskill(sd, SU_TUNAPARTY) == 5 && pc_checkskill(sd, SU_BUNCHOFSHRIMP) == 5 && pc_checkskill(sd, SU_FRESHSHRIMP) == 5)
|
||||
bonus += 2000;
|
||||
if ((pc_checkskill(sd, SU_TUNABELLY) + pc_checkskill(sd, SU_TUNAPARTY) + pc_checkskill(sd, SU_BUNCHOFSHRIMP) + pc_checkskill(sd, SU_FRESHSHRIMP) +
|
||||
pc_checkskill(sd, SU_GROOMING) + pc_checkskill(sd, SU_PURRING) + pc_checkskill(sd, SU_SHRIMPARTY)) > 19)
|
||||
bonus += 2000;
|
||||
}
|
||||
#ifndef HP_SP_TABLES
|
||||
if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99)
|
||||
@ -3047,8 +3061,9 @@ static int status_get_spbonus(struct block_list *bl, enum e_status_bonus type) {
|
||||
bonus += 100;
|
||||
if (pc_checkskill(sd, SU_POWEROFSEA) > 0) {
|
||||
bonus += 100;
|
||||
if (pc_checkskill(sd, SU_TUNABELLY) == 5 && pc_checkskill(sd, SU_TUNAPARTY) == 5 && pc_checkskill(sd, SU_BUNCHOFSHRIMP) == 5 && pc_checkskill(sd, SU_FRESHSHRIMP) == 5)
|
||||
bonus += 200;
|
||||
if ((pc_checkskill(sd, SU_TUNABELLY) + pc_checkskill(sd, SU_TUNAPARTY) + pc_checkskill(sd, SU_BUNCHOFSHRIMP) + pc_checkskill(sd, SU_FRESHSHRIMP) +
|
||||
pc_checkskill(sd, SU_GROOMING) + pc_checkskill(sd, SU_PURRING) + pc_checkskill(sd, SU_SHRIMPARTY)) > 19)
|
||||
bonus += 200;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3880,6 +3895,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
|
||||
if (pc_checkskill(sd, SU_POWEROFLIFE) > 0)
|
||||
base_status->hit += 20;
|
||||
|
||||
if ((skill = pc_checkskill(sd, SU_SOULATTACK)) > 0)
|
||||
base_status->rhw.range += skill_get_range2(&sd->bl, SU_SOULATTACK, skill, true);
|
||||
|
||||
// ----- FLEE CALCULATION -----
|
||||
|
||||
// Absolute modifiers from passive skills
|
||||
@ -4143,7 +4161,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
|
||||
clif_skillinfoblock(sd);
|
||||
|
||||
// If the skill is learned, the status is infinite.
|
||||
if( (skill = pc_checkskill(sd,SU_SPRITEMABLE)) > 0 )
|
||||
if( (skill = pc_checkskill(sd,SU_SPRITEMABLE)) > 0 && !sd->sc.data[SC_SPRITEMABLE] )
|
||||
sc_start(&sd->bl, &sd->bl, SC_SPRITEMABLE, 100, 1, -1);
|
||||
|
||||
calculating = 0;
|
||||
@ -4377,12 +4395,15 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt)
|
||||
void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen)
|
||||
{
|
||||
struct map_session_data *sd;
|
||||
struct status_change *sc;
|
||||
int val, skill, reg_flag;
|
||||
|
||||
if( !(bl->type&BL_REGEN) || !regen )
|
||||
return;
|
||||
|
||||
sd = BL_CAST(BL_PC,bl);
|
||||
sc = status_get_sc(bl);
|
||||
|
||||
val = 1 + (status->vit/5) + (status->max_hp/200);
|
||||
|
||||
if( sd && sd->hprecov_rate != 100 )
|
||||
@ -4423,6 +4444,9 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct
|
||||
if( (skill=pc_checkskill(sd,WM_LESSON)) > 0 )
|
||||
val += 3 + 3 * skill;
|
||||
|
||||
if (sc && sc->count && sc->data[SC_SHRIMPBLESSING])
|
||||
val += 150 / 100;
|
||||
|
||||
sregen->sp = cap_value(val, 0, SHRT_MAX);
|
||||
|
||||
// Skill-related recovery (only when sit)
|
||||
@ -4963,7 +4987,8 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
|
||||
if (sd->bonus.ematk > 0)
|
||||
status->matk_min += sd->bonus.ematk;
|
||||
if (pc_checkskill(sd, SU_POWEROFLAND) > 0) {
|
||||
if (pc_checkskill(sd, SU_SV_STEMSPEAR) == 5 && pc_checkskill(sd, SU_CN_POWDERING) == 5 && pc_checkskill(sd, SU_CN_METEOR) == 5 && pc_checkskill(sd, SU_SV_ROOTTWIST) == 5)
|
||||
if ((pc_checkskill(sd, SU_SV_STEMSPEAR) + pc_checkskill(sd, SU_CN_POWDERING) + pc_checkskill(sd, SU_CN_METEOR) + pc_checkskill(sd, SU_SV_ROOTTWIST) +
|
||||
pc_checkskill(sd, SU_CHATTERING) + pc_checkskill(sd, SU_MEOWMEOW) + pc_checkskill(sd, SU_NYANGGRASS)) > 19)
|
||||
status->matk_min += status->matk_min * 20 / 100;
|
||||
}
|
||||
}
|
||||
@ -4996,9 +5021,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
|
||||
variance += status->lhw.matk * status->lhw.wlv / 10;
|
||||
}
|
||||
|
||||
if (sc && sc->data[SC_CATNIPPOWDER])
|
||||
wMatk -= wMatk * sc->data[SC_CATNIPPOWDER]->val2 / 100;
|
||||
|
||||
status->matk_min += wMatk - variance;
|
||||
status->matk_max += wMatk + variance;
|
||||
}
|
||||
@ -5903,6 +5925,8 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
|
||||
watk += sc->data[SC_FLASHCOMBO]->val2;
|
||||
if (sc->data[SC_CATNIPPOWDER])
|
||||
watk -= watk * sc->data[SC_CATNIPPOWDER]->val2 / 100;
|
||||
if (sc->data[SC_CHATTERING])
|
||||
watk += sc->data[SC_CHATTERING]->val2;
|
||||
|
||||
return (unsigned short)cap_value(watk,0,USHRT_MAX);
|
||||
}
|
||||
@ -5952,6 +5976,12 @@ static unsigned short status_calc_ematk(struct block_list *bl, struct status_cha
|
||||
matk += sc->data[SC_MTF_MATK2]->val1;
|
||||
if(sc->data[SC_2011RWC_SCROLL])
|
||||
matk += 30;
|
||||
if (sc->data[SC_CATNIPPOWDER])
|
||||
matk -= matk * sc->data[SC_CATNIPPOWDER]->val2 / 100;
|
||||
if (sc->data[SC_CHATTERING])
|
||||
matk += sc->data[SC_CHATTERING]->val2;
|
||||
if (sc->data[SC_DORAM_MATK])
|
||||
matk += sc->data[SC_DORAM_MATK]->val1;
|
||||
|
||||
return (unsigned short)cap_value(matk,0,USHRT_MAX);
|
||||
}
|
||||
@ -6211,6 +6241,8 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
|
||||
// flee -= (flee * sc->data[SC_C_MARKER]->val3) / 100;
|
||||
if(sc->data[SC_HEAT_BARREL])
|
||||
flee -= sc->data[SC_HEAT_BARREL]->val4;
|
||||
if (sc->data[SC_GROOMING])
|
||||
flee += sc->data[SC_GROOMING]->val2;
|
||||
|
||||
return (short)cap_value(flee,1,SHRT_MAX);
|
||||
}
|
||||
@ -6233,6 +6265,10 @@ static signed short status_calc_flee2(struct block_list *bl, struct status_chang
|
||||
flee2 += sc->data[SC_WHISTLE]->val3*10;
|
||||
if(sc->data[SC__UNLUCKY])
|
||||
flee2 -= flee2 * sc->data[SC__UNLUCKY]->val2 / 100;
|
||||
if (sc->data[SC_HISS])
|
||||
flee2 += sc->data[SC_HISS]->val2;
|
||||
if (sc->data[SC_DORAM_FLEE2])
|
||||
flee2 += sc->data[SC_DORAM_FLEE2]->val1;
|
||||
|
||||
return (short)cap_value(flee2,10,SHRT_MAX);
|
||||
}
|
||||
@ -6259,6 +6295,12 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
|
||||
if(sc->data[SC_STEELBODY])
|
||||
return 90;
|
||||
#endif
|
||||
if (sc->data[SC_NYANGGRASS]) {
|
||||
if (bl->type == BL_PC)
|
||||
return 0;
|
||||
else
|
||||
return def >>= 1;
|
||||
}
|
||||
if(sc->data[SC_DEFSET])
|
||||
return sc->data[SC_DEFSET]->val1;
|
||||
|
||||
@ -6421,6 +6463,12 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc,
|
||||
if(sc->data[SC_STEELBODY])
|
||||
return 90;
|
||||
#endif
|
||||
if (sc->data[SC_NYANGGRASS]) {
|
||||
if (bl->type == BL_PC)
|
||||
return 0;
|
||||
else
|
||||
return mdef >>= 1;
|
||||
}
|
||||
if(sc->data[SC_MDEFSET])
|
||||
return sc->data[SC_MDEFSET]->val1;
|
||||
|
||||
@ -6642,6 +6690,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
|
||||
val = max( val, 25 );
|
||||
if (sc->data[SC_ARCLOUSEDASH])
|
||||
val = max(val, sc->data[SC_ARCLOUSEDASH]->val3);
|
||||
if( sc->data[SC_DORAM_WALKSPEED] )
|
||||
val = max(val, sc->data[SC_DORAM_WALKSPEED]->val1);
|
||||
|
||||
// !FIXME: official items use a single bonus for this [ultramage]
|
||||
if( sc->data[SC_SPEEDUP0] ) // Temporary item-based speedup
|
||||
@ -8677,6 +8727,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
if (sc->data[SC_DEVOTION] || sc->data[SC_WHITEIMPRISON])
|
||||
return 0;
|
||||
break;
|
||||
case SC_GROOMING:
|
||||
case SC_CHATTERING:
|
||||
if (sc->data[type])
|
||||
return 0;
|
||||
|
||||
case SC_WEDDING:
|
||||
case SC_XMAS:
|
||||
@ -9038,23 +9092,25 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
status_change_end(bl, SC_BLIND, INVALID_TIMER);
|
||||
break;
|
||||
case SC_KINGS_GRACE:
|
||||
status_change_end(bl,SC_POISON,INVALID_TIMER);
|
||||
status_change_end(bl,SC_BLIND,INVALID_TIMER);
|
||||
status_change_end(bl,SC_FREEZE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_STONE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_STUN,INVALID_TIMER);
|
||||
status_change_end(bl,SC_SLEEP,INVALID_TIMER);
|
||||
status_change_end(bl,SC_BLEEDING,INVALID_TIMER);
|
||||
status_change_end(bl,SC_CURSE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_CONFUSION,INVALID_TIMER);
|
||||
status_change_end(bl,SC_HALLUCINATION,INVALID_TIMER);
|
||||
status_change_end(bl,SC_SILENCE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_BURNING,INVALID_TIMER);
|
||||
status_change_end(bl,SC_CRYSTALIZE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_FREEZING,INVALID_TIMER);
|
||||
status_change_end(bl,SC_DEEPSLEEP,INVALID_TIMER);
|
||||
// Fall through
|
||||
case SC_GROOMING:
|
||||
status_change_end(bl,SC_STUN,INVALID_TIMER);
|
||||
status_change_end(bl,SC_FREEZE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_STONE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_SLEEP,INVALID_TIMER);
|
||||
status_change_end(bl,SC_SILENCE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_BLEEDING,INVALID_TIMER);
|
||||
status_change_end(bl,SC_POISON,INVALID_TIMER);
|
||||
status_change_end(bl,SC_FEAR,INVALID_TIMER);
|
||||
status_change_end(bl,SC_MANDRAGORA,INVALID_TIMER);
|
||||
status_change_end(bl,SC_CRYSTALIZE,INVALID_TIMER);
|
||||
status_change_end(bl,SC_FREEZING,INVALID_TIMER);
|
||||
break;
|
||||
case SC_2011RWC_SCROLL:
|
||||
status_change_end(bl,SC_FOOD_STR_CASH,INVALID_TIMER);
|
||||
@ -10847,11 +10903,16 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
case SC_CATNIPPOWDER:
|
||||
val2 = 50; // WATK%, MATK%
|
||||
val3 = 25 * val1; // Move speed reduction
|
||||
if (bl->type == BL_PC && pc_checkskill(sd, SU_SPIRITOFLAND))
|
||||
val4 = status_get_lv(src) / 12;
|
||||
break;
|
||||
case SC_BITESCAR:
|
||||
val2 = 2 * val1; // MHP% damage
|
||||
val4 = tick / 1000;
|
||||
tick_time = 1000;
|
||||
case SC_BITESCAR: {
|
||||
const struct status_data *b_status = status_get_base_status(src); // Base Status
|
||||
|
||||
val2 = (status_get_max_hp(bl) * (val1 + (b_status->dex / 25))) / status_get_max_hp(bl); // MHP% damage
|
||||
tick_time = 1000;
|
||||
val4 = tick / tick_time;
|
||||
}
|
||||
break;
|
||||
case SC_ARCLOUSEDASH:
|
||||
val2 = 15 + 5 * val1; // AGI
|
||||
@ -10862,15 +10923,59 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
case SC_SHRIMP:
|
||||
val2 = 10; // BATK%, MATK%
|
||||
break;
|
||||
case SC_FRESHSHRIMP:
|
||||
val4 = tick / (10000 - ((val1 - 1) * 1000));
|
||||
tick_time = 10000 - ((val1 - 1) * 1000);
|
||||
if (val4 <= 0) // Prevents a negeative value from happening
|
||||
val4 = 0;
|
||||
case SC_FRESHSHRIMP: {
|
||||
int min = 0, max = 0;
|
||||
|
||||
#ifdef RENEWAL
|
||||
min = max = status_base_matk(src, status, status_get_lv(src));
|
||||
if (status->rhw.matk > 0) {
|
||||
int wMatk, variance;
|
||||
|
||||
wMatk = status->rhw.matk;
|
||||
variance = wMatk * status->rhw.wlv / 10;
|
||||
min += wMatk - variance;
|
||||
max += wMatk + variance;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sd && sd->right_weapon.overrefine > 0) {
|
||||
min++;
|
||||
max += sd->right_weapon.overrefine - 1;
|
||||
}
|
||||
|
||||
val2 += min + 178; // Heal
|
||||
if (max > min)
|
||||
val2 += rnd() % (max - min); // Heal
|
||||
|
||||
if (sd) {
|
||||
if (pc_checkskill(sd, SU_POWEROFSEA)) {
|
||||
val2 += val2 * 10 / 100;
|
||||
if ((pc_checkskill(sd, SU_TUNABELLY) + pc_checkskill(sd, SU_TUNAPARTY) + pc_checkskill(sd, SU_BUNCHOFSHRIMP) + pc_checkskill(sd, SU_FRESHSHRIMP) +
|
||||
pc_checkskill(sd, SU_GROOMING) + pc_checkskill(sd, SU_PURRING) + pc_checkskill(sd, SU_SHRIMPARTY)) > 19)
|
||||
val2 += val2 * 20 / 100;
|
||||
}
|
||||
if (pc_checkskill(sd, SU_SPIRITOFSEA))
|
||||
val2 *= 2; // Doubles HP
|
||||
}
|
||||
tick_time = 10000 - ((val1 - 1) * 1000);
|
||||
val4 = tick / tick_time;
|
||||
}
|
||||
break;
|
||||
case SC_TUNAPARTY:
|
||||
val2 = (status->max_hp * (val1 * 10) / 100); // %Max HP to absorb
|
||||
//val3 = 6 + val1; // Hits !TODO: Does it have hits too?
|
||||
val2 = (status->max_hp * (val1 * 10) / 100); // Max HP% to absorb
|
||||
if (sd && pc_checkskill(sd, SU_SPIRITOFSEA))
|
||||
val2 <<= 1; // Double the shield life
|
||||
break;
|
||||
case SC_HISS:
|
||||
val2 = 50; // Perfect Dodge
|
||||
sc_start(src, bl, SC_DORAM_WALKSPEED, 100, 50, skill_get_time2(SU_HISS, val1));
|
||||
break;
|
||||
case SC_GROOMING:
|
||||
val2 = 100; // Flee
|
||||
break;
|
||||
case SC_CHATTERING:
|
||||
val2 = 100; // eATK, eMATK
|
||||
sc_start(src, bl, SC_DORAM_WALKSPEED, 100, 50, skill_get_time2(SU_CHATTERING, val1));
|
||||
break;
|
||||
case SC_SWORDCLAN:
|
||||
case SC_ARCWANDCLAN:
|
||||
@ -12078,7 +12183,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
break;
|
||||
case SC_NEUTRALBARRIER_MASTER:
|
||||
case SC_STEALTHFIELD_MASTER:
|
||||
case SC_SV_ROOTTWIST:
|
||||
if( sce->val2 ) {
|
||||
struct skill_unit_group* group = skill_id2group(sce->val2);
|
||||
sce->val2 = 0;
|
||||
@ -13319,8 +13423,9 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
break;
|
||||
case SC_FRESHSHRIMP:
|
||||
if (--(sce->val4) >= 0) {
|
||||
status_heal(bl, status->max_hp * 4 / 100, 0, 2);
|
||||
status_heal(bl, sce->val2, 0, 3);
|
||||
sc_timer_next((10000 - ((sce->val1 - 1) * 1000)) + tick, status_change_timer, bl->id, data);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case SC_DORAM_BUF_01:
|
||||
|
@ -804,9 +804,22 @@ typedef enum sc_type {
|
||||
|
||||
SC_DAILYSENDMAILCNT,
|
||||
|
||||
SC_DORAM_BUF_01,
|
||||
SC_DORAM_BUF_01,
|
||||
SC_DORAM_BUF_02,
|
||||
|
||||
/**
|
||||
* Summoner - Extended
|
||||
*/
|
||||
SC_HISS,
|
||||
SC_NYANGGRASS,
|
||||
SC_GROOMING,
|
||||
SC_SHRIMPBLESSING,
|
||||
SC_CHATTERING,
|
||||
SC_DORAM_WALKSPEED,
|
||||
SC_DORAM_MATK,
|
||||
SC_DORAM_FLEE2,
|
||||
SC_DORAM_SVSP,
|
||||
|
||||
#ifdef RENEWAL
|
||||
SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user