Ver código fonte

Merge branch 'master' into feature/lapine_synthesis_and_upgrade

Cydh 3 anos atrás
pai
commit
4a2a2ab483

+ 1 - 0
db/import-tmpl/item_db.yml

@@ -478,6 +478,7 @@ Header:
 #    Gender: Male
 #    Locations:
 #      Armor: true
+#    ArmorLevel: 1
 #    Refineable: true
 #    EquipScript: |
 #      sc_start SC_WEDDING,INFINITE_TICK,0;

+ 1 - 0
db/mercenary_db.txt

@@ -36,6 +36,7 @@
 2351,MER_CHEPET,Chepet,83,9815,234,2,1100,1300,60,60,85,90,71,43,85,105,10,12,0,6,47,150,1080,780,180
 2378,MER_ANTLER_SCARABA,Antler Scaraba,136,30000,1,1,1418,1828,155,102,23,99,59,129,137,45,10,12,1,4,42,200,504,624,360
 2937,M_LOKI,Loki's Shadow,145,1215600,1,2,1835,2279,15,89,76,66,90,55,189,22,10,12,1,7,20,175,800,750,300
+3087,M_NYDHOG,Guardian's Alter Ego,160,215000,1,2,1835,444,15,89,76,66,90,55,189,22,10,12,1,7,20,175,800,750,300
 
 // Normal Mercenaries
 6017,MER_ARCHER01,Mina,20,256,200,10,170,85,7,5,1,16,5,1,28,8,10,0,0,7,20,150,700,432,300

+ 3 - 1
db/mob_chat_db.yml

@@ -107,11 +107,13 @@ Body:
   - Id: 37
     Dialog: Is there anyone waiting for you outside of here?  Throw them all away, you are mine now...
   - Id: 38
-    Dialog: Discard your life and stay confined here.  You will yearn for freedom in captivity !!
+    Dialog: Discard your life and stay confined here. You will yearn for freedom in captivity !!
   - Id: 39
     Dialog: How much will the outside world change if you stay here in solitude for one thousand years?
   - Id: 40
     Dialog: Yes! Yearn for your freedom from this confined place, your captivity here will be permanent !!
+  - Id: 41
+    Dialog: Arrival!
 
 Footer:
   Imports:

+ 12 - 0
db/pre-re/skill_db.yml

@@ -16336,6 +16336,18 @@ Body:
     MaxLevel: 1
     Flags:
       ShowScale: true
+  - Id: 721
+    Name: NPC_WIDEWEB
+    Description: Wide Web
+    MaxLevel: 1
+  - Id: 722
+    Name: NPC_WIDESUCK
+    Description: Wide Suck
+    MaxLevel: 1
+  - Id: 724
+    Name: NPC_FIRESTORM
+    Description: Fire Storm
+    MaxLevel: 3
   - Id: 725
     Name: NPC_REVERBERATION
     Description: Reverberation 2

+ 18 - 18
db/re/instance_db.yml

@@ -198,18 +198,18 @@ Body:
       Map: 1@glast
       X: 367
       Y: 304
-#  - Id: 22
-#    Name: Wave Mode - Forest
-#    Enter:
-#      Map: 1@def01
-#      X: 50
-#      Y: 21
-#  - Id: 23
-#    Name: Wave Mode - Sky
-#    Enter:
-#      Map: 1@def02
-#      X: 29
-#      Y: 35
+  - Id: 22
+    Name: Wave Mode - Forest
+    Enter:
+      Map: 1@def01
+      X: 50
+      Y: 21
+  - Id: 23
+    Name: Wave Mode - Sky
+    Enter:
+      Map: 1@def02
+      X: 29
+      Y: 35
   - Id: 24
     Name: Nightmarish Jitterbug
     Enter:
@@ -231,12 +231,12 @@ Body:
       Map: 1@rev
       X: 26
       Y: 181
-#  - Id: 27
-#    Name: Temple of the Demon God
-#    Enter:
-#      Map: 1@eom
-#      X: 101
-#      Y: 16
+  - Id: 27
+    Name: Temple of the Demon God
+    Enter:
+      Map: 1@eom
+      X: 101
+      Y: 16
   - Id: 28
     Name: Central Laboratory
     Enter:

+ 43 - 42
db/re/item_noequip.txt

@@ -19,6 +19,7 @@
 // 1024 - restricted in zone 6
 // 2048 - restricted in zone 7
 // 4096 - restricted in zone 8
+// 8192 - restricted in zone 9
 //
 // Passing negative value as flag will unset the flag instead.
 //
@@ -240,45 +241,45 @@
 //----------------------------------------------------------------------------
 // WoE:TE Items - Only can be used in WoE:TE Castles (All except &16)
 //----------------------------------------------------------------------------
-1299,8175	// TE_Woe_Katar
-1319,8175	// TE_Woe_Axe
-1399,8175	// TE_Woe_Two_Handed_Axe
-1437,8175	// TE_Woe_Pike
-1495,8175	// TE_Woe_Lance
-1591,8175	// TE_Woe_Book
-1667,8175	// TE_Woe_Staff
-1834,8175	// TE_Woe_Fist
-1932,8175	// TE_Woe_Guitar
-1987,8175	// TE_Woe_Rope
-2019,8175	// TE_Woe_Two_Hand_Staff
-2178,8175	// TE_Woe_Buckler
-2179,8175	// TE_Woe_Shield
-2180,8175	// TE_Woe_Magic_Guard
-2496,8175	// TE_Woe_Shoes
-2497,8175	// TE_Woe_Boots
-2498,8175	// TE_Woe_Magic_Sandal
-2944,8175	// TE_Ring_Of_Protection
-2945,8175	// TE_Ring_Of_Rage
-2946,8175	// TE_Ring_Of_Defiance
-11557,8175	// TE_White_Potion
-11558,8175	// TE_White_Slim_Potion
-13083,8175	// TE_Woe_Knife
-13117,8175	// TE_Woe_Pistol
-13184,8175	// TE_Woe_Rifle
-13185,8175	// TE_Woe_Gatling
-13186,8175	// TE_Woe_Shotgun
-13187,8175	// TE_Woe_Grenade
-13317,8175	// TE_Woe_Huuma
-13439,8175	// TE_Woe_Sword
-15062,8175	// TE_Woe_Coat
-15063,8175	// TE_Woe_Chain_Mail
-15064,8175	// TE_Woe_Mage_Coat
-16025,8175	// TE_Woe_Mace
-18118,8175	// TE_Woe_Bow
-18732,8175	// TE_Woe_Cap
-18733,8175	// TE_Woe_Bone_Helm
-18734,8175	// TE_Woe_Magic_Eyes
-20702,8175	// TE_Woe_Muffler
-20703,8175	// TE_Woe_Manteau
-20704,8175	// TE_Woe_Magic_Manteau
-21006,8175	// TE_Woe_Two_Hand_Sword
+1299,16367	// TE_Woe_Katar
+1319,16367	// TE_Woe_Axe
+1399,16367	// TE_Woe_Two_Handed_Axe
+1437,16367	// TE_Woe_Pike
+1495,16367	// TE_Woe_Lance
+1591,16367	// TE_Woe_Book
+1667,16367	// TE_Woe_Staff
+1834,16367	// TE_Woe_Fist
+1932,16367	// TE_Woe_Guitar
+1987,16367	// TE_Woe_Rope
+2019,16367	// TE_Woe_Two_Hand_Staff
+2178,16367	// TE_Woe_Buckler
+2179,16367	// TE_Woe_Shield
+2180,16367	// TE_Woe_Magic_Guard
+2496,16367	// TE_Woe_Shoes
+2497,16367	// TE_Woe_Boots
+2498,16367	// TE_Woe_Magic_Sandal
+2944,16367	// TE_Ring_Of_Protection
+2945,16367	// TE_Ring_Of_Rage
+2946,16367	// TE_Ring_Of_Defiance
+11557,16367	// TE_White_Potion
+11558,16367	// TE_White_Slim_Potion
+13083,16367	// TE_Woe_Knife
+13117,16367	// TE_Woe_Pistol
+13184,16367	// TE_Woe_Rifle
+13185,16367	// TE_Woe_Gatling
+13186,16367	// TE_Woe_Shotgun
+13187,16367	// TE_Woe_Grenade
+13317,16367	// TE_Woe_Huuma
+13439,16367	// TE_Woe_Sword
+15062,16367	// TE_Woe_Coat
+15063,16367	// TE_Woe_Chain_Mail
+15064,16367	// TE_Woe_Mage_Coat
+16025,16367	// TE_Woe_Mace
+18118,16367	// TE_Woe_Bow
+18732,16367	// TE_Woe_Cap
+18733,16367	// TE_Woe_Bone_Helm
+18734,16367	// TE_Woe_Magic_Eyes
+20702,16367	// TE_Woe_Muffler
+20703,16367	// TE_Woe_Manteau
+20704,16367	// TE_Woe_Magic_Manteau
+21006,16367	// TE_Woe_Two_Hand_Sword

Diferenças do arquivo suprimidas por serem muito extensas
+ 657 - 1171
db/re/mob_db.yml


+ 78 - 0
db/re/mob_skill_db.txt

@@ -11260,6 +11260,84 @@
 3074,Time Holder@NPC_SUMMONSLAVE,attack,196,5,1000,700,10000,no,self,slavele,0,2917,,,,,,
 3074,Time Holder@NPC_SUMMONSLAVE,idle,196,5,1000,700,10000,no,self,slavele,0,2917,,,,,,
 
+// Temple demon god instance
+3088,MM_BRINARANEA_BABY@NPC_WATERATTACK,attack,184,1,5000,0,10000,yes,target,always,0,,,,,,,
+3088,MM_BRINARANEA_BABY@MG_COLDBOLT,chase,14,1,1000,0,3000,yes,target,always,0,,,,,,,
+3088,MM_BRINARANEA_BABY@NPC_WIDEWEB,attack,721,1,3000,0,20000,yes,self,always,0,,,,,,,
+3088,MM_BRINARANEA_BABY@NPC_WIDEWEB,chase,721,1,3000,0,20000,yes,self,always,0,,,,,,,
+3089,MM_LOCO_KASA@NPC_SELFDESTRUCTION,attack,173,1,500,0,5000,yes,self,myhpltmaxrate,25,,,,,,,
+3089,MM_LOCO_KASA@NPC_FIREATTACK,attack,186,1,2500,0,8000,yes,target,always,0,,,,,,,
+3090,MM_LOCO_SALAMANDER@NPC_FIREATTACK,attack,186,1,5000,0,10000,yes,target,always,0,,,,,,,
+3090,MM_LOCO_SALAMANDER@MG_FIREBOLT,chase,19,1,1000,0,3000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@NPC_WATERATTACK,chase,184,10,3000,1000,10000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@NPC_WATERATTACK,attack,184,10,3000,1000,10000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@MG_COLDBOLT,chase,14,10,2500,1000,15000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@MG_COLDBOLT,attack,14,10,2500,1000,15000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@MG_FROSTDIVER,chase,15,40,1500,300,18000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@MG_FROSTDIVER,attack,15,40,1500,300,18000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@WZ_QUAGMIRE,chase,92,5,3500,250,10000,yes,target,always,0,,,,,,,
+3091,MM_BRINARANEA@WZ_QUAGMIRE,attack,92,5,3500,250,10000,yes,target,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@NPC_FIREATTACK,chase,186,10,3000,1000,10000,yes,target,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@NPC_FIREATTACK,attack,186,10,3000,1000,10000,yes,target,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@MG_FIREBOLT,chase,19,10,2500,1000,15000,yes,target,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@MG_FIREBOLT,attack,19,10,2500,1000,15000,yes,target,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@NPC_FIREBREATH,chase,654,5,2000,500,8000,yes,target,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@NPC_FIREBREATH,attack,654,5,2000,500,8000,yes,target,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@NPC_WIDESILENCE,chase,663,5,10000,1000,30000,yes,self,always,0,,,,,,,
+3092,MM_MUSPELLSKOLL@NPC_WIDESILENCE,attack,663,5,10000,1000,30000,yes,self,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_BLOODDRAIN,chase,199,1,2500,0,60000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_BLOODDRAIN,attack,199,1,2500,0,60000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_DARKCROSS,chase,338,10,2000,0,90000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_DARKCROSS,attack,338,10,2000,0,90000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_BLEEDING,chase,660,5,3500,0,180000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_BLEEDING,attack,660,5,3500,0,180000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_HOLYATTACK,chase,189,10,2000,500,15000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_HOLYATTACK,attack,189,10,2000,500,15000,yes,target,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_EARTHQUAKE,chase,653,5,1000,3000,300000,yes,self,myhpltmaxrate,50,,,,,,,
+3096,MM_MOROCC_KID@NPC_EARTHQUAKE,attack,653,5,1000,3000,300000,yes,self,myhpltmaxrate,50,,,,,,,
+3096,MM_MOROCC_KID@NPC_SLOWCAST,chase,672,5,1000,1000,180000,yes,self,always,0,,,,,,,
+3096,MM_MOROCC_KID@NPC_SLOWCAST,attack,672,5,1000,1000,180000,yes,self,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_BLOODDRAIN,chase,199,1,2500,0,60000,yes,target,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_BLOODDRAIN,attack,199,1,2500,0,60000,yes,target,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_GRANDDARKNESS,chase,339,10,2000,0,120000,yes,self,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_GRANDDARKNESS,attack,339,10,2000,0,120000,yes,self,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_CRITICALWOUND,chase,673,5,3500,0,180000,yes,target,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_CRITICALWOUND,attack,673,5,3500,0,180000,yes,target,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_DARKNESSATTACK,chase,190,10,2500,500,30000,yes,target,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_DARKNESSATTACK,attack,190,10,2500,500,30000,yes,target,always,0,,,,,,,
+3097,MM_MOROCC_ADT@NPC_EARTHQUAKE,chase,653,5,1000,1000,300000,yes,self,myhpltmaxrate,50,,,,,,,
+3097,MM_MOROCC_ADT@NPC_EARTHQUAKE,attack,653,5,1000,1000,300000,yes,self,myhpltmaxrate,50,,,,,,,
+3097,MM_MOROCC_ADT@NPC_EVILLAND,chase,670,10,1000,1000,180000,yes,self,myhpltmaxrate,70,,,,,,,
+3097,MM_MOROCC_ADT@NPC_EVILLAND,attack,670,10,1000,1000,180000,yes,self,myhpltmaxrate,70,,,,,,,
+3097,MM_MOROCC_ADT@NPC_VAMPIRE_GIFT,chase,679,5,3000,500,300000,yes,self,myhpltmaxrate,80,,,,,,,
+3097,MM_MOROCC_ADT@NPC_VAMPIRE_GIFT,attack,679,5,3000,500,300000,yes,self,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@NPC_DRAGONFEAR,chase,659,10,10000,0,600000,no,self,myhpltmaxrate,30,,,,,,,
+3098,MM_MOROCC_ORIGIN@NPC_DRAGONFEAR,attack,659,10,10000,0,600000,no,self,myhpltmaxrate,30,,,,,,,
+3098,MM_MOROCC_ORIGIN@NPC_EARTHQUAKE,chase,653,10,10000,2000,180000,yes,self,myhpltmaxrate,40,,,,,,,
+3098,MM_MOROCC_ORIGIN@NPC_EARTHQUAKE,attack,653,10,10000,2000,180000,yes,self,myhpltmaxrate,40,,,,,,,
+3098,MM_MOROCC_ORIGIN@WZ_METEOR,chase,83,5,10000,800,60000,yes,target,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@WZ_METEOR,attack,83,5,10000,800,60000,yes,target,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@MG_FIREBOLT,chase,19,10,10000,300,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@MG_FIREBOLT,attack,19,10,10000,300,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@MG_FROSTDIVER,chase,15,40,10000,1000,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@MG_FROSTDIVER,attack,15,40,10000,1000,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@WZ_JUPITEL,chase,84,28,10000,1000,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3098,MM_MOROCC_ORIGIN@WZ_JUPITEL,attack,84,28,10000,1000,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3099,MM_MOROCC_REST@NPC_PULSESTRIKE,chase,661,5,10000,800,60000,yes,self,myhpltmaxrate,40,,,,,,,
+3099,MM_MOROCC_REST@NPC_PULSESTRIKE,attack,661,5,10000,800,60000,yes,self,myhpltmaxrate,40,,,,,,,
+3099,MM_MOROCC_REST@NPC_HELLJUDGEMENT,chase,662,5,10000,800,35000,yes,self,myhpltmaxrate,60,,,,,,,
+3099,MM_MOROCC_REST@NPC_HELLJUDGEMENT,attack,662,5,10000,800,35000,yes,self,myhpltmaxrate,60,,,,,,,
+3099,MM_MOROCC_REST@MG_STONECURSE,chase,16,10,10000,1000,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3099,MM_MOROCC_REST@MG_STONECURSE,attack,16,10,10000,1000,20000,yes,target,myhpltmaxrate,80,,,,,,,
+3099,MM_MOROCC_REST@NPC_WIDESLEEP,chase,668,5,10000,700,35000,yes,self,myhpltmaxrate,60,,,,,,,
+3099,MM_MOROCC_REST@NPC_WIDESLEEP,attack,668,5,10000,700,35000,yes,self,myhpltmaxrate,60,,,,,,,
+3099,MM_MOROCC_REST@NPC_VAMPIRE_GIFT,chase,679,9,10000,1000,50000,yes,self,myhpltmaxrate,50,,,,,,,
+3099,MM_MOROCC_REST@NPC_VAMPIRE_GIFT,attack,679,9,10000,1000,50000,yes,self,myhpltmaxrate,50,,,,,,,
+3099,MM_MOROCC_REST@NPC_WIDESOULDRAIN,chase,680,10,10000,1000,50000,yes,self,myhpltmaxrate,50,,,,,,,
+3099,MM_MOROCC_REST@NPC_WIDESOULDRAIN,attack,680,10,10000,1000,50000,yes,self,myhpltmaxrate,50,,,,,,,
+3099,MM_MOROCC_REST@NPC_EVILLAND,chase,670,10,10000,1000,50000,yes,self,myhpltmaxrate,50,,,,,,,
+3099,MM_MOROCC_REST@NPC_EVILLAND,attack,670,10,10000,1000,50000,yes,self,myhpltmaxrate,50,,,,,,,
+
 // Jitterbug instance
 3108,Jitterbug@NPC_WIDESILENCE,attack,663,5,3000,1000,10000,yes,self,always,0,,,,,,,
 3108,Jitterbug@NPC_LEX_AETERNA,attack,727,3,2000,2000,10000,yes,self,always,0,,,,,,,

+ 26 - 0
db/re/quest_db.yml

@@ -4068,6 +4068,15 @@ Body:
         Count: 3
       - Mob: MM_MANA_YELLOW
         Count: 3
+  - Id: 7596
+    Title: Qualifications of the Guests
+    Drops:
+      - Mob: MM_GB_MOROCC_1
+        Item: Heart_of_Soul
+        Rate: 10000
+      - Mob: MM_GB_MOROCC_4
+        Item: Sheenas_Soul
+        Rate: 10000
   - Id: 7597
     Title: Fall of the False God
   - Id: 7598
@@ -4079,6 +4088,23 @@ Body:
   - Id: 7600
     Title: Promising Tomorrow
     TimeLimit: +23h
+  - Id: 7601
+    Title: Temple of the Demon God Phase 1
+    Targets:
+      - Mob: MM_BRINARANEA
+        Count: 1
+  - Id: 7602
+    Title: Temple of the Demon God Phase 1 Completed
+  - Id: 7603
+    Title: Temple of the Demon God Phase 2
+    Targets:
+      - Mob: MM_MUSPELLSKOLL
+        Count: 1
+  - Id: 7604
+    Title: Temple of the Demon God Phase 2 Completed
+  - Id: 7605
+    Title: Guardian's Blessing
+    TimeLimit: +3h
   - Id: 7606
     Title: Phantasmagorika Excavator Recruitment
   - Id: 7607

+ 56 - 0
db/re/skill_db.yml

@@ -16888,6 +16888,62 @@ Body:
         Time: 27500
       - Level: 5
         Time: 32500
+  - Id: 721
+    Name: NPC_WIDEWEB
+    Description: Wide Web
+    MaxLevel: 1
+    TargetType: Self
+    DamageFlags:
+      NoDamage: true
+      Splash: true
+    Flags:
+      IsNpc: true
+      ShowScale: true
+    Range: 1
+    Hit: Single
+    HitCount: 1
+    SplashArea: 7
+    Duration2: 10000
+  - Id: 722
+    Name: NPC_WIDESUCK
+    Description: Wide Suck
+    MaxLevel: 1
+    Type: Misc
+    TargetType: Ground
+    DamageFlags:
+      Splash: true
+      IgnoreFlee: true
+    Flags:
+      IsNpc: true
+    Range: 1
+    Hit: Single
+    HitCount: 1
+    SplashArea: 13
+    Duration1: 3000
+  - Id: 724
+    Name: NPC_FIRESTORM
+    Description: Fire Storm
+    MaxLevel: 3
+    Type: Magic
+    TargetType: Self
+    DamageFlags:
+      NoDamage: true
+      Splash: true
+    Flags:
+      IsNpc: true
+    Range: 1
+    Hit: Multi_Hit
+    HitCount:
+      - Level: 1
+        Count: 1
+      - Level: 2
+        Count: 3
+      - Level: 3
+        Count: 5
+    Element: Fire
+    SplashArea: 3
+    Knockback: 3
+    Duration1: 10000
   - Id: 725
     Name: NPC_REVERBERATION
     Description: Reverberation 2

+ 15 - 0
db/re/skill_nocast_db.txt

@@ -19,6 +19,7 @@
 // 1024 - cannot be used in zone 6 maps
 // 2048 - cannot be used in zone 7 maps
 // 4096 - cannot be used in zone 8 maps
+// 8192 - cannot be used in zone 9 maps
 //
 // Example:
 // 8,6  // Endure cannot be used in PvP and GvG maps (2+4)
@@ -229,3 +230,17 @@
 409,4096 // WE_CALLPARENT
 410,4096 // WE_CALLBABY
 5063,4096	//WE_CALLALLFAMILY
+
+//----------------------------------------------------------------------------
+// Zone 9 - Wave Mode
+//----------------------------------------------------------------------------
+26,8192	//AL_TELEPORT
+87,8192	//WZ_ICEWALL
+197,8192	//NPC_EMOTION
+219,8192	//RG_INTIMIDATE
+405,8192	//PF_SPIDERWEB
+474,8192	//NPC_EMOTION_ON
+674,8192	//NPC_EXPULSION
+2284,8192	//SC_FATALMENACE
+2294,8192	//SC_IGNORANCE
+2300,8192	//SC_DIMENSIONDOOR

+ 81 - 29
doc/script_commands.txt

@@ -143,7 +143,7 @@ to move away from their specified spawn region.
 
 Monster name is the name the monsters will have on screen, and has no relation
 whatsoever to their names anywhere else. It's the mob id that counts, which
-identifies monster record in 'mob_db.txt' database of monsters. If the mob name
+identifies monster record in 'mob_db.yml' database of monsters. If the mob name
 is given as "--ja--", the 'japanese name' field from the monster database is
 used, (which, in rAthena, actually contains an English name) if it's "--en--",
 it's the 'english name' from the monster database (which contains an uppercase
@@ -168,6 +168,7 @@ player who triggers the script must be within 'trigger' range for the event to
 work.
 
 There are two optional fields for monster size and AI.
+Natural enemies for AI monsters are normal monsters.
 
 <mob size> can be:
 	Size_Small	(0)
@@ -182,6 +183,7 @@ There are two optional fields for monster size and AI.
 	AI_ZANZOU	(4)		(Kagerou/Oboro skill)
 	AI_LEGION	(5)		(Sera skill)
 	AI_FAW		(6)		(Mechanic skill)
+	AI_WAVEMODE	(7)		Normal monsters will ignore attack from AI_WAVEMODE monsters
 
 Alternately, a monster spawned using 'boss_monster' instead of 'monster' is able
 to be detected on the map with the SC_BOSSMAPINFO status (used by Convex Mirror).
@@ -246,7 +248,7 @@ it's facing 5.)
 Sprite ID is the sprite number or constant used to display this particular NPC.
 You may also use a monster's ID instead to display a monster sprite for this NPC.
 It is possible to use a job sprite as well, but you must first define it as a
-monster sprite in 'mob_avail.txt', a full description on how to do this is not
+monster sprite in 'mob_avail.yml', a full description on how to do this is not
 in the scope of this manual.
 A '-1' Sprite ID will make the NPC invisible (and unclickable).
 A '111' Sprite ID will make an NPC which does not have a sprite, but is still
@@ -2954,7 +2956,7 @@ recreate these items perfectly if they are destroyed. Here's what you get:
 @inventorylist_option_id5[]        - fifth array of random option IDs
 @inventorylist_option_value5[]     - fifth array of random option values
 @inventorylist_option_parameter5[] - fifth array of random option parameters
-@inventorylist_tradable            - Returns if an item is tradable or not (Pass item_trade.txt, bound, and rental restrictions).
+@inventorylist_tradable            - Returns if an item is tradable or not (Pass item_db.yml, bound, and rental restrictions).
 @inventorylist_favorite            - Returns if an item is favorite or not
 
 This could be handy to save/restore a character's inventory, since no other
@@ -3085,7 +3087,7 @@ Examples
 *mergeitem2({"<item name>"{,<char_id>}});
 
 Merge all stackable items that separated by GUID flags
-(either by flag 4 item_flag.txt or GUID  in item_group).
+(UniqueId in item_db or in item_group).
 If no item ID/name given, all possible items in player's inventory will be merged.
 
 ---------------------------------------
@@ -3435,7 +3437,7 @@ of his/her guild, or, if a guild ID is specified, of that guild.
 *getcastlename("<map name>")
 
 This function returns the name of the castle when given the map name for that
-castle. The data is read from 'db/castle_db.txt'.
+castle. The data is read from 'db/castle_db.yml'.
 
 ---------------------------------------
 
@@ -3611,6 +3613,12 @@ $@MobDrop_item[] is a global temporary number array which contains the
 $@MobDrop_rate[] is a global temporary number array which contains the
                  drop percentages of each item. (1 = .01%)
 
+$@MobDrop_nosteal[] is a global temporary number array which contains the
+                 StealProtected flag of each item. (default false)
+
+$@MobDrop_randomopt[] is a global temporary number array which contains the
+                 random option group ID of each item. (default 0)
+
 $@MobDrop_count is the number of item drops found.
 
 Be sure to use $@MobDrop_count to go through the arrays, and not
@@ -4781,7 +4789,7 @@ eggs, and may hatch from either, although, I'm not sure what kind of a mess will
 this really cause.
 
 'getitem3' is advance version of 'getitem2' that also use Item Random Option as additional values.
-<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.txt
+<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.yml
 <RandomValueArray> : Array variable of item random option's value.
 <RandomParamArray> : Array variable of item random option's param.
 
@@ -4823,7 +4831,7 @@ some cases cannot be traded or stored.
 For a list of bound types see 'getitembound'.
 
 'getitembound3' is advance version of 'getitembound2' that also use Item Random Option as additional values.
-<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.txt
+<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.yml
 <RandomValueArray> : Array variable of item random option's value.
 <RandomParamArray> : Array variable of item random option's param.
 
@@ -4889,7 +4897,7 @@ in <time> seconds and be automatically deleted. See 'rentitem' for further detai
 See 'getitem2' for an explanation of the expanded parameters.
 
 'rentitem3' is advance version of 'rentitem2' that also use Item Random Option as additional values.
-<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.txt
+<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.yml
 <RandomValueArray> : Array variable of item random option's value.
 <RandomParamArray> : Array variable of item random option's param.
 
@@ -4902,8 +4910,8 @@ Example to get Crimson Weapon with Ghost property:
 
 ---------------------------------------
 
-*makeitem <item id>,<amount>,"<map name>",<X>,<Y>;
-*makeitem "<item name>",<amount>,"<map name>",<X>,<Y>;
+*makeitem <item id>,<amount>,"<map name>",<X>,<Y>{,<canShowEffect>};
+*makeitem "<item name>",<amount>,"<map name>",<X>,<Y>{,<canShowEffect>};
 
 This command will create an item on the specified cell of a map.
 
@@ -4914,13 +4922,14 @@ given amount, not multiple stacks of 1.
 Like 'getitem', it also accepts an 'english name' field from the database and creates
 Apples if the name isn't found.
 If the map name is given as "this", the map the invoking character is on will be used.
+If <canShowEffect> flag is set to true, it will show a pillar effect on the ground when dropped, depending on the item database's DropEffect flag.
 
 ---------------------------------------
 
-*makeitem2 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>;
-*makeitem2 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>;
-*makeitem3 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>;
-*makeitem3 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>;
+*makeitem2 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<canShowEffect>};
+*makeitem2 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<canShowEffect>};
+*makeitem3 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>{,<canShowEffect>};
+*makeitem3 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>{,<canShowEffect>};
 
 This command will create an item on the specified cell of a map. See 'makeitem' for
 further details.
@@ -4928,7 +4937,7 @@ further details.
 See 'getitem2' for an explanation of the expanded parameters.
 
 'makeitem3' is advance version of 'makeitem2' that also use Item Random Option as additional values.
-<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.txt
+<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.yml
 <RandomValueArray> : Array variable of item random option's value.
 <RandomParamArray> : Array variable of item random option's param.
 
@@ -5014,7 +5023,7 @@ This command will remove a specified amount of items from the invoking/target ch
 See 'getitem2' for an explanation of the expanded parameters.
 
 'delitem3' is advance version of 'delitem2' that also use Item Random Option as criteria.
-<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.txt
+<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.yml
 <RandomValueArray> : Array variable of item random option's value.
 <RandomParamArray> : Array variable of item random option's param.
 
@@ -5108,7 +5117,7 @@ other parameters that the invoking character has in the inventory.
 See 'getitem2' for an explanation of the expanded parameters.
 
 'countitem3' is advance version of 'countitem2' that also use Item Random Option as criteria.
-<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.txt
+<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.yml
 <RandomValueArray> : Array variable of item random option's value.
 <RandomParamArray> : Array variable of item random option's param.
 
@@ -5149,7 +5158,7 @@ other parameters that the invoking character has in the inventory.
 See 'getitem2' for an explanation of the expanded parameters.
 
 'rentalcountitem3' is advance version of 'rentalcountitem2' that also use Item Random Option as criteria.
-<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.txt
+<RandomIDArray>    : Array variable of ID for item random option, see db/[pre-]re/item_randomopt_db.yml
 <RandomValueArray> : Array variable of item random option's value.
 <RandomParamArray> : Array variable of item random option's param.
 
@@ -5177,7 +5186,7 @@ Example:
 *groupranditem <group id>{,<sub_group>};
 
 Returns the item_id of a random item picked from the group specified. The
-different groups and their group number are specified in 'db/(pre-)re/item_group_db.txt'.
+different groups and their group number are specified in 'db/(pre-)re/item_group_db.yml'.
 
 When used in conjunction with other functions, you can get a random item. For
 example, for a random pet lure:
@@ -5195,7 +5204,7 @@ More info, see doc/item_group.txt.
 
 Similar to the above example, this command allows players to obtain the specified
 quantity of a random item from the group "<group id>". The different groups and
-their group number are specified in db/(pre-)re/item_group_db.txt
+their group number are specified in db/(pre-)re/item_group_db.yml
 
 If 'quantity' is not defined or 0, it will uses defined amount from Item Group list.
 
@@ -6416,6 +6425,7 @@ The variable 'killedgid' is set to the ID (unique mob game ID) of the monster ki
 	AI_ZANZOU	(4)		(Kagerou/Oboro skill)
 	AI_LEGION	(5)		(Sera skill)
 	AI_FAW		(6)		(Mechanic skill)
+	AI_WAVEMODE	(7)		Normal monsters will ignore attack from AI_WAVEMODE monsters
 
     monster "place",60,100,"Poring",1002,1,"NPCNAME::OnLabel";
 
@@ -6519,7 +6529,7 @@ command, simply use 1 for type. Any other number won't be recognized.
 *strmobinfo(<type>,<monster id>);
 
 This function will return information about a monster record in the database, as
