Browse Source

Merge branch 'master' into feature/map_zones

aleos 11 tháng trước cách đây
mục cha
commit
2553658eb9
79 tập tin đã thay đổi với 3429 bổ sung2233 xóa
  1. 4 4
      .github/workflows/analysis_codeql.yml
  2. 1 1
      .github/workflows/build_servers_clang.yml
  3. 1 1
      .github/workflows/build_servers_cmake.yml
  4. 6 2
      .github/workflows/build_servers_gcc.yml
  5. 1 1
      .github/workflows/build_servers_modes.yml
  6. 2 2
      .github/workflows/build_servers_msbuild.yml
  7. 1 1
      .github/workflows/build_servers_packetversions.yml
  8. 1 1
      .github/workflows/build_servers_vip.yml
  9. 1 1
      .github/workflows/npc_db_validation.yml
  10. 11 2
      conf/battle/battle.conf
  11. 7 0
      conf/battle/misc.conf
  12. 9 0
      conf/battle/monster.conf
  13. 2 2
      conf/battle/skill.conf
  14. 2 1
      db/import-tmpl/mob_db.yml
  15. 2 1
      db/mob_db.yml
  16. 125 1
      db/pre-re/mob_db.yml
  17. 10 27
      db/pre-re/mob_skill_db.txt
  18. 5 2
      db/re/item_db_usable.yml
  19. 2 2
      db/re/job_stats.yml
  20. 126 2
      db/re/mob_db.yml
  21. 38 57
      db/re/mob_skill_db.txt
  22. 1 2
      db/re/skill_db.yml
  23. 12 0
      doc/mob_db.txt
  24. 2 2
      doc/mob_skill_db_powerskill.txt
  25. 23 5
      doc/script_commands.txt
  26. 1 0
      doc/yaml/db/mob_db.yml
  27. 3 0
      doc/yaml/sql/mob_db.sql
  28. 3 0
      doc/yaml/sql/mob_db2.sql
  29. 3 0
      doc/yaml/sql/mob_db2_re.sql
  30. 3 0
      doc/yaml/sql/mob_db_re.sql
  31. 20 0
      npc/other/CashShop_Functions.txt
  32. 323 318
      npc/re/mobs/championmobs.txt
  33. 23 31
      npc/re/mobs/fields/prontera.txt
  34. 2 0
      npc/re/quests/quests_illusion_dungeons.txt
  35. 1 1
      src/char/char_clif.cpp
  36. 1 1
      src/common/strlib.cpp
  37. 1 1
      src/login/loginclif.cpp
  38. 49 45
      src/map/atcommand.cpp
  39. 111 62
      src/map/battle.cpp
  40. 3 0
      src/map/battle.hpp
  41. 8 8
      src/map/chat.cpp
  42. 2 2
      src/map/chrif.cpp
  43. 347 345
      src/map/clif.cpp
  44. 296 122
      src/map/clif.hpp
  45. 5 101
      src/map/clif_packetdb.hpp
  46. 4 4
      src/map/guild.cpp
  47. 23 19
      src/map/homunculus.cpp
  48. 11 7
      src/map/intif.cpp
  49. 2 2
      src/map/mail.cpp
  50. 21 18
      src/map/map.cpp
  51. 1 1
      src/map/map.hpp
  52. 10 3
      src/map/mercenary.cpp
  53. 139 53
      src/map/mob.cpp
  54. 7 2
      src/map/mob.hpp
  55. 38 23
      src/map/npc.cpp
  56. 595 67
      src/map/packets.hpp
  57. 31 1
      src/map/packets_struct.hpp
  58. 1 1
      src/map/party.cpp
  59. 211 205
      src/map/pc.cpp
  60. 11 12
      src/map/pet.cpp
  61. 56 47
      src/map/script.cpp
  62. 3 2
      src/map/script.hpp
  63. 112 98
      src/map/skill.cpp
  64. 0 4
      src/map/skill.hpp
  65. 63 63
      src/map/status.cpp
  66. 2 1
      src/map/status.hpp
  67. 33 27
      src/map/storage.cpp
  68. 15 15
      src/map/trade.cpp
  69. 71 29
      src/map/unit.cpp
  70. 2 2
      src/map/unit.hpp
  71. 6 6
      src/map/vending.cpp
  72. 12 12
      tools/check-doc.pl
  73. 253 254
      tools/config.pl
  74. 54 54
      tools/convert_emotions.py
  75. 7 7
      tools/convert_monstermode.pl
  76. 2 2
      tools/convert_sql.pl
  77. 5 7
      tools/runserver.bat
  78. 1 1
      tools/stackdump
  79. 27 27
      tools/update.pl

+ 4 - 4
.github/workflows/analysis_codeql.yml

@@ -38,11 +38,11 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       # Initializes the CodeQL tools for scanning.
       - name: Initialize CodeQL
-        uses: github/codeql-action/init@v2
+        uses: github/codeql-action/init@v3
         with:
            # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
            # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
@@ -74,7 +74,7 @@ jobs:
       #- name: Autobuild
       #  uses: github/codeql-action/autobuild@v2
 
-      # ✏️ If the Autobuild fails above, remove it and uncomment the following
+      # ?? If the Autobuild fails above, remove it and uncomment the following
       #    three lines and modify them (or add more) to build your code if your
       #    project uses a compiled language
       - name: Command - configure
@@ -89,4 +89,4 @@ jobs:
         run: make server
 
       - name: Perform CodeQL Analysis
-        uses: github/codeql-action/analyze@v2
+        uses: github/codeql-action/analyze@v3

+ 1 - 1
.github/workflows/build_servers_clang.yml

@@ -34,7 +34,7 @@ jobs:
           clang: ['6.0', '7', '8', '9', '10', '11'] #, '12', '13']
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
 
       - name: Set up Clang
         uses: egor-tensin/setup-clang@v1

+ 1 - 1
.github/workflows/build_servers_cmake.yml

@@ -34,7 +34,7 @@ jobs:
           os: [ubuntu-latest]
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
 
       # Install latest CMake.
       - uses: lukka/get-cmake@latest

+ 6 - 2
.github/workflows/build_servers_gcc.yml

@@ -31,10 +31,14 @@ jobs:
           # Available: ubuntu-22.04, ubuntu-20.04
           os: [ubuntu-latest]
           # Older versions of GCC are not available via unaltered aptitude repo lists.
-          gcc: ['9', '10', '11', '12', '13']
+          gcc: ['9', '10', '11', '12']
+          # GCC 13 was removed from 22.04, include it as a separate job
+          include:
+            - os: ubuntu-24.04
+              gcc: 13
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
 
       - name: Update & Install packages
         # Ubuntu runners already have most of the packages rAthena requires to build.

+ 1 - 1
.github/workflows/build_servers_modes.yml

@@ -36,7 +36,7 @@ jobs:
           mode: ['PRE','RE']
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
 
       # A simple 'yes' and 'no' can be confusing, so we use names to display in the current job then convert them for use in the compiler.
       - name: Variable Parsing - PRE

+ 2 - 2
.github/workflows/build_servers_msbuild.yml

@@ -34,10 +34,10 @@ jobs:
           mode: ['PRE', 'RE']
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
 
       - name: Add msbuild to PATH
-        uses: microsoft/setup-msbuild@v1.1
+        uses: microsoft/setup-msbuild@v2
 
       - name: Build solution in Debug
         if: ${{ matrix.mode == 'PRE' }}

+ 1 - 1
.github/workflows/build_servers_packetversions.yml

@@ -38,7 +38,7 @@ jobs:
           packetver: ['20211103', '20200902', '20200401', '20180620', '20151104']
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
 
       # A simple 'yes' and 'no' can be confusing, so we use names to display in the current job then convert them for use in the compiler.
       - name: Variable Parsing - PRE

+ 1 - 1
.github/workflows/build_servers_vip.yml

@@ -36,7 +36,7 @@ jobs:
           mode: ['PRE', 'RE']
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
 
       # A simple 'yes' and 'no' can be confusing, so we use names to display in the current job then convert them for use in the compiler.
       - name: Variable Parsing - PRE

+ 1 - 1
.github/workflows/npc_db_validation.yml

@@ -39,7 +39,7 @@ jobs:
           mode: ['PRE', 'RE']
 
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
       
       # A simple 'yes' and 'no' can be confusing, so we use names to display in the current job then convert them for use in the compiler.
       - name: Variable Parsing - PRE

+ 11 - 2
conf/battle/battle.conf

@@ -130,10 +130,19 @@ equip_self_break_rate: 100
 // This affects the behaviour of skills like acid terror and meltdown
 equip_skill_break_rate: 100
 
-// Do weapon attacks have a attack speed delay before actual damage is applied? (Note 1)
-// NOTE: The official setting is yes, even thought it degrades performance a bit.
+// Should damage have a delay before it is applied? (Note 1)
+// Some skills might not have a delay by default regardless of this setting.
+// The official setting is yes, even thought it degrades performance a bit.
 delay_battle_damage: yes
 
+// Should the damage timing be synchronized between the client and server? (Note 1)
+// This is not official behavior, but it should remove the position lag after being hit by a monster.
+// This setting only affects normal monster attacks and takes priority over "delay_battle_damage".
+// Many skills show their damage immediately, so setting "delay_battle_damage" to "no" at the same
+// time might improve the experience further, but will not work for all skills.
+// Tired of Dark Illusion hitting you 5 seconds too late? Then turn this on.
+synchronize_damage: no
+
 // Are arrows/ammo consumed when used on a bow/gun?
 // 0 = No
 // 1 = Yes

+ 7 - 0
conf/battle/misc.conf

@@ -175,3 +175,10 @@ mail_delay: 1000
 
 // Hides items from the player's favorite tab from being sold to a NPC. (Note 1)
 hide_fav_sell: no
+
+// When searching for a random position on the map, how much of the border of the map shall not be considered?
+// Officially the 15 tiles from the edge of the map on each side are not considered as target cells.
+// On some maps like in Pyramids this causes there to be very few monsters in the outer areas. This also
+// affects teleportation. Set this to 1 if you want it to be closer to the old emulator behavior.
+// Valid values: 1-40
+map_edge_size: 15

+ 9 - 0
conf/battle/monster.conf

@@ -163,6 +163,15 @@ no_spawn_on_player: 0
 // map regardless of what the mob-spawn file says.
 force_random_spawn: no
 
+// Should each monster's center cell be randomized? (Note 1)
+// Officially, at server start, each monster's center cell is set to a random cell in the spawn area.
+// Each time the monster spawns it will spawn in an area around its center cell rather than the
+// original center of the spawn definition. This results in a much larger total spawn area and a
+// different experience each server start.
+// Set this to "no" if you want all monsters of a spawn to spawn around the original center of the
+// spawn definition, making the total spawn area much smaller (old eAthena behavior).
+randomize_center_cell: yes
+
 // Do summon slaves inherit the passive/aggressive traits of their master?
 // 0: No, retain original mode.
 // 1: Slaves are always aggressive.

+ 2 - 2
conf/battle/skill.conf

@@ -26,8 +26,8 @@ min_skill_delay_limit: 100
 
 // This delay is the min 'can't walk delay' of all skills.
 // NOTE: Do not set this too low, if a character starts moving too soon after 
-// doing a skill, the client will not update this, and the player/mob will 
-// appear to "teleport" afterwards.
+// doing a skill, the client will not update this, and the player will appear
+// to "teleport" afterwards. Monsters use AttackMotion instead.
 default_walk_delay: 300
 
 // Completely disable skill delay of the following types (Note 3)

+ 2 - 1
db/import-tmpl/mob_db.yml

@@ -56,6 +56,7 @@
 #   WalkSpeed               Walk speed. (Default: DEFAULT_WALK_SPEED)
 #   AttackDelay             Attack speed. (Default: 0)
 #   AttackMotion            Attack animation speed. (Default: 0)
+#   ClientAttackMotion      Client attack speed. (Default: AttackMotion)
 #   DamageMotion            Damage animation speed. (Default: 0)
 #   DamageTaken             Rate at which the monster will receive incoming damage. (Default: 100)
 #   Ai                      Aegis monster type AI behavior. (Default: 06)
@@ -77,7 +78,7 @@
 
 Header:
   Type: MOB_DB
-  Version: 3
+  Version: 4
 
 #Body:
 # eAthena Dev Team

+ 2 - 1
db/mob_db.yml

@@ -56,6 +56,7 @@
 #   WalkSpeed               Walk speed. (Default: DEFAULT_WALK_SPEED)
 #   AttackDelay             Attack speed. (Default: 0)
 #   AttackMotion            Attack animation speed. (Default: 0)
+#   ClientAttackMotion      Client attack speed. (Default: AttackMotion)
 #   DamageMotion            Damage animation speed. (Default: 0)
 #   DamageTaken             Rate at which the monster will receive incoming damage. (Default: 100)
 #   Ai                      Aegis monster type AI behavior. (Default: 06)
@@ -77,7 +78,7 @@
 
 Header:
   Type: MOB_DB
-  Version: 3
+  Version: 4
 
 Footer:
   Imports:

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 125 - 1
db/pre-re/mob_db.yml


+ 10 - 27
db/pre-re/mob_skill_db.txt

@@ -4055,7 +4055,7 @@
 1764,Skeggiold@NPC_HOLYATTACK,chase,189,2,500,500,5000,no,target,always,0,,,,,,18,
 1764,Skeggiold@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 1764,Skeggiold@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
-1765,Valkyrie@AL_HEAL,idle,28,10,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,3,
+1765,Valkyrie@AL_HEAL,idle,28,11,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,3,
 1765,Valkyrie@AL_HEAL,attack,28,11,10000,500,10000,yes,friend,friendhpltmaxrate,60,,,,,,3,
 1765,Valkyrie@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 1765,Valkyrie@AS_SONICBLOW,attack,136,10,2000,0,5000,yes,target,always,0,,,,,,,
@@ -5594,7 +5594,7 @@
 2017,Rata@NPC_ARMORBRAKE,attack,344,3,2000,0,5000,yes,target,myhpltmaxrate,60,,,,,,,
 2017,Rata@WZ_EARTHSPIKE,attack,90,5,3000,1000,5000,no,target,always,0,,,,,,6,
 2017,Rata@NPC_PIERCINGATT,attack,158,3,500,0,5000,yes,target,always,0,,,,,,,
-2017,Rata@SM_MAGNUM,attack,7,10,500,500,5000,no,self,always,0,,,,,,,
+2017,Rata@SM_MAGNUM,attack,7,25,500,500,5000,no,self,always,0,,,,,,,
 2017,Rata@NPC_GROUNDATTACK,attack,185,2,500,500,5000,no,target,always,0,,,,,,,
 2017,Rata@NPC_CURSEATTACK,attack,181,3,500,800,5000,no,target,always,0,,,,,,,
 2017,Rata@NPC_POISONATTACK,attack,188,1,2000,0,5000,yes,target,always,0,,,,,,,
@@ -5694,6 +5694,14 @@
 2027,Dark Shadow@NPC_FIREATTACK,attack,186,3,500,500,5000,no,target,always,0,,,,,,,
 2027,Dark Shadow@NPC_DARKNESSBREATH,attack,658,1,500,1000,5000,no,target,always,0,,,,,,,
 
+//****
+// NC Mechanic Summons
+2042,Silver Sniper@NPC_REVENGE,idle,333,1,10000,0,0,yes,self,masterattacked,0,,,,,,,
+2043,Magic Decoy Fire@MG_FIREBOLT,idle,19,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
+2044,Magic Decoy Water@MG_COLDBOLT,idle,14,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
+2045,Magic Decoy Earth@WZ_EARTHSPIKE,idle,90,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
+2046,Magic Decoy Wind@MG_LIGHTNINGBOLT,idle,20,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
+
 // Brasilis
 2068,Boitata@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,0,,,,,,,
 2068,Boitata@MG_FIREBALL,idle,17,5,10000,0,5000,yes,randomtarget,always,0,,,,,,,
@@ -5771,28 +5779,3 @@
 2082,Piranha@MG_COLDBOLT,chase,14,3,500,1000,5000,yes,target,always,0,,,,,,,
 2082,Piranha@WZ_WATERBALL,attack,86,3,500,1000,5000,yes,target,always,0,,,,,,6,
 2082,Piranha@NPC_BLOODDRAIN,attack,199,1,500,0,5000,yes,target,always,0,,,,,,,
-//****
-// NC Mechanic Summons
-2042,Silver Sniper@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2042,Silver Sniper@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2042,Silver Sniper@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2043,Magic Decoy Fire@MG_FIREBOLT,attack,19,10,10000,800,3500,no,target,always,0,,,,,,,
-2043,Magic Decoy Fire@MG_FIREBOLT,chase,19,10,10000,800,3500,no,target,always,0,,,,,,,
-2043,Magic Decoy Fire@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2043,Magic Decoy Fire@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2043,Magic Decoy Fire@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2044,Magic Decoy Water@MG_COLDBOLT,attack,14,10,10000,800,3500,no,target,always,0,,,,,,,
-2044,Magic Decoy Water@MG_COLDBOLT,chase,14,10,10000,800,3500,no,target,always,0,,,,,,,
-2044,Magic Decoy Water@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2044,Magic Decoy Water@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2044,Magic Decoy Water@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2045,Magic Decoy Earth@WZ_EARTHSPIKE,attack,90,10,10000,800,3500,no,target,always,0,,,,,,,
-2045,Magic Decoy Earth@WZ_EARTHSPIKE,chase,90,10,10000,800,3500,no,target,always,0,,,,,,,
-2045,Magic Decoy Earth@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2045,Magic Decoy Earth@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2045,Magic Decoy Earth@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2046,Magic Decoy Wind@MG_LIGHTNINGBOLT,attack,20,10,10000,800,3500,no,target,always,0,,,,,,,
-2046,Magic Decoy Wind@MG_LIGHTNINGBOLT,chase,20,10,10000,800,3500,no,target,always,0,,,,,,,
-2046,Magic Decoy Wind@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2046,Magic Decoy Wind@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2046,Magic Decoy Wind@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,

+ 5 - 2
db/re/item_db_usable.yml

@@ -9511,6 +9511,8 @@ Body:
       NoGuildStorage: true
       NoMail: true
       NoAuction: true
+    Script: |
+      callfunc "F_CashSiegeTele2";
   - Id: 12416
     AegisName: Lucky_Egg_C3
     Name: Lucky Egg C3
@@ -14443,14 +14445,15 @@ Body:
   - Id: 12858
     AegisName: Golden_Potion_RG
     Name: RG Golden Potion
-    Type: Delayconsume
+    Type: Usable
     Weight: 30
     Delay:
       Duration: 1000
       Status: Reuse_Limit_F
     Script: |
       percentheal 100,100;
-      itemskill "PR_KYRIE",10;
+      sc_start SC_KYRIE,100000,10;
+      skilleffect "PR_KYRIE",0;
   - Id: 12860
     AegisName: Mommy_Day_Cake
     Name: Mommy Day Cake

+ 2 - 2
db/re/job_stats.yml

@@ -9213,7 +9213,7 @@ Body:
         Vit: 1
         Int: 1
       - Level: 13
-        Agi: 1
+        Dex: 1
         Spl: 1
       - Level: 14
         Sta: 1
@@ -9229,7 +9229,7 @@ Body:
         Int: 1
         Dex: 1
       - Level: 19
-        Dex: 1
+        Int: 1
       - Level: 20
         Vit: 1
         Int: 1

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 126 - 2
db/re/mob_db.yml


+ 38 - 57
db/re/mob_skill_db.txt

@@ -4063,7 +4063,7 @@
 1764,Skeggiold@NPC_HOLYATTACK,chase,189,2,500,500,5000,no,target,always,0,,,,,,18,
 1764,Skeggiold@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 1764,Skeggiold@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
-1765,Valkyrie@AL_HEAL,idle,28,10,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,3,
+1765,Valkyrie@AL_HEAL,idle,28,11,10000,500,5000,yes,friend,friendhpltmaxrate,60,,,,,,3,
 1765,Valkyrie@AL_HEAL,attack,28,11,10000,500,10000,yes,friend,friendhpltmaxrate,60,,,,,,3,
 1765,Valkyrie@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 1765,Valkyrie@AS_SONICBLOW,attack,136,10,2000,0,5000,yes,target,always,0,,,,,,,
@@ -5704,30 +5704,11 @@
 
 //****
 // NC Mechanic Summons
-2042,Silver Sniper@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2042,Silver Sniper@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2042,Silver Sniper@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2042,Silver Sniper@NPC_REVENGE,idle,333,1,10000,0,0,yes,self,always,0,,,,,,,
-2043,Magic Decoy Fire@MG_FIREBOLT,attack,19,10,10000,800,3500,no,target,always,0,,,,,,,
-2043,Magic Decoy Fire@MG_FIREBOLT,chase,19,10,10000,800,3500,no,target,always,0,,,,,,,
-2043,Magic Decoy Fire@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2043,Magic Decoy Fire@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2043,Magic Decoy Fire@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2044,Magic Decoy Water@MG_COLDBOLT,attack,14,10,10000,800,3500,no,target,always,0,,,,,,,
-2044,Magic Decoy Water@MG_COLDBOLT,chase,14,10,10000,800,3500,no,target,always,0,,,,,,,
-2044,Magic Decoy Water@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2044,Magic Decoy Water@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2044,Magic Decoy Water@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2045,Magic Decoy Earth@WZ_EARTHSPIKE,attack,90,10,10000,800,3500,no,target,always,0,,,,,,,
-2045,Magic Decoy Earth@WZ_EARTHSPIKE,chase,90,10,10000,800,3500,no,target,always,0,,,,,,,
-2045,Magic Decoy Earth@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2045,Magic Decoy Earth@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2045,Magic Decoy Earth@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2046,Magic Decoy Wind@MG_LIGHTNINGBOLT,attack,20,10,10000,800,3500,no,target,always,0,,,,,,,
-2046,Magic Decoy Wind@MG_LIGHTNINGBOLT,chase,20,10,10000,800,3500,no,target,always,0,,,,,,,
-2046,Magic Decoy Wind@AL_HEAL,chase,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2046,Magic Decoy Wind@AL_HEAL,idle,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
-2046,Magic Decoy Wind@AL_HEAL,attack,28,10,10000,0,1000,no,self,myhpltmaxrate,99,,,,,,,
+2042,Silver Sniper@NPC_REVENGE,idle,333,1,10000,0,0,yes,self,masterattacked,0,,,,,,,
+2043,Magic Decoy Fire@MG_FIREBOLT,idle,19,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
+2044,Magic Decoy Water@MG_COLDBOLT,idle,14,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
+2045,Magic Decoy Earth@WZ_EARTHSPIKE,idle,90,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
+2046,Magic Decoy Wind@MG_LIGHTNINGBOLT,idle,20,10,10000,800,3500,no,randomtarget,always,0,,,,,,,
 
 //2053,Dimik@NPC_ATTRICHANGE,idle,161,1,500,2000,50000,no,self,always,0,,,,,,10,
 //2053,Dimik@NPC_EMOTION_ON,idle,474,1,100,0,60000,yes,self,always,0,20,0x81,,,,,
@@ -8856,11 +8837,11 @@
 2481,Wraith Dead (Nightmare)@NPC_ENERGYDRAIN,attack,200,1,500,0,5000,yes,target,always,,,,,,,9,
 2483,Baphomet (Nightmare)@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 2483,Baphomet (Nightmare)@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
-2483,Baphomet (Nightmare)@AL_HEAL,idle,28,10,10000,0,5000,yes,self,myhpltmaxrate,50,,,,,,,
+2483,Baphomet (Nightmare)@AL_HEAL,idle,28,11,10000,0,5000,yes,self,myhpltmaxrate,50,,,,,,,
 2483,Baphomet (Nightmare)@KN_BRANDISHSPEAR,attack,57,10,2000,500,5000,no,target,always,,,,,,,29,
-2483,Baphomet (Nightmare)@WZ_VERMILION,attack,85,10,2000,500,2000,no,target,always,,,,,,,29,
-2483,Baphomet (Nightmare)@WZ_VERMILION,chase,85,10,2000,500,2000,no,target,always,,,,,,,29,
-2483,Baphomet (Nightmare)@WZ_VERMILION,chase,85,10,5000,500,2000,no,target,skillused,18,,,,,,29,
+2483,Baphomet (Nightmare)@WZ_VERMILION,attack,85,21,2000,500,2000,no,target,always,,,,,,,29,
+2483,Baphomet (Nightmare)@WZ_VERMILION,chase,85,21,2000,500,2000,no,target,always,,,,,,,29,
+2483,Baphomet (Nightmare)@WZ_VERMILION,chase,85,21,5000,500,2000,no,target,skillused,18,,,,,,29,
 2483,Baphomet (Nightmare)@NPC_GUIDEDATTACK,attack,172,5,500,0,20000,no,target,always,,,,,,,,
 2483,Baphomet (Nightmare)@NPC_DARKBREATH,attack,202,5,2000,800,5000,no,target,always,,,,,,,29,
 2483,Baphomet (Nightmare)@MO_BODYRELOCATION,chase,264,1,2000,200,1000,yes,target,always,,,,,,,,
@@ -8948,15 +8929,15 @@
 2534,Blue Faceworm Queen@WZ_STORMGUST,chase,89,10,2000,1000,5000,no,target,always,,,,,,,,
 2534,Blue Faceworm Queen@WZ_STORMGUST,attack,89,10,2000,1000,5000,no,target,always,,,,,,,,
 2534,Blue Faceworm Queen@NPC_WATERATTACK,attack,184,9,3000,500,5000,no,target,always,,,,,,,,
-2534,Blue Faceworm Queen@MG_FROSTDIVER,chase,15,10,10000,500,5000,yes,target,always,,,,,,,,
-2535,Yellow Faceworm Queen@WZ_VERMILION,attack,85,10,2000,1000,10000,no,target,always,,,,,,,,
-2535,Yellow Faceworm Queen@WZ_VERMILION,chase,85,10,5000,1000,10000,no,target,always,,,,,,,,
+2534,Blue Faceworm Queen@MG_FROSTDIVER,chase,15,40,10000,500,5000,yes,target,always,,,,,,,,
+2535,Yellow Faceworm Queen@WZ_VERMILION,attack,85,21,2000,1000,10000,no,target,always,,,,,,,,
+2535,Yellow Faceworm Queen@WZ_VERMILION,chase,85,21,5000,1000,10000,no,target,always,,,,,,,,
 2535,Yellow Faceworm Queen@NPC_WIDEBLEEDING,chase,665,3,10000,2000,30000,no,self,always,,,,,,,36,
 2535,Yellow Faceworm Queen@NPC_WIDEBLEEDING,attack,665,3,10000,2000,30000,no,self,always,,,,,,,36,
 2535,Yellow Faceworm Queen@WZ_JUPITEL,attack,84,9,1000,500,5000,yes,target,always,,,,,,,,
 2535,Yellow Faceworm Queen@WZ_JUPITEL,chase,84,9,1000,500,5000,yes,target,always,,,,,,,,
 2535,Yellow Faceworm Queen@NPC_WINDATTACK,attack,187,9,3000,500,5000,no,target,always,,,,,,,,
-2535,Yellow Faceworm Queen@MG_THUNDERSTORM,attack,21,10,2000,1000,5000,no,target,always,,,,,,,,
+2535,Yellow Faceworm Queen@MG_THUNDERSTORM,attack,21,20,2000,1000,5000,no,target,always,,,,,,,,
 2536,Monster 3@NPC_INVISIBLE,idle,353,1,10000,0,30000,yes,self,always,,,,,,,,
 2536,Monster 3@NPC_INVISIBLE,attack,353,1,10000,0,30000,yes,self,always,,,,,,,,
 2536,Monster 3@NPC_VENOMFOG,idle,706,1,10000,0,3000,yes,self,always,,,,,,,,
@@ -9840,7 +9821,7 @@
 2741,Muka Ringleader@NPC_PIERCINGATT,attack,158,2,500,0,5000,yes,target,always,,,,,,,6,
 2741,Muka Ringleader@NPC_SPLASHATTACK,attack,174,1,2000,0,5000,yes,target,attackpcge,2,,,,,,,
 2741,Muka Ringleader@NPC_SUMMONSLAVE,idle,196,2,10000,700,30000,no,self,slavele,0,1055,,,,,,
-2742,Furious Incarnation of Morocc@AL_HEAL,idle,28,10,10000,0,5000,yes,self,myhpltmaxrate,45,,,,,,,
+2742,Furious Incarnation of Morocc@AL_HEAL,idle,28,11,10000,0,5000,yes,self,myhpltmaxrate,45,,,,,,,
 2742,Furious Incarnation of Morocc@AL_PNEUMA,idle,25,1,10000,0,1000,yes,self,longrangeattacked,,,,,,,,
 2742,Furious Incarnation of Morocc@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 2742,Furious Incarnation of Morocc@AL_TELEPORT,chase,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
@@ -9853,7 +9834,7 @@
 2742,Furious Incarnation of Morocc@NPC_WIDECURSE,chase,677,5,5000,800,5000,no,self,always,,,,,,,,
 2742,Furious Incarnation of Morocc@SA_DISPELL,attack,289,5,100,0,30000,yes,target,always,,,,,,,,
 2742,Furious Incarnation of Morocc@SA_DISPELL,chase,289,5,100,0,30000,yes,target,always,,,,,,,,
-2743,Elusive Incarnation of Morocc@AL_HEAL,idle,28,10,10000,0,5000,yes,self,myhpltmaxrate,45,,,,,,,
+2743,Elusive Incarnation of Morocc@AL_HEAL,idle,28,11,10000,0,5000,yes,self,myhpltmaxrate,45,,,,,,,
 2743,Elusive Incarnation of Morocc@AL_PNEUMA,idle,25,1,10000,0,1000,yes,self,longrangeattacked,,,,,,,,
 2743,Elusive Incarnation of Morocc@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 2743,Elusive Incarnation of Morocc@AL_TELEPORT,chase,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
@@ -9869,7 +9850,7 @@
 2744,Swift Incarnation of Morocc@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 2744,Swift Incarnation of Morocc@AL_TELEPORT,chase,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
 2744,Swift Incarnation of Morocc@AL_TELEPORT,attack,26,1,500,0,5000,yes,self,myhpltmaxrate,50,,,,,,,
-2744,Swift Incarnation of Morocc@AL_HEAL,idle,28,10,10000,0,5000,yes,self,myhpltmaxrate,45,,,,,,,
+2744,Swift Incarnation of Morocc@AL_HEAL,idle,28,11,10000,0,5000,yes,self,myhpltmaxrate,45,,,,,,,
 2744,Swift Incarnation of Morocc@AL_HEAL,attack,28,5,10000,500,5000,yes,self,myhpltmaxrate,50,,,,,,,
 2744,Swift Incarnation of Morocc@AL_PNEUMA,idle,25,1,10000,0,1000,yes,self,longrangeattacked,,,,,,,,
 2744,Swift Incarnation of Morocc@NPC_GRANDDARKNESS,attack,339,5,10000,2000,30000,no,self,myhpltmaxrate,80,,,,,,6,
@@ -11387,7 +11368,7 @@
 3209,V_MAGALETA@AL_HEAL,idle,28,9,300,0,2000,yes,self,myhpltmaxrate,99,,,,,,3,
 3209,V_MAGALETA@HP_ASSUMPTIO,chase,361,5,1000,1000,10000,no,self,myhpltmaxrate,99,,,,,,,
 3209,V_MAGALETA@HP_ASSUMPTIO,chase,361,5,1000,1000,10000,no,friend,friendhpltmaxrate,99,,,,,,,
-3209,V_MAGALETA@AL_DECAGI,chase,30,10,200,0,10000,yes,target,always,,,,,,,,
+3209,V_MAGALETA@AL_DECAGI,chase,30,48,200,0,10000,yes,target,always,,,,,,,,
 3209,V_MAGALETA@NPC_MAXPAIN,chase,716,5,1000,1000,60000,no,self,longrangeattacked,,,,,,,19,
 3209,V_MAGALETA@PR_LEXDIVINA,chase,76,10,500,0,10000,yes,target,casttargeted,,,,,,,18,
 3209,V_MAGALETA@PR_LEXAETERNA,chase,78,1,100,0,10000,yes,target,always,,,,,,,29,
@@ -11405,11 +11386,11 @@
 3209,V_MAGALETA@NPC_WIDESILENCE,attack,663,2,300,500,5000,no,self,always,,,,,,,,
 3210,V_KATRINN@MG_SIGHT,idle,10,1,200,0,10000,yes,self,always,,,,,,,,
 3210,V_KATRINN@AL_TELEPORT,idle,26,1,1000,0,0,yes,self,rudeattacked,,,,,,,,
-3210,V_KATRINN@WZ_JUPITEL,chase,84,10,300,0,10000,yes,target,always,,,,,,,,
+3210,V_KATRINN@WZ_JUPITEL,chase,84,28,300,0,10000,yes,target,always,,,,,,,,
 3210,V_KATRINN@WZ_WATERBALL,chase,86,5,300,0,10000,yes,target,always,,,,,,,,
 3210,V_KATRINN@NPC_DARKSTRIKE,chase,340,10,300,0,10000,yes,target,always,,,,,,,,
 3210,V_KATRINN@MG_FIREWALL,chase,18,10,300,0,10000,yes,target,always,,,,,,,,
-3210,V_KATRINN@MG_FROSTDIVER,chase,15,10,300,0,10000,yes,target,always,,,,,,,,
+3210,V_KATRINN@MG_FROSTDIVER,chase,15,40,300,0,10000,yes,target,always,,,,,,,,
 3210,V_KATRINN@HW_NAPALMVULCAN,chase,400,5,300,0,10000,yes,target,always,,,,,,,,
 3210,V_KATRINN@WZ_FROSTNOVA,chase,88,10,300,0,10000,yes,target,longrangeattacked,,,,,,,,
 3210,V_KATRINN@WL_EARTHSTRAIN,chase,2216,5,300,0,10000,yes,target,always,,,,,,,,
@@ -11420,7 +11401,7 @@
 3210,V_KATRINN@NPC_WIDEFREEZE,attack,664,3,300,500,10000,no,self,always,,,,,,,,
 3210,V_KATRINN@NPC_DARKSTRIKE,attack,340,10,300,0,10000,yes,target,always,,,,,,,,
 3210,V_KATRINN@WL_TETRAVORTEX,attack,2217,2,300,500,10000,no,target,always,,,,,,,,
-3210,V_KATRINN@WZ_JUPITEL,attack,84,10,300,0,10000,yes,target,always,,,,,,,,
+3210,V_KATRINN@WZ_JUPITEL,attack,84,28,300,0,10000,yes,target,always,,,,,,,,
 3210,V_KATRINN@WL_EARTHSTRAIN,attack,2216,3,300,500,10000,no,target,always,,,,,,,,
 3210,V_KATRINN@WZ_SIGHTRASHER,attack,81,10,300,0,10000,yes,self,always,,,,,,,,
 3210,V_KATRINN@NPC_SUMMONSLAVE,attack,196,1,50,0,600000,yes,self,slavele,0,1641,,,,,,
@@ -11489,11 +11470,11 @@
 3215,V_G_MAGALETA@HP_ASSUMPTIO,chase,361,5,1000,1000,10000,no,self,myhpltmaxrate,99,,,,,,,
 3215,V_G_MAGALETA@HP_ASSUMPTIO,chase,361,5,1000,1000,10000,no,friend,friendhpltmaxrate,99,,,,,,,
 3215,V_G_MAGALETA@AL_INCAGI,chase,29,10,200,0,240000,yes,self,always,,,,,,,2,
-3215,V_G_MAGALETA@AL_DECAGI,chase,30,10,200,0,10000,yes,target,always,,,,,,,,
+3215,V_G_MAGALETA@AL_DECAGI,chase,30,48,200,0,10000,yes,target,always,,,,,,,,
 3215,V_G_MAGALETA@NPC_WIDESILENCE,chase,663,2,500,0,10000,yes,target,casttargeted,,,,,,,18,
 3215,V_G_MAGALETA@AL_PNEUMA,chase,25,1,500,0,10000,yes,self,longrangeattacked,,,,,,,19,
-3215,V_G_MAGALETA@AL_HEAL,chase,28,10,300,0,1500,yes,friend,friendhpltmaxrate,99,,,,,,3,
-3215,V_G_MAGALETA@AL_HEAL,chase,28,10,300,0,1500,yes,self,myhpltmaxrate,99,,,,,,3,
+3215,V_G_MAGALETA@AL_HEAL,chase,28,11,300,0,1500,yes,friend,friendhpltmaxrate,99,,,,,,3,
+3215,V_G_MAGALETA@AL_HEAL,chase,28,11,300,0,1500,yes,self,myhpltmaxrate,99,,,,,,3,
 3215,V_G_MAGALETA@AL_INCAGI,attack,29,10,200,0,240000,yes,self,always,,,,,,,2,
 3215,V_G_MAGALETA@MG_SAFETYWALL,attack,12,10,100,0,10000,yes,self,always,,,,,,,,
 3215,V_G_MAGALETA@AL_PNEUMA,attack,25,1,500,0,10000,yes,self,longrangeattacked,,,,,,,19,
@@ -11510,14 +11491,14 @@
 3216,V_G_KATRINN@NPC_WIDEFREEZE,chase,664,5,300,3000,10000,no,self,always,,,,,,,,
 3216,V_G_KATRINN@HW_NAPALMVULCAN,chase,400,5,200,1000,2000,no,target,always,,,,,,,,
 3216,V_G_KATRINN@NPC_STORMGUST2,chase,723,3,300,1000,10000,no,target,always,,,,,,,,
-3216,V_G_KATRINN@WZ_VERMILION,chase,85,10,300,1000,10000,no,target,always,,,,,,,,
-3216,V_G_KATRINN@WZ_METEOR,chase,83,10,300,1000,10000,no,target,always,,,,,,,,
+3216,V_G_KATRINN@WZ_VERMILION,chase,85,21,300,1000,10000,no,target,always,,,,,,,,
+3216,V_G_KATRINN@WZ_METEOR,chase,83,11,300,1000,10000,no,target,always,,,,,,,,
 3216,V_G_KATRINN@NPC_COMET,attack,708,5,300,1000,7000,no,self,always,,,,,,,,
 3216,V_G_KATRINN@NPC_STORMGUST2,attack,723,3,200,1000,10000,no,target,always,,,,,,,,
 3216,V_G_KATRINN@NPC_WIDESTONE,attack,666,1,200,1000,10000,no,self,always,,,,,,,,
 3216,V_G_KATRINN@HW_GANBANTEIN,attack,483,1,300,500,10000,no,target,always,,,,,,,,
 3216,V_G_KATRINN@WL_EARTHSTRAIN,attack,2216,5,300,1000,7000,no,target,always,,,,,,,,
-3216,V_G_KATRINN@WZ_JUPITEL,attack,84,10,200,1000,10000,no,target,always,,,,,,,,
+3216,V_G_KATRINN@WZ_JUPITEL,attack,84,28,200,1000,10000,no,target,always,,,,,,,,
 3216,V_G_KATRINN@WL_TETRAVORTEX,attack,2217,5,300,1000,7000,no,target,always,,,,,,,,
 3216,V_G_KATRINN@NPC_WIDEFREEZE,attack,664,5,200,1000,10000,no,self,always,,,,,,,,
 3217,V_G_SHECIL@NPC_AGIUP,idle,350,1,1000,0,600000,yes,self,always,,,,,,,,
@@ -11534,7 +11515,7 @@
 3218,V_G_HARWORD@NPC_SELFDESTRUCTION,attack,173,1,200,2000,0,no,self,myhpltmaxrate,10,,,,,,,
 3218,V_G_HARWORD@BS_ADRENALINE,attack,111,10,200,0,150000,yes,self,always,,,,,,,,
 3218,V_G_HARWORD@BS_MAXIMIZE,attack,114,1,100,0,60000,yes,self,always,,,,,,,,
-3218,V_G_HARWORD@MC_MAMMONITE,attack,42,10,200,0,10000,yes,target,always,,,,,,,23,
+3218,V_G_HARWORD@MC_MAMMONITE,attack,42,22,200,0,10000,yes,target,always,,,,,,,23,
 3218,V_G_HARWORD@BS_HAMMERFALL,attack,110,10,200,0,30000,yes,target,always,,,,,,,,
 3218,V_G_HARWORD@NPC_POWERUP,attack,349,5,200,0,100000,yes,self,always,,,,,,,,
 3218,V_G_HARWORD@NPC_SPLASHATTACK,attack,174,1,100,0,0,yes,target,attackpcge,2,,,,,,,
@@ -11548,7 +11529,7 @@
 3219,V_G_SEYREN@SM_PROVOKE,chase,6,10,100,0,10000,yes,target,always,,,,,,,29,
 3219,V_G_SEYREN@SM_ENDURE,chase,8,10,500,0,30000,yes,self,longrangeattacked,,,,,,,6,
 3219,V_G_SEYREN@NPC_DARKPIERCING,chase,715,1,100,0,10000,yes,target,always,,,,,,,,
-3219,V_G_SEYREN@KN_TWOHANDQUICKEN,attack,60,10,1000,0,300000,yes,self,always,,,,,,,2,
+3219,V_G_SEYREN@KN_TWOHANDQUICKEN,attack,60,30,1000,0,300000,yes,self,always,,,,,,,2,
 3219,V_G_SEYREN@LK_SPIRALPIERCE,attack,397,5,200,0,10000,yes,target,always,,,,,,,,
 3219,V_G_SEYREN@NPC_POWERUP,attack,349,5,200,0,25000,yes,self,myhpltmaxrate,30,,,,,,,
 3219,V_G_SEYREN@NPC_DRAGONBREATH,attack,731,5,300,500,10000,no,target,always,,,,,,,,
@@ -11639,7 +11620,7 @@
 3223,V_B_HARWORD@NPC_SUMMONMONSTER,attack,209,1,1000,700,60000000,yes,self,myhpltmaxrate,30,3219,3214,3215,3216,3217,,
 3223,V_B_HARWORD@BS_ADRENALINE,attack,111,10,200,0,150000,yes,self,always,,,,,,,,
 3223,V_B_HARWORD@BS_MAXIMIZE,attack,114,1,100,0,60000,yes,self,always,,,,,,,,
-3223,V_B_HARWORD@MC_MAMMONITE,attack,42,10,200,0,10000,yes,target,always,,,,,,,23,
+3223,V_B_HARWORD@MC_MAMMONITE,attack,42,22,200,0,10000,yes,target,always,,,,,,,23,
 3223,V_B_HARWORD@BS_HAMMERFALL,attack,110,10,200,0,10000,yes,target,always,,,,,,,,
 3223,V_B_HARWORD@NPC_POWERUP,attack,349,5,200,0,100000,yes,self,always,,,,,,,,
 3223,V_B_HARWORD@NPC_MAXPAIN,attack,716,10,500,1000,10000,no,self,always,,,,,,,19,
@@ -11661,7 +11642,7 @@
 3224,V_B_KATRINN@NPC_WIDESTONE,attack,666,1,200,1000,10000,no,self,always,,,,,,,,
 3224,V_B_KATRINN@HW_GANBANTEIN,attack,483,1,300,500,10000,no,target,always,,,,,,,,
 3224,V_B_KATRINN@WL_EARTHSTRAIN,attack,2216,5,300,1000,7000,no,target,always,,,,,,,,
-3224,V_B_KATRINN@WZ_JUPITEL,attack,84,10,200,1000,10000,no,target,always,,,,,,,,
+3224,V_B_KATRINN@WZ_JUPITEL,attack,84,28,200,1000,10000,no,target,always,,,,,,,,
 3224,V_B_KATRINN@WL_TETRAVORTEX,attack,2217,5,300,1000,7000,no,target,always,,,,,,,,
 3224,V_B_KATRINN@NPC_WIDEFREEZE,attack,664,5,200,1000,10000,no,self,always,,,,,,,,
 3224,V_B_KATRINN@NPC_WIDESILENCE,attack,663,5,200,1000,10000,no,self,always,,,,,,,,
@@ -11675,7 +11656,7 @@
 3225,V_B_SEYREN@NPC_MAXPAIN,attack,716,5,1000,0,10000,yes,self,skillused,490,,,,,,8,
 3225,V_B_SEYREN@NPC_CALLSLAVE,attack,352,1,1000,0,10000,yes,self,always,,,,,,,,
 3225,V_B_SEYREN@NPC_SUMMONSLAVE,attack,196,1,1000,700,10000,no,self,slavele,3,3214,3218,3215,3216,3217,,
-3225,V_B_SEYREN@KN_TWOHANDQUICKEN,attack,60,10,1000,0,300000,yes,self,always,,,,,,,2,
+3225,V_B_SEYREN@KN_TWOHANDQUICKEN,attack,60,30,1000,0,300000,yes,self,always,,,,,,,2,
 3225,V_B_SEYREN@LK_SPIRALPIERCE,attack,397,5,200,0,10000,yes,target,always,,,,,,,,
 3225,V_B_SEYREN@NPC_DRAGONBREATH,attack,731,10,300,500,10000,no,target,always,,,,,,,,
 3225,V_B_SEYREN@NPC_DRAGONBREATH,attack,731,5,300,500,10000,no,target,always,,,,,,,,
@@ -11724,7 +11705,7 @@
 3228,V_CELIA@NPC_WIDEWEB,chase,721,1,500,1000,10000,no,self,always,,,,,,,,
 3228,V_CELIA@NPC_PSYCHIC_WAVE,chase,736,1,500,0,10000,no,target,always,,,,,,,,
 3228,V_CELIA@SA_DISPELL,chase,289,5,50,0,10000,yes,target,always,,,,,,,,
-3228,V_CELIA@MG_THUNDERSTORM,chase,21,10,300,500,10000,no,target,always,,,,,,,,
+3228,V_CELIA@MG_THUNDERSTORM,chase,21,20,300,500,10000,no,target,always,,,,,,,,
 3228,V_CELIA@NPC_WIDESOULDRAIN,chase,680,4,300,0,10000,no,self,always,,,,,,,,
 3228,V_CELIA@NPC_MENTALBREAKER,attack,159,3,50,800,10000,no,target,always,,,,,,,,
 3228,V_CELIA@SA_DISPELL,attack,289,5,300,0,10000,yes,target,always,,,,,,,,
@@ -11737,7 +11718,7 @@
 3229,V_CHEN@AL_TELEPORT,idle,26,1,1000,0,0,yes,self,rudeattacked,,,,,,,,
 3229,V_CHEN@AL_TELEPORT,walk,26,1,500,0,10000,yes,self,rudeattacked,,,,,,,,
 3229,V_CHEN@MO_BODYRELOCATION,chase,264,1,200,500,5000,no,target,always,,,,,,,28,
-3229,V_CHEN@AL_DECAGI,chase,30,10,200,0,10000,yes,target,always,,,,,,,,
+3229,V_CHEN@AL_DECAGI,chase,30,48,200,0,10000,yes,target,always,,,,,,,,
 3229,V_CHEN@MO_BALKYOUNG,attack,1016,1,10,0,10000,no,target,always,,,,,,,19,
 3229,V_CHEN@MO_EXTREMITYFIST,attack,271,1,500,1000,6000,no,target,always,,,,,,,,
 3229,V_CHEN@NPC_CRITICALSLASH,attack,170,1,100,0,10000,yes,target,always,,,,,,,,
@@ -12759,7 +12740,7 @@
 3756,Bomi@NPC_SUMMONSLAVE,idle,196,1,10000,200,10000,no,self,slavele,2,3751,,,,,,
 3756,Bomi@NPC_WIDESUCK,idle,722,1,10000,500,30000,no,self,always,0,,,,,,,
 3757,Dracula of Rage@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
-3757,Dracula of Rage@AL_DECAGI,chase,30,10,2000,0,5000,no,target,always,0,,,,,,,
+3757,Dracula of Rage@AL_DECAGI,chase,30,48,2000,0,5000,no,target,always,0,,,,,,,
 3757,Dracula of Rage@AS_GRIMTOOTH,chase,137,5,2000,0,5000,yes,target,always,0,,,,,,,
 3757,Dracula of Rage@NPC_CRITICALWOUND,chase,673,5,2000,500,12000,no,target,myhpltmaxrate,50,,,,,,,
 3757,Dracula of Rage@NPC_HELLJUDGEMENT,attack,662,10,10000,500,20000,no,self,myhpltmaxrate,80,,,,,,36,
@@ -12847,12 +12828,12 @@
 3763,Resentful Soldier@NPC_UNDEADATTACK,attack,347,5,500,500,5000,no,target,always,0,,,,,,,
 3763,Resentful Soldier@AC_CHARGEARROW,attack,148,1,500,0,15000,yes,target,always,0,,,,,,,
 3764,Wizard of Truth@NPC_TALK,idle,682,10,2500,0,60000,yes,self,always,0,,,,,,,55
-3764,Wizard of Truth@WZ_VERMILION,idle,85,10,10000,1000,25000,no,target,always,0,,,,,,,
+3764,Wizard of Truth@WZ_VERMILION,idle,85,21,10000,1000,25000,no,target,always,0,,,,,,,
 3764,Wizard of Truth@AL_TELEPORT,idle,26,1,10000,0,0,yes,self,rudeattacked,,,,,,,,
 3764,Wizard of Truth@AL_TELEPORT,walk,26,1,5000,0,5000,yes,self,rudeattacked,,,,,,,,
-3764,Wizard of Truth@WZ_VERMILION,chase,85,10,10000,500,27000,no,target,always,0,,,,,,,
+3764,Wizard of Truth@WZ_VERMILION,chase,85,21,10000,500,27000,no,target,always,0,,,,,,,
 3764,Wizard of Truth@WZ_STORMGUST,attack,89,9,10000,1000,26000,no,target,always,0,,,,,,,
-3764,Wizard of Truth@WZ_VERMILION,attack,85,10,10000,1000,25000,no,target,always,0,,,,,,,
+3764,Wizard of Truth@WZ_VERMILION,attack,85,21,10000,1000,25000,no,target,always,0,,,,,,,
 3764,Wizard of Truth@MG_FIREWALL,attack,18,9,2000,200,19000,yes,target,always,0,,,,,,,
 3764,Wizard of Truth@WZ_METEOR,attack,83,9,10000,1000,29000,no,target,always,,,,,,,,
 3764,Wizard of Truth@WZ_HEAVENDRIVE,attack,91,5,2000,1000,22000,no,target,always,0,,,,,,,

+ 1 - 2
db/re/skill_db.yml

@@ -7663,7 +7663,6 @@ Body:
     Type: Weapon
     TargetType: Attack
     DamageFlags:
-      IgnoreDefense: true
       IgnoreFlee: true
     Flags:
       TargetTrap: true
@@ -24520,7 +24519,7 @@ Body:
     TargetType: Attack
     Range: 1
     Hit: Single
-    HitCount: 5
+    HitCount: -5
     CopyFlags:
       Skill:
         Reproduce: true

+ 12 - 0
doc/mob_db.txt

@@ -204,6 +204,18 @@ AttackMotion: Attack animation motion. Low value means monster's attack will be
 
 ---------------------------------------
 
+ClientAttackMotion: The time from the start of a normal attack until the damage frame shows on client. At the same time you also get stopped on the client.
+This value is only needed if you use the "synchronize_damage" feature (battle/battle.conf).
+
+If you created a custom sprite, you want to set this value to the timing of the damage frame in your *.act file.
+In Act Editor you can set the damage frame by setting the frame sound to "atk". If you don't define a damage frame, it will default to the second to last
+frame. Also keep in mind that the Act Editor displays slightly inaccurate speed. Every 25ms in Act Editor is 24ms in reality.
+
+Example: Drops has a animation speed of 24ms per frame and the 13th frame (frame #12) is the damage frame. This means the damage shows after 12 frames.
+That's why Drops has a ClientAttackMotion of 24*12 = 288.
+
+---------------------------------------
+
 DamageMotion: Damage animation motion, same as aMotion but used to display the "I am hit" animation. Coincidentally, this same value is used to determine how long it is before the monster/player can move again. Endure is dMotion = 0, obviously.
 
 ---------------------------------------

+ 2 - 2
doc/mob_skill_db_powerskill.txt

@@ -10,8 +10,8 @@
 
 When a monster uses a level 10 skill on Aegis, it will be much stronger than the 
 normal player version. On rAthena we reflect this by giving the monster a skill
-level above the maximum player level.
-The following lists explains the skill specialities and the corresponding level
+level above the maximum player skill level.
+The following list explains the skill specialities and the corresponding level
 which needs to be put for these skills in the mob_skill_db.
 
 Note: The "SkillDatabase::parseNode" template has a linear determination feature

+ 23 - 5
doc/script_commands.txt

@@ -1,4 +1,4 @@
-//===== rAthena Documentation================================
+//===== rAthena Documentation================================
 //= rAthena Script Commands
 //===== By:==================================================
 //= rAthena Dev Team
@@ -135,11 +135,26 @@ and 'doc/mapflags.txt'.
 <map name>{,<x>{,<y>{,<xs>{,<ys>}}}}%TAB%monster%TAB%<monster name>{,<monster level>}%TAB%<mob id>,<amount>{,<delay1>{,<delay2>{,<event>{,<mob size>{,<mob ai>}}}}}
 
 Map name is the name of the map the monsters will spawn on. x,y are the
-coordinates where the mob should spawn. If xs and ys are non-zero, they
-specify the 'radius' of a spawn-rectangle area centered at x,y.
-Putting zeros instead of these coordinates will spawn the monsters randomly.
+coordinates where the mob should spawn. Putting zeros instead of these
+coordinates will spawn the monsters randomly.
+
+If the coordinates are non-zero and xs and ys are above 1, each monster will
+spawn in a radius around x,y. At server start, each monster will get assigned
+its own center cell adding or substracting up to (xs-1),(ys-1) from the given
+x,y coordinates. Each time a monster respawns, it will spawn in a radius around
+its personal center cell by adding or substracting up to (xs-1),(ys-1) again.
+This results in a total possible spawn area over all monsters of the spawn line
+of (xs,ys)*4-3, but with a strong bias towards the center of that area:
+2,2 - 5x5
+3,3 - 9x9
+4,4 - 13x13
+5,5 - 17x17
+etc.
+
 Note this is only the initial spawn zone, as mobs random-walk, they are free
 to move away from their specified spawn region.
+You can disable the picking of a random center cell for each monster in the
+battle config. (See /conf/battle/monster.conf::randomize_center_cell.)
 
 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
@@ -188,6 +203,8 @@ Natural enemies for AI monsters are normal 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).
+A boss monster spawn with fixed coordinates will always spawn at the given 
+coordinates, even if they are blocked (e.g. by Icewall).
 
 ** NPC names
 
@@ -6591,7 +6608,8 @@ Available <type>:
 	PCBLOCK_COMMANDS			Prevent the player from using atcommands/charcommands.
 	PCBLOCK_NPCCLICK			Prevent the player from clicking/touching any NPC/shop/warp.
 	PCBLOCK_EMOTION				Prevent the player from using emotions.
-	PCBLOCK_NPC				Simulate NPC interaction. Useful for NPC with no mes window. Sum of PCBLOCK_MOVE|PCBLOCK_SKILL|PCBLOCK_USEITEM|PCBLOCK_COMMANDS|PCBLOCK_NPCCLICK.
+	PCBLOCK_EQUIP				Prevent the player from replacing equipment.
+	PCBLOCK_NPC				Simulate NPC interaction. Useful for NPC with no mes window. Sum of PCBLOCK_MOVE|PCBLOCK_SKILL|PCBLOCK_USEITEM|PCBLOCK_COMMANDS|PCBLOCK_NPCCLICK|PCBLOCK_EQUIP.
 	PCBLOCK_ALL				Sum of all the flags.
 
 Examples:

+ 1 - 0
doc/yaml/db/mob_db.yml

@@ -39,6 +39,7 @@
 #   WalkSpeed               Walk speed. (Default: DEFAULT_WALK_SPEED)
 #   AttackDelay             Attack speed. (Default: 0)
 #   AttackMotion            Attack animation speed. (Default: 0)
+#   ClientAttackMotion      Client attack speed. (Default: AttackMotion)
 #   DamageMotion            Damage animation speed. (Default: 0)
 #   DamageTaken             Rate at which the monster will receive incoming damage. (Default: 100)
 #   Ai                      Aegis monster type AI behavior. (Default: 06)

+ 3 - 0
doc/yaml/sql/mob_db.sql

@@ -60,6 +60,9 @@ CREATE TABLE `mob_db` (
   `racegroup_ep172alpha` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172beta` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172bath` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_turtle` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_rachel_sanctuary` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_luanda` tinyint(1) unsigned DEFAULT NULL,
   `element` varchar(24) DEFAULT NULL,
   `element_level` tinyint(4) unsigned DEFAULT NULL,
   `walk_speed` smallint(6) unsigned DEFAULT NULL,

+ 3 - 0
doc/yaml/sql/mob_db2.sql

@@ -60,6 +60,9 @@ CREATE TABLE `mob_db2` (
   `racegroup_ep172alpha` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172beta` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172bath` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_turtle` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_rachel_sanctuary` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_luanda` tinyint(1) unsigned DEFAULT NULL,
   `element` varchar(24) DEFAULT NULL,
   `element_level` tinyint(4) unsigned DEFAULT NULL,
   `walk_speed` smallint(6) unsigned DEFAULT NULL,

+ 3 - 0
doc/yaml/sql/mob_db2_re.sql

@@ -62,6 +62,9 @@ CREATE TABLE `mob_db2_re` (
   `racegroup_ep172alpha` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172beta` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172bath` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_turtle` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_rachel_sanctuary` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_luanda` tinyint(1) unsigned DEFAULT NULL,
   `element` varchar(24) DEFAULT NULL,
   `element_level` tinyint(4) unsigned DEFAULT NULL,
   `walk_speed` smallint(6) unsigned DEFAULT NULL,

+ 3 - 0
doc/yaml/sql/mob_db_re.sql

@@ -62,6 +62,9 @@ CREATE TABLE `mob_db_re` (
   `racegroup_ep172alpha` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172beta` tinyint(1) unsigned DEFAULT NULL,
   `racegroup_ep172bath` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_turtle` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_rachel_sanctuary` tinyint(1) unsigned DEFAULT NULL,
+  `racegroup_illusion_luanda` tinyint(1) unsigned DEFAULT NULL,
   `element` varchar(24) DEFAULT NULL,
   `element_level` tinyint(4) unsigned DEFAULT NULL,
   `walk_speed` smallint(6) unsigned DEFAULT NULL,

+ 20 - 0
npc/other/CashShop_Functions.txt

@@ -263,6 +263,26 @@ function	script	F_CashSiegeTele	{
 	return;
 }
 
+// Siege Teleport Scroll 2 (WoE 1.5)
+//============================================================ 
+// - Warp player to selected guild castle.
+// - No arguments.
+function	script	F_CashSiegeTele2	{
+	switch(select("Mardoll (arug_cas01):Cyr (arug_cas02):Horn (arug_cas03):Gefn (arug_cas04):Badanis (arug_cas05):Himinn (schg_cas01):Andlangr (schg_cas02):Vidblainn (schg_cas03):Hljod (schg_cas04):Schatirnil (schg_cas05)")) {
+	case 1: warp "aru_gld",159,272; end;
+	case 2: warp "aru_gld",86,50; end;
+	case 3: warp "aru_gld",63,157; end;
+	case 4: warp "aru_gld",307,354; end;
+	case 5: warp "aru_gld",298,110; end;
+	case 6: warp "sch_gld",300,100; end;
+	case 7: warp "sch_gld",284,249; end;
+	case 8: warp "sch_gld",102,196; end;
+	case 9: warp "sch_gld",140,83; end;
+	case 10: warp "sch_gld",70,320; end;
+	}
+	return;
+}
+
 // Curious Snowball
 //============================================================ 
 // - You can get an effect of Restore, Endure, or Wing of Butterfly.

+ 323 - 318
npc/re/mobs/championmobs.txt

@@ -3,329 +3,334 @@
 //===== By: ==================================================
 //= nanakiwurtz
 //===== Current Version: =====================================
-//= 1.1
+//= 1.2
 //===== Compatible With: =====================================
 //= rAthena Project
 //===== Additional Comments: =================================
 //= 1.0 First version
 //= 1.1 Correct Spawn by Navigation's mob data. [attackjom]
+//= 1.2 Correct respawn times and prontera field spawns [Playtester]
 //============================================================
 
-abbey02,0,0	monster	Swift Zombie Slaughter	2603,3,300000
-gl_prison,0,0	monster	Solid Zombie Prisoner	2604,1,300000
-gld_dun04,0,0	monster	Zombie Master Ringleader	2605,2,300000
-pay_dun00,0,0	monster	Furious Zombie	2606,2,300000
-schg_dun01,0,0	monster	Elusive Zakudam	2607,2,300000
-prt_fild03,0,0	monster	Swift Yoyo	2608,2,300000
-ayo_fild02,0,0	monster	Solid Yoyo	2609,1,300000
-pay_fild06,0,0	monster	Wormtail Ringleader	2610,3,300000
-um_fild02,0,0	monster	Furious Wootan Fighter	2611,1,300000
-mosk_dun01,0,0	monster	Elusive Wood Goblin	2612,2,300000
-moc_fild03,0,0	monster	Swift Wolf	2613,2,300000
-gl_step,0,0	monster	Solid Wind Ghost	2614,2,300000
-gef_dun03,0,0	monster	Solid Wind Ghost	2614,1,300000
-pay_fild01,0,0	monster	Willow Ringleader	2615,2,300000
-um_fild04,0,0	monster	Furious Wild Rose	2616,1,300000
-gon_dun03,0,0	monster	Elusive Evil Nymph	2617,2,300000
-gl_sew01,0,0	monster	Solid Whisper	2618,1,300000
-treasure_n2,0,0	monster	Weak Skeleton Ringleader	2619,2,300000
-gl_cas02,0,0	monster	Furious Wanderer	2620,2,300000
-gefenia04,0,0	monster	Elusive Violy	2621,2,300000
-gefenia03,0,0	monster	Swift Violy	2622,2,300000
-gefenia02,0,0	monster	Solid Violy	2623,2,300000
-ein_fild04,0,0	monster	Venomous Ringleader	2624,2,300000
-juperos_01,0,0	monster	Furious Venatu	2625,3,300000
-mosk_dun03,0,0	monster	Elusive Vavayaga	2626,2,300000
-ra_san01,0,0	monster	Swift Vanberk	2627,2,300000
-iz_dun01,0,0	monster	Solid Vadon	2628,2,300000
-ein_fild02,0,0	monster	Ungoliant Ringleader	2629,2,300000
-bra_fild01,0,0	monster	Furious Toucan	2630,3,300000
-ma_fild01,0,0	monster	Elusive Tiyanak	2631,2,300000
-prt_sewb4,0,0	monster	Solid Thief Bug	2632,2,300000
-prt_sewb3,0,0	monster	Thief Bug Ringleader	2633,3,300000
-prt_sewb2,0,0	monster	Furious Thief Bug	2634,2,300000
-beach_dun3,0,0	monster	Elusive Thara Frog	2635,2,300000
-ein_fild03,0,0	monster	Swift Teddy Bear	2636,2,300000
-man_fild03,0,0	monster	Solid Tatacho	2637,1,300000
-mjo_dun01,0,0	monster	Tarou Ringleader	2638,2,300000
-ayo_dun02,0,0	monster	Furious Tamruan	2639,2,300000
-gl_sew03,0,0	monster	Elusive Sting	2640,2,300000
-lhz_fild02,0,0	monster	Swift Stem Worm	2641,2,300000
-moc_fild13,0,0	monster	Solid Steel Chonchon	2642,3,300000
-ve_fild07,0,0	monster	Stapo Ringleader	2643,2,300000
-beach_dun2,0,0	monster	Furious Stalactic Golem	2644,2,300000
-prt_fild02,0,0	monster	Elusive Stainer	2645,3,300000
-treasure_n1,0,0	monster	Swift Spore	2646,2,300000
-tur_dun02,0,0	monster	Solid Solider	2647,2,300000
-pay_dun02,0,0	monster	Soldier Skeleton Ringleader	2648,3,300000
-pay_dun01,0,0	monster	Furious Soldier Skeleton	2649,2,300000
-tha_t09,0,0	monster	Elusive Lady Solace	2650,2,300000	//--Remove after Thanatos Ravamped Patch
-pay_dun03,0,0	monster	Swift Sohee	2651,2,300000
-ice_dun02,0,0	monster	Solid Snowier	2652,2,300000
-pay_fild02,0,0	monster	Boa Ringleader	2653,3,300000
-ayo_fild01,0,0	monster	Furious Smokie	2654,2,300000
-yuno_fild06,0,0	monster	Elusive Sleeper	2655,1,300000
-yuno_fild02,0,0	monster	Swift Sleeper	2656,2,300000
-odin_tem02,0,0	monster	Solid Skogul	2657,1,300000
-gld2_pay,0,0	monster	Skeleton General Ringleader	2658,2,300000
-gld_dun01_2,0,0	monster	Furious Skeleton General	2659,2,300000
-mjo_dun03,0,0	monster	Elusive Skeleton Worker	2660,2,300000
-ice_dun01,0,0	monster	Swift Siroma	2661,1,300000
-mosk_fild02,0,0	monster	Solid Side Winder	2662,1,300000
-mjolnir_03,0,0	monster	Side Winder Ringleader	2663,2,300000
-ama_dun03,0,0	monster	Furious Shinobi	2664,2,300000
-tha_t11,0,0	monster	Elusive Mistress of Shelter	2665,2,300000	//--Remove after Thanatos Ravamped Patch
-hu_fild06,0,0	monster	Swift Shellfish	2666,1,300000
-lhz_dun03,0,0	monster	Solid Cecil Damon	2667,3,300000
-cmd_fild04,0,0	monster	Sea Otter Ringleader	2668,2,300000
-iz_dun05,0,0	monster	Furious Lamp Rey	2669,2,300000
-moc_fild18,0,0	monster	Elusive Scorpion	2670,3,300000
-mjolnir_09,0,0	monster	Swift Savage Babe	2671,2,300000
-prt_maze01,0,0	monster	Solid Savage	2672,2,300000
-mjolnir_07,0,0	monster	Savage Ringleader	2673,3,300000
-moc_fild16,0,0	monster	Furious Sandman	2674,2,300000
-thor_v03,0,0	monster	Elusive Salamander	2675,2,300000
-treasure02,0,0	monster	Swift Sailor Skeleton	2676,1,300000
-ra_fild12,0,0	monster	Solid Roween	2677,2,300000
-prt_fild00,0,0	monster	Roda Frog Ringleader	2678,2,300000
-gef_fild01,0,0	monster	Furious Roda Frog	2679,2,300000
-prt_fild07,0,0	monster	Elusive Rocker	2680,2,300000
-tha_t01,0,0	monster	Swift Rideword	2681,2,300000
-//tha_t01,0,0	monster	Swift Rideword	2681,1,300000	//--Applied after Thanatos Revamped Patch.
-c_tower1,0,0	monster	Solid Rideword	2682,2,300000
-gon_fild01,0,0	monster	Dumpling Child Ringleader	2683,2,300000
-tha_t10,0,0	monster	Furious Baroness of Retribution	2684,2,300000	//--Remove after Thanatos Ravamped Patch
-tha_t08,0,0	monster	Elusive Baroness of Retribution	2685,2,300000
-//tha_t08,0,0	monster	Elusive Baroness of Retribution	2685,1,300000	//--Applied after Thanatos Revamped Patch.
-tha_t07,0,0	monster	Swift Baroness of Retribution	2686,2,300000
-//tha_t07,0,0	monster	Swift Baroness of Retribution	2686,1,300000	//--Applied after Thanatos Revamped Patch.
-in_sphinx2,0,0	monster	Solid Requiem	2687,2,300000
-lhz_dun01,0,0	monster	Remover Ringleader	2688,3,300000
-mal_dun01,0,0	monster	Elusive Red Eruma	2689,2,300000
-gl_knt02,0,0	monster	Swift Raydric	2690,2,300000
-gl_knt01,0,0	monster	Solid Raydric	2691,2,300000
-lhz_dun02,0,0	monster	Laurell Weinder Ringleader	2692,3,300000
-dic_dun03,0,0	monster	Furious Rake Scaraba	2693,2,300000
-cmd_fild07,0,0	monster	Elusive Raggler	2694,2,300000
-lhz_fild01,0,0	monster	Swift Rafflesia	2695,3,300000
-lhz_fild01,0,0	monster	Poring Ringleader	2696,2,300000
-lhz_fild01,0,0	monster	Furious Poring	2697,2,300000
-lhz_fild01,0,0	monster	Elusive Poring	2698,2,300000
-gef_fild07,0,0	monster	Swift Poring	2699,2,300000
-ein_fild09,0,0	monster	Solid Porcellio	2700,2,300000
-prt_maze03,0,0	monster	Poporing Ringleader	2701,2,300000
-prt_maze02,0,0	monster	Furious Poporing	2702,2,300000
-pay_fild04,0,0	monster	Elusive Poporing	2703,2,300000
-ama_dun02,0,0	monster	Swift Poison Toad	2704,1,300000
-mjolnir_06,0,0	monster	Solid Poison Spore	2705,3,300000
-odin_tem03,0,0	monster	Plasma Ringleader	2706,2,300000
-iz_dun00,0,0	monster	Furious Plankton	2707,2,300000
-ein_dun01,0,0	monster	Elusive Pitman	2708,2,300000
-bra_dun01,0,0	monster	Swift Piranha	2709,2,300000
-spl_fild01,0,0	monster	Solid Dark Pinguicula	2710,2,300000
-spl_fild02,0,0	monster	Pinguicula Ringleader	2711,2,300000
-moc_fild12,0,0	monster	Furious Picky	2712,2,300000
-iz_dun03,0,0	monster	Elusive Phen	2713,2,300000
-gef_fild08,0,0	monster	Swift Petite	2714,2,300000
-gef_fild06,0,0	monster	Solid Petite	2715,2,300000
-treasure02,0,0	monster	Penomena Ringleader	2716,2,300000
-alde_dun03,0,0	monster	Furious Penomena	2717,2,300000
-moc_fild02,0,0	monster	Elusive Peco Peco	2718,2,300000
-in_sphinx5,0,0	monster	Swift Pasana	2719,2,300000
-um_fild03,0,0	monster	Solid Parasite	2720,1,300000
-tha_t05,0,0	monster	Owl Duke Ringleader	2721,2,300000
-//tha_t05,0,0	monster	Owl Duke Ringleader	2721,3,300000	//--Applied after Thanatos Revamped Patch.
-gef_fild10,0,0	monster	Furious Orc Warrior	2722,2,300000
-orcsdun01,0,0	monster	Elusive Orc Zombie	2723,2,300000
-orcsdun02,0,0	monster	Swift Orc Skeleton	2724,2,300000
-gef_fild03,0,0	monster	Solid Orc Lady	2725,3,300000
-tha_t12,0,0	monster	Dame of Sentinel Ringleader	2726,2,300000	//--Remove after Thanatos Ravamped Patch
-ein_fild05,0,0	monster	Furious Noxious	2727,2,300000
-hu_fild05,0,0	monster	Elusive Novus	2728,2,300000
-hu_fild04,0,0	monster	Swift Novus	2729,2,300000
-hu_fild02,0,0	monster	Solid Novus	2730,2,300000
-hu_fild01,0,0	monster	Novus Ringleader	2731,2,300000
-mag_dun02,0,0	monster	Furious Nightmare Terror	2732,2,300000
-gl_chyard_,0,0	monster	Elusive Wraith Dead (Nightmare)	2733,2,180000,0
+abbey01,0,0	monster	Swift Banshee	2887,3,180000
+abbey02,0,0	monster	Swift Zombie Slaughter	2603,3,180000
+abbey03,0,0	monster	Necromancer Ringleader	2736,2,180000
+abyss_01,0,0	monster	Furious Ferus	2832,2,180000
+abyss_02,0,0	monster	Acidus Ringleader	2913,2,180000
+abyss_03,0,0	monster	Solid Acidus	2912,2,180000
+alde_dun01,0,0	monster	Arclouze Ringleader	2894,1,180000
+alde_dun02,0,0	monster	Solid High Orc	2805,2,180000
+alde_dun03,0,0	monster	Furious Penomena	2717,2,180000
+alde_dun04,0,0	monster	Furious Bathory	2885,1,180000
+ama_dun01,0,0	monster	Miyabi Doll Ringleader	2746,2,180000
+ama_dun02,0,0	monster	Swift Poison Toad	2704,1,180000
+ama_dun03,0,0	monster	Furious Shinobi	2664,2,180000
+ama_fild01,0,0	monster	Swift Karakasa	2789,2,180000
+anthell01,0,0	monster	Elusive Deniro	2857,3,180000
+anthell02,0,0	monster	Solid Andre	2902,2,180000
+arug_dun01,0,0	monster	Elusive Banshee Master	2886,2,180000
+ayo_dun01,0,0	monster	Leaf Cat Ringleader	2781,2,180000
+ayo_dun02,0,0	monster	Furious Tamruan	2639,2,180000
+ayo_fild01,0,0	monster	Furious Smokie	2654,2,180000
+ayo_fild02,0,0	monster	Solid Yoyo	2609,1,180000
+beach_dun,0,0	monster	Swift Medusa	2759,2,180000
+beach_dun2,0,0	monster	Furious Stalactic Golem	2644,2,180000
+beach_dun3,0,0	monster	Elusive Thara Frog	2635,2,180000
+bif_fild01,0,0	monster	Miming Ringleader	2751,2,180000
+bif_fild02,0,0	monster	Furious Little Fatum	2777,2,180000
+bra_dun01,0,0	monster	Swift Piranha	2709,2,180000
+bra_dun02,0,0	monster	Solid Iara	2795,3,180000
+bra_fild01,0,0	monster	Furious Toucan	2630,3,180000
+c_tower1,0,0	monster	Solid Rideword	2682,2,180000
+c_tower2,0,0	monster	Furious Clock	2871,1,180000
+c_tower3,0,0	monster	Elusive Alarm	2910,1,180000
+c_tower4,0,0	monster	Clock Ringleader	2870,2,180000
+cmd_fild01,0,0	monster	Elusive Grove	2808,2,180000
+cmd_fild02,0,0	monster	Swift Seal	2829,3,180000
+cmd_fild03,0,0	monster	Solid Alligator	2907,3,180000
+cmd_fild04,0,0	monster	Sea Otter Ringleader	2668,2,180000
+cmd_fild06,0,0	monster	Furious Golem	2812,2,180000
+cmd_fild07,0,0	monster	Elusive Raggler	2694,2,180000
+cmd_fild08,0,0	monster	Elusive Deniro	2857,2,180000
+cmd_fild09,0,0	monster	Swift Metaller	2754,2,180000
+dew_dun01,0,0	monster	Elusive Comodo	2867,2,180000
+dew_dun02,0,0	monster	Solid Banaspaty	2888,2,180000
+dew_fild01,0,0	monster	Swift Rafflesia Arnoldi	2906,2,180000
+dic_dun01,0,0	monster	Swift Uni-horn Scaraba	2799,2,180000
+dic_dun02,0,0	monster	Elusive Antler Scaraba	2896,2,180000
+dic_dun03,0,0	monster	Furious Rake Scaraba	2693,2,180000
+dic_fild01,0,0	monster	Swift Centipede	2873,2,180000
+dic_fild02,0,0	monster	Dolomedes Ringleader	2850,2,180000
+ecl_fild01,0,0	monster	Elusive Menblatt	2758,1,180000
+ecl_tdun01,0,0	monster	Solid Cenere	2874,1,180000
+ecl_tdun02,0,0	monster	Solid Antique Book	2898,1,180000
+ecl_tdun03,0,0	monster	Swift Antique Book	2897,1,180000
+ein_dun01,0,0	monster	Elusive Pitman	2708,2,180000
+ein_dun02,0,0	monster	Solid Mineral	2750,2,180000
+ein_fild02,0,0	monster	Ungoliant Ringleader	2629,2,180000
+ein_fild03,0,0	monster	Swift Teddy Bear	2636,2,180000
+ein_fild04,0,0	monster	Venomous Ringleader	2624,2,180000
+ein_fild05,0,0	monster	Furious Noxious	2727,2,180000
+ein_fild06,0,0	monster	Solid Holden	2745,2,180000
+ein_fild07,0,0	monster	Metaling Ringleader	2756,2,180000
+ein_fild08,0,0	monster	Solid Metaling	2755,2,180000
+ein_fild09,0,0	monster	Solid Porcellio	2700,2,180000
+gef_dun00,0,0	monster	Furious Hunter Fly	2797,1,180000
+gef_dun01,0,0	monster	Elusive Ghoul	2823,2,180000
+gef_dun02,0,0	monster	Solid Deviruchi	2854,2,180000
+gef_dun03,0,0	monster	Solid Wind Ghost	2614,1,180000
+gef_fild00,0,0	monster	Elusive Chonchon	2872,2,180000
+gef_fild01,0,0	monster	Furious Roda Frog	2679,2,180000
+gef_fild02,0,0	monster	Solid Coco	2869,3,180000
+gef_fild03,0,0	monster	Solid Orc Lady	2725,3,180000
+gef_fild04,0,0	monster	Solid Mandragora	2765,2,180000
+gef_fild05,0,0	monster	Swift Creamy	2863,2,180000
+gef_fild06,0,0	monster	Solid Petite	2715,2,180000
+gef_fild07,0,0	monster	Swift Poring	2699,2,180000
+gef_fild08,0,0	monster	Swift Petite	2714,2,180000
+gef_fild09,0,0	monster	Swift Coco	2868,2,180000
+gef_fild10,0,0	monster	Furious Orc Warrior	2722,2,180000
+gef_fild11,0,0	monster	Swift Goblin	2814,3,180000
+gefenia01,0,0	monster	Swift False Angel	2834,2,180000
+gefenia02,0,0	monster	Solid Violy	2623,2,180000
+gefenia03,0,0	monster	Swift Violy	2622,2,180000
+gefenia04,0,0	monster	Elusive Violy	2621,2,180000
+gl_cas01,0,0	monster	Elusive Carat	2877,2,180000
 gl_cas02_,0,0	monster	Furious Wanderer (Nightmare)	2734,2,180000,0
-man_fild01,0,0	monster	Solid Nephentes	2735,2,300000
-abbey03,0,0	monster	Necromancer Ringleader	2736,2,300000
-xmas_dun02,0,0	monster	Furious Myst Case	2737,2,300000
-ve_fild04,0,0	monster	Elusive Muscipular	2738,2,300000
-moc_pryd03,0,0	monster	Swift Mummy	2739,2,300000
-moc_pryd02,0,0	monster	Solid Mummy	2740,2,300000
-moc_fild01,0,0	monster	Muka Ringleader	2741,3,300000
-moc_fild22,0,0	monster	Furious Incarnation of Morocc	2742,3,300000
-moc_fild21,0,0	monster	Elusive Incarnation of Morocc	2743,2,300000
-moc_fild20,0,0	monster	Swift Incarnation of Morocc	2744,1,300000
-ein_fild06,0,0	monster	Solid Holden	2745,2,300000
-ama_dun01,0,0	monster	Miyabi Doll Ringleader	2746,2,300000
-moc_prydn1,0,0	monster	Furious Minorous	2747,2,300000
-moc_pryd05,0,0	monster	Elusive Minorous	2748,2,300000
-in_sphinx4,0,0	monster	Swift Minorous	2749,1,300000
-ein_dun02,0,0	monster	Solid Mineral	2750,2,300000
-bif_fild01,0,0	monster	Miming Ringleader	2751,2,300000
-moc_prydn2,0,0	monster	Furious Mimic	2752,2,300000
-moc_pryd06,0,0	monster	Elusive Mimic	2753,2,300000
-cmd_fild09,0,0	monster	Swift Metaller	2754,2,300000
-ein_fild08,0,0	monster	Solid Metaling	2755,2,300000
-ein_fild07,0,0	monster	Metaling Ringleader	2756,2,300000
-iz_dun04,0,0	monster	Furious Merman	2757,2,300000
-ecl_fild01,0,0	monster	Elusive Menblatt	2758,1,300000
-beach_dun,0,0	monster	Swift Medusa	2759,2,300000
-mjo_dun02,0,0	monster	Solid Martin	2760,2,300000
-gl_in01,0,0	monster	Marionette Ringleader	2761,1,300000
-xmas_fild01,0,0	monster	Furious Marin	2762,1,300000
-in_sphinx3,0,0	monster	Elusive Marduk	2763,1,300000
-prt_maze03,0,0	monster	Swift Mantis	2764,2,300000
-gef_fild04,0,0	monster	Solid Mandragora	2765,2,300000
-ma_dun01,0,0	monster	Manananggal Ringleader	2766,2,300000
-gl_dun02,0,0	monster	Furious Majoruros	2767,1,300000
-prt_fild09,0,0	monster	Elusive Magnolia	2768,2,300000
-ve_fild03,0,0	monster	Swift Magmaring	2769,2,300000
-prt_fild08,0,0	monster	Solid Lunatic	2770,1,300000
-prt_fild01,0,0	monster	Lunatic Ringleader	2771,2,300000
-niflheim,0,0	monster	Furious Lude	2772,1,300000
-spl_fild03,0,0	monster	Elusive Luciola Vespa	2773,1,300000
-nif_fild02,0,0	monster	Swift Loli Ruri	2774,1,300000
-gon_dun02,0,0	monster	Solid Enchanted Peach Tree	2775,1,300000
-new_1-3,0,0	monster	Baby Poring Ringleader	2776,2,300000
-bif_fild02,0,0	monster	Furious Little Fatum	2777,2,300000
-lou_dun01,0,0	monster	Elusive Jing Guai	2778,2,300000
-mosk_dun02,0,0	monster	Swift Les	2779,1,300000
-gld_dun01,0,0	monster	Solid Leib Olmai	2780,2,300000
-ayo_dun01,0,0	monster	Leaf Cat Ringleader	2781,2,300000
-teg_dun02,0,0	monster	Furious Wickebine Tres	2782,2,300000,0
-teg_dun01,0,0	monster	Elusive Eremes	2783,2,300000,0
-ra_fild06,0,0	monster	Swift Kobold Archer	2784,3,300000
-ra_fild05,0,0	monster	Solid Kobold	2785,3,300000
-thor_v02,0,0	monster	Knocker Ringleader	2786,1,300000
-mjolnir_08,0,0	monster	Furious Beetle King	2787,2,300000
-thor_v01,0,0	monster	Elusive Kasa	2788,2,300000
-ama_fild01,0,0	monster	Swift Karakasa	2789,2,300000
-moc_pryd04,0,0	monster	Solid Isis	2790,2,300000
-ra_san02,0,0	monster	Isilla Ringleader	2791,2,300000
-gl_prison1,0,0	monster	Furious Injustice	2792,2,300000
-lou_fild01,0,0	monster	Elusive Mi Gao	2793,1,300000
-ice_dun03,0,0	monster	Swift Ice Titan	2794,2,300000
-bra_dun02,0,0	monster	Solid Iara	2795,3,300000
-lou_dun02,0,0	monster	Yao Jun Ringleader	2796,1,300000
-gef_dun00,0,0	monster	Furious Hunter Fly	2797,1,300000
-prt_fild05,0,0	monster	Elusive Hornet	2798,2,300000
-dic_dun01,0,0	monster	Swift Uni-horn Scaraba	2799,2,300000
-pay_fild09,0,0	monster	Solid Horn	2800,2,300000
-ra_san03,0,0	monster	Hodremlin Ringleader	2801,2,300000
-moc_fild17,0,0	monster	Furious Hode	2802,2,300000
-ra_fild04,0,0	monster	Elusive Hill Wind	2803,3,300000
-ra_fild03,0,0	monster	Swift Hill Wind	2804,3,300000
-alde_dun02,0,0	monster	Solid High Orc	2805,2,300000
-yuno_fild04,0,0	monster	Harpy Ringleader	2806,3,300000
-yuno_fild03,0,0	monster	Furious Harpy	2807,3,300000
-cmd_fild01,0,0	monster	Elusive Grove	2808,2,300000
-pay_fild10,0,0	monster	Swift Greatest General	2809,2,300000
-yuno_fild09,0,0	monster	Solid Grand Peco	2810,2,300000
-yuno_fild08,0,0	monster	Grand Peco Ringleader	2811,2,300000
-cmd_fild06,0,0	monster	Furious Golem	2812,2,300000
-prt_fild11,0,0	monster	Elusive Goblin	2813,3,300000
-gef_fild11,0,0	monster	Swift Goblin	2814,3,300000
-yuno_fild11,0,0	monster	Solid Goat	2815,2,300000
-yuno_fild07,0,0	monster	Goat Ringleader	2816,2,300000
-gld2_prt,0,0	monster	Furious Dark Hammer Kobold	2817,2,300000
-gld_dun03_2,0,0	monster	Elusive Dark Hammer Kobold	2818,2,300000
-gld2_gef,0,0	monster	Swift Dark Shadow	2819,2,300000
-gld_dun04_2,0,0	monster	Solid Dark Shadow	2820,2,300000
-gld_dun02,0,0	monster	Giant Hornet Ringleader	2821,2,300000
-nameless_n,0,0	monster	Furious Ghoul	2822,1,300000
-gef_dun01,0,0	monster	Elusive Ghoul	2823,2,300000
-yuno_fild12,0,0	monster	Swift Geographer	2824,1,300000
-yuno_fild01,0,0	monster	Solid Geographer	2825,2,300000
-glast_01,0,0	monster	Gargoyle Ringleader	2826,1,300000
-gl_sew02,0,0	monster	Furious Gargoyle	2827,1,300000
-ve_fild01,0,0	monster	Elusive Galion	2828,1,300000
-cmd_fild02,0,0	monster	Swift Seal	2829,3,300000
-tur_dun05,0,0	monster	Solid Freezer	2830,1,300000
-tur_dun03,0,0	monster	Freezer Ringleader	2831,1,300000
-abyss_01,0,0	monster	Furious Ferus	2832,2,300000
-prt_sewb1,0,0	monster	Elusive Familiar	2833,1,300000
-gefenia01,0,0	monster	Swift False Angel	2834,2,300000
-prt_fild06,0,0	monster	Solid Fabre	2835,2,300000
-pay_fild03,0,0	monster	Fabre Ringleader	2836,3,300000
-mag_dun01,0,0	monster	Furious Explosion	2837,1,300000
-gl_church,0,0	monster	Elusive Evil Druid	2838,2,300000
-prt_fild10,0,0	monster	Swift Elder Willow	2839,3,300000
-mjolnir_02,0,0	monster	Solid Elder Willow	2840,3,300000
-ra_san04,0,0	monster	Echio Ringleader	2841,1,300000
-mjolnir_12,0,0	monster	Furious Dustiness	2842,2,300000
-um_fild01,0,0	monster	Swift Dryad	2843,2,300000
-ve_fild02,0,0	monster	Solid Drosera	2844,2,300000
-moc_fild07,0,0	monster	Drops Ringleader	2845,3,300000
-mjolnir_04,0,0	monster	Furious Driller	2846,3,300000
-in_sphinx1,0,0	monster	Elusive Drainliar	2847,1,300000
-tur_dun01,0,0	monster	Swift Dragon Tail	2848,1,300000
-nyd_dun01,0,0	monster	Solid Draco	2849,2,300000
-dic_fild02,0,0	monster	Dolomedes Ringleader	2850,2,300000
-pay_dun04,0,0	monster	Furious Dokebi	2851,2,300000
-nif_fild01,0,0	monster	Elusive Disguise	2852,2,300000
-jupe_core,0,0	monster	Swift Dimik	2853,3,300000
-gef_dun02,0,0	monster	Solid Deviruchi	2854,2,300000
-ra_fild01,0,0	monster	Baby Desert Wolf Ringleader	2855,2,300000
-moc_fild11,0,0	monster	Furious Baby Desert Wolf	2856,3,300000
-cmd_fild08,0,0	monster	Elusive Deniro	2857,2,300000
-anthell01,0,0	monster	Elusive Deniro	2857,3,300000
-tha_t06,0,0	monster	Swift Death Word	2858,2,300000
-//tha_t06,0,0	monster	Swift Death Word	2858,3,300000	//--Applied after Thanatos Revamped Patch.
-tha_t04,0,0	monster	Solid Death Word	2859,2,300000
-tha_t03,0,0	monster	Death Word Ringleader	2860,2,300000
-gl_chyard,0,0	monster	Furious Dark Priest	2861,2,300000
-lou_dun03,0,0	monster	Elusive Zhu Po Long	2862,1,300000
-gef_fild05,0,0	monster	Swift Creamy	2863,2,300000
-iz_dun02,0,0	monster	Solid Cornutus	2864,2,300000
-xmas_dun01,0,0	monster	Cookie Ringleader	2865,2,300000
-kh_kiehl01,0,0	monster	Furious Constant	2866,2,300000
-dew_dun01,0,0	monster	Elusive Comodo	2867,2,300000
-gef_fild09,0,0	monster	Swift Coco	2868,2,300000
-gef_fild02,0,0	monster	Solid Coco	2869,3,300000
-c_tower4,0,0	monster	Clock Ringleader	2870,2,300000
-c_tower2,0,0	monster	Furious Clock	2871,1,300000
-gef_fild00,0,0	monster	Elusive Chonchon	2872,2,300000
-dic_fild01,0,0	monster	Swift Centipede	2873,2,300000
-ecl_tdun01,0,0	monster	Solid Cenere	2874,1,300000
-lhz_dun04,0,0	monster	Celia Ringleader	2875,3,300000
-gld_dun03,0,0	monster	Furious Caterpillar	2876,2,300000
-gl_cas01,0,0	monster	Elusive Carat	2877,2,300000
-mjolnir_01,0,0	monster	Swift Caramel	2878,2,300000
-ma_fild02,0,0	monster	Solid Bungisngis	2879,2,300000
-odin_tem01,0,0	monster	Breeze Ringleader	2880,1,300000
-lhz_fild03,0,0	monster	Furious Breeze	2881,3,300000
-man_fild02,0,0	monster	Elusive Bradium Golem	2882,2,300000
-gon_dun01,0,0	monster	Swift Bloody Butterfly	2883,2,300000
-pay_fild07,0,0	monster	Bigfoot Ringleader	2884,2,300000
-alde_dun04,0,0	monster	Furious Bathory	2885,1,300000
-arug_dun01,0,0	monster	Elusive Banshee Master	2886,2,300000
-abbey01,0,0	monster	Swift Banshee	2887,3,300000
-dew_dun02,0,0	monster	Solid Banaspaty	2888,2,300000
-tur_dun04,0,0	monster	Assaulter Ringleader	2889,1,300000
-mjolnir_10,0,0	monster	Furious Argos	2890,2,300000
-mjolnir_11,0,0	monster	Elusive Argiope	2891,2,300000
-mjolnir_05,0,0	monster	Swift Argiope	2892,2,300000
-gl_dun01,0,0	monster	Solid Arclouze	2893,1,300000
-alde_dun01,0,0	monster	Arclouze Ringleader	2894,1,300000
-juperos_02,0,0	monster	Furious Apocalypse	2895,3,300000
-dic_dun02,0,0	monster	Elusive Antler Scaraba	2896,2,300000
-ecl_tdun03,0,0	monster	Swift Antique Book	2897,1,300000
-ecl_tdun02,0,0	monster	Solid Antique Book	2898,1,300000
-gl_sew04,0,0	monster	Furious Anolian	2899,2,300000
-gld2_ald,0,0	monster	Elusive Angra Mantis	2900,2,300000
-gld_dun02_2,0,0	monster	Swift Angra Mantis	2901,2,300000
-anthell02,0,0	monster	Solid Andre	2902,2,300000
-tha_t02,0,0	monster	Ancient Mimic Ringleader	2903,2,300000
-ra_fild08,0,0	monster	Furious Anacondaq	2904,2,300000
-prt_fild04,0,0	monster	Elusive Ambernite	2905,2,300000
-dew_fild01,0,0	monster	Swift Rafflesia Arnoldi	2906,2,300000
-cmd_fild03,0,0	monster	Solid Alligator	2907,3,300000
-kh_dun01,0,0	monster	Aliza Ringleader	2908,1,300000
-kh_dun02,0,0	monster	Furious Alicel	2909,1,300000
-c_tower3,0,0	monster	Elusive Alarm	2910,1,300000
-ra_san05,0,0	monster	Swift Agav	2911,2,300000
-abyss_03,0,0	monster	Solid Acidus	2912,2,300000
-abyss_02,0,0	monster	Acidus Ringleader	2913,2,300000
+gl_cas02,0,0	monster	Furious Wanderer	2620,2,180000
+gl_church,0,0	monster	Elusive Evil Druid	2838,2,180000
+gl_chyard_,0,0	monster	Elusive Wraith Dead (Nightmare)	2733,2,180000,0
+gl_chyard,0,0	monster	Furious Dark Priest	2861,2,180000
+gl_dun01,0,0	monster	Solid Arclouze	2893,1,180000
+gl_dun02,0,0	monster	Furious Majoruros	2767,1,180000
+gl_in01,0,0	monster	Marionette Ringleader	2761,1,180000
+gl_knt01,0,0	monster	Solid Raydric	2691,2,180000
+gl_knt02,0,0	monster	Swift Raydric	2690,2,180000
+gl_prison,0,0	monster	Solid Zombie Prisoner	2604,1,180000
+gl_prison1,0,0	monster	Furious Injustice	2792,2,180000
+gl_sew01,0,0	monster	Solid Whisper	2618,1,180000
+gl_sew02,0,0	monster	Furious Gargoyle	2827,1,180000
+gl_sew03,0,0	monster	Elusive Sting	2640,2,180000
+gl_sew04,0,0	monster	Furious Anolian	2899,2,180000
+gl_step,0,0	monster	Solid Wind Ghost	2614,2,180000
+glast_01,0,0	monster	Gargoyle Ringleader	2826,1,180000
+gld_dun01_2,0,0	monster	Furious Skeleton General	2659,2,180000
+gld_dun01,0,0	monster	Solid Leib Olmai	2780,2,180000
+gld_dun02_2,0,0	monster	Swift Angra Mantis	2901,2,180000
+gld_dun02,0,0	monster	Giant Hornet Ringleader	2821,2,180000
+gld_dun03_2,0,0	monster	Elusive Dark Hammer Kobold	2818,2,180000
+gld_dun03,0,0	monster	Furious Caterpillar	2876,2,180000
+gld_dun04_2,0,0	monster	Solid Dark Shadow	2820,2,180000
+gld_dun04,0,0	monster	Zombie Master Ringleader	2605,2,180000
+gld2_ald,0,0	monster	Elusive Angra Mantis	2900,2,180000
+gld2_gef,0,0	monster	Swift Dark Shadow	2819,2,180000
+gld2_pay,0,0	monster	Skeleton General Ringleader	2658,2,180000
+gld2_prt,0,0	monster	Furious Dark Hammer Kobold	2817,2,180000
+gon_dun01,0,0	monster	Swift Bloody Butterfly	2883,2,180000
+gon_dun02,0,0	monster	Solid Enchanted Peach Tree	2775,1,180000
+gon_dun03,0,0	monster	Elusive Evil Nymph	2617,2,180000
+gon_fild01,0,0	monster	Dumpling Child Ringleader	2683,2,180000
+hu_fild01,0,0	monster	Novus Ringleader	2731,2,180000
+hu_fild02,0,0	monster	Solid Novus	2730,2,180000
+hu_fild04,0,0	monster	Swift Novus	2729,2,180000
+hu_fild05,0,0	monster	Elusive Novus	2728,2,180000
+hu_fild06,0,0	monster	Swift Shellfish	2666,1,180000
+ice_dun01,0,0	monster	Swift Siroma	2661,1,180000
+ice_dun02,0,0	monster	Solid Snowier	2652,2,180000
+ice_dun03,0,0	monster	Swift Ice Titan	2794,2,180000
+in_sphinx1,0,0	monster	Elusive Drainliar	2847,1,180000
+in_sphinx2,0,0	monster	Solid Requiem	2687,2,180000
+in_sphinx3,0,0	monster	Elusive Marduk	2763,1,180000
+in_sphinx4,0,0	monster	Swift Minorous	2749,1,180000
+in_sphinx5,0,0	monster	Swift Pasana	2719,2,180000
+iz_dun00,0,0	monster	Furious Plankton	2707,2,180000
+iz_dun01,0,0	monster	Solid Vadon	2628,2,180000
+iz_dun02,0,0	monster	Solid Cornutus	2864,2,180000
+iz_dun03,0,0	monster	Elusive Phen	2713,2,180000
+iz_dun04,0,0	monster	Furious Merman	2757,2,180000
+iz_dun05,0,0	monster	Furious Lamp Rey	2669,2,180000
+jupe_core,0,0	monster	Swift Dimik	2853,3,180000
+juperos_01,0,0	monster	Furious Venatu	2625,3,180000
+juperos_02,0,0	monster	Furious Apocalypse	2895,3,180000
+kh_dun01,0,0	monster	Aliza Ringleader	2908,1,180000
+kh_dun02,0,0	monster	Furious Alicel	2909,1,180000
+kh_kiehl01,0,0	monster	Furious Constant	2866,2,180000
+lhz_dun01,0,0	monster	Remover Ringleader	2688,3,180000
+lhz_dun02,0,0	monster	Laurell Weinder Ringleader	2692,3,180000
+lhz_dun03,0,0	monster	Solid Cecil Damon	2667,3,180000
+lhz_dun04,0,0	monster	Celia Ringleader	2875,3,180000
+lhz_fild01,0,0	monster	Swift Rafflesia	2695,3,180000
+lhz_fild01,0,0	monster	Poring Ringleader	2696,2,180000
+lhz_fild01,0,0	monster	Furious Poring	2697,2,180000
+lhz_fild01,0,0	monster	Elusive Poring	2698,2,180000
+lhz_fild02,0,0	monster	Swift Stem Worm	2641,2,180000
+lhz_fild03,0,0	monster	Furious Breeze	2881,3,180000
+lou_dun01,0,0	monster	Elusive Jing Guai	2778,2,180000
+lou_dun02,0,0	monster	Yao Jun Ringleader	2796,1,180000
+lou_dun03,0,0	monster	Elusive Zhu Po Long	2862,1,180000
+lou_fild01,0,0	monster	Elusive Mi Gao	2793,1,180000
+ma_dun01,0,0	monster	Manananggal Ringleader	2766,2,180000
+ma_fild01,0,0	monster	Elusive Tiyanak	2631,2,180000
+ma_fild02,0,0	monster	Solid Bungisngis	2879,2,180000
+mag_dun01,0,0	monster	Furious Explosion	2837,1,180000
+mag_dun02,0,0	monster	Furious Nightmare Terror	2732,2,180000
+mal_dun01,0,0	monster	Elusive Red Eruma	2689,2,180000
+man_fild01,0,0	monster	Solid Nephentes	2735,2,180000
+man_fild02,0,0	monster	Elusive Bradium Golem	2882,2,180000
+man_fild03,0,0	monster	Solid Tatacho	2637,1,180000
+mjo_dun01,0,0	monster	Tarou Ringleader	2638,2,180000
+mjo_dun02,0,0	monster	Solid Martin	2760,2,180000
+mjo_dun03,0,0	monster	Elusive Skeleton Worker	2660,2,180000
+mjolnir_01,0,0	monster	Swift Caramel	2878,2,180000
+mjolnir_02,0,0	monster	Solid Elder Willow	2840,3,180000
+mjolnir_03,0,0	monster	Side Winder Ringleader	2663,2,180000
+mjolnir_04,0,0	monster	Furious Driller	2846,3,180000
+mjolnir_05,0,0	monster	Swift Argiope	2892,2,180000
+mjolnir_06,0,0	monster	Solid Poison Spore	2705,3,180000
+mjolnir_07,0,0	monster	Savage Ringleader	2673,3,180000
+mjolnir_08,0,0	monster	Furious Beetle King	2787,2,180000
+mjolnir_09,0,0	monster	Swift Savage Babe	2671,2,180000
+mjolnir_10,0,0	monster	Furious Argos	2890,2,180000
+mjolnir_11,0,0	monster	Elusive Argiope	2891,2,180000
+mjolnir_12,0,0	monster	Furious Dustiness	2842,2,180000
+moc_fild01,0,0	monster	Muka Ringleader	2741,3,180000
+moc_fild02,0,0	monster	Elusive Peco Peco	2718,2,180000
+moc_fild03,0,0	monster	Swift Wolf	2613,2,180000
+moc_fild07,0,0	monster	Drops Ringleader	2845,3,180000
+moc_fild11,0,0	monster	Furious Baby Desert Wolf	2856,3,180000
+moc_fild12,0,0	monster	Furious Picky	2712,2,180000
+moc_fild13,0,0	monster	Solid Steel Chonchon	2642,3,180000
+moc_fild16,0,0	monster	Furious Sandman	2674,2,180000
+moc_fild17,0,0	monster	Furious Hode	2802,2,180000
+moc_fild18,0,0	monster	Elusive Scorpion	2670,3,180000
+moc_fild20,0,0	monster	Swift Incarnation of Morocc	2744,1,180000
+moc_fild21,0,0	monster	Elusive Incarnation of Morocc	2743,2,180000
+moc_fild22,0,0	monster	Furious Incarnation of Morocc	2742,3,180000
+moc_pryd02,0,0	monster	Solid Mummy	2740,2,180000
+moc_pryd03,0,0	monster	Swift Mummy	2739,2,180000
+moc_pryd04,0,0	monster	Solid Isis	2790,2,180000
+moc_pryd05,0,0	monster	Elusive Minorous	2748,2,180000
+moc_pryd06,0,0	monster	Elusive Mimic	2753,2,180000
+moc_prydn1,0,0	monster	Furious Minorous	2747,2,180000
+moc_prydn2,0,0	monster	Furious Mimic	2752,2,180000
+mosk_dun01,0,0	monster	Elusive Wood Goblin	2612,2,180000
+mosk_dun02,0,0	monster	Swift Les	2779,1,180000
+mosk_dun03,0,0	monster	Elusive Vavayaga	2626,2,180000
+mosk_fild02,0,0	monster	Solid Side Winder	2662,1,180000
+nameless_n,0,0	monster	Furious Ghoul	2822,1,180000
+new_1-3,0,0	monster	Baby Poring Ringleader	2776,2,180000
+nif_fild01,0,0	monster	Elusive Disguise	2852,2,180000
+nif_fild02,0,0	monster	Swift Loli Ruri	2774,1,180000
+niflheim,0,0	monster	Furious Lude	2772,1,180000
+nyd_dun01,0,0	monster	Solid Draco	2849,2,180000
+odin_tem01,0,0	monster	Breeze Ringleader	2880,1,180000
+odin_tem02,0,0	monster	Solid Skogul	2657,1,180000
+odin_tem03,0,0	monster	Plasma Ringleader	2706,2,180000
+orcsdun01,0,0	monster	Elusive Orc Zombie	2723,2,180000
+orcsdun02,0,0	monster	Swift Orc Skeleton	2724,2,180000
+pay_dun00,0,0	monster	Furious Zombie	2606,2,180000
+pay_dun01,0,0	monster	Furious Soldier Skeleton	2649,2,180000
+pay_dun02,0,0	monster	Soldier Skeleton Ringleader	2648,3,180000
+pay_dun03,0,0	monster	Swift Sohee	2651,2,180000
+pay_dun04,0,0	monster	Furious Dokebi	2851,2,180000
+pay_fild01,0,0	monster	Willow Ringleader	2615,2,180000
+pay_fild02,0,0	monster	Boa Ringleader	2653,3,180000
+pay_fild03,0,0	monster	Fabre Ringleader	2836,3,180000
+pay_fild04,0,0	monster	Elusive Poporing	2703,2,180000
+pay_fild06,0,0	monster	Wormtail Ringleader	2610,3,180000
+pay_fild07,0,0	monster	Bigfoot Ringleader	2884,2,180000
+pay_fild09,0,0	monster	Solid Horn	2800,2,180000
+pay_fild10,0,0	monster	Swift Greatest General	2809,2,180000
+prt_fild00,0,0	monster	Roda Frog Ringleader	2678,2,180000
+prt_fild01,0,0	monster	Lunatic Ringleader	2771,2,180000
+prt_fild02,0,0	monster	Elusive Stainer	2645,3,180000
+prt_fild03,0,0	monster	Swift Yoyo	2608,2,180000
+prt_fild04,0,0	monster	Elusive Ambernite	2905,2,180000
+prt_fild05,0,0	monster	Elusive Hornet	2798,2,180000
+prt_fild06,0,0	monster	Solid Fabre	2835,2,180000
+prt_fild07,0,0	monster	Elusive Rocker	2680,3,180000
+prt_fild08,0,0	monster	Solid Lunatic	2770,1,180000
+prt_fild08,0,0	monster	Poring Ringleader	2696,1,180000
+prt_fild08,0,0	monster	Furious Poring	2697,1,180000
+prt_fild08,0,0	monster	Elusive Poring	2698,1,180000
+prt_fild08,0,0	monster	Swift Poring	2699,1,180000
+prt_fild09,0,0	monster	Elusive Magnolia	2768,2,180000
+prt_fild10,0,0	monster	Swift Elder Willow	2839,3,180000
+prt_fild11,0,0	monster	Elusive Goblin	2813,3,180000
+prt_maze01,0,0	monster	Solid Savage	2672,2,180000
+prt_maze02,0,0	monster	Furious Poporing	2702,2,180000
+prt_maze03,0,0	monster	Poporing Ringleader	2701,2,180000
+prt_maze03,0,0	monster	Swift Mantis	2764,2,180000
+prt_sewb1,0,0	monster	Elusive Familiar	2833,1,180000
+prt_sewb2,0,0	monster	Furious Thief Bug	2634,2,180000
+prt_sewb3,0,0	monster	Thief Bug Ringleader	2633,3,180000
+prt_sewb4,0,0	monster	Solid Thief Bug	2632,2,180000
+ra_fild01,0,0	monster	Baby Desert Wolf Ringleader	2855,2,180000
+ra_fild03,0,0	monster	Swift Hill Wind	2804,3,180000
+ra_fild04,0,0	monster	Elusive Hill Wind	2803,3,180000
+ra_fild05,0,0	monster	Solid Kobold	2785,3,180000
+ra_fild06,0,0	monster	Swift Kobold Archer	2784,3,180000
+ra_fild08,0,0	monster	Furious Anacondaq	2904,2,180000
+ra_fild12,0,0	monster	Solid Roween	2677,2,180000
+ra_san01,0,0	monster	Swift Vanberk	2627,2,180000
+ra_san02,0,0	monster	Isilla Ringleader	2791,2,180000
+ra_san03,0,0	monster	Hodremlin Ringleader	2801,2,180000
+ra_san04,0,0	monster	Echio Ringleader	2841,1,180000
+ra_san05,0,0	monster	Swift Agav	2911,2,180000
+schg_dun01,0,0	monster	Elusive Zakudam	2607,2,180000
+spl_fild01,0,0	monster	Solid Dark Pinguicula	2710,2,180000
+spl_fild02,0,0	monster	Pinguicula Ringleader	2711,2,180000
+spl_fild03,0,0	monster	Elusive Luciola Vespa	2773,1,180000
+teg_dun01,0,0	monster	Elusive Eremes	2783,2,180000,0
+teg_dun02,0,0	monster	Furious Wickebine Tres	2782,2,180000,0
+tha_t01,0,0	monster	Swift Rideword	2681,2,180000
+//tha_t01,0,0	monster	Swift Rideword	2681,1,180000	//--Applied after Thanatos Revamped Patch.
+tha_t02,0,0	monster	Ancient Mimic Ringleader	2903,2,180000
+tha_t03,0,0	monster	Death Word Ringleader	2860,2,180000
+tha_t04,0,0	monster	Solid Death Word	2859,2,180000
+tha_t05,0,0	monster	Owl Duke Ringleader	2721,2,180000
+//tha_t05,0,0	monster	Owl Duke Ringleader	2721,3,180000	//--Applied after Thanatos Revamped Patch.
+tha_t06,0,0	monster	Swift Death Word	2858,2,180000
+//tha_t06,0,0	monster	Swift Death Word	2858,3,180000	//--Applied after Thanatos Revamped Patch.
+tha_t07,0,0	monster	Swift Baroness of Retribution	2686,2,180000
+//tha_t07,0,0	monster	Swift Baroness of Retribution	2686,1,180000	//--Applied after Thanatos Revamped Patch.
+tha_t08,0,0	monster	Elusive Baroness of Retribution	2685,2,180000
+//tha_t08,0,0	monster	Elusive Baroness of Retribution	2685,1,180000	//--Applied after Thanatos Revamped Patch.
+tha_t09,0,0	monster	Elusive Lady Solace	2650,2,180000	//--Remove after Thanatos Ravamped Patch
+tha_t10,0,0	monster	Furious Baroness of Retribution	2684,2,180000	//--Remove after Thanatos Ravamped Patch
+tha_t11,0,0	monster	Elusive Mistress of Shelter	2665,2,180000	//--Remove after Thanatos Ravamped Patch
+tha_t12,0,0	monster	Dame of Sentinel Ringleader	2726,2,180000	//--Remove after Thanatos Ravamped Patch
+thor_v01,0,0	monster	Elusive Kasa	2788,2,180000
+thor_v02,0,0	monster	Knocker Ringleader	2786,1,180000
+thor_v03,0,0	monster	Elusive Salamander	2675,2,180000
+treasure_n1,0,0	monster	Swift Spore	2646,2,180000
+treasure_n2,0,0	monster	Weak Skeleton Ringleader	2619,2,180000
+treasure02,0,0	monster	Swift Sailor Skeleton	2676,1,180000
+treasure02,0,0	monster	Penomena Ringleader	2716,2,180000
+tur_dun01,0,0	monster	Swift Dragon Tail	2848,1,180000
+tur_dun02,0,0	monster	Solid Solider	2647,2,180000
+tur_dun03,0,0	monster	Freezer Ringleader	2831,1,180000
+tur_dun04,0,0	monster	Assaulter Ringleader	2889,1,180000
+tur_dun05,0,0	monster	Solid Freezer	2830,1,180000
+um_fild01,0,0	monster	Swift Dryad	2843,2,180000
+um_fild02,0,0	monster	Furious Wootan Fighter	2611,1,180000
+um_fild03,0,0	monster	Solid Parasite	2720,1,180000
+um_fild04,0,0	monster	Furious Wild Rose	2616,1,180000
+ve_fild01,0,0	monster	Elusive Galion	2828,1,180000
+ve_fild02,0,0	monster	Solid Drosera	2844,2,180000
+ve_fild03,0,0	monster	Swift Magmaring	2769,2,180000
+ve_fild04,0,0	monster	Elusive Muscipular	2738,2,180000
+ve_fild07,0,0	monster	Stapo Ringleader	2643,2,180000
+xmas_dun01,0,0	monster	Cookie Ringleader	2865,2,180000
+xmas_dun02,0,0	monster	Furious Myst Case	2737,2,180000
+xmas_fild01,0,0	monster	Furious Marin	2762,1,180000
+yuno_fild01,0,0	monster	Solid Geographer	2825,2,180000
+yuno_fild02,0,0	monster	Swift Sleeper	2656,2,180000
+yuno_fild03,0,0	monster	Furious Harpy	2807,3,180000
+yuno_fild04,0,0	monster	Harpy Ringleader	2806,3,180000
+yuno_fild06,0,0	monster	Elusive Sleeper	2655,1,180000
+yuno_fild07,0,0	monster	Goat Ringleader	2816,2,180000
+yuno_fild08,0,0	monster	Grand Peco Ringleader	2811,2,180000
+yuno_fild09,0,0	monster	Solid Grand Peco	2810,2,180000
+yuno_fild11,0,0	monster	Solid Goat	2815,2,180000
+yuno_fild12,0,0	monster	Swift Geographer	2824,1,180000

+ 23 - 31
npc/re/mobs/fields/prontera.txt

@@ -3,7 +3,7 @@
 //===== By: ==================================================
 //= Athena (1.0)
 //===== Current Version: =====================================
-//= 1.7
+//= 1.8
 //===== Additional Comments: =================================
 //= 1.2 fixed some map name typos [Lupus]
 //= 1.3 Official kRO 10.1 spawns [Playtester]
@@ -11,6 +11,7 @@
 //= 1.5 Updated to Renewal spawns.
 //= 1.6 Added Prontera Field 8 duplicates. [Euphy]
 //= 1.7 Correct Spawn by Navigation's mob data. [attackjom]
+//= 1.8 Official 18.1 Field 8 spawns, duplicates removed [Playtester]
 //============================================================
 
 //==================================================
@@ -90,36 +91,27 @@ prt_fild07,225,110,5,5	monster	Black Mushroom	1084,3,360000,180000
 //==================================================
 // prt_fild08 - Prontera Field
 //==================================================
-prt_fild08,0,0	monster	Poring	1002,110,5000
-prt_fild08,0,0	monster	Lunatic	1063,110,5000
-prt_fild08,0,0	monster	Fabre	1007,88,5000
-prt_fild08,0,0	monster	Little Poring	2398,33,50000
-prt_fild08,0,0	monster	Pupa	1008,66,5000
-
-//==================================================
-// prt_fild08 - Duplicates
-//==================================================
-prt_fild08a,0,0	monster	Poring	1002,110,5000
-prt_fild08a,0,0	monster	Lunatic	1063,110,5000
-prt_fild08a,0,0	monster	Fabre	1007,88,5000
-prt_fild08a,0,0	monster	Little Poring	2398,33,50000
-prt_fild08a,0,0	monster	Pupa	1008,66,5000
-prt_fild08b,0,0	monster	Poring	1002,110,5000
-prt_fild08b,0,0	monster	Lunatic	1063,110,5000
-prt_fild08b,0,0	monster	Fabre	1007,88,5000
-prt_fild08b,0,0	monster	Little Poring	2398,33,50000
-prt_fild08b,0,0	monster	Pupa	1008,66,5000
-prt_fild08c,0,0	monster	Poring	1002,110,5000
-prt_fild08c,0,0	monster	Lunatic	1063,110,5000
-prt_fild08c,0,0	monster	Fabre	1007,88,5000
-prt_fild08c,0,0	monster	Little Poring	2398,33,50000
-prt_fild08c,0,0	monster	Pupa	1008,66,5000
-prt_fild08d,0,0	monster	Poring	1002,110,5000
-prt_fild08d,0,0	monster	Lunatic	1063,110,5000
-prt_fild08d,0,0	monster	Fabre	1007,88,5000
-prt_fild08d,0,0	monster	Little Poring	2398,33,50000
-prt_fild08d,0,0	monster	Pupa	1008,66,5000
-
+prt_fild08,0,0	monster	Poring	1002,20,5000
+prt_fild08,0,0	monster	Lunatic	1063,20,5000
+prt_fild08,0,0	monster	Fabre	1007,10,5000
+prt_fild08,305,233,10,10	monster	Poring	1002,2,15000
+prt_fild08,305,233,10,10	monster	Lunatic	1063,2,15000
+prt_fild08,305,233,10,10	monster	Fabre	1007,2,15000
+prt_fild08,271,249,20,20	monster	Poring	1002,5,15000
+prt_fild08,271,249,20,20	monster	Lunatic	1063,5,15000
+prt_fild08,271,249,20,20	monster	Fabre	1007,5,15000
+prt_fild08,94,335,50,50	monster	Poring	1002,20,10000
+prt_fild08,166,334,50,50	monster	Poring	1002,20,10000
+prt_fild08,253,337,50,50	monster	Poring	1002,20,10000
+prt_fild08,228,230,30,30	monster	Lunatic	1063,10,10000
+prt_fild08,246,263,50,50	monster	Lunatic	1063,10,10000
+prt_fild08,190,237,50,50	monster	Lunatic	1063,10,10000
+prt_fild08,100,256,50,50	monster	Lunatic	1063,10,10000
+prt_fild08,70,164,70,70	monster	Fabre	1007,20,10000
+prt_fild08,144,147,70,70	monster	Fabre	1007,20,10000
+prt_fild08,263,79,90,90	monster	Fabre	1007,20,10000
+prt_fild08,336,113,40,40	monster	Pupa	1008,20,10000
+prt_fild08,330,269,40,40	monster	Little Poring	2398,20,10000
 
 //==================================================
 // prt_fild09 - Prontera Field

+ 2 - 0
npc/re/quests/quests_illusion_dungeons.txt

@@ -9563,6 +9563,7 @@ iz_d04_i,127,228,4	script	Jerrymon#jerry3	1_M_01,{
 			.@menu$[0] = "^999999" + getitemname(25899) + " Collection - Pending^000000";
 			break;
 		case 2:
+			.@menu$[0] = "Collect " + getitemname(25899) + "";
 			break;
 		}
 
@@ -9586,6 +9587,7 @@ iz_d04_i,127,228,4	script	Jerrymon#jerry3	1_M_01,{
 			.@menu$[1] = "^999999Deep Sea Creatures Killed - Pending^000000";
 			break;
 		case 2:
+			.@menu$[1] = "Kill Deep Sea Creatures";
 			break;
 		}
 

+ 1 - 1
src/char/char_clif.cpp

@@ -950,7 +950,7 @@ int chclif_parse_select_accessible_map( int fd, struct char_session_data* sd, ui
 
 void chclif_accessible_maps( int fd ){
 #if PACKETVER >= 20100714
-	struct PACKET_HC_NOTIFY_ACCESSIBLE_MAPNAME* p = (struct PACKET_HC_NOTIFY_ACCESSIBLE_MAPNAME*)packet_buffer;
+	PACKET_HC_NOTIFY_ACCESSIBLE_MAPNAME* p = reinterpret_cast<PACKET_HC_NOTIFY_ACCESSIBLE_MAPNAME*>( packet_buffer );
 
 	p->packetType = HEADER_HC_NOTIFY_ACCESSIBLE_MAPNAME;
 	p->packetLength = sizeof( *p );

+ 1 - 1
src/common/strlib.cpp

@@ -1011,7 +1011,7 @@ size_t _StringBuf_Vprintf( const char* file, int line, const char* func, StringB
 		int n = vsnprintf( self->ptr_, size, fmt, apcopy );
 		va_end(apcopy);
 		/* If that worked, return the length. */
-		if( n > -1 && n < size )
+		if( n > -1 && static_cast<size_t>(n) < size )
 		{
 			self->ptr_ += n;
 			return self->ptr_ - self->buf_;

+ 1 - 1
src/login/loginclif.cpp

@@ -111,7 +111,7 @@ static void logclif_auth_ok(struct login_session_data* sd) {
 	login_log(ip, sd->userid, 100, "login ok");
 	ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);
 
-	PACKET_AC_ACCEPT_LOGIN* p = (PACKET_AC_ACCEPT_LOGIN*)packet_buffer;
+	PACKET_AC_ACCEPT_LOGIN* p = reinterpret_cast<PACKET_AC_ACCEPT_LOGIN*>( packet_buffer );
 
 	p->packetType = HEADER_AC_ACCEPT_LOGIN;
 	p->packetLength = sizeof( *p );

+ 49 - 45
src/map/atcommand.cpp

@@ -1606,7 +1606,7 @@ ACMD_FUNC(baselevelup)
 		sd->status.base_level += (unsigned int)level;
 		status_calc_pc(sd, SCO_FORCE);
 		status_percent_heal(&sd->bl, 100, 100);
-		clif_misceffect(&sd->bl, 0);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_BASE_LEVEL_UP );
 		for (uint32 j = sd->status.base_level - level; j <= sd->status.base_level; j++) {
 			achievement_update_objective(sd, AG_GOAL_LEVEL, 1, j);
 			achievement_update_objective(sd, AG_GOAL_STATUS, 2, j, sd->status.class_);
@@ -1641,11 +1641,11 @@ ACMD_FUNC(baselevelup)
 		level*=-1;
 	}
 	sd->status.base_exp = 0;
-	clif_updatestatus(sd, SP_STATUSPOINT);
-	clif_updatestatus(sd, SP_TRAITPOINT);
-	clif_updatestatus(sd, SP_BASELEVEL);
-	clif_updatestatus(sd, SP_BASEEXP);
-	clif_updatestatus(sd, SP_NEXTBASEEXP);
+	clif_updatestatus(*sd, SP_STATUSPOINT);
+	clif_updatestatus(*sd, SP_TRAITPOINT);
+	clif_updatestatus(*sd, SP_BASELEVEL);
+	clif_updatestatus(*sd, SP_BASEEXP);
+	clif_updatestatus(*sd, SP_NEXTBASEEXP);
 	pc_baselevelchanged(sd);
 	if(sd->status.party_id)
 		party_send_levelup(sd);
@@ -1679,7 +1679,7 @@ ACMD_FUNC(joblevelup)
 			level = pc_maxjoblv(sd) - sd->status.job_level;
 		sd->status.job_level += (unsigned int)level;
 		sd->status.skill_point += level;
-		clif_misceffect(&sd->bl, 1);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_JOB_LEVEL_UP );
 		for (uint32 i = sd->status.job_level - level; i <= sd->status.job_level; i++)
 			achievement_update_objective(sd, AG_GOAL_LEVEL, 1, i);
 		clif_displaymessage(fd, msg_txt(sd,24)); // Job level raised.
@@ -1702,10 +1702,10 @@ ACMD_FUNC(joblevelup)
 		level *=-1;
 	}
 	sd->status.job_exp = 0;
-	clif_updatestatus(sd, SP_JOBLEVEL);
-	clif_updatestatus(sd, SP_JOBEXP);
-	clif_updatestatus(sd, SP_NEXTJOBEXP);
-	clif_updatestatus(sd, SP_SKILLPOINT);
+	clif_updatestatus(*sd, SP_JOBLEVEL);
+	clif_updatestatus(*sd, SP_JOBEXP);
+	clif_updatestatus(*sd, SP_NEXTJOBEXP);
+	clif_updatestatus(*sd, SP_SKILLPOINT);
 	status_calc_pc(sd, SCO_FORCE);
 
 	if( level > 0 && battle_config.atcommand_levelup_events )
@@ -2418,11 +2418,11 @@ ACMD_FUNC(refine)
 			sd->inventory.u.items_inventory[i].refine = final_refine;
 			current_position = sd->inventory.u.items_inventory[i].equip;
 			pc_unequipitem(sd, i, 3);
-			clif_refine(fd, 0, i, sd->inventory.u.items_inventory[i].refine);
-			clif_delitem(sd, i, 1, 3);
+			clif_refine( *sd, i, ITEMREFINING_SUCCESS );
+			clif_delitem( *sd, i, 1, 3 );
 			clif_additem(sd, i, 1, 0);
 			pc_equipitem(sd, i, current_position);
-			clif_misceffect(&sd->bl, 3);
+			clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 			if( sd->inventory_data[i]->type == IT_WEAPON ){
 				achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, sd->inventory_data[i]->weapon_level, sd->inventory.u.items_inventory[i].refine);
 			}
@@ -2498,10 +2498,10 @@ ACMD_FUNC(grade)
 			sd->inventory.u.items_inventory[i].enchantgrade = final_grade;
 			current_position = sd->inventory.u.items_inventory[i].equip;
 			pc_unequipitem(sd, i, 3);
-			clif_delitem(sd, i, 1, 3);
+			clif_delitem( *sd, i, 1, 3 );
 			clif_additem(sd, i, 1, 0);
 			pc_equipitem(sd, i, current_position);
-			clif_misceffect(&sd->bl, 3);
+			clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 			count++;
 		}
 	}
@@ -2564,7 +2564,7 @@ ACMD_FUNC(produce)
 		tmp_item.card[2] = GetWord(sd->status.char_id, 0);
 		tmp_item.card[3] = GetWord(sd->status.char_id, 1);
 		clif_produceeffect(sd, 0, item_id);
-		clif_misceffect(&sd->bl, 3);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 
 		if ((flag = pc_additem(sd, &tmp_item, 1, LOG_TYPE_COMMAND)))
 			clif_additem(sd, 0, 0, flag);
@@ -2692,7 +2692,7 @@ ACMD_FUNC(statuspoint)
 
 	if (new_status_point != sd->status.status_point) {
 		sd->status.status_point = new_status_point;
-		clif_updatestatus(sd, SP_STATUSPOINT);
+		clif_updatestatus(*sd, SP_STATUSPOINT);
 		clif_displaymessage(fd, msg_txt(sd,174)); // Number of status points changed.
 	} else {
 		if (point < 0)
@@ -2740,7 +2740,7 @@ ACMD_FUNC(traitpoint)
 
 	if (new_trait_point != sd->status.trait_point) {
 		sd->status.trait_point = new_trait_point;
-		clif_updatestatus(sd, SP_TRAITPOINT);
+		clif_updatestatus(*sd, SP_TRAITPOINT);
 		clif_displaymessage(fd, msg_txt(sd, 174)); // Number of status points changed.
 	}
 	else {
@@ -2790,7 +2790,7 @@ ACMD_FUNC(skillpoint)
 
 	if (new_skill_point != sd->status.skill_point) {
 		sd->status.skill_point = new_skill_point;
-		clif_updatestatus(sd, SP_SKILLPOINT);
+		clif_updatestatus(*sd, SP_SKILLPOINT);
 		clif_displaymessage(fd, msg_txt(sd,175)); // Number of skill points changed.
 	} else {
 		if (point < 0)
@@ -2886,12 +2886,12 @@ ACMD_FUNC(param)
 	if( new_value != status ){
 		if (stat < PARAM_POW) {
 			pc_setstat( sd, SP_STR + stat - PARAM_STR, new_value );
-			clif_updatestatus(sd, SP_STR + stat);
-			clif_updatestatus(sd, SP_USTR + stat);
+			clif_updatestatus(*sd, static_cast<_sp>( SP_STR + stat ) );
+			clif_updatestatus(*sd, static_cast<_sp>( SP_USTR + stat ) );
 		} else {
 			pc_setstat( sd, SP_POW + stat - PARAM_POW, new_value );
-			clif_updatestatus(sd, SP_POW + stat - PARAM_POW);
-			clif_updatestatus(sd, SP_UPOW + stat - PARAM_POW);
+			clif_updatestatus(*sd, static_cast<_sp>( SP_POW + stat - PARAM_POW ) );
+			clif_updatestatus(*sd, static_cast<_sp>( SP_UPOW + stat - PARAM_POW ) );
 		}
 		status_calc_pc(sd, SCO_FORCE);
 		clif_displaymessage(fd, msg_txt(sd,42)); // Stat changed.
@@ -2949,8 +2949,8 @@ ACMD_FUNC(stat_all)
 
 		if (new_value != status[i]) {
 			pc_setstat( sd, SP_STR + i, new_value );
-			clif_updatestatus(sd, SP_STR + i);
-			clif_updatestatus(sd, SP_USTR + i);
+			clif_updatestatus(*sd, static_cast<_sp>( SP_STR + i ) );
+			clif_updatestatus(*sd, static_cast<_sp>( SP_USTR + i ) );
 			count++;
 		}
 	}
@@ -3023,8 +3023,8 @@ ACMD_FUNC(trait_all) {
 
 		if (new_value != status[i]) {
 			pc_setstat( sd, SP_POW + i - PARAM_POW, new_value );
-			clif_updatestatus(sd, SP_POW + i - PARAM_POW);
-			clif_updatestatus(sd, SP_UPOW + i - PARAM_POW);
+			clif_updatestatus(*sd, static_cast<_sp>( SP_POW + i - PARAM_POW ) );
+			clif_updatestatus(*sd, static_cast<_sp>( SP_UPOW + i - PARAM_POW ) );
 			count++;
 		}
 	}
@@ -3659,7 +3659,7 @@ ACMD_FUNC(allskill)
 	nullpo_retr(-1, sd);
 	pc_allskillup(sd); // all skills
 	sd->status.skill_point = 0; // 0 skill points
-	clif_updatestatus(sd, SP_SKILLPOINT); // update
+	clif_updatestatus(*sd, SP_SKILLPOINT); // update
 	clif_displaymessage(fd, msg_txt(sd,76)); // All skills have been added to your skill tree.
 
 	return 0;
@@ -4297,7 +4297,7 @@ ACMD_FUNC(reload) {
 		iter = mapit_getallusers();
 		for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ){
 			pc_close_npc(pl_sd,1);
-			clif_cutin(pl_sd, "", 255);
+			clif_cutin( *pl_sd, "", 255 );
 			pl_sd->state.block_action &= ~(PCBLOCK_ALL ^ PCBLOCK_IMMUNE);
 			bg_queue_leave(pl_sd);
 		}
@@ -4458,7 +4458,7 @@ ACMD_FUNC(mapinfo) {
 		clif_displaymessage(fd, atcmd_output);
 		if (!mapdata->skill_damage.empty()) {
 			clif_displaymessage(fd, msg_txt(sd, 1054)); // > [Map Skill] Name : Player, Monster, Boss Monster, Other | Caster
-			for (auto skilldmg : mapdata->skill_damage) {
+			for (const auto& skilldmg : mapdata->skill_damage) {
 				sprintf(atcmd_output,"     %s : %d%%, %d%%, %d%%, %d%% | %d",
 					skill_get_name(skilldmg.first),
 					skilldmg.second.rate[SKILLDMG_PC],
@@ -4940,7 +4940,7 @@ ACMD_FUNC(repairall)
 	}
 
 	if (count > 0) {
-		clif_misceffect(&sd->bl, 3);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 		clif_equiplist(sd);
 		clif_displaymessage(fd, msg_txt(sd,107)); // All items have been repaired.
 	} else {
@@ -6158,7 +6158,7 @@ ACMD_FUNC(clearcart)
 	}
 
 	clif_clearcart(fd);
-	clif_updatestatus(sd,SP_CARTINFO);
+	clif_updatestatus(*sd,SP_CARTINFO);
 
 	clif_displaymessage(fd, msg_txt(sd,1397)); // Your cart was cleaned.
 	return 0;
@@ -6581,7 +6581,7 @@ ACMD_FUNC(changegm)
 
 	if( !battle_config.guild_leaderchange_woe && is_agit_start() ){
 #if PACKETVER >= 20151001
-		clif_msg(sd, GUILD_MASTER_WOE);
+		clif_msg(sd, MSI_IMPOSSIBLE_CHANGE_GUILD_MASTER_IN_SIEGE_TIME);
 #else
 		clif_displaymessage(fd, msg_txt(sd,1513)); // Currently in WoE hours, unable to delegate Guild leader
 #endif
@@ -6590,7 +6590,7 @@ ACMD_FUNC(changegm)
 
 	if( battle_config.guild_leaderchange_delay && DIFF_TICK(time(nullptr),sd->guild->guild.last_leader_change) < battle_config.guild_leaderchange_delay ){
 #if PACKETVER >= 20151001
-		clif_msg(sd, GUILD_MASTER_DELAY);
+		clif_msg(sd, MSI_IMPOSSIBLE_CHANGE_GUILD_MASTER_NOT_TIME);
 #else
 		clif_displaymessage(fd, msg_txt(sd,1514)); // You have to wait for a while before delegating a new Guild leader
 #endif
@@ -7734,7 +7734,9 @@ ACMD_FUNC(misceffect)
 		return -1;
 	if (sscanf(message, "%11d", &effect) < 1)
 		return -1;
-	clif_misceffect(&sd->bl,effect);
+	if (effect < NOTIFYEFFECT_BASE_LEVEL_UP || effect > NOTIFYEFFECT_TAEKWON_BASE_LEVEL_UP)
+		return -1;
+	clif_misceffect( sd->bl, static_cast<e_notify_effect>(effect) );
 
 	return 0;
 }
@@ -7964,7 +7966,7 @@ ACMD_FUNC(showmobs)
 			continue; // hide mobs waiting for respawn
 
 		++number;
-		clif_viewpoint(sd, 1, 0, md->bl.x, md->bl.y, number, 0xFFFFFF);
+		clif_viewpoint( *sd, 1, 0, md->bl.x, md->bl.y, number, 0xFFFFFF );
 	}
 	mapit_free(it);
 
@@ -8022,7 +8024,9 @@ ACMD_FUNC(homevolution)
 		clif_displaymessage(fd, msg_txt(sd,1255)); // Your homunculus doesn't evolve.
 		return -1;
 	}
-	clif_homskillinfoblock(sd);
+
+	clif_homskillinfoblock( *sd->hd );
+
 	return 0;
 }
 
@@ -8105,7 +8109,7 @@ ACMD_FUNC(homfriendly)
 	friendly = cap_value(friendly, 0, 1000);
 
 	sd->hd->homunculus.intimacy = friendly * 100 ;
-	clif_send_homdata(sd,SP_INTIMATE,friendly);
+	clif_send_homdata( *sd->hd, SP_INTIMATE );
 	return 0;
 }
 
@@ -8132,7 +8136,7 @@ ACMD_FUNC(homhungry)
 	hungry = cap_value(hungry, 0, 100);
 
 	sd->hd->homunculus.hunger = hungry;
-	clif_send_homdata(sd,SP_HUNGRY,hungry);
+	clif_send_homdata( *sd->hd, SP_HUNGRY );
 	return 0;
 }
 
@@ -10610,8 +10614,8 @@ ACMD_FUNC(clonestat) {
 		clonestat_check(luk, PARAM_LUK);
 
 		for (i = PARAM_STR; i < PARAM_POW; i++) {
-			clif_updatestatus(sd, SP_STR + i);
-			clif_updatestatus(sd, SP_USTR + i);
+			clif_updatestatus(*sd, static_cast<_sp>( SP_STR + i ) );
+			clif_updatestatus(*sd, static_cast<_sp>( SP_USTR + i ) );
 		}
 
 		if (sd->class_ & JOBL_FOURTH) {
@@ -10623,8 +10627,8 @@ ACMD_FUNC(clonestat) {
 			clonestat_check(crt, PARAM_CRT);
 
 			for (i = PARAM_POW; i < PARAM_MAX; i++) {
-				clif_updatestatus(sd, SP_POW + i - PARAM_POW);
-				clif_updatestatus(sd, SP_UPOW + i - PARAM_POW);
+				clif_updatestatus(*sd, static_cast<_sp>( SP_POW + i - PARAM_POW ) );
+				clif_updatestatus(*sd, static_cast<_sp>( SP_UPOW + i - PARAM_POW ) );
 			}
 
 		}
@@ -10970,7 +10974,7 @@ ACMD_FUNC(setcard)
 	log_pick_pc( sd, LOG_TYPE_COMMAND, -1, &sd->inventory.u.items_inventory[i] );
 	sd->inventory.u.items_inventory[i].card[slot] = card_id;
 	log_pick_pc( sd, LOG_TYPE_COMMAND, 1, &sd->inventory.u.items_inventory[i] );
-	clif_delitem(sd, i, 1, 0);
+	clif_delitem( *sd, i, 1, 0 );
 	clif_additem(sd, i, 1, 0);
 	pc_equipitem(sd, i, current_position);
 	return 0;

+ 111 - 62
src/map/battle.cpp

@@ -393,7 +393,20 @@ int battle_delay_damage(t_tick tick, int amotion, struct block_list *src, struct
 		damage = 0;
 	}
 
-	if ( !battle_config.delay_battle_damage || amotion <= 1 ) {
+	// The client refuses to display animations slower than 1x speed
+	// So we need to shorten AttackMotion to be in-sync with the client in this case
+	if (battle_config.synchronize_damage && skill_id == 0 && src->type == BL_MOB && amotion > status_get_clientamotion(src))
+		amotion = status_get_clientamotion(src);
+	// Check for delay battle damage config
+	else if (!battle_config.delay_battle_damage)
+		amotion = 1;
+	// Aegis places a damage-delay cap of 1 sec to non player attacks
+	// We only want to apply this cap if damage was not synchronized
+	else if (src->type != BL_PC && amotion > 1000)
+		amotion = 1000;
+
+	// Skip creation of timer
+	if (amotion <= 1) {
 		//Deal damage
 		battle_damage(src, target, damage, ddelay, skill_lv, skill_id, dmg_lv, attack_type, additional_effects, gettick(), isspdamage);
 		return 0;
@@ -411,8 +424,6 @@ int battle_delay_damage(t_tick tick, int amotion, struct block_list *src, struct
 	dat->additional_effects = additional_effects;
 	dat->src_type = src->type;
 	dat->isspdamage = isspdamage;
-	if (src->type != BL_PC && amotion > 1000)
-		amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
 
 	if( src->type == BL_PC )
 		((TBL_PC*)src)->delayed_damage++;
@@ -1426,11 +1437,9 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe
 
 	// ATK_DEF Type
 	if ((sce = sc->getSCE(SC_LIGHTNINGWALK)) && !(flag & BF_MAGIC) && flag&BF_LONG && rnd() % 100 < sce->val1) {
-		const int dx[8] = { 0,-1,-1,-1,0,1,1,1 };
-		const int dy[8] = { 1,1,0,-1,-1,-1,0,1 };
 		uint8 dir = map_calc_dir(target, src->x, src->y);
 
-		if (unit_movepos(target, src->x - dx[dir], src->y - dy[dir], 1, 1)) {
+		if (unit_movepos(target, src->x - dirx[dir], src->y - diry[dir], 1, 1)) {
 			clif_blown(target);
 			unit_setdir(target, dir);
 		}
@@ -5118,6 +5127,9 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			//ATK [{(Skill Level x 150) + 300} x Caster's Base Level / 120]% + ATK [(AGI x 2) + (Caster's Job Level x 4)]%
 			skillratio += -100 + 300 + 150 * skill_lv;
 			RE_LVL_DMOD(120);
+			skillratio += sstatus->agi * 2;
+			// If 4th job, job level of your 3rd job counts
+			skillratio += (sd ? (sd->class_&JOBL_FOURTH ? sd->change_level_4th : sd->status.job_level) * 4 : 0);
 			break;
 		case GC_VENOMPRESSURE:
 			skillratio += 900;
@@ -5270,8 +5282,11 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			RE_LVL_DMOD(100);
 			break;
 		case LG_SHIELDPRESS:
-			skillratio += -100 + 200 * skill_lv + sstatus->str;
+			skillratio += -100 + 200 * skill_lv;
 			if (sd) {
+				// Shield Press only considers base STR without job bonus
+				skillratio += sd->status.str;
+
 				if( sc != nullptr && sc->getSCE( SC_SHIELD_POWER ) ){
 					skillratio += skill_lv * 15 * pc_checkskill( sd, IG_SHIELD_MASTERY );
 				}
@@ -6279,19 +6294,6 @@ static int64 battle_calc_skill_constant_addition(struct Damage* wd, struct block
 				atk = 40 * pc_checkskill(sd, RA_RESEARCHTRAP);
 			break;
 #endif
-		case GC_COUNTERSLASH:
-			atk = sstatus->agi * 2 + (sd ? sd->status.job_level * 4 : 0);
-			break;
-		case LG_SHIELDPRESS:
-			if (sd) {
-				int damagevalue = 0;
-				short index = sd->equip_index[EQI_HAND_L];
-
-				if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR)
-					damagevalue = sstatus->vit * sd->inventory.u.items_inventory[index].refine;
-				atk = damagevalue;
-			}
-			break;
 	}
 	return atk;
 }
@@ -6620,6 +6622,7 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
 		case RK_DRAGONBREATH_WATER:
 		case NC_ARMSCANNON:
 		case GN_CARTCANNON:
+		case MO_EXTREMITYFIST:
 			if (attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R) || attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L))
 				return;
 			if (is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_R) || is_attack_piercing(wd, src, target, skill_id, skill_lv, EQI_HAND_L))
@@ -7348,18 +7351,14 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 #endif
 			battle_calc_skill_base_damage(&wd, src, target, skill_id, skill_lv); // base skill damage
 
-		int64 ratio = 0;
-
 #ifndef RENEWAL
-		ratio = battle_calc_attack_skill_ratio(&wd, src, target, skill_id, skill_lv); // skill level ratios
+		// Skill ratio
+		ATK_RATE(wd.damage, wd.damage2, battle_calc_attack_skill_ratio(&wd, src, target, skill_id, skill_lv));
 
-		ATK_RATE(wd.damage, wd.damage2, ratio);
+		// Additive damage bonus
+		ATK_ADD(wd.damage, wd.damage2, battle_calc_skill_constant_addition(&wd, src, target, skill_id, skill_lv));
 #endif
 
-		int64 bonus_damage = battle_calc_skill_constant_addition(&wd, src, target, skill_id, skill_lv); // other skill bonuses
-
-		ATK_ADD(wd.damage, wd.damage2, bonus_damage);
-
 #ifdef RENEWAL
 		if(skill_id == HW_MAGICCRASHER) { // Add weapon attack for MATK onto Magic Crasher
 			struct status_data *sstatus = status_get_status_data(src);
@@ -7431,11 +7430,6 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 			if( is_attack_left_handed( src, skill_id ) ){
 				wd.damage2 += wd.masteryAtk2;
 			}
-			// Apply bonus damage
-			wd.damage += bonus_damage;
-			if( is_attack_left_handed( src, skill_id ) ){
-				wd.damage2 += bonus_damage;
-			}
 
 			// CritAtkRate modifier
 			if (wd.type == DMG_CRITICAL || wd.type == DMG_MULTI_HIT_CRITICAL) {
@@ -7457,9 +7451,11 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 				ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.long_attack_atk_rate);
 		}
 
-		ratio = battle_calc_attack_skill_ratio(&wd, src, target, skill_id, skill_lv); // skill level ratios
+		// Skill ratio
+		ATK_RATE(wd.damage, wd.damage2, battle_calc_attack_skill_ratio(&wd, src, target, skill_id, skill_lv));
 
-		ATK_RATE(wd.damage, wd.damage2, ratio);
+		// Additive damage bonus
+		ATK_ADD(wd.damage, wd.damage2, battle_calc_skill_constant_addition(&wd, src, target, skill_id, skill_lv));
 
 		// Advance Katar Mastery
 		if (sd) {
@@ -7472,7 +7468,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 		// Res reduces physical damage by a percentage and
 		// is calculated before DEF and other reductions.
 		// This should be the official formula. [Rytech]
-		if ((wd.damage + wd.damage2) && tstatus->res > 0) {
+		if ((wd.damage + wd.damage2) && tstatus->res > 0 && skill_id != MO_EXTREMITYFIST) {
 			short res = tstatus->res;
 			short ignore_res = 0;// Value used as a percentage.
 
@@ -7557,6 +7553,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 			if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
 				ATK_ADD(wd.damage, wd.damage2, 10 * pc_checkskill(sd, TK_RUN));
 			break;
+		case LG_SHIELDPRESS:
+			if (sd) {
+				int damagevalue = 0;
+				short index = sd->equip_index[EQI_HAND_L];
+
+				if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR)
+					damagevalue = sstatus->vit * sd->inventory.u.items_inventory[index].refine;
+				ATK_ADD(wd.damage, wd.damage2, damagevalue);
+			}
+			break;
 		case SR_TIGERCANNON:
 			// (Tiger Cannon skill level x 240) + (Target Base Level x 40)
 			if (wd.miscflag&8) {
@@ -7704,8 +7710,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 		nullpo_info(NLP_MARK);
 		return ad;
 	}
-	//Initial Values
-	ad.damage = 0;
+	// Initial Values
+	// Set to 1 because magic damage on plants is 1 per hit; if target is not a plant this gets reinitialized to 0 later
+	ad.damage = 1;
 	ad.div_ = skill_get_num(skill_id,skill_lv);
 	ad.amotion = (skill_get_inf(skill_id)&INF_GROUND_SKILL ? 0 : sstatus->amotion); //Amotion should be 0 for ground skills.
 	ad.dmotion = tstatus->dmotion;
@@ -7786,9 +7793,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 
 	if (!flag.infdef) { //No need to do the math for plants
 		unsigned int skillratio = 100; //Skill dmg modifiers.
-#ifdef RENEWAL
-		ad.damage = 0; //reinitialize..
-#endif
+		//Damage was set to 1 to simulate plant damage; if not plant, need to reinitialize damage with 0
+		ad.damage = 0;
 //MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
 #define MATK_RATE(a) { ad.damage = ad.damage * (a) / 100; }
 //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
@@ -8146,8 +8152,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 					case WL_SUMMON_ATK_WATER:
 					case WL_SUMMON_ATK_WIND:
 					case WL_SUMMON_ATK_GROUND:
-						skillratio += -100 + (1 + skill_lv) / 2 * (status_get_lv(src) + (sd ? sd->status.job_level : 0));
-						RE_LVL_DMOD(100); // ! TODO: Confirm new formula
+						skillratio += 200;
+						RE_LVL_DMOD(100);
 						break;
 					case LG_RAYOFGENESIS:
 						skillratio += -100 + 350 * skill_lv + sstatus->int_; // !TODO: What's the INT bonus?
@@ -8701,7 +8707,11 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						(sc->getSCE(SC_EARTH_INSIGNIA) && sc->getSCE(SC_EARTH_INSIGNIA)->val1 == 3 && s_ele == ELE_EARTH))
 						skillratio += 25;
 				}
-
+#ifdef RENEWAL
+				// SMATK needs to be applied before the skill ratio to prevent rounding issues
+				if (sd && sstatus->smatk > 0)
+					ad.damage += ad.damage * sstatus->smatk / 100;
+#endif
 				MATK_RATE(skillratio);
 
 				//Constant/misc additions from skills
@@ -8732,9 +8742,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 			ad.damage -= (int64)ad.damage*i/100;
 
 #ifdef RENEWAL
-		if (sd && sstatus->smatk > 0)
-			ad.damage += ad.damage * sstatus->smatk / 100;
-
 		// MRes reduces magical damage by a percentage and
 		// is calculated before MDEF and other reductions.
 		// This should be the official formula. [Rytech]
@@ -9100,17 +9107,40 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 #endif
 			break;
 		case NJ_ZENYNAGE:
+			md.damage = skill_get_zeny( skill_id, skill_lv );
+
+			if( md.damage == 0 ){
+				md.damage = 2;
+			}
+
+			md.damage += rnd_value( static_cast<decltype(md.damage)>( 0 ), md.damage );
+
+			// Specific to Boss Class
+			if( status_get_class_( target ) == CLASS_BOSS ){
+				md.damage /= 3;
+			}
+
+			if( tsd != nullptr ){
+				md.damage /= 2;
+			}
+			break;
 		case KO_MUCHANAGE:
-				md.damage = skill_get_zeny(skill_id, skill_lv);
-				if (!md.damage)
-					md.damage = (skill_id == NJ_ZENYNAGE ? 2 : 10);
-				md.damage = (skill_id == NJ_ZENYNAGE ? rnd()%md.damage + md.damage : md.damage * rnd_value(50,100)) / (skill_id == NJ_ZENYNAGE ? 1 : 100);
-				if (sd && skill_id == KO_MUCHANAGE && !pc_checkskill(sd, NJ_TOBIDOUGU))
-					md.damage = md.damage / 2;
-				if (status_get_class_(target) == CLASS_BOSS) // Specific to Boss Class
-					md.damage = md.damage / (skill_id == NJ_ZENYNAGE ? 3 : 2);
-				else if (tsd && skill_id == NJ_ZENYNAGE)
-					md.damage = md.damage / 2;
+			md.damage = skill_get_zeny( skill_id, skill_lv );
+
+			if( md.damage == 0 ){
+				md.damage = 10;
+			}
+
+			md.damage = rnd_value( md.damage / 2, md.damage );
+
+			if( pc_checkskill( sd, NJ_TOBIDOUGU ) == 0 ){
+				md.damage /= 2;
+			}
+
+			// Specific to Boss Class
+			if( status_get_class_( target ) == CLASS_BOSS ){
+				md.damage /= 2;
+			}
 			break;
 #ifdef RENEWAL
 		case NJ_ISSEN:
@@ -9284,7 +9314,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 			if (sd) {
 				if (md.damage > sd->status.zeny)
 					md.damage = sd->status.zeny;
-				pc_payzeny(sd,(int)cap_value(md.damage, INT_MIN, INT_MAX),LOG_TYPE_STEAL);
+				pc_payzeny( sd, static_cast<int32>( md.damage ), LOG_TYPE_CONSUME );
 			}
 			break;
 	}
@@ -9777,7 +9807,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 				if (sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA)
 					clif_skill_fail( *sd, 0, USESKILL_FAIL_NEED_MORE_BULLET );
 				else
-					clif_arrow_fail(sd,0);
+					clif_arrow_fail( *sd, ARROWFAIL_NO_AMMO );
 				return ATK_NONE;
 			}
 			//Ammo check by Ishizu-chan
@@ -9785,7 +9815,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 				switch (sd->status.weapon) {
 					case W_BOW:
 						if (sd->inventory_data[index]->subtype != AMMO_ARROW) {
-							clif_arrow_fail(sd,0);
+							clif_arrow_fail( *sd, ARROWFAIL_NO_AMMO );
 							return ATK_NONE;
 						}
 						break;
@@ -9829,7 +9859,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		if (dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) {
 			uint16 skill_lv = tsc->getSCE(SC_AUTOCOUNTER)->val1;
 
-			clif_skillcastcancel(target); //Remove the casting bar. [Skotlex]
+			clif_skillcastcancel( *target ); //Remove the casting bar. [Skotlex]
 			clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0, false); //Display MISS.
 			status_change_end(target, SC_AUTOCOUNTER);
 			skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0);
@@ -10438,6 +10468,22 @@ struct block_list* battle_get_master(struct block_list *src)
 	return prev;
 }
 
+bool battle_get_exception_ai(block_list &src) {
+	mob_data *md = BL_CAST(BL_MOB, &src);
+
+	if (!md)
+		return false;
+
+	switch (md->special_state.ai) {
+		case AI_ABR:
+		case AI_ATTACK:
+		case AI_BIONIC:
+		case AI_ZANZOU:
+			return true;
+	}
+	return false;
+}
+
 /*==========================================
  * Checks the state between two targets
  * (enemy, friend, party, guild, etc)
@@ -10689,7 +10735,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 			if( !md->special_state.ai )
 			{ //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 ) ) ||
+					( target->type == BL_MOB && t_bl->type == BL_PC && !battle_get_exception_ai(*target) ) ||
 					( 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 or with AI_WAVEMODE are friends.
@@ -11428,6 +11474,8 @@ static const struct _battle_data {
 
 	{ "mob_respawn_time",                   &battle_config.mob_respawn_time,                1000,   1000,   INT_MAX,        },
 	{ "mob_unlock_time",                    &battle_config.mob_unlock_time,                 2000,   0,      INT_MAX,        },
+	{ "map_edge_size",                      &battle_config.map_edge_size,                   15,     1,      40,             },
+	{ "randomize_center_cell",              &battle_config.randomize_center_cell,           1,      0,      1,              },
 
 	{ "feature.stylist",                    &battle_config.feature_stylist,                 1,      0,      1,              },
 	{ "feature.banking_state_enforce",      &battle_config.feature_banking_state_enforce,   0,      0,      1,              },
@@ -11436,6 +11484,7 @@ static const struct _battle_data {
 #else
 	{ "feature.instance_allow_reconnect",   &battle_config.instance_allow_reconnect,        0,      0,      1,              },
 #endif
+	{ "synchronize_damage",                 &battle_config.synchronize_damage,              0,      0,      1,              },
 
 #include <custom/battle_config_init.inc>
 };

+ 3 - 0
src/map/battle.hpp

@@ -731,10 +731,13 @@ struct Battle_Config
 
 	int mob_respawn_time;
 	int mob_unlock_time;
+	int map_edge_size;
+	int randomize_center_cell;
 
 	int feature_stylist;
 	int feature_banking_state_enforce;
 	int instance_allow_reconnect;
+	int synchronize_damage;
 
 #include <custom/battle_config_struct.inc>
 };

+ 8 - 8
src/map/chat.cpp

@@ -105,7 +105,7 @@ int chat_createpcchat(map_session_data* sd, const char* title, const char* pass,
 		cd->usersd[0] = sd;
 		pc_setchatid(sd,cd->bl.id);
 		pc_stop_attack(sd);
-		clif_createchat(sd,0);
+		clif_createchat( *sd, CREATEROOM_SUCCESS );
 		clif_dispchat(cd,0);
 
 		if (status_isdead(&sd->bl))
@@ -113,7 +113,7 @@ int chat_createpcchat(map_session_data* sd, const char* title, const char* pass,
 		else
 			achievement_update_objective(sd, AG_CHATTING_CREATE, 1, 1);
 	} else
-		clif_createchat(sd,1);
+		clif_createchat( *sd, CREATEROOM_LIMIT_EXCEEDED );
 
 	return 0;
 }
@@ -134,31 +134,31 @@ int chat_joinchat(map_session_data* sd, int chatid, const char* pass)
 	cd = (struct chat_data*)map_id2bl(chatid);
 
 	if( cd == nullptr || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit ) {
-		clif_joinchatfail(sd,0);
+		clif_joinchatfail( *sd, ENTERROOM_FULL );
 		return 0;
 	}
 
 	if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) {
-		clif_joinchatfail(sd,1);
+		clif_joinchatfail( *sd, ENTERROOM_WRONG_PASSWORD );
 		return 0;
 	}
 
 	if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) {
 		if(sd->status.base_level < cd->minLvl)
-			clif_joinchatfail(sd,5);
+			clif_joinchatfail( *sd, ENTERROOM_TOO_LOW_LEVEL );
 		else
-			clif_joinchatfail(sd,6);
+			clif_joinchatfail( *sd, ENTERROOM_TOO_HIGH_LEVEL );
 
 		return 0;
 	}
 
 	if( sd->status.zeny < cd->zeny ) {
-		clif_joinchatfail(sd,4);
+		clif_joinchatfail( *sd, ENTERROOM_NO_ZENY );
 		return 0;
 	}
 
 	if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) {
-		clif_joinchatfail(sd,2);//You have been kicked out of the room.
+		clif_joinchatfail( *sd, ENTERROOM_KICKED );
 		return 0;
 	}
 

+ 2 - 2
src/map/chrif.cpp

@@ -463,7 +463,7 @@ int chrif_changemapserverack(uint32 account_id, int login_id1, int login_id2, ui
 		clif_authfail_fd(node->fd, 0);
 		chrif_char_offline(node->sd);
 	} else
-		clif_changemapserver(node->sd, map, x, y, ntohl(ip), ntohs(port));
+		clif_changemapserver( *node->sd, map, x, y, ntohl(ip), ntohs(port) );
 
 	//Player has been saved already, remove him from memory. [Skotlex]
 	chrif_auth_delete(account_id, char_id, ST_MAPCHANGE);
@@ -994,7 +994,7 @@ int chrif_changedsex(int fd) {
 				}
 			}
 
-			clif_updatestatus(sd, SP_SKILLPOINT);
+			clif_updatestatus(*sd, SP_SKILLPOINT);
 			// Change to other gender version of the job if needed.
 			if (sd->status.sex)// Changed from female version of job.
 				sd->status.class_ -= 1;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 347 - 345
src/map/clif.cpp


+ 296 - 122
src/map/clif.hpp

@@ -49,6 +49,8 @@ struct s_laphine_upgrade;
 struct s_captcha_data;
 enum e_macro_detect_status : uint8;
 enum e_macro_report_status : uint8;
+enum e_hom_state2 : uint8;
+enum _sp;
 
 enum e_PacketDBVersion { // packet DB
 	MIN_PACKET_DB  = 0x064,
@@ -494,13 +496,7 @@ enum useskill_fail_cause : uint8_t
 	USESKILL_FAIL_MAX
 };
 
-enum clif_messages : uint16_t {
-	/* Constant values */
-	// clif_cart_additem_ack flags
-	ADDITEM_TO_CART_FAIL_WEIGHT = 0x0,
-	ADDITEM_TO_CART_FAIL_COUNT = 0x1,
-
-	// clif_equipitemack flags
+enum clif_equipitemack_flag : uint8_t {
 #if PACKETVER_MAIN_NUM >= 20121205 || PACKETVER_RE_NUM >= 20121107 || defined(PACKETVER_ZERO)
 	ITEM_EQUIP_ACK_OK = 0,
 	ITEM_EQUIP_ACK_FAIL = 2,
@@ -510,48 +506,148 @@ enum clif_messages : uint16_t {
 	ITEM_EQUIP_ACK_FAIL = 0,
 	ITEM_EQUIP_ACK_FAILLEVEL = 0,
 #endif
-	/* -end- */
-
-	//! NOTE: These values below need client version validation
-	ITEM_CANT_OBTAIN_WEIGHT = 0x34, /* You cannot carry more items because you are overweight. */
-	ITEM_NOUSE_SITTING = 0x297,
-	ITEM_PARTY_MEMBER_NOT_SUMMONED = 0x4c5, ///< "The party member was not summoned because you are not the party leader."
-	ITEM_PARTY_NO_MEMBER_IN_MAP = 0x4c6, ///< "There is no party member to summon in the current map."
-	MERC_MSG_BASE = 0x4f2,
-	SKILL_CANT_USE_AREA = 0x536,
-	ITEM_CANT_USE_AREA = 0x537,
-	VIEW_EQUIP_FAIL = 0x54d,
-	ITEM_NEED_MADOGEAR = 0x59b,
-	ITEM_NEED_CART = 0x5ef,
-	RUNE_CANT_CREATE = 0x61b,
-	ITEM_CANT_COMBINE = 0x623,
-	INVENTORY_SPACE_FULL = 0x625,
-	ITEM_PRODUCE_SUCCESS = 0x627,
-	ITEM_PRODUCE_FAIL = 0x628,
-	ITEM_UNIDENTIFIED = 0x62d,
-	ITEM_NEED_BOW = 0x69b,
-	ITEM_REUSE_LIMIT = 0x746,
-	WORK_IN_PROGRESS = 0x783,
-	NEED_REINS_OF_MOUNT = 0x78c,
-	PARTY_MASTER_CHANGE_SAME_MAP = 0x82e, ///< "It is only possible to change the party leader while on the same map."
-	MERGE_ITEM_NOT_AVAILABLE = 0x887,
-	ITEM_BULLET_EQUIP_FAIL = 0x9bd,
-	SKILL_NEED_GATLING = 0x9fa,
-	SKILL_NEED_SHOTGUN = 0x9fb,
-	SKILL_NEED_RIFLE = 0x9fc,
-	SKILL_NEED_REVOLVER = 0x9fd,
-	SKILL_NEED_HOLY_BULLET = 0x9fe,
-	SKILL_NEED_GRENADE = 0xa01,
-	GUILD_MASTER_WOE = 0xb93, /// <"Currently in WoE hours, unable to delegate Guild leader"
-	GUILD_MASTER_DELAY = 0xb94, /// <"You have to wait for one day before delegating a new Guild leader"
-	MSG_ATTENDANCE_DISABLED = 0xd92,
-
-	// Unofficial names
-	C_ITEM_EQUIP_SWITCH = 0xbc7,
-	C_ITEM_NOEQUIP = 0x174,	/// <"You can't put this item on."
-	C_ENCHANT_OVERWEIGHT = 0xEFD,
-	C_ENCHANT_SUCCESS = 0xF11,
-	C_ENCHANT_FAILURE = 0xF12,
+};
+
+//! NOTE: These values below need client version validation
+// These values correspond to the msgstringtable line number minus 1
+enum clif_messages : uint16_t {
+
+	// You cannot carry more items because you are overweight.
+	MSI_CANT_GET_ITEM_BECAUSE_WEIGHT = 52,
+
+	// You can't put this item on.
+	MSI_CAN_NOT_EQUIP_ITEM = 372,
+
+	// You cannot use this item while sitting.
+	MSI_CANT_USE_WHEN_SITDOWN = 663,
+
+	// The party member was not summoned because you are not the party leader.
+	MSI_CANNOT_PARTYCALL = 1221,
+
+	// There is no party member to summon in the current map.
+	MSI_NO_PARTYMEM_ON_THISMAP = 1222,
+
+	// The mercenary contract has expired.
+	MSI_MER_FINISH = 1266,
+
+	// The mercenary has died.
+	MSI_MER_DIE = 1267,
+
+	// This skill cannot be used within this area.
+	MSI_IMPOSSIBLE_SKILL_AREA = 1334,
+
+	// This item cannot be used within this area.
+	MSI_IMPOSSIBLE_USEITEM_AREA = 1335,
+
+	// This character's equipment information is not open to the public.
+	MSI_OPEN_EQUIPEDITEM_REFUSED = 1357,
+
+	// Item can only be used when Mado Gear is mounted.
+	MSI_USESKILL_FAIL_MADOGEAR = 1435,
+
+	// Only available when cart is mounted.
+	MSI_USESKILL_FAIL_CART = 1519,
+
+	// Cannot create rune stone more than the maximum amount.
+	MSI_RUNESTONE_MAKEERROR_OVERCOUNT = 1563,
+
+	// Combination of item is not possible in conversion.
+	MSI_SKILL_RECIPE_NOTEXIST = 1570,
+
+	// Please ensure an extra space in your inventory.
+	MSI_SKILL_INVENTORY_KINDCNT_OVER = 1572,
+
+	// Successful.
+	MSI_SKILL_SUCCESS = 1574,
+
+	// Failed.
+	MSI_SKILL_FAIL = 1575,
+
+	// Items cannot be used in materials cannot be emotional.
+	MSI_SKILL_FAIL_MATERIAL_IDENTITY = 1581,
+
+	// [Bow] must be equipped.
+	MSI_FAIL_NEED_EQUIPPED_BOW = 1691,							
+
+#if (PACKETVER >= 20130807 && PACKETVER <= 20130814) && !defined(PACKETVER_ZERO)
+	// %d seconds left until you can use
+	MSI_ITEM_REUSE_LIMIT_SECOND = 1862,
+
+	// Any work in progress (NPC dialog, manufacturing ...) quit and try again.
+	MSI_BUSY = 1924,
+
+	// While boarding reins is not available for items.
+	MSI_FAIELD_RIDING_OVERLAPPED = 1932,
+
+	// It is only possible to change the party leader while on the same map.
+	MSI_PARTY_MASTER_CHANGE_SAME_MAP = 2095,
+
+	// Merge items available does not exist.
+	MSI_NOT_EXIST_MERGE_ITEM = 2183,
+
+	// This bullet is not suitable for the weapon you are equipping.
+	MSI_WRONG_BULLET = 2494,
+#else
+	// %d seconds left until you can use
+	MSI_ITEM_REUSE_LIMIT_SECOND = 1861,
+
+	// Any work in progress (NPC dialog, manufacturing ...) quit and try again.
+	MSI_BUSY = 1923,
+
+	// While boarding reins is not available for items.
+	MSI_FAIELD_RIDING_OVERLAPPED = 1931,
+
+	// It is only possible to change the party leader while on the same map.
+	MSI_PARTY_MASTER_CHANGE_SAME_MAP = 2094,
+
+	// Merge items available does not exist.
+	MSI_NOT_EXIST_MERGE_ITEM = 2182,
+
+	// This bullet is not suitable for the weapon you are equipping.
+	MSI_WRONG_BULLET = 2493,
+#endif
+
+	// [Gatling Gun] weapon class must be equipped.
+	MSI_FAIL_NEED_EQUIPPED_GUN_GATLING = 2554,
+
+	// [Shotgun] weapon class must be equipped.
+	MSI_FAIL_NEED_EQUIPPED_GUN_SHOTGUN = 2555,
+
+	// [Rifle] weapon class must be equipped.
+	MSI_FAIL_NEED_EQUIPPED_GUN_RIFLE = 2556,
+
+	// [Revolver] weapon class must be equipped.
+	MSI_FAIL_NEED_EQUIPPED_GUN_HANDGUN = 2557,
+
+	// [Silver Bullet] must be equipped.
+	MSI_FAIL_NEED_EQUIPPED_PROPERTY_SAINT_BULLET = 2558,
+
+	// [Holy Water] must be equipped.
+	MSI_FAIL_NEED_EQUIPPED_GUN_GRANADE = 2561,
+
+	// [Grenade Launcher] weapon class must be equipped.
+	MSI_IMPOSSIBLE_CHANGE_GUILD_MASTER_IN_SIEGE_TIME = 2963,
+
+	// You have to wait for one day before delegating a new Guild leader
+	MSI_IMPOSSIBLE_CHANGE_GUILD_MASTER_NOT_TIME = 2964,
+
+	// This item has been set for Swap Equipment.
+	MSI_SWAP_EQUIPITEM_UNREGISTER_FIRST = 3015,
+
+	// Possession limit is over 70%, or you have less than 10 free inventory space.
+	MSI_PICKUP_FAILED_ITEMCREATE = 3022,
+
+	// Currently there is no attendance check event.
+	MSI_CHECK_ATTENDANCE_NOT_EVENT = 3474,
+
+	// It weighs more than 70%. Decrease the Weight and try again.
+	MSI_ENCHANT_FAILED_OVER_WEIGHT = 3837,
+
+	// Enchantment successful!
+	MSI_ENCHANT_SUCCESS = 3857,
+
+	// Enchantment failed!
+	MSI_ENCHANT_FAILED = 3858,
 };
 
 enum e_personalinfo : uint8_t {
@@ -622,6 +718,85 @@ enum e_siege_teleport_result : uint8 {
 	SIEGE_TP_INVALID_MODE = 2
 };
 
+enum e_ack_remember_warppoint_result : uint8 {
+	WARPPOINT_SUCCESS = 0,
+	WARPPOINT_LOW_LEVEL = 1,
+	WARPPOINT_NOT_LEARNED = 2
+};
+
+enum e_notify_mapinfo_result : uint8 {
+	NOTIFY_MAPINFO_CANT_TP = 0,
+	NOTIFY_MAPINFO_CANT_MEMO = 1,
+	NOTIFY_MAPINFO_CANT_USE_SKILL = 2,
+	NOTIFY_MAPINFO_CANT_USE_ITEM = 3,
+};
+
+enum e_ack_itemrefining : uint8 {
+	ITEMREFINING_SUCCESS = 0,
+	ITEMREFINING_FAILURE = 1,
+	ITEMREFINING_DOWNGRADE = 2,
+	ITEMREFINING_FAILURE2 = 3
+};
+
+enum e_refuse_enter_room : uint8 {
+	ENTERROOM_FULL = 0,
+	ENTERROOM_WRONG_PASSWORD = 1,
+	ENTERROOM_KICKED = 2,
+	ENTERROOM_SUCCESS = 3,
+	ENTERROOM_NO_ZENY = 4,
+	ENTERROOM_TOO_LOW_LEVEL = 5,
+	ENTERROOM_TOO_HIGH_LEVEL = 6,
+	ENTERROOM_UNSUITABLE_JOB = 7
+};
+
+enum e_create_chatroom : uint8 {
+	CREATEROOM_SUCCESS = 0,
+	CREATEROOM_LIMIT_EXCEEDED = 1,
+	CREATEROOM_ALREADY_EXISTS = 2
+};
+
+enum e_action_failure : uint8 {
+	ARROWFAIL_NO_AMMO = 0,
+	ARROWFAIL_WEIGHT_LIMIT = 1,
+	ARROWFAIL_WEIGHT_LIMIT2 = 2,
+	ARROWFAIL_SUCCESS = 3
+};
+
+enum e_notify_effect : uint8 {
+	NOTIFYEFFECT_BASE_LEVEL_UP = 0,
+	NOTIFYEFFECT_JOB_LEVEL_UP = 1,
+	NOTIFYEFFECT_REFINE_FAILURE = 2,
+	NOTIFYEFFECT_REFINE_SUCCESS = 3,
+	NOTIFYEFFECT_GAME_OVER = 4,
+	NOTIFYEFFECT_PHARMACY_SUCCESS = 5,
+	NOTIFYEFFECT_PHARMACY_FAILURE = 6,
+	NOTIFYEFFECT_SUPER_NOVICE_BASE_LEVEL_UP = 7,
+	NOTIFYEFFECT_SUPER_NOVICE_JOB_LEVEL_UP = 8,
+	NOTIFYEFFECT_TAEKWON_BASE_LEVEL_UP = 9,
+};
+
+enum e_pc_purchase_result_frommc : uint8 {
+	PURCHASEMC_SUCCESS = 0,
+	PURCHASEMC_NO_ZENY = 1,
+	PURCHASEMC_OVERWEIGHT = 2,
+	PURCHASEMC_OUT_OF_STOCK = 4,
+	PURCHASEMC_TRADING = 5,
+	PURCHASEMC_STORE_INCORRECT = 6,
+	PURCHASEMC_NO_SALES_INFO = 7,
+};
+
+enum e_ack_whisper : uint8 {
+	ACKWHISPER_SUCCESS = 0,
+	ACKWHISPER_TARGET_OFFLINE = 1,
+	ACKWHISPER_IGNORED = 2,
+	ACKWHISPER_ALL_IGNORED = 3
+};
+
+enum e_ack_additem_to_cart : uint8 {
+	ADDITEM_TO_CART_FAIL_WEIGHT = 0,
+	ADDITEM_TO_CART_FAIL_COUNT = 1
+};
+
 int clif_setip(const char* ip);
 void clif_setbindip(const char* ip);
 void clif_setport(uint16 port);
@@ -635,40 +810,40 @@ void clif_authrefuse(int fd, uint8 error_code);
 void clif_authfail_fd(int fd, int type);
 void clif_charselectok(int id, uint8 ok);
 void clif_dropflooritem(struct flooritem_data* fitem, bool canShowEffect);
-void clif_clearflooritem(struct flooritem_data *fitem, int fd);
+void clif_clearflooritem( flooritem_data& fitem, map_session_data* tsd = nullptr );
 
-void clif_clearunit_single(int id, clr_type type, int fd);
-void clif_clearunit_area(struct block_list* bl, clr_type type);
+void clif_clearunit_single( uint32 GID, clr_type type, map_session_data& tsd );
+void clif_clearunit_area( block_list& bl, clr_type type );
 void clif_clearunit_delayed(struct block_list* bl, clr_type type, t_tick tick);
 int clif_spawn(struct block_list *bl, bool walking = false);	//area
-void clif_walkok(map_session_data *sd);	// self
+void clif_walkok( map_session_data& sd );
 void clif_move(struct unit_data *ud); //area
-void clif_changemap(map_session_data *sd, short m, int x, int y);	//self
-void clif_changemapserver( map_session_data* sd, const char* map, int x, int y, uint32 ip, uint16 port );
+void clif_changemap( map_session_data& sd, short m, uint16 x, uint16 y );
+void clif_changemapserver( map_session_data& sd, const char* map, uint16 x, uint16 y, uint32 ip, uint16 port );
 void clif_blown(struct block_list *bl); // area
 void clif_slide(struct block_list *bl, int x, int y); // area
-void clif_fixpos(struct block_list *bl);	// area
-void clif_npcbuysell(map_session_data* sd, int id);	//self
-void clif_buylist(map_session_data *sd, struct npc_data *nd);	//self
-void clif_selllist(map_session_data *sd);	//self
+void clif_fixpos( block_list& bl );
+void clif_npcbuysell( map_session_data& sd, npc_data& nd );
+void clif_buylist( map_session_data& sd, npc_data& nd );
+void clif_selllist( map_session_data& sd );
 void clif_npc_market_open(map_session_data *sd, struct npc_data *nd);
 void clif_parse_NPCMarketClosed(int fd, map_session_data *sd);
 void clif_parse_NPCMarketPurchase(int fd, map_session_data *sd);
 void clif_scriptmes( map_session_data& sd, uint32 npcid, const char *mes );
 void clif_scriptnext( map_session_data& sd, uint32 npcid );
-void clif_scriptclose(map_session_data *sd, int npcid);	//self
+void clif_scriptclose( map_session_data& sd, uint32 npcid );
 void clif_scriptclear( map_session_data& sd, int npcid ); //self
-void clif_scriptmenu(map_session_data* sd, int npcid, const char* mes);	//self
-void clif_scriptinput(map_session_data *sd, int npcid);	//self
-void clif_scriptinputstr(map_session_data *sd, int npcid);	// self
-void clif_cutin(map_session_data* sd, const char* image, int type);	//self
-void clif_viewpoint(map_session_data *sd, int npc_id, int type, int x, int y, int id, int color);	//self
+void clif_scriptmenu( map_session_data& sd, uint32 npcid, const char* mes );
+void clif_scriptinput( map_session_data& sd, uint32 npcid );
+void clif_scriptinputstr( map_session_data& sd, uint32 npcid );
+void clif_cutin( map_session_data& sd, const char* image, int type );
+void clif_viewpoint( map_session_data& sd, uint32 npc_id, int type, uint16 x, uint16 y, int id, uint32 color );
 void clif_additem(map_session_data *sd, int n, int amount, unsigned char fail); // self
-void clif_dropitem(map_session_data *sd,int n,int amount);	//self
-void clif_delitem(map_session_data *sd,int n,int amount, short reason); //self
+void clif_dropitem( map_session_data& sd, int index, int amount );
+void clif_delitem( map_session_data& sd, int index, int amount, short reason );
 void clif_update_hp(map_session_data &sd);
-void clif_updatestatus(map_session_data *sd,int type);	//self
-void clif_changestatus(map_session_data* sd,int type,int val);	//area
+void clif_updatestatus( map_session_data& sd, _sp type );
+void clif_changemanner( map_session_data& sd );
 int clif_damage(struct block_list* src, struct block_list* dst, t_tick tick, int sdelay, int ddelay, int64 sdamage, int div, enum e_damage_type type, int64 sdamage2, bool spdamage);	// area
 void clif_takeitem(struct block_list* src, struct block_list* dst);
 void clif_sitting(struct block_list* bl);
@@ -677,21 +852,21 @@ void clif_sprite_change(struct block_list *bl, int id, int type, int val, int va
 void clif_changelook(struct block_list *bl,int type,int val);	// area
 void clif_changetraplook(struct block_list *bl,int val); // area
 void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_target target); //area specified in 'target'
-void clif_arrowequip(map_session_data *sd,int val); //self
-void clif_arrow_fail(map_session_data *sd,int type); //self
-void clif_arrow_create_list(map_session_data *sd);	//self
-void clif_statusupack(map_session_data *sd,int type,int ok,int val);	// self
+void clif_arrowequip( map_session_data& sd );
+void clif_arrow_fail( map_session_data& sd, e_action_failure type );
+void clif_arrow_create_list( map_session_data& sd );
+void clif_statusupack( map_session_data& sd, int32 type, bool success, int32 val = 0 );
 void clif_equipitemack( map_session_data& sd, uint8 flag, int index, int pos = 0 ); // self
 void clif_unequipitemack(map_session_data *sd,int n,int pos,int ok);	// self
-void clif_misceffect(struct block_list* bl,int type);	// area
+void clif_misceffect( block_list& bl, e_notify_effect type );
 void clif_changeoption_target(struct block_list* bl, struct block_list* target);
 #define clif_changeoption(bl) clif_changeoption_target(bl, nullptr)	// area
-void clif_changeoption2(struct block_list* bl);	// area
+void clif_changeoption2( block_list& bl );
 void clif_useitemack(map_session_data *sd,int index,int amount,bool ok);	// self
-void clif_GlobalMessage(struct block_list* bl, const char* message,enum send_target target);
-void clif_createchat(map_session_data* sd, int flag);	// self
+void clif_GlobalMessage( block_list& bl, const char* message, enum send_target target );
+void clif_createchat( map_session_data& sd, e_create_chatroom flag );
 void clif_dispchat(struct chat_data* cd, int fd);	// area or fd
-void clif_joinchatfail(map_session_data *sd,int flag);	// self
+void clif_joinchatfail( map_session_data& sd, e_refuse_enter_room result );
 void clif_joinchatok(map_session_data *sd,struct chat_data* cd);	// self
 void clif_addchat(struct chat_data* cd,map_session_data *sd);	// chat
 void clif_changechatowner(struct chat_data* cd, map_session_data* sd);	// chat
@@ -717,17 +892,17 @@ void clif_traderequest(map_session_data* sd, const char* name);
 void clif_tradestart(map_session_data* sd, uint8 type);
 void clif_tradeadditem(map_session_data* sd, map_session_data* tsd, int index, int amount);
 void clif_tradeitemok(map_session_data& sd, int index, e_exitem_add_result result);
-void clif_tradedeal_lock(map_session_data* sd, int fail);
-void clif_tradecancelled(map_session_data* sd);
-void clif_tradecompleted(map_session_data* sd, int fail);
-void clif_tradeundo(map_session_data* sd);
+void clif_tradedeal_lock( map_session_data& sd, bool who );
+void clif_tradecancelled( map_session_data& sd );
+void clif_tradecompleted( map_session_data& sd );
+void clif_tradeundo( map_session_data& sd );
 
 // storage
 void clif_storagelist(map_session_data* sd, struct item* items, int items_length, const char *storename);
-void clif_updatestorageamount(map_session_data* sd, int amount, int max_amount);
+void clif_updatestorageamount( map_session_data& sd, uint16 amount, uint16 max_amount );
 void clif_storageitemadded(map_session_data* sd, struct item* i, int index, int amount);
-void clif_storageitemremoved(map_session_data* sd, int index, int amount);
-void clif_storageclose(map_session_data* sd);
+void clif_storageitemremoved( map_session_data& sd, uint16 index, uint32 amount );
+void clif_storageclose( map_session_data& sd );
 
 int clif_insight(struct block_list *bl,va_list ap);	// map_forallinmovearea callback
 int clif_outsight(struct block_list *bl,va_list ap);	// map_forallinmovearea callback
@@ -743,25 +918,25 @@ void clif_addskill(map_session_data *sd, int skill_id);
 void clif_deleteskill(map_session_data *sd, int skill_id, bool skip_infoblock = false);
 
 void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, uint16 skill_lv, int property, int casttime);
-void clif_skillcastcancel(struct block_list* bl);
+void clif_skillcastcancel( block_list& bl );
 void clif_skill_fail( map_session_data& sd, uint16 skill_id, enum useskill_fail_cause cause = USESKILL_FAIL_LEVEL, int btype = 0, t_itemid itemId = 0 );
-void clif_skill_cooldown(map_session_data *sd, uint16 skill_id, t_tick tick);
+void clif_skill_cooldown( map_session_data &sd, uint16 skill_id, t_tick tick );
 int clif_skill_damage(struct block_list *src,struct block_list *dst,t_tick tick,int sdelay,int ddelay,int64 sdamage,int div,uint16 skill_id,uint16 skill_lv,enum e_damage_type type);
 //int clif_skill_damage2(struct block_list *src,struct block_list *dst,t_tick tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,enum e_damage_type type);
 bool clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,t_tick tick);
 void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,int y,t_tick tick);
 void clif_skill_estimation(map_session_data *sd,struct block_list *dst);
 void clif_skill_warppoint( map_session_data* sd, uint16 skill_id, uint16 skill_lv, const char* map1, const char* map2 = "", const char* map3 = "", const char* map4 = "" );
-void clif_skill_memomessage(map_session_data* sd, int type);
-void clif_skill_teleportmessage(map_session_data *sd, int type);
+void clif_skill_memomessage( map_session_data& sd, e_ack_remember_warppoint_result result );
+void clif_skill_teleportmessage( map_session_data& sd, e_notify_mapinfo_result result );
 void clif_skill_produce_mix_list(map_session_data *sd, int skill_id, int trigger);
 void clif_cooking_list(map_session_data *sd, int trigger, uint16 skill_id, int qty, int list_type);
 
 void clif_produceeffect(map_session_data* sd,int flag, t_itemid nameid);
 
 void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *unit, enum send_target target, bool visible);
-void clif_skill_delunit(struct skill_unit *unit);
-void clif_skillunit_update(struct block_list* bl);
+void clif_skill_delunit( skill_unit& unit );
+void clif_skillunit_update( block_list& bl);
 
 void clif_skill_unit_test(struct block_list *bl, short x, short y, int unit_id, short range, short skill_lv);
 
@@ -781,7 +956,7 @@ void clif_efst_status_change(struct block_list *bl, int tid, enum send_target ta
 void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target);
 
 void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, size_t mes_len, int gmlvl);
-void clif_wis_end(int fd, int result);
+void clif_wis_end( map_session_data& sd, e_ack_whisper result );
 
 void clif_solved_charname(int fd, int charid, const char* name);
 void clif_name( struct block_list* src, struct block_list *bl, send_target target );
@@ -789,25 +964,25 @@ void clif_name( struct block_list* src, struct block_list *bl, send_target targe
 #define clif_name_area(bl) clif_name( (bl), (bl), AREA )
 
 void clif_use_card(map_session_data *sd,int idx);
-void clif_insert_card(map_session_data *sd,int idx_equip,int idx_card,int flag);
+void clif_insert_card( map_session_data& sd, int32 idx_equip, int32 idx_card, bool failure );
 
 void clif_inventorylist(map_session_data *sd);
 void clif_equiplist(map_session_data *sd);
 
 void clif_cart_additem(map_session_data *sd,int n,int amount);
-void clif_cart_additem_ack(map_session_data *sd, uint8 flag);
-void clif_cart_delitem(map_session_data *sd,int n,int amount);
+void clif_cart_additem_ack( map_session_data& sd, e_ack_additem_to_cart flag );
+void clif_cart_delitem( map_session_data& sd, int32 index, int32 amount );
 void clif_cartlist(map_session_data *sd);
 void clif_clearcart(int fd);
 
 void clif_item_identify_list(map_session_data *sd);
-void clif_item_identified(map_session_data *sd,int idx,int flag);
+void clif_item_identified( map_session_data& sd, int32 idx, bool failure );
 void clif_item_repair_list( map_session_data& sd, map_session_data& dstsd, uint16 lv );
-void clif_item_repaireffect(map_session_data *sd, int idx, int flag);
-void clif_item_damaged(map_session_data* sd, unsigned short position);
-void clif_item_refine_list(map_session_data *sd);
-void clif_hat_effects( map_session_data* sd, struct block_list* bl, enum send_target target );
-void clif_hat_effect_single( map_session_data* sd, uint16 effectId, bool enable );
+void clif_item_repaireffect( map_session_data& sd, int32 idx, bool failure );
+void clif_item_damaged( map_session_data& sd, uint16 position );
+void clif_item_refine_list( map_session_data& sd );
+void clif_hat_effects( map_session_data& sd, block_list& bl, enum send_target target );
+void clif_hat_effect_single( map_session_data& sd, uint16 effectId, bool enable );
 
 void clif_item_skill(map_session_data *sd,uint16 skill_id,uint16 skill_lv);
 
@@ -818,15 +993,15 @@ void clif_mvp_noitem(map_session_data* sd);
 void clif_changed_dir(struct block_list *bl, enum send_target target);
 
 // vending
-void clif_openvendingreq(map_session_data* sd, int num);
+void clif_openvendingreq( map_session_data& sd, uint16 num );
 void clif_showvendingboard( map_session_data& sd, enum send_target target = AREA_WOS, struct block_list* tbl = nullptr );
 void clif_closevendingboard(struct block_list* bl, int fd);
 void clif_vendinglist( map_session_data* sd, map_session_data* vsd );
-void clif_buyvending(map_session_data* sd, int index, int amount, int fail);
+void clif_buyvending( map_session_data& sd, uint16 index, uint16 amount, e_pc_purchase_result_frommc result );
 void clif_openvending(map_session_data* sd, int id, struct s_vending* vending);
-void clif_vendingreport(map_session_data* sd, int index, int amount, uint32 char_id, int zeny);
+void clif_vendingreport( map_session_data& sd, uint16 index, uint16 amount, uint32 char_id, int32 zeny );
 
-void clif_movetoattack(map_session_data *sd,struct block_list *bl);
+void clif_movetoattack( map_session_data& sd, block_list& bl );
 
 // party
 void clif_party_created( map_session_data& sd, int result );
@@ -869,9 +1044,9 @@ void clif_guild_allianceack(map_session_data *sd,int flag);
 void clif_guild_delalliance(map_session_data *sd,int guild_id,int flag);
 void clif_guild_oppositionack(map_session_data *sd,int flag);
 void clif_guild_broken(map_session_data *sd,int flag);
-void clif_guild_xy(map_session_data *sd);
-void clif_guild_xy_single(int fd, map_session_data *sd);
-void clif_guild_xy_remove(map_session_data *sd);
+void clif_guild_xy( map_session_data& sd );
+void clif_guild_xy_single( map_session_data& sd, map_session_data& tsd );
+void clif_guild_xy_remove( map_session_data& sd );
 void clif_guild_castle_list(map_session_data& sd);
 void clif_guild_castle_info(map_session_data& sd, std::shared_ptr<guild_castle> castle );
 void clif_guild_castle_teleport_res(map_session_data& sd, enum e_siege_teleport_result result);
@@ -909,17 +1084,17 @@ void clif_displaymessage(const int fd, const char* mes);
 void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target);
 void clif_broadcast(struct block_list* bl, const char* mes, size_t len, int type, enum send_target target);
 void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
-void clif_heal(int fd,int type,int val);
-void clif_resurrection(struct block_list *bl,int type);
+void clif_heal( map_session_data& sd, int32 type, uint32 val );
+void clif_resurrection( block_list& bl );
 void clif_map_property(struct block_list *bl, enum map_property property, enum send_target t);
 void clif_pvpset(map_session_data *sd, int pvprank, int pvpnum,int type);
 void clif_map_property_mapall(int map, enum map_property property);
-void clif_refine(int fd, int fail, int index, int val);
+void clif_refine( map_session_data& sd, uint16 index, e_ack_itemrefining result );
 void clif_upgrademessage( map_session_data* sd, int result, t_itemid item_id );
 
 //petsystem
-void clif_catch_process(map_session_data *sd);
-void clif_pet_roulette(map_session_data *sd,int data);
+void clif_catch_process( map_session_data& sd );
+void clif_pet_roulette( map_session_data& sd, bool success );
 void clif_sendegg(map_session_data *sd);
 void clif_send_petstatus(map_session_data *sd);
 void clif_send_petdata(map_session_data* sd, struct pet_data* pd, int type, int param);
@@ -927,7 +1102,7 @@ void clif_send_petdata(map_session_data* sd, struct pet_data* pd, int type, int
 #define clif_pet_equip_area(pd) clif_send_petdata(nullptr, pd, 3, (pd)->vd.head_bottom)
 #define clif_pet_performance(pd, param) clif_send_petdata(nullptr, pd, 4, param)
 void clif_pet_emotion(struct pet_data *pd,int param);
-void clif_pet_food(map_session_data *sd,int foodid,int fail);
+void clif_pet_food( map_session_data& sd, int32 foodid, bool success );
 void clif_pet_autofeed_status(map_session_data* sd, bool force);
 
 //friends list
@@ -964,13 +1139,13 @@ void clif_feel_hate_reset(map_session_data *sd);
 
 // [blackhole89]
 void clif_hominfo(map_session_data *sd, struct homun_data *hd, int flag);
-int clif_homskillinfoblock(map_session_data *sd);
-void clif_homskillup(map_session_data *sd, uint16 skill_id);	//[orn]
-void clif_hom_food(map_session_data *sd,int foodid,int fail);	//[orn]
-void clif_send_homdata(map_session_data *sd, int state, int param);	//[orn]
+void clif_homskillinfoblock( homun_data& hd );
+void clif_homskillup( homun_data& hd, uint16 skill_id );
+void clif_hom_food( map_session_data& sd, int32 foodid, bool success );
+void clif_send_homdata( homun_data& hd, e_hom_state2 state );
 
 void clif_configuration( map_session_data* sd, enum e_config_type type, bool enabled );
-void clif_viewequip_ack(map_session_data* sd, map_session_data* tsd);
+void clif_viewequip_ack( map_session_data& sd, map_session_data& tsd );
 void clif_equipcheckbox(map_session_data* sd);
 
 void clif_msg(map_session_data* sd, unsigned short id);
@@ -1020,7 +1195,7 @@ void clif_Auction_close(int fd, unsigned char flag);
 void clif_parse_Auction_cancelreg(int fd, map_session_data *sd);
 
 void clif_bossmapinfo( map_session_data& sd, mob_data* md, e_bossmap_info flag );
-void clif_cashshop_show(map_session_data *sd, struct npc_data *nd);
+void clif_cashshop_show( map_session_data& sd, npc_data& nd );
 
 // ADOPTION
 void clif_Adopt_reply(map_session_data *sd, int type);
@@ -1029,7 +1204,6 @@ void clif_Adopt_request(map_session_data *sd, map_session_data *src, int p_id);
 // MERCENARIES
 void clif_mercenary_info(map_session_data *sd);
 void clif_mercenary_skillblock(map_session_data *sd);
-void clif_mercenary_message(map_session_data* sd, int message);
 void clif_mercenary_updatestatus(map_session_data *sd, int type);
 
 // RENTAL SYSTEM
@@ -1096,7 +1270,7 @@ void clif_parse_roulette_close(int fd, map_session_data *sd);
 void clif_parse_roulette_generate(int fd, map_session_data *sd);
 void clif_parse_roulette_item(int fd, map_session_data *sd);
 
-void clif_elementalconverter_list(map_session_data *sd);
+void clif_elementalconverter_list( map_session_data& sd );
 
 void clif_millenniumshield(struct block_list *bl, short shields);
 

+ 5 - 101
src/map/clif_packetdb.hpp

@@ -22,12 +22,9 @@
 	packet(0x0070,6);
 	packet(0x0071,28);
 	parseable_packet(0x0072,19,clif_parse_WantToConnection,2,6,10,14,18);
-	packet(0x0073,11);
-	packet(0x0074,3);
 	packet(0x0075,-1);
 	packet(0x0076,9);
 	packet(0x0077,5);
-	packet(0x0078,54);
 	packet(0x0079,53);
 	packet(0x007a,58);
 	packet(0x007b,60);
@@ -35,15 +32,10 @@
 	parseable_packet(0x007d,2,clif_parse_LoadEndAck,0);
 	parseable_packet(0x007e,6,clif_parse_TickSend,2);
 	packet(0x007f,6);
-	packet(0x0080,7);
-	packet(0x0081,3);
 	packet(0x0082,2);
 	packet(0x0083,2);
 	packet(0x0084,2);
 	parseable_packet(0x0085,5,clif_parse_WalkToXY,2);
-	packet(0x0086,16);
-	packet(0x0087,12);
-	packet(0x0088,10);
 	parseable_packet(0x0089,7,clif_parse_ActionRequest,2,6);
 	packet(0x008a,29);
 	packet(0x008b,2);
@@ -52,12 +44,9 @@
 	packet(0x008e,-1);
 	//packet(0x008f,-1);
 	parseable_packet(0x0090,7,clif_parse_NpcClicked,2,6);
-	packet(0x0091,22);
-	packet(0x0092,28);
 	packet(0x0093,2);
 	parseable_packet(0x0094,6,clif_parse_GetCharNameRequest,2);
 	parseable_packet(0x0096,-1,clif_parse_WisMessage,2,4,28);
-	packet(0x0098,3);
 	parseable_packet(0x0099,-1,clif_parse_Broadcast,2,4);
 	packet(0x009a,-1);
 	parseable_packet(0x009b,5,clif_parse_ChangeDir,2,4);
@@ -65,7 +54,6 @@
 	packet( HEADER_ZC_ITEM_ENTRY, sizeof( struct PACKET_ZC_ITEM_ENTRY ) );
 	packet(0x009e,17);
 	parseable_packet(0x009f,6,clif_parse_TakeItem,2);
-	packet(0x00a1,6);
 	parseable_packet(0x00a2,6,clif_parse_DropItem,2,4);
 	packet( inventorylistnormalType, -1 );
 	packet( inventorylistequipType, -1 );
@@ -78,29 +66,18 @@
 	packet(0x00ac,7);
 	//packet(0x00ad,-1);
 	packet(0x00ae,-1);
-	packet(0x00af,6);
-	packet(0x00b0,8);
-	packet(0x00b1,8);
 	parseable_packet(0x00b2,3,clif_parse_Restart,2);
-	packet(0x00b3,3);
-	packet(0x00b6,6);
-	packet(0x00b7,-1);
 	parseable_packet(0x00b8,7,clif_parse_NpcSelectMenu,2,6);
 	parseable_packet(0x00b9,6,clif_parse_NpcNextClicked,2);
 	packet(0x00ba,2);
 	parseable_packet(0x00bb,5,clif_parse_StatusUp,2,4);
-	packet(0x00bc,6);
-	packet(0x00bd,44);
-	packet(0x00be,5);
 	parseable_packet(0x00bf,3,clif_parse_Emotion,2);
 	packet(0x00c0,7);
 	parseable_packet(0x00c1,2,clif_parse_HowManyConnections,0);
 	packet(0x00c2,6);
 	packet(0x00c3,8);
-	packet(0x00c4,6);
 	parseable_packet(0x00c5,7,clif_parse_NpcBuySellSelected,2,6);
 	packet(0x00c6,-1);
-	packet(0x00c7,-1);
 	parseable_packet(0x00c8,-1,clif_parse_NpcBuyListSend,2,4);
 	parseable_packet(HEADER_CZ_PC_SELL_ITEMLIST,-1,clif_parse_NpcSellListSend,2,4);
 	packet(0x00ca,3);
@@ -115,11 +92,9 @@
 	parseable_packet(0x00d3,2,clif_parse_PMIgnoreList,0);
 	packet(0x00d4,-1);
 	parseable_packet(0x00d5,-1,clif_parse_CreateChatRoom,2,4,6,7,15);
-	packet(0x00d6,3);
 	packet(0x00d7,-1);
 	packet(0x00d8,6);
 	parseable_packet(0x00d9,14,clif_parse_ChatAddMember,2,6);
-	packet(0x00da,3);
 	packet(0x00db,-1);
 	packet(0x00dc,28);
 	packet(0x00dd,29);
@@ -136,18 +111,11 @@
 	parseable_packet(0x00e8,8,clif_parse_TradeAddItem,2,4);
 	packet(0x00ea,5);
 	parseable_packet(0x00eb,2,clif_parse_TradeOk,0);
-	packet(0x00ec,3);
 	parseable_packet(0x00ed,2,clif_parse_TradeCancel,0);
-	packet(0x00ee,2);
 	parseable_packet(0x00ef,2,clif_parse_TradeCommit,0);
-	packet(0x00f0,3);
-	packet(0x00f1,2);
-	packet(0x00f2,6);
 	parseable_packet(0x00f3,8,clif_parse_MoveToKafra,2,4);
 	parseable_packet(0x00f5,8,clif_parse_MoveFromKafra,2,4);
-	packet(0x00f6,8);
 	parseable_packet(0x00f7,2,clif_parse_CloseKafra,0);
-	packet(0x00f8,2);
 	parseable_packet(0x00f9,26,clif_parse_CreateParty,2);
 	packet(0x00fb,-1);
 	parseable_packet(0x00fc,6,clif_parse_PartyInvite,2);
@@ -180,45 +148,27 @@
 	parseable_packet(0x011b,20,clif_parse_UseSkillMap,2,4);
 	packet(0x011c,68);
 	parseable_packet(0x011d,2,clif_parse_RequestMemo,0);
-	packet(0x011e,3);
 	packet(0x011f,16);
-	packet(0x0120,6);
-	packet(0x0121,14);
 	packet( cartlistequipType, -1 );
 	packet( cartlistnormalType, -1 );
-	packet(0x0125,8);
 	parseable_packet( HEADER_CZ_MOVE_ITEM_FROM_BODY_TO_CART, sizeof( PACKET_CZ_MOVE_ITEM_FROM_BODY_TO_CART ), clif_parse_PutItemToCart, 0 );
 	parseable_packet(0x0127,8,clif_parse_GetItemFromCart,2,4);
 	parseable_packet(0x0128,8,clif_parse_MoveFromKafraToCart,2,4);
 	parseable_packet(0x0129,8,clif_parse_MoveToKafraFromCart,2,4);
 	parseable_packet(0x012a,2,clif_parse_RemoveOption,0);
-	packet(0x012b,2);
-	packet(0x012c,3);
-	packet(0x012d,4);
 	parseable_packet(0x012e,2,clif_parse_CloseVending,0);
 	parseable_packet(0x012f,-1,clif_parse_OpenVending,2,4,0,84);
 	parseable_packet(0x0130,6,clif_parse_VendingListReq,2);
 	packet(0x0132,6);
 	parseable_packet( HEADER_CZ_PC_PURCHASE_ITEMLIST_FROMMC, -1, clif_parse_PurchaseReq, 0 );
-	packet(0x0135,7);
-	packet(0x0137,6);
 	packet(0x0138,3);
-	packet(0x0139,16);
-	packet(0x013a,4);
-	packet(0x013b,4);
-	packet(0x013c,4);
-	packet(0x013d,6);
 	packet(0x013e,24);
 	parseable_packet(0x013f,26,clif_parse_GM_Item_Monster,2);
 	parseable_packet(0x0140,22,clif_parse_MapMove,2,18,20);
-	packet(0x0141,14);
-	packet(0x0142,6);
 	parseable_packet(0x0143,10,clif_parse_NpcAmountInput,2,6);
-	packet(0x0144,23);
 	packet(0x0145,19);
 	parseable_packet(0x0146,6,clif_parse_NpcCloseClicked,2);
 	packet(0x0147,39);
-	packet(0x0148,8);
 	parseable_packet(0x0149,9,clif_parse_GMReqNoChat,2,6,7);
 	packet(0x014a,6);
 	packet(0x014b,27);
@@ -267,11 +217,9 @@
 	packet(0x0176,106);
 	packet(0x0177,-1);
 	parseable_packet(0x0178,4,clif_parse_ItemIdentify,2);
-	packet(0x0179,5);
 	parseable_packet(0x017a,4,clif_parse_UseCard,2);
 	packet(0x017b,-1);
 	parseable_packet(0x017c,6,clif_parse_InsertCard,2,4);
-	packet(0x017d,7);
 	parseable_packet(0x017e,-1,clif_parse_GuildMessage,2,4);
 	packet(0x017f,-1);
 	parseable_packet(0x0180,6,clif_parse_GuildOpposition,2);
@@ -282,8 +230,6 @@
 	packet(0x0185,34);
 	//packet(0x0186,-1);
 	packet(0x0187,6);
-	packet(0x0188,8);
-	packet(0x0189,4);
 	parseable_packet(0x018a,4,clif_parse_QuitGame,2);
 	packet(0x018b,4);
 	packet(0x018c,29);
@@ -301,12 +247,9 @@
 	parseable_packet(0x0198,8,clif_parse_GMChangeMapType,2,4,6);
 	packet(0x0199,4);
 	packet(0x019a,14);
-	packet(0x019b,10);
 	parseable_packet(0x019c,-1,clif_parse_LocalBroadcast,2,4);
 	parseable_packet(0x019d,6,clif_parse_GMHide,2);
-	packet(0x019e,2);
 	parseable_packet(0x019f,6,clif_parse_CatchPet,2);
-	packet(0x01a0,3);
 	parseable_packet(0x01a1,3,clif_parse_PetMenu,2);
 	packet(0x01a2,35);
 	packet(0x01a3,5);
@@ -317,7 +260,6 @@
 	packet(0x01a8,4);
 	parseable_packet(0x01a9,6,clif_parse_SendEmotion,2);
 	packet(0x01aa,10);
-	packet(0x01ab,12);
 	packet(0x01ac,6);
 	packet(0x01ad,-1);
 	parseable_packet( HEADER_CZ_REQ_MAKINGARROW, sizeof( PACKET_CZ_REQ_MAKINGARROW ), clif_parse_SelectArrow, 0 );
@@ -325,13 +267,11 @@
 	packet(0x01b0,11);
 	packet(0x01b1,7);
 	parseable_packet(0x01b2,-1,clif_parse_OpenVending,2,4,84,85);
-	packet(0x01b3,67);
 	packet(0x01b4,12);
 	packet(0x01b5,18);
 	packet(0x01b6,114);
 	packet(0x01b7,6);
 	packet(0x01b8,3);
-	packet(0x01b9,6);
 	parseable_packet(0x01ba,26,clif_parse_GMShift,2);
 	parseable_packet(0x01bb,26,clif_parse_GMShift,2);
 	parseable_packet(0x01bc,26,clif_parse_GMRecall,2);
@@ -353,9 +293,7 @@
 	packet(0x01d0,8);
 	packet(0x01d1,14);
 	packet(0x01d2,10);
-	packet(0x01d4,6);
 	parseable_packet(0x01d5,-1,clif_parse_NpcStringInput,2,4,8);
-	packet(0x01d6,4);
 	packet(0x01d7,11);
 	packet(0x01d8,54);
 	packet(0x01d9,53);
@@ -375,7 +313,6 @@
 	parseable_packet(0x01e7,2,clif_parse_NoviceDoriDori,0);
 	parseable_packet(0x01e8,28,clif_parse_CreateParty2,2,26,27);
 	packet(0x01ea,6);
-	packet(0x01eb,10);
 	packet(0x01ec,26);
 	parseable_packet(0x01ed,2,clif_parse_NoviceExplosionSpirits,0);
 	packet(0x01f0,-1);
@@ -392,7 +329,6 @@
 	packet(0x01fb,56);
 	packet(0x01fc,-1);
 	parseable_packet( HEADER_CZ_REQ_ITEMREPAIR1, sizeof( struct PACKET_CZ_REQ_ITEMREPAIR1 ), clif_parse_RepairItem, 0 );
-	packet(0x01fe,5);
 	packet(0x01ff,10);
 	packet(0x0200,26);
 	packet(0x0201,-1);
@@ -693,13 +629,11 @@
 // 2005-05-23aSakexe
 #if PACKETVER >= 20050523
 	packet(0x022e,69);
-	packet(0x0230,12);
 #endif
 
 // 2005-05-30aSakexe
 #if PACKETVER >= 20050530
 	packet(0x022e,71);
-	packet(0x0235,-1);
 	packet(0x0236,10);
 	parseable_packet(0x0237,2,clif_parse_RankingPk,0);
 	packet(0x0238,282);
@@ -708,7 +642,6 @@
 // 2005-05-31aSakexe
 #if PACKETVER >= 20050531
 	packet(0x0216,2);
-	packet(0x0239,11);
 #endif
 
 // 2005-06-08aSakexe
@@ -958,7 +891,6 @@
 	packet(0x0287,-1);
 	packet(0x0288,6);
 	packet(0x0289,8);
-	packet(0x028a,18);
 	packet(0x028b,-1);
 	packet(0x028c,46);
 	packet(0x028d,34);
@@ -1059,7 +991,6 @@
 	packet( HEADER_ZC_ITEM_PICKUP_PARTY, sizeof( struct PACKET_ZC_ITEM_PICKUP_PARTY ) );
 	packet(0x02b9,191);
 	parseable_packet(0x02ba,11,clif_parse_Hotkey,2,4,5,9);
-	packet(0x02bb,8);
 	packet(0x02bc,6);
 	packet(0x02bf,10);
 	packet(0x02c0,2);
@@ -1096,7 +1027,6 @@
 
 // 2007-11-06aSakexe
 #if PACKETVER >= 20071106
-	packet(0x0078,55);
 	packet(0x007c,42);
 	packet(0x022c,65);
 	packet(0x029b,80);
@@ -1125,7 +1055,6 @@
 // 2008-01-02aSakexe
 #if PACKETVER >= 20080102
 	parseable_packet(0x01df,6,clif_parse_GMReqAccountName,2);
-	packet(0x02eb,13);
 	packet(0x02ec,67);
 	packet(0x02ed,59);
 	packet(0x02ee,60);
@@ -1319,7 +1248,6 @@
 
 // 2008-11-13aSakexe
 #if PACKETVER >= 20081113
-	packet(0x043d,8);
 	packet(0x043e,-1);
 	packet(0x043f,8);
 #endif
@@ -1327,13 +1255,12 @@
 // 2008-11-26aSakexe
 #if PACKETVER >= 20081126
 	packet(0x01a2,37);
-	packet(0x0440,10);
 	packet(0x0441,4);
 #endif
 
 // 2008-12-10aSakexe
 #if PACKETVER >= 20081210
-	parseable_packet(0x0443,8,clif_parse_SkillSelectMenu,2,6);
+	parseable_packet( HEADER_CZ_SKILL_SELECT_RESPONSE, sizeof( PACKET_CZ_SKILL_SELECT_RESPONSE ), clif_parse_SkillSelectMenu, 0 );
 #endif
 
 // 2009-01-14aSakexe
@@ -1400,7 +1327,6 @@
 
 // 2008-11-12aRagexeRE
 #if PACKETVER >= 20081112
-	packet(0x043d,8);
 	//packet(0x043e,-1);
 	packet(0x043f,8);
 #endif
@@ -1408,7 +1334,6 @@
 // 2008-12-17aRagexeRE
 #if PACKETVER >= 20081217
 	packet(0x01a2,37);
-	//packet(0x0440,10);
 	//packet(0x0441,4);
 	//packet(0x0443,8);
 #endif
@@ -1559,11 +1484,6 @@
 	packet(0x07f9,-1);
 #endif
 
-// 2009-11-17aRagexeRE
-#if PACKETVER >= 20091117
-	packet(0x07fa,8);
-#endif
-
 // 2009-11-24aRagexeRE
 #if PACKETVER >= 20091124
 	packet(0x07fb,25);
@@ -1801,7 +1721,6 @@
 	parseable_packet(0x08ab,-1,clif_parse_SearchStoreInfo,2,4,5,9,13,14,15);
 	parseable_packet(0x088b,2,clif_parse_SearchStoreInfoNextPage,0);
 	parseable_packet(0x08a2,sizeof(struct PACKET_CZ_SSILIST_ITEM_CLICK),clif_parse_SearchStoreInfoListItemClick,2,6,10);
-	packet(0x08cf,10); //Amulet spirits
 #endif
 
 // 2012-03-07fRagexeRE
@@ -1915,7 +1834,7 @@
 	parseable_packet(0x0974,2,clif_parse_merge_item_cancel,0); // CZ_CANCEL_MERGE_ITEM
 	parseable_packet(0x0844,2,clif_parse_cashshop_open_request,0);
 	packet(0x0849,16); //clif_cashshop_result
-	parseable_packet(0x0848,-1,clif_parse_cashshop_buy,2,6,4,10);
+	parseable_packet(HEADER_CZ_SE_PC_BUY_CASHITEM_LIST,-1,clif_parse_cashshop_buy,0);
 	parseable_packet(0x084a,2,clif_parse_cashshop_close,0);
 	parseable_packet(0x08c9,2,clif_parse_cashshop_list_request,0);
 #endif
@@ -1981,7 +1900,6 @@
 	parseable_packet(0x044A,6,clif_parse_client_version,2);
 	parseable_packet(0x0844,2,clif_parse_cashshop_open_request,0);
 	packet(0x0849,16); //clif_cashshop_result
-	parseable_packet(0x0848,-1,clif_parse_cashshop_buy,2,6,4,10);
 	parseable_packet(0x084a,2,clif_parse_cashshop_close,0);
 	packet(0x084b,19); //fallitem4
 	parseable_packet(0x085a,90,clif_parse_UseSkillToPosMoreInfo,2,4,6,8,10);
@@ -1999,7 +1917,6 @@
 	parseable_packet(0x089b,10,clif_parse_UseSkillToId,2,4,6);
 	parseable_packet(0x08ac,8,clif_parse_MoveToKafra,2,4);
 	parseable_packet(0x08c9,2,clif_parse_cashshop_list_request,0);
-	packet(0x08cf,10); //Amulet spirits
 	packet(0x08d2,10);
 	parseable_packet(0x0922,-1,clif_parse_ReqTradeBuyingStore,2,4,8,12);
 	//parseable_packet(0x092e,2,clif_parse_SearchStoreInfoNextPage,0);
@@ -2031,7 +1948,6 @@
 
 // 2013-07-10Ragexe
 #if PACKETVER >= 20130710
-	parseable_packet(0x0848,-1,clif_parse_cashshop_buy,2,6,4,10);
 	packet(0x097D,288); //ZC_ACK_RANKING
 	packet(0x097E,12); //ZC_UPDATE_RANKING_POINT
 #endif
@@ -2097,7 +2013,6 @@
 	packet(0x09DB,-1); // ZC_NOTIFY_MOVEENTRY10
 	packet(0x09DC,-1); // ZC_NOTIFY_NEWENTRY10
 	packet(0x09DD,-1); // ZC_NOTIFY_STANDENTRY10
-	packet(0x09DF,7); // ZC_ACK_WHISPER02
 #endif
 
 // 2014-02-05bRagexeRE
@@ -2113,14 +2028,12 @@
 
 // 2014-10-16Ragexe
 #if PACKETVER >= 20141016
-	packet(0x09DF,7);
 	// New packet
 	packet(0x0A00,269); // ZC_SHORTCUT_KEY_LIST_V3
 	parseable_packet(0x0A01,3,clif_parse_HotkeyRowShift,2); // CZ_SHORTCUTKEYBAR_ROTATE
 	packet(0x0A02,4); // ZC_DRESSROOM_OPEN
 	packet(0x0A0E,14); // ZC_BATTLEFIELD_NOTIFY_HP2
 	packet(0x09F7,75); // ZC_PROPERTY_HOMUN_2
-	packet(0x09E5,18); // ZC_DELETEITEM_FROM_MCSTORE2
 	packet(0x09E6,22); // ZC_UPDATE_ITEM_FROM_BUYING_STORE2
 	// Roulette System [Yommy]
 	parseable_packet(0x0A19,2,clif_parse_roulette_open,0); // CZ_REQ_OPEN_ROULETTE
@@ -2140,9 +2053,6 @@
 	packet(0x006d,149);
 	packet(0x08e3,149);
 	// New Packet
-	packet(0x0A18,14); // ZC_ACCEPT_ENTER3
-	packet(0x0A27,8);
-	packet(0x0A28,3); // ZC_ACK_OPENSTORE2
 	packet(0x09FD,-1); // ZC_NOTIFY_MOVEENTRY11
 	packet(0x09FE,-1); // ZC_NOTIFY_NEWENTRY11
 	packet(0x09FF,-1); // ZC_NOTIFY_STANDENTRY11
@@ -2278,11 +2188,6 @@
 	packet(0x0A9D,4);
 #endif
 
-// 2017-03-15cRagexeRE
-#if PACKETVER >= 20170315
-	packet(0xac7,156);
-#endif
-
 // 2017-04-19bRagexeRE
 #if PACKETVER >= 20170419
 	parseable_packet(0x0AC0,26,clif_parse_Mail_refreshinbox,2,10);
@@ -2304,7 +2209,6 @@
 
 // 2017-08-30bRagexeRE
 #if PACKETVER >= 20170830
-	packet(0x0ACB,12);
 	packet(0x0ACC,18);
 #endif
 
@@ -2379,7 +2283,7 @@
 #endif
 
 #if PACKETVER >= 20190724
-	parseable_packet(HEADER_CZ_GUILD_EMBLEM_CHANGE2, sizeof( PACKET_CZ_GUILD_EMBLEM_CHANGE2 ), clif_parse_GuildChangeEmblem2, 0 );
+	parseable_packet(HEADER_CZ_REQ_ADD_NEW_EMBLEM, sizeof( PACKET_CZ_REQ_ADD_NEW_EMBLEM ), clif_parse_GuildChangeEmblem2, 0 );
 	packet(HEADER_ZC_CHANGE_GUILD, sizeof(PACKET_ZC_CHANGE_GUILD));
 #endif
 
@@ -2412,7 +2316,7 @@
 #endif
 
 #if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
-	parseable_packet( HEADER_CZ_UNCONFIRMED_TSTATUS_UP, sizeof( PACKET_CZ_UNCONFIRMED_TSTATUS_UP ), clif_parse_traitstatus_up, 0 );
+	parseable_packet( HEADER_CZ_ADVANCED_STATUS_CHANGE, sizeof( PACKET_CZ_ADVANCED_STATUS_CHANGE ), clif_parse_traitstatus_up, 0 );
 	parseable_packet( HEADER_CZ_GRADE_ENCHANT_SELECT_EQUIPMENT, sizeof( struct PACKET_CZ_GRADE_ENCHANT_SELECT_EQUIPMENT ), clif_parse_enchantgrade_add, 0 );
 	parseable_packet( HEADER_CZ_GRADE_ENCHANT_REQUEST, sizeof( struct PACKET_CZ_GRADE_ENCHANT_REQUEST ), clif_parse_enchantgrade_start, 0 );
 	parseable_packet( HEADER_CZ_GRADE_ENCHANT_CLOSE_UI, sizeof( struct PACKET_CZ_GRADE_ENCHANT_CLOSE_UI ), clif_parse_enchantgrade_close, 0 );
@@ -2429,7 +2333,7 @@
 
 #if PACKETVER_RE_NUM >= 20211103 || PACKETVER_ZERO_NUM >= 20210818 || PACKETVER_MAIN_NUM >= 20220330
 	parseable_packet( HEADER_CZ_CHECKNAME2, sizeof( struct PACKET_CZ_CHECKNAME2 ), clif_parse_Mail_Receiver_Check, 0 );
-	parseable_packet( HEADER_CZ_UNCONFIRMED_RODEX_RETURN, sizeof( struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN ), clif_parse_Mail_return, 0 );
+	parseable_packet( HEADER_CZ_RODEX_RETURN, sizeof( struct PACKET_CZ_RODEX_RETURN ), clif_parse_Mail_return, 0 );
 	parseable_packet( HEADER_CZ_REQ_TAKEOFF_EQUIP_ALL, sizeof( struct PACKET_CZ_REQ_TAKEOFF_EQUIP_ALL ), clif_parse_unequipall, 0 );
 	parseable_packet( 0xb93, 12, clif_parse_dull, 0 );
 #endif

+ 4 - 4
src/map/guild.cpp

@@ -664,7 +664,7 @@ int guild_send_xy_timer_sub(const struct mmo_guild& g) {
 	for (int i = 0; i < g.max_member; i++) {
 		map_session_data* sd = g.member[i].sd;
 		if( sd != nullptr && sd->fd && (sd->guild_x != sd->bl.x || sd->guild_y != sd->bl.y) && !sd->bg_id ) {
-			clif_guild_xy(sd);
+			clif_guild_xy( *sd );
 			sd->guild_x = sd->bl.x;
 			sd->guild_y = sd->bl.y;
 		}
@@ -683,7 +683,7 @@ static TIMER_FUNC(guild_send_xy_timer){
 
 int guild_send_dot_remove(map_session_data *sd) {
 	if (sd->status.guild_id)
-		clif_guild_xy_remove(sd);
+		clif_guild_xy_remove( *sd );
 	return 0;
 }
 //------------------------------------------------------------------------
@@ -1360,8 +1360,8 @@ int guild_recv_memberinfoshort(int guild_id,uint32 account_id,uint32 char_id,int
 			g->guild.member[i].sd->bl.m != g->guild.member[idx].sd->bl.m)
 			continue;
 
-		clif_guild_xy_single(g->guild.member[idx].sd->fd, g->guild.member[i].sd);
-		clif_guild_xy_single(g->guild.member[i].sd->fd, g->guild.member[idx].sd);
+		clif_guild_xy_single( *g->guild.member[idx].sd, *g->guild.member[i].sd );
+		clif_guild_xy_single( *g->guild.member[i].sd, *g->guild.member[idx].sd );
 	}
 
 	return 0;

+ 23 - 19
src/map/homunculus.cpp

@@ -394,8 +394,7 @@ void hom_calc_skilltree(homun_data *hd) {
 
 	hom_calc_skilltree_sub(*hd, homun_current->skill_tree);
 
-	if (hd->master)
-		clif_homskillinfoblock(hd->master);
+	clif_homskillinfoblock( *hd );
 }
 
 /**
@@ -484,11 +483,14 @@ void hom_skillup(struct homun_data *hd, uint16 skill_id)
 		hd->homunculus.hskill[idx].lv++;
 		hd->homunculus.skillpts-- ;
 		status_calc_homunculus(hd, SCO_NONE);
+
+		clif_homskillup( *hd, skill_id );
+
 		if (hd->master) {
-			clif_homskillup(hd->master, skill_id);
 			clif_hominfo(hd->master,hd,0);
-			clif_homskillinfoblock(hd->master);
 		}
+
+		clif_homskillinfoblock( *hd );
 	}
 }
 
@@ -570,7 +572,7 @@ int hom_levelup(struct homun_data *hd)
 	// Needed to update skill list for mutated homunculus so unlocked skills will appear when the needed level is reached.
 	status_calc_homunculus(hd,SCO_NONE);
 	clif_hominfo(hd->master,hd,0);
-	clif_homskillinfoblock(hd->master);
+	clif_homskillinfoblock( *hd );
 
 	if ( hd->master && battle_config.homunculus_show_growth ) {
 		char output[256] ;
@@ -876,7 +878,7 @@ int hom_food(map_session_data *sd, struct homun_data *hd)
 	foodID = hd->homunculusDB->foodID;
 	i = pc_search_inventory(sd,foodID);
 	if (i < 0) {
-		clif_hom_food(sd,foodID,0);
+		clif_hom_food( *sd, foodID, 0 );
 		return 1;
 	}
 	pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME);
@@ -905,9 +907,9 @@ int hom_food(map_session_data *sd, struct homun_data *hd)
 	log_feeding(sd, LOG_FEED_HOMUNCULUS, foodID);
 
 	clif_emotion(&hd->bl,emotion);
-	clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger);
-	clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100);
-	clif_hom_food(sd,foodID,1);
+	clif_send_homdata( *hd, SP_HUNGRY );
+	clif_send_homdata( *hd, SP_INTIMATE );
+	clif_hom_food( *sd, foodID, 1 );
 
 	// Too much food :/
 	if(hd->homunculus.intimacy == 0)
@@ -955,10 +957,10 @@ static TIMER_FUNC(hom_hungry){
 		// Delete the homunculus if intimacy <= 100
 		if (!hom_decrease_intimacy(hd, 100))
 			return hom_delete(hd, ET_HUK);
-		clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100);
+		clif_send_homdata( *hd, SP_INTIMATE );
 	}
 
-	clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger);
+	clif_send_homdata( *hd, SP_HUNGRY );
 
 	int hunger_delay = (battle_config.homunculus_starving_rate > 0 && hd->homunculus.hunger <= battle_config.homunculus_starving_rate) ? battle_config.homunculus_starving_delay : hd->homunculusDB->hungryDelay; // Every 20 seconds if hunger <= 10
 
@@ -1132,10 +1134,10 @@ bool hom_call(map_session_data *sd)
 		if(map_addblock(&hd->bl))
 			return false;
 		clif_spawn(&hd->bl);
-		clif_send_homdata(sd,SP_ACK,0);
+		clif_send_homdata( *hd, SP_ACK );
 		clif_hominfo(sd,hd,1);
 		clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
-		clif_homskillinfoblock(sd);
+		clif_homskillinfoblock( *hd );
 		if (battle_config.hom_setting&HOMSET_COPY_SPEED)
 			status_calc_bl(&hd->bl, { SCB_SPEED });
 		hom_save(hd);
@@ -1196,10 +1198,10 @@ int hom_recv_data(uint32 account_id, struct s_homunculus *sh, int flag)
 		if(map_addblock(&hd->bl))
 			return 0;
 		clif_spawn(&hd->bl);
-		clif_send_homdata(sd,SP_ACK,0);
+		clif_send_homdata( *hd, SP_ACK );
 		clif_hominfo(sd,hd,1);
 		clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
-		clif_homskillinfoblock(sd);
+		clif_homskillinfoblock( *hd );
 		hom_init_timers(hd);
 
 #ifdef RENEWAL
@@ -1314,12 +1316,14 @@ void hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
 	hd->homunculus.hp = hd->battle_status.hp;
 	if (!sd)
 		return;
-	clif_send_homdata(sd,SP_ACK,0);
+	clif_send_homdata( *hd, SP_ACK );
 	clif_hominfo(sd,hd,1);
 	clif_hominfo(sd,hd,0);
-	clif_homskillinfoblock(sd);
-	if (hd->homunculus.class_ == 6052) //eleanor
+	clif_homskillinfoblock( *hd );
+
+	if( hd->homunculus.class_ == MER_ELEANOR ){
 		sc_start(&hd->bl,&hd->bl, SC_STYLE_CHANGE, 100, MH_MD_FIGHTING, INFINITE_TICK);
+	}
 }
 
 /**
@@ -1394,7 +1398,7 @@ int hom_shuffle(struct homun_data *hd)
 	hd->homunculus.exp = exp;
 	memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill));
 	hd->homunculus.skillpts = skillpts;
-	clif_homskillinfoblock(sd);
+	clif_homskillinfoblock( *hd );
 	status_calc_homunculus(hd, SCO_NONE);
 	status_percent_heal(&hd->bl, 100, 100);
 	clif_specialeffect(&hd->bl,EF_HO_UP,AREA);

+ 11 - 7
src/map/intif.cpp

@@ -320,7 +320,7 @@ int intif_wis_message(map_session_data *sd, char *nick, char *mes, size_t mes_le
 
 	if (other_mapserver_count < 1)
 	{	//Character not found.
-		clif_wis_end(sd->fd, 1);
+		clif_wis_end( *sd, ACKWHISPER_TARGET_OFFLINE );
 		return 0;
 	}
 
@@ -1323,13 +1323,17 @@ int intif_parse_WisMessage(int fd)
  */
 int intif_parse_WisEnd(int fd)
 {
-	map_session_data* sd;
-
 	if (battle_config.etc_log)
 		ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-	sd = (map_session_data *)map_nick2sd(RFIFOCP(fd,2),false);
-	if (sd != nullptr)
-		clif_wis_end(sd->fd, RFIFOB(fd,26));
+
+	map_session_data* sd = map_nick2sd( RFIFOCP( fd, 2 ), false );
+
+	if (sd != nullptr) {
+		uint8 result = RFIFOB( fd, 26 );
+
+		if ( result >= ACKWHISPER_SUCCESS && result <= ACKWHISPER_ALL_IGNORED )
+			clif_wis_end( *sd, static_cast<e_ack_whisper>(result) );
+	}
 
 	return 1;
 }
@@ -3518,7 +3522,7 @@ static bool intif_parse_StorageReceived(int fd)
 				clif_cartlist(sd);
 				// Only open the vending UI, if it has not been opened already
 				if (sd->state.pending_vending_ui) {
-					clif_openvendingreq(sd, sd->vend_skill_lv + 2);
+					clif_openvendingreq( *sd, sd->vend_skill_lv + 2 );
 					sd->state.pending_vending_ui = false;
 				}
 			}

+ 2 - 2
src/map/mail.cpp

@@ -143,7 +143,7 @@ bool mail_removezeny( map_session_data *sd, bool flag ){
 			}
 		}else{
 			// Update is called by pc_payzeny, so only call it in the else condition
-			clif_updatestatus(sd, SP_ZENY);
+			clif_updatestatus(*sd, SP_ZENY);
 		}
 	}
 
@@ -176,7 +176,7 @@ enum mail_attach_result mail_setitem(map_session_data *sd, short idx, uint32 amo
 #endif
 
 		sd->mail.zeny = amount;
-		// clif_updatestatus(sd, SP_ZENY);
+		// clif_updatestatus(*sd, SP_ZENY);
 		return MAIL_ATTACH_SUCCESS;
 	} else { // Item Transfer
 		int i;

+ 21 - 18
src/map/map.cpp

@@ -2159,7 +2159,7 @@ TIMER_FUNC(map_clearflooritem_timer){
 	if (pet_db_search(fitem->item.nameid, PET_EGG))
 		intif_delete_petdata(MakeDWord(fitem->item.card[1], fitem->item.card[2]));
 
-	clif_clearflooritem(fitem, 0);
+	clif_clearflooritem( *fitem );
 	map_deliddb(&fitem->bl);
 	map_delblock(&fitem->bl);
 	map_freeblock(&fitem->bl);
@@ -2175,7 +2175,7 @@ void map_clearflooritem(struct block_list *bl) {
 	if( fitem->cleartimer != INVALID_TIMER )
 		delete_timer(fitem->cleartimer,map_clearflooritem_timer);
 
-	clif_clearflooritem(fitem, 0);
+	clif_clearflooritem( *fitem );
 	map_deliddb(&fitem->bl);
 	map_delblock(&fitem->bl);
 	map_freeblock(&fitem->bl);
@@ -2236,9 +2236,9 @@ static int map_count_sub(struct block_list *bl,va_list ap)
  * &2 = the target should be able to walk to the target tile.
  * &4 = there shouldn't be any players around the target tile (use the no_spawn_on_player setting)
  *------------------------------------------*/
-int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int16 rx, int16 ry, int flag)
+int map_search_freecell(struct block_list *src, int16 m, int16 *x, int16 *y, int16 rx, int16 ry, int flag, int32 tries)
 {
-	int tries, spawn=0;
+	int spawn=0;
 	int bx, by;
 
 	if( !src && (!(flag&1) || flag&2) )
@@ -2268,21 +2268,23 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
 		return 0;
 	}
 
-	if (rx >= 0 && ry >= 0) {
-		tries = (rx * 2 + 1) * (ry * 2 + 1);
-		if (tries > 100) tries = 100;
-	} else {
-		tries = mapdata->xs*mapdata->ys;
-		if (tries > 500) tries = 500;
-	}
-
+	int16 edge = battle_config.map_edge_size;
+	int16 edge_valid = std::min(edge, (int16)5);
+	// In most situations there are 50 tries officially (default value)
 	while(tries--) {
-		*x = (rx >= 0) ? rnd_value(bx - rx, bx + rx) : rnd_value<int16>(1, mapdata->xs - 1);
-		*y = (ry >= 0) ? rnd_value(by - ry, by + ry) : rnd_value<int16>(1, mapdata->ys - 1);
+		// For map-wide search, the configured tiles from the edge are not considered (default: 15)
+		*x = (rx >= 0) ? rnd_value(bx - rx, bx + rx) : rnd_value<int16>(edge, mapdata->xs - edge - 1);
+		*y = (ry >= 0) ? rnd_value(by - ry, by + ry) : rnd_value<int16>(edge, mapdata->ys - edge - 1);
 
 		if (*x == bx && *y == by)
 			continue; //Avoid picking the same target tile.
 
+		// Cells outside the map or within 4-5 cells of the map edge are considered invalid officially
+		// Note that unlike the other edge, this isn't symmetric (NE - 4 cells, SW - 5 cells)
+		// If for some reason edge size was set to below 5 cells, we consider them as valid
+		if (*x < edge_valid || *x > mapdata->xs - edge_valid || *y < edge_valid || *y > mapdata->ys - edge_valid)
+			continue;
+
 		if (map_getcell(m,*x,*y,CELL_CHKREACH))
 		{
 			if(flag&2 && !unit_can_reach_pos(src, *x, *y, 1))
@@ -2291,10 +2293,11 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
 				if (spawn >= 100) return 0; //Limit of retries reached.
 				if (spawn++ < battle_config.no_spawn_on_player &&
 					map_foreachinallarea(map_count_sub, m,
-						*x-AREA_SIZE, *y-AREA_SIZE,
-					  	*x+AREA_SIZE, *y+AREA_SIZE, BL_PC)
-				)
-				continue;
+						*x - AREA_SIZE, *y - AREA_SIZE,
+						*x + AREA_SIZE, *y + AREA_SIZE, BL_PC)) {
+					tries++; // This failure should not affect the number of official tries
+					continue;
+				}
 			}
 			return 1;
 		}

+ 1 - 1
src/map/map.hpp

@@ -1181,7 +1181,7 @@ int map_count_oncell(int16 m,int16 x,int16 y,int type,int flag);
 struct skill_unit *map_find_skill_unit_oncell(struct block_list *,int16 x,int16 y,uint16 skill_id,struct skill_unit *, int flag);
 // search and creation
 int map_get_new_object_id(void);
-int map_search_freecell(struct block_list *src, int16 m, int16 *x, int16 *y, int16 rx, int16 ry, int flag);
+int map_search_freecell(struct block_list *src, int16 m, int16 *x, int16 *y, int16 rx, int16 ry, int flag, int32 tries = 50);
 bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag);
 //
 int map_quit(map_session_data *);

+ 10 - 3
src/map/mercenary.cpp

@@ -286,11 +286,18 @@ int mercenary_delete(s_mercenary_data *md, int reply) {
 
 	switch( reply )
 	{
-		case 0: mercenary_set_faith(md, 1); break; // +1 Loyalty on Contract ends.
-		case 1: mercenary_set_faith(md, -1); break; // -1 Loyalty on Mercenary killed
+		case 0:
+			// +1 Loyalty on Contract ends.
+			mercenary_set_faith(md, 1);
+			clif_msg(sd, MSI_MER_FINISH);
+			break; 
+		case 1:
+			// -1 Loyalty on Mercenary killed
+			mercenary_set_faith(md, -1);
+			clif_msg(sd, MSI_MER_DIE);
+			break; 
 	}
 
-	clif_mercenary_message(sd, reply);
 	return unit_remove_map(&md->bl, CLR_OUTSIGHT);
 }
 

+ 139 - 53
src/map/mob.cpp

@@ -45,8 +45,6 @@ using namespace rathena;
 
 #define ACTIVE_AI_RANGE 2	//Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode.
 
-#define IDLE_SKILL_INTERVAL 10	//Active idle skills should be triggered every 1 second (1000/MIN_MOBTHINKTIME)
-
 const t_tick MOB_MAX_DELAY = 24 * 3600 * 1000;
 #define RUDE_ATTACKED_COUNT 1	//After how many rude-attacks should the skill be used?
 
@@ -239,7 +237,7 @@ void mvptomb_destroy(struct mob_data *md) {
 		int i;
 		struct map_data *mapdata = map_getmapdata(nd->bl.m);
 
-		clif_clearunit_area(&nd->bl,CLR_OUTSIGHT);
+		clif_clearunit_area( nd->bl, CLR_OUTSIGHT );
 		map_delblock(&nd->bl);
 
 		ARR_FIND( 0, mapdata->npc_num, i, mapdata->npc[i] == nd );
@@ -476,6 +474,8 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data)
 	md->spawn_timer = INVALID_TIMER;
 	md->deletetimer = INVALID_TIMER;
 	md->skill_idx = -1;
+	md->centerX = data->x;
+	md->centerY = data->y;
 	status_set_viewdata(&md->bl, md->mob_id);
 	status_change_init(&md->bl);
 	unit_dataset(&md->bl);
@@ -1086,11 +1086,12 @@ int mob_setdelayspawn(struct mob_data *md)
 int mob_count_sub(struct block_list *bl, va_list ap) {
     int mobid[10], i;
     ARR_FIND(0, 10, i, (mobid[i] = va_arg(ap, int)) == 0); //fetch till 0
-    if (mobid[0]) { //if there one let's check it otherwise go backward
-        TBL_MOB *md = BL_CAST(BL_MOB, bl);
+	mob_data* md = BL_CAST(BL_MOB, bl);
+	if (md && mobid[0]) { //if there one let's check it otherwise go backward
         ARR_FIND(0, 10, i, md->mob_id == mobid[i]);
         return (i < 10) ? 1 : 0;
     }
+	// If not counting monsters, count all
     return 1; //backward compatibility
 }
 
@@ -1118,20 +1119,33 @@ int mob_spawn (struct mob_data *md)
 
 	if (md->spawn) { //Respawn data
 		md->bl.m = md->spawn->m;
-		md->bl.x = md->spawn->x;
-		md->bl.y = md->spawn->y;
-
-		if( (md->bl.x == 0 && md->bl.y == 0) || md->spawn->xs || md->spawn->ys )
-		{	//Monster can be spawned on an area.
-			if( !map_search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, md->spawn->xs, md->spawn->ys, battle_config.no_spawn_on_player?4:0) )
-			{ // retry again later
-				if( md->spawn_timer != INVALID_TIMER )
-					delete_timer(md->spawn_timer, mob_delayspawn);
-				md->spawn_timer = add_timer(tick + battle_config.mob_respawn_time,mob_delayspawn,md->bl.id,0);
-				return 1;
+		md->bl.x = md->centerX;
+		md->bl.y = md->centerY;
+
+		// Search can be skipped for boss monster spawns if spawn location is fixed
+		// We can't skip normal monsters as they should pick a random location if the cell is blocked (e.g. Icewall)
+		// The center cell has a 1/(xs*ys) chance to be picked if free
+		if ((!md->spawn->state.boss || (md->bl.x == 0 && md->bl.y == 0) || md->spawn->xs != 1 || md->spawn->ys != 1)
+			&& (md->spawn->xs + md->spawn->ys < 1 || !rnd_chance(1, md->spawn->xs * md->spawn->ys) || !map_getcell(md->bl.m, md->bl.x, md->bl.y, CELL_CHKREACH)))
+		{
+			// Officially the area is split into 4 squares, 4 lines and 1 dot and for each of those there is one attempt
+			// We simplify this to trying 8 times in the whole area and then at the center cell even though that's not fully accurate
+
+			// Try to spawn monster in defined area (8 tries)
+			if (!map_search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, md->spawn->xs-1, md->spawn->ys-1, battle_config.no_spawn_on_player?4:0, 8))
+			{
+				// If area search failed and center cell not reachable, try to spawn the monster anywhere on the map (50 tries)
+				if (!map_getcell(md->bl.m, md->bl.x, md->bl.y, CELL_CHKREACH) && !map_search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, -1, -1, battle_config.no_spawn_on_player?4:0))
+				{
+					// Retry again later
+					if (md->spawn_timer != INVALID_TIMER)
+						delete_timer(md->spawn_timer, mob_delayspawn);
+					md->spawn_timer = add_timer(tick + battle_config.mob_respawn_time, mob_delayspawn, md->bl.id, 0);
+					return 1;
+				}
 			}
 		}
-		else if( battle_config.no_spawn_on_player > 99 && map_foreachinallrange(mob_count_sub, &md->bl, AREA_SIZE, BL_PC) )
+		if( battle_config.no_spawn_on_player > 99 && map_foreachinallrange(mob_count_sub, &md->bl, AREA_SIZE, BL_PC) )
 		{ // retry again later (players on sight)
 			if( md->spawn_timer != INVALID_TIMER )
 				delete_timer(md->spawn_timer, mob_delayspawn);
@@ -1165,6 +1179,7 @@ int mob_spawn (struct mob_data *md)
 	md->dmgtick = tick - 5000;
 	md->last_pcneartime = 0;
 	md->last_canmove = tick;
+	md->last_skillcheck = 0;
 
 	t_tick c = tick - MOB_MAX_DELAY;
 
@@ -1445,8 +1460,17 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,t_tick tick)
 			}
 		}
 
-		if(md->target_id) //Slave is busy with a target.
-			return 0;
+		// Slave is busy with a target.
+		if(md->target_id) {
+			// Player's slave should come back when master's too far, even if it is doing with a target.
+			if (bl->type == BL_PC && md->master_dist > 5) {
+				mob_unlocktarget(md, tick);
+				unit_walktobl(&md->bl, bl, MOB_SLAVEDISTANCE, 1);
+				return 1;
+			} else {
+				return 0;
+			}
+		}
 
 		// Approach master if within view range, chase back to Master's area also if standing on top of the master.
 		if ((md->master_dist > MOB_SLAVEDISTANCE || md->master_dist == 0) && unit_can_move(&md->bl)) {
@@ -1522,14 +1546,17 @@ int mob_unlocktarget(struct mob_data *md, t_tick tick)
 			break;
 		}
 		// Idle skill.
-		if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mobskill_use(md, tick, -1))
+		if (DIFF_TICK(tick, md->last_skillcheck) >= MOB_SKILL_INTERVAL && mobskill_use(md, tick, -1))
 			break;
 		//Random walk.
 		if (!md->master_id &&
 			DIFF_TICK(md->next_walktime, tick) <= 0 &&
 			!mob_randomwalk(md,tick))
 			//Delay next random walk when this one failed.
-			md->next_walktime = tick+rnd()%1000;
+			if (md->next_walktime < md->ud.canmove_tick)
+				md->next_walktime = md->ud.canmove_tick;
+			else
+				md->next_walktime = tick+rnd()%1000;
 		break;
 	default:
 		mob_stop_attack(md);
@@ -1563,8 +1590,7 @@ int mob_unlocktarget(struct mob_data *md, t_tick tick)
 int mob_randomwalk(struct mob_data *md,t_tick tick)
 {
 	const int d=7;
-	int i,c,r,rdir,dx,dy,max;
-	int speed;
+	int i,r,rdir,dx,dy,max;
 
 	nullpo_ret(md);
 
@@ -1648,16 +1674,9 @@ int mob_randomwalk(struct mob_data *md,t_tick tick)
 		}
 		return 0;
 	}
-	speed=status_get_speed(&md->bl);
-	for(i=c=0;i<md->ud.walkpath.path_len;i++){	// The next walk start time is calculated.
-		if( direction_diagonal( md->ud.walkpath.path[i] ) )
-			c+=speed*MOVE_DIAGONAL_COST/MOVE_COST;
-		else
-			c+=speed;
-	}
 	md->state.skillstate=MSS_WALK;
 	md->move_fail_count=0;
-	md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME+c;
+	md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME + unit_get_walkpath_time(md->bl);
 	return 1;
 }
 
@@ -1917,8 +1936,23 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 		return true;
 	}
 
-	//Attempt to attack.
-	//At this point we know the target is attackable, we just gotta check if the range matches.
+	// At this point we know the target is attackable, attempt to attack
+
+	// Monsters in angry state, after having used a normal attack, will always attempt a skill
+	if (md->ud.walktimer == INVALID_TIMER && md->state.skillstate == MSS_ANGRY && md->ud.skill_id == 0)
+	{
+		// Only use skill if able to walk on next tick and not attempted a skill the last second
+		if (DIFF_TICK(md->ud.canmove_tick, tick) <= MIN_MOBTHINKTIME && DIFF_TICK(tick, md->last_skillcheck) >= MOB_SKILL_INTERVAL){
+			if (mobskill_use(md, tick, -1)) {
+				// After the monster used an angry skill, it will not attack for aDelay
+				// Setting the delay here because not all monster skill use situations will cause an attack delay
+				md->ud.attackabletime = tick + md->status.adelay;
+				return true;
+			}
+		}
+	}
+
+	// Normal attack / berserk skill is only used when target is in range
 	if (battle_check_range(&md->bl, tbl, md->status.rhw.range) && !(md->sc.option&OPTION_HIDE))
 	{	//Target within range and able to use normal attack, engage
 		if (md->ud.target != tbl->id || md->ud.attacktimer == INVALID_TIMER) 
@@ -1940,16 +1974,6 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 		return true;
 	}
 
-	//Monsters in berserk state, unable to use normal attacks, will always attempt a skill
-	if(md->ud.walktimer == INVALID_TIMER && (md->state.skillstate == MSS_BERSERK || md->state.skillstate == MSS_ANGRY)) 
-	{
-		if (DIFF_TICK(md->ud.canmove_tick, tick) <= MIN_MOBTHINKTIME && DIFF_TICK(md->ud.canact_tick, tick) < -MIN_MOBTHINKTIME*IDLE_SKILL_INTERVAL) 
-		{ //Only use skill if able to walk on next tick and not used a skill the last second
-			if (mobskill_use(md, tick, -1))
-				return true;
-		}
-	}
-
 	//Target still in attack range, no need to chase the target
 	if(battle_check_range(&md->bl, tbl, md->status.rhw.range))
 		return true;
@@ -1971,7 +1995,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 			else {
 				// Use idle skill but keep target for now
 				md->state.skillstate = MSS_IDLE;
-				if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
+				if (DIFF_TICK(tick, md->last_skillcheck) >= MOB_SKILL_INTERVAL)
 					mobskill_use(md, tick, -1);
 			}
 		}
@@ -1986,10 +2010,24 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 		return true;
 
 	//Follow up if possible.
-	//Hint: Chase skills are handled in the walktobl routine
-	if(!mob_can_reach(md, tbl, md->min_chase) ||
-		!unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2))
-		mob_unlocktarget(md,tick);
+	if (!mob_can_reach(md, tbl, md->min_chase)) {
+		mob_unlocktarget(md, tick);
+		return true;
+	}
+	// Monsters can use chase skills before starting to walk
+	// So we need to change the state and check for a skill here already
+	// But only use skill if able to walk on next tick and not attempted a skill the last second
+	// Skills during movement are handled in the walktobl routine
+	if (md->ud.walktimer == INVALID_TIMER
+		&& DIFF_TICK(md->ud.canmove_tick, tick) <= MIN_MOBTHINKTIME
+		&& DIFF_TICK(tick, md->last_skillcheck) >= MOB_SKILL_INTERVAL) {
+		md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH;
+		if (mobskill_use(md, tick, -1))
+			return true;
+	}
+
+	if(!unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2))
+		mob_unlocktarget(md, tick);
 
 	return true;
 }
@@ -2063,12 +2101,19 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args)
 	//Clean the spotted log
 	mob_clean_spotted(md);
 
-	if(DIFF_TICK(tick,md->last_thinktime)< 10*MIN_MOBTHINKTIME)
+	if(DIFF_TICK(tick,md->last_thinktime) < MOB_SKILL_INTERVAL)
 		return 0;
 
 	md->last_thinktime=tick;
 
 	if (md->master_id) {
+		if (!mob_is_spotted(md)) {
+			// Get mob data of master
+			mob_data* mmd = map_id2md(md->master_id);
+			// If neither master nor slave have been spotted we don't have to execute the slave AI
+			if (mmd && !mob_is_spotted(mmd))
+				return 0;
+		}
 		mob_ai_sub_hard_slavemob (md,tick);
 		return 0;
 	}
@@ -3171,7 +3216,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 
 		if( pcdb_checkid(md->vd->class_) ) {//Player mobs are not removed automatically by the client.
 			/* first we set them dead, then we delay the outsight effect */
-			clif_clearunit_area(&md->bl,CLR_DEAD);
+			clif_clearunit_area( md->bl, CLR_DEAD );
 			clif_clearunit_delayed(&md->bl, CLR_OUTSIGHT,tick+3000);
 		} else
 			/**
@@ -3496,6 +3541,33 @@ int mob_countslave(struct block_list *bl)
 	return map_foreachinmap(mob_countslave_sub, bl->m, BL_MOB,bl->id);
 }
 
+/**
+ * Remove slaves if master logs off.
+ * @param bl: Mob data
+ * @param ap: List of arguments
+ * @return 1 on removal, otherwise 0
+ */
+int mob_removeslaves_sub(block_list *bl, va_list ap) {
+	int id = va_arg(ap, int);
+	mob_data *md = (mob_data *)bl;
+
+	if (md != nullptr && md->master_id == id) {
+		unit_free(bl, CLR_OUTSIGHT);
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * Remove slaves on a map.
+ * @param bl: Player data
+ * @return 1 on removal, otherwise 0
+ */
+int mob_removeslaves(block_list *bl) {
+	return map_foreachinmap(mob_removeslaves_sub, bl->m, BL_MOB, bl->id);
+}
+
 /*==========================================
  * Summons amount slaves contained in the value[5] array using round-robin. [adapted by Skotlex]
  *------------------------------------------*/
@@ -3759,8 +3831,9 @@ int mobskill_use(struct mob_data *md, t_tick tick, int event, int64 damage)
 	if (!battle_config.mob_skill_rate || md->ud.skilltimer != INVALID_TIMER || ms.empty() || status_has_mode(&md->status,MD_NOCAST))
 		return 0;
 
-	if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0)
-		return 0; //Skill act delay only affects non-event skills.
+	// Monsters check their non-attack-state skills once per second, but we ignore this for events for now
+	if (event == -1)
+		md->last_skillcheck = tick;
 
 	//Pick a starting position and loop from that.
 	i = battle_config.mob_ai&0x100?rnd()%ms.size():0;
@@ -4395,6 +4468,7 @@ s_mob_db::s_mob_db()
 	status.speed = DEFAULT_WALK_SPEED;
 	status.adelay = cap_value(0, battle_config.monster_max_aspd * 2, 4000);
 	status.amotion = cap_value(0, battle_config.monster_max_aspd, 2000);
+	status.clientamotion = cap_value(status.amotion, 1, USHRT_MAX);
 	status.mode = static_cast<e_mode>(MONSTER_TYPE_06);
 
 	vd.class_ = id;
@@ -4818,6 +4892,18 @@ uint64 MobDatabase::parseBodyNode(const ryml::NodeRef& node) {
 		mob->status.amotion = cap_value(speed, battle_config.monster_max_aspd, 2000);
 	}
 
+	if (this->nodeExists(node, "ClientAttackMotion")) {
+		uint16 speed;
+
+		if (!this->asUInt16(node, "ClientAttackMotion", speed))
+			return 0;
+
+		mob->status.clientamotion = cap_value(speed, 1, USHRT_MAX);
+	} else {
+		if (!exists)
+			mob->status.clientamotion = cap_value(mob->status.amotion, 1, USHRT_MAX);
+	}
+
 	if (this->nodeExists(node, "DamageMotion")) {
 		uint16 speed;
 
@@ -6695,7 +6781,7 @@ static int mob_reload_sub( struct mob_data *md, va_list args ){
 		// If they are spawned right now
 		if( md->bl.prev != nullptr ){
 			// Respawn all mobs on client side so that they are displayed correctly(if their view id changed)
-			clif_clearunit_area(&md->bl, CLR_OUTSIGHT);
+			clif_clearunit_area( md->bl, CLR_OUTSIGHT );
 			clif_spawn(&md->bl);
 		}
 	}

+ 7 - 2
src/map/mob.hpp

@@ -38,6 +38,9 @@ const t_tick MIN_MOBLINKTIME = 1000;
 //Min time between random walks
 const t_tick MIN_RANDOMWALKTIME = 4000;
 
+// How often a monster will check for using a skill on non-attack states (in ms)
+const t_tick MOB_SKILL_INTERVAL = 1000;
+
 //Distance that slaves should keep from their master.
 #define MOB_SLAVEDISTANCE 2
 
@@ -277,7 +280,7 @@ private:
 	bool parseDropNode(std::string nodeName, const ryml::NodeRef& node, uint8 max, s_mob_drop *drops);
 
 public:
-	MobDatabase() : TypesafeCachedYamlDatabase("MOB_DB", 3, 1) {
+	MobDatabase() : TypesafeCachedYamlDatabase("MOB_DB", 4, 1) {
 
 	}
 
@@ -351,6 +354,7 @@ struct mob_data {
 	uint32 spotted_log[DAMAGELOG_SIZE];
 	struct spawn_data *spawn; //Spawn data.
 	int spawn_timer; //Required for Convex Mirror
+	int16 centerX, centerY; // Spawn center of this individual monster
 	struct s_mob_lootitem *lootitems;
 	short mob_id;
 	unsigned int tdmg; //Stores total damage given to the mob, for exp calculations. [Skotlex]
@@ -359,7 +363,7 @@ struct mob_data {
 	int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
 	int bg_id; // BattleGround System
 
-	t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick,last_canmove;
+	t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick,last_canmove,last_skillcheck;
 	short move_fail_count;
 	short lootitem_count;
 	short min_chase;
@@ -536,6 +540,7 @@ int mobskill_event(struct mob_data *md,struct block_list *src,t_tick tick, int f
 int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id);
 int mob_countslave(struct block_list *bl);
 int mob_count_sub(struct block_list *bl, va_list ap);
+int mob_removeslaves(block_list* bl);
 
 int mob_is_clone(int mob_id);
 

+ 38 - 23
src/map/npc.cpp

@@ -1026,7 +1026,7 @@ bool npc_enable_target(npc_data& nd, uint32 char_id, e_npcv_status flag)
 			clif_changeoption_target(&nd.bl, &sd->bl);
 		else {
 			if (nd.sc.option&(OPTION_HIDE|OPTION_CLOAK))
-				clif_clearunit_single(nd.bl.id, CLR_OUTSIGHT, sd->fd);
+				clif_clearunit_single( nd.bl.id, CLR_OUTSIGHT, *sd );
 			else
 				clif_spawn(&nd.bl);
 		}
@@ -1053,11 +1053,11 @@ bool npc_enable_target(npc_data& nd, uint32 char_id, e_npcv_status flag)
 		if (nd.class_ != JT_WARPNPC && nd.class_ != JT_GUILD_FLAG) {	//Client won't display option changes for these classes [Toms]
 			clif_changeoption(&nd.bl);
 			if (nd.is_invisible)
-				clif_clearunit_area(&nd.bl,CLR_OUTSIGHT);  // Hack to trick maya purple card [Xazax]
+				clif_clearunit_area( nd.bl, CLR_OUTSIGHT );  // Hack to trick maya purple card [Xazax]
 		}
 		else {
 			if (nd.sc.option&(OPTION_HIDE|OPTION_CLOAK))
-				clif_clearunit_area(&nd.bl,CLR_OUTSIGHT);
+				clif_clearunit_area( nd.bl, CLR_OUTSIGHT );
 			else
 				clif_spawn(&nd.bl);
 		}
@@ -1146,7 +1146,7 @@ int npc_event_dequeue(map_session_data* sd,bool free_script_stack)
 	if(sd->npc_id)
 	{	//Current script is aborted.
 		if(sd->state.using_fake_npc){
-			clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
+			clif_clearunit_single( sd->npc_id, CLR_OUTSIGHT, *sd );
 			sd->state.using_fake_npc = 0;
 		}
 		if (free_script_stack&&sd->st) {
@@ -2141,7 +2141,7 @@ int npc_globalmessage(const char* name, const char* mes)
 		return 0;
 
 	snprintf(temp, sizeof(temp), "%s", mes);
-	clif_GlobalMessage(&nd->bl,temp,ALL_CLIENT);
+	clif_GlobalMessage( nd->bl, temp, ALL_CLIENT );
 
 	return 0;
 }
@@ -2168,7 +2168,7 @@ void run_tomb(map_session_data* sd, struct npc_data* nd)
 	snprintf( buffer, sizeof( buffer ), msg_txt( sd, 661 ), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : "Unknown" ); // [^EE0000%s^000000]
 	clif_scriptmes( *sd, nd->bl.id, buffer );
 
-	clif_scriptclose(sd, nd->bl.id);
+	clif_scriptclose( *sd, nd->bl.id );
 }
 
 /*==========================================
@@ -2196,7 +2196,7 @@ int npc_click(map_session_data* sd, struct npc_data* nd)
 	}
 
 	if (sd->state.block_action & PCBLOCK_NPCCLICK) {
-		clif_msg(sd, WORK_IN_PROGRESS);
+		clif_msg(sd, MSI_BUSY);
 		return 1;
 	}
 
@@ -2206,12 +2206,12 @@ int npc_click(map_session_data* sd, struct npc_data* nd)
 
 	switch(nd->subtype) {
 		case NPCTYPE_SHOP:
-			clif_npcbuysell(sd,nd->bl.id);
+			clif_npcbuysell( *sd, *nd );
 			break;
 		case NPCTYPE_CASHSHOP:
 		case NPCTYPE_ITEMSHOP:
 		case NPCTYPE_POINTSHOP:
-			clif_cashshop_show(sd,nd);
+			clif_cashshop_show( *sd, *nd );
 			break;
 		case NPCTYPE_MARKETSHOP:
 #if PACKETVER >= 20131223
@@ -2306,7 +2306,7 @@ bool npc_scriptcont(map_session_data* sd, int id, bool closing){
 			case CLOSE:
 				sd->st->state = END;
 				if (sd->st->clear_cutin)
-					clif_cutin(sd,"",255);
+					clif_cutin( *sd, "", 255 );
 				break;
 			// close2
 			case STOP:
@@ -2375,10 +2375,11 @@ int npc_buysellsel(map_session_data* sd, int id, int type)
 	sd->npc_shopid = id;
 
 	if (type == 0) {
-		clif_buylist(sd,nd);
+		clif_buylist( *sd, *nd );
 	} else {
-		clif_selllist(sd);
+		clif_selllist( *sd );
 	}
+
 	return 0;
 }
 
@@ -3381,7 +3382,7 @@ int npc_remove_map(struct npc_data* nd)
 
 	if (nd->subtype == NPCTYPE_SCRIPT)
 		skill_clear_unitgroup(&nd->bl);
-	clif_clearunit_area(&nd->bl,CLR_RESPAWN);
+	clif_clearunit_area( nd->bl, CLR_RESPAWN );
 	npc_unsetcells(nd);
 	map_delblock(&nd->bl);
 	//Remove npc from map[].npc list. [Skotlex]
@@ -5179,6 +5180,13 @@ void npc_parse_mob2(struct spawn_data* mob)
 	{
 		struct mob_data* md = mob_spawn_dataset(mob);
 		md->spawn = mob;
+		// Determine center cell for each mob in the spawn line
+		if (battle_config.randomize_center_cell) {
+			if (mob->xs > 1)
+				md->centerX = rnd_value(mob->x - mob->xs + 1, mob->x + mob->xs - 1);
+			if (mob->ys > 1)
+				md->centerY = rnd_value(mob->y - mob->ys + 1, mob->y + mob->ys - 1);
+		}
 		md->spawn->active++;
 		mob_spawn(md);
 	}
@@ -5187,7 +5195,7 @@ void npc_parse_mob2(struct spawn_data* mob)
 static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
 {
 	int num, mob_id, mob_lv = -1, delay = 5000, size = -1, w1count, w4count;
-	short m, x = 0, y = 0, xs = -1, ys = -1;
+	short m, x = 0, y = 0, xs = 0, ys = 0;
 	char mapname[MAP_NAME_LENGTH_EXT], mobname[NAME_LENGTH], sprite[NAME_LENGTH];
 	struct spawn_data mob, *data;
 	int ai = AI_NONE; // mob_ai
@@ -5196,7 +5204,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
 
 	mob.state.boss = !strcmpi(w2,"boss_monster");
 
-	// w1=<map name>{,<x>,<y>,<xs>{,<ys>}}
+	// w1=<map name>{,<x>,<y>{,<xs>,<ys>}}
 	// w3=<mob name>{,<mob level>}
 	// w4=<mob id>,<amount>{,<delay1>{,<delay2>{,<event>{,<mob size>{,<mob ai>}}}}}
 	if( ( w1count = sscanf(w1, "%15[^,],%6hd,%6hd,%6hd,%6hd", mapname, &x, &y, &xs, &ys) ) < 1
@@ -5288,28 +5296,35 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
 		mob.state.ai = static_cast<enum mob_ai>(ai);
 
 	if (mob.xs < 0) {
-		if (w1count > 3) {
-			ShowWarning("npc_parse_mob: Negative x-span %hd for mob ID %d (file '%s', line '%d').\n", mob.xs, mob_id, filepath, strline(buffer, start - buffer));
-		}
+		ShowWarning("npc_parse_mob: Negative x-span %hd for mob ID %d (file '%s', line '%d'). Defaulting to map-wide.\n", mob.xs, mob_id, filepath, strline(buffer, start - buffer));
 		mob.xs = 0;
 	}
+	else if (mob.xs == 0 && mob.x > 0) {
+		// Fixed X coordinate
+		// Need to set this to 1 as we reduce it by 1 when calling the search function
+		mob.xs = 1;
+	}
 
 	if (mob.ys < 0) {
-		if (w1count > 4) {
-			ShowWarning("npc_parse_mob: Negative y-span %hd for mob ID %d (file '%s', line '%d').\n", mob.ys, mob_id, filepath, strline(buffer, start - buffer));
-		}
+		ShowWarning("npc_parse_mob: Negative y-span %hd for mob ID %d (file '%s', line '%d'). Defaulting to map-wide.\n", mob.ys, mob_id, filepath, strline(buffer, start - buffer));
 		mob.ys = 0;
 	}
+	else if (mob.ys == 0 && mob.y > 0) {
+		// Fixed Y coordinate
+		// Need to set this to 1 as we reduce it by 1 when calling the search function
+		mob.ys = 1;
+	}
 
 	if (mob.num > 1 && battle_config.mob_count_rate != 100) {
 		if ((mob.num = mob.num * battle_config.mob_count_rate / 100) < 1)
 			mob.num = 1;
 	}
 
-	if (battle_config.force_random_spawn || (mob.x == 0 && mob.y == 0))
+	if (battle_config.force_random_spawn || (mob.x == 0 && mob.y == 0)
+		|| (mob.xs == 1 && mob.ys == 1 && !map_getcell(mob.m, mob.x, mob.y, CELL_CHKREACH)))
 	{	//Force a random spawn anywhere on the map.
 		mob.x = mob.y = 0;
-		mob.xs = mob.ys = -1;
+		mob.xs = mob.ys = 0;
 	}
 
 	// Check if monsters should have variance applied to their respawn time

+ 595 - 67
src/map/packets.hpp

@@ -36,6 +36,7 @@ struct PACKET_ZC_PC_PURCHASE_RESULT{
 	int16 packetType;
 	uint8 result;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PC_PURCHASE_RESULT, 0xca)
 
 struct PACKET_CZ_REQ_MAKINGARROW{
 	int16 packetType;
@@ -45,6 +46,7 @@ struct PACKET_CZ_REQ_MAKINGARROW{
 	uint16 itemId;
 #endif
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_MAKINGARROW, 0x1ae)
 
 struct PACKET_CZ_SE_PC_BUY_CASHITEM_LIST_sub{
 	uint32 itemId;
@@ -59,6 +61,7 @@ struct PACKET_CZ_SE_PC_BUY_CASHITEM_LIST{
 	uint32 kafraPoints;
 	struct PACKET_CZ_SE_PC_BUY_CASHITEM_LIST_sub items[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_SE_PC_BUY_CASHITEM_LIST, 0x848)
 
 struct PACKET_CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO{
 	int16 packetType;
@@ -70,6 +73,7 @@ struct PACKET_CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO{
 	uint16 itemId;
 #endif
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ac)
 
 struct PACKET_ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO{
 	int16 packetType;
@@ -81,6 +85,7 @@ struct PACKET_ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO{
 #endif
 	uint32 price;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ad)
 
 struct PACKET_CZ_REQ_APPLY_BARGAIN_SALE_ITEM{
 	int16 packetType;
@@ -98,6 +103,7 @@ struct PACKET_CZ_REQ_APPLY_BARGAIN_SALE_ITEM{
 	uint8 hours;
 #endif
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_APPLY_BARGAIN_SALE_ITEM, 0x9ae)
 
 struct PACKET_CZ_REQ_REMOVE_BARGAIN_SALE_ITEM{
 	int16 packetType;
@@ -108,6 +114,7 @@ struct PACKET_CZ_REQ_REMOVE_BARGAIN_SALE_ITEM{
 	uint16 itemId;
 #endif
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_REMOVE_BARGAIN_SALE_ITEM, 0x9b0)
 
 struct PACKET_ZC_NOTIFY_BARGAIN_SALE_SELLING{
 	int16 packetType;
@@ -118,6 +125,7 @@ struct PACKET_ZC_NOTIFY_BARGAIN_SALE_SELLING{
 #endif
 	uint32 remainingTime;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_SELLING, 0x9b2)
 
 struct PACKET_ZC_NOTIFY_BARGAIN_SALE_CLOSE{
 	int16 packetType;
@@ -127,6 +135,7 @@ struct PACKET_ZC_NOTIFY_BARGAIN_SALE_CLOSE{
 	uint16 itemId;
 #endif
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_CLOSE, 0x9b3)
 
 struct PACKET_ZC_ACK_COUNT_BARGAIN_SALE_ITEM{
 	int16 packetType;
@@ -137,6 +146,7 @@ struct PACKET_ZC_ACK_COUNT_BARGAIN_SALE_ITEM{
 #endif
 	uint32 amount;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_COUNT_BARGAIN_SALE_ITEM, 0x9c4)
 
 struct PACKET_ZC_ACK_GUILDSTORAGE_LOG_sub{
 	uint32 id;
@@ -164,24 +174,28 @@ struct PACKET_ZC_ACK_GUILDSTORAGE_LOG{
 	uint16 amount;
 	struct PACKET_ZC_ACK_GUILDSTORAGE_LOG_sub items[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_GUILDSTORAGE_LOG, 0x9da)
 
-struct PACKET_CZ_UNCONFIRMED_TSTATUS_UP{
+struct PACKET_CZ_ADVANCED_STATUS_CHANGE{
 	int16 packetType;
 	int16 type;
 	int16 amount;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_ADVANCED_STATUS_CHANGE, 0x0b24)
 
-struct PACKET_CZ_GUILD_EMBLEM_CHANGE2 {
+struct PACKET_CZ_REQ_ADD_NEW_EMBLEM {
 	int16 packetType;
 	uint32 guild_id;
 	uint32 version;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_ADD_NEW_EMBLEM, 0x0b46)
 
 struct PACKET_ZC_BROADCAST{
 	int16 packetType;
 	int16 PacketLength;
 	char message[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_BROADCAST, 0x9a)
 
 struct PACKET_ZC_BROADCAST2{
 	int16 packetType;
@@ -193,25 +207,23 @@ struct PACKET_ZC_BROADCAST2{
 	int16 fontY;
 	char message[];
 } __attribute__((packed));
-
-struct PACKET_ZC_SOULENERGY{
-	int16 PacketType;
-	uint32 AID;
-	uint16 num;
-} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_BROADCAST2, 0x1c3)
 
 struct PACKET_ZC_ENTRY_QUEUE_INIT {
 	int16 packetType;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ENTRY_QUEUE_INIT, 0x90e)
 
-struct PACKET_CZ_UNCONFIRMED_RODEX_RETURN{
+struct PACKET_CZ_RODEX_RETURN{
 	int16 packetType;
 	uint32 msgId;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_RODEX_RETURN, 0xb98)
 
 struct PACKET_CZ_REQ_STYLE_CLOSE{
 	int16 packetType;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_STYLE_CLOSE, 0xa48)
 
 struct PACKET_ZC_SUMMON_HP_INIT {
 	int16 PacketType;
@@ -219,6 +231,7 @@ struct PACKET_ZC_SUMMON_HP_INIT {
 	uint32 CurrentHP;
 	uint32 MaxHP;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SUMMON_HP_INIT, 0xb6b)
 
 struct PACKET_ZC_SUMMON_HP_UPDATE {
 	int16 PacketType;
@@ -226,6 +239,7 @@ struct PACKET_ZC_SUMMON_HP_UPDATE {
 	uint16 VarId;
 	uint32 Value;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SUMMON_HP_UPDATE, 0xb6c)
 
 struct PACKET_ZC_REPUTE_INFO_sub{
 	uint64 type;
@@ -238,12 +252,14 @@ struct PACKET_ZC_REPUTE_INFO{
 	uint8 success;
 	struct PACKET_ZC_REPUTE_INFO_sub list[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_REPUTE_INFO, 0x0b8d)
 
 struct PACKET_ZC_UI_OPEN_V3{
 	int16 packetType;
 	uint8 type;
 	uint64 data;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_UI_OPEN_V3, 0x0b9a)
 
 struct PACKET_ZC_TARGET_SPIRITS {
 	int16 packetType;
@@ -251,6 +267,7 @@ struct PACKET_ZC_TARGET_SPIRITS {
 	uint32 unknown_val;
 	uint16 amount;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_TARGET_SPIRITS, 0xb68)
 
 struct PACKET_ZC_FRIENDS_LIST_sub{
 	uint32 AID;
@@ -265,6 +282,7 @@ struct PACKET_ZC_FRIENDS_LIST{
 	int16 PacketLength;
 	struct PACKET_ZC_FRIENDS_LIST_sub friends[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_FRIENDS_LIST, 0x201)
 
 struct PACKET_CZ_PC_SELL_ITEMLIST_sub {
 	uint16 index;
@@ -276,6 +294,7 @@ struct PACKET_CZ_PC_SELL_ITEMLIST {
 	int16 packetLength;
 	PACKET_CZ_PC_SELL_ITEMLIST_sub sellList[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_PC_SELL_ITEMLIST, 0x00c9)
 
 struct PACKET_CZ_REQ_CHANGE_MEMBERPOS_sub{
 	uint32 AID;
@@ -288,22 +307,26 @@ struct PACKET_CZ_REQ_CHANGE_MEMBERPOS{
 	int16 packetLength;
 	struct PACKET_CZ_REQ_CHANGE_MEMBERPOS_sub list[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_CHANGE_MEMBERPOS, 0x155)
 
 struct PACKET_ZC_CLEAR_DIALOG{
 	int16 packetType;
 	uint32 GID;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CLEAR_DIALOG, 0x8d6)
 
 struct PACKET_ZC_NOTIFY_BIND_ON_EQUIP{
 	int16 packetType;
 	int16 index;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_BIND_ON_EQUIP, 0x2d3)
 
 struct PACKET_ZC_BANKING_CHECK{
 	int16 packetType;
 	int64 money;
 	int16 reason;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_BANKING_CHECK, 0x9a6)
 
 struct PACKET_ZC_ACK_BANKING_WITHDRAW{
 	int16 packetType;
@@ -311,6 +334,7 @@ struct PACKET_ZC_ACK_BANKING_WITHDRAW{
 	int64 money;
 	int32 zeny;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_BANKING_WITHDRAW, 0x9aa)
 
 struct PACKET_ZC_ACK_BANKING_DEPOSIT{
 	int16 packetType;
@@ -318,33 +342,39 @@ struct PACKET_ZC_ACK_BANKING_DEPOSIT{
 	int64 money;
 	int32 zeny;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_BANKING_DEPOSIT, 0x9a8)
 
 struct PACKET_ZC_ACK_CLOSE_BANKING{
 	int16 packetType;
 	int16 unknown;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_CLOSE_BANKING, 0x9b9)
 
 struct PACKET_ZC_ACK_OPEN_BANKING{
 	int16 packetType;
 	int16 unknown;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_OPEN_BANKING, 0x9b7)
 
 struct PACKET_ZC_ACK_ADD_EXCHANGE_ITEM {
 	int16 packetType;
 	uint16 index;
 	uint8 result;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_ADD_EXCHANGE_ITEM, 0xea)
 
 struct PACKET_ZC_COUPLENAME {
 	int16 packetType;
 	char name[NAME_LENGTH];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_COUPLENAME, 0x1e6);
 
 struct PACKET_CZ_PARTY_REQ_MASTER_TO_JOIN{
 	int16 packetType;
 	uint32 CID;
 	uint32 AID;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_PARTY_REQ_MASTER_TO_JOIN, 0x0ae6)
 
 struct PACKET_ZC_PARTY_REQ_MASTER_TO_JOIN{
 	int16 packetType;
@@ -354,6 +384,7 @@ struct PACKET_ZC_PARTY_REQ_MASTER_TO_JOIN{
 	uint16 x;
 	uint16 y;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PARTY_REQ_MASTER_TO_JOIN, 0x0ae7)
 
 struct PACKET_CZ_PARTY_REQ_ACK_MASTER_TO_JOIN{
 	int16 packetType;
@@ -361,6 +392,7 @@ struct PACKET_CZ_PARTY_REQ_ACK_MASTER_TO_JOIN{
 	uint32 AID;
 	uint8 accept;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_PARTY_REQ_ACK_MASTER_TO_JOIN, 0x0af8)
 
 struct PACKET_ZC_PARTY_JOIN_REQ_ACK_FROM_MASTER{
 	int16 packetType;
@@ -369,11 +401,13 @@ struct PACKET_ZC_PARTY_JOIN_REQ_ACK_FROM_MASTER{
 	uint32 AID;
 	uint32 refused;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PARTY_JOIN_REQ_ACK_FROM_MASTER, 0x0afa)
 
 struct PACKET_CZ_REQ_SE_CASH_TAB_CODE{
 	int16 packetType;
 	int16 tab;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_SE_CASH_TAB_CODE, 0x846)
 
 struct PACKET_ZC_ACK_SE_CASH_ITEM_LIST2_sub{
 #if PACKETVER_MAIN_NUM >= 20181121 || PACKETVER_RE_NUM >= 20180704 || PACKETVER_ZERO_NUM >= 20181114
@@ -391,17 +425,20 @@ struct PACKET_ZC_ACK_SE_CASH_ITEM_LIST2{
 	int16 count;
 	struct PACKET_ZC_ACK_SE_CASH_ITEM_LIST2_sub items[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_SE_CASH_ITEM_LIST2, 0x8c0)
 
 struct PACKET_CZ_REQ_MERGE_ITEM{
 	int16 packetType;
 	int16 packetLength;
 	uint16 indices[];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_REQ_MERGE_ITEM, 0x96e)
 
 struct PACKET_CZ_RESET_SKILL{
 	int16 packetType;
 	uint8 unknown;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_RESET_SKILL, 0x0bb1)
 
 struct PACKET_ZC_BOSS_INFO{
 	int16 packetType;
@@ -414,29 +451,21 @@ struct PACKET_ZC_BOSS_INFO{
 	uint16 maxMinutes;
 	char name[51];
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_BOSS_INFO, 0x293)
 
 struct PACKET_CZ_INVENTORY_TAB{
 	int16 packetType;
 	int16 index;
 	bool favorite;
 } __attribute__((packed));
+DEFINE_PACKET_HEADER(CZ_INVENTORY_TAB, 0x907)
 
 struct PACKET_ZC_INVENTORY_TAB{
 	int16 packetType;
 	int16 index;
 	bool favorite;
 } __attribute__((packed));
-
-struct PACKET_ZC_SKILL_SELECT_REQUEST_sub{
-	int16 skill_id;
-} __attribute__((packed));
-
-struct PACKET_ZC_SKILL_SELECT_REQUEST{
-	int16 packetType;
-	int16 packetLength;
-	int32 why;
-	struct PACKET_ZC_SKILL_SELECT_REQUEST_sub skills[];
-} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_INVENTORY_TAB, 0x908)
 
 struct PACKET_CZ_REQ_OPEN_BANKING{
 	int16 packetType;
@@ -465,88 +494,587 @@ struct PACKET_CZ_REQ_BANKING_WITHDRAW{
 	int32 zeny;
 } __attribute__((packed));
 
+#if PACKETVER < 20080102
+struct PACKET_ZC_ACCEPT_ENTER {
+	int16 packetType;
+	uint32 startTime;
+	uint8 posDir[3];
+	uint8 xSize;
+	uint8 ySize;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACCEPT_ENTER, 0x73)
+#elif PACKETVER < 20141022 || PACKETVER >= 20160330
+struct PACKET_ZC_ACCEPT_ENTER {
+	int16 packetType;
+	uint32 startTime;
+	uint8 posDir[3];
+	uint8 xSize;
+	uint8 ySize;
+	uint16 font;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACCEPT_ENTER, 0x2eb)
+#else
+struct PACKET_ZC_ACCEPT_ENTER {
+	int16 packetType;
+	uint32 startTime;
+	uint8 posDir[3];
+	uint8 xSize;
+	uint8 ySize;
+	uint16 font;
+	uint8 sex;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACCEPT_ENTER, 0xa18)
+#endif
+
+struct PACKET_ZC_REFUSE_ENTER {
+	int16 packetType;
+	uint8 errorCode;
+} __attribute__((packed));
+static_assert(sizeof(PACKET_ZC_REFUSE_ENTER) == 3);
+DEFINE_PACKET_HEADER(ZC_REFUSE_ENTER, 0x74)
+
+struct PACKET_SC_NOTIFY_BAN {
+	int16 packetType;
+	uint8 errorCode;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(SC_NOTIFY_BAN, 0x81)
+
+struct PACKET_ZC_RESTART_ACK {
+	int16 packetType;
+	uint8 type;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_RESTART_ACK, 0xb3)
+
+struct PACKET_ZC_NOTIFY_VANISH {
+	int16 packetType;
+	uint32 gid;
+	uint8 type;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_VANISH, 0x80)
+
+struct PACKET_ZC_ITEM_DISAPPEAR {
+	int16 packetType;
+	uint32 itemAid;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ITEM_DISAPPEAR, 0xa1)
+
+struct PACKET_ZC_MILLENNIUMSHIELD {
+	int16 packetType;
+	uint32 aid;
+	int16 num;
+	int16 state;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_MILLENNIUMSHIELD, 0x440)
+
+struct PACKET_ZC_SPIRITS_ATTRIBUTE {
+	int16 packetType;
+	uint32 aid;
+	int16 spiritsType;
+	int16 num;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SPIRITS_ATTRIBUTE, 0x8cf)
+
+struct PACKET_ZC_CHANGESTATE_MER {
+	int16 packetType;
+	uint8 type;
+	uint8 state;
+	uint32 gid;
+	uint32 data;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CHANGESTATE_MER, 0x230)
+
+struct PACKET_ZC_HOSKILLINFO_LIST_sub {
+	uint16 id;
+	uint16 inf;
+	uint16 unknown;
+	uint16 level;
+	uint16 sp;
+	uint16 range;
+	char name[NAME_LENGTH];
+	uint8 upgradable;
+} __attribute__((packed));
+
+struct PACKET_ZC_HOSKILLINFO_LIST {
+	int16 packetType;
+	int16 packetLength;
+	PACKET_ZC_HOSKILLINFO_LIST_sub skills[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_HOSKILLINFO_LIST, 0x235)
+
+struct PACKET_ZC_HOSKILLINFO_UPDATE {
+	int16 packetType;
+	uint16 skill_id;
+	int16 Level;
+	int16 SP;
+	int16 AttackRange;
+	bool upgradable;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_HOSKILLINFO_UPDATE, 0x239)
+
+struct PACKET_ZC_NOTIFY_MOVE {
+	int16 packetType;
+	uint32 gid;
+	uint8 moveData[6];
+	uint32 moveStartTime;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_MOVE, 0x86)
+
+struct PACKET_ZC_NOTIFY_PLAYERMOVE {
+	int16 packetType;
+	uint32 moveStartTime;
+	uint8 moveData[6];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_PLAYERMOVE, 0x87);
+
+struct PACKET_ZC_NPCACK_MAPMOVE {
+	int16 packetType;
+	char mapName[MAP_NAME_LENGTH_EXT];
+	uint16 xPos;
+	uint16 yPos;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPCACK_MAPMOVE, 0x91)
+
+#if PACKETVER >= 20170315
+// Actually ZC_NPCACK_SERVERMOVE_DOMAIN
+struct PACKET_ZC_NPCACK_SERVERMOVE {
+	int16 packetType;
+	char mapName[MAP_NAME_LENGTH_EXT];
+	uint16 xPos;
+	uint16 yPos;
+	uint32 ip;
+	uint16 port;
+	char domain[128];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPCACK_SERVERMOVE, 0xac7)
+#else
+struct PACKET_ZC_NPCACK_SERVERMOVE {
+	int16 packetType;
+	char mapName[MAP_NAME_LENGTH_EXT];
+	uint16 xPos;
+	uint16 yPos;
+	uint32 ip;
+	uint16 port;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPCACK_SERVERMOVE, 0x92)
+#endif
+
+struct PACKET_ZC_STOPMOVE {
+	int16 packetType;
+	uint32	AID;
+	uint16	xPos;
+	uint16	yPos;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_STOPMOVE, 0x88)
+
+struct PACKET_ZC_SELECT_DEALTYPE {
+	int16 packetType;
+	uint32 npcId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SELECT_DEALTYPE, 0xc4)
+
+struct PACKET_ZC_PC_SELL_ITEMLIST_sub {
+	uint16 index;
+	uint32 price;
+	uint32 overcharge;
+} __attribute__((packed));
+
+struct PACKET_ZC_PC_SELL_ITEMLIST {
+	int16 packetType;
+	int16 packetLength;
+	PACKET_ZC_PC_SELL_ITEMLIST_sub items[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PC_SELL_ITEMLIST, 0xc7)
+
+struct PACKET_ZC_CLOSE_DIALOG {
+	int16 packetType;
+	uint32 npcId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CLOSE_DIALOG, 0xb6)
+
+struct PACKET_ZC_MENU_LIST {
+	int16 packetType;
+	int16 packetLength;
+	uint32 npcId;
+	char menu[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_MENU_LIST, 0xb7)
+
+struct PACKET_ZC_OPEN_EDITDLG {
+	int16 packetType;
+	uint32 npcId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_OPEN_EDITDLG, 0x142)
+
+struct PACKET_ZC_OPEN_EDITDLGSTR {
+	int16 packetType;
+	uint32 npcId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_OPEN_EDITDLGSTR, 0x1d4)
+
+struct PACKET_ZC_COMPASS {
+	int16 packetType;
+	uint32 npcId;
+	uint32 type;
+	uint32 xPos;
+	uint32 yPos;
+	uint8 id;
+	uint32 color;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_COMPASS, 0x144)
+
+struct PACKET_ZC_ITEM_THROW_ACK {
+	int16 packetType;
+	uint16 index;
+	uint16 count;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ITEM_THROW_ACK, 0xaf)
+
+struct PACKET_ZC_DELETE_ITEM_FROM_BODY {
+	int16 packetType;
+	int16 deleteType;
+	uint16 index;
+	int16 count;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_DELETE_ITEM_FROM_BODY, 0x7fa)
+
+struct PACKET_ZC_CARTOFF {
+	int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CARTOFF, 0x12b)
+
+struct PACKET_ZC_NOTIFY_POSITION_TO_GUILDM {
+	int16 packetType;
+	uint32 aid;
+	int16 xPos;
+	int16 yPos;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_POSITION_TO_GUILDM, 0x1eb)
+
+struct PACKET_ZC_STATUS {
+	int16 packetType;
+	uint16 point;
+	uint8 str;
+	uint8 standardStr;
+	uint8 agi;
+	uint8 standardAgi;
+	uint8 vit;
+	uint8 standardVit;
+	uint8 int_;
+	uint8 standardInt;
+	uint8 dex;
+	uint8 standardDex;
+	uint8 luk;
+	uint8 standardLuk;
+	int16 attPower;
+	int16 refiningPower;
+	int16 max_mattPower;
+	int16 min_mattPower;
+	int16 itemdefPower;
+	int16 plusdefPower;
+	int16 mdefPower;
+	int16 plusmdefPower;
+	int16 hitSuccessValue;
+	int16 avoidSuccessValue;
+	int16 plusAvoidSuccessValue;
+	int16 criticalSuccessValue;
+	int16 ASPD;
+	int16 plusASPD;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_STATUS, 0xbd)
+
+struct PACKET_ZC_NOTIFY_MAPINFO {
+	int16 packetType;
+	int16 type;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_MAPINFO, 0x189)
+
+struct PACKET_ZC_ACK_REMEMBER_WARPPOINT {
+	int16 packetType;
+	uint8 type;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_REMEMBER_WARPPOINT, 0x11e)
+
+struct PACKET_ZC_DISPEL {
+	int16 packetType;
+	uint32 gid;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_DISPEL, 0x1b9)
+
+struct PACKET_ZC_RESURRECTION {
+	int16 packetType;
+	uint32 gid;
+	int16 type;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_RESURRECTION, 0x148)
+
+struct PACKET_ZC_NOTIFY_MAPPROPERTY2 {
+	int16 packetType;
+	int16 type;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_MAPPROPERTY2, 0x1d6)
+
+struct PACKET_ZC_ACK_ITEMREFINING {
+	int16 packetType;
+	uint16 result;
+	uint16 index;
+	uint16 value;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_ITEMREFINING, 0x188)
+
+struct PACKET_ZC_PAR_CHANGE_USER {
+	int16 packetType;
+	uint32 gid;
+	int16 type;
+	uint16 value;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PAR_CHANGE_USER, 0x1ab)
+
+struct PACKET_ZC_EQUIP_ARROW {
+	int16 packetType;
+	uint16 index;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_EQUIP_ARROW, 0x13c)
+
+struct PACKET_ZC_CLOSE_STORE {
+	int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CLOSE_STORE, 0xf8);
+
+struct PACKET_ZC_DELETE_ITEM_FROM_STORE {
+	int16 packetType;
+	uint16 index;
+	uint32 amount;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_DELETE_ITEM_FROM_STORE, 0xf6);
+
+struct PACKET_ZC_NOTIFY_STOREITEM_COUNTINFO {
+	int16 packetType;
+	uint16 amount;
+	uint16 max_amount;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_STOREITEM_COUNTINFO, 0xf2);
+
+struct PACKET_ZC_EXCHANGEITEM_UNDO {
+	int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_EXCHANGEITEM_UNDO, 0xf1);
+
+struct PACKET_ZC_EXEC_EXCHANGE_ITEM {
+	int16 packetType;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_EXEC_EXCHANGE_ITEM, 0xf0);
+
+struct PACKET_ZC_CANCEL_EXCHANGE_ITEM {
+	int16 packetType;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_CANCEL_EXCHANGE_ITEM, 0xee);
+
+struct PACKET_ZC_CONCLUDE_EXCHANGE_ITEM {
+	int16 packetType;
+	uint8 who;
+} __attribute__((packed));
+
+struct PACKET_ZC_ACK_CREATE_CHATROOM {
+	int16 packetType;
+	uint8 flag;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_CREATE_CHATROOM, 0xd6);
+
+DEFINE_PACKET_HEADER(ZC_CONCLUDE_EXCHANGE_ITEM, 0xec);
+
+struct PACKET_ZC_REFUSE_ENTER_ROOM {
+	int16 packetType;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_REFUSE_ENTER_ROOM, 0xda);
+
+struct PACKET_ZC_NPC_SHOWEFST_UPDATE {
+	int16 packetType;
+	uint32 gid;
+	uint32 effectState;
+	int32 level;
+	uint32 showEFST;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NPC_SHOWEFST_UPDATE, 0x28a);
+
+struct PACKET_ZC_ACTION_FAILURE {
+	int16 packetType;
+	uint16 type;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACTION_FAILURE, 0x13b)
+
+struct PACKET_ZC_NOTIFY_EFFECT {
+	int16 packetType;
+	uint32 aid;
+	uint32 effectId;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_NOTIFY_EFFECT, 0x19b);
+
+struct PACKET_ZC_ACK_ITEMCOMPOSITION {
+	int16 packetType;
+	uint16 equipIndex;
+	uint16 cardIndex;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_ITEMCOMPOSITION, 0x17d);
+
+struct PACKET_ZC_ACK_ITEMIDENTIFY {
+	int16 packetType;
+	uint16 index;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_ITEMIDENTIFY, 0x179);
+
+struct PACKET_ZC_ACK_ITEMREPAIR {
+	int16 packetType;
+	uint16 index;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_ITEMREPAIR, 0x1fe);
+
+struct PACKET_ZC_EQUIPITEM_DAMAGED {
+	int16 packetType;
+	uint16 equipLocation;
+	uint32 GID;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_EQUIPITEM_DAMAGED, 0x2bb);
+
+struct PACKET_ZC_DELETE_ITEM_FROM_CART {
+	int16 packetType;
+	uint16 index;
+	int32 amount;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_DELETE_ITEM_FROM_CART, 0x125);
+
+struct PACKET_ZC_OPENSTORE {
+	int16 packetType;
+	uint16 num;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_OPENSTORE, 0x12d);
+
+struct PACKET_ZC_PC_PURCHASE_RESULT_FROMMC {
+	int16 packetType;
+	uint16 index;
+	uint16 amount;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_PC_PURCHASE_RESULT_FROMMC, 0x135);
+
+struct PACKET_ZC_ACK_OPENSTORE2 {
+	int16 packetType;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_OPENSTORE2, 0xa28 );
+
+struct PACKET_ZC_SKILL_DISAPPEAR {
+	int16 packetType;
+	uint32 GID;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SKILL_DISAPPEAR, 0x120);
+
+struct PACKET_ZC_SKILL_UPDATE {
+	int16 packetType;
+	uint32 GID;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SKILL_UPDATE, 0x1ac);
+
+#if PACKETVER >= 20141022
+struct PACKET_ZC_RECOVERY {
+	int16 packetType;
+	uint16 type;
+	int32 amount;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_RECOVERY, 0xa27);
+#else
+struct PACKET_ZC_RECOVERY {
+	int16 packetType;
+	uint16 type;
+	int16 amount;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_RECOVERY, 0x13d);
+#endif
+
+#if PACKETVER >= 20131223
+struct PACKET_ZC_ACK_WHISPER {
+	int16 packetType;
+	uint8 result;
+	uint32 CID;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_WHISPER, 0x9df);
+#else
+struct PACKET_ZC_ACK_WHISPER {
+	int16 packetType;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_WHISPER, 0x98);
+#endif
+
+struct PACKET_ZC_ACK_ADDITEM_TO_CART {
+	int16 packetType;
+	uint8 result;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_ACK_ADDITEM_TO_CART, 0x12c);
+
+// TODO : not sure for client date [Napster]
+#if PACKETVER >= 20141016
+struct PACKET_ZC_DELETEITEM_FROM_MCSTORE {
+	int16 packetType;
+	uint16 index;
+	uint16 amount;
+	uint32 buyerCID;
+	uint32 date;
+	int32 zeny;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_DELETEITEM_FROM_MCSTORE, 0x9e5);
+#else
+struct PACKET_ZC_DELETEITEM_FROM_MCSTORE {
+	int16 packetType;
+	uint16 index;
+	uint16 amount;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_DELETEITEM_FROM_MCSTORE, 0x137);
+#endif
+
 // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
 #if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
 	#pragma pack( pop )
 #endif
 
+// Other packets without struct defined in this file
 DEFINE_PACKET_HEADER(ZC_NOTIFY_CHAT, 0x8d)
-DEFINE_PACKET_HEADER(ZC_BROADCAST, 0x9a)
 DEFINE_PACKET_HEADER(ZC_ITEM_ENTRY, 0x9d)
-DEFINE_PACKET_HEADER(ZC_PC_PURCHASE_RESULT, 0xca)
-DEFINE_PACKET_HEADER(ZC_ACK_ADD_EXCHANGE_ITEM, 0xea)
 DEFINE_PACKET_HEADER(ZC_MVP_GETTING_ITEM, 0x10a)
-DEFINE_PACKET_HEADER(CZ_REQ_CHANGE_MEMBERPOS, 0x155)
 DEFINE_PACKET_HEADER(CZ_REQMAKINGITEM, 0x18e)
 DEFINE_PACKET_HEADER(ZC_ACK_REQMAKINGITEM, 0x18f)
-DEFINE_PACKET_HEADER(CZ_REQ_MAKINGARROW, 0x1ae)
-DEFINE_PACKET_HEADER(ZC_BROADCAST2, 0x1c3)
 #if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200724
 	DEFINE_PACKET_HEADER(CZ_REQ_ITEMREPAIR, 0xb66)
 #else
 	DEFINE_PACKET_HEADER(CZ_REQ_ITEMREPAIR, 0x1fd)
 #endif
-DEFINE_PACKET_HEADER(ZC_COUPLENAME, 0x1e6);
-DEFINE_PACKET_HEADER(ZC_FRIENDS_LIST, 0x201)
 DEFINE_PACKET_HEADER(ZC_NOTIFY_WEAPONITEMLIST, 0x221)
 DEFINE_PACKET_HEADER(ZC_ACK_WEAPONREFINE, 0x223)
 DEFINE_PACKET_HEADER(CZ_REQ_MAKINGITEM, 0x25b)
 DEFINE_PACKET_HEADER(ZC_PC_CASH_POINT_ITEMLIST, 0x287)
-DEFINE_PACKET_HEADER(ZC_BOSS_INFO, 0x293)
 DEFINE_PACKET_HEADER(ZC_CASH_TIME_COUNTER, 0x298)
 DEFINE_PACKET_HEADER(ZC_CASH_ITEM_DELETE, 0x299)
-DEFINE_PACKET_HEADER(ZC_NOTIFY_BIND_ON_EQUIP, 0x2d3)
-DEFINE_PACKET_HEADER(ZC_SKILL_SELECT_REQUEST, 0x442)
+DEFINE_PACKET_HEADER(CZ_SKILL_SELECT_RESPONSE, 0x443)
 DEFINE_PACKET_HEADER(ZC_FAILED_TRADE_BUYING_STORE_TO_SELLER, 0x824)
 DEFINE_PACKET_HEADER(CZ_SSILIST_ITEM_CLICK, 0x83c)
-DEFINE_PACKET_HEADER(CZ_REQ_SE_CASH_TAB_CODE, 0x846)
-DEFINE_PACKET_HEADER(ZC_ACK_SE_CASH_ITEM_LIST2, 0x8c0)
 DEFINE_PACKET_HEADER(ZC_ACK_SCHEDULER_CASHITEM, 0x8ca)
-DEFINE_PACKET_HEADER(ZC_CLEAR_DIALOG, 0x8d6)
-DEFINE_PACKET_HEADER(CZ_INVENTORY_TAB, 0x907)
-DEFINE_PACKET_HEADER(ZC_INVENTORY_TAB, 0x908)
-DEFINE_PACKET_HEADER(ZC_ENTRY_QUEUE_INIT, 0x90e)
-DEFINE_PACKET_HEADER(CZ_REQ_MERGE_ITEM, 0x96e)
-DEFINE_PACKET_HEADER(ZC_BANKING_CHECK, 0x9a6)
 DEFINE_PACKET_HEADER(CZ_REQ_BANKING_DEPOSIT, 0x9a7)
-DEFINE_PACKET_HEADER(ZC_ACK_BANKING_DEPOSIT, 0x9a8)
 DEFINE_PACKET_HEADER(CZ_REQ_BANKING_WITHDRAW, 0x9a9)
-DEFINE_PACKET_HEADER(ZC_ACK_BANKING_WITHDRAW, 0x9aa)
 DEFINE_PACKET_HEADER(CZ_REQ_BANKING_CHECK, 0x9ab)
-DEFINE_PACKET_HEADER(CZ_REQ_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ac)
-DEFINE_PACKET_HEADER(ZC_ACK_CASH_BARGAIN_SALE_ITEM_INFO, 0x9ad)
-DEFINE_PACKET_HEADER(CZ_REQ_APPLY_BARGAIN_SALE_ITEM, 0x9ae)
-DEFINE_PACKET_HEADER(CZ_REQ_REMOVE_BARGAIN_SALE_ITEM, 0x9b0)
-DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_SELLING, 0x9b2)
-DEFINE_PACKET_HEADER(ZC_NOTIFY_BARGAIN_SALE_CLOSE, 0x9b3)
 DEFINE_PACKET_HEADER(CZ_REQ_OPEN_BANKING, 0x9b6)
-DEFINE_PACKET_HEADER(ZC_ACK_OPEN_BANKING, 0x9b7)
 DEFINE_PACKET_HEADER(CZ_REQ_CLOSE_BANKING, 0x9b8)
-DEFINE_PACKET_HEADER(ZC_ACK_CLOSE_BANKING, 0x9b9)
-DEFINE_PACKET_HEADER(ZC_ACK_COUNT_BARGAIN_SALE_ITEM, 0x9c4)
-DEFINE_PACKET_HEADER(ZC_ACK_GUILDSTORAGE_LOG, 0x9da)
 DEFINE_PACKET_HEADER(CZ_REQ_APPLY_BARGAIN_SALE_ITEM2, 0xa3d)
 DEFINE_PACKET_HEADER(CZ_REQ_STYLE_CHANGE, 0xa46)
 DEFINE_PACKET_HEADER(ZC_STYLE_CHANGE_RES, 0xa47)
-DEFINE_PACKET_HEADER(CZ_REQ_STYLE_CLOSE, 0xa48)
 DEFINE_PACKET_HEADER(ZC_GROUP_ISALIVE, 0xab2)
-DEFINE_PACKET_HEADER(CZ_PARTY_REQ_MASTER_TO_JOIN, 0x0ae6)
-DEFINE_PACKET_HEADER(ZC_PARTY_REQ_MASTER_TO_JOIN, 0x0ae7)
-DEFINE_PACKET_HEADER(CZ_PARTY_REQ_ACK_MASTER_TO_JOIN, 0x0af8)
-DEFINE_PACKET_HEADER(ZC_PARTY_JOIN_REQ_ACK_FROM_MASTER, 0x0afa)
 DEFINE_PACKET_HEADER(CZ_REQ_STYLE_CHANGE2, 0xafc)
 DEFINE_PACKET_HEADER(ZC_REMOVE_EFFECT, 0x0b0d)
-DEFINE_PACKET_HEADER(CZ_UNCONFIRMED_TSTATUS_UP, 0x0b24)
-DEFINE_PACKET_HEADER(CZ_GUILD_EMBLEM_CHANGE2, 0x0b46)
-DEFINE_PACKET_HEADER(ZC_TARGET_SPIRITS, 0xb68)
-DEFINE_PACKET_HEADER(ZC_SOULENERGY, 0xb73)
-DEFINE_PACKET_HEADER(CZ_UNCONFIRMED_RODEX_RETURN, 0xb98)
-DEFINE_PACKET_HEADER(ZC_SUMMON_HP_INIT, 0xb6b)
-DEFINE_PACKET_HEADER(ZC_SUMMON_HP_UPDATE, 0xb6c)
-DEFINE_PACKET_HEADER(ZC_REPUTE_INFO, 0x0b8d)
-DEFINE_PACKET_HEADER(ZC_UI_OPEN_V3, 0x0b9a)
-DEFINE_PACKET_HEADER(CZ_RESET_SKILL, 0x0bb1)
-DEFINE_PACKET_HEADER(CZ_PC_SELL_ITEMLIST, 0x00c9)
+DEFINE_PACKET_HEADER(ZC_FEED_MER, 0x22f)
+DEFINE_PACKET_HEADER(ZC_FEED_PET, 0x1a3)
 
 const int16 MAX_INVENTORY_ITEM_PACKET_NORMAL = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_normal ) - ( sizeof( struct NORMALITEM_INFO ) * MAX_ITEMLIST) ) ) / sizeof( struct NORMALITEM_INFO ) );
 const int16 MAX_INVENTORY_ITEM_PACKET_EQUIP = ( ( INT16_MAX - ( sizeof( struct packet_itemlist_equip ) - ( sizeof( struct EQUIPITEM_INFO ) * MAX_ITEMLIST ) ) ) / sizeof( struct EQUIPITEM_INFO ) );

+ 31 - 1
src/map/packets_struct.hpp

@@ -3297,6 +3297,20 @@ struct PACKET_ZC_MAKINGARROW_LIST {
 } __attribute__((packed));
 DEFINE_PACKET_HEADER(ZC_MAKINGARROW_LIST, 0x01ad);
 
+struct PACKET_ZC_SKILL_SELECT_REQUEST {
+	int16 packetType;
+	int16 packetLength;
+	int32 flag; //< 0 = old code compatibility; 1 = Auto Shadow Spell; same value is received in CZ_SKILL_SELECT_RESPONSE
+	int16 skillIds[];
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SKILL_SELECT_REQUEST, 0x0442);
+
+struct PACKET_CZ_SKILL_SELECT_RESPONSE {
+	int16 packetType;
+	int32 flag; //< currently unused, matches ZC_SKILL_SELECT_REQUEST.flag
+	int16 selectedSkillId;
+} __attribute__((packed));
+
 #if PACKETVER_MAIN_NUM >= 20200916 || PACKETVER_RE_NUM >= 20200723 || PACKETVER_ZERO_NUM >= 20221024
 #define REPAIRITEM_INFO REPAIRITEM_INFO2
 struct PACKET_ZC_REPAIRITEMLIST {
@@ -4752,7 +4766,7 @@ struct PACKET_ZC_NOTIFY_SKILL {
 	int8 action;
 } __attribute__((packed));
 DEFINE_PACKET_HEADER(ZC_NOTIFY_SKILL, 0x01de);
-#endif 
+#endif
 
 #if PACKETVER_MAIN_NUM >= 20130731 || PACKETVER_RE_NUM >= 20130724 || defined(PACKETVER_ZERO)
 struct PACKET_ZC_USE_SKILL {
@@ -5548,6 +5562,22 @@ struct PACKET_ZC_SPIRITS {
 } __attribute__((packed));
 DEFINE_PACKET_HEADER(ZC_SPIRITS, 0x01d0)
 
+struct PACKET_ZC_SPIRITS2 {
+	int16 PacketType;
+	uint32 AID;
+	int16 num;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SPIRITS2, 0x01e1)
+
+#if PACKETVER_MAIN_NUM >= 20200414 || PACKETVER_RE_NUM >= 20200723 || PACKETVER_ZERO_NUM >= 20200506
+struct PACKET_ZC_SOULENERGY {
+	int16 PacketType;
+	uint32 AID;
+	uint16 num;
+} __attribute__((packed));
+DEFINE_PACKET_HEADER(ZC_SOULENERGY, 0x0b73)
+#endif
+
 struct PACKET_ZC_SAY_DIALOG {
 	int16 PacketType;
 	int16 PacketLength;

+ 1 - 1
src/map/party.cpp

@@ -917,7 +917,7 @@ int party_changeleader(map_session_data *sd, map_session_data *tsd, struct party
 			return 0; // Shouldn't happen
 
 		if( battle_config.change_party_leader_samemap && strncmp( p->party.member[mi].map, p->party.member[tmi].map, sizeof( p->party.member[mi].map ) ) != 0 ){
-			clif_msg(sd, PARTY_MASTER_CHANGE_SAME_MAP);
+			clif_msg(sd, MSI_PARTY_MASTER_CHANGE_SAME_MAP);
 			return 0;
 		}
 	} else {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 211 - 205
src/map/pc.cpp


+ 11 - 12
src/map/pet.cpp

@@ -1226,7 +1226,7 @@ int pet_catch_process1(map_session_data *sd,int target_class)
 	}
 
 	sd->catch_target_class = target_class;
-	clif_catch_process(sd);
+	clif_catch_process( *sd );
 
 	return 0;
 }
@@ -1247,7 +1247,7 @@ int pet_catch_process2(map_session_data* sd, int target_id)
 	md = (struct mob_data*)map_id2bl(target_id);
 
 	if(!md || md->bl.type != BL_MOB || md->bl.prev == nullptr) { // Invalid inputs/state, abort capture.
-		clif_pet_roulette(sd,0);
+		clif_pet_roulette( *sd, false );
 		sd->catch_target_class = PET_CATCH_FAIL;
 		sd->itemid = 0;
 		sd->itemindex = -1;
@@ -1255,7 +1255,7 @@ int pet_catch_process2(map_session_data* sd, int target_id)
 	}
 
 	if (map_getmapflag(sd->bl.m, MF_NOPETCAPTURE)) {
-		clif_pet_roulette(sd, 0);
+		clif_pet_roulette( *sd, false );
 		sd->catch_target_class = PET_CATCH_FAIL;
 		sd->itemid = 0;
 		sd->itemindex = -1;
@@ -1280,14 +1280,14 @@ int pet_catch_process2(map_session_data* sd, int target_id)
 
 	if(sd->catch_target_class != md->mob_id || !pet) {
 		clif_emotion(&md->bl, ET_ANGER);	//mob will do /ag if wrong lure is used on them.
-		clif_pet_roulette(sd,0);
+		clif_pet_roulette( *sd, false );
 		sd->catch_target_class = PET_CATCH_FAIL;
 
 		return 1;
 	}
 
 	if( battle_config.pet_distance_check && distance_bl( &sd->bl, &md->bl ) > battle_config.pet_distance_check ){
-		clif_pet_roulette( sd, 0 );
+		clif_pet_roulette( *sd, false );
 		sd->catch_target_class = PET_CATCH_FAIL;
 
 		return 1;
@@ -1296,7 +1296,7 @@ int pet_catch_process2(map_session_data* sd, int target_id)
 	status_change* tsc = status_get_sc( &md->bl );
 
 	if( battle_config.pet_hide_check && tsc && ( tsc->getSCE(SC_HIDING) || tsc->getSCE(SC_CLOAKING) || tsc->getSCE(SC_CAMOUFLAGE) || tsc->getSCE(SC_NEWMOON) || tsc->getSCE(SC_CLOAKINGEXCEED) ) ){
-		clif_pet_roulette( sd, 0 );
+		clif_pet_roulette( *sd, false );
 		sd->catch_target_class = PET_CATCH_FAIL;
 
 		return 1;
@@ -1318,13 +1318,13 @@ int pet_catch_process2(map_session_data* sd, int target_id)
 		achievement_update_objective(sd, AG_TAMING, 1, md->mob_id);
 		unit_remove_map(&md->bl,CLR_OUTSIGHT);
 		status_kill(&md->bl);
-		clif_pet_roulette(sd,1);
+		clif_pet_roulette( *sd, true );
 
 		std::shared_ptr<s_mob_db> mdb = mob_db.find(pet->class_);
 
 		intif_create_pet(sd->status.account_id, sd->status.char_id, pet->class_, mdb->lv, pet->EggID, 0, pet->intimate, 100, 0, 1, mdb->jname.c_str());
 	} else {
-		clif_pet_roulette(sd,0);
+		clif_pet_roulette( *sd, false );
 		sd->catch_target_class = PET_CATCH_FAIL;
 	}
 
@@ -1608,8 +1608,7 @@ int pet_food(map_session_data *sd, struct pet_data *pd)
 	i = pc_search_inventory(sd,k);
 
 	if( i < 0 ) {
-		clif_pet_food(sd,k,0);
-
+		clif_pet_food( *sd, k, 0 );
 		return 1;
 	}
 
@@ -1646,7 +1645,7 @@ int pet_food(map_session_data *sd, struct pet_data *pd)
 
 	clif_send_petdata(sd,pd,2,pd->pet.hungry);
 	clif_send_petdata(sd,pd,1,pd->pet.intimate);
-	clif_pet_food(sd, pet_db_ptr->FoodID,1);
+	clif_pet_food( *sd, pet_db_ptr->FoodID, 1 );
 
 	return 0;
 }
@@ -2287,7 +2286,7 @@ void pet_evolution(map_session_data *sd, int16 pet_id) {
 
 	// Virtually delete the old egg
 	log_pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->inventory.u.items_inventory[idx]);
-	clif_delitem(sd, idx, 1, 0);
+	clif_delitem( *sd, idx, 1, 0 );
 
 	// Change the old egg to the new one
 	sd->inventory.u.items_inventory[idx].nameid = new_data->EggID;

+ 56 - 47
src/map/script.cpp

@@ -3674,7 +3674,7 @@ void script_free_state(struct script_state* st)
 
 		if (sd && sd->st == st) { // Current script is aborted.
 			if(sd->state.using_fake_npc) {
-				clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
+				clif_clearunit_single( sd->npc_id, CLR_OUTSIGHT, *sd );
 				sd->state.using_fake_npc = 0;
 			}
 			sd->st = nullptr;
@@ -4306,7 +4306,7 @@ static void script_detach_state(struct script_state* st, bool dequeue_event)
 
 	if(st->rid && (sd = map_id2sd(st->rid))!=nullptr) {
 		if( sd->state.using_fake_npc ){
-			clif_clearunit_single( sd->npc_id, CLR_OUTSIGHT, sd->fd );
+			clif_clearunit_single( sd->npc_id, CLR_OUTSIGHT, *sd );
 			sd->state.using_fake_npc = 0;
 		}
 
@@ -4511,7 +4511,7 @@ void run_script_main(struct script_state *st)
 		if ((sd = map_id2sd(st->rid))!=nullptr)
 		{	//Restore previous stack and save char.
 			if(sd->state.using_fake_npc){
-				clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
+				clif_clearunit_single( sd->npc_id, CLR_OUTSIGHT, *sd );
 				sd->state.using_fake_npc = 0;
 			}
 			//Restore previous script if any.
@@ -5008,7 +5008,8 @@ BUILDIN_FUNC(close)
 		st->clear_cutin = true;
 	}
 
-	clif_scriptclose(sd, st->oid);
+	clif_scriptclose( *sd, st->oid );
+
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -5028,7 +5029,8 @@ BUILDIN_FUNC(close2)
 	if( st->mes_active )
 		st->mes_active = 0;
 
-	clif_scriptclose(sd, st->oid);
+	clif_scriptclose( *sd, st->oid );
+
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -5148,10 +5150,10 @@ BUILDIN_FUNC(menu)
 			CREATE(menu, char, 2048);
 			safestrncpy(menu, StringBuf_Value(&buf), 2047);
 			ShowWarning("buildin_menu: NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf));
-			clif_scriptmenu(sd, st->oid, menu);
+			clif_scriptmenu( *sd, st->oid, menu );
 			aFree(menu);
 		} else
-			clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf));
+			clif_scriptmenu( *sd, st->oid, StringBuf_Value( &buf ) );
 
 		StringBuf_Destroy(&buf);
 
@@ -5252,10 +5254,10 @@ BUILDIN_FUNC(select)
 			CREATE(menu, char, 2048);
 			safestrncpy(menu, StringBuf_Value(&buf), 2047);
 			ShowWarning("buildin_select: NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf));
-			clif_scriptmenu(sd, st->oid, menu);
+			clif_scriptmenu( *sd, st->oid, menu );
 			aFree(menu);
 		} else
-			clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf));
+			clif_scriptmenu( *sd, st->oid, StringBuf_Value( &buf ) );
 		StringBuf_Destroy(&buf);
 
 		if( sd->npc_menu >= 0xff ) {
@@ -5330,10 +5332,10 @@ BUILDIN_FUNC(prompt)
 			CREATE(menu, char, 2048);
 			safestrncpy(menu, StringBuf_Value(&buf), 2047);
 			ShowWarning("buildin_prompt: NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf));
-			clif_scriptmenu(sd, st->oid, menu);
+			clif_scriptmenu( *sd, st->oid, menu );
 			aFree(menu);
 		} else
-			clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf));
+			clif_scriptmenu( *sd, st->oid, StringBuf_Value( &buf ) );
 		StringBuf_Destroy(&buf);
 
 		if( sd->npc_menu >= 0xff )
@@ -6161,9 +6163,9 @@ BUILDIN_FUNC(input)
 		sd->state.menu_or_input = 1;
 		st->state = RERUNLINE;
 		if( is_string_variable(name) )
-			clif_scriptinputstr(sd,st->oid);
+			clif_scriptinputstr( *sd, st->oid );
 		else
-			clif_scriptinput(sd,st->oid);
+			clif_scriptinput( *sd, st->oid );
 	}
 	else
 	{	// take received text/value and store it in the designated variable
@@ -6909,7 +6911,8 @@ BUILDIN_FUNC(cutin)
 	if( !script_rid2sd(sd) )
 		return SCRIPT_CMD_SUCCESS;
 
-	clif_cutin(sd,script_getstr(st,2),script_getnum(st,3));
+	clif_cutin( *sd, script_getstr( st, 2 ), script_getnum( st, 3 ) );
+
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -6932,7 +6935,7 @@ BUILDIN_FUNC(viewpoint)
 	id=script_getnum(st,5);
 	color=script_getnum(st,6);
 
-	clif_viewpoint(sd,st->oid,type,x,y,id,color);
+	clif_viewpoint( *sd, st->oid, type, x, y, id, color );
 
 	return SCRIPT_CMD_SUCCESS;
 }
@@ -6947,7 +6950,8 @@ static int buildin_viewpointmap_sub(block_list *bl, va_list ap) {
 	id = va_arg(ap, int);
 	color = va_arg(ap, int);
 
-	clif_viewpoint((map_session_data *)bl, oid, type, x, y, id, color);
+	clif_viewpoint( *reinterpret_cast<map_session_data*>( bl ), oid, type, x, y, id, color );
+
 	return 0;
 }
 
@@ -8588,7 +8592,8 @@ BUILDIN_FUNC(delitem)
 	ShowError("buildin_%s: failed to delete %d items (AID=%d item_id=%u).\n", command, it.amount, sd->status.account_id, it.nameid);
 	st->state = END;
 	st->mes_active = 0;
-	clif_scriptclose(sd, st->oid);
+	clif_scriptclose( *sd, st->oid );
+
 	return SCRIPT_CMD_FAILURE;
 }
 
@@ -8712,7 +8717,8 @@ BUILDIN_FUNC(delitem2)
 	ShowError("buildin_%s: failed to delete %d items (AID=%d item_id=%u).\n", command, it.amount, sd->status.account_id, it.nameid);
 	st->state = END;
 	st->mes_active = 0;
-	clif_scriptclose(sd, st->oid);
+	clif_scriptclose( *sd, st->oid );
+
 	return SCRIPT_CMD_FAILURE;
 }
 
@@ -9337,7 +9343,7 @@ BUILDIN_FUNC(repair)
 					sd->inventory.u.items_inventory[i].attribute = 0;
 					clif_equiplist(sd);
 					clif_produceeffect(sd, 0, sd->inventory.u.items_inventory[i].nameid);
-					clif_misceffect(&sd->bl, 3);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 					break;
 				}
 		}
@@ -9368,7 +9374,7 @@ BUILDIN_FUNC(repairall)
 
 	if(repaircounter)
 	{
-		clif_misceffect(&sd->bl, 3);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 		clif_equiplist(sd);
 	}
 
@@ -9628,15 +9634,15 @@ BUILDIN_FUNC(successrefitem) {
 		sd->inventory.u.items_inventory[i].refine = cap_value( sd->inventory.u.items_inventory[i].refine, 0, MAX_REFINE);
 		pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below
 
-		clif_refine(sd->fd,0,i,sd->inventory.u.items_inventory[i].refine);
-		clif_delitem(sd,i,1,3);
+		clif_refine( *sd, i, ITEMREFINING_SUCCESS );
+		clif_delitem( *sd, i, 1, 3 );
 
 		//Logs items, got from (N)PC scripts [Lupus]
 		log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->inventory.u.items_inventory[i]);
 
 		clif_additem(sd,i,1,0);
 		pc_equipitem(sd,i,ep);
-		clif_misceffect(&sd->bl,3);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 		if( sd->inventory_data[i]->type == IT_WEAPON ){
 			achievement_update_objective(sd, AG_ENCHANT_SUCCESS, 2, sd->inventory_data[i]->weapon_level, sd->inventory.u.items_inventory[i].refine);
 		}
@@ -9687,9 +9693,9 @@ BUILDIN_FUNC(failedrefitem) {
 	if (i >= 0) {
 		sd->inventory.u.items_inventory[i].refine = 0;
 		pc_unequipitem(sd,i,3); //recalculate bonus
-		clif_refine(sd->fd,1,i,sd->inventory.u.items_inventory[i].refine); //notify client of failure
+		clif_refine( *sd, i, ITEMREFINING_FAILURE);
 		pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT);
-		clif_misceffect(&sd->bl,2); 	// display failure effect
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_FAILURE );
 		achievement_update_objective(sd, AG_ENCHANT_FAIL, 1, 1);
 		script_pushint(st, 1);
 		return SCRIPT_CMD_SUCCESS;
@@ -9730,15 +9736,15 @@ BUILDIN_FUNC(downrefitem) {
 		sd->inventory.u.items_inventory[i].refine -= down;
 		sd->inventory.u.items_inventory[i].refine = cap_value( sd->inventory.u.items_inventory[i].refine, 0, MAX_REFINE);
 
-		clif_refine(sd->fd,2,i,sd->inventory.u.items_inventory[i].refine);
-		clif_delitem(sd,i,1,3);
+		clif_refine( *sd, i, ITEMREFINING_DOWNGRADE );
+		clif_delitem( *sd, i, 1, 3 );
 
 		//Logs items, got from (N)PC scripts [Lupus]
 		log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->inventory.u.items_inventory[i]);
 
 		clif_additem(sd,i,1,0);
 		pc_equipitem(sd,i,ep);
-		clif_misceffect(&sd->bl,2);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_FAILURE );
 		achievement_update_objective(sd, AG_ENCHANT_FAIL, 1, sd->inventory.u.items_inventory[i].refine);
 		script_pushint(st, sd->inventory.u.items_inventory[i].refine);
 		return SCRIPT_CMD_SUCCESS;
@@ -10381,9 +10387,10 @@ BUILDIN_FUNC(end)
 		st->mes_active = 0;
 
 	if (sd){
-		if (sd->state.callshop == 0)
-			clif_scriptclose(sd, st->oid); // If a menu/select/prompt is active, close it.
-		else 
+		if (sd->state.callshop == 0){
+			// If a menu/select/prompt is active, close it.
+			clif_scriptclose( *sd, st->oid );
+		}else
 			sd->state.callshop = 0;
 	}
 
@@ -11379,11 +11386,11 @@ BUILDIN_FUNC(killmonster)
 
 static int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap)
 { //Strips the event from the mob if it's killed the old method.
-	struct mob_data *md;
+	mob_data* md = BL_CAST(BL_MOB, bl);
 
-	md = BL_CAST(BL_MOB, bl);
-	if (md->npc_event[0])
-		md->npc_event[0] = 0;
+	if( md != nullptr ){
+		strcpy( md->npc_event, "" );
+	}
 
 	status_kill(bl);
 	return 0;
@@ -14043,7 +14050,7 @@ BUILDIN_FUNC(successremovecards) {
 			map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0,0);
 		}
 
-		clif_misceffect(&sd->bl,3);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 	}
 	return SCRIPT_CMD_SUCCESS;
 }
@@ -14130,7 +14137,7 @@ BUILDIN_FUNC(failedremovecards) {
 				map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0,0);
 			}
 		}
-		clif_misceffect(&sd->bl,2);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_FAILURE );
 	}
 	return SCRIPT_CMD_SUCCESS;
 }
@@ -15846,7 +15853,9 @@ BUILDIN_FUNC(addhomintimacy)
 		hom_increase_intimacy(hd, (uint32)value);
 	else
 		hom_decrease_intimacy(hd, (uint32)abs(value));
-	clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy / 100);
+
+	clif_send_homdata( *hd, SP_INTIMATE );
+
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -16050,7 +16059,7 @@ BUILDIN_FUNC(chatmes)
 	if (nd != nullptr && nd->chat_id) {
 		char message[256];
 		safesnprintf(message, sizeof(message), "%s", str);
-		clif_GlobalMessage(map_id2bl(nd->chat_id), message, CHAT_WOS);
+		clif_GlobalMessage( *map_id2bl( nd->chat_id ), message, CHAT_WOS );
 	}
 	return SCRIPT_CMD_SUCCESS;
 }
@@ -17890,7 +17899,7 @@ BUILDIN_FUNC(callshop)
 		switch (flag) {
 			case 1: npc_buysellsel(sd,nd->bl.id,0); break; //Buy window
 			case 2: npc_buysellsel(sd,nd->bl.id,1); break; //Sell window
-			default: clif_npcbuysell(sd,nd->bl.id); break; //Show menu
+			default: clif_npcbuysell( *sd, *nd ); break; //Show menu
 		}
 	}
 #if PACKETVER >= 20131223
@@ -17923,7 +17932,7 @@ BUILDIN_FUNC(callshop)
 			clif_barter_open( *sd, *nd );
 		}
 	}else
-		clif_cashshop_show(sd, nd);
+		clif_cashshop_show( *sd, *nd );
 
 	sd->npc_shopid = nd->bl.id;
 	script_pushint(st,1);
@@ -19273,8 +19282,8 @@ BUILDIN_FUNC(setunitdata)
 			case UHOM_MAPID: if (mapname) value = map_mapname2mapid(mapname); unit_warp(bl, (short)value, 0, 0, CLR_TELEPORT); break;
 			case UHOM_X: if (!unit_walktoxy(bl, (short)value, hd->bl.y, 2)) unit_movepos(bl, (short)value, hd->bl.y, 0, 0); break;
 			case UHOM_Y: if (!unit_walktoxy(bl, hd->bl.x, (short)value, 2)) unit_movepos(bl, hd->bl.x, (short)value, 0, 0); break;
-			case UHOM_HUNGER: hd->homunculus.hunger = (short)value; clif_send_homdata(map_charid2sd(hd->homunculus.char_id), SP_HUNGRY, hd->homunculus.hunger); break;
-			case UHOM_INTIMACY: hom_increase_intimacy(hd, (unsigned int)value); clif_send_homdata(map_charid2sd(hd->homunculus.char_id), SP_INTIMATE, hd->homunculus.intimacy / 100); break;
+			case UHOM_HUNGER: hd->homunculus.hunger = (short)value; clif_send_homdata(*hd, SP_HUNGRY); break;
+			case UHOM_INTIMACY: hom_increase_intimacy(hd, (unsigned int)value); clif_send_homdata(*hd, SP_INTIMATE); break;
 			case UHOM_SPEED: hd->base_status.speed = (unsigned short)value; status_calc_misc(bl, &hd->base_status, hd->homunculus.level); calc_status = true; break;
 			case UHOM_LOOKDIR: unit_setdir(bl, (uint8)value); break;
 			case UHOM_CANMOVETICK: hd->ud.canmove_tick = value > 0 ? (unsigned int)value : 0; break;
@@ -19570,7 +19579,7 @@ BUILDIN_FUNC(setunitdata)
 	// Client information updates
 	switch (bl->type) {
 		case BL_HOM:
-			clif_send_homdata(hd->master, SP_ACK, 0);
+			clif_send_homdata( *hd, SP_ACK );
 			break;
 		case BL_PET:
 			clif_send_petstatus(pd->master);
@@ -22532,7 +22541,7 @@ BUILDIN_FUNC(setmounting) {
 	if (!script_charid2sd(2,sd))
 		return SCRIPT_CMD_FAILURE;
 	if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) {
-		clif_msg(sd, NEED_REINS_OF_MOUNT);
+		clif_msg(sd, MSI_FAIELD_RIDING_OVERLAPPED);
 		script_pushint(st,0); //can't mount with one of these
 	} else if (sd->sc.getSCE(SC_CLOAKING) || sd->sc.getSCE(SC_CHASEWALK) || sd->sc.getSCE(SC_CLOAKINGEXCEED) || sd->sc.getSCE(SC_CAMOUFLAGE) || sd->sc.getSCE(SC_STEALTHFIELD) || sd->sc.getSCE(SC__FEINTBOMB)) {
 		// SC_HIDING, SC__INVISIBILITY, SC__SHADOWFORM, SC_SUHIDE already disable item usage
@@ -24393,7 +24402,7 @@ BUILDIN_FUNC(hateffect){
 	}
 
 	if( !sd->state.connect_new ){
-		clif_hat_effect_single( sd, effectID, enable );
+		clif_hat_effect_single( *sd, effectID, enable );
 	}
 
 #endif
@@ -24521,7 +24530,7 @@ BUILDIN_FUNC(setrandomoption) {
 		sd->inventory.u.items_inventory[i].option[index].id = id;
 		sd->inventory.u.items_inventory[i].option[index].value = value;
 		sd->inventory.u.items_inventory[i].option[index].param = param;
-		clif_delitem(sd, i, 1, 3);
+		clif_delitem( *sd, i, 1, 3 );
 		log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->inventory.u.items_inventory[i]);
 		clif_additem(sd, i, 1, 0);
 		pc_equipitem(sd, i, ep);

+ 3 - 2
src/map/script.hpp

@@ -2155,9 +2155,10 @@ enum e_pcblock_action_flag : uint16 {
 	PCBLOCK_SITSTAND = 0x040,
 	PCBLOCK_COMMANDS = 0x080,
 	PCBLOCK_NPCCLICK = 0x100,
-	PCBLOCK_NPC      = 0x18D,
 	PCBLOCK_EMOTION  = 0x200,
-	PCBLOCK_ALL      = 0x3FF,
+	PCBLOCK_EQUIP    = 0x400,
+	PCBLOCK_NPC      = 0x58D,
+	PCBLOCK_ALL      = 0x7FF,
 };
 
 /* getiteminfo/setiteminfo script commands */

+ 112 - 98
src/map/skill.cpp

@@ -867,7 +867,7 @@ bool skill_isNotOk( uint16 skill_id, map_session_data& sd ){
 	uint32 skill_nocast = skill_get_nocast(skill_id);
 	// Check skill restrictions [Celest]
 	if (mapdata != nullptr && mapdata->zone->isSkillDisabled(skill_id, sd.bl)) {
-		clif_msg(&sd, SKILL_CANT_USE_AREA); // This skill cannot be used within this area
+		clif_msg(&sd, MSI_IMPOSSIBLE_SKILL_AREA); // This skill cannot be used within this area
 		return true;
 	}
 
@@ -884,7 +884,7 @@ bool skill_isNotOk( uint16 skill_id, map_session_data& sd ){
 		case ALL_THANATOS_RECALL:
 		case ALL_LIGHTHALZEN_RECALL:
 			if(mapdata->getMapFlag(MF_NOWARP)) {
-				clif_skill_teleportmessage(&sd,0);
+				clif_skill_teleportmessage( sd, NOTIFY_MAPINFO_CANT_TP );
 				return true;
 			}
 			return false;
@@ -894,7 +894,7 @@ bool skill_isNotOk( uint16 skill_id, map_session_data& sd ){
 		case ALL_ODINS_RECALL:
 		case WE_CALLALLFAMILY:
 			if(mapdata->getMapFlag(MF_NOTELEPORT)) {
-				clif_skill_teleportmessage(&sd,0);
+				clif_skill_teleportmessage( sd, NOTIFY_MAPINFO_CANT_TP );
 				return true;
 			}
 			return false; // gonna be checked in 'skill_castend_nodamage_id'
@@ -902,7 +902,7 @@ bool skill_isNotOk( uint16 skill_id, map_session_data& sd ){
 		case WE_CALLPARENT:
 		case WE_CALLBABY:
 			if (mapdata->getMapFlag(MF_NOMEMO)) {
-				clif_skill_teleportmessage(&sd,1);
+				clif_skill_teleportmessage( sd, NOTIFY_MAPINFO_CANT_MEMO );
 				return true;
 			}
 			break;
@@ -978,7 +978,7 @@ bool skill_isNotOk( uint16 skill_id, map_session_data& sd ){
 		case WM_GLOOMYDAY:
 		case WM_SATURDAY_NIGHT_FEVER:
 			if( !mapdata_flag_vs(mapdata) ) {
-				clif_skill_teleportmessage(&sd,2); // This skill uses this msg instead of skill fails.
+				clif_skill_teleportmessage( sd, NOTIFY_MAPINFO_CANT_USE_SKILL );	// This skill cannot be used in this area
 				return true;
 			}
 			break;
@@ -2584,12 +2584,11 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 		break;
 	case HFLI_SBR44:	//[orn]
 		if(src->type == BL_HOM){
-			struct homun_data *hd = (struct homun_data *)src;
-			if (hd != nullptr) {
-				hd->homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION);
-				if (hd->master)
-					clif_send_homdata(hd->master,SP_INTIMATE,hd->homunculus.intimacy / 100);
-			}
+			homun_data& hd = reinterpret_cast<homun_data&>( *src );
+
+			hd.homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION);
+
+			clif_send_homdata( hd, SP_INTIMATE );
 		}
 		break;
 	case CR_GRANDCROSS:
@@ -3206,9 +3205,8 @@ void skill_combo_toggle_inf(struct block_list* bl, uint16 skill_id, int inf){
 				TBL_HOM *hd = BL_CAST(BL_HOM, bl);
 				if (idx == -1)
 					break;
-				sd = hd->master;
 				hd->homunculus.hskill[idx].flag= flag;
-				if(sd) clif_homskillinfoblock(sd); //refresh info //@FIXME we only want to refresh one skill
+				clif_homskillinfoblock( *hd ); //refresh info //@FIXME we only want to refresh one skill
 			}
 			break;
 		case MO_COMBOFINISH:
@@ -3377,7 +3375,7 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
 			case 1: //Copied by Plagiarism
 				{
 					if (tsd->cloneskill_idx > 0 && tsd->status.skill[tsd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED) {
-						clif_deleteskill(tsd,tsd->status.skill[tsd->cloneskill_idx].id);
+						clif_deleteskill(tsd,tsd->status.skill[tsd->cloneskill_idx].id, true);
 						tsd->status.skill[tsd->cloneskill_idx].id = 0;
 						tsd->status.skill[tsd->cloneskill_idx].lv = 0;
 						tsd->status.skill[tsd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
@@ -3397,7 +3395,7 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
 					//Skill level copied depends on Reproduce skill that used
 					lv = (tsc) ? tsc->getSCE(SC__REPRODUCE)->val1 : 1;
 					if( tsd->reproduceskill_idx > 0 && tsd->status.skill[tsd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
-						clif_deleteskill(tsd,tsd->status.skill[tsd->reproduceskill_idx].id);
+						clif_deleteskill(tsd,tsd->status.skill[tsd->reproduceskill_idx].id, true);
 						tsd->status.skill[tsd->reproduceskill_idx].id = 0;
 						tsd->status.skill[tsd->reproduceskill_idx].lv = 0;
 						tsd->status.skill[tsd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
@@ -3493,7 +3491,8 @@ void skill_attack_blow(struct block_list *src, struct block_list *dsrc, struct b
 			}
 			break;
 	}
-	clif_fixpos(target);
+
+	clif_fixpos( *target );
 }
 
 /*
@@ -6621,11 +6620,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 		break;
 	case RA_WUGSTRIKE:
 		if( sd && pc_isridingwug(sd) ){
-			short x[8]={0,-1,-1,-1,0,1,1,1};
-			short y[8]={1,1,0,-1,-1,-1,0,1};
 			uint8 dir = map_calc_dir(bl, src->x, src->y);
 
-			if( unit_movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) ) {
+			if( unit_movepos(src, bl->x+dirx[dir], bl->y+diry[dir], 1, 1) ) {
 				clif_blown(src);
 				skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
 			}
@@ -8552,8 +8549,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		break;
 
 	case AC_MAKINGARROW:
-		if(sd) {
-			clif_arrow_create_list(sd);
+		if( sd != nullptr ){
+			clif_arrow_create_list( *sd );
 			clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
 		}
 		break;
@@ -8566,8 +8563,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		break;
 
 	case SA_CREATECON:
-		if(sd) {
-			clif_elementalconverter_list(sd);
+		if( sd != nullptr ){
+			clif_elementalconverter_list( *sd );
 			clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
 		}
 		break;
@@ -8828,12 +8825,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		}
 		status_damage(src, src, sstatus->max_hp,0,0,1, skill_id);
 		if(skill_id == HVAN_EXPLOSION && src->type == BL_HOM) {
-			struct homun_data *hd = (struct homun_data *)src;
-			if (hd != nullptr) {
-				hd->homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION);
-				if (hd->master)
-					clif_send_homdata(hd->master,SP_INTIMATE,hd->homunculus.intimacy / 100);
-			}
+			homun_data& hd = reinterpret_cast<homun_data&>( *src );
+
+			hd.homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION);
+
+			clif_send_homdata( hd, SP_INTIMATE );
 		}
 		break;
 	case AL_ANGELUS:
@@ -8996,7 +8992,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		}
 		clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,unit_getdir(bl),0,0,0));
 		if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex]
-			clif_walkok(sd); // So aegis has to resend the walk ok.
+			clif_walkok(*sd); // So aegis has to resend the walk ok.
 		break;
 
 	case AS_CLOAKING:
@@ -9282,8 +9278,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 
 	// Weapon Refining [Celest]
 	case WS_WEAPONREFINE:
-		if(sd)
-			clif_item_refine_list(sd);
+		if( sd != nullptr ){
+			clif_item_refine_list( *sd );
+		}
 		break;
 
 	case MC_VENDING:
@@ -9304,7 +9301,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				else{
 					// Instantly open the vending UI
 					sd->state.pending_vending_ui = false;
-					clif_openvendingreq(sd,2+skill_lv);
+					clif_openvendingreq( *sd, 2+skill_lv );
 				}
 			}
 		}
@@ -9315,7 +9312,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		if(sd)
 		{
 			if (map_getmapflag(bl->m, MF_NOTELEPORT) && skill_lv <= 2) {
-				clif_skill_teleportmessage(sd,0);
+				clif_skill_teleportmessage( *sd, NOTIFY_MAPINFO_CANT_TP );
 				break;
 			}
 			if(!battle_config.duel_allow_teleport && sd->duel_group && skill_lv <= 2) { // duel restriction [LuzZza]
@@ -9933,7 +9930,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			if (tbl) {
 				md->state.can_escape = 1;
 				mob_unlocktarget(md, tick);
-				unit_escape(src, tbl, skill_lv > 1 ? skill_lv : AREA_SIZE, 2); // Send distance in skill level > 1
+				// Official distance is 7, if level > 1, distance = level
+				t_tick time = unit_escape(src, tbl, skill_lv > 1 ? skill_lv : 7, 2);
+
+				if (time) {
+					// Need to set state here as it's not set otherwise
+					md->state.skillstate = MSS_WALK;
+					// Set AI to inactive for the duration of this movement
+					md->last_thinktime = tick + time;
+				}
 			}
 		}
 		break;
@@ -11330,7 +11335,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		}
 		if( sd && pc_isridingwug(sd) ) {
 			clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,bl,type,100,skill_lv,unit_getdir(bl),0,0,0));
-			clif_walkok(sd);
+			clif_walkok(*sd);
 		}
 		break;
 
@@ -11698,7 +11703,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			tstatus->sp -= tstatus->sp * ( 60 - 10 * skill_lv ) / 100;
 			clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
 			pc_revive((TBL_PC*)bl,heal,0);
-			clif_resurrection(bl,1);
+			clif_resurrection( *bl );
 		}
 		break;
 
@@ -13416,8 +13421,14 @@ TIMER_FUNC(skill_castend_id){
 			}
 			}
 		}
-		if (skill_get_state(ud->skill_id) != ST_MOVE_ENABLE)
-			unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skill_id, ud->skill_lv), 1);
+		if (skill_get_state(ud->skill_id) != ST_MOVE_ENABLE) {
+			// When monsters used a skill they won't walk for amotion, this does not apply to players
+			// This is also important for monster skill usage behavior
+			if (src->type == BL_MOB)
+				unit_set_walkdelay(src, tick, max((int)status_get_amotion(src), skill_get_walkdelay(ud->skill_id, ud->skill_lv)), 1);
+			else
+				unit_set_walkdelay(src, tick, battle_config.default_walk_delay + skill_get_walkdelay(ud->skill_id, ud->skill_lv), 1);
+		}
 
 		if(battle_config.skill_log && battle_config.skill_log&src->type)
 			ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n",
@@ -13631,7 +13642,12 @@ TIMER_FUNC(skill_castend_pos){
 //				break;
 //			}
 //		}
-		unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skill_id, ud->skill_lv), 1);
+		// When monsters used a skill they won't walk for amotion, this does not apply to players
+		// This is also important for monster skill usage behavior
+		if (src->type == BL_MOB)
+			unit_set_walkdelay(src, tick, max((int)status_get_amotion(src), skill_get_walkdelay(ud->skill_id, ud->skill_lv)), 1);
+		else
+			unit_set_walkdelay(src, tick, battle_config.default_walk_delay + skill_get_walkdelay(ud->skill_id, ud->skill_lv), 1);
 		map_freeblock_lock();
 		skill_castend_pos2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,tick,0);
 
@@ -15661,7 +15677,7 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, t_
 						if (td)
 							sec = DIFF_TICK(td->tick, tick);
 						map_moveblock(bl, unit->bl.x, unit->bl.y, tick);
-						clif_fixpos(bl);
+						clif_fixpos( *bl );
 					}
 					else
 						sec = 3000; //Couldn't trap it?
@@ -16202,13 +16218,13 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
 						|| !unit_blown_immune(bl,0x1) )
 					{
 						unit_movepos(bl, unit->bl.x, unit->bl.y, 0, 0);
-						clif_fixpos(bl);
+						clif_fixpos( *bl );
 					}
 					sg->val2 = bl->id;
 				} else
 					sec = 3000; //Couldn't trap it?
 				if (sg->unit_id == UNT_ANKLESNARE) {
-					clif_skillunit_update(&unit->bl);
+					clif_skillunit_update( unit->bl );
 					/**
 					 * If you're snared from a trap that was invisible this makes the trap be
 					 * visible again -- being you stepped on it (w/o this the trap remains invisible and you go "WTF WHY I CANT MOVE")
@@ -16231,7 +16247,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
 			if( bl->id != ss->id ) {
 				if( status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id, sg->skill_lv), SCSTART_NORATEDEF) ) {
 					map_moveblock(bl, unit->bl.x, unit->bl.y, tick);
-					clif_fixpos(bl);
+					clif_fixpos( *bl );
 				}
 				map_foreachinallrange(skill_trap_splash, &unit->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &unit->bl, tick);
 				sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again.
@@ -16543,7 +16559,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
 						if( td )
 							sec = DIFF_TICK(td->tick, tick);
 						///map_moveblock(bl, src->bl.x, src->bl.y, tick); // in official server it doesn't behave like this. [malufett]
-						clif_fixpos(bl);
+						clif_fixpos( *bl );
 						sg->val2 = bl->id;
 					} else
 						sec = 3000;	// Couldn't trap it?
@@ -17509,10 +17525,8 @@ bool skill_check_condition_castbegin( map_session_data& sd, uint16 skill_id, uin
 		{
 			if( skill_lv < 3 && ((sd.bl.type == BL_PC && battle_config.pc_cloak_check_type&1)
 			||	(sd.bl.type != BL_PC && battle_config.monster_cloak_check_type&1) )) { //Check for walls.
-				static int dx[DIR_MAX] = { 0, 1, 0, -1, -1,  1, 1, -1};
-				static int dy[DIR_MAX] = {-1, 0, 1,  0, -1, -1, 1,  1};
 				int dir;
-				ARR_FIND( 0, DIR_MAX, dir, map_getcell(sd.bl.m, sd.bl.x+dx[dir], sd.bl.y+dy[dir], CELL_CHKNOPASS) != 0 );
+				ARR_FIND( 0, DIR_MAX, dir, map_getcell(sd.bl.m, sd.bl.x+dirx[dir], sd.bl.y+diry[dir], CELL_CHKNOPASS) != 0 );
 				if( dir == DIR_MAX ) {
 					clif_skill_fail( sd, skill_id );
 					return false;
@@ -18260,7 +18274,7 @@ bool skill_check_condition_castbegin( map_session_data& sd, uint16 skill_id, uin
 						count--;
 						if (!count) {
 							if( skill_id == RL_P_ALTER ){
-								clif_msg( &sd, SKILL_NEED_HOLY_BULLET );
+								clif_msg( &sd, MSI_FAIL_NEED_EQUIPPED_PROPERTY_SAINT_BULLET );
 							}else{
 								clif_skill_fail( sd, skill_id, USESKILL_FAIL_THIS_WEAPON );
 							}
@@ -18309,19 +18323,19 @@ bool skill_check_condition_castbegin( map_session_data& sd, uint16 skill_id, uin
 			default:
 				switch((unsigned int)log2(require.weapon)) {
 					case W_REVOLVER:
-						clif_msg(&sd, SKILL_NEED_REVOLVER);
+						clif_msg(&sd, MSI_FAIL_NEED_EQUIPPED_GUN_HANDGUN);
 						break;
 					case W_RIFLE:
-						clif_msg(&sd, SKILL_NEED_RIFLE);
+						clif_msg(&sd, MSI_FAIL_NEED_EQUIPPED_GUN_RIFLE);
 						break;
 					case W_GATLING:
-						clif_msg(&sd, SKILL_NEED_GATLING);
+						clif_msg(&sd, MSI_FAIL_NEED_EQUIPPED_GUN_GATLING);
 						break;
 					case W_SHOTGUN:
-						clif_msg(&sd, SKILL_NEED_SHOTGUN);
+						clif_msg(&sd, MSI_FAIL_NEED_EQUIPPED_GUN_SHOTGUN);
 						break;
 					case W_GRENADE:
-						clif_msg(&sd, SKILL_NEED_GRENADE);
+						clif_msg(&sd, MSI_FAIL_NEED_EQUIPPED_GUN_GRANADE);
 						break;
 					default:
 						clif_skill_fail( sd, skill_id, USESKILL_FAIL_THIS_WEAPON );
@@ -18576,7 +18590,7 @@ bool skill_check_condition_castend( map_session_data& sd, uint16 skill_id, uint1
 		}
 #endif
 		if((i=sd.equip_index[EQI_AMMO]) < 0 || !sd.inventory_data[i] ) {
-			clif_arrow_fail(&sd,0);
+			clif_arrow_fail( sd, ARROWFAIL_NO_AMMO );
 			return false;
 		} else if( sd.inventory.u.items_inventory[i].amount < require.ammo_qty + extra_ammo ) {
 			char e_msg[100];
@@ -18597,7 +18611,7 @@ bool skill_check_condition_castend( map_session_data& sd, uint16 skill_id, uint1
 		}
 		if (!(require.ammo&1<<sd.inventory_data[i]->subtype)) { //Ammo type check. Send the "wrong weapon type" message
 			//which is the closest we have to wrong ammo type. [Skotlex]
-			clif_arrow_fail(&sd,0); //Haplo suggested we just send the equip-arrows message instead. [Skotlex]
+			clif_arrow_fail( sd, ARROWFAIL_NO_AMMO ); //Haplo suggested we just send the equip-arrows message instead. [Skotlex]
 			//clif_skill_fail( sd, skill_id, USESKILL_FAIL_THIS_WEAPON );
 			return false;
 		}
@@ -19575,7 +19589,7 @@ void skill_repairweapon( map_session_data& sd, int idx ){
 		return;
 
 	if (sd.status.char_id != target_sd->status.char_id && !battle_check_range(&sd.bl, &target_sd->bl, skill_get_range2(&sd.bl, sd.menuskill_id, sd.menuskill_val2, true))) {
-		clif_item_repaireffect(&sd, idx, 1);
+		clif_item_repaireffect( sd, idx, true );
 		return;
 	}
 
@@ -19598,10 +19612,10 @@ void skill_repairweapon( map_session_data& sd, int idx ){
 
 	pc_delitem(&sd,pc_search_inventory(&sd,material),1,0,0,LOG_TYPE_CONSUME);
 
-	clif_item_repaireffect(&sd,idx,0);
+	clif_item_repaireffect( sd, idx, false );
 
 	if( sd.status.char_id != target_sd->status.char_id )
-		clif_item_repaireffect(target_sd,idx,0);
+		clif_item_repaireffect( *target_sd, idx, false );
 }
 
 /*==========================================
@@ -19609,7 +19623,7 @@ void skill_repairweapon( map_session_data& sd, int idx ){
  *------------------------------------------*/
 void skill_identify(map_session_data *sd, int idx)
 {
-	int flag=1;
+	bool failure = true;
 
 	nullpo_retv(sd);
 
@@ -19617,11 +19631,11 @@ void skill_identify(map_session_data *sd, int idx)
 
 	if(idx >= 0 && idx < MAX_INVENTORY) {
 		if(sd->inventory.u.items_inventory[idx].nameid > 0 && sd->inventory.u.items_inventory[idx].identify == 0 ){
-			flag=0;
+			failure = false;
 			sd->inventory.u.items_inventory[idx].identify = 1;
 		}
 	}
-	clif_item_identified(sd,idx,flag);
+	clif_item_identified( *sd, idx, failure );
 }
 
 /*==========================================
@@ -19696,16 +19710,16 @@ void skill_weaponrefine( map_session_data& sd, int idx ){
 					ep = item->equip;
 					pc_unequipitem(&sd,idx,3);
 				}
-				clif_delitem(&sd,idx,1,3);
+				clif_delitem(sd,idx,1,3);
 				clif_upgrademessage(&sd, 0, item->nameid);
 				clif_inventorylist(&sd);
-				clif_refine(sd.fd,0,idx,item->refine);
+				clif_refine( sd, idx, ITEMREFINING_SUCCESS );
 				if( ditem->type == IT_WEAPON ){
 					achievement_update_objective(&sd, AG_ENCHANT_SUCCESS, 2, ditem->weapon_level, item->refine);
 				}
 				if (ep)
 					pc_equipitem(&sd,idx,ep);
-				clif_misceffect(&sd.bl,3);
+				clif_misceffect( sd.bl, NOTIFYEFFECT_REFINE_SUCCESS );
 				if(item->refine == 10 &&
 					item->card[0] == CARD0_FORGE &&
 					(int)MakeDWord(item->card[2],item->card[3]) == sd.status.char_id)
@@ -19727,10 +19741,10 @@ void skill_weaponrefine( map_session_data& sd, int idx ){
 				if(item->equip)
 					pc_unequipitem(&sd,idx,3);
 				clif_upgrademessage(&sd, 1, item->nameid);
-				clif_refine(sd.fd,1,idx,item->refine);
+				clif_refine( sd, idx, ITEMREFINING_FAILURE );
 				achievement_update_objective(&sd, AG_ENCHANT_FAIL, 1, 1);
 				pc_delitem(&sd,idx,1,0,2, LOG_TYPE_OTHER);
-				clif_misceffect(&sd.bl,2);
+				clif_misceffect( sd.bl, NOTIFYEFFECT_REFINE_FAILURE );
 				clif_emotion(&sd.bl, ET_HUK);
 			}
 		}
@@ -20431,7 +20445,7 @@ static int skill_trap_splash(struct block_list *bl, va_list ap)
 					break;
 				if (status_change_start(ss, bl, SC_ELECTRICSHOCKER, 10000, sg->skill_lv, sg->group_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), SCSTART_NORATEDEF)) {
 					map_moveblock(bl, unit->bl.x, unit->bl.y, tick);
-					clif_fixpos(bl);
+					clif_fixpos( *bl );
 					clif_skill_damage(src, bl, tick, 0, 0, -30000, 1, sg->skill_id, sg->skill_lv, DMG_SPLASH);
 				}
 			}
@@ -20855,7 +20869,7 @@ int skill_delunit(struct skill_unit* unit)
 			break;
 	}
 
-	clif_skill_delunit(unit);
+	clif_skill_delunit( *unit );
 
 	unit->group=nullptr;
 	map_delblock(&unit->bl); // don't free yet
@@ -22294,7 +22308,7 @@ bool skill_produce_mix(map_session_data *sd, uint16 skill_id, t_itemid nameid, i
 
 		if (equip) {
 			clif_produceeffect(sd,0,nameid);
-			clif_misceffect(&sd->bl,3);
+			clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 			if (wlv >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG]
 				pc_addfame(*sd, battle_config.fame_forge); // Success to forge a lv3 weapon with 3 additional ingredients = +10 fame point
 		} else {
@@ -22346,13 +22360,13 @@ bool skill_produce_mix(map_session_data *sd, uint16 skill_id, t_itemid nameid, i
 				case ASC_CDP:
 				case GC_CREATENEWPOISON:
 					clif_produceeffect(sd,2,nameid);
-					clif_misceffect(&sd->bl,5);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_SUCCESS );
 					break;
 				case BS_IRON:
 				case BS_STEEL:
 				case BS_ENCHANTEDSTONE:
 					clif_produceeffect(sd,0,nameid);
-					clif_misceffect(&sd->bl,3);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
 					break;
 				default: //Those that don't require a skill?
 					if (skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20) { //Cooking items.
@@ -22389,8 +22403,8 @@ bool skill_produce_mix(map_session_data *sd, uint16 skill_id, t_itemid nameid, i
 			}
 			if (k) {
 				clif_produceeffect(sd,6,nameid);
-				clif_misceffect(&sd->bl,5);
-				clif_msg_skill(sd,skill_id,ITEM_PRODUCE_SUCCESS);
+				clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_SUCCESS );
+				clif_msg_skill(sd,skill_id, MSI_SKILL_SUCCESS);
 				return true;
 			}
 		} else if (tmp_item.amount) { //Success
@@ -22403,24 +22417,24 @@ bool skill_produce_mix(map_session_data *sd, uint16 skill_id, t_itemid nameid, i
 			switch (skill_id) {
 				case RK_RUNEMASTERY:
 					clif_produceeffect(sd, 4, nameid);
-					clif_misceffect(&sd->bl, 5);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_SUCCESS );
 					break;
 				case GN_MIX_COOKING:
 				case GN_MAKEBOMB:
 				case GN_S_PHARMACY:
 					clif_produceeffect(sd, 6, nameid);
-					clif_misceffect(&sd->bl, 5);
-					clif_msg_skill(sd, skill_id, ITEM_PRODUCE_SUCCESS);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_SUCCESS );
+					clif_msg_skill(sd, skill_id, MSI_SKILL_SUCCESS);
 					break;
 				case MT_M_MACHINE:
 					clif_produceeffect(sd, 0, nameid);
-					clif_misceffect(&sd->bl, 3);
-					clif_msg_skill(sd, skill_id, ITEM_PRODUCE_SUCCESS);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_SUCCESS );
+					clif_msg_skill(sd, skill_id, MSI_SKILL_SUCCESS);
 					break;
 				case BO_BIONIC_PHARMACY:
 					clif_produceeffect(sd, 2, nameid);
-					clif_misceffect(&sd->bl, 5);
-					clif_msg_skill(sd, skill_id, ITEM_PRODUCE_SUCCESS);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_SUCCESS );
+					clif_msg_skill(sd, skill_id, MSI_SKILL_SUCCESS);
 					break;
 			}
 			return true;
@@ -22434,7 +22448,7 @@ bool skill_produce_mix(map_session_data *sd, uint16 skill_id, t_itemid nameid, i
 
 	if (equip) {
 		clif_produceeffect(sd,1,nameid);
-		clif_misceffect(&sd->bl,2);
+		clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_FAILURE );
 	} else {
 		switch (skill_id) {
 			case ASC_CDP: //25% Damage yourself, and display same effect as failed potion.
@@ -22446,18 +22460,18 @@ bool skill_produce_mix(map_session_data *sd, uint16 skill_id, t_itemid nameid, i
 			case AM_TWILIGHT3:
 			case GC_CREATENEWPOISON:
 				clif_produceeffect(sd,3,nameid);
-				clif_misceffect(&sd->bl,6);
+				clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_FAILURE );
 				sd->potion_success_counter = 0; // Fame point system [DracoRPG]
 				break;
 			case BS_IRON:
 			case BS_STEEL:
 			case BS_ENCHANTEDSTONE:
 				clif_produceeffect(sd,1,nameid);
-				clif_misceffect(&sd->bl,2);
+				clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_FAILURE );
 				break;
 			case RK_RUNEMASTERY:
 				clif_produceeffect(sd,5,nameid);
-				clif_misceffect(&sd->bl,6);
+				clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_FAILURE );
 				break;
 			case GN_MIX_COOKING:
 				if (qty == 0) {
@@ -22488,26 +22502,26 @@ bool skill_produce_mix(map_session_data *sd, uint16 skill_id, t_itemid nameid, i
 						}
 					}
 					clif_produceeffect(sd,7,nameid);
-					clif_misceffect(&sd->bl,6);
-					clif_msg_skill(sd,skill_id,ITEM_PRODUCE_FAIL);
+					clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_FAILURE );
+					clif_msg_skill(sd, skill_id, MSI_SKILL_FAIL);
 				}
 				break;
 			case GN_MAKEBOMB:
 			case GN_S_PHARMACY:
 			case GN_CHANGEMATERIAL:
 				clif_produceeffect(sd,7,nameid);
-				clif_misceffect(&sd->bl,6);
-				clif_msg_skill(sd,skill_id,ITEM_PRODUCE_FAIL);
+				clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_FAILURE );
+				clif_msg_skill(sd, skill_id, MSI_SKILL_FAIL);
 				break;
 			case MT_M_MACHINE:
 				clif_produceeffect(sd, 1, nameid);
-				clif_misceffect(&sd->bl, 2);
-				clif_msg_skill(sd, skill_id, ITEM_PRODUCE_FAIL);
+				clif_misceffect( sd->bl, NOTIFYEFFECT_REFINE_FAILURE );
+				clif_msg_skill(sd, skill_id, MSI_SKILL_FAIL);
 				break;
 			case BO_BIONIC_PHARMACY:
 				clif_produceeffect(sd, 3, nameid);
-				clif_misceffect(&sd->bl, 6);
-				clif_msg_skill(sd, skill_id, ITEM_PRODUCE_FAIL);
+				clif_misceffect( sd->bl, NOTIFYEFFECT_PHARMACY_FAILURE );
+				clif_msg_skill(sd, skill_id, MSI_SKILL_FAIL);
 				break;
 			default:
 				if (skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20 ) { //Cooking items.
@@ -22638,8 +22652,8 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id)
 			sc->getSCE(SC_MAGICPOWER)->val4 = 1;
 			status_calc_bl_(bl, status_db.getCalcFlag(SC_MAGICPOWER));
 			if(bl->type == BL_PC){// update current display.
-				clif_updatestatus(((TBL_PC *)bl),SP_MATK1);
-				clif_updatestatus(((TBL_PC *)bl),SP_MATK2);
+				clif_updatestatus(*((map_session_data *)bl),SP_MATK1);
+				clif_updatestatus(*((map_session_data *)bl),SP_MATK2);
 			}
 		}
 	}
@@ -22869,7 +22883,7 @@ int skill_changematerial(map_session_data *sd, int n, unsigned short *item_list)
 							nameid = sd->inventory.u.items_inventory[idx].nameid;
 							amount = item_list[k*2+1];
 							if( nameid > 0 && sd->inventory.u.items_inventory[idx].identify == 0 ){
-								clif_msg_skill(sd,GN_CHANGEMATERIAL,ITEM_UNIDENTIFIED);
+								clif_msg_skill(sd, GN_CHANGEMATERIAL, MSI_SKILL_FAIL_MATERIAL_IDENTITY);
 								return 0;
 							}
 							if( nameid == skill_produce_db[i].mat_id[j] && (amount-p*skill_produce_db[i].mat_amount[j]) >= skill_produce_db[i].mat_amount[j]
@@ -22891,7 +22905,7 @@ int skill_changematerial(map_session_data *sd, int n, unsigned short *item_list)
 	}
 
 	if( p == 0)
-		clif_msg_skill(sd,GN_CHANGEMATERIAL,ITEM_CANT_COMBINE);
+		clif_msg_skill(sd, GN_CHANGEMATERIAL, MSI_SKILL_RECIPE_NOTEXIST);
 
 	return 0;
 }
@@ -22994,7 +23008,7 @@ int skill_blockpc_start(map_session_data *sd, int skill_id, t_tick tick) {
 		sd->scd[i]->timer = add_timer(gettick() + tick, skill_blockpc_end, sd->bl.id, i);
 
 		if (battle_config.display_status_timers)
-			clif_skill_cooldown(sd, skill_id, tick);
+			clif_skill_cooldown( *sd, skill_id, tick );
 
 		return 1;
 	} else {

+ 0 - 4
src/map/skill.hpp

@@ -183,10 +183,6 @@ enum e_skill_unit_flag : uint8 {
 	UF_MAX,
 };
 
-/// Walk intervals at which chase-skills are attempted to be triggered.
-/// If you change this, make sure it's an odd value (for icewall block behavior).
-#define WALK_SKILL_INTERVAL 5
-
 /// Time that's added to canact delay on castbegin and substracted on castend
 /// This is to prevent hackers from sending a skill packet after cast but before a timer triggers castend
 const t_tick SECURITY_CASTTIME = 100;

+ 63 - 63
src/map/status.cpp

@@ -1660,7 +1660,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 		unit_stop_attack(target);
 		unit_stop_walking(target,1);
 		unit_skillcastcancel(target,0);
-		clif_clearunit_area(target,CLR_DEAD);
+		clif_clearunit_area( *target, CLR_DEAD );
 		skill_unit_move(target,gettick(),4);
 		skill_cleartimerskill(target);
 	}
@@ -1910,7 +1910,7 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per
 	status->ap += ap;
 
 	if (bl->prev) // Animation only if character is already on a map.
-		clif_resurrection(bl, 1);
+		clif_resurrection( *bl );
 	switch (bl->type) {
 		case BL_PC:  pc_revive((TBL_PC*)bl, hp, sp, ap); break;
 		case BL_MOB: mob_revive((TBL_MOB*)bl, hp); break;
@@ -1964,7 +1964,7 @@ bool status_check_skilluse(struct block_list *src, struct block_list *target, ui
 
 		if (mapdata != nullptr && mapdata->zone->isSkillDisabled(skill_id, sd->bl)) {
 			if (sd != nullptr)
-				clif_msg(sd, SKILL_CANT_USE_AREA); // This skill cannot be used within this area
+				clif_msg(sd, MSI_IMPOSSIBLE_SKILL_AREA); // This skill cannot be used within this area
 			return false;
 		}
 	}
@@ -2996,7 +2996,7 @@ void status_calc_pet_(struct pet_data *pd, uint8 opt)
 
 			pd->pet.level = lv;
 			if (!(opt&SCO_FIRST)) // Lv Up animation
-				clif_misceffect(&pd->bl, 0);
+				clif_misceffect( pd->bl, NOTIFYEFFECT_BASE_LEVEL_UP );
 			status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv;
 			status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv;
 			status->str = (bstat->str*lv)/pd->db->lv;
@@ -3564,9 +3564,9 @@ bool status_calc_weight(map_session_data *sd, enum e_status_calc_weight_opt flag
 
 	// Update the client if the new weight calculations don't match
 	if (b_weight != sd->weight)
-		clif_updatestatus(sd, SP_WEIGHT);
+		clif_updatestatus(*sd, SP_WEIGHT);
 	if (b_max_weight != sd->max_weight) {
-		clif_updatestatus(sd, SP_MAXWEIGHT);
+		clif_updatestatus(*sd, SP_MAXWEIGHT);
 		pc_updateweightstatus(sd);
 	}
 
@@ -3612,7 +3612,7 @@ bool status_calc_cart_weight(map_session_data *sd, enum e_status_calc_weight_opt
 
 	// Update the client if the new weight calculations don't match
 	if (b_cart_weight_max != sd->cart_weight_max)
-		clif_updatestatus(sd, SP_CARTINFO);
+		clif_updatestatus(*sd, SP_CARTINFO);
 
 	return true;
 }
@@ -5920,7 +5920,7 @@ void status_calc_bl_main(struct block_list *bl, std::bitset<SCB_MAX> flag)
 
 		if( status->hp > status->max_hp ) { // !FIXME: Should perhaps a status_zap should be issued?
 			status->hp = status->max_hp;
-			if( sd ) clif_updatestatus(sd,SP_HP);
+			if( sd ) clif_updatestatus(*sd,SP_HP);
 		}
 	}
 
@@ -5938,7 +5938,7 @@ void status_calc_bl_main(struct block_list *bl, std::bitset<SCB_MAX> flag)
 
 		if( status->sp > status->max_sp ) {
 			status->sp = status->max_sp;
-			if( sd ) clif_updatestatus(sd,SP_SP);
+			if( sd ) clif_updatestatus(*sd,SP_SP);
 		}
 	}
 
@@ -6164,7 +6164,7 @@ void status_calc_bl_main(struct block_list *bl, std::bitset<SCB_MAX> flag)
 
 		if (status->ap > status->max_ap) {
 			status->ap = status->max_ap;
-			if (sd) clif_updatestatus(sd, SP_AP);
+			if (sd) clif_updatestatus(*sd, SP_AP);
 		}
 	}
 #endif
@@ -6234,37 +6234,37 @@ void status_calc_bl_(struct block_list* bl, std::bitset<SCB_MAX> flag, uint8 opt
 		TBL_PC* sd = BL_CAST(BL_PC, bl);
 
 		if(b_status.str != status->str)
-			clif_updatestatus(sd,SP_STR);
+			clif_updatestatus(*sd,SP_STR);
 		if(b_status.agi != status->agi)
-			clif_updatestatus(sd,SP_AGI);
+			clif_updatestatus(*sd,SP_AGI);
 		if(b_status.vit != status->vit)
-			clif_updatestatus(sd,SP_VIT);
+			clif_updatestatus(*sd,SP_VIT);
 		if(b_status.int_ != status->int_)
-			clif_updatestatus(sd,SP_INT);
+			clif_updatestatus(*sd,SP_INT);
 		if(b_status.dex != status->dex)
-			clif_updatestatus(sd,SP_DEX);
+			clif_updatestatus(*sd,SP_DEX);
 		if(b_status.luk != status->luk)
-			clif_updatestatus(sd,SP_LUK);
+			clif_updatestatus(*sd,SP_LUK);
 		if(b_status.hit != status->hit)
-			clif_updatestatus(sd,SP_HIT);
+			clif_updatestatus(*sd,SP_HIT);
 		if(b_status.flee != status->flee)
-			clif_updatestatus(sd,SP_FLEE1);
+			clif_updatestatus(*sd,SP_FLEE1);
 		if(b_status.amotion != status->amotion)
-			clif_updatestatus(sd,SP_ASPD);
+			clif_updatestatus(*sd,SP_ASPD);
 		if(b_status.speed != status->speed)
-			clif_updatestatus(sd,SP_SPEED);
+			clif_updatestatus(*sd,SP_SPEED);
 
 		if(b_status.batk != status->batk
 #ifndef RENEWAL
 			|| b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk
 #endif
 			)
-			clif_updatestatus(sd,SP_ATK1);
+			clif_updatestatus(*sd,SP_ATK1);
 
 		if(b_status.def != status->def) {
-			clif_updatestatus(sd,SP_DEF1);
+			clif_updatestatus(*sd,SP_DEF1);
 #ifdef RENEWAL
-			clif_updatestatus(sd,SP_DEF2);
+			clif_updatestatus(*sd,SP_DEF2);
 #endif
 		}
 
@@ -6275,80 +6275,80 @@ void status_calc_bl_(struct block_list* bl, std::bitset<SCB_MAX> flag, uint8 opt
 			b_status.rhw.atk2 != status->rhw.atk2 || b_status.lhw.atk2 != status->lhw.atk2
 #endif
 			)
-			clif_updatestatus(sd,SP_ATK2);
+			clif_updatestatus(*sd,SP_ATK2);
 
 		if(b_status.def2 != status->def2) {
-			clif_updatestatus(sd,SP_DEF2);
+			clif_updatestatus(*sd,SP_DEF2);
 #ifdef RENEWAL
-			clif_updatestatus(sd,SP_DEF1);
+			clif_updatestatus(*sd,SP_DEF1);
 #endif
 		}
 		if(b_status.flee2 != status->flee2)
-			clif_updatestatus(sd,SP_FLEE2);
+			clif_updatestatus(*sd,SP_FLEE2);
 		if(b_status.cri != status->cri)
-			clif_updatestatus(sd,SP_CRITICAL);
+			clif_updatestatus(*sd,SP_CRITICAL);
 #ifndef RENEWAL
 		if(b_status.matk_max != status->matk_max)
-			clif_updatestatus(sd,SP_MATK1);
+			clif_updatestatus(*sd,SP_MATK1);
 		if(b_status.matk_min != status->matk_min)
-			clif_updatestatus(sd,SP_MATK2);
+			clif_updatestatus(*sd,SP_MATK2);
 #else
 		if(b_status.matk_max != status->matk_max || b_status.matk_min != status->matk_min) {
-			clif_updatestatus(sd,SP_MATK2);
-			clif_updatestatus(sd,SP_MATK1);
+			clif_updatestatus(*sd,SP_MATK2);
+			clif_updatestatus(*sd,SP_MATK1);
 		}
 #endif
 		if(b_status.mdef != status->mdef) {
-			clif_updatestatus(sd,SP_MDEF1);
+			clif_updatestatus(*sd,SP_MDEF1);
 #ifdef RENEWAL
-			clif_updatestatus(sd,SP_MDEF2);
+			clif_updatestatus(*sd,SP_MDEF2);
 #endif
 		}
 		if(b_status.mdef2 != status->mdef2) {
-			clif_updatestatus(sd,SP_MDEF2);
+			clif_updatestatus(*sd,SP_MDEF2);
 #ifdef RENEWAL
-			clif_updatestatus(sd,SP_MDEF1);
+			clif_updatestatus(*sd,SP_MDEF1);
 #endif
 		}
 		if(b_status.rhw.range != status->rhw.range)
-			clif_updatestatus(sd,SP_ATTACKRANGE);
+			clif_updatestatus(*sd,SP_ATTACKRANGE);
 		if(b_status.max_hp != status->max_hp)
-			clif_updatestatus(sd,SP_MAXHP);
+			clif_updatestatus(*sd,SP_MAXHP);
 		if(b_status.max_sp != status->max_sp)
-			clif_updatestatus(sd,SP_MAXSP);
+			clif_updatestatus(*sd,SP_MAXSP);
 		if(b_status.hp != status->hp)
-			clif_updatestatus(sd,SP_HP);
+			clif_updatestatus(*sd,SP_HP);
 		if(b_status.sp != status->sp)
-			clif_updatestatus(sd,SP_SP);
+			clif_updatestatus(*sd,SP_SP);
 #ifdef RENEWAL
 		if (b_status.pow != status->pow)
-			clif_updatestatus(sd,SP_POW);
+			clif_updatestatus(*sd,SP_POW);
 		if (b_status.sta != status->sta)
-			clif_updatestatus(sd,SP_STA);
+			clif_updatestatus(*sd,SP_STA);
 		if (b_status.wis != status->wis)
-			clif_updatestatus(sd,SP_WIS);
+			clif_updatestatus(*sd,SP_WIS);
 		if (b_status.spl != status->spl)
-			clif_updatestatus(sd,SP_SPL);
+			clif_updatestatus(*sd,SP_SPL);
 		if (b_status.con != status->con)
-			clif_updatestatus(sd,SP_CON);
+			clif_updatestatus(*sd,SP_CON);
 		if (b_status.crt != status->crt)
-			clif_updatestatus(sd,SP_CRT);
+			clif_updatestatus(*sd,SP_CRT);
 		if (b_status.patk != status->patk)
-			clif_updatestatus(sd, SP_PATK);
+			clif_updatestatus(*sd, SP_PATK);
 		if (b_status.smatk != status->smatk)
-			clif_updatestatus(sd, SP_SMATK);
+			clif_updatestatus(*sd, SP_SMATK);
 		if (b_status.res != status->res)
-			clif_updatestatus(sd, SP_RES);
+			clif_updatestatus(*sd, SP_RES);
 		if (b_status.mres != status->mres)
-			clif_updatestatus(sd, SP_MRES);
+			clif_updatestatus(*sd, SP_MRES);
 		if (b_status.hplus != status->hplus)
-			clif_updatestatus(sd, SP_HPLUS);
+			clif_updatestatus(*sd, SP_HPLUS);
 		if (b_status.crate != status->crate)
-			clif_updatestatus(sd, SP_CRATE);
+			clif_updatestatus(*sd, SP_CRATE);
 		if (b_status.max_ap != status->max_ap)
-			clif_updatestatus(sd, SP_MAXAP);
+			clif_updatestatus(*sd, SP_MAXAP);
 		if (b_status.ap != status->ap)
-			clif_updatestatus(sd, SP_AP);
+			clif_updatestatus(*sd, SP_AP);
 #endif
 	} else if( bl->type == BL_HOM ) {
 		TBL_HOM* hd = BL_CAST(BL_HOM, bl);
@@ -10897,8 +10897,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			tick = 60000;
 			val1 = battle_config.manner_system; // Mute filters.
 			if (sd) {
-				clif_changestatus(sd,SP_MANNER,sd->status.manner);
-				clif_updatestatus(sd,SP_MANNER);
+				clif_changemanner( *sd );
+				clif_updatestatus(*sd,SP_MANNER);
 			}
 			break;
 
@@ -13401,8 +13401,8 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 			if (sd && sd->status.manner < 0 && tid != INVALID_TIMER)
 				sd->status.manner = 0;
 			if (sd && tid == INVALID_TIMER) {
-				clif_changestatus(sd,SP_MANNER,sd->status.manner);
-				clif_updatestatus(sd,SP_MANNER);
+				clif_changemanner( *sd );
+				clif_updatestatus(*sd,SP_MANNER);
 			}
 			break;
 		case SC_SPLASHER:
@@ -13813,7 +13813,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 	clif_status_change(bl,status_icon,0,0,0,0,0);
 
 	if( opt_flag[SCF_NONPLAYER] ) // bugreport:681
-		clif_changeoption2(bl);
+		clif_changeoption2( *bl );
 	else if (!disable_opt_flag && (opt_flag[SCF_SENDOPTION] || opt_flag[SCF_ONTOUCH] || opt_flag[SCF_UNITMOVE] || opt_flag[SCF_NONPLAYER] || opt_flag[SCF_SENDLOOK])) {
 		clif_changeoption(bl);
 		if (sd && opt_flag[SCF_SENDLOOK]) {
@@ -14222,8 +14222,8 @@ TIMER_FUNC(status_change_timer){
 	case SC_NOCHAT:
 		if(sd) {
 			sd->status.manner++;
-			clif_changestatus(sd,SP_MANNER,sd->status.manner);
-			clif_updatestatus(sd,SP_MANNER);
+			clif_changemanner( *sd );
+			clif_updatestatus(*sd,SP_MANNER);
 			if (sd->status.manner < 0) { // Every 60 seconds your manner goes up by 1 until it gets back to 0.
 				sc_timer_next(60000+tick);
 				return 0;
@@ -14712,7 +14712,7 @@ TIMER_FUNC(status_change_timer){
 
 				if (distance_xy(x, y, bl->x, bl->y) <= skill_get_unit_range(SO_VACUUM_EXTREME, sce->val1) && unit_movepos(bl, x, y, 0, false)) {
 					clif_slide(bl, x, y);
-					clif_fixpos(bl);
+					clif_fixpos( *bl );
 				}
 			}
 			sc_timer_next(tick + sce->val4);

+ 2 - 1
src/map/status.hpp

@@ -3172,7 +3172,7 @@ struct status_data {
 #endif
 		matk_min, matk_max,
 		speed,
-		amotion, adelay, dmotion;
+		amotion, clientamotion, adelay, dmotion;
 	int mode;
 	short
 		hit, flee, cri, flee2,
@@ -3392,6 +3392,7 @@ defType status_get_def(struct block_list *bl);
 unsigned short status_get_speed(struct block_list *bl);
 #define status_get_adelay(bl) status_get_status_data(bl)->adelay
 #define status_get_amotion(bl) status_get_status_data(bl)->amotion
+#define status_get_clientamotion(bl) status_get_status_data(bl)->clientamotion
 #define status_get_dmotion(bl) status_get_status_data(bl)->dmotion
 #define status_get_patk(bl) status_get_status_data(bl)->patk
 #define status_get_smatk(bl) status_get_status_data(bl)->smatk

+ 33 - 27
src/map/storage.cpp

@@ -145,7 +145,7 @@ int storage_storageopen(map_session_data *sd)
 	sd->state.storage_flag = 1;
 	storage_sortitem(sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage));
 	clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage), storage_getName(0));
-	clif_updatestorageamount(sd, sd->storage.amount, sd->storage.max_amount);
+	clif_updatestorageamount(*sd, sd->storage.amount, sd->storage.max_amount);
 
 	return 0;
 }
@@ -290,7 +290,7 @@ static int storage_additem(map_session_data* sd, struct s_storage *stor, struct
 	stor->u.items_storage[i].amount = amount;
 	stor->dirty = true;
 	clif_storageitemadded(sd,&stor->u.items_storage[i],i,amount);
-	clif_updatestorageamount(sd, stor->amount, stor->max_amount);
+	clif_updatestorageamount(*sd, stor->amount, stor->max_amount);
 
 	return 0;
 }
@@ -314,11 +314,11 @@ int storage_delitem(map_session_data* sd, struct s_storage *stor, int index, int
 		memset(&stor->u.items_storage[index],0,sizeof(stor->u.items_storage[0]));
 		stor->amount--;
 		if( sd->state.storage_flag == 1 || sd->state.storage_flag == 3 )
-			clif_updatestorageamount(sd, stor->amount, stor->max_amount);
+			clif_updatestorageamount(*sd, stor->amount, stor->max_amount);
 	}
 
 	if( sd->state.storage_flag == 1 || sd->state.storage_flag == 3 )
-		clif_storageitemremoved(sd,index,amount);
+		clif_storageitemremoved( *sd, index, amount );
 
 	return 0;
 }
@@ -353,8 +353,8 @@ void storage_storageadd(map_session_data* sd, struct s_storage *stor, int index,
 		}
 	}
 
-	clif_storageitemremoved(sd,index,0);
-	clif_dropitem(sd,index,0);
+	clif_storageitemremoved( *sd, index, 0 );
+	clif_dropitem( *sd, index, 0 );
 }
 
 /**
@@ -378,7 +378,7 @@ void storage_storageget(map_session_data *sd, struct s_storage *stor, int index,
 	if ((flag = pc_additem(sd,&stor->u.items_storage[index],amount,LOG_TYPE_STORAGE)) == ADDITEM_SUCCESS)
 		storage_delitem(sd,stor,index,amount);
 	else {
-		clif_storageitemremoved(sd,index,0);
+		clif_storageitemremoved( *sd, index, 0 );
 		clif_additem(sd,0,0,flag);
 	}
 }
@@ -416,8 +416,8 @@ void storage_storageaddfromcart(map_session_data *sd, struct s_storage *stor, in
 		}
 	}
 
-	clif_storageitemremoved(sd,index,0);
-	clif_dropitem(sd,index,0);
+	clif_storageitemremoved( *sd, index, 0 );
+	clif_dropitem( *sd, index, 0 );
 }
 
 /**
@@ -446,8 +446,11 @@ void storage_storagegettocart(map_session_data* sd, struct s_storage *stor, int
 	if ((flag = pc_cart_additem(sd,&stor->u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0)
 		storage_delitem(sd,stor,index,amount);
 	else {
-		clif_storageitemremoved(sd,index,0);
-		clif_cart_additem_ack(sd,(flag==1)?ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT);
+		clif_storageitemremoved( *sd, index, 0 );
+		if (flag == ADDITEM_INVALID)
+			clif_cart_additem_ack( *sd, ADDITEM_TO_CART_FAIL_WEIGHT );
+		else
+			clif_cart_additem_ack( *sd, ADDITEM_TO_CART_FAIL_COUNT );
 	}
 }
 
@@ -480,7 +483,7 @@ void storage_storageclose(map_session_data *sd)
 	
 	if( sd->state.storage_flag == 1 ){
 		sd->state.storage_flag = 0;
-		clif_storageclose( sd );
+		clif_storageclose( *sd );
 	}
 }
 
@@ -600,7 +603,7 @@ char storage_guild_storageopen(map_session_data* sd)
 	sd->state.storage_flag = 2;
 	storage_sortitem(gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild));
 	clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild), "Guild Storage");
-	clif_updatestorageamount(sd, gstor->amount, gstor->max_amount);
+	clif_updatestorageamount(*sd, gstor->amount, gstor->max_amount);
 
 	return GSTORAGE_OPEN;
 }
@@ -777,7 +780,7 @@ bool storage_guild_additem(map_session_data* sd, struct s_storage* stor, struct
 	stor->u.items_guild[i].amount = amount;
 	stor->amount++;
 	clif_storageitemadded(sd,&stor->u.items_guild[i],i,amount);
-	clif_updatestorageamount(sd, stor->amount, stor->max_amount);
+	clif_updatestorageamount(*sd, stor->amount, stor->max_amount);
 	stor->dirty = true;
 
 	storage_guild_log( sd, &stor->u.items_guild[i], amount );
@@ -856,10 +859,10 @@ bool storage_guild_delitem(map_session_data* sd, struct s_storage* stor, int n,
 	if(!stor->u.items_guild[n].amount) {
 		memset(&stor->u.items_guild[n],0,sizeof(stor->u.items_guild[0]));
 		stor->amount--;
-		clif_updatestorageamount(sd, stor->amount, stor->max_amount);
+		clif_updatestorageamount(*sd, stor->amount, stor->max_amount);
 	}
 
-	clif_storageitemremoved(sd,n,amount);
+	clif_storageitemremoved( *sd, n, amount );
 	stor->dirty = true;
 	return true;
 }
@@ -899,8 +902,8 @@ void storage_guild_storageadd(map_session_data* sd, int index, int amount)
 	if(storage_guild_additem(sd,stor,&sd->inventory.u.items_inventory[index],amount))
 		pc_delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE);
 	else {
-		clif_storageitemremoved(sd,index,0);
-		clif_dropitem(sd,index,0);
+		clif_storageitemremoved( *sd, index, 0 );
+		clif_dropitem( *sd, index, 0 );
 	}
 }
 
@@ -939,7 +942,7 @@ void storage_guild_storageget(map_session_data* sd, int index, int amount)
 	if((flag = pc_additem(sd,&stor->u.items_guild[index],amount,LOG_TYPE_GSTORAGE)) == 0)
 		storage_guild_delitem(sd,stor,index,amount);
 	else { // inform fail
-		clif_storageitemremoved(sd,index,0);
+		clif_storageitemremoved( *sd, index, 0 );
 		clif_additem(sd,0,0,flag);
 	}
 }
@@ -972,8 +975,8 @@ void storage_guild_storageaddfromcart(map_session_data* sd, int index, int amoun
 	if(storage_guild_additem(sd,stor,&sd->cart.u.items_cart[index],amount))
 		pc_cart_delitem(sd,index,amount,0,LOG_TYPE_GSTORAGE);
 	else {
-		clif_storageitemremoved(sd,index,0);
-		clif_dropitem(sd,index,0);
+		clif_storageitemremoved( *sd, index, 0 );
+		clif_dropitem( *sd, index, 0 );
 	}
 }
 
@@ -1007,8 +1010,11 @@ void storage_guild_storagegettocart(map_session_data* sd, int index, int amount)
 	if((flag = pc_cart_additem(sd,&stor->u.items_guild[index],amount,LOG_TYPE_GSTORAGE)) == 0)
 		storage_guild_delitem(sd,stor,index,amount);
 	else {
-		clif_storageitemremoved(sd,index,0);
-		clif_cart_additem_ack(sd,(flag == 1) ? ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT);
+		clif_storageitemremoved( *sd, index, 0 );
+		if (flag == ADDITEM_INVALID)
+			clif_cart_additem_ack( *sd, ADDITEM_TO_CART_FAIL_WEIGHT );
+		else
+			clif_cart_additem_ack( *sd, ADDITEM_TO_CART_FAIL_COUNT );
 	}
 }
 
@@ -1061,7 +1067,7 @@ void storage_guild_storageclose(map_session_data* sd)
 	nullpo_retv(sd);
 	nullpo_retv(stor = guild2storage2(sd->status.guild_id));
 
-	clif_storageclose(sd);
+	clif_storageclose( *sd );
 	if (stor->status) {
 		if (save_settings&CHARSAVE_STORAGE)
 			chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART); //This one also saves the storage. [Skotlex]
@@ -1087,7 +1093,7 @@ void storage_guild_storage_quit(map_session_data* sd, int flag)
 	nullpo_retv(stor = guild2storage2(sd->status.guild_id));
 
 	if (flag) {	//Only during a guild break flag is 1 (don't save storage)
-		clif_storageclose(sd);
+		clif_storageclose( *sd );
 
 		if (save_settings&CHARSAVE_STORAGE)
 			chrif_save(sd, CSAVE_INVENTORY|CSAVE_CART);
@@ -1118,7 +1124,7 @@ void storage_premiumStorage_open(map_session_data *sd) {
 	sd->state.storage_flag = 3;
 	storage_sortitem(sd->premiumStorage.u.items_storage, ARRAYLENGTH(sd->premiumStorage.u.items_storage));
 	clif_storagelist(sd, sd->premiumStorage.u.items_storage, ARRAYLENGTH(sd->premiumStorage.u.items_storage), storage_getName(sd->premiumStorage.stor_id));
-	clif_updatestorageamount(sd, sd->premiumStorage.amount, sd->premiumStorage.max_amount);
+	clif_updatestorageamount(*sd, sd->premiumStorage.amount, sd->premiumStorage.max_amount);
 }
 
 /**
@@ -1184,7 +1190,7 @@ void storage_premiumStorage_close(map_session_data *sd) {
 
 	if( sd->state.storage_flag == 3 ){
 		sd->state.storage_flag = 0;
-		clif_storageclose( sd );
+		clif_storageclose( *sd );
 	}
 }
 

+ 15 - 15
src/map/trade.cpp

@@ -57,12 +57,12 @@ void trade_traderequest(map_session_data *sd, map_session_data *target_sd)
 	if ( sd->trade_partner != 0 ) { // If a character tries to trade to another one then cancel the previous one
 		map_session_data *previous_sd = map_id2sd(sd->trade_partner);
 
-		if( previous_sd ){
+		if( previous_sd != nullptr ){
 			previous_sd->trade_partner = 0;
-			clif_tradecancelled(previous_sd);
+			clif_tradecancelled( *previous_sd );
 		} // Once cancelled then continue to the new one.
 		sd->trade_partner = 0;
-		clif_tradecancelled(sd);
+		clif_tradecancelled( *sd );
 	}
 
 	if (target_sd->trade_partner != 0) {
@@ -399,7 +399,7 @@ void trade_tradeadditem(map_session_data *sd, short index, short amount)
 	}
 
 	if( item->equipSwitch ){
-		clif_msg(sd, C_ITEM_EQUIP_SWITCH);
+		clif_msg(sd, MSI_SWAP_EQUIPITEM_UNREGISTER_FIRST);
 		return;
 	}
 
@@ -485,8 +485,8 @@ void trade_tradeok(map_session_data *sd)
 
 	sd->state.deal_locked = 1;
 	clif_tradeitemok(*sd, -2, EXITEM_ADD_SUCCEED); // We pass -2 which will becomes 0 in clif_tradeitemok (Official behavior)
-	clif_tradedeal_lock(sd, 0);
-	clif_tradedeal_lock(target_sd, 1);
+	clif_tradedeal_lock( *sd, false );
+	clif_tradedeal_lock( *target_sd, true );
 }
 
 /**
@@ -504,12 +504,12 @@ void trade_tradecancel(map_session_data *sd)
 	sd->state.isBoundTrading = 0;
 
 	if(!sd->state.trading) { // Not trade accepted
-		if( target_sd ) {
+		if( target_sd != nullptr ) {
 			target_sd->trade_partner = 0;
-			clif_tradecancelled(target_sd);
+			clif_tradecancelled( *target_sd );
 		}
 		sd->trade_partner = 0;
-		clif_tradecancelled(sd);
+		clif_tradecancelled( *sd );
 		return;
 	}
 
@@ -523,14 +523,14 @@ void trade_tradecancel(map_session_data *sd)
 	}
 
 	if (sd->deal.zeny) {
-		clif_updatestatus(sd, SP_ZENY);
+		clif_updatestatus(*sd, SP_ZENY);
 		sd->deal.zeny = 0;
 	}
 
 	sd->state.deal_locked = 0;
 	sd->state.trading = 0;
 	sd->trade_partner = 0;
-	clif_tradecancelled(sd);
+	clif_tradecancelled( *sd );
 
 	if (!target_sd)
 		return;
@@ -544,14 +544,14 @@ void trade_tradecancel(map_session_data *sd)
 	}
 
 	if (target_sd->deal.zeny) {
-		clif_updatestatus(target_sd, SP_ZENY);
+		clif_updatestatus(*target_sd, SP_ZENY);
 		target_sd->deal.zeny = 0;
 	}
 
 	target_sd->state.deal_locked = 0;
 	target_sd->trade_partner = 0;
 	target_sd->state.trading = 0;
-	clif_tradecancelled(target_sd);
+	clif_tradecancelled( *target_sd );
 }
 
 /**
@@ -651,8 +651,8 @@ void trade_tradecommit(map_session_data *sd)
 	tsd->state.trading = 0;
 	tsd->state.isBoundTrading = 0;
 
-	clif_tradecompleted(sd, 0);
-	clif_tradecompleted(tsd, 0);
+	clif_tradecompleted( *sd );
+	clif_tradecompleted( *tsd );
 
 	// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
 	if (save_settings&CHARSAVE_TRADE) {

+ 71 - 29
src/map/unit.cpp

@@ -131,7 +131,7 @@ int unit_walktoxy_sub(struct block_list *bl)
 		map_session_data *sd = BL_CAST(BL_PC, bl);
 
 		sd->head_dir = DIR_NORTH;
-		clif_walkok(sd);
+		clif_walkok(*sd);
 	}
 #if PACKETVER >= 20170726
 	// If this is a walking NPC and it will use a player sprite
@@ -447,12 +447,11 @@ static TIMER_FUNC(unit_walktoxy_timer)
 	if(md && !ud->state.force_walk && md->walktoxy_fail_count < icewall_walk_block && map_getcell(bl->m,x,y,CELL_CHKICEWALL) && (dx > 0 || dy > 0)) {
 		//Needs to be done here so that rudeattack skills are invoked
 		md->walktoxy_fail_count++;
-		clif_fixpos(bl);
-		//Monsters in this situation first use a chase skill, then unlock target and then use an idle skill
-		if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
-			mobskill_use(md, tick, -1);
+		clif_fixpos( *bl );
+		// Monsters in this situation will unlock target and then attempt an idle skill
+		// When they start chasing again, they will check for a chase skill before returning here
 		mob_unlocktarget(md, tick);
-		if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
+		if (DIFF_TICK(tick, md->last_skillcheck) >= MOB_SKILL_INTERVAL)
 			mobskill_use(md, tick, -1);
 		return 0;
 	}
@@ -463,7 +462,6 @@ static TIMER_FUNC(unit_walktoxy_timer)
 	x += dx;
 	y += dy;
 	map_moveblock(bl, x, y, tick);
-	ud->walk_count++; // Walked cell counter, to be used for walk-triggered skills. [Skotlex]
 
 	if (bl->x != x || bl->y != y || ud->walktimer != INVALID_TIMER)
 		return 0; // map_moveblock has altered the object beyond what we expected (moved/warped it)
@@ -542,15 +540,19 @@ static TIMER_FUNC(unit_walktoxy_timer)
 				md->min_chase--;
 			// Walk skills are triggered regardless of target due to the idle-walk mob state.
 			// But avoid triggering on stop-walk calls.
+			// Monsters use walk/chase skills every second, but we only get here every "speed" ms
+			// To make sure we check one skill per second on average, we substract half the speed as ms
 			if(!ud->state.force_walk && tid != INVALID_TIMER &&
-				!(ud->walk_count%WALK_SKILL_INTERVAL) &&
+				DIFF_TICK(tick, md->last_skillcheck) > MOB_SKILL_INTERVAL - md->status.speed / 2 &&
+				DIFF_TICK(tick, md->last_thinktime) > 0 &&
 				map[bl->m].users > 0 &&
 				mobskill_use(md, tick, -1)) {
 				if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)
 					&& ud->skill_id != NPC_EMOTION && ud->skill_id != NPC_EMOTION_ON //NPC_EMOTION doesn't make the monster stop
 					&& md->state.skillstate != MSS_WALK) //Walk skills are supposed to be used while walking
 				{ // Skill used, abort walking
-					clif_fixpos(bl); // Fix position as walk has been cancelled.
+					// Fix position as walk has been cancelled.
+					clif_fixpos( *bl );
 					return 0;
 				}
 				// Resend walk packet for proper Self Destruction display.
@@ -601,7 +603,7 @@ static TIMER_FUNC(unit_walktoxy_timer)
 		if(unit_walktoxy_sub(bl)) {
 			return 1;	
 		} else {
-			clif_fixpos(bl);
+			clif_fixpos( *bl );
 			return 0;
 		}
 	}
@@ -616,6 +618,12 @@ static TIMER_FUNC(unit_walktoxy_timer)
 		speed = status_get_speed(bl);
 
 	if(speed > 0) {
+		// For some reason sometimes the walk timer is not empty here
+		// TODO: Need to check why (e.g. when the monster spams NPC_RUN)
+		if (ud->walktimer != INVALID_TIMER) {
+			delete_timer(ud->walktimer, unit_walktoxy_timer);
+			ud->walktimer = INVALID_TIMER;
+		}
 		ud->walktimer = add_timer(tick+speed,unit_walktoxy_timer,id,speed);
 		if( md && DIFF_TICK(tick,md->dmgtick) < 3000 ) // Not required not damaged recently
 			clif_move(ud);
@@ -641,7 +649,7 @@ static TIMER_FUNC(unit_walktoxy_timer)
 				// Aegis uses one before every attack, we should
 				// only need this one for syncing purposes. [Skotlex]
 				ud->target_to = 0;
-				clif_fixpos(bl);
+				clif_fixpos( *bl );
 				unit_attack(bl, tbl->id, ud->state.attack_continue);
 			}
 		} else { // Update chase-path
@@ -931,7 +939,7 @@ void unit_run_hit(struct block_list *bl, status_change *sc, map_session_data *sd
 		skill_blown(bl, bl, skill_get_blewcount(TK_RUN, lv), unit_getdir(bl), BLOWN_NONE);
 		clif_status_change(bl, EFST_TING, 0, 0, 0, 0, 0);
 	} else if (sd) {
-		clif_fixpos(bl);
+		clif_fixpos( *bl );
 		skill_castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL);
 	}
 	return;
@@ -1004,22 +1012,47 @@ bool unit_run(struct block_list *bl, map_session_data *sd, enum sc_type type)
 	return true;
 }
 
+/**
+ * Returns duration of an object's current walkpath
+ * @param bl: Object that is moving
+ * @return Duration of the walkpath
+ */
+t_tick unit_get_walkpath_time(struct block_list& bl)
+{
+	t_tick time = 0;
+	unsigned short speed = status_get_speed(&bl);
+	struct unit_data* ud = unit_bl2ud(&bl);
+
+	// The next walk start time is calculated.
+	for (uint8 i = 0; i < ud->walkpath.path_len; i++) {
+		if (direction_diagonal(ud->walkpath.path[i]))
+			time += speed * MOVE_DIAGONAL_COST / MOVE_COST;
+		else
+			time += speed;
+	}
+
+	return time;
+}
+
 /**
  * Makes unit attempt to run away from target using hard paths
  * @param bl: Object that is running away from target
  * @param target: Target
  * @param dist: How far bl should run
  * @param flag: unit_walktoxy flag
- * @return 1: Success 0: Fail
+ * @return The duration the unit will run (0 on fail)
  */
-int unit_escape(struct block_list *bl, struct block_list *target, short dist, uint8 flag)
+t_tick unit_escape(struct block_list *bl, struct block_list *target, short dist, uint8 flag)
 {
 	uint8 dir = map_calc_dir(target, bl->x, bl->y);
 
 	while( dist > 0 && map_getcell(bl->m, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], CELL_CHKNOREACH) )
 		dist--;
 
-	return ( dist > 0 && unit_walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], flag) );
+	if (dist > 0 && unit_walktoxy(bl, bl->x + dist * dirx[dir], bl->y + dist * diry[dir], flag))
+		return unit_get_walkpath_time(*bl);
+
+	return 0;
 }
 
 /**
@@ -1414,7 +1447,7 @@ int unit_stop_walking(struct block_list *bl,int type)
 	}
 
 	if(type&USW_FIXPOS)
-		clif_fixpos(bl);
+		clif_fixpos( *bl );
 
 	ud->walkpath.path_len = 0;
 	ud->walkpath.path_pos = 0;
@@ -1532,7 +1565,7 @@ TIMER_FUNC(unit_resume_running){
 		clif_skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skill_lv,sc_start4(ud->bl,ud->bl,SC_RUN,100,ud->skill_lv,unit_getdir(ud->bl),0,0,0));
 
 	if (sd)
-		clif_walkok(sd);
+		clif_walkok(*sd);
 
 	return 0;
 }
@@ -2753,7 +2786,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, t_tick tick)
 
 	if(sd && !check_distance_client_bl(src,target,range)) {
 		// Player tries to attack but target is too far, notify client
-		clif_movetoattack(sd,target);
+		clif_movetoattack( *sd, *target );
 		return 1;
 	} else if(md && !check_distance_bl(src,target,range)) {
 		// Monster: Chase if required
@@ -2776,7 +2809,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, t_tick tick)
 	// Sync packet only for players.
 	// Non-players use the sync packet on the walk timer. [Skotlex]
 	if (tid == INVALID_TIMER && sd)
-		clif_fixpos(src);
+		clif_fixpos( *src );
 
 	if( DIFF_TICK(ud->attackabletime,tick) <= 0 ) {
 		if (battle_config.attack_direction_change && (src->type&battle_config.attack_direction_change))
@@ -2786,10 +2819,14 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, t_tick tick)
 			unit_stop_walking(src,1);
 
 		if(md) {
-			//First attack is always a normal attack
-			if(md->state.skillstate == MSS_ANGRY || md->state.skillstate == MSS_BERSERK) {
-				if (mobskill_use(md,tick,-1))
+			// Berserk skills can replace normal attacks except for the first attack
+			// If this is the first attack, the state is not Berserk yet, so the skill check is skipped
+			if(md->state.skillstate == MSS_BERSERK) {
+				if (mobskill_use(md, tick, -1)) {
+					// Setting the delay here because not all monster skill use situations will cause an attack delay
+					ud->attackabletime = tick + sstatus->adelay;
 					return 1;
+				}
 			}
 			// Set mob's ANGRY/BERSERK states.
 			md->state.skillstate = md->state.aggressive?MSS_ANGRY:MSS_BERSERK;
@@ -2821,6 +2858,10 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, t_tick tick)
 
 		ud->attackabletime = tick + sstatus->adelay;
 
+		// Only reset skill_id here if no skilltimer is currently ongoing
+		if (ud->skilltimer == INVALID_TIMER)
+			ud->skill_id = 0;
+
 		// You can't move if you can't attack neither.
 		if (src->type&battle_config.attack_walk_delay)
 			unit_set_walkdelay(src, tick, sstatus->amotion, 1);
@@ -2949,7 +2990,7 @@ int unit_skillcastcancel(struct block_list *bl, char type)
 	if(bl->type==BL_MOB)
 		((TBL_MOB*)bl)->skill_idx = -1;
 
-	clif_skillcastcancel(bl);
+	clif_skillcastcancel( *bl );
 
 	return 1;
 }
@@ -3215,7 +3256,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 
 			if( pd->pet.intimate <= PET_INTIMATE_NONE && !(pd->master && !pd->master->state.active) ) {
 				// If logging out, this is deleted on unit_free
-				clif_clearunit_area(bl,clrtype);
+				clif_clearunit_area( *bl, clrtype );
 				map_delblock(bl);
 				unit_free(bl,CLR_OUTSIGHT);
 				map_freeblock_unlock();
@@ -3232,7 +3273,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 			if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) ) {
 				// If logging out, this is deleted on unit_free
 				clif_emotion(bl, ET_CRY);
-				clif_clearunit_area(bl,clrtype);
+				clif_clearunit_area( *bl, clrtype );
 				map_delblock(bl);
 				unit_free(bl,CLR_OUTSIGHT);
 				map_freeblock_unlock();
@@ -3247,7 +3288,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 			ud->canact_tick = ud->canmove_tick;
 
 			if( mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) ) {
-				clif_clearunit_area(bl,clrtype);
+				clif_clearunit_area( *bl, clrtype );
 				map_delblock(bl);
 				unit_free(bl,CLR_OUTSIGHT);
 				map_freeblock_unlock();
@@ -3262,7 +3303,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 			ud->canact_tick = ud->canmove_tick;
 
 			if( elemental_get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) ) {
-				clif_clearunit_area(bl,clrtype);
+				clif_clearunit_area( *bl, clrtype );
 				map_delblock(bl);
 				unit_free(bl,CLR_OUTSIGHT);
 				map_freeblock_unlock();
@@ -3296,7 +3337,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 			}
 			[[fallthrough]];
 		default:
-			clif_clearunit_area(bl, clrtype);
+			clif_clearunit_area( *bl, clrtype );
 			map_delblock(bl);
 			break;
 	}
@@ -3321,7 +3362,7 @@ void unit_refresh(struct block_list *bl, bool walking) {
 	// Using CLR_TRICKDEAD because other flags show effects
 	// Probably need to use another flag or other way to refresh it
 	if (mapdata->users) {
-		clif_clearunit_area(bl, CLR_TRICKDEAD); // Fade out
+		clif_clearunit_area( *bl, CLR_TRICKDEAD ); // Fade out
 		clif_spawn(bl,walking); // Fade in
 	}
 }
@@ -3426,6 +3467,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 			pc_inventory_rental_clear(sd);
 			pc_delspiritball(sd, sd->spiritball, 1);
 			pc_delspiritcharm(sd, sd->spiritcharm, sd->spiritcharm_type);
+			mob_removeslaves(&sd->bl);
 
 			if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting
 				script_free_state(sd->st);

+ 2 - 2
src/map/unit.hpp

@@ -44,7 +44,6 @@ struct unit_data {
 	t_tick canmove_tick;
 	bool immune_attack; ///< Whether the unit is immune to attacks
 	uint8 dir;
-	unsigned char walk_count;
 	unsigned char target_count;
 	struct s_udState {
 		unsigned change_walk_target : 1 ;
@@ -122,7 +121,8 @@ bool unit_can_move(struct block_list *bl);
 int unit_is_walking(struct block_list *bl);
 int unit_set_walkdelay(struct block_list *bl, t_tick tick, t_tick delay, int type);
 
-int unit_escape(struct block_list *bl, struct block_list *target, short dist, uint8 flag = 0);
+t_tick unit_get_walkpath_time(struct block_list& bl);
+t_tick unit_escape(struct block_list *bl, struct block_list *target, short dist, uint8 flag = 0);
 
 // Instant unit changes
 bool unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath);

+ 6 - 6
src/map/vending.cpp

@@ -132,7 +132,7 @@ void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* da
 		return; // invalid shop
 
 	if( vsd->vender_id != uid ) { // shop has changed
-		clif_buyvending(sd, 0, 0, 6);  // store information was incorrect
+		clif_buyvending( *sd, 0, 0, PURCHASEMC_STORE_INCORRECT );  // store information was incorrect
 		return;
 	}
 
@@ -172,17 +172,17 @@ void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* da
 
 		z += ((double)vsd->vending[j].value * (double)amount);
 		if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) {
-			clif_buyvending(sd, idx, amount, 1); // you don't have enough zeny
+			clif_buyvending( *sd, idx, amount, PURCHASEMC_NO_ZENY ); // you don't have enough zeny
 			return;
 		}
 		if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max ) {
-			clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow
+			clif_buyvending( *sd, idx, vsd->vending[j].amount, PURCHASEMC_OUT_OF_STOCK ); // too much zeny = overflow
 			return;
 
 		}
 		w += itemdb_weight(vsd->cart.u.items_cart[idx].nameid) * amount;
 		if( w + sd->weight > sd->max_weight ) {
-			clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight
+			clif_buyvending( *sd, idx, amount, PURCHASEMC_OVERWEIGHT );
 			return;
 		}
 
@@ -194,7 +194,7 @@ void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* da
 		// here, we check cumulative amounts
 		if( vending[j].amount < amount ) {
 			// send more quantity is not a hack (an other player can have buy items just before)
-			clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
+			clif_buyvending( *sd, idx, vsd->vending[j].amount, PURCHASEMC_OUT_OF_STOCK );
 			return;
 		}
 
@@ -241,7 +241,7 @@ void vending_purchasereq(map_session_data* sd, int aid, int uid, const uint8* da
 
 		pc_cart_delitem(vsd, idx, amount, 0, LOG_TYPE_VENDING);
 		z = vending_calc_tax(sd, z);
-		clif_vendingreport(vsd, idx, amount, sd->status.char_id, (int)z);
+		clif_vendingreport( *vsd, idx, amount, sd->status.char_id, (int)z );
 
 		//print buyer's name
 		if( battle_config.buyer_name ) {

+ 12 - 12
tools/check-doc.pl

@@ -32,8 +32,8 @@ sub GetArgs {
     'target=s'	=> \$sTarget,	 #Target (wich files to run-cmd into)
     'leftover=i' => \$sLeftOverChk, #should we chk if all doc are linked to a src ?
     'help!' => \$sHelp,
-    ) or $sHelp=1; #display help if invalid option	
-	
+    ) or $sHelp=1; #display help if invalid option
+
     if( $sHelp ) {
 	print "Incorrect option specified, available options are:\n"
 	    ."\t --atcf filename => file (specify atcommand doc to use)\n"
@@ -96,7 +96,7 @@ sub Script_GetCmd {
 	my @aSct_src = ("../src/map/script.cpp","../src/custom/script_def.inc");
 	my @aDef_sct = ();
 	foreach my $sSct_srcf (@aSct_src){
-		unless(open FILE_SRC, "<$sSct_srcf") { 
+		unless(open FILE_SRC, "<$sSct_srcf") {
 			print "Couldn't open file '$sSct_srcf'.\n";
 			next;
 		}
@@ -139,16 +139,16 @@ sub Script_Chk { my ($raDef_sct) = @_;
 				@line = split('\(',$line[0]);
 				@line = split('\<',$line[0]);
 				$line[0] =~ s/\(|\{|\*|\r|\s|\;|\)|\"|\,//g; #todo please harmonize command definition for easier parse
-				
-				next if($line[0] eq "Name" || $line[0] eq "" || $line[0] eq "function" 
+
+				next if($line[0] eq "Name" || $line[0] eq "" || $line[0] eq "function"
 				|| $line[0] eq "if" || $line[0] eq "while" || $line[0] eq "do"  || $line[0] eq "for" ); #exception list
-				
+
 				push(@aDoc_sct,$line[0]);
 			}
 		}
 		close FILE_DOC;
 	}
-	
+
 	$raMiss_sct = Chk($raDef_sct,\@aDoc_sct); #check missing documentation
 	if(scalar(@$raMiss_sct)){
 		print "Missing script documentation for function :{\n";
@@ -158,7 +158,7 @@ sub Script_Chk { my ($raDef_sct) = @_;
 		print "}\n\n";
 	}
 	else { print "All script commands in src are documented, no issues found.\n"; }
-	
+
 	if($sLeftOverChk){
 		my $raLeftover_sct = Chk(\@aDoc_sct,$raDef_sct); #we just inverse the chk for leftover
 		if(scalar(@$raLeftover_sct)){
@@ -185,7 +185,7 @@ sub Atc_GetCmd {
 			if($_ =~ /ACMD_DEF|ACMD_DEF2|ACMD_DEFR|ACMD_DEF2R/){
 				$_ =~ s/\s+$//; #Remove trailing spaces.
 				$_ =~ s/^\s+//; #Remove leading spaces.
-				
+
 				if($_ =~ /^ACMD_DEF2|^ACMD_DEF2R/){
 					my @line = split('"',$_);
 					push(@aDef_act,$line[1]);
@@ -207,7 +207,7 @@ sub Atc_Chk {  my ($raDef_act) = @_;
 	my @aAct_docf = ($sAtcf,$sInc_atcf);
 	my @aDoc_act = ();
 	my $raMiss_act;
-	
+
 	foreach my $sAct_docf (@aAct_docf){
 		unless(open FILE_DOC, "$sAct_docf"){
 			print "Couldn't open file '$sAct_docf'.\n";
@@ -226,7 +226,7 @@ sub Atc_Chk {  my ($raDef_act) = @_;
 		}
 		close FILE_DOC;
 	}
-	
+
 	$raMiss_act = Chk($raDef_act,\@aDoc_act); #check missing documentation
 	if(scalar(@$raMiss_act)){
 		print "Missing atcommand documentation for function :{\n";
@@ -236,7 +236,7 @@ sub Atc_Chk {  my ($raDef_act) = @_;
 		print "}\n\n";
 	}
 	else { print "All atcommands in src are documented, no issues found.\n"; }
-	
+
 	if($sLeftOverChk){
 		my $raLeftover_sct = Chk(\@aDoc_act,$raDef_act); #we just inverse the chk for leftover
 		if(scalar(@$raLeftover_sct)){

+ 253 - 254
tools/config.pl

@@ -16,30 +16,30 @@ use rA_Common;
 use LWP::Simple;
 
 use constant {
-    SERV_UID => "Serv_userid",
-    SERV_PW => "Serv_userpass",
-    LOGIN_PRIV_IP => "login_priv_ip",
+	SERV_UID => "Serv_userid",
+	SERV_PW => "Serv_userpass",
+	LOGIN_PRIV_IP => "login_priv_ip",
 	CHAR_PRIV_IP => "char_priv_ip",
-    SERV_WAN_IP => "Serv_wan_ip",
-    MAP_PORT => "Map_port",
-    CHAR_PORT => "Char_port",
-    LOGIN_PORT => "Login_port",
-    MD5_ENABLE => "enable_MD5",
-    PINCODE_ENABLE => "enable_pincode",
-    SQL_HOST => "SQL_host",
-    SQL_PORT => "SQL_port",
-    SQL_UID => "SQL_userid",
-    SQL_PW => "SQL_userpass",
-    SQL_MAIN_DB => "SQL_maindb",
-    SQL_LOG_DB => ,"SQL_logdb",
-
-    MAP_CONF_FILE => "map_conf.txt",
-    CHAR_CONF_FILE => "char_conf.txt",
-    LOGIN_CONF_FILE => "login_conf.txt",
-    INTER_CONF_FILE => "inter_conf.txt",
-    DESD_CONF_FILE => ".tmp-desd_conf.yml",
-    MIN_PORT => 2000, #below are usually reserved for system
-    MAX_PORT => 65535,
+	SERV_WAN_IP => "Serv_wan_ip",
+	MAP_PORT => "Map_port",
+	CHAR_PORT => "Char_port",
+	LOGIN_PORT => "Login_port",
+	MD5_ENABLE => "enable_MD5",
+	PINCODE_ENABLE => "enable_pincode",
+	SQL_HOST => "SQL_host",
+	SQL_PORT => "SQL_port",
+	SQL_UID => "SQL_userid",
+	SQL_PW => "SQL_userpass",
+	SQL_MAIN_DB => "SQL_maindb",
+	SQL_LOG_DB => ,"SQL_logdb",
+
+	MAP_CONF_FILE => "map_conf.txt",
+	CHAR_CONF_FILE => "char_conf.txt",
+	LOGIN_CONF_FILE => "login_conf.txt",
+	INTER_CONF_FILE => "inter_conf.txt",
+	DESD_CONF_FILE => ".tmp-desd_conf.yml",
+	MIN_PORT => 2000, #below are usually reserved for system
+	MAX_PORT => 65535,
 };
 # setup default options
 my $sDsdFile    = DESD_CONF_FILE;
@@ -53,46 +53,46 @@ GetArgs();
 Main();
 
 sub GetArgs {
-    GetOptions(
-    'f=s' => \$sDsdFile, #give desired conf file
-    'auto=i' => \$sAutoyes,   #Force (auto-yes)
-    'C=i'	=> \$sClean,	 #Clean (like force but remove before adding)
-    'target=s'	=> \$sTarget,	 #Target (which setup to run)
-    'Force=i'	=> \$sForce,	 #Force (bypass verification)
-    'OS=s'	=> \$sOS, #OS (specify the OS you wish to use)
-    'help!' => \$sHelp,
-    ) or $sHelp=1; #display help if invalid option
-    my $sValidTarget = "All|Conf|DB|Inst|Dump";
-    
-	
-    if( $sHelp ) {
+	GetOptions(
+	'f=s' => \$sDsdFile, #give desired conf file
+	'auto=i' => \$sAutoyes,   #Force (auto-yes)
+	'C=i'	=> \$sClean,	 #Clean (like force but remove before adding)
+	'target=s'	=> \$sTarget,	 #Target (which setup to run)
+	'Force=i'	=> \$sForce,	 #Force (bypass verification)
+	'OS=s'	=> \$sOS, #OS (specify the OS you wish to use)
+	'help!' => \$sHelp,
+	) or $sHelp=1; #display help if invalid option
+	my $sValidTarget = "All|Conf|DB|Inst|Dump";
+
+
+	if( $sHelp ) {
 	print "Incorrect option specified. Available options are:\n"
-	    ."\t --f filename => file (specify desiredconf to use)\n"
-	    ."\t --auto => auto-yes to question? \n"
-	    ."\t --C => Clean (remove file, db, user before adding new)\n"
-	    ."\t --target => target (specify which setup to run [$sValidTarget])\n"
-	    ."\t --Force => Force (bypass verification)\n"
-	    ."\t --OS => (specify the OS you wish to use and avoid check)";
+		."\t --f filename => file (specify desiredconf to use)\n"
+		."\t --auto => auto-yes to question? \n"
+		."\t --C => Clean (remove file, db, user before adding new)\n"
+		."\t --target => target (specify which setup to run [$sValidTarget])\n"
+		."\t --Force => Force (bypass verification)\n"
+		."\t --OS => (specify the OS you wish to use and avoid check)";
 	exit;
-    }
-    unless($sTarget =~ /$sValidTarget/i){
+	}
+	unless($sTarget =~ /$sValidTarget/i){
 	print "Incorrect target specified. Available targets are:\n"
-	    ."\t --target => target (specify which setup to run [(default)$sValidTarget])\n";
+		."\t --target => target (specify which setup to run [(default)$sValidTarget])\n";
 	exit;
-    }
-    if($sDsdFile ne DESD_CONF_FILE && !(-e -r $sDsdFile)){
+	}
+	if($sDsdFile ne DESD_CONF_FILE && !(-e -r $sDsdFile)){
 	print "File '$sDsdFile' could not be read or does not exist.\n";
 	exit;
-    }
+	}
 }
 
 sub Main {
-    my($filename, $dir, $suffix) = fileparse($0);
-    chdir $dir; #put ourself like was called in tools
-    print "Running rAthena's configuration tool...\n";
-    #default conf
-    my $pubip = GetPublicIP();
-    my %hDefConf = (    SERV_UID => "s1",
+	my($filename, $dir, $suffix) = fileparse($0);
+	chdir $dir; #put ourself like was called in tools
+	print "Running rAthena's configuration tool...\n";
+	#default conf
+	my $pubip = GetPublicIP();
+	my %hDefConf = (    SERV_UID => "s1",
 			SERV_PW => "p1",
 			SERV_WAN_IP => $pubip || "localhost",
 			LOGIN_PRIV_IP => "localhost",
@@ -109,7 +109,6 @@ sub Main {
 			SQL_MAIN_DB => "ragnarok",
 			SQL_LOG_DB => ,"ragnarok",
 			);
-			
 
 	my $sBasedir = getcwd; #for setupdb
 	if($sTarget =~ /All|Inst/i){ InstallSoft(); }
@@ -121,7 +120,7 @@ sub Main {
 }
 
 
-sub EnableCoredump { 
+sub EnableCoredump {
 	print "\n== Enabling Coredumps ==\n";
 	my $sCurfile = "~/.bashrc";
 	my @lines = ();
@@ -130,7 +129,7 @@ sub EnableCoredump {
 	foreach(<PIPE>){
 		if($_ =~ /ulimit -c unlimited/){
 			$sJump = 1; #already in here nothing to do
-			last; 
+			last;
 		}
 		push(@lines,$_) if /ulimit/;
 	}
@@ -174,7 +173,7 @@ sub EnableCoredump {
 			."Are you sure you want to continue? [y/n] \n";
 		$sJump=2 if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i);
 	}
-    unless($sJump==2){
+	unless($sJump==2){
 		system('sudo su root -c "echo \"echo kernel.core_uses_pid = 1 >> /etc/sysctl.conf\" | sudo bash"');
 		system('sudo su root -c "echo \"echo kernel.core_pattern = /tmp/core-%e-%s-%u-%g-%p-%t >> /etc/sysctl.conf\" | sudo bash"');
 		system('sudo su root -c "echo \"echo fs.suid_dumpable = 1 >> /etc/sysctl.conf\" | sudo bash"');
@@ -203,7 +202,7 @@ sub GetOS {
 	}
 	else {
 		my @aSupportedOS = ("Debian","Ubuntu","Fedora","CentOs","FreeBSD");
-		my $sOSregex = join("|",@aSupportedOS); 
+		my $sOSregex = join("|",@aSupportedOS);
 		until($sOS =~ /$sOSregex/i){
 			print "Please enter your OS [$sOSregex] or enter 'quit' to exit.\n";
 			$sOS = <>; chomp($sOS);
@@ -214,11 +213,11 @@ sub GetOS {
 }
 
 sub InstallSoft {
-    print "\n== Installing Software ==\n";
-    print "NOTE: This auto-install feature is experimental. Package names vary in different distributions and versions, so they may be incorrect.\n";
-    $sOS = GetOS() unless $sOS;
-    if($sOS eq "quit"){ print "Skipping software installation...\n"; return; }
-    elsif($sOS =~ /Ubuntu|Debian/i) { #tested on ubuntu 12.10,13.10
+	print "\n== Installing Software ==\n";
+	print "NOTE: This auto-install feature is experimental. Package names vary in different distributions and versions, so they may be incorrect.\n";
+	$sOS = GetOS() unless $sOS;
+	if($sOS eq "quit"){ print "Skipping software installation...\n"; return; }
+	elsif($sOS =~ /Ubuntu|Debian/i) { #tested on ubuntu 12.10,13.10
 	my @aListSoft = ("gcc","gdb","zlibc","zlib1g-dev","make","git","mysql-client","mysql-server","mysql-common","libmysqlclient-dev","phpmyadmin","libpcre3-dev");
 	print "Going to install: @aListSoft\n";
 	system("sudo apt-get install @aListSoft");
@@ -227,77 +226,77 @@ sub InstallSoft {
 	my @aListSoft = ("gcc","gdb","zlib","zlib-devel","make","git","mariadb-server","mariadb","mariadb-devel","phpmyadmin","pcre-devel");
 #	my @aListSoft = ("gcc","gdb","zlib","zlib-devel","make","git","mysql-server","mysql-devel","phpmyadmin","pcre-devel");
 	system("sudo yum install @aListSoft");
-    }
-    elsif($sOS =~ /FreeBSD/i){ #tested on FreeBSD 9.01
+	}
+	elsif($sOS =~ /FreeBSD/i){ #tested on FreeBSD 9.01
 	system("portsnap fetch extract && portsnap update"); #fetch port lib and extract
 	my @aDevel = ("binutils","git","autoconf","pcre","gmake","gdb");
 	foreach(@aDevel){
-	    system("cd /usr/ports/devel/$_ && make install clean"); #install devels
+		system("cd /usr/ports/devel/$_ && make install clean"); #install devels
 	}
 #	system("cd /usr/ports/lang/gcc46 && make install"); #gcc4.6 use latest ? 4.8 ?
 	system("cd /usr/ports/databases/mysql55-server && make install clean");
 	#other utils ?
 	system("cd /usr/ports/www/wget && make install clean");
 	system("cd /usr/ports/archivers/unrar && make install clean");
-    }
+	}
 }
 
 sub ConfigConf { my ($rhDefConf) = @_;
-    print "\n== Setting Configurations ==\n";
-    my $rhUserConf;
-    while(1) {
+	print "\n== Setting Configurations ==\n";
+	my $rhUserConf;
+	while(1) {
 	$rhUserConf = GetDesiredConf($rhDefConf);
 	print "SetupConf using conf: \n";
 	ShowConfig($rhUserConf);
 	last if($sForce || AutoCheckConf($rhUserConf));
-    }
-    ApplySetupConf($rhUserConf);
+	}
+	ApplySetupConf($rhUserConf);
 }
 
 sub ConfigDB { my ($rhDefConf) = @_;
-    print "\n== Setting Up Databases ==\n";
-    my $rhUserConf;
-    while(1) {
+	print "\n== Setting Up Databases ==\n";
+	my $rhUserConf;
+	while(1) {
 		$rhUserConf = GetDesiredConf($rhDefConf);
 		print "SetupDb using conf: \n";
 		ShowConfig($rhUserConf);
 		last if($sForce || AutoCheckConf($rhUserConf));
-    }
-    ApplySetupDB($rhUserConf);
+	}
+	ApplySetupDB($rhUserConf);
 }
 
 #conf function
 sub ApplySetupConf { my ($rhConfig) = @_;
-    print "\nApplying configurations...\n";
-    my @aTargetfile = (MAP_CONF_FILE,CHAR_CONF_FILE,LOGIN_CONF_FILE,INTER_CONF_FILE);
-    my $sConfDir = "conf";
-    my $sUserConfDir = "import";
-
-    die "'$sConfDir' doesn't seem to exist or couldn't be read/written" unless(-d -r -w "../$sConfDir");
-    chdir "../$sConfDir";
-    print "Saving tmp user-conf.\n";
-    YAML::XS::DumpFile(DESD_CONF_FILE,$rhConfig);
-    unless(-d "$sUserConfDir") {
+	print "\nApplying configurations...\n";
+	my @aTargetfile = (MAP_CONF_FILE,CHAR_CONF_FILE,LOGIN_CONF_FILE,INTER_CONF_FILE);
+	my $sConfDir = "conf";
+	my $sUserConfDir = "import";
+
+	die "'$sConfDir' doesn't seem to exist or couldn't be read/written" unless(-d -r -w "../$sConfDir");
+	chdir "../$sConfDir";
+	print "Saving tmp user-conf.\n";
+	YAML::XS::DumpFile(DESD_CONF_FILE,$rhConfig);
+	unless(-d "$sUserConfDir") {
 	print "Directory 'conf/import' doesn't exist. Create it? [y/n] (will be generated by compilation otherwise) \n";
 	if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i) { die "Cannot apply configurations without 'import' folder, exiting...\n"; }
 	mkdir "$sUserConfDir";
-    }
-    chdir $sUserConfDir;
+	}
+	chdir $sUserConfDir;
 
-    if($sClean){ unlink @aTargetfile; } #deleting file before applying conf if clean
-    opendir(DIR, ".") or die $!;
-    my @aDirfile = grep { /\.txt/ && -f "$_"  } readdir(DIR);
-    close DIR;
-    print "Current file in directory '@aDirfile' is target '@aTargetfile'.\n";
+	if($sClean){ unlink @aTargetfile; } #deleting file before applying conf if clean
+	opendir(DIR, ".") or die $!;
+	my @aDirfile = grep { /\.txt/ && -f "$_"  } readdir(DIR);
+	close DIR;
+	print "Current file in directory '@aDirfile' is target '@aTargetfile'.\n";
 
-    foreach my $sCurfile(@aTargetfile) {
+	foreach my $sCurfile(@aTargetfile) {
 	print "Checking if target file '$sCurfile' exists... ";
 	if(-e -r $sCurfile) {
-	    print "Yes. Overwrite it? [y/n] \n";
-	    if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i) {
+		print "Yes. Overwrite it? [y/n] \n";
+		if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i) {
 		print "Only overwrite option currently supported. File skipped...\n\n";
 		next;
-	    }
+		}
 	}
 	else { print "No.\n" };
 
@@ -306,206 +305,206 @@ sub ApplySetupConf { my ($rhConfig) = @_;
 	elsif($sCurfile eq CHAR_CONF_FILE) { ApplyCharConf($rhConfig,$sCurfile); }
 	elsif($sCurfile eq LOGIN_CONF_FILE) { ApplyLoginConf($rhConfig,$sCurfile); }
 	elsif($sCurfile eq INTER_CONF_FILE) { ApplyInterConf($rhConfig,$sCurfile); }
-    }
+	}
 }
 
 sub ApplyMapConf { my ($rhUserConf,$sCurfile) = @_;
-    open FILE, "> $sCurfile" || die "Couldn't open or create file '$sCurfile'.\n";
-    print FILE "userid: " . $$rhUserConf{SERV_UID}."\n";
-    print FILE "passwd: " . $$rhUserConf{SERV_PW}."\n\n";
-
-    print FILE "map_ip: " . $$rhUserConf{SERV_WAN_IP}."\n";
-    print FILE "map_port: " . $$rhUserConf{MAP_PORT}."\n";    
-    print FILE "char_ip: " . $$rhUserConf{CHAR_PRIV_IP}."\n";
-    print FILE "char_port: " . $$rhUserConf{CHAR_PORT}."\n";
+	open FILE, "> $sCurfile" || die "Couldn't open or create file '$sCurfile'.\n";
+	print FILE "userid: " . $$rhUserConf{SERV_UID}."\n";
+	print FILE "passwd: " . $$rhUserConf{SERV_PW}."\n\n";
+
+	print FILE "map_ip: " . $$rhUserConf{SERV_WAN_IP}."\n";
+	print FILE "map_port: " . $$rhUserConf{MAP_PORT}."\n";
+	print FILE "char_ip: " . $$rhUserConf{CHAR_PRIV_IP}."\n";
+	print FILE "char_port: " . $$rhUserConf{CHAR_PORT}."\n";
 }
 
 sub ApplyCharConf { my ($rhUserConf,$sCurfile) = @_;
-    open FILE, "> $sCurfile" || die "Couldn't open file '$sCurfile'.\n";
-    print FILE "userid: " . $$rhUserConf{SERV_UID}."\n";
-    print FILE "passwd: " . $$rhUserConf{SERV_PW}."\n\n";
-	
-    print FILE "char_ip: " . $$rhUserConf{SERV_WAN_IP}."\n";
-    print FILE "char_port: " . $$rhUserConf{CHAR_PORT}."\n";
-    print FILE "login_ip: " . $$rhUserConf{LOGIN_PRIV_IP}."\n";
-    print FILE "login_port: " . $$rhUserConf{LOGIN_PORT}."\n";
-    
-    print FILE "pincode_enabled: " . $$rhUserConf{PINCODE_ENABLE}."\n";
+	open FILE, "> $sCurfile" || die "Couldn't open file '$sCurfile'.\n";
+	print FILE "userid: " . $$rhUserConf{SERV_UID}."\n";
+	print FILE "passwd: " . $$rhUserConf{SERV_PW}."\n\n";
+
+	print FILE "char_ip: " . $$rhUserConf{SERV_WAN_IP}."\n";
+	print FILE "char_port: " . $$rhUserConf{CHAR_PORT}."\n";
+	print FILE "login_ip: " . $$rhUserConf{LOGIN_PRIV_IP}."\n";
+	print FILE "login_port: " . $$rhUserConf{LOGIN_PORT}."\n";
+
+	print FILE "pincode_enabled: " . $$rhUserConf{PINCODE_ENABLE}."\n";
 }
 
 sub ApplyLoginConf { my ($rhUserConf,$sCurfile) = @_;
-    open FILE, "> $sCurfile" || die "Couldn't open file '$sCurfile'.\n";
-    print FILE "login_port: " . $$rhUserConf{LOGIN_PORT}."\n";
-    print FILE "use_MD5_passwords: " . $$rhUserConf{MD5_ENABLE}."\n";
+	open FILE, "> $sCurfile" || die "Couldn't open file '$sCurfile'.\n";
+	print FILE "login_port: " . $$rhUserConf{LOGIN_PORT}."\n";
+	print FILE "use_MD5_passwords: " . $$rhUserConf{MD5_ENABLE}."\n";
 }
 
 sub ApplyInterConf { my ($rhUserConf,$sCurfile) = @_;
-    open FILE, "> $sCurfile" || die "Couldn't open file '$sCurfile'.\n";
-
-    print FILE "login_server_ip: " . $$rhUserConf{SQL_HOST}."\n";
-    print FILE "login_server_port: " . $$rhUserConf{SQL_PORT}."\n";
-    print FILE "login_server_id: " . $$rhUserConf{SQL_UID}."\n";
-    print FILE "login_server_pw: " . $$rhUserConf{SQL_PW}."\n";
-    print FILE "login_server_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
-
-    print FILE "ipban_db_ip: " . $$rhUserConf{SQL_HOST}."\n";
-    print FILE "ipban_db_port: " . $$rhUserConf{SQL_PORT}."\n";
-    print FILE "ipban_db_id: " . $$rhUserConf{SQL_UID}."\n";
-    print FILE "ipban_db_pw: " . $$rhUserConf{SQL_PW}."\n";
-    print FILE "ipban_db_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
-
-    print FILE "char_server_ip: " . $$rhUserConf{SQL_HOST}."\n";
-    print FILE "char_server_port: " . $$rhUserConf{SQL_PORT}."\n";
-    print FILE "char_server_id: " . $$rhUserConf{SQL_UID}."\n";
-    print FILE "char_server_pw: " . $$rhUserConf{SQL_PW}."\n";
-    print FILE "char_server_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
-
-    print FILE "map_server_ip: " . $$rhUserConf{SQL_HOST}."\n";
-    print FILE "map_server_port: " . $$rhUserConf{SQL_PORT}."\n";
-    print FILE "map_server_id: " . $$rhUserConf{SQL_UID}."\n";
-    print FILE "map_server_pw: " . $$rhUserConf{SQL_PW}."\n";
-    print FILE "map_server_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
-
-    print FILE "log_db_ip: " . $$rhUserConf{SQL_HOST} ."\n";
-    print FILE "log_db_port: " . $$rhUserConf{SQL_PORT}."\n";
-    print FILE "log_db_id: " . $$rhUserConf{SQL_UID}."\n";
-    print FILE "log_db_pw: " . $$rhUserConf{SQL_PW}."\n";
-    print FILE "log_db_db: " . $$rhUserConf{SQL_LOG_DB}."\n\n";
+	open FILE, "> $sCurfile" || die "Couldn't open file '$sCurfile'.\n";
+
+	print FILE "login_server_ip: " . $$rhUserConf{SQL_HOST}."\n";
+	print FILE "login_server_port: " . $$rhUserConf{SQL_PORT}."\n";
+	print FILE "login_server_id: " . $$rhUserConf{SQL_UID}."\n";
+	print FILE "login_server_pw: " . $$rhUserConf{SQL_PW}."\n";
+	print FILE "login_server_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
+
+	print FILE "ipban_db_ip: " . $$rhUserConf{SQL_HOST}."\n";
+	print FILE "ipban_db_port: " . $$rhUserConf{SQL_PORT}."\n";
+	print FILE "ipban_db_id: " . $$rhUserConf{SQL_UID}."\n";
+	print FILE "ipban_db_pw: " . $$rhUserConf{SQL_PW}."\n";
+	print FILE "ipban_db_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
+
+	print FILE "char_server_ip: " . $$rhUserConf{SQL_HOST}."\n";
+	print FILE "char_server_port: " . $$rhUserConf{SQL_PORT}."\n";
+	print FILE "char_server_id: " . $$rhUserConf{SQL_UID}."\n";
+	print FILE "char_server_pw: " . $$rhUserConf{SQL_PW}."\n";
+	print FILE "char_server_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
+
+	print FILE "map_server_ip: " . $$rhUserConf{SQL_HOST}."\n";
+	print FILE "map_server_port: " . $$rhUserConf{SQL_PORT}."\n";
+	print FILE "map_server_id: " . $$rhUserConf{SQL_UID}."\n";
+	print FILE "map_server_pw: " . $$rhUserConf{SQL_PW}."\n";
+	print FILE "map_server_db: " . $$rhUserConf{SQL_MAIN_DB}."\n\n";
+
+	print FILE "log_db_ip: " . $$rhUserConf{SQL_HOST} ."\n";
+	print FILE "log_db_port: " . $$rhUserConf{SQL_PORT}."\n";
+	print FILE "log_db_id: " . $$rhUserConf{SQL_UID}."\n";
+	print FILE "log_db_pw: " . $$rhUserConf{SQL_PW}."\n";
+	print FILE "log_db_db: " . $$rhUserConf{SQL_LOG_DB}."\n\n";
 }
 
 sub AutoCheckConf { my ($rhConfig) = @_;
-    print "\n== Auto-Check Configuration ==\n";
+	print "\n== Auto-Check Configuration ==\n";
 	print "NOTE: You can use option --force=1 to bypass this.\n";
-    foreach my $sKeys (keys %$rhConfig){
+	foreach my $sKeys (keys %$rhConfig){
 	my $sVal = $$rhConfig{$sKeys};
 	if($sKeys =~ /PORT/) { #chek if valid port
-	    if(($sVal<MIN_PORT) && ($sVal>MAX_PORT)) {
+		if(($sVal<MIN_PORT) && ($sVal>MAX_PORT)) {
 		warn "Invalid port specified for $sKeys => $sVal. Port must be in [".MIN_PORT.":".MAX_PORT."].\n";
 		return 0;
-	    }
-	    elsif(!($sKeys =~ /SQL/) && CheckUsedPort($sVal)) { #skip SQL service
+		}
+		elsif(!($sKeys =~ /SQL/) && CheckUsedPort($sVal)) { #skip SQL service
 		warn "Port '$sVal' seems to already be in use by your system.\n";
 		return 0;
-	    }
-	    elsif(CheckDupPort($rhConfig,$sKeys)) {
+		}
+		elsif(CheckDupPort($rhConfig,$sKeys)) {
 		warn "Port '$sVal' seems to already be used by another key in config.\n";
 		return 0;
-	    }
+		}
 	}
 	elsif($sKeys =~ /IP|HOST/){ #chek if ip valid, can we reach it ? trough SYN ACK
-	    my $p = Net::Ping->new("syn");
-	    my $sTest = $p->ping($sVal);
-	    $p->close();
-	    unless($sTest) {
+		my $p = Net::Ping->new("syn");
+		my $sTest = $p->ping($sVal);
+		$p->close();
+		unless($sTest) {
 		print "Invalid IP/Host, ping couldn't reach $sKeys => $sVal.\n";
 		print "(NOTE: ICMP may just be unallowed.)\n";
 		return 0;
-	    }
+		}
 	}
-    }
-    return 1;
+	}
+	return 1;
 }
 
 sub CheckDupPort { my ($rhConfig,$sChkKeys) = @_;
-    my $sChkport = $$rhConfig{$sChkKeys};
-    foreach my $sKeys (keys %$rhConfig){
+	my $sChkport = $$rhConfig{$sChkKeys};
+	foreach my $sKeys (keys %$rhConfig){
 		next if($sKeys eq $sChkKeys); #skip ourself
 		my $sVal = $$rhConfig{$sKeys};
 		return 1 if($sChkport eq $sVal);
-    }
-    return 0;
+	}
+	return 0;
 }
 
 
 
 #Db function
 sub ApplySetupDB { my($rhConfig) = @_;
-    my $sDbH; #db handle
-    my $sHost = $$rhConfig{SQL_HOST};
-    my $sPort = $$rhConfig{SQL_PORT};
-    my $sDsn = "dbi:mysql::$sHost:$sPort"; #don't try to auto connect to db
-    $$rhConfig{"Dsn"} = $sDsn;
-
-    $sDbH = RootCo($rhConfig);
-    CreateDB($sDbH,$rhConfig); #create db if not exist
-    $sDbH = CreateUser($sDbH,$rhConfig); #loged as user now
-    LoadSqlFile($sDbH,$rhConfig); #Load .sql file into db
-    CreateServUser($sDbH,$rhConfig);
-    print "Database setup successful.\n";
+	my $sDbH; #db handle
+	my $sHost = $$rhConfig{SQL_HOST};
+	my $sPort = $$rhConfig{SQL_PORT};
+	my $sDsn = "dbi:mysql::$sHost:$sPort"; #don't try to auto connect to db
+	$$rhConfig{"Dsn"} = $sDsn;
+
+	$sDbH = RootCo($rhConfig);
+	CreateDB($sDbH,$rhConfig); #create db if not exist
+	$sDbH = CreateUser($sDbH,$rhConfig); #loged as user now
+	LoadSqlFile($sDbH,$rhConfig); #Load .sql file into db
+	CreateServUser($sDbH,$rhConfig);
+	print "Database setup successful.\n";
 }
 
 
 
 sub CreateDB { my($sDbH,$rhConfig) = @_;
-    print "\n== Creating Databases ==\n";
-    my $sDBn = $$rhConfig{SQL_MAIN_DB};
-    my $sLogDBn = $$rhConfig{SQL_LOG_DB};
-    my @aQuery = ("create database IF NOT EXISTS $sDBn;","create database IF NOT EXISTS $sLogDBn;");
-    if($sClean){ #deleting database if clean
+	print "\n== Creating Databases ==\n";
+	my $sDBn = $$rhConfig{SQL_MAIN_DB};
+	my $sLogDBn = $$rhConfig{SQL_LOG_DB};
+	my @aQuery = ("create database IF NOT EXISTS $sDBn;","create database IF NOT EXISTS $sLogDBn;");
+	if($sClean){ #deleting database if clean
 	unshift(@aQuery,"drop database IF EXISTS $sDBn;");
 	unshift(@aQuery,"drop database IF EXISTS $sLogDBn;");
-    }
-    else {
+	}
+	else {
 	my $sRes = $sDbH->selectcol_arrayref('show databases');
 	foreach my $db (@$sRes){ #relevant later for import
-	    if($db eq "$sDBn") { ValidateDBMerge($db); } #may exit here
-	    elsif ($db eq "$sLogDBn") { ValidateDBMerge($db); } #may exit here
+		if($db eq "$sDBn") { ValidateDBMerge($db); } #may exit here
+		elsif ($db eq "$sLogDBn") { ValidateDBMerge($db); } #may exit here
 	}
-    }
-    ExeQuery($sDbH,@aQuery);
+	}
+	ExeQuery($sDbH,@aQuery);
 }
 
 sub ValidateDBMerge { my($sDBn) = @_;
-    warn "Database '$sDBn' seems to already exist.\n";
-    warn "Do you wish to continue loading data from the existing database? [y/n] \n";
-    if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i) {
+	warn "Database '$sDBn' seems to already exist.\n";
+	warn "Do you wish to continue loading data from the existing database? [y/n] \n";
+	if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i) {
 	print "Exiting setup, please try again with another dbname or manually...\n";
 	exit;
-    }
+	}
 }
 
 sub CreateUser { my($sDbH,$rhConfig) = @_;
-    print "\n== Creating User ==\n";
-    my $sDsn = $$rhConfig{"Dsn"};
-    print "My dsn = $sDsn \n";
-    my $sHost = $$rhConfig{SQL_HOST};
-    my $sPw = $$rhConfig{SQL_PW};
-    my $sUser = $$rhConfig{SQL_UID};
-    my $sDBn = $$rhConfig{SQL_MAIN_DB};
-    my $sLogDBn = $$rhConfig{SQL_LOG_DB};
-
-    my @aQuery= ("GRANT ALL PRIVILEGES ON $sDBn.* TO $sUser\@'$sHost' IDENTIFIED BY '$sPw' WITH GRANT OPTION", #maindb
-		 "GRANT ALL PRIVILEGES ON $sLogDBn.* TO $sUser\@'$sHost' IDENTIFIED BY '$sPw' WITH GRANT OPTION"); #logdb
-    my $sUserDbh = DBI->connect($sDsn, $sUser, $sPw,  {"PrintError" => 0}); #try connect with user
-
-    if($sUserDbh && !$sClean) {
+	print "\n== Creating User ==\n";
+	my $sDsn = $$rhConfig{"Dsn"};
+	print "My dsn = $sDsn \n";
+	my $sHost = $$rhConfig{SQL_HOST};
+	my $sPw = $$rhConfig{SQL_PW};
+	my $sUser = $$rhConfig{SQL_UID};
+	my $sDBn = $$rhConfig{SQL_MAIN_DB};
+	my $sLogDBn = $$rhConfig{SQL_LOG_DB};
+
+	my @aQuery= ("GRANT ALL PRIVILEGES ON $sDBn.* TO $sUser\@'$sHost' IDENTIFIED BY '$sPw' WITH GRANT OPTION", #maindb
+		"GRANT ALL PRIVILEGES ON $sLogDBn.* TO $sUser\@'$sHost' IDENTIFIED BY '$sPw' WITH GRANT OPTION"); #logdb
+	my $sUserDbh = DBI->connect($sDsn, $sUser, $sPw,  {"PrintError" => 0}); #try connect with user
+
+	if($sUserDbh && !$sClean) {
 	print "User '$sUser' seems to already exist, skipping creation...\n"
-	    ."(Please check if you have correct privileges set for database '$sDBn'.)\n";
-    }
-    else { #create user only if not exist (or mode clean)
+		."(Please check if you have correct privileges set for database '$sDBn'.)\n";
+	}
+	else { #create user only if not exist (or mode clean)
 	if($sClean && $sUser ne "root"){ unshift(@aQuery,"DELETE FROM mysql.user WHERE User = '$sUser';"); }
 	print "Creating user $sUser for databases '$sDBn' and '$sLogDBn' on '$sHost'.\n";
 	ExeQuery($sDbH,@aQuery);
 	$sUserDbh = DBI->connect($sDsn, $sUser, $sPw);
-    }
-    return $sUserDbh; #drop old co and connect with user now
+	}
+	return $sUserDbh; #drop old co and connect with user now
 }
 
 sub LoadSqlFile { my($sDbH,$rhConfig) = @_;
-    print "\n== Loading SQL Files ==\n";
-    my $sDBn = $$rhConfig{SQL_MAIN_DB};
-    my $sLogDBn = $$rhConfig{SQL_LOG_DB};
+	print "\n== Loading SQL Files ==\n";
+	my $sDBn = $$rhConfig{SQL_MAIN_DB};
+	my $sLogDBn = $$rhConfig{SQL_LOG_DB};
 
-    my $sSqldir = "sql-files";
-    my @aMainFiles = ("main.sql"); #add other file to load for main db here
-    my @aLogFiles = ("logs.sql"); #add other file to load for log db here
+	my $sSqldir = "sql-files";
+	my @aMainFiles = ("main.sql"); #add other file to load for main db here
+	my @aLogFiles = ("logs.sql"); #add other file to load for log db here
 
-    die "$sSqldir doesn't seem to exist or couldn't be read." unless(-d -r "../$sSqldir");
-    chdir "../$sSqldir";
-    print "Checking if target files exist:\n\tMain: [@aMainFiles]\n\tLog: [@aLogFiles]\n";
+	die "$sSqldir doesn't seem to exist or couldn't be read." unless(-d -r "../$sSqldir");
+	chdir "../$sSqldir";
+	print "Checking if target files exist:\n\tMain: [@aMainFiles]\n\tLog: [@aLogFiles]\n";
 
-    CheckAndLoadSQL(\@aMainFiles,$rhConfig,$sDBn);
-    CheckAndLoadSQL(\@aLogFiles,$rhConfig,$sLogDBn);
+	CheckAndLoadSQL(\@aMainFiles,$rhConfig,$sDBn);
+	CheckAndLoadSQL(\@aLogFiles,$rhConfig,$sLogDBn);
 
 #    my $raMainQuerys = CheckAndAddQuery(\@aMainFiles,$rhConfig);
 #    my $raLogQuerys = CheckAndAddQuery(\@aLogFiles,$rhConfig);
@@ -531,43 +530,43 @@ sub LoadSqlFile { my($sDbH,$rhConfig) = @_;
 #}
 
 sub CreateServUser { my($sDbH,$rhConfig) = @_;
-    my $sUid = $$rhConfig{SERV_UID};
-    my $sUpw = $$rhConfig{SERV_PW};
-    my $sMD5 = $$rhConfig{MD5_ENABLE};
-    my $sDBn = $$rhConfig{SQL_MAIN_DB};
-    my @aQuery = ("use $sDBn;","DELETE FROM login WHERE sex='S';");
-    if($sMD5){ push(@aQuery,"INSERT INTO login(account_id, userid, user_pass, sex) values(1,'$sUid',MD5('$sUpw'),'S');"); }
-    else { push(@aQuery,"INSERT INTO login(account_id, userid, user_pass, sex) values(1,'$sUid','$sUpw','S');"); }
-    ExeQuery($sDbH,@aQuery);
+	my $sUid = $$rhConfig{SERV_UID};
+	my $sUpw = $$rhConfig{SERV_PW};
+	my $sMD5 = $$rhConfig{MD5_ENABLE};
+	my $sDBn = $$rhConfig{SQL_MAIN_DB};
+	my @aQuery = ("use $sDBn;","DELETE FROM login WHERE sex='S';");
+	if($sMD5){ push(@aQuery,"INSERT INTO login(account_id, userid, user_pass, sex) values(1,'$sUid',MD5('$sUpw'),'S');"); }
+	else { push(@aQuery,"INSERT INTO login(account_id, userid, user_pass, sex) values(1,'$sUid','$sUpw','S');"); }
+	ExeQuery($sDbH,@aQuery);
 }
 
 sub GetDesiredConf { my ($rhDefConf) = @_;
-    print "Please enter desired configuration.\n";
-    my $rhUserConf;
-    my $sDesdConfFile = $sDsdFile;
-    #if default search in conf otherwise get specified name with cwd
-    if($sDsdFile eq DESD_CONF_FILE) { $sDesdConfFile = "../conf/".$sDsdFile; }
-
-    print "Checking if there is a DesiredConf file...\n";
-    if(-e -r $sDesdConfFile) {
+	print "Please enter desired configuration.\n";
+	my $rhUserConf;
+	my $sDesdConfFile = $sDsdFile;
+	#if default search in conf otherwise get specified name with cwd
+	if($sDsdFile eq DESD_CONF_FILE) { $sDesdConfFile = "../conf/".$sDsdFile; }
+
+	print "Checking if there is a DesiredConf file...\n";
+	if(-e -r $sDesdConfFile) {
 	print "Found DesiredConf.\n";
 	$rhUserConf = YAML::XS::LoadFile($sDesdConfFile);
 	if(!($rhUserConf)){
-	    print "DesiredConf is invalid or empty. Please check the file, and relaunch setup or enter Config.\n";
-	    $rhUserConf=GetValidateConf($rhDefConf);
+		print "DesiredConf is invalid or empty. Please check the file, and relaunch setup or enter Config.\n";
+		$rhUserConf=GetValidateConf($rhDefConf);
 	}
 	else {
-	    ShowConfig($rhUserConf);
-	    print "Would you like to apply these settings? [y/n] ";
-	    if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i) {  #no take user entry
+		ShowConfig($rhUserConf);
+		print "Would you like to apply these settings? [y/n] ";
+		if(GetValidAnwser("y|o|n",$sAutoyes) =~ /n/i) {  #no take user entry
 		print "DesiredConf not applied. Please enter config.\n";
 		$rhUserConf=GetValidateConf($rhDefConf);
-	    }
+		}
+	}
 	}
-    }
-    else { #no files take user entry
+	else { #no files take user entry
 	print "No DesiredConf found. Please enter config.\n";
 	$rhUserConf=GetValidateConf($rhDefConf);
-    }
-    return $rhUserConf;
+	}
+	return $rhUserConf;
 }

+ 54 - 54
tools/convert_emotions.py

@@ -113,13 +113,13 @@ emotion_dict_old = collections.OrderedDict([
 ])
 """
 def parse_emotion_dict(filepath):
-    ret_list = []
-    with fileinput.FileInput(filepath) as fiFile:
-        for line in fiFile:
-            found = re.search('"(E_[A-Z_0-9]+)"\s*,\s*(ET_[A-Z_0-9]+)\s*', line)
-            if found:
-                ret_list.append((found.group(1), found.group(2)))
-    return ret_list
+	ret_list = []
+	with fileinput.FileInput(filepath) as fiFile:
+		for line in fiFile:
+			found = re.search('"(E_[A-Z_0-9]+)"\s*,\s*(ET_[A-Z_0-9]+)\s*', line)
+			if found:
+				ret_list.append((found.group(1), found.group(2)))
+	return ret_list
 
 emotion_dict = collections.OrderedDict(parse_emotion_dict(parse_dict_file))
 
@@ -128,59 +128,59 @@ pattern_oldconst = re.compile(r'\b(' + '|'.join(emotion_dict.keys()) + r')\b', r
 pattern_value = re.compile(r'\b(' + '|'.join(["emotion\s+%d+"%i for i in range(len(emotion_array))]) + r')\b', re.IGNORECASE)
 
 def revert_to_backup(filename):
-   os.rename(filename+BACKUP_EXT, filename)
-   
+	os.rename(filename+BACKUP_EXT, filename)
+
 def apply_substitutions(new_line, is_script):
-    remove_backup = True # only keep backup if the original file changed
-    rpl_cnt = 0
-    # E_GASP -> ET_SURPRISE
-    new_line, rpl_cnt = pattern_oldconst.subn(lambda x: emotion_dict[x.group().upper()], new_line)
-    remove_backup = False if rpl_cnt > 0 else remove_backup
-    if is_script: # script only replacements
-        # 0 -> ET_SURPRISE
-        new_line, rpl_cnt = pattern_value.subn(lambda x: 'emotion '+emotion_array[int(x.group().split()[-1])], new_line)
-        remove_backup = False if rpl_cnt > 0 else remove_backup
-        # emotion e,0,"Record player#e152a01"; -> emotion e, getnpcid(0,"Record player#e152a01");
-        new_line, rpl_cnt = re.subn(r"emotion\s+([^,]+)\s*,\s*0\s*,\s*([^;]+);",
-                           "emotion \g<1>, getnpcid(0, \g<2>);", new_line)
-        remove_backup = False if rpl_cnt > 0 else remove_backup
-        # emotion e,1; -> emotion e, playerattached();
-        new_line, rpl_cnt = re.subn(r"emotion\s+([^,]+)\s*,\s*1\s*;",
-                           "emotion \g<1>, playerattached();", new_line)
-        remove_backup = False if rpl_cnt > 0 else remove_backup
-        # unitemote <id>,<emotion>; -> emotion <emotion>, <id>;
-        new_line, rpl_cnt = re.subn(r"unitemote\s+([^,]+)\s*,\s*([^,;]+)\s*;",
-                           "emotion \g<2>, \g<1>;", new_line)
-        remove_backup = False if rpl_cnt > 0 else remove_backup
+	remove_backup = True # only keep backup if the original file changed
+	rpl_cnt = 0
+	# E_GASP -> ET_SURPRISE
+	new_line, rpl_cnt = pattern_oldconst.subn(lambda x: emotion_dict[x.group().upper()], new_line)
+	remove_backup = False if rpl_cnt > 0 else remove_backup
+	if is_script: # script only replacements
+		# 0 -> ET_SURPRISE
+		new_line, rpl_cnt = pattern_value.subn(lambda x: 'emotion '+emotion_array[int(x.group().split()[-1])], new_line)
+		remove_backup = False if rpl_cnt > 0 else remove_backup
+		# emotion e,0,"Record player#e152a01"; -> emotion e, getnpcid(0,"Record player#e152a01");
+		new_line, rpl_cnt = re.subn(r"emotion\s+([^,]+)\s*,\s*0\s*,\s*([^;]+);",
+						"emotion \g<1>, getnpcid(0, \g<2>);", new_line)
+		remove_backup = False if rpl_cnt > 0 else remove_backup
+		# emotion e,1; -> emotion e, playerattached();
+		new_line, rpl_cnt = re.subn(r"emotion\s+([^,]+)\s*,\s*1\s*;",
+						"emotion \g<1>, playerattached();", new_line)
+		remove_backup = False if rpl_cnt > 0 else remove_backup
+		# unitemote <id>,<emotion>; -> emotion <emotion>, <id>;
+		new_line, rpl_cnt = re.subn(r"unitemote\s+([^,]+)\s*,\s*([^,;]+)\s*;",
+						"emotion \g<2>, \g<1>;", new_line)
+		remove_backup = False if rpl_cnt > 0 else remove_backup
 
-    return new_line, remove_backup
+	return new_line, remove_backup
 
 def replace_emoticons_in_file(filename):
-    is_script = True if any([filename.endswith(script_ext) for script_ext in script_file_extensions]) else False
-    remove_backup = True
-    with fileinput.FileInput(filename, inplace=True, backup=BACKUP_EXT) as fiFile:
-        try:
-            for line in fiFile:
-                new_line, rm_backup = apply_substitutions(line, is_script)
-                if not rm_backup:
-                    remove_backup = False
-                print(new_line, end='')
-            if remove_backup:
-                os.remove(filename+BACKUP_EXT)
-        except UnicodeDecodeError:
-            # Encoding error, reapply the backup
-            revert_to_backup(filename)
+	is_script = True if any([filename.endswith(script_ext) for script_ext in script_file_extensions]) else False
+	remove_backup = True
+	with fileinput.FileInput(filename, inplace=True, backup=BACKUP_EXT) as fiFile:
+		try:
+			for line in fiFile:
+				new_line, rm_backup = apply_substitutions(line, is_script)
+				if not rm_backup:
+					remove_backup = False
+				print(new_line, end='')
+			if remove_backup:
+				os.remove(filename+BACKUP_EXT)
+		except UnicodeDecodeError:
+			# Encoding error, reapply the backup
+			revert_to_backup(filename)
 
 
 fileiter = (os.path.join(root, f)
-    for conv_folder in convert_folders 
-    for root, _, files in os.walk(conv_folder)
-    for f in files
-    if any([f.endswith(wl) for wl in wl_file_extensions])
-    if not any([bl in f for bl in bl_files])
-    )
+	for conv_folder in convert_folders
+	for root, _, files in os.walk(conv_folder)
+	for f in files
+	if any([f.endswith(wl) for wl in wl_file_extensions])
+	if not any([bl in f for bl in bl_files])
+	)
 
 for f in fileiter:
-    print("Updating file", f)
-    replace_emoticons_in_file(f)
-    
+	print("Updating file", f)
+	replace_emoticons_in_file(f)
+

+ 7 - 7
tools/convert_monstermode.pl

@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 # rAthena Monster Mode Converter
 # Upgrades monster's mode to the new structure.
-# 
+#
 
 use strict;
 use warnings;
@@ -102,15 +102,15 @@ sub Main {
 			next;
 		}
 		unless(open FHOUT,">$sFileouttmp"){
-		   print "ERROR: Can't write or locate $aFileout[$sI].\n";
-		   next;
+			print "ERROR: Can't write or locate $aFileout[$sI].\n";
+			next;
 		}
 		$sI++;
 		while (<FHIN>){
 			if( $_ =~ /^\s*$/) {  #ignore empty line
-				print FHOUT $_; 
-				next;  
-			} 
+				print FHOUT $_;
+				next;
+			}
 			my @champ = split(",",$_);
 			my $sDoconvertion=0; #should this comment be converted
 			if( $_ =~ /^\/\// ) { # // line
@@ -121,7 +121,7 @@ sub Main {
 				}
 				if($sDoconvertion==0) {
 					print FHOUT $_;
-					next; 
+					next;
 				}
 			}
 			if(scalar(@champ>0)){

+ 2 - 2
tools/convert_sql.pl

@@ -85,7 +85,7 @@ sub ConvertFile { my($sFilein,$sFileout,$sType)=@_;
 	print "Starting ConvertFile with: \n\t filein=$sFilein \n\t fileout=$sFileout \n";
 	open FHIN,"$sFilein" or die "ERROR: Can't read or locate $sFilein.\n";
 	open $sFHout,">$sFileout" or die "ERROR: Can't write $sFileout.\n";
-	
+
 	printf $sFHout ("%s\n",$create_table);
 	while(my $ligne=<FHIN>) {
 		my $sWasCom = 0;
@@ -176,7 +176,7 @@ sub escape { my ($str,$sregex,$sreplace) = @_;
 
 sub BuildDataForType{ my($sTarget,$sType) = @_;
 	print "Starting BuildDataForType with: \n\t Target=$sTarget, Type=$sType \n";
-	
+
 	if($sType =~ /mob_skill/i) { #Same format for Pre-Renewal and Renewal.
 		$db = $sTable;
 		if($sTarget =~ /Pre/i){

+ 5 - 7
tools/runserver.bat

@@ -27,8 +27,6 @@ if "%target%" == "status" (
  call :Watch
 ) else if "%target%" == "stop" (
  call :Stop
-) else if "%target%" == "stop" (
- call :Stop
 ) else if "%target%" == "start" (
  call :Start
 )
@@ -69,7 +67,7 @@ call :getCharStatus
 call :getWebStatus
 call :getMapStatus
 
-if "%login_running%" == "false" ( echo "login_serv is not running" 
+if "%login_running%" == "false" ( echo "login_serv is not running"
 ) else echo "login_serv is running pid=%LoginServPID%"
 if "%char_running%" == "false" ( echo "char_serv is not running"
 ) else echo "char_serv is running pid=%CharServPID%"
@@ -111,13 +109,13 @@ REM start sub targets
 :startLogin
 call :getLoginStatus
 if "%login_running%" == "false" ( start cmd /k logserv.bat %restart_mode%
-) else echo "Login serv is already running pid=%LoginServPID%" 
+) else echo "Login serv is already running pid=%LoginServPID%"
 goto :EOF
 
 :startChar
 call :getCharStatus
 if "%char_running%" == "false" ( start cmd /k charserv.bat %restart_mode%
-) else echo "Char serv is already running, pid=%CharServPID%" 
+) else echo "Char serv is already running, pid=%CharServPID%"
 goto :EOF
 
 :startWeb
@@ -129,8 +127,8 @@ goto :EOF
 :startMap
 call :getMapStatus
 if "%map_running%" == "false" ( start cmd /k mapserv.bat %restart_mode%
-) else echo "Map serv is already running, pid=%MapServPID%" 
-goto :EOF  
+) else echo "Map serv is already running, pid=%MapServPID%"
+goto :EOF
 
 REM status sub targets
 

+ 1 - 1
tools/stackdump

@@ -57,7 +57,7 @@ fi
 # Finally dump the backtrace
 # If number is given, Sig-plugin format. otherwise, standard stackdump format
 if [ $# -gt 2 ]; then
-	awk '$2 ~ /[0-9a-eA-E]\]$/{print $2}' $STACK | tr -d \[\] | addr2line -f -e $SERVER 
+	awk '$2 ~ /[0-9a-eA-E]\]$/{print $2}' $STACK | tr -d \[\] | addr2line -f -e $SERVER
 else
 	awk '/^[0-9]/{print $2}' $STACK | addr2line -f -e $SERVER
 fi

+ 27 - 27
tools/update.pl

@@ -51,7 +51,7 @@ sub GetArgs {
 	'target=s'	=> \$sTarget,	 #Target (which setup to run)
 	'help!' => \$sHelp,
 	) or $sHelp=1; #display help if invalid option
-	
+
 	if( $sHelp ) {
 	print "Incorrect option specified. Available options:\n"
 	    ."\t --target => target (specify which check to ignore [$sValidTarget])\n";
@@ -59,7 +59,7 @@ sub GetArgs {
 	}
 	if(!$sTarget || !($sTarget =~ /$sValidTarget/i)){
 		print "Incorrect target specified. Available targets:\n"
-			."\t --target => target (specify which check to ignore [(default)$sValidTarget])\n 
+			."\t --target => target (specify which check to ignore [(default)$sValidTarget])\n
 			(NOTE: restart is compiling dependent.)\n";
 		exit;
     }
@@ -68,7 +68,7 @@ sub GetArgs {
 sub Main {
 	my $sCurdir = getcwd;
 	chdir "..";
-	
+
 	UpdateSQL($sCurdir,1,\%hFileState);
 	if($sTarget =~ "All|Upd") { GitUpdate($sCurdir); }
 	if($sTarget =~ "All|DB") { UpdateSQL($sCurdir,0,\%hFileState); }
@@ -77,8 +77,8 @@ sub Main {
 
 sub GetSqlFileInDir { my($sDir) = @_;
 	opendir (DIR, $sDir) or die $!;
-	my @aFiles 
-		= grep { 
+	my @aFiles
+		= grep {
 		/^(?!\.)/      # not begins with a period
 		&& /\.sql$/      # finish by .sql
 		&& -f "$sDir/$_"   # and is a file
@@ -98,7 +98,7 @@ sub UpdateSQL  { my($sBaseDir,$sInit,$rhFileState) = @_;
 		print "Reading file status...\n";
 		$rhFileState = YAML::XS::LoadFile("sql-files/".STATE_FILE);
 	}
-	
+
 	if($sTarget =~ "All|MapDB") {
 			chdir "sql-files";
 			print "Getting Map SQL Db file...\n";
@@ -119,17 +119,17 @@ sub UpdateSQL  { my($sBaseDir,$sInit,$rhFileState) = @_;
 			}
 			chdir "..";
 	}
-	
+
 	chdir "sql-files/upgrades";
 	my $raFiles = GetSqlFileInDir("./");
-	
+
 	foreach my $sFile (@$raFiles){
 		#print "Cur file = $sFile \n";
 		if($sInit==1){
 			if(exists $$rhFileState{$sFile} && $$rhFileState{$sFile}{"status"} == ST_DONE ){
 				next;
 			}
-			
+
 			if( $sFile =~ /_opt_/){
 				$$rhFileState{$sFile}{"status"} = ST_SK;
 			} else {
@@ -144,42 +144,42 @@ sub UpdateSQL  { my($sBaseDir,$sInit,$rhFileState) = @_;
 		#		#if it's done or skipped don't do it, if it's old but updated do it
 				next if ( $sT eq ST_OLD or $sT eq ST_DONE or $sLastMode == (stat ($sFile))[9] );
 			}
-			
-			if( $sFile =~ /_log.sql$/) { 
+
+			if( $sFile =~ /_log.sql$/) {
 				print "Found log file '$sFile'.\n";
 				push(@aLogDBFiles,$sFile);
 			}
-			else { 
+			else {
 				print "Found char file '$sFile'.\n";
 				push(@aCharDBFiles,$sFile);
 			}
 			$$rhFileState{$sFile}{"status"} = "done"; #  the query will be applied so mark it so
-			
+
 		# This part is for distributed DB, not supported yet
 		# proposed nomenclature [lighta] : update_date_{opt_}(map|chr|acc|log).sql
 		# (e.g : update_20141218_opt_map.sql or update_20141218_acc.sql
-		
-		#	if( $sFile =~ /_map.sql$/) { 
+
+		#	if( $sFile =~ /_map.sql$/) {
 		#		print "Found log file = $sFile \n";
 		#		push(@aMapDBFiles,$sFile);
-		#		
+		#
 		#	}
-		#	elsif( $sFile =~ /_acc.sql$/) { 
+		#	elsif( $sFile =~ /_acc.sql$/) {
 		#		print "Found log file = $sFile \n";
 		#		push(@aLoginDBFiles,$sFile);
-		#		
+		#
 		#	}
-		#	elsif( $sFile =~ /_chr.sql$/) { 
+		#	elsif( $sFile =~ /_chr.sql$/) {
 		#		print "Found log file = $sFile \n";
 		#		push(@aCharDBFiles,$sFile);
-		#		
+		#
 		#	}
 		}
 	}
 	if($sInit==0){ #apply update
 		return;
-		if( scalar(@aCharDBFiles)==0 and  scalar(@aLogDBFiles)==0 
-			and  scalar(@aMapDBFiles)==0 and  scalar(@aLoginDBFiles)==0
+		if( scalar(@aCharDBFiles)==0 and scalar(@aLogDBFiles)==0 
+			and  scalar(@aMapDBFiles)==0 and scalar(@aLoginDBFiles)==0
 		){
 			print "No SQL update to perform.\n";
 		}
@@ -194,7 +194,7 @@ sub UpdateSQL  { my($sBaseDir,$sInit,$rhFileState) = @_;
 			else {
 				$rhUserConf=\%hDefConf; #we assume it's set correctly
 			}
-			
+
 			CheckAndLoadSQL(\@aMapDBFiles,$rhUserConf,$$rhUserConf{SQL_MAP_DB});
 			CheckAndLoadSQL(\@aCharDBFiles,$rhUserConf,$$rhUserConf{SQL_MAIN_DB});
 			#CheckAndLoadSQL(\@aLoginDBFiles,$rhUserConf,$$rhUserConf{SQL_ACC_DB});
@@ -228,7 +228,7 @@ sub GitUpdate { my($sBaseDir) = @_;
 	my $sGit = Git::Repository->new(
 		work_tree => "$sBaseDir/..",
 	);
-	
+
 	my $sIsOrigin = CheckRemote($sGit);
 	if($sIsOrigin==0){
 		print "Saving current working tree...\n";
@@ -252,10 +252,10 @@ sub GitUpdate { my($sBaseDir) = @_;
 sub CheckRemote { my($sGit) = @_;
 	my $sRaOrigin=0;
 	my $sRaUpstream=0;
-	
+
 	print "Checking remotes\n";
-	my @aRemotes = $sGit->run("remote" => "-v");	
-	
+	my @aRemotes = $sGit->run("remote" => "-v");
+
 	#print "My Remotes are\n";
 	foreach my $sCurRem (@aRemotes){
 		my @aCol = split(' ',$sCurRem);

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác