Browse Source

Merge pull request #2 from rathena/master

rathena -> fork
anubisK 10 years ago
parent
commit
78f9f797ae
95 changed files with 7345 additions and 5938 deletions
  1. 16 2
      conf/battle/feature.conf
  2. 3 0
      conf/battle/misc.conf
  3. 16 0
      conf/battle/player.conf
  4. 1 0
      conf/groups.conf
  5. 6 0
      conf/login_athena.conf
  6. 3 3
      conf/msg_conf/map_msg.conf
  7. 39 21
      conf/msg_conf/map_msg_idn.conf
  8. 2 1
      conf/subnet_athena.conf
  9. 1 0
      db/const.txt
  10. 1 0
      db/import-tmpl/item_avail.txt
  11. 1 0
      db/item_avail.txt
  12. 4 4
      db/pre-re/attr_fix.txt
  13. 10 10
      db/pre-re/skill_db.txt
  14. 2 2
      db/pre-re/skill_unit_db.txt
  15. 4 4
      db/re/attr_fix.txt
  16. 20 6
      db/re/item_db.txt
  17. 1 1
      db/re/skill_cast_db.txt
  18. 10 10
      db/re/skill_db.txt
  19. 2 2
      db/re/skill_unit_db.txt
  20. 15 0
      doc/atcommands.txt
  21. 200 0
      doc/mob_db.txt
  22. 25 23
      doc/mob_db_mode_list.txt
  23. 145 0
      doc/skill_require_db.txt
  24. 8 7
      npc/custom/events/cluckers.txt
  25. 270 277
      npc/other/comodo_gambling.txt
  26. 117 137
      npc/quests/first_class/tu_acolyte.txt
  27. 136 171
      npc/quests/first_class/tu_archer.txt
  28. 677 1217
      npc/quests/first_class/tu_ma_th01.txt
  29. 79 112
      npc/quests/first_class/tu_magician01.txt
  30. 347 632
      npc/quests/first_class/tu_merchant.txt
  31. 184 183
      npc/quests/first_class/tu_thief01.txt
  32. 521 393
      npc/quests/quests_airship.txt
  33. 272 242
      npc/quests/quests_moscovia.txt
  34. 10 0
      npc/re/other/stone_change.txt
  35. 3 3
      npc/re/quests/quests_brasilis.txt
  36. 26 91
      npc/warps/dungeons/mosk_dun.txt
  37. 20 6
      sql-files/item_db_re.sql
  38. 1 1
      sql-files/logs.sql
  39. 6 0
      sql-files/main.sql
  40. 1 0
      sql-files/upgrades/upgrade_20140713.sql
  41. 7 0
      sql-files/upgrades/upgrade_20140723.sql
  42. 3 35
      src/char/char.c
  43. 9 0
      src/char/char_clif.c
  44. 2 2
      src/char/char_mapif.c
  45. 1 1
      src/common/mmo.h
  46. 7 1
      src/common/utils.h
  47. 3 0
      src/config/const.h
  48. 115 53
      src/login/account.c
  49. 11 6
      src/login/account.h
  50. 135 103
      src/login/ipban.c
  51. 36 11
      src/login/ipban.h
  52. 116 934
      src/login/login.c
  53. 135 15
      src/login/login.h
  54. 972 0
      src/login/loginchrif.c
  55. 56 0
      src/login/loginchrif.h
  56. 564 0
      src/login/loginclif.c
  57. 42 0
      src/login/loginclif.h
  58. 176 0
      src/login/logincnslif.c
  59. 58 0
      src/login/logincnslif.h
  60. 95 65
      src/login/loginlog.c
  61. 49 3
      src/login/loginlog.h
  62. 9 3
      src/login/sql/CMakeLists.txt
  63. 29 14
      src/map/atcommand.c
  64. 197 254
      src/map/battle.c
  65. 6 2
      src/map/battle.h
  66. 167 76
      src/map/buyingstore.c
  67. 5 2
      src/map/buyingstore.h
  68. 4 2
      src/map/cashshop.c
  69. 9 12
      src/map/chrif.c
  70. 106 78
      src/map/clif.c
  71. 18 2
      src/map/clif.h
  72. 4 4
      src/map/elemental.c
  73. 10 2
      src/map/map.c
  74. 9 5
      src/map/map.h
  75. 4 4
      src/map/mercenary.c
  76. 26 16
      src/map/mob.c
  77. 75 71
      src/map/npc.c
  78. 140 59
      src/map/pc.c
  79. 21 3
      src/map/pc.h
  80. 37 29
      src/map/script.c
  81. 1 2
      src/map/searchstore.c
  82. 265 226
      src/map/skill.c
  83. 4 3
      src/map/skill.h
  84. 140 164
      src/map/status.c
  85. 3 3
      src/map/status.h
  86. 57 36
      src/map/unit.c
  87. 77 47
      src/map/vending.c
  88. 1 1
      src/map/vending.h
  89. 9 3
      vcproj-10/login-server_sql.vcxproj
  90. 23 5
      vcproj-10/login-server_sql.vcxproj.filters
  91. 9 3
      vcproj-12/login-server_sql.vcxproj
  92. 23 5
      vcproj-12/login-server_sql.vcxproj.filters
  93. 9 3
      vcproj-13/login-server_sql.vcxproj
  94. 24 6
      vcproj-13/login-server_sql.vcxproj.filters
  95. 27 3
      vcproj-9/login-server_sql.vcproj

+ 16 - 2
conf/battle/feature.conf

@@ -39,7 +39,21 @@ feature.autotrade: on
 // In which direction should respawned autotraders look?
 // In which direction should respawned autotraders look?
 // Possible values are from 0-7
 // Possible values are from 0-7
 // Default: 4(South)
 // Default: 4(South)
+// -1 = Last player's direction
 feature.autotrade_direction: 4
 feature.autotrade_direction: 4
 
 
-// Do you want your autotraders to sit? (Note 1)
-feature.autotrade_sit: yes
+// Change player's head direction?
+// -1 = Last condition
+//  0 = Forward
+//  1 = Right
+//  2 = Left
+feature.autotrade_head_direction: 0
+
+// Do you want your autotraders to sit?
+// -1 = Last player's condition, sitting or standing
+//  0 = Standing
+//  1 = Sitting
+feature.autotrade_sit: 1
+
+// Delay in miliseconds to open vending/buyingsotre after player logged in.
+feature.autotrade_open_delay: 5000

+ 3 - 0
conf/battle/misc.conf

@@ -101,6 +101,9 @@ at_mapflag: no
 // Set this to the amount of minutes autotrade chars will be kicked from the server.
 // Set this to the amount of minutes autotrade chars will be kicked from the server.
 at_timeout: 0
 at_timeout: 0
 
 
+// Makes player cannot be attacked when autotrade? (turns player's state.monster_ignore) (Note 1)
+at_monsterignore: no
+
 // Auction system, fee per hour. Default is 12000
 // Auction system, fee per hour. Default is 12000
 auction_feeperhour: 12000
 auction_feeperhour: 12000
 
 

+ 16 - 0
conf/battle/player.conf

@@ -229,3 +229,19 @@ fame_pharmacy_3: 1
 fame_pharmacy_5: 3
 fame_pharmacy_5: 3
 fame_pharmacy_7: 10
 fame_pharmacy_7: 10
 fame_pharmacy_10: 50
 fame_pharmacy_10: 50
+
+// How the server should measure the character's idle time? (Note 3)
+// 0x001 - Walk Request
+// 0x002 - UseSkillToID Request (Targetted skill use attempt)
+// 0x004 - UseSkillToPos Request (AoE skill use attempt)
+// 0x008 - UseItem Request (Including equip/unequip)
+// 0x010 - Attack Request
+// 0x020 - Chat Request (Whisper, Party, Guild, Battlegrounds, etc)
+// 0x040 - Sit/Standup Request
+// 0x080 - Emotion Request
+// 0x100 - DropItem Request
+// 0x200 - @/#Command Request
+// Please note that at least 1 option has to be enabled.
+// Be mindful that the more options used, the easier it becomes to cheat features that rely on idletime (e.g. checkidle()).
+// Default: walk (0x1) + useskilltoid (0x2) + useskilltopos (0x4) + useitem (0x8) + attack (0x10) = 0x1F
+idletime_option: 0x1F

+ 1 - 0
conf/groups.conf

@@ -292,6 +292,7 @@ groups: (
 		can_trade_bounded: true
 		can_trade_bounded: true
 		item_unconditional: false
 		item_unconditional: false
 		bypass_stat_onclone: true
 		bypass_stat_onclone: true
+		bypass_max_stat: true
 		/* all_permission: true */
 		/* all_permission: true */
 	}
 	}
 }
 }

+ 6 - 0
conf/login_athena.conf

@@ -180,5 +180,11 @@ client_hash_check: off
 //client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae
 //client_hash: 10, cb1ea78023d337c38e8ba5124e2338ae
 //client_hash: 99, disabled
 //client_hash: 99, disabled
 
 
+//New registration flood protection [Kevin]
+//Number of new registration allowed
+allowed_regs: 1
+//Time in second before the counter for the number of registration is reset
+time_allowed: 10
+
 import: conf/inter_athena.conf
 import: conf/inter_athena.conf
 import: conf/import/login_conf.txt
 import: conf/import/login_conf.txt

+ 3 - 3
conf/msg_conf/map_msg.conf

@@ -392,8 +392,8 @@
 377:  -- Player %s has rejected the duel --
 377:  -- Player %s has rejected the duel --
 //etc
 //etc
 378: Eleanor is now in %s mode.
 378: Eleanor is now in %s mode.
-379: Able to use %.1f min later.
-380: Able to use %d sec later.
+379: Item Failed. [%s] is cooling down. Wait %.1f minutes.
+380: Item Failed. [%s] is cooling down. Wait %d seconds.
 381: Skill Failed. [%s] requires %dx %s.
 381: Skill Failed. [%s] requires %dx %s.
 382: You're too close to a stone or emperium to use this skill.
 382: You're too close to a stone or emperium to use this skill.
 383: You cannot create a savepoint in an instance.
 383: You cannot create a savepoint in an instance.
@@ -404,7 +404,7 @@
 387: The chosen emblem was detected invalid as it contain too much transparency (limit=%d)
 387: The chosen emblem was detected invalid as it contain too much transparency (limit=%d)
 //etc
 //etc
 388: You cannot use this item while storage is open.
 388: You cannot use this item while storage is open.
-//389 free
+389: Speed returned to normal.
 //NoAsk
 //NoAsk
 390: Autorejecting is activated.
 390: Autorejecting is activated.
 391: Autorejecting is deactivated.
 391: Autorejecting is deactivated.

+ 39 - 21
conf/msg_conf/map_msg_idn.conf

@@ -392,9 +392,9 @@
 377:  -- Pemain %s telah menolak permintaan duel --
 377:  -- Pemain %s telah menolak permintaan duel --
 //lain-lain
 //lain-lain
 378: Eleanor sekarang dalam mode %s.
 378: Eleanor sekarang dalam mode %s.
-379: Dapat digunakan setelah %.1f menit.
-380: Dapat digunakan setelah %d detik.
-381: Penggunaan skill gagal. [%s] membutuhkan %dx %s.
+379: Penggunaan item [%s] gagal. Dapat digunakan setelah %1.f menit.
+380: Penggunaan item [%s] gagal. Dapat digunakan setelah %d detik.
+381: Penggunaan skill [%s] gagal. Membutuhkan %dx %s.
 382: Kamu terlalu dekat dengan batu atau emperium untuk menggunakan skill ini.
 382: Kamu terlalu dekat dengan batu atau emperium untuk menggunakan skill ini.
 383: Kamu tidak dapat membuat save point di instance
 383: Kamu tidak dapat membuat save point di instance
 384: Kamu tidak dapat membuat memo di instance
 384: Kamu tidak dapat membuat memo di instance
@@ -519,7 +519,25 @@
 // @auction
 // @auction
 517: Sistem Auction tidak tersedia.
 517: Sistem Auction tidak tersedia.
 
 
-//518~534: kosong
+// @itemlist -- continued
+518: Lower Costume Head, 
+519: Top Costume Head, 
+520: Top/Lower Costume Head, 
+521: Mid Costume Head, 
+522: Mid/Lower Costume Head, 
+523: Top/Mid/Lower Costume Head, 
+524: Costume Robe, 
+525: Costume Floor, 
+526: Ammo, 
+527: Shadow Body, 
+528: Shadow Right Hand, 
+529: Shadow Left Hand, 
+530: Shadow Both Hands, 
+531: Shadow Shoes, 
+532: Shadow Right Accessory, 
+533: Shadow Left Accessory, 
+
+//534: kosong
 
 
 // Pesan yang berhubungan dengan deteksi Bot (Saat ini belum diimplementasikan)
 // Pesan yang berhubungan dengan deteksi Bot (Saat ini belum diimplementasikan)
 535: Kemungkinan BOT (99%%) atau client yang digunakan sudah dimodifikasi '%s' (akun: %d, char_id: %d). Pemain ini bisa melihat nama kamu saat kamu sedang tidak terlihat.
 535: Kemungkinan BOT (99%%) atau client yang digunakan sudah dimodifikasi '%s' (akun: %d, char_id: %d). Pemain ini bisa melihat nama kamu saat kamu sedang tidak terlihat.
@@ -1373,25 +1391,25 @@
 
 
 // @itemlist
 // @itemlist
 1332: ------ %s daftar item dari '%s' ------
 1332: ------ %s daftar item dari '%s' ------
-1333:  | dipakai: 
-1334: jubah, 
-1335: aksesori kiri, 
-1336: badan/armor, 
-1337: tangan kanan, 
-1338: tangan kiri, 
-1339: kedua tangan, 
-1340: kaki, 
-1341: aksesori kanan, 
-1342: kepala bagian bawah, 
-1343: kepala bagian atas, 
-1344: kepala bagian bawah/atas, 
-1345: kepala bagian tengah, 
-1346: kepala bagian bawah/tengah, 
-1347: kepala bagian bawah/tengah/atas, 
+1333:  | Dipakai: 
+1334: Jubah, 
+1335: Aksesori kiri, 
+1336: Badan/armor, 
+1337: Tangan kanan, 
+1338: Tangan kiri, 
+1339: Kedua tangan, 
+1340: Kaki, 
+1341: Aksesori kanan, 
+1342: Kepala bagian bawah, 
+1343: Kepala bagian atas, 
+1344: Kepala bagian bawah/atas, 
+1345: Kepala bagian tengah, 
+1346: Kepala bagian bawah/tengah, 
+1347: Kepala bagian bawah/tengah/atas, 
 1348:  -> (telur peliharaan, id peliharaan: %u, sudah diberi nama)
 1348:  -> (telur peliharaan, id peliharaan: %u, sudah diberi nama)
 1349:  -> (telur peliharaan, id peliharaan: %u, belum diberi nama)
 1349:  -> (telur peliharaan, id peliharaan: %u, belum diberi nama)
-1350:  -> (item dibuat, id pembuat: %u, %d star crumb, elemen %d)
-1351:  -> (memproduksi item, id pembuat: %u)
+1350:  -> (item buatan, id pembuat: %u, %d star crumb, elemen %d)
+1351:  -> (item produksi, id pembuat: %u)
 1352:  -> (kartu: 
 1352:  -> (kartu: 
 1353: Tidak ada item yang ditemukan di %s pemain.
 1353: Tidak ada item yang ditemukan di %s pemain.
 1354: %d item ditemukan di slot %d %s.
 1354: %d item ditemukan di slot %d %s.

+ 2 - 1
conf/subnet_athena.conf

@@ -1,6 +1,7 @@
 // Subnet support file
 // Subnet support file
 // Format is:
 // Format is:
 // subnet: net-submask:char_ip:map_ip
 // subnet: net-submask:char_ip:map_ip
-// you can add more than one subnet 
+// you can add more than one subnet (max 16)
+// check is if((net-submask & char_ip ) == (net-submask & servip)) => ok
 
 
 subnet: 255.0.0.0:127.0.0.1:127.0.0.1
 subnet: 255.0.0.0:127.0.0.1:127.0.0.1

+ 1 - 0
db/const.txt

@@ -4618,6 +4618,7 @@ IT_AMMO	10
 IT_DELAYCONSUME	11
 IT_DELAYCONSUME	11
 IT_CASH	18
 IT_CASH	18
 
 
+Bound_None	0
 Bound_Account	1
 Bound_Account	1
 Bound_Guild	2
 Bound_Guild	2
 Bound_Party	3
 Bound_Party	3

+ 1 - 0
db/import-tmpl/item_avail.txt

@@ -9,3 +9,4 @@
 //
 //
 // NOTE: Replaces an item client-side while keeping them separate server-side.
 // NOTE: Replaces an item client-side while keeping them separate server-side.
 // Think of it as a way to disguise items.
 // Think of it as a way to disguise items.
+// Don't sell the item in same shop with the source. Example, don't put 2240 & 2241 in same place!

+ 1 - 0
db/item_avail.txt

@@ -9,6 +9,7 @@
 //
 //
 // NOTE: Replaces an item client-side while keeping them separate server-side.
 // NOTE: Replaces an item client-side while keeping them separate server-side.
 // Think of it as a way to disguise items.
 // Think of it as a way to disguise items.
+// Don't sell the item in same shop with the source. Example, don't put 2240 & 2241 in same place!
 
 
 2240,2241 //Beard - Grampa Beard
 2240,2241 //Beard - Grampa Beard
 
 

+ 4 - 4
db/pre-re/attr_fix.txt

@@ -4,7 +4,7 @@
 // Columns - attacker's weapon element
 // Columns - attacker's weapon element
 // Rows    - target's defense element
 // Rows    - target's defense element
 
 
-1,10	// lv1 Attribute table
+1	// lv1 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,  25, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,  25, 100,  // Neutral
   100,  25, 100, 150,  50, 100,  75, 100, 100, 100,  // Water
   100,  25, 100, 150,  50, 100,  75, 100, 100, 100,  // Water
@@ -17,7 +17,7 @@
    25, 100, 100, 100, 100, 100,  75,  75, 125, 100,  // Ghost
    25, 100, 100, 100, 100, 100,  75,  75, 125, 100,  // Ghost
   100, 100, 100, 100, 100,  50, 100,   0, 100,   0,  // Undead
   100, 100, 100, 100, 100,  50, 100,   0, 100,   0,  // Undead
 
 
-2,10	// lv2 Attribute table
+2	// lv2 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,  25, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,  25, 100,  // Neutral
   100,   0, 100, 175,  25, 100,  50,  75, 100, 100,  // Water
   100,   0, 100, 175,  25, 100,  50,  75, 100, 100,  // Water
@@ -30,7 +30,7 @@
     0,  75,  75,  75,  75,  75,  50,  50, 150, 125,  // Ghost
     0,  75,  75,  75,  75,  75,  50,  50, 150, 125,  // Ghost
   100,  75,  75,  75,  75,  25, 125,   0, 100,   0,  // Undead
   100,  75,  75,  75,  75,  25, 125,   0, 100,   0,  // Undead
 
 
-3,10	// lv3 Attribute table
+3	// lv3 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, -25, 100, 200,   0, 100,  25,  50, 100, 125,  // Water
   100, -25, 100, 200,   0, 100,  25,  50, 100, 125,  // Water
@@ -43,7 +43,7 @@
     0,  50,  50,  50,  50,  50,  25,  25, 175, 150,  // Ghost
     0,  50,  50,  50,  50,  50,  25,  25, 175, 150,  // Ghost
   100,  50,  50,  50,  50,   0, 150,   0, 100,   0,  // Undead
   100,  50,  50,  50,  50,   0, 150,   0, 100,   0,  // Undead
 
 
-4,10	// lv4 Attribute table
+4	// lv4 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, -50, 100, 200,   0,  75,   0,  25, 100, 150,  // Water
   100, -50, 100, 200,   0,  75,   0,  25, 100, 150,  // Water

+ 10 - 10
db/pre-re/skill_db.txt

@@ -228,7 +228,7 @@
 128,0,0,0,0,0,0,10,0,no,0,0,0,misc,0,0x0,		HT_STEELCROW,Steel Crow
 128,0,0,0,0,0,0,10,0,no,0,0,0,misc,0,0x0,		HT_STEELCROW,Steel Crow
 129,5,8,1,0,0x42,1,5,1:2:3:4:5,yes,0,0,0,misc,0,0x80,	HT_BLITZBEAT,Blitz Beat
 129,5,8,1,0,0x42,1,5,1:2:3:4:5,yes,0,0,0,misc,0,0x80,	HT_BLITZBEAT,Blitz Beat
 130,3:5:7:9,6,2,0,0x3,3,4,1,no,0,0,0,misc,0,0x0,	HT_DETECTING,Detect
 130,3:5:7:9,6,2,0,0x3,3,4,1,no,0,0,0,misc,0,0x0,	HT_DETECTING,Detect
-131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x2000,	HT_SPRINGTRAP,Spring Trap
+131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x0,	HT_SPRINGTRAP,Spring Trap
 
 
 //****
 //****
 // Assassin
 // Assassin
@@ -870,7 +870,7 @@
 1010,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	BA_PANGVOICE,Pang Voice
 1010,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	BA_PANGVOICE,Pang Voice
 1011,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	DC_WINKCHARM,Wink of Charm
 1011,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	DC_WINKCHARM,Wink of Charm
 1012,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0,0x4000,	BS_UNFAIRLYTRICK,Unfair Trick
 1012,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0,0x4000,	BS_UNFAIRLYTRICK,Unfair Trick
-1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x0,	BS_GREED,Greed
+1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x2000,	BS_GREED,Greed
 1014,0,6,4,6,0x3,14,1,0,yes,0,0x1,0,magic,0,0x0,	PR_REDEMPTIO,Redemptio
 1014,0,6,4,6,0x3,14,1,0,yes,0,0x1,0,magic,0,0x0,	PR_REDEMPTIO,Redemptio
 1015,9,6,16,0,0x1,0,1,1,no,0,0x401,0,weapon,0,0x0,	MO_KITRANSLATION,Ki Translation
 1015,9,6,16,0,0x1,0,1,1,no,0,0x401,0,weapon,0,0x0,	MO_KITRANSLATION,Ki Translation
 1016,-1,6,1,-1,0x2,1,1,1,no,0,0x1,0,weapon,5,0x0,	MO_BALKYOUNG,Ki Explosion
 1016,-1,6,1,-1,0x2,1,1,1,no,0,0x1,0,weapon,5,0x0,	MO_BALKYOUNG,Ki Explosion
@@ -989,7 +989,7 @@
 2235,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0x0,		RA_RANGERMAIN,Ranger Main
 2235,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0x0,		RA_RANGERMAIN,Ranger Main
 2236,9,8,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x80,	RA_AIMEDBOLT,Aimed Bolt
 2236,9,8,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x80,	RA_AIMEDBOLT,Aimed Bolt
 2237,9,6,2,0,0x3,3,1,1,no,0,0,0,none,0,0x2000,		RA_DETONATOR,Detonator
 2237,9,6,2,0,0x3,3,1,1,no,0,0,0,none,0,0x2000,		RA_DETONATOR,Detonator
-2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x0,	RA_ELECTRICSHOCKER,Electric Shocker
+2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x2000,	RA_ELECTRICSHOCKER,Electric Shocker
 2239,3,6,2,0,0x42,3,5,1,no,0,0x80,3,misc,0,0x2800,	RA_CLUSTERBOMB,Cluster Bomb
 2239,3,6,2,0,0x42,3,5,1,no,0,0x80,3,misc,0,0x2800,	RA_CLUSTERBOMB,Cluster Bomb
 2240,0,6,4,0,0,0,1,1,no,0,0,0,none,0,0x0,		RA_WUGMASTERY,Warg Mastery
 2240,0,6,4,0,0,0,1,1,no,0,0,0,none,0,0x0,		RA_WUGMASTERY,Warg Mastery
 2241,0,6,4,0,0,0,3,1,no,0,0,0,none,0,0x2000,		RA_WUGRIDER,Warg Rider
 2241,0,6,4,0,0,0,3,1,no,0,0,0,none,0,0x2000,		RA_WUGRIDER,Warg Rider
@@ -1000,10 +1000,10 @@
 2246,0,6,4,0,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0,0x0,	RA_SENSITIVEKEEN,Sensitive Keen
 2246,0,6,4,0,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0,0x0,	RA_SENSITIVEKEEN,Sensitive Keen
 2247,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x42,		RA_CAMOUFLAGE,Camouflage
 2247,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x42,		RA_CAMOUFLAGE,Camouflage
 2248,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0,		RA_RESEARCHTRAP,Research Trap
 2248,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0,		RA_RESEARCHTRAP,Research Trap
-2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_MAGENTATRAP,Magenta Trap
-2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_COBALTTRAP,Cobalt Trap
-2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_MAIZETRAP,Maize Trap
-2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_VERDURETRAP,Verdure Trap
+2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_MAGENTATRAP,Magenta Trap
+2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_COBALTTRAP,Cobalt Trap
+2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_MAIZETRAP,Maize Trap
+2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_VERDURETRAP,Verdure Trap
 2253,3,6,2,3,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_FIRINGTRAP,Firing Trap
 2253,3,6,2,3,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_FIRINGTRAP,Firing Trap
 2254,3,6,2,1,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_ICEBOUNDTRAP,Icebound Trap
 2254,3,6,2,1,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_ICEBOUNDTRAP,Icebound Trap
 
 
@@ -1194,7 +1194,7 @@
 2479,9,6,2,0,0,0,5,1,yes,0,0x80,3,misc,0,0x0,	GN_THORNS_TRAP,Thorn Trap
 2479,9,6,2,0,0,0,5,1,yes,0,0x80,3,misc,0,0x0,	GN_THORNS_TRAP,Thorn Trap
 2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0,0x0,		GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm....
 2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0,0x0,		GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm....
 2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0,0x0,	GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm.
 2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0,0x0,	GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm.
-2482,11,6,16,0,0,0,5,1,yes,0,0,1,weapon,2,0x0,	GN_WALLOFTHORN,Wall of Thorns
+2482,11,6,2,0,0x8,0,5,1,yes,0,0,1,weapon,2,0x0,	GN_WALLOFTHORN,Wall of Thorns
 2483,11,6,2,0,0x3,4,10,1,yes,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED,Crazy Weed
 2483,11,6,2,0,0x3,4,10,1,yes,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED,Crazy Weed
 2484,0,6,2,2,0x2,2,10,1,no,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED_ATK,Crazy Weed Attack
 2484,0,6,2,2,0x2,2,10,1,no,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED_ATK,Crazy Weed Attack
 2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0,0x0,		GN_DEMONIC_FIRE,Demonic Fire
 2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0,0x0,		GN_DEMONIC_FIRE,Demonic Fire
@@ -1341,8 +1341,8 @@
 8019,5,6,1,5,0,0,5,1,no,0,0,0,weapon,0,0x0,		MH_NEEDLE_OF_PARALYZE,Needle of Paralyze
 8019,5,6,1,5,0,0,5,1,no,0,0,0,weapon,0,0x0,		MH_NEEDLE_OF_PARALYZE,Needle of Paralyze
 8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0,0x0,		MH_POISON_MIST,Poison Mist
 8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0,0x0,		MH_POISON_MIST,Poison Mist
 8021,1,6,16,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_PAIN_KILLER,Pain Killer
 8021,1,6,16,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_PAIN_KILLER,Pain Killer
-8022,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0,0x0,		MH_LIGHT_OF_REGENE,Light of Regene
-8023,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0,0x0,		MH_OVERED_BOOST,Overed Boost
+8022,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_LIGHT_OF_REGENE,Light of Regene
+8023,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_OVERED_BOOST,Overed Boost
 8024,7,8,1,4:0:4:0:4,0,0,5,-6,yes,0,0,0,magic,0,0x0,	MH_ERASER_CUTTER,Eraser Cutter
 8024,7,8,1,4:0:4:0:4,0,0,5,-6,yes,0,0,0,magic,0,0x0,	MH_ERASER_CUTTER,Eraser Cutter
 8025,7,8,2,4:0:4:0:4,0x2,2:2:3:3:4,5,-6,no,0,0,0,magic,0,0x0,	MH_XENO_SLASHER,Xeno Slasher
 8025,7,8,2,4:0:4:0:4,0x2,2:2:3:3:4,5,-6,no,0,0,0,magic,0,0x0,	MH_XENO_SLASHER,Xeno Slasher
 8026,5:5:7:7:9,6,6,0,0x1,0,5,1,no,0,0,0,magic,0,0x0,	MH_SILENT_BREEZE,Silent Breeze
 8026,5:5:7:7:9,6,6,0,0x1,0,5,1,no,0,0,0,magic,0,0x0,	MH_SILENT_BREEZE,Silent Breeze

+ 2 - 2
db/pre-re/skill_unit_db.txt

@@ -151,8 +151,8 @@
 2482,0xe6,0x7f,  0, 1, 100,all,   0x000	//GN_WALLOFTHORN
 2482,0xe6,0x7f,  0, 1, 100,all,   0x000	//GN_WALLOFTHORN
 2484,0x86,    ,  0, 1, 100,enemy, 0x080	//GN_CRAZYWEED_ATK
 2484,0x86,    ,  0, 1, 100,enemy, 0x080	//GN_CRAZYWEED_ATK
 2485,0xe7,    ,  0, 2,2000,enemy, 0x098	//GN_DEMONIC_FIRE
 2485,0xe7,    ,  0, 2,2000,enemy, 0x098	//GN_DEMONIC_FIRE
-2487,0xe8,    ,  2, 0,  -1,all,   0x2000	//GN_FIRE_EXPANSION_SMOKE_POWDER
-2488,0xe9,    ,  2, 0,  -1,all,   0x2000	//GN_FIRE_EXPANSION_TEAR_GAS
+2487,0xe8,    ,  2, 0,  -1,enemy, 0x2000	//GN_FIRE_EXPANSION_SMOKE_POWDER
+2488,0xe9,    ,  2, 0,  -1,enemy, 0x2000	//GN_FIRE_EXPANSION_TEAR_GAS
 2490,0xea,    ,  0, 1,1000,enemy, 0x002	//GN_HELLS_PLANT
 2490,0xea,    ,  0, 1,1000,enemy, 0x002	//GN_HELLS_PLANT
 
 
 2555,0x104,   ,  0, 1:2:2:3:3,500,enemy,0x6	//RL_B_TRAP
 2555,0x104,   ,  0, 1:2:2:3:3,500,enemy,0x6	//RL_B_TRAP

+ 4 - 4
db/re/attr_fix.txt

@@ -4,7 +4,7 @@
 // Columns - attacker's weapon element
 // Columns - attacker's weapon element
 // Rows    - target's defense element
 // Rows    - target's defense element
 
 
-1,10	// lv1 Attribute table
+1	// lv1 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,  70, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,  70, 100,  // Neutral
   100,  25, 100, 150,  90, 100,  75, 100, 100, 100,  // Water
   100,  25, 100, 150,  90, 100,  75, 100, 100, 100,  // Water
@@ -17,7 +17,7 @@
    70, 100, 100, 100, 100, 100,  75,  75, 125, 100,  // Ghost
    70, 100, 100, 100, 100, 100,  75,  75, 125, 100,  // Ghost
   100, 100, 100, 100, 100,  50, 100,   0, 100,   0,  // Undead
   100, 100, 100, 100, 100,  50, 100,   0, 100,   0,  // Undead
 
 
-2,10	// lv2 Attribute table
+2	// lv2 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,  50, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,  50, 100,  // Neutral
   100,   0, 100, 175,  80, 100,  50,  75, 100, 100,  // Water
   100,   0, 100, 175,  80, 100,  50,  75, 100, 100,  // Water
@@ -30,7 +30,7 @@
    50,  75,  75,  75,  75,  75,  50,  50, 150, 125,  // Ghost
    50,  75,  75,  75,  75,  75,  50,  50, 150, 125,  // Ghost
   100,  75,  75,  75,  75,  25, 125,   0, 100,   0,  // Undead
   100,  75,  75,  75,  75,  25, 125,   0, 100,   0,  // Undead
 
 
-3,10	// lv3 Attribute table
+3	// lv3 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, -25, 100, 200,  70, 100,  25,  50, 100, 125,  // Water
   100, -25, 100, 200,  70, 100,  25,  50, 100, 125,  // Water
@@ -43,7 +43,7 @@
     0,  50,  50,  50,  50,  50,  25,  25, 175, 150,  // Ghost
     0,  50,  50,  50,  50,  50,  25,  25, 175, 150,  // Ghost
   100,  50,  50,  50,  50,   0, 150,   0, 100,   0,  // Undead
   100,  50,  50,  50,  50,   0, 150,   0, 100,   0,  // Undead
 
 
-4,10	// lv4 Attribute table
+4	// lv4 Attribute table
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
 //Neut Watr Erth Fire Wind Pois Holy Shdw Gho  Und
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, 100, 100, 100, 100, 100, 100, 100,   0, 100,  // Neutral
   100, -50, 100, 200,  60,  75,   0,  25, 100, 150,  // Water
   100, -50, 100, 200,  60,  75,   0,  25, 100, 150,  // Water

+ 20 - 6
db/re/item_db.txt

@@ -2457,7 +2457,7 @@
 4412,Isilla_Card,Isilla Card,6,20,,10,,,,,,,,769,,,,,{ bonus bInt,2; autobonus "{ bonus bVariableCastrate,-50; bonus bFlee,30; }",50,5000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }"; },{},{}
 4412,Isilla_Card,Isilla Card,6,20,,10,,,,,,,,769,,,,,{ bonus bInt,2; autobonus "{ bonus bVariableCastrate,-50; bonus bFlee,30; }",50,5000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }"; },{},{}
 4413,Hodremlin_Card,Hodremlin Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubSize,Size_All,15; autobonus2 "{ bonus bFlee2,30; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_WIND; }"; },{},{}
 4413,Hodremlin_Card,Hodremlin Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubSize,Size_All,15; autobonus2 "{ bonus bFlee2,30; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_WIND; }"; },{},{}
 4414,Seeker_Card,Seeker Card,6,20,,10,,,,,,,,32,,,,,{ skill "MG_STONECURSE",1; bonus2 bResEff,Eff_Stone,3000; bonus bMdef,10; },{},{}
 4414,Seeker_Card,Seeker Card,6,20,,10,,,,,,,,32,,,,,{ skill "MG_STONECURSE",1; bonus2 bResEff,Eff_Stone,3000; bonus bMdef,10; },{},{}
-4415,Snowier_Card,Snowier Card,6,20,,10,,,,,,,,136,,,,,{ bonus2 bAddMonsterDropItem,536,2000; bonus2 bAddItemHealRate,536,500; },{},{}
+4415,Snowier_Card,Snowier Card,6,20,,10,,,,,,,,136,,,,,{ bonus2 bAddMonsterDropItem,536,500; bonus2 bAddItemHealRate,536,100; },{},{}
 4416,Siroma_Card,Siroma Card,6,20,,10,,,,,,,,136,,,,,{ bonus2 bSkillAtk,"MG_COLDBOLT",25; bonus2 bVariableCastrate,"MG_COLDBOLT",-25; },{},{}
 4416,Siroma_Card,Siroma Card,6,20,,10,,,,,,,,136,,,,,{ bonus2 bSkillAtk,"MG_COLDBOLT",25; bonus2 bVariableCastrate,"MG_COLDBOLT",-25; },{},{}
 4417,Ice_Titan_Card,Ice Titan Card,6,20,,10,,,,,,,,64,,,,,{ bonus bVit,2; autobonus2 "{ bonus bDef,10; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_FREEZED; }"; },{},{}
 4417,Ice_Titan_Card,Ice Titan Card,6,20,,10,,,,,,,,64,,,,,{ bonus bVit,2; autobonus2 "{ bonus bDef,10; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_FREEZED; }"; },{},{}
 4418,Gazeti_Card,Gazeti Card,6,20,,10,,,,,,,,136,,,,,{ bonus3 bAutoSpell,"MG_COLDBOLT",2,100; },{},{}
 4418,Gazeti_Card,Gazeti Card,6,20,,10,,,,,,,,136,,,,,{ bonus3 bAutoSpell,"MG_COLDBOLT",2,100; },{},{}
@@ -2500,9 +2500,9 @@
 4456,Nidhogg_Shadow_Card,Nidhoggur Shadow Card,6,20,,10,,,,,,,,16,,,,,{ bonus bInt,5; if (Class == Job_High_Wizard || Class == Job_Baby_Warlock || Class == Job_Warlock || Class == Job_Warlock_T) bonus bFixedCastrate,-50; },{},{}
 4456,Nidhogg_Shadow_Card,Nidhoggur Shadow Card,6,20,,10,,,,,,,,16,,,,,{ bonus bInt,5; if (Class == Job_High_Wizard || Class == Job_Baby_Warlock || Class == Job_Warlock || Class == Job_Warlock_T) bonus bFixedCastrate,-50; },{},{}
 4457,Nahtzigger_Card,Naght Sieger Card,6,20,,10,,,,,,,,16,,,,,{ bonus2 bMagicAtkEle,Ele_Ghost,30; },{},{}
 4457,Nahtzigger_Card,Naght Sieger Card,6,20,,10,,,,,,,,16,,,,,{ bonus2 bMagicAtkEle,Ele_Ghost,30; },{},{}
 4458,Duneirre_Card,Duneyrr Card,6,20,,10,,,,,,,,769,,,,,{ bonus bBaseAtk,10; autobonus "{ bonus bAspdRate,5; }",10,10000,0,"{ specialeffect2 EF_HASTEUP; }"; },{},{}
 4458,Duneirre_Card,Duneyrr Card,6,20,,10,,,,,,,,769,,,,,{ bonus bBaseAtk,10; autobonus "{ bonus bAspdRate,5; }",10,10000,0,"{ specialeffect2 EF_HASTEUP; }"; },{},{}
-4459,Lata_Card,Rata Card,6,20,,10,,,,,,,,769,,,,,{ bonus bMatk,10; autobonus "{ bonus bFixedCastrate,-50; }",10,4000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }"; },{},{}
-4460,Ringco_Card,Rhyncho Card,6,20,,10,,,,,,,,769,,,,,{ bonus bHealPower,4; bonus bUseSPrate,5; },{},{}
-4461,Pillar_Card,Phylla Card,6,20,,10,,,,,,,,769,,,,,{ bonus bDex,1; bonus bAgi,1; autobonus "{ bonus bCritical,20; }",4,4000,0,"{ specialeffect2 EF_ENHANCE; }"; },{},{}
+4459,Lata_Card,Rata Card,6,20,,10,,,,,,,,769,,,,,{ bonus bMatk,10; autobonus "{ bonus bFixedCastrate,-50; }",5,4000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }"; },{},{}
+4460,Ringco_Card,Rhyncho Card,6,20,,10,,,,,,,,769,,,,,{ bonus bHealPower,4; bonus2 bSkillUseSP,"AL_HEAL",-15; },{},{}
+4461,Pillar_Card,Phylla Card,6,20,,10,,,,,,,,769,,,,,{ bonus bDex,1; bonus bAgi,1; autobonus "{ bonus bCritical,20; }",15,4000,0,"{ specialeffect2 EF_ENHANCE; }"; },{},{}
 4462,Hardrock_Mammos_Card,Hardrock Mammoth Card,6,20,,10,,,,,,,,16,,,,,{ bonus bDef,5; if(getrefine()>=12) { bonus bDef,20; bonus bMaxHPrate,10; } if(getrefine()>=14) { bonus bMaxHPrate,3; } },{},{}
 4462,Hardrock_Mammos_Card,Hardrock Mammoth Card,6,20,,10,,,,,,,,16,,,,,{ bonus bDef,5; if(getrefine()>=12) { bonus bDef,20; bonus bMaxHPrate,10; } if(getrefine()>=14) { bonus bMaxHPrate,3; } },{},{}
 4463,Tendrilrion_Card,Tendrilrion Card,6,20,,10,,,,,,,,2,,,,,{ bonus bCritical,5; if(getrefine()>=12) { bonus bBaseAtk,35; } if(getrefine()>=14) { bonus bCritical,10; } },{},{}
 4463,Tendrilrion_Card,Tendrilrion Card,6,20,,10,,,,,,,,2,,,,,{ bonus bCritical,5; if(getrefine()>=12) { bonus bBaseAtk,35; } if(getrefine()>=14) { bonus bCritical,10; } },{},{}
 4464,Aunoe_Card,Aunoe Card,6,20,,10,,,,,,,,2,,,,,{ bonus bCritAtkRate,20; },{},{}
 4464,Aunoe_Card,Aunoe Card,6,20,,10,,,,,,,,2,,,,,{ bonus bCritAtkRate,20; },{},{}
@@ -4512,6 +4512,7 @@
 6863,Strong_Piece_Of_Soul_Tiger,Strong Piece Of Soul Tiger,3,10,,0,,,,,,,,,,,,,{},{},{}
 6863,Strong_Piece_Of_Soul_Tiger,Strong Piece Of Soul Tiger,3,10,,0,,,,,,,,,,,,,{},{},{}
 6864,Safe_to_19_Weapon_Certificate,Safe to 19 Weapon Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
 6864,Safe_to_19_Weapon_Certificate,Safe to 19 Weapon Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
 6865,Safe_to_19_Armor_Certificate,Safe to 19 Armor Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
 6865,Safe_to_19_Armor_Certificate,Safe to 19 Armor Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
+6866,Piece_Of_Soul_Rabbit,Piece Of Soul Rabbit,3,0,,0,,,,,,,,,,,,,{},{},{}
 6885,Piece_Of_Soul_Dragon,Piece Of Soul Dragon,3,10,,0,,,,,,,,,,,,,{},{},{}
 6885,Piece_Of_Soul_Dragon,Piece Of Soul Dragon,3,10,,0,,,,,,,,,,,,,{},{},{}
 6870,Safe_to_13_Weapon_Certificate,Safe to 13 Weapon Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
 6870,Safe_to_13_Weapon_Certificate,Safe to 13 Weapon Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
 6871,Safe_to_14_Weapon_Certificate,Safe to 14 Weapon Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
 6871,Safe_to_14_Weapon_Certificate,Safe to 14 Weapon Certificate,3,10,,0,,,,,,,,,,,,,{},{},{}
@@ -6189,7 +6190,7 @@
 12421,Falmons_F,Falmons F,3,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_LIFE_FORCE_F,500000,5; },{},{}
 12421,Falmons_F,Falmons F,3,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_LIFE_FORCE_F,500000,5; },{},{}
 12422,HP_Increase_Potion_(Small),HP Increase Potion (Small),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMHP,500000,(500+(BaseLevel*10/3)); percentheal 1,0; },{},{}
 12422,HP_Increase_Potion_(Small),HP Increase Potion (Small),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMHP,500000,(500+(BaseLevel*10/3)); percentheal 1,0; },{},{}
 12423,HP_Increase_Potion_(Medium),HP Increase Potion (Medium),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMHP,500000,(1500+(BaseLevel*10/3)); percentheal 2,0; },{},{}
 12423,HP_Increase_Potion_(Medium),HP Increase Potion (Medium),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMHP,500000,(1500+(BaseLevel*10/3)); percentheal 2,0; },{},{}
-12424,HP_Increase_Potion_(Large),HP Increase Potion (Large),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMHP,500000,(2500+(BaseLevel*10/3)); percentheal 5,0; },{},{}
+12424,HP_Increase_Potion_(Large),HP Increase Potion (Large),0,10,,80,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMHP,500000,(2500+(BaseLevel*10/3)); percentheal 5,0; },{},{}
 12425,SP_Increase_Potion_(Small),SP Increase Potion (Small),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMSPRATE,500000,((BaseLevel/10)-5); percentheal 0,2; },{},{}
 12425,SP_Increase_Potion_(Small),SP Increase Potion (Small),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMSPRATE,500000,((BaseLevel/10)-5); percentheal 0,2; },{},{}
 12426,SP_Increase_Potion_(Medium),SP Increase Potion (Medium),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMSPRATE,500000,(BaseLevel/10); percentheal 0,4; },{},{}
 12426,SP_Increase_Potion_(Medium),SP Increase Potion (Medium),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMSPRATE,500000,(BaseLevel/10); percentheal 0,4; },{},{}
 12427,SP_Increase_Potion_(Large),SP Increase Potion (Large),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMSPRATE,500000,((BaseLevel/10)+5); percentheal 0,8; },{},{}
 12427,SP_Increase_Potion_(Large),SP Increase Potion (Large),0,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ sc_start SC_INCMSPRATE,500000,((BaseLevel/10)+5); percentheal 0,8; },{},{}
@@ -8188,7 +8189,7 @@
 15121,Sarah_Combat_Robe,Sarah Combat Robe,4,10,,800,,35,,1,0xFFFFFFFF,63,2,16,,145,1,,{ /*TODO: Confirm the real rate and additional MAtk*/ autobonus "{ bonus bMatk,20; }",100,(10+((getrefine()) ? getrefine()*8 : 0))*1000,BF_MAGIC;},{},{}
 15121,Sarah_Combat_Robe,Sarah Combat Robe,4,10,,800,,35,,1,0xFFFFFFFF,63,2,16,,145,1,,{ /*TODO: Confirm the real rate and additional MAtk*/ autobonus "{ bonus bMatk,20; }",100,(10+((getrefine()) ? getrefine()*8 : 0))*1000,BF_MAGIC;},{},{}
 
 
 // More Maces
 // More Maces
-16000,Erde,Erde,5,20,,500,130,,1,2,0x0004C5B2,18,2,2,4,50,1,8,{ bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus bMaxSP,50; bonus bHealPower,10; },{},{}
+16000,Erde,Erde,5,20,,500,130,,1,2,0x0004C5B2,18,2,2,3,50,1,8,{ bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus bMaxSP,50; bonus bHealPower,10; },{},{}
 16001,Red_Square_Bag,Red Square Bag,5,20,,500,130,,1,2,0x0004C5B2,18,2,2,3,50,1,8,{ bonus bMaxHP,200; bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus2 bAddMonsterDropItem,501,50; bonus2 bAddMonsterDropItem,502,20; bonus2 bAddMonsterDropItem,503,20; bonus2 bAddMonsterDropItem,504,20; bonus2 bAddMonsterDropItem,505,10; if(readparam(bStr)>=95) bonus2 bAddEff,Eff_Stun,500; },{},{}
 16001,Red_Square_Bag,Red Square Bag,5,20,,500,130,,1,2,0x0004C5B2,18,2,2,3,50,1,8,{ bonus bMaxHP,200; bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus2 bAddMonsterDropItem,501,50; bonus2 bAddMonsterDropItem,502,20; bonus2 bAddMonsterDropItem,503,20; bonus2 bAddMonsterDropItem,504,20; bonus2 bAddMonsterDropItem,505,10; if(readparam(bStr)>=95) bonus2 bAddEff,Eff_Stun,500; },{},{}
 16002,Stunner_C,Stunner,5,0,,0,175,,1,0,0x00008110,63,2,2,3,1,0,8,{ bonus2 bAddEff,Eff_Stun,1000; bonus2 bAddSize,Size_All,40; },{},{}
 16002,Stunner_C,Stunner,5,0,,0,175,,1,0,0x00008110,63,2,2,3,1,0,8,{ bonus2 bAddEff,Eff_Stun,1000; bonus2 bAddSize,Size_All,40; },{},{}
 16003,Carga_Mace,Carga Mace,5,20,,1500,175,,1,2,0x0004C5B2,63,2,2,3,100,1,8,{},{},{}
 16003,Carga_Mace,Carga Mace,5,20,,1500,175,,1,2,0x0004C5B2,63,2,2,3,100,1,8,{},{},{}
@@ -9311,7 +9312,10 @@
 19590,C_Twin_Maiden_Ribbon_J,Maiden's Twin Ribbon,4,20,,0,,0,,0,0xFFFFFFFF,63,2,1024,,0,0,239,{},{},{}
 19590,C_Twin_Maiden_Ribbon_J,Maiden's Twin Ribbon,4,20,,0,,0,,0,0xFFFFFFFF,63,2,1024,,0,0,239,{},{},{}
 19598,C_Wandering_Wolf_Hat,Costume Wandering Wolf Hat,4,20,,600,,5,,0,0xFFFFFFFE,63,2,768,,20,0,490,{ bonus bVit,5; bonus bFlee,10; },{},{}
 19598,C_Wandering_Wolf_Hat,Costume Wandering Wolf Hat,4,20,,600,,5,,0,0xFFFFFFFE,63,2,768,,20,0,490,{ bonus bVit,5; bonus bFlee,10; },{},{}
 19599,C_Imp_Hat,Costume Imp Hat,4,20,,400,,1,,0,0xFFFFFFFF,63,2,256,,1,1,589,{ bonus3 bAutoSpell,"SA_FLAMELAUNCHER",1,5; },{},{}
 19599,C_Imp_Hat,Costume Imp Hat,4,20,,400,,1,,0,0xFFFFFFFF,63,2,256,,1,1,589,{ bonus3 bAutoSpell,"SA_FLAMELAUNCHER",1,5; },{},{}
+19600,C_Drooping_Kiehl,Costume Drooping Kiehl,12,0,,40,,,,,0xFFFFFFFF,63,2,1024,,30,,909,{},{},{}
+19601,C_Drooping_Aliot,Costume Drooping Aliot,12,0,,10,,,,,0xFFFFFFFF,63,2,1024,,1,,910,{},{},{}
 19603,C_Invisible_Sunglasses,Costume Invisible Sunglasses,4,0,,0,,0,,0,0xFFFFFFFF,63,2,2048,,1,0,0,{},{},{}
 19603,C_Invisible_Sunglasses,Costume Invisible Sunglasses,4,0,,0,,0,,0,0xFFFFFFFF,63,2,2048,,1,0,0,{},{},{}
+19604,Brawler's_Supply_Crate,Brawler's Supply Crate,18,0,,0,,,,,0xFFFFFFFF,63,2,,,,,,{ getitem(12208,4); getitem(12072,6); getitem(12082,6); getitem(12087,6); getitem(11502,30); },{},{}
 19607,C_Love_Chick_Hat,Costume Love Chick Hat,4,0,,0,,0,,0,0xFFFFFFFF,63,2,1024,,1,0,500,{},{},{}
 19607,C_Love_Chick_Hat,Costume Love Chick Hat,4,0,,0,,0,,0,0xFFFFFFFF,63,2,1024,,1,0,500,{},{},{}
 19613,C_Valkyrie_Feather_Hat,Costume Valkyrie Feather Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,300,{ bonus bAllStats,1; skill "PR_MAGNUS",5; skill "SA_FLAMELAUNCHER",1; skill "SA_FROSTWEAPON",1; skill "SA_LIGHTNINGLOADER",1; skill "SA_SEISMICWEAPON",1; },{},{}
 19613,C_Valkyrie_Feather_Hat,Costume Valkyrie Feather Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,300,{ bonus bAllStats,1; skill "PR_MAGNUS",5; skill "SA_FLAMELAUNCHER",1; skill "SA_FROSTWEAPON",1; skill "SA_LIGHTNINGLOADER",1; skill "SA_SEISMICWEAPON",1; },{},{}
 19617,C_Puppy_Headband,Costume Puppy Headband,4,0,,0,,,,,0xFFFFFFFF,63,2,1024,,,,199,{},{},{}
 19617,C_Puppy_Headband,Costume Puppy Headband,4,0,,0,,,,,0xFFFFFFFF,63,2,1024,,,,199,{},{},{}
@@ -9411,6 +9415,8 @@
 19800,C_Carnation_Hairband,Costume Carnation Headband,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,878,{},{},{}
 19800,C_Carnation_Hairband,Costume Carnation Headband,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,878,{},{},{}
 //
 //
 19821,C_Hyegun_hat,C Yao Jun,4,20,,10,,0,,0,0xFFFFFFFF,63,2,1024,,1,0,375,{},{},{}
 19821,C_Hyegun_hat,C Yao Jun,4,20,,10,,0,,0,0xFFFFFFFF,63,2,1024,,1,0,375,{},{},{}
+19824,C_Evil_Druid_Hat,Costume Evil Druid Hat,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,1053,{},{},{}
+19825,C_Vicious_Stop_Bandage,Costume Vicious Stop Bandage,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,1054,{},{},{}
 19826,C_Ice_Wing_Ear,C Ice Wing Ear,4,20,,10,,0,,0,0xFFFFFFFF,63,2,2048,,1,0,584,{},{},{}
 19826,C_Ice_Wing_Ear,C Ice Wing Ear,4,20,,10,,0,,0,0xFFFFFFFF,63,2,2048,,1,0,584,{},{},{}
 19829,C_Straw_Hat,C Straw Hat,4,20,,0,,0,,0,0xFFFFFFFF,63,2,1024,,0,0,146,{},{},{}
 19829,C_Straw_Hat,C Straw Hat,4,20,,0,,0,,0,0xFFFFFFFF,63,2,1024,,0,0,146,{},{},{}
 19830,C_Sunglasses,Costume Sunglasses,4,10,,0,,,,,0xFFFFFFFF,63,2,2048,,1,,12,{},{},{}
 19830,C_Sunglasses,Costume Sunglasses,4,10,,0,,,,,0xFFFFFFFF,63,2,2048,,1,,12,{},{},{}
@@ -9445,6 +9451,8 @@
 19864,C_Dokebi's_Wig,Dokebi's Wig,4,20,,0,,0,,0,0xFFFFFFFF,63,2,3072,,0,0,302,{},{},{}
 19864,C_Dokebi's_Wig,Dokebi's Wig,4,20,,0,,0,,0,0xFFFFFFFF,63,2,3072,,0,0,302,{},{},{}
 19865,C_Joker_Jester,Joker Jester,4,20,,0,,0,,0,0xFFFFFFFF,63,2,1024,,0,0,89,{},{},{}
 19865,C_Joker_Jester,Joker Jester,4,20,,0,,0,,0,0xFFFFFFFF,63,2,1024,,0,0,89,{},{},{}
 19871,C_DecorationOfMusic_Accessory,Decoration of Music,4,20,,0,,0,,0,0xFFFFFFFF,63,2,2048,,0,0,1074,{ sc_start SC_DECORATION_OF_MUSIC,-1,0; },{},{ sc_end SC_DECORATION_OF_MUSIC; }
 19871,C_DecorationOfMusic_Accessory,Decoration of Music,4,20,,0,,0,,0,0xFFFFFFFF,63,2,2048,,0,0,1074,{ sc_start SC_DECORATION_OF_MUSIC,-1,0; },{},{ sc_end SC_DECORATION_OF_MUSIC; }
+19878,C_Evolved_Drooping_Bunny,Costume Evolved Drooping Bunny,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,249,{},{},{}
+19883,C_Cyclops_Glasses,Costume Cyclops Glasses,12,0,,0,,,,,0xFFFFFFFF,63,2,2048,,1,,1087,{},{},{}
 19884,C_Vanargand_Helm,Costume Vanargand Helm,4,10,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,804,{},{},{}
 19884,C_Vanargand_Helm,Costume Vanargand Helm,4,10,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,804,{},{},{}
 19885,C_Blinker,Costume Blinker,4,10,,0,,,,,0xFFFFFFFF,63,2,2048,,1,,82,{},{},{}
 19885,C_Blinker,Costume Blinker,4,10,,0,,,,,0xFFFFFFFF,63,2,2048,,1,,82,{},{},{}
 19886,C_Purple_Glasses,Costume Purple Glasses,4,10,,0,,,,,0xFFFFFFFF,63,2,2048,,1,,26,{},{},{}
 19886,C_Purple_Glasses,Costume Purple Glasses,4,10,,0,,,,,0xFFFFFFFF,63,2,2048,,1,,26,{},{},{}
@@ -9461,6 +9469,7 @@
 19922,Costume_Noahs_Hat,Costume Noahs Hat,4,0,,0,,0,,0,0xFFFFFFFF,63,2,7168,,1,0,636,{ /* TODO */ },{},{}
 19922,Costume_Noahs_Hat,Costume Noahs Hat,4,0,,0,,0,,0,0xFFFFFFFF,63,2,7168,,1,0,636,{ /* TODO */ },{},{}
 19929,C_Classical_Ribbon,Costume Classical Ribbon,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,,1,,{ /*TODO: View ID*/ },{},{}
 19929,C_Classical_Ribbon,Costume Classical Ribbon,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,,1,,{ /*TODO: View ID*/ },{},{}
 19934,C_Lolita_Ten_Gallon_Hat,Costume Alive Ten Gallon Hat Of Flame,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1048,{},{},{}
 19934,C_Lolita_Ten_Gallon_Hat,Costume Alive Ten Gallon Hat Of Flame,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1048,{},{},{}
+19935,C_Hunting_Cap_Of_Gust,Costume Hunting Cap Of Gust,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,1076,{},{},{}
 19938,Costume_Love_Rabbit_Hood,Costume Love Rabbit Hood,4,0,,0,,0,,0,0xFFFFFFFF,63,2,7168,,1,0,549,{},{},{}
 19938,Costume_Love_Rabbit_Hood,Costume Love Rabbit Hood,4,0,,0,,0,,0,0xFFFFFFFF,63,2,7168,,1,0,549,{},{},{}
 19961,C_Rune_Circlet,Costume Rune Circlet,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,623,{},{},{}
 19961,C_Rune_Circlet,Costume Rune Circlet,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,623,{},{},{}
 19962,C_Mitra,Costume Mitra,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,624,{},{},{}
 19962,C_Mitra,Costume Mitra,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,624,{},{},{}
@@ -9499,9 +9508,14 @@
 20028,C_Cow_Hat4,Costume Cow Hat 4,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1214,{ bonus bDex,2; bonus2 bAddMonsterDropItem,519,100; },{},{}
 20028,C_Cow_Hat4,Costume Cow Hat 4,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1214,{ bonus bDex,2; bonus2 bAddMonsterDropItem,519,100; },{},{}
 20034,C_Jack_Castle_Bat,Costume Jack Castle Bat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1041,{},{},{}
 20034,C_Jack_Castle_Bat,Costume Jack Castle Bat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1041,{},{},{}
 20038,C_Alphonse_Helmet,Costume Alphonse Helmet,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,,1,,{ /*TODO: View ID*/ },{},{}
 20038,C_Alphonse_Helmet,Costume Alphonse Helmet,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,,1,,{ /*TODO: View ID*/ },{},{}
+20049,C_Giant_Band_Aid,Costume Giant Band Aid,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,147,{},{},{}
 20053,C_W_King_Tiger_Doll_Hat,Costume White King Tiger Doll Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,973,{},{},{}
 20053,C_W_King_Tiger_Doll_Hat,Costume White King Tiger Doll Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,973,{},{},{}
 20063,C_Yellow_Brain_Hat,Costume Yellow Brain Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1228,{},{},{}
 20063,C_Yellow_Brain_Hat,Costume Yellow Brain Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1228,{},{},{}
 20064,C_Blue_Brain_Hat,Costume Blue Brain Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1228,{},{},{}
 20064,C_Blue_Brain_Hat,Costume Blue Brain Hat,4,10,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1228,{},{},{}
+20067,C_White_Rabbit_Headband,Costume White Rabbit Headband,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,719,{},{},{}
+20068,C_Black_Rabbit_Headband,Costume Black Rabbit Headband,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,718,{},{},{}
+20073,C_Hair_Band,Costume Hair Band,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,9,{},{},{}
+20074,C_Biretta,Costume_Biretta,12,0,,0,,,,,0xFFFFFFFF,63,2,1024,,1,,11,{},{},{}
 20086,C_Dragon_Cintamani_Hat1,Costume Dragon Cintamani Hat,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1245,{},{},{}
 20086,C_Dragon_Cintamani_Hat1,Costume Dragon Cintamani Hat,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1245,{},{},{}
 20087,C_Dragon_Cintamani_Hat2,Costume Dragon Cintamani Hat,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1246,{},{},{}
 20087,C_Dragon_Cintamani_Hat2,Costume Dragon Cintamani Hat,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1246,{},{},{}
 20088,C_Dragon_Cintamani_Hat3,Costume Dragon Cintamani Hat,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1247,{},{},{}
 20088,C_Dragon_Cintamani_Hat3,Costume Dragon Cintamani Hat,4,0,,0,,,,0,0xFFFFFFFF,63,2,1024,,1,1,1247,{},{},{}

+ 1 - 1
db/re/skill_cast_db.txt

@@ -1575,7 +1575,7 @@
 //-- SO_EARTH_INSIGNIA
 //-- SO_EARTH_INSIGNIA
 2468,1000,0,0,60000,0,60000,1000
 2468,1000,0,0,60000,0,60000,1000
 //-- SO_ELEMENTAL_SHIELD
 //-- SO_ELEMENTAL_SHIELD
-5008,1000,0,0,0,0,10000,-1
+5008,1000,0,0,10000,0,10000,-1
 //==========================================
 //==========================================
 
 
 //==== Genetic skills ======================
 //==== Genetic skills ======================

+ 10 - 10
db/re/skill_db.txt

@@ -228,7 +228,7 @@
 128,0,0,0,0,0,0,10,0,no,0,0,0,misc,0,0x0,		HT_STEELCROW,Steel Crow
 128,0,0,0,0,0,0,10,0,no,0,0,0,misc,0,0x0,		HT_STEELCROW,Steel Crow
 129,5,8,1,0,0x42,1,5,1:2:3:4:5,yes,0,0,0,misc,0,0x80,	HT_BLITZBEAT,Blitz Beat
 129,5,8,1,0,0x42,1,5,1:2:3:4:5,yes,0,0,0,misc,0,0x80,	HT_BLITZBEAT,Blitz Beat
 130,3:5:7:9,6,2,0,0x3,3,4,1,no,0,0,0,misc,0,0x0,	HT_DETECTING,Detect
 130,3:5:7:9,6,2,0,0x3,3,4,1,no,0,0,0,misc,0,0x0,	HT_DETECTING,Detect
-131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x2000,	HT_SPRINGTRAP,Spring Trap
+131,4:5:6:7:8,6,32,0,0x1,0,5,1,no,0,0,0,misc,0,0x0,	HT_SPRINGTRAP,Spring Trap
 
 
 //****
 //****
 // Assassin
 // Assassin
@@ -870,7 +870,7 @@
 1010,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	BA_PANGVOICE,Pang Voice
 1010,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	BA_PANGVOICE,Pang Voice
 1011,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	DC_WINKCHARM,Wink of Charm
 1011,9,6,1,0,0x1,0,1,0,no,0,0x1,0,misc,0,0x0,	DC_WINKCHARM,Wink of Charm
 1012,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0,0x4000,	BS_UNFAIRLYTRICK,Unfair Trick
 1012,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0,0x4000,	BS_UNFAIRLYTRICK,Unfair Trick
-1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x0,	BS_GREED,Greed
+1013,0,6,4,0,0x3,2,1,0,no,0,0x1,0,weapon,0,0x2000,	BS_GREED,Greed
 1014,0,6,4,6,0x3,14,1,0,yes,0,0x1,0,magic,0,0x0,	PR_REDEMPTIO,Redemptio
 1014,0,6,4,6,0x3,14,1,0,yes,0,0x1,0,magic,0,0x0,	PR_REDEMPTIO,Redemptio
 1015,9,6,16,0,0x1,0,1,1,no,0,0x401,0,weapon,0,0x0,	MO_KITRANSLATION,Ki Translation
 1015,9,6,16,0,0x1,0,1,1,no,0,0x401,0,weapon,0,0x0,	MO_KITRANSLATION,Ki Translation
 1016,-1,6,1,-1,0x2,1,1,1,no,0,0x1,0,weapon,5,0x0,	MO_BALKYOUNG,Ki Explosion
 1016,-1,6,1,-1,0x2,1,1,1,no,0,0x1,0,weapon,5,0x0,	MO_BALKYOUNG,Ki Explosion
@@ -989,7 +989,7 @@
 2235,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0x0,		RA_RANGERMAIN,Ranger Main
 2235,0,0,0,0,0,0,10,0,no,0,0,0,none,0,0x0,		RA_RANGERMAIN,Ranger Main
 2236,9,8,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x80,	RA_AIMEDBOLT,Aimed Bolt
 2236,9,8,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x80,	RA_AIMEDBOLT,Aimed Bolt
 2237,9,6,2,0,0x3,3,1,1,no,0,0,0,none,0,0x2000,		RA_DETONATOR,Detonator
 2237,9,6,2,0,0x3,3,1,1,no,0,0,0,none,0,0x2000,		RA_DETONATOR,Detonator
-2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x0,	RA_ELECTRICSHOCKER,Electric Shocker
+2238,3,6,2,0,0x3,2,5,1,no,0,0x80,3,misc,0,0x2000,	RA_ELECTRICSHOCKER,Electric Shocker
 2239,3,6,2,0,0x42,3,5,1,no,0,0x80,3,misc,0,0x2800,	RA_CLUSTERBOMB,Cluster Bomb
 2239,3,6,2,0,0x42,3,5,1,no,0,0x80,3,misc,0,0x2800,	RA_CLUSTERBOMB,Cluster Bomb
 2240,0,6,4,0,0,0,1,1,no,0,0,0,none,0,0x0,		RA_WUGMASTERY,Warg Mastery
 2240,0,6,4,0,0,0,1,1,no,0,0,0,none,0,0x0,		RA_WUGMASTERY,Warg Mastery
 2241,0,6,4,0,0,0,3,1,no,0,0,0,none,0,0x2000,		RA_WUGRIDER,Warg Rider
 2241,0,6,4,0,0,0,3,1,no,0,0,0,none,0,0x2000,		RA_WUGRIDER,Warg Rider
@@ -1000,10 +1000,10 @@
 2246,0,6,4,0,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0,0x0,	RA_SENSITIVEKEEN,Sensitive Keen
 2246,0,6,4,0,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0,0x0,	RA_SENSITIVEKEEN,Sensitive Keen
 2247,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x42,		RA_CAMOUFLAGE,Camouflage
 2247,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x42,		RA_CAMOUFLAGE,Camouflage
 2248,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0,		RA_RESEARCHTRAP,Research Trap
 2248,0,0,0,0,0,0,5,0,no,0,0,0,none,0,0x0,		RA_RESEARCHTRAP,Research Trap
-2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_MAGENTATRAP,Magenta Trap
-2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_COBALTTRAP,Cobalt Trap
-2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_MAIZETRAP,Maize Trap
-2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x0,	RA_VERDURETRAP,Verdure Trap
+2249,3,6,2,3,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_MAGENTATRAP,Magenta Trap
+2250,3,6,2,1,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_COBALTTRAP,Cobalt Trap
+2251,3,6,2,2,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_MAIZETRAP,Maize Trap
+2252,3,6,2,4,0x43,2,1,1,no,0,0x80,1,misc,0,0x2000,	RA_VERDURETRAP,Verdure Trap
 2253,3,6,2,3,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_FIRINGTRAP,Firing Trap
 2253,3,6,2,3,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_FIRINGTRAP,Firing Trap
 2254,3,6,2,1,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_ICEBOUNDTRAP,Icebound Trap
 2254,3,6,2,1,0x42,2,5,1,no,0,0x80,2,misc,0,0x2800,	RA_ICEBOUNDTRAP,Icebound Trap
 
 
@@ -1194,7 +1194,7 @@
 2479,9,6,2,0,0,0,5,1,yes,0,0x80,3,misc,0,0x0,	GN_THORNS_TRAP,Thorn Trap
 2479,9,6,2,0,0,0,5,1,yes,0,0x80,3,misc,0,0x0,	GN_THORNS_TRAP,Thorn Trap
 2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0,0x0,		GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm....
 2480,11,6,1,0,0x1,0,5,1,yes,0,0,3,misc,0,0x0,		GN_BLOOD_SUCKER,Blood Sucker //CHECK Data says its a magic attack. Hmmmm....
 2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0,0x0,	GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm.
 2481,11,6,1,-1,0x2,1:2:3:4:5,5,1,yes,0,0,0,weapon,0,0x0,	GN_SPORE_EXPLOSION,Spore Explosion //CHECK Data says its element is set to neutral. Need to confirm.
-2482,11,6,16,0,0,0,5,1,yes,0,0,1,weapon,2,0x0,	GN_WALLOFTHORN,Wall of Thorns
+2482,11,6,2,0,0x8,0,5,1,yes,0,0,1,weapon,2,0x0,	GN_WALLOFTHORN,Wall of Thorns
 2483,11,6,2,0,0x3,4,10,1,yes,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED,Crazy Weed
 2483,11,6,2,0,0x3,4,10,1,yes,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED,Crazy Weed
 2484,0,6,2,2,0x2,2,10,1,no,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED_ATK,Crazy Weed Attack
 2484,0,6,2,2,0x2,2,10,1,no,0,0x0,0,weapon,0,0x1,	GN_CRAZYWEED_ATK,Crazy Weed Attack
 2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0,0x0,		GN_DEMONIC_FIRE,Demonic Fire
 2485,9,6,2,3,0,0,5,1,yes,0,0,0,magic,0,0x0,		GN_DEMONIC_FIRE,Demonic Fire
@@ -1344,8 +1344,8 @@
 8019,5,6,1,5,0,0,5,1,no,0,0,0,weapon,0,0x0,		MH_NEEDLE_OF_PARALYZE,Needle of Paralyze
 8019,5,6,1,5,0,0,5,1,no,0,0,0,weapon,0,0x0,		MH_NEEDLE_OF_PARALYZE,Needle of Paralyze
 8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0,0x0,		MH_POISON_MIST,Poison Mist
 8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0,0x0,		MH_POISON_MIST,Poison Mist
 8021,1,6,16,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_PAIN_KILLER,Pain Killer
 8021,1,6,16,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_PAIN_KILLER,Pain Killer
-8022,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0,0x0,		MH_LIGHT_OF_REGENE,Light of Regene
-8023,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0,0x0,		MH_OVERED_BOOST,Overed Boost
+8022,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_LIGHT_OF_REGENE,Light of Regene
+8023,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0,		MH_OVERED_BOOST,Overed Boost
 8024,7,8,1,4:0:4:0:4,0,0,5,-6,yes,0,0,0,magic,0,0x0,	MH_ERASER_CUTTER,Eraser Cutter
 8024,7,8,1,4:0:4:0:4,0,0,5,-6,yes,0,0,0,magic,0,0x0,	MH_ERASER_CUTTER,Eraser Cutter
 8025,7,8,2,4:0:4:0:4,0x2,2:2:3:3:4,5,-6,no,0,0,0,magic,0,0x0,	MH_XENO_SLASHER,Xeno Slasher
 8025,7,8,2,4:0:4:0:4,0x2,2:2:3:3:4,5,-6,no,0,0,0,magic,0,0x0,	MH_XENO_SLASHER,Xeno Slasher
 8026,5:5:7:7:9,6,6,0,0x1,0,5,1,no,0,0,0,magic,0,0x0,	MH_SILENT_BREEZE,Silent Breeze
 8026,5:5:7:7:9,6,6,0,0x1,0,5,1,no,0,0,0,magic,0,0x0,	MH_SILENT_BREEZE,Silent Breeze

+ 2 - 2
db/re/skill_unit_db.txt

@@ -153,8 +153,8 @@
 2482,0xe6,0x7f,  0, 1, 100,all,   0x000	//GN_WALLOFTHORN
 2482,0xe6,0x7f,  0, 1, 100,all,   0x000	//GN_WALLOFTHORN
 2484,0x86,    ,  0, 1, 100,enemy, 0x080	//GN_CRAZYWEED_ATK
 2484,0x86,    ,  0, 1, 100,enemy, 0x080	//GN_CRAZYWEED_ATK
 2485,0xe7,    ,  0, 2,2000,enemy, 0x098	//GN_DEMONIC_FIRE
 2485,0xe7,    ,  0, 2,2000,enemy, 0x098	//GN_DEMONIC_FIRE
-2487,0xe8,    ,  2, 0,  -1,all,   0x2000	//GN_FIRE_EXPANSION_SMOKE_POWDER
-2488,0xe9,    ,  2, 0,  -1,all,   0x2000	//GN_FIRE_EXPANSION_TEAR_GAS
+2487,0xe8,    ,  2, 0,  -1,enemy, 0x2000	//GN_FIRE_EXPANSION_SMOKE_POWDER
+2488,0xe9,    ,  2, 0,  -1,enemy, 0x2000	//GN_FIRE_EXPANSION_TEAR_GAS
 2490,0xea,    ,  0, 1,1000,enemy, 0x002	//GN_HELLS_PLANT
 2490,0xea,    ,  0, 1,1000,enemy, 0x002	//GN_HELLS_PLANT
 
 
 2555,0x104,   ,  0, 1:2:2:3:3,500,enemy,0x6	//RL_B_TRAP
 2555,0x104,   ,  0, 1:2:2:3:3,500,enemy,0x6	//RL_B_TRAP

+ 15 - 0
doc/atcommands.txt

@@ -1304,6 +1304,21 @@ Configuration files:
 -- pcdb: Player Settings
 -- pcdb: Player Settings
 -- statusdb: Status Settings
 -- statusdb: Status Settings
 
 
+Affected files:
+-- atcommand: atcommand_athena.conf, groups.conf
+-- battleconf: battle_athena.conf, battle_conf.txt
+-- instancedb: instance_db.txt
+-- itemdb: item_db.txt, item_group_db.txt, item_trade.txt, item_noequip.txt, item_nouse.txt, item_combo_db.txt, item_avail.txt, item_stack.txt, item_delay.txt, item_buyingstore.txt, item_flag.txt
+-- mobdb: mob_db.txt, mob_item_ratio.txt, mob_chat_db.txt, mob_avail.txt, mob_race2_db.txt, mob_branch.txt, mob_poring.txt, mob_boss.txt, mob_pouch.txt, mob_classchange.txt, pet_db.txt, homunculus_db.txt, homun_skill_tree.txt, exp_homun.txt, mercenary_db.txt, mercenary_skill_db.txt, elemental_db.txt, elemental_skill_db.txt
+-- motd: motd.txt
+-- msgconf: atcommand_athena.conf
+-- packetdb: packet_db.txt
+-- pcdb: statpoint.txt, job_exp.txt, skill_tree.txt, attr_fix.txt, job_db1.txt, job_db2.txt, job_basehpsp_db.txt, job_maxhpsp_db.txt, job_param_db.txt, level_penalty.txt
+-- questdb: quest_db.txt
+-- script: /npc/*.txt, /npc/*.conf
+-- skilldb: skill_db.txt, const.txt, skill_require_db.txt, skill_cast_db.txt, skill_castnodex_db.txt, skill_nocast_db.txt, skill_copyable_db.txt, skill_improvise_db.txt, skill_changematerial_db.txt, skill_nonearnpc_db.txt, skill_damage_db.txt, skill_unit_db.txt, abra_db.txt, create_arrow_db.txt, produce_db.txt, spellbook_db.txt, magicmushroom_db.txt
+ -- statusdb: attr_fix.txt, size_fix.txt, refine_db.tx
+
 ---------------------------------------
 ---------------------------------------
 
 
 @set <variable> {<value>}
 @set <variable> {<value>}

+ 200 - 0
doc/mob_db.txt

@@ -0,0 +1,200 @@
+//===== rAthena Documentation ================================
+//= rAthena Monster Database Reference
+//===== By: ==================================================
+//= rAthena Dev Team
+//===== Last Updated: ========================================
+//= 20140719
+//===== Description: =========================================
+//= Explanation of the mob_db.txt file and structure.
+//============================================================
+
+ID,Sprite_Name,kROName,iROName,LV,HP,SP,EXP,JEXP,Range1,ATK1,ATK2,DEF,MDEF,STR,AGI,VIT,INT,DEX,LUK,Range2,Range3,Scale,Race,Element,Mode,Speed,aDelay,aMotion,dMotion,MEXP,MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per,Drop1id,Drop1per,Drop2id,Drop2per,Drop3id,Drop3per,Drop4id,Drop4per,Drop5id,Drop5per,Drop6id,Drop6per,Drop7id,Drop7per,Drop8id,Drop8per,Drop9id,Drop9per,DropCardid,DropCardper
+
+---------------------------------------
+
+ID: The ID of the monster.
+
+---------------------------------------
+
+SpriteName: The sprite name of the monster (.act & .spr)
+
+---------------------------------------
+
+kROName: The name of the monster, this will be used when you use "--ja--".
+
+---------------------------------------
+
+iROName: The name of the monster, this will be used when you use "--en--".
+
+---------------------------------------
+
+LV: The level of the monster.
+
+---------------------------------------
+
+HP: The HP of the monster.
+
+---------------------------------------
+
+SP: The SP of the monster.
+
+---------------------------------------
+
+EXP: Base experience point of the monster.
+
+---------------------------------------
+
+JEXP: Job experience point of the monster.
+
+---------------------------------------
+
+Range1: Range of the monster attack. If set to 1 or 2, it will be set to melee attack. If set to 3 or more, it will be set to ranged attack.
+
+---------------------------------------
+
+ATK1: The minimum attack of the monster.
+
+---------------------------------------
+
+ATK2: The maximum attack of the monster. If undefined, the value of ATK1 will be used as the absolute attack.
+
+---------------------------------------
+
+DEF: Physical defense of the monster, reduce melee & ranged physical attack/skill.
+
+---------------------------------------
+
+MDEF: Magic defense of the monster, reduce magical skill.
+
+---------------------------------------
+
+STR: Strength of the monster. Affects ATK.
+
+---------------------------------------
+
+AGI: Agility of the monster. Affects FLEE.
+
+---------------------------------------
+
+VIT: Vitality of the monster. Adds additional DEF.
+
+---------------------------------------
+
+INT: Intelligence of the monster. Adds additional MATK.
+
+---------------------------------------
+
+DEX: Dexterity of the monster. Affects HIT rate.
+
+---------------------------------------
+
+LUK: Luck of the monster. Affects Perfect dodge/Lucky flee/Perfect flee/Lucky dodge rate.
+
+---------------------------------------
+
+Range2: Maximum Skill Range.
+
+---------------------------------------
+
+Range3: Sight limit of the monster. If set to 1000 or beyond, the monster will follow you all over the map.
+
+---------------------------------------
+
+Scale: Size of the monster
+
+	0 = Small
+	1 = Medium
+	2 = Large
+
+---------------------------------------
+
+Race: Race of the monster
+
+	0  = Formless
+	1  = Undead
+	2  = Brute
+	3  = Plant
+	4  = Insect
+	5  = Fish
+	6  = Demon
+	7  = Demi-Human
+	8  = Angel
+	9  = Dragon.
+	10 = Player (default race for player)
+
+Demi-Human is not same nor includes Player.
+
+---------------------------------------
+
+Element: Element of the monster, also for Element of db/elemental_db.txt, db/mercenary_db.txt, and db/[pre-]re/homunculus_db.txt
+
+	+-----------+-------+-------+-------+-------+
+	| Type		|  Lv1	|  Lv2	|  Lv3	|  Lv4	|
+	+-----------+-------+-------+-------+-------+
+	| Neutral	|  20	|  40	|  60	|  80	|
+	| Water		|  21	|  41	|  61	|  81	|
+	| Earth		|  22	|  42	|  62	|  82	|
+	| Fire		|  23	|  43	|  63	|  83	|
+	| Wind		|  24	|  44	|  64	|  84	|
+	| Poison	|  25	|  45	|  65	|  85	|
+	| Holy		|  26	|  46	|  66	|  86	|
+	| Shadow	|  27	|  47	|  67	|  87	|
+	| Ghost		|  28	|  48	|  68	|  88	|
+	| Undead	|  29	|  49	|  69	|  89	|
+	+-----------+-------+-------+-------+-------+
+	| For custom start from 30, 50, 70, and 90	|
+	+-----------+-------+-------+-------+-------+
+
+---------------------------------------
+
+Mode: Behaviour of the monster. Full explanation can be found on 'doc/mob_db_mode_list.txt'
+
+---------------------------------------
+
+Speed: Walk speed of the monster
+
+	1		= Fastest
+	100		= Normal
+	1000	= Slowest
+
+---------------------------------------
+
+aDelay: Attack Delay of the monster, also known as ASPD. Low value means faster attack speed, but don't make it too low or it will lag when a player got mobbed by several of these mobs.
+
+---------------------------------------
+
+aMotion: Attack animation motion. Low value means monster's attack will be displayed in higher fps (making it shorter, too) (Thanks to Wallex for this)
+
+---------------------------------------
+
+dMotion: 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.
+
+---------------------------------------
+
+MEXP: The MVP Experience point the monster gives when it is defeated (to the player who got the MVP reward) (This exp is a percentage of the exp the monster gives.)
+
+---------------------------------------
+
+MVP1-3id: The Item ID of the MVP drop goes here. Maximum of 3 items.
+
+---------------------------------------
+
+MVP1-3per: The rate of the MVP item being dropped, n/10000.
+
+---------------------------------------
+
+Drop1-9id: The Item ID of the drop goes here. Maximum of 9 items.
+
+---------------------------------------
+
+Drop1-9per: The rate of the item being dropped, n/10000.
+
+---------------------------------------
+
+DropCardid: The Item ID of the monster's card (if any).
+
+---------------------------------------
+
+DropCardper: The rate of the card being dropped, n/10000.
+
+---------------------------------------

+ 25 - 23
doc/mob_db_mode_list.txt

@@ -8,33 +8,34 @@
 //= A reference description of rAthena's mob_db 'mode' field.
 //= A reference description of rAthena's mob_db 'mode' field.
 //============================================================
 //============================================================
 
 
-Bit Legend:
+Bit Legend
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 
-MD_CANMOVE            | 0x000001 |      1
-MD_LOOTER             | 0x000002 |      2
-MD_AGGRESSIVE         | 0x000004 |      4
-MD_ASSIST             | 0x000008 |      8
-MD_CASTSENSOR_IDLE    | 0x000010 |     16
-MD_BOSS               | 0x000020 |     32
-MD_PLANT              | 0x000040 |     64
-MD_CANATTACK          | 0x000080 |    128
-MD_DETECTOR           | 0x000100 |    256
-MD_CASTSENSOR_CHASE   | 0x000200 |    512
-MD_CHANGECHASE        | 0x000400 |   1024
-MD_ANGRY              | 0x000800 |   2048
-MD_CHANGETARGET_MELEE | 0x001000 |   4096
-MD_CHANGETARGET_CHASE | 0x002000 |   8192
-MD_TARGETWEAK         | 0x004000 |  16384
-MD_RANDOMTARGET       | 0x008000 |  32768
-MD_IGNOREMELEE        | 0x010000 |  65536
-MD_IGNOREMAGIC        | 0x020000 |  131072
-MD_IGNORERANGED       | 0x040000 |  262144
-MD_MVP                | 0x080000 |  524288
+MD_CANMOVE            | 0x000001 |        1
+MD_LOOTER             | 0x000002 |        2
+MD_AGGRESSIVE         | 0x000004 |        4
+MD_ASSIST             | 0x000008 |        8
+MD_CASTSENSOR_IDLE    | 0x000010 |       16
+MD_BOSS               | 0x000020 |       32
+MD_PLANT              | 0x000040 |       64
+MD_CANATTACK          | 0x000080 |      128
+MD_DETECTOR           | 0x000100 |      256
+MD_CASTSENSOR_CHASE   | 0x000200 |      512
+MD_CHANGECHASE        | 0x000400 |     1024
+MD_ANGRY              | 0x000800 |     2048
+MD_CHANGETARGET_MELEE | 0x001000 |     4096
+MD_CHANGETARGET_CHASE | 0x002000 |     8192
+MD_TARGETWEAK         | 0x004000 |    16384
+MD_RANDOMTARGET       | 0x008000 |    32768
+MD_IGNOREMELEE        | 0x010000 |    65536
+MD_IGNOREMAGIC        | 0x020000 |   131072
+MD_IGNORERANGED       | 0x040000 |   262144
+MD_MVP                | 0x080000 |   524288
 MD_IGNOREMISC         | 0x100000 |  1048576
 MD_IGNOREMISC         | 0x100000 |  1048576
 MD_KNOCKBACK_IMMUNE   | 0x200000 |  2097152
 MD_KNOCKBACK_IMMUNE   | 0x200000 |  2097152
 
 
-Explanation for modes:
+
+Explanation for modes
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 
 CanMove: Enables the mob to move/chase characters.
 CanMove: Enables the mob to move/chase characters.
@@ -94,7 +95,8 @@ Ignore Misc: The mob will take 1 HP damage from "none" attack type.
 
 
 Knockback Immune: The mob will be unable to be knocked back.
 Knockback Immune: The mob will be unable to be knocked back.
 
 
-Aegis Mob Types:
+
+Aegis Mob Types
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
 
 What Aegis has are mob-types, where each type represents an AI behavior that
 What Aegis has are mob-types, where each type represents an AI behavior that

+ 145 - 0
doc/skill_require_db.txt

@@ -0,0 +1,145 @@
+//===== rAthena Documentation ================================
+//= rAthena Skill Requirement Reference
+//===== By: ==================================================
+//= rAthena Dev Team
+//===== Last Updated: ========================================
+//= 20140719
+//===== Description: =========================================
+//= Explanation of the skill_require_db.txt file and structure.
+//============================================================
+
+Structure:
+SkillID,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,RequiredStatuses,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10,RequiredEquipment
+
+---------------------------------------
+
+SkillID: The ID of the skill. (See \db\[re|pre-re]\skill_db.txt for more details)
+
+---------------------------------------
+
+HPCost:	Amount of HP needed to use the skill.
+
+---------------------------------------
+
+MaxHPTrigger: Player's HP has to be below this % of Max HP, in order to use the skill.
+
+---------------------------------------
+
+SPCost: Amount of SP needed to use the skill.
+
+---------------------------------------
+
+HPRateCost: If more than 0, it's a percentage of the player's current HP. If less than 0, it's a percentage of the player's Max HP.
+
+---------------------------------------
+
+SPRateCost: If more than 0, it's a percentage of the player's current SP. If less than 0, it's a percentage of the player's Max SP.
+
+---------------------------------------
+
+ZenyCost: Amount of Zeny needed to use the skill.
+
+---------------------------------------
+
+RequiredWeapons: Player needs to equip this type of weapon, in order to use the skill.
+	0: bare fist
+	1: Daggers
+	2: One-handed swords
+	3: Two-handed swords
+	4: One-handed spears
+	5: Two-handed spears
+	6: One-handed axes
+	7: Two-handed axes
+	8: Maces
+	9: Unused
+	10: Staves
+	11: Bows
+	12: Knuckles
+	13: Musical Instruments
+	14: Whips
+	15: Books
+	16: Katars
+	17: Revolvers
+	18: Rifles
+	19: Gatling guns
+	20: Shotguns
+	21: Grenade launchers
+	22: Fuuma Shurikens
+	23: Two-handed staves
+	24: Max Type
+	25: Dual-wield Daggers
+	26: Dual-wield Swords
+	27: Dual-wield Axes
+	28: Dagger + Sword
+	29: Dagger + Axe
+	30: Sword + Axe
+	
+Example usage of multiple values = type1:type2:type3
+Maximum multiple value is 30.
+
+---------------------------------------
+
+RequiredAmmoTypes: Player needs to equip this type of ammo to use the skill.
+	1: Arrows
+	2: Throwable daggers
+	3: Bullets
+	4: Shells
+	5: Grenades
+	6: Shuriken
+	7: Kunai
+	8: Cannonballs
+	9: Throwable Items (Sling Item)
+
+Example usage of multiple values = type1:type2:type3
+Maximum multiple value is 9.
+---------------------------------------
+
+RequiredAmmoAmount: Amount of ammo needed to use the skill.
+
+---------------------------------------
+
+RequiredState: Specify the 'State' required to be active, in order to use the skill.
+none = Nothing special.
+hidden = Requires hidden status by using Hiding, Cloaking, or Chasewalk.
+riding = Requires the player to ride either a Peco or a Dragon.
+falcon = Requires a Falcon.
+cart = Requires a Pushcart (For renewal, this state can be replaced by SC_PUSH_CART in 'RequiredStatuses' field).
+shield = Requires a shield equipped.
+recover_weight_rate = Requires to be less than 50% weight.
+move_enable = Requires to be able to move.
+water = Requires to be standing on a water cell.
+dragon = Requires to ride a Dragon.
+warg = Requires a Warg.
+ridingwarg = Requires to ride a Warg.
+mado = Requires to have an active Mado.
+elementalspirit = Requires to have an Elemental Spirit summoned.
+peco = Requires riding a Peco.
+
+---------------------------------------
+
+RequiredStatuses: List of status needed to be active, in order to use the skill.
+Example usage of values = SC_STATUS1:SC_STATUS2:SC_STATUS3 (see db/const.txt for more details).
+Maximum multiple value is 3. (Refer to skill.h: MAX_SKILL_STATUS_REQUIRE)
+Use any number or SC_ALL to disable status requirements.
+
+---------------------------------------
+
+SpiritSphereCost: Amount of Spirit Sphere needed to use the skill.
+
+---------------------------------------
+
+RequiredItemID1-10: These items will be used when players use the skill. Maximum of 10 items.
+
+---------------------------------------
+
+RequiredItemAmount1-10: Amount of item used when player uses the skill.
+0 means the item is required to be in inventory but won't be consumed.
+---------------------------------------
+
+RequiredEquipment: Player needs to equip these equipments to use the skill. (Use Item ID).
+Example usage of multiple values = item1:item2:item3
+Maximum multiple value is 10. (Refer to skill.h: MAX_SKILL_EQUIP_REQUIRE)
+
+---------------------------------------
+
+Note: On some fields, ":" delimiter means for each skill level, but there are some level dependent check. (Refer to https://github.com/rathena/rathena/blob/master/src/map/skill.c#L14963)

+ 8 - 7
npc/custom/events/cluckers.txt

@@ -16,6 +16,7 @@
 //= 1.1 Using 'switch rand' instead.
 //= 1.1 Using 'switch rand' instead.
 //= 1.2 Cleaned and standardized. [Euphy]
 //= 1.2 Cleaned and standardized. [Euphy]
 //= 1.2a Switched 'atcommand' to 'unitskilluseid'.
 //= 1.2a Switched 'atcommand' to 'unitskilluseid'.
+//= 1.3 Switched 'unitskilluseid' to 'unitkill'.
 //============================================================
 //============================================================
 
 
 prontera,156,219,4	script	Cluckers	800,{
 prontera,156,219,4	script	Cluckers	800,{
@@ -25,20 +26,20 @@ prontera,156,219,4	script	Cluckers	800,{
 	if (.startcluck) {
 	if (.startcluck) {
 		specialeffect2 EF_HIT3;
 		specialeffect2 EF_HIT3;
 		switch(rand(15)) {
 		switch(rand(15)) {
-			case 0: npctalk "CLUUUUUUCK!!!"; unitskilluseid getcharid(3),"NPC_SELFDESTRUCTION",1; emotion e_omg; break;
+			case 0: npctalk "CLUUUUUUCK!!!"; unitkill getcharid(3); skilleffect "NPC_SELFDESTRUCTION",1; emotion e_omg; break;
 			case 1: npctalk "Cluuuuuck!~"; break;
 			case 1: npctalk "Cluuuuuck!~"; break;
-			case 2: unitskilluseid getcharid(3),"NPC_SELFDESTRUCTION",1; break;
+			case 2: unitkill getcharid(3); skilleffect "NPC_SELFDESTRUCTION",1; break;
 			case 3: sc_start SC_Freeze,10000,0; break;
 			case 3: sc_start SC_Freeze,10000,0; break;
-			case 4: npctalk "CLUUUUUUUUUCK!!!"; unitskilluseid getcharid(3),"NPC_SELFDESTRUCTION",1; emotion e_omg; break;
+			case 4: npctalk "CLUUUUUUUUUCK!!!"; unitkill getcharid(3); skilleffect "NPC_SELFDESTRUCTION",1; emotion e_omg; break;
 			case 5: sc_start SC_Sleep,10000,0; break;
 			case 5: sc_start SC_Sleep,10000,0; break;
 			case 6: sc_start SC_Stone,10000,0; emotion e_gg; break;
 			case 6: sc_start SC_Stone,10000,0; emotion e_gg; break;
-			case 7: npctalk "CLUUUUUUCK!!!"; unitskilluseid getcharid(3),"NPC_SELFDESTRUCTION",1; emotion e_omg; break;
-			case 8: npctalk "Cluck! CLUUUCK!!"; unitskilluseid getcharid(3),"NPC_SELFDESTRUCTION",1; emotion e_omg; break;
+			case 7: npctalk "CLUUUUUUCK!!!"; unitkill getcharid(3); skilleffect "NPC_SELFDESTRUCTION",1; emotion e_omg; break;
+			case 8: npctalk "Cluck! CLUUUCK!!"; unitkill getcharid(3); skilleffect "NPC_SELFDESTRUCTION",1; emotion e_omg; break;
 			case 9: sc_start SC_Stun,10000,0; break;
 			case 9: sc_start SC_Stun,10000,0; break;
 			case 10: sc_start SC_Sleep,10000,0; emotion e_gg; break;
 			case 10: sc_start SC_Sleep,10000,0; emotion e_gg; break;
 			case 11: npctalk "Cluck! Cluck!"; break;
 			case 11: npctalk "Cluck! Cluck!"; break;
 			case 12: sc_start SC_Stun,10000,0; break;
 			case 12: sc_start SC_Stun,10000,0; break;
-			case 13: unitskilluseid getcharid(3),"NPC_SELFDESTRUCTION",1; break;
+			case 13: unitkill getcharid(3); skilleffect "NPC_SELFDESTRUCTION",1; break;
 			default:
 			default:
 				if (rand(50) < 4) {
 				if (rand(50) < 4) {
 					npctalk "WOOF!...........";
 					npctalk "WOOF!...........";
@@ -48,7 +49,7 @@ prontera,156,219,4	script	Cluckers	800,{
 					set .startcluck,0;
 					set .startcluck,0;
 				} else {
 				} else {
 					npctalk "Cluck! CLUUUCK!!";
 					npctalk "Cluck! CLUUUCK!!";
-					unitskilluseid getcharid(3),"NPC_SELFDESTRUCTION",1;
+					unitkill getcharid(3); skilleffect "NPC_SELFDESTRUCTION",1;
 				}
 				}
 				break;
 				break;
 		}
 		}

+ 270 - 277
npc/other/comodo_gambling.txt

@@ -3,7 +3,7 @@
 //===== By: ==================================================
 //===== By: ==================================================
 //= Reddozen, Cypress, Zefris
 //= Reddozen, Cypress, Zefris
 //===== Current Version: =====================================
 //===== Current Version: =====================================
-//= 1.4a
+//= 1.4c
 //===== Compatible With: =====================================
 //===== Compatible With: =====================================
 //= rAthena Project
 //= rAthena Project
 //===== Description: =========================================
 //===== Description: =========================================
@@ -25,6 +25,7 @@
 //= 1.4 Updated Script to match AEGIS file. [Masao]
 //= 1.4 Updated Script to match AEGIS file. [Masao]
 //= 1.4a Minor script updates. [Euphy]
 //= 1.4a Minor script updates. [Euphy]
 //= 1.4b Minor fix about Weight and miscs updates. [Capuche]
 //= 1.4b Minor fix about Weight and miscs updates. [Capuche]
+//= 1.4c Another clean-up. [Capuche]
 //============================================================ 
 //============================================================ 
 
 
 comodo,219,158,6	script	Kachua	4_F_02,{
 comodo,219,158,6	script	Kachua	4_F_02,{
@@ -41,7 +42,6 @@ comodo,219,158,6	script	Kachua	4_F_02,{
 	mes "showed me that diamond,";
 	mes "showed me that diamond,";
 	mes "it's been all I think about!";
 	mes "it's been all I think about!";
 	next;
 	next;
-
 	if (select("Would you like to have mine?", "Ah, what a shame...") == 2) {
 	if (select("Would you like to have mine?", "Ah, what a shame...") == 2) {
 		mes "[Kachua]";
 		mes "[Kachua]";
 		mes "Yes, I know...";
 		mes "Yes, I know...";
@@ -52,7 +52,6 @@ comodo,219,158,6	script	Kachua	4_F_02,{
 		cutin "katsua01.bmp",255;
 		cutin "katsua01.bmp",255;
 		end;
 		end;
 	}
 	}
-
 	if (countitem(732) == 0) {
 	if (countitem(732) == 0) {
 		cutin "katsua01.bmp",255;
 		cutin "katsua01.bmp",255;
 		cutin "katsua03.bmp",2;
 		cutin "katsua03.bmp",2;
@@ -64,7 +63,6 @@ comodo,219,158,6	script	Kachua	4_F_02,{
 		cutin "katsua03.bmp",255;
 		cutin "katsua03.bmp",255;
 		end;
 		end;
 	}
 	}
-
 	mes "[Kachua]";
 	mes "[Kachua]";
 	mes "Are you sure you don't mind";
 	mes "Are you sure you don't mind";
 	mes "giving this to me? Thank you";
 	mes "giving this to me? Thank you";
@@ -73,7 +71,6 @@ comodo,219,158,6	script	Kachua	4_F_02,{
 	mes "you something from one of my";
 	mes "you something from one of my";
 	mes "collections~";
 	mes "collections~";
 	next;
 	next;
-	
 	if (MaxWeight - Weight < 5500) {
 	if (MaxWeight - Weight < 5500) {
 		cutin "katsua01.bmp",255;
 		cutin "katsua01.bmp",255;
 		cutin "katsua03.bmp",2;
 		cutin "katsua03.bmp",2;
@@ -86,300 +83,296 @@ comodo,219,158,6	script	Kachua	4_F_02,{
 		cutin "katsua03.bmp",255;
 		cutin "katsua03.bmp",255;
 		end;
 		end;
 	}
 	}
-
 	if (countitem(732) == 0) { // anti-hack
 	if (countitem(732) == 0) { // anti-hack
 		logmes "Hack: Tried to bypass item check.";
 		logmes "Hack: Tried to bypass item check.";
 		cutin "katsua01.bmp",255;
 		cutin "katsua01.bmp",255;
 		close;
 		close;
 	}
 	}
 	delitem 732,1;
 	delitem 732,1;
-
 	mes "[Kachua]";
 	mes "[Kachua]";
 	mes "So what would";
 	mes "So what would";
 	mes "you like to have?";
 	mes "you like to have?";
 	next;
 	next;
-
 	switch (select("Weapon", "Armor", "Garment", "Helmet", "Shoes", "Shield")) {
 	switch (select("Weapon", "Armor", "Garment", "Helmet", "Shoes", "Shield")) {
-
 	case 1: // Weapons
 	case 1: // Weapons
-			.@gamble1 = rand(1,1000);
-			if ((.@gamble1 > 920) && (.@gamble1 < 931)) {
-				.@gamble2 = rand(1,85);
-				if      (.@gamble2 ==  1) .@item = 1128; // Haedonggum[2]
-				else if (.@gamble2 ==  2) .@item = 1120; // Tsurugi[2]
-				else if (.@gamble2 ==  3) .@item = 1127; // Saber[3]
-				else if (.@gamble2 ==  4) .@item = 1158; // Two-Handed Sword[2]
-				else if (.@gamble2 ==  5) .@item = 1155; // Bastard Sword[3]
-				else if (.@gamble2 ==  6) .@item = 1220; // Gladius[3]
-				else if (.@gamble2 ==  7) .@item = 1222; // Damascus[1]
-				else if (.@gamble2 ==  8) .@item = 1253; // Katar[2]
-				else if (.@gamble2 ==  9) .@item = 1529; // Iron Driver
-				else if (.@gamble2 == 10) .@item = 1251; // Jur[3]
-				else if (.@gamble2 == 11) .@item = 1361; // Two-Handed Axe[2]
-				else if (.@gamble2 == 12) .@item = 1258; // Katar of Raging Blaze
-				else if (.@gamble2 == 13) .@item = 1257; // Katar of Quaking
-				else if (.@gamble2 == 14) .@item = 1256; // Katar of Frozen Icicle
-				else if (.@gamble2 == 15) .@item = 1259; // Katar of Piercing Wind
-				else if (.@gamble2 == 16) .@item = 1260; // Sharpened Legbone of Ghoul
-				else if (.@gamble2 == 17) .@item = 1716; // Gakkung Bow[2]
-				else if (.@gamble2 == 18) .@item = 1715; // Arbalest[2]
-				else if (.@gamble2 == 19) .@item = 1711; // Crossbow[3]
-				else if (.@gamble2 == 20) .@item = 1702; // Bow[4]
-				else if (.@gamble2 == 21) .@item = 1520; // Chain[3]
-				else if (.@gamble2 == 22) .@item = 1610; // Arc Wand[1]
-				else if (.@gamble2 == 23) .@item = 1615; // Evil Bone Wand
-				else if (.@gamble2 == 24) .@item = 1602; // Rod[4]
-				else if (.@gamble2 == 25) .@item = 1461; // Trident[3]
-				else if (.@gamble2 == 26) .@item = 1402; // Javelin[4]
-				else if (.@gamble2 == 27) .@item = 1961; // Whip[2]
-				else if (.@gamble2 == 28) .@item = 1957; // Rante Whip[1]
-				else if (.@gamble2 == 29) .@item = 1552; // Tablet[1]
-				else if (.@gamble2 == 30) .@item = 1551; // Bible[2]
-				else if (.@gamble2 == 31) .@item = 1553; // Book of Billows
-				else if (.@gamble2 == 32) .@item = 1554; // Book of Mother Earth
-				else if (.@gamble2 == 33) .@item = 1555; // Book of the Blazing Sun
-				else if (.@gamble2 == 34) .@item = 1556; // Book of Gust of Wind
-				else if (.@gamble2 == 35) .@item = 1951; // Rope[4]
-				else if (.@gamble2 == 36) .@item = 1959; // Tail Whip[2]
-				else if (.@gamble2 == 37) .@item = 1953; // Whip[3]
-				else if (.@gamble2 == 38) .@item = 1955; // Wire Whip[3]
-				else if (.@gamble2 == 39) .@item = 1810; // Claw[2]
-				else if (.@gamble2 == 40) .@item = 1910; // Harp[2]
-				else if (.@gamble2 == 41) .@item = 1906; // Lute[3]
-				else if (.@gamble2 == 42) .@item = 1902; // Violin[4]
-				else if (.@gamble2 == 43) .@item = 1904; // Mandolin[3]
-				else if (.@gamble2 == 44) .@item = 1912; // Gumoongoh[2]
-				else if (.@gamble2 == 45) .@item = 1908; // Guitar[1]
-				else if (.@gamble2 == 46) .@item = 1808; // Fist[1]
-				else if (.@gamble2 == 47) .@item = 1802; // Waghnak[4]
-				else if (.@gamble2 == 48) .@item = 1812; // Finger[2]
-				else if (.@gamble2 == 49) .@item = 1806; // Studded Knuckles[3]
-				else if (.@gamble2 == 50) .@item = 1804; // Knuckle Duster[3]
-				else if (.@gamble2 == 51) .@item = 1550; // Book[3]
-				else if (.@gamble2 == 52) .@item = 1246; // Cinquedea[2]
-				else if (.@gamble2 == 53) .@item = 1147; // Town Sword
-				else if (.@gamble2 > 53 && .@gamble2 < 56) .@item = 1264; // Specialty Jur[4]
-				else if (.@gamble2 > 55 && .@gamble2 < 58) .@item = 1262; // Loki's Nail
-				else if (.@gamble2 > 57 && .@gamble2 < 60) .@item = 1622; // Hypnotist's Staff[2]
-				else if (.@gamble2 == 60) .@item = 1723; // Luna Bow[2]
-				else if (.@gamble2 > 60 && .@gamble2 < 63) .@item = 1965; // Red Flame Whip
-				else if (.@gamble2 > 62 && .@gamble2 < 65) .@item = 1966; // Icicle Whip
-				else if (.@gamble2 > 64 && .@gamble2 < 67) .@item = 1967; // Gaia Whip
-				else if (.@gamble2 > 66 && .@gamble2 < 69) .@item = 1968; // Skipping Rope
-				else if (.@gamble2 > 68 && .@gamble2 < 71) .@item = 1914; // Burning Passion Guitar
-				else if (.@gamble2 > 70 && .@gamble2 < 73) .@item = 1915; // Loner's Guitar
-				else if (.@gamble2 > 72 && .@gamble2 < 75) .@item = 1916; // Green Acre Guitar
-				else if (.@gamble2 > 74 && .@gamble2 < 77) .@item = 1917; // Gentle Breeze Guitar
-				else if (.@gamble2 > 76 && .@gamble2 < 79) .@item = 13004; // Cowardice Blade[2]
-				else if (.@gamble2 > 78 && .@gamble2 < 81) .@item = 1307; // Windhawk
-				else if (.@gamble2 == 81) .@item = 1560; // Sage's Diary[2]
-				else if (.@gamble2 == 82) .@item = 1618; // Survivor's Rod[1]
-				else if (.@gamble2 == 83) .@item = 1620; // Survivor's Rod[1]
-				else if (.@gamble2 > 83 && .@gamble2 < 86) .@item = 1971; // Electric Wire
-			}
-			else if ((.@gamble1 >   0) && (.@gamble1 <  201)) .@item = 1201; // Knife[3]
-			else if ((.@gamble1 > 200) && (.@gamble1 <  301)) .@item = 1101; // Sword[3]
-			else if ((.@gamble1 > 300) && (.@gamble1 <  401)) .@item = 1601; // Rod[3]
-			else if ((.@gamble1 > 400) && (.@gamble1 <  501)) .@item = 1116; // Katana[3]
-			else if ((.@gamble1 > 500) && (.@gamble1 <  601)) .@item = 1250; // Jur[2]
-			else if ((.@gamble1 > 600) && (.@gamble1 <  701)) .@item = 1301; // Axe[3]
-			else if ((.@gamble1 > 700) && (.@gamble1 <  801)) .@item = 1701; // Bow[3]
-			else if ((.@gamble1 > 800) && (.@gamble1 <  851)) .@item = 1504; // Mace[3]
-			else if ((.@gamble1 > 850) && (.@gamble1 <  901)) .@item = 1604; // Wand[2]
-			else if ((.@gamble1 > 900) && (.@gamble1 <  911)) .@item = 1108; // Blade[4]
-			else if ((.@gamble1 > 910) && (.@gamble1 <  921)) .@item = 1163; // Claymore
-			else if ((.@gamble1 > 930) && (.@gamble1 <  961)) .@item = 1522; // Stunner
-			else if ((.@gamble1 > 960) && (.@gamble1 <  971)) .@item = 1608; // Staff[3]
-			else if ((.@gamble1 > 970) && (.@gamble1 <  981)) .@item = 1408; // Pike[4]
-			else if ((.@gamble1 > 980) && (.@gamble1 <  991)) .@item = 1452; // Guisarme[3]
-			else if ((.@gamble1 > 990) && (.@gamble1 < 1001)) .@item = 1208; // Main Gauche[4]
-	break;
+		.@gamble1 = rand(1,1000);
+		if (.@gamble1 > 920 && .@gamble1 < 931) {
+			.@gamble2 = rand(1,85);
+			if      (.@gamble2 ==  1) .@item = 1128; // Haedonggum[2]
+			else if (.@gamble2 ==  2) .@item = 1120; // Tsurugi[2]
+			else if (.@gamble2 ==  3) .@item = 1127; // Saber[3]
+			else if (.@gamble2 ==  4) .@item = 1158; // Two-Handed Sword[2]
+			else if (.@gamble2 ==  5) .@item = 1155; // Bastard Sword[3]
+			else if (.@gamble2 ==  6) .@item = 1220; // Gladius[3]
+			else if (.@gamble2 ==  7) .@item = 1222; // Damascus[1]
+			else if (.@gamble2 ==  8) .@item = 1253; // Katar[2]
+			else if (.@gamble2 ==  9) .@item = 1529; // Iron Driver
+			else if (.@gamble2 == 10) .@item = 1251; // Jur[3]
+			else if (.@gamble2 == 11) .@item = 1361; // Two-Handed Axe[2]
+			else if (.@gamble2 == 12) .@item = 1258; // Katar of Raging Blaze
+			else if (.@gamble2 == 13) .@item = 1257; // Katar of Quaking
+			else if (.@gamble2 == 14) .@item = 1256; // Katar of Frozen Icicle
+			else if (.@gamble2 == 15) .@item = 1259; // Katar of Piercing Wind
+			else if (.@gamble2 == 16) .@item = 1260; // Sharpened Legbone of Ghoul
+			else if (.@gamble2 == 17) .@item = 1716; // Gakkung Bow[2]
+			else if (.@gamble2 == 18) .@item = 1715; // Arbalest[2]
+			else if (.@gamble2 == 19) .@item = 1711; // Crossbow[3]
+			else if (.@gamble2 == 20) .@item = 1702; // Bow[4]
+			else if (.@gamble2 == 21) .@item = 1520; // Chain[3]
+			else if (.@gamble2 == 22) .@item = 1610; // Arc Wand[1]
+			else if (.@gamble2 == 23) .@item = 1615; // Evil Bone Wand
+			else if (.@gamble2 == 24) .@item = 1602; // Rod[4]
+			else if (.@gamble2 == 25) .@item = 1461; // Trident[3]
+			else if (.@gamble2 == 26) .@item = 1402; // Javelin[4]
+			else if (.@gamble2 == 27) .@item = 1961; // Whip[2]
+			else if (.@gamble2 == 28) .@item = 1957; // Rante Whip[1]
+			else if (.@gamble2 == 29) .@item = 1552; // Tablet[1]
+			else if (.@gamble2 == 30) .@item = 1551; // Bible[2]
+			else if (.@gamble2 == 31) .@item = 1553; // Book of Billows
+			else if (.@gamble2 == 32) .@item = 1554; // Book of Mother Earth
+			else if (.@gamble2 == 33) .@item = 1555; // Book of the Blazing Sun
+			else if (.@gamble2 == 34) .@item = 1556; // Book of Gust of Wind
+			else if (.@gamble2 == 35) .@item = 1951; // Rope[4]
+			else if (.@gamble2 == 36) .@item = 1959; // Tail Whip[2]
+			else if (.@gamble2 == 37) .@item = 1953; // Whip[3]
+			else if (.@gamble2 == 38) .@item = 1955; // Wire Whip[3]
+			else if (.@gamble2 == 39) .@item = 1810; // Claw[2]
+			else if (.@gamble2 == 40) .@item = 1910; // Harp[2]
+			else if (.@gamble2 == 41) .@item = 1906; // Lute[3]
+			else if (.@gamble2 == 42) .@item = 1902; // Violin[4]
+			else if (.@gamble2 == 43) .@item = 1904; // Mandolin[3]
+			else if (.@gamble2 == 44) .@item = 1912; // Gumoongoh[2]
+			else if (.@gamble2 == 45) .@item = 1908; // Guitar[1]
+			else if (.@gamble2 == 46) .@item = 1808; // Fist[1]
+			else if (.@gamble2 == 47) .@item = 1802; // Waghnak[4]
+			else if (.@gamble2 == 48) .@item = 1812; // Finger[2]
+			else if (.@gamble2 == 49) .@item = 1806; // Studded Knuckles[3]
+			else if (.@gamble2 == 50) .@item = 1804; // Knuckle Duster[3]
+			else if (.@gamble2 == 51) .@item = 1550; // Book[3]
+			else if (.@gamble2 == 52) .@item = 1246; // Cinquedea[2]
+			else if (.@gamble2 == 53) .@item = 1147; // Town Sword
+			else if (.@gamble2 < 56) .@item = 1264;	// Specialty Jur[4]
+			else if (.@gamble2 < 58) .@item = 1262; // Loki's Nail
+			else if (.@gamble2 < 60) .@item = 1622; // Hypnotist's Staff[2]
+			else if (.@gamble2 == 60) .@item = 1723;// Luna Bow[2]
+			else if (.@gamble2 < 63) .@item = 1965; // Red Flame Whip
+			else if (.@gamble2 < 65) .@item = 1966; // Icicle Whip
+			else if (.@gamble2 < 67) .@item = 1967; // Gaia Whip
+			else if (.@gamble2 < 69) .@item = 1968; // Skipping Rope
+			else if (.@gamble2 < 71) .@item = 1914; // Burning Passion Guitar
+			else if (.@gamble2 < 73) .@item = 1915; // Loner's Guitar
+			else if (.@gamble2 < 75) .@item = 1916; // Green Acre Guitar
+			else if (.@gamble2 < 77) .@item = 1917; // Gentle Breeze Guitar
+			else if (.@gamble2 < 79) .@item = 13004; // Cowardice Blade[2]
+			else if (.@gamble2 < 81) .@item = 1307; // Windhawk
+			else if (.@gamble2 == 81) .@item = 1560; // Sage's Diary[2]
+			else if (.@gamble2 == 82) .@item = 1618; // Survivor's Rod[1]
+			else if (.@gamble2 == 83) .@item = 1620; // Survivor's Rod[1]
+			else if (.@gamble2 < 86) .@item = 1971; // Electric Wire
+		}
+		else if (.@gamble1 <  201) .@item = 1201; // Knife[3]
+		else if (.@gamble1 <  301) .@item = 1101; // Sword[3]
+		else if (.@gamble1 <  401) .@item = 1601; // Rod[3]
+		else if (.@gamble1 <  501) .@item = 1116; // Katana[3]
+		else if (.@gamble1 <  601) .@item = 1250; // Jur[2]
+		else if (.@gamble1 <  701) .@item = 1301; // Axe[3]
+		else if (.@gamble1 <  801) .@item = 1701; // Bow[3]
+		else if (.@gamble1 <  851) .@item = 1504; // Mace[3]
+		else if (.@gamble1 <  901) .@item = 1604; // Wand[2]
+		else if (.@gamble1 <  911) .@item = 1108; // Blade[4]
+		else if (.@gamble1 <  921) .@item = 1163; // Claymore
+		else if (.@gamble1 <  961) .@item = 1522; // Stunner
+		else if (.@gamble1 <  971) .@item = 1608; // Staff[3]
+		else if (.@gamble1 <  981) .@item = 1408; // Pike[4]
+		else if (.@gamble1 <  991) .@item = 1452; // Guisarme[3]
+		else if (.@gamble1 < 1001) .@item = 1208; // Main Gauche[4]
+		break;
 
 
 	case 2: // Armors
 	case 2: // Armors
-			.@gamble1 = rand(1,500);
-			if ((.@gamble1 > 299) && (.@gamble1 < 303)) {
-				.@gamble2 = rand(1,30);
-				if      ((.@gamble2 >  0) && (.@gamble2 <  3)) .@item = 2315; // Chain Mail[1]
-				else if ((.@gamble2 >  2) && (.@gamble2 <  5)) .@item = 2336; // Thief Clothes[1]
-				else if ((.@gamble2 >  4) && (.@gamble2 <  7)) .@item = 2318; // Lord's Clothes[1]
-				else if ((.@gamble2 >  6) && (.@gamble2 <  9)) .@item = 2326; // Saint's Robe[1]
-				else if ((.@gamble2 >  8) && (.@gamble2 < 11)) .@item = 2327; // Holy Robe
-				else if ((.@gamble2 > 10) && (.@gamble2 < 13)) .@item = 2342; // Legion Plate Armor[1]
-				else if ((.@gamble2 > 12) && (.@gamble2 < 15)) .@item = 2331; // Tights[1]
-				else if ((.@gamble2 > 14) && (.@gamble2 < 17)) .@item = 2342; // Legion Plate Armor[1]
-				else if ((.@gamble2 > 16) && (.@gamble2 < 19)) .@item = 2311; // Mink Coat[1]
-				else if ((.@gamble2 > 18) && (.@gamble2 < 21)) .@item = 2320; // Formal Suit[1]
-				else if ((.@gamble2 > 20) && (.@gamble2 < 23)) .@item = 2319; // Glittering Jacket[1]
-				else if ((.@gamble2 > 22) && (.@gamble2 < 25)) .@item = 2344; // Lucius's Fierce Armor of Volcano
-				else if ((.@gamble2 > 24) && (.@gamble2 < 27)) .@item = 2346; // Saphien's Armor of Ocean
-				else if ((.@gamble2 > 26) && (.@gamble2 < 29)) .@item = 2348; // Aebeccee's Raging Typhoon Armor
-				else if ((.@gamble2 > 28) && (.@gamble2 < 31)) .@item = 2350; // Claytos Cracking Earth Armor
-			}
-			else if ((.@gamble1 >   0) && (.@gamble1 <  51)) .@item = 2301; // Cotton Shirt
-			else if ((.@gamble1 >  50) && (.@gamble1 < 101)) .@item = 2302; // Cotton Shirt[1]
-			else if ((.@gamble1 > 100) && (.@gamble1 < 151)) .@item = 2303; // Jacket
-			else if ((.@gamble1 > 150) && (.@gamble1 < 201)) .@item = 2304; // Jacket[1]
-			else if ((.@gamble1 > 200) && (.@gamble1 < 251)) .@item = 2305; // Adventurer's Suit
-			else if ((.@gamble1 > 250) && (.@gamble1 < 300)) .@item = 2301; // Cotton Shirt
-			else if ((.@gamble1 > 301) && (.@gamble1 < 351)) .@item = 2307; // Mantle
-			else if ((.@gamble1 > 350) && (.@gamble1 < 401)) .@item = 2309; // Coat
-			else if ((.@gamble1 > 400) && (.@gamble1 < 402)) .@item = 2322; // Silk Robe[1]
-			else if ((.@gamble1 > 401) && (.@gamble1 < 403)) .@item = 2310; // Coat[1]
-			else if ((.@gamble1 > 402) && (.@gamble1 < 411)) .@item = 2306; // Adventurer's Suit[1]
-			else if ((.@gamble1 > 410) && (.@gamble1 < 416)) .@item = 2308; // Mantle[1]
-			else if ((.@gamble1 > 415) && (.@gamble1 < 421)) .@item = 2313; // Padded Armor[1]
-			else if ((.@gamble1 > 420) && (.@gamble1 < 426)) .@item = 2337; // Ninja Suit
-			else if ((.@gamble1 > 425) && (.@gamble1 < 431)) .@item = 2341; // Legion Plate Armor
-			else if ((.@gamble1 > 430) && (.@gamble1 < 436)) .@item = 2325; // Saint's Robe
-			else if ((.@gamble1 > 435) && (.@gamble1 < 441)) .@item = 2317; // Full Plate
-			else if ((.@gamble1 > 440) && (.@gamble1 < 446)) .@item = 2330; // Tights
-			else if ((.@gamble1 > 445) && (.@gamble1 < 451)) .@item = 2314; // Chain Mail
-			else if ((.@gamble1 > 450) && (.@gamble1 < 456)) .@item = 2335; // Thief Clothes
-			else if ((.@gamble1 > 455) && (.@gamble1 < 461)) .@item = 2324; // Scapulare[1]
-			else if ((.@gamble1 > 460) && (.@gamble1 < 466)) .@item = 2329; // Wooden Mail[1]
-			else if ((.@gamble1 > 465) && (.@gamble1 < 471)) .@item = 2340; // Novice Breastplate[1]
-			else if ((.@gamble1 > 470) && (.@gamble1 < 476)) .@item = 2312; // Padded Armor
-			else if ((.@gamble1 > 475) && (.@gamble1 < 481)) .@item = 2339; // Pantie
-			else if ((.@gamble1 > 480) && (.@gamble1 < 486)) .@item = 2328; // Wooden Mail
-			else if ((.@gamble1 > 485) && (.@gamble1 < 491)) .@item = 2321; // Silk Robe
-			else if ((.@gamble1 > 490) && (.@gamble1 < 501)) .@item = 2323; // Scapulare
-	break;
+		.@gamble1 = rand(1,500);
+		if (.@gamble1 > 299 && .@gamble1 < 303) {
+			.@gamble2 = rand(1,30);
+			if      (.@gamble2 <  3) .@item = 2315; // Chain Mail[1]
+			else if (.@gamble2 <  5) .@item = 2336; // Thief Clothes[1]
+			else if (.@gamble2 <  7) .@item = 2318; // Lord's Clothes[1]
+			else if (.@gamble2 <  9) .@item = 2326; // Saint's Robe[1]
+			else if (.@gamble2 < 11) .@item = 2327; // Holy Robe
+			else if (.@gamble2 < 13) .@item = 2342; // Legion Plate Armor[1]
+			else if (.@gamble2 < 15) .@item = 2331; // Tights[1]
+			else if (.@gamble2 < 17) .@item = 2342; // Legion Plate Armor[1]
+			else if (.@gamble2 < 19) .@item = 2311; // Mink Coat[1]
+			else if (.@gamble2 < 21) .@item = 2320; // Formal Suit[1]
+			else if (.@gamble2 < 23) .@item = 2319; // Glittering Jacket[1]
+			else if (.@gamble2 < 25) .@item = 2344; // Lucius's Fierce Armor of Volcano
+			else if (.@gamble2 < 27) .@item = 2346; // Saphien's Armor of Ocean
+			else if (.@gamble2 < 29) .@item = 2348; // Aebeccee's Raging Typhoon Armor
+			else if (.@gamble2 < 31) .@item = 2350; // Claytos Cracking Earth Armor
+		}
+		else if (.@gamble1 <  51) .@item = 2301; // Cotton Shirt
+		else if (.@gamble1 < 101) .@item = 2302; // Cotton Shirt[1]
+		else if (.@gamble1 < 151) .@item = 2303; // Jacket
+		else if (.@gamble1 < 201) .@item = 2304; // Jacket[1]
+		else if (.@gamble1 < 251) .@item = 2305; // Adventurer's Suit
+		else if (.@gamble1 < 300) .@item = 2301; // Cotton Shirt
+		else if (.@gamble1 < 351) .@item = 2307; // Mantle
+		else if (.@gamble1 < 401) .@item = 2309; // Coat
+		else if (.@gamble1 < 402) .@item = 2322; // Silk Robe[1]
+		else if (.@gamble1 < 403) .@item = 2310; // Coat[1]
+		else if (.@gamble1 < 411) .@item = 2306; // Adventurer's Suit[1]
+		else if (.@gamble1 < 416) .@item = 2308; // Mantle[1]
+		else if (.@gamble1 < 421) .@item = 2313; // Padded Armor[1]
+		else if (.@gamble1 < 426) .@item = 2337; // Ninja Suit
+		else if (.@gamble1 < 431) .@item = 2341; // Legion Plate Armor
+		else if (.@gamble1 < 436) .@item = 2325; // Saint's Robe
+		else if (.@gamble1 < 441) .@item = 2317; // Full Plate
+		else if (.@gamble1 < 446) .@item = 2330; // Tights
+		else if (.@gamble1 < 451) .@item = 2314; // Chain Mail
+		else if (.@gamble1 < 456) .@item = 2335; // Thief Clothes
+		else if (.@gamble1 < 461) .@item = 2324; // Scapulare[1]
+		else if (.@gamble1 < 466) .@item = 2329; // Wooden Mail[1]
+		else if (.@gamble1 < 471) .@item = 2340; // Novice Breastplate[1]
+		else if (.@gamble1 < 476) .@item = 2312; // Padded Armor
+		else if (.@gamble1 < 481) .@item = 2339; // Pantie
+		else if (.@gamble1 < 486) .@item = 2328; // Wooden Mail
+		else if (.@gamble1 < 491) .@item = 2321; // Silk Robe
+		else if (.@gamble1 < 501) .@item = 2323; // Scapulare
+		break;
 
 
 	case 3:  // Garments
 	case 3:  // Garments
-			.@gamble1 = rand(1,500);
-			if ((.@gamble1 > 200) && (.@gamble1 < 204)) {
-				.@gamble2 = rand(1,16);
-				if      ((.@gamble2 >  0) && (.@gamble2 <  3)) .@item = 2506; // Manteau[1]
-				else if ((.@gamble2 >  2) && (.@gamble2 <  5)) .@item = 2504; // Muffler[1]
-				else if ((.@gamble2 >  4) && (.@gamble2 <  8)) .@item = 2508; // Ragamuffin Manteau
-				else if ((.@gamble2 >  7) && (.@gamble2 < 11)) .@item = 2507; // Ancient Cape
-				else if (.@gamble2 == 11) .@item = 2513; // Heavenly Maiden Robe[1]
-				else if (.@gamble2 == 12) .@item = 2514; // Pauldron[1]
-				else if (.@gamble2 == 13) .@item = 2523; // Undershirt[1]
-				else if (.@gamble2 == 14) .@item = 2530; // Rider Insigna[1]
-				else if (.@gamble2 == 15) .@item = 2509; // Survivor's Manteau
-				else if (.@gamble2 == 16) .@item = 2515; // Eagle Wing[1]
-			}
-			else if ((.@gamble1 >   0) && (.@gamble1 < 101)) .@item = 2503; // Muffler
-			else if ((.@gamble1 > 100) && (.@gamble1 < 201)) .@item = 2505; // Manteau
-			else if ((.@gamble1 > 203) && (.@gamble1 < 451)) .@item = 2501; // Hood
-			else if ((.@gamble1 > 450) && (.@gamble1 < 501)) .@item = 2502; // Hood[1]
-	break;
+		.@gamble1 = rand(1,500);
+		if (.@gamble1 > 200 && .@gamble1 < 204) {
+			.@gamble2 = rand(1,16);
+			if      (.@gamble2 <  3) .@item = 2506; // Manteau[1]
+			else if (.@gamble2 <  5) .@item = 2504; // Muffler[1]
+			else if (.@gamble2 <  8) .@item = 2508; // Ragamuffin Manteau
+			else if (.@gamble2 < 11) .@item = 2507; // Ancient Cape
+			else if (.@gamble2 == 11) .@item = 2513; // Heavenly Maiden Robe[1]
+			else if (.@gamble2 == 12) .@item = 2514; // Pauldron[1]
+			else if (.@gamble2 == 13) .@item = 2523; // Undershirt[1]
+			else if (.@gamble2 == 14) .@item = 2530; // Rider Insigna[1]
+			else if (.@gamble2 == 15) .@item = 2509; // Survivor's Manteau
+			else if (.@gamble2 == 16) .@item = 2515; // Eagle Wing[1]
+		}
+		else if (.@gamble1 < 101) .@item = 2503; // Muffler
+		else if (.@gamble1 < 201) .@item = 2505; // Manteau
+		else if (.@gamble1 < 451) .@item = 2501; // Hood
+		else if (.@gamble1 < 501) .@item = 2502; // Hood[1]
+		break;
 
 
 	case 4: // Headgears
 	case 4: // Headgears
-			.@gamble1 = rand(1,1000);
-			if ((.@gamble1 > 299) && (.@gamble1 < 304)) {
-				.@gamble2 = rand(1,93);
-				if      ((.@gamble2 >  0) && (.@gamble2 <  3)) .@item = 2251; // Monk Hat
-				else if ((.@gamble2 >  2) && (.@gamble2 <  5)) .@item = 2285; // Apple of Archer
-				else if ((.@gamble2 >  4) && (.@gamble2 <  7)) .@item = 2255; // Evil Wing
-				else if ((.@gamble2 >  6) && (.@gamble2 <  9)) .@item = 5045; // Magician Hat
-				else if ((.@gamble2 >  8) && (.@gamble2 < 11)) .@item = 2233; // Circlet[1]
-				else if ((.@gamble2 > 10) && (.@gamble2 < 13)) .@item = 2231; // Gemmed Sallet[1]
-				else if ((.@gamble2 > 12) && (.@gamble2 < 15)) .@item = 2217; // Biretta[1]
-				else if ((.@gamble2 > 14) && (.@gamble2 < 17)) .@item = 2206; // Wedding Veil
-				else if ((.@gamble2 > 16) && (.@gamble2 < 19)) .@item = 2246; // Golden Gear
-				else if ((.@gamble2 > 18) && (.@gamble2 < 21)) .@item = 2261; // Army Cap
-				else if ((.@gamble2 > 20) && (.@gamble2 < 23)) .@item = 2287; // Pirate Bandana
-				else if ((.@gamble2 > 22) && (.@gamble2 < 25)) .@item = 5012; // Ph.D Hat
-				else if ((.@gamble2 > 24) && (.@gamble2 < 27)) .@item = 2244; // Big Ribbon
-				else if ((.@gamble2 > 26) && (.@gamble2 < 29)) .@item = 2213; // Kitty Band
-				else if ((.@gamble2 > 28) && (.@gamble2 < 31)) .@item = 2248; // Western Grace
-				else if ((.@gamble2 > 30) && (.@gamble2 < 33)) .@item = 2223; // Turban[1]
-				else if ((.@gamble2 > 32) && (.@gamble2 < 35)) .@item = 2247; // Romantic Gent
-				else if ((.@gamble2 > 34) && (.@gamble2 < 37)) .@item = 2245; // Sweet Gent
-				else if ((.@gamble2 > 36) && (.@gamble2 < 39)) .@item = 5003; // Joker Jester
-				else if ((.@gamble2 > 38) && (.@gamble2 < 41)) .@item = 2225; // Goggles[1]
-				else if ((.@gamble2 > 40) && (.@gamble2 < 43)) .@item = 5017; // Bone Helm
-				else if ((.@gamble2 > 42) && (.@gamble2 < 45)) .@item = 5030; // Panda Hat
-				else if ((.@gamble2 > 44) && (.@gamble2 < 47)) .@item = 5035; // Poring Hat
-				else if ((.@gamble2 > 46) && (.@gamble2 < 49)) .@item = 2250; // Cute Ribbon
-				else if ((.@gamble2 > 48) && (.@gamble2 < 51)) .@item = 2277; // Nurse Cap
-				else if ((.@gamble2 > 50) && (.@gamble2 < 53)) .@item = 5011; // Aerial
-				else if ((.@gamble2 > 52) && (.@gamble2 < 55)) .@item = 2290; // Funeral Hat
-				else if ((.@gamble2 > 54) && (.@gamble2 < 57)) .@item = 5010; // Indian Fillet
-				else if ((.@gamble2 > 56) && (.@gamble2 < 60)) .@item = 2259; // Mini Propeller
-				else if ((.@gamble2 > 59) && (.@gamble2 < 62)) .@item = 5008; // Puppy Love
-				else if ((.@gamble2 > 61) && (.@gamble2 < 63)) .@item = 2249; // Coronet
-				else if ((.@gamble2 > 62) && (.@gamble2 < 65)) .@item = 2229; // Helm[1]
-				else if (.@gamble2 == 65) .@item = 2258; // Spiky Band
-				else if (.@gamble2 == 66) .@item = 2274; // Ghost Bandana
-				else if (.@gamble2 == 67) .@item = 5019; // Corsair
-				else if (.@gamble2 == 68) .@item = 2254; // Angel Wing
-				else if (.@gamble2 == 69) .@item = 5007; // Grand Circlet
-				else if (.@gamble2 == 70) .@item = 5066; // Succubus Horn
-				else if (.@gamble2 == 71) .@item = 2235; // Crown
-				else if (.@gamble2 == 72) .@item = 2234; // Tiara
-				else if (.@gamble2 == 73) .@item = 2256; // Majestic Goat
-				else if (.@gamble2 == 74) .@item = 5093; // Coif[1]
-				else if (.@gamble2 == 75) .@item = 5072; // Incubus Horn
-				else if (.@gamble2 == 76) .@item = 5002; // Jewel Crown
-				else if (.@gamble2 > 76 && .@gamble2 < 80) .@item = 5118; // Puppy Headband
-				else if (.@gamble2 > 79 && .@gamble2 < 83) .@item = 5120; // Bucket Hat[1]
-				else if (.@gamble2 > 82 && .@gamble2 < 86) .@item = 5111; // Galapago Cap
-				else if (.@gamble2 > 85 && .@gamble2 < 89) .@item = 5116; // Banana Hat
-				else if (.@gamble2 > 88 && .@gamble2 < 92) .@item = 5119; // Super Novice Hat[1]
-				else if (.@gamble2 > 91 && .@gamble2 < 94) .@item = 5141; // Marionetta Doll[1]
-			}
-			else if ((.@gamble1 >   0) && (.@gamble1 <  101)) .@item = 2226; // Cap
-			else if ((.@gamble1 > 100) && (.@gamble1 <  201)) .@item = 2211; // Bandana
-			else if ((.@gamble1 > 200) && (.@gamble1 <  300)) .@item = 2209; // Ribbon[1]
-			else if ((.@gamble1 > 303) && (.@gamble1 <  401)) .@item = 2220; // Hat
-			else if ((.@gamble1 > 400) && (.@gamble1 <  501)) .@item = 2232; // Circlet
-			else if ((.@gamble1 > 500) && (.@gamble1 <  601)) .@item = 2216; // Biretta
-			else if ((.@gamble1 > 600) && (.@gamble1 <  701)) .@item = 2230; // Gemmed Sallet
-			else if ((.@gamble1 > 700) && (.@gamble1 <  801)) .@item = 2224; // Goggles
-			else if ((.@gamble1 > 800) && (.@gamble1 <  901)) .@item = 2222; // Turban
-			else if ((.@gamble1 > 900) && (.@gamble1 <  906)) .@item = 2228; // Helm
-			else if ((.@gamble1 > 905) && (.@gamble1 <  911)) .@item = 2252; // Wizard Hat
-			else if ((.@gamble1 > 910) && (.@gamble1 <  916)) .@item = 2227; // Cap[1]
-			else if ((.@gamble1 > 915) && (.@gamble1 <  921)) .@item = 2221; // Hat[1]
-			else if ((.@gamble1 > 920) && (.@gamble1 <  926)) .@item = 2299; // Orc Helm
-			else if ((.@gamble1 > 925) && (.@gamble1 <  931)) .@item = 2236; // Santa Hat
-			else if ((.@gamble1 > 930) && (.@gamble1 <  936)) .@item = 2275; // Red Bandana
-			else if ((.@gamble1 > 935) && (.@gamble1 <  941)) .@item = 5015; // Egg Shell
-			else if ((.@gamble1 > 940) && (.@gamble1 <  946)) .@item = 2215; // Flower Band
-			else if ((.@gamble1 > 945) && (.@gamble1 <  951)) .@item = 5092; // Coif
-			else if ((.@gamble1 > 950) && (.@gamble1 < 1001)) .@item = 2226; // Cap
-	break;
+		.@gamble1 = rand(1,1000);
+		if (.@gamble1 > 299 && .@gamble1 < 304) {
+			.@gamble2 = rand(1,93);
+			if      (.@gamble2 <  3) .@item = 2251; // Monk Hat
+			else if (.@gamble2 <  5) .@item = 2285; // Apple of Archer
+			else if (.@gamble2 <  7) .@item = 2255; // Evil Wing
+			else if (.@gamble2 <  9) .@item = 5045; // Magician Hat
+			else if (.@gamble2 < 11) .@item = 2233; // Circlet[1]
+			else if (.@gamble2 < 13) .@item = 2231; // Gemmed Sallet[1]
+			else if (.@gamble2 < 15) .@item = 2217; // Biretta[1]
+			else if (.@gamble2 < 17) .@item = 2206; // Wedding Veil
+			else if (.@gamble2 < 19) .@item = 2246; // Golden Gear
+			else if (.@gamble2 < 21) .@item = 2261; // Army Cap
+			else if (.@gamble2 < 23) .@item = 2287; // Pirate Bandana
+			else if (.@gamble2 < 25) .@item = 5012; // Ph.D Hat
+			else if (.@gamble2 < 27) .@item = 2244; // Big Ribbon
+			else if (.@gamble2 < 29) .@item = 2213; // Kitty Band
+			else if (.@gamble2 < 31) .@item = 2248; // Western Grace
+			else if (.@gamble2 < 33) .@item = 2223; // Turban[1]
+			else if (.@gamble2 < 35) .@item = 2247; // Romantic Gent
+			else if (.@gamble2 < 37) .@item = 2245; // Sweet Gent
+			else if (.@gamble2 < 39) .@item = 5003; // Joker Jester
+			else if (.@gamble2 < 41) .@item = 2225; // Goggles[1]
+			else if (.@gamble2 < 43) .@item = 5017; // Bone Helm
+			else if (.@gamble2 < 45) .@item = 5030; // Panda Hat
+			else if (.@gamble2 < 47) .@item = 5035; // Poring Hat
+			else if (.@gamble2 < 49) .@item = 2250; // Cute Ribbon
+			else if (.@gamble2 < 51) .@item = 2277; // Nurse Cap
+			else if (.@gamble2 < 53) .@item = 5011; // Aerial
+			else if (.@gamble2 < 55) .@item = 2290; // Funeral Hat
+			else if (.@gamble2 < 57) .@item = 5010; // Indian Fillet
+			else if (.@gamble2 < 60) .@item = 2259; // Mini Propeller
+			else if (.@gamble2 < 62) .@item = 5008; // Puppy Love
+			else if (.@gamble2 < 63) .@item = 2249; // Coronet
+			else if (.@gamble2 < 65) .@item = 2229; // Helm[1]
+			else if (.@gamble2 == 65) .@item = 2258; // Spiky Band
+			else if (.@gamble2 == 66) .@item = 2274; // Ghost Bandana
+			else if (.@gamble2 == 67) .@item = 5019; // Corsair
+			else if (.@gamble2 == 68) .@item = 2254; // Angel Wing
+			else if (.@gamble2 == 69) .@item = 5007; // Grand Circlet
+			else if (.@gamble2 == 70) .@item = 5066; // Succubus Horn
+			else if (.@gamble2 == 71) .@item = 2235; // Crown
+			else if (.@gamble2 == 72) .@item = 2234; // Tiara
+			else if (.@gamble2 == 73) .@item = 2256; // Majestic Goat
+			else if (.@gamble2 == 74) .@item = 5093; // Coif[1]
+			else if (.@gamble2 == 75) .@item = 5072; // Incubus Horn
+			else if (.@gamble2 == 76) .@item = 5002; // Jewel Crown
+			else if (.@gamble2 < 80) .@item = 5118; // Puppy Headband
+			else if (.@gamble2 < 83) .@item = 5120; // Bucket Hat[1]
+			else if (.@gamble2 < 86) .@item = 5111; // Galapago Cap
+			else if (.@gamble2 < 89) .@item = 5116; // Banana Hat
+			else if (.@gamble2 < 92) .@item = 5119; // Super Novice Hat[1]
+			else if (.@gamble2 < 94) .@item = 5141; // Marionetta Doll[1]
+		}
+		else if (.@gamble1 <  101) .@item = 2226; // Cap
+		else if (.@gamble1 <  201) .@item = 2211; // Bandana
+		else if (.@gamble1 <  300) .@item = 2209; // Ribbon[1]
+		else if (.@gamble1 <  401) .@item = 2220; // Hat
+		else if (.@gamble1 <  501) .@item = 2232; // Circlet
+		else if (.@gamble1 <  601) .@item = 2216; // Biretta
+		else if (.@gamble1 <  701) .@item = 2230; // Gemmed Sallet
+		else if (.@gamble1 <  801) .@item = 2224; // Goggles
+		else if (.@gamble1 <  901) .@item = 2222; // Turban
+		else if (.@gamble1 <  906) .@item = 2228; // Helm
+		else if (.@gamble1 <  911) .@item = 2252; // Wizard Hat
+		else if (.@gamble1 <  916) .@item = 2227; // Cap[1]
+		else if (.@gamble1 <  921) .@item = 2221; // Hat[1]
+		else if (.@gamble1 <  926) .@item = 2299; // Orc Helm
+		else if (.@gamble1 <  931) .@item = 2236; // Santa Hat
+		else if (.@gamble1 <  936) .@item = 2275; // Red Bandana
+		else if (.@gamble1 <  941) .@item = 5015; // Egg Shell
+		else if (.@gamble1 <  946) .@item = 2215; // Flower Band
+		else if (.@gamble1 <  951) .@item = 5092; // Coif
+		else if (.@gamble1 < 1001) .@item = 2226; // Cap
+		break;
 	case 5: // Footgear
 	case 5: // Footgear
-			.@gamble1 = rand(1,500);
-			if ((.@gamble1 > 299) && (.@gamble1 < 303)) {
-				.@gamble2 = rand(1,10);
-				if      ((.@gamble2 > 0) && (.@gamble2 <  3)) .@item = 2406; // Boots[1]
-				else if ((.@gamble2 > 2) && (.@gamble2 <  5)) .@item = 2412; // Greaves[1]
-				else if ((.@gamble2 > 4) && (.@gamble2 <  8)) .@item = 2404; // Shoes[1]
-				else if ((.@gamble2 > 7) && (.@gamble2 < 11)) .@item = 2407; // Crystal Pumps
-			}
-			else if ((.@gamble1 >   0) && (.@gamble1 < 201)) .@item = 2401; // Sandals
-			else if ((.@gamble1 > 200) && (.@gamble1 < 300)) .@item = 2408; // Shackles
-			else if ((.@gamble1 > 302) && (.@gamble1 < 351)) .@item = 2411; // Greaves
-			else if ((.@gamble1 > 350) && (.@gamble1 < 401)) .@item = 2403; // Shoes
-			else if ((.@gamble1 > 400) && (.@gamble1 < 451)) .@item = 2405; // Boots
-			else if ((.@gamble1 > 450) && (.@gamble1 < 476)) .@item = 2409; // High Heels
-			else if ((.@gamble1 > 475) && (.@gamble1 < 501)) .@item = 2402; // Sandals[1]
-	break;
+		.@gamble1 = rand(1,500);
+		if (.@gamble1 > 299 && .@gamble1 < 303) {
+			.@gamble2 = rand(1,10);
+			if      (.@gamble2 <  3) .@item = 2406; // Boots[1]
+			else if (.@gamble2 <  5) .@item = 2412; // Greaves[1]
+			else if (.@gamble2 <  8) .@item = 2404; // Shoes[1]
+			else if (.@gamble2 < 11) .@item = 2407; // Crystal Pumps
+		}
+		else if (.@gamble1 < 201) .@item = 2401; // Sandals
+		else if (.@gamble1 < 300) .@item = 2408; // Shackles
+		else if (.@gamble1 < 351) .@item = 2411; // Greaves
+		else if (.@gamble1 < 401) .@item = 2403; // Shoes
+		else if (.@gamble1 < 451) .@item = 2405; // Boots
+		else if (.@gamble1 < 476) .@item = 2409; // High Heels
+		else if (.@gamble1 < 501) .@item = 2402; // Sandals[1]
+		break;
 
 
 	case 6: // Shields
 	case 6: // Shields
-			.@gamble1 = rand(1,500);
-			if ((.@gamble1 > 200) && (.@gamble1 < 205)) {
-				.@gamble2 = rand(1,10);
-				if      ((.@gamble2 > 0) && (.@gamble2 <  3)) .@item = 2104; // Buckler[1]
-				else if ((.@gamble2 > 2) && (.@gamble2 <  5)) .@item = 2106; // Shield[1]
-				else if ((.@gamble2 > 4) && (.@gamble2 <  7)) .@item = 2102; // Guard[1]
-				else if ((.@gamble2 > 6) && (.@gamble2 <  9)) .@item = 2111; // Sacred Mission
-				else if ((.@gamble2 > 8) && (.@gamble2 < 11)) .@item = 2109; // Memory Book
-			}
-			else if ((.@gamble1 >   0) && (.@gamble1 < 201)) .@item = 2101; // Guard
-			else if ((.@gamble1 > 204) && (.@gamble1 < 301)) .@item = 2103; // Buckler
-			else if ((.@gamble1 > 300) && (.@gamble1 < 401)) .@item = 2107; // Mirror Shield
-			else if ((.@gamble1 > 401) && (.@gamble1 < 481)) .@item = 2105; // Shield
-			else if ((.@gamble1 > 480) && (.@gamble1 < 501)) .@item = 2108; // Mirror Shield[1]
-	break;
+		.@gamble1 = rand(1,500);
+		if (.@gamble1 > 200 && .@gamble1 < 205) {
+			.@gamble2 = rand(1,10);
+			if      (.@gamble2 <  3) .@item = 2104; // Buckler[1]
+			else if (.@gamble2 <  5) .@item = 2106; // Shield[1]
+			else if (.@gamble2 <  7) .@item = 2102; // Guard[1]
+			else if (.@gamble2 <  9) .@item = 2111; // Sacred Mission
+			else if (.@gamble2 < 11) .@item = 2109; // Memory Book
+		}
+		else if (.@gamble1 < 201) .@item = 2101; // Guard
+		else if (.@gamble1 < 301) .@item = 2103; // Buckler
+		else if (.@gamble1 < 401) .@item = 2107; // Mirror Shield
+		else if (.@gamble1 < 481) .@item = 2105; // Shield
+		else if (.@gamble1 < 501) .@item = 2108; // Mirror Shield[1]
+		break;
 	default: // Cancel button / hack
 	default: // Cancel button / hack
-			cutin "katsua01.bmp",255;
-			close;
-	break;
+		cutin "katsua01.bmp",255;
+		close;
+		break;
 	}
 	}
 	getitem .@item,1;
 	getitem .@item,1;
 	cutin "katsua01.bmp",255;
 	cutin "katsua01.bmp",255;

+ 117 - 137
npc/quests/first_class/tu_acolyte.txt

@@ -1,15 +1,15 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= Acolyte Class Tutorial and Job Specific Quest
 //= Acolyte Class Tutorial and Job Specific Quest
-//===== By: ================================================== 
+//===== By: ==================================================
 //= Fix up by Jukka
 //= Fix up by Jukka
-//===== Current Version: ===================================== 
-//= 1.9
-//===== Compatible With: ===================================== 
+//===== Current Version: =====================================
+//= 2.0
+//===== Compatible With: =====================================
 //= rAthena Project
 //= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= [Official Conversion]
 //= Acolyte training quest.
 //= Acolyte training quest.
-//===== Additional Comments: ================================= 
+//===== Additional Comments: =================================
 //= 1.0 Fully working
 //= 1.0 Fully working
 //= 1.1 optimized [Lupus]
 //= 1.1 optimized [Lupus]
 //= 1.2 Fixed experience gains to match upcoming rate adjustments. [SinSloth]
 //= 1.2 Fixed experience gains to match upcoming rate adjustments. [SinSloth]
@@ -21,11 +21,12 @@
 //= 1.7 Fixed exp, texts, and requirements in pre-renewal [Daegaladh]
 //= 1.7 Fixed exp, texts, and requirements in pre-renewal [Daegaladh]
 //= 1.8 Updated to match the official script. [Euphy]
 //= 1.8 Updated to match the official script. [Euphy]
 //= 1.9 Added GM management function. [Euphy]
 //= 1.9 Added GM management function. [Euphy]
-//============================================================ 
+//= 2.0 Clean-up and little fix in Cleope Verce. [Capuche]
+//============================================================
 
 
 // Priest Praupin
 // Priest Praupin
 //============================================================
 //============================================================
-prt_church,179,15,1	script	Priest Praupin	110,{
+prt_church,179,15,1	script	Priest Praupin	4_M_MINISTER,{
 	mes "[Priest Praupin]";
 	mes "[Priest Praupin]";
 	if(BaseJob != Job_Acolyte){
 	if(BaseJob != Job_Acolyte){
 		if(tu_acolyte01 == 25){
 		if(tu_acolyte01 == 25){
@@ -65,7 +66,7 @@ prt_church,179,15,1	script	Priest Praupin	110,{
 			mes "[Priest Praupin]";
 			mes "[Priest Praupin]";
 			mes "I look forward to seeing you";
 			mes "I look forward to seeing you";
 			mes "become a better Acolyte after learning from Sister Asthe's instructions. If you like, I can send you to the convent.";
 			mes "become a better Acolyte after learning from Sister Asthe's instructions. If you like, I can send you to the convent.";
-			set tu_acolyte01, 1;
+			tu_acolyte01 = 1;
 			next;
 			next;
 			if(select("Go to the convent.:Do not go.")==1){
 			if(select("Go to the convent.:Do not go.")==1){
 				mes "[Priest Praupin]";
 				mes "[Priest Praupin]";
@@ -94,7 +95,7 @@ prt_church,179,15,1	script	Priest Praupin	110,{
 		mes "Ah, he's away at the convent right now. If you want to meet Bishop Maugins in the Saint Capitolina Convent, travel ^3131FFnorth^000000, ^3131FFeast^000000, ^3131FFeast^000000 and then ^3131FFeast^000000 from Prontera.";
 		mes "Ah, he's away at the convent right now. If you want to meet Bishop Maugins in the Saint Capitolina Convent, travel ^3131FFnorth^000000, ^3131FFeast^000000, ^3131FFeast^000000 and then ^3131FFeast^000000 from Prontera.";
 		close;
 		close;
 	case 22:
 	case 22:
-		if(countitem(7181) > 0){	// Receipt_01
+		if(countitem(7181) > 0){// Receipt_01
 			emotion e_gasp;
 			emotion e_gasp;
 			mes "Oh my, you seem";
 			mes "Oh my, you seem";
 			mes "to be growing quickly";
 			mes "to be growing quickly";
@@ -119,25 +120,18 @@ prt_church,179,15,1	script	Priest Praupin	110,{
 			mes "I know I'm not offering much,";
 			mes "I know I'm not offering much,";
 			mes "but they were quite helpful to me when I was a young Acolyte like yourself.";
 			mes "but they were quite helpful to me when I was a young Acolyte like yourself.";
 			next;
 			next;
-			switch(select("Wand:Flail")) {
-			case 1:
-				delitem 7181,1; //Receipt_01
-				set tu_acolyte01,23;
+			if (select("Wand:Flail") == 1)
 				getitem 1604,1; //Wand
 				getitem 1604,1; //Wand
-				break;
-			case 2:
-				delitem 7181,1; //Receipt_01
-				set tu_acolyte01,23;
+			else
 				getitem 1510,1; //Flail
 				getitem 1510,1; //Flail
-				break;
-			}
+			delitem 7181,1; //Receipt_01
+			tu_acolyte01 = 23;
 			close;
 			close;
 		} else {
 		} else {
 			mes "You are such a good person,";
 			mes "You are such a good person,";
 			mes "a true child of the light. I hope that many others will benefit from the purity of your heart and mind.";
 			mes "a true child of the light. I hope that many others will benefit from the purity of your heart and mind.";
 			close;
 			close;
 		}
 		}
-		break;
 	case 25:
 	case 25:
 		mes "You must now find";
 		mes "You must now find";
 		mes "your own path and become";
 		mes "your own path and become";
@@ -176,7 +170,7 @@ prt_church,179,15,1	script	Priest Praupin	110,{
 
 
 // Asthe
 // Asthe
 //============================================================
 //============================================================
-prt_monk,230,106,3	script	Asthe#tu	79,{
+prt_monk,230,106,3	script	Asthe#tu	1_F_PRIEST,{
 	mes "[Asthe]";
 	mes "[Asthe]";
 	switch(tu_acolyte01){
 	switch(tu_acolyte01){
 	case 1:
 	case 1:
@@ -189,8 +183,8 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		if(select("I came for fun.:Priest Praupin suggested I come here.")==1){
 		if(select("I came for fun.:Priest Praupin suggested I come here.")==1){
 			mes "[Asthe]";
 			mes "[Asthe]";
 			mes "This convent is always quiet and peaceful. Sitting on the benches and feeling the almighty presense all around you is such a relaxing, meditative experience.";
 			mes "This convent is always quiet and peaceful. Sitting on the benches and feeling the almighty presense all around you is such a relaxing, meditative experience.";
-			close;
-		} else {
+		}
+		else {
 			mes "[Asthe]";
 			mes "[Asthe]";
 			mes "Priest Praupin?";
 			mes "Priest Praupin?";
 			mes "He's a very kind man";
 			mes "He's a very kind man";
@@ -203,10 +197,9 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 			mes "why don't you rest";
 			mes "why don't you rest";
 			mes "for a little bit? You must be tired after traveling all the way here. When you're ready, just come";
 			mes "for a little bit? You must be tired after traveling all the way here. When you're ready, just come";
 			mes "see me, okay?";
 			mes "see me, okay?";
-			set tu_acolyte01, 2;
-			close;
+			tu_acolyte01 = 2;
 		}
 		}
-		break;
+		close;
 	case 2:
 	case 2:
 		mes "This castle, Saint Capitolina Convent, is a beautiful and peaceful place that brings";
 		mes "This castle, Saint Capitolina Convent, is a beautiful and peaceful place that brings";
 		mes "calm to any heart.";
 		mes "calm to any heart.";
@@ -249,13 +242,12 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "is the most necessary";
 		mes "is the most necessary";
 		mes "skill for an Acolyte?";
 		mes "skill for an Acolyte?";
 		next;
 		next;
-		switch(select("Heal:Aqua Benedicta:Teleport")){ 
+		switch(select("Heal:Aqua Benedicta:Teleport")){
 		case 1:
 		case 1:
 			mes "[Asthe]";
 			mes "[Asthe]";
 			mes "Ah, yes.";
 			mes "Ah, yes.";
 			mes "^3131FFHeal ^000000 is a basic, yet important skill for people like us. It can recover your own health as";
 			mes "^3131FFHeal ^000000 is a basic, yet important skill for people like us. It can recover your own health as";
 			mes "well as that of others.";
 			mes "well as that of others.";
-			next;
 			break;
 			break;
 		case 2:
 		case 2:
 			mes "[Asthe]";
 			mes "[Asthe]";
@@ -268,7 +260,6 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 			mes "^3131FFHeal^000000 is the most important";
 			mes "^3131FFHeal^000000 is the most important";
 			mes "skill that an Acolyte can learn. It's a special ability that can save others and defeat the";
 			mes "skill that an Acolyte can learn. It's a special ability that can save others and defeat the";
 			mes "monsters borne of darkness.";
 			mes "monsters borne of darkness.";
-			next;
 			break;
 			break;
 		case 3:
 		case 3:
 			mes "[Asthe]";
 			mes "[Asthe]";
@@ -278,10 +269,9 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 			mes "In my opinion,";
 			mes "In my opinion,";
 			mes "^3131FFHeal^000000 is the most important skill that an Acolyte can learn. It's a special ability that can save others and defeat the";
 			mes "^3131FFHeal^000000 is the most important skill that an Acolyte can learn. It's a special ability that can save others and defeat the";
 			mes "monsters borne of darkness.";
 			mes "monsters borne of darkness.";
-			next;
 			break;
 			break;
 		}
 		}
-
+		next;
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "You can use the holy power";
 		mes "You can use the holy power";
 		mes "in the Heal skill to attack Undead monsters (^3131FFShift + Heal^000000). The light of truth protects the righteous and destroys the wicked.";
 		mes "in the Heal skill to attack Undead monsters (^3131FFShift + Heal^000000). The light of truth protects the righteous and destroys the wicked.";
@@ -294,7 +284,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "HEAL !!";
 		mes "HEAL !!";
 		npcskill "AL_HEAL",11,99,60;
 		npcskill "AL_HEAL",11,99,60;
-		set tu_acolyte01, 3;
+		tu_acolyte01 = 3;
 		if(getskilllv("AL_HEAL") == 0){
 		if(getskilllv("AL_HEAL") == 0){
 			getexp 0,100;
 			getexp 0,100;
 			specialeffect2 EF_CONE;
 			specialeffect2 EF_CONE;
@@ -332,12 +322,12 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 			mes "Well then,";
 			mes "Well then,";
 			mes "I hope you";
 			mes "I hope you";
 			mes "have a safe trip.";
 			mes "have a safe trip.";
-			set tu_acolyte01,4;
+			tu_acolyte01 = 4;
 			getitem 1504,1; //Mace
 			getitem 1504,1; //Mace
 			getitem 602,1; //Wing_Of_Butterfly
 			getitem 602,1; //Wing_Of_Butterfly
 			savepoint "prt_monk",30,250;
 			savepoint "prt_monk",30,250;
-			close;
-		} else {
+		}
+		else {
 			mes "[Asthe]";
 			mes "[Asthe]";
 			mes "Oh my!";
 			mes "Oh my!";
 			mes "You've already";
 			mes "You've already";
@@ -350,13 +340,12 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 			mes "ready for me to discuss";
 			mes "ready for me to discuss";
 			mes "the next subject. Now,";
 			mes "the next subject. Now,";
 			mes "let's see... Hmm...";
 			mes "let's see... Hmm...";
-			set tu_acolyte01, 5;
-			close;
+			tu_acolyte01 = 5;
 		}
 		}
-		break;
+		close;
 	case 4:
 	case 4:
 		if(getskilllv("AL_HEAL") > 2){
 		if(getskilllv("AL_HEAL") > 2){
-			if(countitem(1504) > 0){
+			if(countitem(1504) > 0){// Mace
 				mes "Oh my!";
 				mes "Oh my!";
 				mes "Welcome back~";
 				mes "Welcome back~";
 				mes "I see that you've";
 				mes "I see that you've";
@@ -382,18 +371,15 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 				mes "Thank you so much.";
 				mes "Thank you so much.";
 				mes "You have returned the Mace.";
 				mes "You have returned the Mace.";
 				emotion e_heh;
 				emotion e_heh;
-				set tu_acolyte01, 5;
-				delitem 1504, 1; //Mace
-				if(Class == Job_Acolyte_High) {
+				tu_acolyte01 = 5;
+				delitem 1504,1; //Mace
+				if(Class == Job_Acolyte_High)
 					getexp 2000,1000;
 					getexp 2000,1000;
-					specialeffect2 EF_CONE;
-					close;
-				} else {
+				else
 					getexp 1000,500;
 					getexp 1000,500;
-					specialeffect2 EF_CONE;
-					close;
-				}
-			} else {
+				specialeffect2 EF_CONE;
+			}
+			else {
 				mes "Oh my!";
 				mes "Oh my!";
 				mes "Welcome back~";
 				mes "Welcome back~";
 				mes "I see that you've";
 				mes "I see that you've";
@@ -401,8 +387,8 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 				next;
 				next;
 				mes "[Asthe]";
 				mes "[Asthe]";
 				mes "But you must have forgotten the Mace I've lent you. Would you bring it back so that I can return it to the church?";
 				mes "But you must have forgotten the Mace I've lent you. Would you bring it back so that I can return it to the church?";
-				close;  
 			}
 			}
+			close;
 		}
 		}
 		mes "Are you having";
 		mes "Are you having";
 		mes "a hard time training";
 		mes "a hard time training";
@@ -435,7 +421,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "Did you undertand all that?";
 		mes "Did you undertand all that?";
 		mes "Ho ho ho~ No need to try to remember everything right now. You'll get the hang of it.";
 		mes "Ho ho ho~ No need to try to remember everything right now. You'll get the hang of it.";
-		set tu_acolyte01, 6;
+		tu_acolyte01 = 6;
 		close;
 		close;
 	case 6:
 	case 6:
 		mes ""+strcharinfo(0)+",";
 		mes ""+strcharinfo(0)+",";
@@ -446,7 +432,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "However, I'm a little busy with";
 		mes "However, I'm a little busy with";
 		mes "my work right now, so would you deliver this to Priest Gardron in the next building for me?";
 		mes "my work right now, so would you deliver this to Priest Gardron in the next building for me?";
-		set tu_acolyte01,7;
+		tu_acolyte01 = 7;
 		getitem 7148,1; //Mother_Letter
 		getitem 7148,1; //Mother_Letter
 		close;
 		close;
 	case 7:
 	case 7:
@@ -494,7 +480,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		next;
 		next;
 		mes "^3355FFSister Asthe gives";
 		mes "^3355FFSister Asthe gives";
 		mes "you some dog food.^000000";
 		mes "you some dog food.^000000";
-		set tu_acolyte01, 10;
+		tu_acolyte01 = 10;
 		close;
 		close;
 	case 11:
 	case 11:
 	case 12:
 	case 12:
@@ -515,7 +501,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "know the answer.";
 		mes "know the answer.";
 		mes "Think carefully";
 		mes "Think carefully";
 		mes "and it will come.";
 		mes "and it will come.";
-		set tu_acolyte01, 12;
+		tu_acolyte01 = 12;
 		close;
 		close;
 	case 13:
 	case 13:
 		mes "You remember that";
 		mes "You remember that";
@@ -544,7 +530,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "Let's take a break before";
 		mes "Let's take a break before";
 		mes "we proceed to the next lesson,";
 		mes "we proceed to the next lesson,";
 		mes "alright? I'll be right here.";
 		mes "alright? I'll be right here.";
-		set tu_acolyte01, 14;
+		tu_acolyte01 = 14;
 		close;
 		close;
 	case 14:
 	case 14:
 		mes "Now it's time";
 		mes "Now it's time";
@@ -566,7 +552,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "Try it for";
 		mes "Try it for";
 		mes "yourself, okay?";
 		mes "yourself, okay?";
-		set tu_acolyte01, 15;
+		tu_acolyte01 = 15;
 		npcskill "AL_INCAGI",10,0,0;
 		npcskill "AL_INCAGI",10,0,0;
 		close;
 		close;
 	case 15:
 	case 15:
@@ -577,7 +563,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		next;
 		next;
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "Like you'd expect, Decrease AGI slows down enemies, reducing their agility, Movement Speed, Dodge Rate and Attack Speed. Its effect is the exact reverse of Increase AGI.";
 		mes "Like you'd expect, Decrease AGI slows down enemies, reducing their agility, Movement Speed, Dodge Rate and Attack Speed. Its effect is the exact reverse of Increase AGI.";
-		set tu_acolyte01, 15;
+		tu_acolyte01 = 15;
 		next;
 		next;
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "The last skill in the Heal skill tree is ^3131FFCure^000000. You can learn Cure after learning Level 2 Heal.";
 		mes "The last skill in the Heal skill tree is ^3131FFCure^000000. You can learn Cure after learning Level 2 Heal.";
@@ -593,7 +579,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "For now, don't forget that the Increase AGI, Decrease AGI and";
 		mes "For now, don't forget that the Increase AGI, Decrease AGI and";
 		mes "Cure skills can only be learned";
 		mes "Cure skills can only be learned";
 		mes "by learning the Heal skill.";
 		mes "by learning the Heal skill.";
-		set tu_acolyte01, 16;
+		tu_acolyte01 = 16;
 		close;
 		close;
 	case 16:
 	case 16:
 		mes "You've been learning";
 		mes "You've been learning";
@@ -660,7 +646,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 			mes "[Asthe]";
 			mes "[Asthe]";
 			mes "Ho ho!";
 			mes "Ho ho!";
 			mes "What a smart Acolyte~";
 			mes "What a smart Acolyte~";
-			set tu_acolyte01, 17;
+			tu_acolyte01 = 17;
 		}
 		}
 		close;
 		close;
 	case 17:
 	case 17:
@@ -693,7 +679,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 			mes "to carry everything.";
 			mes "to carry everything.";
 			mes "Why don't you put some of your things in Kafra Storage first?";
 			mes "Why don't you put some of your things in Kafra Storage first?";
 		} else {
 		} else {
-			set tu_acolyte01, 18;
+			tu_acolyte01 = 18;
 			getitem 7183,1; //Sister_Letter
 			getitem 7183,1; //Sister_Letter
 			getitem 7181,1; //Receipt_01
 			getitem 7181,1; //Receipt_01
 			getitem 1081,2; //Merchant_Box_1
 			getitem 1081,2; //Merchant_Box_1
@@ -743,7 +729,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		mes "the next time we";
 		mes "the next time we";
 		mes "meet, I will give";
 		mes "meet, I will give";
 		mes "you my final lesson.";
 		mes "you my final lesson.";
-		set tu_acolyte01, 24;
+		tu_acolyte01 = 24;
 		close;
 		close;
 	case 24:
 	case 24:
 		mes "The last skill";
 		mes "The last skill";
@@ -777,7 +763,7 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 		next;
 		next;
 		mes "[Asthe]";
 		mes "[Asthe]";
 		mes "Well, please don't forget what I've taught you. I hope you look back with fondness at our time together amongst these beautiful flowers. May God bless you~";
 		mes "Well, please don't forget what I've taught you. I hope you look back with fondness at our time together amongst these beautiful flowers. May God bless you~";
-		set tu_acolyte01, 25;
+		tu_acolyte01 = 25;
 		if (checkre(3))
 		if (checkre(3))
 			getexp 1000,1000;
 			getexp 1000,1000;
 		else
 		else
@@ -802,10 +788,10 @@ prt_monk,230,106,3	script	Asthe#tu	79,{
 
 
 // Priest Gardron
 // Priest Gardron
 //============================================================
 //============================================================
-monk_in,18,38,6	script	Priest Gardron#tu	110,{
+monk_in,18,38,6	script	Priest Gardron#tu	4_M_MINISTER,{
 	mes "[Priest Gardron]";
 	mes "[Priest Gardron]";
 	if(tu_acolyte01 == 7){
 	if(tu_acolyte01 == 7){
-		if(countitem(7148) >= 1){
+		if(countitem(7148) >= 1){// Mother_Letter
 			mes "Hmm...?";
 			mes "Hmm...?";
 			mes "What's that?";
 			mes "What's that?";
 			mes "You have something for me?";
 			mes "You have something for me?";
@@ -820,8 +806,7 @@ monk_in,18,38,6	script	Priest Gardron#tu	110,{
 			mes "she is getting old now, but I'm relieved to hear that her health";
 			mes "she is getting old now, but I'm relieved to hear that her health";
 			mes "is good. We are truly blessed...";
 			mes "is good. We are truly blessed...";
 			delitem 7148,1; //Mother_Letter
 			delitem 7148,1; //Mother_Letter
-			set tu_acolyte01,8;
-			close;
+			tu_acolyte01 = 8;
 		} else {
 		} else {
 			mes "Hmm...?";
 			mes "Hmm...?";
 			mes "What's that?";
 			mes "What's that?";
@@ -832,10 +817,10 @@ monk_in,18,38,6	script	Priest Gardron#tu	110,{
 			mes "Well, it seems that";
 			mes "Well, it seems that";
 			mes "you must have forgotten";
 			mes "you must have forgotten";
 			mes "it or misplaced it somewhere.";
 			mes "it or misplaced it somewhere.";
-			close;
 		}
 		}
+		close;
 	} else if(tu_acolyte01 == 8){
 	} else if(tu_acolyte01 == 8){
-		if(countitem((checkre(0)?939:957)) > 4){
+		if(countitem((checkre(0)?939:957)) > 4){// Bee_Sting
 			mes "Oh...!";
 			mes "Oh...!";
 			mes "You've returned!";
 			mes "You've returned!";
 			mes "Let's see... One...";
 			mes "Let's see... One...";
@@ -855,7 +840,7 @@ monk_in,18,38,6	script	Priest Gardron#tu	110,{
 			mes "should return to Sister";
 			mes "should return to Sister";
 			mes "Asthe to continue your";
 			mes "Asthe to continue your";
 			mes "Acolyte training.";
 			mes "Acolyte training.";
-			set tu_acolyte01, 9;
+			tu_acolyte01 = 9;
 			percentheal 100,100;
 			percentheal 100,100;
 			if (checkre(3))
 			if (checkre(3))
 				getexp 1000,1000;
 				getexp 1000,1000;
@@ -954,7 +939,7 @@ monk_in,18,38,6	script	Priest Gardron#tu	110,{
 
 
 // Dog
 // Dog
 //============================================================
 //============================================================
-prt_monk,235,245,5	script	Dog#tu	81,{
+prt_monk,235,245,5	script	Dog#tu	4_DOG01,{
 	mes "[Dog]";
 	mes "[Dog]";
 	mes "^CDB79EBark bark!";
 	mes "^CDB79EBark bark!";
 	mes "Woof woof!^000000";
 	mes "Woof woof!^000000";
@@ -963,7 +948,7 @@ prt_monk,235,245,5	script	Dog#tu	81,{
 		while(1) {
 		while(1) {
 			switch(select("Give a treat.:Pet the dog.:End actions.")){
 			switch(select("Give a treat.:Pet the dog.:End actions.")){
 			case 1:
 			case 1:
-				set .@dog_food, .@dog_food + 1;
+				.@dog_food++;
 				if(.@dog_food > 4){
 				if(.@dog_food > 4){
 					mes "[Dog]";
 					mes "[Dog]";
 					mes "^CDB79EGrrrrrr...!^000000";
 					mes "^CDB79EGrrrrrr...!^000000";
@@ -972,26 +957,23 @@ prt_monk,235,245,5	script	Dog#tu	81,{
 					mes "^3355FFThe dog grinds";
 					mes "^3355FFThe dog grinds";
 					mes "its teeth and glares";
 					mes "its teeth and glares";
 					mes "at you menacingly.^000000";
 					mes "at you menacingly.^000000";
-					next;
 				} else {
 				} else {
 					mes "[Dog]";
 					mes "[Dog]";
 					mes "^CDB79ERoof roof!^000000";
 					mes "^CDB79ERoof roof!^000000";
 					emotion e_lv;
 					emotion e_lv;
-					next;
 				}
 				}
 				break;
 				break;
 			case 2:
 			case 2:
 				mes "[Dog]";
 				mes "[Dog]";
 				mes "^CDB79ERoof roof~^000000";
 				mes "^CDB79ERoof roof~^000000";
 				emotion e_lv;
 				emotion e_lv;
-				next;
 				break;
 				break;
 			case 3:
 			case 3:
 				mes "[Dog]";
 				mes "[Dog]";
 				mes "^CDB79ERoof roof!^000000";
 				mes "^CDB79ERoof roof!^000000";
-				next;
 				break;
 				break;
 			}
 			}
+			next;
 		}
 		}
 	}
 	}
 	mes "["+strcharinfo(0)+"]";
 	mes "["+strcharinfo(0)+"]";
@@ -1001,9 +983,9 @@ prt_monk,235,245,5	script	Dog#tu	81,{
 
 
 // Boy
 // Boy
 //============================================================
 //============================================================
-prt_monk,243,238,5	script	Boy#boy_voi	139,5,5,{
+prt_monk,243,238,5	script	Boy#boy_voi	HIDDEN_WARP_NPC,5,5,{
 OnTouch_:
 OnTouch_:
-	if(tu_acolyte01 != 10)end;
+	if(tu_acolyte01 != 10) end;
 	mes "[??]";
 	mes "[??]";
 	mes "^333333*Sniff*^000000";
 	mes "^333333*Sniff*^000000";
 	mes "Sister...";
 	mes "Sister...";
@@ -1012,7 +994,7 @@ OnTouch_:
 
 
 // Ill Girl
 // Ill Girl
 //============================================================
 //============================================================
-prt_monk,226,257,6	script	Ill Girl#tu	93,{
+prt_monk,226,257,6	script	Ill Girl#tu	4_F_04,{
 	mes "[Angelic]";
 	mes "[Angelic]";
 	if(tu_acolyte01 > 12){
 	if(tu_acolyte01 > 12){
 		mes "Thanks for helping me.";
 		mes "Thanks for helping me.";
@@ -1087,15 +1069,15 @@ prt_monk,226,257,6	script	Ill Girl#tu	93,{
 		mes "["+strcharinfo(0)+"]";
 		mes "["+strcharinfo(0)+"]";
 		mes "I'll cure you...";
 		mes "I'll cure you...";
 		mes "For sure.";
 		mes "For sure.";
-		set tu_acolyte01, 11;
-		close;
-	} else if(tu_acolyte01 == 11){
+		tu_acolyte01 = 11;
+	}
+	else if(tu_acolyte01 == 11){
 		next;
 		next;
 		mes "[Angelic]";
 		mes "[Angelic]";
 		mes "It hurts...!";
 		mes "It hurts...!";
 		mes "I... I can't...!";
 		mes "I... I can't...!";
-		close;
-	} else if(tu_acolyte01 == 12){
+	}
+	else if(tu_acolyte01 == 12){
 		next;
 		next;
 		mes "^3355FFYou go towards";
 		mes "^3355FFYou go towards";
 		mes "the girl, place your hands";
 		mes "the girl, place your hands";
@@ -1112,8 +1094,7 @@ prt_monk,226,257,6	script	Ill Girl#tu	93,{
 			mes "^3355FFNothing happened.";
 			mes "^3355FFNothing happened.";
 			mes "It doesn't look like";
 			mes "It doesn't look like";
 			mes "that skill will work.^000000";
 			mes "that skill will work.^000000";
-			close; 
-			break;
+			close;
 		case 2:
 		case 2:
 			if(getskilllv("AL_BLESSING") > 0){
 			if(getskilllv("AL_BLESSING") > 0){
 				mes "["+strcharinfo(0)+"]";
 				mes "["+strcharinfo(0)+"]";
@@ -1131,7 +1112,7 @@ prt_monk,226,257,6	script	Ill Girl#tu	93,{
 					mes "practice your abilities!";
 					mes "practice your abilities!";
 					mes "It seemed that this good";
 					mes "It seemed that this good";
 					mes "deed has improved your skills.^000000";
 					mes "deed has improved your skills.^000000";
-					set tu_acolyte01, 13;
+					tu_acolyte01 = 13;
 					if (checkre(3))
 					if (checkre(3))
 						getexp 0,500;
 						getexp 0,500;
 					else
 					else
@@ -1153,7 +1134,6 @@ prt_monk,226,257,6	script	Ill Girl#tu	93,{
 				mes "not able to use it for now.^000000";
 				mes "not able to use it for now.^000000";
 				close;
 				close;
 			}
 			}
-			break;
 		case 3:
 		case 3:
 			if(getskilllv("AL_CURE") > 0){
 			if(getskilllv("AL_CURE") > 0){
 				mes "["+strcharinfo(0)+"]";
 				mes "["+strcharinfo(0)+"]";
@@ -1163,13 +1143,13 @@ prt_monk,226,257,6	script	Ill Girl#tu	93,{
 				mes "^3355FFNothing happened.";
 				mes "^3355FFNothing happened.";
 				mes "It doesn't look like";
 				mes "It doesn't look like";
 				mes "that skill will work.^000000";
 				mes "that skill will work.^000000";
-				close;
-			} else {
+			}
+			else {
 				mes "^3355FFYou didn't learn";
 				mes "^3355FFYou didn't learn";
 				mes "this skill yet, so you're";
 				mes "this skill yet, so you're";
 				mes "not able to use it for now.^000000";
 				mes "not able to use it for now.^000000";
-				close;
 			}
 			}
+			close;
 		case 4:
 		case 4:
 			mes "^3355FFThis isn't a skill";
 			mes "^3355FFThis isn't a skill";
 			mes "that Acolytes can use...^000000";
 			mes "that Acolytes can use...^000000";
@@ -1184,19 +1164,18 @@ prt_monk,226,257,6	script	Ill Girl#tu	93,{
 				mes "^3355FFNothing happened.";
 				mes "^3355FFNothing happened.";
 				mes "It doesn't look like";
 				mes "It doesn't look like";
 				mes "that skill will work.^000000";
 				mes "that skill will work.^000000";
-				close;
-			} else {
+			}
+			else {
 				mes "^3355FFYou didn't learn";
 				mes "^3355FFYou didn't learn";
 				mes "this skill yet, so you're";
 				mes "this skill yet, so you're";
 				mes "not able to use it for now.^000000";
 				mes "not able to use it for now.^000000";
-				close;
 			}
 			}
+			close;
 		case 6:
 		case 6:
 			mes "^3355FFThis isn't a skill";
 			mes "^3355FFThis isn't a skill";
 			mes "that Acolytes can use...^000000";
 			mes "that Acolytes can use...^000000";
 			close;
 			close;
 		}
 		}
-
 		mes "[Angelic]";
 		mes "[Angelic]";
 		mes "Ah...";
 		mes "Ah...";
 		mes "I feel...";
 		mes "I feel...";
@@ -1214,9 +1193,9 @@ prt_monk,226,257,6	script	Ill Girl#tu	93,{
 
 
 // Veiner
 // Veiner
 //============================================================
 //============================================================
-prt_monk,197,228,3	script	Veiner	89,{
+prt_monk,197,228,3	script	Veiner	4_M_ORIENT02,{
 	mes "[Veiner]";
 	mes "[Veiner]";
-	if(countitem(1081) && tu_acolyte01 == 18){
+	if(countitem(1081) && tu_acolyte01 == 18){// Merchant_Box_1
 		mes "So very exhausted...";
 		mes "So very exhausted...";
 		mes "Should I just go back home?";
 		mes "Should I just go back home?";
 		next;
 		next;
@@ -1238,34 +1217,35 @@ prt_monk,197,228,3	script	Veiner	89,{
 		mes "Oh right!";
 		mes "Oh right!";
 		mes "Thank you very much for delivering this to me. Sorry, but I'm always excited to hear from my cutie pie~";
 		mes "Thank you very much for delivering this to me. Sorry, but I'm always excited to hear from my cutie pie~";
 		emotion e_thx;
 		emotion e_thx;
-		set tu_acolyte01,19;
+		tu_acolyte01 = 19;
 		delitem 1081,1; //Merchant_Box_1
 		delitem 1081,1; //Merchant_Box_1
-		close;
-	} else if(tu_acolyte01 > 18){
+	}
+	else if(tu_acolyte01 > 18){
 		mes "I can't wait";
 		mes "I can't wait";
 		mes "to see her again!";
 		mes "to see her again!";
 		mes "Bibi...! I loooove you!";
 		mes "Bibi...! I loooove you!";
 		emotion e_kis2;
 		emotion e_kis2;
-		close;
 	}
 	}
-	mes "So very";
-	mes "exhausted...";
-	mes "Would you help";
-	mes "me carry my stuff?";
-	mes "P-please...";
+	else {
+		mes "So very";
+		mes "exhausted...";
+		mes "Would you help";
+		mes "me carry my stuff?";
+		mes "P-please...";
+	}
 	close;
 	close;
 }
 }
 
 
 // Hedrick
 // Hedrick
 //============================================================
 //============================================================
-prt_monk,28,260,5	script	Hedrick	50,{
+prt_monk,28,260,5	script	Hedrick	1_M_04,{
 	mes "[Hedrick]";
 	mes "[Hedrick]";
 	mes "^333333*Whew!*^000000";
 	mes "^333333*Whew!*^000000";
 	mes "Man I worked hard today!";
 	mes "Man I worked hard today!";
 	mes "And so efficiently too!";
 	mes "And so efficiently too!";
 	mes "Awesome job as usual,";
 	mes "Awesome job as usual,";
 	mes "Hedrick. You're number one!";
 	mes "Hedrick. You're number one!";
-	if(countitem(7148)==0 || tu_acolyte01 != 19) close;
+	if(countitem(7148)==0 || tu_acolyte01 != 19) close;// Mother_Letter
 	next;
 	next;
 	mes "[Hedrick]";
 	mes "[Hedrick]";
 	mes "Oh...?";
 	mes "Oh...?";
@@ -1287,16 +1267,16 @@ prt_monk,28,260,5	script	Hedrick	50,{
 	mes "you have one of the";
 	mes "you have one of the";
 	mes "cookies she sent me?";
 	mes "cookies she sent me?";
 	delitem 7148,1; //Mother_Letter
 	delitem 7148,1; //Mother_Letter
-	set tu_acolyte01,20;
+	tu_acolyte01 = 20;
 	getitem 538,1; //Well_Baked_Cookie
 	getitem 538,1; //Well_Baked_Cookie
 	close;
 	close;
 }
 }
 
 
 // Weapon Merchant
 // Weapon Merchant
 //============================================================
 //============================================================
-prt_monk,136,261,0	script	Weapon Merchant#tu	139,9,9,{
+prt_monk,136,261,0	script	Weapon Merchant#tu	HIDDEN_WARP_NPC,9,9,{
 OnTouch:
 OnTouch:
-	if(tu_acolyte01 != 20 || countitem(1081)==0) end;
+	if(tu_acolyte01 != 20 || countitem(1081) == 0) end;// Merchant_Box_1
 	mes "[Weapon Merchant]";
 	mes "[Weapon Merchant]";
 	mes "The stuff I requested from the guild is finally here!";
 	mes "The stuff I requested from the guild is finally here!";
 	mes "It's pretty tough to keep everything in stock since this is such a remote place.";
 	mes "It's pretty tough to keep everything in stock since this is such a remote place.";
@@ -1306,18 +1286,18 @@ OnTouch:
 	mes "Oh, and come here if";
 	mes "Oh, and come here if";
 	mes "you need anything, okay?";
 	mes "you need anything, okay?";
 	delitem 1081,1; //Merchant_Box_1
 	delitem 1081,1; //Merchant_Box_1
-	set tu_acolyte01,21;
+	tu_acolyte01 = 21;
 	close;
 	close;
 }
 }
 
 
 // Karven
 // Karven
 //============================================================
 //============================================================
-monk_in,103,176,7	script	Karven	60,{
+monk_in,103,176,7	script	Karven	1_M_PASTOR,{
 	mes "[Karven]";
 	mes "[Karven]";
 	mes "May you rest";
 	mes "May you rest";
 	if(tu_acolyte01 == 21 && countitem(7183)){
 	if(tu_acolyte01 == 21 && countitem(7183)){
-		delitem 7183, 1;
-		set tu_acolyte01, 22;
+		delitem 7183, 1;// Sister_Letter
+		tu_acolyte01 = 22;
 		mes "in peace forever...";
 		mes "in peace forever...";
 		next;
 		next;
 		mes "[Karven]";
 		mes "[Karven]";
@@ -1346,7 +1326,7 @@ monk_in,103,176,7	script	Karven	60,{
 
 
 // Gloria
 // Gloria
 //============================================================
 //============================================================
-prt_monk,219,164,3	script	Gloria#tu	95,{
+prt_monk,219,164,3	script	Gloria#tu	4_F_SISTER,{
 	mes "[Gloria]";
 	mes "[Gloria]";
 	if(BaseJob != Job_Acolyte){
 	if(BaseJob != Job_Acolyte){
 		mes "Hi, hi~";
 		mes "Hi, hi~";
@@ -1419,12 +1399,12 @@ prt_monk,219,164,3	script	Gloria#tu	95,{
 
 
 // Cleope Verce
 // Cleope Verce
 //============================================================
 //============================================================
-prt_monk,153,210,3	script	Cleope Verce	95,{
+prt_monk,153,210,3	script	Cleope Verce	4_F_SISTER,{
 	mes "[Cleope Verce]";
 	mes "[Cleope Verce]";
-	if(BaseJob != Job_Acolyte){
+	if(BaseJob == Job_Acolyte){
 		if (JobLevel < 40) {
 		if (JobLevel < 40) {
 			if (BaseLevel < 26) {
 			if (BaseLevel < 26) {
-				mes "Oh my.. "; 
+				mes "Oh my.. ";
 				mes "A newbie Acolyte?";
 				mes "A newbie Acolyte?";
 				mes "It doesn't even seem";
 				mes "It doesn't even seem";
 				mes "like you've learned";
 				mes "like you've learned";
@@ -1466,7 +1446,7 @@ prt_monk,153,210,3	script	Cleope Verce	95,{
 				mes "Rookie.";
 				mes "Rookie.";
 				close;
 				close;
 			} else if(BaseLevel < 36){
 			} else if(BaseLevel < 36){
-				mes "Oh my.. "; 
+				mes "Oh my.. ";
 				mes "A young Acolyte?";
 				mes "A young Acolyte?";
 				mes "You seem to have just";
 				mes "You seem to have just";
 				mes "started learning your skills?";
 				mes "started learning your skills?";
@@ -1517,7 +1497,7 @@ prt_monk,153,210,3	script	Cleope Verce	95,{
 				mes "young friend.";
 				mes "young friend.";
 				close;
 				close;
 			} else if(BaseLevel < 46){
 			} else if(BaseLevel < 46){
-				mes "Well, well, well~"; 
+				mes "Well, well, well~";
 				mes "Hello, young Acolyte.";
 				mes "Hello, young Acolyte.";
 				mes "You're still kind of";
 				mes "You're still kind of";
 				mes "green, but I guess you're";
 				mes "green, but I guess you're";
@@ -1593,7 +1573,7 @@ prt_monk,153,210,3	script	Cleope Verce	95,{
 }
 }
 // Range NPC
 // Range NPC
 //============================================================
 //============================================================
-prt_monk,217,123,0	script	#tu_monk	139,10,10,{
+prt_monk,217,123,0	script	#tu_monk	HIDDEN_WARP_NPC,10,10,{
 OnTouch_:
 OnTouch_:
 	if(BaseJob == Job_Acolyte){
 	if(BaseJob == Job_Acolyte){
 		switch(tu_acolyte01){
 		switch(tu_acolyte01){
@@ -1614,7 +1594,7 @@ OnTouch_:
 
 
 // Eavesdrop
 // Eavesdrop
 //============================================================
 //============================================================
-prt_monk,223,123,3	script	Eavesdrop#tu	111,{
+prt_monk,223,123,3	script	Eavesdrop#tu	HIDDEN_NPC,{
 	if(BaseJob != Job_Acolyte){
 	if(BaseJob != Job_Acolyte){
 		mes "^3355FFThere's nothing here.^000000";
 		mes "^3355FFThere's nothing here.^000000";
 		close;
 		close;
@@ -1643,8 +1623,8 @@ prt_monk,223,123,3	script	Eavesdrop#tu	111,{
 		mes "^A68064 Alright, sir.";
 		mes "^A68064 Alright, sir.";
 		mes "Still, I can't help";
 		mes "Still, I can't help";
 		mes "but feel uneasy...^000000";
 		mes "but feel uneasy...^000000";
-		close;
-	} else if(tu_acolyte01 > 9 && tu_acolyte01 < 25){
+	}
+	else if(tu_acolyte01 > 9 && tu_acolyte01 < 25){
 		mes "[Voices from Window]";
 		mes "[Voices from Window]";
 		mes "^A68064I heard from an";
 		mes "^A68064I heard from an";
 		mes "official at the palace";
 		mes "official at the palace";
@@ -1674,8 +1654,8 @@ prt_monk,223,123,3	script	Eavesdrop#tu	111,{
 		next;
 		next;
 		mes "[Voices from Window]";
 		mes "[Voices from Window]";
 		mes "^CD6600Thank you...^000000";
 		mes "^CD6600Thank you...^000000";
-		close;
-	} else if(tu_acolyte01 > 24){
+	}
+	else if(tu_acolyte01 > 24){
 		mes "[Voices from Window]";
 		mes "[Voices from Window]";
 		mes "^A68064...Sir, do you know anything about the ^855E42curse of the Gaebolg family^A68064?^000000";
 		mes "^A68064...Sir, do you know anything about the ^855E42curse of the Gaebolg family^A68064?^000000";
 		next;
 		next;
@@ -1776,34 +1756,34 @@ prt_monk,223,123,3	script	Eavesdrop#tu	111,{
 		mes "[Voice from Window]";
 		mes "[Voice from Window]";
 		mes "^CD6600Oh dear God.";
 		mes "^CD6600Oh dear God.";
 		mes "Please expel the darkness that approaches the Rune-Midgarts Kingdom. Please protect us with your light and compassion.^000000";
 		mes "Please expel the darkness that approaches the Rune-Midgarts Kingdom. Please protect us with your light and compassion.^000000";
-		close;
 	}
 	}
+	close;
 }
 }
 
 
-sec_in02,17,156,3	script	1st Job Quest Reset	726,{
+sec_in02,17,156,3	script	1st Job Quest Reset	4_F_JOB_BLACKSMITH,{
 	callfunc "F_GM_NPC";
 	callfunc "F_GM_NPC";
 	mes "[1st Job Quest]";
 	mes "[1st Job Quest]";
 	mes "Which would you like to reset?";
 	mes "Which would you like to reset?";
 	next;
 	next;
 	switch(select("Swordsman:Merchant:Archer:Acolyte:Thief:Mage")) {
 	switch(select("Swordsman:Merchant:Archer:Acolyte:Thief:Mage")) {
 	case 1:
 	case 1:
-		set tu_swordman,0;
+		tu_swordman = 0;
 		break;
 		break;
 	case 2:
 	case 2:
-		set tu_merchant,0;
+		tu_merchant = 0;
 		break;
 		break;
 	case 3:
 	case 3:
-		set tu_archer01,0;
-		set tu_archer02,0;
+		tu_archer01 = 0;
+		tu_archer02 = 0;
 		break;
 		break;
 	case 4:
 	case 4:
-		set tu_acolyte01,0;
+		tu_acolyte01 = 0;
 		break;
 		break;
 	case 5:
 	case 5:
-		set tu_thief01,0;
+		tu_thief01 = 0;
 		break;
 		break;
 	case 6:
 	case 6:
-		set tu_magician01,0;
+		tu_magician01 = 0;
 		break;
 		break;
 	}
 	}
 	mes "Completed.";
 	mes "Completed.";

+ 136 - 171
npc/quests/first_class/tu_archer.txt

@@ -1,15 +1,15 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= Archer Class Tutorial and Job Specific Quest
 //= Archer Class Tutorial and Job Specific Quest
-//===== By: ================================================== 
+//===== By: ==================================================
 //= Fix up by Jukka
 //= Fix up by Jukka
-//===== Current Version: ===================================== 
-//= 2.0
-//===== Compatible With: ===================================== 
+//===== Current Version: =====================================
+//= 3.0
+//===== Compatible With: =====================================
 //= rAthena Project
 //= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= [Official Conversion]
 //= Archer training quest.
 //= Archer training quest.
-//===== Additional Comments: ================================= 
+//===== Additional Comments: =================================
 //= 1.0 Fully working
 //= 1.0 Fully working
 //= 1.1 optimized [Lupus]
 //= 1.1 optimized [Lupus]
 //= 1.2 fixed Weight check
 //= 1.2 fixed Weight check
@@ -24,11 +24,12 @@
 //= 1.9a Added 'npcskill' command. [Euphy]
 //= 1.9a Added 'npcskill' command. [Euphy]
 //= 2.0 Updated to match the official script. [Euphy]
 //= 2.0 Updated to match the official script. [Euphy]
 //=     Added Pre-Renewal support.
 //=     Added Pre-Renewal support.
-//============================================================ 
+//= 3.0 Clean-up. [Capuche]
+//============================================================
 
 
 // Bard Jet
 // Bard Jet
 //============================================================
 //============================================================
-payon_in02,67,65,3	script	Bard Jet#tu	51,{
+payon_in02,67,65,3	script	Bard Jet#tu	1_M_BARD,{
 	mes "[Jet]";
 	mes "[Jet]";
 	mes "Every god never grows old";
 	mes "Every god never grows old";
 	mes "Because of beautiful";
 	mes "Because of beautiful";
@@ -37,7 +38,7 @@ payon_in02,67,65,3	script	Bard Jet#tu	51,{
 	mes "Goddess of immortality.";
 	mes "Goddess of immortality.";
 	next;
 	next;
 	mes "[Jet]";
 	mes "[Jet]";
-	if(Class == Job_Archer || Class == Job_Baby_Archer || Class == Job_Archer_High){
+	if (BaseJob == Job_Archer){
 		mes "Ooh, you're an Archer?";
 		mes "Ooh, you're an Archer?";
 		mes "There was a time when I too";
 		mes "There was a time when I too";
 		mes "was an Archer. But I've changed jobs, so now I entertain the masses with my songs and humor.";
 		mes "was an Archer. But I've changed jobs, so now I entertain the masses with my songs and humor.";
@@ -103,8 +104,7 @@ payon_in02,67,65,3	script	Bard Jet#tu	51,{
 		mes "everything and change";
 		mes "everything and change";
 		mes "jobs so that you can";
 		mes "jobs so that you can";
 		mes "come play with me!";
 		mes "come play with me!";
-		close;
-	} else if(Class == Job_Bard || Class == Job_Clown || Class == Job_Baby_Bard){	//CHECK
+	} else if (BaseJob == Job_Bard){
 		mes "Ooh...!";
 		mes "Ooh...!";
 		mes "You're...!";
 		mes "You're...!";
 		next;
 		next;
@@ -130,15 +130,13 @@ payon_in02,67,65,3	script	Bard Jet#tu	51,{
 		mes "and the word Mammonite";
 		mes "and the word Mammonite";
 		mes "sounds-- wait. It's not funny";
 		mes "sounds-- wait. It's not funny";
 		mes "if I have to explain it, huh?";
 		mes "if I have to explain it, huh?";
-		close;
-	} else if(Class == Job_Dancer || Class == Job_Gypsy || Class == Job_Baby_Dancer){
+	} else if (BaseJob == Job_Dancer){
 		mes "Ooh...!";
 		mes "Ooh...!";
 		mes "Hello, hello!";
 		mes "Hello, hello!";
 		mes "Wouldn't it be";
 		mes "Wouldn't it be";
 		mes "nice if we could";
 		mes "nice if we could";
 		mes "perform together";
 		mes "perform together";
 		mes "one of these days?";
 		mes "one of these days?";
-		close;
 	} else {
 	} else {
 		mes "You look bored...";
 		mes "You look bored...";
 		mes "Is life really that";
 		mes "Is life really that";
@@ -164,7 +162,7 @@ payon_in02,67,65,3	script	Bard Jet#tu	51,{
 
 
 // Sign
 // Sign
 //============================================================
 //============================================================
-pay_arche,127,154,4	script	Sign#arc	835,{
+pay_arche,127,154,4	script	Sign#arc	2_BOARD1,{
 	mes " ";
 	mes " ";
 	mes " Archer Job Change Office ---> ";
 	mes " Archer Job Change Office ---> ";
 	mes " <--- Icarus ";
 	mes " <--- Icarus ";
@@ -174,7 +172,7 @@ pay_arche,127,154,4	script	Sign#arc	835,{
 
 
 // Master Kavaruk
 // Master Kavaruk
 //============================================================
 //============================================================
-payon_in02,54,13,3	script	Master Kavaruk	55,{
+payon_in02,54,13,3	script	Master Kavaruk	1_M_JOBTESTER,{
 	mes "[Master Kavaruk]";
 	mes "[Master Kavaruk]";
 	mes "Hello, young one.";
 	mes "Hello, young one.";
 	mes "I am Master Kavaruk";
 	mes "I am Master Kavaruk";
@@ -200,25 +198,22 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 		mes "The members of our guild are those who not only wish to be brave, but to reach out for our dreams like Icarus did. Our members are aspiring Archers, former Archers and current Archers.";
 		mes "The members of our guild are those who not only wish to be brave, but to reach out for our dreams like Icarus did. Our members are aspiring Archers, former Archers and current Archers.";
 		next;
 		next;
 		mes "[Master Kavaruk]";
 		mes "[Master Kavaruk]";
-		if(Class == Job_Novice || Class == Job_Baby){
+		if (Class == Job_Novice){
 			mes "If you'd like to become an Archer, why don't you go around and learn";
 			mes "If you'd like to become an Archer, why don't you go around and learn";
 			mes "a few things about the profession? I'm sure you'll be able to hear plenty of stories around here.";
 			mes "a few things about the profession? I'm sure you'll be able to hear plenty of stories around here.";
-			close;
-
-		} else if(Class == Job_Archer){
+		}
+		else if(Class == Job_Archer){
 			mes "Since you're an Archer, you might";
 			mes "Since you're an Archer, you might";
 			mes "benefit from going around and listening to everyone else's battle experiences. Becoming familiar with different fight scenarios will help you in the future.";
 			mes "benefit from going around and listening to everyone else's battle experiences. Becoming familiar with different fight scenarios will help you in the future.";
-			close;
-
-		} else if(Class == Job_Hunter || Class == Job_Sniper || Class == Job_Baby_Hunter){	//CHECK
+		}
+		else if (BaseJob == Job_Hunter){
 			mes "[Master Kavaruk]";
 			mes "[Master Kavaruk]";
 			mes "Arpesto is waiting";
 			mes "Arpesto is waiting";
 			mes "outside. Since he's a";
 			mes "outside. Since he's a";
 			mes "veteran hunter, he can";
 			mes "veteran hunter, he can";
 			mes "be of great help to you.";
 			mes "be of great help to you.";
-			close;
-
-		} else if(Class == Job_Dancer || Class == Job_Gypsy || Class == Job_Baby_Dancer){	//CHECK
+		}
+		else if (BaseJob == Job_Dancer){
 			mes "In fact, a few of our";
 			mes "In fact, a few of our";
 			mes "members specialize in";
 			mes "members specialize in";
 			mes "capturing the fascination";
 			mes "capturing the fascination";
@@ -230,24 +225,23 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 			mes "any of them around here right now. They never seem to remain in one";
 			mes "any of them around here right now. They never seem to remain in one";
 			mes "place for very long. Still, I'm sure of them will turn up here";
 			mes "place for very long. Still, I'm sure of them will turn up here";
 			mes "one of these days.";
 			mes "one of these days.";
-			close;
-
-		} else if(Class == Job_Bard || Class == Job_Clown || Class == Job_Baby_Bard){	//CHECK
+		}
+		else if (BaseJob == Job_Bard){
 			mes "In fact, a few of our members";
 			mes "In fact, a few of our members";
 			mes "are highly skilled in singing and entertaining their allies, much in the same way you do.";
 			mes "are highly skilled in singing and entertaining their allies, much in the same way you do.";
 			next;
 			next;
 			mes "[Master Kavaruk]";
 			mes "[Master Kavaruk]";
 			mes "...But I don't seem to see any of them around here right now. They always wander wherever the wind takes them, but I'm sure one of them will wander back here one";
 			mes "...But I don't seem to see any of them around here right now. They always wander wherever the wind takes them, but I'm sure one of them will wander back here one";
 			mes "of these days.";
 			mes "of these days.";
-			close;
 		}
 		}
-		mes "They happen to know a lot of information about jobs related to Archers. Why don't you speak to them and learn more about";
-		mes "these other jobs?";
+		else {
+			mes "They happen to know a lot of information about jobs related to Archers. Why don't you speak to them and learn more about";
+			mes "these other jobs?";
+		}
 		close;
 		close;
-		break;
 	case 2:
 	case 2:
 		mes "[Master Kavaruk]";
 		mes "[Master Kavaruk]";
-		if(Class == Job_Archer || Class == Job_Baby_Archer || Class == Job_Archer_High){
+		if (BaseJob == Job_Archer) {
 			if(tu_archer02 == 0){
 			if(tu_archer02 == 0){
 				mes "Oh, it's a good thing";
 				mes "Oh, it's a good thing";
 				mes "you're here, "+strcharinfo(0)+".";
 				mes "you're here, "+strcharinfo(0)+".";
@@ -267,9 +261,7 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 				next;
 				next;
 				mes "[Master Kavaruk]";
 				mes "[Master Kavaruk]";
 				mes "If you're interested, it would probably be best to speak to the Alchemist Guild member who is waiting to hear from us at the ^3131FFshop next to the road south of Icarus^000000.";
 				mes "If you're interested, it would probably be best to speak to the Alchemist Guild member who is waiting to hear from us at the ^3131FFshop next to the road south of Icarus^000000.";
-				set tu_archer02,1;
-				close;
-
+				tu_archer02 = 1;
 			} else if(tu_archer02 == 1){
 			} else if(tu_archer02 == 1){
 				mes "Hmmm...";
 				mes "Hmmm...";
 				mes "..........";
 				mes "..........";
@@ -293,27 +285,23 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 				mes "[Master Kavaruk]";
 				mes "[Master Kavaruk]";
 				mes "Please find out if he is all right and help him with whatever he";
 				mes "Please find out if he is all right and help him with whatever he";
 				mes "may need. In the meantime, I will be waiting to hear from you. Thank you very much.";
 				mes "may need. In the meantime, I will be waiting to hear from you. Thank you very much.";
-				set tu_archer02, 2;
-				close;
-
+				tu_archer02 = 2;
 			} else if(tu_archer02 == 2){
 			} else if(tu_archer02 == 2){
 				mes "Find Arthail";
 				mes "Find Arthail";
 				mes "of the Wind for me.";
 				mes "of the Wind for me.";
 				mes "He must be somewhere";
 				mes "He must be somewhere";
 				mes "in Prontera...";
 				mes "in Prontera...";
-				close;
-
 			} else if(tu_archer02 == 9){
 			} else if(tu_archer02 == 9){
 				mes "Hmmm, I see. Thank you";
 				mes "Hmmm, I see. Thank you";
 				mes "for bringing me the news. As Arthail has said, I shall wait until he has more news for me.";
 				mes "for bringing me the news. As Arthail has said, I shall wait until he has more news for me.";
 				mes "You should also train and prepare for the future as well.";
 				mes "You should also train and prepare for the future as well.";
-				set tu_archer02, 10;
+				tu_archer02 = 10;
 				if (checkre(3))
 				if (checkre(3))
 					getexp 1000,1000;
 					getexp 1000,1000;
 				else
 				else
 					getexp 2000,1000;
 					getexp 2000,1000;
-				close;
 			}
 			}
+			close;
 		}
 		}
 		mes "I don't know...";
 		mes "I don't know...";
 		mes "Recently, I haven't heard any noteworthy news. For now, the warmth of the sun seems to be protecting the peace here.";
 		mes "Recently, I haven't heard any noteworthy news. For now, the warmth of the sun seems to be protecting the peace here.";
@@ -323,8 +311,6 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 		mes "any interesting rumors,";
 		mes "any interesting rumors,";
 		mes "I will let you know.";
 		mes "I will let you know.";
 		close;
 		close;
-		break;
-
 	case 3:
 	case 3:
 		mes "[Master Kavaruk]";
 		mes "[Master Kavaruk]";
 		if(tu_archer01 < 1){
 		if(tu_archer01 < 1){
@@ -333,21 +319,18 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 				mes "So are you";
 				mes "So are you";
 				mes "interested in";
 				mes "interested in";
 				mes "becoming an Archer?";
 				mes "becoming an Archer?";
-
-			} else if(BaseClass == Job_Archer){
+			} else if (Class == Job_Archer_High || BaseJob == Job_Dancer || BaseJob == Job_Bard){
 				mes "Although I can't deny that you're an expert, I suppose it is a good idea to review the basics of archery from time to time. Would you like to try some refresher training?";
 				mes "Although I can't deny that you're an expert, I suppose it is a good idea to review the basics of archery from time to time. Would you like to try some refresher training?";
-			} else if(Class == Job_Hunter || Class == Job_Sniper){	//CHECK
+			} else if (BaseJob == Job_Hunter){
 				mes "[Master Kavaruk]";
 				mes "[Master Kavaruk]";
 				mes "Arpesto is waiting";
 				mes "Arpesto is waiting";
 				mes "outside. Since he's a";
 				mes "outside. Since he's a";
 				mes "veteran hunter, he can";
 				mes "veteran hunter, he can";
 				mes "be of great help to you.";
 				mes "be of great help to you.";
 				close;
 				close;
-
 			} else if(Class == Job_Archer || Class == Job_Baby_Archer){
 			} else if(Class == Job_Archer || Class == Job_Baby_Archer){
 				mes "As an Archer, I can see that you'd want to make sure that you have a strong grasp on the fundamentals";
 				mes "As an Archer, I can see that you'd want to make sure that you have a strong grasp on the fundamentals";
 				mes "of our job. Would you like some specialized instruction?";
 				mes "of our job. Would you like some specialized instruction?";
-
 			} else {
 			} else {
 				mes "Although you may not be able";
 				mes "Although you may not be able";
 				mes "to directly apply archery related knowledge, it's a good idea to understand the capabilities of";
 				mes "to directly apply archery related knowledge, it's a good idea to understand the capabilities of";
@@ -360,7 +343,7 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 			next;
 			next;
 			switch(select("Yes:No")){
 			switch(select("Yes:No")){
 			case 1:
 			case 1:
-				set tu_archer01, 1;
+				tu_archer01 = 1;
 				mes "[Master Kavaruk]";
 				mes "[Master Kavaruk]";
 				mes "Ah yes. Well then, please";
 				mes "Ah yes. Well then, please";
 				mes "take this message over to ^3131FFSeisner^000000 who is in the Training Grounds west of Icarus.";
 				mes "take this message over to ^3131FFSeisner^000000 who is in the Training Grounds west of Icarus.";
@@ -391,25 +374,22 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 			mes "hills west of Icarus and";
 			mes "hills west of Icarus and";
 			mes "talk to ^3131FFSeisner^000000 to begin your special training.";
 			mes "talk to ^3131FFSeisner^000000 to begin your special training.";
 			close;
 			close;
-
 		} else if(tu_archer01 == 3){
 		} else if(tu_archer01 == 3){
 			mes "So "+strcharinfo(0)+",";
 			mes "So "+strcharinfo(0)+",";
 			mes "Did you have a good experience? Learning theory alone is never too enjoyable, but it is necessary.";
 			mes "Did you have a good experience? Learning theory alone is never too enjoyable, but it is necessary.";
 			next;
 			next;
 			mes "[Master Kavaruk]";
 			mes "[Master Kavaruk]";
-			if(Class == Job_Archer || Class == Job_Archer_High || Class == Job_Baby_Archer){
+			if (BaseJob == Job_Archer){
 				mes "Now it is time to experience the principles you've just learned firsthand. Go speak to ^3131FFReidin Corse^000000, who is just outside of this building, and he'll tell you about the different skills.";
 				mes "Now it is time to experience the principles you've just learned firsthand. Go speak to ^3131FFReidin Corse^000000, who is just outside of this building, and he'll tell you about the different skills.";
-				set tu_archer01, 4;
+				tu_archer01 = 4;
 			} else {
 			} else {
 				mes "Still, there's no need for you to do any field training since only Archers can actually participate";
 				mes "Still, there's no need for you to do any field training since only Archers can actually participate";
 				mes "in that.";
 				mes "in that.";
 			}
 			}
 			close;
 			close;
-
-		} else if(tu_archer01 == 4){
+		} else if(tu_archer01 == 4 && BaseJob == Job_Archer) {
 			mes "Reidin Corse is just outside of this building. Didn't you see him on your way in?";
 			mes "Reidin Corse is just outside of this building. Didn't you see him on your way in?";
 			close;
 			close;
-
 		}
 		}
 	}
 	}
 	mes "You're great";
 	mes "You're great";
@@ -420,8 +400,14 @@ payon_in02,54,13,3	script	Master Kavaruk	55,{
 
 
 // Reidin Corse
 // Reidin Corse
 //============================================================
 //============================================================
-pay_arche,103,165,5	script	Reidin Corse#tu	832,{
+pay_arche,103,165,5	script	Reidin Corse#tu	4_M_REIDIN_KURS,{
 	mes "[Reidin Corse]";
 	mes "[Reidin Corse]";
+	if (checkweight(1201,1) == 0) {
+		mes "[Reidin Corse]";
+		mes "Why are you carrying";
+		mes "so much stuff? You better put everything you don't need into Kafra Storage.";
+		close;
+	}
 	if(MaxWeight - Weight < 2000){
 	if(MaxWeight - Weight < 2000){
 		mes "Hey, you're carrying an";
 		mes "Hey, you're carrying an";
 		mes "awful lot of stuff. You ought";
 		mes "awful lot of stuff. You ought";
@@ -429,7 +415,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 		mes "into Kafra Storage...";
 		mes "into Kafra Storage...";
 		close;
 		close;
 	}
 	}
-	if(tu_archer01 > 0){
+	if(tu_archer01 > 0 && (BaseJob != Job_Hunter && BaseJob != Job_Bard && BaseJob != Job_Dancer || Upper == 2)){
 		if(tu_archer01 == 4){
 		if(tu_archer01 == 4){
 			mes "Ah, what is it?";
 			mes "Ah, what is it?";
 			mes "Can I help you";
 			mes "Can I help you";
@@ -493,27 +479,25 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 			mes "^3355FFReidin Corse narrows his experienced eyes and sizes you up.^000000";
 			mes "^3355FFReidin Corse narrows his experienced eyes and sizes you up.^000000";
 			next;
 			next;
 			mes "[Reidin Corse]";
 			mes "[Reidin Corse]";
-			if(JobLevel > 39){
+			if(JobLevel > 39)
 				mes "Hey! You're ready to change jobs, aren't you? Don't waste time here and just get a new job already! Eh, or you can ask Master Kavaruk for something to do.";
 				mes "Hey! You're ready to change jobs, aren't you? Don't waste time here and just get a new job already! Eh, or you can ask Master Kavaruk for something to do.";
-				close;
-			} else if(JobLevel < 5){
+			else if(JobLevel < 5){
 				mes "Alright! We got a fresh Archer here! You're lucky you came to me, I'm the best teacher you can find! But let me warn you, I teach at a really fast pace, so try to keep";
 				mes "Alright! We got a fresh Archer here! You're lucky you came to me, I'm the best teacher you can find! But let me warn you, I teach at a really fast pace, so try to keep";
 				mes "up. Okay? Good.";
 				mes "up. Okay? Good.";
 				next;
 				next;
-				set tu_archer01, 5;
+				tu_archer01 = 5;
 				mes "[Reidin Corse]";
 				mes "[Reidin Corse]";
 				mes "Okay, I'm ready to begin the lessons! Come back over here once you've got your bow and arrows and everything else ready, got it?";
 				mes "Okay, I'm ready to begin the lessons! Come back over here once you've got your bow and arrows and everything else ready, got it?";
-				close;
 			} else {
 			} else {
 				mes "Okay. It looks like you know";
 				mes "Okay. It looks like you know";
 				mes "some stuff. But even if you're";
 				mes "some stuff. But even if you're";
 				mes "a little experienced, there's still room for you to learn. So try and keep up, got it?";
 				mes "a little experienced, there's still room for you to learn. So try and keep up, got it?";
 				next;
 				next;
-				set tu_archer01, 5;
+				tu_archer01 = 5;
 				mes "[Reidin Corse]";
 				mes "[Reidin Corse]";
 				mes "Well, I'm ready to teach whenever you're ready to learn. Come back once your bow and arrows and everything else is ready, alright?";
 				mes "Well, I'm ready to teach whenever you're ready to learn. Come back once your bow and arrows and everything else is ready, alright?";
-				close;
 			}
 			}
+			close;
 		} else if(tu_archer01 == 5){
 		} else if(tu_archer01 == 5){
 			mes "You ready? I think it's fair to remind you that I won't tolerate any complaining! Just do what";
 			mes "You ready? I think it's fair to remind you that I won't tolerate any complaining! Just do what";
 			mes "I say and you'll be the second best Archer in the world! After me, of course~";
 			mes "I say and you'll be the second best Archer in the world! After me, of course~";
@@ -544,9 +528,9 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				mes "if you can't aim at your targets, you'd be horrible at archery, right? You gotta have Accuracy!";
 				mes "if you can't aim at your targets, you'd be horrible at archery, right? You gotta have Accuracy!";
 				next;
 				next;
 				mes "[Reidin Corse]";
 				mes "[Reidin Corse]";
-				set .@skill_owl, getskilllv("AC_OWL");
+				.@skill_owl = getskilllv("AC_OWL");
 				if(.@skill_owl < 3){
 				if(.@skill_owl < 3){
-					set tu_archer01, 6;
+					tu_archer01 = 6;
 					mes "Now, your first assignment";
 					mes "Now, your first assignment";
 					mes "is to learn ^3131FFLevel 3 Owl's Eye^000000!";
 					mes "is to learn ^3131FFLevel 3 Owl's Eye^000000!";
 					if (checkre(0))
 					if (checkre(0))
@@ -624,7 +608,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				} else {
 				} else {
 					emotion e_ag;
 					emotion e_ag;
 					mes "Huh. So you already know a little about Owl's Eye already, huh? Well then, I guess I oughta talk about something you don't know about!";
 					mes "Huh. So you already know a little about Owl's Eye already, huh? Well then, I guess I oughta talk about something you don't know about!";
-					set tu_archer01, 7;
+					tu_archer01 = 7;
 					getexp 500,0;
 					getexp 500,0;
 					close;
 					close;
 				}
 				}
@@ -639,7 +623,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				close;
 				close;
 			}
 			}
 		} else if(tu_archer01 == 6){
 		} else if(tu_archer01 == 6){
-			set .@owl, getskilllv(43);
+			.@owl = getskilllv(43);
 			if(.@owl > 2){
 			if(.@owl > 2){
 				mes "Ah, you're";
 				mes "Ah, you're";
 				mes "finally back.";
 				mes "finally back.";
@@ -651,7 +635,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				mes "Ah, but your eyes look a lot sharper than they used to be.";
 				mes "Ah, but your eyes look a lot sharper than they used to be.";
 				mes "Here, this is a small, special reward for you.";
 				mes "Here, this is a small, special reward for you.";
 				specialeffect2 EF_WIND;
 				specialeffect2 EF_WIND;
-				set tu_archer01, 7;
+				tu_archer01 = 7;
 				getexp 500,0;
 				getexp 500,0;
 				next;
 				next;
 				emotion e_pif;
 				emotion e_pif;
@@ -730,8 +714,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 			mes "so they're perfect for target";
 			mes "so they're perfect for target";
 			mes "practice from a distance!";
 			mes "practice from a distance!";
 			next;
 			next;
-
-			set .@eagle, getskilllv("AC_VULTURE");
+			.@eagle = getskilllv("AC_VULTURE");
 			if(.@eagle < 3){
 			if(.@eagle < 3){
 				if (checkre(0))
 				if (checkre(0))
 					mes "Alright, Mandagora usually live around Geffen. I can send you to Geffen, so just travel north from there to find";
 					mes "Alright, Mandagora usually live around Geffen. I can send you to Geffen, so just travel north from there to find";
@@ -745,16 +728,15 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				if(MaxWeight - Weight < 1000){
 				if(MaxWeight - Weight < 1000){
 					mes "You've got plenty of arrows";
 					mes "You've got plenty of arrows";
 					mes "for that, so go for it!";
 					mes "for that, so go for it!";
-					set tu_archer01, 8;
-					next;
+					tu_archer01 = 8;
 				} else {
 				} else {
 					next;
 					next;
 					mes "[Reidin Corse]";
 					mes "[Reidin Corse]";
 					mes "Here's a little something to encourage you. Since Mandagora are Earth property monsters, these Fire Arrows will work really well.";
 					mes "Here's a little something to encourage you. Since Mandagora are Earth property monsters, these Fire Arrows will work really well.";
-					set tu_archer01,8;
+					tu_archer01 = 8;
 					getitem 1752,300; //Fire_Arrow
 					getitem 1752,300; //Fire_Arrow
-					next;
 				}
 				}
+				next;
 				mes "[Reidin Corse]";
 				mes "[Reidin Corse]";
 				mes "Alright~";
 				mes "Alright~";
 				mes "Ready to go?";
 				mes "Ready to go?";
@@ -786,12 +768,12 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				mes "You already";
 				mes "You already";
 				mes "learned Vulture's Eye!";
 				mes "learned Vulture's Eye!";
 				mes "Why did I spend so much time explaining about it? Well, I guess we're ready to move on to the next lesson...";
 				mes "Why did I spend so much time explaining about it? Well, I guess we're ready to move on to the next lesson...";
-				set tu_archer01,9;
+				tu_archer01 = 9;
 				getitem 1752,500; //Fire_Arrow
 				getitem 1752,500; //Fire_Arrow
 				close;
 				close;
 			}
 			}
 		} else if(tu_archer01 == 8){
 		} else if(tu_archer01 == 8){
-			set .@eagle, getskilllv("AC_VULTURE");
+			.@eagle = getskilllv("AC_VULTURE");
 			if(.@eagle < 3){
 			if(.@eagle < 3){
 				if (checkre(0))
 				if (checkre(0))
 					mes "Mandagora lives in the area north of Geffen. Learn up to Level 3 Vulture's Eye and get acquainted with your attack range.";
 					mes "Mandagora lives in the area north of Geffen. Learn up to Level 3 Vulture's Eye and get acquainted with your attack range.";
@@ -824,7 +806,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 			} else {
 			} else {
 				mes "Ah, so you've learned";
 				mes "Ah, so you've learned";
 				mes "a little something about Vulture's Eye! What do you think about it now? Ah, and here's a little reward for you before I start the next lesson~";
 				mes "a little something about Vulture's Eye! What do you think about it now? Ah, and here's a little reward for you before I start the next lesson~";
-				set tu_archer01,9;
+				tu_archer01 = 9;
 				getitem 1752,500; //Fire_Arrow
 				getitem 1752,500; //Fire_Arrow
 				close;
 				close;
 			}
 			}
@@ -846,7 +828,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 			mes "Whaddya think?";
 			mes "Whaddya think?";
 			mes "Exciting, yes?";
 			mes "Exciting, yes?";
 			next;
 			next;
-			set .@eagle, getskilllv("AC_DOUBLE");
+			.@eagle = getskilllv("AC_DOUBLE");
 			if(.@eagle > 2){
 			if(.@eagle > 2){
 				mes "["+strcharinfo(0)+"]";
 				mes "["+strcharinfo(0)+"]";
 				mes "I...";
 				mes "I...";
@@ -860,7 +842,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				mes "[Reidin Corse]";
 				mes "[Reidin Corse]";
 				mes "^333333*Sigh*^000000";
 				mes "^333333*Sigh*^000000";
 				mes "Next lesson...";
 				mes "Next lesson...";
-				set tu_archer01, 10;
+				tu_archer01 = 10;
 				close;
 				close;
 			} else {
 			} else {
 				mes "[Reidin Corse]";
 				mes "[Reidin Corse]";
@@ -878,7 +860,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				next;
 				next;
 				if(.@eagle == 0){
 				if(.@eagle == 0){
 					specialeffect2 EF_WIND;
 					specialeffect2 EF_WIND;
-					set tu_archer01, 10;
+					// tu_archer01 = 10;
 					getexp 0,500;
 					getexp 0,500;
 				}
 				}
 				emotion e_no1;
 				emotion e_no1;
@@ -928,9 +910,9 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				mes "[Reidin Corse]";
 				mes "[Reidin Corse]";
 				mes "It's easier to find Izlude if you pass by Prontera, so head towards the fields near Prontera. Alright, off you go, " + strcharinfo(0) + "~";
 				mes "It's easier to find Izlude if you pass by Prontera, so head towards the fields near Prontera. Alright, off you go, " + strcharinfo(0) + "~";
 			}
 			}
-			set tu_archer01,11;
+			tu_archer01 = 11;
 			close;
 			close;
-		} else if(tu_archer01 == 11){
+		} else if(tu_archer01 == 11){// Grasshopper's_Leg
 			if (checkre(0) && countitem(940) < 10) {
 			if (checkre(0) && countitem(940) < 10) {
 				mes "Hey...";
 				mes "Hey...";
 				mes "You gotta bring";
 				mes "You gotta bring";
@@ -956,7 +938,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 				mes "Good! You pass.";
 				mes "Good! You pass.";
 				mes "Don't forget that you gotta keep training and improve your skills. Before you know it, you'll be an expert almost as good as me!";
 				mes "Don't forget that you gotta keep training and improve your skills. Before you know it, you'll be an expert almost as good as me!";
 				specialeffect2 EF_WIND;
 				specialeffect2 EF_WIND;
-				set tu_archer01, 12;
+				tu_archer01 = 12;
 				if (checkre(0))
 				if (checkre(0))
 					delitem 940,10; //Grasshopper's_Leg
 					delitem 940,10; //Grasshopper's_Leg
 				getexp 1000,1000;
 				getexp 1000,1000;
@@ -984,7 +966,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 			mes "[Reidin Corse]";
 			mes "[Reidin Corse]";
 			mes "You might not be able";
 			mes "You might not be able";
 			mes "to see it now, but as you become more skilled, you'll eventually recognize all the benefits of this skill.";
 			mes "to see it now, but as you become more skilled, you'll eventually recognize all the benefits of this skill.";
-			set tu_archer01, 13;
+			tu_archer01 = 13;
 			close;
 			close;
 		} else if(tu_archer01 == 13){
 		} else if(tu_archer01 == 13){
 			mes "^333333*Sigh*^000000";
 			mes "^333333*Sigh*^000000";
@@ -1029,14 +1011,14 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 			} else {
 			} else {
 				mes "This stuff is just a little something to encourage you, so don't take it the wrong way! Now hurry up, get what I asked for,";
 				mes "This stuff is just a little something to encourage you, so don't take it the wrong way! Now hurry up, get what I asked for,";
 				mes "and come back!";
 				mes "and come back!";
-				set tu_archer01,14;
+				tu_archer01 = 14;
 				getitem 601,10; //Wing_Of_Fly
 				getitem 601,10; //Wing_Of_Fly
 				getitem 501,10; //Red_Potion
 				getitem 501,10; //Red_Potion
 				getitem 602,1; //Wing_Of_Butterfly
 				getitem 602,1; //Wing_Of_Butterfly
 				close;
 				close;
 			}
 			}
 		} else if((tu_archer01 == 14) || (tu_archer01 == 15)){
 		} else if((tu_archer01 == 14) || (tu_archer01 == 15)){
-			if (checkre(0) && (countitem(906) < 10 || countitem(921) < 10)) {
+			if (checkre(0) && (countitem(906) < 10 || countitem(921) < 10)) {// Pointed_Scale, Mushroom_Spore
 				mes "Remember, you";
 				mes "Remember, you";
 				mes "need to head into";
 				mes "need to head into";
 				mes "the forest east of Payon and get me";
 				mes "the forest east of Payon and get me";
@@ -1089,7 +1071,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 			mes "my final exam! Here, take";
 			mes "my final exam! Here, take";
 			mes "this little reward!";
 			mes "this little reward!";
 			specialeffect2 EF_WIND;
 			specialeffect2 EF_WIND;
-			set tu_archer01,16;
+			tu_archer01 = 16;
 			if (checkre(3))
 			if (checkre(3))
 				getexp 1000,1000;
 				getexp 1000,1000;
 			else
 			else
@@ -1189,7 +1171,7 @@ pay_arche,103,165,5	script	Reidin Corse#tu	832,{
 
 
 // Seisner
 // Seisner
 //============================================================
 //============================================================
-pay_arche,84,139,3	script	Seisner	727,{
+pay_arche,84,139,3	script	Seisner	4_F_JOB_HUNTER,{
 	specialeffect EF_HIT2,"#Target";
 	specialeffect EF_HIT2,"#Target";
 	mes "[Seisner]";
 	mes "[Seisner]";
 	mes "Aaaah!";
 	mes "Aaaah!";
@@ -1216,8 +1198,8 @@ pay_arche,84,139,3	script	Seisner	727,{
 		mes "So Master Kavaruk";
 		mes "So Master Kavaruk";
 		mes "wants me to teach you";
 		mes "wants me to teach you";
 		mes "about Archers and Archery? Alright, what would you like to know more about?";
 		mes "about Archers and Archery? Alright, what would you like to know more about?";
-		next;
 		while(1){
 		while(1){
+			next;
 			switch(select("About Archers.:Stats for Archers:End Conversation.")){
 			switch(select("About Archers.:Stats for Archers:End Conversation.")){
 			case 1:
 			case 1:
 				mes "[Seisner]";
 				mes "[Seisner]";
@@ -1243,8 +1225,7 @@ pay_arche,84,139,3	script	Seisner	727,{
 				next;
 				next;
 				mes "[Seisner]";
 				mes "[Seisner]";
 				mes "Hunters can ultimately transcend into ^3131FFSnipers^000000, Bards into ^3131FFMinstrels^000000, and Dancers into ^3131FFGypsies^000000. I know that's pretty complex.";
 				mes "Hunters can ultimately transcend into ^3131FFSnipers^000000, Bards into ^3131FFMinstrels^000000, and Dancers into ^3131FFGypsies^000000. I know that's pretty complex.";
-				if(tu_archer01 == 1) set tu_archer01, 2;
-				next;  
+				if(tu_archer01 == 1) tu_archer01 = 2;
 				break;
 				break;
 			case 2:
 			case 2:
 				mes "[Seisner]";
 				mes "[Seisner]";
@@ -1270,8 +1251,8 @@ pay_arche,84,139,3	script	Seisner	727,{
 						mes "increase the amount of weight";
 						mes "increase the amount of weight";
 						mes "that any character can carry. So if you have more STR, you can carry around more arrows.";
 						mes "that any character can carry. So if you have more STR, you can carry around more arrows.";
 						next;
 						next;
-						if(tu_archer01 == 1) set tu_archer01, 2;
-						break;
+						if(tu_archer01 == 1) tu_archer01 = 2;
+						continue;
 					case 2:
 					case 2:
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "^FF3131AGI^000000 as you know, ";
 						mes "^FF3131AGI^000000 as you know, ";
@@ -1281,8 +1262,8 @@ pay_arche,84,139,3	script	Seisner	727,{
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "One of the drawbacks of being an Archer is having weaker strength and lower Dodge Rate. However, the Dodge Rate disadvantage is lessened by increasing your ^FF3131AGI^000000.";
 						mes "One of the drawbacks of being an Archer is having weaker strength and lower Dodge Rate. However, the Dodge Rate disadvantage is lessened by increasing your ^FF3131AGI^000000.";
 						next;
 						next;
-						if(tu_archer01 == 1) set tu_archer01, 2;
-						break;
+						if(tu_archer01 == 1) tu_archer01 = 2;
+						continue;
 					case 3:
 					case 3:
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "^3131FFVIT^000000 will increase";
 						mes "^3131FFVIT^000000 will increase";
@@ -1297,8 +1278,8 @@ pay_arche,84,139,3	script	Seisner	727,{
 						mes "VIT might be helpful";
 						mes "VIT might be helpful";
 						mes "depending on how you use it. Still, I wouldn't recommend focusing too much on increasing your VIT if you're an Archer.";
 						mes "depending on how you use it. Still, I wouldn't recommend focusing too much on increasing your VIT if you're an Archer.";
 						next;
 						next;
-						if(tu_archer01 == 1) set tu_archer01, 2;
-						break;
+						if(tu_archer01 == 1) tu_archer01 = 2;
+						continue;
 					case 4:
 					case 4:
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "^FF0000INT^000000 is more";
 						mes "^FF0000INT^000000 is more";
@@ -1313,8 +1294,8 @@ pay_arche,84,139,3	script	Seisner	727,{
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "For Hunters, one of the Second Job Classes for Archers, having higher INT will increase the damage inflicted by ^3131FFFalcons^000000.";
 						mes "For Hunters, one of the Second Job Classes for Archers, having higher INT will increase the damage inflicted by ^3131FFFalcons^000000.";
 						next;
 						next;
-						if(tu_archer01 == 1) set tu_archer01, 2;
-						break;
+						if(tu_archer01 == 1) tu_archer01 = 2;
+						continue;
 					case 5:
 					case 5:
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "Now DEX is almost";
 						mes "Now DEX is almost";
@@ -1332,8 +1313,8 @@ pay_arche,84,139,3	script	Seisner	727,{
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "Just like any other class, ^FF3131DEX^000000 increases ^3131FFAccuracy (HIT)^000000 and slightly enhances Attack Speed (ASPD).";
 						mes "Just like any other class, ^FF3131DEX^000000 increases ^3131FFAccuracy (HIT)^000000 and slightly enhances Attack Speed (ASPD).";
 						next;
 						next;
-						if(tu_archer01 == 1) set tu_archer01, 2;
-						break;
+						if(tu_archer01 == 1) tu_archer01 = 2;
+						continue;
 					case 6:
 					case 6:
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "^FF0000LUK^000000 affects your";
 						mes "^FF0000LUK^000000 affects your";
@@ -1343,18 +1324,16 @@ pay_arche,84,139,3	script	Seisner	727,{
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "For Hunters, one of the Second Classes for the Archer, LUK increases the chance of ^3131FFBlitz Beat^000000 occurring automatically. So Hunters who rely on their Falcons might want to invest in LUK.";
 						mes "For Hunters, one of the Second Classes for the Archer, LUK increases the chance of ^3131FFBlitz Beat^000000 occurring automatically. So Hunters who rely on their Falcons might want to invest in LUK.";
 						next;
 						next;
-						if(tu_archer01 == 1) set tu_archer01, 2;
-						break;
+						if(tu_archer01 == 1) tu_archer01 = 2;
+						continue;
 					case 7:
 					case 7:
 						mes "[Seisner]";
 						mes "[Seisner]";
 						mes "So is there";
 						mes "So is there";
 						mes "anything else that";
 						mes "anything else that";
 						mes "you want to ask me?";
 						mes "you want to ask me?";
-						next;
-						set .@exitwhile,1;
 						break;
 						break;
 					}
 					}
-					if (.@exitwhile) break;
+					break;
 				}
 				}
 				break;
 				break;
 			case 3:
 			case 3:
@@ -1378,7 +1357,7 @@ pay_arche,84,139,3	script	Seisner	727,{
 		mes "If you feel comfortable enough with the knowledge I've taught you, you should go back to Master Kavaruk. But if you still have questions, you can always come and ask me.";
 		mes "If you feel comfortable enough with the knowledge I've taught you, you should go back to Master Kavaruk. But if you still have questions, you can always come and ask me.";
 		close2;
 		close2;
 		specialeffect2 EF_WIND;
 		specialeffect2 EF_WIND;
-		set tu_archer01, 3;
+		tu_archer01 = 3;
 		if(JobLevel == 1){
 		if(JobLevel == 1){
 			getexp 0,30;
 			getexp 0,30;
 		} else if((JobLevel > 1) && (JobLevel < 11)){
 		} else if((JobLevel > 1) && (JobLevel < 11)){
@@ -1395,7 +1374,7 @@ pay_arche,84,139,3	script	Seisner	727,{
 
 
 // Target
 // Target
 //============================================================
 //============================================================
-pay_arche,76,135,3	script	#Target	111,{ end; }
+pay_arche,76,135,3	script	#Target	HIDDEN_NPC,{ end; }
 
 
 // Acolyte
 // Acolyte
 //============================================================
 //============================================================
@@ -1431,7 +1410,7 @@ pay_arche,76,135,3	script	#Target	111,{ end; }
 				mes "Wow!";
 				mes "Wow!";
 				mes "Thank you, thank you!";
 				mes "Thank you, thank you!";
 				mes "I''ll try my very best!";
 				mes "I''ll try my very best!";
-				set tu_archer01, 15;
+				tu_archer01 = 15;
 				close;
 				close;
 			case 2:
 			case 2:
 				mes "[Acolyte]";
 				mes "[Acolyte]";
@@ -1456,8 +1435,6 @@ pay_arche,76,135,3	script	#Target	111,{ end; }
 					mes "Y-you're a man!";
 					mes "Y-you're a man!";
 					mes "D-d-d-don't tease me";
 					mes "D-d-d-don't tease me";
 					mes "like that! I'm serious!";
 					mes "like that! I'm serious!";
-					set tu_archer01, 15;
-					close;
 				} else {
 				} else {
 					mes "And he's so brave";
 					mes "And he's so brave";
 					mes "and funny and smart.";
 					mes "and funny and smart.";
@@ -1468,12 +1445,12 @@ pay_arche,76,135,3	script	#Target	111,{ end; }
 					mes "^333333*Sniffle*^000000";
 					mes "^333333*Sniffle*^000000";
 					mes "I'll d-do my best to help you!";
 					mes "I'll d-do my best to help you!";
 					mes "I wish you both happiness! (Waaaaaah~!)";
 					mes "I wish you both happiness! (Waaaaaah~!)";
-					set tu_archer01, 15;
-					close;
 				}
 				}
+				tu_archer01 = 15;
+				close;
 			}
 			}
-			end;
-		} else {
+		}
+		else {
 			mes "^666666Zzzzz...^000000";
 			mes "^666666Zzzzz...^000000";
 			mes "Wh-wha...?";
 			mes "Wh-wha...?";
 			mes "Who are you?";
 			mes "Who are you?";
@@ -1487,7 +1464,6 @@ pay_arche,76,135,3	script	#Target	111,{ end; }
 				case 0: npcskill "AL_HEAL",3,90,62; break;
 				case 0: npcskill "AL_HEAL",3,90,62; break;
 				case 1: npcskill "AL_HEAL",9,90,62; break;
 				case 1: npcskill "AL_HEAL",9,90,62; break;
 				case 2: npcskill "AL_HEAL",8,90,62; break;
 				case 2: npcskill "AL_HEAL",8,90,62; break;
-				case 3: break;
 			}
 			}
 			switch(rand(3)) {
 			switch(rand(3)) {
 				case 0: npcskill "AL_INCAGI",1,0,0; break;
 				case 0: npcskill "AL_INCAGI",1,0,0; break;
@@ -1501,7 +1477,8 @@ pay_arche,76,135,3	script	#Target	111,{ end; }
 			}
 			}
 			close;
 			close;
 		}
 		}
-	} else if(tu_archer01 == 15){
+	}
+	else if(tu_archer01 == 15){
 		if((gettime(3) >= 18) && (gettime(3) < 22)){
 		if((gettime(3) >= 18) && (gettime(3) < 22)){
 			mes "^666666Zzzzz...^000000";
 			mes "^666666Zzzzz...^000000";
 			mes "Wh-wha...?";
 			mes "Wh-wha...?";
@@ -1528,7 +1505,6 @@ pay_arche,76,135,3	script	#Target	111,{ end; }
 			case 0: npcskill "AL_HEAL",3,90,62; break;
 			case 0: npcskill "AL_HEAL",3,90,62; break;
 			case 1: npcskill "AL_HEAL",10,90,62; break;
 			case 1: npcskill "AL_HEAL",10,90,62; break;
 			case 2: npcskill "AL_HEAL",8,90,62; break;
 			case 2: npcskill "AL_HEAL",8,90,62; break;
-			case 3: break;
 		}
 		}
 		switch(rand(3)) {
 		switch(rand(3)) {
 			case 0: npcskill "AL_INCAGI",1,0,0; break;
 			case 0: npcskill "AL_INCAGI",1,0,0; break;
@@ -1553,7 +1529,7 @@ pay_arche,76,135,3	script	#Target	111,{ end; }
 
 
 // Alchemist Guildmember
 // Alchemist Guildmember
 //============================================================
 //============================================================
-pay_arche,130,113,3	script	Alchemist Guildmember#tu	740,{
+pay_arche,130,113,3	script	Alchemist Guildmember#tu	2_M_ALCHE,{
 	mes "[Alchemist Guildmember]";
 	mes "[Alchemist Guildmember]";
 	if(tu_archer02 > 0){
 	if(tu_archer02 > 0){
 		if((countitem(1032) > 0) || (countitem(905) > 0 )){	// Blossom_Of_Maneater & Stem
 		if((countitem(1032) > 0) || (countitem(905) > 0 )){	// Blossom_Of_Maneater & Stem
@@ -1580,20 +1556,14 @@ pay_arche,130,113,3	script	Alchemist Guildmember#tu	740,{
 				mes "Flora field! I really";
 				mes "Flora field! I really";
 				mes "appreciate your help~";
 				mes "appreciate your help~";
 
 
-				set .@alche_f,countitem(1032); // Blossom_Of_Maneater
-				set .@alche_s,countitem(905); // Stem
-				set .@f_zeny, .@alche_f * 130;
-				set .@s_zeny, .@alche_s * 30;
-				set .@total_zeny, .@f_zeny + .@s_zeny;
-				if(countitem(1032) == 0){
-					delitem 905, .@alche_s; //Stem
-				} else if(countitem(905) == 0){
-					delitem 1032, .@alche_f; //Blossom_Of_Maneater
-				} else {
+				.@alche_f = countitem(1032); // Blossom_Of_Maneater
+				.@alche_s = countitem(905); // Stem
+				.@total_zeny = .@alche_f * 130 + .@alche_s * 30;
+				if (countitem(1032))
 					delitem 1032, .@alche_f; //Blossom_Of_Maneater
 					delitem 1032, .@alche_f; //Blossom_Of_Maneater
+				if (countitem(905))
 					delitem 905, .@alche_s; //Stem
 					delitem 905, .@alche_s; //Stem
-				}
-				set Zeny,Zeny+.@total_zeny;
+				Zeny = Zeny+.@total_zeny;
 				close;
 				close;
 			case 2:
 			case 2:
 				mes "[Alchemist Guildmember]";
 				mes "[Alchemist Guildmember]";
@@ -1627,7 +1597,7 @@ pay_arche,130,113,3	script	Alchemist Guildmember#tu	740,{
 
 
 // Arthail
 // Arthail
 //============================================================
 //============================================================
-prontera,126,335,5	script	Arthail	51,{
+prontera,126,335,5	script	Arthail	1_M_BARD,{
 	mes "[Arthail]";
 	mes "[Arthail]";
 	if(tu_archer02 < 3){
 	if(tu_archer02 < 3){
 		mes "I am the Bard";
 		mes "I am the Bard";
@@ -1679,16 +1649,15 @@ prontera,126,335,5	script	Arthail	51,{
 			next;
 			next;
 			mes "[Arthail]";
 			mes "[Arthail]";
 			mes "Would you please go and see if there's any news being spread around in that area for me?";
 			mes "Would you please go and see if there's any news being spread around in that area for me?";
-			set tu_archer02, 3;
+			tu_archer02 = 3;
 		}
 		}
-		close;
-	} else if(tu_archer02 == 3){
+	}
+	else if(tu_archer02 == 3){
 		mes "I'm ashamed to ask,";
 		mes "I'm ashamed to ask,";
 		mes "but would you go the fountain in Prontera's central plaza and see";
 		mes "but would you go the fountain in Prontera's central plaza and see";
 		mes "if there's any news?";
 		mes "if there's any news?";
-		close;
-
-	} else if(tu_archer02 == 4){
+	}
+	else if(tu_archer02 == 4){
 		mes "I see...";
 		mes "I see...";
 		mes "Nothing much.";
 		mes "Nothing much.";
 		mes "Another person";
 		mes "Another person";
@@ -1767,14 +1736,11 @@ prontera,126,335,5	script	Arthail	51,{
 		mes "I can't help it then.";
 		mes "I can't help it then.";
 		mes "I'd better go check";
 		mes "I'd better go check";
 		mes "this out on my own.";
 		mes "this out on my own.";
-		set tu_archer02, 5;
-		close;
-
-	} else if(tu_archer02 > 4 && tu_archer02 < 7){
+		tu_archer02 = 5;
+	}
+	else if(tu_archer02 > 4 && tu_archer02 < 7)
 		mes "^333333Zzzzz...^000000";
 		mes "^333333Zzzzz...^000000";
-		close;
-
-	} else if(tu_archer02 == 8){
+	else if(tu_archer02 == 8){
 		mes "Where did you go?";
 		mes "Where did you go?";
 		mes "I thought you might have been kidnapped since you weren't";
 		mes "I thought you might have been kidnapped since you weren't";
 		mes "here when I woke up.";
 		mes "here when I woke up.";
@@ -1798,17 +1764,18 @@ prontera,126,335,5	script	Arthail	51,{
 		mes "I guess I'll finally";
 		mes "I guess I'll finally";
 		mes "have a song that";
 		mes "have a song that";
 		mes "I can share with you.";
 		mes "I can share with you.";
-		set tu_archer02, 9;
-		close;
+		tu_archer02 = 9;
+	}
+	else {
+		mes "...";
+		mes "......";
 	}
 	}
-	mes "...";
-	mes "......";
 	close;
 	close;
 }
 }
 
 
 // New Guild Master
 // New Guild Master
 //============================================================
 //============================================================
-prontera,167,281,3	script	New Guild Master#tu	753,{
+prontera,167,281,3	script	New Guild Master#tu	4_M_MONK,{
 	mes "[New Guild Master]";
 	mes "[New Guild Master]";
 	mes "Hearken, all";
 	mes "Hearken, all";
 	mes "of you who seek";
 	mes "of you who seek";
@@ -1825,13 +1792,13 @@ prontera,167,281,3	script	New Guild Master#tu	753,{
 	mes "those who call themselves";
 	mes "those who call themselves";
 	mes "my comrades will never";
 	mes "my comrades will never";
 	mes "know the taste of defeat!";
 	mes "know the taste of defeat!";
-	if(tu_archer02 == 3) set tu_archer02, 4;
+	if(tu_archer02 == 3) tu_archer02 = 4;
 	close;
 	close;
 }
 }
 
 
 // Mage
 // Mage
 //============================================================
 //============================================================
-prontera,144,301,5	script	Mage#tu	123,{
+prontera,144,301,5	script	Mage#tu	2_F_MAGICMASTER,{
 	mes "[Mage]";
 	mes "[Mage]";
 	mes "Did you see that";
 	mes "Did you see that";
 	mes "new guild master?";
 	mes "new guild master?";
@@ -1859,7 +1826,7 @@ prontera,144,301,5	script	Mage#tu	123,{
 
 
 // Minister
 // Minister
 //============================================================
 //============================================================
-prt_castle,76,165,6	script	Minister#tu	55,{
+prt_castle,76,165,6	script	Minister#tu	1_M_JOBTESTER,{
 	mes "[Minister]";
 	mes "[Minister]";
 	mes "The royal family";
 	mes "The royal family";
 	mes "is extremely busy";
 	mes "is extremely busy";
@@ -1878,15 +1845,15 @@ prt_castle,76,165,6	script	Minister#tu	55,{
 		next;
 		next;
 		mes "[Minister]";
 		mes "[Minister]";
 		mes "Ah, there are a few stray cats running around, those Wild Roses, so those noises you heard must have been them. Everything is fine here in the palace.";
 		mes "Ah, there are a few stray cats running around, those Wild Roses, so those noises you heard must have been them. Everything is fine here in the palace.";
-		set tu_archer02, 6;
-		close;
-	} else if(tu_archer02 == 7){
+		tu_archer02 = 6;
+	}
+	else if(tu_archer02 == 7){
 		next;
 		next;
 		mes "^3355FFThe urgency that the Minister expressed earlier has been";
 		mes "^3355FFThe urgency that the Minister expressed earlier has been";
 		mes "replaced with a stone cold feeling of sternness. He probably won't tell you much more information,";
 		mes "replaced with a stone cold feeling of sternness. He probably won't tell you much more information,";
 		mes "no matter how much you ask him.";
 		mes "no matter how much you ask him.";
-		close;
-	} else if(tu_acolyte01 == 25){
+	}
+	else if(tu_acolyte01 == 25){
 		next;
 		next;
 		mes "["+strcharinfo(0)+"]";
 		mes "["+strcharinfo(0)+"]";
 		mes "Um...";
 		mes "Um...";
@@ -1913,20 +1880,20 @@ prt_castle,76,165,6	script	Minister#tu	55,{
 		next;
 		next;
 		mes "[Minister]";
 		mes "[Minister]";
 		mes "As a holy servant, I'm sure that you'll find plenty of other people who have need of your help and abilities outside of the palace.";
 		mes "As a holy servant, I'm sure that you'll find plenty of other people who have need of your help and abilities outside of the palace.";
-	} 
+	}
 	close;
 	close;
 }
 }
 
 
 // Range NPC
 // Range NPC
 //============================================================
 //============================================================
-prt_castle,94,150,4	script	#sound_tu	139,6,6,{
+prt_castle,94,150,4	script	#sound_tu	HIDDEN_WARP_NPC,6,6,{
 OnTouch_:
 OnTouch_:
 	if(tu_archer02 == 6) {
 	if(tu_archer02 == 6) {
 		mes "[Minister]";
 		mes "[Minister]";
 		mes "Contact the";
 		mes "Contact the";
 		mes "Prontera Church.";
 		mes "Prontera Church.";
 		mes "Hurry, this is urgent!";
 		mes "Hurry, this is urgent!";
-		set tu_archer02, 7;
+		tu_archer02 = 7;
 		close;
 		close;
 	}
 	}
 	end;
 	end;
@@ -1934,7 +1901,7 @@ OnTouch_:
 
 
 // Bishop Maugins
 // Bishop Maugins
 //============================================================
 //============================================================
-monk_in,19,43,1	script	Bishop Maugins	60,{
+monk_in,19,43,1	script	Bishop Maugins	1_M_PASTOR,{
 	mes "[Bishop Maugins]";
 	mes "[Bishop Maugins]";
 	if(tu_archer02 == 7){
 	if(tu_archer02 == 7){
 		mes "Greetings.";
 		mes "Greetings.";
@@ -1947,8 +1914,7 @@ monk_in,19,43,1	script	Bishop Maugins	60,{
 		mes "charge of that area. So";
 		mes "charge of that area. So";
 		mes "how may I help you?";
 		mes "how may I help you?";
 		next;
 		next;
-		switch(select("Has something happened to the Kingdom?:Nothing.")) {
-		case 1:
+		if (select("Has something happened to the Kingdom?:Nothing.") == 1) {
 			mes "[Bishop Maugins]";
 			mes "[Bishop Maugins]";
 			mes "...!!";
 			mes "...!!";
 			next;
 			next;
@@ -1961,8 +1927,7 @@ monk_in,19,43,1	script	Bishop Maugins	60,{
 			mes "Of course not!";
 			mes "Of course not!";
 			mes "The king and I regularly write to each other, but I haven't heard of anything in particular. Please don't worry yourself.";
 			mes "The king and I regularly write to each other, but I haven't heard of anything in particular. Please don't worry yourself.";
 			next;
 			next;
-			set tu_archer02, 8;
-			break;
+			tu_archer02 = 8;
 		}
 		}
 		mes "[Bishop Maugins]";
 		mes "[Bishop Maugins]";
 		mes "Good luck on";
 		mes "Good luck on";

+ 677 - 1217
npc/quests/first_class/tu_ma_th01.txt

@@ -1,1336 +1,796 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= Thief Mage Quest Story Mode
 //= Thief Mage Quest Story Mode
-//===== By: ================================================== 
+//===== By: ==================================================
 //= Fix up by Jukka
 //= Fix up by Jukka
-//===== Current Version: ===================================== 
-//= 1.3
-//===== Compatible With: ===================================== 
+//===== Current Version: =====================================
+//= 2.0
+//===== Compatible With: =====================================
 //= rAthena Project
 //= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= [Official Conversion]
 //= Battle Traces from Thief and Magician training quests.
 //= Battle Traces from Thief and Magician training quests.
-//===== Additional Comments: ================================= 
+//===== Additional Comments: =================================
 //= 1.0 Fully working
 //= 1.0 Fully working
 //= 1.1 optimized [Lupus]
 //= 1.1 optimized [Lupus]
 //= 1.2 Changed "battle_trace" to "Trace of Battle". [L0ne_W0lf]
 //= 1.2 Changed "battle_trace" to "Trace of Battle". [L0ne_W0lf]
 //= 1.3 Misc. updates. [L0ne_W0lf]
 //= 1.3 Misc. updates. [L0ne_W0lf]
-//============================================================ 
+//= 2.0 Clean-up. [Capuche]
+//============================================================
 
 
 // Battle Traces 1
 // Battle Traces 1
 //============================================================
 //============================================================
-moc_fild12,166,369,0	script	Trace of Battle#1	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 5){
-			mes "^3355FFYou find traces of poison";
-			mes "used in a battle. You sense";
-			mes "its potency and decide not";
-			mes "to get too close to it.^000000";
-			close;
-		} else if(tu_thief01 == 5){
-			mes "^3355FFYou find traces of poison";
-			mes "used in a battle. A feeling";
-			mes "of acute dizziness overcomes";
-			mes "you after examining the scene.^000000";
-			set tu_thief01, 6;
-			sc_start SC_Poison,60000,0;
-			specialeffect EF_VENOMDUST2;
-			close;
-		} else if(tu_thief01 == 6){
-			mes "^3355FFYou find traces of poison";
-			mes "used in a battle. A feeling";
-			mes "of acute dizziness overcomes";
-			mes "you after examining the scene.^000000";
-			sc_start SC_Poison,60000,0;
-			specialeffect EF_VENOMDUST2;
-			close;
-		} else if(tu_thief01 == 7){
-			mes "^3355FFYou find traces of poison";
-			mes "used in a battle. You sense";
-			mes "its potency and decide not";
-			mes "to get too close to it.^000000";
-			close;
-		} else if(tu_thief01 == 8){
-			mes "^3355FFThere are traces of a battle";
-			mes "that seem to be leading in";
-			mes "different directions. From the";
-			mes "peculiar smell that permeates";
-			mes "the area, it seems that some";
-			mes "kind of lethal poison was used.^000000";
-			next;
-			mes "^3355FFStill...";
-			mes "The trail of this";
-			mes "battle decidedly";
-			mes "heads southward.^000000";
-			set tu_thief01, 9;
-			close;
-		} else {
-			mes "^3355FFYou find signs of";
-			mes "a heated pursuit";
-			mes "that head south.";
-			close;
-		}
-	}
-	if(BaseClass == Job_Mage){
-		if(tu_magician01 < 8){
-			mes "^3355FFYou find traces of poison";
-			mes "used in a battle. You sense";
-			mes "its potency and decide not";
-			mes "to get too close to it.^000000";
+moc_fild12,166,369,0	script	Trace of Battle#1	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThere are signs that show";
+		mes "that some violent scuffle";
+		mes "might have occurred here,";
+		mes "but you can't tell what had";
+		mes "happened exactly...^000000";
+	} else if (tu_thief01 < 5 && .@class_thief || .@class_mage && tu_magician01 < 8) {
+		mes "^3355FFYou find traces of poison";
+		mes "used in a battle. You sense";
+		mes "its potency and decide not";
+		mes "to get too close to it.^000000";
+		if (.@class_mage)
 			specialeffect EF_VENOMDUST2;
 			specialeffect EF_VENOMDUST2;
-			close;
-		} else if(tu_magician01 == 8){
-			mes "^3355FFThere are traces of a battle";
-			mes "that seem to be leading in";
-			mes "different directions. From the";
-			mes "peculiar smell that permeates";
-			mes "the area, it seems that some";
-			mes "kind of lethal poison was used.^000000";
-			next;
-			mes "^3355FFStill...";
-			mes "The trail of this";
-			mes "battle decidedly";
-			mes "heads southward.^000000";
-			set tu_magician01, 9;
-			close;
-		} else {
-			mes "^3355FFYou find signs of";
-			mes "a heated pursuit";
-			mes "that head south.";
-			close;
-		}
+	} else if (tu_thief01 == 5 && .@class_thief) {
+		mes "^3355FFYou find traces of poison";
+		mes "used in a battle. A feeling";
+		mes "of acute dizziness overcomes";
+		mes "you after examining the scene.^000000";
+		tu_thief01 = 6;
+		sc_start SC_Poison,60000,0;
+		specialeffect EF_VENOMDUST2;
+	} else if (tu_thief01 == 6 && .@class_thief) {
+		mes "^3355FFYou find traces of poison";
+		mes "used in a battle. A feeling";
+		mes "of acute dizziness overcomes";
+		mes "you after examining the scene.^000000";
+		sc_start SC_Poison,60000,0;
+		specialeffect EF_VENOMDUST2;
+	} else if (tu_thief01 == 7 && .@class_thief) {
+		mes "^3355FFYou find traces of poison";
+		mes "used in a battle. You sense";
+		mes "its potency and decide not";
+		mes "to get too close to it.^000000";
+	} else if (.@class_thief && tu_thief01 == 8 || .@class_mage && tu_magician01 == 8) {
+		mes "^3355FFThere are traces of a battle";
+		mes "that seem to be leading in";
+		mes "different directions. From the";
+		mes "peculiar smell that permeates";
+		mes "the area, it seems that some";
+		mes "kind of lethal poison was used.^000000";
+		next;
+		mes "^3355FFStill...";
+		mes "The trail of this";
+		mes "battle decidedly";
+		mes "heads southward.^000000";
+		if (tu_magician01 == 8)
+			tu_magician01 = 9;
+		else
+			tu_thief01 = 9;
+	} else {
+		mes "^3355FFYou find signs of";
+		mes "a heated pursuit";
+		mes "that head south.";
 	}
 	}
-	mes "^3355FFThere are signs that show";
-	mes "that some violent scuffle";
-	mes "might have occurred here,";
-	mes "but you can't tell what had";
-	mes "happened exactly...^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 2
 // Battle Traces 2
 //============================================================
 //============================================================
-moc_fild12,173,215,0	script	Trace of Battle#2	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 9){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_thief01 == 9){
-			mes "^3355FFYou've found traces";
-			mes "of the pursuit which";
-			mes "continue eastward.^000000";
-			set tu_thief01, 10;
-			close;
-		} else {
-			mes "^3355FFThese traces of";
-			mes "the pursuit lead";
-			mes "towards the east.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 9){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_magician01 == 9){
-			mes "^3355FFYou've found traces";
-			mes "of the pursuit which";
-			mes "continue eastward.^000000";
-			set tu_magician01, 10;
-			close;
-		} else {
-			mes "^3355FFThese traces of";
-			mes "the pursuit lead";
-			mes "towards the east.^000000";
-			close;
-		}
+moc_fild12,173,215,0	script	Trace of Battle#2	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThere are signs that show";
+		mes "that some violent scuffle";
+		mes "might have occurred here,";
+		mes "but you can't tell what had";
+		mes "happened exactly...^000000";
+	} else if (tu_thief01 < 9 && .@class_thief || tu_magician01 < 9 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "that many people";
+		mes "have traveled through";
+		mes "this particular area.^000000";
+	} else if (tu_thief01 == 9 && .@class_thief || tu_magician01 == 9 && .@class_mage) {
+		mes "^3355FFYou've found traces";
+		mes "of the pursuit which";
+		mes "continue eastward.^000000";
+		if (tu_magician01 == 9)
+			tu_magician01 = 10;
+		else
+			tu_thief01 = 10;
+	} else {
+		mes "^3355FFThese traces of";
+		mes "the pursuit lead";
+		mes "towards the east.^000000";
 	}
 	}
-	mes "^3355FFThere are signs that show";
-	mes "that some violent scuffle";
-	mes "might have occurred here,";
-	mes "but you can't tell what had";
-	mes "happened exactly...^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 3
 // Battle Traces 3
 //============================================================
 //============================================================
-moc_fild12,276,165,0	script	Trace of Battle#3	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 10){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_thief01 == 10){
-			mes "^3355FFYou examine these traces";
-			mes "and notice that one set of";
-			mes "footprints looks almost too";
-			mes "pronounced, as if it had been";
-			mes "made for somebody to find.^000000";
-			set tu_thief01, 11;
-			close;
-		} else {
-			mes "^3355FFIt's a very";
-			mes "strange looking";
-			mes "set of footprints.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 10){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_magician01 == 10){
-			mes "^3355FFYou examine these traces";
-			mes "and notice that one set of";
-			mes "footprints looks almost too";
-			mes "pronounced, as if it had been";
-			mes "made for somebody to find.^000000";
-			set tu_magician01, 11;
-			close;
-		} else {
-			mes "^3355FFIt's a very";
-			mes "strange looking";
-			mes "set of footprints.^000000";
-			close;
-		}
+moc_fild12,276,165,0	script	Trace of Battle#3	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 10 && .@class_thief || tu_magician01 < 10 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "that many people";
+		mes "have traveled through";
+		mes "this particular area.^000000";
+	} else if (tu_thief01 == 10 && .@class_thief || tu_magician01 == 10 && .@class_mage) {
+		mes "^3355FFYou examine these traces";
+		mes "and notice that one set of";
+		mes "footprints looks almost too";
+		mes "pronounced, as if it had been";
+		mes "made for somebody to find.^000000";
+		if (tu_magician01 == 10)
+			tu_magician01 = 11;
+		else
+			tu_thief01 = 11;
+	} else {
+		mes "^3355FFIt's a very";
+		mes "strange looking";
+		mes "set of footprints.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 4
 // Battle Traces 4
 //============================================================
 //============================================================
-moc_fild11,39,163,0	script	Trace of Battle#4	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 11){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_thief01 == 11){
-			mes "^3355FFFrom these traces,";
-			mes "you see that another";
-			mes "set of footprints has";
-			mes "been added. It looks like";
-			mes "someone } else got involved.";
-			mes "These prints are distinctly";
-			mes "clearer and much smaller.^000000";
-			set tu_thief01, 12;
-			close;
-		} else {
-			mes "^3355FFFrom these traces,";
-			mes "you see that another";
-			mes "person has gotten involved";
-			mes "in this heated scuffle.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 11){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_magician01 == 11){
-			mes "^3355FFFrom these traces,";
-			mes "you see that another";
-			mes "set of footprints has";
-			mes "been added. It looks like";
-			mes "someone } else got involved.";
-			mes "These prints are distinctly";
-			mes "clearer and much smaller.^000000";
-			set tu_magician01, 12;
-			close;
-		} else {
-			mes "^3355FFFrom these traces,";
-			mes "you see that another";
-			mes "person has gotten involved";
-			mes "in this heated scuffle.^000000";
-			close;
-		}
+moc_fild11,39,163,0	script	Trace of Battle#4	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThere are signs that show";
+		mes "that some violent scuffle";
+		mes "might have occurred here,";
+		mes "but you can't tell what had";
+		mes "happened exactly...^000000";
+	} else if (tu_thief01 < 11 && .@class_thief || tu_magician01 < 11 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "that many people";
+		mes "have traveled through";
+		mes "this particular area.^000000";
+	} else if (tu_thief01 == 11 && .@class_thief || tu_magician01 == 11 && .@class_mage) {
+		mes "^3355FFFrom these traces,";
+		mes "you see that another";
+		mes "set of footprints has";
+		mes "been added. It looks like";
+		mes "someone else got involved.";
+		mes "These prints are distinctly";
+		mes "clearer and much smaller.^000000";
+		if (tu_magician01 == 11)
+			tu_magician01 = 12;
+		else
+			tu_thief01 = 12;
+	} else {
+		mes "^3355FFFrom these traces,";
+		mes "you see that another";
+		mes "person has gotten involved";
+		mes "in this heated scuffle.^000000";
 	}
 	}
-	mes "^3355FFThere are signs that show";
-	mes "that some violent scuffle";
-	mes "might have occurred here,";
-	mes "but you can't tell what had";
-	mes "happened exactly...^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 5
 // Battle Traces 5
 //============================================================
 //============================================================
-moc_fild11,205,52,0	script	Trace of Battle#5	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 12){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_thief01 == 12){
-			mes "^3355FFThe traces of the battle";
-			mes "now split and head towards";
-			mes "the north and south. However,^000000";
-			if(countitem(506) == 0){
-				mes "^3355FFthere is a puddle of strong poison that you must neutralize before you can investigate this scene.^000000";
+moc_fild11,205,52,0	script	Trace of Battle#5	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 12 && .@class_thief || tu_magician01 < 12 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "that many people";
+		mes "have traveled through";
+		mes "this particular area.^000000";
+	} else if (tu_thief01 == 12 && .@class_thief || tu_magician01 == 12 && .@class_mage) {
+		mes "^3355FFThe traces of the battle";
+		mes "now split and head towards";
+		mes "the north and south. However,^000000";
+		if (countitem(506) == 0) {// Green_Potion
+			mes "^3355FFthere is a puddle of strong poison that you must neutralize before you can investigate this scene.^000000";
+			close;
+		}
+		mes "^3355FFthere is a puddle of strong poison that you must neutralize before you can investigate this scene.^000000";
+		next;
+		mes "^3355FFFortunately, you can";
+		mes "temporarily nullify the";
+		mes "poison by using one";
+		mes "of your Green Potions.^000000";
+		next;
+		switch(select("Use Green Potion.:Don't use it.")) {
+		case 1:
+			mes "^3355FFThe poison weakens";
+			mes "and some of it evaporates,";
+			mes "revealing a piece of cloth that";
+			mes "was hidden in that puddle.^000000";
+			next;
+			switch(select("Don't investigate.:Investigate.")) {
+			case 1:
+				mes "["+strcharinfo(0)+"]";
+				mes "A piece of cloth";
+				mes "is nothing to be";
+				mes "concerned about.";
 				close;
 				close;
-			} else {
-				mes "^3355FFthere is a puddle of strong poison that you must neutralize before you can investigate this scene.^000000";
-				next;
-				mes "^3355FFFortunately, you can";
-				mes "temporarily nullify the";
-				mes "poison by using one";
-				mes "of your Green Potions.^000000";
+			case 2:
+				mes "["+strcharinfo(0)+"]";
+				mes "Hey... There's";
+				mes "blood on this cloth";
+				mes "and some writing on";
+				mes "it that I can't recognize.";
+				mes "Hopefully, this'll provide";
+				mes "some sort of clue to all this?";
+				if (tu_thief01 == 12)
+					tu_thief01 = 13;
+				else
+					tu_magician01 = 13;
 				next;
 				next;
-				switch(select("Use Green Potion.:Don't use it.")){
-				case 1:
-					mes "^3355FFThe poison weakens";
-					mes "and some of it evaporates,";
-					mes "revealing a piece of cloth that";
-					mes "was hidden in that puddle.^000000";
-					next;
-					switch(select("Don't investigate.:Investigate.")){
-					case 1:
-						mes "["+strcharinfo(0)+"]";
-						mes "A piece of cloth";
-						mes "is nothing to be";
-						mes "concerned about.";
-						close;
-					case 2:
-						mes "["+strcharinfo(0)+"]";
-						mes "Hey... There's";
-						mes "blood on this cloth";
-						mes "and some writing on";
-						mes "it that I can't recognize.";
-						mes "Hopefully, this'll provide";
-						mes "some sort of clue to all this?";
-						set tu_thief01, 13;
-						next;
-						mes "^3355FFYou take the piece";
-						mes "of cloth from the puddle";
-						mes "of poison and keep it with you.^000000";
-						close;
-					}
-				case 2:
-					mes "["+strcharinfo(0)+"]";
-					mes "Hmm...";
-					mes "It'll probably be";
-					mes "faster if I follow this";
-					mes "trail, rather than stop to";
-					mes "investigate this scene.";
-					close;
-				}
-			}
-		} else {
-			mes "^3355FFYou can't find";
-			mes "anything } else here,";
-			mes "aside from the traces";
-			mes "that split and lead both";
-			mes "northward and southward.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 12){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_magician01 == 12){
-			mes "^3355FFThe traces of the battle";
-			mes "now split and head towards";
-			mes "the north and south. However,^000000";
-			if(countitem(506) == 0){
-				mes "^3355FFthere is a puddle of strong poison that you must neutralize before you can investigate this scene.^000000";
+				mes "^3355FFYou take the piece";
+				mes "of cloth from the puddle";
+				mes "of poison and keep it with you.^000000";
 				close;
 				close;
-			} else {
-				mes "^3355FFthere is a puddle of strong poison that you must neutralize before you can investigate this scene.^000000";
-				next;
-				mes "^3355FFFortunately, you can";
-				mes "temporarily nullify the";
-				mes "poison by using one";
-				mes "of your Green Potions.^000000";
-				next;
-				switch(select("Use Green Potion.:Don't use it.")){
-				case 1:
-					mes "^3355FFThe poison weakens";
-					mes "and some of it evaporates,";
-					mes "revealing a piece of cloth that";
-					mes "was hidden in that puddle.^000000";
-					next;
-					switch(select("Don't investigate.:Investigate.")){
-					case 1:
-						mes "["+strcharinfo(0)+"]";
-						mes "A piece of cloth";
-						mes "is nothing to be";
-						mes "concerned about.";
-						close;
-					case 2:
-						mes "["+strcharinfo(0)+"]";
-						mes "Hey... There's";
-						mes "blood on this cloth";
-						mes "and some writing on";
-						mes "it that I can't recognize.";
-						mes "Hopefully, this'll provide";
-						mes "some sort of clue to all this?";
-						set tu_magician01,13;
-						next;
-						mes "^3355FFYou take the piece";
-						mes "of cloth from the puddle";
-						mes "of poison and keep it with you.^000000";
-						close;
-					}
-				case 2:
-					mes "["+strcharinfo(0)+"]";
-					mes "Hmm...";
-					mes "It'll probably be";
-					mes "faster if I follow this";
-					mes "trail, rather than stop to";
-					mes "investigate this scene.";
-					close;
-				}
 			}
 			}
-		} else {
-			mes "^3355FFYou can't find";
-			mes "anything } else here,";
-			mes "aside from the traces";
-			mes "that split and lead both";
-			mes "northward and southward.^000000";
-			close;
-		}
+		case 2:
+			mes "["+strcharinfo(0)+"]";
+			mes "Hmm...";
+			mes "It'll probably be";
+			mes "faster if I follow this";
+			mes "trail, rather than stop to";
+			mes "investigate this scene.";
+			close;
+		}
+	} else {
+		mes "^3355FFYou can't find";
+		mes "anything else here,";
+		mes "aside from the traces";
+		mes "that split and lead both";
+		mes "northward and southward.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 6
 // Battle Traces 6
 //============================================================
 //============================================================
-moc_fild11,226,235,0	script	Trace of Battle#6	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 13){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else {
-			mes "^3355FFThese footprints";
-			mes "look like they're";
-			mes "heading towards the";
-			mes "north from the south.";
-			mes "But you can't really";
-			mes "be sure just yet.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 13){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else {
-			mes "^3355FFThese footprints";
-			mes "look like they're";
-			mes "heading towards the";
-			mes "north from the south.";
-			mes "But you can't really";
-			mes "be sure just yet.^000000";
-			close;
-		}
+moc_fild11,226,235,0	script	Trace of Battle#6	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 13 && .@class_thief || tu_magician01 < 13 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "that many people";
+		mes "have traveled through";
+		mes "this particular area.^000000";
+	} else {
+		mes "^3355FFThese footprints";
+		mes "look like they're";
+		mes "heading towards the";
+		mes "north from the south.";
+		mes "But you can't really";
+		mes "be sure just yet.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 7
 // Battle Traces 7
 //============================================================
 //============================================================
-moc_fild11,184,342,0	script	Trace of Battle#7	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 13){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else {
-			mes "^3355FFThe trail here looks pretty";
-			mes "muddled, since it looks like";
-			mes "they battled here for quite a";
-			mes "while. But the footprints are";
-			mes "definitely heading south.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 13){
-			mes "^3355FFThere are signs";
-			mes "that many people";
-			mes "have traveled through";
-			mes "this particular area.^000000";
-			close;
-		} else {
-			mes "^3355FFThe trail here looks pretty";
-			mes "muddled, since it looks like";
-			mes "they battled here for quite a";
-			mes "while. But the footprints are";
-			mes "definitely heading south.^000000";
-			close;
-		}
+moc_fild11,184,342,0	script	Trace of Battle#7	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 13 && .@class_thief || tu_magician01 < 13 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "that many people";
+		mes "have traveled through";
+		mes "this particular area.^000000";
+	} else {
+		mes "^3355FFThe trail here looks pretty";
+		mes "muddled, since it looks like";
+		mes "they battled here for quite a";
+		mes "while. But the footprints are";
+		mes "definitely heading south.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 8
 // Battle Traces 8
 //============================================================
 //============================================================
-moc_fild17,213,358,0	script	Trace of Battle#8	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 13){
-			mes "^3355FFThere are two";
-			mes "distinct sets of";
-			mes "footprints in this";
-			mes "area, but they don't";
-			mes "hold any significance";
-			mes "right about now.^000000";
-			close;
-		} else if(tu_thief01 == 13){
-			mes "^3355FFAround here, it";
-			mes "looks like there are";
-			mes "only two sets of footprints.";
-			mes "What happened to the other";
-			mes "set that you found earlier?^000000";
-			set tu_thief01, 14;
-			close;
-		} else {
-			mes "^3355FFFrom the evidence";
-			mes "that you've found here,";
-			mes "it looks like the battle";
-			mes "involves only two people";
-			mes "from this point onward.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 13){
-			mes "^3355FFThere are two";
-			mes "distinct sets of";
-			mes "footprints in this";
-			mes "area, but they don't";
-			mes "hold any significance";
-			mes "right about now.^000000";
-			close;
-		} else if(tu_magician01 == 13){
-			mes "^3355FFAround here, it";
-			mes "looks like there are";
-			mes "only two sets of footprints.";
-			mes "What happened to the other";
-			mes "set that you found earlier?^000000";
-			set tu_magician01, 14;
-			close;
-		} else {
-			mes "^3355FFFrom the evidence";
-			mes "that you've found here,";
-			mes "it looks like the battle";
-			mes "involves only two people";
-			mes "from this point onward.^000000";
-			close;
-		}
+moc_fild17,213,358,0	script	Trace of Battle#8	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 13 && .@class_thief || tu_magician01 < 13 && .@class_mage) {
+		mes "^3355FFThere are two";
+		mes "distinct sets of";
+		mes "footprints in this";
+		mes "area, but they don't";
+		mes "hold any significance";
+		mes "right about now.^000000";
+	} else if (tu_thief01 == 13 && .@class_thief || tu_magician01 == 13 && .@class_mage) {
+		mes "^3355FFAround here, it";
+		mes "looks like there are";
+		mes "only two sets of footprints.";
+		mes "What happened to the other";
+		mes "set that you found earlier?^000000";
+		if (tu_magician01 == 13)
+			tu_magician01 = 14;
+		else
+			tu_thief01 = 14;
+	} else {
+		mes "^3355FFFrom the evidence";
+		mes "that you've found here,";
+		mes "it looks like the battle";
+		mes "involves only two people";
+		mes "from this point onward.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 9
 // Battle Traces 9
 //============================================================
 //============================================================
-moc_fild17,228,274,0	script	Trace of Battle#9	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 14){
-			mes "^3355FFTraces of some";
-			mes "sort of battle are";
-			mes "scattered all over";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_thief01 == 14){
-			mes "^3355FFYou follow the trail";
-			mes "and although traces from";
-			mes "the north and southeast mix";
-			mes "together, it looks like the battle continues towards the east.";
-			mes "But you should check this";
-			mes "spot a little bit more...^000000";
-			set tu_thief01, 15;
-			close;
-		} else if(tu_thief01 == 15){
-			set .@seek_tm, rand(1,10);
-			if(.@seek_tm == 7){
-				mes "^3355FFAfter investigating this";
-				mes "area more thoroughly,";
-				mes "you find another piece of";
-				mes "cloth stained with blood.";
-				mes "You decide to keep it with";
-				mes "you, hoping that it will";
-				mes "provide more clues.^000000";
-				set tu_thief01, 16;
-				close;
-			} else {
-				mes "^3355FFYou don't find anything,";
-				mes "but you still can't shake";
-				mes "the feeling that there is";
-				mes "some important clue that";
-				mes "you have to find here. It won't hurt to keep investigating here.^000000";
-				close;
-			}
-		} else {
-			mes "^3355FFYou better continue";
-			mes "following this trail";
-			mes "which leads westward.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 14){
-			mes "^3355FFTraces of some";
-			mes "sort of battle are";
-			mes "scattered all over";
-			mes "this particular area.^000000";
-			close;
-		} else if(tu_magician01 == 14){
-			mes "^3355FFYou follow the trail";
-			mes "and although traces from";
-			mes "the north and southeast mix";
-			mes "together, it looks like the battle continues towards the east.";
-			mes "But you should check this";
-			mes "spot a little bit more...^000000";
-			set tu_magician01, 15;
-			close;
-		} else if(tu_magician01 == 15){
-			set .@seek_tm1, rand(1,10);
-			if(.@seek_tm1 == 7){
-				mes "^3355FFAfter investigating this";
-				mes "area more thoroughly,";
-				mes "you find another piece of";
-				mes "cloth stained with blood.";
-				mes "You decide to keep it with";
-				mes "you, hoping that it will";
-				mes "provide more clues.^000000";
-				set tu_magician01, 16;
-				close;
-			} else {
-				mes "^3355FFYou don't find anything,";
-				mes "but you still can't shake";
-				mes "the feeling that there is";
-				mes "some important clue that";
-				mes "you have to find here. It won't hurt to keep investigating here.^000000";
-				close;
-			}
-		} else {
-			mes "^3355FFYou better continue";
-			mes "following this trail";
-			mes "which leads westward.^000000";
-			close;
-		}
+moc_fild17,228,274,0	script	Trace of Battle#9	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 14 && .@class_thief || tu_magician01 < 14 && .@class_mage) {
+		mes "^3355FFTraces of some";
+		mes "sort of battle are";
+		mes "scattered all over";
+		mes "this particular area.^000000";
+	} else if (tu_thief01 == 14 && .@class_thief || tu_magician01 == 14 && .@class_mage) {
+		mes "^3355FFYou follow the trail";
+		mes "and although traces from";
+		mes "the north and southeast mix";
+		mes "together, it looks like the battle continues towards the east.";
+		mes "But you should check this";
+		mes "spot a little bit more...^000000";
+		if (tu_magician01 == 14)
+			tu_magician01 = 15;
+		else
+			tu_thief01 = 15;
+	} else if (tu_thief01 == 15 && .@class_thief || tu_magician01 == 15 && .@class_mage) {
+		if (rand(1,10) == 7) {
+			mes "^3355FFAfter investigating this";
+			mes "area more thoroughly,";
+			mes "you find another piece of";
+			mes "cloth stained with blood.";
+			mes "You decide to keep it with";
+			mes "you, hoping that it will";
+			mes "provide more clues.^000000";
+			if (tu_magician01 == 15)
+				tu_magician01 = 16;
+			else
+				tu_thief01 = 16;
+		} else {
+			mes "^3355FFYou don't find anything,";
+			mes "but you still can't shake";
+			mes "the feeling that there is";
+			mes "some important clue that";
+			mes "you have to find here. It won't hurt to keep investigating here.^000000";
+		}
+	} else {
+		mes "^3355FFYou better continue";
+		mes "following this trail";
+		mes "which leads westward.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 10
 // Battle Traces 10
 //============================================================
 //============================================================
-moc_fild17,34,292,0	script	Trace of Battle#10	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 16){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_thief01 == 16){
-			mes "^3355FFThe lead set of footprints,";
-			mes "probably belonging to the one";
-			mes "who was being pursued, look";
-			mes "more erratic, as if exhaustion";
-			mes "and desperation were setting in. These traces lead to the west.^000000";
-			set tu_thief01, 17;
-			close;
-		} else {
-			mes "^3355FFThe trail from";
-			mes "this point heads";
-			mes "towards the west.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 16){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_magician01 == 16){
-			mes "^3355FFThe lead set of footprints,";
-			mes "probably belonging to the one";
-			mes "who was being pursued, look";
-			mes "more erratic, as if exhaustion";
-			mes "and desperation were setting in. These traces lead to the west.^000000";
-			set tu_magician01, 17;
-			close;
-		} else {
-			mes "^3355FFThe trail from";
-			mes "this point heads";
-			mes "towards the west.^000000";
-			close;
-		}
+moc_fild17,34,292,0	script	Trace of Battle#10	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 16 && .@class_thief || tu_magician01 < 16 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "showing that a lot";
+		mes "of people were in";
+		mes "this area earlier.^000000";
+	} else if (tu_thief01 == 16 && .@class_thief || tu_magician01 == 16 && .@class_mage) {
+		mes "^3355FFThe lead set of footprints,";
+		mes "probably belonging to the one";
+		mes "who was being pursued, look";
+		mes "more erratic, as if exhaustion";
+		mes "and desperation were setting in. These traces lead to the west.^000000";
+		if (tu_magician01 == 16)
+			tu_magician01 = 17;
+		else
+			tu_thief01 = 17;
+	} else {
+		mes "^3355FFThe trail from";
+		mes "this point heads";
+		mes "towards the west.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 11
 // Battle Traces 11
 //============================================================
 //============================================================
-moc_fild18,346,296,0	script	Trace of Battle#11	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 17){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_thief01 == 17){
-			mes "^3355FFFollowing the";
-			mes "trail, you see signs";
-			mes "that blood was spilled";
-			mes "in this area. It looks like";
-			mes "someone was injured";
-			mes "pretty badly around here.^000000";
-			set tu_thief01, 18;
-			close;
-		} else {
-			mes "^3355FFSince someone involved";
-			mes "in this conflict was bleeding,";
-			mes "further traces of this pursuit";
-			mes "might be easier to find now.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 17){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_magician01 == 17){
-			mes "^3355FFFollowing the";
-			mes "trail, you see signs";
-			mes "that blood was spilled";
-			mes "in this area. It looks like";
-			mes "someone was injured";
-			mes "pretty badly around here.^000000";
-			set tu_magician01, 18;
-			close;
-		} else {
-			mes "^3355FFSince someone involved";
-			mes "in this conflict was bleeding,";
-			mes "further traces of this pursuit";
-			mes "might be easier to find now.^000000";
-			close;
-		}
+moc_fild18,346,296,0	script	Trace of Battle#11	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 17 && .@class_thief || tu_magician01 < 17 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "showing that a lot";
+		mes "of people were in";
+		mes "this area earlier.^000000";
+	} else if (tu_thief01 == 17 && .@class_thief || tu_magician01 == 17 && .@class_mage) {
+		mes "^3355FFFollowing the";
+		mes "trail, you see signs";
+		mes "that blood was spilled";
+		mes "in this area. It looks like";
+		mes "someone was injured";
+		mes "pretty badly around here.^000000";
+		if (tu_magician01 == 17)
+			tu_magician01 = 18;
+		else
+			tu_thief01 = 18;
+	} else {
+		mes "^3355FFSince someone involved";
+		mes "in this conflict was bleeding,";
+		mes "further traces of this pursuit";
+		mes "might be easier to find now.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 12
 // Battle Traces 12
 //============================================================
 //============================================================
-moc_fild18,309,257,0	script	Trace of Battle#12	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 18){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_thief01 == 18){
-			mes "^3355FFThese traces lead";
-			mes "northward and it looks";
-			mes "like whoever is doing";
-			mes "the chasing is getting";
-			mes "much closer to his prey.^000000";
-			set tu_thief01, 19;
-			close;
-		} else {
-			mes "^3355FFThe trail of this";
-			mes "pursuit now leads";
-			mes "towards the north.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 18){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_magician01 == 18){
-			mes "^3355FFThese traces lead";
-			mes "northward and it looks";
-			mes "like whoever is doing";
-			mes "the chasing is getting";
-			mes "much closer to his prey.^000000";
-			set tu_magician01, 19;
-			close;
-		} else {
-			mes "^3355FFThe trail of this";
-			mes "pursuit now leads";
-			mes "towards the north.^000000";
-			close;
-		}
+moc_fild18,309,257,0	script	Trace of Battle#12	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 18 && .@class_thief || tu_magician01 < 18 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "showing that a lot";
+		mes "of people were in";
+		mes "this area earlier.^000000";
+	} else if (tu_thief01 == 18 && .@class_thief || tu_magician01 == 18 && .@class_mage) {
+		mes "^3355FFThese traces lead";
+		mes "northward and it looks";
+		mes "like whoever is doing";
+		mes "the chasing is getting";
+		mes "much closer to his prey.^000000";
+		if (tu_magician01 == 18)
+			tu_magician01 = 19;
+		else
+			tu_thief01 = 19;
+	} else {
+		mes "^3355FFThe trail of this";
+		mes "pursuit now leads";
+		mes "towards the north.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 13
 // Battle Traces 13
 //============================================================
 //============================================================
-moc_fild18,177,333,0	script	Trace of Battle#13	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 19){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_thief01 == 19){
-			mes "^3355FFJudging from these";
-			mes "traces, it looks like";
-			mes "even more people have";
-			mes "joined the battle which";
-			mes "now seems to be leading";
-			mes "in the southwest direction.^000000";
-			set tu_thief01, 20;
-			close;
-		} else {
-			mes "^3355FFIt looks like";
-			mes "the battle heads";
-			mes "towards the southwest";
-			mes "from this particular point.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 19){
-			mes "A large group of people seem to have gone by.";
-			close;
-		} else if(tu_magician01 == 19){
-			mes "^3355FFJudging from these";
-			mes "traces, it looks like";
-			mes "even more people have";
-			mes "joined the battle which";
-			mes "now seems to be leading";
-			mes "in the southwest direction.^000000";
-			set tu_magician01, 20;
-			close;
-		} else {
-			mes "^3355FFIt looks like";
-			mes "the battle heads";
-			mes "towards the southwest";
-			mes "from this particular point.^000000";
-			close;
-		}
+moc_fild18,177,333,0	script	Trace of Battle#13	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 19 && .@class_thief) {
+		mes "^3355FFThere are signs";
+		mes "showing that a lot";
+		mes "of people were in";
+		mes "this area earlier.^000000";
+	} else if (tu_magician01 < 19 && .@class_mage) {
+		mes "A large group of people seem to have gone by.";
+	} else if (tu_thief01 == 19 && .@class_thief || tu_magician01 == 19 && .@class_mage) {
+		mes "^3355FFJudging from these";
+		mes "traces, it looks like";
+		mes "even more people have";
+		mes "joined the battle which";
+		mes "now seems to be leading";
+		mes "in the southwest direction.^000000";
+		if (tu_magician01 == 19)
+			tu_magician01 = 20;
+		else
+			tu_thief01 = 20;
+	} else {
+		mes "^3355FFIt looks like";
+		mes "the battle heads";
+		mes "towards the southwest";
+		mes "from this particular point.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 14
 // Battle Traces 14
 //============================================================
 //============================================================
-moc_fild18,111,303,0	script	Trace of Battle#14	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 20){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_thief01 == 20){
-			mes "^3355FFIn this area, it looks";
-			mes "like even more people";
-			mes "joined in this battle and";
-			mes "the pursuit clearly heads";
-			mes "towards the south.^000000";
-			set tu_thief01, 21;
-			close;
-		} else {
-			mes "^3355FFThe trail of";
-			mes "this battle heads";
-			mes "towards the south.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 20){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_magician01 == 20){
-			mes "^3355FFIn this area, it looks";
-			mes "like even more people";
-			mes "joined in this battle and";
-			mes "the pursuit clearly heads";
-			mes "towards the south.^000000";
-			set tu_magician01, 21;
-			close;
-		} else {
-			mes "^3355FFThe trail of";
-			mes "this battle heads";
-			mes "towards the south.^000000";
-			close;
-		}
+moc_fild18,111,303,0	script	Trace of Battle#14	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 20 && .@class_thief || tu_magician01 < 20 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "showing that a lot";
+		mes "of people were in";
+		mes "this area earlier.^000000";
+	} else if (tu_thief01 == 20 && .@class_thief || tu_magician01 == 20 && .@class_mage) {
+		mes "^3355FFIn this area, it looks";
+		mes "like even more people";
+		mes "joined in this battle and";
+		mes "the pursuit clearly heads";
+		mes "towards the south.^000000";
+		if (tu_magician01 == 20)
+			tu_magician01 = 21;
+		else
+			tu_thief01 = 21;
+	} else {
+		mes "^3355FFThe trail of";
+		mes "this battle heads";
+		mes "towards the south.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 15
 // Battle Traces 15
 //============================================================
 //============================================================
-moc_fild18,109,197,0	script	Trace of Battle#15	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 21){
-			mes "^3355FFThere are signs";
-			mes "showing that a lot";
-			mes "of people were in";
-			mes "this area earlier.^000000";
-			close;
-		} else if(tu_thief01 == 21){
-			mes "^3355FFThis area is clearly";
-			mes "marked with signs";
-			mes "of a violent battle, with";
-			mes "traces of poison strewn";
-			mes "all over the ground.^000000";
+moc_fild18,109,197,0	script	Trace of Battle#15	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 21 && .@class_thief) {
+		mes "^3355FFThere are signs";
+		mes "showing that a lot";
+		mes "of people were in";
+		mes "this area earlier.^000000";
+	} else if (tu_magician01 < 21 && .@class_mage)
+		mes "A large group of people seem to have gone by.";
+	else if (tu_thief01 == 21 && .@class_thief || tu_magician01 == 21 && .@class_mage) {
+		mes "^3355FFThis area is clearly";
+		mes "marked with signs";
+		mes "of a violent battle, with";
+		mes "traces of poison strewn";
+		mes "all over the ground.^000000";
+		next;
+		switch(select("Continue following the traces.:Further investigate the area.")) {
+		case 1:
+			mes "^3355FFYou examine the";
+			mes "trail, but can't really";
+			mes "discern the direction";
+			mes "in which the battle";
+			mes "continues...^000000";
+			close;
+		case 2:
+			mes "^3355FFYou find a bunch of";
+			mes "traps that use different";
+			mes "kinds of poison. The ones";
+			mes "that have been set off are";
+			mes "mixed with the ones which";
+			mes "haven't been triggered.^000000";
+			if (tu_thief01 == 21)
+				tu_thief01 = 22;
+			else
+				tu_magician01 = 22;
+			close;
+		}
+	} else if (tu_thief01 == 22 && .@class_thief || tu_magician01 == 22 && .@class_mage) {
+		if (rand(1,3) == 3) {
+			mes "^3355FFOne trap in particular";
+			mes "stands out to you more";
+			mes "than the rest. Perhaps";
+			mes "you should pour some";
+			mes "Green Potion on it to";
+			mes "neutralize it first.^000000";
 			next;
 			next;
-			switch(select("Continue following the traces.:Further investigate the area.")){
+			switch(select("Pour Green Potion.:Don't use Green Potion.")) {
 			case 1:
 			case 1:
-				mes "^3355FFYou examine the";
-				mes "trail, but can't really";
-				mes "discern the direction";
-				mes "in which the battle";
-				mes "continues...^000000";
-				close;
-			case 2:
-				mes "^3355FFYou find a bunch of";
-				mes "traps that use different";
-				mes "kinds of poison. The ones";
-				mes "that have been set off are";
-				mes "mixed with the ones which";
-				mes "haven't been triggered.^000000";
-				set tu_thief01, 22;
-				close;
-			}
-		} else if(tu_thief01 == 22){
-			set .@trap_tm, rand(1,3);
-			if(.@trap_tm == 3){
-				mes "^3355FFOne trap in particular";
-				mes "stands out to you more";
-				mes "than the rest. Perhaps";
-				mes "you should pour some";
-				mes "Green Potion on it to";
-				mes "neutralize it first.^000000";
-				next;
-				switch(select("Pour Green Potion.:Don't use Green Potion.")){
-				case 1:
-					if(countitem(506) < 1){
-						mes "^3355FFUnfortunately, you";
-						mes "don't have a Green";
-						mes "Potion that you can";
-						mes "use to pour on this trap...^000000";
-						close;
-					} else {
-						mes "^3355FFPouring that";
-						mes "Green Potion didn't";
-						mes "really make anything";
-						mes "happen. Perhaps you";
-						mes "should try something else.^000000";
-						delitem 506,1; //Green_Potion
-						set tu_thief01, 23;
-						close;
-					}
-				case 2:
-					mes "["+strcharinfo(0)+"]";
-					mes "I guess...";
-					mes "I'll try investigating";
-					mes "this area a little more?";
-					close;
-				}
-			} else {
-				mes "^3355FFBy sheer accident,";
-				mes "you set off one of";
-				mes "the traps in the area.^000000";
-				sc_start SC_Poison,60000,0;
-				specialeffect EF_VENOMDUST2;
-				percentheal -30,0;
-				close;
-			}
-		} else if(tu_thief01 == 23){
-			if(countitem(511) > 0 || countitem(716) > 0){
-				if(countitem(511) > 0 && countitem(716) > 0){
-					mes "^3355FFYou try grinding";
-					mes "a Green Herb and";
-					mes "sprinkling it on the";
-					mes "trap and then place";
-					mes "a Red Gemstone on it.";
-					mes "The gem glows and";
-					mes "slowly melts away...^000000";
-					next;
-					mes "^3355FFAlthough you don't";
-					mes "fully understand the";
-					mes "science of using poisons";
-					mes "or antidotes, you managed";
-					mes "to successfully dismantle";
-					mes "the trap. Now you can safely";
-					mes "check what might be inside.^000000";
-					delitem 511,1; //Green_Herb
-					delitem 716,1; //Red_Gemstone
-					set tu_thief01, 24;
-					close;
-				} else if(countitem(511) > 0){
-					mes "^3355FFYou should try to";
-					mes "dismantle this trap";
-					mes "by using other catalysts";
-					mes "related to the curing or";
-					mes "use of poison. You do have";
-					mes "a Green Herb on you, so you";
-					mes "try sprinkling it on the trap.^000000";
-					next;
-					mes "^3355FFHowever, nothing";
-					mes "happens. It seems that";
-					mes "you need another catalyst";
-					mes "in addition to the Green Herb";
-					mes "that you have in order to";
-					mes "dismantle this trap.^000000";
+				if (countitem(506) < 1) {// Green_Potion
+					mes "^3355FFUnfortunately, you";
+					mes "don't have a Green";
+					mes "Potion that you can";
+					mes "use to pour on this trap...^000000";
 					close;
 					close;
 				} else {
 				} else {
-					mes "^3355FFYou should try to";
-					mes "dismantle this trap";
-					mes "by using other catalysts";
-					mes "related to the curing or use";
-					mes "of poison. You do have a";
-					mes "Red Gemstone, so you grind";
-					mes "it and sprinkle it on the trap.^000000";
-					next;
-					mes "^3355FFHowever, nothing";
-					mes "happens. It seems that";
-					mes "you need another catalyst to";
-					mes "use with the Red Gemstone";
-					mes "that you have in order to";
-					mes "dismantle this trap.^000000";
+					mes "^3355FFPouring that";
+					mes "Green Potion didn't";
+					mes "really make anything";
+					mes "happen. Perhaps you";
+					mes "should try something else.^000000";
+					delitem 506,1; //Green_Potion
+					if (tu_thief01 == 22)
+						tu_thief01 = 23;
+					else
+						tu_magician01 = 23;
 					close;
 					close;
 				}
 				}
-			} else {
-				mes "^3355FFYou should try to";
-				mes "dismantle this trap";
-				mes "by using other catalysts";
-				mes "related to the curing or";
-				mes "use of poison. But what";
-				mes "items should you bring?^000000";
-				close;
-			}
-		} else if(tu_thief01 == 24){
-			mes "^3355FFInside the dismantled";
-			mes "trap, you find another";
-			mes "piece of strange cloth";
-			mes "that's stained with blood.";
-			mes "You take it with you in";
-			mes "hopes that it provides";
-			mes "some kind of evidence.^000000";
-			set tu_thief01, 25;
-			close;
-		} else {
-			mes "^3355FFYou examine the area";
-			mes "a little further and guess";
-			mes "that the battle might head";
-			mes "towards the south.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 21){
-			mes "A large group of people seem to have gone by.";
-			close;
-		} else if(tu_magician01 == 21){
-			mes "^3355FFThis area is clearly";
-			mes "marked with signs";
-			mes "of a violent battle, with";
-			mes "traces of poison strewn";
-			mes "all over the ground.^000000";
-			next;
-			switch(select("Continue following the traces.:Further investigate the area.")){
-			case 1:
-				mes "^3355FFYou examine the";
-				mes "trail, but can't really";
-				mes "discern the direction";
-				mes "in which the battle";
-				mes "continues...^000000";
-				close;
 			case 2:
 			case 2:
-				mes "^3355FFYou find a bunch of";
-				mes "traps that use different";
-				mes "kinds of poison. The ones";
-				mes "that have been set off are";
-				mes "mixed with the ones which";
-				mes "haven't been triggered.^000000";
-				set tu_magician01, 22;
-				close;
-			}
-		} else if(tu_magician01 == 22){
-			set .@trap_tm, rand(1,3);
-			if(.@trap_tm == 3){
-				mes "^3355FFOne trap in particular";
-				mes "stands out to you more";
-				mes "than the rest. Perhaps";
-				mes "you should pour some";
-				mes "Green Potion on it to";
-				mes "neutralize it first.^000000";
-				next;
-				switch(select("Pour Green Potion.:Don't use Green Potion.")){
-				case 1:
-					if(countitem(506) < 1){
-						mes "^3355FFUnfortunately, you";
-						mes "don't have a Green";
-						mes "Potion that you can";
-						mes "use to pour on this trap...^000000";
-						close;
-					} else {
-						mes "^3355FFPouring that";
-						mes "Green Potion didn't";
-						mes "really make anything";
-						mes "happen. Perhaps you";
-						mes "should try something else.^000000";
-						delitem 506,1; //Green_Potion
-						set tu_magician01, 23;
-						close;
-					}
-				case 2:
-					mes "["+strcharinfo(0)+"]";
-					mes "I guess...";
-					mes "I'll try investigating";
-					mes "this area a little more?";
-					close;
-				}
-			} else {
-				mes "^3355FFBy sheer accident,";
-				mes "you set off one of";
-				mes "the traps in the area.^000000";
-				sc_start SC_Poison,60000,0;
-				specialeffect EF_VENOMDUST2;
-				percentheal -30,0;
-				close;
-			}
-		} else if(tu_magician01 == 23){
-			if(countitem(511) > 0 || countitem(716) > 0){
-				if(countitem(511) > 0 && countitem(716) > 0){
-					mes "^3355FFYou try grinding";
-					mes "a Green Herb and";
-					mes "sprinkling it on the";
-					mes "trap and then place";
-					mes "a Red Gemstone on it.";
-					mes "The gem glows and";
-					mes "slowly melts away...^000000";
-					next;
-					mes "^3355FFAlthough you don't";
-					mes "fully understand the";
-					mes "science of using poisons";
-					mes "or antidotes, you managed";
-					mes "to successfully dismantle";
-					mes "the trap. Now you can safely";
-					mes "check what might be inside.^000000";
-					delitem 511,1; //Green_Herb
-					delitem 716,1; //Red_Gemstone
-					set tu_magician01, 24;
-					close;
-				} else if(countitem(511) > 0){
-					mes "^3355FFYou should try to";
-					mes "dismantle this trap";
-					mes "by using other catalysts";
-					mes "related to the curing or";
-					mes "use of poison. You do have";
-					mes "a Green Herb on you, so you";
-					mes "try sprinkling it on the trap.^000000";
-					next;
-					mes "^3355FFHowever, nothing";
-					mes "happens. It seems that";
-					mes "you need another catalyst";
-					mes "in addition to the Green Herb";
-					mes "that you have in order to";
-					mes "dismantle this trap.^000000";
-					close;
-				} else {
-					mes "^3355FFYou should try to";
-					mes "dismantle this trap";
-					mes "by using other catalysts";
-					mes "related to the curing or use";
-					mes "of poison. You do have a";
-					mes "Red Gemstone, so you grind";
-					mes "it and sprinkle it on the trap.^000000";
-					next;
-					mes "^3355FFHowever, nothing";
-					mes "happens. It seems that";
-					mes "you need another catalyst to";
-					mes "use with the Red Gemstone";
-					mes "that you have in order to";
-					mes "dismantle this trap.^000000";
-					close;
-				}
-			} else {
-				mes "^3355FFYou should try to";
-				mes "dismantle this trap";
-				mes "by using other catalysts";
-				mes "related to the curing or";
-				mes "use of poison. But what";
-				mes "items should you bring?^000000";
+				mes "["+strcharinfo(0)+"]";
+				mes "I guess...";
+				mes "I'll try investigating";
+				mes "this area a little more?";
 				close;
 				close;
 			}
 			}
-		} else if(tu_magician01 == 24){
-			mes "^3355FFInside the dismantled";
-			mes "trap, you find another";
-			mes "piece of strange cloth";
-			mes "that's stained with blood.";
-			mes "You take it with you in";
-			mes "hopes that it provides";
-			mes "some kind of evidence.^000000";
-			set tu_magician01, 25;
-			close;
 		} else {
 		} else {
-			mes "^3355FFYou examine the area";
-			mes "a little further and guess";
-			mes "that the battle might head";
-			mes "towards the south.^000000";
-			close;
-		}
-
+			mes "^3355FFBy sheer accident,";
+			mes "you set off one of";
+			mes "the traps in the area.^000000";
+			sc_start SC_Poison,60000,0;
+			specialeffect EF_VENOMDUST2;
+			percentheal -30,0;
+		}
+	} else if (tu_thief01 == 23 && .@class_thief || tu_magician01 == 23 && .@class_mage) {
+		if (countitem(511) > 0 && countitem(716) > 0) {
+			mes "^3355FFYou try grinding";
+			mes "a Green Herb and";
+			mes "sprinkling it on the";
+			mes "trap and then place";
+			mes "a Red Gemstone on it.";
+			mes "The gem glows and";
+			mes "slowly melts away...^000000";
+			next;
+			mes "^3355FFAlthough you don't";
+			mes "fully understand the";
+			mes "science of using poisons";
+			mes "or antidotes, you managed";
+			mes "to successfully dismantle";
+			mes "the trap. Now you can safely";
+			mes "check what might be inside.^000000";
+			delitem 511,1; //Green_Herb
+			delitem 716,1; //Red_Gemstone
+			if (tu_thief01 == 23)
+				tu_thief01 = 24;
+			else
+				tu_magician01 = 24;
+		} else if (countitem(511) > 0) {
+			mes "^3355FFYou should try to";
+			mes "dismantle this trap";
+			mes "by using other catalysts";
+			mes "related to the curing or";
+			mes "use of poison. You do have";
+			mes "a Green Herb on you, so you";
+			mes "try sprinkling it on the trap.^000000";
+			next;
+			mes "^3355FFHowever, nothing";
+			mes "happens. It seems that";
+			mes "you need another catalyst";
+			mes "in addition to the Green Herb";
+			mes "that you have in order to";
+			mes "dismantle this trap.^000000";
+		} else if (countitem(716) > 0) {
+			mes "^3355FFYou should try to";
+			mes "dismantle this trap";
+			mes "by using other catalysts";
+			mes "related to the curing or use";
+			mes "of poison. You do have a";
+			mes "Red Gemstone, so you grind";
+			mes "it and sprinkle it on the trap.^000000";
+			next;
+			mes "^3355FFHowever, nothing";
+			mes "happens. It seems that";
+			mes "you need another catalyst to";
+			mes "use with the Red Gemstone";
+			mes "that you have in order to";
+			mes "dismantle this trap.^000000";
+		} else {
+			mes "^3355FFYou should try to";
+			mes "dismantle this trap";
+			mes "by using other catalysts";
+			mes "related to the curing or";
+			mes "use of poison. But what";
+			mes "items should you bring?^000000";
+		}
+	} else if (tu_thief01 == 24 && .@class_thief || tu_magician01 == 24 && .@class_mage) {
+		mes "^3355FFInside the dismantled";
+		mes "trap, you find another";
+		mes "piece of strange cloth";
+		mes "that's stained with blood.";
+		mes "You take it with you in";
+		mes "hopes that it provides";
+		mes "some kind of evidence.^000000";
+		if (tu_thief01 == 24)
+			tu_thief01 = 25;
+		else
+			tu_magician01 = 25;
+	} else {
+		mes "^3355FFYou examine the area";
+		mes "a little further and guess";
+		mes "that the battle might head";
+		mes "towards the south.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
 }
 }
 
 
 // Battle Traces 16
 // Battle Traces 16
 //============================================================
 //============================================================
-moc_fild18,156,96,0	script	Trace of Battle#16	844,{
-	if(BaseClass == Job_Thief){
-		if(tu_thief01 < 25){
-			mes "^3355FFThere are signs";
-			mes "that a large group";
-			mes "of people have been in";
-			mes "this area for some reason.^000000";
-			close;
-		} else if(tu_thief01 == 25){
-			mes "^3355FFThese traces lead";
-			mes "to the edge of the cliff.";
-			mes "marking the end of the trail.";
-			mes "Apparently, the one who was";
-			mes "being chased met his fate here.^000000";
-			next;
-			mes "^3355FFThere are many footprints";
-			mes "leading to the edge of the";
-			mes "cliff and all of them leave";
-			mes "this scene, save for the set";
-			mes "of footprints that distinctly";
-			mes "belong to the person who";
-			mes "was pursued all this time...^3355FF";
-			next;
-			mes "^3355FFIt looks like you've";
-			mes "learned all that you can";
-			mes "from this investigation. You";
-			mes "better return and report your";
-			mes "findings to Yierhan soon.^000000";
-			set tu_thief01, 26;
-			close;
-		} else {
-			mes "^3355FFThis is the end";
-			mes "of the trail. There";
-			mes "aren't any more traces";
-			mes "of the battle left to find.^000000";
-			close;
-		}
-	} else if(BaseClass == Job_Mage){
-		if(tu_magician01 < 25){
-			mes "^3355FFThere are signs";
-			mes "that a large group";
-			mes "of people have been in";
-			mes "this area for some reason.^000000";
-			close;
-		} else if(tu_magician01 == 25){
-			mes "^3355FFThese traces lead";
-			mes "to the edge of the cliff.";
-			mes "marking the end of the trail.";
-			mes "Apparently, the one who was";
-			mes "being chased met his fate here.^000000";
-			next;
-			mes "^3355FFThere are many footprints";
-			mes "leading to the edge of the";
-			mes "cliff and all of them leave";
-			mes "this scene, save for the set";
-			mes "of footprints that distinctly";
-			mes "belong to the person who";
-			mes "was pursued all this time...^3355FF";
-			next;
-			mes "^3355FFIt looks like you've";
-			mes "learned all that you can";
-			mes "from this investigation. You";
-			mes "better return and report your";
-			mes "findings to Yierhan soon.^000000";
-			set tu_magician01, 26;
-			close;
-		} else {
-			mes "^3355FFThis is the end";
-			mes "of the trail. There";
-			mes "aren't any more traces";
-			mes "of the battle left to find.^000000";
-			close;
-		}
+moc_fild18,156,96,0	script	Trace of Battle#16	CLEAR_NPC,{
+	.@class_thief = ( BaseClass == Job_Thief );
+	.@class_mage = ( BaseClass == Job_Mage );
+	if (.@class_thief == 0 && .@class_mage == 0 || eaclass()&EAJL_BABY) {
+		mes "^3355FFThese look like";
+		mes "traces of some kind";
+		mes "of pursuit or battle, but";
+		mes "you can't really tell for sure.^000000";
+	} else if (tu_thief01 < 25 && .@class_thief || tu_magician01 < 25 && .@class_mage) {
+		mes "^3355FFThere are signs";
+		mes "that a large group";
+		mes "of people have been in";
+		mes "this area for some reason.^000000";
+	} else if (tu_thief01 == 25 && .@class_thief || tu_magician01 == 25 && .@class_mage) {
+		mes "^3355FFThese traces lead";
+		mes "to the edge of the cliff.";
+		mes "marking the end of the trail.";
+		mes "Apparently, the one who was";
+		mes "being chased met his fate here.^000000";
+		next;
+		mes "^3355FFThere are many footprints";
+		mes "leading to the edge of the";
+		mes "cliff and all of them leave";
+		mes "this scene, save for the set";
+		mes "of footprints that distinctly";
+		mes "belong to the person who";
+		mes "was pursued all this time...^3355FF";
+		next;
+		mes "^3355FFIt looks like you've";
+		mes "learned all that you can";
+		mes "from this investigation. You";
+		mes "better return and report your";
+		mes "findings to Yierhan soon.^000000";
+		if (tu_magician01 == 25)
+			tu_magician01 = 26;
+		else
+			tu_thief01 = 26;
+	} else {
+		mes "^3355FFThis is the end";
+		mes "of the trail. There";
+		mes "aren't any more traces";
+		mes "of the battle left to find.^000000";
 	}
 	}
-	mes "^3355FFThese look like";
-	mes "traces of some kind";
-	mes "of pursuit or battle, but";
-	mes "you can't really tell for sure.^000000";
 	close;
 	close;
-}
+}

+ 79 - 112
npc/quests/first_class/tu_magician01.txt

@@ -1,35 +1,35 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= Magician Class Tutorial and Job Specific Quest
 //= Magician Class Tutorial and Job Specific Quest
-//===== By: ================================================== 
+//===== By: ==================================================
 //= Fix up by Jukka
 //= Fix up by Jukka
-//===== Current Version: ===================================== 
-//= 1.4
-//===== Compatible With: ===================================== 
+//===== Current Version: =====================================
+//= 2.0
+//===== Compatible With: =====================================
 //= rAthena Project
 //= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= [Official Conversion]
 //= Magician training quest.
 //= Magician training quest.
-//===== Additional Comments: ================================= 
+//===== Additional Comments: =================================
 //= 1.0 Fully working
 //= 1.0 Fully working
 //= 1.1 Optimized [Lupus]
 //= 1.1 Optimized [Lupus]
 //= 1.2 Fixed experience gains to match upcoming rate adjustments. [SinSloth]
 //= 1.2 Fixed experience gains to match upcoming rate adjustments. [SinSloth]
 //= 1.3 Misc. updates. [L0ne_W0lf]
 //= 1.3 Misc. updates. [L0ne_W0lf]
 //= 1.4 Updated to match the official script. [Euphy]
 //= 1.4 Updated to match the official script. [Euphy]
-//============================================================ 
+//= 2.0 Replaced occurrence of PcName and clean-up. [Capuche]
+//============================================================
 
 
 // Sign
 // Sign
 //============================================================
 //============================================================
-geffen,61,174,4	script	Sign#M	111,{
+geffen,61,174,4	script	Sign#M	HIDDEN_NPC,{
 	mes "- Mage Job Change -";
 	mes "- Mage Job Change -";
 	close;
 	close;
 }
 }
 
 
 // New Mage Manager
 // New Mage Manager
 //============================================================
 //============================================================
-geffen,67,180,4	script	New Mage Manager#M	102,{
+geffen,67,180,4	script	New Mage Manager#M	8_F,{
 	mes "[Mana]";
 	mes "[Mana]";
 	if(Class == Job_Novice){
 	if(Class == Job_Novice){
-		mes "[Mana]";
 		mes "You're not ready for";
 		mes "You're not ready for";
 		mes "any of the training I have";
 		mes "any of the training I have";
 		mes "to offer. You'll have to train";
 		mes "to offer. You'll have to train";
@@ -37,7 +37,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 		mes "a Mage first. Alright, dear?";
 		mes "a Mage first. Alright, dear?";
 		close;
 		close;
 	}
 	}
-	if(BaseClass != Job_Mage){
+	if(BaseClass != Job_Mage || eaclass()&EAJL_BABY){
 		mes "You know, sometimes";
 		mes "You know, sometimes";
 		mes "other jobs might look a";
 		mes "other jobs might look a";
 		mes "little better in some battle";
 		mes "little better in some battle";
@@ -46,8 +46,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 		mes "anyone can do what you do~";
 		mes "anyone can do what you do~";
 		close;
 		close;
 	}
 	}
-	if(eaclass()&(EAJL_UPPER|EAJL_2|EAJL_THIRD) && tu_magician01 < 7){
-		mes "[Mana]";
+	if(Class != Job_Mage && tu_magician01 < 7){
 		mes "Although I offer magic";
 		mes "Although I offer magic";
 		mes "training, it's not very helpful";
 		mes "training, it's not very helpful";
 		mes "if you're already experienced";
 		mes "if you're already experienced";
@@ -133,7 +132,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 		mes "sitting! I'm bushed, so it's";
 		mes "sitting! I'm bushed, so it's";
 		mes "time for a break. But we'll";
 		mes "time for a break. But we'll";
 		mes "continue this later, okay?";
 		mes "continue this later, okay?";
-		set tu_magician01, 1;
+		tu_magician01 = 1;
 		if (checkre(3))
 		if (checkre(3))
 			getexp BaseLevel*3,BaseLevel*2;
 			getexp BaseLevel*3,BaseLevel*2;
 		else
 		else
@@ -165,8 +164,8 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 		mes "In other words, even the same properties";
 		mes "In other words, even the same properties";
 		mes "have different features that must be considered.";
 		mes "have different features that must be considered.";
 		mes "I will explain the properties now.";
 		mes "I will explain the properties now.";
-		next;
 		while((1)){
 		while((1)){
+			next;
 			switch(select("^ff0000Fire^000000", "^5C4033Earth^000000", "^93DB70Wind^000000", "^0000FFWater^000000", "^CFB53BGhost^000000", "Quit.")){
 			switch(select("^ff0000Fire^000000", "^5C4033Earth^000000", "^93DB70Wind^000000", "^0000FFWater^000000", "^CFB53BGhost^000000", "Quit.")){
 			case 1:
 			case 1:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -211,8 +210,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "only slightly injured and the";
 				mes "only slightly injured and the";
 				mes "Fire Wall won't necessarily";
 				mes "Fire Wall won't necessarily";
 				mes "block its approach. So beware!";
 				mes "block its approach. So beware!";
-				set .@eread_1,1;
-				next;
+				.@eread_1 = 1;
 				break;
 				break;
 			case 2:
 			case 2:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -246,8 +244,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "afterwards, like Fire Bolt and";
 				mes "afterwards, like Fire Bolt and";
 				mes "Fire Ball, to take advantage of";
 				mes "Fire Ball, to take advantage of";
 				mes "the monster's Earth property.";
 				mes "the monster's Earth property.";
-				set .@eread_2,1;
-				next;
+				.@eread_2 = 1;
 				break;
 				break;
 			case 3:
 			case 3:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -284,8 +281,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "the ^93DB70Wind^000000 property skills";
 				mes "the ^93DB70Wind^000000 property skills";
 				mes "that we Mages can use are";
 				mes "that we Mages can use are";
 				mes "Lighning Bolt and Thunder Storm.";
 				mes "Lighning Bolt and Thunder Storm.";
-				set .@eread_3,1;
-				next;
+				.@eread_3 = 1;
 				break;
 				break;
 			case 4:
 			case 4:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -321,8 +317,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "actually freeze monsters.";
 				mes "actually freeze monsters.";
 				mes "While monsters are frozen by";
 				mes "While monsters are frozen by";
 				mes "Frost Diver, they're considered Water monsters. Interesting, huh?";
 				mes "Frost Diver, they're considered Water monsters. Interesting, huh?";
-				set .@eread_4,1;
-				next;
+				.@eread_4 = 1;
 				break;
 				break;
 			case 5:
 			case 5:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -354,8 +349,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "shield against long range";
 				mes "shield against long range";
 				mes "attacks or strong property";
 				mes "attacks or strong property";
 				mes "attacks, so be really careful!";
 				mes "attacks, so be really careful!";
-				set .@eread_5,1;
-				next;
+				.@eread_5 = 1;
 				break;
 				break;
 			case 6:
 			case 6:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -371,18 +365,15 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 					mes "Alrighty, we'll";
 					mes "Alrighty, we'll";
 					mes "move on to the next";
 					mes "move on to the next";
 					mes "subject then. Ho ho ho~!";
 					mes "subject then. Ho ho ho~!";
-					set tu_magician01,2;
+					tu_magician01 = 2;
 					specialeffect2 EF_HIT5;
 					specialeffect2 EF_HIT5;
-					if(.@eread_1) getexp 150,70;
-					if(.@eread_2) getexp 150,70;
-					if(.@eread_3) getexp 150,70;
-					if(.@eread_4) getexp 150,70;
-					if(.@eread_5) getexp 150,70;
+					.@total = .@eread_1 + .@eread_2 + .@eread_3 + .@eread_4 + .@eread_5;
+					if (.@total) getexp (.@total*150),(.@total*70);
+					close;
 				}
 				}
-				close;
+				break;
 			}
 			}
 		}
 		}
-		break;
 	case 2:
 	case 2:
 		mes "I know that the concept";
 		mes "I know that the concept";
 		mes "of properties might be";
 		mes "of properties might be";
@@ -458,75 +449,66 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 		mes "until you've collected";
 		mes "until you've collected";
 		mes "10 Chrysalis from them.";
 		mes "10 Chrysalis from them.";
 		mes "Then bring them to me, okay?";
 		mes "Then bring them to me, okay?";
-		set tu_magician01, 3;
+		tu_magician01 = 3;
 		getexp 400,200;
 		getexp 400,200;
 		specialeffect2 EF_HIT5;
 		specialeffect2 EF_HIT5;
 		close;
 		close;
 	case 3:
 	case 3:
-		mes "Ah, you're back?";
-		mes "Let's see if you gathered";
-		mes "all 10 Chrysalis from hunting";
-		mes "all of those Pupa. Hmmmm...";
-		next;
-		if (countitem(915) < 10) {
-			mes "[Mana]";
-			mes "Aw, you don't";
-			mes "have enough of";
-			mes "them yet. Head west";
-			mes "from here and hunt Pupa";
-			mes "to get more Chrysalis, okay?";
-			mes "For now, I'll just heal you up.";
-			set tu_magician01, 4;
-			percentheal 100,100;
-			close;
-		} else {
-			mes "[Mana]";
-			mes "...Nine, ten.";
-			mes "Alright, you pass!";
-			mes "By now, you must be more";
-			mes "used to using your skills, huh?";
-			mes "Anyway, let me know when you're ready for the next lesson, okay?";
-			set tu_magician01, 5;
-			getexp 400,200;
-			specialeffect2 EF_HIT5;
-			close;
-		}
 	case 4:
 	case 4:
-		mes "So...";
-		mes "Did you get";
-		mes "10 Chrysalis";
-		mes "from hunting Pupa";
-		mes "like I asked? I hope so...";
-		mes "Because I'm going to check~";
+		if (tu_magician01 == 3) {
+			mes "Ah, you're back?";
+			mes "Let's see if you gathered";
+			mes "all 10 Chrysalis from hunting";
+			mes "all of those Pupa. Hmmmm...";
+		}
+		else {
+			mes "So...";
+			mes "Did you get";
+			mes "10 Chrysalis";
+			mes "from hunting Pupa";
+			mes "like I asked? I hope so...";
+			mes "Because I'm going to check~";
+		}
 		next;
 		next;
-		if(countitem(915) < 10){
-			mes "[Mana]";
-			mes "Whoa, you need";
-			mes "more than just this.";
-			mes "I know you can do it...";
-			mes "Pupas are completely";
-			mes "defenseless monsters!";
-			close;
-		} else {
-			mes "[Mana]";
+		mes "[Mana]";
+		if (countitem(915) < 10){// Chrysalis
+			if (tu_magician01 == 3) {
+				mes "Aw, you don't";
+				mes "have enough of";
+				mes "them yet. Head west";
+				mes "from here and hunt Pupa";
+				mes "to get more Chrysalis, okay?";
+				mes "For now, I'll just heal you up.";
+				tu_magician01 = 4;
+				percentheal 100,100;
+			}
+			else {
+				mes "Whoa, you need";
+				mes "more than just this.";
+				mes "I know you can do it...";
+				mes "Pupas are completely";
+				mes "defenseless monsters!";
+			}
+		}
+		else {
 			mes "...Nine, ten.";
 			mes "...Nine, ten.";
 			mes "Alright, you pass!";
 			mes "Alright, you pass!";
 			mes "By now, you must be more";
 			mes "By now, you must be more";
 			mes "used to using your skills, huh?";
 			mes "used to using your skills, huh?";
 			mes "Anyway, let me know when you're ready for the next lesson, okay?";
 			mes "Anyway, let me know when you're ready for the next lesson, okay?";
-			set tu_magician01, 5;
+			tu_magician01 = 5;
 			getexp 400,200;
 			getexp 400,200;
 			specialeffect2 EF_HIT5;
 			specialeffect2 EF_HIT5;
-			close;
 		}
 		}
+		close;
 	case 5:
 	case 5:
 		mes "Now I'll tell you";
 		mes "Now I'll tell you";
 		mes "what I know about the";
 		mes "what I know about the";
 		mes "more advanced Mage";
 		mes "more advanced Mage";
 		mes "skills. Which one would";
 		mes "skills. Which one would";
 		mes "you like me to explain?";
 		mes "you like me to explain?";
-		next;
 		while(1){
 		while(1){
+			next;
 			switch(select("Soul Strike:Safety Wall:Fire Ball:Frost Diver:Thunderstorm:Fire Wall:Energy Coat:Quit.")) {
 			switch(select("Soul Strike:Safety Wall:Fire Ball:Frost Diver:Thunderstorm:Fire Wall:Energy Coat:Quit.")) {
 			case 1:
 			case 1:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -544,8 +526,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "of Soul Strike and increase";
 				mes "of Soul Strike and increase";
 				mes "that skill's level, it will grow in strength and you'll be able";
 				mes "that skill's level, it will grow in strength and you'll be able";
 				mes "to cast it much more quickly.";
 				mes "to cast it much more quickly.";
-				set .@skill_e1,1;
-				next;
+				.@skill_e1 = 1;
 				break;
 				break;
 			case 2:
 			case 2:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -564,8 +545,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "certain number of attacks,";
 				mes "certain number of attacks,";
 				mes "depending on the level of the";
 				mes "depending on the level of the";
 				mes "Safety Wall skill that you use.";
 				mes "Safety Wall skill that you use.";
-				set .@skill_e2,1;
-				next;
+				.@skill_e2 = 1;
 				break;
 				break;
 			case 3:
 			case 3:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -583,8 +563,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "the range of the skill. Make";
 				mes "the range of the skill. Make";
 				mes "good use of the destructive";
 				mes "good use of the destructive";
 				mes "power of the Fire Ball!";
 				mes "power of the Fire Ball!";
-				next;
-				set .@skill_e3,1;
+				.@skill_e3 = 1;
 				break;
 				break;
 			case 4:
 			case 4:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -610,8 +589,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "skill, its damage and chance";
 				mes "skill, its damage and chance";
 				mes "of freezing monsters will also";
 				mes "of freezing monsters will also";
 				mes "increase. Pretty dangerous, eh? ^FFFFFFkamenriderblack^000000";
 				mes "increase. Pretty dangerous, eh? ^FFFFFFkamenriderblack^000000";
-				set .@skill_e4,1;
-				next;
+				.@skill_e4 = 1;
 				break;
 				break;
 			case 5:
 			case 5:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -629,8 +607,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "within a certain range.";
 				mes "within a certain range.";
 				mes "It's an incredibly potent";
 				mes "It's an incredibly potent";
 				mes "ground targeting attack.";
 				mes "ground targeting attack.";
-				set .@skill_e5,1;
-				next;
+				.@skill_e5 = 1;
 				break;
 				break;
 			case 6:
 			case 6:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -655,8 +632,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "Fire Well strategically";
 				mes "Fire Well strategically";
 				mes "and effectively, it can";
 				mes "and effectively, it can";
 				mes "be a very powerful skill~";
 				mes "be a very powerful skill~";
-				set .@skill_e6,1;
-				next;
+				.@skill_e6 = 1;
 				break;
 				break;
 			case 7:
 			case 7:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -674,8 +650,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "learn Energy Coat, I'm";
 				mes "learn Energy Coat, I'm";
 				mes "sure Blizardis will tell";
 				mes "sure Blizardis will tell";
 				mes "you all you need to know.";
 				mes "you all you need to know.";
-				set .@skill_e7,1;
-				next;
+				.@skill_e7 = 1;
 				break;
 				break;
 			case 8:
 			case 8:
 				mes "[Mana]";
 				mes "[Mana]";
@@ -692,19 +667,12 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 				mes "you to help you in your";
 				mes "you to help you in your";
 				mes "training. I hope it comes";
 				mes "training. I hope it comes";
 				mes "in handy when fighting...";
 				mes "in handy when fighting...";
-				set tu_magician01, 6;
+				tu_magician01 = 6;
 				getitem 1604,1; //Wand
 				getitem 1604,1; //Wand
 				specialeffect2 EF_HIT5;
 				specialeffect2 EF_HIT5;
-				if(.@skill_e1) getexp 300,100;
-				if(.@skill_e2) getexp 300,100;
-				if(.@skill_e3) getexp 300,100;
-				if(.@skill_e4) getexp 300,100;
-				if(.@skill_e5) getexp 300,100;
-				if(.@skill_e6) getexp 300,100;
-				if(.@skill_e7) getexp 300,100;
+				.@total = .@skill_e1 + .@skill_e2 + .@skill_e3 + .@skill_e4 + .@skill_e5;
+				if (.@total) getexp (.@total*300),(.@total*100);
 				close;
 				close;
-			default: 
-				break;
 			}
 			}
 		}
 		}
 		close;
 		close;
@@ -739,7 +707,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 			mes "done with what Yierhan";
 			mes "done with what Yierhan";
 			mes "has you do, come back";
 			mes "has you do, come back";
 			mes "and report to me, okay?";
 			mes "and report to me, okay?";
-			set tu_magician01, 7;
+			tu_magician01 = 7;
 			emotion e_heh;
 			emotion e_heh;
 			warp "morocc",182,286;
 			warp "morocc",182,286;
 			close;
 			close;
@@ -764,7 +732,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 		mes "a message, saying that";
 		mes "a message, saying that";
 		mes "you've done a great job in";
 		mes "you've done a great job in";
 		mes "completing your mission.";
 		mes "completing your mission.";
-		mes "Very nice work, "+PcName+"~";
+		mes "Very nice work, "+strcharinfo(0)+"~";
 		next;
 		next;
 		mes "[Mana]";
 		mes "[Mana]";
 		mes "It seems like there are";
 		mes "It seems like there are";
@@ -786,9 +754,9 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 		mes "a little reward for helping";
 		mes "a little reward for helping";
 		mes "out both of our guilds. Once";
 		mes "out both of our guilds. Once";
 		mes "again, thanks very much~";
 		mes "again, thanks very much~";
-		set tu_magician01, 28;
+		tu_magician01 = 28;
 		getitem 2321,1; //Silk_Robe
 		getitem 2321,1; //Silk_Robe
-		set Zeny, Zeny + 3000;
+		Zeny = Zeny + 3000;
 		getexp 3000,1000;
 		getexp 3000,1000;
 		close;
 		close;
 	default:
 	default:
@@ -804,7 +772,6 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 			mes "keep up the good";
 			mes "keep up the good";
 			mes "work. And, um, is";
 			mes "work. And, um, is";
 			mes "Yierhan doing well?";
 			mes "Yierhan doing well?";
-			close;
 		} else {
 		} else {
 			mes "You seem to be well";
 			mes "You seem to be well";
 			mes "experienced now and there";
 			mes "experienced now and there";
@@ -812,7 +779,7 @@ geffen,67,180,4	script	New Mage Manager#M	102,{
 			mes "really teach you. Now it's up";
 			mes "really teach you. Now it's up";
 			mes "to you to find ways to master";
 			mes "to you to find ways to master";
 			mes "the ways of magic on your own.";
 			mes "the ways of magic on your own.";
-			close;
 		}
 		}
+		close;
 	}
 	}
 }
 }

File diff suppressed because it is too large
+ 347 - 632
npc/quests/first_class/tu_merchant.txt


+ 184 - 183
npc/quests/first_class/tu_thief01.txt

@@ -1,26 +1,27 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= Thief Class Tutorial and Job Specific Quest
 //= Thief Class Tutorial and Job Specific Quest
-//===== By: ================================================== 
+//===== By: ==================================================
 //= Fix up by Jukka
 //= Fix up by Jukka
-//===== Current Version: ===================================== 
-//= 1.5
-//===== Compatible With: ===================================== 
+//===== Current Version: =====================================
+//= 2.0
+//===== Compatible With: =====================================
 //= rAthena Project
 //= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= [Official Conversion]
 //= Thief training quest.
 //= Thief training quest.
-//===== Additional Comments: ================================= 
+//===== Additional Comments: =================================
 //= 1.0 Fully working
 //= 1.0 Fully working
 //= 1.1 optimized [Lupus]
 //= 1.1 optimized [Lupus]
 //= 1.2 Fixed experience gains to match upcoming rate adjustments. [SinSloth]
 //= 1.2 Fixed experience gains to match upcoming rate adjustments. [SinSloth]
 //= 1.3 Fixed a few minor mistakes [Playtester]
 //= 1.3 Fixed a few minor mistakes [Playtester]
 //= 1.4 Misc. updates. [L0ne_W0lf]
 //= 1.4 Misc. updates. [L0ne_W0lf]
 //= 1.5 Added Pre-Renewal support. [Euphy]
 //= 1.5 Added Pre-Renewal support. [Euphy]
-//============================================================ 
+//= 2.0 Fixed a wrong exp value & clean-up. [Capuche]
+//============================================================
 
 
 // Thief Trainer
 // Thief Trainer
 //============================================================
 //============================================================
-moc_ruins,66,164,4	script	Thief Trainer#T	84,{
+moc_ruins,66,164,4	script	Thief Trainer#T	4_M_02,{
 	mes "[Yierhan]";
 	mes "[Yierhan]";
 	if(Class == Job_Novice){
 	if(Class == Job_Novice){
 		mes "Eh...?";
 		mes "Eh...?";
@@ -34,22 +35,20 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 		mes "Listen, if you ever decide to become a Thief--a smart choice";
 		mes "Listen, if you ever decide to become a Thief--a smart choice";
 		mes "I might add--come and talk to me. I'll show you the ropes!";
 		mes "I might add--come and talk to me. I'll show you the ropes!";
 		close;
 		close;
-
-	} else if(Class == Job_Thief || Class == Job_Thief_High || Class == Job_Assassin || Class ==Job_Assassin_Cross || Class == Job_Rogue || Class == Job_Stalker){
-		if(Class == Job_Thief_High || Class == Job_Assassin || Class == Job_Assassin_Cross || Class == Job_Rogue || Class == Job_Stalker){
-			if(tu_thief01 < 8){
-				mes "Whaaaat are you";
-				mes "doin' here? There's";
-				mes "nothing I can teach you!";
-				mes "You're waaay beyond me!";
-				next;
-				mes "[Yierhan]";
-				mes "In fact, I think";
-				mes "you're qualified";
-				mes "to teach me some stuff!";
-				mes "Come on! I need new moves!";
-				close;
-			}
+	}
+	else if (BaseClass == Job_Thief && Upper != 2) {
+		if (Class != Job_Thief && tu_thief01 < 8) {
+			mes "Whaaaat are you";
+			mes "doin' here? There's";
+			mes "nothing I can teach you!";
+			mes "You're waaay beyond me!";
+			next;
+			mes "[Yierhan]";
+			mes "In fact, I think";
+			mes "you're qualified";
+			mes "to teach me some stuff!";
+			mes "Come on! I need new moves!";
+			close;
 		}
 		}
 		if(tu_thief01 == 0){
 		if(tu_thief01 == 0){
 			mes "Heya pal.";
 			mes "Heya pal.";
@@ -88,10 +87,8 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 				next;
 				next;
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "So if you're feeling like the damage you're making is pretty weak, you might want more stat points in ^2F4F2FSTR^000000. How high your raise your own STR is really up to you.";
 				mes "So if you're feeling like the damage you're making is pretty weak, you might want more stat points in ^2F4F2FSTR^000000. How high your raise your own STR is really up to you.";
-				set tu_thief01, 1;
 				getexp 200,100;
 				getexp 200,100;
-				specialeffect2 EF_HIT5;
-				close;
+				break;
 			case 2:
 			case 2:
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "Yeah, that's right! If you wanna increase your damage, you need";
 				mes "Yeah, that's right! If you wanna increase your damage, you need";
@@ -104,10 +101,8 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "Sure, ^23238EDEX^000000 and LUK can";
 				mes "Sure, ^23238EDEX^000000 and LUK can";
 				mes "also increase your attack damage, but they're insignificant compared to STR. I repeat: ^660000insignificant^000000.";
 				mes "also increase your attack damage, but they're insignificant compared to STR. I repeat: ^660000insignificant^000000.";
-				set tu_thief01, 1;
 				getexp 400,200;
 				getexp 400,200;
-				specialeffect2 EF_HIT5;
-				close;
+				break;
 			case 3:
 			case 3:
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "Say whaaat? ^23238EDEX^000000 affects";
 				mes "Say whaaat? ^23238EDEX^000000 affects";
@@ -119,129 +114,131 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 				next;
 				next;
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "So if you're feeling like the damage you're making is pretty weak, you might want more stat points in ^2F4F2FSTR^000000. How high your raise your own STR is really up to you.";
 				mes "So if you're feeling like the damage you're making is pretty weak, you might want more stat points in ^2F4F2FSTR^000000. How high your raise your own STR is really up to you.";
-				set tu_thief01, 1;
 				getexp 200,100;
 				getexp 200,100;
-				specialeffect2 EF_HIT5;
-				close;
 			}
 			}
-		} else if(tu_thief01 == 1){
+			tu_thief01 = 1;
+			specialeffect2 EF_HIT5;
+			close;
+		}
+		else if(tu_thief01 == 1){
 			mes "Alright, enough about stats.";
 			mes "Alright, enough about stats.";
 			mes "You know what? I think I'll just talk to you about the skills that we Thieves use.";
 			mes "You know what? I think I'll just talk to you about the skills that we Thieves use.";
 			next;
 			next;
 			mes "[Yierhan]";
 			mes "[Yierhan]";
 			mes "So level up your skills, learn a few new ones if you want, and";
 			mes "So level up your skills, learn a few new ones if you want, and";
 			mes "then come back over here.";
 			mes "then come back over here.";
-			set tu_thief01, 2;
+			tu_thief01 = 2;
 			close;
 			close;
-		} else if(tu_thief01 == 2){
+		}
+		else if(tu_thief01 == 2){
 			mes "Okay, let me see your skills. You know you gotta change your battle strategy depending on what skills you have, right? Skills are just as important as stats!";
 			mes "Okay, let me see your skills. You know you gotta change your battle strategy depending on what skills you have, right? Skills are just as important as stats!";
 			next;
 			next;
-			set .@chk_th_skill1, getskilllv("TF_DOUBLE");
-			set .@chk_th_skill2, getskilllv("TF_MISS");
-			set .@chk_th_skill3, getskilllv("TF_STEAL");
-			set .@chk_th_skill4, getskilllv("TF_HIDING");
-			set .@chk_th_skill5, getskilllv("TF_POISON");
-			set .@chk_th_skill6, getskilllv("TF_DETOXIFY");
+			.@chk_th_skill1 = getskilllv("TF_DOUBLE");
+			.@chk_th_skill2 = getskilllv("TF_MISS");
+			.@chk_th_skill3 = getskilllv("TF_STEAL");
+			.@chk_th_skill4 = getskilllv("TF_HIDING");
+			.@chk_th_skill5 = getskilllv("TF_POISON");
+			.@chk_th_skill6 = getskilllv("TF_DETOXIFY");
 
 
 			if(.@chk_th_skill1 == 0 && .@chk_th_skill2 == 0 && .@chk_th_skill3 == 0 && .@chk_th_skill4 == 0 && .@chk_th_skill5 == 0 && .@chk_th_skill6 == 0){
 			if(.@chk_th_skill1 == 0 && .@chk_th_skill2 == 0 && .@chk_th_skill3 == 0 && .@chk_th_skill4 == 0 && .@chk_th_skill5 == 0 && .@chk_th_skill6 == 0){
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "You haven't learned any skills yet? Come on, it's your skills that'll set you apart from Novices and everyone else!";
 				mes "You haven't learned any skills yet? Come on, it's your skills that'll set you apart from Novices and everyone else!";
 				close;
 				close;
-			} else {
-				if(.@chk_th_skill1 > 0){
-					mes "[Yierhan]";
-					mes "Ah, so you've learned";
-					mes "Level "+.@chk_th_skill1+" Double Attack.";
-					mes "Nice! This skill gives you the chance to attack twice in one";
-					mes "attack. Wicked!";
-					next;
-					mes "[Yierhan]";
-					mes "It's a Passive skill, so it's always in effect and won't have to use any SP to use it. The higher your Double Attack skill level, the more double attacks you'll do.";
-					next;
-				}
-				if(.@chk_th_skill2 > 0){
-					mes "[Yierhan]";
-					mes "Let's see...";
-					mes "Level "+.@chk_th_skill2+" Increase Dodge?";
-					mes "That increases your Flee Rate, meaning you've got a better chance of dodging attacks from your enemies.";
-					next;
-					mes "[Yierhan]";
-					mes "Just like the Double Attack skill, Increase Dodge is a Passive skill. It won't use SP and it's always in";
-					mes "effect. If you don't like to bruise, this is your skill.";
-					next;
-				}
-				if(.@chk_th_skill3 > 0){
-					mes "[Yierhan]";
-					mes "Whoa, so you've";
-					mes "got Level "+.@chk_th_skill3+" Steal~";
-					mes "Now that's the skill which gives our job its name! You can't use";
-					mes "it against people, though...";
-					next;
-					mes "[Yierhan]";
-					mes "But you can use Steal to take items from monsters. If you're lucky, you can get some good items that way. Oh, and Steal doesn't affect monster drop rates.";
-					next;
-				}
-				if(.@chk_th_skill4 > 0){
-					mes "[Yierhan]";
-					mes "You've learned";
-					mes "Level "+.@chk_th_skill4+" Hiding?";
-					mes "Let's see, you can only learn";
-					mes "that after learning the Steal skill up to a certain level.";
-					next;
-					mes "[Yierhan]";
-					mes "Of course, you use ";
-					mes "the Hiding skill to hide underground in an emergency, like when you're surrounded by tough enemies. Be careful though...";
-					next;
-					mes "[Yierhan]";
-					mes "Certain monsters will still be able to find you, no matter how well you hide. There are even a few monsters that can flush you out of hiding!";
-					next;
-				}
-				if(.@chk_th_skill5 > 0){
-					mes "[Yierhan]";
-					mes "Alright, I see that you";
-					mes "know Level "+.@chk_th_skill5+" Envenom.";
-					mes "You like being dangerous,";
-					mes "don't you?";
-					next;
-					mes "[Yierhan]";
-					mes "This attack skill has the chance";
-					mes "to poison your enemy for a set amount of time. While poisoned, an enemy will constantly lose its HP and will have decreased defense.";
-					next;
-					mes "[Yierhan]";
-					mes "Eh, but remember.";
-					mes "If the monster's too strong for you, you might not be able to poison it. So don't go crazy.";
-					next;
-				}
-				if(.@chk_th_skill6 > 0){
-					mes "[Yierhan]";
-					mes "Level "+.@chk_th_skill6+" Detoxify.";
-					mes "If you took the trouble to learn that, you must be the cautious";
-					mes "type or something.";
-					next;
-					mes "[Yierhan]";
-					mes "You can only learn Detoxify";
-					mes "after you learn the Envenom skill. Detoxify allows you to counteract the effects of poison on a target.";
-					next;
-				}
+			}
+			if(.@chk_th_skill1 > 0){
+				mes "[Yierhan]";
+				mes "Ah, so you've learned";
+				mes "Level "+.@chk_th_skill1+" Double Attack.";
+				mes "Nice! This skill gives you the chance to attack twice in one";
+				mes "attack. Wicked!";
+				next;
+				mes "[Yierhan]";
+				mes "It's a Passive skill, so it's always in effect and won't have to use any SP to use it. The higher your Double Attack skill level, the more double attacks you'll do.";
+				next;
+			}
+			if(.@chk_th_skill2 > 0){
+				mes "[Yierhan]";
+				mes "Let's see...";
+				mes "Level "+.@chk_th_skill2+" Increase Dodge?";
+				mes "That increases your Flee Rate, meaning you've got a better chance of dodging attacks from your enemies.";
+				next;
+				mes "[Yierhan]";
+				mes "Just like the Double Attack skill, Increase Dodge is a Passive skill. It won't use SP and it's always in";
+				mes "effect. If you don't like to bruise, this is your skill.";
+				next;
+			}
+			if(.@chk_th_skill3 > 0){
+				mes "[Yierhan]";
+				mes "Whoa, so you've";
+				mes "got Level "+.@chk_th_skill3+" Steal~";
+				mes "Now that's the skill which gives our job its name! You can't use";
+				mes "it against people, though...";
+				next;
+				mes "[Yierhan]";
+				mes "But you can use Steal to take items from monsters. If you're lucky, you can get some good items that way. Oh, and Steal doesn't affect monster drop rates.";
+				next;
+			}
+			if(.@chk_th_skill4 > 0){
+				mes "[Yierhan]";
+				mes "You've learned";
+				mes "Level "+.@chk_th_skill4+" Hiding?";
+				mes "Let's see, you can only learn";
+				mes "that after learning the Steal skill up to a certain level.";
+				next;
+				mes "[Yierhan]";
+				mes "Of course, you use ";
+				mes "the Hiding skill to hide underground in an emergency, like when you're surrounded by tough enemies. Be careful though...";
+				next;
+				mes "[Yierhan]";
+				mes "Certain monsters will still be able to find you, no matter how well you hide. There are even a few monsters that can flush you out of hiding!";
+				next;
+			}
+			if(.@chk_th_skill5 > 0){
+				mes "[Yierhan]";
+				mes "Alright, I see that you";
+				mes "know Level "+.@chk_th_skill5+" Envenom.";
+				mes "You like being dangerous,";
+				mes "don't you?";
+				next;
+				mes "[Yierhan]";
+				mes "This attack skill has the chance";
+				mes "to poison your enemy for a set amount of time. While poisoned, an enemy will constantly lose its HP and will have decreased defense.";
+				next;
+				mes "[Yierhan]";
+				mes "Eh, but remember.";
+				mes "If the monster's too strong for you, you might not be able to poison it. So don't go crazy.";
+				next;
+			}
+			if(.@chk_th_skill6 > 0){
+				mes "[Yierhan]";
+				mes "Level "+.@chk_th_skill6+" Detoxify.";
+				mes "If you took the trouble to learn that, you must be the cautious";
+				mes "type or something.";
+				next;
+				mes "[Yierhan]";
+				mes "You can only learn Detoxify";
+				mes "after you learn the Envenom skill. Detoxify allows you to counteract the effects of poison on a target.";
+				next;
 			}
 			}
 			mes "[Yierhan]";
 			mes "[Yierhan]";
 			mes "Alright, I guess";
 			mes "Alright, I guess";
 			mes "if you want to know";
 			mes "if you want to know";
 			mes "about any other skills,";
 			mes "about any other skills,";
 			mes "I can explain real quick.";
 			mes "I can explain real quick.";
-			set tu_thief01, 3;
+			tu_thief01 = 3;
 			getexp BaseLevel*30,BaseLevel*15;
 			getexp BaseLevel*30,BaseLevel*15;
 			specialeffect2 EF_HIT5;
 			specialeffect2 EF_HIT5;
 			close;
 			close;
-		} else if(tu_thief01 == 3){
+		}
+		else if(tu_thief01 == 3){
 			mes "So...";
 			mes "So...";
 			mes "Are there any";
 			mes "Are there any";
 			mes "skills you want";
 			mes "skills you want";
 			mes "explained or is this";
 			mes "explained or is this";
 			mes "pretty much stuff you";
 			mes "pretty much stuff you";
 			mes "already know?";
 			mes "already know?";
-			next;
 			while(1){
 			while(1){
+				next;
 				switch(select("Double Attack:Increase Dodge:Steal:Hiding:Envenom:Detoxify:I know enough.")) {
 				switch(select("Double Attack:Increase Dodge:Steal:Hiding:Envenom:Detoxify:I know enough.")) {
 				case 1:
 				case 1:
 					mes "[Yierhan]";
 					mes "[Yierhan]";
@@ -250,8 +247,7 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 					next;
 					next;
 					mes "[Yierhan]";
 					mes "[Yierhan]";
 					mes "It's a Passive skill, so it's always in effect and won't have to use any SP to use it. The higher your Double Attack skill level, the more double attacks you'll do.";
 					mes "It's a Passive skill, so it's always in effect and won't have to use any SP to use it. The higher your Double Attack skill level, the more double attacks you'll do.";
-					set .@read_d, 1;
-					next;
+					.@read_d = 1;
 					break;
 					break;
 				case 2:
 				case 2:
 					mes "[Yierhan]";
 					mes "[Yierhan]";
@@ -265,8 +261,7 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 					mes "[Yierhan]";
 					mes "[Yierhan]";
 					mes "Just like the Double Attack skill, Increase Dodge is a Passive skill. It won't use SP and it's always in";
 					mes "Just like the Double Attack skill, Increase Dodge is a Passive skill. It won't use SP and it's always in";
 					mes "effect. If you don't like to bruise, this is your skill.";
 					mes "effect. If you don't like to bruise, this is your skill.";
-					set .@read_f, 1;
-					next;
+					.@read_f = 1;
 					break;
 					break;
 				case 3:
 				case 3:
 					mes "[Yierhan]";
 					mes "[Yierhan]";
@@ -276,8 +271,7 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 					specialeffect2 EF_STEAL;
 					specialeffect2 EF_STEAL;
 					mes "[Yierhan]";
 					mes "[Yierhan]";
 					mes "But you can use Steal to take items from monsters! If you're lucky, you can get some good items that way. Oh, and Steal doesn't affect monster drop rates.";
 					mes "But you can use Steal to take items from monsters! If you're lucky, you can get some good items that way. Oh, and Steal doesn't affect monster drop rates.";
-					set .@read_s, 1;
-					next;
+					.@read_s = 1;
 					break;
 					break;
 				case 4:
 				case 4:
 					mes "[Yierhan]";
 					mes "[Yierhan]";
@@ -289,8 +283,7 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 					next;
 					next;
 					mes "[Yierhan]";
 					mes "[Yierhan]";
 					mes "Certain monsters will still be able to find you, no matter how well you hide. There are even a few monsters that can flush you out of hiding!";
 					mes "Certain monsters will still be able to find you, no matter how well you hide. There are even a few monsters that can flush you out of hiding!";
-					set .@read_p, 1;
-					next;
+					.@read_p = 1;
 					break;
 					break;
 				case 5:
 				case 5:
 					mes "[Yierhan]";
 					mes "[Yierhan]";
@@ -300,8 +293,7 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 					mes "This attack skill has the chance";
 					mes "This attack skill has the chance";
 					mes "to poison your enemy for a set amount of time. While poisoned, an enemy will constantly lose its HP and will have decreased defense.";
 					mes "to poison your enemy for a set amount of time. While poisoned, an enemy will constantly lose its HP and will have decreased defense.";
 					mes "Remember that.";
 					mes "Remember that.";
-					set .@read_h, 1;
-					next;
+					.@read_h = 1;
 					break;
 					break;
 				case 6:
 				case 6:
 					mes "[Yierhan]";
 					mes "[Yierhan]";
@@ -314,10 +306,9 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 					mes "[Yierhan]";
 					mes "[Yierhan]";
 					mes "You can learn Detoxify";
 					mes "You can learn Detoxify";
 					mes "after you learn the Envenom skill. Detoxify allows you to counteract the effects of poison on a target.";
 					mes "after you learn the Envenom skill. Detoxify allows you to counteract the effects of poison on a target.";
-					set .@read_r, 1;
+					.@read_r = 1;
 					next;
 					next;
 					specialeffect2 EF_DETOXICATION;
 					specialeffect2 EF_DETOXICATION;
-					next;
 					break;
 					break;
 				case 7:
 				case 7:
 					mes "[Yierhan]";
 					mes "[Yierhan]";
@@ -327,18 +318,16 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 					next;
 					next;
 					mes "[Yierhan]";
 					mes "[Yierhan]";
 					mes "Now that you're such an expert on skills, I want you to level up your skills and come back, got it?";
 					mes "Now that you're such an expert on skills, I want you to level up your skills and come back, got it?";
-					set tu_thief01, 4;
+					tu_thief01 = 4;
 					specialeffect2 EF_HIT5;
 					specialeffect2 EF_HIT5;
-					if(.@read_d) getexp 300,100;
-					if(.@read_f) getexp 300,100;
-					if(.@read_s) getexp 300,100;
-					if(.@read_p) getexp 300,100;
-					if(.@read_h) getexp 300,100;
-					if(.@read_r) getexp 300,100;
+					.@total = .@read_d + .@read_f + .@read_s + .@read_p + .@read_h + .@read_r;
+					if (.@total)
+						getexp (.@total*300),(.@total*100);
 					close;
 					close;
 				}
 				}
 			}
 			}
-		} else if(tu_thief01 == 4){
+		}
+		else if(tu_thief01 == 4){
 			mes "Alright, we studied the skills and you've been practicing a little, right? You better have...";
 			mes "Alright, we studied the skills and you've been practicing a little, right? You better have...";
 			next;
 			next;
 			mes "[Yierhan]";
 			mes "[Yierhan]";
@@ -348,7 +337,7 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			mes "Go and get me";
 			mes "Go and get me";
 			mes "10 ^ff0000Feather of Birds^000000.";
 			mes "10 ^ff0000Feather of Birds^000000.";
 			mes "You can go ahead and kill Pickies to get those. It really shouldn't be that hard. Oh, and use this Wing thingee to come back.";
 			mes "You can go ahead and kill Pickies to get those. It really shouldn't be that hard. Oh, and use this Wing thingee to come back.";
-			set tu_thief01, 5;
+			tu_thief01 = 5;
 			savepoint "moc_ruins",80,164;
 			savepoint "moc_ruins",80,164;
 			getitem 602,1; //Wing_Of_Butterfly
 			getitem 602,1; //Wing_Of_Butterfly
 			getexp 100,50;
 			getexp 100,50;
@@ -356,14 +345,16 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			close2;
 			close2;
 			warp "moc_fild12",158,373;
 			warp "moc_fild12",158,373;
 			end;
 			end;
-		} else if(tu_thief01 == 5 || tu_thief01 == 6){
+		}
+		else if(tu_thief01 == 5 || tu_thief01 == 6){
 			if(countitem(916) < 10){
 			if(countitem(916) < 10){
 				mes "'Ey, you don't have the 10 ^ff0000Feather of Birds^000000 I asked you for! You gotta apply what you know, you know.";
 				mes "'Ey, you don't have the 10 ^ff0000Feather of Birds^000000 I asked you for! You gotta apply what you know, you know.";
 				mes "Now hurry up and do it!";
 				mes "Now hurry up and do it!";
 				close2;
 				close2;
 				warp "moc_fild07",203,38;
 				warp "moc_fild07",203,38;
 				end;
 				end;
-			} else {
+			}
+			else {
 				mes "Alright...!";
 				mes "Alright...!";
 				mes "Nice work, pal.";
 				mes "Nice work, pal.";
 				mes "Seeing as you got these feathers, you must be really gung-ho about becoming a good Thief.";
 				mes "Seeing as you got these feathers, you must be really gung-ho about becoming a good Thief.";
@@ -407,7 +398,7 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 						mes "not to get too close";
 						mes "not to get too close";
 						mes "to the poison! That stuff";
 						mes "to the poison! That stuff";
 						mes "is pretty strong!";
 						mes "is pretty strong!";
-						set tu_thief01, 8;
+						tu_thief01 = 8;
 						getitem 1207,1; //Main_Gauche
 						getitem 1207,1; //Main_Gauche
 						getexp 1000,500;
 						getexp 1000,500;
 						specialeffect2 EF_HIT5;
 						specialeffect2 EF_HIT5;
@@ -417,13 +408,14 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 						mes "Good!";
 						mes "Good!";
 						mes "Less work for me!";
 						mes "Less work for me!";
 						mes "Alright, you better get stronger the next time I see you. Oh, and you can have this stuff. You know, since you're so gangster and all.";
 						mes "Alright, you better get stronger the next time I see you. Oh, and you can have this stuff. You know, since you're so gangster and all.";
-						set tu_thief01, 7;
+						tu_thief01 = 7;
 						getitem 1207,1; //Main_Gauche
 						getitem 1207,1; //Main_Gauche
 						getexp 500,200;
 						getexp 500,200;
 						specialeffect2 EF_HIT5;
 						specialeffect2 EF_HIT5;
 						close;
 						close;
 					}
 					}
-				} else {
+				}
+				else {
 					switch(select("It was nice to meet you.:Nope.")) {
 					switch(select("It was nice to meet you.:Nope.")) {
 					case 1:
 					case 1:
 						mes "[Yierhan]";
 						mes "[Yierhan]";
@@ -436,22 +428,24 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 						mes "you so much, kid,";
 						mes "you so much, kid,";
 						mes "you can have this.";
 						mes "you can have this.";
 						mes "Take it, it's yours!";
 						mes "Take it, it's yours!";
+						getexp 500,200;
 						break;
 						break;
 					case 2:
 					case 2:
 						mes "[Yierhan]";
 						mes "[Yierhan]";
 						mes "Good!";
 						mes "Good!";
 						mes "Less work for me!";
 						mes "Less work for me!";
 						mes "Alright, you better get stronger the next time I see you. Oh, and you can have this stuff. You know, since you're so gangster and all.";
 						mes "Alright, you better get stronger the next time I see you. Oh, and you can have this stuff. You know, since you're so gangster and all.";
+						getexp 50,20;
 						break;
 						break;
 					}
 					}
-					set tu_thief01, 7;
+					tu_thief01 = 7;
 					getitem 1207,1; //Main_Gauche
 					getitem 1207,1; //Main_Gauche
-					getexp 500,200;
 					specialeffect2 EF_HIT5;
 					specialeffect2 EF_HIT5;
 					close;
 					close;
 				}
 				}
 			}
 			}
-		} else if(tu_thief01 == 7){
+		}
+		else if(tu_thief01 == 7){
 			mes "[Yierhan]";
 			mes "[Yierhan]";
 			mes "You know...";
 			mes "You know...";
 			mes "There was this";
 			mes "There was this";
@@ -488,11 +482,12 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			mes "decide to check it";
 			mes "decide to check it";
 			mes "out, be real careful";
 			mes "out, be real careful";
 			mes "other there, okay?";
 			mes "other there, okay?";
-			set tu_thief01, 8;
+			tu_thief01 = 8;
 			getexp 200,100;
 			getexp 200,100;
 			specialeffect2 EF_HIT5;
 			specialeffect2 EF_HIT5;
 			close;
 			close;
-		} else if(tu_thief01 == 8){
+		}
+		else if(tu_thief01 == 8){
 			mes "Heya pal.";
 			mes "Heya pal.";
 			mes "You doin' alright?";
 			mes "You doin' alright?";
 			next;
 			next;
@@ -504,7 +499,8 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			mes "It's a good policy to just be really careful on your adventures. Look out for monsters and look";
 			mes "It's a good policy to just be really careful on your adventures. Look out for monsters and look";
 			mes "out for people! Got it?";
 			mes "out for people! Got it?";
 			close;
 			close;
-		} else if(tu_thief01 < 26){
+		}
+		else if(tu_thief01 < 26){
 			mes "I heard there was";
 			mes "I heard there was";
 			mes "this one Assassin";
 			mes "this one Assassin";
 			mes "that went on a mission";
 			mes "that went on a mission";
@@ -520,7 +516,8 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			mes "Anyway, take";
 			mes "Anyway, take";
 			mes "care of yourself.";
 			mes "care of yourself.";
 			close;
 			close;
-		} else if(tu_thief01 == 26){
+		}
+		else if(tu_thief01 == 26){
 			mes "'Ey, did you";
 			mes "'Ey, did you";
 			mes "complete your mission?";
 			mes "complete your mission?";
 			mes "I know, I know, the thing you've gotta do is pretty rough.";
 			mes "I know, I know, the thing you've gotta do is pretty rough.";
@@ -570,13 +567,14 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 				next;
 				next;
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "Hey, this stuff is yours. Think of it as a reward for helping us out. Take care of yourself now~";
 				mes "Hey, this stuff is yours. Think of it as a reward for helping us out. Take care of yourself now~";
-				set tu_thief01, 27;
+				tu_thief01 = 27;
 				getitem 2307,1; //Mantle
 				getitem 2307,1; //Mantle
-				set Zeny, Zeny + 5000;
+				Zeny = Zeny + 5000;
 				getexp 8000,3000;
 				getexp 8000,3000;
 				close;
 				close;
 			}
 			}
-		} else {
+		}
+		else {
 			mes "[Yierhan]";
 			mes "[Yierhan]";
 			mes "Hey...";
 			mes "Hey...";
 			mes "You got dreams,";
 			mes "You got dreams,";
@@ -589,7 +587,8 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			mes "I just like telling people to follow their dreams. So do it. Life without anything to look forward to is pretty boring, doncha think?";
 			mes "I just like telling people to follow their dreams. So do it. Life without anything to look forward to is pretty boring, doncha think?";
 			close;
 			close;
 		}
 		}
-	} else if(Class == Job_Mage || Class == Job_Mage_High || Class == Job_Wizard || Class == Job_High_Wizard || Class == Job_Sage || Class == Job_Professor){
+	}
+	else if (BaseClass == Job_Mage && Upper != 2){
 		if(tu_magician01 < 7){
 		if(tu_magician01 < 7){
 			mes "[Yierhan]";
 			mes "[Yierhan]";
 			mes "Heya.";
 			mes "Heya.";
@@ -599,31 +598,31 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			mes "I actually got a few magic using friends here and there. That mystic stuff is waaay over my head, but";
 			mes "I actually got a few magic using friends here and there. That mystic stuff is waaay over my head, but";
 			mes "I got a lotta respect for it.";
 			mes "I got a lotta respect for it.";
 			close;
 			close;
-		} else if(tu_magician01 == 7){
+		}
+		else if(tu_magician01 == 7){
 			mes "Hm...?";
 			mes "Hm...?";
 			mes "That's weird, usually only";
 			mes "That's weird, usually only";
 			mes "Thieves hang around this joint. What's someone like you doing";
 			mes "Thieves hang around this joint. What's someone like you doing";
 			mes "here? Unless...";
 			mes "here? Unless...";
 			next;
 			next;
-			switch(select("I'm here on behalf of 'Mana.'")) {
-			case 1:
-				mes "[Yierhan]";
-				mes "Right, you must be the help that Mana sent! You came just at the right time. You see, we found something weird in South Morroc.";
-				next;
-				mes "[Yierhan]";
-				mes "Basically, we found traces of poison that were used in a fight. We were going to investigate it, but we've been swamped with all this other work.";
-				next;
-				mes "[Yierhan]";
-				mes "That's why we've been asking";
-				mes "for help from the Mage Guild. Fortunately, I'm pals with Mana, so...";
-				next;
-				mes "[Yierhan]";
-				mes "Anyway, head over to";
-				mes "South Morroc since it seems to be a good place to start investigating. You'll see what we found right outside the South Morroc gate.";
-				set tu_magician01, 8;
-				break;
-			}
-		} else if(tu_magician01 < 26){
+			select("I'm here on behalf of 'Mana.'");
+			mes "[Yierhan]";
+			mes "Right, you must be the help that Mana sent! You came just at the right time. You see, we found something weird in South Morroc.";
+			next;
+			mes "[Yierhan]";
+			mes "Basically, we found traces of poison that were used in a fight. We were going to investigate it, but we've been swamped with all this other work.";
+			next;
+			mes "[Yierhan]";
+			mes "That's why we've been asking";
+			mes "for help from the Mage Guild. Fortunately, I'm pals with Mana, so...";
+			next;
+			mes "[Yierhan]";
+			mes "Anyway, head over to";
+			mes "South Morroc since it seems to be a good place to start investigating. You'll see what we found right outside the South Morroc gate.";
+			tu_magician01 = 8;
+			close;
+		}
+		else if(tu_magician01 < 26){
 			mes "I heard there was";
 			mes "I heard there was";
 			mes "this one Assassin";
 			mes "this one Assassin";
 			mes "that went on a mission";
 			mes "that went on a mission";
@@ -641,7 +640,8 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 			mes "might be related to";
 			mes "might be related to";
 			mes "that mysterious Assassin...";
 			mes "that mysterious Assassin...";
 			close;
 			close;
-		} else if(tu_magician01 == 26){
+		}
+		else if(tu_magician01 == 26){
 			mes "So how's the";
 			mes "So how's the";
 			mes "investigation";
 			mes "investigation";
 			mes "coming along?";
 			mes "coming along?";
@@ -694,12 +694,13 @@ moc_ruins,66,164,4	script	Thief Trainer#T	84,{
 				next;
 				next;
 				mes "[Yierhan]";
 				mes "[Yierhan]";
 				mes "Hey, this stuff is yours. Think of it as a reward for helping us out. Right, and I'll let Mana know you did a great job. Take care of yourself now~";
 				mes "Hey, this stuff is yours. Think of it as a reward for helping us out. Right, and I'll let Mana know you did a great job. Take care of yourself now~";
-				set tu_magician01, 27;
-				set Zeny, Zeny + 5000;
+				tu_magician01 = 27;
+				Zeny = Zeny + 5000;
 				getexp 5000,2000;
 				getexp 5000,2000;
 				close;
 				close;
 			}
 			}
-		} else {
+		}
+		else {
 			mes "Just as I thought,";
 			mes "Just as I thought,";
 			mes "more than one group";
 			mes "more than one group";
 			mes "was involved in all this.";
 			mes "was involved in all this.";

File diff suppressed because it is too large
+ 521 - 393
npc/quests/quests_airship.txt


File diff suppressed because it is too large
+ 272 - 242
npc/quests/quests_moscovia.txt


+ 10 - 0
npc/re/other/stone_change.txt

@@ -43,6 +43,16 @@ geffen_in,99,174,5	script	Ore Tester#sorty	8_F_GIRL,{
 			mes "You don't have any "+getitemname(.@item)+"...";
 			mes "You don't have any "+getitemname(.@item)+"...";
 			close;
 			close;
 		}
 		}
+		// while(1) {
+			// if (countitem(.@item)) {
+				// set .@count, countitem(.@item);
+				// set .@total, .@total + .@count;
+				// delitem .@item, .@count;
+			// } else {
+				// getitem .@item, .@total;
+				// break;
+			// }
+		// }
 		.@count = countitem(.@item);
 		.@count = countitem(.@item);
 		delitem .@item, .@count;
 		delitem .@item, .@count;
 		getitem .@item, .@count;
 		getitem .@item, .@count;

+ 3 - 3
npc/re/quests/quests_brasilis.txt

@@ -190,7 +190,7 @@ brasilis,192,133,6	script	Lucia#brasilis	4_F_BRZ_WOMAN,{
 			mes "See you then.";
 			mes "See you then.";
 			close;
 			close;
 		case 3:
 		case 3:
-		L_whathappen:
+		L_WhatHappen:
 			mes "[Lucia]";
 			mes "[Lucia]";
 			mes "One day ^FF0000Strange Hydra^000000s";
 			mes "One day ^FF0000Strange Hydra^000000s";
 			mes "came here and surrounded the town.";
 			mes "came here and surrounded the town.";
@@ -261,7 +261,7 @@ brasilis,192,133,6	script	Lucia#brasilis	4_F_BRZ_WOMAN,{
 					mes "Ok, please do me a favor.";
 					mes "Ok, please do me a favor.";
 					close;
 					close;
 				case 2:
 				case 2:
-					goto L_whathappen;
+					goto L_WhatHappen;
 				}
 				}
 			}
 			}
 		}
 		}
@@ -297,7 +297,7 @@ brasilis,192,133,6	script	Lucia#brasilis	4_F_BRZ_WOMAN,{
 				mes "See you then.";
 				mes "See you then.";
 				close;
 				close;
 			case 3:
 			case 3:
-				goto L_whathappen;
+				goto L_WhatHappen;
 			}
 			}
 		}
 		}
 	}
 	}

+ 26 - 91
npc/warps/dungeons/mosk_dun.txt

@@ -3,7 +3,7 @@
 //===== By: ==================================================
 //===== By: ==================================================
 //= Kisuka, $ephiroth
 //= Kisuka, $ephiroth
 //===== Current Version: =====================================
 //===== Current Version: =====================================
-//= 1.4
+//= 2.0
 //===== Compatible With: =====================================
 //===== Compatible With: =====================================
 //= rAthena Project
 //= rAthena Project
 //===== Description: =========================================
 //===== Description: =========================================
@@ -13,13 +13,14 @@
 //= 1.1, 1.2 Updated from jA [$ephiroth]
 //= 1.1, 1.2 Updated from jA [$ephiroth]
 //= 1.3 Added warp npcs. Removed place holder warps. [Kisuka]
 //= 1.3 Added warp npcs. Removed place holder warps. [Kisuka]
 //= 1.4 Fixed cords on milestone 1-3. [Kisuka]
 //= 1.4 Fixed cords on milestone 1-3. [Kisuka]
+//= 2.0 Clean-up. [Capuche]
 //============================================================
 //============================================================
 
 
 mosk_fild02,190,257,0	warp	moscoviawarp0401	1,1,mosk_dun01,189,45
 mosk_fild02,190,257,0	warp	moscoviawarp0401	1,1,mosk_dun01,189,45
 mosk_dun01,189,42,0	warp	moscoviawarp0501	1,1,mosk_fild02,190,254
 mosk_dun01,189,42,0	warp	moscoviawarp0501	1,1,mosk_fild02,190,254
 mosk_in,215,36,0	warp	babayagaout		1,1,mosk_dun02,53,217
 mosk_in,215,36,0	warp	babayagaout		1,1,mosk_dun02,53,217
 
 
-mosk_dun02,53,220,4	script	#babayagain	45,1,1,{
+mosk_dun02,53,220,4	script	#babayagain	WARPNPC,1,1,{
 	end;
 	end;
 OnTouch:
 OnTouch:
 	if (mos_nowinter == 11) {
 	if (mos_nowinter == 11) {
@@ -47,7 +48,7 @@ OnTouch:
 		warp "mosk_in",125,92;
 		warp "mosk_in",125,92;
 		end;
 		end;
 	}
 	}
-	else if (mos_nowinter == 12) {
+	else if (mos_nowinter == 12 || mos_nowinter == 13) {
 		donpcevent "Soldier1#mos::OnEnable";
 		donpcevent "Soldier1#mos::OnEnable";
 		donpcevent "Soldier2#mos::OnEnable";
 		donpcevent "Soldier2#mos::OnEnable";
 		donpcevent "Soldier3#mos::OnEnable";
 		donpcevent "Soldier3#mos::OnEnable";
@@ -61,51 +62,17 @@ OnTouch:
 			mes "I should get out of here...";
 			mes "I should get out of here...";
 			close2;
 			close2;
 			warp "mosk_dun02",100,100;
 			warp "mosk_dun02",100,100;
-			donpcevent "Soldier1#mos::OnInit";
-			donpcevent "Soldier2#mos::OnInit";
-			donpcevent "Soldier3#mos::OnInit";
-			end;
 		}
 		}
-		mes "-I explain what happend until now.-";
-		next;
-		mes "[Soldier]";
-		mes "If you have something to say, speak";
-		mes "to the Csar.";
-		mes "If you leave to this place,";
-		mes "you will be considered as our enemy.";
-		close2;
-		donpcevent "Soldier1#mos::OnInit";
-		donpcevent "Soldier2#mos::OnInit";
-		donpcevent "Soldier3#mos::OnInit";
-		end;
-	}
-	else if (mos_nowinter == 13) {
-		donpcevent "Soldier1#mos::OnEnable";
-		donpcevent "Soldier2#mos::OnEnable";
-		donpcevent "Soldier3#mos::OnEnable";
-		mes "[Soldier]";
-		mes "We expected";
-		mes "that you would appear again.";
-		mes "What is your business with the Csar?";
-		next;
-		if(select("Run away.:Explain the situation.") == 1) {
-			mes "["+strcharinfo(0)+"]";
-			mes "I should get out of here...";
+		else {
+			mes "-I explain what happend until now.-";
+			next;
+			mes "[Soldier]";
+			mes "If you have something to say, speak";
+			mes "to the Csar.";
+			mes "If you leave to this place,";
+			mes "you will be considered as our enemy.";
 			close2;
 			close2;
-			warp "mosk_dun02",100,100;
-			donpcevent "Soldier1#mos::OnInit";
-			donpcevent "Soldier2#mos::OnInit";
-			donpcevent "Soldier3#mos::OnInit";
-			end;
 		}
 		}
-		mes "-I explain what happend until now.-";
-		next;
-		mes "[Soldier]";
-		mes "If you have something to say, speak";
-		mes "to the Csar.";
-		mes "If you leave to this place,";
-		mes "you will be considered as our enemy.";
-		close2;
 		donpcevent "Soldier1#mos::OnInit";
 		donpcevent "Soldier1#mos::OnInit";
 		donpcevent "Soldier2#mos::OnInit";
 		donpcevent "Soldier2#mos::OnInit";
 		donpcevent "Soldier3#mos::OnInit";
 		donpcevent "Soldier3#mos::OnInit";
@@ -117,7 +84,7 @@ OnTouch:
 	}
 	}
 }
 }
 
 
-mosk_dun02,53,215,3	script	Soldier1#mos	966,{
+mosk_dun02,53,215,3	script	Soldier1#mos	4_M_RUSKNIGHT,{
 	mes "[Soldier]";
 	mes "[Soldier]";
 	mes "We're the Csar's soldiers.";
 	mes "We're the Csar's soldiers.";
 	mes "We're called out for emergencies,";
 	mes "We're called out for emergencies,";
@@ -125,55 +92,23 @@ mosk_dun02,53,215,3	script	Soldier1#mos	966,{
 	close;
 	close;
 	
 	
 OnInit:
 OnInit:
-	hideonnpc "Soldier1#mos";
-	end;
-
-OnEnable:
-	hideoffnpc "Soldier1#mos";
+	hideonnpc strnpcinfo(0);
 	end;
 	end;
-}
-
-mosk_dun02,50,217,3	script	Soldier2#mos	966,{
-	mes "[Soldier]";
-	mes "We're the Csar's soldiers.";
-	mes "We're called out for emergencies,";
-	mes "don't disturb us anymore.";
-	close;
-	
-OnInit:
-	hideonnpc "Soldier2#mos";
-	end;
-
-OnEnable:
-	hideoffnpc "Soldier2#mos";
-	end;
-}
-
-
-mosk_dun02,56,217,5	script	Soldier3#mos	966,{
-	mes "[Soldier]";
-	mes "We're the Csar's soldiers.";
-	mes "We're called out for emergencies,";
-	mes "don't disturb us anymore.";
-	close;
-	
-OnInit:
-	hideonnpc "Soldier3#mos";
-	end;
-
 OnEnable:
 OnEnable:
-	hideoffnpc "Soldier3#mos";
+	hideoffnpc strnpcinfo(0);
 	end;
 	end;
 }
 }
+mosk_dun02,50,217,3	duplicate(Soldier1#mos)	Soldier2#mos	4_M_RUSKNIGHT
+mosk_dun02,56,217,5	duplicate(Soldier1#mos)	Soldier3#mos	4_M_RUSKNIGHT
 
 
-mosk_dun01,170,164,3	script	Milestone#1	111,{
+mosk_dun01,170,164,3	script	Milestone#1	HIDDEN_NPC,{
 	mes "- There is writing on a big rock. -";
 	mes "- There is writing on a big rock. -";
 	next;
 	next;
 	mes "^3131FF- Those who serve the Sun will die, Go to the North. -^000000";
 	mes "^3131FF- Those who serve the Sun will die, Go to the North. -^000000";
 	close;
 	close;
 }
 }
 
 
-mosk_dun01,207,276,3	script	Milestone#1-2	111,{
+mosk_dun01,207,276,3	script	Milestone#1-2	HIDDEN_NPC,{
 	mes "- There is writing on a big rock. -";
 	mes "- There is writing on a big rock. -";
 	next;
 	next;
 	mes "^3131FF- Those who advance may get hurt but are courageous of heart and those who move back will remain safe.";
 	mes "^3131FF- Those who advance may get hurt but are courageous of heart and those who move back will remain safe.";
@@ -189,7 +124,7 @@ mosk_dun01,207,276,3	script	Milestone#1-2	111,{
 	close;
 	close;
 }
 }
 
 
-mosk_dun01,264,191,3	script	Milestone#1-3	111,{
+mosk_dun01,264,191,3	script	Milestone#1-3	HIDDEN_NPC,{
 	mes "- There is writing on a big rock. -";
 	mes "- There is writing on a big rock. -";
 	next;
 	next;
 	mes "^3131FF- Those who advance may get hurt but are brave of heart and those who move back will remain safe.";
 	mes "^3131FF- Those who advance may get hurt but are brave of heart and those who move back will remain safe.";
@@ -205,7 +140,7 @@ mosk_dun01,264,191,3	script	Milestone#1-3	111,{
 	close;
 	close;
 }
 }
 
 
-mosk_dun02,168,28,3	script	Milestone#2-1	111,{
+mosk_dun02,168,28,3	script	Milestone#2-1	HIDDEN_NPC,{
 	mes "- There is writing on a big rock. -";
 	mes "- There is writing on a big rock. -";
 	next;
 	next;
 	mes "^3131FF- Those who advance may get hurt but are valorous of heart and those who move back will remain safe.";
 	mes "^3131FF- Those who advance may get hurt but are valorous of heart and those who move back will remain safe.";
@@ -221,7 +156,7 @@ mosk_dun02,168,28,3	script	Milestone#2-1	111,{
 	close;
 	close;
 }
 }
 
 
-mosk_dun02,268,117,3	script	Milestone#2-3	111,{
+mosk_dun02,268,117,3	script	Milestone#2-3	HIDDEN_NPC,{
 	mes "- There is writing on a big rock. -";
 	mes "- There is writing on a big rock. -";
 	next;
 	next;
 	mes "^3131FF- Those who step forward will gain honor but may die, those who step backward will have courage but may still get hurt.";
 	mes "^3131FF- Those who step forward will gain honor but may die, those who step backward will have courage but may still get hurt.";
@@ -237,7 +172,7 @@ mosk_dun02,268,117,3	script	Milestone#2-3	111,{
 	close;
 	close;
 }
 }
 
 
-mosk_dun03,27,131,3	script	Milestone#3-2	111,{
+mosk_dun03,27,131,3	script	Milestone#3-2	HIDDEN_NPC,{
 	mes "- There is writing on a big rock. -";
 	mes "- There is writing on a big rock. -";
 	next;
 	next;
 	mes "^3131FF- Those who stay may die but will gain honor, those who go back may get hurt but will gain courage.";
 	mes "^3131FF- Those who stay may die but will gain honor, those who go back may get hurt but will gain courage.";
@@ -253,7 +188,7 @@ mosk_dun03,27,131,3	script	Milestone#3-2	111,{
 	close;
 	close;
 }
 }
 
 
-mosk_dun03,119,46,3	script	Milestone#3-1	111,{
+mosk_dun03,119,46,3	script	Milestone#3-1	HIDDEN_NPC,{
 	mes "There is writing on a big rock.";
 	mes "There is writing on a big rock.";
 	next;
 	next;
 	mes "^3131FF- Those who stay may die but will gain honor, those who go back may get hurt but will gain courage.";
 	mes "^3131FF- Those who stay may die but will gain honor, those who go back may get hurt but will gain courage.";
@@ -269,14 +204,14 @@ mosk_dun03,119,46,3	script	Milestone#3-1	111,{
 	close;
 	close;
 }
 }
 
 
-mosk_dun01,194,43,3	script	Milestone#1-1	111,{
+mosk_dun01,194,43,3	script	Milestone#1-1	HIDDEN_NPC,{
 	mes "- There is writing on a big rock. -";
 	mes "- There is writing on a big rock. -";
 	next;
 	next;
 	mes "- If you want to protect your life, go back -";
 	mes "- If you want to protect your life, go back -";
 	close;
 	close;
 }
 }
 
 
-mosk_fild02,198,53,3	script	Ship#mos_dun	111,{
+mosk_fild02,198,53,3	script	Ship#mos_dun	HIDDEN_NPC,{
 	mes "- You find a ship at anchor. -";
 	mes "- You find a ship at anchor. -";
 	next;
 	next;
 	if(select("Take the ship and go back to the village.:Explore more.") == 1) {
 	if(select("Take the ship and go back to the village.:Explore more.") == 1) {

+ 20 - 6
sql-files/item_db_re.sql

@@ -2488,7 +2488,7 @@ REPLACE INTO `item_db_re` VALUES (4411,'Vanberk_Card','Vanberk Card',6,20,NULL,1
 REPLACE INTO `item_db_re` VALUES (4412,'Isilla_Card','Isilla Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bInt,2; autobonus "{ bonus bVariableCastrate,-50; bonus bFlee,30; }",50,5000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4412,'Isilla_Card','Isilla Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bInt,2; autobonus "{ bonus bVariableCastrate,-50; bonus bFlee,30; }",50,5000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4413,'Hodremlin_Card','Hodremlin Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,32,NULL,NULL,NULL,NULL,'bonus2 bSubSize,Size_All,15; autobonus2 "{ bonus bFlee2,30; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_WIND; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4413,'Hodremlin_Card','Hodremlin Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,32,NULL,NULL,NULL,NULL,'bonus2 bSubSize,Size_All,15; autobonus2 "{ bonus bFlee2,30; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_WIND; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4414,'Seeker_Card','Seeker Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,32,NULL,NULL,NULL,NULL,'skill "MG_STONECURSE",1; bonus2 bResEff,Eff_Stone,3000; bonus bMdef,10;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4414,'Seeker_Card','Seeker Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,32,NULL,NULL,NULL,NULL,'skill "MG_STONECURSE",1; bonus2 bResEff,Eff_Stone,3000; bonus bMdef,10;',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (4415,'Snowier_Card','Snowier Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,136,NULL,NULL,NULL,NULL,'bonus2 bAddMonsterDropItem,536,2000; bonus2 bAddItemHealRate,536,500;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (4415,'Snowier_Card','Snowier Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,136,NULL,NULL,NULL,NULL,'bonus2 bAddMonsterDropItem,536,500; bonus2 bAddItemHealRate,536,100;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4416,'Siroma_Card','Siroma Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,136,NULL,NULL,NULL,NULL,'bonus2 bSkillAtk,"MG_COLDBOLT",25; bonus2 bVariableCastrate,"MG_COLDBOLT",-25;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4416,'Siroma_Card','Siroma Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,136,NULL,NULL,NULL,NULL,'bonus2 bSkillAtk,"MG_COLDBOLT",25; bonus2 bVariableCastrate,"MG_COLDBOLT",-25;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4417,'Ice_Titan_Card','Ice Titan Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,64,NULL,NULL,NULL,NULL,'bonus bVit,2; autobonus2 "{ bonus bDef,10; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_FREEZED; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4417,'Ice_Titan_Card','Ice Titan Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,64,NULL,NULL,NULL,NULL,'bonus bVit,2; autobonus2 "{ bonus bDef,10; }",3,10000,BF_WEAPON|BF_MAGIC,"{ specialeffect2 EF_FREEZED; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4418,'Gazeti_Card','Gazeti Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,136,NULL,NULL,NULL,NULL,'bonus3 bAutoSpell,"MG_COLDBOLT",2,100;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4418,'Gazeti_Card','Gazeti Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,136,NULL,NULL,NULL,NULL,'bonus3 bAutoSpell,"MG_COLDBOLT",2,100;',NULL,NULL);
@@ -2531,9 +2531,9 @@ REPLACE INTO `item_db_re` VALUES (4455,'Light_Up_Card2','Light Up Card',6,20,NUL
 REPLACE INTO `item_db_re` VALUES (4456,'Nidhogg_Shadow_Card','Nidhoggur Shadow Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16,NULL,NULL,NULL,NULL,'bonus bInt,5; if (Class == Job_High_Wizard || Class == Job_Baby_Warlock || Class == Job_Warlock || Class == Job_Warlock_T) bonus bFixedCastrate,-50;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4456,'Nidhogg_Shadow_Card','Nidhoggur Shadow Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16,NULL,NULL,NULL,NULL,'bonus bInt,5; if (Class == Job_High_Wizard || Class == Job_Baby_Warlock || Class == Job_Warlock || Class == Job_Warlock_T) bonus bFixedCastrate,-50;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4457,'Nahtzigger_Card','Naght Sieger Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16,NULL,NULL,NULL,NULL,'bonus2 bMagicAtkEle,Ele_Ghost,30;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4457,'Nahtzigger_Card','Naght Sieger Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16,NULL,NULL,NULL,NULL,'bonus2 bMagicAtkEle,Ele_Ghost,30;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4458,'Duneirre_Card','Duneyrr Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bBaseAtk,10; autobonus "{ bonus bAspdRate,5; }",10,10000,0,"{ specialeffect2 EF_HASTEUP; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4458,'Duneirre_Card','Duneyrr Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bBaseAtk,10; autobonus "{ bonus bAspdRate,5; }",10,10000,0,"{ specialeffect2 EF_HASTEUP; }";',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (4459,'Lata_Card','Rata Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bMatk,10; autobonus "{ bonus bFixedCastrate,-50; }",10,4000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }";',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (4460,'Ringco_Card','Rhyncho Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bHealPower,4; bonus bUseSPrate,5;',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (4461,'Pillar_Card','Phylla Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bDex,1; bonus bAgi,1; autobonus "{ bonus bCritical,20; }",4,4000,0,"{ specialeffect2 EF_ENHANCE; }";',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (4459,'Lata_Card','Rata Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bMatk,10; autobonus "{ bonus bFixedCastrate,-50; }",5,4000,BF_MAGIC,"{ specialeffect2 EF_SUFFRAGIUM; }";',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (4460,'Ringco_Card','Rhyncho Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bHealPower,4; bonus2 bSkillUseSP,"AL_HEAL",-15;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (4461,'Pillar_Card','Phylla Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,769,NULL,NULL,NULL,NULL,'bonus bDex,1; bonus bAgi,1; autobonus "{ bonus bCritical,20; }",15,4000,0,"{ specialeffect2 EF_ENHANCE; }";',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4462,'Hardrock_Mammos_Card','Hardrock Mammoth Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16,NULL,NULL,NULL,NULL,'bonus bDef,5; if(getrefine()>=12) { bonus bDef,20; bonus bMaxHPrate,10; } if(getrefine()>=14) { bonus bMaxHPrate,3; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4462,'Hardrock_Mammos_Card','Hardrock Mammoth Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,16,NULL,NULL,NULL,NULL,'bonus bDef,5; if(getrefine()>=12) { bonus bDef,20; bonus bMaxHPrate,10; } if(getrefine()>=14) { bonus bMaxHPrate,3; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4463,'Tendrilrion_Card','Tendrilrion Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,2,NULL,NULL,NULL,NULL,'bonus bCritical,5; if(getrefine()>=12) { bonus bBaseAtk,35; } if(getrefine()>=14) { bonus bCritical,10; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4463,'Tendrilrion_Card','Tendrilrion Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,2,NULL,NULL,NULL,NULL,'bonus bCritical,5; if(getrefine()>=12) { bonus bBaseAtk,35; } if(getrefine()>=14) { bonus bCritical,10; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4464,'Aunoe_Card','Aunoe Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,2,NULL,NULL,NULL,NULL,'bonus bCritAtkRate,20;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (4464,'Aunoe_Card','Aunoe Card',6,20,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,2,NULL,NULL,NULL,NULL,'bonus bCritAtkRate,20;',NULL,NULL);
@@ -4543,6 +4543,7 @@ REPLACE INTO `item_db_re` VALUES (6862,'Piece_Of_Soul_Tiger','Piece Of Soul Tige
 REPLACE INTO `item_db_re` VALUES (6863,'Strong_Piece_Of_Soul_Tiger','Strong Piece Of Soul Tiger',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6863,'Strong_Piece_Of_Soul_Tiger','Strong Piece Of Soul Tiger',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6864,'Safe_to_19_Weapon_Certificate','Safe to 19 Weapon Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6864,'Safe_to_19_Weapon_Certificate','Safe to 19 Weapon Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6865,'Safe_to_19_Armor_Certificate','Safe to 19 Armor Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6865,'Safe_to_19_Armor_Certificate','Safe to 19 Armor Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (6866,'Piece_Of_Soul_Rabbit','Piece Of Soul Rabbit',3,0,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6885,'Piece_Of_Soul_Dragon','Piece Of Soul Dragon',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6885,'Piece_Of_Soul_Dragon','Piece Of Soul Dragon',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6870,'Safe_to_13_Weapon_Certificate','Safe to 13 Weapon Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6870,'Safe_to_13_Weapon_Certificate','Safe to 13 Weapon Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6871,'Safe_to_14_Weapon_Certificate','Safe to 14 Weapon Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (6871,'Safe_to_14_Weapon_Certificate','Safe to 14 Weapon Certificate',3,10,NULL,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
@@ -6220,7 +6221,7 @@ REPLACE INTO `item_db_re` VALUES (12420,'Stamina_Up_M','Stamina Up M',2,100,NULL
 REPLACE INTO `item_db_re` VALUES (12421,'Falmons_F','Falmons F',3,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_LIFE_FORCE_F,500000,5;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12421,'Falmons_F','Falmons F',3,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_LIFE_FORCE_F,500000,5;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12422,'HP_Increase_Potion_(Small)','HP Increase Potion (Small)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMHP,500000,(500+(BaseLevel*10/3)); percentheal 1,0;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12422,'HP_Increase_Potion_(Small)','HP Increase Potion (Small)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMHP,500000,(500+(BaseLevel*10/3)); percentheal 1,0;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12423,'HP_Increase_Potion_(Medium)','HP Increase Potion (Medium)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMHP,500000,(1500+(BaseLevel*10/3)); percentheal 2,0;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12423,'HP_Increase_Potion_(Medium)','HP Increase Potion (Medium)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMHP,500000,(1500+(BaseLevel*10/3)); percentheal 2,0;',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (12424,'HP_Increase_Potion_(Large)','HP Increase Potion (Large)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMHP,500000,(2500+(BaseLevel*10/3)); percentheal 5,0;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (12424,'HP_Increase_Potion_(Large)','HP Increase Potion (Large)',0,10,NULL,80,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMHP,500000,(2500+(BaseLevel*10/3)); percentheal 5,0;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12425,'SP_Increase_Potion_(Small)','SP Increase Potion (Small)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMSPRATE,500000,((BaseLevel/10)-5); percentheal 0,2;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12425,'SP_Increase_Potion_(Small)','SP Increase Potion (Small)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMSPRATE,500000,((BaseLevel/10)-5); percentheal 0,2;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12426,'SP_Increase_Potion_(Medium)','SP Increase Potion (Medium)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMSPRATE,500000,(BaseLevel/10); percentheal 0,4;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12426,'SP_Increase_Potion_(Medium)','SP Increase Potion (Medium)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMSPRATE,500000,(BaseLevel/10); percentheal 0,4;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12427,'SP_Increase_Potion_(Large)','SP Increase Potion (Large)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMSPRATE,500000,((BaseLevel/10)+5); percentheal 0,8;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (12427,'SP_Increase_Potion_(Large)','SP Increase Potion (Large)',0,10,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'sc_start SC_INCMSPRATE,500000,((BaseLevel/10)+5); percentheal 0,8;',NULL,NULL);
@@ -8219,7 +8220,7 @@ REPLACE INTO `item_db_re` VALUES (15117,'Tarlock\'s_Armor','Tarlock\'s Armor',4,
 REPLACE INTO `item_db_re` VALUES (15121,'Sarah_Combat_Robe','Sarah Combat Robe',4,10,NULL,800,NULL,35,NULL,1,0xFFFFFFFF,63,2,16,NULL,'145',1,NULL,'/*TODO: Confirm the real rate and additional MAtk*/ autobonus "{ bonus bMatk,20; }",100,(10+((getrefine()) ? getrefine()*8 : 0))*1000,BF_MAGIC;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (15121,'Sarah_Combat_Robe','Sarah Combat Robe',4,10,NULL,800,NULL,35,NULL,1,0xFFFFFFFF,63,2,16,NULL,'145',1,NULL,'/*TODO: Confirm the real rate and additional MAtk*/ autobonus "{ bonus bMatk,20; }",100,(10+((getrefine()) ? getrefine()*8 : 0))*1000,BF_MAGIC;',NULL,NULL);
 
 
 # More Maces
 # More Maces
-REPLACE INTO `item_db_re` VALUES (16000,'Erde','Erde',5,20,NULL,500,'130',NULL,1,2,0x0004C5B2,18,2,2,4,'50',1,8,'bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus bMaxSP,50; bonus bHealPower,10;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (16000,'Erde','Erde',5,20,NULL,500,'130',NULL,1,2,0x0004C5B2,18,2,2,3,'50',1,8,'bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus bMaxSP,50; bonus bHealPower,10;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (16001,'Red_Square_Bag','Red Square Bag',5,20,NULL,500,'130',NULL,1,2,0x0004C5B2,18,2,2,3,'50',1,8,'bonus bMaxHP,200; bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus2 bAddMonsterDropItem,501,50; bonus2 bAddMonsterDropItem,502,20; bonus2 bAddMonsterDropItem,503,20; bonus2 bAddMonsterDropItem,504,20; bonus2 bAddMonsterDropItem,505,10; if(readparam(bStr)>=95) bonus2 bAddEff,Eff_Stun,500;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (16001,'Red_Square_Bag','Red Square Bag',5,20,NULL,500,'130',NULL,1,2,0x0004C5B2,18,2,2,3,'50',1,8,'bonus bMaxHP,200; bonus2 bSkillAtk,"AM_ACIDTERROR",20; bonus2 bSkillAtk,"AM_DEMONSTRATION",20; bonus2 bAddMonsterDropItem,501,50; bonus2 bAddMonsterDropItem,502,20; bonus2 bAddMonsterDropItem,503,20; bonus2 bAddMonsterDropItem,504,20; bonus2 bAddMonsterDropItem,505,10; if(readparam(bStr)>=95) bonus2 bAddEff,Eff_Stun,500;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (16002,'Stunner_C','Stunner',5,0,NULL,0,'175',NULL,1,0,0x00008110,63,2,2,3,'1',0,8,'bonus2 bAddEff,Eff_Stun,1000; bonus2 bAddSize,Size_All,40;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (16002,'Stunner_C','Stunner',5,0,NULL,0,'175',NULL,1,0,0x00008110,63,2,2,3,'1',0,8,'bonus2 bAddEff,Eff_Stun,1000; bonus2 bAddSize,Size_All,40;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (16003,'Carga_Mace','Carga Mace',5,20,NULL,1500,'175',NULL,1,2,0x0004C5B2,63,2,2,3,'100',1,8,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (16003,'Carga_Mace','Carga Mace',5,20,NULL,1500,'175',NULL,1,2,0x0004C5B2,63,2,2,3,'100',1,8,NULL,NULL,NULL);
@@ -9342,7 +9343,10 @@ REPLACE INTO `item_db_re` VALUES (19589,'C_Fallen_Angel_Lost_J','Costume Fallen
 REPLACE INTO `item_db_re` VALUES (19590,'C_Twin_Maiden_Ribbon_J','Maiden\'s Twin Ribbon',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'0',0,239,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19590,'C_Twin_Maiden_Ribbon_J','Maiden\'s Twin Ribbon',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'0',0,239,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19598,'C_Wandering_Wolf_Hat','Costume Wandering Wolf Hat',4,20,NULL,600,NULL,5,NULL,0,0xFFFFFFFE,63,2,768,NULL,'20',0,490,'bonus bVit,5; bonus bFlee,10;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19598,'C_Wandering_Wolf_Hat','Costume Wandering Wolf Hat',4,20,NULL,600,NULL,5,NULL,0,0xFFFFFFFE,63,2,768,NULL,'20',0,490,'bonus bVit,5; bonus bFlee,10;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19599,'C_Imp_Hat','Costume Imp Hat',4,20,NULL,400,NULL,1,NULL,0,0xFFFFFFFF,63,2,256,NULL,'1',1,589,'bonus3 bAutoSpell,"SA_FLAMELAUNCHER",1,5;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19599,'C_Imp_Hat','Costume Imp Hat',4,20,NULL,400,NULL,1,NULL,0,0xFFFFFFFF,63,2,256,NULL,'1',1,589,'bonus3 bAutoSpell,"SA_FLAMELAUNCHER",1,5;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (19600,'C_Drooping_Kiehl','Costume Drooping Kiehl',12,0,NULL,40,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'30',NULL,909,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (19601,'C_Drooping_Aliot','Costume Drooping Aliot',12,0,NULL,10,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,910,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19603,'C_Invisible_Sunglasses','Costume Invisible Sunglasses',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,2048,NULL,'1',0,0,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19603,'C_Invisible_Sunglasses','Costume Invisible Sunglasses',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,2048,NULL,'1',0,0,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (19604,'Brawler\'s_Supply_Crate','Brawler\'s Supply Crate',18,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,NULL,NULL,NULL,NULL,NULL,'getitem(12208,4); getitem(12072,6); getitem(12082,6); getitem(12087,6); getitem(11502,30);',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19607,'C_Love_Chick_Hat','Costume Love Chick Hat',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',0,500,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19607,'C_Love_Chick_Hat','Costume Love Chick Hat',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',0,500,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19613,'C_Valkyrie_Feather_Hat','Costume Valkyrie Feather Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,300,'bonus bAllStats,1; skill "PR_MAGNUS",5; skill "SA_FLAMELAUNCHER",1; skill "SA_FROSTWEAPON",1; skill "SA_LIGHTNINGLOADER",1; skill "SA_SEISMICWEAPON",1;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19613,'C_Valkyrie_Feather_Hat','Costume Valkyrie Feather Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,300,'bonus bAllStats,1; skill "PR_MAGNUS",5; skill "SA_FLAMELAUNCHER",1; skill "SA_FROSTWEAPON",1; skill "SA_LIGHTNINGLOADER",1; skill "SA_SEISMICWEAPON",1;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19617,'C_Puppy_Headband','Costume Puppy Headband',4,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,NULL,NULL,199,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19617,'C_Puppy_Headband','Costume Puppy Headband',4,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,NULL,NULL,199,NULL,NULL,NULL);
@@ -9442,6 +9446,8 @@ REPLACE INTO `item_db_re` VALUES (19799,'C_Golden_Gear','Costume Golden Gear',4,
 REPLACE INTO `item_db_re` VALUES (19800,'C_Carnation_Hairband','Costume Carnation Headband',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,878,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19800,'C_Carnation_Hairband','Costume Carnation Headband',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,878,NULL,NULL,NULL);
 #
 #
 REPLACE INTO `item_db_re` VALUES (19821,'C_Hyegun_hat','C Yao Jun',4,20,NULL,10,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',0,375,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19821,'C_Hyegun_hat','C Yao Jun',4,20,NULL,10,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',0,375,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (19824,'C_Evil_Druid_Hat','Costume Evil Druid Hat',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,1053,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (19825,'C_Vicious_Stop_Bandage','Costume Vicious Stop Bandage',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,1054,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19826,'C_Ice_Wing_Ear','C Ice Wing Ear',4,20,NULL,10,NULL,0,NULL,0,0xFFFFFFFF,63,2,2048,NULL,'1',0,584,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19826,'C_Ice_Wing_Ear','C Ice Wing Ear',4,20,NULL,10,NULL,0,NULL,0,0xFFFFFFFF,63,2,2048,NULL,'1',0,584,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19829,'C_Straw_Hat','C Straw Hat',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'0',0,146,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19829,'C_Straw_Hat','C Straw Hat',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'0',0,146,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19830,'C_Sunglasses','Costume Sunglasses',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,2048,NULL,'1',NULL,12,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19830,'C_Sunglasses','Costume Sunglasses',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,2048,NULL,'1',NULL,12,NULL,NULL,NULL);
@@ -9476,6 +9482,8 @@ REPLACE INTO `item_db_re` VALUES (19863,'C_Incubus_Horn','Incubus Horn',4,20,NUL
 REPLACE INTO `item_db_re` VALUES (19864,'C_Dokebi\'s_Wig','Dokebi\'s Wig',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,3072,NULL,'0',0,302,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19864,'C_Dokebi\'s_Wig','Dokebi\'s Wig',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,3072,NULL,'0',0,302,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19865,'C_Joker_Jester','Joker Jester',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'0',0,89,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19865,'C_Joker_Jester','Joker Jester',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'0',0,89,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19871,'C_DecorationOfMusic_Accessory','Decoration of Music',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,2048,NULL,'0',0,1074,'sc_start SC_DECORATION_OF_MUSIC,-1,0;',NULL,'sc_end SC_DECORATION_OF_MUSIC;');
 REPLACE INTO `item_db_re` VALUES (19871,'C_DecorationOfMusic_Accessory','Decoration of Music',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,2048,NULL,'0',0,1074,'sc_start SC_DECORATION_OF_MUSIC,-1,0;',NULL,'sc_end SC_DECORATION_OF_MUSIC;');
+REPLACE INTO `item_db_re` VALUES (19878,'C_Evolved_Drooping_Bunny','Costume Evolved Drooping Bunny',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,249,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (19883,'C_Cyclops_Glasses','Costume Cyclops Glasses',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,2048,NULL,'1',NULL,1087,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19884,'C_Vanargand_Helm','Costume Vanargand Helm',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,804,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19884,'C_Vanargand_Helm','Costume Vanargand Helm',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,804,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19885,'C_Blinker','Costume Blinker',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,2048,NULL,'1',NULL,82,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19885,'C_Blinker','Costume Blinker',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,2048,NULL,'1',NULL,82,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19886,'C_Purple_Glasses','Costume Purple Glasses',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,2048,NULL,'1',NULL,26,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19886,'C_Purple_Glasses','Costume Purple Glasses',4,10,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,2048,NULL,'1',NULL,26,NULL,NULL,NULL);
@@ -9492,6 +9500,7 @@ REPLACE INTO `item_db_re` VALUES (19920,'C_Adv_Whisper_Mask','Costume Evolved Wh
 REPLACE INTO `item_db_re` VALUES (19922,'Costume_Noahs_Hat','Costume Noahs Hat',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,7168,NULL,'1',0,636,'/* TODO */',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19922,'Costume_Noahs_Hat','Costume Noahs Hat',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,7168,NULL,'1',0,636,'/* TODO */',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19929,'C_Classical_Ribbon','Costume Classical Ribbon',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,NULL,1,NULL,'/*TODO: View ID*/',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19929,'C_Classical_Ribbon','Costume Classical Ribbon',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,NULL,1,NULL,'/*TODO: View ID*/',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19934,'C_Lolita_Ten_Gallon_Hat','Costume Alive Ten Gallon Hat Of Flame',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1048,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19934,'C_Lolita_Ten_Gallon_Hat','Costume Alive Ten Gallon Hat Of Flame',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1048,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (19935,'C_Hunting_Cap_Of_Gust','Costume Hunting Cap Of Gust',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,1076,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19938,'Costume_Love_Rabbit_Hood','Costume Love Rabbit Hood',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,7168,NULL,'1',0,549,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19938,'Costume_Love_Rabbit_Hood','Costume Love Rabbit Hood',4,0,NULL,0,NULL,0,NULL,0,0xFFFFFFFF,63,2,7168,NULL,'1',0,549,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19961,'C_Rune_Circlet','Costume Rune Circlet',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,623,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19961,'C_Rune_Circlet','Costume Rune Circlet',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,623,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19962,'C_Mitra','Costume Mitra',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,624,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (19962,'C_Mitra','Costume Mitra',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,624,NULL,NULL,NULL);
@@ -9530,9 +9539,14 @@ REPLACE INTO `item_db_re` VALUES (20027,'C_Cow_Hat3','Costume Cow Hat 3',4,10,NU
 REPLACE INTO `item_db_re` VALUES (20028,'C_Cow_Hat4','Costume Cow Hat 4',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1214,'bonus bDex,2; bonus2 bAddMonsterDropItem,519,100;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20028,'C_Cow_Hat4','Costume Cow Hat 4',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1214,'bonus bDex,2; bonus2 bAddMonsterDropItem,519,100;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20034,'C_Jack_Castle_Bat','Costume Jack Castle Bat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1041,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20034,'C_Jack_Castle_Bat','Costume Jack Castle Bat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1041,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20038,'C_Alphonse_Helmet','Costume Alphonse Helmet',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,NULL,1,NULL,'/*TODO: View ID*/',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20038,'C_Alphonse_Helmet','Costume Alphonse Helmet',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,NULL,1,NULL,'/*TODO: View ID*/',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (20049,'C_Giant_Band_Aid','Costume Giant Band Aid',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,147,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20053,'C_W_King_Tiger_Doll_Hat','Costume White King Tiger Doll Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,973,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20053,'C_W_King_Tiger_Doll_Hat','Costume White King Tiger Doll Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,973,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20063,'C_Yellow_Brain_Hat','Costume Yellow Brain Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1228,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20063,'C_Yellow_Brain_Hat','Costume Yellow Brain Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1228,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20064,'C_Blue_Brain_Hat','Costume Blue Brain Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1228,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20064,'C_Blue_Brain_Hat','Costume Blue Brain Hat',4,10,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1228,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (20067,'C_White_Rabbit_Headband','Costume White Rabbit Headband',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,719,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (20068,'C_Black_Rabbit_Headband','Costume Black Rabbit Headband',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,718,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (20073,'C_Hair_Band','Costume Hair Band',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,9,NULL,NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (20074,'C_Biretta','Costume_Biretta',12,0,NULL,0,NULL,NULL,NULL,NULL,0xFFFFFFFF,63,2,1024,NULL,'1',NULL,11,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20086,'C_Dragon_Cintamani_Hat1','Costume Dragon Cintamani Hat',4,0,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1245,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20086,'C_Dragon_Cintamani_Hat1','Costume Dragon Cintamani Hat',4,0,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1245,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20087,'C_Dragon_Cintamani_Hat2','Costume Dragon Cintamani Hat',4,0,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1246,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20087,'C_Dragon_Cintamani_Hat2','Costume Dragon Cintamani Hat',4,0,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1246,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20088,'C_Dragon_Cintamani_Hat3','Costume Dragon Cintamani Hat',4,0,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1247,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (20088,'C_Dragon_Cintamani_Hat3','Costume Dragon Cintamani Hat',4,0,NULL,0,NULL,NULL,NULL,0,0xFFFFFFFF,63,2,1024,NULL,'1',1,1247,NULL,NULL,NULL);

+ 1 - 1
sql-files/logs.sql

@@ -32,7 +32,7 @@ CREATE TABLE IF NOT EXISTS `zenylog` (
   `time` datetime NOT NULL default '0000-00-00 00:00:00',
   `time` datetime NOT NULL default '0000-00-00 00:00:00',
   `char_id` int(11) NOT NULL default '0',
   `char_id` int(11) NOT NULL default '0',
   `src_id` int(11) NOT NULL default '0',
   `src_id` int(11) NOT NULL default '0',
-  `type` enum('T','V','P','M','S','N','D','C','A','E','I','B') NOT NULL default 'S',
+  `type` enum('T','V','P','M','S','N','D','C','A','E','I','B','K') NOT NULL default 'S',
   `amount` int(11) NOT NULL default '0',
   `amount` int(11) NOT NULL default '0',
   `map` varchar(11) NOT NULL default '',
   `map` varchar(11) NOT NULL default '',
   PRIMARY KEY  (`id`),
   PRIMARY KEY  (`id`),

+ 6 - 0
sql-files/main.sql

@@ -731,6 +731,9 @@ CREATE TABLE IF NOT EXISTS `vendings` (
   `x` smallint(5) unsigned NOT NULL,
   `x` smallint(5) unsigned NOT NULL,
   `y` smallint(5) unsigned NOT NULL,
   `y` smallint(5) unsigned NOT NULL,
   `title` varchar(80) NOT NULL,
   `title` varchar(80) NOT NULL,
+  `body_direction` CHAR( 1 ) NOT NULL DEFAULT '4',
+  `head_direction` CHAR( 1 ) NOT NULL DEFAULT '0',
+  `sit` CHAR( 1 ) NOT NULL DEFAULT '1',
   `autotrade` tinyint(4) NOT NULL,
   `autotrade` tinyint(4) NOT NULL,
   PRIMARY KEY (`id`)
   PRIMARY KEY (`id`)
 ) ENGINE=MyISAM;
 ) ENGINE=MyISAM;
@@ -753,6 +756,9 @@ CREATE TABLE IF NOT EXISTS `buyingstores` (
   `y` smallint(5) unsigned NOT NULL,
   `y` smallint(5) unsigned NOT NULL,
   `title` varchar(80) NOT NULL,
   `title` varchar(80) NOT NULL,
   `limit` int(10) unsigned NOT NULL,
   `limit` int(10) unsigned NOT NULL,
+  `body_direction` CHAR( 1 ) NOT NULL DEFAULT '4',
+  `head_direction` CHAR( 1 ) NOT NULL DEFAULT '0',
+  `sit` CHAR( 1 ) NOT NULL DEFAULT '1',
   `autotrade` tinyint(4) NOT NULL,
   `autotrade` tinyint(4) NOT NULL,
   PRIMARY KEY (`id`)
   PRIMARY KEY (`id`)
 ) ENGINE=MyISAM;
 ) ENGINE=MyISAM;

+ 1 - 0
sql-files/upgrades/upgrade_20140713.sql

@@ -0,0 +1 @@
+ALTER TABLE `zenylog` CHANGE `type` `type` ENUM('T','V','P','M','S','N','D','C','A','E','I','B','K') NOT NULL DEFAULT 'S';

+ 7 - 0
sql-files/upgrades/upgrade_20140723.sql

@@ -0,0 +1,7 @@
+ALTER TABLE `vendings` ADD `body_direction` CHAR( 1 ) NOT NULL DEFAULT '4',
+ADD `head_direction` CHAR( 1 ) NOT NULL DEFAULT '0',
+ADD `sit` CHAR( 1 ) NOT NULL DEFAULT '1';
+
+ALTER TABLE `buyingstores` ADD `body_direction` CHAR( 1 ) NOT NULL DEFAULT '4',
+ADD `head_direction` CHAR( 1 ) NOT NULL DEFAULT '0',
+ADD `sit` CHAR( 1 ) NOT NULL DEFAULT '1';

+ 3 - 35
src/char/char.c

@@ -1968,43 +1968,11 @@ int char_lan_subnetcheck(uint32 ip){
 }
 }
 
 
 // Console Command Parser [Wizputer]
 // Console Command Parser [Wizputer]
-int parse_console(const char* buf)
-{
-	char type[64];
-	char command[64];
-	int n=0;
-
-	if( ( n = sscanf(buf, "%63[^:]:%63[^\n]", type, command) ) < 2 ){
-		if((n = sscanf(buf, "%63[^\n]", type))<1) return -1; //nothing to do no arg
-	}
-	if( n != 2 ){ //end string
-		ShowNotice("Type: '%s'\n",type);
-		command[0] = '\0';
-	}
-	else
-		ShowNotice("Type of command: '%s' || Command: '%s'\n",type,command);
-
-	if( n == 2 && strcmpi("server", type) == 0 ){
-		if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
-			runflag = CHARSERVER_ST_SHUTDOWN;
-		}
-		else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
-			ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
-	}
-	else if( strcmpi("ers_report", type) == 0 ){
-		ers_report();
-	}
-	else if( strcmpi("help", type) == 0 ){
-		ShowInfo("Available commands:\n");
-		ShowInfo("\t server:shutdown => Stops the server.\n");
-		ShowInfo("\t server:alive => Checks if the server is running.\n");
-		ShowInfo("\t ers_report => Displays database usage.\n");
-	}
-
-	return 0;
+//FIXME to be remove (moved to cnslif / will be done once map/char/login, all have their cnslif interface ready)
+int parse_console(const char* buf){
+	return cnslif_parse(buf);
 }
 }
 
 
-
 //------------------------------------------------
 //------------------------------------------------
 //Pincode system
 //Pincode system
 //------------------------------------------------
 //------------------------------------------------

+ 9 - 0
src/char/char_clif.c

@@ -337,6 +337,15 @@ void chclif_char_delete2_ack(int fd, int char_id, uint32 result, time_t delete_d
 /// Any (0x718): An unknown error has occurred.
 /// Any (0x718): An unknown error has occurred.
 /// HC: <082a>.W <char id>.L <Msg:0-5>.L
 /// HC: <082a>.W <char id>.L <Msg:0-5>.L
 void chclif_char_delete2_accept_ack(int fd, int char_id, uint32 result) {
 void chclif_char_delete2_accept_ack(int fd, int char_id, uint32 result) {
+	if(result == 1 ){
+		struct char_session_data* sd;
+		sd = (struct char_session_data*)session[fd]->session_data;
+
+		if( sd->version >= date2version(20130000) ){
+			chclif_mmo_char_send(fd, sd);
+		}
+	}
+
 	WFIFOHEAD(fd,10);
 	WFIFOHEAD(fd,10);
 	WFIFOW(fd,0) = 0x82a;
 	WFIFOW(fd,0) = 0x82a;
 	WFIFOL(fd,2) = char_id;
 	WFIFOL(fd,2) = char_id;

+ 2 - 2
src/char/char_mapif.c

@@ -348,7 +348,7 @@ int chmapif_parse_regmapuser(int fd, int id){
  */
  */
 int chmapif_parse_reqsavechar(int fd, int id){
 int chmapif_parse_reqsavechar(int fd, int id){
 	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
 	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-            return 0;
+		return 0;
 	{
 	{
 		int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2);
 		int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2);
 		struct online_char_data* character;
 		struct online_char_data* character;
@@ -449,7 +449,7 @@ int chmapif_parse_authok(int fd){
 //Request to save skill cooldown data
 //Request to save skill cooldown data
 int chmapif_parse_req_saveskillcooldown(int fd){
 int chmapif_parse_req_saveskillcooldown(int fd){
 	if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
 	if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
-            return 0;
+		return 0;
 	else {
 	else {
 		int count, aid, cid;
 		int count, aid, cid;
 		aid = RFIFOL(fd,4);
 		aid = RFIFOL(fd,4);

+ 1 - 1
src/common/mmo.h

@@ -60,7 +60,7 @@
 #define ACCOUNT_REG2_NUM 16 ///Max permanent global account variables per account
 #define ACCOUNT_REG2_NUM 16 ///Max permanent global account variables per account
 #define MAX_REG_NUM 256 ///Should hold the max of GLOBAL/ACCOUNT/ACCOUNT2 (needed for some arrays that hold all three)
 #define MAX_REG_NUM 256 ///Should hold the max of GLOBAL/ACCOUNT/ACCOUNT2 (needed for some arrays that hold all three)
 #define DEFAULT_WALK_SPEED 150 ///Default walk speed
 #define DEFAULT_WALK_SPEED 150 ///Default walk speed
-#define MIN_WALK_SPEED 0 ///Min walk speed
+#define MIN_WALK_SPEED 20 ///Min walk speed
 #define MAX_WALK_SPEED 1000 ///Max walk speed
 #define MAX_WALK_SPEED 1000 ///Max walk speed
 #define MAX_STORAGE 600 ///Max number of storage slots a player can have, (up to ~850 tested)
 #define MAX_STORAGE 600 ///Max number of storage slots a player can have, (up to ~850 tested)
 #define MAX_GUILD_STORAGE 600 ///Max number of storage slots a guild
 #define MAX_GUILD_STORAGE 600 ///Max number of storage slots a guild

+ 7 - 1
src/common/utils.h

@@ -14,9 +14,15 @@ void ShowDump(const void* buffer, size_t length);
 void findfile(const char *p, const char *pat, void (func)(const char*));
 void findfile(const char *p, const char *pat, void (func)(const char*));
 bool exists(const char* filename);
 bool exists(const char* filename);
 
 
-//Caps values to min/max
+/// Caps values to min/max
 #define cap_value(a, min, max) ((a >= max) ? max : (a <= min) ? min : a)
 #define cap_value(a, min, max) ((a >= max) ? max : (a <= min) ? min : a)
 
 
+/// Apply rate for val, divided by 100)
+#define apply_rate(val, rate) (((rate) == 100) ? (val) : ((val) > 100000) ? (val) / 100 * (rate) : (val) * (rate) / 100)
+
+/// Apply rate for val, divided by per
+#define apply_rate2(val, rate, per) (((rate) == (per)) ? (val) : ((val) > 100000) ? (val) / (per) * (rate) : (val) * (rate) / (per))
+
 /// calculates the value of A / B, in percent (rounded down)
 /// calculates the value of A / B, in percent (rounded down)
 unsigned int get_percentage(const unsigned int A, const unsigned int B);
 unsigned int get_percentage(const unsigned int A, const unsigned int B);
 
 

+ 3 - 0
src/config/const.h

@@ -89,6 +89,9 @@
 /* Feb 1st 2012 */
 /* Feb 1st 2012 */
 #if PACKETVER >= 20120201
 #if PACKETVER >= 20120201
 	#define NEW_CARTS
 	#define NEW_CARTS
+	#ifndef ENABLE_SC_SAVING
+	 #warning "Cart won't be able to be saved for relog"
+	#endif
 	#define MAX_CARTS 9
 	#define MAX_CARTS 9
 #else
 #else
 	#define MAX_CARTS 5
 	#define MAX_CARTS 5

+ 115 - 53
src/login/account_sql.c → src/login/account.c

@@ -1,5 +1,11 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+/**
+ * @file account.c
+ * Module purpose is to save, load, and update changes into the account table or file.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams < r15k
+ * @author rAthena Dev Team
+ */
 
 
 #include "../common/malloc.h"
 #include "../common/malloc.h"
 #include "../common/mmo.h"
 #include "../common/mmo.h"
@@ -16,8 +22,7 @@
 #define ACCOUNT_SQL_DB_VERSION 20110114
 #define ACCOUNT_SQL_DB_VERSION 20110114
 
 
 /// internal structure
 /// internal structure
-typedef struct AccountDB_SQL
-{
+typedef struct AccountDB_SQL {
 	AccountDB vtable;    // public interface
 	AccountDB vtable;    // public interface
 
 
 	Sql* accounts;       // SQL accounts storage
 	Sql* accounts;       // SQL accounts storage
@@ -44,10 +49,8 @@ typedef struct AccountDB_SQL
 } AccountDB_SQL;
 } AccountDB_SQL;
 
 
 /// internal structure
 /// internal structure
-typedef struct AccountDBIterator_SQL
-{
+typedef struct AccountDBIterator_SQL {
 	AccountDBIterator vtable;    // public interface
 	AccountDBIterator vtable;    // public interface
-
 	AccountDB_SQL* db;
 	AccountDB_SQL* db;
 	int last_account_id;
 	int last_account_id;
 } AccountDBIterator_SQL;
 } AccountDBIterator_SQL;
@@ -70,8 +73,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
 static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new);
 static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new);
 
 
 /// public constructor
 /// public constructor
-AccountDB* account_db_sql(void)
-{
+AccountDB* account_db_sql(void) {
 	AccountDB_SQL* db = (AccountDB_SQL*)aCalloc(1, sizeof(AccountDB_SQL));
 	AccountDB_SQL* db = (AccountDB_SQL*)aCalloc(1, sizeof(AccountDB_SQL));
 
 
 	// set up the vtable
 	// set up the vtable
@@ -114,9 +116,11 @@ AccountDB* account_db_sql(void)
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
 
 
 
 
-/// establishes database connection
-static bool account_db_sql_init(AccountDB* self)
-{
+/**
+ * Establish the database connection.
+ * @param self: pointer to db
+ */
+static bool account_db_sql_init(AccountDB* self) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	Sql* sql_handle;
 	Sql* sql_handle;
 	const char* username;
 	const char* username;
@@ -162,9 +166,11 @@ static bool account_db_sql_init(AccountDB* self)
 	return true;
 	return true;
 }
 }
 
 
-/// disconnects from database
-static void account_db_sql_destroy(AccountDB* self)
-{
+/**
+ * Destroy the database and close the connection to it.
+ * @param self: pointer to db
+ */
+static void account_db_sql_destroy(AccountDB* self){
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 
 
 	Sql_Free(db->accounts);
 	Sql_Free(db->accounts);
@@ -172,7 +178,15 @@ static void account_db_sql_destroy(AccountDB* self)
 	aFree(db);
 	aFree(db);
 }
 }
 
 
-/// Gets a property from this database.
+/**
+ * Get configuration information into buf.
+ *  If the option is supported, adjust the internal state.
+ * @param self: pointer to db
+ * @param key: config keyword
+ * @param buf: value set of the keyword
+ * @param buflen: size of buffer to avoid out of bound
+ * @return true if successful, false if something has failed
+ */
 static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen)
 static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen)
 {
 {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
@@ -259,9 +273,15 @@ static bool account_db_sql_get_property(AccountDB* self, const char* key, char*
 	return false;// not found
 	return false;// not found
 }
 }
 
 
-/// if the option is supported, adjusts the internal state
-static bool account_db_sql_set_property(AccountDB* self, const char* key, const char* value)
-{
+/**
+ * Read and set configuration.
+ *  If the option is supported, adjust the internal state.
+ * @param self: pointer to db
+ * @param key: config keyword
+ * @param value: config value for keyword
+ * @return true if successful, false if something has failed
+ */
+static bool account_db_sql_set_property(AccountDB* self, const char* key, const char* value) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	const char* signature;
 	const char* signature;
 
 
@@ -330,11 +350,15 @@ static bool account_db_sql_set_property(AccountDB* self, const char* key, const
 	return false;// not found
 	return false;// not found
 }
 }
 
 
-/// create a new account entry
-/// If acc->account_id is -1, the account id will be auto-generated,
-/// and its value will be written to acc->account_id if everything succeeds.
-static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc)
-{
+/**
+ * Create a new account entry.
+ *  If acc->account_id is -1, the account id will be auto-generated,
+ *  and its value will be written to acc->account_id if everything succeeds.
+ * @param self: pointer to db
+ * @param acc: pointer of mmo_account to save
+ * @return true if successful, false if something has failed
+ */
+static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	Sql* sql_handle = db->accounts;
 	Sql* sql_handle = db->accounts;
 
 
@@ -383,9 +407,13 @@ static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc)
 	return mmo_auth_tosql(db, acc, true);
 	return mmo_auth_tosql(db, acc, true);
 }
 }
 
 
-/// delete an existing account entry + its regs
-static bool account_db_sql_remove(AccountDB* self, const int account_id)
-{
+/**
+ * Delete an existing account entry and its regs.
+ * @param self: pointer to db
+ * @param account_id: id of user account
+ * @return true if successful, false if something has failed
+ */
+static bool account_db_sql_remove(AccountDB* self, const int account_id) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	Sql* sql_handle = db->accounts;
 	Sql* sql_handle = db->accounts;
 	bool result = false;
 	bool result = false;
@@ -402,23 +430,40 @@ static bool account_db_sql_remove(AccountDB* self, const int account_id)
 	return result;
 	return result;
 }
 }
 
 
-/// update an existing account with the provided new data (both account and regs)
-static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc)
-{
+/**
+ * Update an existing account with the new data provided (both account and regs).
+ * @param self: pointer to db
+ * @param acc: pointer of mmo_account to save
+ * @return true if successful, false if something has failed
+ */
+static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	return mmo_auth_tosql(db, acc, false);
 	return mmo_auth_tosql(db, acc, false);
 }
 }
 
 
-/// retrieve data from db and store it in the provided data structure
-static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id)
-{
+/**
+ * Retrieve data from db and store it in the provided data structure.
+ *  Filled data structure is done by delegation to mmo_auth_fromsql.
+ * @param self: pointer to db
+ * @param acc: pointer of mmo_account to fill
+ * @param account_id: id of user account
+ * @return true if successful, false if something has failed
+ */
+static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	return mmo_auth_fromsql(db, acc, account_id);
 	return mmo_auth_fromsql(db, acc, account_id);
 }
 }
 
 
-/// retrieve data from db and store it in the provided data structure
-static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid)
-{
+/**
+ * Retrieve data from db and store it in the provided data structure.
+ *  Doesn't actually retrieve data yet: escapes and checks userid, then transforms it to accid for fetching.
+ *  Filled data structure is done by delegation to account_db_sql_load_num.
+ * @param self: pointer to db
+ * @param acc: pointer of mmo_account to fill
+ * @param userid: name of user account
+ * @return true if successful, false if something has failed
+ */
+static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	Sql* sql_handle = db->accounts;
 	Sql* sql_handle = db->accounts;
 	char esc_userid[2*NAME_LENGTH+1];
 	char esc_userid[2*NAME_LENGTH+1];
@@ -454,10 +499,12 @@ static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, co
 	return account_db_sql_load_num(self, acc, account_id);
 	return account_db_sql_load_num(self, acc, account_id);
 }
 }
 
 
-
-/// Returns a new forward iterator.
-static AccountDBIterator* account_db_sql_iterator(AccountDB* self)
-{
+/**
+ * Create a new forward iterator.
+ * @param self: pointer to db iterator
+ * @return a new db iterator
+ */
+static AccountDBIterator* account_db_sql_iterator(AccountDB* self) {
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)self;
 	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)aCalloc(1, sizeof(AccountDBIterator_SQL));
 	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)aCalloc(1, sizeof(AccountDBIterator_SQL));
 
 
@@ -472,18 +519,22 @@ static AccountDBIterator* account_db_sql_iterator(AccountDB* self)
 	return &iter->vtable;
 	return &iter->vtable;
 }
 }
 
 
-
-/// Destroys this iterator, releasing all allocated memory (including itself).
-static void account_db_sql_iter_destroy(AccountDBIterator* self)
-{
+/**
+ * Destroys this iterator, releasing all allocated memory (including itself).
+ * @param self: pointer to db iterator
+ */
+static void account_db_sql_iter_destroy(AccountDBIterator* self) {
 	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
 	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
 	aFree(iter);
 	aFree(iter);
 }
 }
 
 
-
-/// Fetches the next account in the database.
-static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc)
-{
+/**
+ * Fetches the next account in the database.
+ * @param self: pointer to db iterator
+ * @param acc: pointer of mmo_account to fill
+ * @return true if next account found and filled, false if something has failed
+ */
+static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc) {
 	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
 	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
 	AccountDB_SQL* db = (AccountDB_SQL*)iter->db;
 	AccountDB_SQL* db = (AccountDB_SQL*)iter->db;
 	Sql* sql_handle = db->accounts;
 	Sql* sql_handle = db->accounts;
@@ -514,9 +565,14 @@ static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account
 	return false;
 	return false;
 }
 }
 
 
-
-static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id)
-{
+/**
+ * Fetch a struct mmo_account from sql.
+ * @param db: pointer to db
+ * @param acc: pointer of mmo_account to fill
+ * @param account_id: id of user account to take data from
+ * @return true if successful, false if something has failed
+ */
+static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id) {
 	Sql* sql_handle = db->accounts;
 	Sql* sql_handle = db->accounts;
 	char* data;
 	char* data;
 	int i = 0;
 	int i = 0;
@@ -587,8 +643,14 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc
 	return true;
 	return true;
 }
 }
 
 
-static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new)
-{
+/**
+ * Save a struct mmo_account in sql.
+ * @param db: pointer to db
+ * @param acc: pointer of mmo_account to save
+ * @param is_new: if it's a new entry or should we update
+ * @return true if successful, false if something has failed
+ */
+static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new) {
 	Sql* sql_handle = db->accounts;
 	Sql* sql_handle = db->accounts;
 	SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
 	SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
 	bool result = false;
 	bool result = false;

+ 11 - 6
src/login/account.h

@@ -1,11 +1,18 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+/**
+ * @file account.h
+ * Module purpose is to save, load, and update changes into the account table or file.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams < r15k
+ * @author rAthena Dev Team
+ */
 
 
 #ifndef __ACCOUNT_H_INCLUDED__
 #ifndef __ACCOUNT_H_INCLUDED__
 #define __ACCOUNT_H_INCLUDED__
 #define __ACCOUNT_H_INCLUDED__
 
 
 #include "../common/cbasetypes.h"
 #include "../common/cbasetypes.h"
 #include "../common/mmo.h" // ACCOUNT_REG2_NUM
 #include "../common/mmo.h" // ACCOUNT_REG2_NUM
+#include "../config/core.h"
 
 
 typedef struct AccountDB AccountDB;
 typedef struct AccountDB AccountDB;
 typedef struct AccountDBIterator AccountDBIterator;
 typedef struct AccountDBIterator AccountDBIterator;
@@ -61,8 +68,7 @@ struct mmo_account {
 };
 };
 
 
 
 
-struct AccountDBIterator
-{
+struct AccountDBIterator {
 	/// Destroys this iterator, releasing all allocated memory (including itself).
 	/// Destroys this iterator, releasing all allocated memory (including itself).
 	///
 	///
 	/// @param self Iterator
 	/// @param self Iterator
@@ -77,8 +83,7 @@ struct AccountDBIterator
 };
 };
 
 
 
 
-struct AccountDB
-{
+struct AccountDB {
 	/// Initializes this database, making it ready for use.
 	/// Initializes this database, making it ready for use.
 	/// Call this after setting the properties.
 	/// Call this after setting the properties.
 	///
 	///

+ 135 - 103
src/login/ipban_sql.c → src/login/ipban.c

@@ -1,5 +1,12 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+/**
+ * @file ipban.c
+ * Module purpose is to read configuration for login-server and handle accounts,
+ *  and also to synchronize all login interfaces: loginchrif, loginclif, logincnslif.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams < r15k
+ * @author rAthena Dev Team
+ */
 
 
 #include "../common/cbasetypes.h"
 #include "../common/cbasetypes.h"
 #include "../common/db.h"
 #include "../common/db.h"
@@ -35,82 +42,90 @@ static Sql* sql_handle = NULL;
 static int cleanup_timer_id = INVALID_TIMER;
 static int cleanup_timer_id = INVALID_TIMER;
 static bool ipban_inited = false;
 static bool ipban_inited = false;
 
 
+//early declaration
 int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data);
 int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data);
 
 
+/**
+ * Check if ip is in the active bans list.
+ * @param ip: ipv4 ip to check if ban
+ * @return true if found or error, false if not in list
+ */
+bool ipban_check(uint32 ip) {
+	uint8* p = (uint8*)&ip;
+	char* data = NULL;
+	int matches;
 
 
-// initialize
-void ipban_init(void)
-{
-	const char* username;
-	const char* password;
-	const char* hostname;
-	uint16      port;
-	const char* database;
-	const char* codepage;
+	if( !login_config.ipban )
+		return false;// ipban disabled
 
 
-	ipban_inited = true;
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `rtime` > NOW() AND (`list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u')",
+		ipban_table, p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) )
+	{
+		Sql_ShowDebug(sql_handle);
+		// close connection because we can't verify their connectivity.
+		return true;
+	}
+
+	if( SQL_ERROR == Sql_NextRow(sql_handle) )
+		return true;// Shouldn't happen, but just in case...
+
+	Sql_GetData(sql_handle, 0, &data, NULL);
+	matches = atoi(data);
+	Sql_FreeResult(sql_handle);
+
+	return( matches > 0 );
+}
+
+/**
+ * Log a failed attempt.
+ *  Also bans the user if too many failed attempts are made.
+ * @param ip: ipv4 ip to record the failure
+ */
+void ipban_log(uint32 ip) {
+	unsigned long failures;
 
 
 	if( !login_config.ipban )
 	if( !login_config.ipban )
 		return;// ipban disabled
 		return;// ipban disabled
 
 
-	if( ipban_db_hostname[0] != '\0' )
-	{// local settings
-		username = ipban_db_username;
-		password = ipban_db_password;
-		hostname = ipban_db_hostname;
-		port     = ipban_db_port;
-		database = ipban_db_database;
-		codepage = ipban_codepage;
-	}
-	else
-	{// global settings
-		username = global_db_username;
-		password = global_db_password;
-		hostname = global_db_hostname;
-		port     = global_db_port;
-		database = global_db_database;
-		codepage = global_codepage;
-	}
+	failures = loginlog_failedattempts(ip, login_config.dynamic_pass_failure_ban_interval);// how many times failed account? in one ip.
 
 
-	// establish connections
-	sql_handle = Sql_Malloc();
-	if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
+	// if over the limit, add a temporary ban entry
+	if( failures >= login_config.dynamic_pass_failure_ban_limit )
 	{
 	{
-		Sql_ShowDebug(sql_handle);
-		Sql_Free(sql_handle);
-		exit(EXIT_FAILURE);
+		uint8* p = (uint8*)&ip;
+		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() +  INTERVAL %d MINUTE ,'Password error ban')",
+			ipban_table, p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration) )
+			Sql_ShowDebug(sql_handle);
 	}
 	}
-	if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
-		Sql_ShowDebug(sql_handle);
-
-	if( login_config.ipban_cleanup_interval > 0 )
-	{ // set up periodic cleanup of connection history and active bans
-		add_timer_func_list(ipban_cleanup, "ipban_cleanup");
-		cleanup_timer_id = add_timer_interval(gettick()+10, ipban_cleanup, 0, 0, login_config.ipban_cleanup_interval*1000);
-	} else // make sure it gets cleaned up on login-server start regardless of interval-based cleanups
-		ipban_cleanup(0,0,0,0);
 }
 }
 
 
-// finalize
-void ipban_final(void)
-{
+/**
+ * Timered function to remove expired bans.
+ *  Request all characters to update their registered ip and transmit their new ip.
+ *  Performed each ip_sync_interval.
+ * @param tid: timer id
+ * @param tick: tick of execution
+ * @param id: unused
+ * @param data: unused
+ * @return 0
+ */
+int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data) {
 	if( !login_config.ipban )
 	if( !login_config.ipban )
-		return;// ipban disabled
+		return 0;// ipban disabled
 
 
-	if( login_config.ipban_cleanup_interval > 0 )
-		// release data
-		delete_timer(cleanup_timer_id, ipban_cleanup);
-	
-	ipban_cleanup(0,0,0,0); // always clean up on login-server stop
+	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") )
+		Sql_ShowDebug(sql_handle);
 
 
-	// close connections
-	Sql_Free(sql_handle);
-	sql_handle = NULL;
+	return 0;
 }
 }
 
 
-// load configuration options
-bool ipban_config_read(const char* key, const char* value)
-{
+/**
+ * Read configuration options.
+ * @param key: config keyword
+ * @param value: config value for keyword
+ * @return true if successful, false if config not complete or server already running
+ */
+bool ipban_config_read(const char* key, const char* value) {
 	const char* signature;
 	const char* signature;
 
 
 	if( ipban_inited )
 	if( ipban_inited )
@@ -197,62 +212,79 @@ bool ipban_config_read(const char* key, const char* value)
 	return false;// not found
 	return false;// not found
 }
 }
 
 
-// check ip against active bans list
-bool ipban_check(uint32 ip)
-{
-	uint8* p = (uint8*)&ip;
-	char* data = NULL;
-	int matches;
 
 
-	if( !login_config.ipban )
-		return false;// ipban disabled
+/// Constructor destructor
 
 
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `rtime` > NOW() AND (`list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u')",
-		ipban_table, p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) )
-	{
-		Sql_ShowDebug(sql_handle);
-		// close connection because we can't verify their connectivity.
-		return true;
-	}
-
-	if( SQL_ERROR == Sql_NextRow(sql_handle) )
-		return true;// Shouldn't happen, but just in case...
-
-	Sql_GetData(sql_handle, 0, &data, NULL);
-	matches = atoi(data);
-	Sql_FreeResult(sql_handle);
-
-	return( matches > 0 );
-}
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ */
+void ipban_init(void) {
+	const char* username;
+	const char* password;
+	const char* hostname;
+	uint16      port;
+	const char* database;
+	const char* codepage;
 
 
-// log failed attempt
-void ipban_log(uint32 ip)
-{
-	unsigned long failures;
+	ipban_inited = true;
 
 
 	if( !login_config.ipban )
 	if( !login_config.ipban )
 		return;// ipban disabled
 		return;// ipban disabled
 
 
-	failures = loginlog_failedattempts(ip, login_config.dynamic_pass_failure_ban_interval);// how many times failed account? in one ip.
+	if( ipban_db_hostname[0] != '\0' )
+	{// local settings
+		username = ipban_db_username;
+		password = ipban_db_password;
+		hostname = ipban_db_hostname;
+		port     = ipban_db_port;
+		database = ipban_db_database;
+		codepage = ipban_codepage;
+	}
+	else
+	{// global settings
+		username = global_db_username;
+		password = global_db_password;
+		hostname = global_db_hostname;
+		port     = global_db_port;
+		database = global_db_database;
+		codepage = global_codepage;
+	}
 
 
-	// if over the limit, add a temporary ban entry
-	if( failures >= login_config.dynamic_pass_failure_ban_limit )
+	// establish connections
+	sql_handle = Sql_Malloc();
+	if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
 	{
 	{
-		uint8* p = (uint8*)&ip;
-		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() +  INTERVAL %d MINUTE ,'Password error ban')",
-			ipban_table, p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration) )
-			Sql_ShowDebug(sql_handle);
+		Sql_ShowDebug(sql_handle);
+		Sql_Free(sql_handle);
+		exit(EXIT_FAILURE);
 	}
 	}
+	if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
+		Sql_ShowDebug(sql_handle);
+
+	if( login_config.ipban_cleanup_interval > 0 )
+	{ // set up periodic cleanup of connection history and active bans
+		add_timer_func_list(ipban_cleanup, "ipban_cleanup");
+		cleanup_timer_id = add_timer_interval(gettick()+10, ipban_cleanup, 0, 0, login_config.ipban_cleanup_interval*1000);
+	} else // make sure it gets cleaned up on login-server start regardless of interval-based cleanups
+		ipban_cleanup(0,0,0,0);
 }
 }
 
 
-// remove expired bans
-int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data)
-{
+/**
+ * Destroy the module.
+ * Launched at login-serv end, cleanup db connection or other thing here.
+ */
+void ipban_final(void) {
 	if( !login_config.ipban )
 	if( !login_config.ipban )
-		return 0;// ipban disabled
+		return;// ipban disabled
 
 
-	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") )
-		Sql_ShowDebug(sql_handle);
+	if( login_config.ipban_cleanup_interval > 0 )
+		// release data
+		delete_timer(cleanup_timer_id, ipban_cleanup);
 
 
-	return 0;
+	ipban_cleanup(0,0,0,0); // always clean up on login-server stop
+
+	// close connections
+	Sql_Free(sql_handle);
+	sql_handle = NULL;
 }
 }

+ 36 - 11
src/login/ipban.h

@@ -1,25 +1,50 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+/**
+ * @file ipban.h
+ * Module purpose is to read configuration for login-server and handle accounts,
+ *  and also to synchronize all login interfaces: loginchrif, loginclif, logincnslif.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams < r15k
+ * @author rAthena Dev Team
+ */
 
 
 #ifndef __IPBAN_H_INCLUDED__
 #ifndef __IPBAN_H_INCLUDED__
 #define __IPBAN_H_INCLUDED__
 #define __IPBAN_H_INCLUDED__
 
 
 #include "../common/cbasetypes.h"
 #include "../common/cbasetypes.h"
 
 
-// initialize
-void ipban_init(void);
-
-// finalize
-void ipban_final(void);
-
-// check ip against ban list
+/**
+ * Check if ip is in the active bans list.
+ * @param ip: ipv4 ip to check if ban
+ * @return true if found or error, false if not in list
+ */
 bool ipban_check(uint32 ip);
 bool ipban_check(uint32 ip);
 
 
-// increases failure count for the specified IP
+/**
+ * Log a failed attempt.
+ *  Also bans the user if too many failed attempts are made.
+ * @param ip: ipv4 ip to record the failure
+ */
 void ipban_log(uint32 ip);
 void ipban_log(uint32 ip);
 
 
-// parses configuration option
+/**
+ * Read configuration options.
+ * @param key: config keyword
+ * @param value: config value for keyword
+ * @return true if successful, false if config not complete or server already running
+ */
 bool ipban_config_read(const char* key, const char* value);
 bool ipban_config_read(const char* key, const char* value);
 
 
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ */
+void ipban_init(void);
+
+/**
+ * Destroy the module.
+ * Launched at login-serv end, cleanup db connection or other thing here.
+ */
+void ipban_final(void);
 
 
 #endif // __IPBAN_H_INCLUDED__
 #endif // __IPBAN_H_INCLUDED__

File diff suppressed because it is too large
+ 116 - 934
src/login/login.c


+ 135 - 15
src/login/login.h

@@ -1,15 +1,22 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+/**
+ * @file login.h
+ * Module purpose is to read configuration for login-server and handle accounts,
+ *  and also to synchronise all login interfaces: loginchrif, loginclif, logincnslif.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams < r15k
+ * @author rAthena Dev Team
+ */
 
 
 #ifndef _LOGIN_H_
 #ifndef _LOGIN_H_
 #define _LOGIN_H_
 #define _LOGIN_H_
 
 
 #include "../common/mmo.h" // NAME_LENGTH,SEX_*
 #include "../common/mmo.h" // NAME_LENGTH,SEX_*
 #include "../common/core.h" // CORE_ST_LAST
 #include "../common/core.h" // CORE_ST_LAST
+#include "account.h"
 #include "../config/core.h"
 #include "../config/core.h"
 
 
-enum E_LOGINSERVER_ST
-{
+enum E_LOGINSERVER_ST {
 	LOGINSERVER_ST_RUNNING = CORE_ST_LAST,
 	LOGINSERVER_ST_RUNNING = CORE_ST_LAST,
 	LOGINSERVER_ST_STARTING,
 	LOGINSERVER_ST_STARTING,
 	LOGINSERVER_ST_SHUTDOWN,
 	LOGINSERVER_ST_SHUTDOWN,
@@ -27,7 +34,7 @@ struct login_session_data {
 	char sex;			/// 'F','M','S'
 	char sex;			/// 'F','M','S'
 
 
 	char userid[NAME_LENGTH];	/// account name
 	char userid[NAME_LENGTH];	/// account name
-	char passwd[32+1];		/// 23+1 for plaintext, 32+1 for md5-ed passwords
+	char passwd[PASSWD_LENGTH]; // 23+1 for plaintext, 32+1 for md5-ed passwords
 	int passwdenc;			/// was the passwd transmited encrypted or clear ?
 	int passwdenc;			/// was the passwd transmited encrypted or clear ?
 	char md5key[20];		/// md5 key of session (each connection could be encrypted with a md5 key)
 	char md5key[20];		/// md5 key of session (each connection could be encrypted with a md5 key)
 	uint16 md5keylen;		/// len of the md5 key
 	uint16 md5keylen;		/// len of the md5 key
@@ -43,6 +50,7 @@ struct login_session_data {
 	int fd;				///socket of client
 	int fd;				///socket of client
 };
 };
 
 
+#define MAX_SERVERS 30 //max number of mapserv that could be attach
 ///Struct describing 1 char-serv attach to us
 ///Struct describing 1 char-serv attach to us
 struct mmo_char_server {
 struct mmo_char_server {
 	char name[20];	///char-serv name
 	char name[20];	///char-serv name
@@ -53,9 +61,10 @@ struct mmo_char_server {
 	uint16 type;	/// 0=normal, 1=maintenance, 2=over 18, 3=paying, 4=P2P
 	uint16 type;	/// 0=normal, 1=maintenance, 2=over 18, 3=paying, 4=P2P
 	uint16 new_;	/// should display as 'new'?
 	uint16 new_;	/// should display as 'new'?
 };
 };
+extern struct mmo_char_server ch_server[MAX_SERVERS];
 
 
 struct client_hash_node {
 struct client_hash_node {
-	unsigned int group_id;			///group
+	unsigned int group_id;			//inferior or egal group to apply restriction
 	uint8 hash[16];					///hash required for that groupid or below
 	uint8 hash[16];					///hash required for that groupid or below
 	struct client_hash_node *next;	///next entry
 	struct client_hash_node *next;	///next entry
 };
 };
@@ -84,10 +93,16 @@ struct Login_Config {
 	bool use_dnsbl;                                 /// dns blacklist blocking ?
 	bool use_dnsbl;                                 /// dns blacklist blocking ?
 	char dnsbl_servs[1024];                         /// comma-separated list of dnsbl servers
 	char dnsbl_servs[1024];                         /// comma-separated list of dnsbl servers
 
 
-	char account_engine[256];                       /// name of the engine to use (defaults to auto, for the first available engine)
+	char account_engine[256];				// name of the engine to use (defaults to auto, for the first available engine)
+	int allowed_regs;					//max number of registration
+	int time_allowed;					//registration intervall in seconds
 
 
-	int client_hash_check;                          /// flags for checking client md5
-	struct client_hash_node *client_hash_nodes;     /// linked list containg md5 hash for each gm group
+	int client_hash_check;					// flags for checking client md5
+	struct client_hash_node *client_hash_nodes;		// linked list containg md5 hash for each gm group
+	char loginconf_name[256];				//name of main config file
+	char msgconf_name[256];					//name of msg_conf config file
+	char lanconf_name[256];					//name of lan config file
+	
 	int char_per_account;                           /// number of characters an account can have
 	int char_per_account;                           /// number of characters an account can have
 #ifdef VIP_ENABLE
 #ifdef VIP_ENABLE
 	struct {
 	struct {
@@ -96,6 +111,7 @@ struct Login_Config {
 	} vip_sys;
 	} vip_sys;
 #endif
 #endif
 };
 };
+extern struct Login_Config login_config;
 
 
 #define sex_num2str(num) ( (num ==  SEX_FEMALE  ) ? 'F' : (num ==  SEX_MALE  ) ? 'M' : 'S' )
 #define sex_num2str(num) ( (num ==  SEX_FEMALE  ) ? 'F' : (num ==  SEX_MALE  ) ? 'M' : 'S' )
 #define sex_str2num(str) ( (str == 'F' ) ?  SEX_FEMALE  : (str == 'M' ) ?  SEX_MALE  :  SEX_SERVER  )
 #define sex_str2num(str) ( (str == 'F' ) ?  SEX_FEMALE  : (str == 'M' ) ?  SEX_MALE  :  SEX_SERVER  )
@@ -103,15 +119,119 @@ struct Login_Config {
 #define msg_config_read(cfgName) login_msg_config_read(cfgName)
 #define msg_config_read(cfgName) login_msg_config_read(cfgName)
 #define msg_txt(msg_number) login_msg_txt(msg_number)
 #define msg_txt(msg_number) login_msg_txt(msg_number)
 #define do_final_msg() login_do_final_msg()
 #define do_final_msg() login_do_final_msg()
-
 int login_msg_config_read(char *cfgName);
 int login_msg_config_read(char *cfgName);
 const char* login_msg_txt(int msg_number);
 const char* login_msg_txt(int msg_number);
 void login_do_final_msg(void);
 void login_do_final_msg(void);
 
 
-
-#define MAX_SERVERS 30					///number of charserv loginserv can handle
-extern struct mmo_char_server ch_server[MAX_SERVERS];	///array of char-servs data
-extern struct Login_Config login_config;		///config of login serv
-
+/// Online User Database [Wizputer]
+struct online_login_data {
+	int account_id;
+	int waiting_disconnect;
+	int char_server;
+};
+extern DBMap* online_db; // int account_id -> struct online_login_data*
+
+/// Auth database
+#define AUTH_TIMEOUT 30000
+struct auth_node {
+	int account_id;
+	uint32 login_id1;
+	uint32 login_id2;
+	uint32 ip;
+	char sex;
+	uint32 version;
+	uint8 clienttype;
+};
+extern DBMap* auth_db; // int account_id -> struct auth_node*
+
+///Accessors
+AccountDB* login_get_accounts_db(void);
+
+/**
+ * Sub function to create an online_login_data and save it to db.
+ * @param key: Key of the database entry
+ * @param ap: args
+ * @return : Data identified by the key to be put in the database
+ * @see DBCreateData
+ */
+DBData login_create_online_user(DBKey key, va_list args);
+
+/**
+ * Function to add a user in online_db.
+ *  Checking if the user is already registered in the db.
+ *  Stop disconnection timer if set.
+ * @param char_server: id of char-serv on wich the player is
+ * @param account_id: the account identifier
+ * @return the new|registered online data
+ */
+struct online_login_data* login_add_online_user(int char_server, int account_id);
+
+/**
+ * Function to remove a user from online_db.
+ *  Checking if user was already scheduled for deletion, and remove that timer if found.
+ * @param account_id: the account identifier
+ */
+void login_remove_online_user(int account_id);
+
+/**
+ * Timered function to disconnect a user from login.
+ *  This is done either after auth_ok or kicked by char-server.
+ *  Removing user from auth_db and online_db.
+ *  Delay is AUTH_TIMEOUT by default.
+ * @param tid: timer id
+ * @param tick: tick of execution
+ * @param id: user account id
+ * @param data: unused
+ * @return :0
+ */
+int login_waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t data);
+
+/**
+ * Sub function to apply on online_db.
+ * Mark a character as offline.
+ * @param data: 1 entry in the db
+ * @param ap: args
+ * @return : Value to be added up by the function that is applying this
+ * @see DBApply
+ */
+int login_online_db_setoffline(DBKey key, DBData *data, va_list ap);
+
+/**
+ * Test to determine if an IP come from LAN or WAN.
+ * @param ip: ip to check if in auth network
+ * @return 0 if from wan, or subnet_char_ip if lan
+ */
+int lan_subnetcheck(uint32 ip);
+
+
+/**
+ * Create a new account and save it in db/sql.
+ * @param userid: string for user login
+ * @param pass: string for user pass
+ * @param sex: should be M|F|S (todo make an enum ?)
+ * @param last_ip:
+ * @return :
+ *	-1: success
+ *	0: unregistered id (wrong sex fail to create in db);
+ *	1: incorrect pass or userid (userid|pass too short or already exist);
+ *	3: registration limit exceeded;
+ */
+int login_mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
+
+/**
+ * Check/authentication of a connection.
+ * @param sd: string (atm:md5key or dbpass)
+ * @param isServer: string (atm:md5key or dbpass)
+ * @return :
+ *	-1: success
+ *	0: unregistered id;
+ *	1: incorrect pass;
+ *	2: expired id
+ *	3: blacklisted (or registration limit exceeded if new acc);
+ *	5: invalid client_version|hash;
+ *	6: banned
+ *	x: acc state (TODO document me deeper)
+ */
+int login_mmo_auth(struct login_session_data* sd, bool isServer);
 
 
 #endif /* _LOGIN_H_ */
 #endif /* _LOGIN_H_ */

+ 972 - 0
src/login/loginchrif.c

@@ -0,0 +1,972 @@
+/**
+ * @file loginchrif.c
+ * Module purpose is to handle incoming and outgoing requests with char-server.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams originally in login.c
+ * @author rAthena Dev Team
+ */
+
+#include "../common/timer.h" //difftick
+#include "../common/strlib.h" //safeprint
+#include "../common/showmsg.h" //show notice
+#include "../common/socket.h" //wfifo session
+#include "../common/malloc.h"
+#include "account.h"
+#include "ipban.h" //ipban_check
+#include "login.h"
+#include "loginlog.h"
+#include "loginclif.h"
+#include "loginchrif.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+//early declaration
+void logchrif_on_disconnect(int id);
+
+/**
+ * Packet send to all char-servers, except one. (wos: without our self)
+ * @param sfd: fd to discard sending to
+ * @param buf: packet to send in form of an array buffer
+ * @param len: size of packet
+ * @return : the number of char-serv the packet was sent to
+ */
+int logchrif_sendallwos(int sfd, uint8* buf, size_t len) {
+	int i, c;
+	for( i = 0, c = 0; i < ARRAYLENGTH(ch_server); ++i ) {
+		int fd = ch_server[i].fd;
+		if( session_isValid(fd) && fd != sfd ){
+			WFIFOHEAD(fd,len);
+			memcpy(WFIFOP(fd,0), buf, len);
+			WFIFOSET(fd,len);
+			++c;
+		}
+	}
+	return c;
+}
+
+/**
+ * Timered function to synchronize ip addresses.
+ *  Requesting all char to update their registered ip and transmit their new ip.
+ *  Performed each ip_sync_interval.
+ * @param tid: timer id
+ * @param tick: tick of execution
+ * @param id: unused
+ * @param data: unused
+ * @return 0
+ */
+static int logchrif_sync_ip_addresses(int tid, unsigned int tick, int id, intptr_t data) {
+	uint8 buf[2];
+	ShowInfo("IP Sync in progress...\n");
+	WBUFW(buf,0) = 0x2735;
+	logchrif_sendallwos(-1, buf, 2);
+	return 0;
+}
+
+
+
+
+/// Parsing handlers
+
+/**
+ * Request from char-server to authenticate an account.
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_reqauth(int fd, int id,char* ip){
+	if( RFIFOREST(fd) < 23 )
+		return 0;
+	else{
+		struct auth_node* node;
+		int account_id = RFIFOL(fd,2);
+		uint32 login_id1 = RFIFOL(fd,6);
+		uint32 login_id2 = RFIFOL(fd,10);
+		uint8 sex = RFIFOB(fd,14);
+		//uint32 ip_ = ntohl(RFIFOL(fd,15));
+		int request_id = RFIFOL(fd,19);
+		RFIFOSKIP(fd,23);
+
+		node = (struct auth_node*)idb_get(auth_db, account_id);
+		if( runflag == LOGINSERVER_ST_RUNNING &&
+			node != NULL &&
+			node->account_id == account_id &&
+			node->login_id1  == login_id1 &&
+			node->login_id2  == login_id2 &&
+			node->sex        == sex_num2str(sex) /*&&
+			node->ip         == ip_*/ ){// found
+			//ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip);
+
+			// send ack
+			WFIFOHEAD(fd,25);
+			WFIFOW(fd,0) = 0x2713;
+			WFIFOL(fd,2) = account_id;
+			WFIFOL(fd,6) = login_id1;
+			WFIFOL(fd,10) = login_id2;
+			WFIFOB(fd,14) = sex;
+			WFIFOB(fd,15) = 0;// ok
+			WFIFOL(fd,16) = request_id;
+			WFIFOL(fd,20) = node->version;
+			WFIFOB(fd,24) = node->clienttype;
+			WFIFOSET(fd,25);
+
+			// each auth entry can only be used once
+			idb_remove(auth_db, account_id);
+		}else{// authentication not found
+			ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", ch_server[id].name, account_id, ip);
+			WFIFOHEAD(fd,25);
+			WFIFOW(fd,0) = 0x2713;
+			WFIFOL(fd,2) = account_id;
+			WFIFOL(fd,6) = login_id1;
+			WFIFOL(fd,10) = login_id2;
+			WFIFOB(fd,14) = sex;
+			WFIFOB(fd,15) = 1;// auth failed
+			WFIFOL(fd,16) = request_id;
+			WFIFOL(fd,20) = 0;
+			WFIFOB(fd,24) = 0;
+			WFIFOSET(fd,25);
+		}
+	}
+	return 1;
+}
+
+/**
+ * Receive a request to update user count for char-server identified by id.
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_ackusercount(int fd, int id){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	else{
+		int users = RFIFOL(fd,2);
+		RFIFOSKIP(fd,6);
+		// how many users on world? (update)
+		if( ch_server[id].users != users ){
+			ShowStatus("set users %s : %d\n", ch_server[id].name, users);
+			ch_server[id].users = users;
+		}
+	}
+	return 1;
+}
+
+/**
+ * Receive a request from char-server to change e-mail from default "a@a.com".
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_updmail(int fd, int id, char* ip){
+	if (RFIFOREST(fd) < 46)
+		return 0;
+	else{
+		AccountDB* accounts = login_get_accounts_db();
+		struct mmo_account acc;
+		char email[40];
+
+		int account_id = RFIFOL(fd,2);
+		safestrncpy(email, (char*)RFIFOP(fd,6), 40); remove_control_chars(email);
+		RFIFOSKIP(fd,46);
+
+		if( e_mail_check(email) == 0 )
+			ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
+		else if( !accounts->load_num(accounts, &acc, account_id) || strcmp(acc.email, "a@a.com") == 0 || acc.email[0] == '\0' )
+			ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else{
+			memcpy(acc.email, email, 40);
+			ShowNotice("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, email, ip);
+			// Save
+			accounts->save(accounts, &acc);
+		}
+	}
+	return 1;
+}
+
+/**
+ * Transmit account data to char_server
+ * S 2717 aid.W email.40B exp_time.L group_id.B char_slot.B birthdate.11B pincode.5B pincode_change.L bank_vault.L
+ *  isvip.1B char_vip.1B max_billing.1B (tot 79)  
+ * @return -1 : account not found, 1:sucess
+ */
+int logchrif_send_accdata(int fd, uint32 aid) {
+	struct mmo_account acc;
+	time_t expiration_time = 0;
+	char email[40] = "";
+	int group_id = 0;
+	char birthdate[10+1] = "";
+	char pincode[PINCODE_LENGTH+1];
+	int bank_vault = 0;
+	char isvip = false;
+	uint8 char_slots = MIN_CHARS, char_vip = 0;
+	AccountDB* accounts = login_get_accounts_db();
+
+	memset(pincode,0,PINCODE_LENGTH+1);
+	if( !accounts->load_num(accounts, &acc, aid) )
+		return -1;
+	else {
+		safestrncpy(email, acc.email, sizeof(email));
+		expiration_time = acc.expiration_time;
+		group_id = acc.group_id;
+
+		safestrncpy(birthdate, acc.birthdate, sizeof(birthdate));
+		safestrncpy(pincode, acc.pincode, sizeof(pincode));
+		bank_vault = acc.bank_vault;
+#ifdef VIP_ENABLE
+		char_vip = login_config.vip_sys.char_increase;
+		if( acc.vip_time > time(NULL) ) {
+			isvip = true;
+			char_slots = login_config.char_per_account + char_vip;
+		} else
+			char_slots = login_config.char_per_account;
+#endif
+	}
+
+	WFIFOHEAD(fd,79);
+	WFIFOW(fd,0) = 0x2717;
+	WFIFOL(fd,2) = aid;
+	safestrncpy((char*)WFIFOP(fd,6), email, 40);
+	WFIFOL(fd,46) = (uint32)expiration_time;
+	WFIFOB(fd,50) = (unsigned char)group_id;
+	WFIFOB(fd,51) = char_slots;
+	safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1);
+	safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 );
+	WFIFOL(fd,68) = (uint32)acc.pincode_change;
+	WFIFOL(fd,72) = bank_vault;
+	WFIFOB(fd,76) = isvip;
+	WFIFOB(fd,77) = char_vip;
+	WFIFOB(fd,78) = MAX_CHAR_BILLING; //TODO create a config for this
+	WFIFOSET(fd,79);
+	return 1;
+}
+
+/**
+ * Transmit vip specific data to char-serv (will be transfered to mapserv)
+ */
+int logchrif_sendvipdata(int fd, struct mmo_account acc, char isvip, char isgm, int mapfd) {
+#ifdef VIP_ENABLE
+	WFIFOHEAD(fd,19);
+	WFIFOW(fd,0) = 0x2743;
+	WFIFOL(fd,2) = acc.account_id;
+	WFIFOL(fd,6) = (int)acc.vip_time;
+	WFIFOB(fd,10) = isvip;
+	WFIFOL(fd,11) = acc.group_id; //new group id
+	WFIFOL(fd,15) = isgm;
+	WFIFOL(fd,16) = mapfd; //link to mapserv
+	WFIFOSET(fd,20);
+	logchrif_send_accdata(fd,acc.account_id); //refresh char with new setting
+#endif
+	return 1;
+}
+
+/**
+ * Receive a request for account data reply by sending all mmo_account information.
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_reqaccdata(int fd, int id, char *ip){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	else {
+		uint32 aid = RFIFOL(fd,2);
+		RFIFOSKIP(fd,6);
+		if( logchrif_send_accdata(fd,aid) < 0 )
+			ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", ch_server[id].name, aid, ip);
+	}
+	return 1;
+}
+
+/**
+ * Ping request from char-server to send a reply.
+ * @param fd: fd to parse from (char-serv)
+ * @return 1 success
+ */
+int logchrif_parse_keepalive(int fd){
+	RFIFOSKIP(fd,2);
+	WFIFOHEAD(fd,2);
+	WFIFOW(fd,0) = 0x2718;
+	WFIFOSET(fd,2);
+	return 1;
+}
+
+/**
+ * Map server send information to change an email of an account via char-server.
+ * 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_reqchangemail(int fd, int id, char* ip){
+	if (RFIFOREST(fd) < 86)
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+		char actual_email[40];
+		char new_email[40];
+
+		int account_id = RFIFOL(fd,2);
+		safestrncpy(actual_email, (char*)RFIFOP(fd,6), 40);
+		safestrncpy(new_email, (char*)RFIFOP(fd,46), 40);
+		RFIFOSKIP(fd, 86);
+
+		if( e_mail_check(actual_email) == 0 )
+			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
+		else if( e_mail_check(new_email) == 0 )
+			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
+		else if( strcmpi(new_email, "a@a.com") == 0 )
+			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", ch_server[id].name, account_id, ip);
+		else if( !accounts->load_num(accounts, &acc, account_id) )
+			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else if( strcmpi(acc.email, actual_email) != 0 )
+			ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, acc.email, actual_email, ip);
+		else{
+			safestrncpy(acc.email, new_email, 40);
+			ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", ch_server[id].name, account_id, acc.userid, new_email, ip);
+			// Save
+			accounts->save(accounts, &acc);
+		}
+	}
+	return 1;
+}
+
+/**
+ * Receiving an account state update request from a map-server (relayed via char-server).
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ * TODO seems pretty damn close to logchrif_parse_reqbanacc
+ */
+int logchrif_parse_requpdaccstate(int fd, int id, char* ip){
+	if (RFIFOREST(fd) < 10)
+		return 0;
+	else{
+		struct mmo_account acc;
+
+		int account_id = RFIFOL(fd,2);
+		unsigned int state = RFIFOL(fd,6);
+		AccountDB* accounts = login_get_accounts_db();
+
+		RFIFOSKIP(fd,10);
+
+		if( !accounts->load_num(accounts, &acc, account_id) )
+			ShowNotice("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n", ch_server[id].name, account_id, state, ip);
+		else if( acc.state == state )
+			ShowNotice("Char-server '%s':  Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n", ch_server[id].name, account_id, state, ip);
+		else{
+			ShowNotice("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n", ch_server[id].name, account_id, state, ip);
+
+			acc.state = state;
+			// Save
+			accounts->save(accounts, &acc);
+
+			// notify other servers
+			if (state != 0){
+				uint8 buf[11];
+				WBUFW(buf,0) = 0x2731;
+				WBUFL(buf,2) = account_id;
+				WBUFB(buf,6) = 0; // 0: change of state, 1: ban
+				WBUFL(buf,7) = state; // status or final date of a banishment
+				logchrif_sendallwos(-1, buf, 11);
+			}
+		}
+	}
+	return 1;
+}
+
+/**
+ * Receiving a ban request from map-server via char-server.
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ * TODO check logchrif_parse_requpdaccstate for possible merge
+ */
+int logchrif_parse_reqbanacc(int fd, int id, char* ip){
+	if (RFIFOREST(fd) < 10)
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+
+		int account_id = RFIFOL(fd,2);
+		int timediff = RFIFOL(fd,6);
+		RFIFOSKIP(fd,10);
+
+		if( !accounts->load_num(accounts, &acc, account_id) )
+			ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else{
+			time_t timestamp;
+			if (acc.unban_time == 0 || acc.unban_time < time(NULL))
+				timestamp = time(NULL); // new ban
+			else
+				timestamp = acc.unban_time; // add to existing ban
+			timestamp += timediff;
+			if (timestamp == -1)
+				ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", ch_server[id].name, account_id, ip);
+			else if( timestamp <= time(NULL) || timestamp == 0 )
+				ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", ch_server[id].name, account_id, ip);
+			else{
+				uint8 buf[11];
+				char tmpstr[24];
+				timestamp2string(tmpstr, sizeof(tmpstr), timestamp, login_config.date_format);
+				ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", ch_server[id].name, account_id, timestamp, tmpstr, ip);
+
+				acc.unban_time = timestamp;
+
+				// Save
+				accounts->save(accounts, &acc);
+
+				WBUFW(buf,0) = 0x2731;
+				WBUFL(buf,2) = account_id;
+				WBUFB(buf,6) = 1; // 0: change of status, 1: ban
+				WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment
+				logchrif_sendallwos(-1, buf, 11);
+			}
+		}
+	}
+	return 1;
+}
+
+/**
+ * Receiving a sex change request (sex is reversed).
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_reqchgsex(int fd, int id, char* ip){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+
+		int account_id = RFIFOL(fd,2);
+		RFIFOSKIP(fd,6);
+
+		if( !accounts->load_num(accounts, &acc, account_id) )
+			ShowNotice("Char-server '%s': Error of sex change (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else if( acc.sex == 'S' )
+			ShowNotice("Char-server '%s': Error of sex change - account to change is a Server account (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else{
+			unsigned char buf[7];
+			char sex = ( acc.sex == 'M' ) ? 'F' : 'M'; //Change gender
+
+			ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", ch_server[id].name, account_id, sex, ip);
+
+			acc.sex = sex;
+			// Save
+			accounts->save(accounts, &acc);
+
+			// announce to other servers
+			WBUFW(buf,0) = 0x2723;
+			WBUFL(buf,2) = account_id;
+			WBUFB(buf,6) = sex_str2num(sex);
+			logchrif_sendallwos(-1, buf, 7);
+		}
+	}
+	return 1;
+}
+
+/**
+ * We receive account_reg2 from a char-server, and we send them to other char-servers.
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_updreg2(int fd, int id, char* ip){
+	int j;
+	if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+		int account_id = RFIFOL(fd,4);
+
+		if( !accounts->load_num(accounts, &acc, account_id) )
+			ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else{
+			int len;
+			int p;
+			ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
+			for( j = 0, p = 13; j < ACCOUNT_REG2_NUM && p < RFIFOW(fd,2); ++j ){
+				sscanf((char*)RFIFOP(fd,p), "%31c%n", acc.account_reg2[j].str, &len);
+				acc.account_reg2[j].str[len]='\0';
+				p +=len+1; //+1 to skip the '\0' between strings.
+				sscanf((char*)RFIFOP(fd,p), "%255c%n", acc.account_reg2[j].value, &len);
+				acc.account_reg2[j].value[len]='\0';
+				p +=len+1;
+				remove_control_chars(acc.account_reg2[j].str);
+				remove_control_chars(acc.account_reg2[j].value);
+			}
+			acc.account_reg2_num = j;
+			// Save
+			accounts->save(accounts, &acc);
+			// Sending information towards the other char-servers.
+			RFIFOW(fd,0) = 0x2729;// reusing read buffer
+			logchrif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
+		}
+		RFIFOSKIP(fd,RFIFOW(fd,2));
+	}
+	return 1;
+}
+
+/**
+ * Receiving an unban request from map-server via char-server.
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @param ip: char-serv ip (used for info)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_requnbanacc(int fd, int id, char* ip){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+
+		int account_id = RFIFOL(fd,2);
+		RFIFOSKIP(fd,6);
+
+		if( !accounts->load_num(accounts, &acc, account_id) )
+			ShowNotice("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else if( acc.unban_time == 0 )
+			ShowNotice("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else{
+			ShowNotice("Char-server '%s': UnBan request (account: %d, ip: %s).\n", ch_server[id].name, account_id, ip);
+			acc.unban_time = 0;
+			accounts->save(accounts, &acc);
+		}
+	}
+	return 1;
+}
+
+/**
+ * Set account_id to online.
+ * @author [Wizputer]
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_setacconline(int fd, int id){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	login_add_online_user(id, RFIFOL(fd,2));
+	RFIFOSKIP(fd,6);
+	return 1;
+}
+
+/**
+ * Set account_id to offline.
+ * @author  [Wizputer]
+ * @param fd: fd to parse from (char-serv)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_setaccoffline(int fd){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	login_remove_online_user(RFIFOL(fd,2));
+	RFIFOSKIP(fd,6);
+	return 1;
+}
+
+/**
+ * Receive list of all online accounts.
+ * @author  [Skotlex]
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_updonlinedb(int fd, int id){
+	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
+		return 0;
+	else{
+		uint32 i, users;
+		online_db->foreach(online_db, login_online_db_setoffline, id); //Set all chars from this char-server offline first
+		users = RFIFOW(fd,4);
+		for (i = 0; i < users; i++) {
+			int aid = RFIFOL(fd,6+i*4);
+			struct online_login_data *p = idb_ensure(online_db, aid, login_create_online_user);
+			p->char_server = id;
+			if (p->waiting_disconnect != INVALID_TIMER){
+				delete_timer(p->waiting_disconnect, login_waiting_disconnect_timer);
+				p->waiting_disconnect = INVALID_TIMER;
+			}
+		}
+		RFIFOSKIP(fd,RFIFOW(fd,2));
+	}
+	return 1;
+}
+
+/**
+ * Request account_reg2 for a character.
+ * @param fd: fd to parse from (char-serv)
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_reqacc2reg(int fd){
+	int j;
+	if (RFIFOREST(fd) < 10)
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+		size_t off;
+
+		int account_id = RFIFOL(fd,2);
+		int char_id = RFIFOL(fd,6);
+		RFIFOSKIP(fd,10);
+
+		WFIFOHEAD(fd,ACCOUNT_REG2_NUM*sizeof(struct global_reg));
+		WFIFOW(fd,0) = 0x2729;
+		WFIFOL(fd,4) = account_id;
+		WFIFOL(fd,8) = char_id;
+		WFIFOB(fd,12) = 1; //Type 1 for Account2 registry
+
+		off = 13;
+		if( accounts->load_num(accounts, &acc, account_id) ){
+			for( j = 0; j < acc.account_reg2_num; j++ ){
+				if( acc.account_reg2[j].str[0] != '\0' ){
+					off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].str)+1; //We add 1 to consider the '\0' in place.
+					off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].value)+1;
+				}
+			}
+		}
+
+		WFIFOW(fd,2) = (uint16)off;
+		WFIFOSET(fd,WFIFOW(fd,2));
+	}
+	return 1;
+}
+
+/**
+ * Received new charip from char-serv, update information.
+ * @param fd: char-serv file descriptor
+ * @param id: char-serv id
+ * @return 0 not enough info transmitted, 1 success
+ */
+int logchrif_parse_updcharip(int fd, int id){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	ch_server[id].ip = ntohl(RFIFOL(fd,2));
+	ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(ch_server[id].ip));
+	RFIFOSKIP(fd,6);
+	return 1;
+}
+
+/**
+ * Request to set all accounts offline.
+ * @param fd: fd to parse from (char-serv)
+ * @param id: id of char-serv (char-serv)
+ * @return 1 success
+ */
+int logchrif_parse_setalloffline(int fd, int id){
+	ShowInfo("Setting accounts from char-server %d offline.\n", id);
+	online_db->foreach(online_db, login_online_db_setoffline, id);
+	RFIFOSKIP(fd,2);
+	return 1;
+}
+
+/**
+ * Request to change PIN Code for an account.
+ * @param fd: fd to parse from (char-serv)
+ * @return 0 fail (packet does not have enough data), 1 success
+ */
+int logchrif_parse_updpincode(int fd){
+	if( RFIFOREST(fd) < 11 )
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+
+		if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ){
+			strncpy( acc.pincode, (char*)RFIFOP(fd,6), 5 );
+			acc.pincode_change = time( NULL );
+			accounts->save(accounts, &acc);
+		}
+		RFIFOSKIP(fd,11);
+	}
+	return 1;
+}
+
+/**
+ * PIN Code was incorrectly entered too many times.
+ * @param fd: fd to parse from (char-serv)
+ * @return 0 fail (packet does not have enough data), 1 success (continue parsing)
+ */
+int logchrif_parse_pincode_authfail(int fd){
+	if( RFIFOREST(fd) < 6 )
+		return 0;
+	else{
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+		if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ){
+			struct online_login_data* ld;
+
+			ld = (struct online_login_data*)idb_get(online_db,acc.account_id);
+
+			if( ld == NULL )
+				return 0;
+
+			login_log( host2ip(acc.last_ip), acc.userid, 100, "PIN Code check failed" );
+		}
+		login_remove_online_user(acc.account_id);
+		RFIFOSKIP(fd,6);
+	}
+	return 1;
+}
+
+/**
+ * Request the bank info of login
+ * @param fd: fd to parse from (char-serv)
+ * @param id: char serv id
+ * @param ip: char-serv ip (used for info)
+ * @return 0 fail (packet does not have enough data), 1 success (continue parsing)
+ */
+int logchrif_parse_bankvault(int fd, int id, char* ip){
+	if( RFIFOREST(fd) < 11 )
+		return 0;
+	else {
+		struct mmo_account acc;
+
+
+		int account_id = RFIFOL(fd,2);
+		char type = RFIFOB(fd,6);
+		int32 data = RFIFOL(fd,7);
+		AccountDB* accounts = login_get_accounts_db();
+
+		RFIFOSKIP(fd,11);
+
+		if( !accounts->load_num(accounts, &acc, account_id) )
+			ShowNotice("Char-server '%s': Error on banking  (account: %d not found, ip: %s).\n", ch_server[id].name, account_id, ip);
+		else{
+			unsigned char buf[12];
+			if(type==2){ // upd and Save
+				acc.bank_vault = data;
+				accounts->save(accounts, &acc);
+				WBUFB(buf,10) = 1;
+			} else {
+				WBUFB(buf,10) = 0;
+			}
+			// announce to other servers
+			WBUFW(buf,0) = 0x2741;
+			WBUFL(buf,2) = account_id;
+			WBUFL(buf,6) = acc.bank_vault;
+			logchrif_sendallwos(-1, buf, 11);
+		}
+	}
+	return 1;
+}
+
+/**
+ * Received a vip data reqest from char
+ * type is the query to perform
+ *  &1 : Select info and update old_groupid
+ *  &2 : Update vip time
+ * @param fd link to charserv
+ * @return 0 missing data, 1 succeeded
+ */
+int logchrif_parse_reqvipdata(int fd) {
+#ifdef VIP_ENABLE
+	if( RFIFOREST(fd) < 15 )
+		return 0;
+	else { //request vip info
+		struct mmo_account acc;
+		AccountDB* accounts = login_get_accounts_db();
+		int aid = RFIFOL(fd,2);
+		int8 type = RFIFOB(fd,6);
+		int32 timediff = RFIFOL(fd,7);
+		int mapfd = RFIFOL(fd,11);
+		RFIFOSKIP(fd,15);
+		
+		if( accounts->load_num(accounts, &acc, aid ) ) {
+			time_t now = time(NULL);
+			time_t vip_time = acc.vip_time;
+			bool isvip = false;
+
+			if( acc.group_id > login_config.vip_sys.group ) { //Don't change group if it's higher.
+				logchrif_sendvipdata(fd,acc,false,true,mapfd);
+				return 1;
+			}
+			if( type&2 ) {
+				if(!vip_time)
+					vip_time = now; //new entry
+				vip_time += timediff; // set new duration
+			}
+			if( now < vip_time ) { //isvip
+				if(acc.group_id != login_config.vip_sys.group) //only upd this if we're not vip already
+					acc.old_group = acc.group_id;
+				acc.group_id = login_config.vip_sys.group;
+				acc.char_slots = login_config.char_per_account + login_config.vip_sys.char_increase;
+				isvip = true;
+			} else { //expired or @vip -xx
+				vip_time = 0;
+				if(acc.group_id == login_config.vip_sys.group) //prevent alteration in case account wasn't registered as vip yet
+					acc.group_id = acc.old_group;
+				acc.old_group = 0;
+				acc.char_slots = login_config.char_per_account;
+			}
+			acc.vip_time = vip_time;
+			accounts->save(accounts,&acc);
+			if( type&1 )
+				logchrif_sendvipdata(fd,acc,isvip,false,mapfd);
+		}
+	}
+#endif
+	return 1;
+}
+
+/**
+ * Entry point from char-server to log-server.
+ * Function that checks incoming command, then splits it to the correct handler.
+ * @param fd: file descriptor to parse, (link to char-serv)
+ * @return 0=invalid server,marked for disconnection,unknow packet; 1=success
+ */
+int logchrif_parse(int fd){
+	int cid; //char-serv id
+	uint32 ipl;
+	char ip[16];
+
+	ARR_FIND( 0, ARRAYLENGTH(ch_server), cid, ch_server[cid].fd == fd );
+	if( cid == ARRAYLENGTH(ch_server) ){// not a char server
+		ShowDebug("logchrif_parse: Disconnecting invalid session #%d (is not a char-server)\n", fd);
+		set_eof(fd);
+		do_close(fd);
+		return 0;
+	}
+
+	if( session[fd]->flag.eof ){
+		do_close(fd);
+		ch_server[cid].fd = -1;
+		logchrif_on_disconnect(cid);
+		return 0;
+	}
+
+	ipl = ch_server[cid].ip;
+	ip2str(ipl, ip);
+
+	while( RFIFOREST(fd) >= 2 ){
+		int next = 1;
+		uint16 command = RFIFOW(fd,0);
+		switch( command ){
+		case 0x2712: next = logchrif_parse_reqauth(fd, cid, ip); break;
+		case 0x2714: next = logchrif_parse_ackusercount(fd, cid); break;
+		case 0x2715: next = logchrif_parse_updmail(fd, cid, ip); break;
+		case 0x2716: next = logchrif_parse_reqaccdata(fd, cid, ip); break;
+		case 0x2719: next = logchrif_parse_keepalive(fd); break;
+		case 0x2722: next = logchrif_parse_reqchangemail(fd,cid,ip); break;
+		case 0x2724: next = logchrif_parse_requpdaccstate(fd,cid,ip); break;
+		case 0x2725: next = logchrif_parse_reqbanacc(fd,cid,ip); break;
+		case 0x2727: next = logchrif_parse_reqchgsex(fd,cid,ip); break;
+		case 0x2728: next = logchrif_parse_updreg2(fd,cid,ip); break;
+		case 0x272a: next = logchrif_parse_requnbanacc(fd,cid,ip); break;
+		case 0x272b: next = logchrif_parse_setacconline(fd,cid); break;
+		case 0x272c: next = logchrif_parse_setaccoffline(fd); break;
+		case 0x272d: next = logchrif_parse_updonlinedb(fd,cid); break;
+		case 0x272e: next = logchrif_parse_reqacc2reg(fd); break;
+		case 0x2736: next = logchrif_parse_updcharip(fd,cid); break;
+		case 0x2737: next = logchrif_parse_setalloffline(fd,cid); break;
+		case 0x2738: next = logchrif_parse_updpincode(fd); break;
+		case 0x2739: next = logchrif_parse_pincode_authfail(fd); break;
+		case 0x2740: next = logchrif_parse_bankvault(fd,cid,ip); break;
+		case 0x2742: next = logchrif_parse_reqvipdata(fd); break; //Vip sys
+		default:
+			ShowError("logchrif_parse: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
+			set_eof(fd);
+			return 0;
+		} // switch
+		if(next==0) return 0; // avoid processing of followup packets (prev was probably incomplete)
+	} // while
+	return 1; //or 0
+}
+
+
+
+
+/// Constructor destructor and signal handlers
+
+/**
+ * Initializes a server structure.
+ * @param id: id of char-serv (should be >0, FIXME)
+ */
+void logchrif_server_init(int id) {
+	memset(&ch_server[id], 0, sizeof(ch_server[id]));
+	ch_server[id].fd = -1;
+}
+
+/**
+ * Destroys a server structure.
+ * @param id: id of char-serv (should be >0, FIXME)
+ */
+void logchrif_server_destroy(int id){
+	if( ch_server[id].fd != -1 ) {
+		do_close(ch_server[id].fd);
+		ch_server[id].fd = -1;
+	}
+}
+
+/**
+ * Resets all the data related to a server.
+ *  Actually destroys then recreates the struct.
+ * @param id: id of char-serv (should be >0, FIXME)
+ */
+void logchrif_server_reset(int id) {
+	online_db->foreach(online_db, login_online_db_setoffline, id); //Set all chars from this char server to offline.
+	logchrif_server_destroy(id);
+	logchrif_server_init(id);
+}
+
+/**
+ * Called when the connection to Char Server is disconnected.
+ * @param id: id of char-serv (should be >0, FIXME)
+ */
+void logchrif_on_disconnect(int id) {
+	ShowStatus("Char-server '%s' has disconnected.\n", ch_server[id].name);
+	logchrif_server_reset(id);
+}
+
+/**
+ * loginchrif constructor
+ *  Initialisation, function called at start of the login-serv.
+ */
+void do_init_loginchrif(void){
+	int i;
+	for( i = 0; i < ARRAYLENGTH(ch_server); ++i )
+		logchrif_server_init(i);
+
+	// add timer to detect ip address change and perform update
+	if (login_config.ip_sync_interval) {
+		add_timer_func_list(logchrif_sync_ip_addresses, "sync_ip_addresses");
+		add_timer_interval(gettick() + login_config.ip_sync_interval, logchrif_sync_ip_addresses, 0, 0, login_config.ip_sync_interval);
+	}
+}
+
+/**
+ * Signal handler
+ *  This function attempts to properly close the server when an interrupt signal is received.
+ *  current signal catch : SIGTERM, SIGINT
+ */
+void do_shutdown_loginchrif(void){
+	int id;
+	for( id = 0; id < ARRAYLENGTH(ch_server); ++id )
+		logchrif_server_reset(id);
+}
+
+/**
+ * loginchrif destructor
+ *  dealloc..., function called at exit of the login-serv
+ */
+void do_final_loginchrif(void){
+	int i;
+	for( i = 0; i < ARRAYLENGTH(ch_server); ++i )
+		logchrif_server_destroy(i);
+}

+ 56 - 0
src/login/loginchrif.h

@@ -0,0 +1,56 @@
+/**
+ * @file loginchrif.h
+ * Module purpose is to handle incoming and outgoing requests with char-server.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams originally in login.c
+ * @author rAthena Dev Team
+ */
+
+#ifndef LOGINCHRIF_H
+#define	LOGINCHRIF_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/**
+ * Entry point from char-server to log-server.
+ * Function that checks incoming command, then splits it to the correct handler.
+ * @param fd: file descriptor to parse, (link to char-serv)
+ * @return 0=invalid server,marked for disconnection,unknow packet; 1=success
+ */
+int logchrif_parse(int fd);
+
+/**
+ * Packet send to all char-servers, except one. (wos: without our self)
+ * @param sfd: fd to discard sending to
+ * @param buf: packet to send in form of an array buffer
+ * @param len: size of packet
+ * @return : the number of char-serv the packet was sent to
+ */
+int logchrif_sendallwos(int sfd, uint8* buf, size_t len);
+
+/**
+ * loginchrif constructor
+ *  Initialisation, function called at start of the login-serv.
+ */
+void do_init_loginchrif(void);
+/**
+ * Signal handler
+ *  This function attempts to properly close the server when an interrupt signal is received.
+ *  current signal catch : SIGTERM, SIGINT
+ */
+void do_shutdown_loginchrif(void);
+/**
+ * loginchrif destructor
+ *  dealloc..., function called at exit of the login-serv
+ */
+void do_final_loginchrif(void);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* LOGINCHRIF_H */
+

+ 564 - 0
src/login/loginclif.c

@@ -0,0 +1,564 @@
+/**
+ * @file loginclif.c
+ * Module purpose is to handle incoming and outgoing requests with client.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams originally in login.c
+ * @author rAthena Dev Team
+ */
+
+#include "../common/timer.h" //difftick
+#include "../common/strlib.h" //safeprint
+#include "../common/showmsg.h" //show notice
+#include "../common/socket.h" //wfifo session
+#include "../common/malloc.h"
+#include "../common/utils.h"
+#include "../common/md5calc.h"
+#include "../common/random.h"
+#include "account.h"
+#include "ipban.h" //ipban_check
+#include "login.h"
+#include "loginlog.h"
+#include "loginclif.h"
+#include "loginchrif.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Transmit auth result to client.
+ * @param fd: client file desciptor link
+ * @param result: result to transmit to client, see below
+ *  1 : Server closed
+ *  2 : Someone has already logged in with this id
+ *  8 : already online
+ * <result>.B (SC_NOTIFY_BAN)
+ */
+static void logclif_sent_auth_result(int fd,char result){
+	WFIFOHEAD(fd,3);
+	WFIFOW(fd,0) = 0x81;
+	WFIFOB(fd,2) = result;
+	WFIFOSET(fd,3);
+}
+
+/**
+ * Auth successful, inform client and create a temp auth_node.
+ * @param sd: player session
+ */
+static void logclif_auth_ok(struct login_session_data* sd) {
+	int fd = sd->fd;
+	uint32 ip = session[fd]->client_addr;
+
+	uint8 server_num, n;
+	uint32 subnet_char_ip;
+	struct auth_node* node;
+	int i;
+
+	if( runflag != LOGINSERVER_ST_RUNNING ){
+		// players can only login while running
+		logclif_sent_auth_result(fd,1); // server closed
+		return;
+	}
+
+	if( login_config.group_id_to_connect >= 0 && sd->group_id != login_config.group_id_to_connect ) {
+		ShowStatus("Connection refused: the required group id for connection is %d (account: %s, group: %d).\n", login_config.group_id_to_connect, sd->userid, sd->group_id);
+		logclif_sent_auth_result(fd,1); // server closed
+		return;
+	} else if( login_config.min_group_id_to_connect >= 0 && login_config.group_id_to_connect == -1 && sd->group_id < login_config.min_group_id_to_connect ) {
+		ShowStatus("Connection refused: the minimum group id required for connection is %d (account: %s, group: %d).\n", login_config.min_group_id_to_connect, sd->userid, sd->group_id);
+		logclif_sent_auth_result(fd,1); // server closed
+		return;
+	}
+
+	server_num = 0;
+	for( i = 0; i < ARRAYLENGTH(ch_server); ++i )
+		if( session_isActive(ch_server[i].fd) )
+			server_num++;
+
+	if( server_num == 0 )
+	{// if no char-server, don't send void list of servers, just disconnect the player with proper message
+		ShowStatus("Connection refused: there is no char-server online (account: %s).\n", sd->userid);
+		logclif_sent_auth_result(fd,1); // server closed
+		return;
+	}
+
+	{
+		struct online_login_data* data = (struct online_login_data*)idb_get(online_db, sd->account_id);
+		if( data )
+		{// account is already marked as online!
+			if( data->char_server > -1 )
+			{// Request char servers to kick this account out. [Skotlex]
+				uint8 buf[6];
+				ShowNotice("User '%s' is already online - Rejected.\n", sd->userid);
+				WBUFW(buf,0) = 0x2734;
+				WBUFL(buf,2) = sd->account_id;
+				logchrif_sendallwos(-1, buf, 6);
+				if( data->waiting_disconnect == INVALID_TIMER )
+					data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0);
+				logclif_sent_auth_result(fd,8); // 08 = Server still recognizes your last login
+				return;
+			}
+			else
+			if( data->char_server == -1 )
+			{// client has authed but did not access char-server yet
+				// wipe previous session
+				idb_remove(auth_db, sd->account_id);
+				login_remove_online_user(sd->account_id);
+				data = NULL;
+			}
+		}
+	}
+
+	login_log(ip, sd->userid, 100, "login ok");
+	ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);
+
+	WFIFOHEAD(fd,47+32*server_num);
+	WFIFOW(fd,0) = 0x69;
+	WFIFOW(fd,2) = 47+32*server_num;
+	WFIFOL(fd,4) = sd->login_id1;
+	WFIFOL(fd,8) = sd->account_id;
+	WFIFOL(fd,12) = sd->login_id2;
+	WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
+	//memcpy(WFIFOP(fd,20), sd->lastlogin, 24); // in old version, that was for name (not more used)
+	memset(WFIFOP(fd,20), 0, 24);
+	WFIFOW(fd,44) = 0; // unknown
+	WFIFOB(fd,46) = sex_str2num(sd->sex);
+	for( i = 0, n = 0; i < ARRAYLENGTH(ch_server); ++i ) {
+		if( !session_isValid(ch_server[i].fd) )
+			continue;
+		subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
+		WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : ch_server[i].ip);
+		WFIFOW(fd,47+n*32+4) = ntows(htons(ch_server[i].port)); // [!] LE byte order here [!]
+		memcpy(WFIFOP(fd,47+n*32+6), ch_server[i].name, 20);
+		WFIFOW(fd,47+n*32+26) = ch_server[i].users;
+		WFIFOW(fd,47+n*32+28) = ch_server[i].type;
+		WFIFOW(fd,47+n*32+30) = ch_server[i].new_;
+		n++;
+	}
+	WFIFOSET(fd,47+32*server_num);
+
+	// create temporary auth entry
+	CREATE(node, struct auth_node, 1);
+	node->account_id = sd->account_id;
+	node->login_id1 = sd->login_id1;
+	node->login_id2 = sd->login_id2;
+	node->sex = sd->sex;
+	node->ip = ip;
+	node->version = sd->version;
+	node->clienttype = sd->clienttype;
+	idb_put(auth_db, sd->account_id, node);
+	{
+		struct online_login_data* data;
+		// mark client as 'online'
+		data = login_add_online_user(-1, sd->account_id);
+		// schedule deletion of this node
+		data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0);
+	}
+}
+
+/**
+ * Inform client that auth has failed.
+ * @param sd: player session
+ * @param result: nb (msg define in conf)
+    0 = Unregistered ID
+    1 = Incorrect Password
+    2 = This ID is expired
+    3 = Rejected from Server
+    4 = You have been blocked by the GM Team
+    5 = Your Game's EXE file is not the latest version
+    6 = Your are Prohibited to log in until %s
+    7 = Server is jammed due to over populated
+    8 = No more accounts may be connected from this company
+    9 = MSI_REFUSE_BAN_BY_DBA
+    10 = MSI_REFUSE_EMAIL_NOT_CONFIRMED
+    11 = MSI_REFUSE_BAN_BY_GM
+    12 = MSI_REFUSE_TEMP_BAN_FOR_DBWORK
+    13 = MSI_REFUSE_SELF_LOCK
+    14 = MSI_REFUSE_NOT_PERMITTED_GROUP
+    15 = MSI_REFUSE_NOT_PERMITTED_GROUP
+    99 = This ID has been totally erased
+    100 = Login information remains at %s
+    101 = Account has been locked for a hacking investigation. Please contact the GM Team for more information
+    102 = This account has been temporarily prohibited from login due to a bug-related investigation
+    103 = This character is being deleted. Login is temporarily unavailable for the time being
+    104 = This character is being deleted. Login is temporarily unavailable for the time being
+     default = Unknown Error.
+ */
+static void logclif_auth_failed(struct login_session_data* sd, int result) {
+	int fd = sd->fd;
+	uint32 ip = session[fd]->client_addr;
+
+	if (login_config.log_login)
+	{
+		if(result >= 0 && result <= 15)
+		    login_log(ip, sd->userid, result, msg_txt(result));
+		else if(result >= 99 && result <= 104)
+		    login_log(ip, sd->userid, result, msg_txt(result-83)); //-83 offset
+		else
+		    login_log(ip, sd->userid, result, msg_txt(22)); //unknow error
+	}
+
+	if( result == 1 && login_config.dynamic_pass_failure_ban )
+		ipban_log(ip); // log failed password attempt
+
+//#if PACKETVER >= 20120000 /* not sure when this started */
+	if( sd->version >= date2version(20120000) ){ /* not sure when this started */
+		WFIFOHEAD(fd,26);
+		WFIFOW(fd,0) = 0x83e;
+		WFIFOL(fd,2) = result;
+		if( result != 6 )
+			memset(WFIFOP(fd,6), '\0', 20);
+		else { // 6 = Your are Prohibited to log in until %s
+			struct mmo_account acc;
+			AccountDB* accounts = login_get_accounts_db();
+			time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
+			timestamp2string((char*)WFIFOP(fd,6), 20, unban_time, login_config.date_format);
+		}
+		WFIFOSET(fd,26);
+	}
+//#else	
+	else {
+		WFIFOHEAD(fd,23);
+		WFIFOW(fd,0) = 0x6a;
+		WFIFOB(fd,2) = (uint8)result;
+		if( result != 6 )
+			memset(WFIFOP(fd,3), '\0', 20);
+		else { // 6 = Your are Prohibited to log in until %s
+			struct mmo_account acc;
+			AccountDB* accounts = login_get_accounts_db();
+			time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0;
+			timestamp2string((char*)WFIFOP(fd,3), 20, unban_time, login_config.date_format);
+		}
+		WFIFOSET(fd,23);
+	}
+//#endif	
+}
+
+/**
+ * Received a keepalive packet to maintain connection.
+ * 0x200 <account.userid>.24B.
+ * @param fd: fd to parse from (client fd)
+ * @return 0 not enough info transmitted, 1 success
+ */
+static int logclif_parse_keepalive(int fd){
+	if (RFIFOREST(fd) < 26)
+		return 0;
+	RFIFOSKIP(fd,26);
+	return 1;
+}
+
+/**
+ * Received a keepalive packet to maintain connection.
+ * S 0204 <md5 hash>.16B (kRO 2004-05-31aSakexe langtype 0 and 6)
+ * @param fd: fd to parse from (client fd)
+ * @return 0 not enough info transmitted, 1 success
+ */
+static int logclif_parse_updclhash(int fd, struct login_session_data *sd){
+	if (RFIFOREST(fd) < 18)
+		return 0;
+	sd->has_client_hash = 1;
+	memcpy(sd->client_hash, RFIFOP(fd, 2), 16);
+	RFIFOSKIP(fd,18);
+	return 1;
+}
+
+/**
+ * Received a connection request.
+ * @param fd: file descriptor to parse from (client)
+ * @param sd: client session
+ * @param command: packet type sent
+ * @param ip: ipv4 address (client)
+ *  S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
+ *  S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
+ *  S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
+ *  S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
+ *  S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
+ *  S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
+ *  S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
+ * @param fd: fd to parse from (client fd)
+ * @return 0 failure, 1 success
+ */
+static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int command, char* ip){
+	size_t packet_len = RFIFOREST(fd);
+
+	if( (command == 0x0064 && packet_len < 55)
+	||  (command == 0x0277 && packet_len < 84)
+	||  (command == 0x02b0 && packet_len < 85)
+	||  (command == 0x01dd && packet_len < 47)
+	||  (command == 0x01fa && packet_len < 48)
+	||  (command == 0x027c && packet_len < 60)
+	||  (command == 0x0825 && (packet_len < 4 || packet_len < RFIFOW(fd, 2))) )
+		return 0;
+	else {
+		int result;
+		uint32 version;
+		char username[NAME_LENGTH];
+		char password[PASSWD_LENGTH];
+		unsigned char passhash[16];
+		uint8 clienttype;
+		bool israwpass = (command==0x0064 || command==0x0277 || command==0x02b0 || command == 0x0825);
+
+		// Shinryo: For the time being, just use token as password.
+		if(command == 0x0825) {
+			char *accname = (char *)RFIFOP(fd, 9);
+			char *token = (char *)RFIFOP(fd, 0x5C);
+			size_t uAccLen = strlen(accname);
+			size_t uTokenLen = RFIFOREST(fd) - 0x5C;
+
+			version = RFIFOL(fd,4);
+
+			if(uAccLen > NAME_LENGTH - 1 || uAccLen <= 0 || uTokenLen > NAME_LENGTH - 1  || uTokenLen <= 0)
+			{
+				logclif_auth_failed(sd, 3);
+				return 0;
+			}
+
+			safestrncpy(username, accname, uAccLen + 1);
+			safestrncpy(password, token, uTokenLen + 1);
+			clienttype = RFIFOB(fd, 8);
+		}
+		else
+		{
+			version = RFIFOL(fd,2);
+			safestrncpy(username, (const char*)RFIFOP(fd,6), NAME_LENGTH);
+			if( israwpass )
+			{
+				safestrncpy(password, (const char*)RFIFOP(fd,30), PASSWD_LENGTH);
+				clienttype = RFIFOB(fd,54);
+			}
+			else
+			{
+				memcpy(passhash, RFIFOP(fd,30), 16);
+				clienttype = RFIFOB(fd,46);
+			}
+		}
+		RFIFOSKIP(fd,RFIFOREST(fd)); // assume no other packet was sent
+
+		sd->clienttype = clienttype;
+		sd->version = version;
+		safestrncpy(sd->userid, username, NAME_LENGTH);
+		if( israwpass )
+		{
+			ShowStatus("Request for connection of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
+			safestrncpy(sd->passwd, password, NAME_LENGTH);
+			if( login_config.use_md5_passwds )
+				MD5_String(sd->passwd, sd->passwd);
+			sd->passwdenc = 0;
+		}
+		else
+		{
+			ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s) version=%d\n", sd->userid, ip,sd->version);
+			bin2hex(sd->passwd, passhash, 16); // raw binary data here!
+			sd->passwdenc = PASSWORDENC;
+		}
+
+		if( sd->passwdenc != 0 && login_config.use_md5_passwds )
+		{
+			logclif_auth_failed(sd, 3); // send "rejected from server"
+			return 0;
+		}
+
+		result = login_mmo_auth(sd, false);
+
+		if( result == -1 )
+			logclif_auth_ok(sd);
+		else
+			logclif_auth_failed(sd, result);
+	}
+	return 1;
+}
+
+/**
+ * Client requests an md5key for his session: keys will be generated and sent back.
+ * @param fd: file descriptor to parse from (client)
+ * @param sd: client session
+ * @return 1 success
+ */
+static int logclif_parse_reqkey(int fd, struct login_session_data *sd){
+	RFIFOSKIP(fd,2);
+	{
+		memset(sd->md5key, '\0', sizeof(sd->md5key));
+		sd->md5keylen = (uint16)(12 + rnd() % 4);
+		MD5_Salt(sd->md5keylen, sd->md5key);
+
+		WFIFOHEAD(fd,4 + sd->md5keylen);
+		WFIFOW(fd,0) = 0x01dc;
+		WFIFOW(fd,2) = 4 + sd->md5keylen;
+		memcpy(WFIFOP(fd,4), sd->md5key, sd->md5keylen);
+		WFIFOSET(fd,WFIFOW(fd,2));
+	}
+	return 1;
+}
+
+/**
+ * Char-server request to connect to the login-server.
+ * This is needed to exchange packets.
+ * @param fd: file descriptor to parse from (client)
+ * @param sd: client session
+ * @param ip: ipv4 address (client)
+ * @return 0 packet received too shirt, 1 success
+ */
+static int logclif_parse_reqcharconnec(int fd, struct login_session_data *sd, char* ip){
+	if (RFIFOREST(fd) < 86)
+		return 0;
+	{
+		int result;
+		char server_name[20];
+		char message[256];
+		uint32 server_ip;
+		uint16 server_port;
+		uint16 type;
+		uint16 new_;
+
+		safestrncpy(sd->userid, (char*)RFIFOP(fd,2), NAME_LENGTH);
+		safestrncpy(sd->passwd, (char*)RFIFOP(fd,26), NAME_LENGTH);
+		if( login_config.use_md5_passwds )
+			MD5_String(sd->passwd, sd->passwd);
+		sd->passwdenc = 0;
+		sd->version = login_config.client_version_to_connect; // hack to skip version check
+		server_ip = ntohl(RFIFOL(fd,54));
+		server_port = ntohs(RFIFOW(fd,58));
+		safestrncpy(server_name, (char*)RFIFOP(fd,60), 20);
+		type = RFIFOW(fd,82);
+		new_ = RFIFOW(fd,84);
+		RFIFOSKIP(fd,86);
+
+		ShowInfo("Connection request of the char-server '%s' @ %u.%u.%u.%u:%u (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, sd->userid, sd->passwd, ip);
+		sprintf(message, "charserver - %s@%u.%u.%u.%u:%u", server_name, CONVIP(server_ip), server_port);
+		login_log(session[fd]->client_addr, sd->userid, 100, message);
+
+		result = login_mmo_auth(sd, true);
+		if( runflag == LOGINSERVER_ST_RUNNING &&
+			result == -1 &&
+			sd->sex == 'S' &&
+			sd->account_id >= 0 && sd->account_id < ARRAYLENGTH(ch_server) &&
+			!session_isValid(ch_server[sd->account_id].fd) )
+		{
+			ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
+			safestrncpy(ch_server[sd->account_id].name, server_name, sizeof(ch_server[sd->account_id].name));
+			ch_server[sd->account_id].fd = fd;
+			ch_server[sd->account_id].ip = server_ip;
+			ch_server[sd->account_id].port = server_port;
+			ch_server[sd->account_id].users = 0;
+			ch_server[sd->account_id].type = type;
+			ch_server[sd->account_id].new_ = new_;
+
+			session[fd]->func_parse = logchrif_parse;
+			session[fd]->flag.server = 1;
+			realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
+
+			// send connection success
+			WFIFOHEAD(fd,3);
+			WFIFOW(fd,0) = 0x2711;
+			WFIFOB(fd,2) = 0;
+			WFIFOSET(fd,3);
+		}
+		else
+		{
+			ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name);
+			WFIFOHEAD(fd,3);
+			WFIFOW(fd,0) = 0x2711;
+			WFIFOB(fd,2) = 3;
+			WFIFOSET(fd,3);
+		}
+	}
+	return 1;
+}
+
+/**
+ * Entry point from client to log-server.
+ * Function that checks incoming command, then splits it to the correct handler.
+ * @param fd: file descriptor to parse, (link to client)
+ * @return 0=invalid session,marked for disconnection,unknow packet, banned..; 1=success
+ */
+int logclif_parse(int fd) {
+	struct login_session_data* sd = (struct login_session_data*)session[fd]->session_data;
+
+	char ip[16];
+	uint32 ipl = session[fd]->client_addr;
+	ip2str(ipl, ip);
+
+	if( session[fd]->flag.eof )
+	{
+		ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip);
+		do_close(fd);
+		return 0;
+	}
+
+	if( sd == NULL )
+	{
+		// Perform ip-ban check
+		if( login_config.ipban && ipban_check(ipl) )
+		{
+			ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
+			login_log(ipl, "unknown", -3, "ip banned");
+			WFIFOHEAD(fd,23);
+			WFIFOW(fd,0) = 0x6a;
+			WFIFOB(fd,2) = 3; // 3 = Rejected from Server
+			WFIFOSET(fd,23);
+			set_eof(fd);
+			return 0;
+		}
+		// create a session for this new connection
+		CREATE(session[fd]->session_data, struct login_session_data, 1);
+		sd = (struct login_session_data*)session[fd]->session_data;
+		sd->fd = fd;
+	}
+
+	while( RFIFOREST(fd) >= 2 )
+	{
+		uint16 command = RFIFOW(fd,0);
+		int next=1;
+
+		switch( command )
+		{
+		// New alive packet: used to verify if client is always alive.
+		case 0x0200: next = logclif_parse_keepalive(fd); break;
+		// client md5 hash (binary)
+		case 0x0204: next = logclif_parse_updclhash(fd,sd); break;
+		// request client login (raw password)
+		case 0x0064: // S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
+		case 0x0277: // S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
+		case 0x02b0: // S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
+		// request client login (md5-hashed password)
+		case 0x01dd: // S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
+		case 0x01fa: // S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
+		case 0x027c: // S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
+		case 0x0825: // S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
+			next = logclif_parse_reqauth(fd,  sd, command, ip); 
+			break;
+		// Sending request of the coding key
+		case 0x01db: next = logclif_parse_reqkey(fd, sd); break;
+		// Connection request of a char-server
+		case 0x2710: logclif_parse_reqcharconnec(fd,sd, ip); return 0; // processing will continue elsewhere
+		default:
+			ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
+			set_eof(fd);
+			return 0;
+		}
+		if(next==0) return 0; // avoid processing of followup packets (prev was probably incomplete)
+	}
+
+	return 0;
+}
+
+
+
+/// Constructor destructor
+
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ */
+void do_init_loginclif(void){
+	return;
+}
+
+/**
+ * loginclif destructor
+ *  dealloc..., function called at exit of the login-serv
+ */
+void do_final_loginclif(void){
+	return;
+}

+ 42 - 0
src/login/loginclif.h

@@ -0,0 +1,42 @@
+/**
+ * @file loginclif.h
+ * Module purpose is to handle incoming and outgoing requests with client.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams originally in login.c
+ * @author rAthena Dev Team
+ */
+
+#ifndef _LOGINCLIF_H
+#define	_LOGINCLIF_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/**
+ * Entry point from client to log-server.
+ * Function that checks incoming command, then splits it to the correct handler.
+ * @param fd: file descriptor to parse, (link to client)
+ * @return 0=invalid session,marked for disconnection,unknow packet, banned..; 1=success
+ */
+int logclif_parse(int fd);
+
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ */
+void do_init_loginclif(void);
+
+/**
+ * loginclif destructor
+ *  dealloc..., function called at exit of the login-serv
+ */
+void do_final_loginclif(void);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _LOGINCLIF_H */
+

+ 176 - 0
src/login/logincnslif.c

@@ -0,0 +1,176 @@
+/**
+ * @file logincnslif.c
+ * Module purpose is to handle incoming and outgoing requests with console.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams originally in login.c
+ * @author rAthena Dev Team
+ */
+
+#include "../common/mmo.h" //cbasetype + NAME_LENGTH
+#include "../common/showmsg.h" //show notice
+#include "../common/md5calc.h"
+#include "../common/ers.h"
+#include "../common/cli.h"
+#include "../common/timer.h"
+#include "../common/strlib.h"
+#include "login.h"
+#include "logincnslif.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * Login-server console help: starting option info.
+ *  Do not rename function used as extern.
+ * @param do_exit: terminate program execution ?
+ */
+void display_helpscreen(bool do_exit) {
+	ShowInfo("Usage: %s [options]\n", SERVER_NAME);
+	ShowInfo("\n");
+	ShowInfo("Options:\n");
+	ShowInfo("  -?, -h [--help]\t\tDisplays this help screen.\n");
+	ShowInfo("  -v [--version]\t\tDisplays the server's version.\n");
+	ShowInfo("  --run-once\t\t\tCloses server after loading (testing).\n");
+	ShowInfo("  --login-config <file>\t\tAlternative login-server configuration.\n");
+	ShowInfo("  --lan-config <file>\t\tAlternative lag configuration.\n");
+	ShowInfo("  --msg-config <file>\t\tAlternative message configuration.\n");
+	if( do_exit )
+		exit(EXIT_SUCCESS);
+}
+
+/**
+ * Read the option specified in command line
+ *  and assign the confs used by the different server.
+ * @param argc:
+ * @param argv:
+ * @return true or Exit on failure.
+ */
+int logcnslif_get_options(int argc, char ** argv) {
+	int i = 0;
+	for (i = 1; i < argc; i++) {
+		const char* arg = argv[i];
+
+		if (arg[0] != '-' && (arg[0] != '/' || arg[1] == '-')) {// -, -- and /
+			ShowError("Unknown option '%s'.\n", argv[i]);
+			exit(EXIT_FAILURE);
+		} else if ((++arg)[0] == '-') {// long option
+			arg++;
+
+			if (strcmp(arg, "help") == 0) {
+				display_helpscreen(true);
+			} else if (strcmp(arg, "version") == 0) {
+				display_versionscreen(true);
+			} else if (strcmp(arg, "run-once") == 0){ // close the map-server as soon as its done.. for testing [Celest]
+				runflag = CORE_ST_STOP;
+			} else if (SERVER_TYPE & (ATHENA_SERVER_LOGIN)) { //login
+				if (strcmp(arg, "lan-config") == 0) {
+					if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.lanconf_name, argv[++i], sizeof(login_config.lanconf_name));
+				}
+				if (strcmp(arg, "login-config") == 0) {
+					if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.loginconf_name, argv[++i], sizeof(login_config.loginconf_name));
+				}
+				if (strcmp(arg, "msg-config") == 0) {
+					if (opt_has_next_value(arg, i, argc)) safestrncpy(login_config.msgconf_name, argv[++i], sizeof(login_config.msgconf_name));
+				} else {
+					ShowError("Unknown option '%s'.\n", argv[i]);
+					exit(EXIT_FAILURE);
+				}
+			}
+		} else switch (arg[0]) {// short option
+			case '?':
+			case 'h':
+				display_helpscreen(true);
+				break;
+			case 'v':
+				display_versionscreen(true);
+				break;
+			default:
+				ShowError("Unknown option '%s'.\n", argv[i]);
+				exit(EXIT_FAILURE);
+		}
+	}
+	return 1;
+}
+
+/**
+ * Console Command Parser
+ * Transmited from command cli.c
+ * note common name for all serv do not rename (extern in cli)
+ * @author [Wizputer]
+ * @param buf: buffer to parse, (from console)
+ * @return 1=success
+ */
+int cnslif_parse(const char* buf){
+	char type[64];
+	char command[64];
+	int n=0;
+
+	if( ( n = sscanf(buf, "%127[^:]:%255[^\n\r]", type, command) ) < 2 ){
+		if((n = sscanf(buf, "%63[^\n]", type))<1) return -1; //nothing to do no arg
+	}
+	if( n != 2 ){ //end string
+		ShowNotice("Type: '%s'\n",type);
+		command[0] = '\0';
+	}
+	else
+		ShowNotice("Type of command: '%s' || Command: '%s'\n",type,command);
+
+	if( n == 2 ){
+		if(strcmpi("server", type) == 0 ){
+			if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ){
+				runflag = 0;
+			}
+			else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 )
+				ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
+		}
+		if( strcmpi("create",type) == 0 )
+		{
+			char username[NAME_LENGTH], password[NAME_LENGTH], md5password[32+1], sex; //23+1 plaintext 32+1 md5
+			bool md5 = 0;
+			if( sscanf(command, "%23s %23s %c", username, password, &sex) < 3 || strnlen(username, sizeof(username)) < 4 || strnlen(password, sizeof(password)) < 1 ){
+				ShowWarning("Console: Invalid parameters for '%s'. Usage: %s <username> <password> <sex:F/M>\n", type, type);
+				return 0;
+			}
+			if( login_config.use_md5_passwds ){
+				MD5_String(password,md5password);
+				md5 = 1;
+			}
+			if( login_mmo_auth_new(username,(md5?md5password:password), TOUPPER(sex), "0.0.0.0") != -1 ){
+				ShowError("Console: Account creation failed.\n");
+				return 0;
+			}
+			ShowStatus("Console: Account '%s' created successfully.\n", username);
+		}
+	}
+	else if( strcmpi("ers_report", type) == 0 ){
+		ers_report();
+	}
+	else if( strcmpi("help", type) == 0 ){
+		ShowInfo("Available commands:\n");
+		ShowInfo("\t server:shutdown => Stops the server.\n");
+		ShowInfo("\t server:alive => Checks if the server is running.\n");
+		ShowInfo("\t ers_report => Displays database usage.\n");
+		ShowInfo("\t create:<username> <password> <sex:M|F> => Creates a new account.\n");
+	}
+	return 1;
+}
+
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ */
+void do_init_logincnslif(void){
+	if( login_config.console ) {
+		add_timer_func_list(parse_console_timer, "parse_console_timer");
+		add_timer_interval(gettick()+1000, parse_console_timer, 0, 0, 1000); //start in 1s each 1sec
+	}
+}
+
+/**
+ * Handler to cleanup module, called when login-server stops.
+ */
+void do_final_logincnslif(void){
+	return;
+}

+ 58 - 0
src/login/logincnslif.h

@@ -0,0 +1,58 @@
+/**
+ * @file logincnslif.h
+ * Module purpose is to handle incoming and outgoing requests with console.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams originally in login.c
+ * @author rAthena Dev Team
+ */
+
+#ifndef CONSOLEIF_H
+#define	CONSOLEIF_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/**
+ * Console Command Parser
+ * Transmited from command cli.c
+ * note common name for all serv do not rename (extern in cli)
+ * @author [Wizputer]
+ * @param buf: buffer to parse, (from console)
+ * @return 1=success
+ */
+int cnslif_parse(const char* buf);
+
+/**
+ * Read the option specified in command line
+ *  and assign the confs used by the different server.
+ * @param argc:
+ * @param argv:
+ * @return true or Exit on failure.
+ */
+int logcnslif_get_options(int argc, char ** argv);
+
+/**
+ * Login-server console help: starting option info.
+ *  Do not rename function used as extern.
+ * @param do_exit: terminate program execution ?
+ */
+void display_helpscreen(bool do_exit);
+
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ */
+void do_init_logincnslif(void);
+/**
+ * Handler to cleanup module, called when login-server stops.
+ */
+void do_final_logincnslif(void);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* CONSOLEIF_H */
+

+ 95 - 65
src/login/loginlog_sql.c → src/login/loginlog.c

@@ -1,5 +1,11 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+/**
+ * @file loginlog.c
+ * Module purpose is to register (log) events into a file or sql database.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams rev < 15k
+ * @author rAthena Dev Team
+ */
 
 
 #include "../common/cbasetypes.h"
 #include "../common/cbasetypes.h"
 #include "../common/mmo.h"
 #include "../common/mmo.h"
@@ -13,7 +19,7 @@
 static char   global_db_hostname[32] = "127.0.0.1";
 static char   global_db_hostname[32] = "127.0.0.1";
 static uint16 global_db_port = 3306;
 static uint16 global_db_port = 3306;
 static char   global_db_username[32] = "ragnarok";
 static char   global_db_username[32] = "ragnarok";
-static char   global_db_password[32] = "";
+static char   global_db_password[32] = ""; //empty by default since mysql is empty by default as well
 static char   global_db_database[32] = "ragnarok";
 static char   global_db_database[32] = "ragnarok";
 static char   global_codepage[32] = "";
 static char   global_codepage[32] = "";
 // local sql settings
 // local sql settings
@@ -29,9 +35,13 @@ static Sql* sql_handle = NULL;
 static bool enabled = false;
 static bool enabled = false;
 
 
 
 
-// Returns the number of failed login attemps by the ip in the last minutes.
-unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes)
-{
+/**
+ * Get the number of failed login attempts by the ip in the last minutes.
+ * @param ip: ip to search attempt from
+ * @param minutes: intervall to search
+ * @return number of failed attempts
+ */
+unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes) {
 	unsigned long failures = 0;
 	unsigned long failures = 0;
 
 
 	if( !enabled )
 	if( !enabled )
@@ -52,11 +62,14 @@ unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes)
 }
 }
 
 
 
 
-/*=============================================
- * Records an event in the login log
- *---------------------------------------------*/
-void login_log(uint32 ip, const char* username, int rcode, const char* message)
-{
+/**
+ * Records an event in the login log.
+ * @param ip:
+ * @param username:
+ * @param rcode:
+ * @param message:
+ */
+void login_log(uint32 ip, const char* username, int rcode, const char* message) {
 	char esc_username[NAME_LENGTH*2+1];
 	char esc_username[NAME_LENGTH*2+1];
 	char esc_message[255*2+1];
 	char esc_message[255*2+1];
 	int retcode;
 	int retcode;
@@ -75,60 +88,13 @@ void login_log(uint32 ip, const char* username, int rcode, const char* message)
 		Sql_ShowDebug(sql_handle);
 		Sql_ShowDebug(sql_handle);
 }
 }
 
 
-bool loginlog_init(void)
-{
-	const char* username;
-	const char* password;
-	const char* hostname;
-	uint16      port;
-	const char* database;
-	const char* codepage;
-
-	if( log_db_hostname[0] != '\0' )
-	{// local settings
-		username = log_db_username;
-		password = log_db_password;
-		hostname = log_db_hostname;
-		port     = log_db_port;
-		database = log_db_database;
-		codepage = log_codepage;
-	}
-	else
-	{// global settings
-		username = global_db_username;
-		password = global_db_password;
-		hostname = global_db_hostname;
-		port     = global_db_port;
-		database = global_db_database;
-		codepage = global_codepage;
-	}
-
-	sql_handle = Sql_Malloc();
-
-	if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
-	{
-		Sql_ShowDebug(sql_handle);
-		Sql_Free(sql_handle);
-		exit(EXIT_FAILURE);
-	}
-
-	if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
-		Sql_ShowDebug(sql_handle);
-
-	enabled = true;
-
-	return true;
-}
-
-bool loginlog_final(void)
-{
-	Sql_Free(sql_handle);
-	sql_handle = NULL;
-	return true;
-}
-
-bool loginlog_config_read(const char* key, const char* value)
-{
+/**
+ * Read configuration options.
+ * @param key: config keyword
+ * @param value: config value for keyword
+ * @return true if successful, false if config not complete or server already running
+ */
+bool loginlog_config_read(const char* key, const char* value) {
 	const char* signature;
 	const char* signature;
 
 
 	signature = "sql.";
 	signature = "sql.";
@@ -182,3 +148,67 @@ bool loginlog_config_read(const char* key, const char* value)
 
 
 	return true;
 	return true;
 }
 }
+
+
+/// Constructor destructor
+
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ * @return true if success else exit execution
+ */
+bool loginlog_init(void) {
+	const char* username;
+	const char* password;
+	const char* hostname;
+	uint16      port;
+	const char* database;
+	const char* codepage;
+
+	if( log_db_hostname[0] != '\0' )
+	{// local settings
+		username = log_db_username;
+		password = log_db_password;
+		hostname = log_db_hostname;
+		port     = log_db_port;
+		database = log_db_database;
+		codepage = log_codepage;
+	}
+	else
+	{// global settings
+		username = global_db_username;
+		password = global_db_password;
+		hostname = global_db_hostname;
+		port     = global_db_port;
+		database = global_db_database;
+		codepage = global_codepage;
+	}
+
+	sql_handle = Sql_Malloc();
+
+	if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
+	{
+		Sql_ShowDebug(sql_handle);
+		Sql_Free(sql_handle);
+		exit(EXIT_FAILURE);
+	}
+
+	if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
+		Sql_ShowDebug(sql_handle);
+
+	enabled = true;
+
+	return true;
+}
+
+
+/**
+ * Handler to cleanup module, called when login-server stops.
+ * Currently closing sql connection to log schema.
+ * @return true success
+ */
+bool loginlog_final(void) {
+	Sql_Free(sql_handle);
+	sql_handle = NULL;
+	return true;
+}

+ 49 - 3
src/login/loginlog.h

@@ -1,15 +1,61 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+/**
+ * @file loginlog.h
+ * Module purpose is to register (log) events into a file or sql database.
+ * Licensed under GNU GPL.
+ *  For more information, see LICENCE in the main folder.
+ * @author Athena Dev Teams rev < 15k
+ * @author rAthena Dev Team
+ */
 
 
 #ifndef __LOGINLOG_H_INCLUDED__
 #ifndef __LOGINLOG_H_INCLUDED__
 #define __LOGINLOG_H_INCLUDED__
 #define __LOGINLOG_H_INCLUDED__
 
 
+#ifdef	__cplusplus
+extern "C" {
+#endif
 
 
+/**
+ * Get the number of failed login attempts by the ip in the last minutes.
+ * @param ip: ip to search attempt from
+ * @param minutes: intervall to search
+ * @return number of failed attempts
+ */
 unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes);
 unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes);
+
+/**
+ * Records an event in the login log.
+ * @param ip:
+ * @param username:
+ * @param rcode:
+ * @param message:
+ */
 void login_log(uint32 ip, const char* username, int rcode, const char* message);
 void login_log(uint32 ip, const char* username, int rcode, const char* message);
+
+/**
+ * Read configuration options.
+ * @param key: config keyword
+ * @param value: config value for keyword
+ * @return true if successful, false if config not complete or server already running
+ */
+bool loginlog_config_read(const char* w1, const char* w2);
+
+
+/**
+ * Initialize the module.
+ * Launched at login-serv start, create db or other long scope variable here.
+ * @return true if success else exit execution
+ */
 bool loginlog_init(void);
 bool loginlog_init(void);
+
+/**
+ * Handler to cleanup module, called when login-server stops.
+ * atm closing sql connection to log schema
+ * @return true success
+ */
 bool loginlog_final(void);
 bool loginlog_final(void);
-bool loginlog_config_read(const char* w1, const char* w2);
 
 
+#ifdef	__cplusplus
+}
+#endif
 
 
 #endif // __LOGINLOG_H_INCLUDED__
 #endif // __LOGINLOG_H_INCLUDED__

+ 9 - 3
src/login/sql/CMakeLists.txt

@@ -8,13 +8,19 @@ set( SQL_LOGIN_HEADERS
 	"${SQL_LOGIN_SOURCE_DIR}/account.h"
 	"${SQL_LOGIN_SOURCE_DIR}/account.h"
 	"${SQL_LOGIN_SOURCE_DIR}/ipban.h"
 	"${SQL_LOGIN_SOURCE_DIR}/ipban.h"
 	"${SQL_LOGIN_SOURCE_DIR}/login.h"
 	"${SQL_LOGIN_SOURCE_DIR}/login.h"
+	"${SQL_LOGIN_SOURCE_DIR}/loginclif.h"
+	"${SQL_LOGIN_SOURCE_DIR}/loginchrif.h"
+	"${SQL_LOGIN_SOURCE_DIR}/logincnslif.h"
 	"${SQL_LOGIN_SOURCE_DIR}/loginlog.h"
 	"${SQL_LOGIN_SOURCE_DIR}/loginlog.h"
 	)
 	)
 set( SQL_LOGIN_SOURCES
 set( SQL_LOGIN_SOURCES
-	"${SQL_LOGIN_SOURCE_DIR}/account_sql.c"
-	"${SQL_LOGIN_SOURCE_DIR}/ipban_sql.c"
+	"${SQL_LOGIN_SOURCE_DIR}/account.c"
+	"${SQL_LOGIN_SOURCE_DIR}/ipban.c"
 	"${SQL_LOGIN_SOURCE_DIR}/login.c"
 	"${SQL_LOGIN_SOURCE_DIR}/login.c"
-	"${SQL_LOGIN_SOURCE_DIR}/loginlog_sql.c"
+	"${SQL_LOGIN_SOURCE_DIR}/loginclif.c"
+	"${SQL_LOGIN_SOURCE_DIR}/loginchrif.c"
+	"${SQL_LOGIN_SOURCE_DIR}/logincnslif.c"
+	"${SQL_LOGIN_SOURCE_DIR}/loginlog.c"
 	)
 	)
 set( DEPENDENCIES common_sql )
 set( DEPENDENCIES common_sql )
 set( LIBRARIES ${GLOBAL_LIBRARIES} )
 set( LIBRARIES ${GLOBAL_LIBRARIES} )

+ 29 - 14
src/map/atcommand.c

@@ -862,15 +862,21 @@ ACMD_FUNC(speed)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	if (speed < 0) {
+	sd->state.permanent_speed = 0; // Remove lock when set back to default speed.
+
+	if (speed < 0)
 		sd->base_status.speed = DEFAULT_WALK_SPEED;
 		sd->base_status.speed = DEFAULT_WALK_SPEED;
-		sd->state.permanent_speed = 0; // Remove lock when set back to default speed.
-	} else {
+	else
 		sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
 		sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
+
+	if (sd->base_status.speed != DEFAULT_WALK_SPEED) {
 		sd->state.permanent_speed = 1; // Set lock when set to non-default speed.
 		sd->state.permanent_speed = 1; // Set lock when set to non-default speed.
-	}
+		clif_displaymessage(fd, msg_txt(sd,8)); // Speed changed.
+	} else
+		clif_displaymessage(fd, msg_txt(sd,389)); // Speed returned to normal.
+
 	status_calc_bl(&sd->bl, SCB_SPEED);
 	status_calc_bl(&sd->bl, SCB_SPEED);
-	clif_displaymessage(fd, msg_txt(sd,8)); // Speed changed.
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1165,7 +1171,7 @@ ACMD_FUNC(heal)
 
 
 	if ( hp < 0 && sp <= 0 ) {
 	if ( hp < 0 && sp <= 0 ) {
 		status_damage(NULL, &sd->bl, -hp, -sp, 0, 0);
 		status_damage(NULL, &sd->bl, -hp, -sp, 0, 0);
-		clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0);
+		clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, DMG_ENDURE, 0);
 		clif_displaymessage(fd, msg_txt(sd,156)); // HP or/and SP modified.
 		clif_displaymessage(fd, msg_txt(sd,156)); // HP or/and SP modified.
 		return 0;
 		return 0;
 	}
 	}
@@ -1176,7 +1182,7 @@ ACMD_FUNC(heal)
 			status_heal(&sd->bl, hp, 0, 0);
 			status_heal(&sd->bl, hp, 0, 0);
 		else {
 		else {
 			status_damage(NULL, &sd->bl, -hp, 0, 0, 0);
 			status_damage(NULL, &sd->bl, -hp, 0, 0, 0);
-			clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0);
+			clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, DMG_ENDURE, 0);
 		}
 		}
 	}
 	}
 
 
@@ -3539,7 +3545,7 @@ ACMD_FUNC(recallall)
 				count++;
 				count++;
 			else {
 			else {
 				if (pc_isdead(pl_sd)) { //Wake them up
 				if (pc_isdead(pl_sd)) { //Wake them up
-					pc_setstand(pl_sd);
+					pc_setstand(pl_sd, true);
 					pc_setrestartvalue(pl_sd,1);
 					pc_setrestartvalue(pl_sd,1);
 				}
 				}
 				pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN);
 				pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN);
@@ -5752,13 +5758,15 @@ ACMD_FUNC(autotrade) {
 	}
 	}
 
 
 	sd->state.autotrade = 1;
 	sd->state.autotrade = 1;
+	if (battle_config.autotrade_monsterignore)
+		sd->state.monster_ignore = 1;
 
 
 	if( sd->state.vending ){
 	if( sd->state.vending ){
 		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;", vendings_db, sd->vender_id ) != SQL_SUCCESS ){
 		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;", vendings_db, sd->vender_id ) != SQL_SUCCESS ){
 			Sql_ShowDebug( mmysql_handle );
 			Sql_ShowDebug( mmysql_handle );
 		}
 		}
 	}else if( sd->state.buyingstore ){
 	}else if( sd->state.buyingstore ){
-		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;", buyingstore_db, sd->buyer_id ) != SQL_SUCCESS ){
+		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;", buyingstores_db, sd->buyer_id ) != SQL_SUCCESS ){
 			Sql_ShowDebug( mmysql_handle );
 			Sql_ShowDebug( mmysql_handle );
 		}
 		}
 	}
 	}
@@ -5770,7 +5778,7 @@ ACMD_FUNC(autotrade) {
 
 
 	channel_pcquit(sd,0xF); //leave all chan
 	channel_pcquit(sd,0xF); //leave all chan
 	clif_authfail_fd(sd->fd, 15);
 	clif_authfail_fd(sd->fd, 15);
-	
+
 	chrif_save(sd,3);
 	chrif_save(sd,3);
 
 
 	return 0;
 	return 0;
@@ -6928,9 +6936,9 @@ ACMD_FUNC(mail)
  *------------------------------------------*/
  *------------------------------------------*/
 ACMD_FUNC(mobinfo)
 ACMD_FUNC(mobinfo)
 {
 {
-	unsigned char msize[3][7] = {"Small", "Medium", "Large"};
-	unsigned char mrace[12][11] = {"Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Boss", "Non-Boss"};
-	unsigned char melement[10][8] = {"Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead"};
+	unsigned char msize[SZ_ALL][7] = { "Small", "Medium", "Large" };
+	unsigned char mrace[RC_ALL][11] = { "Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Player" };
+	unsigned char melement[ELE_ALL][8] = { "Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead" };
 	char atcmd_output2[CHAT_SIZE_MAX];
 	char atcmd_output2[CHAT_SIZE_MAX];
 	struct item_data *item_data;
 	struct item_data *item_data;
 	struct mob_db *mob, *mob_array[MAX_SEARCH];
 	struct mob_db *mob, *mob_array[MAX_SEARCH];
@@ -7847,6 +7855,8 @@ ACMD_FUNC(fakename)
 		{
 		{
 			sd->fakename[0] = '\0';
 			sd->fakename[0] = '\0';
 			clif_charnameack(0, &sd->bl);
 			clif_charnameack(0, &sd->bl);
+			if (sd->disguise)
+				clif_charnameack(sd->fd, &sd->bl);
 			clif_displaymessage(sd->fd, msg_txt(sd,1307)); // Returned to real name.
 			clif_displaymessage(sd->fd, msg_txt(sd,1307)); // Returned to real name.
 			return 0;
 			return 0;
 		}
 		}
@@ -7863,6 +7873,8 @@ ACMD_FUNC(fakename)
 
 
 	safestrncpy(sd->fakename, message, sizeof(sd->fakename));
 	safestrncpy(sd->fakename, message, sizeof(sd->fakename));
 	clif_charnameack(0, &sd->bl);
 	clif_charnameack(0, &sd->bl);
+	if (sd->disguise) // Another packet should be sent so the client updates the name for sd
+		clif_charnameack(sd->fd, &sd->bl);
 	clif_displaymessage(sd->fd, msg_txt(sd,1310)); // Fake name enabled.
 	clif_displaymessage(sd->fd, msg_txt(sd,1310)); // Fake name enabled.
 
 
 	return 0;
 	return 0;
@@ -9520,7 +9532,7 @@ ACMD_FUNC(cloneequip) {
 	else {
 	else {
 		int8 i;
 		int8 i;
 		for (i = 0; i < EQI_MAX; i++) {
 		for (i = 0; i < EQI_MAX; i++) {
-			int8 idx;
+			short idx;
 			char flag = 0;
 			char flag = 0;
 			struct item tmp_item;
 			struct item tmp_item;
 			if ((idx = pl_sd->equip_index[i]) < 0)
 			if ((idx = pl_sd->equip_index[i]) < 0)
@@ -10148,6 +10160,9 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
 		sprintf(atcmd_msg, "%s", message);
 		sprintf(atcmd_msg, "%s", message);
 	}
 	}
 
 
+	if (battle_config.idletime_option&IDLE_ATCOMMAND)
+		sd->idletime = last_tick;
+
 	//Clearing these to be used once more.
 	//Clearing these to be used once more.
 	memset(command, '\0', sizeof(command));
 	memset(command, '\0', sizeof(command));
 	memset(params, '\0', sizeof(params));
 	memset(params, '\0', sizeof(params));

+ 197 - 254
src/map/battle.c

@@ -309,10 +309,14 @@ int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src,
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+* Get attribute ratio
+* @param atk_elem Attack element enum e_element
+* @param def_type Defense element enum e_element
+* @param def_lv Element level 1 ~ MAX_ELE_LEVEL
+*/
 int battle_attr_ratio(int atk_elem,int def_type, int def_lv) {
 int battle_attr_ratio(int atk_elem,int def_type, int def_lv) {
-	if (!CHK_ELEMENT(atk_elem))
-		return 100;
-	if (!CHK_ELEMENT(def_type) || def_lv < 1 || def_lv > 4)
+	if (!CHK_ELEMENT(atk_elem) || !CHK_ELEMENT(def_type) || !CHK_ELEMENT_LEVEL(def_lv))
 		return 100;
 		return 100;
 
 
 	return attr_fix_table[def_lv-1][atk_elem][def_type];
 	return attr_fix_table[def_lv-1][atk_elem][def_type];
@@ -334,8 +338,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
 	if (!CHK_ELEMENT(atk_elem))
 	if (!CHK_ELEMENT(atk_elem))
 		atk_elem = rnd()%ELE_ALL;
 		atk_elem = rnd()%ELE_ALL;
 
 
-	if (!CHK_ELEMENT(def_type) ||
-		def_lv < 1 || def_lv > 4) {
+	if (!CHK_ELEMENT(def_type) || !CHK_ELEMENT_LEVEL(def_lv)) {
 		ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv);
 		ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv);
 		return damage;
 		return damage;
 	}
 	}
@@ -343,18 +346,18 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
 	ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
 	ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
 	if (sc && sc->count) { //increase dmg by src status
 	if (sc && sc->count) { //increase dmg by src status
 		switch(atk_elem){
 		switch(atk_elem){
-		case ELE_FIRE:
-			if(sc->data[SC_VOLCANO]) ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
-			break;
-		case ELE_WIND:
-			if(sc->data[SC_VIOLENTGALE]) ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
-			break;
-		case ELE_WATER:
-			if(sc->data[SC_DELUGE]) ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
-			break;
-		case ELE_GHOST:
-			if(sc->data[SC_TELEKINESIS_INTENSE]) ratio += (sc->data[SC_TELEKINESIS_INTENSE]->val3);
-			break;
+			case ELE_FIRE:
+				if(sc->data[SC_VOLCANO]) ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
+				break;
+			case ELE_WIND:
+				if(sc->data[SC_VIOLENTGALE]) ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
+				break;
+			case ELE_WATER:
+				if(sc->data[SC_DELUGE]) ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
+				break;
+			case ELE_GHOST:
+				if(sc->data[SC_TELEKINESIS_INTENSE]) ratio += (sc->data[SC_TELEKINESIS_INTENSE]->val3);
+				break;
 		}
 		}
 	}
 	}
 	if( target && target->type == BL_SKILL ) {
 	if( target && target->type == BL_SKILL ) {
@@ -792,20 +795,29 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 
 
 		if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) {
 		if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) {
 			struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
 			struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
-			//uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; (safetywall or steinwand)
+			uint16 skill_id_val = sc->data[SC_SAFETYWALL]->val2;
 			if (group) {
 			if (group) {
-			//in RE, SW possesses a lifetime equal to group val2, (3x caster hp, or homon formula)
-#ifdef RENEWAL
 				d->dmg_lv = ATK_BLOCK;
 				d->dmg_lv = ATK_BLOCK;
+
+				if (skill_id_val == MH_STEINWAND) {
+					if (--group->val2 <= 0)
+						skill_delunitgroup(group);
+					if( (group->val3 - damage) > 0 )
+						group->val3 -= (int)cap_value(damage, INT_MIN, INT_MAX);
+					else
+						skill_delunitgroup(group);
+					return 0;
+				}
+				//in RE, SW possesses a lifetime equal to group val2, (3x caster hp, or homon formula)
+#ifdef RENEWAL
 				if ( ( group->val2 - damage) > 0 ) {
 				if ( ( group->val2 - damage) > 0 ) {
-					group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
+					group->val2 -= (int)cap_value(damage, INT_MIN, INT_MAX);
 				} else
 				} else
 					skill_delunitgroup(group);
 					skill_delunitgroup(group);
 				return 0;
 				return 0;
 #else
 #else
-				if (--group->val2<=0)
+				if (--group->val2 <= 0)
 					skill_delunitgroup(group);
 					skill_delunitgroup(group);
-				d->dmg_lv = ATK_BLOCK;
 				return 0;
 				return 0;
 #endif
 #endif
 			}
 			}
@@ -851,18 +863,18 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 		}
 		}
 
 
 		if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) {
 		if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) {
-			clif_skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1);
 			sce->val3 -= (int)cap_value(damage,INT_MIN,INT_MAX); // absorb damage
 			sce->val3 -= (int)cap_value(damage,INT_MIN,INT_MAX); // absorb damage
 			d->dmg_lv = ATK_BLOCK;
 			d->dmg_lv = ATK_BLOCK;
-			sc_start(src,bl,SC_STUN,15,0,skill_get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stunned when one shield is broken.
 			if( sce->val3 <= 0 ) { // Shield Down
 			if( sce->val3 <= 0 ) { // Shield Down
 				sce->val2--;
 				sce->val2--;
-				if( sce->val2 > 0 ) {
-					if( sd )
-						clif_millenniumshield(sd,sce->val2);
-					sce->val3 = 1000; // Next Shield
-				} else
-					status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down
+				if( sce->val2 >= 0 ) {
+					clif_millenniumshield(bl,sce->val2);
+					if( !sce->val2 )
+						status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down
+					else
+						sce->val3 = 1000; // Next shield
+				}
+				status_change_start(src,bl,SC_STUN,10000,0,0,0,0,1000,2);
 			}
 			}
 			return 0;
 			return 0;
 		}
 		}
@@ -877,7 +889,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 			(flag&BF_LONG || sc->data[SC_SPURT])
 			(flag&BF_LONG || sc->data[SC_SPURT])
 			&& rnd()%100 < 20)
 			&& rnd()%100 < 20)
 		{
 		{
-			if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge.
+			if (sd && pc_issit(sd)) pc_setstand(sd, true); //Stand it to dodge.
 			clif_skill_nodamage(bl,bl,TK_DODGE,1,1);
 			clif_skill_nodamage(bl,bl,TK_DODGE,1,1);
 			if (!sc->data[SC_COMBO])
 			if (!sc->data[SC_COMBO])
 				sc_start4(src,bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000);
 				sc_start4(src,bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000);
@@ -1493,6 +1505,10 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
 			break;
 			break;
 	}
 	}
 
 
+
+	if(sd->sc.data[SC_GN_CARTBOOST]) // cart boost adds mastery type damage
+		damage += 10*sd->sc.data[SC_GN_CARTBOOST]->val1;
+
 	return damage;
 	return damage;
 }
 }
 
 
@@ -1556,11 +1572,11 @@ static int battle_calc_base_weapon_attack(struct block_list *src, struct status_
  *------------------------------------------
  *------------------------------------------
  * Pass damage2 as NULL to not calc it.
  * Pass damage2 as NULL to not calc it.
  * Flag values:
  * Flag values:
- * &1: Critical hit
- * &2: Arrow attack
- * &4: Skill is Magic Crasher
- * &8: Skip target size adjustment (Extremity Fist?)
- *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX)
+ * &1 : Critical hit
+ * &2 : Arrow attack
+ * &4 : Skill is Magic Crasher
+ * &8 : Skip target size adjustment (Extremity Fist?)
+ * &16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX)
  *
  *
  * Credits:
  * Credits:
  *	Original coder Skoltex
  *	Original coder Skoltex
@@ -1675,7 +1691,7 @@ void battle_consume_ammo(TBL_PC*sd, int skill, int lv)
 		if (!qty) qty = 1;
 		if (!qty) qty = 1;
 	}
 	}
 
 
-	if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition
+	if (sd->equip_index[EQI_AMMO] >= 0) //Qty check should have been done in skill_check_condition
 		pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME);
 		pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME);
 
 
 	sd->state.arrow_atk = 0;
 	sd->state.arrow_atk = 0;
@@ -1853,6 +1869,26 @@ static int battle_skill_damage(struct block_list *src, struct block_list *target
 }
 }
 #endif
 #endif
 
 
+/**
+ * Calculates Minstrel/Wanderer bonus for Chorus skills.
+ * @param sd Player who has Chorus skill active
+ * @return Bonus value based on party count
+ */
+static int battle_calc_chorusbonus(struct map_session_data *sd) {
+	int members = 0;
+
+	if (!sd || !sd->status.party_id)
+		return 0;
+
+	members = party_foreachsamemap(party_sub_count_class, sd, MAPID_THIRDMASK, MAPID_MINSTRELWANDERER);
+
+	if (members < 3)
+		return 0; // Bonus remains 0 unless 3 or more Minstrels/Wanderers are in the party.
+	if (members > 7)
+		return 5; // Maximum effect possible from 7 or more Minstrels/Wanderers.
+	return members - 2; // Effect bonus from additional Minstrels/Wanderers if not above the max possible.
+}
+
 struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
 struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
 struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
 struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
 
 
@@ -1967,12 +2003,12 @@ static bool is_attack_critical(struct Damage wd, struct block_list *src, struct
 	struct map_session_data *tsd = BL_CAST(BL_PC, target);
 	struct map_session_data *tsd = BL_CAST(BL_PC, target);
 
 
 	if (!first_call)
 	if (!first_call)
-		return (wd.type == 0x0a);
+		return (wd.type == DMG_CRITICAL);
 
 
 	if (skill_id == NPC_CRITICALSLASH || skill_id == LG_PINPOINTATTACK) //Always critical skills
 	if (skill_id == NPC_CRITICALSLASH || skill_id == LG_PINPOINTATTACK) //Always critical skills
 		return true;
 		return true;
 
 
-	if( !(wd.type&0x08) && sstatus->cri && (!skill_id ||
+	if( !(wd.type&DMG_MULTI_HIT) && sstatus->cri && (!skill_id ||
 		skill_id == KN_AUTOCOUNTER || skill_id == SN_SHARPSHOOTING ||
 		skill_id == KN_AUTOCOUNTER || skill_id == SN_SHARPSHOOTING ||
 		skill_id == MA_SHARPSHOOTING || skill_id == NJ_KIRIKAGE))
 		skill_id == MA_SHARPSHOOTING || skill_id == NJ_KIRIKAGE))
 	{
 	{
@@ -1989,7 +2025,7 @@ static bool is_attack_critical(struct Damage wd, struct block_list *src, struct
 
 
 		//The official equation is *2, but that only applies when sd's do critical.
 		//The official equation is *2, but that only applies when sd's do critical.
 		//Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
 		//Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
-		cri -= tstatus->luk*(!sd&&tsd?3:2);
+		cri -= tstatus->luk * ((!sd && tsd) ? 3 : 2);
 
 
 		if( tsc && tsc->data[SC_SLEEP] )
 		if( tsc && tsc->data[SC_SLEEP] )
 			cri <<= 1;
 			cri <<= 1;
@@ -2203,7 +2239,7 @@ static bool is_attack_hitting(struct Damage wd, struct block_list *src, struct b
 					hitrate -= (10 - (skill_lv - 1));
 					hitrate -= (10 - (skill_lv - 1));
 				break;
 				break;
 		}
 		}
-	} else if (sd && wd.type&0x08 && wd.div_ == 2) // +1 hit per level of Double Attack on a successful double attack (making sure other multi attack skills do not trigger this) [helvetica]
+	} else if (sd && wd.type&DMG_MULTI_HIT && wd.div_ == 2) // +1 hit per level of Double Attack on a successful double attack (making sure other multi attack skills do not trigger this) [helvetica]
 		hitrate += pc_checkskill(sd,TF_DOUBLE);
 		hitrate += pc_checkskill(sd,TF_DOUBLE);
 
 
 	if (sd) {
 	if (sd) {
@@ -2531,11 +2567,6 @@ static struct Damage battle_calc_attack_masteries(struct Damage wd, struct block
 		if (sc) { // Status change considered as masteries
 		if (sc) { // Status change considered as masteries
 			uint8 i;
 			uint8 i;
 
 
-#ifdef RENEWAL
-			if(sc->data[SC_NIBELUNGEN]) //With renewal, the level 4 weapon limitation has beed removed
-				ATK_ADD(wd.masteryAtk, wd.masteryAtk2, sc->data[SC_NIBELUNGEN]->val2);
-#endif
-
 			if (sc->data[SC_MIRACLE])
 			if (sc->data[SC_MIRACLE])
 				i = 2; //Star anger
 				i = 2; //Star anger
 			else
 			else
@@ -2776,9 +2807,8 @@ struct Damage battle_calc_skill_base_damage(struct Damage wd, struct block_list
 				if(sd) {
 				if(sd) {
 					short index = sd->equip_index[EQI_AMMO];
 					short index = sd->equip_index[EQI_AMMO];
 
 
-					damagevalue = (3 * (sstatus->batk + sstatus->rhw.atk + sd->inventory_data[index]->atk)) * (skill_lv + 5) / 5;
-					if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_AMMO)
-						ATK_ADD(wd.damage, wd.damage2, damagevalue);
+					damagevalue = (3 * (sstatus->batk + sstatus->rhw.atk + ((index >= 0 && sd->inventory_data[index]) ? sd->inventory_data[index]->atk : 0))) * (skill_lv + 5) / 5;
+					ATK_ADD(wd.damage, wd.damage2, damagevalue);
 				} else {
 				} else {
 					damagevalue = 5000;
 					damagevalue = 5000;
 					ATK_ADD(wd.damage, wd.damage2, damagevalue);
 					ATK_ADD(wd.damage, wd.damage2, damagevalue);
@@ -2851,11 +2881,11 @@ struct Damage battle_calc_skill_base_damage(struct Damage wd, struct block_list
 					RE_ALLATK_ADDRATE(wd, sd->bonus.atk_rate);
 					RE_ALLATK_ADDRATE(wd, sd->bonus.atk_rate);
 				}
 				}
 #ifndef RENEWAL
 #ifndef RENEWAL
-				if(is_attack_critical(wd, src, target, skill_id, skill_lv, false) && sd->bonus.crit_atk_rate) { // add +crit damage bonuses here in pre-renewal mode [helvetica]
+				if(sd->bonus.crit_atk_rate && is_attack_critical(wd, src, target, skill_id, skill_lv, false)) { // add +crit damage bonuses here in pre-renewal mode [helvetica]
 					ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.crit_atk_rate);
 					ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.crit_atk_rate);
 				}
 				}
 #endif
 #endif
-				if(is_attack_critical(wd, src, target, skill_id, skill_lv, false) && sc && sc->data[SC_MTF_CRIDAMAGE]) {
+				if(sc && sc->data[SC_MTF_CRIDAMAGE] && is_attack_critical(wd, src, target, skill_id, skill_lv, false)) {
 					ATK_ADDRATE(wd.damage, wd.damage2, 25);
 					ATK_ADDRATE(wd.damage, wd.damage2, 25);
 					RE_ALLATK_ADDRATE(wd, 25); //Temporary it should be 'bonus.crit_atk_rate'
 					RE_ALLATK_ADDRATE(wd, 25); //Temporary it should be 'bonus.crit_atk_rate'
 				}
 				}
@@ -2899,7 +2929,7 @@ static struct Damage battle_calc_multi_attack(struct Damage wd, struct block_lis
 		{	//Success chance is not added, the higher one is used [Skotlex]
 		{	//Success chance is not added, the higher one is used [Skotlex]
 			if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) {
 			if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) {
 				wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1);
 				wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1);
-				wd.type = 0x08;
+				wd.type = DMG_MULTI_HIT;
 			}
 			}
 		}
 		}
 		else if( ((sd->weapontype1 == W_REVOLVER && (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0) //Normal Chain Action effect
 		else if( ((sd->weapontype1 == W_REVOLVER && (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0) //Normal Chain Action effect
@@ -2907,14 +2937,13 @@ static struct Damage battle_calc_multi_attack(struct Damage wd, struct block_lis
 			&& rnd()%100 < 5*skill_lv ) //Success rate
 			&& rnd()%100 < 5*skill_lv ) //Success rate
 		{
 		{
 			wd.div_ = skill_get_num(GS_CHAINACTION,skill_lv);
 			wd.div_ = skill_get_num(GS_CHAINACTION,skill_lv);
-			wd.type = 0x08;
+			wd.type = DMG_MULTI_HIT;
 			sc_start(src,src,SC_QD_SHOT_READY,100,target->id,skill_get_time(RL_QD_SHOT,1));
 			sc_start(src,src,SC_QD_SHOT_READY,100,target->id,skill_get_time(RL_QD_SHOT,1));
 		}
 		}
 		else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW
 		else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW
 			&& (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1)
 			&& (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1)
 		{
 		{
 			int chance = rnd()%100;
 			int chance = rnd()%100;
-			wd.type = 0x08;
 			switch(sc->data[SC_FEARBREEZE]->val1) {
 			switch(sc->data[SC_FEARBREEZE]->val1) {
 				case 5: if( chance < 4) { wd.div_ = 5; break; } // 3 % chance to attack 5 times.
 				case 5: if( chance < 4) { wd.div_ = 5; break; } // 3 % chance to attack 5 times.
 				case 4: if( chance < 7) { wd.div_ = 4; break; } // 6 % chance to attack 4 times.
 				case 4: if( chance < 7) { wd.div_ = 4; break; } // 6 % chance to attack 4 times.
@@ -2924,6 +2953,8 @@ static struct Damage battle_calc_multi_attack(struct Damage wd, struct block_lis
 			}
 			}
 			wd.div_ = min(wd.div_,sd->status.inventory[i].amount);
 			wd.div_ = min(wd.div_,sd->status.inventory[i].amount);
 			sc->data[SC_FEARBREEZE]->val4 = wd.div_-1;
 			sc->data[SC_FEARBREEZE]->val4 = wd.div_-1;
+			if (wd.div_ > 1)
+				wd.type = DMG_MULTI_HIT;
 		}
 		}
 	}
 	}
 
 
@@ -3418,9 +3449,13 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 			break;
 			break;
 		case RA_WUGDASH:// ATK 300%
 		case RA_WUGDASH:// ATK 300%
 			skillratio += 200;
 			skillratio += 200;
+			if (sc && sc->data[SC_DANCEWITHWUG])
+				skillratio += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd));
 			break;
 			break;
 		case RA_WUGSTRIKE:
 		case RA_WUGSTRIKE:
 			skillratio += -100 + 200 * skill_lv;
 			skillratio += -100 + 200 * skill_lv;
+			if (sc && sc->data[SC_DANCEWITHWUG])
+				skillratio += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd));
 			break;
 			break;
 		case RA_WUGBITE:
 		case RA_WUGBITE:
 			skillratio += 300 + 200 * skill_lv;
 			skillratio += 300 + 200 * skill_lv;
@@ -3463,7 +3498,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 			if( sd ) {
 			if( sd ) {
 				short index = sd->equip_index[EQI_HAND_R];
 				short index = sd->equip_index[EQI_HAND_R];
 				if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
 				if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
-				skillratio += sd->inventory_data[index]->weight / 10;// Weight is divided by 10 since 10 weight in coding make 1 whole actual weight. [Rytech]
+					skillratio += sd->inventory_data[index]->weight / 10;// Weight is divided by 10 since 10 weight in coding make 1 whole actual weight. [Rytech]
 			}
 			}
 			RE_LVL_DMOD(100);
 			RE_LVL_DMOD(100);
 			break;
 			break;
@@ -3521,14 +3556,11 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 			break;
 			break;
 		case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] %
 		case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] %
 			if (sd && skill_lv == 1) {
 			if (sd && skill_lv == 1) {
-				int index = sd->equip_index[EQI_HAND_L];
-				struct item_data *shield_data = NULL;
+				short index = sd->equip_index[EQI_HAND_L];
 
 
 				if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR)
 				if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR)
-					shield_data = sd->inventory_data[index];
+					skillratio += sd->inventory_data[index]->def * 10;
 				skillratio = status_get_lv(src) * 4 + status_get_vit(src) * 2;
 				skillratio = status_get_lv(src) * 4 + status_get_vit(src) * 2;
-				if (shield_data)
-					skillratio += shield_data->def * 10;
 			} else
 			} else
 				skillratio = 0; // Prevent damage since level 2 is MATK. [Aleos]
 				skillratio = 0; // Prevent damage since level 2 is MATK. [Aleos]
 			break;
 			break;
@@ -3829,11 +3861,8 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 			{
 			{
 				uint16 w = 50;
 				uint16 w = 50;
 				int16 idx = 0;
 				int16 idx = 0;
-				if (sd && (idx = sd->equip_index[EQI_AMMO]) > 0) {
-					struct item_data *id = NULL;
-					if ((id = itemdb_exists(sd->status.inventory[idx].nameid)))
-						w = id->weight;
-				}
+				if (sd && (idx = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[idx])
+					w = sd->inventory_data[idx]->weight;
 				w /= 10;
 				w /= 10;
 				skillratio += -100 + (max(w,1) * skill_lv * 30); //(custom)
 				skillratio += -100 + (max(w,1) * skill_lv * 30); //(custom)
 			}
 			}
@@ -3911,11 +3940,15 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li
 		case RA_WUGDASH:
 		case RA_WUGDASH:
 			if( sd && sd->weight )
 			if( sd && sd->weight )
 				atk = (sd->weight / 8) + (30 * pc_checkskill(sd,RA_TOOTHOFWUG));
 				atk = (sd->weight / 8) + (30 * pc_checkskill(sd,RA_TOOTHOFWUG));
+			if (sc && sc->data[SC_DANCEWITHWUG])
+				atk += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd));
 			break;
 			break;
 		case RA_WUGSTRIKE:
 		case RA_WUGSTRIKE:
 		case RA_WUGBITE:
 		case RA_WUGBITE:
 			if(sd)
 			if(sd)
 				atk = (30 * pc_checkskill(sd, RA_TOOTHOFWUG));
 				atk = (30 * pc_checkskill(sd, RA_TOOTHOFWUG));
+			if (sc && sc->data[SC_DANCEWITHWUG])
+				atk += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + battle_calc_chorusbonus(sd));
 			break;
 			break;
 		case GC_COUNTERSLASH:
 		case GC_COUNTERSLASH:
 			atk = sstatus->agi * 2 + (sd ? sd->status.job_level * 4 : 0);
 			atk = sstatus->agi * 2 + (sd ? sd->status.job_level * 4 : 0);
@@ -3955,27 +3988,14 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li
  *	Initial refactoring by Baalberith
  *	Initial refactoring by Baalberith
  *	Refined and optimized by helvetica
  *	Refined and optimized by helvetica
  */
  */
-struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, struct block_list *target, uint16 skill_id)
+struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, uint16 skill_id)
 {
 {
 	struct map_session_data *sd = BL_CAST(BL_PC, src);
 	struct map_session_data *sd = BL_CAST(BL_PC, src);
 	struct status_change *sc = status_get_sc(src);
 	struct status_change *sc = status_get_sc(src);
 	struct status_data *sstatus = status_get_status_data(src);
 	struct status_data *sstatus = status_get_status_data(src);
-#ifdef RENEWAL
-	struct status_data *tstatus = status_get_status_data(target);
-#endif
-	int chorusbonus = 0;
 
 
 	if( sd ) {
 	if( sd ) {
 		int type;
 		int type;
-		// Minstrel/Wanderer number check for chorus skills.
-		// Bonus remains 0 unless 3 or more Minstrels/Wanderers are in the party.
-		if( sd->status.party_id ) {
-			chorusbonus = party_foreachsamemap(party_sub_count_class, sd, MAPID_THIRDMASK, MAPID_MINSTRELWANDERER);
-			if( chorusbonus > 7 )
-				chorusbonus = 5; // Maximum effect possible from 7 or more Minstrels/Wanderers
-			else if( chorusbonus > 2 )
-				chorusbonus = chorusbonus - 2; // Effect bonus from additional Minstrels/Wanderers if not above the max possible.
-		}
 
 
 		// Kagerou/Oboro Earth Charm effect +15% wATK
 		// Kagerou/Oboro Earth Charm effect +15% wATK
 		ARR_FIND(1, 6, type, sd->talisman[type] > 0);
 		ARR_FIND(1, 6, type, sd->talisman[type] > 0);
@@ -3989,35 +4009,19 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s
 
 
 	//The following are applied on top of current damage and are stackable.
 	//The following are applied on top of current damage and are stackable.
 	if (sc) {
 	if (sc) {
-#ifdef RENEWAL
-		if(sc->data[SC_WATK_ELEMENT])
-			if(skill_id != ASC_METEORASSAULT)
-				ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, sc->data[SC_WATK_ELEMENT]->val2);
-		if(sc->data[SC_IMPOSITIO])
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_IMPOSITIO]->val2);
-		if(sc->data[SC_VOLCANO])
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_VOLCANO]->val2);
-		if(sc->data[SC_DRUMBATTLE]) {
-			if(tstatus->size == SZ_SMALL) {
-				ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_DRUMBATTLE]->val2);
-			} else if(tstatus->size == SZ_MEDIUM)
-				ATK_ADD(wd.equipAtk, wd.equipAtk2, 10 * sc->data[SC_DRUMBATTLE]->val1);
-		}
-		if(sc->data[SC_MADNESSCANCEL])
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, 100);
-		if(sc->data[SC_GATLINGFEVER]) {
-			if(tstatus->size == SZ_SMALL) {
-				ATK_ADD(wd.equipAtk, wd.equipAtk2, 10 * sc->data[SC_GATLINGFEVER]->val1);
-			} else if(tstatus->size == SZ_MEDIUM) {
-				ATK_ADD(wd.equipAtk, wd.equipAtk2, 5 * sc->data[SC_GATLINGFEVER]->val1);
-			} else if(tstatus->size == SZ_BIG)
-				ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_GATLINGFEVER]->val1);
-		}
-#endif
 #ifndef RENEWAL
 #ifndef RENEWAL
 		if( sc->data[SC_TRUESIGHT] )
 		if( sc->data[SC_TRUESIGHT] )
 			ATK_ADDRATE(wd.damage, wd.damage2, 2*sc->data[SC_TRUESIGHT]->val1);
 			ATK_ADDRATE(wd.damage, wd.damage2, 2*sc->data[SC_TRUESIGHT]->val1);
 #endif
 #endif
+		if( sc->data[SC_GLOOMYDAY_SK] &&
+		( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR ||
+		  skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ||
+		  skill_id == RK_HUNDREDSPEAR || skill_id == LG_SHIELDPRESS ) ) {
+			ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_GLOOMYDAY_SK]->val2);
+#ifdef RENEWAL
+			ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, sc->data[SC_GLOOMYDAY_SK]->val2);
+#endif
+		}
 		if (sc->data[SC_SPIRIT]) {
 		if (sc->data[SC_SPIRIT]) {
 			if(skill_id == AS_SONICBLOW && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN){
 			if(skill_id == AS_SONICBLOW && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN){
 				ATK_ADDRATE(wd.damage, wd.damage2, map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe
 				ATK_ADDRATE(wd.damage, wd.damage2, map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe
@@ -4073,93 +4077,7 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s
 #endif
 #endif
 			}
 			}
 		}
 		}
-		if(sc->data[SC_FIGHTINGSPIRIT]) {
-			ATK_ADD(wd.damage, wd.damage2, sc->data[SC_FIGHTINGSPIRIT]->val1);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_FIGHTINGSPIRIT]->val1);
-#endif
-		}
-		if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) {
-			ATK_ADD(wd.damage, wd.damage2, sc->data[SC_SHIELDSPELL_DEF]->val2);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_SHIELDSPELL_DEF]->val2);
-#endif
-		}
-		if(sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1) {
-			ATK_ADD(wd.damage, wd.damage2, (10 + 10 * sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, (10 + 10 * sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2);
-#endif
-		}
-		if(sc->data[SC_INSPIRATION]) {
-			ATK_ADD(wd.damage, wd.damage2, 40 * sc->data[SC_INSPIRATION]->val1 + 3 * sc->data[SC_INSPIRATION]->val2);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, 40 * sc->data[SC_INSPIRATION]->val1 + 3 * sc->data[SC_INSPIRATION]->val2);
-#endif
-		}
-		if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val2) {
-			struct block_list *bl; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5]
 
 
-			if( (bl = map_id2bl(sc->data[SC_GT_CHANGE]->val2)) ) {
-				ATK_ADD(wd.damage, wd.damage2, ( status_get_dex(bl)/4 + status_get_str(bl)/2 ) * sc->data[SC_GT_CHANGE]->val1 / 5 );
-#ifdef RENEWAL
-				ATK_ADD(wd.equipAtk, wd.equipAtk2, (status_get_dex(bl) / 4 + status_get_str(bl) / 2) * sc->data[SC_GT_CHANGE]->val1 / 5);
-#endif
-			}
-		}
-		if(sc->data[SC_PYROTECHNIC_OPTION]) {
-			ATK_ADD(wd.damage, wd.damage2, sc->data[SC_PYROTECHNIC_OPTION]->val2);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_PYROTECHNIC_OPTION]->val2);
-#endif
-		}
-		if(sc->data[SC_HEATER_OPTION]) {
-			ATK_ADD(wd.damage, wd.damage2, sc->data[SC_HEATER_OPTION]->val2);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_HEATER_OPTION]->val2);
-#endif
-		}
-		if(sc->data[SC_TROPIC_OPTION]) {
-			ATK_ADD(wd.damage, wd.damage2, sc->data[SC_TROPIC_OPTION]->val2);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_TROPIC_OPTION]->val2);
-#endif
-		}
-		if(sc->data[SC_GN_CARTBOOST]) {
-			ATK_ADD(wd.damage, wd.damage2, 10 * sc->data[SC_GN_CARTBOOST]->val1);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, 10 * sc->data[SC_GN_CARTBOOST]->val1);
-#endif
-		}
-		if(sc->data[SC_RUSHWINDMILL]) {
-			ATK_ADD(wd.damage, wd.damage2, sc->data[SC_RUSHWINDMILL]->val3);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_RUSHWINDMILL]->val3);
-#endif
-		}
-		if( sc->data[SC_GLOOMYDAY_SK] &&
-		( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR ||
-		  skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ||
-		  skill_id == RK_HUNDREDSPEAR || skill_id == LG_SHIELDPRESS ) ) {
-			ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_GLOOMYDAY_SK]->val2);
-			RE_ALLATK_ADDRATE(wd, sc->data[SC_GLOOMYDAY_SK]->val2);
-		}
-		if( sc->data[SC_DANCEWITHWUG] ) {
-			ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_DANCEWITHWUG]->val1 * 2 * chorusbonus);
-#ifdef RENEWAL
-			ATK_ADDRATE(wd.equipAtk, wd.equipAtk2, sc->data[SC_DANCEWITHWUG]->val1 * 2 * chorusbonus);
-#endif
-			if( skill_id == RA_WUGSTRIKE || skill_id == RA_WUGBITE || skill_id == RA_WUGDASH ) {
-				ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_DANCEWITHWUG]->val1 * 10 * chorusbonus);
-				RE_ALLATK_ADDRATE(wd, sc->data[SC_DANCEWITHWUG]->val1 * 10 * chorusbonus);
-			}
-		}
-		if(sc->data[SC_SATURDAYNIGHTFEVER]) {
-			ATK_ADD(wd.damage, wd.damage2, 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1);
-#ifdef RENEWAL
-			ATK_ADD(wd.equipAtk, wd.equipAtk2, 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1);
-#endif
-		}
 		if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2) {
 		if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2) {
 			ATK_ADD(wd.damage, wd.damage2, 200);
 			ATK_ADD(wd.damage, wd.damage2, 200);
 #ifdef RENEWAL
 #ifdef RENEWAL
@@ -4606,9 +4524,10 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl
 			((TBL_PC *)src)->status.weapon == W_2HSWORD
 			((TBL_PC *)src)->status.weapon == W_2HSWORD
 		)) &&
 		)) &&
 		rnd()%100 < tsc->data[SC_REJECTSWORD]->val2
 		rnd()%100 < tsc->data[SC_REJECTSWORD]->val2
-		) {
+		)
+	{
 		ATK_RATER(wd.damage, 50)
 		ATK_RATER(wd.damage, 50)
-		status_fix_damage(target,src,wd.damage,clif_damage(target,src,gettick(),0,0,wd.damage,0,0,0));
+		status_fix_damage(target,src,wd.damage,clif_damage(target,src,gettick(),0,0,wd.damage,0,DMG_NORMAL,0));
 		clif_skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1);
 		clif_skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1);
 		if( --(tsc->data[SC_REJECTSWORD]->val3) <= 0 )
 		if( --(tsc->data[SC_REJECTSWORD]->val3) <= 0 )
 			status_change_end(target, SC_REJECTSWORD, INVALID_TIMER);
 			status_change_end(target, SC_REJECTSWORD, INVALID_TIMER);
@@ -4624,7 +4543,7 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl
 		skill_blown(target, src, skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0);
 		skill_blown(target, src, skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0);
 		clif_skill_damage(target, src, gettick(), status_get_amotion(src), 0, rdamage,
 		clif_skill_damage(target, src, gettick(), status_get_amotion(src), 0, rdamage,
 			1, SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does
 			1, SR_CRESCENTELBOW_AUTOSPELL, tsc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does
-		clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, 0, 0);
+		clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, DMG_NORMAL, 0);
 		status_damage(target, src, rdamage, 0, 0, 0);
 		status_damage(target, src, rdamage, 0, 0, 0);
 		status_damage(src, target, rdamage/10, 0, 0, 1);
 		status_damage(src, target, rdamage/10, 0, 0, 1);
 		status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER);
 		status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER);
@@ -4697,14 +4616,14 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 	struct map_session_data *sd = BL_CAST(BL_PC, src);
 	struct map_session_data *sd = BL_CAST(BL_PC, src);
 	struct Damage wd;
 	struct Damage wd;
 
 
-	wd.type=0; //Normal attack
-	wd.div_=skill_id?skill_get_num(skill_id,skill_lv):1;
-	wd.amotion=(skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
+	wd.type = DMG_NORMAL; //Normal attack
+	wd.div_ = skill_id?skill_get_num(skill_id,skill_lv):1;
+	wd.amotion = (skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
 	// counter attack DOES obey ASPD delay on official, uncomment if you want the old (bad) behavior [helvetica]
 	// counter attack DOES obey ASPD delay on official, uncomment if you want the old (bad) behavior [helvetica]
 	/*if(skill_id == KN_AUTOCOUNTER)
 	/*if(skill_id == KN_AUTOCOUNTER)
 		wd.amotion >>= 1; */
 		wd.amotion >>= 1; */
-	wd.dmotion=tstatus->dmotion;
-	wd.blewcount=skill_get_blewcount(skill_id,skill_lv);
+	wd.dmotion = tstatus->dmotion;
+	wd.blewcount =skill_get_blewcount(skill_id,skill_lv);
 	wd.miscflag = wflag;
 	wd.miscflag = wflag;
 	wd.flag = BF_WEAPON; //Initial Flag
 	wd.flag = BF_WEAPON; //Initial Flag
 	wd.flag |= (skill_id||wd.miscflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
 	wd.flag |= (skill_id||wd.miscflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
@@ -4745,7 +4664,7 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 
 
 			case TF_DOUBLE: //For NPC used skill.
 			case TF_DOUBLE: //For NPC used skill.
 			case GS_CHAINACTION:
 			case GS_CHAINACTION:
-				wd.type = 0x08;
+				wd.type = DMG_MULTI_HIT;
 				break;
 				break;
 
 
 			case GS_GROUNDDRIFT:
 			case GS_GROUNDDRIFT:
@@ -4754,14 +4673,14 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 			case MS_BOWLINGBASH:
 			case MS_BOWLINGBASH:
 			case MO_BALKYOUNG:
 			case MO_BALKYOUNG:
 			case TK_TURNKICK:
 			case TK_TURNKICK:
-				wd.blewcount=0;
+				wd.blewcount = 0;
 				break;
 				break;
 
 
 			case KN_AUTOCOUNTER:
 			case KN_AUTOCOUNTER:
-				wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL;
+				wd.flag = (wd.flag&~BF_SKILLMASK)|BF_NORMAL;
 				break;
 				break;
 			case LK_SPIRALPIERCE:
 			case LK_SPIRALPIERCE:
-				if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC;
+				if (!sd) wd.flag = (wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC;
 				break;
 				break;
 
 
 			// The number of hits is set to 3 by default for use in Inspiration status.
 			// The number of hits is set to 3 by default for use in Inspiration status.
@@ -4784,7 +4703,7 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
  * @param wd : weapon damage
  * @param wd : weapon damage
  * @param src : bl who did the attack
  * @param src : bl who did the attack
  * @param target : target of the attack
  * @param target : target of the attack
- * @parem skill_id : id of casted skill, 0 = basic atk
+ * @param skill_id : id of casted skill, 0 = basic atk
  * @param skill_lv : lvl of skill casted
  * @param skill_lv : lvl of skill casted
  */
  */
 void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv){
 void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* src, struct block_list* target, uint16 skill_id, uint16 skill_lv){
@@ -4810,8 +4729,9 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr
 				if (ssc && ssc->data[SC_DEVOTION] && (d_bl = map_id2bl(ssc->data[SC_DEVOTION]->val1)))
 				if (ssc && ssc->data[SC_DEVOTION] && (d_bl = map_id2bl(ssc->data[SC_DEVOTION]->val1)))
 					isDevotRdamage = true;
 					isDevotRdamage = true;
 			}
 			}
-			rdelay = clif_damage(src, (!isDevotRdamage) ? src : d_bl, tick, wd->amotion, sstatus->dmotion, rdamage, 1, 4, 0);
-			if( tsd ) battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_);
+			rdelay = clif_damage(src, (!isDevotRdamage) ? src : d_bl, tick, wd->amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0);
+			if( tsd )
+				battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_);
 			//Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
 			//Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
 			battle_delay_damage(tick, wd->amotion,target,(!isDevotRdamage) ? src : d_bl,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
 			battle_delay_damage(tick, wd->amotion,target,(!isDevotRdamage) ? src : d_bl,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
 			skill_additional_effect(target, (!isDevotRdamage) ? src : d_bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
 			skill_additional_effect(target, (!isDevotRdamage) ? src : d_bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
@@ -4830,11 +4750,12 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr
 					if (ssc && ssc->data[SC_DEVOTION] && (d_bl = map_id2bl(ssc->data[SC_DEVOTION]->val1)))
 					if (ssc && ssc->data[SC_DEVOTION] && (d_bl = map_id2bl(ssc->data[SC_DEVOTION]->val1)))
 						isDevotRdamage = true;
 						isDevotRdamage = true;
 				}
 				}
-				if(attack_type == BF_WEAPON && tsc->data[SC_REFLECTDAMAGE] ) // Don't reflect your own damage (Grand Cross)
+				if( attack_type == BF_WEAPON && tsc->data[SC_REFLECTDAMAGE] ) // Don't reflect your own damage (Grand Cross)
 					map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd->amotion,sstatus->dmotion,rdamage,tstatus->race);
 					map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd->amotion,sstatus->dmotion,rdamage,tstatus->race);
-				else if(attack_type == BF_WEAPON || attack_type == BF_MISC) {
-					rdelay = clif_damage(src, (!isDevotRdamage) ? src : d_bl, tick, wd->amotion, sstatus->dmotion, rdamage, 1, 4, 0);
-					if( tsd ) battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_);
+				else if( attack_type == BF_WEAPON || attack_type == BF_MISC) {
+					rdelay = clif_damage(src, (!isDevotRdamage) ? src : d_bl, tick, wd->amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0);
+					if( tsd )
+						battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_);
 					// It appears that official servers give skill reflect damage a longer delay
 					// It appears that official servers give skill reflect damage a longer delay
 					battle_delay_damage(tick, wd->amotion,target,(!isDevotRdamage) ? src : d_bl,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
 					battle_delay_damage(tick, wd->amotion,target,(!isDevotRdamage) ? src : d_bl,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true);
 					skill_additional_effect(target, (!isDevotRdamage) ? src : d_bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
 					skill_additional_effect(target, (!isDevotRdamage) ? src : d_bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
@@ -4883,7 +4804,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 
 
 	//Check for Lucky Dodge
 	//Check for Lucky Dodge
 	if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) {
 	if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) {
-		wd.type = 0x0b;
+		wd.type = DMG_LUCY_DODGE;
 		wd.dmg_lv = ATK_LUCKY;
 		wd.dmg_lv = ATK_LUCKY;
 		if(wd.div_ < 0)
 		if(wd.div_ < 0)
 			wd.div_ *= -1;
 			wd.div_ *= -1;
@@ -4895,7 +4816,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 
 
 	// crit check is next since crits always hit on official [helvetica]
 	// crit check is next since crits always hit on official [helvetica]
 	if (is_attack_critical(wd, src, target, skill_id, skill_lv, true))
 	if (is_attack_critical(wd, src, target, skill_id, skill_lv, true))
-		wd.type = 0x0a;
+		wd.type = DMG_CRITICAL;
 
 
 	// check if we're landing a hit
 	// check if we're landing a hit
 	if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true))
 	if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true))
@@ -4941,7 +4862,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 		}
 		}
 
 
 		// final attack bonuses that aren't affected by cards
 		// final attack bonuses that aren't affected by cards
-		wd = battle_attack_sc_bonus(wd, src, target, skill_id);
+		wd = battle_attack_sc_bonus(wd, src, skill_id);
 
 
 		if (sd) { //monsters, homuns and pets have their damage computed directly
 		if (sd) { //monsters, homuns and pets have their damage computed directly
 			wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.masteryAtk;
 			wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.masteryAtk;
@@ -4953,7 +4874,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 		}
 		}
 #else
 #else
 		// final attack bonuses that aren't affected by cards
 		// final attack bonuses that aren't affected by cards
-		wd = battle_attack_sc_bonus(wd, src, target, skill_id);
+		wd = battle_attack_sc_bonus(wd, src, skill_id);
 #endif
 #endif
 
 
 		if (wd.damage + wd.damage2) { //Check if attack ignores DEF
 		if (wd.damage + wd.damage2) { //Check if attack ignores DEF
@@ -5401,7 +5322,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 							skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val1 * 50) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech]
 							skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val1 * 50) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech]
 							ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax]
 							ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax]
 							ad.flag = BF_WEAPON|BF_SHORT;
 							ad.flag = BF_WEAPON|BF_SHORT;
-							ad.type = 0;
+							ad.type = DMG_NORMAL;
 						}
 						}
 						break;
 						break;
 					case MG_THUNDERSTORM:
 					case MG_THUNDERSTORM:
@@ -5945,7 +5866,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 		MATK_ADDRATE(skill_damage);
 		MATK_ADDRATE(skill_damage);
 #endif
 #endif
 
 
-	//battle_do_reflect(BF_MAGIC,&ad, src, target, skill_id, skill_lv); //WIP [lighta]
+	//battle_do_reflect(BF_MAGIC,&ad, src, target, skill_id, skill_lv); //WIP [lighta] Magic skill has own handler at skill_attack
 	return ad;
 	return ad;
 }
 }
 
 
@@ -6336,7 +6257,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 	if(tstatus->mode&MD_IGNOREMISC && md.flag&(BF_MISC) )	//misc @TODO optimize me
 	if(tstatus->mode&MD_IGNOREMISC && md.flag&(BF_MISC) )	//misc @TODO optimize me
 		md.damage = md.damage2 = 1;
 		md.damage = md.damage2 = 1;
 
 
-	//battle_do_reflect(BF_MISC,&md, src, target, skill_id, skill_lv); //WIP [lighta]
+	battle_do_reflect(BF_MISC,&md, src, target, skill_id, skill_lv); //WIP [lighta]
 
 
 	return md;
 	return md;
 }
 }
@@ -6385,10 +6306,11 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i
 	struct map_session_data* sd;
 	struct map_session_data* sd;
 	int64 rdamage = 0, damage = *dmg;
 	int64 rdamage = 0, damage = *dmg;
 	int max_damage = status_get_max_hp(bl);
 	int max_damage = status_get_max_hp(bl);
-	struct status_change* sc;
+	struct status_change *sc, *ssc;
 
 
 	sd = BL_CAST(BL_PC, bl);
 	sd = BL_CAST(BL_PC, bl);
 	sc = status_get_sc(bl);
 	sc = status_get_sc(bl);
+	ssc = status_get_sc(src);
 
 
 	if (flag & BF_SHORT) {//Bounces back part of the damage.
 	if (flag & BF_SHORT) {//Bounces back part of the damage.
 		if ( !status_reflect && sd && sd->bonus.short_weapon_damage_return ) {
 		if ( !status_reflect && sd && sd->bonus.short_weapon_damage_return ) {
@@ -6435,6 +6357,16 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i
 		}
 		}
 	}
 	}
 
 
+	if (ssc && ssc->data[SC_INSPIRATION]) {
+		rdamage += damage / 100;
+#ifdef RENEWAL
+		rdamage = cap_value(rdamage, 1, max_damage);
+#else
+		if( rdamage < 1 )
+			rdamage = 1;
+#endif
+	}
+
 	if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability
 	if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability
 		rdamage = 0;
 		rdamage = 0;
 
 
@@ -6449,6 +6381,9 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama
 	struct weapon_data *wd;
 	struct weapon_data *wd;
 	int64 *damage;
 	int64 *damage;
 	int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp=0, sp=0, i;
 	int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp=0, sp=0, i;
+	if (!CHK_RACE(race) && !CHK_CLASS(class_))
+		return;
+
 	for (i = 0; i < 4; i++) {
 	for (i = 0; i < 4; i++) {
 		//First two iterations: Right hand
 		//First two iterations: Right hand
 		if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
 		if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
@@ -6565,7 +6500,7 @@ int battle_damage_area( struct block_list *bl, va_list ap) {
 			battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true);
 			battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true);
 		else
 		else
 			status_fix_damage(src,bl,damage,0);
 			status_fix_damage(src,bl,damage,0);
-		clif_damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0);
+		clif_damage(bl,bl,tick,amotion,dmotion,damage,1,DMG_ENDURE,0);
 		skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
 		skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
 		map_freeblock_unlock();
 		map_freeblock_unlock();
 	}
 	}
@@ -6608,35 +6543,36 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
 		sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
 		if (sd->state.arrow_atk)
 		if (sd->state.arrow_atk)
 		{
 		{
-			int index = sd->equip_index[EQI_AMMO];
-			if (index<0) {
+			short index = sd->equip_index[EQI_AMMO];
+			if (index < 0) {
 				clif_arrow_fail(sd,0);
 				clif_arrow_fail(sd,0);
 				return ATK_NONE;
 				return ATK_NONE;
 			}
 			}
 			//Ammo check by Ishizu-chan
 			//Ammo check by Ishizu-chan
-			if (sd->inventory_data[index])
-			switch (sd->status.weapon) {
-			case W_BOW:
-				if (sd->inventory_data[index]->look != A_ARROW) {
-					clif_arrow_fail(sd,0);
-					return ATK_NONE;
-				}
-			break;
-			case W_REVOLVER:
-			case W_RIFLE:
-			case W_GATLING:
-			case W_SHOTGUN:
-				if (sd->inventory_data[index]->look != A_BULLET) {
-					clif_arrow_fail(sd,0);
-					return ATK_NONE;
-				}
-			break;
-			case W_GRENADE:
-				if (sd->inventory_data[index]->look != A_GRENADE) {
-					clif_arrow_fail(sd,0);
-					return ATK_NONE;
+			if (sd->inventory_data[index]) {
+				switch (sd->status.weapon) {
+					case W_BOW:
+						if (sd->inventory_data[index]->look != A_ARROW) {
+							clif_arrow_fail(sd,0);
+							return ATK_NONE;
+						}
+						break;
+					case W_REVOLVER:
+					case W_RIFLE:
+					case W_GATLING:
+					case W_SHOTGUN:
+						if (sd->inventory_data[index]->look != A_BULLET) {
+							clif_arrow_fail(sd,0);
+							return ATK_NONE;
+						}
+						break;
+					case W_GRENADE:
+						if (sd->inventory_data[index]->look != A_GRENADE) {
+							clif_arrow_fail(sd,0);
+							return ATK_NONE;
+						}
+						break;
 				}
 				}
-			break;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -6655,7 +6591,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 			uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1;
 			uint16 skill_lv = tsc->data[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, 0, 0); //Display MISS.
+			clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0); //Display MISS.
 			status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER);
 			status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER);
 			skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0);
 			skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0);
 			return ATK_BLOCK;
 			return ATK_BLOCK;
@@ -6669,7 +6605,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER);
 		status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER);
 		if(sc_start4(src,src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration))
 		if(sc_start4(src,src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration))
 		{	//Target locked.
 		{	//Target locked.
-			clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
+			clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, DMG_NORMAL, 0); //Display MISS.
 			clif_bladestop(target, src->id, 1);
 			clif_bladestop(target, src->id, 1);
 			sc_start4(src,target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration);
 			sc_start4(src,target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration);
 			return ATK_BLOCK;
 			return ATK_BLOCK;
@@ -6755,9 +6691,12 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		if( sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rnd()%100 < sc->data[SC_GIANTGROWTH]->val2 )
 		if( sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rnd()%100 < sc->data[SC_GIANTGROWTH]->val2 )
 			wd.damage *= 3; // Triple Damage
 			wd.damage *= 3; // Triple Damage
 
 
-		if( sd && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement){
-			pc_delitem(sd,sd->equip_index[EQI_AMMO],sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME);
-			sc->data[SC_FEARBREEZE]->val4 = 0;
+		if( sd && battle_config.arrow_decrement && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0) {
+			short idx = sd->equip_index[EQI_AMMO];
+			if (idx >= 0 && sd->status.inventory[idx].amount >= sc->data[SC_FEARBREEZE]->val4) {
+				pc_delitem(sd,idx,sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME);
+				sc->data[SC_FEARBREEZE]->val4 = 0;
+			}
 		}
 		}
 	}
 	}
 	if (sd && sd->state.arrow_atk) //Consume arrow.
 	if (sd && sd->state.arrow_atk) //Consume arrow.
@@ -6777,7 +6716,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		}
 		}
 	}
 	}
 
 
-	wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
+	wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , (enum e_damage_type)wd.type, wd.damage2);
 
 
 	if (sd && sd->bonus.splash_range > 0 && damage > 0)
 	if (sd && sd->bonus.splash_range > 0 && damage > 0)
 		skill_castend_damage_id(src, target, 0, 1, tick, 0);
 		skill_castend_damage_id(src, target, 0, 1, tick, 0);
@@ -6813,7 +6752,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 				(d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id)
 				(d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id)
 				) && check_distance_bl(target, d_bl, sce->val3) )
 				) && check_distance_bl(target, d_bl, sce->val3) )
 			{
 			{
-				clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0);
+				clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0);
 				status_fix_damage(NULL, d_bl, damage, 0);
 				status_fix_damage(NULL, d_bl, damage, 0);
 			}
 			}
 			else
 			else
@@ -6829,10 +6768,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) {
 		if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) {
 			struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1);
 			struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1);
 			if( e_bl && !status_isdead(e_bl) ) {
 			if( e_bl && !status_isdead(e_bl) ) {
-				clif_damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2);
+				clif_damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,(enum e_damage_type)wd.type,wd.damage2);
 				status_damage(target,e_bl,damage,0,0,0);
 				status_damage(target,e_bl,damage,0,0,0);
 				// Just show damage in target.
 				// Just show damage in target.
-				clif_damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 );
+				clif_damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, (enum e_damage_type)wd.type, wd.damage2 );
 				map_freeblock_unlock();
 				map_freeblock_unlock();
 				return ATK_BLOCK;
 				return ATK_BLOCK;
 			}
 			}
@@ -7821,8 +7760,10 @@ static const struct _battle_data {
 	{ "update_enemy_position",				&battle_config.update_enemy_position,			0,		0,		1,				},
 	{ "update_enemy_position",				&battle_config.update_enemy_position,			0,		0,		1,				},
 	{ "devotion_rdamage",					&battle_config.devotion_rdamage,				0,		0,		100,			},
 	{ "devotion_rdamage",					&battle_config.devotion_rdamage,				0,		0,		100,			},
 	{ "feature.autotrade",					&battle_config.feature_autotrade,				1,		0,		1,				},
 	{ "feature.autotrade",					&battle_config.feature_autotrade,				1,		0,		1,				},
-	{ "feature.autotrade_direction",		&battle_config.feature_autotrade_direction,		4,		0,		7,				},
-	{ "feature.autotrade_sit",				&battle_config.feature_autotrade_sit,			1,		0,		1,				},
+	{ "feature.autotrade_direction",		&battle_config.feature_autotrade_direction,		4,		-1,		7,				},
+	{ "feature.autotrade_head_direction",	&battle_config.feature_autotrade_head_direction,0,		-1,		2,				},
+	{ "feature.autotrade_sit",				&battle_config.feature_autotrade_sit,			1,		-1,		1,				},
+	{ "feature.autotrade_open_delay",		&battle_config.feature_autotrade_open_delay,	5000,	1000,	INT_MAX,		},
 	{ "disp_serverbank_msg",				&battle_config.disp_serverbank_msg,				0,		0,		1,				},
 	{ "disp_serverbank_msg",				&battle_config.disp_serverbank_msg,				0,		0,		1,				},
 	{ "warg_can_falcon",                    &battle_config.warg_can_falcon,                 0,      0,      1,              },
 	{ "warg_can_falcon",                    &battle_config.warg_can_falcon,                 0,      0,      1,              },
 	{ "path_blown_halt",                    &battle_config.path_blown_halt,                 1,      0,      1,              },
 	{ "path_blown_halt",                    &battle_config.path_blown_halt,                 1,      0,      1,              },
@@ -7846,6 +7787,8 @@ static const struct _battle_data {
 	{ "fame_pharmacy_7",                    &battle_config.fame_pharmacy_7,                 10,     0,      INT_MAX,        },
 	{ "fame_pharmacy_7",                    &battle_config.fame_pharmacy_7,                 10,     0,      INT_MAX,        },
 	{ "fame_pharmacy_10",                   &battle_config.fame_pharmacy_10,                50,     0,      INT_MAX,        },
 	{ "fame_pharmacy_10",                   &battle_config.fame_pharmacy_10,                50,     0,      INT_MAX,        },
 	{ "mail_delay",                         &battle_config.mail_delay,                      1000,   1000,   INT_MAX,        },
 	{ "mail_delay",                         &battle_config.mail_delay,                      1000,   1000,   INT_MAX,        },
+	{ "at_monsterignore",                   &battle_config.autotrade_monsterignore,         0,      0,      1,              },
+	{ "idletime_option",                    &battle_config.idletime_option,                 0x25,   1,      INT_MAX,        },
 };
 };
 #ifndef STATS_OPT_OUT
 #ifndef STATS_OPT_OUT
 /**
 /**

+ 6 - 2
src/map/battle.h

@@ -60,8 +60,8 @@ struct Damage {
 #endif
 #endif
 	int64 damage, /// Right hand damage
 	int64 damage, /// Right hand damage
 		damage2; /// Left hand damage
 		damage2; /// Left hand damage
-	int type, /// chk clif_damage for type @TODO add an enum ?
-		div_; /// Number of hit
+	char type; /// chk clif_damage for type (clif.h enum e_damage_type)
+	short div_; /// Number of hit
 	int amotion,
 	int amotion,
 		dmotion;
 		dmotion;
 	int blewcount; /// Number of knockback
 	int blewcount; /// Number of knockback
@@ -536,7 +536,9 @@ extern struct Battle_Config
 	// autotrade persistency
 	// autotrade persistency
 	int feature_autotrade;
 	int feature_autotrade;
 	int feature_autotrade_direction;
 	int feature_autotrade_direction;
+	int feature_autotrade_head_direction;
 	int feature_autotrade_sit;
 	int feature_autotrade_sit;
+	int feature_autotrade_open_delay;
 
 
 	// Fame points
 	// Fame points
 	int fame_taekwon_mission;
 	int fame_taekwon_mission;
@@ -562,6 +564,8 @@ extern struct Battle_Config
 	int taekwon_ranker_min_lv;
 	int taekwon_ranker_min_lv;
 	int revive_onwarp;
 	int revive_onwarp;
 	int mail_delay;
 	int mail_delay;
+	int autotrade_monsterignore;
+	int idletime_option;
 } battle_config;
 } battle_config;
 
 
 void do_init_battle(void);
 void do_init_battle(void);

+ 167 - 76
src/map/buyingstore.c

@@ -1,6 +1,7 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 // For more information, see LICENCE in the main folder
 
 
+#include "../common/nullpo.h"
 #include "../common/cbasetypes.h"
 #include "../common/cbasetypes.h"
 #include "../common/db.h"  // ARR_FIND
 #include "../common/db.h"  // ARR_FIND
 #include "../common/malloc.h" // aMalloc, aFree
 #include "../common/malloc.h" // aMalloc, aFree
@@ -31,7 +32,7 @@ struct s_autotrade {
 	int buyer_id;
 	int buyer_id;
 	int m;
 	int m;
 	uint16 x, y;
 	uint16 x, y;
-	unsigned char sex;
+	unsigned char sex, dir, head_dir, sit;
 	char title[MESSAGE_SIZE];
 	char title[MESSAGE_SIZE];
 	int limit;
 	int limit;
 	uint16 count;
 	uint16 count;
@@ -41,13 +42,18 @@ struct s_autotrade {
 
 
 //Autotrader
 //Autotrader
 static struct s_autotrade **autotraders; ///Autotraders Storage
 static struct s_autotrade **autotraders; ///Autotraders Storage
-static uint16 autotrader_count; ///Autotrader count
+static uint16 autotrader_count, autotrader_loaded_count; ///Autotrader count
 static void do_final_buyingstore_autotrade(void);
 static void do_final_buyingstore_autotrade(void);
 
 
 /// constants (client-side restrictions)
 /// constants (client-side restrictions)
 #define BUYINGSTORE_MAX_PRICE 99990000
 #define BUYINGSTORE_MAX_PRICE 99990000
 #define BUYINGSTORE_MAX_AMOUNT 9999
 #define BUYINGSTORE_MAX_AMOUNT 9999
 
 
+static DBMap *buyingstore_db;
+
+DBMap *buyingstore_getdb(void) {
+	return buyingstore_db;
+}
 
 
 /// failure constants for clif functions
 /// failure constants for clif functions
 enum e_buyingstore_failure
 enum e_buyingstore_failure
@@ -73,27 +79,34 @@ static unsigned int buyingstore_getuid(void)
 	return ++buyingstore_nextid;
 	return ++buyingstore_nextid;
 }
 }
 
 
+/**
+* Attempt to setup buying store fast check before create new one
+* @param sd
+* @param slots Number of item on the list
+* @return 0 If success, 1 - Cannot open, 2 - Manner penalty, 3 - Mapflag restiction, 4 - Cell restriction
+*/
+char buyingstore_setup(struct map_session_data* sd, unsigned char slots){
+	nullpo_retr(1, sd);
 
 
-bool buyingstore_setup(struct map_session_data* sd, unsigned char slots){
 	if (!battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0) {
 	if (!battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0) {
-		return false;
+		return 1;
 	}
 	}
 
 
 	if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
 	if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
 	{// custom: mute limitation
 	{// custom: mute limitation
-		return false;
+		return 2;
 	}
 	}
 
 
 	if( map[sd->bl.m].flag.novending )
 	if( map[sd->bl.m].flag.novending )
 	{// custom: no vending maps
 	{// custom: no vending maps
 		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
 		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
-		return false;
+		return 3;
 	}
 	}
 
 
 	if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
 	if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
 	{// custom: no vending cells
 	{// custom: no vending cells
 		clif_displaymessage(sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
 		clif_displaymessage(sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
-		return false;
+		return 4;
 	}
 	}
 
 
 	if( slots > MAX_BUYINGSTORE_SLOTS )
 	if( slots > MAX_BUYINGSTORE_SLOTS )
@@ -105,25 +118,36 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots){
 	sd->buyingstore.slots = slots;
 	sd->buyingstore.slots = slots;
 	clif_buyingstore_open(sd);
 	clif_buyingstore_open(sd);
 
 
-	return true;
+	return 0;
 }
 }
 
 
-
-bool buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
+/**
+* Attempt to create new buying store
+* @param sd
+* @param zenylimit
+* @param result
+* @param storename
+* @param *itemlist { <nameid>.W, <amount>.W, <price>.L }*
+* @param count Number of item on the itemlist
+* @return 0 If success, 1 - Cannot open, 2 - Manner penalty, 3 - Mapflag restiction, 4 - Cell restriction, 5 - Invalid count/result, 6 - Cannot give item, 7 - Will be overweight
+*/
+char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count)
 {
 {
 	unsigned int i, weight, listidx;
 	unsigned int i, weight, listidx;
 	char message_sql[MESSAGE_SIZE*2];
 	char message_sql[MESSAGE_SIZE*2];
 
 
+	nullpo_retr(1, sd);
+
 	if( !result || count == 0 )
 	if( !result || count == 0 )
 	{// canceled, or no items
 	{// canceled, or no items
-		return false;
+		return 5;
 	}
 	}
 
 
 	if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
 	if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] )
 	{// disabled or invalid input
 	{// disabled or invalid input
 		sd->buyingstore.slots = 0;
 		sd->buyingstore.slots = 0;
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
-		return false;
+		return 1;
 	}
 	}
 
 
 	if( !pc_can_give_items(sd) )
 	if( !pc_can_give_items(sd) )
@@ -131,24 +155,24 @@ bool buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 		sd->buyingstore.slots = 0;
 		sd->buyingstore.slots = 0;
 		clif_displaymessage(sd->fd, msg_txt(sd,246));
 		clif_displaymessage(sd->fd, msg_txt(sd,246));
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
-		return false;
+		return 6;
 	}
 	}
 
 
 	if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
 	if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) )
 	{// custom: mute limitation
 	{// custom: mute limitation
-		return false;
+		return 2;
 	}
 	}
 
 
 	if( map[sd->bl.m].flag.novending )
 	if( map[sd->bl.m].flag.novending )
 	{// custom: no vending maps
 	{// custom: no vending maps
 		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
 		clif_displaymessage(sd->fd, msg_txt(sd,276)); // "You can't open a shop on this map"
-		return false;
+		return 3;
 	}
 	}
 
 
 	if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
 	if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) )
 	{// custom: no vending cells
 	{// custom: no vending cells
 		clif_displaymessage(sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
 		clif_displaymessage(sd->fd, msg_txt(sd,204)); // "You can't open a shop on this cell."
-		return false;
+		return 4;
 	}
 	}
 
 
 	weight = sd->weight;
 	weight = sd->weight;
@@ -204,14 +228,14 @@ bool buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 	{// invalid item/amount/price
 	{// invalid item/amount/price
 		sd->buyingstore.slots = 0;
 		sd->buyingstore.slots = 0;
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0);
-		return false;
+		return 5;
 	}
 	}
 
 
 	if( (sd->max_weight*90)/100 < weight )
 	if( (sd->max_weight*90)/100 < weight )
 	{// not able to carry all wanted items without getting overweight (90%)
 	{// not able to carry all wanted items without getting overweight (90%)
 		sd->buyingstore.slots = 0;
 		sd->buyingstore.slots = 0;
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight);
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight);
-		return false;
+		return 7;
 	}
 	}
 
 
 	// success
 	// success
@@ -223,7 +247,9 @@ bool buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 
 
 	Sql_EscapeString( mmysql_handle, message_sql, sd->message );
 	Sql_EscapeString( mmysql_handle, message_sql, sd->message );
 
 
-	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`limit`,`autotrade`) VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, %d );", buyingstore_db, sd->buyer_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->buyingstore.zenylimit, sd->state.autotrade ) != SQL_SUCCESS ){
+	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`limit`,`autotrade`, `body_direction`, `head_direction`, `sit`) "
+		"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, %d, '%d', '%d', '%d' );",
+		buyingstores_db, sd->buyer_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->buyingstore.zenylimit, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){
 		Sql_ShowDebug(mmysql_handle);
 		Sql_ShowDebug(mmysql_handle);
 	}
 	}
 
 
@@ -235,38 +261,47 @@ bool buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
 
 
 	clif_buyingstore_myitemlist(sd);
 	clif_buyingstore_myitemlist(sd);
 	clif_buyingstore_entry(sd);
 	clif_buyingstore_entry(sd);
+	idb_put(buyingstore_db, sd->status.char_id, sd);
 
 
-	return true;
+	return 0;
 }
 }
 
 
-
-void buyingstore_close(struct map_session_data* sd)
-{
-	if( sd->state.buyingstore )
-	{
-		if( !sd->state.autotrade ){
-			if( 
-				Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE buyingstore_id = %d;", buyingstore_items_db, sd->buyer_id ) != SQL_SUCCESS ||
-				Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `id` = %d;", buyingstore_db, sd->buyer_id ) != SQL_SUCCESS
-			){
-				Sql_ShowDebug(mmysql_handle);
-			}
+/**
+* Close buying store and clear buying store data from tables
+* @param sd
+*/
+void buyingstore_close(struct map_session_data* sd) {
+	nullpo_retv(sd);
+
+	if( sd->state.buyingstore ) {
+		if( 
+			Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE buyingstore_id = %d;", buyingstore_items_db, sd->buyer_id ) != SQL_SUCCESS ||
+			Sql_Query( mmysql_handle, "DELETE FROM `%s` WHERE `id` = %d;", buyingstores_db, sd->buyer_id ) != SQL_SUCCESS
+		) {
+			Sql_ShowDebug(mmysql_handle);
 		}
 		}
 
 
-		// invalidate data
 		sd->state.buyingstore = false;
 		sd->state.buyingstore = false;
+		sd->buyer_id = 0;
 		memset(&sd->buyingstore, 0, sizeof(sd->buyingstore));
 		memset(&sd->buyingstore, 0, sizeof(sd->buyingstore));
+		idb_remove(buyingstore_db, sd->status.char_id);
 
 
 		// notify other players
 		// notify other players
 		clif_buyingstore_disappear_entry(sd);
 		clif_buyingstore_disappear_entry(sd);
 	}
 	}
 }
 }
 
 
-
+/**
+* Open buying store from buyer
+* @param sd Player
+* @param account_id Buyer account ID
+*/
 void buyingstore_open(struct map_session_data* sd, int account_id)
 void buyingstore_open(struct map_session_data* sd, int account_id)
 {
 {
 	struct map_session_data* pl_sd;
 	struct map_session_data* pl_sd;
 
 
+	nullpo_retv(sd);
+
 	if( !battle_config.feature_buying_store || pc_istrading(sd) )
 	if( !battle_config.feature_buying_store || pc_istrading(sd) )
 	{// not allowed to sell
 	{// not allowed to sell
 		return;
 		return;
@@ -292,13 +327,21 @@ void buyingstore_open(struct map_session_data* sd, int account_id)
 	clif_buyingstore_itemlist(sd, pl_sd);
 	clif_buyingstore_itemlist(sd, pl_sd);
 }
 }
 
 
-
+/**
+* Start transaction
+* @param sd Player/Seller
+* @param account_id Buyer account ID
+* @param *itemlist List of sold items { <index>.W, <nameid>.W, <amount>.W }*
+* @param count Number of item on the itemlist
+*/
 void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count)
 void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count)
 {
 {
 	int zeny = 0;
 	int zeny = 0;
 	unsigned int i, weight, listidx, k;
 	unsigned int i, weight, listidx, k;
 	struct map_session_data* pl_sd;
 	struct map_session_data* pl_sd;
 
 
+	nullpo_retv(sd);
+
 	if( count == 0 )
 	if( count == 0 )
 	{// nothing to do
 	{// nothing to do
 		return;
 		return;
@@ -461,7 +504,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
 	}
 	}
 	else
 	else
 	{// continue buying
 	{// continue buying
-		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `limit` = %d WHERE `id` = %d;", buyingstore_db, pl_sd->buyingstore.zenylimit, pl_sd->buyer_id ) != SQL_SUCCESS ){
+		if( Sql_Query( mmysql_handle, "UPDATE `%s` SET `limit` = %d WHERE `id` = %d;", buyingstores_db, pl_sd->buyingstore.zenylimit, pl_sd->buyer_id ) != SQL_SUCCESS ){
 			Sql_ShowDebug( mmysql_handle );
 			Sql_ShowDebug( mmysql_handle );
 		}
 		}
 
 
@@ -484,6 +527,8 @@ bool buyingstore_search(struct map_session_data* sd, unsigned short nameid)
 {
 {
 	unsigned int i;
 	unsigned int i;
 
 
+	nullpo_ret(sd);
+
 	if( !sd->state.buyingstore )
 	if( !sd->state.buyingstore )
 	{// not buying
 	{// not buying
 		return false;
 		return false;
@@ -506,6 +551,8 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
 	unsigned int i, idx;
 	unsigned int i, idx;
 	struct s_buyingstore_item* it;
 	struct s_buyingstore_item* it;
 
 
+	nullpo_ret(sd);
+
 	if( !sd->state.buyingstore )
 	if( !sd->state.buyingstore )
 	{// not buying
 	{// not buying
 		return true;
 		return true;
@@ -544,14 +591,17 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
 	return true;
 	return true;
 }
 }
 
 
-/** Open buyingstore for Autotrader
+/**
+* Open buyingstore for Autotrader
 * @param sd Player as autotrader
 * @param sd Player as autotrader
 */
 */
 void buyingstore_reopen( struct map_session_data* sd ){
 void buyingstore_reopen( struct map_session_data* sd ){
+	nullpo_retv(sd);
+
 	// Ready to open buyingstore for this char
 	// Ready to open buyingstore for this char
-	if ( sd && autotrader_count > 0 && autotraders){
+	if ( autotrader_count > 0 && autotraders){
 		uint16 i;
 		uint16 i;
-		uint8 *data, *p;
+		uint8 *data, *p, fail = 0;
 		uint16 j, count;
 		uint16 j, count;
 
 
 		ARR_FIND(0,autotrader_count,i,autotraders[i] && autotraders[i]->char_id == sd->status.char_id);
 		ARR_FIND(0,autotrader_count,i,autotraders[i] && autotraders[i]->char_id == sd->status.char_id);
@@ -575,28 +625,39 @@ void buyingstore_reopen( struct map_session_data* sd ){
 			p += 8;
 			p += 8;
 		}
 		}
 
 
+		// Make sure abort all NPCs
+		npc_event_dequeue(sd);
+		pc_cleareventtimer(sd);
+
 		// Open the buyingstore again
 		// Open the buyingstore again
-		if( buyingstore_setup( sd, (unsigned char)autotraders[i]->count ) &&
-			buyingstore_create( sd, autotraders[i]->limit, 1, autotraders[i]->title, data, autotraders[i]->count ) )
+		if( (fail = buyingstore_setup( sd, (unsigned char)autotraders[i]->count ) == 0) &&
+			(fail = buyingstore_create( sd, autotraders[i]->limit, 1, autotraders[i]->title, data, autotraders[i]->count ) == 0) )
 		{
 		{
-			ShowInfo("Loaded autotrade buyingstore data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items at "CL_WHITE"%s (%d,%d)"CL_RESET"\n",
-				sd->status.name,count,mapindex_id2name(sd->mapindex),sd->bl.x,sd->bl.y);
+			ShowInfo("Loaded buyingstore for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items at "CL_WHITE"%s (%d,%d)"CL_RESET"\n",
+				sd->status.name, count, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y);
 
 
 			// Set him to autotrade
 			// Set him to autotrade
-			if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;",
-				buyingstore_db, sd->buyer_id ) != SQL_SUCCESS )
+			if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1, `body_direction` = '%d', `head_direction` = '%d', `sit` = '%d' "
+				"WHERE `id` = %d;",
+				buyingstores_db, autotraders[i]->dir, autotraders[i]->head_dir, autotraders[i]->sit, sd->buyer_id ) != SQL_SUCCESS )
 			{
 			{
 				Sql_ShowDebug( mmysql_handle );
 				Sql_ShowDebug( mmysql_handle );
 			}
 			}
 
 
-			// Make him look perfect
-			unit_setdir(&sd->bl,battle_config.feature_autotrade_direction);
-
-			if( battle_config.feature_autotrade_sit )
+			// Make buyer look perfect
+			pc_setdir(sd, autotraders[i]->dir, autotraders[i]->head_dir);
+			clif_changed_dir(&sd->bl, AREA_WOS);
+			if( autotraders[i]->sit ) {
 				pc_setsit(sd);
 				pc_setsit(sd);
+				skill_sit(sd, 1);
+				clif_sitting(&sd->bl);
+			}
+
+			// Immediate save
+			chrif_save(sd, 3);
 		}else{
 		}else{
 			// Failed to open the buyingstore, set him offline
 			// Failed to open the buyingstore, set him offline
-			ShowWarning("Failed to load autotrade buyingstore data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items\n", sd->status.name, count );
+			ShowError("Failed (%d) to load autotrade buyingstore data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items\n", fail, sd->status.name, count );
 
 
 			map_quit( sd );
 			map_quit( sd );
 		}
 		}
@@ -604,7 +665,7 @@ void buyingstore_reopen( struct map_session_data* sd ){
 		aFree(data);
 		aFree(data);
 
 
 		//If the last autotrade is loaded, clear autotraders [Cydh]
 		//If the last autotrade is loaded, clear autotraders [Cydh]
-		if (i+1 >= autotrader_count)
+		if (++autotrader_loaded_count >= autotrader_count)
 			do_final_buyingstore_autotrade();
 			do_final_buyingstore_autotrade();
 	}
 	}
 }
 }
@@ -615,21 +676,22 @@ void buyingstore_reopen( struct map_session_data* sd ){
 void do_init_buyingstore_autotrade( void ) {
 void do_init_buyingstore_autotrade( void ) {
 	if(battle_config.feature_autotrade) {
 	if(battle_config.feature_autotrade) {
 		uint16 i, items = 0;
 		uint16 i, items = 0;
-		autotrader_count = 0;
+		autotrader_count = autotrader_loaded_count = 0;
 
 
 		// Get autotrader from table. `map`, `x`, and `y`, aren't used here
 		// Get autotrader from table. `map`, `x`, and `y`, aren't used here
 		// Just read player that has data at buyingstore_items [Cydh]
 		// Just read player that has data at buyingstore_items [Cydh]
 		if (Sql_Query(mmysql_handle,
 		if (Sql_Query(mmysql_handle,
-			"SELECT `id`, `account_id`, `char_id`, `sex`, `title`, `limit` "
+			"SELECT `id`, `account_id`, `char_id`, `sex`, `title`, `limit`, `body_direction`, `head_direction`, `sit` "
 			"FROM `%s` "
 			"FROM `%s` "
-			"WHERE `autotrade` = 1 AND `limit` > 0 AND (SELECT COUNT(`buyingstore_id`) FROM `%s` WHERE `buyingstore_id` = `id`) > 0;",
-			buyingstore_db, buyingstore_items_db ) != SQL_SUCCESS )
+			"WHERE `autotrade` = 1 AND `limit` > 0 AND (SELECT COUNT(`buyingstore_id`) FROM `%s` WHERE `buyingstore_id` = `id`) > 0 "
+			"ORDER BY `id`;",
+			buyingstores_db, buyingstore_items_db ) != SQL_SUCCESS )
 		{
 		{
 			Sql_ShowDebug(mmysql_handle);
 			Sql_ShowDebug(mmysql_handle);
 			return;
 			return;
 		}
 		}
 
 
-		if( (autotrader_count = (uint32)Sql_NumRows(mmysql_handle)) > 0 ){
+		if( (autotrader_count = (uint16)Sql_NumRows(mmysql_handle)) > 0 ){
 			// Init autotraders
 			// Init autotraders
 			CREATE(autotraders, struct s_autotrade *, autotrader_count);
 			CREATE(autotraders, struct s_autotrade *, autotrader_count);
 
 
@@ -644,48 +706,59 @@ void do_init_buyingstore_autotrade( void ) {
 			while (SQL_SUCCESS == Sql_NextRow(mmysql_handle) && i < autotrader_count) {
 			while (SQL_SUCCESS == Sql_NextRow(mmysql_handle) && i < autotrader_count) {
 				size_t len;
 				size_t len;
 				char* data;
 				char* data;
+				struct s_autotrade *at = NULL;
 
 
 				CREATE(autotraders[i], struct s_autotrade, 1);
 				CREATE(autotraders[i], struct s_autotrade, 1);
+				at = autotraders[i];
 
 
-				Sql_GetData(mmysql_handle, 0, &data, NULL); autotraders[i]->buyer_id = atoi(data);
-				Sql_GetData(mmysql_handle, 1, &data, NULL); autotraders[i]->account_id = atoi(data);
-				Sql_GetData(mmysql_handle, 2, &data, NULL); autotraders[i]->char_id = atoi(data);
-				Sql_GetData(mmysql_handle, 3, &data, NULL); autotraders[i]->sex = (data[0] == 'F') ? 0 : 1;
-				Sql_GetData(mmysql_handle, 4, &data, &len); safestrncpy(autotraders[i]->title, data, min(len + 1, MESSAGE_SIZE));
-				Sql_GetData(mmysql_handle, 5, &data, NULL); autotraders[i]->limit = atoi(data);
-				autotraders[i]->count = 0;
+				Sql_GetData(mmysql_handle, 0, &data, NULL); at->buyer_id = atoi(data);
+				Sql_GetData(mmysql_handle, 1, &data, NULL); at->account_id = atoi(data);
+				Sql_GetData(mmysql_handle, 2, &data, NULL); at->char_id = atoi(data);
+				Sql_GetData(mmysql_handle, 3, &data, NULL); at->sex = (data[0] == 'F') ? 0 : 1;
+				Sql_GetData(mmysql_handle, 4, &data, &len); safestrncpy(at->title, data, min(len + 1, MESSAGE_SIZE));
+				Sql_GetData(mmysql_handle, 5, &data, NULL); at->limit = atoi(data);
+				Sql_GetData(mmysql_handle, 6, &data, NULL); at->dir = atoi(data);
+				Sql_GetData(mmysql_handle, 7, &data, NULL); at->head_dir = atoi(data);
+				Sql_GetData(mmysql_handle, 8, &data, NULL); at->sit = atoi(data);
+				at->count = 0;
+
+				if (battle_config.feature_autotrade_direction >= 0)
+					at->dir = battle_config.feature_autotrade_direction;
+				if (battle_config.feature_autotrade_head_direction >= 0)
+					at->head_dir = battle_config.feature_autotrade_head_direction;
+				if (battle_config.feature_autotrade_sit >= 0)
+					at->sit = battle_config.feature_autotrade_sit;
 
 
 				// initialize player
 				// initialize player
-				CREATE(autotraders[i]->sd, struct map_session_data, 1);
-			
-				pc_setnewpc(autotraders[i]->sd, autotraders[i]->account_id, autotraders[i]->char_id, 0, gettick(), autotraders[i]->sex, 0);
-			
-				autotraders[i]->sd->state.autotrade = 1;
-				chrif_authreq(autotraders[i]->sd, true);
+				CREATE(at->sd, struct map_session_data, 1);
+				pc_setnewpc(at->sd, at->account_id, at->char_id, 0, gettick(), at->sex, 0);
+				at->sd->state.autotrade = 1;
+				at->sd->state.monster_ignore = (battle_config.autotrade_monsterignore);
+				chrif_authreq(at->sd, true);
 				i++;
 				i++;
 			}
 			}
 			Sql_FreeResult(mmysql_handle);
 			Sql_FreeResult(mmysql_handle);
 
 
-			//Init items on vending list each autotrader
+			//Init items on buying list each autotrader
 			for (i = 0; i < autotrader_count; i++){
 			for (i = 0; i < autotrader_count; i++){
 				struct s_autotrade *at = NULL;
 				struct s_autotrade *at = NULL;
 				uint16 j;
 				uint16 j;
 
 
-				if (autotraders[i] == NULL)
+				if ((at = autotraders[i]) == NULL)
 					continue;
 					continue;
-				at = autotraders[i];
 
 
 				if (SQL_ERROR == Sql_Query(mmysql_handle,
 				if (SQL_ERROR == Sql_Query(mmysql_handle,
 					"SELECT `item_id`, `amount`, `price` "
 					"SELECT `item_id`, `amount`, `price` "
 					"FROM `%s` "
 					"FROM `%s` "
 					"WHERE `buyingstore_id` = %d "
 					"WHERE `buyingstore_id` = %d "
-					"ORDER BY `index` ASC;", buyingstore_items_db, at->buyer_id ) )
+					"ORDER BY `index` ASC;",
+					buyingstore_items_db, at->buyer_id ) )
 				{
 				{
 					Sql_ShowDebug(mmysql_handle);
 					Sql_ShowDebug(mmysql_handle);
 					continue;
 					continue;
 				}
 				}
 
 
-				if (!(at->count = (uint32)Sql_NumRows(mmysql_handle))) {
+				if (!(at->count = (uint16)Sql_NumRows(mmysql_handle))) {
 					map_quit(at->sd);
 					map_quit(at->sd);
 					continue;
 					continue;
 				}
 				}
@@ -708,12 +781,12 @@ void do_init_buyingstore_autotrade( void ) {
 				Sql_FreeResult(mmysql_handle);
 				Sql_FreeResult(mmysql_handle);
 			}
 			}
 
 
-			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
+			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' buyingstore autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
 		}
 		}
 	}
 	}
 
 
 	// Everything is loaded fine, their entries will be reinserted once they are loaded
 	// Everything is loaded fine, their entries will be reinserted once they are loaded
-	if (Sql_Query( mmysql_handle, "DELETE FROM `%s`;", buyingstore_db ) != SQL_SUCCESS ||
+	if (Sql_Query( mmysql_handle, "DELETE FROM `%s`;", buyingstores_db ) != SQL_SUCCESS ||
 		Sql_Query( mmysql_handle, "DELETE FROM `%s`;", buyingstore_items_db ) != SQL_SUCCESS)
 		Sql_Query( mmysql_handle, "DELETE FROM `%s`;", buyingstore_items_db ) != SQL_SUCCESS)
 	{
 	{
 		Sql_ShowDebug(mmysql_handle);
 		Sql_ShowDebug(mmysql_handle);
@@ -748,3 +821,21 @@ void do_final_buyingstore_autotrade(void) {
 		autotrader_count = 0;
 		autotrader_count = 0;
 	}
 	}
 }
 }
+
+/**
+ * Initialise the buyingstore module
+ * called in map::do_init
+ */
+void do_final_buyingstore(void) {
+	db_destroy(buyingstore_db);
+	do_final_buyingstore_autotrade();
+}
+
+/**
+ * Destory the buyingstore module
+ * called in map::do_final
+ */
+void do_init_buyingstore(void) {
+	buyingstore_db = idb_alloc(DB_OPT_BASE);
+	buyingstore_nextid = 0;
+}

+ 5 - 2
src/map/buyingstore.h

@@ -22,13 +22,16 @@ struct s_buyingstore
 	unsigned char slots;
 	unsigned char slots;
 };
 };
 
 
-bool buyingstore_setup(struct map_session_data* sd, unsigned char slots);
-bool buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
+char buyingstore_setup(struct map_session_data* sd, unsigned char slots);
+char buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count);
 void buyingstore_close(struct map_session_data* sd);
 void buyingstore_close(struct map_session_data* sd);
 void buyingstore_open(struct map_session_data* sd, int account_id);
 void buyingstore_open(struct map_session_data* sd, int account_id);
 void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count);
 void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count);
 bool buyingstore_search(struct map_session_data* sd, unsigned short nameid);
 bool buyingstore_search(struct map_session_data* sd, unsigned short nameid);
 bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s);
 bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s);
+DBMap *buyingstore_getdb(void);
+void do_final_buyingstore(void);
+void do_init_buyingstore(void);
 
 
 void do_init_buyingstore_autotrade( void );
 void do_init_buyingstore_autotrade( void );
 void buyingstore_reopen( struct map_session_data* sd );
 void buyingstore_reopen( struct map_session_data* sd );

+ 4 - 2
src/map/cashshop.c

@@ -226,14 +226,16 @@ bool cashshop_buylist( struct map_session_data* sd, uint32 kafrapoints, int n, u
 			return false;
 			return false;
 		}
 		}
 
 
-		ARR_FIND( 0, cash_shop_items[tab].count, j, nameid == cash_shop_items[tab].item[j]->nameid );
+		ARR_FIND( 0, cash_shop_items[tab].count, j, nameid == cash_shop_items[tab].item[j]->nameid || nameid == itemdb_viewid(cash_shop_items[tab].item[j]->nameid) );
+
+		nameid = *( item_list + i * 5 ) = cash_shop_items[tab].item[j]->nameid; //item_avail replacement
 
 
 		if( j == cash_shop_items[tab].count || !itemdb_exists( nameid ) ){
 		if( j == cash_shop_items[tab].count || !itemdb_exists( nameid ) ){
 			clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_UNKONWN_ITEM );
 			clif_cashshop_result( sd, nameid, CASHSHOP_RESULT_ERROR_UNKONWN_ITEM );
 			return false;
 			return false;
 		}else if( !itemdb_isstackable( nameid ) && quantity > 1 ){
 		}else if( !itemdb_isstackable( nameid ) && quantity > 1 ){
 			/* ShowWarning( "Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable cash item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, quantity, nameid ); */
 			/* ShowWarning( "Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable cash item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, quantity, nameid ); */
-			quantity = 1;
+			quantity = *( item_list + i * 5 + 2 ) = 1;
 		}
 		}
 
 
 		switch( pc_checkadditem( sd, nameid, quantity ) ){
 		switch( pc_checkadditem( sd, nameid, quantity ) ){

+ 9 - 12
src/map/chrif.c

@@ -287,12 +287,12 @@ int chrif_save(struct map_session_data *sd, int flag) {
 
 
 	if (flag && sd->state.active) { //Store player data which is quitting
 	if (flag && sd->state.active) { //Store player data which is quitting
 		//FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex]
 		//FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex]
-	if (chrif_isconnected()) {
-		chrif_save_scdata(sd);
-		chrif_skillcooldown_save(sd);
-		chrif_save_bsdata(sd);
-		chrif_req_login_operation(sd->status.account_id, sd->status.name, 7, 0, 2, sd->status.bank_vault); //save Bank data
-	}
+		if (chrif_isconnected()) {
+			chrif_save_scdata(sd);
+			chrif_skillcooldown_save(sd);
+			chrif_save_bsdata(sd);
+			chrif_req_login_operation(sd->status.account_id, sd->status.name, 7, 0, 2, sd->status.bank_vault); //save Bank data
+		}
 		if ( flag != 3 && !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) )
 		if ( flag != 3 && !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) )
 			ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id);
 			ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id);
 	}
 	}
@@ -1130,6 +1130,9 @@ int chrif_disconnectplayer(int fd) {
 			if( sd->state.vending ){
 			if( sd->state.vending ){
 				vending_closevending(sd);
 				vending_closevending(sd);
 			}
 			}
+			else if( sd->state.buyingstore ){
+				buyingstore_close(sd);
+			}
 
 
 			map_quit(sd); //Remove it.
 			map_quit(sd); //Remove it.
 		}
 		}
@@ -1378,12 +1381,6 @@ int chrif_load_scdata(int fd) {
 
 
 	pc_scdata_received(sd);
 	pc_scdata_received(sd);
 #endif
 #endif
-
-	if( sd->state.autotrade ) {
-		buyingstore_reopen( sd );
-		vending_reopen( sd );
-	}
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 106 - 78
src/map/clif.c

@@ -4273,17 +4273,17 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
 
 
 //Modifies the type of damage according to status changes [Skotlex]
 //Modifies the type of damage according to status changes [Skotlex]
 //Aegis data specifies that: 4 endure against single hit sources, 9 against multi-hit.
 //Aegis data specifies that: 4 endure against single hit sources, 9 against multi-hit.
-static inline int clif_calc_delay(int type, int div, int64 damage, int delay)
+static enum e_damage_type clif_calc_delay(char type, int div, int64 damage, int delay)
 {
 {
-	return ( delay == 0 && damage > 0 ) ? ( div > 1 ? 9 : 4 ) : type;
+	return ( delay == 0 && damage > 0 ) ? ( div > 1 ? DMG_MULTI_HIT_ENDURE : DMG_ENDURE ) : (enum e_damage_type)type;
 }
 }
 
 
 /*==========================================
 /*==========================================
  * Estimates walk delay based on the damage criteria. [Skotlex]
  * Estimates walk delay based on the damage criteria. [Skotlex]
  *------------------------------------------*/
  *------------------------------------------*/
-static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int64 damage, int div_)
+static int clif_calc_walkdelay(struct block_list *bl,int delay, char type, int64 damage, int div_)
 {
 {
-	if (type == 4 || type == 9 || damage <=0)
+	if (type == DMG_ENDURE || type == DMG_MULTI_HIT_ENDURE || damage <= 0)
 		return 0;
 		return 0;
 
 
 	if (bl->type == BL_PC) {
 	if (bl->type == BL_PC) {
@@ -4296,7 +4296,7 @@ static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int64
 	if (div_ > 1) //Multi-hit skills mean higher delays.
 	if (div_ > 1) //Multi-hit skills mean higher delays.
 		delay += battle_config.multihit_delay*(div_-1);
 		delay += battle_config.multihit_delay*(div_-1);
 
 
-	return delay>0?delay:1; //Return 1 to specify there should be no noticeable delay, but you should stop walking.
+	return (delay > 0) ? delay:1; //Return 1 to specify there should be no noticeable delay, but you should stop walking.
 }
 }
 
 
 
 
@@ -4317,7 +4317,7 @@ static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int64
 ///     10 = critical hit
 ///     10 = critical hit
 ///     11 = lucky dodge
 ///     11 = lucky dodge
 ///     12 = (touch skill?)
 ///     12 = (touch skill?)
-int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, int type, int64 sdamage2)
+int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, enum e_damage_type type, int64 sdamage2)
 {
 {
 	unsigned char buf[33];
 	unsigned char buf[33];
 	struct status_change *sc;
 	struct status_change *sc;
@@ -4401,7 +4401,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic
  *------------------------------------------*/
  *------------------------------------------*/
 void clif_takeitem(struct block_list* src, struct block_list* dst)
 void clif_takeitem(struct block_list* src, struct block_list* dst)
 {
 {
-	//clif_damage(src,dst,0,0,0,0,0,1,0);
+	//clif_damage(src,dst,0,0,0,0,0,DMG_PICKUP_ITEM,0);
 	unsigned char buf[32];
 	unsigned char buf[32];
 
 
 	nullpo_retv(src);
 	nullpo_retv(src);
@@ -8368,8 +8368,16 @@ void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd)
 
 
 	if( fd > 0 )
 	if( fd > 0 )
 		clif_authfail_fd(fd, 15);
 		clif_authfail_fd(fd, 15);
-	else
+	else {
+		// Close vending/buyingstore
+		if (sd) {
+			if (tsd->state.vending)
+				vending_closevending(tsd);
+			else if (tsd->state.buyingstore)
+				buyingstore_close(tsd);
+		}
 		map_quit(tsd);
 		map_quit(tsd);
+	}
 
 
 	if( sd )
 	if( sd )
 		clif_GM_kickack(sd,tsd->status.account_id);
 		clif_GM_kickack(sd,tsd->status.account_id);
@@ -9700,11 +9708,10 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		// Notify everyone that this char logged in [Skotlex].
 		// Notify everyone that this char logged in [Skotlex].
 		map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1);
 		map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1);
 
 
-		// Set the initial idle time
-		sd->idletime = last_tick;
-
-		//Login Event
-		npc_script_event(sd, NPCE_LOGIN);
+		if (!sd->state.autotrade) { // Don't trigger NPC event or opening vending/buyingstore will be failed
+			//Login Event
+			npc_script_event(sd, NPCE_LOGIN);
+		}
 	} else {
 	} else {
 		//For some reason the client "loses" these on warp/map-change.
 		//For some reason the client "loses" these on warp/map-change.
 		clif_updatestatus(sd,SP_STR);
 		clif_updatestatus(sd,SP_STR);
@@ -9803,7 +9810,8 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		clif_showvendingboard(&sd->bl,sd->message,0);
 		clif_showvendingboard(&sd->bl,sd->message,0);
 	}
 	}
 
 
-	if(map[sd->bl.m].flag.loadevent) // Lance
+	// Don't trigger NPC event or opening vending/buyingstore will be failed
+	if(!sd->state.autotrade && map[sd->bl.m].flag.loadevent) // Lance
 		npc_script_event(sd, NPCE_LOADMAP);
 		npc_script_event(sd, NPCE_LOADMAP);
 
 
 	if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd))
 	if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd))
@@ -9999,7 +10007,8 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
 	RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0], &x, &y, NULL);
 	RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0], &x, &y, NULL);
 
 
 	//Set last idle time... [Skotlex]
 	//Set last idle time... [Skotlex]
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_WALK)
+		sd->idletime = last_tick;
 
 
 	unit_walktoxy(&sd->bl, x, y, 4);
 	unit_walktoxy(&sd->bl, x, y, 4);
 }
 }
@@ -10113,6 +10122,9 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 	}
 	}
 
 
+	if (battle_config.idletime_option&IDLE_CHAT)
+		sd->idletime = last_tick;
+
 	if( sd->gcbind ) {
 	if( sd->gcbind ) {
 		channel_send(sd->gcbind,sd,message);
 		channel_send(sd->gcbind,sd,message);
 		return;
 		return;
@@ -10147,9 +10159,6 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
 	map_foreachinrange(npc_chat_sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
 	map_foreachinrange(npc_chat_sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
 #endif
 #endif
 
 
-	// Reset idle time when using normal chat.
-	sd->idletime = last_tick;
-
 	// Chat logging type 'O' / Global Chat
 	// Chat logging type 'O' / Global Chat
 	log_chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message);
 	log_chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message);
 }
 }
@@ -10245,6 +10254,9 @@ void clif_parse_Emotion(int fd, struct map_session_data *sd)
 		}
 		}
 		sd->emotionlasttime = time(NULL);
 		sd->emotionlasttime = time(NULL);
 
 
+		if (battle_config.idletime_option&IDLE_EMOTION)
+			sd->idletime = last_tick;
+
 		if(battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) {// re-roll dice
 		if(battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) {// re-roll dice
 			emoticon = rnd()%6+E_DICE1;
 			emoticon = rnd()%6+E_DICE1;
 		}
 		}
@@ -10284,13 +10296,13 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 		return;
 		return;
 	}
 	}
 
 
+	// Statuses that don't let the player sit / attack / talk with NPCs(targeted)
+	// (not all are included in pc_can_attack)
 	if (sd->sc.count &&
 	if (sd->sc.count &&
 		(sd->sc.data[SC_TRICKDEAD] ||
 		(sd->sc.data[SC_TRICKDEAD] ||
 		(sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) ||
 		(sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) ||
 		 sd->sc.data[SC_BLADESTOP] ||
 		 sd->sc.data[SC_BLADESTOP] ||
-		 sd->sc.data[SC__MANHOLE] ||
-		 sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
-		 sd->sc.data[SC_CURSEDCIRCLE_TARGET] ))
+		 sd->sc.data[SC__MANHOLE] ))
 		return;
 		return;
 
 
 	pc_stop_walking(sd, 1);
 	pc_stop_walking(sd, 1);
@@ -10313,9 +10325,6 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 		if( sd->sc.option&OPTION_COSTUME )
 		if( sd->sc.option&OPTION_COSTUME )
 			return;
 			return;
 
 
-		if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] )
-			return;
-
 		if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) {
 		if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) {
 			if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
 			if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
 				clif_skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0);
 				clif_skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0);
@@ -10324,7 +10333,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 		}
 		}
 
 
 		pc_delinvincibletimer(sd);
 		pc_delinvincibletimer(sd);
-		sd->idletime = last_tick;
+		if (battle_config.idletime_option&IDLE_ATTACK)
+			sd->idletime = last_tick;
 		unit_attack(&sd->bl, target_id, action_type != 0);
 		unit_attack(&sd->bl, target_id, action_type != 0);
 	break;
 	break;
 	case 0x02: // sitdown
 	case 0x02: // sitdown
@@ -10348,7 +10358,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 		)) //No sitting during these states either.
 		)) //No sitting during these states either.
 			break;
 			break;
 
 
-		sd->idletime = last_tick;
+		if (battle_config.idletime_option&IDLE_SIT)
+			sd->idletime = last_tick;
+
 		skill_sit(sd, 1);
 		skill_sit(sd, 1);
 		pc_setsit(sd);
 		pc_setsit(sd);
 		clif_sitting(&sd->bl);
 		clif_sitting(&sd->bl);
@@ -10360,10 +10372,12 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
 			return;
 			return;
 		}
 		}
 
 
-		sd->idletime = last_tick;
-		pc_setstand(sd);
-		skill_sit(sd, 0);
-		clif_standing(&sd->bl);
+		if (pc_setstand(sd, false)) {
+			if (battle_config.idletime_option&IDLE_SIT)
+				sd->idletime = last_tick;
+			skill_sit(sd, 0);
+			clif_standing(&sd->bl);
+		}
 	break;
 	break;
 	}
 	}
 }
 }
@@ -10444,8 +10458,8 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 	}
 	}
 
 
-	// Reset idle time when using whisper/main chat.
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_CHAT)
+		sd->idletime = last_tick;
 
 
 	// Chat logging type 'W' / Whisper
 	// Chat logging type 'W' / Whisper
 	log_chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message);
 	log_chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message);
@@ -10633,6 +10647,9 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd){
 		if (!pc_dropitem(sd, item_index, item_amount))
 		if (!pc_dropitem(sd, item_index, item_amount))
 			break;
 			break;
 
 
+		if (battle_config.idletime_option&IDLE_DROPITEM)
+			sd->idletime = last_tick;
+
 		return;
 		return;
 	}
 	}
 
 
@@ -10658,7 +10675,8 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
 		return;
 		return;
 
 
 	//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
 	//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_USEITEM)
+		sd->idletime = last_tick;
 	n = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
 	n = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
 
 
 	if(n <0 || n >= MAX_INVENTORY)
 	if(n <0 || n >= MAX_INVENTORY)
@@ -10704,6 +10722,9 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
 		return;
 		return;
 	}
 	}
 
 
+	if (battle_config.idletime_option&IDLE_USEITEM)
+		sd->idletime = last_tick;
+
 	//Client doesn't send the position for ammo.
 	//Client doesn't send the position for ammo.
 	if(sd->inventory_data[index]->type == IT_AMMO)
 	if(sd->inventory_data[index]->type == IT_AMMO)
 		pc_equipitem(sd,index,EQP_AMMO);
 		pc_equipitem(sd,index,EQP_AMMO);
@@ -10740,6 +10761,9 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
 
 
 	index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
 	index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2;
 
 
+	if (battle_config.idletime_option&IDLE_USEITEM)
+		sd->idletime = last_tick;
+
 	pc_unequipitem(sd,index,1);
 	pc_unequipitem(sd,index,1);
 }
 }
 
 
@@ -11297,7 +11321,8 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
 	}
 	}
 
 
 	// Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
 	// Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_USESKILLTOID)
+		sd->idletime = last_tick;
 
 
 	if( sd->npc_id ){
 	if( sd->npc_id ){
 #ifdef RENEWAL
 #ifdef RENEWAL
@@ -11397,7 +11422,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
 	}
 	}
 
 
 	//Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
 	//Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_USESKILLTOPOS)
+		sd->idletime = last_tick;
 
 
 	if( skill_isNotOk(skill_id, sd) )
 	if( skill_isNotOk(skill_id, sd) )
 		return;
 		return;
@@ -12177,8 +12203,8 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd){
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 	}
 	}
 
 
-	// Reset idle time when using party chat.
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_CHAT)
+		sd->idletime = last_tick;
 
 
 	party_send_message(sd, text, textlen);
 	party_send_message(sd, text, textlen);
 }
 }
@@ -12773,8 +12799,8 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd){
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 	}
 	}
 
 
-	// Reset idle time when using guild chat.
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_CHAT)
+		sd->idletime = last_tick;
 
 
 	if( sd->bg_id )
 	if( sd->bg_id )
 		bg_send_message(sd, text, textlen);
 		bg_send_message(sd, text, textlen);
@@ -12975,43 +13001,43 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd)
 	}
 	}
 
 
 	switch (target->type) {
 	switch (target->type) {
-	case BL_PC:
-	{
-		char command[NAME_LENGTH+6];
-		safesnprintf(command,sizeof(command),"%ckick %s", atcommand_symbol, status_get_name(target));
-		is_atcommand(fd, sd, command, 1);
-	}
-	break;
+		case BL_PC:
+		{
+			char command[NAME_LENGTH+6];
+			safesnprintf(command,sizeof(command),"%ckick %s", atcommand_symbol, status_get_name(target));
+			is_atcommand(fd, sd, command, 1);
+		}
+		break;
 
 
-	/**
-	 * This one does not invoke any atcommand, so we need to check for permissions.
-	 */
-	case BL_MOB:
-	{
-		char command[100];
-		if( !pc_can_use_command(sd, "killmonster", COMMAND_ATCOMMAND)) {
-			clif_GM_kickack(sd, 0);
-			return;
+		/**
+		 * This one does not invoke any atcommand, so we need to check for permissions.
+		 */
+		case BL_MOB:
+		{
+			char command[100];
+			if( !pc_can_use_command(sd, "killmonster", COMMAND_ATCOMMAND)) {
+				clif_GM_kickack(sd, 0);
+				return;
+			}
+			safesnprintf(command,sizeof(command),"/kick %s (%d)", status_get_name(target), status_get_class(target));
+			log_atcommand(sd, command);
+			status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target'
 		}
 		}
-		safesnprintf(command,sizeof(command),"/kick %s (%d)", status_get_name(target), status_get_class(target));
-		log_atcommand(sd, command);
-		status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target'
-	}
-	break;
+		break;
 
 
-	case BL_NPC:
-	{
-		struct npc_data* nd = (struct npc_data *)target;
-		if( pc_can_use_command(sd, "unloadnpc", COMMAND_ATCOMMAND)) {
-			npc_unload_duplicates(nd);
-			npc_unload(nd,true);
-			npc_read_event_script();
+		case BL_NPC:
+		{
+			struct npc_data* nd = (struct npc_data *)target;
+			if( pc_can_use_command(sd, "unloadnpc", COMMAND_ATCOMMAND)) {
+				npc_unload_duplicates(nd);
+				npc_unload(nd,true);
+				npc_read_event_script();
+			}
 		}
 		}
-	}
-	break;
+		break;
 
 
-	default:
-		clif_GM_kickack(sd, 0);
+		default:
+			clif_GM_kickack(sd, 0);
 	}
 	}
 }
 }
 
 
@@ -14954,7 +14980,8 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) {
 	WFIFOW(fd, 8) = cash_shop_items[tab].count;
 	WFIFOW(fd, 8) = cash_shop_items[tab].count;
 
 
 	for( j = 0; j < cash_shop_items[tab].count; j++ ) {
 	for( j = 0; j < cash_shop_items[tab].count; j++ ) {
-		WFIFOW(fd, 10 + ( 6 * j ) ) = cash_shop_items[tab].item[j]->nameid;
+		struct item_data *id = itemdb_search(cash_shop_items[tab].item[j]->nameid);
+		WFIFOW(fd, 10 + ( 6 * j ) ) = (id->view_id) ? id->view_id : cash_shop_items[tab].item[j]->nameid;
 		WFIFOL(fd, 12 + ( 6 * j ) ) = cash_shop_items[tab].item[j]->price;
 		WFIFOL(fd, 12 + ( 6 * j ) ) = cash_shop_items[tab].item[j]->price;
 	}
 	}
 
 
@@ -14976,7 +15003,8 @@ void clif_cashshop_list( int fd ){
 		WFIFOW( fd, 6 ) = tab;
 		WFIFOW( fd, 6 ) = tab;
 
 
 		for( i = 0, offset = 8; i < cash_shop_items[tab].count; i++, offset += 6 ){
 		for( i = 0, offset = 8; i < cash_shop_items[tab].count; i++, offset += 6 ){
-			WFIFOW( fd, offset ) = cash_shop_items[tab].item[i]->nameid;
+			struct item_data *id = itemdb_search(cash_shop_items[tab].item[i]->nameid);
+			WFIFOW( fd, offset ) = (id->view_id) ? id->view_id : cash_shop_items[tab].item[i]->nameid;
 			WFIFOL( fd, offset + 2 ) = cash_shop_items[tab].item[i]->price;
 			WFIFOL( fd, offset + 2 ) = cash_shop_items[tab].item[i]->price;
 		}
 		}
 
 
@@ -15773,8 +15801,8 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd){
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 		sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
 	}
 	}
 
 
-	// Reset idle time when using battleground chat.
-	sd->idletime = last_tick;
+	if (battle_config.idletime_option&IDLE_CHAT)
+		sd->idletime = last_tick;
 
 
 	bg_send_message(sd, text, textlen);
 	bg_send_message(sd, text, textlen);
 }
 }
@@ -16661,15 +16689,15 @@ int clif_elementalconverter_list(struct map_session_data *sd) {
 /**
 /**
  * Rune Knight
  * Rune Knight
  **/
  **/
-void clif_millenniumshield(struct map_session_data *sd, short shields ) {
+void clif_millenniumshield(struct block_list *bl, short shields) {
 #if PACKETVER >= 20081217
 #if PACKETVER >= 20081217
 	unsigned char buf[10];
 	unsigned char buf[10];
 
 
 	WBUFW(buf,0) = 0x440;
 	WBUFW(buf,0) = 0x440;
-	WBUFL(buf,2) = sd->bl.id;
+	WBUFL(buf,2) = bl->id;
 	WBUFW(buf,6) = shields;
 	WBUFW(buf,6) = shields;
 	WBUFW(buf,8) = 0;
 	WBUFW(buf,8) = 0;
-	clif_send(buf,packet_len(0x440),&sd->bl,AREA);
+	clif_send(buf,packet_len(0x440),bl,AREA);
 #endif
 #endif
 }
 }
 /**
 /**

+ 18 - 2
src/map/clif.h

@@ -389,6 +389,22 @@ enum e_personalinfo {
 	PINFO_MAX,
 	PINFO_MAX,
 };
 };
 
 
+enum e_damage_type {
+	DMG_NORMAL = 0,			/// damage [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ]
+	DMG_PICKUP_ITEM,		/// pick up item
+	DMG_SIT_DOWN,			/// sit down
+	DMG_STAND_UP,			/// stand up
+	DMG_ENDURE,				/// damage (endure)
+	DMG_SPLASH,				/// (splash?)
+	DMG_SKILL,				/// (skill?)
+	DMG_REPEAT,				/// (repeat damage?)
+	DMG_MULTI_HIT,			/// multi-hit damage
+	DMG_MULTI_HIT_ENDURE,	/// multi-hit damage (endure)
+	DMG_CRITICAL,			/// critical hit
+	DMG_LUCY_DODGE,			/// lucky dodge
+	DMG_TOUCH,				/// (touch skill?)
+};
+
 int clif_setip(const char* ip);
 int clif_setip(const char* ip);
 void clif_setbindip(const char* ip);
 void clif_setbindip(const char* ip);
 void clif_setport(uint16 port);
 void clif_setport(uint16 port);
@@ -433,7 +449,7 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount);	//self
 void clif_delitem(struct map_session_data *sd,int n,int amount, short reason); //self
 void clif_delitem(struct map_session_data *sd,int n,int amount, short reason); //self
 void clif_updatestatus(struct map_session_data *sd,int type);	//self
 void clif_updatestatus(struct map_session_data *sd,int type);	//self
 void clif_changestatus(struct map_session_data* sd,int type,int val);	//area
 void clif_changestatus(struct map_session_data* sd,int type,int val);	//area
-int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, int type, int64 sdamage2);	// area
+int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int64 sdamage, int div, enum e_damage_type type, int64 sdamage2);	// area
 void clif_takeitem(struct block_list* src, struct block_list* dst);
 void clif_takeitem(struct block_list* src, struct block_list* dst);
 void clif_sitting(struct block_list* bl);
 void clif_sitting(struct block_list* bl);
 void clif_standing(struct block_list* bl);
 void clif_standing(struct block_list* bl);
@@ -828,7 +844,7 @@ void clif_msgtable_num(int fd, int line, int num);
 
 
 int clif_elementalconverter_list(struct map_session_data *sd);
 int clif_elementalconverter_list(struct map_session_data *sd);
 
 
-void clif_millenniumshield(struct map_session_data *sd, short shields );
+void clif_millenniumshield(struct block_list *bl, short shields);
 
 
 int clif_spellbook_list(struct map_session_data *sd);
 int clif_spellbook_list(struct map_session_data *sd);
 
 

+ 4 - 4
src/map/elemental.c

@@ -808,14 +808,14 @@ static bool read_elementaldb_sub(char* str[], int columns, int current) {
 	status->race = atoi(str[20]);
 	status->race = atoi(str[20]);
 
 
 	ele = atoi(str[21]);
 	ele = atoi(str[21]);
-	status->def_ele = ele%10;
-	status->ele_lv = ele/20;
+	status->def_ele = ele%20;
+	status->ele_lv = (unsigned char)floor(ele/20.);
 	if( !CHK_ELEMENT(status->def_ele) ) {
 	if( !CHK_ELEMENT(status->def_ele) ) {
 		ShowWarning("read_elementaldb_sub: Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_ALL - 1);
 		ShowWarning("read_elementaldb_sub: Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_ALL - 1);
 		status->def_ele = ELE_NEUTRAL;
 		status->def_ele = ELE_NEUTRAL;
 	}
 	}
-	if( status->ele_lv < 1 || status->ele_lv > 4 ) {
-		ShowWarning("read_elementaldb_sub: Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv);
+	if( !CHK_ELEMENT_LEVEL(status->ele_lv) ) {
+		ShowWarning("read_elementaldb_sub: Elemental %d has invalid element level %d (max is %d)\n", db->class_, status->ele_lv, MAX_ELE_LEVEL);
 		status->ele_lv = 1;
 		status->ele_lv = 1;
 	}
 	}
 
 

+ 10 - 2
src/map/map.c

@@ -70,7 +70,7 @@ char map_server_db[32] = "ragnarok";
 Sql* mmysql_handle;
 Sql* mmysql_handle;
 
 
 int db_use_sqldbs = 0;
 int db_use_sqldbs = 0;
-char buyingstore_db[32] = "buyingstores";
+char buyingstores_db[32] = "buyingstores";
 char buyingstore_items_db[32] = "buyingstore_items";
 char buyingstore_items_db[32] = "buyingstore_items";
 char item_db_db[32] = "item_db";
 char item_db_db[32] = "item_db";
 char item_db2_db[32] = "item_db2";
 char item_db2_db[32] = "item_db2";
@@ -1652,6 +1652,9 @@ int map_quit(struct map_session_data *sd) {
 	if (sd->npc_timer_id != INVALID_TIMER) //Cancel the event timer.
 	if (sd->npc_timer_id != INVALID_TIMER) //Cancel the event timer.
 		npc_timerevent_quit(sd);
 		npc_timerevent_quit(sd);
 
 
+	if (sd->autotrade_tid != INVALID_TIMER)
+		delete_timer(sd->autotrade_tid, pc_autotrade_timer);
+
 	if (sd->npc_id)
 	if (sd->npc_id)
 		npc_event_dequeue(sd);
 		npc_event_dequeue(sd);
 
 
@@ -1765,6 +1768,9 @@ int map_quit(struct map_session_data *sd) {
 	if (sd->state.vending)
 	if (sd->state.vending)
 		idb_remove(vending_getdb(), sd->status.char_id);
 		idb_remove(vending_getdb(), sd->status.char_id);
 
 
+	if (sd->state.buyingstore)
+		idb_remove(buyingstore_getdb(), sd->status.char_id);
+
 	pc_damage_log_clear(sd,0);
 	pc_damage_log_clear(sd,0);
 	party_booking_delete(sd); // Party Booking [Spiria]
 	party_booking_delete(sd); // Party Booking [Spiria]
 	pc_makesavestatus(sd);
 	pc_makesavestatus(sd);
@@ -3584,7 +3590,7 @@ int inter_config_read(char *cfgName)
 			continue;
 			continue;
 
 
 		if( strcmpi( w1, "buyingstore_db" ) == 0 )
 		if( strcmpi( w1, "buyingstore_db" ) == 0 )
-			strcpy( buyingstore_db, w2 );
+			strcpy( buyingstores_db, w2 );
 		else if( strcmpi( w1, "buyingstore_items_db" ) == 0 )
 		else if( strcmpi( w1, "buyingstore_items_db" ) == 0 )
 			strcpy( buyingstore_items_db, w2 );
 			strcpy( buyingstore_items_db, w2 );
 		else if(strcmpi(w1,"item_db_db")==0)
 		else if(strcmpi(w1,"item_db_db")==0)
@@ -3878,6 +3884,7 @@ void do_final(void)
 	do_final_cashshop();
 	do_final_cashshop();
 	do_final_channel(); //should be called after final guild
 	do_final_channel(); //should be called after final guild
 	do_final_vending();
 	do_final_vending();
+	do_final_buyingstore();
 
 
 	map_db->destroy(map_db, map_db_final);
 	map_db->destroy(map_db, map_db_final);
 
 
@@ -4188,6 +4195,7 @@ int do_init(int argc, char *argv[])
 	do_init_battleground();
 	do_init_battleground();
 	do_init_duel();
 	do_init_duel();
 	do_init_vending();
 	do_init_vending();
+	do_init_buyingstore();
 
 
 	npc_event_do_oninit();	// Init npcs (OnInit)
 	npc_event_do_oninit();	// Init npcs (OnInit)
 
 

+ 9 - 5
src/map/map.h

@@ -304,8 +304,8 @@ enum bl_type {
 enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, ITEMSHOP, POINTSHOP, TOMB };
 enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, ITEMSHOP, POINTSHOP, TOMB };
 
 
 enum e_race {
 enum e_race {
-	RC_NONE_=-1, //don't give us bonus
-	RC_FORMLESS=0,
+	RC_NONE_ = -1, //don't give us bonus
+	RC_FORMLESS = 0,
 	RC_UNDEAD,
 	RC_UNDEAD,
 	RC_BRUTE,
 	RC_BRUTE,
 	RC_PLANT,
 	RC_PLANT,
@@ -321,7 +321,7 @@ enum e_race {
 };
 };
 
 
 enum e_classAE {
 enum e_classAE {
-	CLASS_NONE=-1, //don't give us bonus
+	CLASS_NONE = -1, //don't give us bonus
 	CLASS_NORMAL = 0,
 	CLASS_NORMAL = 0,
 	CLASS_BOSS,
 	CLASS_BOSS,
 	CLASS_GUARDIAN,
 	CLASS_GUARDIAN,
@@ -340,7 +340,8 @@ enum e_race2 {
 	RC2_MAX
 	RC2_MAX
 };
 };
 
 
-enum e_elemen {
+/// Element list
+enum e_element {
 	ELE_NONE=-1,
 	ELE_NONE=-1,
 	ELE_NEUTRAL=0,
 	ELE_NEUTRAL=0,
 	ELE_WATER,
 	ELE_WATER,
@@ -356,6 +357,8 @@ enum e_elemen {
 	ELE_MAX
 	ELE_MAX
 };
 };
 
 
+#define MAX_ELE_LEVEL 4 /// Maximum Element level
+
 enum mob_ai {
 enum mob_ai {
 	AI_NONE = 0,
 	AI_NONE = 0,
 	AI_ATTACK,
 	AI_ATTACK,
@@ -868,6 +871,7 @@ void map_addmap2db(struct map_data *m);
 void map_removemapdb(struct map_data *m);
 void map_removemapdb(struct map_data *m);
 
 
 #define CHK_ELEMENT(ele) ((ele) > ELE_NONE && (ele) < ELE_MAX) /// Check valid Element
 #define CHK_ELEMENT(ele) ((ele) > ELE_NONE && (ele) < ELE_MAX) /// Check valid Element
+#define CHK_ELEMENT_LEVEL(lv) ((lv) >= 1 && (lv) <= MAX_ELE_LEVEL) /// Check valid element level
 #define CHK_RACE(race) ((race) > RC_NONE_ && (race) < RC_MAX) /// Check valid Race
 #define CHK_RACE(race) ((race) > RC_NONE_ && (race) < RC_MAX) /// Check valid Race
 #define CHK_RACE2(race2) ((race2) >= RC2_NONE && (race2) < RC2_MAX) /// Check valid Race2
 #define CHK_RACE2(race2) ((race2) >= RC2_NONE && (race2) < RC2_MAX) /// Check valid Race2
 #define CHK_CLASS(class_) ((class_) > CLASS_NONE && (class_) < CLASS_MAX) /// Check valid Class
 #define CHK_CLASS(class_) ((class_) > CLASS_NONE && (class_) < CLASS_MAX) /// Check valid Class
@@ -932,7 +936,7 @@ extern int db_use_sqldbs;
 extern Sql* mmysql_handle;
 extern Sql* mmysql_handle;
 extern Sql* logmysql_handle;
 extern Sql* logmysql_handle;
 
 
-extern char buyingstore_db[32];
+extern char buyingstores_db[32];
 extern char buyingstore_items_db[32];
 extern char buyingstore_items_db[32];
 extern char item_db_db[32];
 extern char item_db_db[32];
 extern char item_db2_db[32];
 extern char item_db2_db[32];

+ 4 - 4
src/map/mercenary.c

@@ -514,16 +514,16 @@ static bool mercenary_readdb_sub(char* str[], int columns, int current)
 	status->race = atoi(str[20]);
 	status->race = atoi(str[20]);
 
 
 	ele = atoi(str[21]);
 	ele = atoi(str[21]);
-	status->def_ele = ele%10;
-	status->ele_lv = ele/20;
+	status->def_ele = ele%20;
+	status->ele_lv = (unsigned char)floor(ele/20.);
 	if( !CHK_ELEMENT(status->def_ele) )
 	if( !CHK_ELEMENT(status->def_ele) )
 	{
 	{
 		ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_ALL - 1);
 		ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_ALL - 1);
 		status->def_ele = ELE_NEUTRAL;
 		status->def_ele = ELE_NEUTRAL;
 	}
 	}
-	if( status->ele_lv < 1 || status->ele_lv > 4 )
+	if( !CHK_ELEMENT_LEVEL(status->ele_lv) )
 	{
 	{
-		ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv);
+		ShowWarning("Mercenary %d has invalid element level %d (max is %d)\n", db->class_, status->ele_lv, MAX_ELE_LEVEL);
 		status->ele_lv = 1;
 		status->ele_lv = 1;
 	}
 	}
 
 

+ 26 - 16
src/map/mob.c

@@ -2266,13 +2266,21 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 
 
 			if (map[m].flag.nobaseexp || !md->db->base_exp)
 			if (map[m].flag.nobaseexp || !md->db->base_exp)
 				base_exp = 0;
 				base_exp = 0;
-			else
-				base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].adjust.bexp/100., 1, UINT_MAX);
+			else {
+				double exp = apply_rate2(md->db->base_exp, per, 1);
+				exp = apply_rate(exp, bonus);
+				exp = apply_rate(exp, map[m].adjust.bexp);
+				base_exp = (unsigned int)cap_value(exp, 1, UINT_MAX);
+			}
 
 
 			if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
 			if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
 				job_exp = 0;
 				job_exp = 0;
-			else
-				job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].adjust.jexp/100., 1, UINT_MAX);
+			else {
+				double exp = apply_rate2(md->db->job_exp, per, 1);
+				exp = apply_rate(exp, bonus);
+				exp = apply_rate(exp, map[m].adjust.jexp);
+				job_exp = (unsigned int)cap_value(exp, 1, UINT_MAX);
+			}
 
 
 			if ( ( temp = tmpsd[i]->status.party_id)>0 ) {
 			if ( ( temp = tmpsd[i]->status.party_id)>0 ) {
 				int j;
 				int j;
@@ -2310,8 +2318,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 					if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) {
 					if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) {
 #ifdef RENEWAL_EXP
 #ifdef RENEWAL_EXP
 						int rate = pc_level_penalty_mod(tmpsd[i], md->level, md->status.class_, 1);
 						int rate = pc_level_penalty_mod(tmpsd[i], md->level, md->status.class_, 1);
-						base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX);
-						job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX);
+						if (rate != 100) {
+							base_exp = (unsigned int)cap_value(apply_rate(base_exp, rate), 1, UINT_MAX);
+							job_exp = (unsigned int)cap_value(apply_rate(job_exp, rate), 1, UINT_MAX);
+						}
 #endif
 #endif
 						pc_gainexp(tmpsd[i], &md->bl, base_exp, job_exp, false);
 						pc_gainexp(tmpsd[i], &md->bl, base_exp, job_exp, false);
 					}
 					}
@@ -2395,7 +2405,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 			}
 			}
 #ifdef RENEWAL_DROP
 #ifdef RENEWAL_DROP
 			if( drop_modifier != 100 ) {
 			if( drop_modifier != 100 ) {
-				drop_rate = drop_rate * drop_modifier / 100;
+				drop_rate = apply_rate(drop_rate, drop_modifier);
 				if( drop_rate < 1 )
 				if( drop_rate < 1 )
 					drop_rate = 1;
 					drop_rate = 1;
 			}
 			}
@@ -3768,14 +3778,14 @@ static bool mob_parse_dbrow(char** str)
 	status->race = atoi(str[23]);
 	status->race = atoi(str[23]);
 
 
 	i = atoi(str[24]); //Element
 	i = atoi(str[24]); //Element
-	status->def_ele = i%10;
-	status->ele_lv = i/20;
+	status->def_ele = i%20;
+	status->ele_lv = (unsigned char)floor(i/20.);
 	if (!CHK_ELEMENT(status->def_ele)) {
 	if (!CHK_ELEMENT(status->def_ele)) {
 		ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, mob_id, ELE_ALL-1);
 		ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, mob_id, ELE_ALL-1);
 		return false;
 		return false;
 	}
 	}
-	if (status->ele_lv < 1 || status->ele_lv > 4) {
-		ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, mob_id);
+	if (!CHK_ELEMENT_LEVEL(status->ele_lv)) {
+		ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-%d.\n", status->ele_lv, mob_id, MAX_ELE_LEVEL);
 		return false;
 		return false;
 	}
 	}
 
 
@@ -4009,9 +4019,9 @@ static int mob_read_sqldb(void)
  *------------------------------------------*/
  *------------------------------------------*/
 static bool mob_readdb_mobavail(char* str[], int columns, int current)
 static bool mob_readdb_mobavail(char* str[], int columns, int current)
 {
 {
-	int mob_id, k;
+	int mob_id, sprite_id;
 
 
-	mob_id=atoi(str[0]);
+	mob_id = atoi(str[0]);
 
 
 	if(mob_db(mob_id) == mob_dummy)	// invalid class (probably undefined in db)
 	if(mob_db(mob_id) == mob_dummy)	// invalid class (probably undefined in db)
 	{
 	{
@@ -4019,13 +4029,13 @@ static bool mob_readdb_mobavail(char* str[], int columns, int current)
 		return false;
 		return false;
 	}
 	}
 
 
-	k=atoi(str[1]);
+	sprite_id = atoi(str[1]);
 
 
 	memset(&mob_db_data[mob_id]->vd, 0, sizeof(struct view_data));
 	memset(&mob_db_data[mob_id]->vd, 0, sizeof(struct view_data));
-	mob_db_data[mob_id]->vd.class_=k;
+	mob_db_data[mob_id]->vd.class_ = sprite_id;
 
 
 	//Player sprites
 	//Player sprites
-	if(pcdb_checkid(k) && columns==12) {
+	if(pcdb_checkid(sprite_id) && columns==12) {
 		mob_db_data[mob_id]->vd.sex=atoi(str[2]);
 		mob_db_data[mob_id]->vd.sex=atoi(str[2]);
 		mob_db_data[mob_id]->vd.hair_style=atoi(str[3]);
 		mob_db_data[mob_id]->vd.hair_style=atoi(str[3]);
 		mob_db_data[mob_id]->vd.hair_color=atoi(str[4]);
 		mob_db_data[mob_id]->vd.hair_color=atoi(str[4]);

+ 75 - 71
src/map/npc.c

@@ -1249,7 +1249,7 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing)
 		TBL_NPC* nd=(TBL_NPC*)map_id2bl(id);
 		TBL_NPC* nd=(TBL_NPC*)map_id2bl(id);
 		ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n",
 		ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n",
 			nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id,
 			nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id,
-		  	nd?(char*)nd->name:"'Unknown NPC'", (int)id);
+			nd?(char*)nd->name:"'Unknown NPC'", (int)id);
 		return 1;
 		return 1;
 	}
 	}
 
 
@@ -1332,82 +1332,84 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type)
 *------------------------------------------*/
 *------------------------------------------*/
 int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list)
 int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list)
 {
 {
-    int i, j, amount, new_, w, vt;
+	int i, j, amount, new_, w, vt;
 	unsigned short nameid;
 	unsigned short nameid;
-    struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
-
-    if( !nd || nd->subtype != CASHSHOP )
-        return 1;
-
-    if( sd->state.trading )
-        return 4;
-
-    new_ = 0;
-    w = 0;
-    vt = 0; // Global Value
-
-    // Validating Process ----------------------------------------------------
-    for( i = 0; i < count; i++ )
-    {
-        nameid = item_list[i*2+1];
-        amount = item_list[i*2+0];
-
-        if( !itemdb_exists(nameid) || amount <= 0 )
-            return 5;
-
-        ARR_FIND(0,nd->u.shop.count,j,nd->u.shop.shop_item[j].nameid == nameid);
-        if( j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0 )
-            return 5;
-
-        if( !itemdb_isstackable(nameid) && amount > 1 )
-        {
-            ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
-            amount = item_list[i*2+0] = 1;
-        }
-
-        switch( pc_checkadditem(sd,nameid,amount) )
-        {
-            case CHKADDITEM_NEW:
-                new_++;
-                break;
-            case CHKADDITEM_OVERAMOUNT:
-                return 3;
-        }
-
-        vt += nd->u.shop.shop_item[j].value * amount;
-        w += itemdb_weight(nameid) * amount;
-    }
-
-    if( w + sd->weight > sd->max_weight )
-        return 3;
-    if( pc_inventoryblank(sd) < new_ )
-        return 3;
-    if( points > vt ) points = vt;
-
-    // Payment Process ----------------------------------------------------
-    if( sd->kafraPoints < points || sd->cashPoints < (vt - points) )
-        return 6;
+	struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid);
+
+	if( !nd || nd->subtype != CASHSHOP )
+		return 1;
+
+	if( sd->state.trading )
+		return 4;
+
+	new_ = 0;
+	w = 0;
+	vt = 0; // Global Value
+
+	// Validating Process ----------------------------------------------------
+	for( i = 0; i < count; i++ )
+	{
+		nameid = item_list[i*2+1];
+		amount = item_list[i*2+0];
+
+		if( !itemdb_exists(nameid) || amount <= 0 )
+			return 5;
+
+		ARR_FIND(0,nd->u.shop.count,j,nd->u.shop.shop_item[j].nameid == nameid || itemdb_viewid(nd->u.shop.shop_item[j].nameid) == nameid);
+		if( j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0 )
+			return 5;
+
+		nameid = item_list[i*2+1] = nd->u.shop.shop_item[j].nameid; //item_avail replacement
+
+		if( !itemdb_isstackable(nameid) && amount > 1 )
+		{
+			ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
+			amount = item_list[i*2+0] = 1;
+		}
+
+		switch( pc_checkadditem(sd,nameid,amount) )
+		{
+			case CHKADDITEM_NEW:
+				new_++;
+				break;
+			case CHKADDITEM_OVERAMOUNT:
+				return 3;
+		}
+
+		vt += nd->u.shop.shop_item[j].value * amount;
+		w += itemdb_weight(nameid) * amount;
+	}
+
+	if( w + sd->weight > sd->max_weight )
+		return 3;
+	if( pc_inventoryblank(sd) < new_ )
+		return 3;
+	if( points > vt ) points = vt;
+
+	// Payment Process ----------------------------------------------------
+	if( sd->kafraPoints < points || sd->cashPoints < (vt - points) )
+		return 6;
 	pc_paycash(sd,vt,points, LOG_TYPE_NPC);
 	pc_paycash(sd,vt,points, LOG_TYPE_NPC);
 
 
-    // Delivery Process ----------------------------------------------------
-    for( i = 0; i < count; i++ )
-    {
-        struct item item_tmp;
+	// Delivery Process ----------------------------------------------------
+	for( i = 0; i < count; i++ )
+	{
+		struct item item_tmp;
 
 
-        nameid = item_list[i*2+1];
-        amount = item_list[i*2+0];
+		nameid = item_list[i*2+1];
+		amount = item_list[i*2+0];
 
 
-        memset(&item_tmp,0,sizeof(item_tmp));
+		memset(&item_tmp,0,sizeof(item_tmp));
 
 
-        if( !pet_create_egg(sd,nameid) )
-        {
-            item_tmp.nameid = nameid;
-            item_tmp.identify = 1;
-            pc_additem(sd,&item_tmp,amount,LOG_TYPE_NPC);
-        }
-    }
+		if( !pet_create_egg(sd,nameid) )
+		{
+			item_tmp.nameid = nameid;
+			item_tmp.identify = 1;
+			pc_additem(sd,&item_tmp,amount,LOG_TYPE_NPC);
+		}
+	}
 
 
-    return 0;
+	return 0;
 }
 }
 
 
 //npc_buylist for script-controlled shops.
 //npc_buylist for script-controlled shops.
@@ -1460,12 +1462,14 @@ int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amo
 	if( (item = itemdb_exists(nameid)) == NULL )
 	if( (item = itemdb_exists(nameid)) == NULL )
 		return 5; // Invalid Item
 		return 5; // Invalid Item
 
 
-	ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid);
+	ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid || itemdb_viewid(nd->u.shop.shop_item[i].nameid) == nameid);
 	if( i == nd->u.shop.count )
 	if( i == nd->u.shop.count )
 		return 5;
 		return 5;
 	if( nd->u.shop.shop_item[i].value <= 0 )
 	if( nd->u.shop.shop_item[i].value <= 0 )
 		return 5;
 		return 5;
 
 
+	nameid = nd->u.shop.shop_item[i].nameid; //item_avail replacement
+
 	if(!itemdb_isstackable(nameid) && amount > 1)
 	if(!itemdb_isstackable(nameid) && amount > 1)
 	{
 	{
 		ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n",
 		ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %hu!\n",

+ 140 - 59
src/map/pc.c

@@ -231,7 +231,7 @@ void pc_addspiritball(struct map_session_data *sd,int interval,int max)
 	sd->spirit_timer[i] = tid;
 	sd->spirit_timer[i] = tid;
 	sd->spiritball++;
 	sd->spiritball++;
 	if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
 	if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
-		clif_millenniumshield(sd,sd->spiritball);
+		clif_millenniumshield(&sd->bl,sd->spiritball);
 	else
 	else
 		clif_spiritball(&sd->bl);
 		clif_spiritball(&sd->bl);
 }
 }
@@ -274,7 +274,7 @@ void pc_delspiritball(struct map_session_data *sd,int count,int type)
 
 
 	if(!type) {
 	if(!type) {
 		if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
 		if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
-			clif_millenniumshield(sd,sd->spiritball);
+			clif_millenniumshield(&sd->bl,sd->spiritball);
 		else
 		else
 			clif_spiritball(&sd->bl);
 			clif_spiritball(&sd->bl);
 	}
 	}
@@ -849,7 +849,7 @@ bool pc_isequipped(struct map_session_data *sd, unsigned short nameid)
 
 
 	for( i = 0; i < EQI_MAX; i++ )
 	for( i = 0; i < EQI_MAX; i++ )
 	{
 	{
-		int8 index = sd->equip_index[i], j;
+		short index = sd->equip_index[i], j;
 		if( index < 0 )
 		if( index < 0 )
 			continue;
 			continue;
 		if( pc_is_same_equip_index((enum equip_index)i, sd->equip_index, index) )
 		if( pc_is_same_equip_index((enum equip_index)i, sd->equip_index, index) )
@@ -1136,6 +1136,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 	sd->npc_timer_id = INVALID_TIMER;
 	sd->npc_timer_id = INVALID_TIMER;
 	sd->pvp_timer = INVALID_TIMER;
 	sd->pvp_timer = INVALID_TIMER;
 	sd->expiration_tid = INVALID_TIMER;
 	sd->expiration_tid = INVALID_TIMER;
+	sd->autotrade_tid = INVALID_TIMER;
 
 
 #ifdef SECURE_NPCTIMEOUT
 #ifdef SECURE_NPCTIMEOUT
 	// Initialize to defaults/expected
 	// Initialize to defaults/expected
@@ -1150,6 +1151,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 	sd->cantalk_tick = tick;
 	sd->cantalk_tick = tick;
 	sd->canskill_tick = tick;
 	sd->canskill_tick = tick;
 	sd->cansendmail_tick = tick;
 	sd->cansendmail_tick = tick;
+	sd->idletime = last_tick;
 
 
 	for(i = 0; i < MAX_SPIRITBALL; i++)
 	for(i = 0; i < MAX_SPIRITBALL; i++)
 		sd->spirit_timer[i] = INVALID_TIMER;
 		sd->spirit_timer[i] = INVALID_TIMER;
@@ -1453,8 +1455,12 @@ void pc_reg_received(struct map_session_data *sd)
 		clif_changeoption( &sd->bl );
 		clif_changeoption( &sd->bl );
 	}
 	}
 
 
-	if( sd->state.autotrade )
+	pc_check_expiration(sd);
+
+	if( sd->state.autotrade ) {
 		clif_parse_LoadEndAck(sd->fd, sd);
 		clif_parse_LoadEndAck(sd->fd, sd);
+		sd->autotrade_tid = add_timer(gettick() + battle_config.feature_autotrade_open_delay, pc_autotrade_timer, sd->bl.id, 0);
+	}
 }
 }
 
 
 static int pc_calc_skillpoint(struct map_session_data* sd)
 static int pc_calc_skillpoint(struct map_session_data* sd)
@@ -4612,7 +4618,7 @@ bool pc_isUseitem(struct map_session_data *sd,int n)
 			return false;
 			return false;
 		}
 		}
 		if( !pc_inventoryblank(sd) ) {
 		if( !pc_inventoryblank(sd) ) {
-			clif_colormes(sd, color_table[COLOR_RED], msg_txt(sd, 1477)); //Item cannot be open when inventory is full
+			clif_colormes(sd, color_table[COLOR_RED], msg_txt(sd, 732)); //Item cannot be open when inventory is full
 			return false;
 			return false;
 		}
 		}
 	}
 	}
@@ -4725,11 +4731,11 @@ int pc_useitem(struct map_session_data *sd,int n)
 					int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000;
 					int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000;
 					char e_msg[100];
 					char e_msg[100];
 					if( e_tick > 99 )
 					if( e_tick > 99 )
-						sprintf(e_msg,msg_txt(sd,379), //Able to use %.1f min later.
-										(double)e_tick / 60);
+						sprintf(e_msg,msg_txt(sd,379), // Item Failed. [%s] is cooling down. Wait %.1f minutes.
+										itemdb_jname(sd->item_delay[i].nameid), (double)e_tick / 60);
 					else
 					else
-						sprintf(e_msg,msg_txt(sd,380), //Able to use %d sec later.
-										e_tick+1);
+						sprintf(e_msg,msg_txt(sd,380), // Item Failed. [%s] is cooling down. Wait %d seconds.
+										itemdb_jname(sd->item_delay[i].nameid), e_tick+1);
 					clif_colormes(sd,color_table[COLOR_YELLOW],e_msg);
 					clif_colormes(sd,color_table[COLOR_YELLOW],e_msg);
 					return 0; // Delay has not expired yet
 					return 0; // Delay has not expired yet
 				}
 				}
@@ -5146,8 +5152,11 @@ char pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int
 		return 1;
 		return 1;
 	}
 	}
 
 
+	if ( sd->state.autotrade && (sd->vender_id || sd->buyer_id) ) // Player with autotrade just causes clif glitch! @ FIXME
+		return 1;
+
 	if( battle_config.revive_onwarp && pc_isdead(sd) ) { //Revive dead people before warping them
 	if( battle_config.revive_onwarp && pc_isdead(sd) ) { //Revive dead people before warping them
-		pc_setstand(sd);
+		pc_setstand(sd, true);
 		pc_setrestartvalue(sd,1);
 		pc_setrestartvalue(sd,1);
 	}
 	}
 
 
@@ -6212,38 +6221,41 @@ int pc_checkjoblevelup(struct map_session_data *sd)
 static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src)
 static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src)
 {
 {
 	int bonus = 0, vip_bonus_base = 0, vip_bonus_job = 0;
 	int bonus = 0, vip_bonus_base = 0, vip_bonus_job = 0;
-	struct status_data *status = status_get_status_data(src);
-
-	if( sd->expaddrace[status->race] )
-		bonus += sd->expaddrace[status->race];
-	if( sd->expaddrace[RC_ALL] )
-		bonus += sd->expaddrace[RC_ALL];
-	if( sd->expaddclass[status->class_] )
-		bonus += sd->expaddclass[status->class_];
-	if( sd->expaddclass[CLASS_ALL] )
-		bonus += sd->expaddclass[CLASS_ALL];
-
-	if (battle_config.pk_mode &&
-		(int)(status_get_lv(src) - sd->status.base_level) >= 20)
-		bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
-
-	if (sd->sc.data[SC_EXPBOOST]) {	
- 		bonus += sd->sc.data[SC_EXPBOOST]->val1;
-		if( battle_config.vip_bm_increase && pc_isvip(sd) ) // Increase Battle Manual EXP rate for VIP.
-			bonus += ( sd->sc.data[SC_EXPBOOST]->val1 / battle_config.vip_bm_increase );
-	}
+
+	if (src) {
+		struct status_data *status = status_get_status_data(src);
+
+		if( sd->expaddrace[status->race] )
+			bonus += sd->expaddrace[status->race];
+		if( sd->expaddrace[RC_ALL] )
+			bonus += sd->expaddrace[RC_ALL];
+		if( sd->expaddclass[status->class_] )
+			bonus += sd->expaddclass[status->class_];
+		if( sd->expaddclass[CLASS_ALL] )
+			bonus += sd->expaddclass[CLASS_ALL];
+
+		if (battle_config.pk_mode &&
+			(int)(status_get_lv(src) - sd->status.base_level) >= 20)
+			bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
 
 
 #ifdef VIP_ENABLE
 #ifdef VIP_ENABLE
-	//EXP bonus for VIP player
-	if (src && src->type == BL_MOB && pc_isvip(sd)) {
-		vip_bonus_base = battle_config.vip_base_exp_increase;
-		vip_bonus_job = battle_config.vip_job_exp_increase;
-	}
+		//EXP bonus for VIP player
+		if (src && src->type == BL_MOB && pc_isvip(sd)) {
+			vip_bonus_base = battle_config.vip_base_exp_increase;
+			vip_bonus_job = battle_config.vip_job_exp_increase;
+		}
 #endif
 #endif
+	}
+
+	if (&sd->sc && sd->sc.data[SC_EXPBOOST]) {
+		bonus += sd->sc.data[SC_EXPBOOST]->val1;
+		if( battle_config.vip_bm_increase && pc_isvip(sd) ) // Increase Battle Manual EXP rate for VIP.
+			bonus += ( sd->sc.data[SC_EXPBOOST]->val1 / battle_config.vip_bm_increase );
+	}
 
 
 	*base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * (bonus + vip_bonus_base)/100., 1, UINT_MAX);
 	*base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * (bonus + vip_bonus_base)/100., 1, UINT_MAX);
-	
-	if (sd->sc.data[SC_JEXPBOOST])
+
+	if (&sd->sc && sd->sc.data[SC_JEXPBOOST])
 		bonus += sd->sc.data[SC_JEXPBOOST]->val1;
 		bonus += sd->sc.data[SC_JEXPBOOST]->val1;
 
 
 	*job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * (bonus + vip_bonus_job)/100., 1, UINT_MAX);
 	*job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * (bonus + vip_bonus_job)/100., 1, UINT_MAX);
@@ -6253,10 +6265,11 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi
 /*==========================================
 /*==========================================
  * Give x exp at sd player and calculate remaining exp for next lvl
  * Give x exp at sd player and calculate remaining exp for next lvl
  *------------------------------------------*/
  *------------------------------------------*/
-int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool quest)
+int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, bool quest)
 {
 {
-	float nextbp=0, nextjp=0;
-	unsigned int nextb=0, nextj=0;
+	float nextbp = 0, nextjp = 0;
+	unsigned int nextb = 0, nextj = 0;
+
 	nullpo_ret(sd);
 	nullpo_ret(sd);
 
 
 	if(sd->bl.prev == NULL || pc_isdead(sd))
 	if(sd->bl.prev == NULL || pc_isdead(sd))
@@ -6268,7 +6281,7 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
 	if(sd->status.guild_id>0)
 	if(sd->status.guild_id>0)
 		base_exp-=guild_payexp(sd,base_exp);
 		base_exp-=guild_payexp(sd,base_exp);
 
 
-	if(src) pc_calcexp(sd, &base_exp, &job_exp, src);
+	pc_calcexp(sd, &base_exp, &job_exp, src); // Give (J)EXPBOOST for quests even if src is NULL.
 
 
 	nextb = pc_nextbaseexp(sd);
 	nextb = pc_nextbaseexp(sd);
 	nextj = pc_nextjobexp(sd);
 	nextj = pc_nextjobexp(sd);
@@ -7049,7 +7062,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
 	if( sd->bg_id && bg_member_respawn(sd) )
 	if( sd->bg_id && bg_member_respawn(sd) )
 		return; // member revived by battleground
 		return; // member revived by battleground
 
 
-	pc_setstand(sd);
+	pc_setstand(sd, true);
 	pc_setrestartvalue(sd,3);
 	pc_setrestartvalue(sd,3);
 	if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) )
 	if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) )
 		clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
 		clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
@@ -7080,7 +7093,7 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h
 		return;
 		return;
 
 
 	if( pc_issit(sd) ) {
 	if( pc_issit(sd) ) {
-		pc_setstand(sd);
+		pc_setstand(sd, true);
 		skill_sit(sd,0);
 		skill_sit(sd,0);
 	}
 	}
 
 
@@ -7461,7 +7474,7 @@ void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
 	if(hp) clif_updatestatus(sd,SP_HP);
 	if(hp) clif_updatestatus(sd,SP_HP);
 	if(sp) clif_updatestatus(sd,SP_SP);
 	if(sp) clif_updatestatus(sd,SP_SP);
 
 
-	pc_setstand(sd);
+	pc_setstand(sd, true);
 	if(battle_config.pc_invincible_time > 0)
 	if(battle_config.pc_invincible_time > 0)
 		pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
 		pc_setinvincibletimer(sd, battle_config.pc_invincible_time);
 
 
@@ -8066,6 +8079,8 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper)
 		elemental_delete(sd->ed, 0);
 		elemental_delete(sd->ed, 0);
 	if (sd->state.vending)
 	if (sd->state.vending)
 		vending_closevending(sd);
 		vending_closevending(sd);
+	if (sd->state.buyingstore)
+		buyingstore_close(sd);
 
 
 	map_foreachinmap(jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id);
 	map_foreachinmap(jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id);
 
 
@@ -8228,7 +8243,7 @@ void pc_setoption(struct map_session_data *sd,int type)
 	} else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
 	} else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
 		clif_clearcart(sd->fd);
 		clif_clearcart(sd->fd);
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
-			status_calc_pc(sd,0); //Remove speed penalty.
+			status_calc_pc(sd,SCO_NONE); //Remove speed penalty.
 	}
 	}
 #endif
 #endif
 
 
@@ -8391,6 +8406,33 @@ bool pc_candrop(struct map_session_data *sd, struct item *item)
 	return (itemdb_isdropable(item, pc_get_group_level(sd)));
 	return (itemdb_isdropable(item, pc_get_group_level(sd)));
 }
 }
 
 
+/**
+ * Determines whether a player can attack based on status changes
+ *  Why not use status_check_skilluse?
+ *  "src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack."
+ *  Even ground-based attacks should be blocked by these statuses
+ * Called from unit_attack and unit_attack_timer_sub
+ * @retval true Can attack
+ **/
+bool pc_can_attack( struct map_session_data *sd, int target_id ) {
+	nullpo_retr(false, sd);
+
+	if( sd->sc.data[SC_BASILICA] ||
+		sd->sc.data[SC__SHADOWFORM] ||
+		sd->sc.data[SC__MANHOLE] ||
+		sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
+		sd->sc.data[SC_CURSEDCIRCLE_TARGET] ||
+		sd->sc.data[SC_CRYSTALIZE] ||
+		sd->sc.data[SC_ALL_RIDING] || // The client doesn't let you, this is to make cheat-safe
+		sd->sc.data[SC_TRICKDEAD] ||
+		(sd->sc.data[SC_VOICEOFSIREN] && sd->sc.data[SC_VOICEOFSIREN]->val2 == target_id) ||
+		sd->sc.data[SC_BLADESTOP] ||
+		sd->sc.data[SC_DEEPSLEEP] )
+			return false;
+
+	return true;
+}
+
 /*==========================================
 /*==========================================
  * Read ram register for player sd
  * Read ram register for player sd
  * get val (int) from reg for player sd
  * get val (int) from reg for player sd
@@ -8873,8 +8915,7 @@ static int pc_checkcombo(struct map_session_data *sd, struct item_data *data) {
 			bool found = false;
 			bool found = false;
 			
 			
 			for( k = 0; k < EQI_MAX; k++ ) {
 			for( k = 0; k < EQI_MAX; k++ ) {
-				int8 index;
-				index = sd->equip_index[k];
+				short index = sd->equip_index[k];
 				if( index < 0 )
 				if( index < 0 )
 					continue;
 					continue;
 				if( pc_is_same_equip_index((enum equip_index)k, sd->equip_index, index) )
 				if( pc_is_same_equip_index((enum equip_index)k, sd->equip_index, index) )
@@ -9014,8 +9055,8 @@ int pc_load_combo(struct map_session_data *sd) {
 	int i, ret = 0;
 	int i, ret = 0;
 	for( i = 0; i < EQI_MAX; i++ ) {
 	for( i = 0; i < EQI_MAX; i++ ) {
 		struct item_data *id = NULL;
 		struct item_data *id = NULL;
-		int idx = sd->equip_index[i];
-		if( sd->equip_index[i] < 0 || !(id = sd->inventory_data[idx] ) )
+		short idx = sd->equip_index[i];
+		if( idx < 0 || !(id = sd->inventory_data[idx] ) )
 			continue;
 			continue;
 		if( id->combos_count )
 		if( id->combos_count )
 			ret += pc_checkcombo(sd,id);
 			ret += pc_checkcombo(sd,id);
@@ -9852,8 +9893,19 @@ int map_night_timer(int tid, unsigned int tick, int id, intptr_t data)
 	return 0;
 	return 0;
 }
 }
 
 
-void pc_setstand(struct map_session_data *sd){
-	nullpo_retv(sd);
+/**
+* Attempt to stand up a player
+* @param sd
+* @param force Ignore the check, ask player to stand up. Used in some cases like pc_damage(), pc_revive(), etc
+* @return True if success, Fals if failed
+*/
+bool pc_setstand(struct map_session_data *sd, bool force){
+	nullpo_ret(sd);
+
+	// Cannot stand yet
+	// TODO: Move to SCS_NOSTAND [Cydh]
+	if (!force && &sd->sc && (sd->sc.data[SC_SITDOWN_FORCE] || sd->sc.data[SC_BANANA_BOMB_SITDOWN]))
+		return false;
 
 
 	status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
 	status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
 	clif_status_load(&sd->bl,SI_SIT,0);
 	clif_status_load(&sd->bl,SI_SIT,0);
@@ -9861,6 +9913,7 @@ void pc_setstand(struct map_session_data *sd){
 	//Reset sitting tick.
 	//Reset sitting tick.
 	sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0;
 	sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0;
 	sd->state.dead_sit = sd->vd.dead_sit = 0;
 	sd->state.dead_sit = sd->vd.dead_sit = 0;
+	return true;
 }
 }
 
 
 /**
 /**
@@ -10730,9 +10783,17 @@ void pc_damage_log_clear(struct map_session_data *sd, int id)
 
 
 /* Status change data arrived from char-server */
 /* Status change data arrived from char-server */
 void pc_scdata_received(struct map_session_data *sd) {
 void pc_scdata_received(struct map_session_data *sd) {
+	// Nothing todo yet
+	return;
+}
+
+/** Check expiration time and rental items
+* @param sd
+*/
+void pc_check_expiration(struct map_session_data *sd) {
 	pc_inventory_rentals(sd);
 	pc_inventory_rentals(sd);
 
 
-	if( sd->expiration_time != 0 ) { //Don't display if it's unlimited or unknow value
+	if (sd->expiration_time != 0) { //Don't display if it's unlimited or unknow value
 		time_t exp_time = sd->expiration_time;
 		time_t exp_time = sd->expiration_time;
 		char tmpstr[1024];
 		char tmpstr[1024];
 
 
@@ -10758,6 +10819,25 @@ int pc_expiration_timer(int tid, unsigned int tick, int id, intptr_t data) {
 	return 0;
 	return 0;
 }
 }
 
 
+int pc_autotrade_timer(int tid, unsigned int tick, int id, intptr_t data) {
+	struct map_session_data *sd = map_id2sd(id);
+
+	if (!sd)
+		return 0;
+
+	sd->autotrade_tid = INVALID_TIMER;
+
+	buyingstore_reopen(sd);
+	vending_reopen(sd);
+
+	if (sd && !sd->vender_id && !sd->buyer_id) {
+		sd->state.autotrade = 0;
+		map_quit(sd);
+	}
+
+	return 0;
+}
+
 /* this timer exists only when a character with a expire timer > 24h is online */
 /* this timer exists only when a character with a expire timer > 24h is online */
 /* it loops thru online players once an hour to check whether a new < 24h is available */
 /* it loops thru online players once an hour to check whether a new < 24h is available */
 int pc_global_expiration_timer(int tid, unsigned int tick, int id, intptr_t data) {
 int pc_global_expiration_timer(int tid, unsigned int tick, int id, intptr_t data) {
@@ -11080,23 +11160,23 @@ short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id)
 * @param index Known index item in inventory from sd->equip_index[] to compare with specified EQI in *equip_index
 * @param index Known index item in inventory from sd->equip_index[] to compare with specified EQI in *equip_index
 * @return True if item in same inventory index, False if doesn't
 * @return True if item in same inventory index, False if doesn't
 */
 */
-bool pc_is_same_equip_index(enum equip_index eqi, int *equip_index, int8 index) {
-	if (index < 0 || index >= ARRAYLENGTH(equip_index))
-		return false;
+bool pc_is_same_equip_index(enum equip_index eqi, short *equip_index, short index) {
+	if (index < 0 || index >= MAX_INVENTORY)
+		return true;
 	// Dual weapon checks
 	// Dual weapon checks
 	if (eqi == EQI_HAND_R && equip_index[EQI_HAND_L] == index)
 	if (eqi == EQI_HAND_R && equip_index[EQI_HAND_L] == index)
 		return true;
 		return true;
 	// Headgear with Mid & Low location
 	// Headgear with Mid & Low location
-	else if (eqi == EQI_HEAD_MID && equip_index[EQI_HEAD_LOW] == index)
+	if (eqi == EQI_HEAD_MID && equip_index[EQI_HEAD_LOW] == index)
 		return true;
 		return true;
 	// Headgear with Top & Mid or Low location
 	// Headgear with Top & Mid or Low location
-	else if (eqi == EQI_HEAD_TOP && (equip_index[EQI_HEAD_MID] == index || equip_index[EQI_HEAD_LOW] == index))
+	if (eqi == EQI_HEAD_TOP && (equip_index[EQI_HEAD_MID] == index || equip_index[EQI_HEAD_LOW] == index))
 		return true;
 		return true;
 	// Headgear with Mid & Low location
 	// Headgear with Mid & Low location
-	else if (eqi == EQI_COSTUME_MID && equip_index[EQI_COSTUME_LOW] == index)
+	if (eqi == EQI_COSTUME_MID && equip_index[EQI_COSTUME_LOW] == index)
 		return true;
 		return true;
 	// Headgear with Top & Mid or Low location
 	// Headgear with Top & Mid or Low location
-	else if (eqi == EQI_COSTUME_TOP && (equip_index[EQI_COSTUME_MID] == index || equip_index[EQI_COSTUME_LOW] == index))
+	if (eqi == EQI_COSTUME_TOP && (equip_index[EQI_COSTUME_MID] == index || equip_index[EQI_COSTUME_LOW] == index))
 		return true;
 		return true;
 	return false;
 	return false;
 }
 }
@@ -11130,6 +11210,7 @@ void do_init_pc(void) {
 	add_timer_func_list(pc_talisman_timer, "pc_talisman_timer");
 	add_timer_func_list(pc_talisman_timer, "pc_talisman_timer");
 	add_timer_func_list(pc_global_expiration_timer, "pc_global_expiration_timer");
 	add_timer_func_list(pc_global_expiration_timer, "pc_global_expiration_timer");
 	add_timer_func_list(pc_expiration_timer, "pc_expiration_timer");
 	add_timer_func_list(pc_expiration_timer, "pc_expiration_timer");
+	add_timer_func_list(pc_autotrade_timer, "pc_autotrade_timer");
 
 
 	add_timer(gettick() + autosave_interval, pc_autosave, 0, 0);
 	add_timer(gettick() + autosave_interval, pc_autosave, 0, 0);
 
 

+ 21 - 3
src/map/pc.h

@@ -252,7 +252,7 @@ struct map_session_data {
 	struct registry save_reg;
 	struct registry save_reg;
 
 
 	struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
 	struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
-	int equip_index[EQI_MAX];
+	short equip_index[EQI_MAX];
 	unsigned int weight,max_weight;
 	unsigned int weight,max_weight;
 	int cart_weight,cart_num,cart_weight_max;
 	int cart_weight,cart_num,cart_weight_max;
 	int fd;
 	int fd;
@@ -610,6 +610,7 @@ struct map_session_data {
 	time_t expiration_time;
 	time_t expiration_time;
 
 
 	short last_addeditem_index; /// Index of latest item added
 	short last_addeditem_index; /// Index of latest item added
+	int autotrade_tid;
 };
 };
 
 
 struct eri *pc_sc_display_ers; /// Player's SC display table
 struct eri *pc_sc_display_ers; /// Player's SC display table
@@ -665,6 +666,19 @@ enum ammo_type {
 	A_THROWWEAPON	//9
 	A_THROWWEAPON	//9
 };
 };
 
 
+enum idletime_option {
+	IDLE_WALK          = 0x001,
+	IDLE_USESKILLTOID  = 0x002,
+	IDLE_USESKILLTOPOS = 0x004,
+	IDLE_USEITEM       = 0x008,
+	IDLE_ATTACK        = 0x010,
+	IDLE_CHAT          = 0x020,
+	IDLE_SIT           = 0x040,
+	IDLE_EMOTION       = 0x080,
+	IDLE_DROPITEM      = 0x100,
+	IDLE_ATCOMMAND     = 0x200,
+};
+
 struct {
 struct {
 	unsigned int base_hp[MAX_LEVEL], base_sp[MAX_LEVEL]; //Storage for the first calculation with hp/sp factor and multiplicator
 	unsigned int base_hp[MAX_LEVEL], base_sp[MAX_LEVEL]; //Storage for the first calculation with hp/sp factor and multiplicator
 	int hp_factor, hp_multiplicator, sp_factor;
 	int hp_factor, hp_multiplicator, sp_factor;
@@ -837,6 +851,7 @@ short pc_checkequip(struct map_session_data *sd,int pos);
 bool pc_checkequip2(struct map_session_data *sd, unsigned short nameid, int min, int max);
 bool pc_checkequip2(struct map_session_data *sd, unsigned short nameid, int min, int max);
 
 
 void pc_scdata_received(struct map_session_data *sd);
 void pc_scdata_received(struct map_session_data *sd);
+void pc_check_expiration(struct map_session_data *sd);
 int pc_expiration_timer(int tid, unsigned int tick, int id, intptr_t data);
 int pc_expiration_timer(int tid, unsigned int tick, int id, intptr_t data);
 int pc_global_expiration_timer(int tid, unsigned tick, int id, intptr_t data);
 int pc_global_expiration_timer(int tid, unsigned tick, int id, intptr_t data);
 void pc_expire_check(struct map_session_data *sd);
 void pc_expire_check(struct map_session_data *sd);
@@ -995,8 +1010,9 @@ struct map_session_data *pc_get_child(struct map_session_data *sd);
 void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick);
 void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick);
 void pc_regen (struct map_session_data *sd, unsigned int diff_tick);
 void pc_regen (struct map_session_data *sd, unsigned int diff_tick);
 
 
-void pc_setstand(struct map_session_data *sd);
+bool pc_setstand(struct map_session_data *sd, bool force);
 bool pc_candrop(struct map_session_data *sd,struct item *item);
 bool pc_candrop(struct map_session_data *sd,struct item *item);
+bool pc_can_attack(struct map_session_data *sd, int target_id);
 
 
 int pc_jobid2mapid(unsigned short b_class);	// Skotlex
 int pc_jobid2mapid(unsigned short b_class);	// Skotlex
 int pc_mapid2jobid(unsigned short class_, int sex);	// Skotlex
 int pc_mapid2jobid(unsigned short class_, int sex);	// Skotlex
@@ -1106,10 +1122,12 @@ void pc_itemgrouphealrate_clear(struct map_session_data *sd);
 short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid);
 short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid);
 short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id);
 short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id);
 
 
-bool pc_is_same_equip_index(enum equip_index eqi, int *equip_index, int8 index);
+bool pc_is_same_equip_index(enum equip_index eqi, short *equip_index, short index);
 /// Check if player is Taekwon Ranker and the level is >= 90 (battle_config.taekwon_ranker_min_lv)
 /// Check if player is Taekwon Ranker and the level is >= 90 (battle_config.taekwon_ranker_min_lv)
 #define pc_is_taekwon_ranker(sd) (((sd)->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && (sd)->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank((sd)->status.char_id,MAPID_TAEKWON))
 #define pc_is_taekwon_ranker(sd) (((sd)->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && (sd)->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank((sd)->status.char_id,MAPID_TAEKWON))
 
 
+int pc_autotrade_timer(int tid, unsigned int tick, int id, intptr_t data);
+
 #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
 #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
 int pc_level_penalty_mod(struct map_session_data *sd, int mob_level, uint32 mob_class, int type);
 int pc_level_penalty_mod(struct map_session_data *sd, int mob_level, uint32 mob_class, int type);
 #endif
 #endif

+ 37 - 29
src/map/script.c

@@ -308,7 +308,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag);
 const char* parse_syntax(const char* p);
 const char* parse_syntax(const char* p);
 static int parse_syntax_for_flag = 0;
 static int parse_syntax_for_flag = 0;
 
 
-extern int current_equip_item_index; //for New CARDS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus]
+extern short current_equip_item_index; //for New CARDS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus]
 int potion_flag=0; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
 int potion_flag=0; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
 int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0;
 int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0;
 int potion_target=0;
 int potion_target=0;
@@ -4910,7 +4910,7 @@ BUILDIN_FUNC(prompt)
 		sd->state.menu_or_input = 0;
 		sd->state.menu_or_input = 0;
 		pc_setreg(sd, add_str("@menu"), 0xff);
 		pc_setreg(sd, add_str("@menu"), 0xff);
 		script_pushint(st, 0xff);
 		script_pushint(st, 0xff);
-		st->state = END;
+		st->state = RUN;
 	}
 	}
 	else
 	else
 	{// return selected option
 	{// return selected option
@@ -6466,6 +6466,7 @@ BUILDIN_FUNC(checkweight2){
  * getitembound <item id>,<amount>,<type>{,<account ID>};
  * getitembound <item id>,<amount>,<type>{,<account ID>};
  * getitembound "<item id>",<amount>,<type>{,<account ID>};
  * getitembound "<item id>",<amount>,<type>{,<account ID>};
  * Type:
  * Type:
+ *	0 - No bound
  *	1 - Account Bound
  *	1 - Account Bound
  *	2 - Guild Bound
  *	2 - Guild Bound
  *	3 - Party Bound
  *	3 - Party Bound
@@ -6509,20 +6510,19 @@ BUILDIN_FUNC(getitem)
 	memset(&it,0,sizeof(it));
 	memset(&it,0,sizeof(it));
 	it.nameid = nameid;
 	it.nameid = nameid;
 	it.identify = 1;
 	it.identify = 1;
+	it.bound = BOUND_NONE;
 
 
 	if( !strcmp(command,"getitembound") ) {
 	if( !strcmp(command,"getitembound") ) {
 		char bound = script_getnum(st,4);
 		char bound = script_getnum(st,4);
-		if( bound > BOUND_NONE && bound < BOUND_MAX ) {
-			it.bound = bound;
-			if( script_hasdata(st,5) )
-				sd = map_id2sd(script_getnum(st,5));
-			else
-				sd = script_rid2sd(st); // Attached player
-		}
-		else { //Not a correct bound type
+		if( bound < BOUND_NONE || bound >= BOUND_MAX ) {
 			ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound);
 			ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound);
 			return SCRIPT_CMD_FAILURE;
 			return SCRIPT_CMD_FAILURE;
 		}
 		}
+		if( script_hasdata(st,5) )
+			sd = map_id2sd(script_getnum(st,5));
+		else
+			sd = script_rid2sd(st); // Attached player
+		it.bound = bound;
 	} else if( script_hasdata(st,4) )
 	} else if( script_hasdata(st,4) )
 		sd = map_id2sd(script_getnum(st,4)); // <Account ID>
 		sd = map_id2sd(script_getnum(st,4)); // <Account ID>
 	else
 	else
@@ -6554,7 +6554,17 @@ BUILDIN_FUNC(getitem)
 }
 }
 
 
 /*==========================================
 /*==========================================
+ * getitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
+ * getitem2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
  *
  *
+ * getitembound2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<bound type>{,<account ID>};
+ * getitembound2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>,<bound type>{,<account ID>};
+ * Type:
+ *	0 - No bound
+ *	1 - Account Bound
+ *	2 - Guild Bound
+ *	3 - Party Bound
+ *	4 - Character Bound
  *------------------------------------------*/
  *------------------------------------------*/
 BUILDIN_FUNC(getitem2)
 BUILDIN_FUNC(getitem2)
 {
 {
@@ -6572,16 +6582,14 @@ BUILDIN_FUNC(getitem2)
 
 
 	if( !strcmp(command,"getitembound2") ) {
 	if( !strcmp(command,"getitembound2") ) {
 		bound = script_getnum(st,11);
 		bound = script_getnum(st,11);
-		if( bound > BOUND_NONE && bound < BOUND_MAX ) {
-			if( script_hasdata(st,12) )
-				sd = map_id2sd(script_getnum(st,12));
-			else
-				sd = script_rid2sd(st); // Attached player
-		}
-		else {
+		if( bound < BOUND_NONE || bound >= BOUND_MAX ) {
 			ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
 			ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
 			return SCRIPT_CMD_FAILURE;
 			return SCRIPT_CMD_FAILURE;
 		}
 		}
+		if( script_hasdata(st,12) )
+			sd = map_id2sd(script_getnum(st,12));
+		else
+			sd = script_rid2sd(st); // Attached player
 	} else if( script_hasdata(st,11) )
 	} else if( script_hasdata(st,11) )
 		sd = map_id2sd(script_getnum(st,11)); // <Account ID>
 		sd = map_id2sd(script_getnum(st,11)); // <Account ID>
 	else
 	else
@@ -13137,8 +13145,7 @@ BUILDIN_FUNC(skilleffect)
 
 
 	/* Ensure we're standing because the following packet causes the client to virtually set the char to stand,
 	/* Ensure we're standing because the following packet causes the client to virtually set the char to stand,
 	 * which leaves the server thinking it still is sitting. */
 	 * which leaves the server thinking it still is sitting. */
-	if( pc_issit(sd) ) {
-		pc_setstand(sd);
+	if( pc_issit(sd) && pc_setstand(sd, false) ) {
 		skill_sit(sd, 0);
 		skill_sit(sd, 0);
 		clif_standing(&sd->bl);
 		clif_standing(&sd->bl);
 	}
 	}
@@ -14006,7 +14013,7 @@ BUILDIN_FUNC(isday)
 BUILDIN_FUNC(isequippedcnt)
 BUILDIN_FUNC(isequippedcnt)
 {
 {
 	TBL_PC *sd;
 	TBL_PC *sd;
-	int i, j, k, id = 1;
+	int i, id = 1;
 	int ret = 0;
 	int ret = 0;
 
 
 	sd = script_rid2sd(st);
 	sd = script_rid2sd(st);
@@ -14016,13 +14023,13 @@ BUILDIN_FUNC(isequippedcnt)
 	}
 	}
 
 
 	for (i=0; id!=0; i++) {
 	for (i=0; id!=0; i++) {
+		short j;
 		FETCH (i+2, id) else id = 0;
 		FETCH (i+2, id) else id = 0;
 		if (id <= 0)
 		if (id <= 0)
 			continue;
 			continue;
 
 
 		for (j=0; j<EQI_MAX; j++) {
 		for (j=0; j<EQI_MAX; j++) {
-			int index;
-			index = sd->equip_index[j];
+			short index = sd->equip_index[j];
 			if(index < 0)
 			if(index < 0)
 				continue;
 				continue;
 			if (pc_is_same_equip_index((enum equip_index)j, sd->equip_index, index))
 			if (pc_is_same_equip_index((enum equip_index)j, sd->equip_index, index))
@@ -14035,6 +14042,7 @@ BUILDIN_FUNC(isequippedcnt)
 				if (sd->inventory_data[index]->nameid == id)
 				if (sd->inventory_data[index]->nameid == id)
 					ret+= sd->status.inventory[index].amount;
 					ret+= sd->status.inventory[index].amount;
 			} else { //Count cards.
 			} else { //Count cards.
+				short k;
 				if (itemdb_isspecial(sd->status.inventory[index].card[0]))
 				if (itemdb_isspecial(sd->status.inventory[index].card[0]))
 					continue; //No cards
 					continue; //No cards
 				for(k=0; k<sd->inventory_data[index]->slot; k++) {
 				for(k=0; k<sd->inventory_data[index]->slot; k++) {
@@ -14058,8 +14066,7 @@ BUILDIN_FUNC(isequippedcnt)
 BUILDIN_FUNC(isequipped)
 BUILDIN_FUNC(isequipped)
 {
 {
 	TBL_PC *sd;
 	TBL_PC *sd;
-	int i, j, k, id = 1;
-	int index, flag;
+	int i, id = 1;
 	int ret = -1;
 	int ret = -1;
 	//Original hash to reverse it when full check fails.
 	//Original hash to reverse it when full check fails.
 	unsigned int setitem_hash = 0, setitem_hash2 = 0;
 	unsigned int setitem_hash = 0, setitem_hash2 = 0;
@@ -14068,18 +14075,19 @@ BUILDIN_FUNC(isequipped)
 
 
 	if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing...
 	if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing...
 		script_pushint(st,0);
 		script_pushint(st,0);
-		return 0;
+		return SCRIPT_CMD_SUCCESS;
 	}
 	}
 
 
 	setitem_hash = sd->bonus.setitem_hash;
 	setitem_hash = sd->bonus.setitem_hash;
 	setitem_hash2 = sd->bonus.setitem_hash2;
 	setitem_hash2 = sd->bonus.setitem_hash2;
 	for (i=0; id!=0; i++) {
 	for (i=0; id!=0; i++) {
+		int flag = 0;
+		short j;
 		FETCH (i+2, id) else id = 0;
 		FETCH (i+2, id) else id = 0;
 		if (id <= 0)
 		if (id <= 0)
 			continue;
 			continue;
-		flag = 0;
 		for (j=0; j<EQI_MAX; j++) {
 		for (j=0; j<EQI_MAX; j++) {
-			index = sd->equip_index[j];
+			short index = sd->equip_index[j];
 			if(index < 0)
 			if(index < 0)
 				continue;
 				continue;
 			if (pc_is_same_equip_index((enum equip_index)i, sd->equip_index, index))
 			if (pc_is_same_equip_index((enum equip_index)i, sd->equip_index, index))
@@ -14094,6 +14102,7 @@ BUILDIN_FUNC(isequipped)
 				flag = 1;
 				flag = 1;
 				break;
 				break;
 			} else { //Cards
 			} else { //Cards
+				short k;
 				if (sd->inventory_data[index]->slot == 0 ||
 				if (sd->inventory_data[index]->slot == 0 ||
 					itemdb_isspecial(sd->status.inventory[index].card[0]))
 					itemdb_isspecial(sd->status.inventory[index].card[0]))
 					continue;
 					continue;
@@ -18288,8 +18297,7 @@ BUILDIN_FUNC(stand)
 	if( sd == NULL)
 	if( sd == NULL)
 		return SCRIPT_CMD_FAILURE;
 		return SCRIPT_CMD_FAILURE;
 
 
-	if( pc_issit(sd) ) {
-		pc_setstand(sd);
+	if( pc_issit(sd) && pc_setstand(sd, false)) {
 		skill_sit(sd, 0);
 		skill_sit(sd, 0);
 		clif_standing(&sd->bl);
 		clif_standing(&sd->bl);
 	}
 	}

+ 1 - 2
src/map/searchstore.c

@@ -114,7 +114,6 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
 	struct s_search_store_search s;
 	struct s_search_store_search s;
 	searchstore_searchall_t store_searchall;
 	searchstore_searchall_t store_searchall;
 	time_t querytime;
 	time_t querytime;
-	DBMap *vending_db = vending_getdb();
 
 
 	if( !battle_config.feature_search_stores ) {
 	if( !battle_config.feature_search_stores ) {
 		return;
 		return;
@@ -179,7 +178,7 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned
 	s.card_count = card_count;
 	s.card_count = card_count;
 	s.min_price  = min_price;
 	s.min_price  = min_price;
 	s.max_price  = max_price;
 	s.max_price  = max_price;
-	iter         = db_iterator(vending_db);
+	iter         = db_iterator((type == SEARCHTYPE_VENDING) ? vending_getdb() : buyingstore_getdb());
 
 
 	for( pl_sd = dbi_first(iter); dbi_exists(iter);  pl_sd = dbi_next(iter) ) {
 	for( pl_sd = dbi_first(iter); dbi_exists(iter);  pl_sd = dbi_next(iter) ) {
 		if( sd == pl_sd ) {// skip own shop, if any
 		if( sd == pl_sd ) {// skip own shop, if any

+ 265 - 226
src/map/skill.c

@@ -2081,7 +2081,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 	 	!(skill_get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) &&
 	 	!(skill_get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) &&
 		(rate=pc_checkskill(sd,HW_SOULDRAIN))>0
 		(rate=pc_checkskill(sd,HW_SOULDRAIN))>0
 	){	//Soul Drain should only work on targetted spells [Skotlex]
 	){	//Soul Drain should only work on targetted spells [Skotlex]
-		if (pc_issit(sd)) pc_setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex]
+		if (pc_issit(sd)) pc_setstand(sd, true); //Character stuck in attacking animation while 'sitting' fix. [Skotlex]
 		clif_skill_nodamage(src,bl,HW_SOULDRAIN,rate,1);
 		clif_skill_nodamage(src,bl,HW_SOULDRAIN,rate,1);
 		status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2);
 		status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2);
 	}
 	}
@@ -2277,7 +2277,7 @@ int skill_break_equip (struct block_list *src,struct block_list *bl, unsigned sh
 		return 0;
 		return 0;
 	if (sd) {
 	if (sd) {
 		for (i = 0; i < EQI_MAX; i++) {
 		for (i = 0; i < EQI_MAX; i++) {
-			int j = sd->equip_index[i];
+			short j = sd->equip_index[i];
 			if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j])
 			if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j])
 				continue;
 				continue;
 
 
@@ -2447,6 +2447,36 @@ static int skill_magic_reflect(struct block_list* src, struct block_list* bl, in
 	return 0;
 	return 0;
 }
 }
 
 
+/**
+ * Checks whether a skill can be used in combos or not
+ * @param skill_id: Target skill
+ * @return true: Skill is a combo, false: otherwise
+ * @author Panikon
+ **/
+bool skill_is_combo(uint16 skill_id) {
+	switch(skill_id) {
+		case MO_CHAINCOMBO:
+		case MO_COMBOFINISH:
+		case CH_TIGERFIST:
+		case CH_CHAINCRUSH:
+		case MO_EXTREMITYFIST:
+		case TK_TURNKICK:
+		case TK_STORMKICK:
+		case TK_DOWNKICK:
+		case TK_COUNTER:
+		case TK_JUMPKICK:
+		case HT_POWER:
+		case GC_COUNTERSLASH:
+		case GC_WEAPONCRUSH:
+		case SR_FALLENEMPIRE:
+		case SR_DRAGONCOMBO:
+		case SR_TIGERCANNON:
+		case SR_GATEOFHELL:
+			return true;
+	}
+	return false;
+}
+
 /*
 /*
  * Combo handler, start stop combo status
  * Combo handler, start stop combo status
  */
  */
@@ -2777,7 +2807,8 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 			{	//Consume one Fragment per hit of the casted skill? [Skotlex]
 			{	//Consume one Fragment per hit of the casted skill? [Skotlex]
 				type = tsd?pc_search_inventory (tsd, ITEMID_FRAGMENT_OF_CRYSTAL):0;
 				type = tsd?pc_search_inventory (tsd, ITEMID_FRAGMENT_OF_CRYSTAL):0;
 				if (type >= 0) {
 				if (type >= 0) {
-					if ( tsd ) pc_delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME);
+					if ( tsd )
+						pc_delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME);
 					dmg.damage = dmg.damage2 = 0;
 					dmg.damage = dmg.damage2 = 0;
 					dmg.dmg_lv = ATK_MISS;
 					dmg.dmg_lv = ATK_MISS;
 					tsc->data[SC_SPIRIT]->val3 = skill_id;
 					tsc->data[SC_SPIRIT]->val3 = skill_id;
@@ -2789,7 +2820,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 		/**
 		/**
 		 * Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target
 		 * Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target
 		 **/
 		 **/
-		#if MAGIC_REFLECTION_TYPE
+#if MAGIC_REFLECTION_TYPE
 #ifdef RENEWAL
 #ifdef RENEWAL
 			if( dmg.dmg_lv != ATK_MISS ) { //Wiz SL cancelled and consumed fragment
 			if( dmg.dmg_lv != ATK_MISS ) { //Wiz SL cancelled and consumed fragment
 #else
 #else
@@ -2819,8 +2850,9 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 					dmg.damage -= dmg.damage * (6 * (1+per)) / 100;
 					dmg.damage -= dmg.damage * (6 * (1+per)) / 100;
 				}
 				}
 			}
 			}
-		#endif
+#endif
 		}
 		}
+
 		if(tsc && tsc->data[SC_MAGICROD] && src == dsrc) {
 		if(tsc && tsc->data[SC_MAGICROD] && src == dsrc) {
 			int sp = skill_get_sp(skill_id,skill_lv);
 			int sp = skill_get_sp(skill_id,skill_lv);
 			dmg.damage = dmg.damage2 = 0;
 			dmg.damage = dmg.damage2 = 0;
@@ -2853,47 +2885,51 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 	}
 	}
 
 
 	//Skill hit type
 	//Skill hit type
-	type=(skill_id==0)?5:skill_get_hit(skill_id);
+	type = (skill_id == 0) ? 5 : skill_get_hit(skill_id);
 
 
-	switch(skill_id){
-	case SC_TRIANGLESHOT:
-		if(rnd()%100 > (1 + skill_lv) ) dmg.blewcount = 0;
-		break;
-	default:
-		if(damage < dmg.div_ && skill_id != CH_PALMSTRIKE)
-			dmg.blewcount = 0; //only pushback when it hit for other
-		break;
+	switch( skill_id ) {
+		case SC_TRIANGLESHOT:
+			if( rnd()%100 > (1 + skill_lv) )
+				dmg.blewcount = 0;
+			break;
+		default:
+			if (damage < dmg.div_ && skill_id != CH_PALMSTRIKE)
+				dmg.blewcount = 0; //only pushback when it hit for other
+			break;
 	}
 	}
 
 
-	switch(skill_id){
-	case CR_GRANDCROSS:
-	case NPC_GRANDDARKNESS:
-		if(battle_config.gx_disptype) dsrc = src;
-		if(src == bl) type = 4;
-		else flag|=SD_ANIMATION;
-		break;
-	case NJ_TATAMIGAESHI: //For correct knockback.
-		dsrc = src;
-		flag|=SD_ANIMATION;
-		break;
-	case TK_COUNTER: {	//bonus from SG_FRIEND [Komurka]
-		int level;
-		if(sd->status.party_id>0 && (level = pc_checkskill(sd,SG_FRIEND)))
-			party_skill_check(sd, sd->status.party_id, TK_COUNTER,level);
-		}
-		break;
-	case SL_STIN:
-	case SL_STUN:
-		if (skill_lv >= 7){
-			struct status_change *sc = status_get_sc(src);
-			if(sc && !sc->data[SC_SMA])
-				sc_start(src,src,SC_SMA,100,skill_lv,skill_get_time(SL_SMA, skill_lv));
-		}
-		break;
-	case GS_FULLBUSTER:
-		if(sd) //Can't attack nor use items until skill's delay expires. [Skotlex]
-			sd->ud.attackabletime = sd->canuseitem_tick = sd->ud.canact_tick;
-		break;
+	switch( skill_id ) {
+		case CR_GRANDCROSS:
+		case NPC_GRANDDARKNESS:
+			if( battle_config.gx_disptype)
+				dsrc = src;
+			if( src == bl)
+				type = 4;
+			else
+				flag|= SD_ANIMATION;
+			break;
+		case NJ_TATAMIGAESHI: //For correct knockback.
+			dsrc = src;
+			flag|= SD_ANIMATION;
+			break;
+		case TK_COUNTER: {	//bonus from SG_FRIEND [Komurka]
+			int level;
+			if( sd->status.party_id>0 && (level = pc_checkskill(sd,SG_FRIEND)) )
+				party_skill_check(sd, sd->status.party_id, TK_COUNTER,level);
+			}
+			break;
+		case SL_STIN:
+		case SL_STUN:
+			if (skill_lv >= 7) {
+				struct status_change *sc = status_get_sc(src);
+				if (sc && !sc->data[SC_SMA])
+					sc_start(src,src,SC_SMA,100,skill_lv,skill_get_time(SL_SMA, skill_lv));
+			}
+			break;
+		case GS_FULLBUSTER:
+			if (sd) //Can't attack nor use items until skill's delay expires. [Skotlex]
+				sd->ud.attackabletime = sd->canuseitem_tick = sd->ud.canact_tick;
+			break;
 	}
 	}
 
 
 	//combo handling
 	//combo handling
@@ -2901,114 +2937,114 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 
 
 	//Display damage.
 	//Display damage.
 	switch( skill_id ) {
 	switch( skill_id ) {
-	case PA_GOSPEL: //Should look like Holy Cross [Skotlex]
-		dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, 5);
-		break;
-	//Skills that need be passed as a normal attack for the client to display correctly.
-	case HVAN_EXPLOSION:
-	case NPC_SELFDESTRUCTION:
-		if(src->type==BL_PC)
-			dmg.blewcount = 10;
-		dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex]
-		// fall through
-	case KN_AUTOCOUNTER:
-	case NPC_CRITICALSLASH:
-	case TF_DOUBLE:
-	case GS_CHAINACTION:
-		dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2);
-		break;
-
-	case AS_SPLASHER:
-		if( flag&SD_ANIMATION ) // the surrounding targets
-			dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, 5); // needs -1 as skill level
-		else // the central target doesn't display an animation
-			dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, 5); // needs -2(!) as skill level
-		break;
-	case WL_HELLINFERNO:
-	case SR_EARTHSHAKER:
-		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,6);
-		break;
-	case WL_SOULEXPANSION:
-	case WL_COMET:
-	case KO_MUCHANAGE:
-	case NJ_HUUMA:
-		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,8);
-		break;
-	case WL_CHAINLIGHTNING_ATK:
-		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6);
-		break;
-	case LG_OVERBRAND:
-	case LG_OVERBRAND_BRANDISH:
-		dmg.amotion = status_get_amotion(src) * 2;
-	case LG_OVERBRAND_PLUSATK:
-		dmg.dmotion = clif_skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
-		break;
-	case EL_FIRE_BOMB:
-	case EL_FIRE_BOMB_ATK:
-	case EL_FIRE_WAVE:
-	case EL_FIRE_WAVE_ATK:
-	case EL_FIRE_MANTLE:
-	case EL_CIRCLE_OF_FIRE:
-	case EL_FIRE_ARROW:
-	case EL_ICE_NEEDLE:
-	case EL_WATER_SCREW:
-	case EL_WATER_SCREW_ATK:
-	case EL_WIND_SLASH:
-	case EL_TIDAL_WEAPON:
-	case EL_ROCK_CRUSHER:
-	case EL_ROCK_CRUSHER_ATK:
-	case EL_HURRICANE:
-	case EL_HURRICANE_ATK:
-	case KO_BAKURETSU:
-	case GN_CRAZYWEED_ATK:
-	case NC_MAGMA_ERUPTION:
-		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
-		break;
-	case GN_FIRE_EXPANSION_ACID:
-		dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, CR_ACIDDEMONSTRATION, skill_lv, 8);
-		break;
-	case GN_SLINGITEM_RANGEMELEEATK:
-		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6);
-		break;
-	case EL_STONE_RAIN:
-		dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5);
-		break;
-	case WM_SEVERE_RAINSTORM_MELEE:
-		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,6);
-		break;
-	case WM_REVERBERATION_MELEE:
-	case WM_REVERBERATION_MAGIC:
-		dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6);
-		break;
-	case HT_CLAYMORETRAP:
-	case HT_BLASTMINE:
-	case HT_FLASHER:
-	case HT_FREEZINGTRAP:
-	case RA_CLUSTERBOMB:
-	case RA_FIRINGTRAP:
-	case RA_ICEBOUNDTRAP:
-		dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id,flag&SD_LEVEL?-1:skill_lv, 5);
-		if( dsrc != src ) // avoid damage display redundancy
+		case PA_GOSPEL: //Should look like Holy Cross [Skotlex]
+			dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, 5);
+			break;
+		//Skills that need be passed as a normal attack for the client to display correctly.
+		case HVAN_EXPLOSION:
+		case NPC_SELFDESTRUCTION:
+			if(src->type == BL_PC)
+				dmg.blewcount = 10;
+			dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex]
+			// fall through
+		case KN_AUTOCOUNTER:
+		case NPC_CRITICALSLASH:
+		case TF_DOUBLE:
+		case GS_CHAINACTION:
+			dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,(enum e_damage_type)dmg.type,dmg.damage2);
+			break;
+
+		case AS_SPLASHER:
+			if( flag&SD_ANIMATION ) // the surrounding targets
+				dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, 5); // needs -1 as skill level
+			else // the central target doesn't display an animation
+				dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, 5); // needs -2(!) as skill level
+			break;
+		case WL_HELLINFERNO:
+		case SR_EARTHSHAKER:
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,6);
+			break;
+		case WL_SOULEXPANSION:
+		case WL_COMET:
+		case KO_MUCHANAGE:
+		case NJ_HUUMA:
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,8);
+			break;
+		case WL_CHAINLIGHTNING_ATK:
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6);
+			break;
+		case LG_OVERBRAND:
+		case LG_OVERBRAND_BRANDISH:
+			dmg.amotion = status_get_amotion(src) * 2;
+		case LG_OVERBRAND_PLUSATK:
+			dmg.dmotion = clif_skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
+			break;
+		case EL_FIRE_BOMB:
+		case EL_FIRE_BOMB_ATK:
+		case EL_FIRE_WAVE:
+		case EL_FIRE_WAVE_ATK:
+		case EL_FIRE_MANTLE:
+		case EL_CIRCLE_OF_FIRE:
+		case EL_FIRE_ARROW:
+		case EL_ICE_NEEDLE:
+		case EL_WATER_SCREW:
+		case EL_WATER_SCREW_ATK:
+		case EL_WIND_SLASH:
+		case EL_TIDAL_WEAPON:
+		case EL_ROCK_CRUSHER:
+		case EL_ROCK_CRUSHER_ATK:
+		case EL_HURRICANE:
+		case EL_HURRICANE_ATK:
+		case KO_BAKURETSU:
+		case GN_CRAZYWEED_ATK:
+		case NC_MAGMA_ERUPTION:
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
+			break;
+		case GN_FIRE_EXPANSION_ACID:
+			dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, CR_ACIDDEMONSTRATION, skill_lv, 8);
+			break;
+		case GN_SLINGITEM_RANGEMELEEATK:
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6);
+			break;
+		case EL_STONE_RAIN:
+			dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5);
+			break;
+		case WM_SEVERE_RAINSTORM_MELEE:
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,6);
+			break;
+		case WM_REVERBERATION_MELEE:
+		case WM_REVERBERATION_MAGIC:
+			dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6);
+			break;
+		case HT_CLAYMORETRAP:
+		case HT_BLASTMINE:
+		case HT_FLASHER:
+		case HT_FREEZINGTRAP:
+		case RA_CLUSTERBOMB:
+		case RA_FIRINGTRAP:
+		case RA_ICEBOUNDTRAP:
+			dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id,flag&SD_LEVEL?-1:skill_lv, 5);
+			if( dsrc != src ) // avoid damage display redundancy
+				break;
+		case HT_LANDMINE:
+			dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, type);
+			break;
+		case WZ_SIGHTBLASTER:
+			dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5);
+			break;
+		case AB_DUPLELIGHT_MELEE:
+		case AB_DUPLELIGHT_MAGIC:
+			dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */
+		default:
+			if( flag&SD_ANIMATION && dmg.div_ < 2 ) //Disabling skill animation doesn't works on multi-hit.
+				type = 5;
+			if( bl->type == BL_SKILL ){
+				TBL_SKILL *su = (TBL_SKILL*)bl;
+				if( su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP )// show damage on trap targets
+					clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5);
+			}
+			dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, type);
 			break;
 			break;
-	case HT_LANDMINE:
-		dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, type);
-		break;
-	case WZ_SIGHTBLASTER:
-		dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5);
-		break;
-	case AB_DUPLELIGHT_MELEE:
-	case AB_DUPLELIGHT_MAGIC:
-		dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */
-	default:
-		if( flag&SD_ANIMATION && dmg.div_ < 2 ) //Disabling skill animation doesn't works on multi-hit.
-			type = 5;
-		if( bl->type == BL_SKILL ){
-			TBL_SKILL *su = (TBL_SKILL*)bl;
-			if( su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP )// show damage on trap targets
-				clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5);
-		}
-		dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, type);
-		break;
 	}
 	}
 
 
 	map_freeblock_lock();
 	map_freeblock_lock();
@@ -3112,13 +3148,17 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 			) && check_distance_bl(bl, d_bl, sce->val3) )
 			) && check_distance_bl(bl, d_bl, sce->val3) )
 		{
 		{
 			if(!rmdamage){
 			if(!rmdamage){
-				clif_damage(d_bl,d_bl, gettick(), 0, 0, damage, 0, 0, 0);
+				clif_damage(d_bl,d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0);
 				status_fix_damage(NULL,d_bl, damage, 0);
 				status_fix_damage(NULL,d_bl, damage, 0);
-			} else {//Reflected magics are done directly on the target not on paladin
-				//This check is only for magical skill.
-				//For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage
-				clif_damage(bl,bl, gettick(), 0, 0, damage, 0, 0, 0);
-				status_fix_damage(bl,bl, damage, 0);
+			} else {
+				bool isDevotRdamage = false;
+				if (battle_config.devotion_rdamage && battle_config.devotion_rdamage > rand()%100)
+					isDevotRdamage = true;
+				// If !isDevotRdamage, reflected magics are done directly on the target not on paladin
+				// This check is only for magical skill.
+				// For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage
+				clif_damage(bl,(!isDevotRdamage) ? bl : d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0);
+				status_fix_damage(bl,(!isDevotRdamage) ? bl : d_bl, damage, 0);
 			}
 			}
 		}
 		}
 		else {
 		else {
@@ -4497,7 +4537,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 		break;
 		break;
 	case CH_PALMSTRIKE: //	Palm Strike takes effect 1sec after casting. [Skotlex]
 	case CH_PALMSTRIKE: //	Palm Strike takes effect 1sec after casting. [Skotlex]
 	//	clif_skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/
 	//	clif_skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/
-		clif_damage(src,bl,tick,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack.
+		clif_damage(src,bl,tick,status_get_amotion(src),0,-1,1,DMG_ENDURE,0); //Display an absorbed damage attack.
 		skill_addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
 		skill_addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
 		break;
 		break;
 
 
@@ -7890,7 +7930,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				case 3:	// 1000 damage, random armor destroyed
 				case 3:	// 1000 damage, random armor destroyed
 					{
 					{
 						status_fix_damage(src, bl, 1000, 0);
 						status_fix_damage(src, bl, 1000, 0);
-						clif_damage(src,bl,tick,0,0,1000,0,0,0);
+						clif_damage(src,bl,tick,0,0,1000,0,DMG_NORMAL,0);
 						if( !status_isdead(bl) ) {
 						if( !status_isdead(bl) ) {
 							int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT };
 							int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT };
 							skill_break_equip(src,bl, where[rnd()%5], 10000, BCT_ENEMY);
 							skill_break_equip(src,bl, where[rnd()%5], 10000, BCT_ENEMY);
@@ -7927,14 +7967,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					break;
 					break;
 				case 10:	// 6666 damage, atk matk halved, cursed
 				case 10:	// 6666 damage, atk matk halved, cursed
 					status_fix_damage(src, bl, 6666, 0);
 					status_fix_damage(src, bl, 6666, 0);
-					clif_damage(src,bl,tick,0,0,6666,0,0,0);
+					clif_damage(src,bl,tick,0,0,6666,0,DMG_NORMAL,0);
 					sc_start(src,bl,SC_INCATKRATE,100,-50,skill_get_time2(skill_id,skill_lv));
 					sc_start(src,bl,SC_INCATKRATE,100,-50,skill_get_time2(skill_id,skill_lv));
 					sc_start(src,bl,SC_INCMATKRATE,100,-50,skill_get_time2(skill_id,skill_lv));
 					sc_start(src,bl,SC_INCMATKRATE,100,-50,skill_get_time2(skill_id,skill_lv));
 					sc_start(src,bl,SC_CURSE,skill_lv,100,skill_get_time2(skill_id,skill_lv));
 					sc_start(src,bl,SC_CURSE,skill_lv,100,skill_get_time2(skill_id,skill_lv));
 					break;
 					break;
 				case 11:	// 4444 damage
 				case 11:	// 4444 damage
 					status_fix_damage(src, bl, 4444, 0);
 					status_fix_damage(src, bl, 4444, 0);
-					clif_damage(src,bl,tick,0,0,4444,0,0,0);
+					clif_damage(src,bl,tick,0,0,4444,0,DMG_NORMAL,0);
 					break;
 					break;
 				case 12:	// stun
 				case 12:	// stun
 					sc_start(src,bl,SC_STUN,100,skill_lv,5000);
 					sc_start(src,bl,SC_STUN,100,skill_lv,5000);
@@ -8087,8 +8127,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 						continue;
 						continue;
 					if(map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH))
 					if(map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH))
 						dx[j] = dy[j] = 0;
 						dx[j] = dy[j] = 0;
-					pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN);
-					called++;
+					if (!pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN))
+						called++;
 				}
 				}
 			}
 			}
 			if (sd)
 			if (sd)
@@ -8290,7 +8330,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 	case ALL_BUYING_STORE:
 	case ALL_BUYING_STORE:
 		if( sd )
 		if( sd )
 		{// players only, skill allows 5 buying slots
 		{// players only, skill allows 5 buying slots
-			clif_skill_nodamage(src, bl, skill_id, skill_lv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS));
+			clif_skill_nodamage(src, bl, skill_id, skill_lv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS) ? 0 : 1);
 		}
 		}
 		break;
 		break;
 	case RK_ENCHANTBLADE:
 	case RK_ENCHANTBLADE:
@@ -8348,7 +8388,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			int8 rate = rnd()%100;
 			int8 rate = rnd()%100;
 			int16 shields = ((rate < 20) ? 4 : (rate < 50) ? 3 : 2);
 			int16 shields = ((rate < 20) ? 4 : (rate < 50) ? 3 : 2);
 			sc_start4(src,bl,type,100,skill_lv,shields,1000,0,skill_get_time(skill_id,skill_lv));
 			sc_start4(src,bl,type,100,skill_lv,shields,1000,0,skill_get_time(skill_id,skill_lv));
-			clif_millenniumshield(sd,shields);
+			clif_millenniumshield(bl,shields);
 			clif_skill_nodamage(src,bl,skill_id,1,1);
 			clif_skill_nodamage(src,bl,skill_id,1,1);
 		}
 		}
 		break;
 		break;
@@ -8397,7 +8437,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				if( skill_area_temp[5]&0x10 ) {
 				if( skill_area_temp[5]&0x10 ) {
 					if( dstsd ) {
 					if( dstsd ) {
 						i = (rnd()%100 < 50) ? 4 : ((rnd()%100 < 80) ? 3 : 2);
 						i = (rnd()%100 < 50) ? 4 : ((rnd()%100 < 80) ? 3 : 2);
-						clif_millenniumshield(dstsd,i);
+						clif_millenniumshield(bl,i);
 						skill_area_temp[5] &= ~0x10;
 						skill_area_temp[5] &= ~0x10;
 						type = SC_MILLENNIUMSHIELD;
 						type = SC_MILLENNIUMSHIELD;
 					}
 					}
@@ -8843,32 +8883,33 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 	case WL_SUMMONWB:
 	case WL_SUMMONWB:
 	case WL_SUMMONSTONE:
 	case WL_SUMMONSTONE:
 		{
 		{
-			short element = 0, sctype = 0, pos = -1;
+			short element = 0, sctype = 0, pos = -1, j = 0;
 			struct status_change *sc = status_get_sc(src);
 			struct status_change *sc = status_get_sc(src);
-			if( !sc ) break;
 
 
-			for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ )
-			{
+			if( !sc )
+				break;
+
+			for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) {
 				if( !sctype && !sc->data[i] )
 				if( !sctype && !sc->data[i] )
 					sctype = i; // Take the free SC
 					sctype = i; // Take the free SC
-				if( sc->data[i] )
+				if( sc->data[i] ) {
 					pos = max(sc->data[i]->val2,pos);
 					pos = max(sc->data[i]->val2,pos);
+					j++;
+				}
 			}
 			}
 
 
-			if( !sctype )
-			{
+			if( !sctype || j >= skill_lv ) {
 				if( sd ) // No free slots to put SC
 				if( sd ) // No free slots to put SC
 					clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
 					clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
 				break;
 				break;
 			}
 			}
 
 
 			pos++; // Used in val2 for SC. Indicates the order of this ball
 			pos++; // Used in val2 for SC. Indicates the order of this ball
-			switch( skill_id )
-			{ // Set val1. The SC element for this ball
-			case WL_SUMMONFB:    element = WLS_FIRE;  break;
-			case WL_SUMMONBL:    element = WLS_WIND;  break;
-			case WL_SUMMONWB:    element = WLS_WATER; break;
-			case WL_SUMMONSTONE: element = WLS_STONE; break;
+			switch( skill_id ) { // Set val1. The SC element for this ball
+				case WL_SUMMONFB:    element = WLS_FIRE;  break;
+				case WL_SUMMONBL:    element = WLS_WIND;  break;
+				case WL_SUMMONWB:    element = WLS_WATER; break;
+				case WL_SUMMONSTONE: element = WLS_STONE; break;
 			}
 			}
 
 
 			sc_start4(src,src,(enum sc_type)sctype,100,element,pos,skill_lv,0,skill_get_time(skill_id,skill_lv));
 			sc_start4(src,src,(enum sc_type)sctype,100,element,pos,skill_lv,0,skill_get_time(skill_id,skill_lv));
@@ -9110,11 +9151,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		else if( sd ) {
 		else if( sd ) {
 			int opt = rnd()%3 + 1;
 			int opt = rnd()%3 + 1;
 			int val = 0, splash = 0;
 			int val = 0, splash = 0;
-			int index = sd->equip_index[EQI_HAND_L];
+			short index = sd->equip_index[EQI_HAND_L];
 			struct item_data *shield_data = NULL;
 			struct item_data *shield_data = NULL;
-			if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
-				shield_data = sd->inventory_data[index];
-			if( !shield_data || shield_data->type != IT_ARMOR ) {	// No shield?
+			if( index < 0 || !(shield_data = sd->inventory_data[index]) || shield_data->type == IT_ARMOR ) {	// No shield?
 				clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
 				clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
 				break;
 				break;
 			}
 			}
@@ -9184,8 +9223,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 
 
 				case 3: // refine based
 				case 3: // refine based
 					{
 					{
-						struct item *shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]];
-						if( !shield || !shield->refine ) {
+						struct item *shield = NULL;
+						if( sd->equip_index[EQI_HAND_L] < 0 || !(shield = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]) || !shield->refine ) {
 							clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 							clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 							break;
 							break;
 						}
 						}
@@ -9401,7 +9440,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				sc_start(src,bl, type, 100, skill_lv,skill_get_time(skill_id, skill_lv));
 				sc_start(src,bl, type, 100, skill_lv,skill_get_time(skill_id, skill_lv));
 		} else if( flag&2 ) {
 		} else if( flag&2 ) {
 			if( src->id != bl->id && battle_check_target(src,bl,BCT_ENEMY) > 0 )
 			if( src->id != bl->id && battle_check_target(src,bl,BCT_ENEMY) > 0 )
-				status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0));
+				status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,DMG_NORMAL,0));
 		} else if( sd ) {
 		} else if( sd ) {
 			short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4;
 			short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4;
 			if( !sd->status.party_id || (rnd()%100 > chance)) {
 			if( !sd->status.party_id || (rnd()%100 > chance)) {
@@ -9417,7 +9456,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			clif_skill_nodamage(src, bl, skill_id, skill_lv,
 			clif_skill_nodamage(src, bl, skill_id, skill_lv,
 				sc_start(src,src,SC_STOP,100,skill_lv,skill_get_time2(skill_id,skill_lv)));
 				sc_start(src,src,SC_STOP,100,skill_lv,skill_get_time2(skill_id,skill_lv)));
 			if( flag&2 ) // Dealed here to prevent conflicts
 			if( flag&2 ) // Dealed here to prevent conflicts
-				status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0));
+				status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,DMG_NORMAL,0));
 		}
 		}
 		break;
 		break;
 	case WM_SONG_OF_MANA:
 	case WM_SONG_OF_MANA:
@@ -9722,7 +9761,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		if( sd ) {
 		if( sd ) {
 			short ammo_id;
 			short ammo_id;
 			i = sd->equip_index[EQI_AMMO];
 			i = sd->equip_index[EQI_AMMO];
-			if( i <= 0 )
+			if( i < 0 )
 				break; // No ammo.
 				break; // No ammo.
 			ammo_id = sd->inventory_data[i]->nameid;
 			ammo_id = sd->inventory_data[i]->nameid;
 			if( ammo_id <= 0 )
 			if( ammo_id <= 0 )
@@ -9786,7 +9825,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 	case EL_WIND_STEP: {
 	case EL_WIND_STEP: {
 			struct elemental_data *ele = BL_CAST(BL_ELEM, src);
 			struct elemental_data *ele = BL_CAST(BL_ELEM, src);
 			if( ele ) {
 			if( ele ) {
-				sc_type type2 = type-1;
+				sc_type type2 = (sc_type)(type-1);
 				struct status_change *sc = status_get_sc(&ele->bl);
 				struct status_change *sc = status_get_sc(&ele->bl);
 
 
 				if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
 				if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
@@ -9814,7 +9853,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			struct elemental_data *ele = BL_CAST(BL_ELEM, src);
 			struct elemental_data *ele = BL_CAST(BL_ELEM, src);
 			if( ele ) {
 			if( ele ) {
 				struct status_change *sc = status_get_sc(&ele->bl);
 				struct status_change *sc = status_get_sc(&ele->bl);
-				sc_type type2 = type-1;
+				sc_type type2 = (sc_type)(type-1);
 
 
 				clif_skill_nodamage(src,src,skill_id,skill_lv,1);
 				clif_skill_nodamage(src,src,skill_id,skill_lv,1);
 				if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
 				if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) {
@@ -12219,8 +12258,8 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
 /*==========================================
 /*==========================================
  *
  *
  *------------------------------------------*/
  *------------------------------------------*/
-void ext_skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsigned int tick){skill_unit_onplace(src, bl, tick);}
-static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick)
+void ext_skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, unsigned int tick){skill_unit_onplace(unit, bl, tick);}
+static int skill_unit_onplace (struct skill_unit *unit, struct block_list *bl, unsigned int tick)
 {
 {
 	struct skill_unit_group *sg;
 	struct skill_unit_group *sg;
 	struct block_list *ss;
 	struct block_list *ss;
@@ -12229,14 +12268,14 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 	enum sc_type type;
 	enum sc_type type;
 	uint16 skill_id;
 	uint16 skill_id;
 
 
-	nullpo_ret(src);
+	nullpo_ret(unit);
 	nullpo_ret(bl);
 	nullpo_ret(bl);
 
 
-	if(bl->prev==NULL || !src->alive || status_isdead(bl))
+	if(bl->prev == NULL || !unit->alive || status_isdead(bl))
 		return 0;
 		return 0;
 
 
-	nullpo_ret(sg=src->group);
-	nullpo_ret(ss=map_id2bl(sg->src_id));
+	nullpo_ret(sg = unit->group);
+	nullpo_ret(ss = map_id2bl(sg->src_id));
 
 
 	if( (skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR) ||
 	if( (skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR) ||
 		map_getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) )
 		map_getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) )
@@ -12271,7 +12310,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 					const struct TimerData* td = sc->data[type]?get_timer(sc->data[type]->timer):NULL;
 					const struct TimerData* td = sc->data[type]?get_timer(sc->data[type]->timer):NULL;
 					if( td )
 					if( td )
 						sec = DIFF_TICK(td->tick, tick);
 						sec = DIFF_TICK(td->tick, tick);
-					map_moveblock(bl, src->bl.x, src->bl.y, tick);
+					map_moveblock(bl, unit->bl.x, unit->bl.y, tick);
 					clif_fixpos(bl);
 					clif_fixpos(bl);
 					sg->val2 = bl->id;
 					sg->val2 = bl->id;
 				}
 				}
@@ -12306,7 +12345,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 			if(bl->type==BL_PC && !working){
 			if(bl->type==BL_PC && !working){
 				struct map_session_data *sd = (struct map_session_data *)bl;
 				struct map_session_data *sd = (struct map_session_data *)bl;
 				if((!sd->chatID || battle_config.chat_warpportal)
 				if((!sd->chatID || battle_config.chat_warpportal)
-					&& sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y)
+					&& sd->ud.to_x == unit->bl.x && sd->ud.to_y == unit->bl.y)
 				{
 				{
 					int x = sg->val2>>16;
 					int x = sg->val2>>16;
 					int y = sg->val2&0xffff;
 					int y = sg->val2&0xffff;
@@ -12346,12 +12385,12 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 		case UNT_SUITON:
 		case UNT_SUITON:
 			if(!sce)
 			if(!sce)
 				sc_start4(ss, bl,type,100,sg->skill_lv,
 				sc_start4(ss, bl,type,100,sg->skill_lv,
-				map_flag_vs(bl->m) || battle_check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi.
+				map_flag_vs(bl->m) || battle_check_target(&unit->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi.
 				0,0,sg->limit);
 				0,0,sg->limit);
 			break;
 			break;
 
 
 		case UNT_HERMODE:
 		case UNT_HERMODE:
-			if (sg->src_id!=bl->id && battle_check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0)
+			if (sg->src_id!=bl->id && battle_check_target(&unit->bl,bl,BCT_PARTY|BCT_GUILD) > 0)
 				status_change_clear_buffs(bl,1); //Should dispell only allies.
 				status_change_clear_buffs(bl,1); //Should dispell only allies.
 		case UNT_RICHMANKIM:
 		case UNT_RICHMANKIM:
 		case UNT_ETERNALCHAOS:
 		case UNT_ETERNALCHAOS:
@@ -12391,7 +12430,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 			if (!sce)
 			if (!sce)
 			{
 			{
 				sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit);
 				sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit);
-				if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0)
+				if (battle_check_target(&unit->bl,bl,BCT_ENEMY)>0)
 					skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick);
 					skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick);
 			}
 			}
 			break;
 			break;
@@ -12403,9 +12442,9 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 
 
 		// officially, icewall has no problems existing on occupied cells [ultramage]
 		// officially, icewall has no problems existing on occupied cells [ultramage]
 		//	case UNT_ICEWALL: //Destroy the cell. [Skotlex]
 		//	case UNT_ICEWALL: //Destroy the cell. [Skotlex]
-		//		src->val1 = 0;
-		//		if(src->limit + sg->tick > tick + 700)
-		//			src->limit = DIFF_TICK(tick+700,sg->tick);
+		//		unit->val1 = 0;
+		//		if(unit->limit + sg->tick > tick + 700)
+		//			unit->limit = DIFF_TICK(tick+700,sg->tick);
 		//		break;
 		//		break;
 
 
 		case UNT_MOONLIT:
 		case UNT_MOONLIT:
@@ -13441,33 +13480,33 @@ static int skill_unit_effect (struct block_list* bl, va_list ap)
 /*==========================================
 /*==========================================
  *
  *
  *------------------------------------------*/
  *------------------------------------------*/
-int64 skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int64 damage, unsigned int tick)
+int64 skill_unit_ondamaged (struct skill_unit *unit, struct block_list *bl, int64 damage, unsigned int tick)
 {
 {
 	struct skill_unit_group *sg;
 	struct skill_unit_group *sg;
 
 
-	nullpo_ret(src);
-	nullpo_ret(sg=src->group);
+	nullpo_ret(unit);
+	nullpo_ret(sg = unit->group);
 
 
 	switch( sg->unit_id ) {
 	switch( sg->unit_id ) {
-	case UNT_BLASTMINE:
-	case UNT_SKIDTRAP:
-	case UNT_LANDMINE:
-	case UNT_SHOCKWAVE:
-	case UNT_SANDMAN:
-	case UNT_FLASHER:
-	case UNT_CLAYMORETRAP:
-	case UNT_FREEZINGTRAP:
-	case UNT_TALKIEBOX:
-	case UNT_ANKLESNARE:
-	case UNT_ICEWALL:
-	case UNT_REVERBERATION:
-	case UNT_WALLOFTHORN:
-	case UNT_NETHERWORLD:
-		src->val1-=(int)cap_value(damage,INT_MIN,INT_MAX);
-		break;
-	default:
-		damage = 0;
-		break;
+		case UNT_BLASTMINE:
+		case UNT_SKIDTRAP:
+		case UNT_LANDMINE:
+		case UNT_SHOCKWAVE:
+		case UNT_SANDMAN:
+		case UNT_FLASHER:
+		case UNT_CLAYMORETRAP:
+		case UNT_FREEZINGTRAP:
+		case UNT_TALKIEBOX:
+		case UNT_ANKLESNARE:
+		case UNT_ICEWALL:
+		case UNT_REVERBERATION:
+		case UNT_WALLOFTHORN:
+		case UNT_NETHERWORLD:
+			unit->val1 -= (int)cap_value(damage,INT_MIN,INT_MAX);
+			break;
+		default:
+			damage = 0;
+			break;
 	}
 	}
 	return damage;
 	return damage;
 }
 }
@@ -16511,7 +16550,7 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit) {
 			return false;
 			return false;
 		}
 		}
 
 
-		status_damage(bl, src, damage, 0, clif_damage(src, src, gettick(), 500, 500, damage, hit, (hit > 1 ? 8 : 0), 0), 0);
+		status_damage(bl, src, damage, 0, clif_damage(src, src, gettick(), 500, 500, damage, hit, (hit > 1 ? DMG_MULTI_HIT : DMG_NORMAL), 0), 0);
 		if( sc && sc->data[SC__SHADOWFORM] && (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) {
 		if( sc && sc->data[SC__SHADOWFORM] && (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) {
 			status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
 			status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
 			if( src->type == BL_PC )
 			if( src->type == BL_PC )

+ 4 - 3
src/map/skill.h

@@ -370,7 +370,7 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
 int skill_break_equip(struct block_list *src,struct block_list *bl, unsigned short where, int rate, int flag);
 int skill_break_equip(struct block_list *src,struct block_list *bl, unsigned short where, int rate, int flag);
 int skill_strip_equip(struct block_list *src,struct block_list *bl, unsigned short where, int rate, int lv, int time);
 int skill_strip_equip(struct block_list *src,struct block_list *bl, unsigned short where, int rate, int lv, int time);
 // Skills unit
 // Skills unit
-struct skill_unit_group* skill_id2group(int group_id);
+struct skill_unit_group *skill_id2group(int group_id);
 struct skill_unit_group *skill_unitsetting(struct block_list* src, uint16 skill_id, uint16 skill_lv, short x, short y, int flag);
 struct skill_unit_group *skill_unitsetting(struct block_list* src, uint16 skill_id, uint16 skill_lv, short x, short y, int flag);
 struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
 struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
 int skill_delunit(struct skill_unit *unit);
 int skill_delunit(struct skill_unit *unit);
@@ -379,8 +379,8 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
 #define skill_delunitgroup(group) skill_delunitgroup_(group,__FILE__,__LINE__,__func__)
 #define skill_delunitgroup(group) skill_delunitgroup_(group,__FILE__,__LINE__,__func__)
 int skill_clear_unitgroup(struct block_list *src);
 int skill_clear_unitgroup(struct block_list *src);
 int skill_clear_group(struct block_list *bl, int flag);
 int skill_clear_group(struct block_list *bl, int flag);
-void ext_skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsigned int tick);
-int64 skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,int64 damage,unsigned int tick);
+void ext_skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, unsigned int tick);
+int64 skill_unit_ondamaged(struct skill_unit *unit,struct block_list *bl,int64 damage,unsigned int tick);
 
 
 int skill_castfix( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
 int skill_castfix( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
 int skill_castfix_sc( struct block_list *bl, int time);
 int skill_castfix_sc( struct block_list *bl, int time);
@@ -1999,6 +1999,7 @@ int skill_elementalanalysis(struct map_session_data *sd, int n, uint16 skill_lv,
 int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list);	// Genetic Change Material.
 int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list);	// Genetic Change Material.
 int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv);
 int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv);
 
 
+bool skill_is_combo(uint16 skill_id);
 void skill_combo_toogle_inf(struct block_list* bl, uint16 skill_id, int inf);
 void skill_combo_toogle_inf(struct block_list* bl, uint16 skill_id, int inf);
 void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int tick);
 void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int tick);
 
 

+ 140 - 164
src/map/status.c

@@ -60,7 +60,7 @@ static int atkmods[3][MAX_WEAPON_TYPE];	/// ATK weapon modification for size (si
 static struct eri *sc_data_ers; /// For sc_data entries
 static struct eri *sc_data_ers; /// For sc_data entries
 static struct status_data dummy_status;
 static struct status_data dummy_status;
 
 
-int current_equip_item_index; /// Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
+short current_equip_item_index; /// Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
 int current_equip_card_id; /// To prevent card-stacking (from jA) [Skotlex]
 int current_equip_card_id; /// To prevent card-stacking (from jA) [Skotlex]
 // We need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only to avoid cards exploits
 // We need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only to avoid cards exploits
 
 
@@ -240,12 +240,7 @@ void initChangeTables(void)
 	add_sc( TF_POISON		, SC_POISON		);
 	add_sc( TF_POISON		, SC_POISON		);
 	set_sc( KN_TWOHANDQUICKEN	, SC_TWOHANDQUICKEN	, SI_TWOHANDQUICKEN	, SCB_ASPD );
 	set_sc( KN_TWOHANDQUICKEN	, SC_TWOHANDQUICKEN	, SI_TWOHANDQUICKEN	, SCB_ASPD );
 	set_sc( KN_AUTOCOUNTER		, SC_AUTOCOUNTER	, SI_AUTOCOUNTER	, SCB_NONE );
 	set_sc( KN_AUTOCOUNTER		, SC_AUTOCOUNTER	, SI_AUTOCOUNTER	, SCB_NONE );
-	set_sc( PR_IMPOSITIO		, SC_IMPOSITIO		, SI_IMPOSITIO		,
-#ifdef RENEWAL
-			SCB_NONE );
-#else
-			SCB_WATK );
-#endif
+	set_sc( PR_IMPOSITIO		, SC_IMPOSITIO		, SI_IMPOSITIO		, SCB_WATK );
 	set_sc( PR_SUFFRAGIUM		, SC_SUFFRAGIUM		, SI_SUFFRAGIUM		, SCB_NONE );
 	set_sc( PR_SUFFRAGIUM		, SC_SUFFRAGIUM		, SI_SUFFRAGIUM		, SCB_NONE );
 	set_sc( PR_ASPERSIO		, SC_ASPERSIO		, SI_ASPERSIO		, SCB_ATK_ELE );
 	set_sc( PR_ASPERSIO		, SC_ASPERSIO		, SI_ASPERSIO		, SCB_ATK_ELE );
 	set_sc( PR_BENEDICTIO		, SC_BENEDICTIO		, SI_BENEDICTIO		, SCB_DEF_ELE );
 	set_sc( PR_BENEDICTIO		, SC_BENEDICTIO		, SI_BENEDICTIO		, SCB_DEF_ELE );
@@ -344,12 +339,7 @@ void initChangeTables(void)
 	set_sc( SA_FROSTWEAPON		, SC_WATERWEAPON	, SI_WATERWEAPON	, SCB_ATK_ELE );
 	set_sc( SA_FROSTWEAPON		, SC_WATERWEAPON	, SI_WATERWEAPON	, SCB_ATK_ELE );
 	set_sc( SA_LIGHTNINGLOADER	, SC_WINDWEAPON		, SI_WINDWEAPON		, SCB_ATK_ELE );
 	set_sc( SA_LIGHTNINGLOADER	, SC_WINDWEAPON		, SI_WINDWEAPON		, SCB_ATK_ELE );
 	set_sc( SA_SEISMICWEAPON	, SC_EARTHWEAPON	, SI_EARTHWEAPON	, SCB_ATK_ELE );
 	set_sc( SA_SEISMICWEAPON	, SC_EARTHWEAPON	, SI_EARTHWEAPON	, SCB_ATK_ELE );
-	set_sc( SA_VOLCANO		, SC_VOLCANO		, SI_LANDENDOW		,
-#ifdef RENEWAL
-			SCB_NONE );
-#else
-			SCB_WATK );
-#endif
+	set_sc( SA_VOLCANO		, SC_VOLCANO		, SI_LANDENDOW		, SCB_WATK );
 	set_sc( SA_DELUGE		, SC_DELUGE		, SI_LANDENDOW		, SCB_MAXHP );
 	set_sc( SA_DELUGE		, SC_DELUGE		, SI_LANDENDOW		, SCB_MAXHP );
 	set_sc( SA_VIOLENTGALE		, SC_VIOLENTGALE	, SI_LANDENDOW		, SCB_FLEE );
 	set_sc( SA_VIOLENTGALE		, SC_VIOLENTGALE	, SI_LANDENDOW		, SCB_FLEE );
 	add_sc( SA_REVERSEORCISH	, SC_ORCISH		);
 	add_sc( SA_REVERSEORCISH	, SC_ORCISH		);
@@ -357,17 +347,8 @@ void initChangeTables(void)
 	set_sc( BD_ENCORE		, SC_DANCING		, SI_BDPLAYING		, SCB_SPEED|SCB_REGEN );
 	set_sc( BD_ENCORE		, SC_DANCING		, SI_BDPLAYING		, SCB_SPEED|SCB_REGEN );
 	set_sc( BD_RICHMANKIM		, SC_RICHMANKIM		, SI_RICHMANKIM	, SCB_NONE	);
 	set_sc( BD_RICHMANKIM		, SC_RICHMANKIM		, SI_RICHMANKIM	, SCB_NONE	);
 	set_sc( BD_ETERNALCHAOS		, SC_ETERNALCHAOS	, SI_ETERNALCHAOS	, SCB_DEF2 );
 	set_sc( BD_ETERNALCHAOS		, SC_ETERNALCHAOS	, SI_ETERNALCHAOS	, SCB_DEF2 );
-	set_sc( BD_DRUMBATTLEFIELD	, SC_DRUMBATTLE		, SI_DRUMBATTLEFIELD	, SCB_DEF
-#ifndef RENEWAL
-			|SCB_WATK
-#endif
-			);
-	set_sc( BD_RINGNIBELUNGEN	, SC_NIBELUNGEN		, SI_RINGNIBELUNGEN		,
-#ifdef RENEWAL
-			SCB_NONE );
-#else
-			SCB_WATK );
-#endif
+	set_sc( BD_DRUMBATTLEFIELD	, SC_DRUMBATTLE		, SI_DRUMBATTLEFIELD	, SCB_WATK|SCB_DEF );
+	set_sc( BD_RINGNIBELUNGEN	, SC_NIBELUNGEN		, SI_RINGNIBELUNGEN		, SCB_WATK );
 	set_sc( BD_ROKISWEIL		, SC_ROKISWEIL	, SI_ROKISWEIL	, SCB_NONE );
 	set_sc( BD_ROKISWEIL		, SC_ROKISWEIL	, SI_ROKISWEIL	, SCB_NONE );
 	set_sc( BD_INTOABYSS		, SC_INTOABYSS	, SI_INTOABYSS	, SCB_NONE );
 	set_sc( BD_INTOABYSS		, SC_INTOABYSS	, SI_INTOABYSS	, SCB_NONE );
 	set_sc( BD_SIEGFRIED		, SC_SIEGFRIED		, SI_SIEGFRIED	, SCB_ALL );
 	set_sc( BD_SIEGFRIED		, SC_SIEGFRIED		, SI_SIEGFRIED	, SCB_ALL );
@@ -392,12 +373,7 @@ void initChangeTables(void)
 	add_sc( NPC_INVISIBLE		, SC_CLOAKING		);
 	add_sc( NPC_INVISIBLE		, SC_CLOAKING		);
 	set_sc( LK_AURABLADE		, SC_AURABLADE		, SI_AURABLADE		, SCB_NONE );
 	set_sc( LK_AURABLADE		, SC_AURABLADE		, SI_AURABLADE		, SCB_NONE );
 	set_sc( LK_PARRYING		, SC_PARRYING		, SI_PARRYING		, SCB_NONE );
 	set_sc( LK_PARRYING		, SC_PARRYING		, SI_PARRYING		, SCB_NONE );
-	set_sc( LK_CONCENTRATION	, SC_CONCENTRATION	, SI_CONCENTRATION	,
-#ifndef RENEWAL
-			SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2 );
-#else
-			SCB_HIT|SCB_DEF );
-#endif
+	set_sc( LK_CONCENTRATION	, SC_CONCENTRATION	, SI_CONCENTRATION	, SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2 );
 	set_sc( LK_TENSIONRELAX		, SC_TENSIONRELAX	, SI_TENSIONRELAX	, SCB_REGEN );
 	set_sc( LK_TENSIONRELAX		, SC_TENSIONRELAX	, SI_TENSIONRELAX	, SCB_REGEN );
 	set_sc( LK_BERSERK		, SC_BERSERK		, SI_BERSERK		, SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
 	set_sc( LK_BERSERK		, SC_BERSERK		, SI_BERSERK		, SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
 	set_sc( HP_ASSUMPTIO		, SC_ASSUMPTIO		,
 	set_sc( HP_ASSUMPTIO		, SC_ASSUMPTIO		,
@@ -477,18 +453,10 @@ void initChangeTables(void)
 	add_sc( GS_CRACKER		, SC_STUN		);
 	add_sc( GS_CRACKER		, SC_STUN		);
 	add_sc( GS_DISARM		, SC_STRIPWEAPON	);
 	add_sc( GS_DISARM		, SC_STRIPWEAPON	);
 	add_sc( GS_PIERCINGSHOT		, SC_BLEEDING		);
 	add_sc( GS_PIERCINGSHOT		, SC_BLEEDING		);
-	set_sc( GS_MADNESSCANCEL	, SC_MADNESSCANCEL	, SI_MADNESSCANCEL	, SCB_ASPD
-#ifndef RENEWAL
-			|SCB_BATK
-#endif
-			);
+	set_sc( GS_MADNESSCANCEL	, SC_MADNESSCANCEL	, SI_MADNESSCANCEL	, SCB_BATK|SCB_ASPD );
 	set_sc( GS_ADJUSTMENT		, SC_ADJUSTMENT		, SI_ADJUSTMENT		, SCB_HIT|SCB_FLEE );
 	set_sc( GS_ADJUSTMENT		, SC_ADJUSTMENT		, SI_ADJUSTMENT		, SCB_HIT|SCB_FLEE );
 	set_sc( GS_INCREASING		, SC_INCREASING		, SI_ACCURACY		, SCB_AGI|SCB_DEX|SCB_HIT );
 	set_sc( GS_INCREASING		, SC_INCREASING		, SI_ACCURACY		, SCB_AGI|SCB_DEX|SCB_HIT );
-	set_sc( GS_GATLINGFEVER		, SC_GATLINGFEVER	, SI_GATLINGFEVER	, SCB_FLEE|SCB_SPEED|SCB_ASPD
-#ifndef RENWAL
-			|SCB_BATK
-#endif
-			);
+	set_sc( GS_GATLINGFEVER		, SC_GATLINGFEVER	, SI_GATLINGFEVER	, SCB_BATK|SCB_FLEE|SCB_SPEED|SCB_ASPD );
 	add_sc( NJ_TATAMIGAESHI		, SC_TATAMIGAESHI	);
 	add_sc( NJ_TATAMIGAESHI		, SC_TATAMIGAESHI	);
 	set_sc( NJ_SUITON		, SC_SUITON		, SI_BLANK		, SCB_AGI|SCB_SPEED );
 	set_sc( NJ_SUITON		, SC_SUITON		, SI_BLANK		, SCB_AGI|SCB_SPEED );
 	add_sc( NJ_HYOUSYOURAKU		, SC_FREEZE		);
 	add_sc( NJ_HYOUSYOURAKU		, SC_FREEZE		);
@@ -609,7 +577,7 @@ void initChangeTables(void)
 	set_sc( RK_GIANTGROWTH		, SC_GIANTGROWTH	, SI_GIANTGROWTH		, SCB_STR );
 	set_sc( RK_GIANTGROWTH		, SC_GIANTGROWTH	, SI_GIANTGROWTH		, SCB_STR );
 	set_sc( RK_STONEHARDSKIN	, SC_STONEHARDSKIN	, SI_STONEHARDSKIN		, SCB_DEF|SCB_MDEF );
 	set_sc( RK_STONEHARDSKIN	, SC_STONEHARDSKIN	, SI_STONEHARDSKIN		, SCB_DEF|SCB_MDEF );
 	set_sc( RK_VITALITYACTIVATION	, SC_VITALITYACTIVATION	, SI_VITALITYACTIVATION		, SCB_REGEN );
 	set_sc( RK_VITALITYACTIVATION	, SC_VITALITYACTIVATION	, SI_VITALITYACTIVATION		, SCB_REGEN );
-	set_sc( RK_FIGHTINGSPIRIT	, SC_FIGHTINGSPIRIT	, SI_FIGHTINGSPIRIT		, SCB_ASPD );
+	set_sc( RK_FIGHTINGSPIRIT	, SC_FIGHTINGSPIRIT	, SI_FIGHTINGSPIRIT		, SCB_WATK|SCB_ASPD );
 	set_sc( RK_ABUNDANCE		, SC_ABUNDANCE		, SI_ABUNDANCE			, SCB_NONE );
 	set_sc( RK_ABUNDANCE		, SC_ABUNDANCE		, SI_ABUNDANCE			, SCB_NONE );
 	set_sc( RK_CRUSHSTRIKE		, SC_CRUSHSTRIKE	, SI_CRUSHSTRIKE		, SCB_NONE );
 	set_sc( RK_CRUSHSTRIKE		, SC_CRUSHSTRIKE	, SI_CRUSHSTRIKE		, SCB_NONE );
 	set_sc_with_vfx( RK_DRAGONBREATH_WATER	, SC_FREEZING	, SI_FROSTMISTY			, SCB_ASPD|SCB_SPEED|SCB_DEF|SCB_DEF2 );
 	set_sc_with_vfx( RK_DRAGONBREATH_WATER	, SC_FREEZING	, SI_FROSTMISTY			, SCB_ASPD|SCB_SPEED|SCB_DEF|SCB_DEF2 );
@@ -680,15 +648,10 @@ void initChangeTables(void)
 	set_sc( LG_FORCEOFVANGUARD	, SC_FORCEOFVANGUARD	, SI_FORCEOFVANGUARD	, SCB_MAXHP );
 	set_sc( LG_FORCEOFVANGUARD	, SC_FORCEOFVANGUARD	, SI_FORCEOFVANGUARD	, SCB_MAXHP );
 	set_sc( LG_EXEEDBREAK		, SC_EXEEDBREAK		, SI_EXEEDBREAK		, SCB_NONE );
 	set_sc( LG_EXEEDBREAK		, SC_EXEEDBREAK		, SI_EXEEDBREAK		, SCB_NONE );
 	set_sc( LG_PRESTIGE		, SC_PRESTIGE		, SI_PRESTIGE		, SCB_DEF );
 	set_sc( LG_PRESTIGE		, SC_PRESTIGE		, SI_PRESTIGE		, SCB_DEF );
-	set_sc( LG_BANDING		, SC_BANDING		, SI_BANDING		,
-#ifndef RENEWAL
-			SCB_DEF );
-#else
-			SCB_DEF2 );
-#endif
+	set_sc( LG_BANDING		, SC_BANDING		, SI_BANDING		, SCB_DEF2|SCB_WATK );
 	set_sc( LG_PIETY		, SC_BENEDICTIO		, SI_BENEDICTIO		, SCB_DEF_ELE );
 	set_sc( LG_PIETY		, SC_BENEDICTIO		, SI_BENEDICTIO		, SCB_DEF_ELE );
 	set_sc( LG_EARTHDRIVE		, SC_EARTHDRIVE		, SI_EARTHDRIVE		, SCB_DEF|SCB_ASPD );
 	set_sc( LG_EARTHDRIVE		, SC_EARTHDRIVE		, SI_EARTHDRIVE		, SCB_DEF|SCB_ASPD );
-	set_sc( LG_INSPIRATION		, SC_INSPIRATION	, SI_INSPIRATION	, SCB_MAXHP|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
+	set_sc( LG_INSPIRATION		, SC_INSPIRATION	, SI_INSPIRATION	, SCB_WATK|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_HIT|SCB_MAXHP);
 	set_sc( LG_KINGS_GRACE		, SC_KINGS_GRACE	, SI_KINGS_GRACE	, SCB_NONE );
 	set_sc( LG_KINGS_GRACE		, SC_KINGS_GRACE	, SI_KINGS_GRACE	, SCB_NONE );
 
 
 	/* Shadow Chaser */
 	/* Shadow Chaser */
@@ -718,7 +681,7 @@ void initChangeTables(void)
 	set_sc( SR_LIGHTNINGWALK		, SC_LIGHTNINGWALK	, SI_LIGHTNINGWALK		, SCB_NONE );
 	set_sc( SR_LIGHTNINGWALK		, SC_LIGHTNINGWALK	, SI_LIGHTNINGWALK		, SCB_NONE );
 	set_sc( SR_RAISINGDRAGON		, SC_RAISINGDRAGON	, SI_RAISINGDRAGON		, SCB_REGEN|SCB_MAXHP|SCB_MAXSP );
 	set_sc( SR_RAISINGDRAGON		, SC_RAISINGDRAGON	, SI_RAISINGDRAGON		, SCB_REGEN|SCB_MAXHP|SCB_MAXSP );
 	set_sc( SR_GENTLETOUCH_ENERGYGAIN	, SC_GT_ENERGYGAIN	, SI_GENTLETOUCH_ENERGYGAIN	, SCB_NONE );
 	set_sc( SR_GENTLETOUCH_ENERGYGAIN	, SC_GT_ENERGYGAIN	, SI_GENTLETOUCH_ENERGYGAIN	, SCB_NONE );
-	set_sc( SR_GENTLETOUCH_CHANGE		, SC_GT_CHANGE		, SI_GENTLETOUCH_CHANGE		, SCB_MDEF|SCB_ASPD|SCB_MAXHP );
+	set_sc( SR_GENTLETOUCH_CHANGE		, SC_GT_CHANGE		, SI_GENTLETOUCH_CHANGE		, SCB_WATK|SCB_MDEF|SCB_ASPD|SCB_MAXHP );
 	set_sc( SR_GENTLETOUCH_REVITALIZE	, SC_GT_REVITALIZE	, SI_GENTLETOUCH_REVITALIZE	, SCB_MAXHP|SCB_REGEN );
 	set_sc( SR_GENTLETOUCH_REVITALIZE	, SC_GT_REVITALIZE	, SI_GENTLETOUCH_REVITALIZE	, SCB_MAXHP|SCB_REGEN );
 	add_sc( SR_FLASHCOMBO			, SC_FLASHCOMBO );
 	add_sc( SR_FLASHCOMBO			, SC_FLASHCOMBO );
 
 
@@ -726,7 +689,7 @@ void initChangeTables(void)
 	set_sc( WA_SWING_DANCE			, SC_SWINGDANCE			, SI_SWINGDANCE			, SCB_SPEED|SCB_ASPD );
 	set_sc( WA_SWING_DANCE			, SC_SWINGDANCE			, SI_SWINGDANCE			, SCB_SPEED|SCB_ASPD );
 	set_sc( WA_SYMPHONY_OF_LOVER		, SC_SYMPHONYOFLOVER		, SI_SYMPHONYOFLOVERS		, SCB_MDEF );
 	set_sc( WA_SYMPHONY_OF_LOVER		, SC_SYMPHONYOFLOVER		, SI_SYMPHONYOFLOVERS		, SCB_MDEF );
 	set_sc( WA_MOONLIT_SERENADE		, SC_MOONLITSERENADE		, SI_MOONLITSERENADE		, SCB_MATK );
 	set_sc( WA_MOONLIT_SERENADE		, SC_MOONLITSERENADE		, SI_MOONLITSERENADE		, SCB_MATK );
-	set_sc( MI_RUSH_WINDMILL		, SC_RUSHWINDMILL		, SI_RUSHWINDMILL		, SCB_NONE  );
+	set_sc( MI_RUSH_WINDMILL		, SC_RUSHWINDMILL		, SI_RUSHWINDMILL		, SCB_WATK  );
 	set_sc( MI_ECHOSONG			, SC_ECHOSONG			, SI_ECHOSONG			, SCB_DEF  );
 	set_sc( MI_ECHOSONG			, SC_ECHOSONG			, SI_ECHOSONG			, SCB_DEF  );
 	set_sc( MI_HARMONIZE			, SC_HARMONIZE			, SI_HARMONIZE			, SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
 	set_sc( MI_HARMONIZE			, SC_HARMONIZE			, SI_HARMONIZE			, SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
 	set_sc_with_vfx( WM_POEMOFNETHERWORLD	, SC_NETHERWORLD		, SI_NETHERWORLD		, SCB_NONE );
 	set_sc_with_vfx( WM_POEMOFNETHERWORLD	, SC_NETHERWORLD		, SI_NETHERWORLD		, SCB_NONE );
@@ -736,7 +699,7 @@ void initChangeTables(void)
 	set_sc( WM_GLOOMYDAY			, SC_GLOOMYDAY			, SI_GLOOMYDAY			, SCB_FLEE|SCB_SPEED|SCB_ASPD );
 	set_sc( WM_GLOOMYDAY			, SC_GLOOMYDAY			, SI_GLOOMYDAY			, SCB_FLEE|SCB_SPEED|SCB_ASPD );
 	set_sc( WM_SONG_OF_MANA			, SC_SONGOFMANA			, SI_SONGOFMANA			, SCB_NONE );
 	set_sc( WM_SONG_OF_MANA			, SC_SONGOFMANA			, SI_SONGOFMANA			, SCB_NONE );
 	set_sc( WM_DANCE_WITH_WUG		, SC_DANCEWITHWUG		, SI_DANCEWITHWUG		, SCB_ASPD );
 	set_sc( WM_DANCE_WITH_WUG		, SC_DANCEWITHWUG		, SI_DANCEWITHWUG		, SCB_ASPD );
-	set_sc( WM_SATURDAY_NIGHT_FEVER		, SC_SATURDAYNIGHTFEVER		, SI_SATURDAYNIGHTFEVER		, SCB_DEF|SCB_FLEE|SCB_REGEN );
+	set_sc( WM_SATURDAY_NIGHT_FEVER		, SC_SATURDAYNIGHTFEVER		, SI_SATURDAYNIGHTFEVER		, SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN );
 	set_sc( WM_LERADS_DEW			, SC_LERADSDEW			, SI_LERADSDEW			, SCB_MAXHP );
 	set_sc( WM_LERADS_DEW			, SC_LERADSDEW			, SI_LERADSDEW			, SCB_MAXHP );
 	set_sc( WM_MELODYOFSINK			, SC_MELODYOFSINK		, SI_MELODYOFSINK		, SCB_INT );
 	set_sc( WM_MELODYOFSINK			, SC_MELODYOFSINK		, SI_MELODYOFSINK		, SCB_INT );
 	set_sc( WM_BEYOND_OF_WARCRY		, SC_BEYONDOFWARCRY		, SI_WARCRYOFBEYOND		, SCB_STR|SCB_CRI|SCB_MAXHP );
 	set_sc( WM_BEYOND_OF_WARCRY		, SC_BEYONDOFWARCRY		, SI_WARCRYOFBEYOND		, SCB_STR|SCB_CRI|SCB_MAXHP );
@@ -763,7 +726,6 @@ void initChangeTables(void)
 	set_sc( GN_CARTBOOST			, SC_GN_CARTBOOST	, SI_GN_CARTBOOST			, SCB_SPEED );
 	set_sc( GN_CARTBOOST			, SC_GN_CARTBOOST	, SI_GN_CARTBOOST			, SCB_SPEED );
 	set_sc( GN_THORNS_TRAP			, SC_THORNSTRAP		, SI_THORNTRAP			, SCB_NONE );
 	set_sc( GN_THORNS_TRAP			, SC_THORNSTRAP		, SI_THORNTRAP			, SCB_NONE );
 	set_sc_with_vfx( GN_BLOOD_SUCKER	, SC_BLOODSUCKER	, SI_BLOODSUCKER		, SCB_NONE );
 	set_sc_with_vfx( GN_BLOOD_SUCKER	, SC_BLOODSUCKER	, SI_BLOODSUCKER		, SCB_NONE );
-	add_sc( GN_WALLOFTHORN			, SC_STOP		);
 	set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER	, SC_SMOKEPOWDER	, SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_FLEE );
 	set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER	, SC_SMOKEPOWDER	, SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_FLEE );
 	set_sc( GN_FIRE_EXPANSION_TEAR_GAS	, SC_TEARGAS		, SI_FIRE_EXPANSION_TEAR_GAS	, SCB_HIT|SCB_FLEE );
 	set_sc( GN_FIRE_EXPANSION_TEAR_GAS	, SC_TEARGAS		, SI_FIRE_EXPANSION_TEAR_GAS	, SCB_HIT|SCB_FLEE );
 	set_sc( GN_MANDRAGORA			, SC_MANDRAGORA		, SI_MANDRAGORA			, SCB_INT );
 	set_sc( GN_MANDRAGORA			, SC_MANDRAGORA		, SI_MANDRAGORA			, SCB_INT );
@@ -781,9 +743,9 @@ void initChangeTables(void)
 	set_sc( EL_SOLID_SKIN		, SC_SOLID_SKIN_OPTION		, SI_SOLID_SKIN_OPTION		, SCB_DEF|SCB_MAXHP );
 	set_sc( EL_SOLID_SKIN		, SC_SOLID_SKIN_OPTION		, SI_SOLID_SKIN_OPTION		, SCB_DEF|SCB_MAXHP );
 	set_sc( EL_STONE_SHIELD		, SC_STONE_SHIELD_OPTION	, SI_STONE_SHIELD_OPTION	, SCB_ALL );
 	set_sc( EL_STONE_SHIELD		, SC_STONE_SHIELD_OPTION	, SI_STONE_SHIELD_OPTION	, SCB_ALL );
 	set_sc( EL_POWER_OF_GAIA	, SC_POWER_OF_GAIA		, SI_POWER_OF_GAIA		, SCB_MAXHP|SCB_DEF|SCB_SPEED );
 	set_sc( EL_POWER_OF_GAIA	, SC_POWER_OF_GAIA		, SI_POWER_OF_GAIA		, SCB_MAXHP|SCB_DEF|SCB_SPEED );
-	set_sc( EL_PYROTECHNIC		, SC_PYROTECHNIC_OPTION		, SI_PYROTECHNIC_OPTION		, SCB_NONE );
-	set_sc( EL_HEATER		, SC_HEATER_OPTION		, SI_HEATER_OPTION		, SCB_NONE );
-	set_sc( EL_TROPIC		, SC_TROPIC_OPTION		, SI_TROPIC_OPTION		, SCB_NONE );
+	set_sc( EL_PYROTECHNIC		, SC_PYROTECHNIC_OPTION		, SI_PYROTECHNIC_OPTION		, SCB_WATK );
+	set_sc( EL_HEATER		, SC_HEATER_OPTION		, SI_HEATER_OPTION		, SCB_WATK );
+	set_sc( EL_TROPIC		, SC_TROPIC_OPTION		, SI_TROPIC_OPTION		, SCB_WATK );
 	set_sc( EL_AQUAPLAY		, SC_AQUAPLAY_OPTION		, SI_AQUAPLAY_OPTION		, SCB_MATK );
 	set_sc( EL_AQUAPLAY		, SC_AQUAPLAY_OPTION		, SI_AQUAPLAY_OPTION		, SCB_MATK );
 	set_sc( EL_COOLER		, SC_COOLER_OPTION		, SI_COOLER_OPTION		, SCB_MATK );
 	set_sc( EL_COOLER		, SC_COOLER_OPTION		, SI_COOLER_OPTION		, SCB_MATK );
 	set_sc( EL_CHILLY_AIR		, SC_CHILLY_AIR_OPTION		, SI_CHILLY_AIR_OPTION		, SCB_MATK );
 	set_sc( EL_CHILLY_AIR		, SC_CHILLY_AIR_OPTION		, SI_CHILLY_AIR_OPTION		, SCB_MATK );
@@ -1081,6 +1043,7 @@ void initChangeTables(void)
 	StatusChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE;
 	StatusChangeFlagTable[SC_PYREXIA] |= SCB_HIT|SCB_FLEE;
 	StatusChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN;
 	StatusChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN;
 	StatusChangeFlagTable[SC_BANDING_DEFENCE] |= SCB_SPEED;
 	StatusChangeFlagTable[SC_BANDING_DEFENCE] |= SCB_SPEED;
+	StatusChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK;
 	StatusChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF;
 	StatusChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF;
 	StatusChangeFlagTable[SC_STOMACHACHE] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_DEX|SCB_INT|SCB_LUK;
 	StatusChangeFlagTable[SC_STOMACHACHE] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_DEX|SCB_INT|SCB_LUK;
 	StatusChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP;
 	StatusChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP;
@@ -1354,6 +1317,8 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 	int hp = (int)cap_value(dhp,INT_MIN,INT_MAX);
 	int hp = (int)cap_value(dhp,INT_MIN,INT_MAX);
 	int sp = (int)cap_value(dsp,INT_MIN,INT_MAX);
 	int sp = (int)cap_value(dsp,INT_MIN,INT_MAX);
 
 
+	nullpo_ret(target);
+
 	if(sp && !(target->type&BL_CONSUME))
 	if(sp && !(target->type&BL_CONSUME))
 		sp = 0; // Not a valid SP target.
 		sp = 0; // Not a valid SP target.
 
 
@@ -1371,7 +1336,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 		return (int)skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick());
 		return (int)skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick());
 
 
 	status = status_get_status_data(target);
 	status = status_get_status_data(target);
-	if( status == &dummy_status )
+	if(!status || status == &dummy_status )
 		return 0;
 		return 0;
 
 
 	if ((unsigned int)hp >= status->hp) {
 	if ((unsigned int)hp >= status->hp) {
@@ -2790,7 +2755,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 	const struct status_change *sc = &sd->sc;
 	const struct status_change *sc = &sd->sc;
 	struct s_skill b_skill[MAX_SKILL]; ///< Previous skill tree
 	struct s_skill b_skill[MAX_SKILL]; ///< Previous skill tree
 	int b_weight, b_max_weight, b_cart_weight_max, ///< Previous weight
 	int b_weight, b_max_weight, b_cart_weight_max, ///< Previous weight
-	i, index, skill,refinedef=0;
+	i, skill,refinedef=0;
+	short index = -1;
 
 
 	if (++calculating > 10) // Too many recursive calls!
 	if (++calculating > 10) // Too many recursive calls!
 		return -1;
 		return -1;
@@ -2883,11 +2849,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 		clif_status_load(&sd->bl, SI_INTRAVISION, 0);
 		clif_status_load(&sd->bl, SI_INTRAVISION, 0);
 
 
 	memset(&sd->special_state,0,sizeof(sd->special_state));
 	memset(&sd->special_state,0,sizeof(sd->special_state));
-	memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp)));
 
 
-	// !FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
-	if (!sd->state.permanent_speed)
+	if (!sd->state.permanent_speed) {
+		memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp)));
 		status->speed = DEFAULT_WALK_SPEED;
 		status->speed = DEFAULT_WALK_SPEED;
+	} else {
+		int pSpeed = status->speed;
+
+		memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp)));
+		status->speed = pSpeed;
+	}
+
+	// !FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
 	// Give them all modes except these (useful for clones)
 	// Give them all modes except these (useful for clones)
 	status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
 	status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
 
 
@@ -2933,6 +2906,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 		+ sizeof(sd->skillfixcast)
 		+ sizeof(sd->skillfixcast)
 		+ sizeof(sd->skillvarcast)
 		+ sizeof(sd->skillvarcast)
 		+ sizeof(sd->skillfixcastrate)
 		+ sizeof(sd->skillfixcastrate)
+		+ sizeof(sd->def_set_race)
+		+ sizeof(sd->mdef_set_race)
 	);
 	);
 
 
 	memset (&sd->bonus, 0,sizeof(sd->bonus));
 	memset (&sd->bonus, 0,sizeof(sd->bonus));
@@ -4279,6 +4254,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 
 
 	if(flag&SCB_SPEED) {
 	if(flag&SCB_SPEED) {
 		struct unit_data *ud = unit_bl2ud(bl);
 		struct unit_data *ud = unit_bl2ud(bl);
+
 		status->speed = status_calc_speed(bl, sc, b_status->speed);
 		status->speed = status_calc_speed(bl, sc, b_status->speed);
 
 
 		/** [Skotlex]
 		/** [Skotlex]
@@ -4289,7 +4265,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 		if (ud)
 		if (ud)
 			ud->state.change_walk_target = ud->state.speed_changed = 1;
 			ud->state.change_walk_target = ud->state.speed_changed = 1;
 
 
-		if( bl->type&BL_PC && status->speed < battle_config.max_walk_speed )
+		if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && status->speed < battle_config.max_walk_speed )
 			status->speed = battle_config.max_walk_speed;
 			status->speed = battle_config.max_walk_speed;
 
 
 		if( bl->type&BL_HOM && battle_config.hom_setting&HOMSET_COPY_SPEED && ((TBL_HOM*)bl)->master)
 		if( bl->type&BL_HOM && battle_config.hom_setting&HOMSET_COPY_SPEED && ((TBL_HOM*)bl)->master)
@@ -4298,8 +4274,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			status->speed = status_get_speed(&((TBL_MER*)bl)->master->bl);
 			status->speed = status_get_speed(&((TBL_MER*)bl)->master->bl);
 		if( bl->type&BL_ELEM && ((TBL_ELEM*)bl)->master)
 		if( bl->type&BL_ELEM && ((TBL_ELEM*)bl)->master)
 			status->speed = status_get_speed(&((TBL_ELEM*)bl)->master->bl);
 			status->speed = status_get_speed(&((TBL_ELEM*)bl)->master->bl);
-
-
 	}
 	}
 
 
 	if(flag&SCB_CRI && b_status->cri) {
 	if(flag&SCB_CRI && b_status->cri) {
@@ -4311,7 +4285,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 		/// After status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240
 		/// After status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240
 		if( bl->type == BL_PC && ((TBL_PC*)bl)->status.weapon == W_KATAR )
 		if( bl->type == BL_PC && ((TBL_PC*)bl)->status.weapon == W_KATAR )
 			status->cri <<= 1;
 			status->cri <<= 1;
-
 	}
 	}
 
 
 	if(flag&SCB_FLEE2 && b_status->flee2) {
 	if(flag&SCB_FLEE2 && b_status->flee2) {
@@ -4780,7 +4753,7 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
 	if(sc->data[SC_SAVAGE_STEAK])
 	if(sc->data[SC_SAVAGE_STEAK])
 		str += sc->data[SC_SAVAGE_STEAK]->val1;
 		str += sc->data[SC_SAVAGE_STEAK]->val1;
 	if(sc->data[SC_INSPIRATION])
 	if(sc->data[SC_INSPIRATION])
-		str += sc->data[SC_INSPIRATION]->val2;
+		str += sc->data[SC_INSPIRATION]->val3;
 	if(sc->data[SC_STOMACHACHE])
 	if(sc->data[SC_STOMACHACHE])
 		str -= sc->data[SC_STOMACHACHE]->val1;
 		str -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 	if(sc->data[SC_KYOUGAKU])
@@ -4844,7 +4817,7 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang
 	if(sc->data[SC_DROCERA_HERB_STEAMED])
 	if(sc->data[SC_DROCERA_HERB_STEAMED])
 		agi += sc->data[SC_DROCERA_HERB_STEAMED]->val1;
 		agi += sc->data[SC_DROCERA_HERB_STEAMED]->val1;
 	if(sc->data[SC_INSPIRATION])
 	if(sc->data[SC_INSPIRATION])
-		agi += sc->data[SC_INSPIRATION]->val2;
+		agi += sc->data[SC_INSPIRATION]->val3;
 	if(sc->data[SC_STOMACHACHE])
 	if(sc->data[SC_STOMACHACHE])
 		agi -= sc->data[SC_STOMACHACHE]->val1;
 		agi -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 	if(sc->data[SC_KYOUGAKU])
@@ -4896,7 +4869,7 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang
 	if(sc->data[SC_MINOR_BBQ])
 	if(sc->data[SC_MINOR_BBQ])
 		vit += sc->data[SC_MINOR_BBQ]->val1;
 		vit += sc->data[SC_MINOR_BBQ]->val1;
 	if(sc->data[SC_INSPIRATION])
 	if(sc->data[SC_INSPIRATION])
-		vit += sc->data[SC_INSPIRATION]->val2;
+		vit += sc->data[SC_INSPIRATION]->val3;
 	if(sc->data[SC_STOMACHACHE])
 	if(sc->data[SC_STOMACHACHE])
 		vit -= sc->data[SC_STOMACHACHE]->val1;
 		vit -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 	if(sc->data[SC_KYOUGAKU])
@@ -4957,14 +4930,14 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang
 		int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF;
 		int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF;
 	if(sc->data[SC_MARIONETTE2])
 	if(sc->data[SC_MARIONETTE2])
 		int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF;
 		int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF;
+	if(sc->data[SC_INSPIRATION])
+		int_ += sc->data[SC_INSPIRATION]->val3;
 	if(sc->data[SC_MELODYOFSINK])
 	if(sc->data[SC_MELODYOFSINK])
 		int_ -= sc->data[SC_MELODYOFSINK]->val3;
 		int_ -= sc->data[SC_MELODYOFSINK]->val3;
 	if(sc->data[SC_MANDRAGORA])
 	if(sc->data[SC_MANDRAGORA])
 		int_ -= 4 * sc->data[SC_MANDRAGORA]->val1;
 		int_ -= 4 * sc->data[SC_MANDRAGORA]->val1;
 	if(sc->data[SC_COCKTAIL_WARG_BLOOD])
 	if(sc->data[SC_COCKTAIL_WARG_BLOOD])
 		int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1;
 		int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1;
-	if(sc->data[SC_INSPIRATION])
-		int_ += sc->data[SC_INSPIRATION]->val2;
 	if(sc->data[SC_STOMACHACHE])
 	if(sc->data[SC_STOMACHACHE])
 		int_ -= sc->data[SC_STOMACHACHE]->val1;
 		int_ -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 	if(sc->data[SC_KYOUGAKU])
@@ -5033,7 +5006,7 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang
 	if(sc->data[SC_SIROMA_ICE_TEA])
 	if(sc->data[SC_SIROMA_ICE_TEA])
 		dex += sc->data[SC_SIROMA_ICE_TEA]->val1;
 		dex += sc->data[SC_SIROMA_ICE_TEA]->val1;
 	if(sc->data[SC_INSPIRATION])
 	if(sc->data[SC_INSPIRATION])
-		dex += sc->data[SC_INSPIRATION]->val2;
+		dex += sc->data[SC_INSPIRATION]->val3;
 	if(sc->data[SC_STOMACHACHE])
 	if(sc->data[SC_STOMACHACHE])
 		dex -= sc->data[SC_STOMACHACHE]->val1;
 		dex -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 	if(sc->data[SC_KYOUGAKU])
@@ -5088,7 +5061,7 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang
 	if(sc->data[SC_PUTTI_TAILS_NOODLES])
 	if(sc->data[SC_PUTTI_TAILS_NOODLES])
 		luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1;
 		luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1;
 	if(sc->data[SC_INSPIRATION])
 	if(sc->data[SC_INSPIRATION])
-		luk += sc->data[SC_INSPIRATION]->val2;
+		luk += sc->data[SC_INSPIRATION]->val3;
 	if(sc->data[SC_STOMACHACHE])
 	if(sc->data[SC_STOMACHACHE])
 		luk -= sc->data[SC_STOMACHACHE]->val1;
 		luk -= sc->data[SC_STOMACHACHE]->val1;
 	if(sc->data[SC_KYOUGAKU])
 	if(sc->data[SC_KYOUGAKU])
@@ -5120,14 +5093,12 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
 
 
 	if(sc->data[SC_ATKPOTION])
 	if(sc->data[SC_ATKPOTION])
 		batk += sc->data[SC_ATKPOTION]->val1;
 		batk += sc->data[SC_ATKPOTION]->val1;
-#ifndef RENEWAL
-	if(sc->data[SC_MADNESSCANCEL])
-		batk += 100;
-	if(sc->data[SC_GATLINGFEVER])
-		batk += sc->data[SC_GATLINGFEVER]->val3;
-#endif
 	if(sc->data[SC_BATKFOOD])
 	if(sc->data[SC_BATKFOOD])
 		batk += sc->data[SC_BATKFOOD]->val1;
 		batk += sc->data[SC_BATKFOOD]->val1;
+	if(sc->data[SC_GATLINGFEVER])
+		batk += sc->data[SC_GATLINGFEVER]->val3;
+	if(sc->data[SC_MADNESSCANCEL])
+		batk += 100;
 	if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)
 	if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)
 		batk += 50;
 		batk += 50;
 	if(bl->type == BL_ELEM
 	if(bl->type == BL_ELEM
@@ -5150,10 +5121,8 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
 		batk += batk * sc->data[SC_INCATKRATE]->val1/100;
 		batk += batk * sc->data[SC_INCATKRATE]->val1/100;
 	if(sc->data[SC_PROVOKE])
 	if(sc->data[SC_PROVOKE])
 		batk += batk * sc->data[SC_PROVOKE]->val3/100;
 		batk += batk * sc->data[SC_PROVOKE]->val3/100;
-#ifndef RENEWAL
 	if(sc->data[SC_CONCENTRATION])
 	if(sc->data[SC_CONCENTRATION])
 		batk += batk * sc->data[SC_CONCENTRATION]->val2/100;
 		batk += batk * sc->data[SC_CONCENTRATION]->val2/100;
-#endif
 	if(sc->data[SC_SKE])
 	if(sc->data[SC_SKE])
 		batk += batk * 3;
 		batk += batk * 3;
 	if(sc->data[SC_BLOODLUST])
 	if(sc->data[SC_BLOODLUST])
@@ -5169,6 +5138,8 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
 		batk += batk * sc->data[SC_FLEET]->val3/100;
 		batk += batk * sc->data[SC_FLEET]->val3/100;
 	if(sc->data[SC__ENERVATION])
 	if(sc->data[SC__ENERVATION])
 		batk -= batk * sc->data[SC__ENERVATION]->val2 / 100;
 		batk -= batk * sc->data[SC__ENERVATION]->val2 / 100;
+	if(sc->data[SC_SATURDAYNIGHTFEVER])
+		batk += 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1;
 	if( sc->data[SC_ZANGETSU] )
 	if( sc->data[SC_ZANGETSU] )
 		batk += sc->data[SC_ZANGETSU]->val2;
 		batk += sc->data[SC_ZANGETSU]->val2;
 	if(sc->data[SC_EQC])
 	if(sc->data[SC_EQC])
@@ -5195,37 +5166,37 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
 	if(!sc || !sc->count)
 	if(!sc || !sc->count)
 		return cap_value(watk,0,USHRT_MAX);
 		return cap_value(watk,0,USHRT_MAX);
 
 
-	if(sc->data[SC_WATKFOOD])
-		watk += sc->data[SC_WATKFOOD]->val1;
-#ifndef RENEWAL
 	if(sc->data[SC_IMPOSITIO])
 	if(sc->data[SC_IMPOSITIO])
 		watk += sc->data[SC_IMPOSITIO]->val2;
 		watk += sc->data[SC_IMPOSITIO]->val2;
-	if(sc->data[SC_VOLCANO])
-		watk += sc->data[SC_VOLCANO]->val2;
+	if(sc->data[SC_WATKFOOD])
+		watk += sc->data[SC_WATKFOOD]->val1;
 	if(sc->data[SC_DRUMBATTLE])
 	if(sc->data[SC_DRUMBATTLE])
 		watk += sc->data[SC_DRUMBATTLE]->val2;
 		watk += sc->data[SC_DRUMBATTLE]->val2;
+	if(sc->data[SC_VOLCANO])
+		watk += sc->data[SC_VOLCANO]->val2;
+	if(sc->data[SC_MERC_ATKUP])
+		watk += sc->data[SC_MERC_ATKUP]->val2;
+	if(sc->data[SC_WATER_BARRIER])
+		watk -= sc->data[SC_WATER_BARRIER]->val3;
 	if(sc->data[SC_NIBELUNGEN]) {
 	if(sc->data[SC_NIBELUNGEN]) {
 		if (bl->type != BL_PC)
 		if (bl->type != BL_PC)
 			watk += sc->data[SC_NIBELUNGEN]->val2;
 			watk += sc->data[SC_NIBELUNGEN]->val2;
+		#ifndef RENEWAL
 		else {
 		else {
 			TBL_PC *sd = (TBL_PC*)bl;
 			TBL_PC *sd = (TBL_PC*)bl;
-			int index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R];
+			short index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R];
 
 
 			if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
 			if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4)
 				watk += sc->data[SC_NIBELUNGEN]->val2;
 				watk += sc->data[SC_NIBELUNGEN]->val2;
 		}
 		}
+		#endif
 	}
 	}
-	if(sc->data[SC_CONCENTRATION])
-		watk += watk * sc->data[SC_CONCENTRATION]->val2/100;
-#endif
-	if(sc->data[SC_MERC_ATKUP])
-		watk += sc->data[SC_MERC_ATKUP]->val2;
-	if(sc->data[SC_WATER_BARRIER])
-		watk -= sc->data[SC_WATER_BARRIER]->val3;
 	if(sc->data[SC_INCATKRATE])
 	if(sc->data[SC_INCATKRATE])
 		watk += watk * sc->data[SC_INCATKRATE]->val1/100;
 		watk += watk * sc->data[SC_INCATKRATE]->val1/100;
 	if(sc->data[SC_PROVOKE])
 	if(sc->data[SC_PROVOKE])
 		watk += watk * sc->data[SC_PROVOKE]->val3/100;
 		watk += watk * sc->data[SC_PROVOKE]->val3/100;
+	if(sc->data[SC_CONCENTRATION])
+		watk += watk * sc->data[SC_CONCENTRATION]->val2/100;
 	if(sc->data[SC_SKE])
 	if(sc->data[SC_SKE])
 		watk += watk * 3;
 		watk += watk * 3;
 	if(sc->data[SC_FLEET])
 	if(sc->data[SC_FLEET])
@@ -5234,15 +5205,33 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
 		watk -= watk * 25/100;
 		watk -= watk * 25/100;
 	if(sc->data[SC_STRIPWEAPON] && bl->type != BL_PC)
 	if(sc->data[SC_STRIPWEAPON] && bl->type != BL_PC)
 		watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100;
 		watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100;
+	if(sc->data[SC_FIGHTINGSPIRIT])
+		watk += sc->data[SC_FIGHTINGSPIRIT]->val1;
+	if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3)
+		watk += sc->data[SC_SHIELDSPELL_DEF]->val2;
+	if(sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1)
+		watk += (10 + 10 * sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2;
+	if(sc->data[SC_INSPIRATION])
+		watk += 40 * sc->data[SC_INSPIRATION]->val1 + 3 * sc->data[SC_INSPIRATION]->val2;
+	if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val2)
+		watk += sc->data[SC_GT_CHANGE]->val2;
 	if(sc->data[SC__ENERVATION])
 	if(sc->data[SC__ENERVATION])
 		watk -= watk * sc->data[SC__ENERVATION]->val2 / 100;
 		watk -= watk * sc->data[SC__ENERVATION]->val2 / 100;
 	if(sc->data[SC_STRIKING])
 	if(sc->data[SC_STRIKING])
 		watk += sc->data[SC_STRIKING]->val2;
 		watk += sc->data[SC_STRIKING]->val2;
+	if(sc->data[SC_RUSHWINDMILL])
+		watk += sc->data[SC_RUSHWINDMILL]->val3;
 	if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)
 	if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)
 	   || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
 	   || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)
 	   || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2)
 	   || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2)
 	   || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2))
 	   || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2))
 		watk += watk / 10;
 		watk += watk / 10;
+	if(sc->data[SC_PYROTECHNIC_OPTION])
+		watk += sc->data[SC_PYROTECHNIC_OPTION]->val2;
+	if(sc->data[SC_HEATER_OPTION])
+		watk += sc->data[SC_HEATER_OPTION]->val2;
+	if(sc->data[SC_TROPIC_OPTION])
+		watk += sc->data[SC_TROPIC_OPTION]->val2;
 	if( sc && sc->data[SC_TIDAL_WEAPON] )
 	if( sc && sc->data[SC_TIDAL_WEAPON] )
 		watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100;
 		watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100;
 	if(bl->type == BL_PC && sc->data[SC_PYROCLASTIC])
 	if(bl->type == BL_PC && sc->data[SC_PYROCLASTIC])
@@ -5420,7 +5409,7 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
 	if(sc->data[SC_CONCENTRATION])
 	if(sc->data[SC_CONCENTRATION])
 		hit += sc->data[SC_CONCENTRATION]->val3;
 		hit += sc->data[SC_CONCENTRATION]->val3;
 	if(sc->data[SC_INSPIRATION])
 	if(sc->data[SC_INSPIRATION])
-		hit += 5 * sc->data[SC_INSPIRATION]->val1 + sc->data[SC_INSPIRATION]->val3 / 2;
+		hit += 5 * sc->data[SC_INSPIRATION]->val1 + sc->data[SC_INSPIRATION]->val2 / 2;
 	if(sc->data[SC_ADJUSTMENT])
 	if(sc->data[SC_ADJUSTMENT])
 		hit -= 30;
 		hit -= 30;
 	if(sc->data[SC_INCREASING])
 	if(sc->data[SC_INCREASING])
@@ -5641,10 +5630,8 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
 		def += sc->data[SC_SHIELDSPELL_REF]->val2;
 		def += sc->data[SC_SHIELDSPELL_REF]->val2;
 	if( sc->data[SC_PRESTIGE] )
 	if( sc->data[SC_PRESTIGE] )
 		def += sc->data[SC_PRESTIGE]->val1;
 		def += sc->data[SC_PRESTIGE]->val1;
-#ifndef RENEWAL
 	if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
 	if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
 		def += (5 + sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2 / 10;
 		def += (5 + sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2 / 10;
-#endif
 	if( sc->data[SC_ECHOSONG] )
 	if( sc->data[SC_ECHOSONG] )
 		def += def * sc->data[SC_ECHOSONG]->val3 / 100;
 		def += def * sc->data[SC_ECHOSONG]->val3 / 100;
 	if( sc->data[SC_SATURDAYNIGHTFEVER] )
 	if( sc->data[SC_SATURDAYNIGHTFEVER] )
@@ -5692,19 +5679,17 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
 
 
 	if(sc->data[SC_SUN_COMFORT])
 	if(sc->data[SC_SUN_COMFORT])
 		def2 += sc->data[SC_SUN_COMFORT]->val2;
 		def2 += sc->data[SC_SUN_COMFORT]->val2;
-#ifdef RENEWAL
 	if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
 	if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
 		def2 += (5 + sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2;
 		def2 += (5 + sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2;
-#endif
 
 
 	if(sc->data[SC_ANGELUS])
 	if(sc->data[SC_ANGELUS])
 #ifdef RENEWAL /// The VIT stat bonus is boosted by angelus [RENEWAL]
 #ifdef RENEWAL /// The VIT stat bonus is boosted by angelus [RENEWAL]
 		def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100;
 		def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100;
 #else
 #else
 		def2 += def2 * sc->data[SC_ANGELUS]->val2/100;
 		def2 += def2 * sc->data[SC_ANGELUS]->val2/100;
+#endif
 	if(sc->data[SC_CONCENTRATION])
 	if(sc->data[SC_CONCENTRATION])
 		def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100;
 		def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100;
-#endif
 	if(sc->data[SC_POISON])
 	if(sc->data[SC_POISON])
 		def2 -= def2 * 25/100;
 		def2 -= def2 * 25/100;
 	if(sc->data[SC_DPOISON])
 	if(sc->data[SC_DPOISON])
@@ -5846,11 +5831,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 	TBL_PC* sd = BL_CAST(BL_PC, bl);
 	TBL_PC* sd = BL_CAST(BL_PC, bl);
 	int speed_rate = 100;
 	int speed_rate = 100;
 
 
-	if( sc == NULL )
-		return cap_value(speed,10,USHRT_MAX);
-
-	if (sd && sd->state.permanent_speed)
-		return (short)cap_value(speed,10,USHRT_MAX);
+	if (sc == NULL || (sd && sd->state.permanent_speed))
+		return (unsigned short)cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
 
 
 	if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) ) {
 	if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) ) {
 		if( sd->ud.skill_id == LG_EXEEDBREAK )
 		if( sd->ud.skill_id == LG_EXEEDBREAK )
@@ -6012,7 +5994,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 	if( sc->data[SC_REBOUND] )
 	if( sc->data[SC_REBOUND] )
 		speed += max(speed, 100);
 		speed += max(speed, 100);
 
 
-	return (short)cap_value(speed,10,USHRT_MAX);
+	return (unsigned short)cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
 }
 }
 
 
 #ifdef RENEWAL_ASPD
 #ifdef RENEWAL_ASPD
@@ -6518,7 +6500,7 @@ const char* status_get_name(struct block_list *bl)
 }
 }
 
 
 /**
 /**
-* Gets the class of the given bl
+* Gets the class/sprite id of the given bl
 * @param bl: Object whose class to get [PC|MOB|PET|HOM|MER|NPC|ELEM]
 * @param bl: Object whose class to get [PC|MOB|PET|HOM|MER|NPC|ELEM]
 * @return class or 0 if any other bl->type than noted above
 * @return class or 0 if any other bl->type than noted above
 **/
 **/
@@ -7683,7 +7665,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	// Strip skills, need to divest something or it fails.
 	// Strip skills, need to divest something or it fails.
 	case SC_STRIPWEAPON:
 	case SC_STRIPWEAPON:
 		if (sd && !(flag&4)) { // Apply sc anyway if loading saved sc_data
 		if (sd && !(flag&4)) { // Apply sc anyway if loading saved sc_data
-			int i;
+			short i;
 			opt_flag = 0; // Reuse to check success condition.
 			opt_flag = 0; // Reuse to check success condition.
 			if(sd->bonus.unstripable_equip&EQP_WEAPON)
 			if(sd->bonus.unstripable_equip&EQP_WEAPON)
 				return 0;
 				return 0;
@@ -7706,7 +7688,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		if( val2 == 1 ) val2 = 0; // GX effect. Do not take shield off..
 		if( val2 == 1 ) val2 = 0; // GX effect. Do not take shield off..
 		else
 		else
 		if (sd && !(flag&4)) {
 		if (sd && !(flag&4)) {
-			int i;
+			short i;
 			if(sd->bonus.unstripable_equip&EQP_SHIELD)
 			if(sd->bonus.unstripable_equip&EQP_SHIELD)
 				return 0;
 				return 0;
 			i = sd->equip_index[EQI_HAND_L];
 			i = sd->equip_index[EQI_HAND_L];
@@ -7718,7 +7700,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	break;
 	break;
 	case SC_STRIPARMOR:
 	case SC_STRIPARMOR:
 		if (sd && !(flag&4)) {
 		if (sd && !(flag&4)) {
-			int i;
+			short i;
 			if(sd->bonus.unstripable_equip&EQP_ARMOR)
 			if(sd->bonus.unstripable_equip&EQP_ARMOR)
 				return 0;
 				return 0;
 			i = sd->equip_index[EQI_ARMOR];
 			i = sd->equip_index[EQI_ARMOR];
@@ -7730,7 +7712,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	break;
 	break;
 	case SC_STRIPHELM:
 	case SC_STRIPHELM:
 		if (sd && !(flag&4)) {
 		if (sd && !(flag&4)) {
-			int i;
+			short i;
 			if(sd->bonus.unstripable_equip&EQP_HELM)
 			if(sd->bonus.unstripable_equip&EQP_HELM)
 				return 0;
 				return 0;
 			i = sd->equip_index[EQI_HEAD_TOP];
 			i = sd->equip_index[EQI_HEAD_TOP];
@@ -7802,7 +7784,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 	break;
 	break;
 	case SC__STRIPACCESSORY:
 	case SC__STRIPACCESSORY:
 		if( sd ) {
 		if( sd ) {
-			int i = -1;
+			short i = -1;
 			if( !(sd->bonus.unstripable_equip&EQP_ACC_L) ) {
 			if( !(sd->bonus.unstripable_equip&EQP_ACC_L) ) {
 				i = sd->equip_index[EQI_ACC_L];
 				i = sd->equip_index[EQI_ACC_L];
 				if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
 				if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR )
@@ -8215,7 +8197,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			case SC_MARIONETTE:
 			case SC_MARIONETTE:
 			case SC_MARIONETTE2:
 			case SC_MARIONETTE2:
 			case SC_NOCHAT:
 			case SC_NOCHAT:
-			case SC_CHANGE: // Otherwise your Hp/Sp would get refilled while still within effect of the last invocation.
 			case SC_ABUNDANCE:
 			case SC_ABUNDANCE:
 			case SC_FEAR:
 			case SC_FEAR:
 			case SC_TOXIN:
 			case SC_TOXIN:
@@ -8933,7 +8914,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val2 = 5*val1; // def increase
 			val2 = 5*val1; // def increase
 			break;
 			break;
 		case SC_IMPOSITIO:
 		case SC_IMPOSITIO:
-			val2 = 5*val1; // Atk increase
+			val2 = 5*val1; // Watk increase
 			break;
 			break;
 		case SC_MELTDOWN:
 		case SC_MELTDOWN:
 			val2 = 100*val1; // Chance to break weapon
 			val2 = 100*val1; // Chance to break weapon
@@ -9455,10 +9436,13 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			tick_time = 10000; // [GodLesZ] tick time
 			tick_time = 10000; // [GodLesZ] tick time
 			break;
 			break;
 		case SC_EXEEDBREAK:
 		case SC_EXEEDBREAK:
-			val1 *= 100; // 100 * skill_lv
-			if( sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]] ) {
-				val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status_get_lv(bl) / 100);
-				val1 += 10 * sd->status.job_level;
+			{
+				short idx = -1;
+				val1 *= 100; // 100 * skill_lv
+				if( sd && (idx = sd->equip_index[EQI_HAND_R]) >= 0 && sd->inventory_data[idx] ) {
+					val1 += (sd->inventory_data[idx]->weight/10 * sd->inventory_data[idx]->wlv * status_get_lv(bl) / 100);
+					val1 += 10 * sd->status.job_level;
+				}
 			}
 			}
 			break;
 			break;
 		case SC_PRESTIGE:
 		case SC_PRESTIGE:
@@ -9476,8 +9460,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			break;
 			break;
 		case SC_INSPIRATION:
 		case SC_INSPIRATION:
 			if( sd ) {
 			if( sd ) {
-				val2 = status_get_lv(bl) / 10 + (sd?sd->status.job_level:50) / 5; // All stat bonus
-				val3 = (sd?sd->status.job_level:50);
+				val2 = (sd?sd->status.job_level:50);
+				val3 = status_get_lv(bl) / 10 + val2 / 5; //All stat bonus
 			}
 			}
 			val4 = tick / 5000;
 			val4 = tick / 5000;
 			tick_time = 5000; // [GodLesZ] tick time
 			tick_time = 5000; // [GodLesZ] tick time
@@ -9501,8 +9485,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			{ // Take note there is no def increase as skill desc says. [malufett]
 			{ // Take note there is no def increase as skill desc says. [malufett]
 				struct block_list * src2;
 				struct block_list * src2;
 				val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] %
 				val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] %
-				if( (src2 = map_id2bl(val2)) )
+				if( (src2 = map_id2bl(val2)) ) {
+					val2 = (status_get_dex(src2) / 4 + status_get_str(src2) / 2) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5]
 					val4 = ( 200/status_get_int(src2) ) * val1; // MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
 					val4 = ( 200/status_get_int(src2) ) * val1; // MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
+				}
 				if( val4 < 0 )
 				if( val4 < 0 )
 					val4 = 0;
 					val4 = 0;
 			}
 			}
@@ -9937,7 +9923,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		case SC_STONE:
 		case SC_STONE:
 		case SC_DEEPSLEEP:
 		case SC_DEEPSLEEP:
 			if (sd && pc_issit(sd)) // Avoid sprite sync problems.
 			if (sd && pc_issit(sd)) // Avoid sprite sync problems.
-				pc_setstand(sd);
+				pc_setstand(sd, true);
 		case SC_TRICKDEAD:
 		case SC_TRICKDEAD:
 			status_change_end(bl, SC_DANCING, INVALID_TIMER);
 			status_change_end(bl, SC_DANCING, INVALID_TIMER);
 			// Cancel cast when get status [LuzZza]
 			// Cancel cast when get status [LuzZza]
@@ -10230,9 +10216,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			}
 			}
 			sce->val2 = 5 * status->max_hp / 100;
 			sce->val2 = 5 * status->max_hp / 100;
 			break;
 			break;
-		case SC_CHANGE:
-			status_percent_heal(bl, 100, 100);
-			break;
 		case SC_RUN:
 		case SC_RUN:
 			{
 			{
 				struct unit_data *ud = unit_bl2ud(bl);
 				struct unit_data *ud = unit_bl2ud(bl);
@@ -10780,7 +10763,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 
 
 		/* 3rd Stuff */
 		/* 3rd Stuff */
 		case SC_MILLENNIUMSHIELD:
 		case SC_MILLENNIUMSHIELD:
-			clif_millenniumshield(sd,0);
+			clif_millenniumshield(bl, 0);
 			break;
 			break;
 		case SC_HALLUCINATIONWALK:
 		case SC_HALLUCINATIONWALK:
 			sc_start(bl,bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill_get_time2(GC_HALLUCINATIONWALK,sce->val1));
 			sc_start(bl,bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill_get_time2(GC_HALLUCINATIONWALK,sce->val1));
@@ -10790,7 +10773,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 				struct block_list* src = map_id2bl(sce->val2);
 				struct block_list* src = map_id2bl(sce->val2);
 				if( tid == -1 || !src)
 				if( tid == -1 || !src)
 					break; // Terminated by Damage
 					break; // Terminated by Damage
-				status_fix_damage(src,bl,400*sce->val1,clif_damage(bl,bl,gettick(),0,0,400*sce->val1,0,0,0));
+				status_fix_damage(src,bl,400*sce->val1,clif_damage(bl,bl,gettick(),0,0,400*sce->val1,0,DMG_NORMAL,0));
 			}
 			}
 			break;
 			break;
 		case SC_WUGDASH:
 		case SC_WUGDASH:
@@ -10824,8 +10807,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 			sc_start(bl, bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1));
 			sc_start(bl, bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1));
 			break;
 			break;
 		case SC_SITDOWN_FORCE:
 		case SC_SITDOWN_FORCE:
-			if( sd && pc_issit(sd) ) {
-				pc_setstand(sd);
+			if( sd && pc_issit(sd) && pc_setstand(sd, false) ) {
 				clif_standing(bl);
 				clif_standing(bl);
 			}
 			}
 			break;
 			break;
@@ -10884,8 +10866,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 			status_change_end(bl,SC_TEARGAS_SOB,INVALID_TIMER);
 			status_change_end(bl,SC_TEARGAS_SOB,INVALID_TIMER);
 			break;
 			break;
 		case SC_BANANA_BOMB_SITDOWN:
 		case SC_BANANA_BOMB_SITDOWN:
-			if( sd && pc_issit(sd) ) {
-				pc_setstand(sd);
+			if( sd && pc_issit(sd) && pc_setstand(sd, false) ) {
 				skill_sit(sd,0);
 				skill_sit(sd,0);
 				clif_standing(bl);
 				clif_standing(bl);
 			}
 			}
@@ -11554,7 +11535,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_PYREXIA:
 	case SC_PYREXIA:
 		if( --(sce->val4) >= 0 ) {
 		if( --(sce->val4) >= 0 ) {
 			map_freeblock_lock();
 			map_freeblock_lock();
-			clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0);
+			clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,DMG_NORMAL,0);
 			status_fix_damage(NULL,bl,100,0);
 			status_fix_damage(NULL,bl,100,0);
 			if( sc->data[type] ) {
 			if( sc->data[type] ) {
 				sc_timer_next(3000+tick,status_change_timer,bl->id,data);
 				sc_timer_next(3000+tick,status_change_timer,bl->id,data);
@@ -11570,7 +11551,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			damage += status->vit * (sce->val1 - 3);
 			damage += status->vit * (sce->val1 - 3);
 			unit_skillcastcancel(bl,2);
 			unit_skillcastcancel(bl,2);
 			map_freeblock_lock();
 			map_freeblock_lock();
-			status_damage(bl, bl, damage, 0, clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1);
+			status_damage(bl, bl, damage, 0, clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,DMG_NORMAL,0), 1);
 			if( sc->data[type] ) {
 			if( sc->data[type] ) {
 				sc_timer_next(1000 + tick, status_change_timer, bl->id, data );
 				sc_timer_next(1000 + tick, status_change_timer, bl->id, data );
 			}
 			}
@@ -11627,7 +11608,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_TOXIN:
 	case SC_TOXIN:
 		if( --(sce->val4) >= 0 ) { // Damage is every 10 seconds including 3%sp drain.
 		if( --(sce->val4) >= 0 ) { // Damage is every 10 seconds including 3%sp drain.
 			map_freeblock_lock();
 			map_freeblock_lock();
-			clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0);
+			clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,DMG_NORMAL,0);
 			status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); // Cancel dmg only if cancelable
 			status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); // Cancel dmg only if cancelable
 			if( sc->data[type] ) {
 			if( sc->data[type] ) {
 				sc_timer_next(10000 + tick, status_change_timer, bl->id, data );
 				sc_timer_next(10000 + tick, status_change_timer, bl->id, data );
@@ -11677,7 +11658,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP)
 			int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP)
 
 
 			map_freeblock_lock();
 			map_freeblock_lock();
-			clif_damage(bl,bl,tick,0,0,damage,1,9,0); // Damage is like endure effect with no walk delay
+			clif_damage(bl,bl,tick,0,0,damage,1,DMG_MULTI_HIT_ENDURE,0); // Damage is like endure effect with no walk delay
 			status_damage(src, bl, damage, 0, 0, 1);
 			status_damage(src, bl, damage, 0, 0, 1);
 			if( sc->data[type]) { // Target still lives. [LimitLine]
 			if( sc->data[type]) { // Target still lives. [LimitLine]
 				sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
 				sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
@@ -11781,7 +11762,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				break;
 				break;
 			map_freeblock_lock();
 			map_freeblock_lock();
 			damage =  200 + 100 * sce->val1 + status_get_int(src);
 			damage =  200 + 100 * sce->val1 + status_get_int(src);
-			status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,0,0), 0);
+			status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,DMG_NORMAL,0), 0);
 			unit_skillcastcancel(bl,1);
 			unit_skillcastcancel(bl,1);
 			if ( sc->data[type] ) {
 			if ( sc->data[type] ) {
 				sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
 				sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
@@ -11888,7 +11869,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			int damage = status->max_hp / 100; // Suggestion 1% each second
 			int damage = status->max_hp / 100; // Suggestion 1% each second
 			if( damage >= status->hp ) damage = status->hp - 1; // Do not kill, just keep you with 1 hp minimum
 			if( damage >= status->hp ) damage = status->hp - 1; // Do not kill, just keep you with 1 hp minimum
 			map_freeblock_lock();
 			map_freeblock_lock();
-			status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,0,0));
+			status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,DMG_NORMAL,0));
 			if( sc->data[type] ) {
 			if( sc->data[type] ) {
 				sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
 				sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
 			}
 			}
@@ -11972,7 +11953,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			int damage = sce->val2;
 			int damage = sce->val2;
 
 
 			map_freeblock_lock();
 			map_freeblock_lock();
-			clif_damage(bl, bl, tick, 0, 0, damage, 1, 9, 0);
+			clif_damage(bl, bl, tick, 0, 0, damage, 1, DMG_MULTI_HIT_ENDURE, 0);
 			status_damage(src, bl, damage,0, 0, 1);
 			status_damage(src, bl, damage,0, 0, 1);
 			if( sc->data[type] ) {
 			if( sc->data[type] ) {
 				sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
 				sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
@@ -12711,47 +12692,42 @@ static bool status_readdb_refine(char* fields[], int columns, int current)
 static bool status_readdb_attrfix(const char *basedir,bool silent)
 static bool status_readdb_attrfix(const char *basedir,bool silent)
 {
 {
 	FILE *fp;
 	FILE *fp;
-	char line[512], path[512],*p;
-	int entries=0;
+	char line[512], path[512];
+	int entries = 0;
 
 
 
 
 	sprintf(path, "%s/attr_fix.txt", basedir);
 	sprintf(path, "%s/attr_fix.txt", basedir);
-	fp=fopen(path,"r");
-	if(fp==NULL) {
-		if(silent==0) ShowError("can't read %s\n", path);
+	fp = fopen(path,"r");
+	if (fp == NULL) {
+		if (silent==0)
+			ShowError("Can't read %s\n", path);
 		return 1;
 		return 1;
 	}
 	}
-	while(fgets(line, sizeof(line), fp))
-	{
-		char *split[10];
-		int lv,n,i,j;
-		if(line[0]=='/' && line[1]=='/')
-			continue;
-		for(j=0,p=line;j<3 && p;j++) {
-			split[j]=p;
-			p=strchr(p,',');
-			if(p) *p++=0;
-		}
-		if( j < 2 )
+	while (fgets(line, sizeof(line), fp)) {
+		int lv, i, j;
+		if (line[0] == '/' && line[1] == '/')
 			continue;
 			continue;
 
 
-		lv=atoi(split[0]);
-		n=atoi(split[1]);
+		lv = atoi(line);
+		if (!CHK_ELEMENT_LEVEL(lv))
+			continue;
 
 
-		for(i=0;i<n && i<ELE_ALL;) {
-			if( !fgets(line, sizeof(line), fp) )
+		for (i = 0; i < ELE_ALL;) {
+			char *p;
+			if (!fgets(line, sizeof(line), fp))
 				break;
 				break;
-			if(line[0]=='/' && line[1]=='/')
+			if (line[0]=='/' && line[1]=='/')
 				continue;
 				continue;
 
 
-			for(j=0,p=line;j<n && j<ELE_ALL && p;j++) {
-				while(*p>0 && *p==32) //skipping newline and space (32=' ')
+			for (j = 0, p = line; j < ELE_ALL && p; j++) {
+				while (*p > 0 && *p == 32) //skipping newline and space (32=' ')
 					p++;
 					p++;
-				attr_fix_table[lv-1][i][j]=atoi(p);
-				if(battle_config.attr_recover == 0 && attr_fix_table[lv-1][i][j] < 0)
+				attr_fix_table[lv-1][i][j] = atoi(p);
+				if (battle_config.attr_recover == 0 && attr_fix_table[lv-1][i][j] < 0)
 					attr_fix_table[lv-1][i][j] = 0;
 					attr_fix_table[lv-1][i][j] = 0;
-				p=strchr(p,',');
-				if(p) *p++=0;
+				p = strchr(p,',');
+				if(p)
+					*p++=0;
 			}
 			}
 
 
 			i++;
 			i++;

+ 3 - 3
src/map/status.h

@@ -1535,7 +1535,7 @@ enum e_joint_break
 	BREAK_FLAGS	= BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK,
 	BREAK_FLAGS	= BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK,
 };
 };
 
 
-extern int current_equip_item_index;
+extern short current_equip_item_index;
 extern int current_equip_card_id;
 extern int current_equip_card_id;
 
 
 //Mode definitions to clear up code reading. [Skotlex]
 //Mode definitions to clear up code reading. [Skotlex]
@@ -1556,9 +1556,9 @@ enum e_mode {
 	MD_CHANGETARGET_CHASE	= 0x002000,
 	MD_CHANGETARGET_CHASE	= 0x002000,
 	MD_TARGETWEAK			= 0x004000,
 	MD_TARGETWEAK			= 0x004000,
 	MD_RANDOMTARGET			= 0x008000,
 	MD_RANDOMTARGET			= 0x008000,
-	MD_IGNOREMELEE			= 0x010000,
+	MD_IGNOREMELEE			= 0x010000, //! TODO: Unused yet
 	MD_IGNOREMAGIC			= 0x020000,
 	MD_IGNOREMAGIC			= 0x020000,
-	MD_IGNORERANGED			= 0x040000,
+	MD_IGNORERANGED			= 0x040000, //! TODO: Unused yet
 	MD_MVP					= 0x080000,
 	MD_MVP					= 0x080000,
 	MD_IGNOREMISC			= 0x100000,
 	MD_IGNOREMISC			= 0x100000,
 	MD_KNOCKBACK_IMMUNE		= 0x200000,
 	MD_KNOCKBACK_IMMUNE		= 0x200000,

+ 57 - 36
src/map/unit.c

@@ -52,7 +52,7 @@ const short diry[8]={1,1,0,-1,-1,-1,0,1}; ///lookup to know where will move to y
 //early declaration
 //early declaration
 static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data);
 static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data);
 static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data);
 static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data);
-
+int unit_unattackable(struct block_list *bl);
 /**
 /**
  * Get the unit_data related to the bl
  * Get the unit_data related to the bl
  * @param bl : Object to get the unit_data from
  * @param bl : Object to get the unit_data from
@@ -204,8 +204,19 @@ int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data)
  */
  */
 int unit_check_start_teleport_timer(struct block_list *sbl)
 int unit_check_start_teleport_timer(struct block_list *sbl)
 {
 {
-	TBL_PC *msd = unit_get_master(sbl);
+	TBL_PC *msd=NULL;
 	int max_dist = 0;
 	int max_dist = 0;
+	switch(sbl->type) {
+		case BL_HOM:	
+		case BL_ELEM:	
+		case BL_PET:	
+		case BL_MER:	
+			msd = unit_get_master(sbl);
+			break;
+		default:
+			return 0;
+	}
+	
 	switch(sbl->type) {
 	switch(sbl->type) {
 		case BL_HOM:	max_dist = AREA_SIZE;			break;
 		case BL_HOM:	max_dist = AREA_SIZE;			break;
 		case BL_ELEM:	max_dist = MAX_ELEDISTANCE;		break;
 		case BL_ELEM:	max_dist = MAX_ELEDISTANCE;		break;
@@ -213,7 +224,7 @@ int unit_check_start_teleport_timer(struct block_list *sbl)
 		case BL_MER:	max_dist = MAX_MER_DISTANCE;	break;
 		case BL_MER:	max_dist = MAX_MER_DISTANCE;	break;
 	}
 	}
 	// If there is a master and it's a valid type
 	// If there is a master and it's a valid type
-	if(msd && (msd->bl.type&BL_PC) && max_dist) { ///TODO the bl.type is an hotfix please dig it to remove it
+	if(msd && max_dist) {
 		int *msd_tid = unit_get_masterteleport_timer(sbl);
 		int *msd_tid = unit_get_masterteleport_timer(sbl);
 		if(msd_tid == NULL) return 0;
 		if(msd_tid == NULL) return 0;
 		if (!check_distance_bl(&msd->bl, sbl, max_dist)) {
 		if (!check_distance_bl(&msd->bl, sbl, max_dist)) {
@@ -244,23 +255,16 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
 	uint8 dir;
 	uint8 dir;
 	struct block_list *bl;
 	struct block_list *bl;
 	struct unit_data *ud;
 	struct unit_data *ud;
-	TBL_PC *sd;
-	TBL_MOB *md;
-	TBL_MER *mrd;
-	TBL_ELEM *ed;
-	TBL_PET *pd;
-	TBL_HOM *hd;
-
+	TBL_PC *sd=NULL;
+	TBL_MOB *md=NULL;
 
 
 	bl = map_id2bl(id);
 	bl = map_id2bl(id);
 	if(bl == NULL)
 	if(bl == NULL)
 		return 0;
 		return 0;
-	sd = BL_CAST(BL_PC, bl);
-	md = BL_CAST(BL_MOB, bl);
-	mrd = BL_CAST(BL_MER, bl);
-	ed = BL_CAST(BL_ELEM, bl);
-	pd = BL_CAST(BL_PET, bl);
-	hd = BL_CAST(BL_HOM, bl);
+	switch(bl->type){ //svoid useless cast, we can only be 1 type
+		case BL_PC: sd = BL_CAST(BL_PC, bl); break;
+		case BL_MOB: md = BL_CAST(BL_MOB, bl); break;
+	}
 	ud = unit_bl2ud(bl);
 	ud = unit_bl2ud(bl);
 
 
 	if(ud == NULL) return 0;
 	if(ud == NULL) return 0;
@@ -305,7 +309,8 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
 	map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
 	map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl);
 	ud->walktimer = INVALID_TIMER;
 	ud->walktimer = INVALID_TIMER;
 
 
-	if(sd) {
+	switch(bl->type){
+	case BL_PC: {
 		if( sd->touching_id )
 		if( sd->touching_id )
 			npc_touchnext_areanpc(sd,false);
 			npc_touchnext_areanpc(sd,false);
 		if(map_getcell(bl->m,x,y,CELL_CHKNPC)) {
 		if(map_getcell(bl->m,x,y,CELL_CHKNPC)) {
@@ -314,14 +319,17 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
 				return 0;
 				return 0;
 		} else
 		} else
 			sd->areanpc_id=0;
 			sd->areanpc_id=0;
-
+		/* WIP disable [Lighta], currently unsuported 
+		 * this was meant to start the timer if the player move but not his slave...
 		if(sd->md) unit_check_start_teleport_timer(&sd->md->bl);
 		if(sd->md) unit_check_start_teleport_timer(&sd->md->bl);
 		if(sd->ed) unit_check_start_teleport_timer(&sd->ed->bl);
 		if(sd->ed) unit_check_start_teleport_timer(&sd->ed->bl);
 		if(sd->hd) unit_check_start_teleport_timer(&sd->hd->bl);
 		if(sd->hd) unit_check_start_teleport_timer(&sd->hd->bl);
 		if(sd->pd) unit_check_start_teleport_timer(&sd->pd->bl);
 		if(sd->pd) unit_check_start_teleport_timer(&sd->pd->bl);
-		
+		*/
 		pc_cell_basilica(sd);
 		pc_cell_basilica(sd);
-	} else if (md) {
+	}
+	break;
+	case BL_MOB: {
 		if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
 		if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
 			if( npc_touch_areanpc2(md) )
 			if( npc_touch_areanpc2(md) )
 				return 0; // Warped
 				return 0; // Warped
@@ -342,10 +350,14 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
 			clif_move(ud);
 			clif_move(ud);
 		}
 		}
 	}
 	}
-	else if (hd) unit_check_start_teleport_timer(&hd->bl);
-	else if (ed) unit_check_start_teleport_timer(&ed->bl);
-	else if (pd) unit_check_start_teleport_timer(&pd->bl);
-	else if (mrd) unit_check_start_teleport_timer(&mrd->bl);
+	break;
+	case BL_HOM: 
+	case BL_ELEM:
+	case BL_PET:
+	case BL_MER:
+		unit_check_start_teleport_timer(bl);
+		break;
+	}
 
 
 	if(tid == INVALID_TIMER) // A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
 	if(tid == INVALID_TIMER) // A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
 		return 0;
 		return 0;
@@ -474,11 +486,14 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
 	if( (battle_config.max_walk_path < wpd.path_len) && (bl->type != BL_NPC) )
 	if( (battle_config.max_walk_path < wpd.path_len) && (bl->type != BL_NPC) )
 		return 0;
 		return 0;
 
 
-	if (flag&4 && DIFF_TICK(ud->canmove_tick, gettick()) > 0 &&
-		DIFF_TICK(ud->canmove_tick, gettick()) < 2000)
-	{	// Delay walking command. [Skotlex]
-		add_timer(ud->canmove_tick+1, unit_delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF));
-		return 1;
+	if (flag&4){
+		unit_unattackable(bl);
+		unit_stop_attack(bl);
+		if(DIFF_TICK(ud->canmove_tick, gettick()) > 0 && DIFF_TICK(ud->canmove_tick, gettick()) < 2000)
+		{	// Delay walking command. [Skotlex]
+			add_timer(ud->canmove_tick+1, unit_delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF));
+			return 1;
+		}
 	}
 	}
 
 
 	if(!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit_can_move(bl)))
 	if(!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit_can_move(bl)))
@@ -504,7 +519,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
 		delete_timer( ud->attacktimer, unit_attack_timer );
 		delete_timer( ud->attacktimer, unit_attack_timer );
 		ud->attacktimer = INVALID_TIMER;
 		ud->attacktimer = INVALID_TIMER;
 	}
 	}
-
+	
 	return unit_walktoxy_sub(bl);
 	return unit_walktoxy_sub(bl);
 }
 }
 
 
@@ -1142,6 +1157,7 @@ int unit_can_move(struct block_list *bl) {
 	))
 	))
 		return 0; // Can't move
 		return 0; // Can't move
 
 
+	// Status changes that block movement
 	if (sc) {
 	if (sc) {
 		if( sc->cant.move // status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability
 		if( sc->cant.move // status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability
 			|| (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
 			|| (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
@@ -1268,7 +1284,9 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
 		sc = NULL; // Unneeded
 		sc = NULL; // Unneeded
 
 
 	// temp: used to signal combo-skills right now.
 	// temp: used to signal combo-skills right now.
-	if (sc && sc->data[SC_COMBO] && (sc->data[SC_COMBO]->val1 == skill_id ||
+	if (sc && sc->data[SC_COMBO] &&
+		skill_is_combo(skill_id) &&
+		(sc->data[SC_COMBO]->val1 == skill_id ||
 		(sd?skill_check_condition_castbegin(sd,skill_id,skill_lv):0) ))
 		(sd?skill_check_condition_castbegin(sd,skill_id,skill_lv):0) ))
 	{
 	{
 		if (sc->data[SC_COMBO]->val2)
 		if (sc->data[SC_COMBO]->val2)
@@ -1814,6 +1832,7 @@ int unit_unattackable(struct block_list *bl)
 	struct unit_data *ud = unit_bl2ud(bl);
 	struct unit_data *ud = unit_bl2ud(bl);
 	if (ud) {
 	if (ud) {
 		ud->state.attack_continue = 0;
 		ud->state.attack_continue = 0;
+		ud->target_to = 0;
 		unit_set_target(ud, 0);
 		unit_set_target(ud, 0);
 	}
 	}
 
 
@@ -1854,6 +1873,10 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
 			unit_stop_attack(src);
 			unit_stop_attack(src);
 			return 0;
 			return 0;
 		}
 		}
+		if( !pc_can_attack(sd, target_id) ) {
+			unit_stop_attack(src);
+			return 0;
+		}
 	}
 	}
 	if( battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) {
 	if( battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) {
 		unit_unattackable(src);
 		unit_unattackable(src);
@@ -2066,7 +2089,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
 #ifdef OFFICIAL_WALKPATH
 #ifdef OFFICIAL_WALKPATH
 	   || !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)
 	   || !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)
 #endif
 #endif
-	   )
+	   || (sd && !pc_can_attack(sd, target->id)) )
 		return 0; // Can't attack under these conditions
 		return 0; // Can't attack under these conditions
 
 
 	if (sd && &sd->sc && sd->sc.count && sd->sc.data[SC_HEAT_BARREL_AFTER])
 	if (sd && &sd->sc && sd->sc.count && sd->sc.data[SC_HEAT_BARREL_AFTER])
@@ -2158,7 +2181,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
 	}
 	}
 
 
 	if(ud->state.attack_continue) {
 	if(ud->state.attack_continue) {
-		if( src->type == BL_PC )
+		if (src->type == BL_PC && battle_config.idletime_option&IDLE_ATTACK)
 			((TBL_PC*)src)->idletime = last_tick;
 			((TBL_PC*)src)->idletime = last_tick;
 		ud->attacktimer = add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
 		ud->attacktimer = add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
 	}
 	}
@@ -2390,7 +2413,6 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 				chat_leavechat(sd,0);
 				chat_leavechat(sd,0);
 			if(sd->trade_partner)
 			if(sd->trade_partner)
 				trade_tradecancel(sd);
 				trade_tradecancel(sd);
-			buyingstore_close(sd);
 			searchstore_close(sd);
 			searchstore_close(sd);
 			if (sd->menuskill_id != AL_TELEPORT) { //bugreport:8027
 			if (sd->menuskill_id != AL_TELEPORT) { //bugreport:8027
 				if (sd->state.storage_flag == 1)
 				if (sd->state.storage_flag == 1)
@@ -2428,8 +2450,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 			if(sd->duel_group > 0)
 			if(sd->duel_group > 0)
 				duel_leave(sd->duel_group, sd);
 				duel_leave(sd->duel_group, sd);
 
 
-			if(pc_issit(sd)) {
-				pc_setstand(sd);
+			if(pc_issit(sd) && pc_setstand(sd, false)) {
 				skill_sit(sd,0);
 				skill_sit(sd,0);
 			}
 			}
 			party_send_dot_remove(sd);// minimap dot fix [Kevin]
 			party_send_dot_remove(sd);// minimap dot fix [Kevin]

+ 77 - 47
src/map/vending.c

@@ -39,7 +39,7 @@ struct s_autotrade {
 	int m;
 	int m;
 	uint16 x,
 	uint16 x,
 		y;
 		y;
-	unsigned char sex;
+	unsigned char sex, dir, head_dir, sit;
 	char title[MESSAGE_SIZE];
 	char title[MESSAGE_SIZE];
 	uint16 count;
 	uint16 count;
 	struct s_autotrade_entry **entries;
 	struct s_autotrade_entry **entries;
@@ -51,7 +51,7 @@ static DBMap *vending_db; ///Db holder the vender : charid -> map_session_data
 
 
 //Autotrader
 //Autotrader
 static struct s_autotrade **autotraders; ///Autotraders Storage
 static struct s_autotrade **autotraders; ///Autotraders Storage
-static uint16 autotrader_count; ///Autotrader count
+static uint16 autotrader_count, autotrader_loaded_count; ///Autotrader count
 static void do_final_vending_autotrade(void);
 static void do_final_vending_autotrade(void);
 
 
 /**
 /**
@@ -85,6 +85,7 @@ void vending_closevending(struct map_session_data* sd)
 		}
 		}
 		
 		
 		sd->state.vending = false;
 		sd->state.vending = false;
+		sd->vender_id = 0;
 		clif_closevendingboard(&sd->bl, 0);
 		clif_closevendingboard(&sd->bl, 0);
 		idb_remove(vending_db, sd->status.char_id);
 		idb_remove(vending_db, sd->status.char_id);
 	}
 	}
@@ -297,29 +298,30 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
  *	data := {<index>.w <amount>.w <value>.l}[count]
  *	data := {<index>.w <amount>.w <value>.l}[count]
  * @param count : number of different items
  * @param count : number of different items
  */
  */
-bool vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
+char vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) {
 	int i, j;
 	int i, j;
 	int vending_skill_lvl;
 	int vending_skill_lvl;
 	char message_sql[MESSAGE_SIZE*2];
 	char message_sql[MESSAGE_SIZE*2];
 	
 	
 	nullpo_retr(false,sd);
 	nullpo_retr(false,sd);
 
 
-	if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd))
-		return false; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once
+	if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) {
+		return 1; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once
+	}
 
 
 	vending_skill_lvl = pc_checkskill(sd, MC_VENDING);
 	vending_skill_lvl = pc_checkskill(sd, MC_VENDING);
 	
 	
 	// skill level and cart check
 	// skill level and cart check
 	if( !vending_skill_lvl || !pc_iscarton(sd) ) {
 	if( !vending_skill_lvl || !pc_iscarton(sd) ) {
 		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
 		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
-		return false;
+		return 2;
 	}
 	}
 
 
 	// check number of items in shop
 	// check number of items in shop
 	if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl )
 	if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl )
 	{	// invalid item count
 	{	// invalid item count
 		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
 		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
-		return false;
+		return 3;
 	}
 	}
 
 
 	if (save_settings&2) // Avoid invalid data from saving
 	if (save_settings&2) // Avoid invalid data from saving
@@ -356,7 +358,7 @@ bool vending_openvending(struct map_session_data* sd, const char* message, const
 			sprintf(msg, msg_txt(sd, 733), idb->jname);
 			sprintf(msg, msg_txt(sd, 733), idb->jname);
 			clif_displaymessage(sd->fd, msg);
 			clif_displaymessage(sd->fd, msg);
 			clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
 			clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
-			return false;
+			return 4;
 		}
 		}
 
 
 		i++; // item successfully added
 		i++; // item successfully added
@@ -367,7 +369,7 @@ bool vending_openvending(struct map_session_data* sd, const char* message, const
 
 
 	if( i == 0 ) { // no valid item found
 	if( i == 0 ) { // no valid item found
 		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
 		clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet
-		return false;
+		return 5;
 	}
 	}
 	sd->state.prevend = 0;
 	sd->state.prevend = 0;
 	sd->state.vending = true;
 	sd->state.vending = true;
@@ -377,7 +379,9 @@ bool vending_openvending(struct map_session_data* sd, const char* message, const
 	
 	
 	Sql_EscapeString( mmysql_handle, message_sql, sd->message );
 	Sql_EscapeString( mmysql_handle, message_sql, sd->message );
 
 
-	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`autotrade`) VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d );", vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade ) != SQL_SUCCESS ){
+	if( Sql_Query( mmysql_handle, "INSERT INTO `%s`(`id`,`account_id`,`char_id`,`sex`,`map`,`x`,`y`,`title`,`autotrade`, `body_direction`, `head_direction`, `sit`) "
+		"VALUES( %d, %d, %d, '%c', '%s', %d, %d, '%s', %d, '%d', '%d', '%d' );",
+		vendings_db, sd->vender_id, sd->status.account_id, sd->status.char_id, sd->status.sex == 0 ? 'F' : 'M', map[sd->bl.m].name, sd->bl.x, sd->bl.y, message_sql, sd->state.autotrade, sd->ud.dir, sd->head_dir, pc_issit(sd) ) != SQL_SUCCESS ){
 		Sql_ShowDebug(mmysql_handle);
 		Sql_ShowDebug(mmysql_handle);
 	}
 	}
 
 
@@ -392,7 +396,7 @@ bool vending_openvending(struct map_session_data* sd, const char* message, const
 
 
 	idb_put(vending_db, sd->status.char_id, sd);
 	idb_put(vending_db, sd->status.char_id, sd);
 
 
-	return true;
+	return 0;
 }
 }
 
 
 /**
 /**
@@ -475,14 +479,17 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
 	return true;
 	return true;
 }
 }
 
 
-/** Open vending for Autotrader
+/**
+* Open vending for Autotrader
 * @param sd Player as autotrader
 * @param sd Player as autotrader
 */
 */
 void vending_reopen( struct map_session_data* sd ){
 void vending_reopen( struct map_session_data* sd ){
+	nullpo_retv(sd);
+
 	// Ready to open vending for this char
 	// Ready to open vending for this char
-	if ( sd && autotrader_count > 0 && autotraders){
+	if ( autotrader_count > 0 && autotraders){
 		uint16 i;
 		uint16 i;
-		uint8 *data, *p;
+		uint8 *data, *p, fail = 0;
 		uint16 j, count;
 		uint16 j, count;
 
 
 		ARR_FIND(0,autotrader_count,i,autotraders[i] && autotraders[i]->char_id == sd->status.char_id);
 		ARR_FIND(0,autotrader_count,i,autotraders[i] && autotraders[i]->char_id == sd->status.char_id);
@@ -508,7 +515,7 @@ void vending_reopen( struct map_session_data* sd ){
 			}
 			}
 
 
 			*index = entry->index + 2;
 			*index = entry->index + 2;
-			*amount = itemdb_isstackable(sd->status.cart[entry->index].id) ? entry->amount : 1;
+			*amount = itemdb_isstackable(sd->status.cart[entry->index].nameid) ? entry->amount : 1;
 			*value = entry->price;
 			*value = entry->price;
 
 
 			p += 8;
 			p += 8;
@@ -517,26 +524,37 @@ void vending_reopen( struct map_session_data* sd ){
 		// Set him into a hacked prevend state
 		// Set him into a hacked prevend state
 		sd->state.prevend = 1;
 		sd->state.prevend = 1;
 
 
+		// Make sure abort all NPCs
+		npc_event_dequeue(sd);
+		pc_cleareventtimer(sd);
+
 		// Open the vending again
 		// Open the vending again
-		if( vending_openvending(sd, autotraders[i]->title, data, count) ){
+		if( (fail = vending_openvending(sd, autotraders[i]->title, data, count)) == 0 ){
 			// Set him to autotrade
 			// Set him to autotrade
-			if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1 WHERE `id` = %d;",
-				vendings_db, sd->vender_id ) != SQL_SUCCESS )
+			if (Sql_Query( mmysql_handle, "UPDATE `%s` SET `autotrade` = 1, `body_direction` = '%d', `head_direction` = '%d', `sit` = '%d' "
+				"WHERE `id` = %d;",
+				vendings_db, autotraders[i]->dir, autotraders[i]->head_dir, autotraders[i]->sit, sd->vender_id ) != SQL_SUCCESS )
 			{
 			{
 				Sql_ShowDebug( mmysql_handle );
 				Sql_ShowDebug( mmysql_handle );
 			}
 			}
 
 
-			// Make him look perfect
-			unit_setdir(&sd->bl,battle_config.feature_autotrade_direction);
-
-			if( battle_config.feature_autotrade_sit )
+			// Make vendor look perfect
+			pc_setdir(sd, autotraders[i]->dir, autotraders[i]->head_dir);
+			clif_changed_dir(&sd->bl, AREA_WOS);
+			if( autotraders[i]->sit ) {
 				pc_setsit(sd);
 				pc_setsit(sd);
+				skill_sit(sd, 1);
+				clif_sitting(&sd->bl);
+			}
+
+			// Immediate save
+			chrif_save(sd, 3);
 
 
-			ShowInfo("Loaded autotrade vending data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items at "CL_WHITE"%s (%d,%d)"CL_RESET"\n",
-				sd->status.name,count,mapindex_id2name(sd->mapindex),sd->bl.x,sd->bl.y);
+			ShowInfo("Loaded vending for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items at "CL_WHITE"%s (%d,%d)"CL_RESET"\n",
+				sd->status.name, count, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y);
 		}else{
 		}else{
 			// Failed to open the vending, set him offline
 			// Failed to open the vending, set him offline
-			ShowWarning("Failed to load autotrade vending data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items\n", sd->status.name, count );
+			ShowError("Failed (%d) to load autotrade vending data for '"CL_WHITE"%s"CL_RESET"' with '"CL_WHITE"%d"CL_RESET"' items\n", fail, sd->status.name, count );
 
 
 			map_quit( sd );
 			map_quit( sd );
 		}
 		}
@@ -544,7 +562,7 @@ void vending_reopen( struct map_session_data* sd ){
 		aFree(data);
 		aFree(data);
 
 
 		//If the last autotrade is loaded, clear autotraders [Cydh]
 		//If the last autotrade is loaded, clear autotraders [Cydh]
-		if (i+1 >= autotrader_count)
+		if (++autotrader_loaded_count >= autotrader_count)
 			do_final_vending_autotrade();
 			do_final_vending_autotrade();
 	}
 	}
 }
 }
@@ -555,21 +573,22 @@ void vending_reopen( struct map_session_data* sd ){
 void do_init_vending_autotrade( void ) {
 void do_init_vending_autotrade( void ) {
 	if (battle_config.feature_autotrade) {
 	if (battle_config.feature_autotrade) {
 		uint16 i, items = 0;
 		uint16 i, items = 0;
-		autotrader_count = 0;
+		autotrader_count = autotrader_loaded_count = 0;
 
 
 		// Get autotrader from table. `map`, `x`, and `y`, aren't used here
 		// Get autotrader from table. `map`, `x`, and `y`, aren't used here
 		// Just read player that has data at vending_items [Cydh]
 		// Just read player that has data at vending_items [Cydh]
 		if (Sql_Query(mmysql_handle,
 		if (Sql_Query(mmysql_handle,
-			"SELECT `id`, `account_id`, `char_id`, `sex`, `title` "
+			"SELECT `id`, `account_id`, `char_id`, `sex`, `title`, `body_direction`, `head_direction`, `sit` "
 			"FROM `%s` "
 			"FROM `%s` "
-			"WHERE `autotrade` = 1 AND (SELECT COUNT(`vending_id`) FROM `%s` WHERE `vending_id` = `id`) > 0;",
+			"WHERE `autotrade` = 1 AND (SELECT COUNT(`vending_id`) FROM `%s` WHERE `vending_id` = `id`) > 0 "
+			"ORDER BY `id`;",
 			vendings_db, vending_items_db ) != SQL_SUCCESS )
 			vendings_db, vending_items_db ) != SQL_SUCCESS )
 		{
 		{
 			Sql_ShowDebug(mmysql_handle);
 			Sql_ShowDebug(mmysql_handle);
 			return;
 			return;
 		}
 		}
 
 
-		if( (autotrader_count = (uint32)Sql_NumRows(mmysql_handle)) > 0 ){
+		if( (autotrader_count = (uint16)Sql_NumRows(mmysql_handle)) > 0 ){
 			// Init autotraders
 			// Init autotraders
 			CREATE(autotraders, struct s_autotrade *, autotrader_count);
 			CREATE(autotraders, struct s_autotrade *, autotrader_count);
 
 
@@ -584,23 +603,34 @@ void do_init_vending_autotrade( void ) {
 			while (SQL_SUCCESS == Sql_NextRow(mmysql_handle) && i < autotrader_count) {
 			while (SQL_SUCCESS == Sql_NextRow(mmysql_handle) && i < autotrader_count) {
 				size_t len;
 				size_t len;
 				char* data;
 				char* data;
+				struct s_autotrade *at = NULL;
 
 
 				CREATE(autotraders[i], struct s_autotrade, 1);
 				CREATE(autotraders[i], struct s_autotrade, 1);
+				at = autotraders[i];
 
 
-				Sql_GetData(mmysql_handle, 0, &data, NULL); autotraders[i]->vendor_id = atoi(data);
-				Sql_GetData(mmysql_handle, 1, &data, NULL); autotraders[i]->account_id = atoi(data);
-				Sql_GetData(mmysql_handle, 2, &data, NULL); autotraders[i]->char_id = atoi(data);
-				Sql_GetData(mmysql_handle, 3, &data, NULL); autotraders[i]->sex = (data[0] == 'F') ? 0 : 1;
-				Sql_GetData(mmysql_handle, 4, &data, &len); safestrncpy(autotraders[i]->title, data, min(len + 1, MESSAGE_SIZE));
-				autotraders[i]->count = 0;
+				Sql_GetData(mmysql_handle, 0, &data, NULL); at->vendor_id = atoi(data);
+				Sql_GetData(mmysql_handle, 1, &data, NULL); at->account_id = atoi(data);
+				Sql_GetData(mmysql_handle, 2, &data, NULL); at->char_id = atoi(data);
+				Sql_GetData(mmysql_handle, 3, &data, NULL); at->sex = (data[0] == 'F') ? 0 : 1;
+				Sql_GetData(mmysql_handle, 4, &data, &len); safestrncpy(at->title, data, min(len + 1, MESSAGE_SIZE));
+				Sql_GetData(mmysql_handle, 5, &data, NULL); at->dir = atoi(data);
+				Sql_GetData(mmysql_handle, 6, &data, NULL); at->head_dir = atoi(data);
+				Sql_GetData(mmysql_handle, 7, &data, NULL); at->sit = atoi(data);
+				at->count = 0;
+
+				if (battle_config.feature_autotrade_direction >= 0)
+					at->dir = battle_config.feature_autotrade_direction;
+				if (battle_config.feature_autotrade_head_direction >= 0)
+					at->head_dir = battle_config.feature_autotrade_head_direction;
+				if (battle_config.feature_autotrade_sit >= 0)
+					at->sit = battle_config.feature_autotrade_sit;
 
 
 				// initialize player
 				// initialize player
-				CREATE(autotraders[i]->sd, struct map_session_data, 1);
-			
-				pc_setnewpc(autotraders[i]->sd, autotraders[i]->account_id, autotraders[i]->char_id, 0, gettick(), autotraders[i]->sex, 0);
-			
-				autotraders[i]->sd->state.autotrade = 1;
-				chrif_authreq(autotraders[i]->sd, true);
+				CREATE(at->sd, struct map_session_data, 1);
+				pc_setnewpc(at->sd, at->account_id, at->char_id, 0, gettick(), at->sex, 0);
+				at->sd->state.autotrade = 1;
+				at->sd->state.monster_ignore = (battle_config.autotrade_monsterignore);
+				chrif_authreq(at->sd, true);
 				i++;
 				i++;
 			}
 			}
 			Sql_FreeResult(mmysql_handle);
 			Sql_FreeResult(mmysql_handle);
@@ -610,21 +640,21 @@ void do_init_vending_autotrade( void ) {
 				struct s_autotrade *at = NULL;
 				struct s_autotrade *at = NULL;
 				uint16 j;
 				uint16 j;
 
 
-				if (autotraders[i] == NULL)
+				if ((at = autotraders[i]) == NULL)
 					continue;
 					continue;
-				at = autotraders[i];
 
 
 				if (SQL_ERROR == Sql_Query(mmysql_handle,
 				if (SQL_ERROR == Sql_Query(mmysql_handle,
 					"SELECT `cartinventory_id`, `amount`, `price` "
 					"SELECT `cartinventory_id`, `amount`, `price` "
 					"FROM `%s` "
 					"FROM `%s` "
 					"WHERE `vending_id` = %d "
 					"WHERE `vending_id` = %d "
-					"ORDER BY `index` ASC;", vending_items_db, at->vendor_id ) )
+					"ORDER BY `index` ASC;",
+					vending_items_db, at->vendor_id ) )
 				{
 				{
 					Sql_ShowDebug(mmysql_handle);
 					Sql_ShowDebug(mmysql_handle);
 					continue;
 					continue;
 				}
 				}
 
 
-				if (!(at->count = (uint32)Sql_NumRows(mmysql_handle))) {
+				if (!(at->count = (uint16)Sql_NumRows(mmysql_handle))) {
 					map_quit(at->sd);
 					map_quit(at->sd);
 					continue;
 					continue;
 				}
 				}
@@ -647,7 +677,7 @@ void do_init_vending_autotrade( void ) {
 				Sql_FreeResult(mmysql_handle);
 				Sql_FreeResult(mmysql_handle);
 			}
 			}
 
 
-			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
+			ShowStatus("Done loading '"CL_WHITE"%d"CL_RESET"' vending autotraders with '"CL_WHITE"%d"CL_RESET"' items.\n", autotrader_count, items);
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
src/map/vending.h

@@ -22,7 +22,7 @@ void do_init_vending_autotrade( void );
  
  
 void vending_reopen( struct map_session_data* sd );
 void vending_reopen( struct map_session_data* sd );
 void vending_closevending(struct map_session_data* sd);
 void vending_closevending(struct map_session_data* sd);
-bool vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count);
+char vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count);
 void vending_vendinglistreq(struct map_session_data* sd, int id);
 void vending_vendinglistreq(struct map_session_data* sd, int id);
 void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count);
 void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count);
 bool vending_search(struct map_session_data* sd, unsigned short nameid);
 bool vending_search(struct map_session_data* sd, unsigned short nameid);

+ 9 - 3
vcproj-10/login-server_sql.vcxproj

@@ -147,6 +147,9 @@
     <ClInclude Include="..\src\login\account.h" />
     <ClInclude Include="..\src\login\account.h" />
     <ClInclude Include="..\src\login\ipban.h" />
     <ClInclude Include="..\src\login\ipban.h" />
     <ClInclude Include="..\src\login\login.h" />
     <ClInclude Include="..\src\login\login.h" />
+    <ClInclude Include="..\src\login\loginchrif.h" />
+    <ClInclude Include="..\src\login\loginclif.h" />
+    <ClInclude Include="..\src\login\logincnslif.h" />
     <ClInclude Include="..\src\login\loginlog.h" />
     <ClInclude Include="..\src\login\loginlog.h" />
     <ClInclude Include="..\src\common\cbasetypes.h" />
     <ClInclude Include="..\src\common\cbasetypes.h" />
     <ClInclude Include="..\src\common\core.h" />
     <ClInclude Include="..\src\common\core.h" />
@@ -178,10 +181,13 @@
     <ClCompile Include="..\src\common\mutex.c" />
     <ClCompile Include="..\src\common\mutex.c" />
     <ClCompile Include="..\src\common\raconf.c" />
     <ClCompile Include="..\src\common\raconf.c" />
     <ClCompile Include="..\src\common\thread.c" />
     <ClCompile Include="..\src\common\thread.c" />
-    <ClCompile Include="..\src\login\account_sql.c" />
-    <ClCompile Include="..\src\login\ipban_sql.c" />
+    <ClCompile Include="..\src\login\account.c" />
+    <ClCompile Include="..\src\login\ipban.c" />
     <ClCompile Include="..\src\login\login.c" />
     <ClCompile Include="..\src\login\login.c" />
-    <ClCompile Include="..\src\login\loginlog_sql.c" />
+    <ClCompile Include="..\src\login\loginchrif.c" />
+    <ClCompile Include="..\src\login\loginclif.c" />
+    <ClCompile Include="..\src\login\logincnslif.c" />
+    <ClCompile Include="..\src\login\loginlog.c" />
     <ClCompile Include="..\src\common\core.c" />
     <ClCompile Include="..\src\common\core.c" />
     <ClCompile Include="..\src\common\db.c" />
     <ClCompile Include="..\src\common\db.c" />
     <ClCompile Include="..\src\common\ers.c" />
     <ClCompile Include="..\src\common\ers.c" />

+ 23 - 5
vcproj-10/login-server_sql.vcxproj.filters

@@ -1,16 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\src\login\account_sql.c">
+    <ClCompile Include="..\src\login\account.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\src\login\ipban_sql.c">
+    <ClCompile Include="..\src\login\ipban.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
     <ClCompile Include="..\src\login\login.c">
     <ClCompile Include="..\src\login\login.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\src\login\loginlog_sql.c">
+    <ClCompile Include="..\src\login\loginchrif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\loginclif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\logincnslif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\loginlog.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
     <ClCompile Include="..\src\common\core.c">
     <ClCompile Include="..\src\common\core.c">
@@ -95,10 +104,19 @@
     <ClInclude Include="..\src\login\ipban.h">
     <ClInclude Include="..\src\login\ipban.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\src\login\loginlog.h">
+    <ClInclude Include="..\src\login\login.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\src\login\login.h">
+    <ClInclude Include="..\src\login\loginchrif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\loginclif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\logincnslif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\loginlog.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
     <ClInclude Include="..\src\common\cbasetypes.h">
     <ClInclude Include="..\src\common\cbasetypes.h">

+ 9 - 3
vcproj-12/login-server_sql.vcxproj

@@ -151,6 +151,9 @@
     <ClInclude Include="..\src\login\ipban.h" />
     <ClInclude Include="..\src\login\ipban.h" />
     <ClInclude Include="..\src\login\login.h" />
     <ClInclude Include="..\src\login\login.h" />
     <ClInclude Include="..\src\login\loginlog.h" />
     <ClInclude Include="..\src\login\loginlog.h" />
+    <ClInclude Include="..\src\login\loginchrif.h" />
+    <ClInclude Include="..\src\login\loginclif.h" />
+    <ClInclude Include="..\src\login\logincnslif.h" />
     <ClInclude Include="..\src\common\cbasetypes.h" />
     <ClInclude Include="..\src\common\cbasetypes.h" />
     <ClInclude Include="..\src\common\core.h" />
     <ClInclude Include="..\src\common\core.h" />
     <ClInclude Include="..\src\common\conf.h" />
     <ClInclude Include="..\src\common\conf.h" />
@@ -181,10 +184,13 @@
     <ClCompile Include="..\src\common\mutex.c" />
     <ClCompile Include="..\src\common\mutex.c" />
     <ClCompile Include="..\src\common\raconf.c" />
     <ClCompile Include="..\src\common\raconf.c" />
     <ClCompile Include="..\src\common\thread.c" />
     <ClCompile Include="..\src\common\thread.c" />
-    <ClCompile Include="..\src\login\account_sql.c" />
-    <ClCompile Include="..\src\login\ipban_sql.c" />
+    <ClCompile Include="..\src\login\account.c" />
+    <ClCompile Include="..\src\login\ipban.c" />
     <ClCompile Include="..\src\login\login.c" />
     <ClCompile Include="..\src\login\login.c" />
-    <ClCompile Include="..\src\login\loginlog_sql.c" />
+    <ClCompile Include="..\src\login\loginlog.c" />
+    <ClCompile Include="..\src\login\loginchrif.c" />
+    <ClCompile Include="..\src\login\loginclif.c" />
+    <ClCompile Include="..\src\login\logincnslif.c" />
     <ClCompile Include="..\src\common\core.c" />
     <ClCompile Include="..\src\common\core.c" />
     <ClCompile Include="..\src\common\conf.c" />
     <ClCompile Include="..\src\common\conf.c" />
     <ClCompile Include="..\src\common\db.c" />
     <ClCompile Include="..\src\common\db.c" />

+ 23 - 5
vcproj-12/login-server_sql.vcxproj.filters

@@ -1,16 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\src\login\account_sql.c">
+    <ClCompile Include="..\src\login\account.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\src\login\ipban_sql.c">
+    <ClCompile Include="..\src\login\ipban.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
     <ClCompile Include="..\src\login\login.c">
     <ClCompile Include="..\src\login\login.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\src\login\loginlog_sql.c">
+    <ClCompile Include="..\src\login\loginchrif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\loginclif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\logincnslif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\loginlog.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
     <ClCompile Include="..\src\common\core.c">
     <ClCompile Include="..\src\common\core.c">
@@ -93,10 +102,19 @@
     <ClInclude Include="..\src\login\ipban.h">
     <ClInclude Include="..\src\login\ipban.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\src\login\loginlog.h">
+    <ClInclude Include="..\src\login\login.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\src\login\login.h">
+    <ClInclude Include="..\src\login\loginchrif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\loginclif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\logincnslif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\loginlog.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
     <ClInclude Include="..\src\common\cbasetypes.h">
     <ClInclude Include="..\src\common\cbasetypes.h">

+ 9 - 3
vcproj-13/login-server_sql.vcxproj

@@ -150,6 +150,9 @@
     <ClInclude Include="..\src\login\account.h" />
     <ClInclude Include="..\src\login\account.h" />
     <ClInclude Include="..\src\login\ipban.h" />
     <ClInclude Include="..\src\login\ipban.h" />
     <ClInclude Include="..\src\login\login.h" />
     <ClInclude Include="..\src\login\login.h" />
+    <ClInclude Include="..\src\login\loginchrif.h" />
+    <ClInclude Include="..\src\login\loginclif.h" />
+    <ClInclude Include="..\src\login\logincnslif.h" />
     <ClInclude Include="..\src\login\loginlog.h" />
     <ClInclude Include="..\src\login\loginlog.h" />
     <ClInclude Include="..\src\common\cbasetypes.h" />
     <ClInclude Include="..\src\common\cbasetypes.h" />
     <ClInclude Include="..\src\common\core.h" />
     <ClInclude Include="..\src\common\core.h" />
@@ -181,10 +184,13 @@
     <ClCompile Include="..\src\common\mutex.c" />
     <ClCompile Include="..\src\common\mutex.c" />
     <ClCompile Include="..\src\common\raconf.c" />
     <ClCompile Include="..\src\common\raconf.c" />
     <ClCompile Include="..\src\common\thread.c" />
     <ClCompile Include="..\src\common\thread.c" />
-    <ClCompile Include="..\src\login\account_sql.c" />
-    <ClCompile Include="..\src\login\ipban_sql.c" />
+    <ClCompile Include="..\src\login\account.c" />
+    <ClCompile Include="..\src\login\ipban.c" />
     <ClCompile Include="..\src\login\login.c" />
     <ClCompile Include="..\src\login\login.c" />
-    <ClCompile Include="..\src\login\loginlog_sql.c" />
+    <ClCompile Include="..\src\login\loginchrif.c" />
+    <ClCompile Include="..\src\login\loginclif.c" />
+    <ClCompile Include="..\src\login\logincnslif.c" />
+    <ClCompile Include="..\src\login\loginlog.c" />
     <ClCompile Include="..\src\common\core.c" />
     <ClCompile Include="..\src\common\core.c" />
     <ClCompile Include="..\src\common\conf.c" />
     <ClCompile Include="..\src\common\conf.c" />
     <ClCompile Include="..\src\common\db.c" />
     <ClCompile Include="..\src\common\db.c" />

+ 24 - 6
vcproj-13/login-server_sql.vcxproj.filters

@@ -1,16 +1,25 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\src\login\account_sql.c">
+    <ClCompile Include="..\src\login\account.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\src\login\ipban_sql.c">
+    <ClCompile Include="..\src\login\ipban.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
     <ClCompile Include="..\src\login\login.c">
     <ClCompile Include="..\src\login\login.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\src\login\loginlog_sql.c">
+    <ClCompile Include="..\src\login\loginchrif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\loginclif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\logincnslif.c">
+      <Filter>login_sql</Filter>
+    </ClCompile>
+    <ClCompile Include="..\src\login\loginlog.c">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClCompile>
     </ClCompile>
     <ClCompile Include="..\src\common\core.c">
     <ClCompile Include="..\src\common\core.c">
@@ -95,10 +104,19 @@
     <ClInclude Include="..\src\login\ipban.h">
     <ClInclude Include="..\src\login\ipban.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\src\login\loginlog.h">
+    <ClInclude Include="..\src\login\login.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="..\src\login\login.h">
+    <ClInclude Include="..\src\login\loginchrif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\loginclif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\logincnslif.h">
+      <Filter>login_sql</Filter>
+    </ClInclude>
+    <ClInclude Include="..\src\login\loginlog.h">
       <Filter>login_sql</Filter>
       <Filter>login_sql</Filter>
     </ClInclude>
     </ClInclude>
     <ClInclude Include="..\src\common\cbasetypes.h">
     <ClInclude Include="..\src\common\cbasetypes.h">
@@ -208,4 +226,4 @@
       <UniqueIdentifier>{779e8145-9bb2-4a88-9149-60586ab0bdd4}</UniqueIdentifier>
       <UniqueIdentifier>{779e8145-9bb2-4a88-9149-60586ab0bdd4}</UniqueIdentifier>
     </Filter>
     </Filter>
   </ItemGroup>
   </ItemGroup>
-</Project>
+</Project>

+ 27 - 3
vcproj-9/login-server_sql.vcproj

@@ -211,7 +211,7 @@
 				>
 				>
 			</File>
 			</File>
 			<File
 			<File
-				RelativePath="..\src\login\account_sql.c"
+				RelativePath="..\src\login\account.c"
 				>
 				>
 			</File>
 			</File>
 			<File
 			<File
@@ -219,7 +219,7 @@
 				>
 				>
 			</File>
 			</File>
 			<File
 			<File
-				RelativePath="..\src\login\ipban_sql.c"
+				RelativePath="..\src\login\ipban.c"
 				>
 				>
 			</File>
 			</File>
 			<File
 			<File
@@ -230,12 +230,36 @@
 				RelativePath="..\src\login\login.h"
 				RelativePath="..\src\login\login.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\src\login\loginchrif.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\login\loginchrif.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\login\loginclif.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\login\loginclif.h"
+				>
+			</File>
+			<File
+				RelativePath="..\src\login\logincnslif.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\login\logincnslif.h"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\src\login\loginlog.h"
 				RelativePath="..\src\login\loginlog.h"
 				>
 				>
 			</File>
 			</File>
 			<File
 			<File
-				RelativePath="..\src\login\loginlog_sql.c"
+				RelativePath="..\src\login\loginlog.c"
 				>
 				>
 			</File>
 			</File>
 		</Filter>
 		</Filter>

Some files were not shown because too many files changed in this diff