-per 'db/(pre-)re/mob_db.txt'. Type is the kind of information returned. Valid types are:
+per 'db/(pre-)re/mob_db.yml'. Type is the kind of information returned. Valid types are:
 It will return 0 if there is no such monster (or the type value is invalid),
 or an empty string if you requested the monster's name.
 
@@ -6602,26 +6612,49 @@ summon "--ja--",-1;
 
 ---------------------------------------
 
-*addmonsterdrop <monster id>,<item id>,<rate>;
-*addmonsterdrop "<monster name>",<item id>,<rate>;
+*addmonsterdrop <monster id>,<item id>,<rate>,{<steal protected>,{<random option group id>}};
+*addmonsterdrop "<monster name>",<item id>,<rate>,{<steal protected>,{<random option group id>}};
 *delmonsterdrop <monster id>,<item id>;
 *delmonsterdrop "<monster name>",<item id>;
 
 These commands will temporarily add or delete a monster drop, which will be reset
-when the mob database reloads or the server shuts down. They return 1 upon success.
+when the mob database reloads or the server shuts down. They return true upon success, false otherwise.
 
 If the monster already drops the specified item, its drop rate will be updated with
 the given rate (100 = 1%).
 
+If <steal protected> is true the item will be protected from TF_STEAL (default false).
+<random option group id> binds the item with the given random option group Id (default 0).
+The Id must be valid, like defined in db/[pre-]re/item_randomopt_group.yml
+
 Examples:
 	// Makes Owl Baron drop Honey at an 80% rate.
 	addmonsterdrop 1295,518,8000;
 
+	// Makes Owl Baron drop Knife_ at an 80% rate, protected from TF_STEAL and with random option group Id 5.
+	addmonsterdrop 1295,1202,8000,true,5;
+
 	// Deletes Executioner's Mitten from Rybio.
 	delmonsterdrop 1201,7017;
 
 ---------------------------------------
 
+*mob_setidleevent <GID>,<event>;
+
+This command will attach an event label to the monster with the given <GID> which will execute
+when the <GID> is idle.
+
+Example:
+	monster "prontera",0,0,"Quest Poring",1002,1;
+	mob_setidleevent $@mobid[0], "NPC NAME::OnIdle";
+	end;
+
+OnIdle:
+	mobchat getattachedrid(),0,0x00FF00,"I'm IDLE!";
+	end;
+
+---------------------------------------
+
 *disablenpc {"<NPC object name>"};
 *enablenpc {"<NPC object name>"};
 
@@ -7635,7 +7668,7 @@ unnerving.
 Only a few NPC sprites have walking animations, and those that do, do not get
 the animation invoked when moving the NPC, due to the problem in the NPC walking
 code, which looks a bit silly. You might have better success by defining a job-
-sprite based sprite id in 'db/mob_avail.txt' with this.
+sprite based sprite id in 'db/mob_avail.yml' with this.
 
 ---------------------------------------
 
@@ -8067,10 +8100,10 @@ flag: Specify target
 
 ---------------------------------------
 
-*unitskilluseid <GID>,<skill id>,<skill lvl>{,<target id>,<casttime>};
-*unitskilluseid <GID>,"<skill name>",<skill lvl>{,<target id>,<casttime>};
-*unitskillusepos <GID>,<skill id>,<skill lvl>,<x>,<y>{,<casttime>};
-*unitskillusepos <GID>,"<skill name>",<skill lvl>,<x>,<y>{,<casttime>};
+*unitskilluseid <GID>,<skill id>,<skill lvl>{,<target id>,<casttime>,<cancel>,<Line_ID>};
+*unitskilluseid <GID>,"<skill name>",<skill lvl>{,<target id>,<casttime>,<cancel>,<Line_ID>};
+*unitskillusepos <GID>,<skill id>,<skill lvl>,<x>,<y>{,<casttime>,<cancel>,<Line_ID>};
+*unitskillusepos <GID>,"<skill name>",<skill lvl>,<x>,<y>{,<casttime>,<cancel>,<Line_ID>};
 
 This is the replacement of the older commands, these use the same values for
 GID as the other unit* commands (See 'GID').
@@ -8080,6 +8113,12 @@ Cast time is the amount of seconds to add or remove from the skill. Use a positi
 add and negative value to subtract. Using 0 or no value will use the default skill cast time.
 For the position, the x and y are given in the UnitSkillUsePos.
 
+<cancel> defines if the cast can be interrupted when hit (true/false).
+CastCancel from skill_db.yml is the default value of <cancel>.
+
+If <Line_ID> is defined (positive number, default 0) the monster will say the message from 'Line_ID'
+in mob_chat_db.yml when casting the skill.
+
 ---------------------------------------
 
 *unitexists <GID>;
@@ -8207,6 +8246,7 @@ Parameters (indexes) for monsters are:
 	UMOB_ROBE
 	UMOB_BODY2
 	UMOB_GROUP_ID
+	UMOB_IGNORE_CELL_STACK_LIMIT
 
 -----
 
@@ -10042,6 +10082,18 @@ This command is typically used in item scripts of mercenary scrolls.
 
 ---------------------------------------
 
+*mercenary_delete {<char id>{,<reply>}};
+
+This command removes the mercenary from a player.
+The parameter 'reply' can be one of the following values:
+
+	0 - Mercenary soldier's duty hour is over, faith increased by 1. (default)
+	1 - Your mercenary soldier has been killed, faith decreased by 1.
+	2 - Your mercenary soldier has been fired.
+	3 - Your mercenary soldier has ran away.
+
+---------------------------------------
+
 *mercenary_heal <hp>,<sp>;
 
 This command works like 'heal', but affects the mercenary of the

+ 2296 - 0
npc/re/instances/TempleOfDemonGod.txt

