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:
Aleos 2017-07-05 19:40:35 -04:00 committed by GitHub
parent 689a3ff9b3
commit 5f7a143d3e
16 changed files with 538 additions and 136 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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