@@ -0,0 +1,2296 @@
+//===== rAthena Script =======================================
+//= Temple of Demon God
+//===== Description: =========================================
+//= [Official Conversion]
+//= Temple of Demon God Instance (part of episode 14.3)
+//===== Changelogs: ==========================================
+//= 1.0 First version. [Capuche]
+//============================================================
+
+moro_cav,41,73,4	script	Guardian Nidhogg#epeom01	4_F_NYDHOG,{
+	if (checkquest(7605,PLAYTIME) == 2)
+		erasequest 7605;
+	if (getcharid(1) < 1) {
+		mes "[Nidhogg]";
+		mes "This place is too dangerous for you to explore alone.";
+		mes "Please form a party and come with your comrades.";
+		cutin "ep14_nyd01.bmp",2;
+		close3;
+	}
+	if (is_party_leader() == false) {
+		mes "[Nidhogg]";
+		mes "Only party leaders can control access to the Temple of the Demon God.";
+		mes "It's to ensure the safety of the entire Expedition. Please let your leader talk to me instead.";
+		cutin "ep14_nyd01.bmp",2;
+		close3;
+	}
+	switch( checkquest(7593,HUNTING) ) {
+	case -1:
+		mes "[Nidhogg]";
+		mes "I'm sorry, but you can't enter this place without approval from the Commander.";
+		mes "You must be on the quest to subjugate the Demon God to enter this place.";
+		cutin "ep14_nyd01.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "Please go to Commander Hiva Agip and receive the Demon God Subjugation quest.";
+		close3;
+	case 0:
+	case 1:
+		mes "[Nidhogg]";
+		mes "I've been waiting for you, hero-in-waiting. ";
+		mes "Let me guide you to the depth of the temple where Morroc lies in wait.";
+		cutin "ep14_nyd03.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "This tree is the spitting image of Yggdrasil.";
+		mes "I just hope Morroc is not intent on what I fear most.";
+		mes "Through this tree the door is opened.";
+		next;
+		mes "[Nidhogg]";
+		mes "I can sense that";
+		mes "this tree is generating mana at certain intervals as if it's breathing.";
+		mes "I'm going to catch a moment between its breaths to open up a path for you. Are you ready?";
+		cutin "ep14_nyd04.bmp",2;
+		next;
+		if (select( "Enter now.", "Do not enter." ) == 2) {
+			mes "[Nidhogg]";
+			mes "Okay.";
+			mes "I understand if you need time.";
+			mes "Take your time. I can wait as long as you want me to.";
+			cutin "ep14_nyd04.bmp",2;
+			close3;
+		}
+		if (instance_create("Temple of the Demon God") < 1) {	// todo, custom text
+			mes "Party Name: " + getpartyname(.@party_id);
+			mes "Party Leader: " + strcharinfo(0);
+			mes "^0000ff" + .@md_name$ + " ^000000 - Reservation Failed.";
+			close;
+		}
+		if (isbegin_quest(7596) == 1)
+			erasequest 7596;
+		mes "[Nidhogg]";
+		mes "Just wait a while, and the entrance will open.";
+		mes "Enter through the tree.";
+		mes "Don't be scared, even though it's not an ordinary tree.";
+		cutin "ep14_nyd04.bmp",2;
+		close3;
+	case 2:	// todo, custom text
+		mes "[Nidhogg]";
+		mes "You have eliminated the God of Despair!?";
+		mes "I can only say that his ambition was too big...";
+		mes "Always talk about creating a new world and becoming a god...";
+		cutin "ep14_nyd03.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "But seriously, he didn't create anything at all!";
+		mes "Abandon the body that used to be a demon, and the appearance after rebirth is just imitating the god...";
+		next;
+		mes "[Nidhogg]";
+		mes "The result is just what a human looks like,";
+		mes "He can't escape the so-called god frame,";
+		mes "...you can only say that you are eating bad luck!";
+		cutin "ep14_nyd02.bmp",2;
+		next;
+		cutin "ep14_nyd04.bmp",2;
+		mes "[Nidhogg]";
+		mes "I will give you approval for the quest, and you can report to the commander.";
+		mes "Thank you!";
+		setquest 7597;
+		erasequest 7593;
+		for ( .@quest = 7601; .@quest < 7605; .@quest++ ) {
+			if (isbegin_quest(.@quest))
+				erasequest .@quest;
+		}
+		if (isbegin_quest(7596))
+			erasequest 7596;
+		close3;
+	}
+}
+
+moro_cav,45,75,0	script	Yggdrasil Lookalike#eom_gate	CLEAR_NPC,{
+	switch( checkquest(7593,HUNTING) ) {
+	case -1:
+		mes "[Nidhogg]";
+		mes "I'm sorry, but you can't enter this place without approval from the Commander.";
+		mes "You must be on the quest to subjugate the Demon God to enter this place.";
+		cutin "ep14_nyd01.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "Please go to Commander Hiva Agip and receive the 'Demon God Subjugation' quest.";
+		close3;
+	case 0:
+	case 1:
+		mes "You touched the tree and felt a strange flow of mana.";
+		mes "Perhaps the flow of mana will guide you to the depth of the temple.";
+		next;
+		if (select( "Enter.", "Quit." ) == 2) {
+			mes "[Nidhogg]";
+			mes "Okay.";
+			mes "I understand if you need time.";
+			mes "Take your time. I can wait as long as you want me to.";
+			cutin "ep14_nyd04.bmp",2;
+			close3;
+		}
+		switch( instance_enter("Temple of the Demon God") ) {
+		case IE_NOMEMBER:
+			mes "[Nidhogg]";
+			mes "This place is too dangerous for you to explore alone.";
+			mes "Please form a party and come with your comrades.";
+			cutin "ep14_nyd01.bmp",2;
+			close3;
+		case IE_NOINSTANCE:
+			mes "[Nidhogg]";
+			mes "No entry permission has been issued under the name of your party.";
+			mes "Please let your party leader submit an entry request, and I'll open the gate to the temple.";
+			cutin "ep14_nyd01.bmp",2;
+			next;
+			mes "[Nidhogg]";
+			mes "You are to comply with the rules set by the Expedition.";
+			mes "It's for everyone's safety.";
+			close3;
+		case IE_OTHER:	// todo, custom text
+			mes "[Nidhogg]";
+			mes "Um...how could this happen... the flow of magic power becomes unstable,";
+			mes "It hurts my brain, this is the gap I finally made...";
+			mes "may not be able to enter at the moment...";
+			cutin "ep14_nyd01.bmp",2;
+			close3;
+		case IE_OK:
+			mapannounce "moro_cav", "" + strcharinfo(0) + " of the party " + getpartyname( getcharid(1) ) + ", is entering Temple of the Demon God.",bc_map;
+			// warp "1@eom",101,16;
+			end;
+		}
+	case 2:	// todo, custom text
+		mes "[Nidhogg]";
+		mes "You have eliminated the God of Despair!?";
+		mes "I can only say that his ambition was too big...";
+		mes "Always talk about creating a new world and becoming a god...";
+		cutin "ep14_nyd01.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "But seriously, he didn't create anything at all!";
+		mes "Abandon the body that used to be a demon, and the appearance after rebirth is just imitating the god...";
+		cutin "ep14_nyd02.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "The result is just what a human looks like,";
+		mes "He can't escape the so-called god frame,";
+		mes "...you can only say that you are eating bad luck!";
+		cutin "ep14_nyd03.bmp",2;
+		next;
+		cutin "ep14_nyd04.bmp",2;
+		mes "[Nidhogg]";
+		mes "I will give you approval for the quest, and you can report to the commander.";
+		mes "Thank you!";
+		setquest 7597;
+		erasequest 7593;
+		for ( .@quest = 7601; .@quest < 7605; .@quest++ ) {
+			if (isbegin_quest(.@quest))
+				erasequest .@quest;
+		}
+		if (isbegin_quest(7596))
+			erasequest 7596;
+		close3;
+	}
+}
+
+1@eom,1,1,0	script	#demon_god_variables	-1,{
+	end;
+OnVariableReset:
+	'boss_id = 0;
+	'boss_hp = 0;
+	'bossx = 'bossy = 0;
+	'boss_phase = 0;
+	'icestunami = false;
+	'spawn = false;
+	'miniboss_id[0] = 'miniboss_id[1] = 0;
+	'combo_is_allowed = false;
+	'flowing_lava_deactivate[0] = 'flowing_lava_deactivate[1] = false;
+	end;
+OnMyMobDead:
+	if (!playerattached())	// shouldn't happen
+		end;
+	.@mob_id = killedrid;
+	sleep 5000;
+	monster 'map_eom$,0,0,"--ja--", .@mob_id,1, instance_npcname("#demon_god_variables") + "::OnMyMobDead";
+	end;
+OnInstanceInit:
+	donpcevent instance_npcname("#demon_god_variables") + "::OnVariableReset";
+
+	'map_eom$ = instance_mapname("1@eom");
+	'step = 0;
+	'inject_soul = 0;
+
+	// Entrance
+	disablenpc instance_npcname("#door_mobmaster");
+	disablenpc instance_npcname("Empty Soul Globe#ahat01");
+	disablenpc instance_npcname("Empty Soul Globe#shnaim01");
+	disablenpc instance_npcname("Filled Soul Globe#ahat02");
+	disablenpc instance_npcname("Filled Soul Globe#shnaim02");
+	disablenpc instance_npcname("#gate_to_center");
+
+	// Center to Ice
+	disablenpc instance_npcname("Strange Boy#mockid01");
+	disablenpc instance_npcname("#gate_to_ice");
+	disablenpc instance_npcname("Loki#eomloki01");
+	disablenpc instance_npcname("Nidhogg#eomnyd01");
+	disablenpc instance_npcname("Brinaranea#brinpc01");
+	disablenpc instance_npcname("#ice_hpcheck");
+	disablenpc instance_npcname("Nidhogg#eomnyd02");
+	disablenpc instance_npcname("#ice_to_center");
+
+	// Center to Fire
+	disablenpc instance_npcname("Morroc#mockid02");
+	disablenpc instance_npcname("#gate_to_fire");
+	disablenpc instance_npcname("#fire_event01");
+	disablenpc instance_npcname("#skollmaster");
+	disablenpc instance_npcname("#loco_call");
+	disablenpc instance_npcname("#fire_combo");
+	disablenpc instance_npcname("Flowing Lava#lavapond01");
+	disablenpc instance_npcname("Flowing Lava#lavapond02");
+	disablenpc instance_npcname("Hardened Lava#lavaseal01");
+	disablenpc instance_npcname("Hardened Lava#lavaseal02");
+	disablenpc instance_npcname("#lavazone11");
+	disablenpc instance_npcname("#lavazone12");
+	disablenpc instance_npcname("#lavazone21");
+	disablenpc instance_npcname("#lavazone22");
+	disablenpc instance_npcname("Nidhogg#eomnyd03");
+	disablenpc instance_npcname("#fire_to_center");
+
+	// Center to Last
+	disablenpc instance_npcname("#gate_to_last");
+	disablenpc instance_npcname("Strange Young Man#mocadt01");
+	disablenpc instance_npcname("#moc_master");
+	disablenpc instance_npcname("#despair_god_main");
+	disablenpc instance_npcname("#mk_hpcheck");
+	disablenpc instance_npcname("#moc_origin");
+	disablenpc instance_npcname("#morocc_god");
+	disablenpc instance_npcname("#despair_main");
+	disablenpc instance_npcname("Nidhogg#eomnyd04");
+
+	// mimic permanent spawn
+	.@event$ = instance_npcname("#demon_god_variables") + "::OnMyMobDead";
+	monster 'map_eom$,0,0,"--ja--", 3101,3, .@event$;	// MM_MANA_WHITE
+	monster 'map_eom$,0,0,"--ja--", 3102,3, .@event$;	// MM_MANA_RED
+	monster 'map_eom$,0,0,"--ja--", 3103,3, .@event$;	// MM_MANA_YELLOW
+	end;
+}
+
+1@eom,101,43,3	script	Demon God's Apostle Aha#ahat	4_HUMAN_GERUTOO,{
+	cutin "ep13_ahat_" + (Sex ? "f" : "m") + ".bmp",2;	// note: cutin f for male, m for female
+	// if (is_party_leader() == false || checkquest(7593,HUNTING) != 1 || isbegin_quest(7596) != 0) {	// quest to 'var for reload
+	if (is_party_leader() == false || checkquest(7593,HUNTING) != 1 || 'step != 0) {
+		mes "[Ahat]";
+		mes "Welcome";
+		mes "to the Temple of the Demon God.";
+		mes "It's my honor to be your host today.";
+		close3;
+	}
+	.@ahat$ = instance_npcname("Demon God's Apostle Aha#ahat");
+	mes "[Ahat]";
+	mes "So, you've come.";
+	mes "Gosh, you're so persistent.";
+	mes "Hah hah, are you surprised to see me here?";
+	npctalk "Ahat: So, you've come.", .@ahat$;
+	next;
+	mes "[Ahat]";
+	mes "Didn't you expect this at all?";
+	mes "Why don't I introduce myself officially?";
+	mes "I'm Ahat, the first servant of the Demon God.";
+	npctalk "Ahat: Why don't I introduce myself officially? I'm Ahat, the first servant of the Demon God.", .@ahat$;
+	next;
+	mes "[Ahat]";
+	mes "Well, well, maybe I forfeit my life today.";
+	mes "Don't look at me like that. Everything is as planned.";
+	npctalk "Ahat: Well, well, maybe I forfeit my life today. Don't look at me like that. Everything is as planned.", .@ahat$;
+	next;
+	mes "[Ahat]";
+	mes "My master wishes for Shnaim and I to put you to the test.";
+	mes "To see if you deserve to be our guests.";
+	npctalk "Ahat: My master wishes for Shnaim and I to put you to the test. To see if you deserve to be our guests.", .@ahat$;
+	next;
+	mes "[Ahat]";
+	mes "If you think you've come this far on your own,";
+	mes "you're mistaken.";
+	npctalk "Ahat: If you think you've come this far on your own, you're mistaken.", .@ahat$;
+	next;
+	mes "[Ahat]";
+	mes "Everything is as the Master has planned.";
+	mes "For now, let's see if you can open this door.";
+	npctalk "Ahat: Everything is as the Master has planned. For now, let's see if you can open this door.", .@ahat$;
+	if (isbegin_quest(7596) == 0)
+		setquest 7596;
+	if ('step != 0)
+		close3;
+	'step = 1;
+	close2;
+	cutin "",255;
+	setpcblock PCBLOCK_NPC, true;
+	sleep2 1000;
+	setpcblock PCBLOCK_NPC, false;
+	disablenpc .@ahat$;
+	warpparty 'map_eom$,101,16,getcharid(1),'map_eom$,2,2;
+	donpcevent instance_npcname("#door_mobmaster") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#door_mobmaster	CLEAR_NPC,{
+	end;
+OnStart:
+	'apostle = 10;
+	enablenpc instance_npcname("#door_mobmaster");
+	.@label$ = instance_npcname("#door_mobmaster") + "::OnMyMobDead";
+	monster 'map_eom$,102,30, "Demon God's Apostle Ahat",3105,1, .@label$;	// MM_GB_MOROCC_1
+	setunitdata $@mobid[0], UMOB_HP, 5000000;
+	monster 'map_eom$, 98,30, "Demon God Fragment",1918,1, .@label$;
+	monster 'map_eom$,100,30, "Demon God Fragment",1918,1, .@label$;
+	monster 'map_eom$,104,30, "Demon God Fragment",1918,1, .@label$;
+	monster 'map_eom$,106,30, "Demon God Fragment",1918,1, .@label$;
+	sleep 2000;
+	mapannounce 'map_eom$, "Eliminate the Demon God's Apostles, Ahat and Shnaim, and collect their souls.", bc_map, 0x00ff00;
+	monster 'map_eom$,102,40, "Demon God's Apostle Shnaim",3106,1, .@label$;	// MM_GB_MOROCC_4
+	setunitdata $@mobid[0], UMOB_HP, 5000000;
+	monster 'map_eom$, 98,40, "Demon God Fragment",1921,1, .@label$;
+	monster 'map_eom$,100,40, "Demon God Fragment",1921,1, .@label$;
+	monster 'map_eom$,104,40, "Demon God Fragment",1921,1, .@label$;
+	monster 'map_eom$,106,40, "Demon God Fragment",1921,1, .@label$;
+	sleep 3000;
+	mapannounce 'map_eom$, "The Apostles' souls are the key to opening the Temple of the Demon God.", bc_map, 0x00ff00;
+	end;
+OnMyMobDead:
+	'apostle -= 1;
+	if ('apostle == 0) {
+		'step = 2;
+		disablenpc instance_npcname("#door_mobmaster");
+		enablenpc instance_npcname("Empty Soul Globe#shnaim01");
+		enablenpc instance_npcname("Empty Soul Globe#ahat01");
+		mapannounce 'map_eom$, "Activated the Soul Globes used to open the Temple of the Demon God.", bc_map, 0x00ff00;
+	}
+	end;
+}
+
+1@eom,104,56,0	script	Empty Soul Globe#ahat01	CLEAR_NPC,{
+	if ('step == 2) {
+		if (strnpcinfo(2) == "ahat01")
+			callsub( S_Globe, 1, "Ahat", 6713, "ahat02" );
+		else
+			callsub( S_Globe, 2, "Shnaim", 6714, "shnaim02" );
+	}
+	end;
+S_Globe:
+	.@bit = getarg(0);
+	.@item_id = getarg(2);
+	.@visible_npc_name$ = getarg(1);
+	.@hidden_npc_name$ = getarg(3);
+
+	disable_items;
+	if (is_party_leader() == false || isbegin_quest(7596) != 1 || 'step != 2) {
+		mes "Only party leaders can perform this event.";
+		close;
+	}
+	if (countitem(.@item_id) < 1) {
+		mes "If you want to activate the soul globes, you need Shnaim's soul.";
+		close;
+	}
+	mes "Inject " + .@visible_npc_name$ + "'s soul into the empty soul globe.";
+	next;
+	specialeffect EF_SPHERE;
+	progressbar "000000",10;
+	if (!('inject_soul & .@bit) && countitem(.@item_id) > 0) {
+		'inject_soul |= .@bit;
+		delitem .@item_id,1;
+		specialeffect EF_ENTRY;
+		disablenpc instance_npcname( strnpcinfo(0) );
+		enablenpc instance_npcname("Filled Soul Globe#" + .@hidden_npc_name$);
+		specialeffect EF_ENTRY,AREA, instance_npcname("Filled Soul Globe#" + .@hidden_npc_name$);
+		specialeffect EF_LEVEL99_3,AREA, instance_npcname("Filled Soul Globe#" + .@hidden_npc_name$);
+		mes "Successfully activated " + .@visible_npc_name$ + "'s soul globe.";
+		if ('inject_soul == 3 && 'step == 2) {
+			'step = 3;
+			if (isbegin_quest(7596) == 1)
+				erasequest 7596;// Qualifications of the Guests
+			enablenpc instance_npcname("#gate_to_center");
+			enablenpc instance_npcname("Strange Boy#mockid01");
+			specialeffect EF_MAPPILLAR,AREA, instance_npcname("#gate_to_center");
+			specialeffect EF_LEVEL99_3,AREA, instance_npcname("#gate_to_center");
+		}
+	}
+	close;
+}
+1@eom,98,56,0	duplicate(Empty Soul Globe#ahat01)	Empty Soul Globe#shnaim01	CLEAR_NPC
+
+1@eom,104,56,0	duplicate(dummy_npc)	Filled Soul Globe#ahat02	CLEAR_NPC
+1@eom,98,56,0	duplicate(dummy_npc)	Filled Soul Globe#shnaim02	CLEAR_NPC
+
+1@eom,101,58,0	script	#gate_to_center	WARPNPC,1,1,{
+	end;
+OnTouch_:
+	if (isbegin_quest(7596) == 1)
+		erasequest 7596;
+	warp 'map_eom$,98,115;
+	end;
+}
+
+1@eom,100,122,3	script	Strange Boy#mockid01	4_F_MOCBOY,{
+	if ('step != 3)
+		end;
+	if (is_party_leader() == false || checkquest(7593,HUNTING) != 1) {
+		mes "[Boy]";
+		mes "You insignificant creature.";
+		mes "How dare you lay a hand on a god-in-waiting?!";
+		close;
+	}
+	cutin "morocc_kid.bmp",2;
+	mes "[Boy]";
+	mes "First, let me applaud you for coming this far.";
+	mes "You've been a good pawn.";
+	next;
+	select("What are you talking about?");
+	unittalk getcharid(3), "" + strcharinfo(0) + " : What are you talking about?";
+	mes "[Boy]";
+	mes "I've been waiting for this day.";
+	mes "To get out of that corner of the demon world and rule the entire universe.";
+	npctalk "Boy: I've been waiting for this day. To get out of that corner of the demon world and rule the entire universe.";
+	sleep2 2000;
+	next;
+	mes "[Boy]";
+	mes "To achieve that, I realized I must abandon my old body.";
+	mes "So I died--well, I let you kill me.";
+	npctalk "Boy: To achieve that, I realized I must abandon my old body. So I died--well, I let you kill me.";
+	sleep2 2000;
+	next;
+	mes "[Boy]";
+	mes "Death is an inevitable step to take before rebirth.";
+	mes "So I'm reborn--again, you brought me back.";
+	npctalk "Boy: Death is an inevitable step to take before rebirth. So I've been reborn--again, you've brought me back.";
+	sleep2 2000;
+	next;
+	mes "[Boy]";
+	mes "All this has been arranged so that I could be reborn as God.";
+	npctalk "Boy: All this has been arranged so that I could be reborn as God.";
+	sleep2 2000;
+	next;
+	mes "[Morroc]";
+	mes "That's right, you foolish humans!";
+	mes "I died once, so that I could circle around the world and embrace it in my arms.";
+	mes "I've been reborn to engulf this world.";
+	npctalk "Morocc: I died once, so that I could circle around the world and embrace it in my arms. I've been reborn to engulf this world.";
+	sleep2 2000;
+	next;
+	mes "[Morroc]";
+	mes "I'll create a new world and become its Creator.";
+	mes "Let me ask you, the first creatures that have stepped into my newborn land.";
+	npctalk "Morocc: I'll create a new world and become its Creator. Let me ask you, the first creatures that have stepped into my newborn land.";
+	sleep2 2000;
+	next;
+	mes "[Morroc]";
+	mes "How'd you like to follow me and watch the birth of a new world?";
+	npctalk "Morocc: How'd you like to follow me and watch the birth of a new world?";
+	close2;
+	setpcblock PCBLOCK_NPC, true;
+	cutin "",255;
+	sleep2 1000;
+	.@loki$ = instance_npcname("Loki#eomloki01");
+	.@nidhogg$ = instance_npcname("Nidhogg#eomnyd01");
+	enablenpc .@loki$;
+	enablenpc .@nidhogg$;
+	npctalk "Loki: Enough with your nonsense. Just say you like destroying things.", .@loki$;
+	sleep2 5000;
+	npctalk "Loki: Create a new world and become its Creator? If this is the new world you're talking about, then I'm disappointed.", .@loki$;
+	sleep2 5000;
+	npctalk "Loki: Even if you burn your body, your power is not as potent as that of Ymir of the Genesis.", .@loki$;
+	sleep2 5000;
+	npctalk "Loki: Just the fact that you had to steal Yggdrasil shows your lack of creativity.", .@loki$;
+	sleep2 5000;
+	npctalk "Loki: Take a good look at yourself. You're delusional if you think you look like a creator of any kind.", .@loki$;
+	sleep2 5000;
+	npctalk "Nidhogg: I second that. You're unnecessary to this world. You don't belong here.", .@nidhogg$;
+	sleep2 4000;
+	npctalk "Nidhogg: Even Yggdrasil denies your existence!", .@nidhogg$;
+	sleep2 4000;
+	npctalk "Nidhogg: As the Guardian of Yggdrasil, I have to remove you from this world.", .@nidhogg$;
+	sleep2 2000;
+	npctalk "Morroc: Pah!";
+	sleep2 2000;
+	npctalk "Morroc: Mortal, you must have a death wish to come at me like this.";
+	sleep2 3000;
+	npctalk "Morroc: I'll take your flesh and blood as housewarming gifts for my new world.";
+	sleep2 3000;
+	npctalk "Morroc: Have you beheld the darkness of the Genesis?";
+	sleep2 3000;
+	npctalk "Morroc: Have you beheld frost, the beginning of life?";
+	sleep2 6000;
+	npctalk "Morroc: Behold the Frost of Audhumla I brought back to life, into this world.";
+	sleep2 3000;
+	specialeffect EF_ENTRY;
+	if ('step == 3) {
+		'step = 4;
+		disablenpc instance_npcname("Strange Boy#mockid01");
+		donpcevent instance_npcname("#gate_to_ice") + "::OnEnable";
+		enablenpc instance_npcname("Nidhogg#eomnyd01");
+		enablenpc instance_npcname("Brinaranea#brinpc01");
+		npctalk "Loki: Are you running?", .@loki$;
+		sleep2 2000;
+		disablenpc .@loki$;
+	}
+	setpcblock PCBLOCK_NPC, false;
+	end;
+}
+
+1@eom,91,120,0	script	#gate_to_ice	WARPNPC,1,1,{
+	end;
+OnEnable:
+	.@gate_to_ice = instance_npcname("#gate_to_ice");
+	enablenpc instance_npcname("#gate_to_ice");
+	specialeffect EF_ICECRASH;
+	sleep 1000;
+	specialeffect EF_MAPPILLAR;
+	end;
+OnTouch_:
+	if (isbegin_quest(7601) == 0 && isbegin_quest(7602) == 0)
+		setquest 7601;
+	warp 'map_eom$,61,88;
+	end;
+}
+
+1@eom,95,122,5	script	Loki#eomloki01	4_M_ROKI2,{
+	mes "[Loki]";
+	mes "You're helpless.";
+	mes "And disgusting.";
+	close;
+}
+
+1@eom,94,120,5	script	Nidhogg#eomnyd01	4_F_NYDHOG,2,2,{
+	if ('step < 4 || is_party_leader() == false)
+		end;
+	if (getmercinfo(0) > 0) {
+		mes "[Nidhogg]";
+		mes "You're with a mercenary.";
+		mes "Could you dismiss your current mercenary and hire me instead?";
+		close;
+	}
+	switch( checkquest(7605,PLAYTIME) ) {
+	case -1:
+		break;
+	case 0:
+	case 1:
+		mes "[Nidhogg]";
+		mes "I already assisted you once.";
+		mes "Please be careful!";
+		close;
+	case 2:
+		erasequest 7605;
+		break;
+	}
+	setnpcdisplay instance_npcname("Nidhogg#eomnyd01"), 3087;
+	mes "[Nidhogg]";
+	mes "" + strcharinfo(0) + ",";
+	mes "allow me to aid you in this battle.";
+	npctalk "Nidhogg: Allow me to aid you in this battle.";
+	specialeffect EF_SPHERE;
+	next;
+	mes "[Nidhogg]";
+	mes "My duty as the guardian isn't over yet.";
+	npctalk "Nidhogg: My duty as the guardian isn't over yet.";
+	next;
+	mercenary_create 3087,1800000;// M_NYDHOG
+	mes "^4d4dffGuardian Nidhogg has joined your party.^000000";
+	setquest 7605;// Guardian's Blessing
+	disablenpc instance_npcname("Nidhogg#eomnyd01");
+	close;
+
+OnTouch:
+	if ('step >= 4 && is_party_leader())
+		npctalk "Nidhogg: Wait!";
+	end;
+}
+
+// Center -> Ice
+1@eom,48,88,0	script	Cold Mana Crystalline#eom01	4_ENERGY_BLUE,{
+	getitem 22566,1;// Frost_Crystal
+	specialeffect EF_LEVEL99_4;
+	disablenpc instance_npcname( strnpcinfo(0) );
+	end;
+}
+1@eom,51,103,0	duplicate(Cold Mana Crystalline#eom01)	Cold Mana Crystalline#eom02	4_ENERGY_BLUE
+1@eom,24,109,0	duplicate(Cold Mana Crystalline#eom01)	Cold Mana Crystalline#eom03	4_ENERGY_BLUE
+1@eom,26,128,0	duplicate(Cold Mana Crystalline#eom01)	Cold Mana Crystalline#eom04	4_ENERGY_BLUE
+1@eom,40,140,0	duplicate(Cold Mana Crystalline#eom01)	Cold Mana Crystalline#eom05	4_ENERGY_BLUE
+1@eom,38,139,0	duplicate(Cold Mana Crystalline#eom01)	Cold Mana Crystalline#eom06	4_ENERGY_BLUE
+1@eom,51,149,0	duplicate(Cold Mana Crystalline#eom01)	Cold Mana Crystalline#eom07	4_ENERGY_BLUE
+1@eom,49,148,0	duplicate(Cold Mana Crystalline#eom01)	Cold Mana Crystalline#eom08	4_ENERGY_BLUE
+
+1@eom,61,88,0	script	#icemob01	HIDDEN_WARP_NPC,2,1,{
+	end;
+OnTouch_:
+	if ('step >= 4) {
+		disablenpc instance_npcname("#icemob01");
+		areamonster 'map_eom$,40,93,48,101, "Frost Spider",3088,4;	// MM_BRINARANEA_BABY
+	}
+	end;
+}
+
+1@eom,22,116,3	script	Frost Spider#icemob02	3088,3,3,{
+	end;
+OnTouch_:
+	if ('step >= 4) {
+		disablenpc instance_npcname("Frost Spider#icemob02");
+		monster 'map_eom$,22,116, "Frost Spider",3088,1;	// MM_BRINARANEA_BABY
+		areamonster 'map_eom$,22,113,28,119, "Frost Spider",3088,3;
+	}
+	end;
+}
+
+1@eom,53,134,3	script	Frost Spider#icemob03	3088,3,3,{
+	end;
+OnTouch_:
+	if ('step >= 4) {
+		disablenpc instance_npcname("Frost Spider#icemob03");
+		monster 'map_eom$,53,134, "Frost Spider",3088,1;	// MM_BRINARANEA_BABY
+		areamonster 'map_eom$,47,133,53,139, "Frost Spider",3088,3;
+	}
+	end;
+}
+
+1@eom,38,129,3	script	Brinaranea#brinpc01	3091,10,10,{
+	end;
+OnTouch_:
+	if ('step == 4) {
+		'step = 5;
+		npctalk "Brinaranea: Ooh, food walks into my lair.";
+		initnpctimer;
+	}
+	end;
+OnTimer3000:
+	npctalk "Brinaranea: My children will have a feast tonight. Ho ho ho!";
+	disablenpc instance_npcname("Brinaranea#brinpc01");
+	donpcevent instance_npcname("#ice_hpcheck") + "::OnSpawn";
+	end;
+OnTimer5000:
+	stopnpctimer;
+	unittalk 'boss_id, "Time to cook! *Giggle*";
+	donpcevent instance_npcname("#ice_combo") + "::OnStart";
+	donpcevent instance_npcname("#ice_hpcheck") + "::OnStart";
+	end;
+}
+
+1@eom,2,3,0	script	#ice_hpcheck	CLEAR_NPC,{
+	end;
+OnSpawn:
+	enablenpc instance_npcname("#ice_hpcheck");
+	monster 'map_eom$,38,123, "Brinaranea",3091,1, instance_npcname("#ice_hpcheck") + "::OnMyMobDead";	// MM_BRINARANEA
+	'boss_id = $@mobid[0];
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_MAXHP];
+	unitskilluseid 'boss_id, "NPC_WIDEFREEZE",5;
+	end;
+OnStart:
+	initnpctimer;
+	end;
+
+OnTimer3000:
+	getunitdata 'boss_id, .@data;
+	.@hp = .@data[UMOB_HP];
+	if ('boss_hp < .@hp) {
+		'boss_hp = .@hp;
+		initnpctimer;
+		end;
+	}
+	if (('boss_hp - .@hp) > 2000000) {
+		'boss_hp = .@hp;
+		donpcevent instance_npcname("#super_heal") + "::OnStart";
+		initnpctimer;
+		end;
+	}
+	'boss_hp = .@hp;
+
+	if (.@hp > 69500000 && .@hp < 70000000) {
+		unittalk 'boss_id, "Come out, my children. An exquisite feast has delivered itself to us!";
+		donpcevent instance_npcname("#ice_hpcheck") + "::OnCallBaby";
+	}
+	else if (.@hp > 59500000 && .@hp < 60000000) {
+		unittalk 'boss_id, "Children, it's time for dinner!";
+		donpcevent instance_npcname("#ice_hpcheck") + "::OnCallBaby";
+	}
+	else if (.@hp > 49500000 && .@hp < 50000000) {
+		unittalk 'boss_id, "Have all of you fed yet? Come out now!";
+		donpcevent instance_npcname("#ice_hpcheck") + "::OnCallBaby";
+	}
+	else if (.@hp < 22200000 && 'icestunami == false)
+		donpcevent instance_npcname("#icestunami") + "::OnStart";
+	initnpctimer;
+	end;
+
+OnMyMobDead:
+	donpcevent instance_npcname("#ice_hpcheck") + "::OnEnd";
+	disablenpc instance_npcname("Brinaranea#brinpc01");
+	stopnpctimer instance_npcname("#ice_combo");
+	stopnpctimer instance_npcname("#brinaranea_event_1");
+	stopnpctimer instance_npcname("#brinaranea_event_2");
+	stopnpctimer instance_npcname("#brinaranea_event_3");
+	stopnpctimer instance_npcname("#brinaranea_event_4");
+	stopnpctimer instance_npcname("Brinaranea#brinpc01");
+	stopnpctimer instance_npcname("#super_heal");
+	// stopnpctimer instance_npcname("#icestunami");
+
+	enablenpc instance_npcname("Nidhogg#eomnyd02");
+	enablenpc instance_npcname("#ice_to_center");
+	enablenpc instance_npcname("Morroc#mockid02");
+	mapannounce 'map_eom$, "Nidhogg: Brinaranea's influence has dissipated, and a new warp gate has appeared.", bc_map, 0x00ff00;
+	'step = 6;
+
+	donpcevent instance_npcname("#demon_god_variables") + "::OnVariableReset";
+	end;
+
+OnEnd:
+	stopnpctimer;
+	disablenpc instance_npcname("#ice_hpcheck");
+	killmonster 'map_eom$, instance_npcname("#ice_hpcheck") + "::OnMyMobDead";
+	end;
+
+OnCallBaby:
+	sleep 500;
+	if ('boss_id == 0)
+		end;
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_HP];
+	killmonster 'map_eom$, instance_npcname("#ice_hpcheck") + "::OnMyMobDead";
+	monster 'map_eom$,38,123, "Brinaranea",3091,1, instance_npcname("#ice_hpcheck") + "::OnMyMobDead";	// MM_BRINARANEA
+	'boss_id = $@mobid[0];
+	setunitdata 'boss_id, UMOB_HP, 'boss_hp;
+	if ('spawn == true)
+		end;
+	'spawn = true;
+	unitskilluseid 'boss_id, "NPC_WIDEFREEZE",5;
+	sleep 1000;
+	if ('boss_id == 0)
+		end;
+	getunitdata 'boss_id, .@data;
+	areamonster 'map_eom$,(.@data[UMOB_X]-5),(.@data[UMOB_Y]-5),(.@data[UMOB_X]+5),(.@data[UMOB_Y]+5), " ",3088,5;	// MM_BRINARANEA_BABY
+	sleep 15000;
+	'spawn = false;
+	end;
+
+OnTest_hp:
+	if ('boss_id && mobcount( 'map_eom$, instance_npcname("#ice_hpcheck") + "::OnMyMobDead" ) > 0)
+		setunitdata 'boss_id, UMOB_HP, 2000000;
+	end;
+}
+
+1@eom,2,6,0	script	#ice_combo	CLEAR_NPC,{
+	end;
+OnStart:
+	initnpctimer;
+	end;
+OnTimer10000:
+	donpcevent instance_npcname("#brinaranea_event_" + rand(1,4)) + "::OnStart";
+	stopnpctimer;
+	end;
+}
+
+1@eom,1,1,0	script	#brinaranea_event_1	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	unittalk 'boss_id, "A show time!";
+	end;
+OnTimer1000:
+	unitskilluseid 'boss_id, "NPC_WIDEFREEZE",5;
+	end;
+OnTimer2500:
+	getunitdata 'boss_id, .@data;
+	'bossx = .@data[UMOB_X];
+	'bossy = .@data[UMOB_Y];
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-3),('bossy+3),-50;
+	end;
+OnTimer4000:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+3),('bossy+3),-50;
+	end;
+OnTimer5500:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+3),('bossy-3),-50;
+	end;
+OnTimer7000:
+	stopnpctimer;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-3),('bossy-3),-50;
+	donpcevent instance_npcname("#ice_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#brinaranea_event_2	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	unittalk 'boss_id, "Ooh, game. It looks delicious!";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_WIDEFREEZE",5;
+	end;
+OnTimer4000:
+	stopnpctimer;
+	getunitdata 'boss_id, .@data;
+	if (.@data[UMOB_TARGETID] > 0)
+		if (getunittype(.@data[UMOB_TARGETID]) == BL_PC)
+			unitskilluseid 'boss_id,"WZ_JUPITEL",28, .@data[UMOB_TARGETID], -50;
+	donpcevent instance_npcname("#ice_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#brinaranea_event_3	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	unittalk 'boss_id, "Wanna play?";
+	end;
+OnTimer1000:
+	unitskilluseid 'boss_id, "NPC_WIDEFREEZE",5;
+	end;
+OnTimer2500:
+	getunitdata 'boss_id, .@data;
+	'bossx = .@data[UMOB_X];
+	'bossy = .@data[UMOB_Y];
+	unitskillusepos 'boss_id,"WZ_VERMILION",5,'bossx,'bossy,-50;
+	end;
+OnTimer3500:
+	callsub( S_Skill,3 );
+	end;
+OnTimer4500:
+	callsub( S_Skill,4 );
+	end;
+OnTimer5500:
+	callsub( S_Skill,5 );
+	end;
+OnTimer6500:
+	callsub( S_Skill,6 );
+	end;
+OnTimer7500:
+	callsub( S_Skill,7 );
+	stopnpctimer;
+	donpcevent instance_npcname("#ice_combo") + "::OnStart";
+	end;
+S_Skill:
+	.@d = getarg(0);
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20, ('bossx - .@d), ('bossy + .@d),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20, ('bossx + .@d), ('bossy + .@d),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20, ('bossx + .@d), ('bossy - .@d),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20, ('bossx - .@d), ('bossy - .@d),-50;
+	return;
+}
+
+1@eom,1,1,0	script	#brinaranea_event_4	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	unittalk 'boss_id, "Hah hah...";
+	end;
+OnTimer1000:
+	unitskilluseid 'boss_id,"AL_HEAL",11;
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id,"AL_HEAL",11;
+	end;
+OnTimer3000:
+	stopnpctimer;
+	unitskilluseid 'boss_id,"AL_HEAL",11;
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_HP];
+	donpcevent instance_npcname("#ice_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#super_heal	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	unittalk 'boss_id, "You're annoying! Don't mess with the Frost of Audhumla!";
+	unitskilluseid 'boss_id, "NPC_ALLHEAL",1;
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_HP];
+	end;
+OnTimer2000:
+	stopnpctimer;
+	mapannounce 'map_eom$, "Nidhogg: No... She's regenerated herself perfectly.", bc_map, 0x00ff00;
+	end;
+}
+
+1@eom,2,4,0	script	#icestunami	CLEAR_NPC,{
+	end;
+OnStart:
+	'icestunami = true;
+	initnpctimer;
+	unittalk 'boss_id, "You hellhounds, can you take this too?";
+	getunitdata 'boss_id, .@data;
+	'x_icemine = .@data[UMOB_X];
+	'y_icemine = .@data[UMOB_Y];
+	callsub( S_Spawn,6 );
+OnTimer2000: callsub( S_Spawn,3 );
+OnTimer4000: callsub( S_Spawn,0 );
+OnTimer6000: callsub( S_Spawn,-3 );
+OnTimer8000: callsub( S_Spawn,-6 );
+OnTimer13000:
+	killmonster 'map_eom$, instance_npcname("#icestunami") + "::OnMobDead";
+	end;
+OnTimer23000:
+	'icestunami = false;
+	'x_icemine = 0;
+	'y_icemine = 0;
+	stopnpctimer;
+	end;
+S_Spawn:
+	.@y = 'y_icemine + getarg(0);
+	.@label$ = instance_npcname("#icestunami") + "::OnMobDead";
+	monster 'map_eom$,('x_icemine-6),.@y," ",2943,1, .@label$;// MM_ICE_MINE
+	monster 'map_eom$,('x_icemine-3),.@y," ",2943,1, .@label$;
+	monster 'map_eom$,  ('x_icemine),.@y," ",2943,1, .@label$;
+	monster 'map_eom$,('x_icemine+3),.@y," ",2943,1, .@label$;
+	monster 'map_eom$,('x_icemine+6),.@y," ",2943,1, .@label$;
+	end;
+OnMobDead:
+	end;
+}
+
+1@eom,59,147,3	script	Nidhogg#eomnyd02	4_F_NYDHOG,{
+	if ('step < 6)
+		end;
+	if (isbegin_quest(7602) == 0 && checkquest(7601,HUNTING) == 2) {
+		mes "[Nidhogg]";
+		mes "That was a tough battle.";
+		mes "This may not be good enough, but I hope it'll help your growth.";
+		next;
+		mes "^4d4dffGuardian Nidhogg has rewarded you with a large amount of EXP for defeating Brinaranea.^000000";
+		erasequest 7601;// Temple of the Demon God Phase 1
+		setquest 7602;// Temple of the Demon God Phase 1 Completed
+		getexp 1000000,500000;
+		close;
+	}
+	mes "[Nidhogg]";
+	mes "Can this dreadful place compete with the Frost of the Genesis?";
+	mes "I can't say.";
+	mes "He's created nothing on his own. How did he convince himself to think that he could be a creator?";
+	close;
+}
+
+1@eom,67,149,0	script	#ice_to_center	WARPNPC,1,1,{
+	end;
+OnTouch_:
+	if (isbegin_quest(7602) == 0 && checkquest(7601,HUNTING) == 2) {
+		mes "[Nidhogg]";
+		mes "That was a tough battle.";
+		mes "This may not be good enough, but I hope it'll help your growth.";
+		next;
+		mes "^4d4dffGuardian Nidhogg has rewarded you with a large amount of EXP for defeating Brinaranea.^000000";
+		setquest 7602;
+		erasequest 7601;
+		getexp 1000000,500000;
+		close;
+	}
+	warp 'map_eom$,98,115;
+	end;
+}
+
+// Center to Fire
+1@eom,100,122,3	script	Morroc#mockid02	4_F_MOCBOY,{
+	if ('step != 6 || is_party_leader() == false || checkquest(7593,HUNTING) != 1)
+		end;
+	cutin "morocc_kid.bmp",2;
+	mes "[Morroc]";
+	mes "You're good.";
+	mes "Can you take on the wolf that swallowed the sun?";
+	npctalk "Morroc: You're good. Can you taken on the wolf that swallowed the sun?";
+	next;
+	mes "[Morroc]";
+	mes "If you can't handle him, then you can't handle a god now, can you?";
+	npctalk "Morroc: If you can't handle him, then you can't handle a god now, can you?";
+	next;
+	mes "[Morroc]";
+	mes "I'll watch you. Mwa hah hah!";
+	npctalk "Morroc: I'll watch you. Mwa hah hah!";
+	close2;
+	cutin "",255;
+	if ('step == 6) {
+		'step = 7;
+		setpcblock PCBLOCK_NPC, true;
+		enablenpc instance_npcname("#fire_event01");
+		donpcevent instance_npcname("#gate_to_fire") + "::OnEnable";
+		sleep2 2000;
+		setpcblock PCBLOCK_NPC, false;
+		specialeffect EF_ENTRY;
+		cloakonnpc instance_npcname("Morroc#mockid02");	// cloakonnpc to properly display the previous effect
+	}
+	end;
+}
+
+1@eom,104,120,0	script	#gate_to_fire	WARPNPC,1,1,{
+	end;
+OnTouch_:
+	if (isbegin_quest(7603) == 0 && isbegin_quest(7604) == 0)
+		setquest 7603;
+	warp 'map_eom$,132,93;
+	end;
+OnEnable:
+	enablenpc instance_npcname("#gate_to_fire");
+	specialeffect EF_METEORSTORM;
+	sleep 1000;
+	specialeffect EF_MAPPILLAR;
+	end;
+}
+
+1@eom,132,93,0	script	#fire_event01	HIDDEN_WARP_NPC,1,1,{
+	end;
+OnTouch_:
+	disablenpc instance_npcname("#fire_event01");
+	sleep 1000;
+	mapannounce 'map_eom$, "Grr...", bc_map, 0xff0000;
+	sleep 3000;
+	mapannounce 'map_eom$, "I smell human... Grr...", bc_map, 0xff0000;
+	monster 'map_eom$,139,101, "Frenzied Kasa",3089,1;	// MM_LOCO_KASA
+	sleep 1000;
+	monster 'map_eom$,142, 98, "Frenzied Kasa",3089,1;
+	sleep 1000;
+	monster 'map_eom$,144, 92, "Frenzied Kasa",3089,1;
+	sleep 3000;
+	monster 'map_eom$,145,104, "Frenzied Kasa",3089,1;
+	sleep 1000;
+	monster 'map_eom$,148, 98, "Frenzied Kasa",3089,1;
+	sleep 1000;
+	monster 'map_eom$,150, 93, "Frenzied Kasa",3089,1;
+	sleep 3000;
+	monster 'map_eom$,151,106, "Frenzied Kasa",3089,1;
+	sleep 1000;
+	monster 'map_eom$,153,100, "Frenzied Kasa",3089,1;
+	sleep 1000;
+	monster 'map_eom$,156, 95, "Frenzied Kasa",3089,1;
+	mapannounce 'map_eom$, "...BURN!", bc_map, 0xff0000;
+	donpcevent instance_npcname("#skollmaster") + "::OnStart";
+	end;
+}
+
+1@eom,3,1,0	script	#skollmaster	CLEAR_NPC,{
+	end;
+OnStart:
+	enablenpc instance_npcname("#skollmaster");
+	enablenpc instance_npcname("Flowing Lava#lavapond01");
+	enablenpc instance_npcname("Flowing Lava#lavapond02");
+	enablenpc instance_npcname("#lavazone11");
+	enablenpc instance_npcname("#lavazone12");
+	enablenpc instance_npcname("#lavazone21");
+	enablenpc instance_npcname("#lavazone22");
+	'flowing_lava_deactivate[0] = 'flowing_lava_deactivate[1] = false;
+
+	monster 'map_eom$,148,98, "Muspellskoll",3092,1, instance_npcname("#skollmaster") + "::OnMobDead";	// MM_MUSPELLSKOLL
+	'boss_id = $@mobid[0];
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_MAXHP];
+	sleep 1000;
+	if ('boss_id)
+		unittalk 'boss_id, "You're the ones... Grr... Good, I'll crush your bones! Grr...";
+	sleep 4000;
+	if ('boss_id)
+		donpcevent instance_npcname("#skollmaster") + "::OnLava_heal";
+	end;
+
+OnLava_heal:
+	'lava_heal = true;
+	donpcevent instance_npcname("#fire_combo") + "::OnEnd";
+	stopnpctimer instance_npcname("#fire_hpcheck");
+	callsub S_Event, 0, 156,117;
+	initnpctimer;
+	end;
+OnTimer2000:
+	callsub S_Event, 1, 180,129;
+	end;
+OnTimer4000:
+	callsub S_ReSpawn, 168,121;
+	unitskilluseid 'boss_id, "CR_REFLECTSHIELD",1;
+	unittalk 'boss_id, "Let's do this again. Come on!";
+	donpcevent instance_npcname("#loco_call") + "::OnSpawn";
+	end;
+OnTimer6000:
+	stopnpctimer;
+	'lava_heal = false;
+	donpcevent instance_npcname("#fire_hpcheck") + "::OnStart";
+	donpcevent instance_npcname("#fire_combo") + "::OnEvent";
+	end;
+S_ReSpawn:
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_HP];
+	killmonster 'map_eom$, instance_npcname("#skollmaster") + "::OnMobDead";
+	monster 'map_eom$,getarg(0),getarg(1), "Muspellskoll",3092,1, instance_npcname("#skollmaster") + "::OnMobDead";	// MM_MUSPELLSKOLL
+	'boss_id = $@mobid[0];
+	setunitdata 'boss_id, UMOB_HP, 'boss_hp;
+	return;
+S_Event:
+	callsub S_ReSpawn, getarg(1),getarg(2);
+	if ('flowing_lava_deactivate[ getarg(0) ] == false) {
+		for ( .@i = 0; .@i < 8; .@i++ ) {
+			unitskilluseid 'boss_id, "AL_HEAL",11;
+			sleep 100;
+			if ('boss_id == 0)
+				end;
+		}
+		unitskilluseid 'boss_id, "AL_HEAL",11;
+	}
+	mapannounce 'map_eom$, "Nidhogg: Muspellskoll is trying to regenerate itself using the lava!", bc_map, 0x00ff00;
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_HP];
+	donpcevent instance_npcname("#loco_call") + "::OnSpawn";
+	return;
+
+OnMobDead:
+	stopnpctimer instance_npcname("#fire_hpcheck");
+	stopnpctimer instance_npcname("#muspellskoll_event_1");
+	stopnpctimer instance_npcname("#muspellskoll_event_2");
+	stopnpctimer instance_npcname("#muspellskoll_event_3");
+	donpcevent instance_npcname("#fire_combo") + "::OnEnd";
+	donpcevent instance_npcname("#loco_call") + "::OnEnd";
+
+	killmonster 'map_eom$, instance_npcname("#skollmaster") + "::OnMobDead";
+	mapannounce 'map_eom$, "Nidhogg: Muspellskoll's influence has dissipated, and a new warp gate has appeared.", bc_map, 0x00ff00;
+
+	enablenpc instance_npcname("Nidhogg#eomnyd03");
+	enablenpc instance_npcname("#fire_to_center");
+	enablenpc instance_npcname("Strange Young Man#mocadt01");
+
+	'step = 8;
+	donpcevent instance_npcname("#demon_god_variables") + "::OnVariableReset";
+	end;
+
+OnTest_hp:
+	if ('boss_id && mobcount( 'map_eom$, instance_npcname("#skollmaster") + "::OnMobDead" ) > 0)
+		setunitdata 'boss_id, UMOB_HP, 2000000;
+	end;
+}
+
+1@eom,3,7,0	script	#fire_hpcheck	CLEAR_NPC,{
+	end;
+OnStart:
+	initnpctimer;
+	end;
+OnTimer3000:
+	getunitdata 'boss_id, .@data;
+	.@hp = .@data[UMOB_HP];
+	if ('boss_hp < .@hp) {
+		initnpctimer;
+		end;
+	}
+	if (('boss_hp - .@hp) > 1000000) {
+		'boss_hp = .@hp;
+		donpcevent instance_npcname("#fire_hpcheck") + "::OnHeal";	// the event can stack and the boss can stay in this state until it demise
+		initnpctimer;
+		end;
+	}
+	'boss_hp = .@hp;
+
+	if ('lava_heal == false) {
+		if (.@hp > 29500000 && .@hp < 30000000 || .@hp > 35500000 && .@hp < 36000000 || .@hp > 39500000 && .@hp < 40000000 || .@hp > 44500000 && .@hp < 45000000) {
+			unittalk 'boss_id, "I'm not going down without a fight!";
+			donpcevent instance_npcname("#skollmaster") + "::OnLava_heal";
+		}
+	}
+	initnpctimer;
+	end;
+
+OnHeal:
+	if ('fire_combo)
+		donpcevent instance_npcname("#fire_combo") + "::OnEnd";
+	unittalk 'boss_id, "Do I look easy to you? I'll burn you to ashes!";
+	sleep 2000;
+	if ('boss_id == 0)
+		end;
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_METEOR",11,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	sleep 1000;
+	if ('boss_id == 0)
+		end;
+	for ( .@i = 0; .@i < 18; .@i++ ) {
+		unitskilluseid 'boss_id, "AL_HEAL",11;
+		sleep 200;
+		if ('boss_id == 0)
+			end;
+	}
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_METEOR",11,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	for ( .@i = 0; .@i < 18; .@i++ ) {
+		unitskilluseid 'boss_id, "AL_HEAL",11;
+		sleep 200;
+		if ('boss_id == 0)
+			end;
+	}
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_HP];
+	if (!'fire_combo)
+		donpcevent instance_npcname("#fire_combo") + "::OnEvent";
+	end;
+}
+
+1@eom,3,5,0	script	#loco_call	CLEAR_NPC,{
+	end;
+OnSpawn:
+	enablenpc instance_npcname("#loco_call");
+	initnpctimer;
+	getunitdata 'boss_id, .@data;
+	'x_loco = .@data[UMOB_X];
+	'y_loco = .@data[UMOB_Y];
+	end;
+OnTimer1000:
+	.@label$ = instance_npcname("#loco_call") + "::OnMobDead";
+	if (mobcount( 'map_eom$, .@label$ ) < 6)
+		areamonster 'map_eom$,('x_loco-5),('y_loco-5),('x_loco+5),('y_loco+5)," ",3089,3, .@label$;	// MM_LOCO_KASA
+	end;
+OnTimer16000:
+	stopnpctimer;
+	disablenpc instance_npcname("#loco_call");
+	end;
+OnMobDead:
+	end;
+OnEnd:
+	stopnpctimer;
+	disablenpc instance_npcname("#loco_call");
+	end;
+}
+
+1@eom,1,1,0	script	#muspellskoll_event_1	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "Crash and burn!";
+	end;
+OnTimer1000:
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	end;
+OnTimer3000:
+	stopnpctimer;
+	unitskilluseid 'boss_id, "WZ_SIGHTRASHER",10;
+	if ('fire_combo)
+		donpcevent instance_npcname("#fire_combo") + "::OnEvent";
+	end;
+}
+
+1@eom,1,1,0	script	#muspellskoll_event_2	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "Grr...";
+	end;
+OnTimer1000:
+	getunitdata 'boss_id, .@data;
+	'bossx = .@data[UMOB_X];
+	'bossy = .@data[UMOB_Y];
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	end;
+OnTimer3000:
+	unitskillusepos 'boss_id,"WZ_FIREPILLAR",1,('bossx-3),('bossy+3),-50;
+	end;
+OnTimer5000:
+	unitskillusepos 'boss_id,"WZ_FIREPILLAR",1,('bossx+3),('bossy+3),-50;
+	end;
+OnTimer7000:
+	unitskillusepos 'boss_id,"WZ_FIREPILLAR",1,('bossx-3),('bossy-3),-50;
+	end;
+OnTimer9000:
+	unitskillusepos 'boss_id,"WZ_FIREPILLAR",1,('bossx+3),('bossy-3),-50;
+	end;
+OnTimer19000:
+	stopnpctimer;
+	if ('fire_combo)
+		donpcevent instance_npcname("#fire_combo") + "::OnEvent";
+	end;
+}
+
+1@eom,1,1,0	script	#muspellskoll_event_3	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "My fire will swallow you whole!";
+	end;
+OnTimer1000:
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	end;
+OnTimer2000:
+	donpcevent instance_npcname("#flamecross") + "::OnStart";
+	end;
+OnTimer7000:
+	getunitdata 'boss_id, .@data;
+	'bossx = .@data[UMOB_X];
+	'bossy = .@data[UMOB_Y];
+	unitskillusepos 'boss_id,"WZ_METEOR",5,('bossx),('bossy+5),-50;
+	end;
+OnTimer9000:
+	unitskillusepos 'boss_id,"WZ_METEOR",5,('bossx),('bossy-5),-50;
+	end;
+OnTimer11000:
+	unitskillusepos 'boss_id,"WZ_METEOR",5,('bossx),('bossy+10),-50;
+	end;
+OnTimer13000:
+	stopnpctimer;
+	unitskillusepos 'boss_id,"WZ_METEOR",5,'bossx,('bossy-10),-50;
+	if ('fire_combo)
+		donpcevent instance_npcname("#fire_combo") + "::OnEvent";
+	end;
+}
+
+1@eom,3,3,0	script	#fire_combo	CLEAR_NPC,{
+	end;
+OnEvent:
+	initnpctimer;
+	'fire_combo = true;
+	end;
+OnTimer10000:
+	stopnpctimer;
+	.@r = rand(1,4);
+	if (.@r == 1)
+		donpcevent instance_npcname("#muspellskoll_event_1") + "::OnEvent";
+	else if (.@r == 2)
+		donpcevent instance_npcname("#muspellskoll_event_2") + "::OnEvent";
+	else if (.@r == 3)
+		donpcevent instance_npcname("#muspellskoll_event_3") + "::OnEvent";
+	else
+		donpcevent instance_npcname("#flamecross") + "::OnSpawn";
+	end;
+OnEnd:
+	stopnpctimer;
+	'fire_combo = false;
+	disablenpc instance_npcname("#fire_combo");
+	end;
+}
+
+1@eom,3,8,0	script	#flamecross	CLEAR_NPC,{
+	end;
+OnStart:
+	getunitdata 'boss_id, .@data;
+	.@x = .@data[UMOB_X];
+	.@y = .@data[UMOB_Y];
+	callsub( S_Spawn,.@x,.@y,3 );
+	sleep 300;
+	callsub( S_Spawn,.@x,.@y,6 );
+	sleep 300;
+	callsub( S_Spawn,.@x,.@y,9 );
+	sleep 300;
+	callsub( S_Spawn,.@x,.@y,13 );
+	sleep 5000;
+	killmonster 'map_eom$, instance_npcname("#flamecross") + "::OnMobDead";
+	end;
+
+S_Spawn:
+	if (!'boss_id) {
+		killmonster 'map_eom$, instance_npcname("#flamecross") + "::OnMobDead";
+		end;
+	}
+	.@x = getarg(0);
+	.@y = getarg(1);
+	.@dxy = getarg(2);
+	.@label$ = instance_npcname("#flamecross") + "::OnMobDead";
+	monster 'map_eom$,(.@x+.@dxy),(.@y+.@dxy)," ",2960,1, .@label$;// MM_FLAMECROSS
+	monster 'map_eom$,(.@x-.@dxy),(.@y-.@dxy)," ",2960,1, .@label$;
+	monster 'map_eom$,(.@x+.@dxy),(.@y-.@dxy)," ",2960,1, .@label$;
+	monster 'map_eom$,(.@x-.@dxy),(.@y+.@dxy)," ",2960,1, .@label$;
+	return;
+
+OnSpawn:
+	getunitdata 'boss_id, .@data;
+	.@label$ = instance_npcname("#flamecross") + "::OnMobDead";	// same OnMobDead than OnStart?
+	if (mobcount( 'map_eom$, .@label$ ) < 2)
+		areamonster 'map_eom$,(.@data[UMOB_X]-1),(.@data[UMOB_Y]-1),(.@data[UMOB_X]+1),(.@data[UMOB_Y]+1)," ",3090,2, .@label$;	// MM_LOCO_SALAMANDER
+	if ('fire_combo)
+		donpcevent instance_npcname("#fire_combo") + "::OnEvent";
+	end;
+
+OnMobDead:
+	end;
+}
+
+1@eom,154,119,0	script	Flowing Lava#lavapond01	CLEAR_NPC,{	// todo, custom text
+	if (countitem(22566) < 1)
+		end;
+	mes "It can be used to block the flow of lava using a Frost Crystal.";
+	next;
+	if (select( "Use a Frost Crystal", "Do not use a Frost Crystal" ) == 2)
+		end;
+	if ('flowing_lava_deactivate[0] == true)
+		end;
+	'flowing_lava_deactivate[0] = true;
+	delitem 22566,1;// Frost_Crystal
+	disablenpc instance_npcname("Flowing Lava#lavapond01");
+	donpcevent instance_npcname("Hardened Lava#lavaseal01") + "::OnEnable";
+	initnpctimer;
+	end;
+OnTimer300:
+	donpcevent instance_npcname("Hardened Lava#lavaseal01") + "::OnEffect";
+	end;
+OnTimer120000:
+	'flowing_lava_deactivate[0] = false;
+	donpcevent instance_npcname("Hardened Lava#lavaseal01") + "::OnDisable";
+	enablenpc instance_npcname("Flowing Lava#lavapond01");
+	mapannounce 'map_eom$, "Nidhogg: The Frost has melted. The lava is flowing again!", bc_map, 0x00ff00;
+	stopnpctimer;
+	end;
+}
+
+1@eom,182,129,0	script	Flowing Lava#lavapond02	CLEAR_NPC,{	// todo, custom text
+	if (countitem(22566) < 1)
+		end;
+	mes "It can be used to block the flow of lava using a Frost Crystal.";
+	next;
+	if (select( "Use a Frost Crystal", "Do not use a Frost Crystal" ) == 2)
+		end;
+	if ('flowing_lava_deactivate[1] == true)
+		end;
+	'flowing_lava_deactivate[1] = true;
+	delitem 22566,1;// Frost_Crystal
+	disablenpc instance_npcname("Flowing Lava#lavapond02");
+	donpcevent instance_npcname("Hardened Lava#lavaseal02") + "::OnEnable";
+	initnpctimer;
+	end;
+OnTimer300:
+	donpcevent instance_npcname("Hardened Lava#lavaseal02") + "::OnEffect";
+	end;
+OnTimer120000:
+	'flowing_lava_deactivate[1] = false;
+	donpcevent instance_npcname("Hardened Lava#lavaseal02") + "::OnDisable";
+	enablenpc instance_npcname("Flowing Lava#lavapond02");
+	mapannounce 'map_eom$, "Nidhogg: The Frost has melted. The lava is flowing again!", bc_map, 0x00ff00;
+	stopnpctimer;
+	end;
+}
+
+1@eom,154,119,0	script	Hardened Lava#lavaseal01	CLEAR_NPC,{
+	end;
+OnEnable:
+	enablenpc instance_npcname("Hardened Lava#lavaseal01");
+	disablenpc instance_npcname("#lavazone11");
+	disablenpc instance_npcname("#lavazone12");
+	end;
+OnDisable:
+	stopnpctimer;
+	disablenpc instance_npcname("Hardened Lava#lavaseal01");
+	enablenpc instance_npcname("#lavazone11");
+	enablenpc instance_npcname("#lavazone12");
+	end;
+OnEffect:
+	initnpctimer;
+	specialeffect EF_LIGHTNINGLOADER;
+	end;
+OnTimer3000:
+	initnpctimer;
+	end;
+}
+
+1@eom,182,129,0	script	Hardened Lava#lavaseal02	CLEAR_NPC,{
+	end;
+OnEnable:
+	enablenpc instance_npcname("Hardened Lava#lavaseal02");
+	disablenpc instance_npcname("#lavazone21");
+	disablenpc instance_npcname("#lavazone22");
+	end;
+OnDisable:
+	stopnpctimer;
+	disablenpc instance_npcname("Hardened Lava#lavaseal02");
+	enablenpc instance_npcname("#lavazone21");
+	enablenpc instance_npcname("#lavazone22");
+	end;
+OnEffect:
+	initnpctimer;
+	specialeffect EF_LIGHTNINGLOADER;
+	end;
+OnTimer3000:
+	initnpctimer;
+	end;
+}
+
+1@eom,161,122,0	script	#lavazone11	HIDDEN_WARP_NPC,10,10,{
+	end;
+OnTouch:
+	percentheal -3,0;
+	specialeffect2 EF_SPRINKLESAND;
+	end;
+}
+1@eom,161,102,0	duplicate(#lavazone11)	#lavazone12	HIDDEN_WARP_NPC,10,10
+1@eom,163,150,0	duplicate(#lavazone11)	#lavazone21	HIDDEN_WARP_NPC,10,10
+1@eom,163,150,0	duplicate(#lavazone11)	#lavazone22	HIDDEN_WARP_NPC,10,10
+
+1@eom,151,155,3	script	Nidhogg#eomnyd03	4_F_NYDHOG,{
+	if (checkquest(7603,HUNTING) == 2 && isbegin_quest(7604) == 0) {
+		mes "[Nidhogg]";
+		mes "Good job, again.";
+		mes "This may not be good enough, but I hope it'll help your growth.";
+		next;
+		mes "^4d4dffGuardian Nidhogg has rewarded you with a large amount of EXP for defeating Muspellskoll.^000000";
+		erasequest 7603;// Temple of the Demon God Phase 2
+		setquest 7604;// Temple of the Demon God Phase 2 Completed
+		getexp 1000000,500000;
+		close;
+	}
+	mes "[Nidhogg]";
+	mes "Skoll... Skoll and Haati...";
+	mes "Everything in here is a mere copy of that in the outside world.";
+	mes "He's not a creator.";
+	close;
+}
+
+1@eom,147,156,0	script	#fire_to_center	WARPNPC,1,1,{
+	end;
+OnTouch_:
+	if (checkquest(7603,HUNTING) == 2 && isbegin_quest(7604) == 0) {
+		mes "[Nidhogg]";
+		mes "Good job, again.";
+		mes "This may not be good enough, but I hope it'll help your growth.";
+		next;
+		mes "^4d4dffGuardian Nidhogg has rewarded you with a large amount of EXP for defeating Muspellskoll.^000000";
+		setquest 7604;
+		erasequest 7603;
+		getexp 1000000,500000;
+		close;
+	}
+	warp 'map_eom$,98,115;
+	end;
+}
+
+// Center to Last
+1@eom,98,123,5	script	Strange Young Man#mocadt01	3097,5,5,{	// MM_MOROCC_ADT
+	end;
+OnTouch_:
+	if ('step == 8 && is_party_leader()) {
+		'step = 9;
+		initnpctimer;
+	}
+	end;
+OnTimer1000:
+	npctalk "You exceed my expectations.";
+	end;
+OnTimer4000:
+	npctalk "I'll accept your challenge.";
+	end;
+OnTimer7000:
+	npctalk "I shall drench the land with your flowing blood and nourish it with your torn flesh.";
+	end;
+OnTimer8000:
+	specialeffect EF_BEGINSPELL5;
+	enablenpc instance_npcname("#gate_to_last");
+	enablenpc instance_npcname("#moc_master");
+	specialeffect EF_READYPORTAL2,AREA, instance_npcname("#gate_to_last");
+	end;
+OnTimer10000:
+	npctalk "I'll show you the true depths of despair.";
+	end;
+OnTimer12000:
+	stopnpctimer;
+	specialeffect EF_ENTRY;
+	disablenpc instance_npcname("Strange Young Man#mocadt01");
+	end;
+}
+
+1@eom,98,127,0	warp	#gate_to_last	1,1,1@eom,102,186
+
+1@eom,101,194,3	script	#moc_master	3096,10,10,{
+	end;
+OnTouch_:
+	if ('step != 9)
+		end;
+	'step = 10;
+	npctalk "Morroc: You're already here, so let's not waste our time on talking.";
+	initnpctimer;
+	end;
+OnTimer2000:
+	stopnpctimer;
+	npctalk "Morroc: Come on, mortals!";
+	disablenpc instance_npcname("#moc_master");
+	donpcevent instance_npcname("#despair_god_main") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#despair_god_main	-1,{
+	end;
+OnStart:
+	enablenpc instance_npcname("#despair_god_main");
+	'boss_phase = 1;
+
+	monster 'map_eom$,101,194, "Demigod",3096,1, instance_npcname("#despair_god_main") + "::OnMobDead";	// MM_MOROCC_KID
+	'boss_id = $@mobid[0];
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_MAXHP];
+
+	unitskillusepos 'boss_id,"WZ_METEOR",11,101,194,-50;
+
+	enablenpc instance_npcname("#mk_trap");
+	donpcevent instance_npcname("#mk_hpcheck") + "::OnStart";
+	donpcevent instance_npcname("#mk_combo") + "::OnEvent";
+	end;
+
+OnPhase02:
+	if ('boss_phase != 1)
+		end;
+	'boss_phase = 2;
+	stopnpctimer instance_npcname("#demigod_event_1");
+	stopnpctimer instance_npcname("#demigod_event_2");
+	stopnpctimer instance_npcname("#demigod_event_3");
+	stopnpctimer instance_npcname("#mk_hpcheck");
+	stopnpctimer instance_npcname("#mk_combo");
+	unittalk 'boss_id, "You'll have to do better than this!";
+	sleep 2000;
+	if ('boss_id == 0)
+		end;
+	getunitdata 'boss_id, .@data;
+	'boss_hp = .@data[UMOB_HP];
+	killmonster 'map_eom$, instance_npcname("#despair_god_main") + "::OnMobDead";
+	monster 'map_eom$,101,207, "Demigod",3096,1, instance_npcname("#despair_god_main") + "::OnMobDead";	// MM_MOROCC_KID
+	'boss_id = $@mobid[0];
+	setunitdata 'boss_id, UMOB_HP, 'boss_hp;
+	setunitdata 'boss_id, UMOB_MODE, (MD_MVP|MD_STATUSIMMUNE|MD_KNOCKBACKIMMUNE|MD_MVP|MD_DETECTOR);	// todo: MD_SKILL_IMMUNE ?
+	sleep 2000;
+	if ('boss_id == 0)
+		end;
+	donpcevent instance_npcname("#moc_origin") + "::OnEnable";
+	end;
+
+OnPhase03:
+	if ('boss_phase != 2)
+		end;
+	'boss_phase = 3;
+	getunitdata 'boss_id, .@data;
+	.@hp = .@data[UMOB_HP] + ('boss_hp - .@data[UMOB_HP]) * 10;
+	'boss_hp = min(80000000,.@hp);
+	killmonster 'map_eom$, instance_npcname("#despair_god_main") + "::OnMobDead";
+	monster 'map_eom$,101,194, "Demigod",3096,1, instance_npcname("#despair_god_main") + "::OnMobDead";	// MM_MOROCC_KID
+	'boss_id = $@mobid[0];
+	setunitdata 'boss_id, UMOB_HP, 'boss_hp;
+	unittalk 'boss_id, "Stop being so persistent!";
+	sleep 2000;
+	if ('boss_id == 0)
+		end;
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	sleep 1000;
+	if ('boss_id == 0)
+		end;
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	sleep 1000;
+	if ('boss_id == 0)
+		end;
+	unitskilluseid 'boss_id, "MG_FIREBALL",1;
+	donpcevent instance_npcname("#mk_hpcheck") + "::OnStart";
+	donpcevent instance_npcname("#mk_combo") + "::OnEvent";
+	end;
+
+OnTest_hp:
+	if ('boss_id && mobcount( 'map_eom$, instance_npcname("#despair_god_main") + "::OnMobDead" ) > 0)
+		setunitdata 'boss_id, UMOB_HP, 2000000;
+	end;
+
+OnMobDead:
+	disablenpc instance_npcname("#despair_god_main");
+	killmonster 'map_eom$, instance_npcname("#despair_god_main") + "::OnMobDead";
+	stopnpctimer instance_npcname("#mk_combo");
+	stopnpctimer instance_npcname("#demigod_event_1");
+	stopnpctimer instance_npcname("#demigod_event_2");
+	stopnpctimer instance_npcname("#demigod_event_3");
+	stopnpctimer instance_npcname("#moc_meddling");
+	stopnpctimer instance_npcname("#mk_hpcheck");
+	donpcevent instance_npcname("#moc_origin") + "::OnEnd";
+
+	donpcevent instance_npcname("#demon_god_variables") + "::OnVariableReset";
+	donpcevent instance_npcname("#morocc_god") + "::OnStart";
+	end;
+}
+
+1@eom,4,2,0	script	#mk_combo	CLEAR_NPC,{
+	end;
+OnEvent:
+	initnpctimer;
+	'combo_is_allowed = true;
+	end;
+OnStart:
+	initnpctimer;
+	end;
+OnTimer10000:
+	donpcevent instance_npcname("#demigod_event_" + rand(1,3)) + "::OnEvent";
+	stopnpctimer;
+	end;
+OnEnd:
+	stopnpctimer;
+	'combo_is_allowed = false;
+	end;
+}
+
+1@eom,4,1,0	script	#mk_hpcheck	CLEAR_NPC,{
+	end;
+OnStart:
+	initnpctimer;
+	end;
+OnTimer6000:
+	getunitdata 'boss_id, .@data;
+	.@hp = .@data[UMOB_HP];
+	if ('boss_hp < .@hp) {
+		initnpctimer;
+		end;
+	}
+	.@hp_a = 'boss_hp - .@hp;
+	if (.@hp_a > 1000000) {
+		if (.@hp_a > 200000) {
+			.@hp_b = .@hp + (.@hp_a - 200000) * 3;
+			.@hp_b = min(80000000, .@hp_b);
+			setunitdata 'boss_id, UMOB_HP, .@hp_b;
+			mapannounce 'map_eom$, "Nidhogg: Wow, his regenerative power is unheard of! Don't let him regenerate again!", bc_map, 0x00ff00;
+		}
+		unitskilluseid 'boss_id, "AL_HEAL",11;
+		getunitdata 'boss_id, .@data;
+		'boss_hp = .@data[UMOB_HP];
+		initnpctimer;
+		end;
+	}
+	'boss_hp = .@hp;
+
+	switch( 'boss_phase ) {	// process by phase instead of (officially) hp, just in case
+	case 1:
+		if (.@hp < 40000000)
+			donpcevent instance_npcname("#despair_god_main") + "::OnPhase02";
+		break;
+	case 2:
+		break;
+	case 3:
+		if (.@hp > 100000 && .@hp < 30000000)
+			donpcevent instance_npcname("#mk_trap") + "::OnTrap";
+		break;
+	}
+	initnpctimer;
+	end;
+}
+
+1@eom,1,1,0	script	#demigod_event_1	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "Mwah hah, dodge this if you can!";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	end;
+OnTimer3000:
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	end;
+OnTimer5000:
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_VERMILION",21,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	end;
+OnTimer7000:
+	stopnpctimer;
+	unitskilluseid 'boss_id, "CR_REFLECTSHIELD",1;
+	if ('combo_is_allowed)
+		donpcevent instance_npcname("#mk_combo") + "::OnEvent";
+	end;
+}
+
+1@eom,1,1,0	script	#demigod_event_2	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "A rhapsody for weak souls...";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	end;
+OnTimer3000:
+	getunitdata 'boss_id, .@data;
+	'bossx = .@data[UMOB_X];
+	'bossy = .@data[UMOB_Y];
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-2),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+2),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+2),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-2),-50;
+	end;
+OnTimer4000:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-6),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+6),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+6),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-6),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-4),('bossy+4),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-4),('bossy-4),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+4),('bossy+4),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+4),('bossy-4),-50;
+	end;
+OnTimer5000:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-10),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+10),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+10),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-10),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-8),('bossy+8),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-8),('bossy-8),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+8),('bossy+8),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+8),('bossy-8),-50;
+	end;
+OnTimer6000:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-16),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+16),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+16),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-16),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-12),('bossy+12),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-12),('bossy-12),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+12),('bossy+12),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+12),('bossy-12),-50;
+	end;
+OnTimer7000:
+	stopnpctimer;
+	if ('combo_is_allowed)
+		donpcevent instance_npcname("#mk_combo") + "::OnEvent";
+	end;
+}
+
+1@eom,1,1,0	script	#demigod_event_3	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "For whom the fugue is played? For whom the requiem is played?";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	end;
+OnTimer3000:
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	end;
+OnTimer5000:
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_METEOR",5,(.@data[UMOB_X]-5),.@data[UMOB_Y],-50;
+	unitskillusepos 'boss_id,"WZ_METEOR",5,(.@data[UMOB_X]+5),.@data[UMOB_Y],-50;
+	unitskillusepos 'boss_id,"WZ_METEOR",5,.@data[UMOB_X],(.@data[UMOB_Y]+5),-50;
+	unitskillusepos 'boss_id,"WZ_METEOR",5,.@data[UMOB_X],(.@data[UMOB_Y]-5),-50;
+	end;
+OnTimer9000:
+	unittalk 'boss_id, "Burn to ashes!";
+	end;
+OnTimer11000:
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_VERMILION",21,.@data[UMOB_X],.@data[UMOB_Y],-50;	// assuming position on (0,0) is self
+	end;
+OnTimer13000:
+	stopnpctimer;
+	if ('combo_is_allowed)
+		donpcevent instance_npcname("#mk_combo") + "::OnEvent";
+	end;
+}
+
+1@eom,4,3,0	script	#moc_origin	CLEAR_NPC,{
+	end;
+OnEnable:
+	enablenpc instance_npcname("#moc_origin");
+	monster 'map_eom$,114,198, "Morroc of the Genesis", 3098,1, instance_npcname("#moc_origin") + "::OnMobDead1";	// MM_MOROCC_ORIGIN
+	'miniboss_id[0] = $@mobid[0];
+	'miniboss_id[1] = 0;
+	initnpctimer;
+	end;
+OnTimer1000:
+	donpcevent instance_npcname("#moc_origin") + "::OnOriginheal";
+	if ('miniboss_id[0] < 1)
+		end;
+	getunitdata 'miniboss_id[0], .@data;
+	if (.@data[UMOB_HP] < 2200000) {
+		if ('miniboss_id[1] == 0) {
+			monster 'map_eom$,86,199, "Morroc of the Sabbath", 3099,1, instance_npcname("#moc_origin") + "::OnMobDead2";	// MM_MOROCC_REST
+			'miniboss_id[1] = $@mobid[0];
+		}
+	}
+	end;
+OnTimer2000:
+	initnpctimer;
+	end;
+
+OnOriginheal:
+	for ( .@i = 0; .@i < 11; .@i++ ) {
+		unitskilluseid 'boss_id, "AL_HEAL",11;
+		sleep 200;
+		if ('boss_id == 0)
+			end;
+	}
+	end;
+
+OnMobDead1:
+	'miniboss_id[0] = 0;
+	callsub S_Dead;
+OnMobDead2:
+	'miniboss_id[1] = 0;
+	callsub S_Dead;
+S_Dead:
+	if ('miniboss_id[1] == 0 && 'miniboss_id[0] > 0) {	// todo, custom text
+		unittalk 'miniboss_id[0], "---!!!";
+		setunitdata 'miniboss_id[0], UMOB_HP, 3000000;
+		stopnpctimer instance_npcname("#moc_meddling");
+	}
+	else if ('miniboss_id[1] == 0 && 'miniboss_id[0] == 0) {
+		donpcevent instance_npcname("#moc_origin") + "::OnEnd";
+		stopnpctimer instance_npcname("#moc_meddling");
+		donpcevent instance_npcname("#despair_god_main") + "::OnPhase03";
+	}
+	else {
+		unittalk 'miniboss_id[1], "I'll put you to rest. It's my mercy!!!"; // todo, custom text
+		setunitdata 'miniboss_id[1], UMOB_HP, 1000000;
+		donpcevent instance_npcname("#moc_meddling") + "::OnStart";
+	}
+	end;
+
+OnEnd:
+	stopnpctimer;
+	disablenpc instance_npcname("#moc_origin");
+	killmonster 'map_eom$, instance_npcname("#moc_origin") + "::OnMobDead1";
+	killmonster 'map_eom$, instance_npcname("#moc_origin") + "::OnMobDead2";
+	end;
+}
+
+1@eom,1,1,0	script	#moc_meddling	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	getunitdata 'miniboss_id[1], .@data;
+	if (.@data[UMOB_HP] > 100000)
+		unitskillusepos 'miniboss_id[1],"WZ_METEOR",9,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	end;
+OnTimer5000:
+	initnpctimer;
+	end;
+}
+
+1@eom,4,6,0	script	#mk_trap	CLEAR_NPC,{
+	end;
+OnTrap:
+	.@label$ = instance_npcname("#mk_trap") + "::OnMobDead";
+	if (mobcount( 'map_eom$, .@label$ ) < 3) {
+		getunitdata 'boss_id, .@data;
+		monster 'map_eom$,.@data[UMOB_X]-4,.@data[UMOB_Y], "Frenzied Kasa", 3089,1, .@label$;	// MM_LOCO_KASA
+		monster 'map_eom$,.@data[UMOB_X],.@data[UMOB_Y]-4, "Frenzied Kasa", 3089,1, .@label$;
+		monster 'map_eom$,.@data[UMOB_X]+4,.@data[UMOB_Y], "Frenzied Kasa", 3089,1, .@label$;
+		monster 'map_eom$,.@data[UMOB_X],.@data[UMOB_Y]+4, "Frenzied Kasa", 3089,1, .@label$;
+	}
+	end;
+OnMobDead:
+	end;
+}
+
+1@eom,102,222,3	script	#morocc_god	3097,{
+	end;
+OnStart:
+	enablenpc instance_npcname("#morocc_god");
+	initnpctimer;
+	end;
+OnTimer2000:
+	mapannounce 'map_eom$, "This is getting more interesting. *Snicker*", bc_map, 0xff0000;
+	end;
+OnTimer6000:
+	mapannounce 'map_eom$, "Hey, you don't think this is over already, do you?", bc_map, 0xff0000;
+	end;
+OnTimer10000:
+	disablenpc instance_npcname("#morocc_god");
+	end;
+OnTimer12000:
+	donpcevent instance_npcname("#despair_main") + "::OnStart";
+	end;
+OnTimer13000:
+	unittalk 'boss_id, "What are you waiting for?!";
+	end;
+OnTimer14000:
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	end;
+OnTimer16000:
+	mapannounce 'map_eom$, "I'll take your blood!", bc_map, 0xff0000;
+	end;
+OnTimer17000:
+	stopnpctimer;
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"NPC_WIDESUCK",1,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	donpcevent instance_npcname("#ma_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#despair_main	-1,{
+	end;
+OnStart:
+	enablenpc instance_npcname("#despair_main");
+	monster 'map_eom$,101,194, "Despair God Morroc",3097,1, instance_npcname("#despair_main") + "::OnMobDead";	// MM_MOROCC_ADT
+	'boss_id = $@mobid[0];
+	end;
+OnMobDead:
+	disablenpc instance_npcname("#despair_main");
+	killmonster 'map_eom$, instance_npcname("#despair_main") + "::OnMobDead";
+	stopnpctimer instance_npcname("#morocc_god");
+	stopnpctimer instance_npcname("#ma_combo");
+	stopnpctimer instance_npcname("#despair_event_1");
+	stopnpctimer instance_npcname("#despair_event_2");
+	stopnpctimer instance_npcname("#despair_event_3");
+	stopnpctimer instance_npcname("#despair_event_4");
+	stopnpctimer instance_npcname("#despair_event_5");
+	mapannounce 'map_eom$, "D-don't think... th-this... is over.. You're... already... time...", bc_map, 0xff0000;
+	initnpctimer;
+
+	'step = 11;
+	donpcevent instance_npcname("#demon_god_variables") + "::OnVariableReset";
+	end;
+OnTimer2000:
+	stopnpctimer;
+	enablenpc instance_npcname("Nidhogg#eomnyd04");
+	end;
+
+OnTest_hp:
+	if ('boss_id && mobcount( 'map_eom$, instance_npcname("#despair_main") + "::OnMobDead" ) > 0)
+		setunitdata 'boss_id, UMOB_HP, 2000000;
+	end;
+}
+
+1@eom,4,8,0	script	#ma_combo	CLEAR_NPC,{
+	end;
+OnStart:
+	initnpctimer;
+	end;
+OnTimer10000:
+	donpcevent instance_npcname("#despair_event_" + rand(1,5)) + "::OnEvent";
+	stopnpctimer;
+	end;
+}
+
+1@eom,1,1,0	script	#despair_event_1	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "I'll burn you slowly and painfully.";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	end;
+OnTimer3000:
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	end;
+OnTimer5000:
+	stopnpctimer;
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_METEOR",11,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	donpcevent instance_npcname("#ma_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#despair_event_2	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "Can you hear the rhapsody? It's the sound of your soul writhing and screaming in pain!";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	end;
+OnTimer3000:
+	getunitdata 'boss_id, .@data;
+	'bossx = .@data[UMOB_X];
+	'bossy = .@data[UMOB_Y];
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-2),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+2),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+2),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-2),-50;
+	end;
+OnTimer4000:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-6),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+6),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+6),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-6),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-4),('bossy+4),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-4),('bossy-4),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+4),('bossy+4),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+4),('bossy-4),-50;
+	end;
+OnTimer5000:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-10),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+10),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+10),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-10),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-8),('bossy+8),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-8),('bossy-8),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+8),('bossy+8),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+8),('bossy-8),-50;
+	end;
+OnTimer6000:
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-16),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+16),'bossy,-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy+16),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,'bossx,('bossy-16),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-12),('bossy+12),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx-12),('bossy-12),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+12),('bossy+12),-50;
+	unitskillusepos 'boss_id,"MG_THUNDERSTORM",20,('bossx+12),('bossy-12),-50;
+	end;
+OnTimer7000:
+	stopnpctimer;
+	donpcevent instance_npcname("#ma_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#despair_event_3	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "This is the thunderbolt of death!";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_WIDEWEB",1;
+	end;
+OnTimer4000:
+	unitskilluseid 'boss_id, "NPC_WIDEFREEZE",5;
+	end;
+OnTimer6000:
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_VERMILION",5,(.@data[UMOB_X]-7),.@data[UMOB_Y],-50;
+	unitskillusepos 'boss_id,"WZ_VERMILION",5,(.@data[UMOB_X]+7),.@data[UMOB_Y],-50;
+	unitskillusepos 'boss_id,"WZ_VERMILION",5,.@data[UMOB_X],(.@data[UMOB_Y]+7),-50;
+	unitskillusepos 'boss_id,"WZ_VERMILION",5,.@data[UMOB_X],(.@data[UMOB_Y]-7),-50;
+	end;
+OnTimer10000:
+	unittalk 'boss_id, "Burn and make beautiful flames!";
+	end;
+OnTimer12000:
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_VERMILION",21,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	end;
+OnTimer14000:
+	stopnpctimer;
+	donpcevent instance_npcname("#ma_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#despair_event_4	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "I'll take your life.";
+	unitskilluseid 'boss_id, "NPC_FLAMECROSS",1;
+	end;
+OnTimer1000:
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"NPC_WIDESUCK",1,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	end;
+OnTimer5000:
+	stopnpctimer;
+	donpcevent instance_npcname("#ma_combo") + "::OnStart";
+	end;
+}
+
+1@eom,1,1,0	script	#despair_event_5	-1,{
+	end;
+OnEvent:
+	initnpctimer;
+	unittalk 'boss_id, "*Chuckle*";
+	end;
+OnTimer2000:
+	unitskilluseid 'boss_id, "NPC_FIRESTORM",3;
+	end;
+OnTimer4000:
+	getunitdata 'boss_id, .@data;
+	unitskillusepos 'boss_id,"WZ_FIREPILLAR",10,.@data[UMOB_X],.@data[UMOB_Y],-50;
+	end;
+OnTimer8000:
+	stopnpctimer;
+	donpcevent instance_npcname("#ma_combo") + "::OnStart";
+	end;
+}
+
+1@eom,103,194,3	script	Nidhogg#eomnyd04	4_F_NYDHOG,{
+	if ('step < 11)
+		end;
+	if (isbegin_quest(7597) == 0 && checkquest(7593,HUNTING) == 2) {
+		mes "[Nidhogg]";
+		mes "I don't know what to say.";
+		mes "We stopped the god-in-waiting.";
+		mes "We accomplished our goal.";
+		mes "But I'm still unnerved.";
+		cutin "ep14_nyd03.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "This world is created in the mind of Morroc's.";
+		mes "He'll live forever in this garden he couldn't finish.";
+		cutin "ep14_nyd02.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "He probably doesn't know his body is destroyed forever.";
+		mes "He was far too ambitious, even for him.";
+		mes "He wanted to create a new world and become its creator,";
+		next;
+		mes "[Nidhogg]";
+		mes "but he couldn't create anything on his own.";
+		mes "He abandoned his Demon body, just to become a mere facsimile of an existing god.";
+		cutin "ep14_nyd03.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "He took the shape of a man.";
+		mes "He wasn't creative enough to reinvent the concept of God.";
+		mes "He was a paradox.";
+		next;
+		mes "[Nidhogg]";
+		mes "Now we need to get out of this trap in time and end; to reality.";
+		mes "This world only exists in the Demon God's mind. The same day repeats forever.";
+		next;
+		mes "[Nidhogg]";
+		mes "Everyone who enters this world will be dragged into the same loop.";
+		mes "In that sense, he succeeded in making his own world.";
+		cutin "ep14_nyd02.bmp",2;
+		next;
+		mes "[Nidhogg]";
+		mes "Today's despair will repeat day after day.";
+		mes "Even though we know this, we'll come back to walk the same path again. I hope I'll be able to fight by you every time...";
+		cutin "ep14_nyd03.bmp",2;
+		next;
+		cutin "ep14_nyd04.bmp",2;
+		mes "[Nidhogg]";
+		mes "I've talked too much. The Commander must be waiting. Let me validate your feat, so you can report to him.";
+		mes "You did great today.";
+		if (isbegin_quest(7593) == 1) {
+			erasequest 7593;// Demon God Subjugation
+			setquest 7597;// Fall of the False God
+		}
+		if (checkquest(7601,HUNTING) == 1)
+			erasequest 7601;
+		if (isbegin_quest(7602) > 0)
+			erasequest 7602;// Temple of the Demon God Phase 1 Completed
+		if (isbegin_quest(7603) == 1)
+			erasequest 7603;
+		if (isbegin_quest(7604) > 0)
+			erasequest 7604;// Temple of the Demon God Phase 2 Completed
+		if (isbegin_quest(7596) == 1)
+			erasequest 7596;
+	}
+	else {	// todo, custom text
+		mes "[Nidhogg]";
+		mes "...It feels like things are not over yet,";
+		mes "This is very close to Morroc's spiritual world,";
+		mes "He should be here to keep thinking about the past!";
+		cutin "ep14_nyd03.bmp",2;
+	}
+	next;
+	select("Exit.");
+	mes "[Nidhogg]";
+	mes "Of course. You must be exhausted.";
+	mes "Let me send you to the other members of your Expedition, free of charge.";
+	close2;
+	warp "moro_vol",91,87;
+	end;
+}
+
+1@eom,5,1,0	script	Little Helper#eomtest	4_ENERGY_BLUE,{
+	mes "What?";
+	next;
+	if (callfunc("F_GM_NPC",1854,0) < 1) {
+		mes "Wrong.";
+		close;
+	}
+	mes "What Boss?";
+	next;
+	switch( select( "Brinaranea", "Muspellskoll", "Demigod", "Despair God" ) ) {
+	case 1:
+		mes "Brinaranea health was set to 2.000.000.";
+		donpcevent instance_npcname("Brinaranea#brinpc01") + "::OnTest_hp";
+		close;
+	case 2:
+		mes "Muspellskoll health was set to 2.000.000.";
+		donpcevent instance_npcname("#skollmaster") + "::OnTest_hp";
+		close;
+
+	case 3:
+		mes "Demigod health was set to 2.000.000.";
+		donpcevent instance_npcname("#despair_god_main") + "::OnTest_hp";
+		close;
+
+	case 4:
+		mes "Despair God health was set to 2.000.000.";
+		donpcevent instance_npcname("#despair_main") + "::OnTest_hp";
+		close;
+	}
+	end;
+}

+ 808 - 0
npc/re/instances/WaveMode.txt

@@ -0,0 +1,808 @@
+//===== rAthena Script =======================================
+//= Wave Mode
+//===== Description: =========================================
+//= [Walkthrough Conversion]
+//= Wave Mode Forest and Sky Instances
+//- Officially monsters can use their skills
+//    (NPC_SUMMONSLAVE, at least). NPC_EMOTION and
+//    NPC_EMOTION_ON have been blocked since it disrupts the
+//    walk system of the instance on rAthena.
+//- Note: The instance is currently disabled on KRO.
+//===== Changelogs: ==========================================
+//= 1.0 First version. [Capuche]
+//============================================================
+
+// Simple function to move the monster when idle.
+// Move the monster to the next coordinates + end the script on successful; kill the monster + return on failure
+// callfunc( "F_mobidle", <npc name + idle label>, <size coord>, <defined x array>, <x shift>,  <defined y array>, <defined spot-spot distance array> );
+function	script	F_mobidle	{
+	sleep2 1000;	// stop if no RID
+
+	.@game_id = getattachedrid();
+	.@dist_min = 300;
+	.@size = getarg(1);
+	.@dx = getarg(3);
+	getunitdata .@game_id, .@data;
+
+	for ( .@i = 0; .@i < .@size; .@i++ ) {
+		.@dist_to_spot[.@i] = distance( .@data[UMOB_X], .@data[UMOB_Y], (getelementofarray( getarg(2),.@i ) + .@dx), getelementofarray( getarg(4),.@i ) );
+		if (.@dist_min >= .@dist_to_spot[.@i]) {
+			.@dist_min = .@dist_to_spot[.@i];
+			.@index = .@i;
+		}
+	}
+
+	if (.@dist_min <= 1) {
+		.@index++;
+		if (.@index >= .@size) {
+			unitskilluseid .@game_id,301,1,.@game_id,1,false,41;	// SA_INSTANTDEATH
+			return;
+		}
+	}
+	else if (.@index < (.@size -1)) {
+		.@total[0] = .@dist_min + getelementofarray( getarg(5), .@index );
+		.@total[1] = .@dist_to_spot[.@index + 1] + getelementofarray( getarg(5), .@index+1 );
+		if (.@total[0] > .@total[1])
+			.@index = .@index + 1;
+	}
+
+	if (.@dist_to_spot[.@index] > 14) {
+		unitkill .@game_id;
+		end;
+	}
+	if (!.@data[UMOB_TARGETID]) {
+		unitwalk .@game_id, (getelementofarray( getarg(2),.@index ) + .@dx), getelementofarray( getarg(4),.@index );
+		sleep2 50;	// for now a delay between unitwalk and mob_setidleevent is needed
+	}
+	mob_setidleevent .@game_id, getarg(0);
+	end;
+}
+
+prontera,146,75,1	script	Zonda Rep#pron	4_F_ZONDAGIRL,{
+	.@player_name$ = strcharinfo(0);
+	getmapxy .@map_name$,.@x,.@y, BL_PC;
+
+	if (is_party_leader() == true) {
+		.@party_id = getcharid(1);
+		getpartymember .@party_id, 1;
+		getpartymember .@party_id, 2;
+		for ( .@i = 0; .@i < $@partymembercount; .@i++ ) {
+			if (isloggedin($@partymemberaid[.@i], $@partymembercid[.@i]) == 1)
+				.@count_online++;
+		}
+		.@menu_entry$ = "Request entry.";
+	}
+
+	mes "[Belka]";
+	mes "Welcome to Zonda, where innovation begins. What can I do for you?";
+	next;
+	switch( select( "Why are you here?", .@menu_entry$, "Enter ^6B9900<Wave Mode - Forest>^000000.", "Enter ^6B9900<Wave Mode - Sky>^000000.", "Cancel." ) ) {
+	case 1:
+		mes "[Belka]";
+		mes "We now offer a new service. Have you heard about the dimensional rifts?";
+		next;
+		mes "[Belka]";
+		mes "In case you haven't, many organizations and scientists study the rifts formed between dimensions.";
+		next;
+		mes "[Belka]";
+		mes "One of them is my company, Zonda, and after long, painstaking research...";
+		next;
+		mes "[Belka]";
+		mes "We've developed two different dimensional rifts that we call Wave Modes - Forest and Sky!";
+		next;
+		mes "[Belka]";
+		mes "Do you have any questions about Zonda's ambitious new project, Wave Mode?";
+		while(true) {
+			next;
+			switch( select( "About ^6B9900<Wave Mode - Forest>^000000", "About ^6B9900<Wave Mode - Sky>^000000", "No." ) ) {
+			case 1:
+				mes "[Belka]";
+				mes "The ^6B9900<Wave Mode - Forest>^000000";
+				mes "Introducing the first Wave Mode service, Zonda's objective is to work with your party members to keep monster waves from reaching the other side of the bridge.";
+				next;
+				mes "[Belka]";
+				mes "Monsters will advance without fighting, but the party will fail if 20 monsters are let go..";
+				break;
+			case 2:
+				mes "[Belka]";
+				mes "The ^6B9900<Wave Mode - Sky>^000000";
+				mes "Available once a day. Like the other Wave Mode, keep the monsters away from reaching the other side of the map.";
+				next;
+				mes "[Belka]";
+				mes "Feel free to come back with your party.";
+				break;
+			case 3:
+				mes "[Belka]";
+				mes "Thank you for visiting Zonda, where innovation begins.";
+				close;
+			}
+			next;
+			mes "[Belka]";
+			mes "Any other questions?";
+		}
+	case 2:
+		mes "[Belka]";
+		mes "Which Wave Mode would you like to enter: Forest or Sky?";
+		next;
+		.@s = select( "Enter ^6B9900<Wave Mode - Forest>^000000.", "Enter ^6B9900<Wave Mode - Sky>^000000." ) - 1;
+		setarray .@instance_name$[0], "Wave Mode - Forest", "Wave Mode - Sky";
+		mes "[Belka]";
+		mes "" + .@count_online + " party " + (.@count_online == 1 ? "member" : "members") + " found " + .@player_name$ + ", right? To enter the ^6B9900<" + .@instance_name$[.@s] + ">^000000, please sign here.";
+		next;
+		select("Sign.");
+		mes "[Belka]";
+		mes "" + .@player_name$ + " has requested to enter the ^6B9900<" + .@instance_name$[.@s] + ">^000000. Please come back when it's your turn to enter.";
+		if (instance_create(.@instance_name$[.@s]) < 0) {
+			mes "Party Name: " + getpartyname( getcharid(1) );
+			mes "Party Leader: " + strcharinfo(0);
+			mes "^0000ff" + .@instance_name$[.@s] + " ^000000 - Reservation Failed.";
+			close;
+		}
+		close;
+	case 3:
+		switch( instance_enter("Wave Mode - Forest") ) {
+		case IE_OTHER:
+			mes "[Belka]";
+			mes "An unknown error has occurred.";
+			close;
+		case IE_NOINSTANCE:
+		case IE_NOMEMBER:
+			mes "[Belka]";
+			mes "Please wait for ^6B9900<Wave Mode - Forest>^000000 stabilization.";
+			close;
+		case IE_OK:
+			mapannounce .@map_name$, "" + .@player_name$ + " of the party " + getpartyname(getcharid(1)) + " is entering <Wave Mode - Forest>.", bc_map,0xFF99;
+			// warp "1@def01",50,21;
+			break;
+		}
+		break;
+	case 4:
+		switch( instance_enter("Wave Mode - Sky") ) {
+		case IE_OTHER:
+			mes "[Belka]";
+			mes "An unknown error has occurred.";
+			close;
+		case IE_NOINSTANCE:
+		case IE_NOMEMBER:
+			mes "[Belka]";
+			mes "Currently the ^6B9900<Wave Mode - Sky>^000000 is being stabilized for your convenience. Please wait.";
+			close;
+		case IE_OK:
+			mapannounce .@map_name$, "" + .@player_name$ + " of the party " + getpartyname(getcharid(1)) + " is entering <Wave Mode - Sky>.", bc_map,0xFF99;
+			// warp "1@def02",29,35;
+			break;
+		}
+		break;
+	case 5:
+		mes "[Belka]";
+		mes "Thank you for visiting Zonda, where innovation begins.";
+		close;
+	}
+	wave_mode_map$ = .@map_name$;
+	wave_mode_x = .@x;
+	wave_mode_y = .@y;
+	end;
+}
+payon,166,98,1	duplicate(Zonda Rep#pron)	Zonda Rep#pay	4_F_ZONDAGIRL
+moc_para01,45,89,3	duplicate(Zonda Rep#pron)	Zonda Rep#para	4_F_ZONDAGIRL
+morocc,168,271,4	duplicate(Zonda Rep#pron)	Zonda Rep#mor	4_F_ZONDAGIRL
+
+
+// Wave mode forest
+1@def01,50,21,0	script	#wave_mode_forest_entrance	HIDDEN_WARP_NPC,1,1,{
+	end;
+OnTouch:
+	disablenpc instance_npcname("#wave_mode_forest_entrance");
+	initnpctimer;
+	end;
+OnTimer2000:
+	mapannounce 'map_def01$, "We would like to thank all loyal customers of the Cool Event Corporation.", bc_map;
+	end;
+OnTimer7000:
+	mapannounce 'map_def01$, "<Wave mode - Forest> prevent monsters from reaching the other side of the bridge.", bc_map;
+	end;
+OnTimer12000:
+	mapannounce 'map_def01$, "If 20 monsters reach the other side, the game is over.", bc_map;
+	end;
+OnTimer17000:
+	mapannounce 'map_def01$, "Ok, here they come.", bc_map;
+	end;
+OnTimer22000:
+	stopnpctimer;
+	donpcevent instance_npcname("#wave_mode_forest_system") + "::OnStart";
+	end;
+}
+
+1@def01,1,1,0	script	#wave_mode_forest_system	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	end;
+OnTimer1000:
+	mapannounce 'map_def01$, "3", bc_map;
+	end;
+OnTimer2000:
+	mapannounce 'map_def01$, "2", bc_map;
+	end;
+OnTimer3000:
+	mapannounce 'map_def01$, "1", bc_map;
+	end;
+OnTimer4000:
+	'wave++;
+	if ('wave % 5)
+		mapannounce 'map_def01$, "-- Wave " + 'wave + " --", bc_map;
+	else
+		mapannounce 'map_def01$, "!! Champions summoned !!", bc_map;
+	donpcevent 'npc_name$ + "::OnSpawn";
+	end;
+OnTimer24000:
+	mapannounce 'map_def01$, "Next monsters will come out soon. Get ready.", bc_map;
+	initnpctimer;
+	end;
+OnStop:
+	stopnpctimer;
+	end;
+}
+
+1@def01,1,1,0	script	#wave_mode_forest_spawn	-1,{
+	end;
+OnSpawn:
+	switch( 'wave % 70 ) {
+	case 1:
+		'mob_id = 2401;	// G_PORING
+		break;
+	case 2:
+		'mob_id = 2582;	// G_LUNATIC
+		break;
+	case 3:
+		'mob_id = 2573;	// G_CHONCHON
+		break;
+	case 4:
+		'mob_id = 2590;	// G_ROCKER
+		break;
+	case 5:
+		'mob_id = 2699;	// C1_PORING
+		break;
+
+	case 6:
+		'mob_id = 2577;	// G_FABRE
+		break;
+	case 7:
+		'mob_id = 1747;	// G_SNAKE
+		break;
+	case 8:
+		'mob_id = 2595;	// G_STAINER
+		break;
+	case 9:
+		'mob_id = 2576;	// G_CREAMY
+		break;
+	case 10:
+		'mob_id = 2678;	// C3_RODA_FROG
+		break;
+
+	case 11:
+		'mob_id = 2572;	// G_CARAMEL
+		break;
+	case 12:
+		'mob_id = 1603;	// G_BIGFOOT
+		break;
+	case 13:
+		'mob_id = 2589;	// G_POPORING
+		break;
+	case 14:
+		'mob_id = 2578;	// G_HORN
+		break;
+	case 15:
+		'mob_id = 2670;	// C5_SCORPION
+		break;
+
+	case 16:
+		'mob_id = 2601;	// G_YOYO
+		break;
+	case 17:
+		'mob_id = 2575;	// G_COCO
+		break;
+	case 18:
+		'mob_id = 2583;	// G_MARTIN
+		break;
+	case 19:
+		'mob_id = 2600;	// G_WOLF
+		break;
+	case 20:
+		'mob_id = 2705;	// C2_POISON_SPORE
+		break;
+
+	case 21:
+		'mob_id = 1430;	// G_ARGOS
+		break;
+	case 22:
+		'mob_id = 2597;	// G_STEEL_CHONCHON
+		break;
+	case 23:
+		'mob_id = 1431;	// G_BAPHOMET_
+		break;
+	case 24:
+		'mob_id = 2591;	// G_SAVAGE
+		break;
+	case 25:
+		'mob_id = 2857;	// C5_DENIRO
+		break;
+
+	case 26:
+		'mob_id = 1457;	// G_MANTIS
+		break;
+	case 27:
+		'mob_id = 1424;	// G_SIDE_WINDER
+		break;
+	case 28:
+		'mob_id = 1429;	// G_ARGIOPE
+		break;
+	case 29:
+		'mob_id = 1441;	// G_PENOMENA
+		break;
+	case 30:
+		'mob_id = 2648;	// C3_SOLDIER_SKELETON
+		break;
+
+	case 31:
+		'mob_id = 1422;	// G_HUNTER_FLY
+		break;
+	case 32:
+		'mob_id = 2585;	// G_MOLE
+		break;
+	case 33:
+		'mob_id = 2592;	// G_SIORAVA
+		break;
+	case 34:
+		'mob_id = 2571;	// G_BUTOIJO
+		break;
+	case 35:
+		'mob_id = 2673;	// C3_SAVAGE
+		break;
+
+	case 36:
+		'mob_id = 2574;	// G_CIVIL_SERVANT
+		break;
+	case 37:
+		'mob_id = 1459;	// G_MARIONETTE
+		break;
+	case 38:
+		'mob_id = 1565;	// G_WILD_GINSENG
+		break;
+	case 39:
+		'mob_id = 2602;	// G_ZIPPER_BEAR
+		break;
+	case 40:
+		'mob_id = 2644;	// C4_STALACTIC_GOLEM
+		break;
+
+	case 41:
+		'mob_id = 2588;	// G_PITMAN
+		break;
+	case 42:
+		'mob_id = 1624;	// G_WASTE_STOVE
+		break;
+	case 43:
+		'mob_id = 2570;	// G_BREEZE
+		break;
+	case 44:
+		'mob_id = 1573;	// G_ELDER
+		break;
+	case 45:
+		'mob_id = 2811;	// C3_GRAND_PECO
+		break;
+
+	case 46:
+		'mob_id = 2598;	// G_UNGOLIANT
+		break;
+	case 47:
+		'mob_id = 1606;	// G_GARM_BABY
+		break;
+	case 48:
+		'mob_id = 1794;	// G_ROWEEN
+		break;
+	case 49:
+		'mob_id = 2596;	// G_STAPO
+		break;
+	case 50:
+		'mob_id = 2838;	// C5_EVIL_DRUID
+		break;
+
+	case 51:
+		'mob_id = 2569;	// G_ANOPHELES
+		break;
+	case 52:
+		'mob_id = 2584;	// G_MINERAL
+		break;
+	case 53:
+		'mob_id = 2599;	// G_WILD_RIDER
+		break;
+	case 54:
+		'mob_id = 1531;	// G_EVIL_CLOUD_HERMIT
+		break;
+	case 55:
+		'mob_id = 2612;	// C5_WOOD_GOBLIN
+		break;
+
+	case 56:
+		'mob_id = 2587;	// G_OBSIDIAN
+		break;
+	case 57:
+		'mob_id = 1564;	// G_WICKED_NYMPH
+		break;
+	case 58:
+		'mob_id = 2586;	// G_NERAID
+		break;
+	case 59:
+		'mob_id = 1483;	// G_RYBIO
+		break;
+	case 60:
+		'mob_id = 2888;	// C2_BANASPATY
+		break;
+
+	case 61:
+		'mob_id = 2593;	// G_SIROMA
+		break;
+	case 62:
+		'mob_id = 2580;	// G_KAHO
+		break;
+	case 63:
+		'mob_id = 1600;	// G_HEATER
+		break;
+	case 64:
+		'mob_id = 1791;	// G_GALION
+		break;
+	case 65:
+		'mob_id = 2629;	// C3_UNGOLIANT
+		break;
+
+	case 66:
+		'mob_id = 2581;	// G_LUDE
+		break;
+	case 67:
+		'mob_id = 2579;	// G_HYLOZOIST
+		break;
+	case 68:
+		'mob_id = 1549;	// G_LAVA_GOLEM
+		break;
+	case 69:
+		'mob_id = 2594;	// G_SNOWIER
+		break;
+	default:
+		'mob_id = 2730;	// C2_NOVUS
+		break;
+	}
+	initnpctimer;
+	end;
+OnTimer1000:
+	stopnpctimer;
+	if (('wave % 5) == 0) {	// champion
+		donpcevent 'npc_name$ + "::OnSpawn0";
+		donpcevent 'npc_name$ + "::OnSpawn1";
+		donpcevent 'npc_name$ + "::OnSpawn2";
+		donpcevent 'npc_name$ + "::OnSpawn3";
+		donpcevent 'npc_name$ + "::OnSpawn4";
+		end;
+	}
+	if ('wave == 1)	// first wave at x = 51
+		.@dx = 3;
+	else
+		.@dx = 2;
+	for ( .@i = 0; .@i < 24; .@i++ ) {
+		donpcevent 'npc_name$ + "::OnSpawn" + .@dx;
+		sleep 300;
+	}
+	// total ~7 secs
+	end;
+OnSpawn0: callsub( S_Spawn, 0 );
+OnSpawn1: callsub( S_Spawn, 1 );
+OnSpawn2: callsub( S_Spawn, 2 );
+OnSpawn3: callsub( S_Spawn, 3 );
+OnSpawn4: callsub( S_Spawn, 4 );
+S_Spawn:
+	.@x = 48 + getarg(0);
+	monster 'map_def01$,.@x,74, "Invader!", 'mob_id,1;
+	.@gid = $@mobid[0];
+	setunitdata .@gid, UMOB_MODE, ( MD_CANMOVE|MD_NORANDOMWALK );
+	setunitdata .@gid, UMOB_IGNORE_CELL_STACK_LIMIT, true;
+	mob_setidleevent .@gid, 'npc_name$ + "::OnIdle" + getarg(0);
+	end;
+
+OnIdle0: callsub( S_Idle, 0 );
+OnIdle1: callsub( S_Idle, 1 );
+OnIdle2: callsub( S_Idle, 2 );
+OnIdle3: callsub( S_Idle, 3 );
+OnIdle4: callsub( S_Idle, 4 );
+S_Idle:
+	callfunc( "F_mobidle", ('npc_name$ + "::OnIdle" + getarg(0)), 'size_coord, 'x_mob, getarg(0), 'y_mob, 'dist_spot_AZ );
+	'mob_escaped++;
+	if ('mob_escaped <= 20)
+		mapannounce 'map_def01$, "" + 'mob_escaped + " " + ('mob_escaped == 1 ? "monster has" : "monsters have") + " escaped.", bc_map;
+	if ('mob_escaped == 20)
+		donpcevent instance_npcname("#wave_mode_forest_out") + "::OnFail";
+	end;
+}
+
+// 1@def01,50,23,0	script	#wave_mode_forest_warp	WARPNPC,2,2,{
+1@def01,50,30,0	script	#wave_mode_forest_warp	WARPNPC,2,2,{// official warp out
+	end;
+OnTouch:
+	if (wave_mode_map$ == "")
+		warp "prontera",0,0;
+	else {
+		warp wave_mode_map$, wave_mode_x, wave_mode_y;
+		wave_mode_map$ = "";
+		wave_mode_x = wave_mode_y = 0;
+	}
+	end;
+}
+
+1@def01,1,1,0	script	#wave_mode_forest_out	-1,{
+	end;
+OnFail:
+	donpcevent instance_npcname("#wave_mode_forest_system") + "::OnStop";
+
+	mapannounce 'map_def01$, "You have failed the <Wave mode - Forest> challenge.", bc_map;
+	enablenpc instance_npcname("#wave_mode_forest_warp");
+	initnpctimer;
+	end;
+OnTimer1000:
+	mapannounce 'map_def01$, "<Wave mode - Forest> service has closed. You will be returned to the place you entered if you use the warp at the entrance.", bc_map;
+	end;
+OnTimer30000:
+	stopnpctimer;
+	instance_destroy();
+	end;
+
+OnInstanceInit:
+	'wave = 'mob_escaped = 0;
+
+	'map_def01$ = instance_mapname("1@def01");
+	'npc_name$ = instance_npcname("#wave_mode_forest_spawn");
+
+	disablenpc instance_npcname("#wave_mode_forest_system");
+	disablenpc instance_npcname("#wave_mode_forest_warp");
+	disablenpc instance_npcname("#wave_mode_forest_out");
+
+	setarray 'x_mob[0], 48, 48, 48, 48, 48, 48, 48;
+	setarray 'y_mob[0], 74, 65, 56, 48, 40, 31, 23;
+
+	'size_coord = getarraysize('y_mob);
+	for ( .@i = 0; .@i < 'size_coord -1; .@i++ ) {
+		.@dist_mob[.@i+1] = distance( 'x_mob[.@i], 'y_mob[.@i], 'x_mob[.@i+1], 'y_mob[.@i+1] );
+		.@total_mob += .@dist_mob[.@i+1];
+	}
+	for ( .@i = 0; .@i < 'size_coord -1; .@i++ )
+		'dist_spot_AZ[.@i] = .@total_mob - .@dist_mob[.@i];
+	end;
+}
+
+
+// Wave mode sky
+1@def02,30,35,0	script	#wave_mode_sky_entrance	WARPNPC,1,1,{
+	end;
+OnTouch:
+	if ('status_instance == 1)
+		end;
+	else if ('status_instance == 0) {
+		'status_instance = 1;
+		initnpctimer;
+		disablenpc instance_npcname("#wave_mode_sky_entrance");
+	}
+	else if ('status_instance == 2) {
+		if (wave_mode_map$ == "")
+			warp "prontera",0,0;
+		else {
+			warp wave_mode_map$, wave_mode_x, wave_mode_y;
+			wave_mode_map$ = "";
+			wave_mode_x = wave_mode_y = 0;
+		}
+	}
+	end;
+OnTimer4000:
+	stopnpctimer;
+	donpcevent instance_npcname("#wave_mode_sky_system") + "::OnStart";
+	end;
+}
+
+1@def02,1,1,0	script	#wave_mode_sky_system	-1,{
+	end;
+OnStart:
+	initnpctimer;
+	mapannounce 'map_def02$, "We would like to thank all costumers who always use Zonda Agency.", bc_map;
+	end;
+OnTimer1000:
+	mapannounce 'map_def02$, "3", bc_map;
+	end;
+OnTimer2000:
+	mapannounce 'map_def02$, "2", bc_map;
+	end;
+OnTimer3000:
+	mapannounce 'map_def02$, "1", bc_map;
+	end;
+OnTimer4000:
+	'wave_num++;
+	if ('wave_num % 5) {
+		donpcevent 'npc_name_mob$ + "::OnSpawn";
+		donpcevent 'npc_name_mercenary$ + "::OnStart";
+		donpcevent 'npc_name_mercenary$ + "::OnStart";
+	}
+	else {
+		donpcevent 'npc_name_treasure$ + "::OnStart";
+	}
+	end;
+OnTimer24000:
+	mapannounce 'map_def02$, "Next monster wave will come out soon. Get ready.", bc_map;
+	initnpctimer;
+	end;
+OnStop:
+	stopnpctimer;
+	end;
+}
+
+1@def02,1,1,0	script	#wave_mode_sky_treasure	-1,{
+	end;
+OnStart:
+	if ('treasure_num < 5)
+		'treasure_num++;
+	mapannounce 'map_def02$, "!! " + 'treasure_num + " treasure box appeared !!", bc_map;
+	for ( .@i = 0; .@i < 'treasure_num; .@i++ ) {
+		monster 'map_def02$,0,0, "Treasure box",3075,1;	// WA_TREASURE
+		'treasure_gid[.@i] = $@mobid[0];
+	}
+	initnpctimer;
+	end;
+OnTimer16500: callsub( S_Dice, ET_DICE3 );
+OnTimer17500: callsub( S_Dice, ET_DICE2 );
+OnTimer18500: callsub( S_Dice, ET_DICE1 );
+OnTimer19500:
+	for ( .@i = 0; .@i < 'treasure_num; .@i++ ) {
+		if (unitexists('treasure_gid[.@i]))
+			unitskilluseid 'treasure_gid[.@i],301,1,'treasure_gid[.@i],-1;	// SA_INSTANTDEATH
+	}
+	donpcevent 'npc_name_treasure$ + "::OnStop";
+	end;
+
+S_Dice:
+	.@emotion_num = getarg(0);
+	for ( .@i = 0; .@i < 'treasure_num; .@i++ ) {
+		if (unitexists('treasure_gid[.@i]))
+			emotion .@emotion_num, 'treasure_gid[.@i];
+	}
+	end;
+
+OnStop:
+	deletearray 'treasure_gid[0], 'treasure_num;
+	stopnpctimer;
+	end;
+}
+
+1@def02,1,1,0	script	#wave_mode_sky_mercenary	-1,{
+	end;
+OnStart:
+	monster 'map_def02$,29,35, "Mercenary", 3086,1, "",0,AI_WAVEMODE;	// WA_MERCENARY
+	.@gid = $@mobid[0];
+	emotion ET_SURPRISE, .@gid;
+	setunitdata .@gid, UMOB_IGNORE_CELL_STACK_LIMIT, true;
+	mob_setidleevent .@gid, 'npc_name_mercenary$ + "::OnIdle";
+	sleep 45000;
+	if (unitexists(.@gid))
+		unitskilluseid .@gid,301,1,.@gid,1,false;	// SA_INSTANTDEATH
+	end;
+
+OnIdle:
+	callfunc( "F_mobidle", ('npc_name_mercenary$ + "::OnIdle"), 'size_coord, 'x_merc, 0, 'y_merc, 'dist_spot_ZA );
+	end;
+}
+
+1@def02,1,1,0	script	#wave_mode_sky_mob_spawn	-1,{
+	end;
+OnSpawn:
+	mapannounce 'map_def02$, "-- Wave " + 'wave_num + " --", bc_map;
+
+	.@i = ('wave_num % 10) - 1;
+	setarray .@mob_list[0],
+		3076,	// WA_MONSTER_1
+		3077,	// WA_MONSTER_2
+		3078,	// WA_MONSTER_3
+		3079,	// WA_MONSTER_4
+		3080,	// WA_MONSTER_5 (skipped)
+		3081,	// WA_MONSTER_6
+		3082,	// WA_MONSTER_7
+		3083,	// WA_MONSTER_8
+		3084,	// WA_MONSTER_9
+		3085;	// WA_MONSTER_10 (skipped)
+	'mob_id = .@mob_list[.@i];
+	initnpctimer;
+	end;
+OnTimer1000: callsub( S_Spawn, true );	// aggressive
+OnTimer1500: callsub( S_Spawn, false );	// passive
+OnTimer2000: callsub( S_Spawn, true );
+OnTimer2500: callsub( S_Spawn, false );
+OnTimer3000: callsub( S_Spawn, true );
+OnTimer3500: callsub( S_Spawn, false );
+OnTimer4000: callsub( S_Spawn, true );
+OnTimer4500: callsub( S_Spawn, false );
+OnTimer5000: callsub( S_Spawn, true );
+OnTimer5500: callsub( S_Spawn, false );
+OnTimer6000: callsub( S_Spawn, true );
+OnTimer6500: callsub( S_Spawn, false );
+OnTimer7000: callsub( S_Spawn, true );
+OnTimer7500: callsub( S_Spawn, false );
+OnTimer8000: callsub( S_Spawn, true );
+OnTimer8500:
+	stopnpctimer;
+	end;
+
+S_Spawn:
+	monster 'map_def02$,48,67, "Go!", 'mob_id,1;
+	if (getarg(0) == true)
+		setunitdata $@mobid[0], UMOB_MODE, ( MD_CANMOVE|MD_NORANDOMWALK|MD_AGGRESSIVE|MD_CANATTACK );
+	.@gid = $@mobid[0];
+	emotion ET_SURPRISE, .@gid;
+	setunitdata .@gid, UMOB_IGNORE_CELL_STACK_LIMIT, true;
+	mob_setidleevent .@gid, 'npc_name_mob$ + "::OnIdle";
+	end;
+
+OnIdle:
+	// monster are walking to the nearest next spot
+	callfunc( "F_mobidle", ('npc_name_mob$ + "::OnIdle"), 'size_coord, 'x_mob, 0, 'y_mob, 'dist_spot_AZ );
+	'mob_escaped++;
+	if ('mob_escaped <= 20)
+		mapannounce 'map_def02$, "" + 'mob_escaped + " " + ('mob_escaped == 1 ? "monster has" : "monsters have") + " escaped.", bc_map;
+	if ('mob_escaped == 20)
+		donpcevent instance_npcname("#wave_mode_sky_out") + "::OnFail";
+	end;
+}
+
+
+1@def02,1,1,0	script	#wave_mode_sky_out	-1,{
+	end;
+OnFail:
+	// monsters timers continue
+	donpcevent instance_npcname("#wave_mode_sky_system") + "::OnStop";
+
+	mapannounce 'map_def02$, "You have failed the <Wave mode - Sky> challenge.", bc_map;
+	'status_instance = 2;
+	enablenpc instance_npcname("#wave_mode_sky_entrance");
+	initnpctimer;
+	end;
+OnTimer1000:
+	mapannounce 'map_def02$, "<Wave mode - Sky> service has closed. You will be returned to the place you entered if you use the warp at the entrance.", bc_map;
+	end;
+OnTimer30000:
+	stopnpctimer;
+	instance_destroy();
+	end;
+
+OnInstanceInit:
+	deletearray 'treasure_gid[0], 'treasure_num;
+	'wave_num = 'treasure_num = 'status_instance = 'mob_escaped = 0;
+
+	'map_def02$ = instance_mapname("1@def02");
+
+	'npc_name_mob$ = instance_npcname("#wave_mode_sky_mob_spawn");
+	'npc_name_treasure$ = instance_npcname("#wave_mode_sky_treasure");
+	'npc_name_mercenary$ = instance_npcname("#wave_mode_sky_mercenary");
+
+	disablenpc instance_npcname("#wave_mode_sky_out");
+
+	setarray 'x_mob[0], 48, 38, 30, 30, 29, 38, 47, 51, 50, 42, 33, 29;
+	setarray 'y_mob[0], 67, 67, 64, 58, 52, 52, 51, 45, 36, 36, 36, 35;
+
+	setarray 'x_merc[0], 29, 33, 42, 50, 51, 47, 38, 29, 30, 30, 38, 47;
+	setarray 'y_merc[0], 35, 36, 36, 36, 45, 51, 52, 52, 58, 64, 67, 67;
+
+	'size_coord = getarraysize('x_mob);
+	for ( .@i = 0; .@i < 'size_coord -1; .@i++ ) {
+		.@dist_mob[.@i+1] = distance( 'x_mob[.@i], 'y_mob[.@i], 'x_mob[.@i+1], 'y_mob[.@i+1] );
+		.@total_mob += .@dist_mob[.@i+1];
+		.@dist_merc[.@i+1] = distance( 'x_merc[.@i], 'y_merc[.@i], 'x_merc[.@i+1], 'y_merc[.@i+1] );
+		.@total_merc += .@dist_merc[.@i+1];
+	}
+	for ( .@i = 0; .@i < 'size_coord -1; .@i++ ) {
+		'dist_spot_AZ[.@i] = .@total_mob - .@dist_mob[.@i];
+		'dist_spot_ZA[.@i] = .@total_merc - .@dist_merc[.@i];
+	}
+	end;
+}

+ 4 - 2
npc/re/jobs/novice/academy.txt

@@ -8897,7 +8897,8 @@ iz_ac02,60,51,5	script	Swordman Trainer#ac	4_M_SWORDMAN,{
 					mes "It should be very easy to find.";
 					cutin "", 255;
 					nov_3_swordman = 4;
-					erasequest 1230;
+					if (isbegin_quest(1230))
+						erasequest 1230;
 					close;
 				}
 			}
@@ -9025,7 +9026,8 @@ iz_ac02,60,51,5	script	Swordman Trainer#ac	4_M_SWORDMAN,{
 						mes "It should be very easy to find.";
 						cutin "", 255;
 						nov_3_swordman = 4;
-						erasequest 1230;
+						if (isbegin_quest(1230))
+							erasequest 1230;
 						close;
 					}
 				case 3:

+ 3 - 3
npc/re/mapflag/restricted.txt

@@ -25,9 +25,9 @@
 2@gl_k	mapflag	restricted	6
 
 // Wave Mode Memorial Dungeon ====
-1@def01	mapflag	restricted	6
-1@def02	mapflag	restricted	6
-1@def03	mapflag	restricted	6
+1@def01	mapflag	restricted	9
+1@def02	mapflag	restricted	9
+1@def03	mapflag	restricted	9
 
 // Heroes' Trail - Part 1 ========
 1@face	mapflag	restricted	6

+ 4 - 3
npc/re/quests/magic_books.txt

@@ -3,7 +3,7 @@
 //===== By: ================================================== 
 //= Masao, Muad_Dib (translation)
 //===== Current Version: ===================================== 
-//= 1.1a
+//= 1.3
 //===== Compatible With: ===================================== 
 //= rAthena Project
 //===== Description: ========================================= 
@@ -16,6 +16,7 @@
 //= 1.1b Fixed the rand part in "Mysterious Documents" to match
 //=	 Aegis & fixed a bracket issue. [Capuche]
 //= 1.2 Updates Magic Books gained from Lea. [Aleos]
+//= 1.3 Fixes checkquest calls. [Everade]
 //============================================================ 
 
 // Main Quest :: war_book
@@ -567,11 +568,11 @@ dic_in01,25,190,0	script	Mysterious Documents	CLEAR_NPC,{
 		mes "When you approach the documents, an Evil Giant that looks like the archive manager tries to call Guard Galton. You should get out of here quickly.";
 		close;
 	}
-	if (checkquest(12165,"PLAYTIME") == 1) {
+	if (checkquest(12165,PLAYTIME) == 1) {
 		mes "The documents are making you feel nauseous. You should come back later after your stomach settles.";
 		close;
 	}
-	if (checkquest(12165,"PLAYTIME") == 2) {
+	if (checkquest(12165,PLAYTIME) == 2) {
 		mes "You don't feel as nauseous anymore. It should be safe to proceed now.";
 		erasequest 12165;
 		close;

+ 2 - 1
npc/re/scripts_athena.conf

@@ -87,7 +87,8 @@ npc: npc/re/instances/RoomOfConsciousness.txt
 npc: npc/re/instances/SarahAndFenrir.txt
 npc: npc/re/instances/SaraMemory.txt
 npc: npc/re/instances/SkyFortress.txt
-
+npc: npc/re/instances/TempleOfDemonGod.txt
+//npc: npc/re/instances/WaveMode.txt
 npc: npc/re/instances/WernerLaboratoryCentralRoom.txt
 npc: npc/re/instances/WolfchevLaboratory.txt
 //npc: npc/custom/official/GeffenMagicTournament.txt

+ 2 - 2
sql-files/item_db2_re.sql

@@ -175,8 +175,8 @@ REPLACE INTO `item_db2_re` (`id`,`name_aegis`,`name_english`,`type`) VALUES (629
 
 # Old Tuxedo and Wedding Dress, will display the outfit when worn.
 #=============================================================
-REPLACE INTO `item_db2_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`job_all`,`job_novice`,`location_armor`,`refineable`,`equip_script`,`unequip_script`) VALUES (2338,'Wedding_Dress','Wedding Dress','Armor',43000,500,true,false,true,true,'sc_start SC_WEDDING,INFINITE_TICK,0;','sc_end SC_WEDDING;');
-REPLACE INTO `item_db2_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`job_all`,`job_novice`,`gender`,`location_armor`,`refineable`,`equip_script`,`unequip_script`) VALUES (7170,'Tuxedo','Tuxedo','Armor',43000,10,true,false,'Male',true,true,'sc_start SC_WEDDING,INFINITE_TICK,0;','sc_end SC_WEDDING;');
+REPLACE INTO `item_db2_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`job_all`,`job_novice`,`gender`,`location_armor`,`refineable`,`equip_script`,`unequip_script`) VALUES (2338,'Wedding_Dress','Wedding Dress','Armor',43000,500,true,false,'Female',true,true,'sc_start SC_WEDDING,INFINITE_TICK,0;','sc_end SC_WEDDING;');
+REPLACE INTO `item_db2_re` (`id`,`name_aegis`,`name_english`,`type`,`price_buy`,`weight`,`job_all`,`job_novice`,`gender`,`location_armor`,`armor_level`,`refineable`,`equip_script`,`unequip_script`) VALUES (7170,'Tuxedo','Tuxedo','Armor',43000,10,true,false,'Male',true,1,true,'sc_start SC_WEDDING,INFINITE_TICK,0;','sc_end SC_WEDDING;');
 
 # Non-kRO Eden Group Mark effect
 #=============================================================

+ 59 - 4
sql-files/mob_db_re.sql

@@ -1593,6 +1593,40 @@ REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`leve
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`mode_canmove`) VALUES (2566,'ALPHONSE_JR','Alphonse Jr','Alphonse Jr',150,100000,250,200,80,20,100,100,50,50,170,100,1,10,12,'Medium','Demihuman','Earth',3,200,936,792,432,'10',true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`mode_canmove`) VALUES (2567,'E_GEFFEN_MAGE_3_2','Geffen Bully','Geffen Bully',50,10000,212,227,89,22,70,7,41,14,15,100,5,1,10,12,'Medium','Demihuman','Neutral',1,200,900,672,480,'10',true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`mode_canmove`) VALUES (2568,'E_GEFFEN_MAGE_3_3','Geffen Gang Member','Geffen Gang Member',50,10000,212,227,89,22,70,7,41,14,15,100,5,1,10,12,'Medium','Demihuman','Neutral',1,200,950,864,480,'10',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2569,'G_ANOPHELES','Anopheles','Anopheles',95,7238,315,18,7,10,64,60,42,58,106,42,1,10,12,'Small','Insect','Wind',3,170,1084,2304,576,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2570,'G_BREEZE','Breeze','Breeze',92,6755,493,52,83,32,75,101,46,35,79,55,2,10,12,'Medium','Formless','Wind',3,100,140,384,504,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2571,'G_BUTOIJO','Butoijo','Butoijo',88,7524,358,102,77,12,66,65,30,30,106,44,1,10,12,'Large','Demon','Fire',2,170,576,768,432,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2572,'G_CARAMEL','Caramel','Caramel',25,518,67,9,39,19,10,15,10,32,5,1,10,12,'Small','Brute','Earth',1,200,1604,840,756,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`str`,`agi`,`vit`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2573,'G_CHONCHON','Chonchon','Chonchon',5,57,11,3,27,13,4,4,8,5,1,10,12,'Small','Insect','Wind',1,200,1076,576,480,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2574,'G_CIVIL_SERVANT','Civil Servant','Civil Servant',89,5292,304,61,90,56,67,76,40,65,74,30,2,10,12,'Medium','Brute','Wind',2,200,1257,528,432,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2575,'G_COCO','Coco','Coco',38,836,71,11,37,22,13,30,20,38,10,1,10,12,'Small','Brute','Earth',1,150,1864,864,1008,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2576,'G_CREAMY','Creamy','Creamy',23,378,61,1,28,20,16,20,1,10,12,'Small','Insect','Wind',1,150,1136,720,840,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2577,'G_FABRE','Fabre','Fabre',6,72,12,3,24,12,5,5,5,12,5,1,10,12,'Small','Insect','Earth',1,400,1672,672,480,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2578,'G_HORN','Horn','Horn',32,705,64,11,52,8,10,12,36,25,21,35,1,10,12,'Medium','Insect','Earth',1,200,1528,528,288,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2579,'G_HYLOZOIST','Hylozoist','Hylozoist',102,12000,548,81,101,68,97,67,72,88,83,60,1,10,12,'Small','Demon','Dark',2,155,741,1536,480,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2580,'G_KAHO','Kaho','Kaho',98,7045,655,224,106,55,81,61,55,65,79,73,1,10,12,'Medium','Demon','Fire',4,150,1700,1000,500,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2581,'G_LUDE','Lude','Lude',101,11574,283,78,90,53,97,38,55,82,83,55,2,10,12,'Small','Undead','Undead',1,150,890,960,480,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`str`,`agi`,`vit`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2582,'G_LUNATIC','Lunatic','Lunatic',3,55,11,1,18,10,3,3,8,5,1,10,12,'Small','Brute','Neutral',3,200,1456,456,336,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2583,'G_MARTIN','Martin','Martin',39,1056,70,18,58,19,25,29,28,15,30,10,1,10,12,'Small','Brute','Earth',2,300,1480,480,480,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2584,'G_MINERAL','Mineral','Mineral',96,8300,751,57,127,23,70,61,40,50,74,50,1,10,12,'Small','Formless','Neutral',2,250,648,480,360,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2585,'G_MOLE','Mole','Mole',85,6228,286,49,82,16,53,65,31,30,58,31,9,10,12,'Small','Brute','Earth',2,300,1400,960,504,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2586,'G_NERAID','Neraid','Neraid',98,9550,255,71,100,37,97,45,60,30,83,50,1,10,12,'Small','Brute','Earth',1,200,776,576,288,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2587,'G_OBSIDIAN','Obsidian','Obsidian',97,10088,767,80,129,37,84,38,40,60,64,50,1,10,12,'Small','Formless','Earth',2,350,720,864,504,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2588,'G_PITMAN','Pitman','Pitman',90,7208,200,60,104,48,78,56,45,35,60,30,1,10,12,'Large','Undead','Earth',2,180,960,336,300,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2589,'G_POPORING','Poporing','Poporing',30,524,74,20,36,17,17,26,20,18,36,5,1,10,12,'Medium','Plant','Poison',1,300,1672,672,480,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2590,'G_ROCKER','Rocker','Rocker',15,185,19,5,16,3,12,18,8,10,17,5,1,10,12,'Medium','Insect','Earth',1,200,1864,864,540,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2591,'G_SAVAGE','Savage','Savage',59,2301,181,23,126,3,56,21,54,10,52,15,1,10,12,'Large','Brute','Earth',2,150,1960,960,384,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2592,'G_SIORAVA','Siorava','Siorava',87,6500,450,210,20,40,10,40,66,70,67,10,1,10,12,'Small','Formless','Water',1,250,1536,1296,576,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2593,'G_SIROMA','Siroma','Siroma',98,11910,506,100,64,38,83,43,50,70,96,60,1,10,12,'Small','Formless','Water',3,180,432,648,240,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2594,'G_SNOWIER','Snowier','Snowier',103,13934,763,82,121,47,91,61,67,45,83,55,2,10,12,'Large','Formless','Water',2,220,936,1020,420,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2595,'G_STAINER','Stainer','Stainer',21,365,65,9,22,25,10,10,24,39,15,1,10,12,'Small','Insect','Wind',1,200,1688,1188,612,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2596,'G_STAPO','Stapo','Stapo',95,8805,573,51,129,36,20,46,25,35,64,30,1,10,12,'Small','Formless','Earth',2,300,936,792,432,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2597,'G_STEEL_CHONCHON','Steel Chonchon','Steel Chonchon',48,1199,77,35,57,20,30,62,20,10,56,10,1,10,12,'Small','Insect','Wind',1,150,1076,576,480,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2598,'G_UNGOLIANT','Ungoliant','Ungoliant',94,27070,1296,144,108,28,71,70,58,43,110,38,1,10,12,'Large','Insect','Poison',2,350,420,576,420,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2599,'G_WILD_RIDER','Wild Rider','Wild Rider',95,33300,1320,330,480,22,89,124,89,56,112,56,1,10,12,'Large','Fish','Water',2,120,432,792,360,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2600,'G_WOLF','Wolf','Wolf',45,1219,80,11,55,3,27,24,30,15,33,5,1,10,12,'Medium','Brute','Earth',1,200,1054,504,432,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2601,'G_YOYO','Yoyo','Yoyo',38,898,63,11,40,20,11,34,20,19,10,1,10,12,'Small','Brute','Earth',1,200,1054,54,384,'02');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (2602,'G_ZIPPER_BEAR','Zipper Bear','Zipper Bear',90,6620,451,57,130,40,68,51,50,35,70,20,1,10,12,'Medium','Brute','Dark',1,155,780,1008,420,'02');
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop7_item`,`drop7_rate`,`drop8_item`,`drop8_rate`,`drop8_nosteal`) VALUES (2603,'C1_ZOMBIE_SLAUGHTER','Swift Zombie Slaughter','Swift Zombie Slaughter',124,202200,17150,42615,1428,117,100,45,117,58,82,13,136,21,1,10,12,'Medium','Undead','Undead',3,150,676,648,432,'21','Clattering_Skull',7500,'Platinum_Shotel',25,'Mementos',3750,'Broken_Farming_Utensil',7500,'Sticky_Mucus',7500,'Carnium',5,'Sabah_Ring',25,'Zombie_Slaughter_Card',5,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop7_item`,`drop7_rate`,`drop8_item`,`drop8_rate`,`drop8_nosteal`) VALUES (2604,'C2_ZOMBIE_PRISONER','Solid Zombie Prisoner','Solid Zombie Prisoner',89,80450,5970,14505,470,60,89,28,87,39,58,5,82,10,1,10,12,'Medium','Undead','Undead',3,420,1768,500,192,'13','Worn_Out_Prison_Uniform',8750,'Spoon_Stub',265,'Iron_Cane',5,'Red_Gemstone',1500,'Rotten_Bandage',8750,'Cuffs',100,'Elunium',280,'Zombie_Prisoner_Card',5,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop7_item`,`drop7_rate`,`drop8_item`,`drop8_rate`,`drop8_nosteal`) VALUES (2605,'C3_ZOMBIE_MASTER','Zombie Master Ringleader','Zombie Master Ringleader',119,127550,14455,35850,988,151,78,46,55,60,48,49,86,48,1,10,12,'Medium','Undead','Undead',1,175,2612,912,288,'21','Tatters_Clothes',10000,'Sticky_Mucus',3750,'Horrendous_Mouth',3750,'Cardinal_Jewel',500,'White_Jewel',250,'Sg_Violet_Potion_Box',25,'Tatters_Clothes',5,'Zombie_Master_Card',5,true);
@@ -1996,12 +2030,33 @@ REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`leve
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`mode_detector`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop6_nosteal`) VALUES (3072,'PERE4','Ferre','Ferre',128,52280,3729,2235,1484,158,98,45,156,110,61,53,133,53,2,10,12,'Small','Demon','Earth',2,200,676,1248,480,'04',true,'Gymnastics_Ribbon',50,'Frozen_Breastplate',1,'Mud_Lump',100,'Crystal_Blue',300,'Mistic_Frozen',25,'SingingPere_Card',1,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop6_nosteal`) VALUES (3073,'GRAND_PERE','Awakened Ferre','Awakened Ferre',140,19471800,3132000,2720300,1500,1000,200,68,200,100,200,200,220,100,1,10,12,'Large','Demon','Undead',3,200,676,2592,480,'21','Boss','Pendant_Of_Harmony',400,'Pendant_Of_Chaos',400,'Gigantic_Bow',100,'Bow_Of_Storm',200,'Jitterbug\'s_Tooth',7000,'Grand_Pere_Card',1,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`mvp_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`racegroup_clocktower`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`damage_taken`,`ai`,`class`,`mode_mvp`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop7_item`,`drop7_rate`,`drop8_item`,`drop8_rate`,`drop8_nosteal`) VALUES (3074,'TIMEHOLDER','Time Holder','Time Holder',170,25000000,4582500,3877500,2291250,5250,2100,288,265,224,152,251,257,402,77,1,10,12,'Large','Demon',true,'Neutral',4,150,100,576,480,10,'21','Boss',true,'Needle_Of_Alarm',3000,'Brigan',3000,'Key_Of_Twisted_Time',3000,'Memorize_Book_',10,'Quadrille_',5,'Menswear',3,'One_Eyed_Glass_',20,'Timeholder_Card',1,true);
-REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`class`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3091,'MM_BRINARANEA','Brinaranea','Brinaranea',165,81650000,8255,197,264,177,135,135,12,72,220,91,3,10,12,'Large','Demon','Water',3,200,1020,500,768,'Boss','Brinaranea_Card',1,true);
-REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`class`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3092,'MM_MUSPELLSKOLL','Muspellskoll','Muspellskoll',165,55620000,9672,98,211,140,202,119,6,45,275,71,3,10,12,'Large','Demon','Fire',3,200,608,408,336,'Boss','Muspellskoll_Card',1,true);
-REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`class`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3097,'MM_MOROCC_ADT','Despair God Morocc','Despair God Morocc',175,120000000,5523,175,203,155,122,103,12,106,269,51,3,10,12,'Medium','Demon','Dark',2,200,750,510,500,'Boss','M_Morocc_Card',1,true);
-REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`mode_ignoremelee`,`mode_ignoremagic`,`mode_ignoreranged`,`mode_ignoremisc`) VALUES (3101,'MM_MANA_WHITE','Mana White','Mana White',1,30,1,1,1,1,10,12,'Small','Formless','Neutral',1,1000,1,1,1,true,true,true,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`dex`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`class`,`mode_norandomwalk`,`mode_ignoremelee`,`mode_ignoremagic`,`mode_ignoreranged`,`mode_ignoremisc`,`mode_knockbackimmune`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`) VALUES (3075,'WA_TREASURE','Treasure','Treasure',1,3,1,1,100,1199,10,12,'Small','Formless','Holy',1,'Battlefield',true,true,true,true,true,true,'Vit_Dish06',3000,'Agi_Dish06',3000,'Int_Dish06',3000,'Dex_Dish06',3000,'Yggdrasilberry',1000);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`mode_norandomwalk`) VALUES (3076,'WA_MONSTER_1','Go!','Go!',100,10000,64,50,10,12,'Small','Angel','Holy',3,300,1332,288,384,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3077,'WA_MONSTER_2','Go!','Go!',100,10500,64,50,10,12,'Small','Angel','Holy',3,300,1332,288,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3078,'WA_MONSTER_3','Go!','Go!',105,11000,106,84,10,12,'Small','Angel','Holy',3,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3079,'WA_MONSTER_4','Go!','Go!',120,12000,66,95,10,12,'Small','Angel','Holy',3,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3080,'WA_MONSTER_5','Go!','Go!',10,12,'Small','Formless','Neutral',4,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3081,'WA_MONSTER_6','Go!','Go!',125,14000,80,89,10,12,'Small','Angel','Holy',3,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3082,'WA_MONSTER_7','Go!','Go!',131,15000,85,92,10,12,'Small','Angel','Holy',2,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3083,'WA_MONSTER_8','Go!','Go!',131,18000,80,86,10,12,'Small','Angel','Holy',2,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3084,'WA_MONSTER_9','Go!','Go!',135,20000,196,96,10,12,'Small','Angel','Holy',3,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`mode_norandomwalk`) VALUES (3085,'WA_MONSTER_10','Go!','Go!',10,12,'Small','Formless','Neutral',4,160,1025,720,'25',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`ai`,`class`,`mode_aggressive`,`mode_ignoremelee`,`mode_ignoremagic`,`mode_ignoreranged`,`mode_ignoremisc`) VALUES (3086,'WA_MERCENARY','Mercenary','Mercenary',101,20099,557,775,66,36,20,46,25,35,64,30,10,12,'Medium','Demihuman','Neutral',1,230,1415,792,'24','Battlefield',true,true,true,true,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`) VALUES (3087,'M_NYDHOG','Guardian\'s Alter Ego','Guardian\'s Alter Ego',160,215000,1,1835,444,15,89,76,66,90,55,189,22,2,10,12,'Medium','Demihuman','Neutral',1,175,800,750,300);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`mode_detector`) VALUES (3088,'MM_BRINARANEA_BABY','Frost Spider','Frost Spider',155,155600,1,1,1,80,200,16,26,30,115,79,5,1,10,12,'Large','Formless','Neutral',1,300,1000,1000,1000,'04',true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`) VALUES (3089,'MM_LOCO_KASA','Frenzied Kasa','Frenzied Kasa',155,185000,3266,666,30,30,88,44,88,21,95,44,1,10,12,'Large','Demon','Dark',2,200,1500,600,500,'21','Boss');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`) VALUES (3090,'MM_LOCO_SALAMANDER','Mad Salamander','Mad Salamander',155,217650,2678,1257,121,36,60,103,45,35,172,15,1,10,12,'Medium','Demon','Dark',2,200,1000,500,600,'21','Boss');
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3091,'MM_BRINARANEA','Brinaranea','Brinaranea',165,81650000,8255,197,264,177,135,135,12,72,220,91,3,10,12,'Large','Demon','Water',3,200,1020,500,768,'10','Boss','Brinaranea_Card',1,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3092,'MM_MUSPELLSKOLL','Muspellskoll','Muspellskoll',165,55620000,9672,98,211,140,202,119,6,45,275,71,3,10,12,'Large','Demon','Fire',3,200,608,408,336,'10','Boss','Muspellskoll_Card',1,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`mode_canmove`,`mode_mvp`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3096,'MM_MOROCC_KID','Demigod','Demigod',175,80000000,4980,209,158,134,90,122,7,87,287,36,3,10,12,'Small','Demon','Holy',3,200,1000,460,350,'10','Boss',true,true,'M_Morocc_Card',1,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3097,'MM_MOROCC_ADT','Despair God Morroc','Despair God Morroc',175,120000000,5523,175,203,155,122,103,12,106,269,51,3,10,12,'Medium','Demon','Dark',2,200,750,510,500,'10','Boss','M_Morocc_Card',1,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`mode_canmove`,`mode_mvp`) VALUES (3098,'MM_MOROCC_ORIGIN','Morroc of the Genesis','Morroc of the Genesis',160,3258000,6177,40,351,212,195,35,5,36,355,7,3,10,12,'Large','Demon','Dark',4,350,2000,750,750,'10','Boss',true,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`mode_canmove`,`mode_mvp`) VALUES (3099,'MM_MOROCC_REST','Morroc of the Sabbath','Morroc of the Sabbath',160,1450000,2963,67,112,98,110,98,13,48,271,9,3,10,12,'Large','Demon','Dark',4,200,500,510,350,'10','Boss',true,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`mode_ignoremelee`,`mode_ignoremagic`,`mode_ignoreranged`,`mode_ignoremisc`) VALUES (3101,'MM_MANA_WHITE','Mana of White','Mana of White',1,30,1,1,1,1,10,12,'Small','Formless','Neutral',1,1000,1,1,1,true,true,true,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`mode_ignoremelee`,`mode_ignoremagic`,`mode_ignoreranged`,`mode_ignoremisc`) VALUES (3102,'MM_MANA_RED','Mana of Life','Mana of Life',1,30,1,1,1,1,10,12,'Small','Formless','Neutral',1,1000,1,1,1,true,true,true,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`mode_ignoremelee`,`mode_ignoremagic`,`mode_ignoreranged`,`mode_ignoremisc`) VALUES (3103,'MM_MANA_YELLOW','Mana of Earth','Mana of Earth',1,30,1,1,1,1,10,12,'Small','Formless','Neutral',1,1000,1,1,1,true,true,true,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`mode_canmove`,`mode_mvp`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3105,'MM_GB_MOROCC_1','Demon God\'s Apostle Aha','Demon God\'s Apostle Aha',149,5000000,1901,145,199,35,126,91,63,61,114,37,1,10,12,'Large','Angel','Fire',2,110,576,480,432,'10','Boss',true,true,'Demon_God\'s_Apostle_Ahat_Card',1,true);
+REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`mode_canmove`,`mode_mvp`,`drop1_item`,`drop1_rate`,`drop1_nosteal`) VALUES (3106,'MM_GB_MOROCC_4','Demon God\'s Apostle Shn','Demon God\'s Apostle Shn',149,5000000,1235,599,109,54,114,88,62,97,164,43,1,10,12,'Medium','Demon','Ghost',3,150,1536,648,300,'10','Boss',true,true,'Demon_God\'s_Apostle_Shnaim_Card',1,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop6_nosteal`) VALUES (3108,'JITTERBUG1','Jitterbug1','Jitterbug1',135,2614000,36804,23170,3210,695,123,68,189,78,81,51,108,56,1,10,12,'Large','Demon','Undead',2,150,676,2592,480,'21','Boss','Ukulele_Of_Newoz',250,'Winged_Ring_Of_Newoz',500,'Harden_Breastplate',500,'Jitterbug\'s_Tooth',5000,'Jitterbug\'s_Tooth',1000,'JitterbugCard',1,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`,`class`,`drop1_item`,`drop1_rate`,`drop2_item`,`drop2_rate`,`drop3_item`,`drop3_rate`,`drop4_item`,`drop4_rate`,`drop5_item`,`drop5_rate`,`drop6_item`,`drop6_rate`,`drop6_nosteal`) VALUES (3109,'JITTERBUG2','Jitterbug2','Jitterbug2',135,2614000,36804,23170,3210,695,123,68,189,78,81,51,108,56,1,10,12,'Large','Demon','Undead',2,150,676,2592,480,'21','Boss','Floral_Mic_Of_Igu',250,'Floral_Bracelet_Of_Igu',500,'Frozen_Breastplate',500,'Jitterbug\'s_Tooth',5000,'Jitterbug\'s_Tooth',1000,'JitterbugCard',1,true);
 REPLACE INTO `mob_db_re` (`id`,`name_aegis`,`name_english`,`name_japanese`,`level`,`hp`,`base_exp`,`job_exp`,`attack`,`attack2`,`defense`,`magic_defense`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`attack_range`,`skill_range`,`chase_range`,`size`,`race`,`element`,`element_level`,`walk_speed`,`attack_delay`,`attack_motion`,`damage_motion`,`ai`) VALUES (3122,'CHARLESTON1','Charleston 1','Charleston 1',140,2614000,36804,21064,3210,695,123,68,189,78,81,51,108,56,1,10,12,'Large','Demon','Earth',1,150,676,2400,480,'09');

+ 36 - 8
src/map/battle.cpp

@@ -508,6 +508,21 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
 #else
 					damage += (int64)(damage * 50 / 100);
 #endif
+				if( tsc->data[SC_WIDEWEB] ) {
+#ifdef RENEWAL
+					ratio += 100;
+#else
+					damage *= 2;
+#endif
+					status_change_end(target,SC_WIDEWEB,INVALID_TIMER);
+				}
+				if( tsc->data[SC_BURNT] ) {
+#ifdef RENEWAL
+					ratio += 400;
+#else
+					damage += (int64)(damage * 400 / 100);
+#endif
+				}
 				break;
 			case ELE_HOLY:
 				if (tsc->data[SC_ORATIO])
@@ -1481,6 +1496,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 			damage <<= 1;
 		if (sc->data[SC_DARKCROW] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT) {
 			int bonus = sc->data[SC_DARKCROW]->val2;
+		if( sc->data[SC_BURNT] && status_get_element(src) == ELE_FIRE )
+			damage += damage * 666 / 100; //Custom value
 
 			if (status_get_class_(bl) == CLASS_BOSS)
 				bonus /= 2;
@@ -2382,9 +2399,10 @@ static int battle_range_type(struct block_list *src, struct block_list *target,
 			break;
 #ifdef RENEWAL
 		case KN_BRANDISHSPEAR:
-			// Renewal changes to ranged physical damage
-			return BF_LONG;
+		// Renewal changes to ranged physical damage
 #endif
+		case SR_RAMPAGEBLASTER:
+			return BF_LONG;
 		case NJ_KIRIKAGE:
 			// Cast range mimics NJ_SHADOWJUMP but damage is considered melee
 		case GC_CROSSIMPACT:
@@ -3752,7 +3770,7 @@ static void battle_calc_multi_attack(struct Damage* wd, struct block_list *src,s
 				wd->div_++;
 			break;
 		case SR_RIDEINLIGHTNING:
-			wd->div_ = (sd ? max(1, sd->spiritball_old) : 1);
+			wd->div_ = (sd ? max(1, skill_lv) : 1);
 			break;
 		case RL_QD_SHOT:
 			wd->div_ = 1 + (sd ? sd->status.job_level : 1) / 20 + (tsc && tsc->data[SC_C_MARKER] ? 2 : 0);
@@ -6105,13 +6123,17 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 #endif
 	}
 
-#ifndef RENEWAL
-	if(tsd) { // Card Fix for target (tsd), 2 is not added to the "left" flag meaning "target cards only"
+#ifdef RENEWAL
+	// In renewal only do it for non player attacks
+	if( tsd && !sd ){
+#else
+	if( tsd ){
+#endif
+		// Card Fix for target (tsd), 2 is not added to the "left" flag meaning "target cards only"
 		wd.damage += battle_calc_cardfix(BF_WEAPON, src, target, nk, right_element, left_element, wd.damage, 0, wd.flag);
 		if(is_attack_left_handed(src, skill_id))
 			wd.damage2 += battle_calc_cardfix(BF_WEAPON, src, target, nk, right_element, left_element, wd.damage2, 1, wd.flag);
 	}
-#endif
 
 	// only do 1 dmg to plant, no need to calculate rest
 	if(infdef){
@@ -6764,6 +6786,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						i = cap_value(i, 1, 4);
 						skillratio = 2500 + ((skill_lv - i + 1) * 500);
 						break;
+					case NPC_FIRESTORM:
+						skillratio += 200;
+						break;
 					case NPC_HELLBURNING:
 						skillratio += 900;
 						break;
@@ -7197,6 +7222,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 			else
 				md.damage = 0;
 			break;
+		case NPC_WIDESUCK:
+			md.damage = tstatus->max_hp * 15 / 100;
+			break;
 		case SU_SV_ROOTTWIST_ATK:
 			md.damage = 100;
 			break;
@@ -8419,9 +8447,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 			{ //Normal mobs
 				if(
 					( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != AI_ZANZOU && ((TBL_MOB*)target)->special_state.ai != AI_ATTACK ) ) ||
-					( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai )
+					( t_bl->type == BL_MOB && (((TBL_MOB*)t_bl)->special_state.ai == AI_NONE || ((TBL_MOB*)t_bl)->special_state.ai == AI_WAVEMODE ))
 				  )
-					state |= BCT_PARTY; //Normal mobs with no ai are friends.
+					state |= BCT_PARTY; //Normal mobs with no ai or with AI_WAVEMODE are friends.
 				else
 					state |= BCT_ENEMY; //However, all else are enemies.
 			}

+ 6 - 7
src/map/clif.cpp

@@ -366,7 +366,7 @@ static inline unsigned char clif_bl_type(struct block_list *bl, bool walking) {
 // There is one exception and this is if they are walking.
 // Since walking NPCs are not supported on official servers, the client does not know how to handle it.
 #if PACKETVER >= 20170726
-				   return ( pcdb_checkid(status_get_viewdata(bl)->class_) && walking ) ? 0x0 : 0x6; //NPC_EVT_TYPE
+					return ( pcdb_checkid(status_get_viewdata(bl)->class_) && walking ) ? 0x0 : 0xC; // New walking NPC type
 #else
 				   return pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x6; //NPC_EVT_TYPE
 #endif
@@ -6995,12 +6995,11 @@ void clif_item_refine_list( struct map_session_data *sd ){
 
 	int refine_item[MAX_WEAPON_LEVEL];
 
-	refine_item[0] = -1;
-	refine_item[1] = pc_search_inventory( sd, ITEMID_PHRACON );
-	refine_item[2] = pc_search_inventory( sd, ITEMID_EMVERETARCON );
-	refine_item[3] = refine_item[4] = pc_search_inventory( sd, ITEMID_ORIDECON );
+	refine_item[0] = pc_search_inventory( sd, ITEMID_PHRACON );
+	refine_item[1] = pc_search_inventory( sd, ITEMID_EMVERETARCON );
+	refine_item[2] = refine_item[3] = pc_search_inventory( sd, ITEMID_ORIDECON );
 #ifdef RENEWAL
-	refine_item[5] = -1;
+	refine_item[4] = -1;
 #endif
 
 	int count = 0;
@@ -7008,7 +7007,7 @@ void clif_item_refine_list( struct map_session_data *sd ){
 		if( sd->inventory.u.items_inventory[i].nameid > 0 && sd->inventory.u.items_inventory[i].refine < skill_lv &&
 			sd->inventory_data[i] != nullptr && sd->inventory_data[i]->type == IT_WEAPON &&
 			sd->inventory.u.items_inventory[i].identify && sd->inventory_data[i]->weapon_level >= 1 &&
-			refine_item[sd->inventory_data[i]->weapon_level] != -1 && !( sd->inventory.u.items_inventory[i].equip & EQP_ARMS ) ){
+			refine_item[sd->inventory_data[i]->weapon_level - 1] != -1 && !( sd->inventory.u.items_inventory[i].equip & EQP_ARMS ) ){
 
 			p->items[count].index = client_index( i );
 			p->items[count].itemId = client_nameid( sd->inventory.u.items_inventory[i].nameid );

+ 3 - 1
src/map/itemdb.cpp

@@ -2325,6 +2325,8 @@ static bool itemdb_read_sqldb_sub(std::vector<std::string> str) {
 
 	if (!str[++index].empty())
 		node["WeaponLevel"] = std::stoi(str[index]);
+	if (!str[++index].empty())
+		node["ArmorLevel"] = std::stoi(str[index]);
 	if (!str[++index].empty())
 		node["EquipLevelMin"] = std::stoi(str[index]);
 	if (!str[++index].empty())
@@ -2457,7 +2459,7 @@ static int itemdb_read_sqldb(void) {
 			"`class_all`,`class_normal`,`class_upper`,`class_baby`,`gender`,"
 			"`location_head_top`,`location_head_mid`,`location_head_low`,`location_armor`,`location_right_hand`,`location_left_hand`,`location_garment`,`location_shoes`,`location_right_accessory`,`location_left_accessory`,"
 			"`location_costume_head_top`,`location_costume_head_mid`,`location_costume_head_low`,`location_costume_garment`,`location_ammo`,`location_shadow_armor`,`location_shadow_weapon`,`location_shadow_shield`,`location_shadow_shoes`,`location_shadow_right_accessory`,`location_shadow_left_accessory`,"
-			"`weapon_level`,`equip_level_min`,`equip_level_max`,`refineable`,`view`,`alias_name`,"
+			"`weapon_level`,`armor_level`,`equip_level_min`,`equip_level_max`,`refineable`,`view`,`alias_name`,"
 			"`flag_buyingstore`,`flag_deadbranch`,`flag_container`,`flag_uniqueid`,`flag_bindonequip`,`flag_dropannounce`,`flag_noconsume`,`flag_dropeffect`,"
 			"`delay_duration`,`delay_status`,`stack_amount`,`stack_inventory`,`stack_cart`,`stack_storage`,`stack_guildstorage`,`nouse_override`,`nouse_sitting`,"
 			"`trade_override`,`trade_nodrop`,`trade_notrade`,`trade_tradepartner`,`trade_nosell`,`trade_nocart`,`trade_nostorage`,`trade_noguildstorage`,`trade_nomail`,`trade_noauction`,`script`,`equip_script`,`unequip_script`"

+ 1 - 0
src/map/map.cpp

@@ -1841,6 +1841,7 @@ bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag)
  * @param third_charid : 3rd player that could loot the item (3rd charid that could loot for third_get_charid duration)
  * @param flag: &1 MVP item. &2 do stacking check. &4 bypass droppable check.
  * @param mob_id: Monster ID if dropped by monster
+ * @param canShowEffect: enable pillar effect on the dropped item (if set in the database)
  * @return 0:failure, x:item_gid [MIN_FLOORITEM;MAX_FLOORITEM]==[2;START_ACCOUNT_NUM]
  *------------------------------------------*/
 int map_addflooritem(struct item *item, int amount, int16 m, int16 x, int16 y, int first_charid, int second_charid, int third_charid, int flags, unsigned short mob_id, bool canShowEffect)

+ 1 - 0
src/map/map.hpp

@@ -381,6 +381,7 @@ enum mob_ai {
 	AI_LEGION,
 	AI_FAW,
 	AI_GUILD,
+	AI_WAVEMODE,
 	AI_MAX
 };
 

+ 40 - 22
src/map/mob.cpp

@@ -1516,6 +1516,10 @@ int mob_unlocktarget(struct mob_data *md, t_tick tick)
 		//Because it is not unset when the mob finishes walking.
 		md->state.skillstate = MSS_IDLE;
 	case MSS_IDLE:
+		if( md->ud.walktimer == INVALID_TIMER && md->idle_event[0] && npc_event_do_id( md->idle_event, md->bl.id ) > 0 ){
+			md->idle_event[0] = 0;
+			break;
+		}
 		// Idle skill.
 		if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mobskill_use(md, tick, -1))
 			break;
@@ -1543,7 +1547,8 @@ int mob_unlocktarget(struct mob_data *md, t_tick tick)
 		md->ud.target_to = 0;
 		unit_set_target(&md->ud, 0);
 	}
-	if (battle_config.official_cell_stack_limit > 0
+	
+	if (!md->ud.state.ignore_cell_stack_limit && battle_config.official_cell_stack_limit > 0
 		&& (md->min_chase == md->db->range3 || battle_config.mob_ai & 0x8)
 		&& map_count_oncell(md->bl.m, md->bl.x, md->bl.y, BL_CHAR | BL_NPC, 1) > battle_config.official_cell_stack_limit) {
 		unit_walktoxy(&md->bl, md->bl.x, md->bl.y, 8);
@@ -2045,6 +2050,15 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
 		return 0;
 	}
 
+	if (md->ud.walktimer == INVALID_TIMER) {
+		// Because it is not unset when the mob finishes walking.
+		md->state.skillstate = MSS_IDLE;
+		if (md->idle_event[0] && npc_event_do_id( md->idle_event, md->bl.id ) > 0) {
+			md->idle_event[0] = 0;
+			return 0;
+		}
+	}
+
 	if( DIFF_TICK(md->next_walktime,tick) < 0 && status_has_mode(&md->status,MD_CANMOVE) && unit_can_move(&md->bl) )
 	{
 		// Move probability for mobs away from players
@@ -2056,9 +2070,6 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
 	}
 	else if( md->ud.walktimer == INVALID_TIMER )
 	{
-		//Because it is not unset when the mob finishes walking.
-		md->state.skillstate = MSS_IDLE;
-
 		// Probability for mobs far from players from doing their IDLE skill.
 		// In Aegis, this is 100% for mobs that have been activated by players and none otherwise.
 		if( mob_is_spotted(md) &&
@@ -3657,6 +3668,24 @@ struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2)
 	return fr;
 }
 
+// Display message from mob_chat_db.yml
+bool mob_chat_display_message(mob_data &md, uint16 msg_id) {
+	std::shared_ptr<s_mob_chat> mc = mob_chat_db.find(msg_id);
+
+	if (mc != nullptr) {
+		std::string name = md.name, output;
+		std::size_t unique = name.find("#");
+
+		if (unique != std::string::npos)
+			name = name.substr(0, unique); // discard extra name identifier if present [Daegaladh]
+		output = name + " : " + mc->msg;
+
+		clif_messagecolor(&md.bl, mc->color, output.c_str(), true, AREA_CHAT_WOC);
+		return true;
+	}
+	return false;
+}
+
 /*==========================================
  * Skill use judging
  *------------------------------------------*/
@@ -3856,18 +3885,7 @@ int mobskill_use(struct mob_data *md, t_tick tick, int event)
 		}
 		//Skill used. Post-setups...
 		if ( ms[i]->msg_id ){ //Display color message [SnakeDrak]
-			std::shared_ptr<s_mob_chat> mc = mob_chat_db.find(ms[i]->msg_id);
-
-			if (mc) {
-				std::string name = md->name, output;
-				std::size_t unique = name.find("#");
-
-				if (unique != std::string::npos)
-					name = name.substr(0, unique); // discard extra name identifier if present [Daegaladh]
-				output = name + " : " + mc->msg;
-
-				clif_messagecolor(&md->bl, mc->color, output.c_str(), true, AREA_CHAT_WOC);
-			}
+			mob_chat_display_message(*md, ms[i]->msg_id);
 		}
 		if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill.
 			for (j = 0; j < ms.size(); j++)
@@ -4446,7 +4464,7 @@ uint64 MobDatabase::parseBodyNode(const YAML::Node &node) {
 			mob->status.rhw.atk2 = 0;
 #endif
 	}
-	
+
 	if (this->nodeExists(node, "Defense")) {
 		uint16 def;
 
@@ -4463,7 +4481,7 @@ uint64 MobDatabase::parseBodyNode(const YAML::Node &node) {
 		if (!exists)
 			mob->status.def = 0;
 	}
-	
+
 	if (this->nodeExists(node, "MagicDefense")) {
 		uint16 def;
 
@@ -4480,7 +4498,7 @@ uint64 MobDatabase::parseBodyNode(const YAML::Node &node) {
 		if (!exists)
 			mob->status.mdef = 0;
 	}
-	
+
 	if (this->nodeExists(node, "Str")) {
 		uint16 stat;
 
@@ -4552,7 +4570,7 @@ uint64 MobDatabase::parseBodyNode(const YAML::Node &node) {
 		if (!exists)
 			mob->status.luk = 1;
 	}
-	
+
 	if (this->nodeExists(node, "AttackRange")) {
 		uint16 range;
 
@@ -4893,10 +4911,10 @@ void MobDatabase::loadingFinished() {
 		}
 
 		if (battle_config.view_range_rate != 100)
-			mob->range2 = cap_value(mob->range2, 1, mob->range2 * battle_config.view_range_rate / 100);
+			mob->range2 = max(1, mob->range2 * battle_config.view_range_rate / 100);
 
 		if (battle_config.chase_range_rate != 100)
-			mob->range3 = cap_value(mob->range3, mob->range2, mob->range3 * battle_config.chase_range_rate / 100);
+			mob->range3 = max(mob->range2, mob->range3 * battle_config.chase_range_rate / 100);
 
 		// Tests showed that chase range is effectively 2 cells larger than expected [Playtester]
 		mob->range3 += 2;

+ 2 - 0
src/map/mob.hpp

@@ -333,6 +333,7 @@ struct mob_data {
 	int8 skill_idx; // Index of last used skill from db->skill[]
 	t_tick skilldelay[MAX_MOBSKILL];
 	char npc_event[EVENT_NAME_LENGTH];
+	char idle_event[EVENT_NAME_LENGTH];
 	/**
 	 * Did this monster summon something?
 	 * Used to flag summon deletions, saves a worth amount of memory
@@ -487,6 +488,7 @@ int mob_class_change(struct mob_data *md,int mob_id);
 int mob_warpslave(struct block_list *bl, int range);
 int mob_linksearch(struct block_list *bl,va_list ap);
 
+bool mob_chat_display_message (mob_data &md, uint16 msg_id);
 int mobskill_use(struct mob_data *md,t_tick tick,int event);
 int mobskill_event(struct mob_data *md,struct block_list *src,t_tick tick, int flag);
 int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id);

+ 31 - 23
src/map/pc.cpp

@@ -2524,10 +2524,13 @@ int pc_disguise(struct map_session_data *sd, int class_)
  * @param id: Skill to cast
  * @param lv: Skill level
  * @param rate: Success chance
- * @param flag: Battle flag
+ * @param battle_flag: Battle flag
  * @param card_id: Used to prevent card stacking
+ * @param flag: Flags used for extra arguments
+ *              &1: forces the skill to be casted on target, rather than self
+ *              &2: random skill level in [1..lv] is chosen
  */
-static void pc_bonus_autospell(std::vector<s_autospell> &spell, short id, short lv, short rate, short flag, unsigned short card_id)
+static void pc_bonus_autospell(std::vector<s_autospell> &spell, uint16 id, uint16 lv, short rate, short battle_flag, t_itemid card_id, uint8 flag)
 {
 	if (spell.size() == MAX_PC_BONUS) {
 		ShowWarning("pc_bonus_autospell: Reached max (%d) number of autospells per character!\n", MAX_PC_BONUS);
@@ -2537,19 +2540,19 @@ static void pc_bonus_autospell(std::vector<s_autospell> &spell, short id, short
 	if (!rate)
 		return;
 
-	if (!(flag&BF_RANGEMASK))
-		flag |= BF_SHORT | BF_LONG; //No range defined? Use both.
-	if (!(flag&BF_WEAPONMASK))
-		flag |= BF_WEAPON; //No attack type defined? Use weapon.
-	if (!(flag&BF_SKILLMASK)) {
-		if (flag&(BF_MAGIC | BF_MISC))
-			flag |= BF_SKILL; //These two would never trigger without BF_SKILL
-		if (flag&BF_WEAPON)
-			flag |= BF_NORMAL; //By default autospells should only trigger on normal weapon attacks.
+	if (!(battle_flag&BF_RANGEMASK))
+		battle_flag |= BF_SHORT | BF_LONG; //No range defined? Use both.
+	if (!(battle_flag&BF_WEAPONMASK))
+		battle_flag |= BF_WEAPON; //No attack type defined? Use weapon.
+	if (!(battle_flag&BF_SKILLMASK)) {
+		if (battle_flag&(BF_MAGIC | BF_MISC))
+			battle_flag |= BF_SKILL; //These two would never trigger without BF_SKILL
+		if (battle_flag&BF_WEAPON)
+			battle_flag |= BF_NORMAL; //By default autospells should only trigger on normal weapon attacks.
 	}
 
 	for (auto &it : spell) {
-		if ((it.card_id == card_id || it.rate < 0 || rate < 0) && it.id == id && it.lv == lv && it.flag == flag) {
+		if ((it.card_id == card_id || it.rate < 0 || rate < 0) && it.id == id && it.lv == lv && it.flag == battle_flag) {
 			if (!battle_config.autospell_stacking && it.rate > 0 && rate > 0) // Stacking disabled
 				return;
 			it.rate = cap_value(it.rate + rate, -10000, 10000);
@@ -2565,8 +2568,9 @@ static void pc_bonus_autospell(std::vector<s_autospell> &spell, short id, short
 	entry.id = id;
 	entry.lv = lv;
 	entry.rate = cap_value(rate, -10000, 10000);
-	entry.flag = flag;
+	entry.battle_flag = battle_flag;
 	entry.card_id = card_id;
+	entry.flag = flag;
 
 	spell.push_back(entry);
 }
@@ -2579,8 +2583,11 @@ static void pc_bonus_autospell(std::vector<s_autospell> &spell, short id, short
  * @param lv: Skill level
  * @param rate: Success chance
  * @param card_id: Used to prevent card stacking
+ * @param flag: Flags used for extra arguments
+ *              &1: forces the skill to be casted on self, rather than on the target of skill
+ *              &2: random skill level in [1..lv] is chosen
  */
-static void pc_bonus_autospell_onskill(std::vector<s_autospell> &spell, short src_skill, short id, short lv, short rate, unsigned short card_id)
+static void pc_bonus_autospell_onskill(std::vector<s_autospell> &spell, uint16 src_skill, uint16 id, uint16 lv, short rate, t_itemid card_id, uint8 flag)
 {
 	if (spell.size() == MAX_PC_BONUS) {
 		ShowWarning("pc_bonus_autospell_onskill: Reached max (%d) number of autospells per character!\n", MAX_PC_BONUS);
@@ -2595,11 +2602,12 @@ static void pc_bonus_autospell_onskill(std::vector<s_autospell> &spell, short sr
 	if (rate < -10000 || rate > 10000)
 		ShowWarning("pc_bonus_onskill: Item bonus rate %d exceeds -10000~10000 range, capping.\n", rate);
 
-	entry.flag = src_skill;
+	entry.trigger_skill = src_skill;
 	entry.id = id;
 	entry.lv = lv;
 	entry.rate = cap_value(rate, -10000, 10000);
 	entry.card_id = card_id;
+	entry.flag = flag;
 
 	spell.push_back(entry);
 }
@@ -4455,7 +4463,7 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 		{
 			int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
 			target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !skill_get_inf2(type2, INF2_NOTARGETSELF));
-			pc_bonus_autospell(sd->autospell, target?-type2:type2, type3, val, 0, current_equip_card_id);
+			pc_bonus_autospell(sd->autospell, type2, type3, val, 0, current_equip_card_id, target ? 1 : 0);
 		}
 		break;
 	case SP_AUTOSPELL_WHENHIT: // bonus3 bAutoSpellWhenHit,sk,y,n;
@@ -4463,7 +4471,7 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 		{
 			int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self.
 			target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !skill_get_inf2(type2, INF2_NOTARGETSELF));
-			pc_bonus_autospell(sd->autospell2, target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id);
+			pc_bonus_autospell(sd->autospell2, type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id, target ? 1 : 0);
 		}
 		break;
 	case SP_ADD_MONSTER_DROP_ITEMGROUP: // bonus3 bAddMonsterDropItemGroup,ig,r,n;
@@ -4581,12 +4589,12 @@ void pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type
 	switch(type){
 	case SP_AUTOSPELL: // bonus4 bAutoSpell,sk,y,n,i;
 		if(sd->state.lr_flag != 2)
-			pc_bonus_autospell(sd->autospell, (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id);
+			pc_bonus_autospell(sd->autospell, type2, type3, type4, 0, current_equip_card_id, val);
 		break;
 
 	case SP_AUTOSPELL_WHENHIT: // bonus4 bAutoSpellWhenHit,sk,y,n,i;
 		if(sd->state.lr_flag != 2)
-			pc_bonus_autospell(sd->autospell2, (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, current_equip_card_id);
+			pc_bonus_autospell(sd->autospell2, type2, type3, type4, BF_NORMAL|BF_SKILL, current_equip_card_id, val);
 		break;
 
 	case SP_AUTOSPELL_ONSKILL: // bonus4 bAutoSpellOnSkill,sk,x,y,n;
@@ -4595,7 +4603,7 @@ void pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type
 			int target = skill_get_inf(type3); //Support or Self (non-auto-target) skills should pick self.
 			target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !skill_get_inf2(type3, INF2_NOTARGETSELF));
 
-			pc_bonus_autospell_onskill(sd->autospell3, type2, target?-type3:type3, type4, val, current_equip_card_id);
+			pc_bonus_autospell_onskill(sd->autospell3, type2, type3, type4, val, current_equip_card_id, target ? 1 : 0);
 		}
 		break;
 
@@ -4664,17 +4672,17 @@ void pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type
 	switch(type){
 	case SP_AUTOSPELL: // bonus5 bAutoSpell,sk,y,n,bf,i;
 		if(sd->state.lr_flag != 2)
-			pc_bonus_autospell(sd->autospell, (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id);
+			pc_bonus_autospell(sd->autospell, type2, type3, type4, type5, current_equip_card_id, val);
 		break;
 
 	case SP_AUTOSPELL_WHENHIT: // bonus5 bAutoSpellWhenHit,sk,y,n,bf,i;
 		if(sd->state.lr_flag != 2)
-			pc_bonus_autospell(sd->autospell2, (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id);
+			pc_bonus_autospell(sd->autospell2, type2, type3, type4, type5, current_equip_card_id, val);
 		break;
 
 	case SP_AUTOSPELL_ONSKILL: // bonus5 bAutoSpellOnSkill,sk,x,y,n,i;
 		if(sd->state.lr_flag != 2)
-			pc_bonus_autospell_onskill(sd->autospell3, type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id);
+			pc_bonus_autospell_onskill(sd->autospell3, type2, type3, type4, type5, current_equip_card_id, val);
 		break;
  
 	case SP_ADDEFF_ONSKILL: // bonus5 bAddEffOnSkill,sk,eff,n,y,t;

+ 4 - 2
src/map/pc.hpp

@@ -194,8 +194,10 @@ struct weapon_data {
 
 /// AutoSpell bonus struct
 struct s_autospell {
-	short id, lv, rate, flag;
-	unsigned short card_id;
+	uint16 id, lv, trigger_skill;
+	short rate, battle_flag;
+	t_itemid card_id;
+	uint8 flag;
 	bool lock;  // bAutoSpellOnSkill: blocks autospell from triggering again, while being executed
 };
 

+ 0 - 5
src/map/quest.cpp

@@ -318,11 +318,6 @@ uint64 QuestDatabase::parseBodyNode(const YAML::Node &node) {
 		const YAML::Node &drops = node["Drops"];
 
 		for (const YAML::Node &dropNode : drops) {
-			if (quest->objectives.size() >= MAX_QUEST_OBJECTIVES) {
-				this->invalidWarning(dropNode, "Drops list exceeds the maximum of %d, skipping.\n", MAX_QUEST_OBJECTIVES);
-				return 0;
-			}
-
 			uint32 mob_id = 0; // Can be 0 which means all monsters
 
 			if (this->nodeExists(dropNode, "Mob")) {

+ 193 - 55
src/map/script.cpp

@@ -7872,8 +7872,8 @@ BUILDIN_FUNC(grouprandomitem) {
 }
 
 /**
-* makeitem <item id>,<amount>,"<map name>",<X>,<Y>;
-* makeitem "<item name>",<amount>,"<map name>",<X>,<Y>;
+* makeitem <item id>,<amount>,"<map name>",<X>,<Y>{,<canShowEffect>};
+* makeitem "<item name>",<amount>,"<map name>",<X>,<Y>{,<canShowEffect>};
 */
 BUILDIN_FUNC(makeitem) {
 	t_itemid nameid;
@@ -7881,6 +7881,7 @@ BUILDIN_FUNC(makeitem) {
 	const char *mapname;
 	int m;
 	struct item item_tmp;
+	bool canShowEffect = false;
 
 	if( script_isstring(st, 2) ){
 		const char *name = script_getstr(st, 2);
@@ -7914,7 +7915,10 @@ BUILDIN_FUNC(makeitem) {
 	x = script_getnum(st,5);
 	y = script_getnum(st,6);
 
-	if(strcmp(mapname,"this")==0) {
+	if (script_hasdata(st, 7))
+		canShowEffect = script_getnum(st, 7) != 0;
+
+	if (strcmp(mapname, "this")==0) {
 		TBL_PC *sd;
 		if (!script_rid2sd(sd))
 			return SCRIPT_CMD_SUCCESS; //Failed...
@@ -7929,16 +7933,16 @@ BUILDIN_FUNC(makeitem) {
 	else
 		item_tmp.identify = itemdb_isidentified(nameid);
 
-	map_addflooritem(&item_tmp,amount,m,x,y,0,0,0,4,0);
+	map_addflooritem(&item_tmp, amount, m, x, y, 0, 0, 0, 4, 0, canShowEffect);
 	return SCRIPT_CMD_SUCCESS;
 }
 
 /**
- * makeitem2 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>;
- * makeitem2 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>;
+ * makeitem2 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<canShowEffect>};
+ * makeitem2 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<canShowEffect>};
  *
- * makeitem3 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>;
- * makeitem3 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>;
+ * makeitem3 <item id>,<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>{,<canShowEffect>};
+ * makeitem3 "<item name>",<amount>,"<map name>",<X>,<Y>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<RandomIDArray>,<RandomValueArray>,<RandomParamArray>{,<canShowEffect>};
  */
 BUILDIN_FUNC(makeitem2) {
 	t_itemid nameid;
@@ -7948,6 +7952,7 @@ BUILDIN_FUNC(makeitem2) {
 	struct item item_tmp;
 	struct item_data *id;
 	const char *funcname = script_getfuncname(st);
+	bool canShowEffect = false;
 
 	if( script_isstring( st, 2 ) ){
 		const char *name = script_getstr( st, 2 );
@@ -8015,9 +8020,20 @@ BUILDIN_FUNC(makeitem2) {
 			int res = script_getitem_randomoption(st, nullptr, &item_tmp, funcname, 14);
 			if (res != SCRIPT_CMD_SUCCESS)
 				return res;
+
+			if (script_hasdata(st, 17)) {
+				if (script_getnum(st, 17) != 0)
+					canShowEffect = script_getnum(st, 17) != 0;
+			}
+		}
+		else {
+			if (script_hasdata(st, 14)) {
+				if (script_getnum(st, 14) != 0)
+					canShowEffect = script_getnum(st, 14) != 0;
+			}
 		}
 
-		map_addflooritem(&item_tmp,amount,m,x,y,0,0,0,4,0);
+		map_addflooritem(&item_tmp, amount, m, x, y, 0, 0, 0, 4, 0, canShowEffect);
 	}
 	else
 		return SCRIPT_CMD_FAILURE;
@@ -10754,6 +10770,8 @@ BUILDIN_FUNC(getmobdrops)
 
 		mapreg_setreg(reference_uid(add_str("$@MobDrop_item"), j), mob->dropitem[i].nameid);
 		mapreg_setreg(reference_uid(add_str("$@MobDrop_rate"), j), mob->dropitem[i].rate);
+		mapreg_setreg(reference_uid(add_str("$@MobDrop_nosteal"), j), mob->dropitem[i].steal_protected);
+		mapreg_setreg(reference_uid(add_str("$@MobDrop_randomopt"), j), mob->dropitem[i].randomopt_group);
 
 		j++;
 	}
@@ -17591,54 +17609,93 @@ BUILDIN_FUNC(setitemscript)
  * Add or Update a mob drop temporarily [Akinari]
  * Original Idea By: [Lupus]
  *
- * addmonsterdrop <mob_id or name>,<item_id>,<rate>;
+ * addmonsterdrop <mob_id or name>,<item_id>,<rate>,{<steal protected>,{<random option group id>}};
  *
  * If given an item the mob already drops, the rate
- * is updated to the new rate.  Rate cannot exceed 10000
- * Returns 1 if succeeded (added/updated a mob drop)
+ * is updated to the new rate. Rate range is 1-10000.
+ * Returns true if succeeded (added/updated a mob drop) false otherwise.
  *-------------------------------------------------------*/
 BUILDIN_FUNC(addmonsterdrop)
 {
 	std::shared_ptr<s_mob_db> mob;
-	int rate;
 
-	if(script_isstring(st, 2))
-		mob = mob_db.find(mobdb_searchname(script_getstr(st,2)));
+	if (script_isstring(st, 2))
+		mob = mob_db.find(mobdb_searchname(script_getstr(st, 2)));
 	else
-		mob = mob_db.find(script_getnum(st,2));
+		mob = mob_db.find(script_getnum(st, 2));
 
-	t_itemid item_id=script_getnum(st,3);
-	rate=script_getnum(st,4);
+	if (mob == nullptr) {
+		if (script_isstring(st, 2))
+			ShowError("addmonsterdrop: bad mob name given %s\n", script_getstr(st, 2));
+		else
+			ShowError("addmonsterdrop: bad mob id given %d\n", script_getnum(st, 2));
+		script_pushint(st, false);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	t_itemid item_id = script_getnum(st, 3);
+	item_data *itm = itemdb_exists(item_id);
 
-	if(!itemdb_exists(item_id)){
-		ShowError("addmonsterdrop: Nonexistant item %u requested.\n", item_id );
+	if (itm == nullptr) {
+		ShowError("addmonsterdrop: Nonexistant item %u requested.\n", item_id);
+		script_pushint(st, false);
 		return SCRIPT_CMD_FAILURE;
 	}
 
-	if(mob) { //We got a valid monster, check for available drop slot
-		unsigned char i, c = 0;
-		for(i = 0; i < MAX_MOB_DROP_TOTAL; i++) {
-			if(mob->dropitem[i].nameid) {
-				if(mob->dropitem[i].nameid == item_id) { //If it equals item_id we update that drop
-					c = i;
-					break;
-				}
-				continue;
-			}
-			if(!c) //Accept first available slot only
+	int rate = script_getnum(st, 4);
+
+	if (rate < 1 || rate > 10000) {
+		ShowError("addmonsterdrop: Invalid rate %d (min 1, max 10000).\n", rate);
+		script_pushint(st, false);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	uint16 c = 0;
+
+	for (uint16 i = 0; i < MAX_MOB_DROP_TOTAL; i++) {
+		if (mob->dropitem[i].nameid > 0) {
+			if (mob->dropitem[i].nameid == item_id) { // If it equals item_id we update that drop
 				c = i;
+				break;
+			}
+			continue;
 		}
-		if(c) { //Fill in the slot with the item and rate
-			mob->dropitem[c].nameid = item_id;
-			mob->dropitem[c].rate = (rate > 10000)?10000:rate;
-			mob_reload_itemmob_data(); // Reload the mob search data stored in the item_data
-			script_pushint(st,1);
-		} else //No place to put the new drop
-			script_pushint(st,0);
-	} else {
-		ShowWarning("addmonsterdrop: bad mob id given %d\n",script_getnum(st,2));
-		return SCRIPT_CMD_FAILURE;
+		if (c == 0) // Accept first available slot only
+			c = i;
 	}
+	if (c == 0) { // No place to put the new drop
+		script_pushint(st, false);
+		return SCRIPT_CMD_SUCCESS;
+	}
+
+	int steal_protected = 0;
+	int group = 0;
+
+	if (script_hasdata(st,5))
+		steal_protected = script_getnum(st, 5);
+	if (script_hasdata(st,6)) {
+		group = script_getnum(st, 6);
+
+		if (!random_option_group.exists(group)) {
+			ShowError("buildin_addmonsterdrop: Unknown random option group %d.\n", group);
+			script_pushint(st, false);
+			return SCRIPT_CMD_FAILURE;
+		}
+		if (itm->type != IT_WEAPON && itm->type != IT_ARMOR && itm->type != IT_SHADOWGEAR) {
+			ShowError("buildin_addmonsterdrop: Random option group can't be used with this type of item (item Id: %d).\n", item_id);
+			script_pushint(st, false);
+			return SCRIPT_CMD_FAILURE;
+		}
+	}
+
+	// Fill in the slot with the item and rate
+	mob->dropitem[c].nameid = item_id;
+	mob->dropitem[c].rate = rate;
+	mob->dropitem[c].steal_protected = steal_protected > 0;
+	mob->dropitem[c].randomopt_group = group;
+	mob_reload_itemmob_data(); // Reload the mob search data stored in the item_data
+
+	script_pushint(st, true);
 	return SCRIPT_CMD_SUCCESS;
 
 }
@@ -17662,7 +17719,7 @@ BUILDIN_FUNC(delmonsterdrop)
 
 	t_itemid item_id=script_getnum(st,3);
 
-	if(!itemdb_exists(item_id)){
+	if(!item_db.exists(item_id)){
 		ShowError("delmonsterdrop: Nonexistant item %u requested.\n", item_id );
 		return SCRIPT_CMD_FAILURE;
 	}
@@ -17673,6 +17730,8 @@ BUILDIN_FUNC(delmonsterdrop)
 			if(mob->dropitem[i].nameid == item_id) {
 				mob->dropitem[i].nameid = 0;
 				mob->dropitem[i].rate = 0;
+				mob->dropitem[i].steal_protected = false;
+				mob->dropitem[i].randomopt_group = 0;
 				mob_reload_itemmob_data(); // Reload the mob search data stored in the item_data
 				script_pushint(st,1);
 				return SCRIPT_CMD_SUCCESS;
@@ -18143,6 +18202,7 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(UMOB_ROBE, md->vd->robe);
 			getunitdata_sub(UMOB_BODY2, md->vd->body_style);
 			getunitdata_sub(UMOB_GROUP_ID, md->ud.group_id);
+			getunitdata_sub(UMOB_IGNORE_CELL_STACK_LIMIT, md->ud.state.ignore_cell_stack_limit);
 			break;
 
 		case BL_HOM:
@@ -18547,6 +18607,7 @@ BUILDIN_FUNC(setunitdata)
 			case UMOB_ROBE: clif_changelook(bl, LOOK_ROBE, (unsigned short)value); break;
 			case UMOB_BODY2: clif_changelook(bl, LOOK_BODY2, (unsigned short)value); break;
 			case UMOB_GROUP_ID: md->ud.group_id = value; unit_refresh(bl); break;
+			case UMOB_IGNORE_CELL_STACK_LIMIT: md->ud.state.ignore_cell_stack_limit = value > 0; break;
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MOB.\n", type);
 				return SCRIPT_CMD_FAILURE;
@@ -19270,8 +19331,8 @@ BUILDIN_FUNC(unitemote)
 
 /// Makes the unit cast the skill on the target or self if no target is specified.
 ///
-/// unitskilluseid <unit_id>,<skill_id>,<skill_lv>{,<target_id>,<casttime>};
-/// unitskilluseid <unit_id>,"<skill name>",<skill_lv>{,<target_id>,<casttime>};
+/// unitskilluseid <unit_id>,<skill_id>,<skill_lv>{,<target_id>,<casttime>,<cancel>,<Line_ID>};
+/// unitskilluseid <unit_id>,"<skill name>",<skill_lv>{,<target_id>,<casttime>,<cancel>,<Line_ID>};
 BUILDIN_FUNC(unitskilluseid)
 {
 	int unit_id, target_id, casttime;
@@ -19297,15 +19358,26 @@ BUILDIN_FUNC(unitskilluseid)
 	skill_lv = script_getnum(st,4);
 	target_id = ( script_hasdata(st,5) ? script_getnum(st,5) : unit_id );
 	casttime = ( script_hasdata(st,6) ? script_getnum(st,6) : 0 );
-	
+	bool cancel = ( script_hasdata(st,7) ? script_getnum(st,7) > 0 : skill_get_castcancel(skill_id) );
+	int msg_id = (script_hasdata(st, 8) ? script_getnum(st, 8) : 0);
+
 	if(script_rid2bl(2,bl)){
+		if (msg_id > 0) {
+			if (bl->type != BL_MOB) {
+				ShowError("buildin_unitskilluseid: Msg can only be used for monster.\n");
+				return SCRIPT_CMD_FAILURE;
+			}
+			TBL_MOB* md = map_id2md(bl->id);
+			if (md)
+				mob_chat_display_message(*md, static_cast<uint16>(msg_id));
+		}
 		if (bl->type == BL_NPC) {
 			if (!((TBL_NPC*)bl)->status.hp)
 				status_calc_npc(((TBL_NPC*)bl), SCO_FIRST);
 			else
 				status_calc_npc(((TBL_NPC*)bl), SCO_NONE);
 		}
-		unit_skilluse_id2(bl, target_id, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), skill_get_castcancel(skill_id));
+		unit_skilluse_id2(bl, target_id, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), cancel);
 	}
 
 	return SCRIPT_CMD_SUCCESS;
@@ -19313,8 +19385,8 @@ BUILDIN_FUNC(unitskilluseid)
 
 /// Makes the unit cast the skill on the target position.
 ///
-/// unitskillusepos <unit_id>,<skill_id>,<skill_lv>,<target_x>,<target_y>{,<casttime>};
-/// unitskillusepos <unit_id>,"<skill name>",<skill_lv>,<target_x>,<target_y>{,<casttime>};
+/// unitskillusepos <unit_id>,<skill_id>,<skill_lv>,<target_x>,<target_y>{,<casttime>,<cancel>,<Line_ID>};
+/// unitskillusepos <unit_id>,"<skill name>",<skill_lv>,<target_x>,<target_y>{,<casttime>,<cancel>,<Line_ID>};
 BUILDIN_FUNC(unitskillusepos)
 {
 	int skill_x, skill_y, casttime;
@@ -19340,15 +19412,26 @@ BUILDIN_FUNC(unitskillusepos)
 	skill_x  = script_getnum(st,5);
 	skill_y  = script_getnum(st,6);
 	casttime = ( script_hasdata(st,7) ? script_getnum(st,7) : 0 );
+	bool cancel = ( script_hasdata(st,8) ? script_getnum(st,8) > 0 : skill_get_castcancel(skill_id) );
+	int msg_id = (script_hasdata(st, 9) ? script_getnum(st, 9) : 0);
 
 	if(script_rid2bl(2,bl)){
+		if (msg_id > 0) {
+			if (bl->type != BL_MOB) {
+				ShowError("buildin_unitskilluseid: Msg can only be used for monster.\n");
+				return SCRIPT_CMD_FAILURE;
+			}
+			TBL_MOB* md = map_id2md(bl->id);
+			if (md)
+				mob_chat_display_message(*md, static_cast<uint16>(msg_id));
+		}
 		if (bl->type == BL_NPC) {
 			if (!((TBL_NPC*)bl)->status.hp)
 				status_calc_npc(((TBL_NPC*)bl), SCO_FIRST);
 			else
 				status_calc_npc(((TBL_NPC*)bl), SCO_NONE);
 		}
-		unit_skilluse_pos2(bl, skill_x, skill_y, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), skill_get_castcancel(skill_id));
+		unit_skilluse_pos2(bl, skill_x, skill_y, skill_id, skill_lv, (casttime * 1000) + skill_castfix(bl, skill_id, skill_lv), cancel);
 	}
 
 	return SCRIPT_CMD_SUCCESS;
@@ -19746,6 +19829,32 @@ BUILDIN_FUNC(mercenary_create)
 	return SCRIPT_CMD_SUCCESS;
 }
 
+BUILDIN_FUNC(mercenary_delete)
+{
+	struct map_session_data *sd;
+	int type = 0;
+
+	if( !script_charid2sd(2, sd) )
+		return SCRIPT_CMD_FAILURE;
+
+	if( sd->md == nullptr ) {
+		ShowWarning("buildin_mercenary_delete: Tried to delete a non existant mercenary from player '%s' (AID: %u, CID: %u)\n", sd->status.name, sd->status.account_id, sd->status.char_id);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	if( script_hasdata(st, 3) ) {
+		type = script_getnum(st, 3);
+		if( type < 0 || type > 3 ) {
+			ShowWarning("buildin_mercenary_delete: invalid type value of %d.\n", type);
+			return SCRIPT_CMD_FAILURE;
+		}
+	}
+	
+	mercenary_delete(sd->md, type);
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
 BUILDIN_FUNC(mercenary_heal)
 {
 	struct map_session_data *sd;
@@ -25272,6 +25381,33 @@ BUILDIN_FUNC(getenchantgrade){
 	return SCRIPT_CMD_SUCCESS;
 }
 
+/*==========================================
+ * mob_setidleevent( <monster game ID>, "<event label>" )
+ *------------------------------------------*/
+BUILDIN_FUNC(mob_setidleevent){
+	struct block_list* bl;
+
+	if( !script_rid2bl( 2, bl ) ){
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	if( bl->type != BL_MOB ){
+		ShowError( "buildin_mob_setidleevent: the target GID was not a monster.\n" );
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	struct mob_data* md = (struct mob_data*)bl;
+	if (md == nullptr)
+		return SCRIPT_CMD_FAILURE;
+
+	const char* idle_event = script_getstr( st, 3 );
+
+	check_event( st, idle_event );
+	safestrncpy( md->idle_event, idle_event, EVENT_NAME_LENGTH );
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
 #include "../custom/script.inc"
 
 // declarations that were supposed to be exported from npc_chat.cpp
@@ -25364,8 +25500,8 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(getitem2,"viiiiiiii?"),
 	BUILDIN_DEF(getnameditem,"vv"),
 	BUILDIN_DEF2(grouprandomitem,"groupranditem","i?"),
-	BUILDIN_DEF(makeitem,"visii"),
-	BUILDIN_DEF(makeitem2,"visiiiiiiiii"),
+	BUILDIN_DEF(makeitem,"visii?"),
+	BUILDIN_DEF(makeitem2,"visiiiiiiiii?"),
 	BUILDIN_DEF(delitem,"vi?"),
 	BUILDIN_DEF2(delitem,"storagedelitem","vi?"),
 	BUILDIN_DEF2(delitem,"guildstoragedelitem","vi?"),
@@ -25688,7 +25824,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(disguise,"i?"), //disguise player. Lupus
 	BUILDIN_DEF(undisguise,"?"), //undisguise player. Lupus
 	BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus
-	BUILDIN_DEF(addmonsterdrop,"vii"), //Akinari [Lupus]
+	BUILDIN_DEF(addmonsterdrop,"vii??"), //Akinari [Lupus]
 	BUILDIN_DEF(delmonsterdrop,"vi"), //Akinari [Lupus]
 	BUILDIN_DEF(axtoi,"s"),
 	BUILDIN_DEF(query_sql,"s*"),
@@ -25725,8 +25861,8 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(unitstopwalk,"i?"),
 	BUILDIN_DEF(unittalk,"is?"),
 	BUILDIN_DEF_DEPRECATED(unitemote,"ii","20170811"),
-	BUILDIN_DEF(unitskilluseid,"ivi??"), // originally by Qamera [Celest]
-	BUILDIN_DEF(unitskillusepos,"iviii?"), // [Celest]
+	BUILDIN_DEF(unitskilluseid,"ivi????"), // originally by Qamera [Celest]
+	BUILDIN_DEF(unitskillusepos,"iviii???"), // [Celest]
 // <--- [zBuffer] List of unit control commands
 	BUILDIN_DEF(sleep,"i"),
 	BUILDIN_DEF(sleep2,"i"),
@@ -25755,6 +25891,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(checkwall,"s"),
 	BUILDIN_DEF(searchitem,"rs"),
 	BUILDIN_DEF(mercenary_create,"ii"),
+	BUILDIN_DEF(mercenary_delete,"??"),
 	BUILDIN_DEF(mercenary_heal,"ii"),
 	BUILDIN_DEF(mercenary_sc_start,"iii"),
 	BUILDIN_DEF(mercenary_get_calls,"i"),
@@ -25929,7 +26066,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF2(getitem2,"getitem3","viiiiiiiirrr?"),
 	BUILDIN_DEF2(getitem2,"getitembound3","viiiiiiiiirrr?"),
 	BUILDIN_DEF2(rentitem2,"rentitem3","viiiiiiiirrr?"),
-	BUILDIN_DEF2(makeitem2,"makeitem3","visiiiiiiiiirrr"),
+	BUILDIN_DEF2(makeitem2,"makeitem3","visiiiiiiiiirrr?"),
 	BUILDIN_DEF2(delitem2,"delitem3","viiiiiiiirrr?"),
 	BUILDIN_DEF2(countitem,"countitem3","viiiiiiirrr?"),
 
@@ -25968,6 +26105,7 @@ struct script_function buildin_func[] = {
 
 	BUILDIN_DEF(getenchantgrade, ""),
 
+	BUILDIN_DEF(mob_setidleevent, "is"),
 #include "../custom/script_def.inc"
 
 	{NULL,NULL,NULL},

+ 1 - 0
src/map/script.hpp

@@ -480,6 +480,7 @@ enum unitdata_mobtypes {
 	UMOB_ROBE,
 	UMOB_BODY2,
 	UMOB_GROUP_ID,
+	UMOB_IGNORE_CELL_STACK_LIMIT,
 };
 
 enum unitdata_homuntypes {

+ 5 - 0
src/map/script_constants.hpp

@@ -1632,6 +1632,9 @@
 	export_constant(SC_PACKING_ENVELOPE9);
 	export_constant(SC_PACKING_ENVELOPE10);
 	export_constant(SC_SOULATTACK);
+	export_constant(SC_WIDEWEB);
+	export_constant(SC_BURNT);
+	export_constant(SC_CHILL);
 #ifdef RENEWAL
 	export_constant(SC_EXTREMITYFIST2);
 #endif
@@ -3847,6 +3850,7 @@
 	export_constant(AI_LEGION);
 	export_constant(AI_FAW);
 	export_constant(AI_GUILD);
+	export_constant(AI_WAVEMODE);
 
 	/* battle flags */
 	export_constant(BF_NONE);
@@ -4380,6 +4384,7 @@
 	export_constant(UMOB_ROBE);
 	export_constant(UMOB_BODY2);
 	export_constant(UMOB_GROUP_ID);
+	export_constant(UMOB_IGNORE_CELL_STACK_LIMIT);
 
 	/* unit control - homunculus */
 	export_constant(UHOM_SIZE);

+ 101 - 61
src/map/skill.cpp

@@ -1684,6 +1684,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 	case NPC_CRITICALWOUND:
 		sc_start(src,bl,SC_CRITICALWOUND,100,skill_lv,skill_get_time2(skill_id,skill_lv));
 		break;
+	case NPC_FIRESTORM:
+		sc_start(src,bl,SC_BURNT,100,skill_lv,skill_get_time(skill_id,skill_lv));
+		break;
 	case RK_DRAGONBREATH:
 		sc_start4(src,bl,SC_BURNING,15,skill_lv,1000,src->id,0,skill_get_time(skill_id,skill_lv));
 		break;
@@ -2168,17 +2171,13 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 	// Autospell when attacking
 	if( sd && !status_isdead(bl) && !sd->autospell.empty() )
 	{
-		struct block_list *tbl;
-		struct unit_data *ud;
-		int autospl_skill_lv, type;
-
 		for (const auto &it : sd->autospell) {
-			if (!(((it.flag)&attack_type)&BF_WEAPONMASK &&
-				  ((it.flag)&attack_type)&BF_RANGEMASK &&
-				  ((it.flag)&attack_type)&BF_SKILLMASK))
+			if (!(((it.battle_flag)&attack_type)&BF_WEAPONMASK &&
+				  ((it.battle_flag)&attack_type)&BF_RANGEMASK &&
+				  ((it.battle_flag)&attack_type)&BF_SKILLMASK))
 				continue; // one or more trigger conditions were not fulfilled
 
-			skill = (it.id > 0) ? it.id : -it.id;
+			skill = it.id;
 
 			sd->state.autocast = 1;
 			if ( skill_isNotOk(skill, sd) ) {
@@ -2187,17 +2186,20 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 			}
 			sd->state.autocast = 0;
 
-			autospl_skill_lv = it.lv?it.lv:1;
-			if (autospl_skill_lv < 0) autospl_skill_lv = 1+rnd()%(-autospl_skill_lv);
+			uint16 autospl_skill_lv = it.lv ? it.lv : 1;
+
+			if (it.flag & 2)
+				autospl_skill_lv = rnd_value( 1, autospl_skill_lv );
 
 			rate = (!sd->state.arrow_atk) ? it.rate : it.rate / 2;
 
 			if (rnd()%1000 >= rate)
 				continue;
 
-			tbl = (it.id < 0) ? src : bl;
+			block_list *tbl = (it.flag & 1) ? src : bl;
+			e_cast_type type = skill_get_casttype(skill);
 
-			if ((type = skill_get_casttype(skill)) == CAST_GROUND) {
+			if (type == CAST_GROUND) {
 				if (!skill_pos_maxcount_check(src, tbl->x, tbl->y, skill, autospl_skill_lv, BL_PC, false))
 					continue;
 			}
@@ -2229,14 +2231,17 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 					break;
 			}
 			sd->state.autocast = 0;
+
 			//Set canact delay. [Skotlex]
-			ud = unit_bl2ud(src);
+			unit_data *ud = unit_bl2ud(src);
+
 			if (ud) {
-				rate = skill_delayfix(src, skill, autospl_skill_lv);
-				if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){
-					ud->canact_tick = i64max(tick + rate, ud->canact_tick);
+				int delay = skill_delayfix(src, skill, autospl_skill_lv);
+
+				if (DIFF_TICK(ud->canact_tick, tick + delay) < 0){
+					ud->canact_tick = i64max(tick + delay, ud->canact_tick);
 					if ( battle_config.display_status_timers && sd )
-						clif_status_change(src, EFST_POSTDELAY, 1, rate, 0, 0, 0);
+						clif_status_change(src, EFST_POSTDELAY, 1, delay, 0, 0, 0);
 				}
 			}
 		}
@@ -2246,6 +2251,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 	if( sd && !sd->autobonus.empty() )
 	{
 		for(auto &it : sd->autobonus) {
+			if( it == nullptr ){
+				continue;
+			}
+
 			if (rnd()%1000 >= it->rate)
 				continue;
 			if (!(((it->atk_type)&attack_type)&BF_WEAPONMASK &&
@@ -2270,48 +2279,43 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 }
 
 int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, t_tick tick) {
-	struct block_list *tbl;
-
-	if( sd == NULL || !skill_id )
+	if( sd == nullptr || !skill_id )
 		return 0;
 
 	for (auto &it : sd->autospell3) {
-		int skill, skill_lv, type;
-
-		if (it.flag != skill_id)
+		if (it.trigger_skill != skill_id)
 			continue;
 
 		if (it.lock)
 			continue;  // autospell already being executed
 
-		skill = it.id;
+		uint16 skill = it.id;
+
 		sd->state.autocast = 1; //set this to bypass sd->canskill_tick check
 
-		if( skill_isNotOk((skill > 0) ? skill : skill*-1, sd) ) {
+		if( skill_isNotOk(skill, sd) ) {
 			sd->state.autocast = 0;
 			continue;
 		}
 
 		sd->state.autocast = 0;
 
-		if( skill >= 0 && bl == NULL )
+		if( skill > 0 && bl == nullptr )
 			continue; // No target
 		if( rnd()%1000 >= it.rate )
 			continue;
 
-		skill_lv = it.lv ? it.lv : 1;
-		if( skill < 0 ) {
-			tbl = &sd->bl;
-			skill *= -1;
-			skill_lv = 1 + rnd()%(-skill_lv); //random skill_lv
-		}
-		else
-			tbl = bl;
+		block_list *tbl = (it.flag & 1) ? &sd->bl : bl;
+		uint16 skill_lv = it.lv ? it.lv : 1;
+
+		if (it.flag & 2)
+			skill_lv = rnd_value( 1, skill_lv ); //random skill_lv
+
+		e_cast_type type = skill_get_casttype(skill);
+
+		if (type == CAST_GROUND && !skill_pos_maxcount_check(&sd->bl, tbl->x, tbl->y, skill_id, skill_lv, BL_PC, false))
+			continue;
 
-		if ((type = skill_get_casttype(skill)) == CAST_GROUND) {
-			if (!skill_pos_maxcount_check(&sd->bl, tbl->x, tbl->y, skill_id, skill_lv, BL_PC, false))
-				continue;
-		}
 		if (battle_config.autospell_check_range &&
 			!battle_check_range(bl, tbl, skill_get_range2(&sd->bl, skill, skill_lv, true)))
 			continue;
@@ -2320,9 +2324,15 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
 		it.lock = true;
 		skill_consume_requirement(sd,skill,skill_lv,1);
 		switch( type ) {
-			case CAST_GROUND:   skill_castend_pos2(&sd->bl, tbl->x, tbl->y, skill, skill_lv, tick, 0); break;
-			case CAST_NODAMAGE: skill_castend_nodamage_id(&sd->bl, tbl, skill, skill_lv, tick, 0); break;
-			case CAST_DAMAGE:   skill_castend_damage_id(&sd->bl, tbl, skill, skill_lv, tick, 0); break;
+			case CAST_GROUND:
+				skill_castend_pos2(&sd->bl, tbl->x, tbl->y, skill, skill_lv, tick, 0);
+				break;
+			case CAST_NODAMAGE:
+				skill_castend_nodamage_id(&sd->bl, tbl, skill, skill_lv, tick, 0);
+				break;
+			case CAST_DAMAGE:
+				skill_castend_damage_id(&sd->bl, tbl, skill, skill_lv, tick, 0);
+				break;
 		}
 		it.lock = false;
 		sd->state.autocast = 0;
@@ -2330,6 +2340,8 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1
 
 	if( sd && !sd->autobonus3.empty() ) {
 		for (auto &it : sd->autobonus3) {
+			if (it == nullptr)
+				continue;
 			if (rnd()%1000 >= it->rate)
 				continue;
 			if (it->atk_type != skill_id)
@@ -2484,21 +2496,19 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 	if(dstsd && !status_isdead(bl) && !dstsd->autospell2.empty() &&
 		!(skill_id && skill_get_nk(skill_id, NK_NODAMAGE)))
 	{
-		struct block_list *tbl;
-		struct unit_data *ud;
-		int autospl_skill_id, autospl_skill_lv, autospl_rate, type;
-
 		for (const auto &it : dstsd->autospell2) {
-			if (!(((it.flag)&attack_type)&BF_WEAPONMASK &&
-				  ((it.flag)&attack_type)&BF_RANGEMASK &&
-				  ((it.flag)&attack_type)&BF_SKILLMASK))
+			if (!(((it.battle_flag)&attack_type)&BF_WEAPONMASK &&
+				  ((it.battle_flag)&attack_type)&BF_RANGEMASK &&
+				  ((it.battle_flag)&attack_type)&BF_SKILLMASK))
 				continue; // one or more trigger conditions were not fulfilled
 
-			autospl_skill_id = (it.id > 0) ? it.id : -it.id;
-			autospl_skill_lv = it.lv ? it.lv : 1;
-			if (autospl_skill_lv < 0) autospl_skill_lv = 1+rnd()%(-autospl_skill_lv);
+			uint16 autospl_skill_id = it.id, autospl_skill_lv = it.lv ? it.lv : 1;
+
+			if (it.flag & 2)
+				autospl_skill_lv = rnd_value( 1, autospl_skill_lv );
+
+			int autospl_rate = it.rate;
 
-			autospl_rate = it.rate;
 			//Physical range attacks only trigger autospells half of the time
 			if ((attack_type&(BF_WEAPON|BF_LONG)) == (BF_WEAPON|BF_LONG))
 				 autospl_rate>>=1;
@@ -2513,11 +2523,11 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 			if (rnd()%1000 >= autospl_rate)
 				continue;
 
-			tbl = (it.id < 0) ? bl : src;
-			if ((type = skill_get_casttype(autospl_skill_id)) == CAST_GROUND) {
-				if (!skill_pos_maxcount_check(bl, tbl->x, tbl->y, autospl_skill_id, autospl_skill_lv, BL_PC, false))
+			block_list *tbl = (it.flag & 1) ? bl : src;
+			e_cast_type type = skill_get_casttype(autospl_skill_id);
+
+			if (type == CAST_GROUND && !skill_pos_maxcount_check(bl, tbl->x, tbl->y, autospl_skill_id, autospl_skill_lv, BL_PC, false))
 					continue;
-			}
 
 			if (!battle_check_range(bl, tbl, skill_get_range2(src, autospl_skill_id, autospl_skill_lv, true)) && battle_config.autospell_check_range)
 				continue;
@@ -2536,14 +2546,17 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 					break;
 			}
 			dstsd->state.autocast = 0;
+
 			//Set canact delay. [Skotlex]
-			ud = unit_bl2ud(bl);
+			unit_data *ud = unit_bl2ud(bl);
+
 			if (ud) {
-				autospl_rate = skill_delayfix(bl, autospl_skill_id, autospl_skill_lv);
-				if (DIFF_TICK(ud->canact_tick, tick + autospl_rate) < 0){
-					ud->canact_tick = i64max(tick + autospl_rate, ud->canact_tick);
+				int delay = skill_delayfix(bl, autospl_skill_id, autospl_skill_lv);
+
+				if (DIFF_TICK(ud->canact_tick, tick + delay) < 0){
+					ud->canact_tick = i64max(tick + delay, ud->canact_tick);
 					if ( battle_config.display_status_timers && dstsd )
-						clif_status_change(bl, EFST_POSTDELAY, 1, autospl_rate, 0, 0, 0);
+						clif_status_change(bl, EFST_POSTDELAY, 1, delay, 0, 0, 0);
 				}
 			}
 		}
@@ -2552,6 +2565,10 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 	//Autobonus when attacked
 	if( dstsd && !status_isdead(bl) && !dstsd->autobonus2.empty() && !(skill_id && skill_get_nk(skill_id, NK_NODAMAGE)) ) {
 		for (auto &it : dstsd->autobonus2) {
+			if( it == nullptr ){
+				continue;
+			}
+
 			if (rnd()%1000 >= it->rate)
 				continue;
 			if (!(((it->atk_type)&attack_type)&BF_WEAPONMASK &&
@@ -5398,6 +5415,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 	case WZ_EARTHSPIKE:
 	case AL_HEAL:
 	case NPC_DARKTHUNDER:
+	case NPC_FIRESTORM:
 	case PR_ASPERSIO:
 	case MG_FROSTDIVER:
 	case WZ_SIGHTBLASTER:
@@ -9603,6 +9621,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 	case NPC_WIDECOLD:
 	case NPC_WIDE_DEEP_SLEEP:
 	case NPC_WIDESIREN:
+	case NPC_WIDEWEB:
 		if (flag&1){
 			switch ( type ) {
 			case SC_BURNING:
@@ -9636,6 +9655,16 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				skill_castend_nodamage_id);
 		}
 		break;
+	case NPC_FIRESTORM: {
+		int sflag = flag;
+
+		if( skill_lv > 1 )
+			sflag |= 4;
+		clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
+		map_foreachinshootrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),splash_target(src),src,
+			skill_id,skill_lv,tick,sflag|BCT_ENEMY|SD_ANIMATION|1,skill_castend_damage_id);
+		}
+		break;
 	case ALL_PARTYFLEE:
 		if( sd  && !(flag&1) ) {
 			if( !sd->status.party_id ) {
@@ -12283,6 +12312,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 	case NPC_EVILLAND:
 	case NPC_VENOMFOG:
 	case NPC_COMET:
+	case NPC_WIDESUCK:
 	case NPC_ICEMINE:
 	case NPC_FLAMECROSS:
 	case NPC_HELLBURNING:
@@ -14219,6 +14249,16 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
 					if (map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR))
 						break; // Nothing should happen if the target is on Land Protector
 					// Fall through
+				case NPC_WIDESUCK: {
+						int heal = (int)skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
+
+						if (heal > 0) {
+							clif_skill_nodamage(ss,bl,sg->skill_id,sg->skill_lv,1);
+							clif_skill_nodamage(nullptr,ss,AL_HEAL,heal,1);
+							status_heal(ss,heal,0,0);
+						}
+					}
+					break;
 				default:
 					skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
 			}

+ 31 - 1
src/map/status.cpp

@@ -1045,6 +1045,8 @@ void initChangeTables(void)
 	add_sc( NPC_FIREWALK		, SC_PROPERTYWALK		);
 	add_sc( NPC_CLOUD_KILL   	, SC_POISON		);
 	set_sc( NPC_HALLUCINATIONWALK	, SC_NPC_HALLUCINATIONWALK	, EFST_NPC_HALLUCINATIONWALK	, SCB_FLEE );
+	set_sc( NPC_WIDEWEB           , SC_WIDEWEB           , EFST_WIDEWEB               , SCB_FLEE );
+	set_sc_with_vfx( NPC_FIRESTORM, SC_BURNT             , EFST_BURNT                 , SCB_NONE );
 
 	set_sc( CASH_BLESSING		, SC_BLESSING		, EFST_BLESSING		, SCB_STR|SCB_INT|SCB_DEX );
 	set_sc( CASH_INCAGI		, SC_INCREASEAGI	, EFST_INC_AGI, SCB_AGI|SCB_SPEED );
@@ -1662,6 +1664,8 @@ void initChangeTables(void)
 	StatusIconChangeTable[SC_DORAM_BUF_02] = EFST_DORAM_BUF_02;
 	StatusIconChangeTable[SC_SOULATTACK] = EFST_SOULATTACK;
 
+	StatusIconChangeTable[SC_CHILL] = EFST_CHILL;
+
 	// Item Reuse Limits
 	StatusIconChangeTable[SC_REUSE_REFRESH] = EFST_REUSE_REFRESH;
 	StatusIconChangeTable[SC_REUSE_LIMIT_A] = EFST_REUSE_LIMIT_A;
@@ -2025,6 +2029,7 @@ void initChangeTables(void)
 #ifndef RENEWAL
 	StatusChangeStateTable[SC_BASILICA]				|= SCS_NOMOVE|SCS_NOMOVECOND;
 #endif
+	StatusChangeStateTable[SC_WIDEWEB]				|= SCS_NOMOVE;
 	StatusChangeStateTable[SC_STOP]					|= SCS_NOMOVE;
 	StatusChangeStateTable[SC_CLOSECONFINE]			|= SCS_NOMOVE;
 	StatusChangeStateTable[SC_CLOSECONFINE2]		|= SCS_NOMOVE;
@@ -7338,7 +7343,7 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
 	// Rate value
 	if(sc->data[SC_INCFLEERATE])
 		flee += flee * sc->data[SC_INCFLEERATE]->val1/100;
-	if(sc->data[SC_SPIDERWEB])
+	if(sc->data[SC_SPIDERWEB] || sc->data[SC_WIDEWEB])
 		flee -= flee * 50/100;
 	if(sc->data[SC_BERSERK])
 		flee -= flee * 50/100;
@@ -9968,6 +9973,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		if (sc->data[type])
 			return 0;
 
+	case SC_BURNT:
+		if( sc->data[SC_CHILL] )
+			return 0;
+		break;
+
 	case SC_WEDDING:
 	case SC_XMAS:
 	case SC_SUMMER:
@@ -10456,6 +10466,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		if (sd)
 			pc_bonus_script_clear(sd, BSF_REM_ON_MADOGEAR);
 		break;
+	case SC_CHILL:
+		status_change_end(bl,SC_BURNT,INVALID_TIMER);
+		break;
 	}
 
 	// Check for overlapping fails
@@ -12330,6 +12343,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val3 = val1 * 25; // -movespeed TODO: Figure out movespeed rate
 			break;
 		case SC_C_MARKER:
+		case SC_BURNT:
 			// val1 = skill_lv
 			// val2 = src_id
 			val3 = 10; // -10 flee
@@ -12783,6 +12797,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_ELECTRICSHOCKER:
 		case SC_MAGNETICFIELD:
 		case SC_NETHERWORLD:
+		case SC_WIDEWEB:
 			if (!unit_blown_immune(bl,0x1))
 				unit_stop_walking(bl,1);
 			break;
@@ -15221,6 +15236,21 @@ TIMER_FUNC(status_change_timer){
 			return 0;
 		}
 		break;
+	case SC_BURNT:
+		if( --(sce->val4) >= 0 ) {
+			int damage = 2000;
+
+			if( damage >= status->hp )
+				damage = status->hp - 1;
+			map_freeblock_lock();
+			status_zap(bl,damage,0);
+			if( sc->data[type] ) {
+				sc_timer_next(1000 + tick);
+			}
+			map_freeblock_unlock();
+			return 0;
+		}
+		break;
 	}
 
 	// If status has an interval and there is at least 100ms remaining time, wait for next interval

+ 4 - 0
src/map/status.hpp

@@ -1023,6 +1023,10 @@ enum sc_type : int16 {
 
 	SC_SOULATTACK,
 
+	SC_WIDEWEB,
+	SC_BURNT,
+	SC_CHILL,
+
 #ifdef RENEWAL
 	SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled
 #endif

+ 2 - 1
src/map/unit.cpp

@@ -628,7 +628,8 @@ static TIMER_FUNC(unit_walktoxy_timer)
 		ud->to_x = bl->x;
 		ud->to_y = bl->y;
 
-		if(battle_config.official_cell_stack_limit > 0
+		if (!ud->state.ignore_cell_stack_limit
+			&& battle_config.official_cell_stack_limit > 0
 			&& map_count_oncell(bl->m, x, y, BL_CHAR|BL_NPC, 1) > battle_config.official_cell_stack_limit) {
 			//Walked on occupied cell, call unit_walktoxy again
 			if(ud->steptimer != INVALID_TIMER) {

+ 1 - 0
src/map/unit.hpp

@@ -57,6 +57,7 @@ struct unit_data {
 		unsigned walk_script : 1;
 		unsigned blockedmove : 1;
 		unsigned blockedskill : 1;
+		unsigned ignore_cell_stack_limit : 1;
 	} state;
 	char walk_done_event[EVENT_NAME_LENGTH];
 	char title[NAME_LENGTH];

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff